Annotation of embedaddon/php/ext/zip/lib/zip_open.c, revision 1.1.1.2

1.1       misho       1: /*
1.1.1.2 ! misho       2:   zip_open.c -- open zip archive by name
        !             3:   Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner
1.1       misho       4: 
                      5:   This file is part of libzip, a library to manipulate ZIP archives.
                      6:   The authors can be contacted at <libzip@nih.at>
                      7: 
                      8:   Redistribution and use in source and binary forms, with or without
                      9:   modification, are permitted provided that the following conditions
                     10:   are met:
                     11:   1. Redistributions of source code must retain the above copyright
                     12:      notice, this list of conditions and the following disclaimer.
                     13:   2. Redistributions in binary form must reproduce the above copyright
                     14:      notice, this list of conditions and the following disclaimer in
                     15:      the documentation and/or other materials provided with the
                     16:      distribution.
                     17:   3. The names of the authors may not be used to endorse or promote
                     18:      products derived from this software without specific prior
                     19:      written permission.
                     20:  
                     21:   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
                     22:   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     23:   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
                     25:   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
                     27:   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     28:   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
                     29:   IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     30:   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
                     31:   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     32: */
                     33: 
                     34: 
                     35: 
                     36: #include <sys/stat.h>
                     37: #include <errno.h>
                     38: #include <limits.h>
                     39: #include <stdio.h>
                     40: #include <stdlib.h>
                     41: #include <string.h>
                     42: 
                     43: #include "zipint.h"
                     44: 
                     45: static void set_error(int *, struct zip_error *, int);
                     46: static struct zip *_zip_allocate_new(const char *, int *);
                     47: static int _zip_checkcons(FILE *, struct zip_cdir *, struct zip_error *);
                     48: static void _zip_check_torrentzip(struct zip *);
                     49: static struct zip_cdir *_zip_find_central_dir(FILE *, int, int *, off_t);
                     50: static int _zip_file_exists(const char *, int, int *);
                     51: static int _zip_headercomp(struct zip_dirent *, int,
                     52:                           struct zip_dirent *, int);
                     53: static unsigned char *_zip_memmem(const unsigned char *, int,
                     54:                                  const unsigned char *, int);
