alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Glassfish example source code file (zip_util.c)

This example Glassfish source code file (zip_util.c) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Glassfish tags/keywords

cen, cen, cenhdr, end, endhdr, getsig, jni_false, jni_false, jni_true, locext, null, null, seek_set, seek_set

The Glassfish zip_util.c source code

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2008-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

/*
 * Support for reading ZIP/JAR files.
 */
#include "zip_util.h"
#include "java.h"

#define MAXREFS 0xFFFF	/* max number of open zip file references */
#define MAXSIZE INT_MAX	/* max size of zip file or zip entry */

static jzfile *zfiles = 0;	/* currently open zip files */
static char errbuf[256];

/*
 * Initialize zip file support. Return 0 if successful otherwise -1
 * if could not be initialized.
 */
static jint initializeZip()
{
    extern void out_of_memory(void);
    static jboolean inited = JNI_FALSE;
    if (inited)
        return 0;
    inited = JNI_TRUE;

    return 0;
}

/*
 * Reads len bytes of data into buf. Returns 0 if all bytes could be read,
 * otherwise returns -1.
 */
static jint readFully(int fd, void *buf, jint len)
{
    unsigned char *bp = buf;
    while (len > 0)
    {
        jint n = read(fd, (char *)bp, len);
        if (n <= 0)
            return -1;
        bp += n;
        len -= n;
    }
    return 0;
}

/*
 * Allocates a new zip file object for the specified file name.
 * Returns the zip file object or NULL if not enough memory.
 */
static jzfile *allocZip(const char *name)
{
    jzfile *zip = calloc(1, sizeof(jzfile));

    if (zip == 0)
        return 0;
    zip->name = strdup(name);
    if (zip->name == 0)
    {
        free(zip);
        return 0;
    }
    return zip;
}

/*
 * Frees the specified zip file object.
 */
static void freeZip(jzfile *zip)
{
    int i;
    /* First free any cached jzentry */
    zipFreeEntry(zip,0);
    if (zip->name != 0)
        free(zip->name);
    if (zip->comment != 0)
        free(zip->comment);
    if (zip->entries != 0)
        free(zip->entries);
    if (zip->table != 0)
        free(zip->table);
    if (zip->metanames != 0)
    {
        for (i = 0; i < zip->metacount; i++)
        {
            if (zip->metanames[i])
                free(zip->metanames[i]);
        }
        free(zip->metanames);
    }
    if (zip->comments != 0)
    {
        for (i = 0; i < zip->total; i++)
        {
            if (zip->comments[i])
                free(zip->comments[i]);
        }
        free(zip->comments);
    }
    free(zip);
}

/*
 * Searches for end of central directory (END) header. The contents of
 * the END header will be read and placed in endbuf. Returns the file
 * position of the END header, otherwise returns 0 if the END header
 * was not found or -1 if an error occurred.
 */
static jint findEND(jzfile *zip, void *endbuf)
{
    unsigned char buf[ENDHDR * 2];
    jint len, pos;
    int fd = zip->fd;

    /* Get the length of the zip file */
    len = pos = lseek(fd, 0, SEEK_END);
    if (len == -1)
        return -1;

    /*
     * Search backwards ENDHDR bytes at a time from end of file stopping
     * when the END header has been found. We need to make sure that we
     * handle the case where the signature may straddle a record boundary.
     * Also, the END header must be located within the last 64k bytes of
     * the file since that is the maximum comment length.
     */
    memset(buf, 0, sizeof(buf));
    while (len - pos < 0xFFFF)
    {
        unsigned char *bp;
        /* Number of bytes to check in next block */
        int count = 0xFFFF - (len - pos);
        if (count > ENDHDR)
            count = ENDHDR;
        /* Shift previous block */
        memcpy(buf + count, buf, count);
        /* Update position and read next block */
        pos -= count;
        if (lseek(fd, pos, SEEK_SET) == -1)
            return -1;
        if (readFully(fd, buf, count) == -1)
            return -1;
        /* Now scan the block for END header signature */
        for (bp = buf; bp < buf + count; bp++)
        {
            if (GETSIG(bp) == ENDSIG)
            {
        	/* Check for possible END header */
        	jint endpos = pos + (bp - buf);
        	jint clen = ENDCOM(bp);
        	if (endpos + ENDHDR + clen == len)
                {
        	    /* Found END header */
        	    memcpy(endbuf, bp, ENDHDR);
        	    if (lseek(fd, endpos + ENDHDR, SEEK_SET) == -1)
        		return -1;
        	    if (clen > 0)
                    {
        		zip->comment = malloc(clen + 1);
        		if (zip->comment == 0)
        		    return -1;
        		if (readFully(zip->fd, zip->comment, clen) == -1)
                        {
        		    free(zip->comment);
        		    zip->comment = 0;
        		    return -1;
        		}
        		zip->comment[clen] = '\0';
        	    }
        	    return endpos;
        	}
            }
        }
    }
    return 0; /* END header not found */
}

