📄 jar.c
字号:
/*0233*/ /* Set currentOffset to be the offset of buffer[0] */
/*0234*/ currentOffset = minOffset;
/*0235*/ /* Set bp to be the location at which to start looking */
/*0236*/ bp = jarFile + length - ENDHDRSIZ; /* Where to start looking */
/*0237*/#endif /* JAR_FILES_USE_STDIO */
/*0238*/
/*0239*/ for (;;) {
/*0240*/ /* "buffer" contains a block of data from the file, starting at
/*0241./ * currentOffset "position" in the file.
/*0242./ * We investigate whether currentOffset + (bp - buffer) is the start
/*0243./ * of the end header in the zip file.
/*0244./ *
/*0245./ * We use a simplified version of Knuth-Morris-Pratt search algorithm.
/*0246./ * The header we're looking for is 'P' 'K' 5 6
/*0247./ */
/*0248*/ switch(bp[0]) {
/*0249*/ case '\006': /* The header must start at least 3 bytes back */
/*0250*/ bp -= 3; break;
/*0251*/ case '\005': /* The header must start at least 2 bytes back */
/*0252*/ bp -= 2; break;
/*0253*/ case 'K': /* The header must start at least 1 byte back */
/*0254*/ bp -= 1; break;
/*0255*/ case 'P': /* Either this is the header, or the header must
/*0256./ * start at least 4 back */
/*0257*/ if (bp[1] == 'K' && bp[2] == 5 && bp[3] == 6) {
/*0258*/ /* We have what may be a header. Let's make sure the
/*0259./ * implied length of the jar file matches the actual
/*0260./ * length.
/*0261./ */
/*0262*/ int endpos = currentOffset + (bp - buffer);
/*0263*/ if (endpos + ENDHDRSIZ + ENDCOM(bp) == length) {
/*0264*/ unsigned long cenOffset = endpos - ENDSIZ(bp);
/*0265*/ unsigned long locOffset = cenOffset - ENDOFF(bp);
/*0266*/#if JAR_FILES_USE_STDIO
/*0267*/ if ( fseek(file, locOffset, SEEK_SET) >= 0
/*0268*/ && getc(file) == 'P' && getc(file) == 'K'
/*0269*/ && getc(file) == 3 && getc(file) == 4) {
/*0270*/ entry->u.jar.file = file;
/*0271*/ entry->u.jar.cenOffset = cenOffset;
/*0272*/ entry->u.jar.locOffset = locOffset;
/*0273*/ return TRUE;
/*0274*/ }
/*0275*/#else
/*0276*/ const unsigned char *cenPtr = jarFile + cenOffset;
/*0277*/ const unsigned char *locPtr = jarFile + locOffset;
/*0278*/ if (GETSIG(locPtr) == LOCSIG) {
/*0279*/ entry->u.mjar.base = jarFile;
/*0280*/ entry->u.mjar.cenPtr = cenPtr;
/*0281*/ entry->u.mjar.locPtr = locPtr;
/*0282*/ return TRUE;
/*0283*/ }
/*0284*/#endif /* JAR_FILES_USE_STDIO */
/*0285*/
/*0286*/ goto failureReturn;
/*0287*/ }
/*0288*/ }
/*0289*/ /* FALL THROUGH */
/*0290*/ default:
/*0291*/ /* The header must start at least four characters back, since
/*0292./ * the current character isn't in the header */
/*0293*/ bp -= 4;
/*0294*/ }
/*0295*/ if (bp < buffer) {
/*0296*/#if JAR_FILES_USE_STDIO
/*0297*/ /* We've moved outside our window into the file. We must
/*0298./ * move the window backwards */
/*0299*/ int count = currentOffset - minOffset; /* Bytes left in file */
/*0300*/ if (count == 0) {
/*0301*/ /* Nothing left to read. Time to give up */
/*0302*/ goto failureReturn;
/*0303*/ } else {
/*0304*/ /* up to ((bp - buffer) + ENDHDRSIZ) bytes in the buffer might
/*0305./ * still be part of the end header, so the most bytes we can
/*0306./ * actually read are
/*0307./ * bufferSize - ((bp - buffer) + ENDHDRSIZE).
/*0308./ */
/*0309*/ int available = (bufferSize - ENDHDRSIZ) + (buffer - bp);
/*0310*/ if (count > available) {
/*0311*/ count = available;
/*0312*/ }
/*0313*/ }
/*0314*/ /* Back up, while keeping our virtual currentOffset the same */
/*0315*/ currentOffset -= count;
/*0316*/ bp += count;
/*0317*/ memmove(buffer + count, buffer, bufferSize - count);
/*0318*/ if ( (fseek(file, currentOffset, SEEK_SET) < 0)
/*0319*/ || (fread(buffer, sizeof(char), count, file)
/*0320*/ != (unsigned)count)) {
/*0321*/ goto failureReturn;
/*0322*/ }
/*0323*/#else
/*0324*/ /* There's nothing left to do. */
/*0325*/ goto failureReturn;
/*0326*/#endif /* JAR_FILE_USE_STDIO */
/*0327*/ }
/*0328*/ } /* end of for loop */
/*0329*/
/*0330*/failureReturn:
/*0331*/#if JAR_FILES_USE_STDIO
/*0332*/ if (file != NULL) {
/*0333*/ fclose(file);
/*0334*/ }
/*0335*/#endif /* JAR_FILES_USE_STDIO */
/*0336*/
/*0337*/ return FALSE;
/*0338*/}
/*0339*/
/*0340*//*=========================================================================
/*0341./ * FUNCTION: closeJARFile
/*0342./ * OVERVIEW: Close a jar file that had previous been opened by
/*0343./ * openJARFile
/*0344./ * parameters:
/*0345./ * JAR_INFO: structure previously filled in by openJARFile
/*0346./ *
/*0347./ * returns:
/*0348./ * nothing
/*0349./ *=======================================================================*/
/*0350*/
/*0351*/void
/*0352*/closeJARFile(JAR_INFO entry)
/*0353*/{
/*0354*/#if JAR_FILES_USE_STDIO
/*0355*/ fclose((FILE *)entry->u.jar.file);
/*0356*/#endif
/*0357*/}
/*0358*/
/*0359*//*=========================================================================
/*0360./ * FUNCTION: loadJARFileEntry()
/*0361./ * OVERVIEW: Reads an entry in a jar file
/*0362./ *
/*0363./ * INTERFACE:
/*0364./ * parameters: JAR_INFO: structure returned by openJARFile
/*0365./ * filename: name of entry to read
/*0366./ * lengthP: on return, contains length of entry in jar file
/*0367./ * (does >>NOT<< include extraBytes)
/*0368./ * extraBytes: value has this many extra bytes padded at the
/*0369./ * beginning.
/*0370./ *
/*0371./ * NOTE: The result is malloc'ed on the heap. It is up to the caller to protect
/*0372./ * this result from garbage collectino
/*0373./ *=======================================================================*/
/*0374*/
/*0375*/void *
/*0376*/loadJARFileEntry(JAR_INFO entry, const char *filename,
/*0377*/ long *lengthP, int extraBytes)
/*0378*/{
/*0379*/ unsigned int filenameLength = strlen(filename);
/*0380*/ unsigned int nameLength;
/*0381*/
/*0382*/#if JAR_FILES_USE_STDIO
/*0383*/ unsigned char *p = (unsigned char *)str_buffer; /* temporary storage */
/*0384*/ int offset = entry->u.jar.cenOffset; /* offset of first header */
/*0385*/ FILE *file = entry->u.jar.file;
/*0386*/#else
/*0387*/ unsigned const char *p = entry->u.mjar.cenPtr; /* pointer to first header */
/*0388*/#endif
/*0389*/
/*0390*/ while(TRUE) {
/*0391*/#if JAR_FILES_USE_STDIO
/*0392*/ /* Offset contains the offset of the next central header. Read the
/*0393./ * header into the temporary buffer */
/*0394*/ if (/* Go to the header */
/*0395*/ (fseek(file, offset, SEEK_SET) < 0)
/*0396*/ /* Read the bytes */
/*0397*/ || (fread(p, sizeof(char), CENHDRSIZ, file) != CENHDRSIZ)) {
/*0398*/ return NULL;
/*0399*/ }
/*0400*/#endif
/*0401*/ /* p contains the current central header */
/*0402*/ if (GETSIG(p) != CENSIG) {
/*0403*/ /* We've reached the end of the headers */
/*0404*/ return NULL;
/*0405*/ }
/*0406*/ nameLength = CENNAM(p);
/*0407*/ if (nameLength == filenameLength) {
/*0408*/#if JAR_FILES_USE_STDIO
/*0409*/ if (fread(p + CENHDRSIZ, sizeof(char), nameLength, file)
/*0410*/ != nameLength) {
/*0411*/ return NULL;
/*0412*/ }
/*0413*/#endif
/*0414*/ if (memcmp(p + CENHDRSIZ, filename, nameLength) == 0) {
/*0415*/ break;
/*0416*/ }
/*0417*/ }
/*0418*/
/*0419*/#if JAR_FILES_USE_STDIO
/*0420*/ /* Set offset to the next central header */
/*0421*/ offset += CENHDRSIZ + nameLength + CENEXT(p) + CENCOM(p);
/*0422*/#else
/*0423*/ /* Have p point to the next central header */
/*0424*/ p += CENHDRSIZ + nameLength + CENEXT(p) + CENCOM(p);
/*0425*/#endif
/*0426*/ }
/*0427*/ return loadJARFileEntryInternal(entry, p, lengthP, extraBytes);
/*0428*/}
/*0429*/
/*0430*//*=========================================================================
/*0431./ * FUNCTION: loadJARFileEntries()
/*0432./ * OVERVIEW: Reads multiple jar entries from a jar file
/*0433./ *
/*0434./ * INTERFACE:
/*0435./ * parameters: JAR_INFO: structure returned by openJARFile
/*0436./ * testFunction: callback to determine whether to read
/*0437./ * the specified file
/*0438./ * runFunction: callback called after each jar file is read.
/*0439./ * info: Info passed to testFunction and runFunction.
/*0440./ *
/*0441./ * NOTE: The jar files are malloc'ed on the heap. It is up to the caller
/*0442./ * to ensure that they are handled correctly.
/*0443./ *
/*0444./ * The testFuction is called as:
/*0445./ * bool_t testFunction(const char *name, int nameLength,
/*0446./ * int *extraBytes, void *info)
/*0447./ * It should return TRUE or FALSE, indicating whether to read the specified
/*0448./ * jar file or not.
/*0449./ * name: name of entry (not NULL terminated)
/*0450./ * nameLength: length of name
/*0451./ * extraBytes: *extraBytes contains 0, but the test function can
/*0452./ * change this to indicate that padding is needed at the
/*0453./ * beginning of the entry.
/*0454./ * info: Arg passed to loadJARFileEntries
/*0455./ *
/*0456./ * The runFunction is called for any entry for which the testFunction
/*0457./ * returned TRUE
/*0458./ * void runFunction(const char *name, int nameLength,
/*0459./ * void *value, long length, void*info);
/*0460./ * The arguments are as follows:
/*0461./ * name: name of entry (not NULL terminated)
/*0462./ * nameLength: length of name
/*0463./ * value: Decoded jar entry, or NULL if a problem.
/*0464./ * length: Length of jar file entry (not included extra bytes)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -