XP_QSORT(zip->dir, (size_t) zip->nel, sizeof(direl_t), ns_zip_direlcmp);
NS_QuickSort(zip->dir, (size_t) zip->nel, sizeof(direl_t), ns_zip_direlcmp2, NULL);
ns_zip_initReader(ns_zip_t *zip){    char endbuf[ENDHDRSIZ];    char HUGEP *cenbuf;    char HUGEP *cp;    PRUint32 locoff;    PRUint32 i, cenlen;    /* Seek to END header and read it in */    if (!nsZipFindEnd(zip, endbuf)) {	ns_ziperr(zip, "Unable to locate end-of-central-directory record");	return PR_FALSE;    }    /* Verify END signature */    if (strncmp(endbuf, ENDSIG, SIGSIZ) != 0) {	ns_ziperr(zip, "Invalid END signature");	return PR_FALSE;    }    /* Get real offset of central directory */    zip->cenoff = zip->endoff - ENDSIZ(endbuf);    /*     * Since there may be a stub prefixed to the ZIP or JAR file, the     * the start offset of the first local file (LOC) header will be     * the difference between the real offset of the first CEN header     * and what is specified in the END header.     */    if (zip->cenoff < ENDOFF(endbuf)) {	ns_ziperr(zip, "Invalid end-of-central directory header");	return PR_FALSE;    }    locoff = zip->cenoff - ENDOFF(endbuf);    /* Get length of central directory */    cenlen = ENDSIZ(endbuf);    /* Check offset and length */    if (zip->cenoff + cenlen != zip->endoff) {	ns_ziperr(zip, "Invalid end-of-central-directory header");	return PR_FALSE;    }    /* Get total number of central directory entries */    zip->nel = ENDTOT(endbuf);    /* Check entry count */    if (zip->nel * CENHDRSIZ > cenlen) {	ns_ziperr(zip, "Invalid end-of-central-directory header");	return PR_FALSE;    }    /* Verify that zip file contains only one drive */    if (ENDSUB(endbuf) != zip->nel) {	ns_ziperr(zip, "Cannot contain more than one drive");	return PR_FALSE;    }    /* Seek to first CEN header */    if (PR_Seek(zip->fd, zip->cenoff, SEEK_SET) == -1) {#if !defined(XP_PC) || defined(_WIN32)	/*	 * perror is not defined for win16	 */	perror(zip->fn);#endif	return PR_FALSE;    }    /* Allocate file lookup table */    CHECK_SIZE_LIMIT( zip->nel * sizeof(direl_t) );    if ((zip->dir = PR_MALLOC((size_t)(zip->nel * sizeof(direl_t)))) == 0) {	ns_ziperr(zip, "Out of memory allocating lookup table");	return PR_FALSE;    }    /* Allocate temporary buffer for contents of central directory */    if ((cenbuf = PR_MALLOC(cenlen)) == 0) {	ns_ziperr(zip, "Out of memory allocating central directory buffer");	return PR_FALSE;    }    /* Read central directory */    if (!nsZipReadFully(zip->fd, cenbuf, cenlen)) {	ns_ziperr(zip, "Fatal error while reading central directory");        PR_Free(cenbuf);	return PR_FALSE;    }    /* Scan each header in central directory */    for (i = 0, cp = cenbuf; i < zip->nel; i++) {	direl_t *dp = &zip->dir[i];	PRUint32 n;	/* Verify signature of CEN header */	if (NS_ZIP_STRNCMP(cp, CENSIG, SIGSIZ) != 0) {	    ns_ziperr(zip, "Invalid central directory header signature");            PR_Free(cenbuf);	    return PR_FALSE;	}	/* Get file name */	n = CENNAM(cp);        CHECK_SIZE_LIMIT( n+1 );	if ((dp->fn = PR_MALLOC((size_t)n + 1)) == 0) {	    ns_ziperr(zip, "Out of memory reading CEN header file name");            PR_Free(cenbuf);	    return PR_FALSE;	}	NS_ZIP_STRNCPY(dp->fn, cp + CENHDRSIZ, (size_t) n);	dp->fn[n] = '\0';	/* Get compression method */	dp->method = CENHOW(cp);	/* Get real offset of LOC header */	dp->off = locoff + CENOFF(cp);	/* Get uncompressed file size */	dp->len = CENLEN(cp);	/* Get compressed file size */	dp->size = CENSIZ(cp);	/* Check offset and size */	if (dp->off + CENSIZ(cp) > zip->cenoff) {	    ns_ziperr(zip, "Invalid CEN header");            PR_Free(cenbuf);	    return PR_FALSE;	}	/* Get file modification time */	dp->mod = (int) CENTIM(cp);	/* Skip to next CEN header */	cp += CENHDRSIZ + CENNAM(cp) + CENEXT(cp) + CENCOM(cp);	if (cp > cenbuf + cenlen) {	    ns_ziperr(zip, "Invalid CEN header");            PR_Free(cenbuf);	    return PR_FALSE;	}    }    /* Free temporary buffer */    PR_Free(cenbuf);    /* Sort directory elements by name */    XP_QSORT(zip->dir, (size_t) zip->nel, sizeof(direl_t), ns_zip_direlcmp);    return PR_TRUE;}