/*
 * Returns a hash code value for the specified string.
 */
static unsigned int
hash(const char *s)
{
    int h = 0;
    while (*s != '\0')
        h = 31*h + *s++;
    return h;
}

/*
 * Returns true if the specified entry's name begins with the string
 * "META-INF/" irrespect of case.
 */
static int
isMetaName(char *name)
{
#define META_INF "META-INF/"
    char *s = META_INF, *t = name;
    while (*s != '\0')
    {
        if (*s++ != (char)toupper(*t++))
            return 0;
    }
    return 1;
}

static void
addMetaName(jzfile *zip, char *name)
{
    int i;
    if (zip->metanames == 0)
    {
        zip->metacount = 2;
        zip->metanames = calloc(zip->metacount, sizeof(char *));
    }
    for (i = 0; i < zip->metacount; i++)
        {
        if (zip->metanames[i] == 0)
        {
            zip->metanames[i] = strdup(name);
            break;
        }
    }
    /* If necessary, grow the metanames array */
    if (i >= zip->metacount)
    {
        int new_count = 2 * zip->metacount;
        char **tmp = calloc(new_count, sizeof(char *));
        for (i = 0; i < zip->metacount; i++)
            tmp[i] = zip->metanames[i];
        tmp[i] = strdup(name);
        free(zip->metanames);
        zip->metanames = tmp;
        zip->metacount = new_count;
    }
}

static void
addEntryComment(jzfile *zip, int index, char *comment)
{
    if (zip->comments == NULL)
        zip->comments = calloc(zip->total, sizeof(char *));
    zip->comments[index] = comment;
}

/*
 * Reads zip file central directory. Returns the file position of first
 * CEN header, otherwise returns 0 if central directory not found or -1
 * if an error occurred. If zip->msg != NULL then the error was a zip
 * format error and zip->msg has the error text.
 */
