📄 jar.c
字号:
/*0001*//*
/*0002./ * Copyright (c) 1998-2001 Sun Microsystems, Inc. All Rights Reserved.
/*0003./ *
/*0004./ * This software is the confidential and proprietary information of Sun
/*0005./ * Microsystems, Inc. ("Confidential Information"). You shall not
/*0006./ * disclose such Confidential Information and shall use it only in
/*0007./ * accordance with the terms of the license agreement you entered into
/*0008./ * with Sun.
/*0009./ *
/*0010./ * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
/*0011./ * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
/*0012./ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
/*0013./ * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
/*0014./ * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
/*0015./ * THIS SOFTWARE OR ITS DERIVATIVES.
/*0016./ *
/*0017./ */
/*0018*/
/*0019*//*=========================================================================
/*0020./ * SYSTEM: KVM
/*0021./ * SUBSYSTEM: JAR file reader / inflater.
/*0022./ * FILE: jar.c
/*0023./ * OVERVIEW: Structures and operations for reading a jar file.
/*0024./ * The JAR file can either be a file, or it can be mapped
/*0025./ * into memory.
/*0026./ * AUTHOR: Tasneem Sayeed, Consumer & Embedded division
/*0027./ * Frank Yellin
/*0028./ *=======================================================================*/
/*0029*/
/*0030*//*=========================================================================
/*0031./ * Include files
/*0032./ *=======================================================================*/
/*0033*/
/*0034*/#include <global.h>
/*0035*/#include <jar.h>
/*0036*/#include <inflate.h>
/*0037*/
/*0038*//* Assume that we're being compiled as part of the KVM, unless told
/*0039./ * otherwise
/*0040./ */
/*0041*/#ifndef COMPILING_FOR_KVM
/*0042*/# define COMPILING_FOR_KVM 1
/*0043*/#endif
/*0044*/
/*0045*//* Change some definitions so that this compiles niceless, even if it
/*0046./ * compiled as part of something that requires real malloc() and free()
/*0047./ */
/*0048*/#if !COMPILING_FOR_KVM
/*0049*/# undef START_TEMPORARY_ROOTS
/*0050*/# undef END_TEMPORARY_ROOTS
/*0051*/# undef DECLARE_TEMPORARY_ROOT
/*0052*/# undef DECLARE_TEMPORARY_ROOT_FROM_BASE
/*0053*/# define START_TEMPORARY_ROOTS {
/*0054*/# define END_TEMPORARY_ROOTS }
/*0055*/# define mallocBytes(x) malloc(x)
/*0056*/# define DECLARE_TEMPORARY_ROOT(type, name, value) type name = value
/*0057*/# define DECLARE_TEMPORARY_ROOT_FROM_BASE(type, name, value, base) \
/*0058*/ type name = value
/*0059*/# define freeBytes(x)
/*0060*/#else
/*0061*/# define freeBytes(x) free(x)
/*0062*/#endif
/*0063*/
/*0064*/#if JAR_FILES_USE_STDIO
/*0065*/#include <stdio.h>
/*0066*/#endif
/*0067*/
/*0068*//*=========================================================================
/*0069./ * Forward declarations of static functions
/*0070./ *=======================================================================*/
/*0071*/
/*0072*/static void *loadJARFileEntryInternal(JAR_INFO entry,
/*0073*/ const unsigned char *centralInfo,
/*0074*/ long *lengthP, int extraBytes);
/*0075*/
/*0076*/static unsigned long jarCRC32(unsigned char *data, unsigned long length);
/*0077*/
/*0078*/static int jar_getByte(void* p);
/*0079*/
/*0080*//*=========================================================================
/*0081./ * JAR Data Stream structure
/*0082./ *=======================================================================*/
/*0083*/
/*0084*/#define LOCSIG (('P' << 0) + ('K' << 8) + (3 << 16) + (4 << 24))
/*0085*/#define CENSIG (('P' << 0) + ('K' << 8) + (1 << 16) + (2 << 24))
/*0086*/#define ENDSIG (('P' << 0) + ('K' << 8) + (5 << 16) + (6 << 24))
/*0087*/
/*0088*//*
/*0089./ * Supported compression types
/*0090./ */
/*0091*/#define STORED 0
/*0092*/#define DEFLATED 8
/*0093*/
/*0094*//*
/*0095./ * Header sizes including signatures
/*0096./ */
/*0097*/#define LOCHDRSIZ 30
/*0098*/#define CENHDRSIZ 46
/*0099*/#define ENDHDRSIZ 22
/*0100*/
/*0101*//*
/*0102./ * Header field access macros
/*0103./ */
/*0104*/#define CH(b, n) ((long)(((unsigned char *)(b))[n]))
/*0105*/#define SH(b, n) ((long)(CH(b, n) | (CH(b, n+1) << 8)))
/*0106*/#define LG(b, n) ((long)(SH(b, n) | (SH(b, n+2) << 16)))
/*0107*/
/*0108*/#define GETSIG(b) LG(b, 0) /* signature */
/*0109*/
/*0110*//*
/*0111./ * Macros for getting local file header (LOC) fields
/*0112./ */
/*0113*/#define LOCVER(b) SH(b, 4) /* version needed to extract */
/*0114*/#define LOCFLG(b) SH(b, 6) /* encrypt flags */
/*0115*/#define LOCHOW(b) SH(b, 8) /* compression method */
/*0116*/#define LOCTIM(b) LG(b, 10) /* modification time */
/*0117*/#define LOCCRC(b) LG(b, 14) /* uncompressed file crc-32 value */
/*0118*/#define LOCSIZ(b) LG(b, 18) /* compressed size */
/*0119*/#define LOCLEN(b) LG(b, 22) /* uncompressed size */
/*0120*/#define LOCNAM(b) SH(b, 26) /* filename size */
/*0121*/#define LOCEXT(b) SH(b, 28) /* extra field size */
/*0122*/
/*0123*//*
/*0124./ * Macros for getting central directory header (CEN) fields
/*0125./ */
/*0126*/#define CENVEM(b) SH(b, 4) /* version made by */
/*0127*/#define CENVER(b) SH(b, 6) /* version needed to extract */
/*0128*/#define CENFLG(b) SH(b, 8) /* general purpose bit flags */
/*0129*/#define CENHOW(b) SH(b, 10) /* compression method */
/*0130*/#define CENTIM(b) LG(b, 12) /* file modification time (DOS format) */
/*0131*/#define CENCRC(b) LG(b, 16) /* crc of uncompressed data */
/*0132*/#define CENSIZ(b) LG(b, 20) /* compressed size */
/*0133*/#define CENLEN(b) LG(b, 24) /* uncompressed size */
/*0134*/#define CENNAM(b) SH(b, 28) /* length of filename */
/*0135*/#define CENEXT(b) SH(b, 30) /* length of extra field */
/*0136*/#define CENCOM(b) SH(b, 32) /* file comment length */
/*0137*/#define CENDSK(b) SH(b, 34) /* disk number start */
/*0138*/#define CENATT(b) SH(b, 36) /* internal file attributes */
/*0139*/#define CENATX(b) LG(b, 38) /* external file attributes */
/*0140*/#define CENOFF(b) LG(b, 42) /* offset of local header */
/*0141*/
/*0142*//*
/*0143./ * Macros for getting end of central directory header (END) fields
/*0144./ */
/*0145*/#define ENDSUB(b) SH(b, 8) /* number of entries on this disk */
/*0146*/#define ENDTOT(b) SH(b, 10) /* total number of entries */
/*0147*/#define ENDSIZ(b) LG(b, 12) /* central directory size */
/*0148*/#define ENDOFF(b) LG(b, 16) /* central directory offset */
/*0149*/#define ENDCOM(b) SH(b, 20) /* size of zip file comment */
/*0150*/
/*0151*//*=========================================================================
/*0152./ * JAR file reading operations
/*0153./ *=======================================================================*/
/*0154*/
/*0155*//*=========================================================================
/*0156./ * FUNCTION: openJARFile
/*0157./ * OVERVIEW: Opens a Jar file so that it can be read using
/*0158./ * loadJARFileEntry or by loadJARFileEntries
/*0159./ *
/*0160./ * This function has two slightly different calling sequences, depending on
/*0161./ * whether JAR files are read using STDIO (JAR_FILES_USE_STDIO) or whether
/*0162./ * they are already in memory:
/*0163./ * parameters:
/*0164./ * nameOrAddress:
/*0165./ * JAR_FILES_USE_STDIO: name of the jar file
/*0166./ * !JAR_FILES_USE_STDIO: address of the jar file
/*0167./ * length:
/*0168./ * JAR_FILES_USE_STDIO: ignored
/*0169./ * !JAR_FILES_USE_STDIO: length of the jar file
/*0170./ * entry:
/*0171./ * Address of data structure that is filled in with information about
/*0172./ * the JAR file, if the "open" is successful.
/*0173./ *
/*0174./ * returns:
/*0175./ * TRUE if the "open" succeeds, false otherwise.
/*0176./ *=======================================================================*/
/*0177*/
/*0178*/bool_t
/*0179*/openJARFile(void *nameOrAddress, int length, JAR_INFO entry)
/*0180*/{
/*0181*/ long currentOffset, minOffset;
/*0182*/ unsigned const char *bp;
/*0183*/
/*0184*/#if JAR_FILES_USE_STDIO
/*0185*/ unsigned char *buffer = (unsigned char *)str_buffer;
/*0186*/ unsigned const int bufferSize = STRINGBUFFERSIZE;
/*0187*/
/*0188*/ FILE *file = fopen((char *)nameOrAddress, "rb");
/*0189*/ if (file == NULL) {
/*0190*/ goto failureReturn;
/*0191*/ }
/*0192*/ /* Get the length of the file */
/*0193*/ fseek(file, 0, SEEK_END);
/*0194*/ length = ftell(file);
/*0195*/ fseek(file, 0, SEEK_SET);
/*0196*/#else
/*0197*/ const unsigned char *jarFile = nameOrAddress;
/*0198*/ const unsigned char *buffer;
/*0199*/#endif /* JAR_FILES_USE_STDIO */
/*0200*/
/*0201*/ /* Calculate the smallest possible offset for the end header. It
/*0202./ * can be at most 0xFFFF + ENDHDRSIZ bytes from the end of the file, but
/*0203./ * the file must also have a local header and a central header
/*0204./ */
/*0205*/ minOffset = length - (0xFFFF + ENDHDRSIZ);
/*0206*/ if (minOffset < LOCHDRSIZ + CENHDRSIZ) {
/*0207*/ minOffset = LOCHDRSIZ + CENHDRSIZ;
/*0208*/ }
/*0209*/
/*0210*/ /* In order to simplify the code, both JAR_FILES_USE_STDIO and
/*0211./ * !JAR_FILES_USE_STDIO assume that "buffer" contains the contents
/*0212./ * of part of the file. currentOffset contains the offset of buffer[0].
/*0213./ *
/*0214./ * For JAR_FILES_USE_STDIO, buffer is a temporary buffer into which we
/*0215./ * read the contents of the file. For !JAR_FILES_USE_STDIO, buffer
/*0216./ * is a pointer into the actual jar file.
/*0217./ */
/*0218*/
/*0219*/#if JAR_FILES_USE_STDIO
/*0220*/ /* Read in the last ENDHDRSIZ bytes into the buffer. 99% of the time,
/*0221./ * the file won't have a comment, and this is the only read we'll need */
/*0222*/ if ( (fseek(file, -ENDHDRSIZ, SEEK_END) < 0)
/*0223*/ || (fread(buffer, sizeof(char), ENDHDRSIZ, file) != ENDHDRSIZ)) {
/*0224*/ goto failureReturn;
/*0225*/ }
/*0226*/ /* Set currentOffset to be the offset of buffer[0] */
/*0227*/ currentOffset = length - ENDHDRSIZ;
/*0228*/ /* Set bp to be the location at which to start looking */
/*0229*/ bp = buffer;
/*0230*/#else
/*0231*/ /* Create a pseudo buffer, that actually points at the jarFile */
/*0232*/ buffer = jarFile + minOffset;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -