diff options
Diffstat (limited to 'memdisk/unzip.c')
-rw-r--r-- | memdisk/unzip.c | 411 |
1 files changed, 205 insertions, 206 deletions
diff --git a/memdisk/unzip.c b/memdisk/unzip.c index 15b3f7dc..9f198a20 100644 --- a/memdisk/unzip.c +++ b/memdisk/unzip.c @@ -24,11 +24,11 @@ #define memzero(s, n) memset ((s), 0, (n)) -typedef uint8_t uch; +typedef uint8_t uch; typedef uint16_t ush; typedef uint32_t ulg; -#define WSIZE 0x8000 /* Window size must be at least 32k, */ +#define WSIZE 0x8000 /* Window size must be at least 32k, */ /* and a power of two */ static uch *inbuf; /* input pointer */ @@ -39,13 +39,13 @@ static unsigned inbytes; /* valid bytes in inbuf */ static unsigned outcnt; /* bytes in output buffer */ /* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ -#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ -#define RESERVED 0xC0 /* bit 6,7: reserved */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ +#define RESERVED 0xC0 /* bit 6,7: reserved */ /* Diagnostic functions */ #ifdef DEBUG @@ -64,7 +64,7 @@ static unsigned outcnt; /* bytes in output buffer */ # define Tracecv(c,x) #endif -static int fill_inbuf(void); +static int fill_inbuf(void); static void flush_window(void); static void error(char *m); static void gzip_mark(void **); @@ -75,20 +75,20 @@ static ulg crc_32_tab[256]; /* Get byte from input buffer */ static inline uch get_byte(void) { - if ( inbytes ) { - uch b = *inbuf++; - inbytes--; - return b; - } else { - return fill_inbuf(); /* Input buffer underrun */ - } + if (inbytes) { + uch b = *inbuf++; + inbytes--; + return b; + } else { + return fill_inbuf(); /* Input buffer underrun */ + } } /* Unget byte from input buffer */ static inline void unget_byte(void) { - inbytes++; - inbuf--; + inbytes++; + inbuf--; } static ulg bytes_out = 0; /* Number of bytes output */ @@ -104,35 +104,36 @@ static ulg free_mem_ptr, free_mem_end_ptr; static void *malloc(int size) { - void *p; + void *p; - if (size < 0) error("malloc error"); + if (size < 0) + error("malloc error"); - free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ + free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ - p = (void *)free_mem_ptr; - free_mem_ptr += size; + p = (void *)free_mem_ptr; + free_mem_ptr += size; - if (free_mem_ptr >= free_mem_end_ptr) - error("out of memory"); + if (free_mem_ptr >= free_mem_end_ptr) + error("out of memory"); - return p; + return p; } static void free(void *where) { - /* Don't care */ - (void)where; + /* Don't care */ + (void)where; } static void gzip_mark(void **ptr) { - *ptr = (void *) free_mem_ptr; + *ptr = (void *)free_mem_ptr; } static void gzip_release(void **ptr) { - free_mem_ptr = (long) *ptr; + free_mem_ptr = (long)*ptr; } /* =========================================================================== @@ -141,10 +142,10 @@ static void gzip_release(void **ptr) */ static int fill_inbuf(void) { - /* This should never happen. We have already pointed the algorithm - to all the data we have. */ - printf("failed\nDecompression error: ran out of input data\n"); - die(); + /* This should never happen. We have already pointed the algorithm + to all the data we have. */ + printf("failed\nDecompression error: ran out of input data\n"); + die(); } /* =========================================================================== @@ -153,194 +154,192 @@ static int fill_inbuf(void) */ static void flush_window(void) { - ulg c = crc; /* temporary variable */ + ulg c = crc; /* temporary variable */ unsigned n; uch *in, *out, ch; - if ( bytes_out+outcnt > output_size ) - error("output buffer overrun"); + if (bytes_out + outcnt > output_size) + error("output buffer overrun"); in = window; out = output_data; for (n = 0; n < outcnt; n++) { - ch = *out++ = *in++; - c = crc_32_tab[(c ^ ch) & 0xff] ^ (c >> 8); + ch = *out++ = *in++; + c = crc_32_tab[(c ^ ch) & 0xff] ^ (c >> 8); } crc = c; output_data = out; - bytes_out += (ulg)outcnt; + bytes_out += (ulg) outcnt; outcnt = 0; } static void error(char *x) { - printf("failed\nDecompression error: %s\n", x); - die(); + printf("failed\nDecompression error: %s\n", x); + die(); } /* GZIP header */ struct gzip_header { - uint16_t magic; - uint8_t method; - uint8_t flags; - uint32_t timestamp; - uint8_t extra_flags; - uint8_t os_type; + uint16_t magic; + uint8_t method; + uint8_t flags; + uint32_t timestamp; + uint8_t extra_flags; + uint8_t os_type; } __attribute__ ((packed)); /* (followed by optional and variable length "extra", "original name", and "comment" fields) */ struct gzip_trailer { - uint32_t crc; - uint32_t dbytes; + uint32_t crc; + uint32_t dbytes; } __attribute__ ((packed)); /* PKZIP header. See * <http://www.pkware.com/products/enterprise/white_papers/appnote.html>. */ struct pkzip_header { - uint32_t magic; - uint16_t version; - uint16_t flags; - uint16_t method; - uint16_t modified_time; - uint16_t modified_date; - uint32_t crc; - uint32_t zbytes; - uint32_t dbytes; - uint16_t filename_len; - uint16_t extra_len; + uint32_t magic; + uint16_t version; + uint16_t flags; + uint16_t method; + uint16_t modified_time; + uint16_t modified_date; + uint32_t crc; + uint32_t zbytes; + uint32_t dbytes; + uint16_t filename_len; + uint16_t extra_len; } __attribute__ ((packed)); /* (followed by optional and variable length "filename" and "extra" fields) */ /* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ -#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ -#define RESERVED 0xC0 /* bit 6,7: reserved */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ +#define RESERVED 0xC0 /* bit 6,7: reserved */ /* pkzip flag byte */ -#define PK_ENCRYPTED 0x01 /* bit 0 set: file is encrypted */ -#define PK_DATADESC 0x08 /* bit 3 set: file has trailing "data - descriptor" */ -#define PK_UNSUPPORTED 0xFFF0 /* All other bits must be zero */ - +#define PK_ENCRYPTED 0x01 /* bit 0 set: file is encrypted */ +#define PK_DATADESC 0x08 /* bit 3 set: file has trailing "data + descriptor" */ +#define PK_UNSUPPORTED 0xFFF0 /* All other bits must be zero */ /* Return 0 if (indata, size) points to a ZIP file, and fill in compressed data size, uncompressed data size, CRC, and offset of data. If indata is not a ZIP file, return -1. */ -int check_zip(void *indata, uint32_t size, uint32_t *zbytes_p, - uint32_t *dbytes_p, uint32_t *orig_crc, uint32_t *offset_p) { - struct gzip_header *gzh = (struct gzip_header *)indata; - struct pkzip_header *pkzh = (struct pkzip_header *)indata; - uint32_t offset; - - if (gzh->magic == 0x8b1f) { - struct gzip_trailer *gzt = indata + size - sizeof (struct gzip_trailer); - /* We only support method #8, DEFLATED */ - if (gzh->method != 8) { - error("gzip file uses invalid method"); - return -1; - } - if (gzh->flags & ENCRYPTED) { - error("gzip file is encrypted; not supported"); - return -1; - } - if (gzh->flags & CONTINUATION) { - error("gzip file is a continuation file; not supported"); - return -1; - } - if (gzh->flags & RESERVED) { - error("gzip file has unsupported flags"); - return -1; - } - offset = sizeof (*gzh); - if (gzh->flags & EXTRA_FIELD) { - /* Skip extra field */ - unsigned len = *(unsigned *)(indata + offset); - offset += 2 + len; - } - if (gzh->flags & ORIG_NAME) { - /* Discard the old name */ - uint8_t *p = indata; - while (p[offset] != 0 && offset < size) { - offset++; - } - offset++; - } - - if (gzh->flags & COMMENT) { - /* Discard the comment */ - uint8_t *p = indata; - while (p[offset] != 0 && offset < size) { - offset++; - } - offset++; - } - - if (offset > size) { - error ("gzip file corrupt"); - return -1; - } - *zbytes_p = size - offset - sizeof (struct gzip_trailer); - *dbytes_p = gzt->dbytes; - *orig_crc = gzt->crc; - *offset_p = offset; - return 0; - } - else if (pkzh->magic == 0x04034b50UL) { - /* Magic number matches pkzip file. */ - - offset = sizeof (*pkzh); - if (pkzh->flags & PK_ENCRYPTED) { - error("pkzip file is encrypted; not supported"); - return -1; - } - if (pkzh->flags & PK_DATADESC) { - error("pkzip file uses data_descriptor field; not supported"); - return -1; - } - if (pkzh->flags & PK_UNSUPPORTED) { - error("pkzip file has unsupported flags"); - return -1; - } - - /* We only support method #8, DEFLATED */ - if (pkzh->method != 8) { - error("pkzip file uses invalid method"); - return -1; - } - /* skip header */ - offset = sizeof (*pkzh); - /* skip filename */ - offset += pkzh->filename_len; - /* skip extra field */ - offset += pkzh->extra_len; - - if (offset + pkzh->zbytes > size) { - error ("pkzip file corrupt"); - return -1; +int check_zip(void *indata, uint32_t size, uint32_t * zbytes_p, + uint32_t * dbytes_p, uint32_t * orig_crc, uint32_t * offset_p) +{ + struct gzip_header *gzh = (struct gzip_header *)indata; + struct pkzip_header *pkzh = (struct pkzip_header *)indata; + uint32_t offset; + + if (gzh->magic == 0x8b1f) { + struct gzip_trailer *gzt = indata + size - sizeof(struct gzip_trailer); + /* We only support method #8, DEFLATED */ + if (gzh->method != 8) { + error("gzip file uses invalid method"); + return -1; + } + if (gzh->flags & ENCRYPTED) { + error("gzip file is encrypted; not supported"); + return -1; + } + if (gzh->flags & CONTINUATION) { + error("gzip file is a continuation file; not supported"); + return -1; + } + if (gzh->flags & RESERVED) { + error("gzip file has unsupported flags"); + return -1; + } + offset = sizeof(*gzh); + if (gzh->flags & EXTRA_FIELD) { + /* Skip extra field */ + unsigned len = *(unsigned *)(indata + offset); + offset += 2 + len; + } + if (gzh->flags & ORIG_NAME) { + /* Discard the old name */ + uint8_t *p = indata; + while (p[offset] != 0 && offset < size) { + offset++; + } + offset++; + } + + if (gzh->flags & COMMENT) { + /* Discard the comment */ + uint8_t *p = indata; + while (p[offset] != 0 && offset < size) { + offset++; + } + offset++; + } + + if (offset > size) { + error("gzip file corrupt"); + return -1; + } + *zbytes_p = size - offset - sizeof(struct gzip_trailer); + *dbytes_p = gzt->dbytes; + *orig_crc = gzt->crc; + *offset_p = offset; + return 0; + } else if (pkzh->magic == 0x04034b50UL) { + /* Magic number matches pkzip file. */ + + offset = sizeof(*pkzh); + if (pkzh->flags & PK_ENCRYPTED) { + error("pkzip file is encrypted; not supported"); + return -1; + } + if (pkzh->flags & PK_DATADESC) { + error("pkzip file uses data_descriptor field; not supported"); + return -1; + } + if (pkzh->flags & PK_UNSUPPORTED) { + error("pkzip file has unsupported flags"); + return -1; + } + + /* We only support method #8, DEFLATED */ + if (pkzh->method != 8) { + error("pkzip file uses invalid method"); + return -1; + } + /* skip header */ + offset = sizeof(*pkzh); + /* skip filename */ + offset += pkzh->filename_len; + /* skip extra field */ + offset += pkzh->extra_len; + + if (offset + pkzh->zbytes > size) { + error("pkzip file corrupt"); + return -1; + } + + *zbytes_p = pkzh->zbytes; + *dbytes_p = pkzh->dbytes; + *orig_crc = pkzh->crc; + *offset_p = offset; + return 0; + } else { + /* Magic number does not match. */ + return -1; } - *zbytes_p = pkzh->zbytes; - *dbytes_p = pkzh->dbytes; - *orig_crc = pkzh->crc; - *offset_p = offset; - return 0; - } - else { - /* Magic number does not match. */ + error("Internal error in check_zip"); return -1; - } - - error ("Internal error in check_zip"); - return -1; } /* @@ -351,40 +350,40 @@ int check_zip(void *indata, uint32_t size, uint32_t *zbytes_p, extern void _end; void *unzip(void *indata, uint32_t zbytes, uint32_t dbytes, - uint32_t orig_crc, void *target) + uint32_t orig_crc, void *target) { - /* Set up the heap; it's the 64K after the bounce buffer */ - free_mem_ptr = (ulg)sys_bounce + 0x10000; - free_mem_end_ptr = free_mem_ptr + 0x10000; - - /* Set up input buffer */ - inbuf = indata; - /* Sometimes inflate() looks beyond the end of the compressed data, - but it always backs up before it is done. So we give it 4 bytes - of slack. */ - insize = inbytes = zbytes + 4; - - /* Set up output buffer */ - outcnt = 0; - output_data = target; - output_size = dbytes; - bytes_out = 0; + /* Set up the heap; it's the 64K after the bounce buffer */ + free_mem_ptr = (ulg) sys_bounce + 0x10000; + free_mem_end_ptr = free_mem_ptr + 0x10000; + + /* Set up input buffer */ + inbuf = indata; + /* Sometimes inflate() looks beyond the end of the compressed data, + but it always backs up before it is done. So we give it 4 bytes + of slack. */ + insize = inbytes = zbytes + 4; + + /* Set up output buffer */ + outcnt = 0; + output_data = target; + output_size = dbytes; + bytes_out = 0; - makecrc(); - gunzip(); + makecrc(); + gunzip(); - /* Verify that gunzip() consumed the entire input. */ - if (inbytes != 4) - error("compressed data length error"); + /* Verify that gunzip() consumed the entire input. */ + if (inbytes != 4) + error("compressed data length error"); - /* Check the uncompressed data length and CRC. */ - if ( bytes_out != dbytes ) - error("uncompressed data length error"); + /* Check the uncompressed data length and CRC. */ + if (bytes_out != dbytes) + error("uncompressed data length error"); - if (orig_crc != CRC_VALUE) - error("crc error"); + if (orig_crc != CRC_VALUE) + error("crc error"); - puts("ok\n"); + puts("ok\n"); - return target; + return target; } |