1.1.1.2 ! misho      55: static struct zip_cdir *_zip_readcdir(FILE *, off_t, unsigned char *, unsigned char *,
1.1       misho      56:                                 int, int, struct zip_error *);
                     57: 
                     58: 
                     59: 
                     60: ZIP_EXTERN(struct zip *)
                     61: zip_open(const char *fn, int flags, int *zep)
                     62: {
                     63:     FILE *fp;
                     64: 
                     65:     if (flags & ZIP_OVERWRITE) {
                     66:        return _zip_allocate_new(fn, zep);
                     67:     }
                     68: 
                     69:     switch (_zip_file_exists(fn, flags, zep)) {
                     70:     case -1:
                     71:                        if (!(flags & ZIP_OVERWRITE)) {
                     72:                                return NULL;
                     73:                        }
                     74:     case 0:
                     75:        return _zip_allocate_new(fn, zep);
                     76:     default:
                     77:        break;
                     78:     }
                     79: 
                     80:     if ((fp=fopen(fn, "rb")) == NULL) {
                     81:        set_error(zep, NULL, ZIP_ER_OPEN);
                     82:        return NULL;
                     83:     }
                     84: 
1.1.1.2 ! misho      85:     return _zip_open(fn, fp, flags, 0, zep);
        !            86: }
        !            87: 
        !            88: 
        !            89: 
        !            90: struct zip *
        !            91: _zip_open(const char *fn, FILE *fp, int flags, int aflags, int *zep)
        !            92: {
        !            93:     struct zip *za;
        !            94:     struct zip_cdir *cdir;
        !            95:     int i;
        !            96:     off_t len;
        !            97: 
        !            98:     if (fseeko(fp, 0, SEEK_END) < 0) {
        !            99:        *zep = ZIP_ER_SEEK;
        !           100:        return NULL;
        !           101:     }
1.1       misho     102:     len = ftello(fp);
                    103: 
                    104:     /* treat empty files as empty archives */
                    105:     if (len == 0) {
                    106:        if ((za=_zip_allocate_new(fn, zep)) == NULL)
                    107:            fclose(fp);
                    108:        else
                    109:            za->zp = fp;
                    110:        return za;
                    111:     }
                    112: 
                    113:     cdir = _zip_find_central_dir(fp, flags, zep, len);
                    114:     if (cdir == NULL) {
                    115:        fclose(fp);
                    116:        return NULL;
                    117:     }
                    118: 
                    119:     if ((za=_zip_allocate_new(fn, zep)) == NULL) {
                    120:        _zip_cdir_free(cdir);
                    121:        fclose(fp);
                    122:        return NULL;
                    123:     }
                    124: 
                    125:     za->cdir = cdir;
                    126:     za->zp = fp;
                    127: 
                    128:     if ((za->entry=(struct zip_entry *)malloc(sizeof(*(za->entry))
                    129:                                              * cdir->nentry)) == NULL) {
                    130:        set_error(zep, NULL, ZIP_ER_MEMORY);
                    131:        _zip_free(za);
                    132:        return NULL;
                    133:     }
                    134:     for (i=0; i<cdir->nentry; i++)
                    135:        _zip_entry_new(za);
                    136: 
                    137:     _zip_check_torrentzip(za);
                    138:     za->ch_flags = za->flags;
                    139: 
                    140:     return za;
                    141: }
                    142: 
                    143: 
                    144: 
                    145: static void
                    146: set_error(int *zep, struct zip_error *err, int ze)
                    147: {
                    148:     int se;
                    149: 
                    150:     if (err) {
                    151:        _zip_error_get(err, &ze, &se);
                    152:        if (zip_error_get_sys_type(ze) == ZIP_ET_SYS)
                    153:            errno = se;
                    154:     }
                    155: 
                    156:     if (zep)
                    157:        *zep = ze;
                    158: }
                    159: 
                    160: 
                    161: 
                    162: /* _zip_readcdir:
                    163:    tries to find a valid end-of-central-directory at the beginning of
                    164:    buf, and then the corresponding central directory entries.
                    165:    Returns a struct zip_cdir which contains the central directory 
                    166:    entries, or NULL if unsuccessful. */
                    167: 
                    168: static struct zip_cdir *
