unzip applet by Laurence Anderson
----------------------------------------------------------------------
This commit is contained in:
parent
438803311b
commit
87ac7028e0
@ -34,6 +34,7 @@ obj-$(CONFIG_GUNZIP) += gunzip.o
|
|||||||
obj-$(CONFIG_GZIP) += gzip.o
|
obj-$(CONFIG_GZIP) += gzip.o
|
||||||
obj-$(CONFIG_RPM2CPIO) += rpm2cpio.o
|
obj-$(CONFIG_RPM2CPIO) += rpm2cpio.o
|
||||||
obj-$(CONFIG_TAR) += tar.o
|
obj-$(CONFIG_TAR) += tar.o
|
||||||
|
obj-$(CONFIG_UNZIP) += unzip.o
|
||||||
|
|
||||||
|
|
||||||
# Hand off to toplevel Rules.mak
|
# Hand off to toplevel Rules.mak
|
||||||
|
@ -20,4 +20,5 @@ if [ "$CONFIG_TAR" = "y" ] ; then
|
|||||||
bool ' Enable -X and --exclude options (exclude files)' CONFIG_FEATURE_TAR_EXCLUDE
|
bool ' Enable -X and --exclude options (exclude files)' CONFIG_FEATURE_TAR_EXCLUDE
|
||||||
bool ' Enable -z option (currently only for extracting)' CONFIG_FEATURE_TAR_GZIP
|
bool ' Enable -z option (currently only for extracting)' CONFIG_FEATURE_TAR_GZIP
|
||||||
fi
|
fi
|
||||||
|
bool 'unzip' CONFIG_UNZIP
|
||||||
endmenu
|
endmenu
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
TOPDIR :=../..
|
TOPDIR :=../..
|
||||||
L_TARGET := libunarchive.a
|
L_TARGET := libunarchive.a
|
||||||
|
|
||||||
obj-y := unarchive.o seek_sub_file.o
|
obj-y := unarchive.o seek_sub_file.o
|
||||||
obj-n :=
|
obj-n :=
|
||||||
obj- :=
|
obj- :=
|
||||||
|
|
||||||
@ -41,13 +41,17 @@ ifeq ($(CONFIG_CPIO),y)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_RPM2CPIO),y)
|
ifeq ($(CONFIG_RPM2CPIO),y)
|
||||||
obj-y += get_header_cpio.o
|
obj-y += get_header_cpio.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_TAR),y)
|
ifeq ($(CONFIG_TAR),y)
|
||||||
obj-y += get_header_tar.o
|
obj-y += get_header_tar.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_UNZIP),y)
|
||||||
|
obj-y += get_header_zip.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
# Hand off to toplevel Rules.mak
|
# Hand off to toplevel Rules.mak
|
||||||
include $(TOPDIR)/Rules.mak
|
include $(TOPDIR)/Rules.mak
|
||||||
|
@ -80,7 +80,7 @@ static const int ERROR = 1;
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* window size--must be a power of two, and
|
* window size--must be a power of two, and
|
||||||
* at least 32K for zip's deflate method
|
* at least 32K for zip's deflate method
|
||||||
*/
|
*/
|
||||||
static const int WSIZE = 0x8000;
|
static const int WSIZE = 0x8000;
|
||||||
|
|
||||||
@ -846,7 +846,7 @@ static int inflate_block(int *e)
|
|||||||
*
|
*
|
||||||
* GLOBAL VARIABLES: outcnt, bk, bb, hufts, inptr
|
* GLOBAL VARIABLES: outcnt, bk, bb, hufts, inptr
|
||||||
*/
|
*/
|
||||||
static int inflate(void)
|
extern int inflate(FILE *in, FILE *out)
|
||||||
{
|
{
|
||||||
int e; /* last block flag */
|
int e; /* last block flag */
|
||||||
int r; /* result code */
|
int r; /* result code */
|
||||||
@ -857,6 +857,13 @@ static int inflate(void)
|
|||||||
bk = 0;
|
bk = 0;
|
||||||
bb = 0;
|
bb = 0;
|
||||||
|
|
||||||
|
in_file = in;
|
||||||
|
out_file = out;
|
||||||
|
|
||||||
|
/* Allocate all global buffers (for DYN_ALLOC option) */
|
||||||
|
window = xmalloc((size_t)(((2L*WSIZE)+1L)*sizeof(unsigned char)));
|
||||||
|
bytes_out = 0L;
|
||||||
|
|
||||||
/* Create the crc table */
|
/* Create the crc table */
|
||||||
make_crc_table();
|
make_crc_table();
|
||||||
|
|
||||||
@ -881,13 +888,15 @@ static int inflate(void)
|
|||||||
|
|
||||||
/* flush out window */
|
/* flush out window */
|
||||||
flush_window();
|
flush_window();
|
||||||
|
free(window);
|
||||||
|
free(crc_table);
|
||||||
|
|
||||||
/* return success */
|
/* return success */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===========================================================================
|
/* ===========================================================================
|
||||||
* Unzip in to out. This routine works on both gzip and pkzip files.
|
* Unzip in to out. This routine works on gzip files only.
|
||||||
*
|
*
|
||||||
* IN assertions: the buffer inbuf contains already the beginning of
|
* IN assertions: the buffer inbuf contains already the beginning of
|
||||||
* the compressed data, from offsets inptr to insize-1 included.
|
* the compressed data, from offsets inptr to insize-1 included.
|
||||||
@ -901,9 +910,6 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file)
|
|||||||
typedef void (*sig_type) (int);
|
typedef void (*sig_type) (int);
|
||||||
unsigned short i;
|
unsigned short i;
|
||||||
|
|
||||||
in_file = l_in_file;
|
|
||||||
out_file = l_out_file;
|
|
||||||
|
|
||||||
if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
|
if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
|
||||||
(void) signal(SIGINT, (sig_type) abort_gzip);
|
(void) signal(SIGINT, (sig_type) abort_gzip);
|
||||||
}
|
}
|
||||||
@ -918,53 +924,48 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Allocate all global buffers (for DYN_ALLOC option) */
|
|
||||||
window = xmalloc((size_t)(((2L*WSIZE)+1L)*sizeof(unsigned char)));
|
|
||||||
outcnt = 0;
|
|
||||||
bytes_out = 0L;
|
|
||||||
|
|
||||||
/* Magic header for gzip files, 1F 8B = \037\213 */
|
/* Magic header for gzip files, 1F 8B = \037\213 */
|
||||||
if ((fgetc(in_file) != 0x1F) || (fgetc(in_file) != 0x8b)) {
|
if ((fgetc(l_in_file) != 0x1F) || (fgetc(l_in_file) != 0x8b)) {
|
||||||
error_msg("Invalid gzip magic");
|
error_msg("Invalid gzip magic");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the compression method */
|
/* Check the compression method */
|
||||||
if (fgetc(in_file) != 8) {
|
if (fgetc(l_in_file) != 8) {
|
||||||
error_msg("Unknown compression method");
|
error_msg("Unknown compression method");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = (unsigned char) fgetc(in_file);
|
flags = (unsigned char) fgetc(l_in_file);
|
||||||
|
|
||||||
/* Ignore time stamp(4), extra flags(1), OS type(1) */
|
/* Ignore time stamp(4), extra flags(1), OS type(1) */
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
fgetc(in_file);
|
fgetc(l_in_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & 0x04) {
|
if (flags & 0x04) {
|
||||||
/* bit 2 set: extra field present */
|
/* bit 2 set: extra field present */
|
||||||
const unsigned short extra = fgetc(in_file) + (fgetc(in_file) << 8);
|
const unsigned short extra = fgetc(l_in_file) + (fgetc(l_in_file) << 8);
|
||||||
|
|
||||||
for (i = 0; i < extra; i++) {
|
for (i = 0; i < extra; i++) {
|
||||||
fgetc(in_file);
|
fgetc(l_in_file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Discard original name if any */
|
/* Discard original name if any */
|
||||||
if (flags & 0x08) {
|
if (flags & 0x08) {
|
||||||
/* bit 3 set: original file name present */
|
/* bit 3 set: original file name present */
|
||||||
while (fgetc(in_file) != 0); /* null */
|
while (fgetc(l_in_file) != 0); /* null */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Discard file comment if any */
|
/* Discard file comment if any */
|
||||||
if (flags & 0x10) {
|
if (flags & 0x10) {
|
||||||
/* bit 4 set: file comment present */
|
/* bit 4 set: file comment present */
|
||||||
while (fgetc(in_file) != 0); /* null */
|
while (fgetc(l_in_file) != 0); /* null */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decompress */
|
/* Decompress */
|
||||||
if (inflate() != 0) {
|
if (inflate(l_in_file, l_out_file) != 0) {
|
||||||
error_msg("invalid compressed data--format violated");
|
error_msg("invalid compressed data--format violated");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -972,7 +973,7 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file)
|
|||||||
* crc32 (see algorithm.doc)
|
* crc32 (see algorithm.doc)
|
||||||
* uncompressed input size modulo 2^32
|
* uncompressed input size modulo 2^32
|
||||||
*/
|
*/
|
||||||
fread(buf, 1, 8, in_file);
|
fread(buf, 1, 8, l_in_file);
|
||||||
|
|
||||||
/* Validate decompression - crc */
|
/* Validate decompression - crc */
|
||||||
if ((unsigned int)((buf[0] | (buf[1] << 8)) |((buf[2] | (buf[3] << 8)) << 16)) != (crc ^ 0xffffffffL)) {
|
if ((unsigned int)((buf[0] | (buf[1] << 8)) |((buf[2] | (buf[3] << 8)) << 16)) != (crc ^ 0xffffffffL)) {
|
||||||
@ -983,14 +984,11 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file)
|
|||||||
error_msg("invalid compressed data--length error");
|
error_msg("invalid compressed data--length error");
|
||||||
}
|
}
|
||||||
|
|
||||||
free(window);
|
|
||||||
free(crc_table);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This needs access to global variables wondow and crc_table, so its not in its own file.
|
* This needs access to global variables window and crc_table, so its not in its own file.
|
||||||
*/
|
*/
|
||||||
extern void gz_close(int gunzip_pid)
|
extern void gz_close(int gunzip_pid)
|
||||||
{
|
{
|
||||||
|
110
archival/libunarchive/get_header_zip.c
Normal file
110
archival/libunarchive/get_header_zip.c
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/* vi: set sw=4 ts=4: */
|
||||||
|
/*
|
||||||
|
* get_header_zip for busybox
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 by Laurence Anderson
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "unarchive.h"
|
||||||
|
#include "libbb.h"
|
||||||
|
|
||||||
|
#define ZIP_FILEHEADER_MAGIC 0x04034b50
|
||||||
|
#define ZIP_CDS_MAGIC 0x02014b50
|
||||||
|
#define ZIP_CDS_END_MAGIC 0x06054b50
|
||||||
|
#define ZIP_DD_MAGIC 0x8074b50
|
||||||
|
|
||||||
|
file_header_t *get_header_zip(FILE *zip_stream)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
short version __attribute__ ((packed));
|
||||||
|
short flags __attribute__ ((packed));
|
||||||
|
short method __attribute__ ((packed));
|
||||||
|
short modtime __attribute__ ((packed));
|
||||||
|
short moddate __attribute__ ((packed));
|
||||||
|
int crc32 __attribute__ ((packed));
|
||||||
|
int cmpsize __attribute__ ((packed));
|
||||||
|
int ucmpsize __attribute__ ((packed));
|
||||||
|
short filename_len __attribute__ ((packed));
|
||||||
|
short extra_len __attribute__ ((packed));
|
||||||
|
} zip_header;
|
||||||
|
file_header_t *zip_entry = NULL;
|
||||||
|
int magic;
|
||||||
|
static int dd_ahead = 0; // If this is true, the we didn't know how long the last extraced file was
|
||||||
|
|
||||||
|
fread (&magic, 4, 1, zip_stream);
|
||||||
|
archive_offset += 4;
|
||||||
|
|
||||||
|
if (feof(zip_stream)) return(NULL);
|
||||||
|
checkmagic:
|
||||||
|
switch (magic) {
|
||||||
|
case ZIP_FILEHEADER_MAGIC:
|
||||||
|
zip_entry = xcalloc(1, sizeof(file_header_t));
|
||||||
|
fread (&zip_header, sizeof(zip_header), 1, zip_stream);
|
||||||
|
archive_offset += sizeof(zip_header);
|
||||||
|
if (!(zip_header.method == 8 || zip_header.method == 0)) { printf("Unsupported compression method %d\n", zip_header.method); return(NULL); }
|
||||||
|
zip_entry->name = calloc(zip_header.filename_len + 1, sizeof(char));
|
||||||
|
fread (zip_entry->name, sizeof(char), zip_header.filename_len, zip_stream);
|
||||||
|
archive_offset += zip_header.filename_len;
|
||||||
|
seek_sub_file(zip_stream, zip_header.extra_len);
|
||||||
|
zip_entry->size = zip_header.cmpsize;
|
||||||
|
if (zip_header.method == 8) zip_entry->extract_func = &inflate;
|
||||||
|
zip_entry->mode = S_IFREG | 0777;
|
||||||
|
// Time/Date?
|
||||||
|
if (*(zip_entry->name + strlen(zip_entry->name) - 1) == '/') { // Files that end in a / are directories
|
||||||
|
zip_entry->mode ^= S_IFREG;
|
||||||
|
zip_entry->mode |= S_IFDIR;
|
||||||
|
*(zip_entry->name + strlen(zip_entry->name) - 1) = '\0'; // Remove trailing / so unarchive doesn't get confused
|
||||||
|
}
|
||||||
|
//printf("cmpsize: %d, ucmpsize: %d, method: %d\n", zip_header.cmpsize, zip_header.ucmpsize, zip_header.method);
|
||||||
|
if (zip_header.flags & 0x8) { // crc32, and sizes are in the data description _after_ the file
|
||||||
|
if (zip_header.cmpsize == 0) dd_ahead = 1; // As we don't know how long this file it is difficult to skip! but it is compressed, so normally its ok
|
||||||
|
if (zip_header.ucmpsize != 0) dd_ahead = 2; // Humm... we would otherwise skip this twice - not good!
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ZIP_CDS_MAGIC: /* FALLTHRU */
|
||||||
|
case ZIP_CDS_END_MAGIC:
|
||||||
|
return(NULL);
|
||||||
|
break;
|
||||||
|
case ZIP_DD_MAGIC: {
|
||||||
|
int cmpsize;
|
||||||
|
seek_sub_file(zip_stream, 4); // Skip crc32
|
||||||
|
fread(&cmpsize, 4, 1, zip_stream);
|
||||||
|
archive_offset += 4;
|
||||||
|
if (dd_ahead == 1) archive_offset += cmpsize;
|
||||||
|
seek_sub_file(zip_stream, 4); // Skip uncompressed size
|
||||||
|
dd_ahead = 0;
|
||||||
|
return (get_header_zip(zip_stream));
|
||||||
|
break; }
|
||||||
|
default:
|
||||||
|
if (!dd_ahead) error_msg("Invalid magic (%#x): Trying to skip junk", magic);
|
||||||
|
dd_ahead = 0;
|
||||||
|
while (!feof(zip_stream)) {
|
||||||
|
int tmpmagic;
|
||||||
|
tmpmagic = fgetc(zip_stream);
|
||||||
|
archive_offset++;
|
||||||
|
magic = ((magic >> 8) & 0x00ffffff) | ((tmpmagic << 24) & 0xff000000);
|
||||||
|
if (magic == ZIP_FILEHEADER_MAGIC || magic == ZIP_CDS_MAGIC || magic == ZIP_CDS_END_MAGIC) goto checkmagic;
|
||||||
|
}
|
||||||
|
error_msg("End of archive reached: Bad archive");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
//if (archive_offset != ftell(zip_stream)) printf("Archive offset out of sync (%d,%d)\n", (int) archive_offset, (int) ftell(zip_stream));
|
||||||
|
return(zip_entry);
|
||||||
|
}
|
@ -120,7 +120,8 @@ char *extract_archive(FILE *src_stream, FILE *out_stream, const file_header_t *f
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
archive_offset += file_entry->size;
|
archive_offset += file_entry->size;
|
||||||
copy_file_chunk(src_stream, dst_stream, file_entry->size);
|
if (file_entry->extract_func) file_entry->extract_func(src_stream, dst_stream);
|
||||||
|
else copy_file_chunk(src_stream, dst_stream, file_entry->size);
|
||||||
fclose(dst_stream);
|
fclose(dst_stream);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -80,7 +80,7 @@ static const int ERROR = 1;
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* window size--must be a power of two, and
|
* window size--must be a power of two, and
|
||||||
* at least 32K for zip's deflate method
|
* at least 32K for zip's deflate method
|
||||||
*/
|
*/
|
||||||
static const int WSIZE = 0x8000;
|
static const int WSIZE = 0x8000;
|
||||||
|
|
||||||
@ -846,7 +846,7 @@ static int inflate_block(int *e)
|
|||||||
*
|
*
|
||||||
* GLOBAL VARIABLES: outcnt, bk, bb, hufts, inptr
|
* GLOBAL VARIABLES: outcnt, bk, bb, hufts, inptr
|
||||||
*/
|
*/
|
||||||
static int inflate(void)
|
extern int inflate(FILE *in, FILE *out)
|
||||||
{
|
{
|
||||||
int e; /* last block flag */
|
int e; /* last block flag */
|
||||||
int r; /* result code */
|
int r; /* result code */
|
||||||
@ -857,6 +857,13 @@ static int inflate(void)
|
|||||||
bk = 0;
|
bk = 0;
|
||||||
bb = 0;
|
bb = 0;
|
||||||
|
|
||||||
|
in_file = in;
|
||||||
|
out_file = out;
|
||||||
|
|
||||||
|
/* Allocate all global buffers (for DYN_ALLOC option) */
|
||||||
|
window = xmalloc((size_t)(((2L*WSIZE)+1L)*sizeof(unsigned char)));
|
||||||
|
bytes_out = 0L;
|
||||||
|
|
||||||
/* Create the crc table */
|
/* Create the crc table */
|
||||||
make_crc_table();
|
make_crc_table();
|
||||||
|
|
||||||
@ -881,13 +888,15 @@ static int inflate(void)
|
|||||||
|
|
||||||
/* flush out window */
|
/* flush out window */
|
||||||
flush_window();
|
flush_window();
|
||||||
|
free(window);
|
||||||
|
free(crc_table);
|
||||||
|
|
||||||
/* return success */
|
/* return success */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===========================================================================
|
/* ===========================================================================
|
||||||
* Unzip in to out. This routine works on both gzip and pkzip files.
|
* Unzip in to out. This routine works on gzip files only.
|
||||||
*
|
*
|
||||||
* IN assertions: the buffer inbuf contains already the beginning of
|
* IN assertions: the buffer inbuf contains already the beginning of
|
||||||
* the compressed data, from offsets inptr to insize-1 included.
|
* the compressed data, from offsets inptr to insize-1 included.
|
||||||
@ -901,9 +910,6 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file)
|
|||||||
typedef void (*sig_type) (int);
|
typedef void (*sig_type) (int);
|
||||||
unsigned short i;
|
unsigned short i;
|
||||||
|
|
||||||
in_file = l_in_file;
|
|
||||||
out_file = l_out_file;
|
|
||||||
|
|
||||||
if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
|
if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
|
||||||
(void) signal(SIGINT, (sig_type) abort_gzip);
|
(void) signal(SIGINT, (sig_type) abort_gzip);
|
||||||
}
|
}
|
||||||
@ -918,53 +924,48 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Allocate all global buffers (for DYN_ALLOC option) */
|
|
||||||
window = xmalloc((size_t)(((2L*WSIZE)+1L)*sizeof(unsigned char)));
|
|
||||||
outcnt = 0;
|
|
||||||
bytes_out = 0L;
|
|
||||||
|
|
||||||
/* Magic header for gzip files, 1F 8B = \037\213 */
|
/* Magic header for gzip files, 1F 8B = \037\213 */
|
||||||
if ((fgetc(in_file) != 0x1F) || (fgetc(in_file) != 0x8b)) {
|
if ((fgetc(l_in_file) != 0x1F) || (fgetc(l_in_file) != 0x8b)) {
|
||||||
error_msg("Invalid gzip magic");
|
error_msg("Invalid gzip magic");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the compression method */
|
/* Check the compression method */
|
||||||
if (fgetc(in_file) != 8) {
|
if (fgetc(l_in_file) != 8) {
|
||||||
error_msg("Unknown compression method");
|
error_msg("Unknown compression method");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = (unsigned char) fgetc(in_file);
|
flags = (unsigned char) fgetc(l_in_file);
|
||||||
|
|
||||||
/* Ignore time stamp(4), extra flags(1), OS type(1) */
|
/* Ignore time stamp(4), extra flags(1), OS type(1) */
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
fgetc(in_file);
|
fgetc(l_in_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & 0x04) {
|
if (flags & 0x04) {
|
||||||
/* bit 2 set: extra field present */
|
/* bit 2 set: extra field present */
|
||||||
const unsigned short extra = fgetc(in_file) + (fgetc(in_file) << 8);
|
const unsigned short extra = fgetc(l_in_file) + (fgetc(l_in_file) << 8);
|
||||||
|
|
||||||
for (i = 0; i < extra; i++) {
|
for (i = 0; i < extra; i++) {
|
||||||
fgetc(in_file);
|
fgetc(l_in_file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Discard original name if any */
|
/* Discard original name if any */
|
||||||
if (flags & 0x08) {
|
if (flags & 0x08) {
|
||||||
/* bit 3 set: original file name present */
|
/* bit 3 set: original file name present */
|
||||||
while (fgetc(in_file) != 0); /* null */
|
while (fgetc(l_in_file) != 0); /* null */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Discard file comment if any */
|
/* Discard file comment if any */
|
||||||
if (flags & 0x10) {
|
if (flags & 0x10) {
|
||||||
/* bit 4 set: file comment present */
|
/* bit 4 set: file comment present */
|
||||||
while (fgetc(in_file) != 0); /* null */
|
while (fgetc(l_in_file) != 0); /* null */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decompress */
|
/* Decompress */
|
||||||
if (inflate() != 0) {
|
if (inflate(l_in_file, l_out_file) != 0) {
|
||||||
error_msg("invalid compressed data--format violated");
|
error_msg("invalid compressed data--format violated");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -972,7 +973,7 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file)
|
|||||||
* crc32 (see algorithm.doc)
|
* crc32 (see algorithm.doc)
|
||||||
* uncompressed input size modulo 2^32
|
* uncompressed input size modulo 2^32
|
||||||
*/
|
*/
|
||||||
fread(buf, 1, 8, in_file);
|
fread(buf, 1, 8, l_in_file);
|
||||||
|
|
||||||
/* Validate decompression - crc */
|
/* Validate decompression - crc */
|
||||||
if ((unsigned int)((buf[0] | (buf[1] << 8)) |((buf[2] | (buf[3] << 8)) << 16)) != (crc ^ 0xffffffffL)) {
|
if ((unsigned int)((buf[0] | (buf[1] << 8)) |((buf[2] | (buf[3] << 8)) << 16)) != (crc ^ 0xffffffffL)) {
|
||||||
@ -983,14 +984,11 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file)
|
|||||||
error_msg("invalid compressed data--length error");
|
error_msg("invalid compressed data--length error");
|
||||||
}
|
}
|
||||||
|
|
||||||
free(window);
|
|
||||||
free(crc_table);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This needs access to global variables wondow and crc_table, so its not in its own file.
|
* This needs access to global variables window and crc_table, so its not in its own file.
|
||||||
*/
|
*/
|
||||||
extern void gz_close(int gunzip_pid)
|
extern void gz_close(int gunzip_pid)
|
||||||
{
|
{
|
||||||
|
94
archival/unzip.c
Normal file
94
archival/unzip.c
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/* vi: set sw=4 ts=4: */
|
||||||
|
/*
|
||||||
|
* Mini unzip implementation for busybox
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 by Laurence Anderson
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "unarchive.h"
|
||||||
|
#include "busybox.h"
|
||||||
|
|
||||||
|
extern int unzip_main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
FILE *src_stream;
|
||||||
|
int extract_function = extract_all_to_fs | extract_create_leading_dirs;
|
||||||
|
char **extract_names = NULL;
|
||||||
|
char **exclude_names = NULL;
|
||||||
|
int opt = 0;
|
||||||
|
int num_of_entries = 0;
|
||||||
|
int exclude = 0;
|
||||||
|
char *outdir = "./";
|
||||||
|
FILE *msgout = stdout;
|
||||||
|
|
||||||
|
while ((opt = getopt(argc, argv, "lnopqxd:")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'l':
|
||||||
|
extract_function |= extract_verbose_list;
|
||||||
|
extract_function ^= extract_all_to_fs;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
extract_function |= extract_unconditional;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
extract_function |= extract_to_stdout;
|
||||||
|
extract_function ^= extract_all_to_fs;
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
case 'q':
|
||||||
|
msgout = xfopen("/dev/null", "w");
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
outdir = xstrdup(optarg);
|
||||||
|
strcat(outdir, "/");
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
exclude = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind == argc) {
|
||||||
|
show_usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*argv[optind] == '-') src_stream = stdin;
|
||||||
|
else src_stream = xfopen(argv[optind++], "r");
|
||||||
|
|
||||||
|
while (optind < argc) {
|
||||||
|
if (exclude) {
|
||||||
|
exclude_names = xrealloc(exclude_names, sizeof(char *) * (num_of_entries + 2));
|
||||||
|
exclude_names[num_of_entries] = xstrdup(argv[optind]);
|
||||||
|
} else {
|
||||||
|
extract_names = xrealloc(extract_names, sizeof(char *) * (num_of_entries + 2));
|
||||||
|
extract_names[num_of_entries] = xstrdup(argv[optind]);
|
||||||
|
}
|
||||||
|
num_of_entries++;
|
||||||
|
if (exclude) exclude_names[num_of_entries] = NULL;
|
||||||
|
else extract_names[num_of_entries] = NULL;
|
||||||
|
optind++;
|
||||||
|
}
|
||||||
|
|
||||||
|
unarchive(src_stream, msgout, &get_header_zip, extract_function, outdir, extract_names, exclude_names);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
@ -470,6 +470,9 @@
|
|||||||
#ifdef CONFIG_UNIX2DOS
|
#ifdef CONFIG_UNIX2DOS
|
||||||
APPLET(unix2dos, dos2unix_main, _BB_DIR_USR_BIN)
|
APPLET(unix2dos, dos2unix_main, _BB_DIR_USR_BIN)
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_UNZIP
|
||||||
|
APPLET(unzip, unzip_main, _BB_DIR_USR_BIN)
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_UPDATE
|
#ifdef CONFIG_UPDATE
|
||||||
APPLET(update, update_main, _BB_DIR_SBIN)
|
APPLET(update, update_main, _BB_DIR_SBIN)
|
||||||
#endif
|
#endif
|
||||||
|
@ -215,6 +215,7 @@ extern long arith (const char *startbuf, int *errcode);
|
|||||||
int read_package_field(const char *package_buffer, char **field_name, char **field_value);
|
int read_package_field(const char *package_buffer, char **field_name, char **field_value);
|
||||||
char *fgets_str(FILE *file, const char *terminating_string);
|
char *fgets_str(FILE *file, const char *terminating_string);
|
||||||
|
|
||||||
|
extern int inflate(FILE *in, FILE *out);
|
||||||
extern int unzip(FILE *l_in_file, FILE *l_out_file);
|
extern int unzip(FILE *l_in_file, FILE *l_out_file);
|
||||||
extern void gz_close(int gunzip_pid);
|
extern void gz_close(int gunzip_pid);
|
||||||
extern FILE *gz_open(FILE *compressed_file, int *pid);
|
extern FILE *gz_open(FILE *compressed_file, int *pid);
|
||||||
|
@ -26,11 +26,13 @@ typedef struct file_headers_s {
|
|||||||
mode_t mode;
|
mode_t mode;
|
||||||
time_t mtime;
|
time_t mtime;
|
||||||
dev_t device;
|
dev_t device;
|
||||||
|
int (*extract_func)(FILE *, FILE *);
|
||||||
} file_header_t;
|
} file_header_t;
|
||||||
|
|
||||||
file_header_t *get_header_ar(FILE *in_file);
|
file_header_t *get_header_ar(FILE *in_file);
|
||||||
file_header_t *get_header_cpio(FILE *src_stream);
|
file_header_t *get_header_cpio(FILE *src_stream);
|
||||||
file_header_t *get_header_tar(FILE *tar_stream);
|
file_header_t *get_header_tar(FILE *tar_stream);
|
||||||
|
file_header_t *get_header_zip(FILE *zip_stream);
|
||||||
|
|
||||||
void seek_sub_file(FILE *src_stream, const int count);
|
void seek_sub_file(FILE *src_stream, const int count);
|
||||||
|
|
||||||
|
@ -1851,6 +1851,19 @@
|
|||||||
"\t-u\toutput will be in UNIX format\n" \
|
"\t-u\toutput will be in UNIX format\n" \
|
||||||
"\t-d\toutput will be in DOS format"
|
"\t-d\toutput will be in DOS format"
|
||||||
|
|
||||||
|
#define unzip_trivial_usage \
|
||||||
|
"[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]"
|
||||||
|
#define unzip_full_usage \
|
||||||
|
"Extracts files from ZIP archives\n" \
|
||||||
|
"Options:\n" \
|
||||||
|
"\t-l\tlist archive contents (short form)\n" \
|
||||||
|
"\t-n\tnever overwrite existing files (default)\n" \
|
||||||
|
"\t-o\toverwrite files without prompting\n" \
|
||||||
|
"\t-p\tsend output to stdout\n" \
|
||||||
|
"\t-q\tbe quiet\n" \
|
||||||
|
"\t-x\texclude these files\n" \
|
||||||
|
"\t-d\textract files into this directory"
|
||||||
|
|
||||||
#define update_trivial_usage \
|
#define update_trivial_usage \
|
||||||
"[options]"
|
"[options]"
|
||||||
#define update_full_usage \
|
#define update_full_usage \
|
||||||
|
@ -80,7 +80,7 @@ static const int ERROR = 1;
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* window size--must be a power of two, and
|
* window size--must be a power of two, and
|
||||||
* at least 32K for zip's deflate method
|
* at least 32K for zip's deflate method
|
||||||
*/
|
*/
|
||||||
static const int WSIZE = 0x8000;
|
static const int WSIZE = 0x8000;
|
||||||
|
|
||||||
@ -846,7 +846,7 @@ static int inflate_block(int *e)
|
|||||||
*
|
*
|
||||||
* GLOBAL VARIABLES: outcnt, bk, bb, hufts, inptr
|
* GLOBAL VARIABLES: outcnt, bk, bb, hufts, inptr
|
||||||
*/
|
*/
|
||||||
static int inflate(void)
|
extern int inflate(FILE *in, FILE *out)
|
||||||
{
|
{
|
||||||
int e; /* last block flag */
|
int e; /* last block flag */
|
||||||
int r; /* result code */
|
int r; /* result code */
|
||||||
@ -857,6 +857,13 @@ static int inflate(void)
|
|||||||
bk = 0;
|
bk = 0;
|
||||||
bb = 0;
|
bb = 0;
|
||||||
|
|
||||||
|
in_file = in;
|
||||||
|
out_file = out;
|
||||||
|
|
||||||
|
/* Allocate all global buffers (for DYN_ALLOC option) */
|
||||||
|
window = xmalloc((size_t)(((2L*WSIZE)+1L)*sizeof(unsigned char)));
|
||||||
|
bytes_out = 0L;
|
||||||
|
|
||||||
/* Create the crc table */
|
/* Create the crc table */
|
||||||
make_crc_table();
|
make_crc_table();
|
||||||
|
|
||||||
@ -881,13 +888,15 @@ static int inflate(void)
|
|||||||
|
|
||||||
/* flush out window */
|
/* flush out window */
|
||||||
flush_window();
|
flush_window();
|
||||||
|
free(window);
|
||||||
|
free(crc_table);
|
||||||
|
|
||||||
/* return success */
|
/* return success */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===========================================================================
|
/* ===========================================================================
|
||||||
* Unzip in to out. This routine works on both gzip and pkzip files.
|
* Unzip in to out. This routine works on gzip files only.
|
||||||
*
|
*
|
||||||
* IN assertions: the buffer inbuf contains already the beginning of
|
* IN assertions: the buffer inbuf contains already the beginning of
|
||||||
* the compressed data, from offsets inptr to insize-1 included.
|
* the compressed data, from offsets inptr to insize-1 included.
|
||||||
@ -901,9 +910,6 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file)
|
|||||||
typedef void (*sig_type) (int);
|
typedef void (*sig_type) (int);
|
||||||
unsigned short i;
|
unsigned short i;
|
||||||
|
|
||||||
in_file = l_in_file;
|
|
||||||
out_file = l_out_file;
|
|
||||||
|
|
||||||
if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
|
if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
|
||||||
(void) signal(SIGINT, (sig_type) abort_gzip);
|
(void) signal(SIGINT, (sig_type) abort_gzip);
|
||||||
}
|
}
|
||||||
@ -918,53 +924,48 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Allocate all global buffers (for DYN_ALLOC option) */
|
|
||||||
window = xmalloc((size_t)(((2L*WSIZE)+1L)*sizeof(unsigned char)));
|
|
||||||
outcnt = 0;
|
|
||||||
bytes_out = 0L;
|
|
||||||
|
|
||||||
/* Magic header for gzip files, 1F 8B = \037\213 */
|
/* Magic header for gzip files, 1F 8B = \037\213 */
|
||||||
if ((fgetc(in_file) != 0x1F) || (fgetc(in_file) != 0x8b)) {
|
if ((fgetc(l_in_file) != 0x1F) || (fgetc(l_in_file) != 0x8b)) {
|
||||||
error_msg("Invalid gzip magic");
|
error_msg("Invalid gzip magic");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the compression method */
|
/* Check the compression method */
|
||||||
if (fgetc(in_file) != 8) {
|
if (fgetc(l_in_file) != 8) {
|
||||||
error_msg("Unknown compression method");
|
error_msg("Unknown compression method");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = (unsigned char) fgetc(in_file);
|
flags = (unsigned char) fgetc(l_in_file);
|
||||||
|
|
||||||
/* Ignore time stamp(4), extra flags(1), OS type(1) */
|
/* Ignore time stamp(4), extra flags(1), OS type(1) */
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
fgetc(in_file);
|
fgetc(l_in_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & 0x04) {
|
if (flags & 0x04) {
|
||||||
/* bit 2 set: extra field present */
|
/* bit 2 set: extra field present */
|
||||||
const unsigned short extra = fgetc(in_file) + (fgetc(in_file) << 8);
|
const unsigned short extra = fgetc(l_in_file) + (fgetc(l_in_file) << 8);
|
||||||
|
|
||||||
for (i = 0; i < extra; i++) {
|
for (i = 0; i < extra; i++) {
|
||||||
fgetc(in_file);
|
fgetc(l_in_file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Discard original name if any */
|
/* Discard original name if any */
|
||||||
if (flags & 0x08) {
|
if (flags & 0x08) {
|
||||||
/* bit 3 set: original file name present */
|
/* bit 3 set: original file name present */
|
||||||
while (fgetc(in_file) != 0); /* null */
|
while (fgetc(l_in_file) != 0); /* null */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Discard file comment if any */
|
/* Discard file comment if any */
|
||||||
if (flags & 0x10) {
|
if (flags & 0x10) {
|
||||||
/* bit 4 set: file comment present */
|
/* bit 4 set: file comment present */
|
||||||
while (fgetc(in_file) != 0); /* null */
|
while (fgetc(l_in_file) != 0); /* null */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decompress */
|
/* Decompress */
|
||||||
if (inflate() != 0) {
|
if (inflate(l_in_file, l_out_file) != 0) {
|
||||||
error_msg("invalid compressed data--format violated");
|
error_msg("invalid compressed data--format violated");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -972,7 +973,7 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file)
|
|||||||
* crc32 (see algorithm.doc)
|
* crc32 (see algorithm.doc)
|
||||||
* uncompressed input size modulo 2^32
|
* uncompressed input size modulo 2^32
|
||||||
*/
|
*/
|
||||||
fread(buf, 1, 8, in_file);
|
fread(buf, 1, 8, l_in_file);
|
||||||
|
|
||||||
/* Validate decompression - crc */
|
/* Validate decompression - crc */
|
||||||
if ((unsigned int)((buf[0] | (buf[1] << 8)) |((buf[2] | (buf[3] << 8)) << 16)) != (crc ^ 0xffffffffL)) {
|
if ((unsigned int)((buf[0] | (buf[1] << 8)) |((buf[2] | (buf[3] << 8)) << 16)) != (crc ^ 0xffffffffL)) {
|
||||||
@ -983,14 +984,11 @@ extern int unzip(FILE *l_in_file, FILE *l_out_file)
|
|||||||
error_msg("invalid compressed data--length error");
|
error_msg("invalid compressed data--length error");
|
||||||
}
|
}
|
||||||
|
|
||||||
free(window);
|
|
||||||
free(crc_table);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This needs access to global variables wondow and crc_table, so its not in its own file.
|
* This needs access to global variables window and crc_table, so its not in its own file.
|
||||||
*/
|
*/
|
||||||
extern void gz_close(int gunzip_pid)
|
extern void gz_close(int gunzip_pid)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user