jar.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 546 行 · 第 1/2 页
C
546 行
/* * * * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */#include <stdio.h>#include <string.h>#include <jar.h>/** * @file * JAR file reading operations. *//*========================================================================= * JAR Data Stream structure *=======================================================================*/#define LOCSIG (('P' << 0) + ('K' << 8) + (3 << 16) + (4 << 24))#define CENSIG (('P' << 0) + ('K' << 8) + (1 << 16) + (2 << 24))#define ENDSIG (('P' << 0) + ('K' << 8) + (5 << 16) + (6 << 24))/* * Supported compression types */#define STORED 0#define DEFLATED 8/* * Header sizes including signatures */#define LOCHDRSIZ 30#define CENHDRSIZ 46#define ENDHDRSIZ 22/* * Header field access macros */#define CH(b, n) ((long)(((unsigned char *)(b))[n]))#define SH(b, n) ((long)(CH(b, n) | (CH(b, n+1) << 8)))#define LG(b, n) ((long)(SH(b, n) | (SH(b, n+2) << 16)))#define GETSIG(b) LG(b, 0) /* signature *//** Get local file header's version needed to extract */#define LOCVER(b) SH(b, 4)/** Get local file header's encrypt flags */#define LOCFLG(b) SH(b, 6)/** Get local file header's compression method */#define LOCHOW(b) SH(b, 8)/** Get local file header's modification time */#define LOCTIM(b) LG(b, 10)/** Get local file header's uncompressed file crc-32 value */#define LOCCRC(b) LG(b, 14)/** Get local file header's compressed size */#define LOCSIZ(b) LG(b, 18)/** Get local file header's uncompressed size */#define LOCLEN(b) LG(b, 22)/** Get local file header's filename size */#define LOCNAM(b) SH(b, 26)/** Get local file header's extra field size */#define LOCEXT(b) SH(b, 28)/** Get central directory header's version made by */#define CENVEM(b) SH(b, 4)/** Get central directory header's version needed to extract */#define CENVER(b) SH(b, 6)/** Get central directory header's general purpose bit flags */#define CENFLG(b) SH(b, 8)/** Get central directory header's compression method */#define CENHOW(b) SH(b, 10)/** Get central directory header's file modification time (DOS format) */#define CENTIM(b) LG(b, 12)/** Get central directory header's crc of uncompressed data */#define CENCRC(b) LG(b, 16)/** Get central directory header's compressed size */#define CENSIZ(b) LG(b, 20)/** Get central directory header's uncompressed size */#define CENLEN(b) LG(b, 24)/** Get central directory header's length of filename */#define CENNAM(b) SH(b, 28)/** Get central directory header's length of extra field */#define CENEXT(b) SH(b, 30)/** Get central directory header's file comment length */#define CENCOM(b) SH(b, 32)/** Get central directory header's disk number start */#define CENDSK(b) SH(b, 34)/** Get central directory header's internal file attributes */#define CENATT(b) SH(b, 36)/** Get central directory header's external file attributes */#define CENATX(b) LG(b, 38)/** Get central directory header's offset of local header */#define CENOFF(b) LG(b, 42)/** Get end header's number of entries on this disk */#define ENDSUB(b) SH(b, 8)/** Get end header's total number of entries */#define ENDTOT(b) SH(b, 10)/** Get end header's central directory size */#define ENDSIZ(b) LG(b, 12)/** Get end header's central directory offset */#define ENDOFF(b) LG(b, 16)/** Get end header's size of zip file comment */#define ENDCOM(b) SH(b, 20)/** * Returns the CRC of an array of bytes, using the same * algorithm as used by the JAR reader. * * @param data pointer to the array of bytes * @param length length of data, in bytes * * @return CRC */static unsigned longjarCRC32(unsigned char *data, unsigned long length) { unsigned long crc = 0xFFFFFFFF; unsigned int j; for ( ; length > 0; length--, data++) { crc ^= *data; for (j = 8; j > 0; --j) { crc = (crc & 1) ? ((crc >> 1) ^ 0xedb88320) : (crc >> 1); } } return ~crc;}/** * Reads the entry at at given file offset. Does not perform * memory allocation. * * @param fileObj file object * @param jarInfo JAR info object * @param offset offset of a central directory entry. * * @return entry info with a status of zero for success or a non-zero * error code. */static JarEntryInforeadJarEntryInfo(FileObj* fileObj, JarInfo* jarInfo, unsigned long offset) { JarEntryInfo entry; unsigned char header[CENHDRSIZ]; memset(&entry, 0, sizeof (entry)); /* * Offset contains the offset of the next central header. Read the * header into the temporary buffer */ /* Go to the header and Read the bytes */ if ((fileObj->seek(fileObj->state, offset, SEEK_SET) < 0) || (fileObj->read(fileObj->state, header, CENHDRSIZ) != CENHDRSIZ)) { entry.status = JAR_CORRUPT; return entry; } /* header should contain the current central header */ if (GETSIG(header) != CENSIG) { /* We've reached the end of the headers */ entry.status = JAR_ENTRY_NOT_FOUND; return entry; } entry.nameLen = CENNAM(header); entry.nameOffset = offset + CENHDRSIZ; entry.decompLen = CENLEN(header); /* the decompressed length */ entry.compLen = CENSIZ(header); /* the compressed length */ entry.method = CENHOW(header); /* how it is stored */ entry.expectedCRC = CENCRC(header); /* expected CRC */ entry.encrypted = (CENFLG(header) & 1) == 1; entry.offset = jarInfo->locOffset + CENOFF(header); entry.nextCenEntryOffset = entry.nameOffset + entry.nameLen + CENEXT(header) + CENCOM(header); return entry;}/** * Fills a Jar info struct so that entries can be read using getJarEntryInfo. * Does not perform memory allocation. * * @param fileObj file object * * @return Jar info status of 0 if success, non-zero otherwise. */JarInfogetJarInfo(FileObj* fileObj) { unsigned char buffer[ENDHDRSIZ * 2]; JarInfo jarInfo; long length; long minOffset; long currentOffset; unsigned const char *bp; memset(&jarInfo, 0, sizeof (jarInfo)); /* Get the length of the JAR */ length = fileObj->size(fileObj->state); /* * Calculate the smallest possible offset for the end header. It * can be at most 0xFFFF + ENDHDRSIZ bytes from the end of the file, but * the JAR must also have a local header and a central header */ minOffset = length - (0xFFFF + ENDHDRSIZ); if (minOffset < LOCHDRSIZ + CENHDRSIZ) { minOffset = LOCHDRSIZ + CENHDRSIZ; } /* * Read in the last ENDHDRSIZ bytes into the buffer. 99% of the time, * the JAR won't have a comment, and this is the only read we'll need */ if ((fileObj->seek(fileObj->state, -ENDHDRSIZ, SEEK_END) < 0) || (fileObj->read(fileObj->state, buffer, ENDHDRSIZ) != ENDHDRSIZ)) { jarInfo.status = -1; return jarInfo; } /* Set currentOffset to be the offset of buffer[0] */ currentOffset = length - ENDHDRSIZ; /* Set bp to be the location at which to start looking */ bp = buffer; for (; ; ) { /* * "buffer" contains a block of data from the JAR, starting at * currentOffset "position" in the JAR. * We investigate whether currentOffset + (bp - buffer) is the start * of the end header in the JAR. * * We use a simplified version of Knuth-Morris-Pratt search algorithm. * The header we're looking for is 'P' 'K' 5 6 */ switch (bp[0]) { case '\006': /* The header must start at least 3 bytes back */ bp -= 3; break; case '\005': /* The header must start at least 2 bytes back */ bp -= 2; break; case 'K': /* The header must start at least 1 byte back */ bp -= 1;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?