Date: Tue, 19 Feb 2002 20:40:02 -0800 (PST) From: "Vadim Mikhailov" <mvp@braz.ru> To: freebsd-ports@FreeBSD.org Subject: Re: ports/33170: zip -T [zip file] fails with message about missing end signature Message-ID: <200202200440.g1K4e2S04126@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR ports/33170; it has been noted by GNATS. From: "Vadim Mikhailov" <mvp@braz.ru> To: <freebsd-gnats-submit@FreeBSD.org>, <idart@hotmail.com> Cc: Subject: Re: ports/33170: zip -T [zip file] fails with message about missing end signature Date: Tue, 19 Feb 2002 20:34:38 -0800 I have run into the same problem on FreeBSD/alpha system. Apparently, I have figured out what's going on. It has nothing to do with 64-bit alignment or endianness. It's all about long-standing bug in FreeBSD - http://www.freebsd.org/cgi/query-pr.cgi?pr=kern%2F6184 Let's take a look at infozip source, file zipfile.c around line 669: ... if (fseek(f, -4096L, SEEK_END) == 0) { zipbeg = (ulg) (ftell(f) + 4096L); while (!found && zipbeg >= 4096) { zipbeg -= 4096L; buf[4096] = t[1]; buf[4097] = t[2]; buf[4098] = t[3]; /* * XXX error check ?? */ fread(buf, 1, 4096, f); fseek(f, -8192L, SEEK_CUR); t = &buf[4095]; ... "f" in this context file handle of archive to be processed. If size of that archive is less than 4096 that means first fseek(f, -4096, SEEK_END) would try to seek to negative file offset. I found out that in this case fseek does not return an error and ftell(f) yields negative result! Of course, this does not make any sense. If archive size is between 4096 and 8192 bytes it would mean that second fseek(f, -8192, SEEK_CUR) also could try to do negative seek. Later this code tries to fseek(f, 0, SEEK_SET) but it does not help much - errno would be 27 (file too big) and everything blows up. I think that fseek should return an error (-1) to negative offset. I have checked what happens on other platforms. On FreeBSD/i386 negative fseek succeeds, but later fseek(f, 0, SEEK_SET) does not give any errors - i.e. this negative fseek works without being caught. On linux negative fseek returns an error. Proper fix for this situation would be apply fix mentioned in kern/6184 to kernel. But I also wrote patch for infozip to avoid even trying negative seeks, so it works without kernel patching: =========================================== --- zipfile.c.orig Sun Nov 7 02:30:11 1999 +++ zipfile.c Tue Feb 19 19:41:10 2002 @@ -628,6 +628,16 @@ #endif /* !UTIL */ +local long fsize(FILE *f) { + long size, curpos; + if(!f) return 0; + curpos = ftell(f); + fseek(f, 0, SEEK_END); + size = ftell(f); + fseek(f, curpos, SEEK_SET); + return size; +} + /* * scanzipf_reg starts searching for the End Signature at the end of the file * The End Signature points to the Central Directory Signature which points @@ -667,7 +677,7 @@ t[1] = '\0'; t[2] = '\0'; t[3] = '\0'; - if (fseek(f, -4096L, SEEK_END) == 0) { + if (fsize(f)>=4096L && fseek(f, -4096L, SEEK_END) == 0) { zipbeg = (ulg) (ftell(f) + 4096L); while (!found && zipbeg >= 4096) { zipbeg -= 4096L; @@ -678,7 +688,7 @@ * XXX error check ?? */ fread(buf, 1, 4096, f); - fseek(f, -8192L, SEEK_CUR); + if(ftell(f)>=8192L) fseek(f, -8192L, SEEK_CUR); t = &buf[4095]; /* * XXX far pointer arithmetic in DOS =========================================== It would be great if someone could commit this patch to ports tree as /usr/ports/archivers/zip/files/patch-negativeseek or something. I have checked that with this patch zip works fine for both i386 and alpha. In the meantime if someone could commit fix proposed in kern/6184 it won't hurt as well. Vadim Mikhailov To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-ports" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200202200440.g1K4e2S04126>