Date: Sat, 26 Apr 2003 12:18:17 +0100 From: "Richard Dawe" Sender: rich AT phekda DOT freeserve DOT co DOT uk To: djgpp-workers AT delorie DOT com X-Mailer: Emacs 21.3.50 (via feedmail 8.3.emacs20_6 I) and Blat ver 1.8.6 Subject: djtar and slightly weirdly formatted ZIPs [PATCH] Message-Id: Reply-To: djgpp-workers AT delorie DOT com Hello. I noticed the other day that djtar cannot extract the flex 2.54 binary package from Simtel.NET - v2gnu/flx254b.zip. This is because it has a slightly weird header. Before the normal ZIP local header it has the header "PK00". I can't find out what this is for. InfoZIP's unzip copes fine with this file. It seems to skip over headers until it finds the first local header. I've made djtar do this - below is a patch. It differs slightly from the InfoZIP approach, because it assumes that all ZIP file headers have a 4-byte identifier before the header data - PK, where a, b identify the header type. Something else I noticed is that the output for djtar -t is not consistent between ZIP and tar'd formats. For ZIPs it just lists the filenames. For tar files it lists attributes, dates and file sizes too. OK to commit? Thanks, bye, Rich =] Index: src/utils/djtar/epunzip.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/utils/djtar/epunzip.c,v retrieving revision 1.4 diff -p -u -3 -r1.4 epunzip.c --- src/utils/djtar/epunzip.c 17 Oct 2002 23:00:26 -0000 1.4 +++ src/utils/djtar/epunzip.c 26 Apr 2003 11:09:47 -0000 @@ -37,6 +37,8 @@ int epcopy(char *, long); void epunzip_read(char *zipfilename) { + int at_local_header = 0; + clear_bufs(); errno = 0; ifd = oread_open(zipfilename); @@ -46,28 +48,70 @@ epunzip_read(char *zipfilename) return; } + /* Find the first local header. Ignore all other headers until + * we find that. */ while(1) { - int buffer, ext_header, timedate, crc, size, length, name_length, - extra_length, should_be_written, count, real_file = 0; - char filename[2048]; + int buffer; + char c = get_byte(); - ((char *)&buffer)[0] = (char)get_byte(); + if (c != 'P') + { + /* not the start of a header - look further */ + continue; + } + + ((char *)&buffer)[0] = c; ((char *)&buffer)[1] = (char)get_byte(); if(*(short *)&buffer != *(short *)"PK") - { - fprintf(log_out, "%s: invalid zip file structure\n", zipfilename); - break; - } + continue; ((char *)&buffer)[0] = (char)get_byte(); ((char *)&buffer)[1] = (char)get_byte(); if(*(short *)&buffer != *(short *)"\3\4") { - /* not a local header - all done */ - break; + /* not a local header - look further */ + continue; + } + + at_local_header = 1; + break; + } + + if (!at_local_header) + fprintf(log_out, "%s: invalid zip file structure\n", zipfilename); + + if (at_local_header) while(1) + { + int buffer, ext_header, timedate, crc, size, length, name_length, + extra_length, should_be_written, count, real_file = 0; + char filename[2048]; + + if (!at_local_header) + { + ((char *)&buffer)[0] = (char)get_byte(); + ((char *)&buffer)[1] = (char)get_byte(); + + if(*(short *)&buffer != *(short *)"PK") + { + fprintf(log_out, "%s: invalid zip file structure\n", zipfilename); + break; + } + + ((char *)&buffer)[0] = (char)get_byte(); + ((char *)&buffer)[1] = (char)get_byte(); + + if(*(short *)&buffer != *(short *)"\3\4") + { + /* not a local header - all done */ + break; + } + } + else + { + at_local_header = 0; } /* version info - ignore it */