static
jint readCEN(jzfile *zip)
{
    jint endpos, locpos, cenpos, cenoff, cenlen;
    jint total, count, tablelen, i, tmplen;
    unsigned char endbuf[ENDHDR], *cenbuf, *cp;
    jzcell *entries;
    unsigned short *table;
    char namebuf[ZIP_TYPNAMELEN + 1];
    char* name = namebuf;
    int namelen = ZIP_TYPNAMELEN + 1;


    /* Clear previous zip error */
    zip->msg = 0;
    /* Get position of END header */
    endpos = findEND(zip, endbuf);
    if (endpos == 0)
        return 0;  /* END header not found */
    if (endpos == -1)
        return -1; /* system error */
    /* Get position and length of central directory */
    cenlen = ENDSIZ(endbuf);
    if (cenlen < 0 || cenlen > endpos)
    {
        zip->msg = "invalid END header (bad central directory size)";
        return -1;
    }
    cenpos = endpos - cenlen;
    /*
     * Get position of first local file (LOC) header, taking into
     * account that there maybe a stub prefixed to the zip file.
     */ 
    cenoff = ENDOFF(endbuf);
    if (cenoff < 0 || cenoff > cenpos)
    {
        zip->msg = "invalid END header (bad central directory offset)";
        return -1;
    }
    locpos = cenpos - cenoff;
    /* Get total number of central directory entries */
    total = zip->total = ENDTOT(endbuf);
    if (total < 0 || total * CENHDR > cenlen)
    {
        zip->msg = "invalid END header (bad entry count)";
        return -1;
    }
    if (total > ZIP_MAXENTRIES)
    {
        zip->msg = "too many entries in ZIP file";
        return -1;
    }
    /* Seek to first CEN header */
    if (lseek(zip->fd, cenpos, SEEK_SET) == -1)
        return -1;

    /* Allocate temporary buffer for central directory bytes */
    cenbuf = malloc(cenlen);
    if (cenbuf == 0)
        return -1;
    /* Read central directory */
    if (readFully(zip->fd, cenbuf, cenlen) == -1)
    {
        free(cenbuf);
        return -1;
    }
    /* Allocate array for item descriptors */
    entries = zip->entries = calloc(total, sizeof(jzcell));
    if (entries == 0)
    {
        free(cenbuf);
        return -1;
    }
    /* Allocate hash table */
    tmplen = total/2;
    tablelen = zip->tablelen = (tmplen > 0 ? tmplen : 1);
    table = zip->table = calloc(tablelen, sizeof(unsigned short));
    if (table == 0)
    {
        free(cenbuf);
        free(entries);
        zip->entries = 0;
        return -1;
    }
    for (i = 0; i < tablelen; i++)
        table[i] = ZIP_ENDCHAIN;

    /* Now read the zip file entries */
    for (count = 0, cp = cenbuf; count < total; count++)
    {
        jzcell *zc = &entries[count];
        int method, nlen, clen, elen, hsh;

        /* Check CEN header looks OK */
        if ((cp - cenbuf) + CENHDR > cenlen)
        {
            zip->msg = "invalid CEN header (bad header size)";
            break;
        }
        /* Verify CEN header signature */
        if (GETSIG(cp) != CENSIG)
        {
            zip->msg = "invalid CEN header (bad signature)";
            break;
        }
        /* Check if entry is encrypted */
        if ((CENVER(cp) & 1) == 1)
        {
            zip->msg = "invalid CEN header (encrypted entry)";
            break;
        }
        method = CENHOW(cp);
        if (method != STORED && method != DEFLATED)
        {
            zip->msg = "invalid CEN header (bad compression method)";
            break;
        }

        /* Get header field lengths */
        nlen         = CENNAM(cp);
        elen         = CENEXT(cp);
        clen         = CENCOM(cp);
        if ((cp - cenbuf) + CENHDR + nlen + clen + elen > cenlen)
        {
            zip->msg = "invalid CEN header (bad header size)";
            break;
        }

        zc->size     = CENLEN(cp);
        zc->csize    = CENSIZ(cp);
        zc->crc      = CENCRC(cp);
        /* Set compressed size to zero if entry uncompressed */
        if (method == STORED)
            zc->csize = 0;

        /*
         * Copy the name into a temporary location so we can null
         * terminate it (sigh) as various functions expect this.
         */
        if (namelen < nlen + 1)
        {
            /* grow temp buffer */
            do  
                namelen = namelen * 2;
            while (namelen < nlen + 1);
            if (name != namebuf) /* free malloc()ated buffer */
                free(name);
            name = malloc(namelen);
        } 
        memcpy(name, cp+CENHDR, nlen);
        name[nlen] = 0;

        /*
         * Record the LOC offset and the name hash in our hash cell.
         */
        zc->pos = CENOFF(cp) + locpos;
        zc->nelen = nlen + elen;
        zc->hash = hash(name);
     	zc->cenpos = cenpos + (cp - cenbuf);
        zc->elen = elen;
        /*
         * if the entry is metdata add it to our metadata names
         */
        if (isMetaName(name))
            addMetaName(zip, name);

        /*
         * If there is a comment add it to our comments array.
         */
        if (clen > 0)
        {
            char *comment = malloc(clen+1);
            memcpy(comment, cp+CENHDR+nlen+elen, clen);
            comment[clen] = 0;
            addEntryComment(zip, count, comment);
 	}

        /*
         * Finally we can add the entry to the hash table
         */
        hsh = zc->hash % tablelen;
        zc->next = table[hsh];
        table[hsh] = count;

        cp += (CENHDR + nlen + elen + clen);
    }
    /* Free up temporary buffers */
    free(cenbuf);
    if (name != namebuf)
        free(name);

    /* Check for error */
    if (count != total)
    {
        /* Central directory was invalid, so free up entries and return */
        free(entries);
        zip->entries = 0;
        free(table);
        zip->table = 0;
        return -1;
    }
    return cenpos;
}

/*
 * Opens a zip file with the specified mode. Returns the jzfile object 
 * or NULL if an error occurred. If a zip error occurred then *msg will 
 * or NULL if an error occurred. If a zip error occurred then *zerror will be
 * set to the error number. Otherwise, *zerror will be set to Z_OK.
 */
