if (inflateEnd(&zs) < 0) {
free(out);
return (NULL);
}
if (size_out) {
*size_out = entry->isize;
}
return (out);
} else
return (NULL);
}
/*
* A very little used routine to handle the case that zip file has
* a comment at the end. Believe it or not, the only way to find the
* END record is to walk backwards, byte by bloody byte looking for
* the END record signature.
*
* fd: File descriptor of the jar file.
* eb: Pointer to a buffer to receive a copy of the END header.
*
* Returns the offset of the END record in the file on success,
* -1 on failure.
*/
static off_t
find_end(int fd, Byte *eb)
{
off_t len;
off_t pos;
off_t flen;
int bytes;
Byte *cp;
Byte *endpos;
Byte *buffer;
/*
* 99.44% (or more) of the time, there will be no comment at the
* end of the zip file. Try reading just enough to read the END
* record from the end of the file.
*/
if ((pos = lseek(fd, -ENDHDR, SEEK_END)) < (off_t)0)
return (-1);
if ((bytes = read(fd, eb, ENDHDR)) < 0)
return (-1);
if (GETSIG(eb) == ENDSIG)
return (pos);
/*
* Shucky-Darn,... There is a comment at the end of the zip file.
*
* Allocate and fill a buffer with enough of the zip file
* to meet the specification for a maximal comment length.
*/
if ((flen = lseek(fd, 0, SEEK_END)) < (off_t)0)
return (-1);
len = (flen < END_MAXLEN) ? flen : END_MAXLEN;
if (lseek(fd, -len, SEEK_END) < (off_t)0)
return (-1);
if ((buffer = malloc(END_MAXLEN)) == NULL)
return (-1);
if ((bytes = read(fd, buffer, len)) < 0) {
free(buffer);
return (-1);
}
/*
* Search backwards from the end of file stopping when the END header
* signature is found. (The first condition of the "if" is just a
* fast fail, because the GETSIG macro isn't always cheap. The
* final condition protects against false positives.)
*/
endpos = &buffer[bytes];
for (cp = &buffer[bytes - ENDHDR]; cp >= &buffer[0]; cp--)
if ((*cp == (ENDSIG & 0xFF)) && (GETSIG(cp) == ENDSIG) &&
(cp + ENDHDR + ENDCOM(cp) == endpos)) {
(void) memcpy(eb, cp, ENDHDR);
free(buffer);
return (flen - (endpos - cp));
}
free(buffer);
return (-1);
}
/*
* Locate the manifest file with the zip/jar file.
*
* fd: File descriptor of the jar file.
* entry: To be populated with the information necessary to perform
* the inflation (the compressed and uncompressed sizes and
* the offset in the file where the compressed data is located).
*
* Returns zero upon success. Returns a negative value upon failure.
*
* The buffer for reading the Central Directory if the zip/jar file needs
* to be large enough to accommodate the largest possible single record
* and the signature of the next record which is:
*
* 3*2**16 + CENHDR + SIGSIZ
*
* Each of the three variable sized fields (name, comment and extension)
=2= |