1.1.1.2 ! misho     169: _zip_readcdir(FILE *fp, off_t buf_offset, unsigned char *buf, unsigned char *eocd, int buflen,
1.1       misho     170:              int flags, struct zip_error *error)
                    171: {
                    172:     struct zip_cdir *cd;
                    173:     unsigned char *cdp, **bufp;
                    174:     int i, comlen, nentry;
1.1.1.2 ! misho     175:     zip_uint32_t left;
1.1       misho     176: 
                    177:     comlen = buf + buflen - eocd - EOCDLEN;
                    178:     if (comlen < 0) {
                    179:        /* not enough bytes left for comment */
                    180:        _zip_error_set(error, ZIP_ER_NOZIP, 0);
                    181:        return NULL;
                    182:     }
                    183: 
                    184:     /* check for end-of-central-dir magic */
                    185:     if (memcmp(eocd, EOCD_MAGIC, 4) != 0) {
                    186:        _zip_error_set(error, ZIP_ER_NOZIP, 0);
                    187:        return NULL;
                    188:     }
                    189: 
                    190:     if (memcmp(eocd+4, "\0\0\0\0", 4) != 0) {
                    191:        _zip_error_set(error, ZIP_ER_MULTIDISK, 0);
                    192:        return NULL;
                    193:     }
                    194: 
                    195:     cdp = eocd + 8;
                    196:     /* number of cdir-entries on this disk */
                    197:     i = _zip_read2(&cdp);
                    198:     /* number of cdir-entries */
                    199:     nentry = _zip_read2(&cdp);
                    200: 
                    201:     if ((cd=_zip_cdir_new(nentry, error)) == NULL)
                    202:        return NULL;
                    203: 
                    204:     cd->size = _zip_read4(&cdp);
                    205:     cd->offset = _zip_read4(&cdp);
                    206:     cd->comment = NULL;
                    207:     cd->comment_len = _zip_read2(&cdp);
                    208: 
1.1.1.2 ! misho     209:     if (((zip_uint64_t)cd->offset)+cd->size > buf_offset + (eocd-buf)) {
        !           210:        /* cdir spans past EOCD record */
        !           211:        _zip_error_set(error, ZIP_ER_INCONS, 0);
        !           212:        cd->nentry = 0;
        !           213:        _zip_cdir_free(cd);
        !           214:        return NULL;
        !           215:     }
        !           216: 
1.1       misho     217:     if ((comlen < cd->comment_len) || (cd->nentry != i)) {
                    218:        _zip_error_set(error, ZIP_ER_NOZIP, 0);
1.1.1.2 ! misho     219:        cd->nentry = 0;
        !           220:        _zip_cdir_free(cd);
1.1       misho     221:        return NULL;
                    222:     }
                    223:     if ((flags & ZIP_CHECKCONS) && comlen != cd->comment_len) {
                    224:        _zip_error_set(error, ZIP_ER_INCONS, 0);
1.1.1.2 ! misho     225:        cd->nentry = 0;
        !           226:        _zip_cdir_free(cd);
1.1       misho     227:        return NULL;
                    228:     }
                    229: 
                    230:     if (cd->comment_len) {
                    231:        if ((cd->comment=(char *)_zip_memdup(eocd+EOCDLEN,
                    232:                                             cd->comment_len, error))
                    233:            == NULL) {
1.1.1.2 ! misho     234:            cd->nentry = 0;
        !           235:            _zip_cdir_free(cd);
1.1       misho     236:            return NULL;
                    237:        }
                    238:     }
                    239: 
1.1.1.2 ! misho     240:     if (cd->offset >= buf_offset) {
1.1       misho     241:        /* if buffer already read in, use it */
1.1.1.2 ! misho     242:        cdp = buf + (cd->offset - buf_offset);
1.1       misho     243:        bufp = &cdp;
                    244:     }
                    245:     else {
                    246:        /* go to start of cdir and read it entry by entry */
                    247:        bufp = NULL;
                    248:        clearerr(fp);
                    249:        fseeko(fp, cd->offset, SEEK_SET);
                    250:        /* possible consistency check: cd->offset =
                    251:           len-(cd->size+cd->comment_len+EOCDLEN) ? */
                    252:        if (ferror(fp) || ((unsigned long)ftello(fp) != cd->offset)) {
                    253:            /* seek error or offset of cdir wrong */
                    254:            if (ferror(fp))
                    255:                _zip_error_set(error, ZIP_ER_SEEK, errno);
                    256:            else
                    257:                _zip_error_set(error, ZIP_ER_NOZIP, 0);
1.1.1.2 ! misho     258:            cd->nentry = 0;
        !           259:            _zip_cdir_free(cd);
1.1       misho     260:            return NULL;
                    261:        }
                    262:     }
                    263: 
                    264:     left = cd->size;
                    265:     i=0;
1.1.1.2 ! misho     266:     while (i<cd->nentry && left > 0) {
1.1       misho     267:        if ((_zip_dirent_read(cd->entry+i, fp, bufp, &left, 0, error)) < 0) {
                    268:            cd->nentry = i;
                    269:            _zip_cdir_free(cd);
                    270:            return NULL;
                    271:        }
                    272:        i++;
                    273:        
1.1.1.2 ! misho     274:        if (i == cd->nentry && left > 0) {
        !           275:            /* Infozip extension for more than 64k entries:
        !           276:               nentries wraps around, size indicates correct EOCD */
        !           277:            if (_zip_cdir_grow(cd, cd->nentry+ZIP_UINT16_MAX, error) < 0) {
        !           278:                cd->nentry = i;
        !           279:                _zip_cdir_free(cd);
        !           280:                return NULL;
        !           281:            }
        !           282:        }
        !           283:     }
        !           284: 
        !           285:     cd->nentry = i;
1.1       misho     286:     
                    287:     return cd;
                    288: }
                    289: 
                    290: 
                    291: 
                    292: /* _zip_checkcons:
                    293:    Checks the consistency of the central directory by comparing central
                    294:    directory entries with local headers and checking for plausible
                    295:    file and header offsets. Returns -1 if not plausible, else the
                    296:    difference between the lowest and the highest fileposition reached */
                    297: 
                    298: static int
                    299: _zip_checkcons(FILE *fp, struct zip_cdir *cd, struct zip_error *error)
                    300: {
                    301:     int i;
                    302:     unsigned int min, max, j;
                    303:     struct zip_dirent temp;
                    304: 
                    305:     if (cd->nentry) {
                    306:        max = cd->entry[0].offset;
                    307:        min = cd->entry[0].offset;
                    308:     }
                    309:     else
                    310:        min = max = 0;
                    311: 
                    312:     for (i=0; i<cd->nentry; i++) {
                    313:        if (cd->entry[i].offset < min)
                    314:            min = cd->entry[i].offset;
                    315:        if (min > cd->offset) {
                    316:            _zip_error_set(error, ZIP_ER_NOZIP, 0);
                    317:            return -1;
                    318:        }
                    319:        
                    320:        j = cd->entry[i].offset + cd->entry[i].comp_size
                    321:            + cd->entry[i].filename_len + LENTRYSIZE;
                    322:        if (j > max)
                    323:            max = j;
                    324:        if (max > cd->offset) {
                    325:            _zip_error_set(error, ZIP_ER_NOZIP, 0);
                    326:            return -1;
                    327:        }
                    328:        
                    329:        if (fseeko(fp, cd->entry[i].offset, SEEK_SET) != 0) {
                    330:            _zip_error_set(error, ZIP_ER_SEEK, 0);
                    331:            return -1;
                    332:        }
                    333:        
                    334:        if (_zip_dirent_read(&temp, fp, NULL, NULL, 1, error) == -1)
                    335:            return -1;
                    336:        
                    337:        if (_zip_headercomp(cd->entry+i, 0, &temp, 1) != 0) {
                    338:            _zip_error_set(error, ZIP_ER_INCONS, 0);
                    339:            _zip_dirent_finalize(&temp);
                    340:            return -1;
                    341:        }
                    342:        _zip_dirent_finalize(&temp);
                    343:     }
                    344: 
                    345:     return max - min;
                    346: }
                    347: 
                    348: 
                    349: 
                    350: /* _zip_check_torrentzip:
1.1.1.2 ! misho     351:    check whether ZA has a valid TORRENTZIP comment, i.e. is torrentzipped */
1.1       misho     352: 
                    353: static void
                    354: _zip_check_torrentzip(struct zip *za)
                    355: {
                    356:     uLong crc_got, crc_should;
                    357:     char buf[8+1];
                    358:     char *end;
                    359: 
                    360:     if (za->zp == NULL || za->cdir == NULL)
                    361:        return;
                    362: 
                    363:     if (za->cdir->comment_len != TORRENT_SIG_LEN+8
                    364:        || strncmp(za->cdir->comment, TORRENT_SIG, TORRENT_SIG_LEN) != 0)
                    365:        return;
1.1.1.2 ! misho     366: 
1.1       misho     367:     memcpy(buf, za->cdir->comment+TORRENT_SIG_LEN, 8);
                    368:     buf[8] = '\0';
                    369:     errno = 0;
                    370:     crc_should = strtoul(buf, &end, 16);
                    371:     if ((crc_should == UINT_MAX && errno != 0) || (end && *end))
                    372:        return;
1.1.1.2 ! misho     373: 
1.1       misho     374:     if (_zip_filerange_crc(za->zp, za->cdir->offset, za->cdir->size,
                    375:                           &crc_got, NULL) < 0)
1.1.1.2 ! misho     376:        return;
1.1       misho     377: 
                    378:     if (crc_got == crc_should)
                    379:        za->flags |= ZIP_AFL_TORRENT;
                    380: }
                    381: 
                    382: 
                    383: 
                    384: 
                    385: /* _zip_headercomp:
                    386:    compares two headers h1 and h2; if they are local headers, set
                    387:    local1p or local2p respectively to 1, else 0. Return 0 if they
                    388:    are identical, -1 if not. */
                    389: 
                    390: static int
                    391: _zip_headercomp(struct zip_dirent *h1, int local1p, struct zip_dirent *h2,
                    392:           int local2p)
                    393: {
                    394:     if ((h1->version_needed != h2->version_needed)
                    395: #if 0
                    396:        /* some zip-files have different values in local
                    397:           and global headers for the bitflags */
                    398:        || (h1->bitflags != h2->bitflags)
                    399: #endif
                    400:        || (h1->comp_method != h2->comp_method)
                    401:        || (h1->last_mod != h2->last_mod)
                    402:        || (h1->filename_len != h2->filename_len)
                    403:        || !h1->filename || !h2->filename
                    404:        || strcmp(h1->filename, h2->filename))
                    405:        return -1;
                    406: 
                    407:     /* check that CRC and sizes are zero if data descriptor is used */
                    408:     if ((h1->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) && local1p
                    409:        && (h1->crc != 0
                    410:            || h1->comp_size != 0
                    411:            || h1->uncomp_size != 0))
                    412:        return -1;
                    413:     if ((h2->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) && local2p
                    414:        && (h2->crc != 0
                    415:            || h2->comp_size != 0
                    416:            || h2->uncomp_size != 0))
                    417:        return -1;
                    418:     
                    419:     /* check that CRC and sizes are equal if no data descriptor is used */
                    420:     if (((h1->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local1p == 0)
                    421:        && ((h2->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local2p == 0)) {
                    422:        if ((h1->crc != h2->crc)
                    423:            || (h1->comp_size != h2->comp_size)
                    424:            || (h1->uncomp_size != h2->uncomp_size))
                    425:            return -1;
                    426:     }
                    427:     
                    428:     if ((local1p == local2p)
                    429:        && ((h1->extrafield_len != h2->extrafield_len)
                    430:            || (h1->extrafield_len && h2->extrafield
                    431:                && memcmp(h1->extrafield, h2->extrafield,
                    432:                          h1->extrafield_len))))
                    433:        return -1;
                    434: 
                    435:     /* if either is local, nothing more to check */
                    436:     if (local1p || local2p)
                    437:        return 0;
                    438: 
                    439:     if ((h1->version_madeby != h2->version_madeby)
                    440:        || (h1->disk_number != h2->disk_number)
                    441:        || (h1->int_attrib != h2->int_attrib)
                    442:        || (h1->ext_attrib != h2->ext_attrib)
                    443:        || (h1->offset != h2->offset)
                    444:        || (h1->comment_len != h2->comment_len)
                    445:        || (h1->comment_len && h2->comment
                    446:            && memcmp(h1->comment, h2->comment, h1->comment_len)))
                    447:        return -1;
                    448: 
                    449:     return 0;
                    450: }
                    451: 
                    452: 
                    453: 
                    454: static struct zip *
                    455: _zip_allocate_new(const char *fn, int *zep)
                    456: {
                    457:     struct zip *za;
                    458:     struct zip_error error;
                    459: 
                    460:     if ((za=_zip_new(&error)) == NULL) {
                    461:        set_error(zep, &error, 0);
                    462:        return NULL;
                    463:     }
1.1.1.2 ! misho     464: 
        !           465:     if (fn == NULL)
        !           466:        za->zn = NULL;
        !           467:     else {
        !           468:        za->zn = strdup(fn);
        !           469:        if (!za->zn) {
        !           470:            _zip_free(za);
        !           471:            set_error(zep, NULL, ZIP_ER_MEMORY);
        !           472:            return NULL;
        !           473:        }
1.1       misho     474:     }
                    475:     return za;
                    476: }
                    477: 
                    478: 
                    479: 
                    480: static int
                    481: _zip_file_exists(const char *fn, int flags, int *zep)
                    482: {
                    483:     struct stat st;
                    484: 
                    485:     if (fn == NULL) {
                    486:        set_error(zep, NULL, ZIP_ER_INVAL);
                    487:        return -1;
                    488:     }
                    489:     
                    490:     if (stat(fn, &st) != 0) {
                    491:        if (flags & ZIP_CREATE || flags & ZIP_OVERWRITE)
                    492:            return 0;
                    493:        else {
                    494:            set_error(zep, NULL, ZIP_ER_OPEN);
                    495:            return -1;
                    496:        }
                    497:     }
                    498:     else if ((flags & ZIP_EXCL)) {
                    499:        set_error(zep, NULL, ZIP_ER_EXISTS);
                    500:        return -1;
                    501:     }
                    502:     /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL,
                    503:        just like open() */
                    504: 
                    505:     return 1;
                    506: }
                    507: 
                    508: 
                    509: 
                    510: static struct zip_cdir *
                    511: _zip_find_central_dir(FILE *fp, int flags, int *zep, off_t len)
                    512: {
                    513:     struct zip_cdir *cdir, *cdirnew;
                    514:     unsigned char *buf, *match;
1.1.1.2 ! misho     515:     off_t buf_offset;
1.1       misho     516:     int a, best, buflen, i;
                    517:     struct zip_error zerr;
                    518: 
                    519:     i = fseeko(fp, -(len < CDBUFSIZE ? len : CDBUFSIZE), SEEK_END);
                    520:     if (i == -1 && errno != EFBIG) {
                    521:        /* seek before start of file on my machine */
                    522:        set_error(zep, NULL, ZIP_ER_SEEK);
                    523:        return NULL;
                    524:     }
1.1.1.2 ! misho     525:     buf_offset = ftello(fp);
        !           526:     
1.1       misho     527:     /* 64k is too much for stack */
                    528:     if ((buf=(unsigned char *)malloc(CDBUFSIZE)) == NULL) {
                    529:        set_error(zep, NULL, ZIP_ER_MEMORY);
                    530:        return NULL;
                    531:     }
                    532: 
                    533:     clearerr(fp);
                    534:     buflen = fread(buf, 1, CDBUFSIZE, fp);
                    535: 
                    536:     if (ferror(fp)) {
                    537:        set_error(zep, NULL, ZIP_ER_READ);
                    538:        free(buf);
                    539:        return NULL;
                    540:     }
                    541:     
                    542:     best = -1;
                    543:     cdir = NULL;
                    544:     match = buf;
                    545:     _zip_error_set(&zerr, ZIP_ER_NOZIP, 0);
                    546: 
                    547:     while ((match=_zip_memmem(match, buflen-(match-buf)-18,
                    548:                              (const unsigned char *)EOCD_MAGIC, 4))!=NULL) {
                    549:        /* found match -- check, if good */
                    550:        /* to avoid finding the same match all over again */
                    551:        match++;
1.1.1.2 ! misho     552:        if ((cdirnew=_zip_readcdir(fp, buf_offset, buf, match-1, buflen, flags,
1.1       misho     553:                                   &zerr)) == NULL)
                    554:            continue;
                    555: 
                    556:        if (cdir) {
                    557:            if (best <= 0)
                    558:                best = _zip_checkcons(fp, cdir, &zerr);
                    559:            a = _zip_checkcons(fp, cdirnew, &zerr);
                    560:            if (best < a) {
                    561:                _zip_cdir_free(cdir);
                    562:                cdir = cdirnew;
                    563:                best = a;
                    564:            }
                    565:            else
                    566:                _zip_cdir_free(cdirnew);
                    567:        }
                    568:        else {
                    569:            cdir = cdirnew;
                    570:            if (flags & ZIP_CHECKCONS)
                    571:                best = _zip_checkcons(fp, cdir, &zerr);
                    572:            else
                    573:                best = 0;
                    574:        }
                    575:        cdirnew = NULL;
                    576:     }
                    577: 
                    578:     free(buf);
                    579:     
                    580:     if (best < 0) {
                    581:        set_error(zep, &zerr, 0);
                    582:        _zip_cdir_free(cdir);
                    583:        return NULL;
                    584:     }
                    585: 
                    586:     return cdir;
                    587: }
                    588: 
                    589: 
                    590: 
                    591: static unsigned char *
                    592: _zip_memmem(const unsigned char *big, int biglen, const unsigned char *little, 
                    593:        int littlelen)
                    594: {
                    595:     const unsigned char *p;
                    596:     
                    597:     if ((biglen < littlelen) || (littlelen == 0))
                    598:        return NULL;
                    599:     p = big-1;
                    600:     while ((p=(const unsigned char *)
                    601:                memchr(p+1, little[0], (size_t)(big-(p+1)+biglen-littlelen+1)))
                    602:           != NULL) {
                    603:        if (memcmp(p+1, little+1, littlelen-1)==0)
                    604:            return (unsigned char *)p;
                    605:     }
                    606: 
                    607:     return NULL;
                    608: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>