jzfile *
zipOpenGeneric(const char *name, int *zerror, int mode, jlong lastModified)
{
    jzfile *zip;

    if (initializeZip())
        return NULL;

    /* Clear zip error message */
    if (zerror != 0)
        *zerror = Z_OK;

    for (zip = zfiles; zip != 0; zip = zip->next)
    {
        if (strcmp(name, zip->name) == 0
            && (zip->lastModified == lastModified || zip->lastModified == 0)
            && zip->refs < MAXREFS)
        {
            zip->refs++;
            break;
        }
    }
    if (zip == 0)
    {
        jlong len;
        /* If not found then allocate a new zip object */
        zip = allocZip(name);
        if (zip == 0)
            return 0;
        zip->refs = 1;
        zip->lastModified = lastModified;
        zip->fd = open(name, mode);
        if (!zip->fd)
        {
            if (zerror != 0)
                *zerror = Z_MEM_ERROR;
            freeZip(zip);
            return 0;
        }
        len = lseek(zip->fd, 0, SEEK_END);
        if (len == -1)
        {
            if (zerror != 0)
                *zerror = Z_STREAM_ERROR;
            close(zip->fd);
            freeZip(zip);
            return 0;
        }
        if (len > MAXSIZE)
        {
            if (zerror != 0)
                *zerror = Z_STREAM_ERROR;
            close(zip->fd);
            freeZip(zip);
            return 0;
        }
        if (readCEN(zip) <= 0)
        {
            /* An error occurred while trying to read the zip file */
            if (zerror != 0)
                *zerror = Z_STREAM_ERROR;
            close(zip->fd);
            freeZip(zip);
            return 0;
        }
        zip->next = zfiles;
        zfiles = zip;
    }
    return zip;
}

/*
 * Opens a zip file for reading. Returns the jzfile object or NULL
 * if an error occurred. If a zip error occurred then *zerror will be
 * set to the error number. Otherwise, *zerror will be set to Z_OK.
 */
jzfile *
zipOpen(const char *name, int *zerror)
{
#ifdef WIN32
    int mode = O_RDONLY | O_BINARY;
#else
    int mode = O_RDONLY;
#endif
    return zipOpenGeneric(name, zerror, mode, 0);
}

/*
 * Closes the specified zip file object.
 */
void zipClose(jzfile *zip)
{
    if (--zip->refs > 0)
    {
        /* Still more references so just return */
        return;
    }
    /* No other references so close the file and remove from list */
    if (zfiles == zip)
    {
        zfiles = zfiles->next;
    }
    else
    {
        jzfile *zp;
        for (zp = zfiles; zp->next != 0; zp = zp->next)
        {
            if (zp->next == zip)
            {
        	zp->next = zip->next;
        	break;
            }
        }
    }
    close(zip->fd);
    freeZip(zip);
    return;
}

/*
 * Read a LOC corresponding to a given hash cell and
 * create a corrresponding jzentry entry descriptor
 * The ZIP lock should be held here.
 */
static jzentry *
readLOC(jzfile *zip, jzcell *zc)
{
    unsigned char *locbuf;
    jint nelen = zc->nelen;
    jint nlen, elen;
    jzentry *ze;

    /* Seek to beginning of LOC header */
    if (lseek(zip->fd, zc->pos, SEEK_SET) == -1)
    {
        zip->msg = "seek failed";
        return NULL;
    }   

    locbuf =  malloc(LOCHDR + nelen);
    /* Try to read in the LOC header including the name and extra data */
    if (readFully(zip->fd, locbuf, LOCHDR+nelen) == -1)
    {
        zip->msg = "couldn't read LOC header";
        free(locbuf);
        return NULL;
    }

    /* Verify signature */
    if (GETSIG(locbuf) != LOCSIG)
    {
        zip->msg = "invalid LOC header (bad signature)";
        free(locbuf);
        return NULL;
    }

    /* verify lengths */
    nlen = LOCNAM(locbuf);
    elen = LOCEXT(locbuf);

    ze = calloc(1, sizeof(jzentry));
    ze->name = malloc(nlen + 1);
    memcpy(ze->name, locbuf+LOCHDR, nlen);
    ze->name[nlen] = 0;

    /* If extra in CEN, use it instead of extra in LOC */
    if (zc->elen > 0)
    {
        int off = CENHDR + zc->nelen - zc->elen + zc->cenpos;
        elen = zc->elen;
        ze->extra = malloc(elen+2);
        ze->extra[0] = (unsigned char)elen;
        ze->extra[1] = (unsigned char)(elen >> 8);

        /* Seek to begin of CEN header extra field */
        if (lseek(zip->fd, off, SEEK_SET) == -1)
        {
            zip->msg = "seek failed";
            free(locbuf);
            return NULL;
        }
        /* Try to read in the CEN Extra */
        if (readFully(zip->fd, &ze->extra[2], elen) == -1)
        {
            zip->msg = "couldn't read CEN extra";
            free(locbuf);
            return NULL;
        }
    }
    else if (LOCEXT(locbuf) != 0)
    {
        ze->extra = malloc(elen + 2);
        /* Store the extra data size in the first two bytes */
        ze->extra[0] = (unsigned char)elen;
        ze->extra[1] = (unsigned char)(elen >> 8);
        memcpy(&ze->extra[2], locbuf+LOCHDR+nlen, elen);
    }

    /*
     * Process any comment (this should be very rare)
     */
    if (zip->comments)
    {	
        int index = zc - zip->entries;
        ze->comment = zip->comments[index];
    }

    /*
     * We'd like to initialize the sizes from the LOC, but unfortunately
     * some ZIPs, including the jar command, don't put them there.
     * So we have to store them in the szcell.
     */
    ze->size = zc->size;
    ze->csize = zc->csize;
    ze->crc = zc->crc;

    /* Fill in the rest of the entry fields from the LOC */
    ze->time = LOCTIM(locbuf);
    ze->pos = zc->pos + LOCHDR + LOCNAM(locbuf) + LOCEXT(locbuf);
    free(locbuf);

    return ze;
}

/*
 * Free the given jzentry.
 * In fact we maintain a one-entry cache of the most recently used
 * jzentry for each zip.  This optimizes a common access pattern.
 */

void
zipFreeEntry(jzfile *jz, jzentry *ze)
{
    jzentry *last;
    last = jz->cache;
    jz->cache = ze;
    if (last != NULL)
    {
        /* Free the previously cached jzentry */
        if (last->extra)
            free(last->extra);
        if (last->name)
            free(last->name);
        free(last);
    }
}

/*
 * Returns the zip entry corresponding to the specified name, or
 * NULL if not found.
 */
jzentry * zipGetEntry(jzfile *zip, const char *name)
{
    unsigned int hsh = hash(name);
    int idx = zip->table[hsh % zip->tablelen];
    jzentry *ze;

    /* Check the cached entry first */
    ze = zip->cache;
    if (ze && strcmp(ze->name,name) == 0)
    {
        /* Cache hit!  Remove and return the cached entry. */
        zip->cache = 0;
        return ze;
    }
    ze = 0;

    /*
     * Search down the target hash chain for a cell who's
     * 32 bit hash matches the hashed name.
     */
    while (idx != ZIP_ENDCHAIN)
    {
        jzcell *zc = &zip->entries[idx];

        if (zc->hash == hsh)
        {
            /*
             * OK, we've found a ZIP entry whose 32 bit hashcode
             * matches the name we're looking for.  Try to read its
             * entry information from the LOC.
             * If the LOC name matches the name we're looking,
             * we're done.  
             * If the names don't (which should be very rare) we
             * keep searching.
             */
            ze = readLOC(zip, zc);
            if (ze && strcmp(ze->name, name)==0)
        	break;
            if (ze != 0)
        	zipFreeEntry(zip, ze);
            ze = 0;
        }
        idx = zc->next;
    }
    return ze;
}

/*
 * Returns the n'th (starting at zero) zip file entry, or NULL if the
 * specified index was out of range.
 */
jzentry *
zipGetNextEntry(jzfile *zip, jint n)
{
    jzentry *result;
    if (n < 0 || n >= zip->total)
        return 0;
    result = readLOC(zip, &zip->entries[n]);
    return result;
}

/*
 * Reads bytes from the specified zip entry. Returns the
 * number of bytes read, or -1 if an error occurred. If err->msg != 0
 * then a zip error occurred and err->msg contains the error text.
 */
jint zipRead(jzfile *zip, jzentry *entry, jint pos, void *buf, jint len)
{
    jint n, avail, size;

    /* Clear previous zip error */
    zip->msg = 0;
    /* Check specified position */
    size = entry->csize != 0 ? entry->csize : entry->size;
    if (pos < 0 || pos > size - 1)
    {
        zip->msg = "zipRead: specified offset out of range";
        return -1;
    }
    /* Check specified length */
    if (len <= 0)
        return 0;
    avail = size - pos;
    if (len > avail)
        len = avail;

    /* Seek to beginning of entry data and read bytes */
    n = lseek(zip->fd, entry->pos + pos, SEEK_SET);
    if (n != -1)
        n = read(zip->fd, buf, len);
    return n;
}

/* The maximum size of a stack-allocated buffer.
 */
#define BUF_SIZE 4096

/*
 * This function is used by the runtime system to load compressed entries
 * from ZIP/JAR files specified in the class path. It is defined here
 * so that it can be dynamically loaded by the runtime if the zip library
 * is found.
 */
static jboolean
inflateFully(jzfile *zip, jzentry *entry, int fd, char **msg)
{
    z_stream strm;
    char tmp[BUF_SIZE];
    unsigned char buf[BUF_SIZE * 4];
    jint pos = 0, count = entry->csize;

    *msg = 0; /* Reset error message */

    if (count == 0)
    {
        *msg = "inflateFully: entry not compressed";
        return JNI_FALSE;
    }

    memset(&strm, 0, sizeof(z_stream));
    if (inflateInit2(&strm, -MAX_WBITS) != Z_OK)
    {
        *msg = strm.msg;
        return JNI_FALSE;
    }

    while (count > 0)
    {
        jint n = count > (jint)sizeof(tmp) ? (jint)sizeof(tmp) : count;
        n = zipRead(zip, entry, pos, tmp, n);
        if (n <= 0)
        {
            if (n == 0)
                *msg = "inflateFully: Unexpected end of file";
            inflateEnd(&strm);
            return JNI_FALSE;
        }
        pos += n;
        count -= n;
        strm.next_in = (Bytef *)tmp;
        strm.avail_in = n;

        do
        {
            strm.next_out = buf;
            strm.avail_out = sizeof(buf);
            if (inflate(&strm, Z_PARTIAL_FLUSH) == Z_STREAM_END)
            {
        	if (count != 0 || strm.total_out != entry->size)
                {
        	    *msg = "inflateFully: Unexpected end of stream";
                    inflateEnd(&strm);
        	    return JNI_FALSE;
        	}
            }
            if (write(fd, buf, sizeof(buf) - strm.avail_out) != sizeof(buf) - strm.avail_out)
            {
                inflateEnd(&strm);
        	return JNI_FALSE;
            }
        } while (strm.avail_in > 0 || !strm.avail_out);
    }
    inflateEnd(&strm);
    return JNI_TRUE;
}

jzentry *
zipFindEntry(jzfile *zip, const char *name, jint *sizeP, jint *nameLenP)
{
    jzentry *entry = zipGetEntry(zip, name);
    if (entry)
    {
        *sizeP = entry->size;
        *nameLenP = strlen(entry->name);
    }
    return entry;
}

/*
 * Reads a zip file entry into the specified byte array into the specified
 * file.
 */
jboolean
zipReadEntry(jzfile *zip, jzentry *entry, const char *path)
{
    char *msg;
    int fd;

#ifdef WIN32
    if ((fd = open(path, O_WRONLY | O_CREAT | O_BINARY, _S_IREAD | _S_IWRITE)) < 0)
#else
    if ((fd = open(path, O_WRONLY | O_CREAT, S_IRWXU)) < 0)
#endif
    {
        msg = "zipReadEntry: cannot open output file";
        return JNI_FALSE;
    }
    if (entry->csize == 0)
    {
        /* Entry is stored */
        jint pos = 0, count = entry->size;
        unsigned char buf[BUF_SIZE * 4];
        while (count > 0)
        {
            jint n;
            n = zipRead(zip, entry, pos, buf, count > sizeof(buf) ? sizeof(buf) : count);
            msg = zip->msg;
            if (n == -1 || write(fd, buf, n) != n)
            {
                close(fd);
                return JNI_FALSE;
            }
            pos += n;
            count -= n;
        }
    }
    else
    {
        /* Entry is compressed */
        int ok = inflateFully(zip, entry, fd, &msg);
        if (!ok)
        {
            if ((msg == NULL) || (*msg == 0))
                msg = zip->msg;
            close(fd);
            return JNI_FALSE;
        }
    }
  
    close(fd);
  
    return JNI_TRUE;
}

Other Glassfish examples (source code examples)

Here is a short list of links related to this Glassfish zip_util.c source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.