Annotation of embedaddon/php/ext/zip/lib/zip_close.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:   zip_close.c -- close zip archive and update changes
                      3:   Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner
                      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 <stdio.h>
                     37: #include <stdlib.h>
                     38: #include <string.h>
                     39: #include <errno.h>
                     40: #include <sys/types.h>
                     41: #include <sys/stat.h>
                     42: 
                     43: #include "zipint.h"
                     44: 
                     45: static int add_data(struct zip *, struct zip_source *, struct zip_dirent *,
                     46:                    FILE *);
                     47: static int add_data_comp(zip_source_callback, void *, struct zip_stat *,
                     48:                         FILE *, struct zip_error *);
                     49: static int add_data_uncomp(struct zip *, zip_source_callback, void *,
                     50:                           struct zip_stat *, FILE *);
                     51: static void ch_set_error(struct zip_error *, zip_source_callback, void *);
                     52: static int copy_data(FILE *, off_t, FILE *, struct zip_error *);
                     53: static int write_cdir(struct zip *, struct zip_cdir *, FILE *);
                     54: static int _zip_cdir_set_comment(struct zip_cdir *, struct zip *);
                     55: static int _zip_changed(struct zip *, int *);
                     56: static char *_zip_create_temp_output(struct zip *, FILE **);
                     57: static int _zip_torrentzip_cmp(const void *, const void *);
                     58: 
                     59: 
                     60: 
                     61: struct filelist {
                     62:     int idx;
                     63:     const char *name;
                     64: };
                     65: 
                     66: 
                     67: 
                     68: ZIP_EXTERN(int)
                     69: zip_close(struct zip *za)
                     70: {
                     71:     int survivors;
                     72:     int i, j, error;
                     73:     char *temp;
                     74:     FILE *out;
                     75:     mode_t mask;
                     76:     struct zip_cdir *cd;
                     77:     struct zip_dirent de;
                     78:     struct filelist *filelist;
                     79:     int reopen_on_error;
                     80:     int new_torrentzip;
                     81: 
                     82:     reopen_on_error = 0;
                     83: 
                     84:     if (za == NULL)
                     85:        return -1;
                     86: 
                     87:     if (!_zip_changed(za, &survivors)) {
                     88:        _zip_free(za);
                     89:        return 0;
                     90:     }
                     91: 
                     92:     /* don't create zip files with no entries */
                     93:     if (survivors == 0) {
                     94:        if (za->zn && za->zp) {
                     95:            if (remove(za->zn) != 0) {
                     96:                _zip_error_set(&za->error, ZIP_ER_REMOVE, errno);
                     97:                return -1;
                     98:            }
                     99:        }
                    100:        _zip_free(za);
                    101:        return 0;
                    102:     }
                    103: 
                    104:     if ((filelist=(struct filelist *)malloc(sizeof(filelist[0])*survivors))
                    105:        == NULL)
                    106:        return -1;
                    107: 
                    108:     if ((cd=_zip_cdir_new(survivors, &za->error)) == NULL) {
                    109:        free(filelist);
                    110:        return -1;
                    111:     }
                    112: 
                    113:     for (i=0; i<survivors; i++)
                    114:        _zip_dirent_init(&cd->entry[i]);
                    115: 
                    116:     /* archive comment is special for torrentzip */
                    117:     if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) {
                    118:        cd->comment = _zip_memdup(TORRENT_SIG "XXXXXXXX",
                    119:                                  TORRENT_SIG_LEN + TORRENT_CRC_LEN,
                    120:                                  &za->error);
                    121:        if (cd->comment == NULL) {
                    122:            _zip_cdir_free(cd);
                    123:            free(filelist);
                    124:            return -1;
                    125:        }
                    126:        cd->comment_len = TORRENT_SIG_LEN + TORRENT_CRC_LEN;
                    127:     }
                    128:     else if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, ZIP_FL_UNCHANGED) == 0) {
                    129:     if (_zip_cdir_set_comment(cd, za) == -1) {
                    130:        _zip_cdir_free(cd);
                    131:            free(filelist);
                    132:        return -1;
                    133:     }
                    134:     }
                    135: 
                    136:     if ((temp=_zip_create_temp_output(za, &out)) == NULL) {
                    137:        _zip_cdir_free(cd);
                    138:        free(filelist);
                    139:        return -1;
                    140:     }
                    141: 
                    142: 
                    143:     /* create list of files with index into original archive  */
                    144:     for (i=j=0; i<za->nentry; i++) {
                    145:        if (za->entry[i].state == ZIP_ST_DELETED)
                    146:            continue;
                    147: 
                    148:        filelist[j].idx = i;
                    149:        filelist[j].name = zip_get_name(za, i, 0);
                    150:        j++;
                    151:     }
                    152:     if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
                    153:        qsort(filelist, survivors, sizeof(filelist[0]),
                    154:              _zip_torrentzip_cmp);
                    155: 
                    156:     new_torrentzip = (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 1
                    157:                      && zip_get_archive_flag(za, ZIP_AFL_TORRENT,
                    158:                                              ZIP_FL_UNCHANGED) == 0);
                    159:     error = 0;
                    160:     for (j=0; j<survivors; j++) {
                    161:        i = filelist[j].idx;
                    162: 
                    163:        /* create new local directory entry */
                    164:        if (ZIP_ENTRY_DATA_CHANGED(za->entry+i) || new_torrentzip) {
                    165:            _zip_dirent_init(&de);
                    166: 
                    167:            if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
                    168:                _zip_dirent_torrent_normalize(&de);
                    169:                
                    170:            /* use it as central directory entry */
                    171:            memcpy(cd->entry+j, &de, sizeof(cd->entry[j]));
                    172: 
                    173:            /* set/update file name */
                    174:            if (za->entry[i].ch_filename == NULL) {
                    175:                if (za->entry[i].state == ZIP_ST_ADDED) {
                    176:                    de.filename = strdup("-");
                    177:                    de.filename_len = 1;
                    178:                    cd->entry[j].filename = "-";
                    179:                    cd->entry[j].filename_len = 1;
                    180:                }
                    181:                else {
                    182:                    de.filename = strdup(za->cdir->entry[i].filename);
                    183:                    de.filename_len = strlen(de.filename);
                    184:                    cd->entry[j].filename = za->cdir->entry[i].filename;
                    185:                    cd->entry[j].filename_len = de.filename_len;
                    186:                }
                    187:            }
                    188:        }
                    189:        else {
                    190:            /* copy existing directory entries */
                    191:            if (fseeko(za->zp, za->cdir->entry[i].offset, SEEK_SET) != 0) {
                    192:                _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
                    193:                error = 1;
                    194:                break;
                    195:            }
                    196:            if (_zip_dirent_read(&de, za->zp, NULL, NULL, 1,
                    197:                                 &za->error) != 0) {
                    198:                error = 1;
                    199:                break;
                    200:            }
                    201:            memcpy(cd->entry+j, za->cdir->entry+i, sizeof(cd->entry[j]));
                    202: 
                    203:            if (de.bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
                    204:                de.crc = za->cdir->entry[i].crc;
                    205:                de.comp_size = za->cdir->entry[i].comp_size;
                    206:                de.uncomp_size = za->cdir->entry[i].uncomp_size;
                    207:                de.bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR;
                    208:            cd->entry[j].bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR;
                    209:                }
                    210:        }
                    211: 
                    212:        if (za->entry[i].ch_filename) {
                    213:            free(de.filename);
                    214:            if ((de.filename=strdup(za->entry[i].ch_filename)) == NULL) {
                    215:                error = 1;
                    216:                break;
                    217:            }
                    218:            de.filename_len = strlen(de.filename);
                    219:            cd->entry[j].filename = za->entry[i].ch_filename;
                    220:            cd->entry[j].filename_len = de.filename_len;
                    221:        }
                    222: 
                    223:        if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 0
                    224:            && za->entry[i].ch_comment_len != -1) {
                    225:            /* as the rest of cd entries, its malloc/free is done by za */
                    226:            cd->entry[j].comment = za->entry[i].ch_comment;
                    227:            cd->entry[j].comment_len = za->entry[i].ch_comment_len;
                    228:        }
                    229: 
                    230:        cd->entry[j].offset = ftello(out);
                    231: 
                    232:        if (ZIP_ENTRY_DATA_CHANGED(za->entry+i) || new_torrentzip) {
                    233:            struct zip_source *zs;
                    234: 
                    235:            zs = NULL;
                    236:            if (!ZIP_ENTRY_DATA_CHANGED(za->entry+i)) {
                    237:                        if ((zs=zip_source_zip(za, za, i, ZIP_FL_RECOMPRESS, 0, -1)) == NULL) {
                    238:                                error = 1;
                    239:                                break;
                    240:                }
                    241:            }
                    242: 
                    243:            if (add_data(za, zs ? zs : za->entry[i].source, &de, out) < 0) {
                    244:                error = 1;
                    245:                break;
                    246:            }
                    247:            cd->entry[j].last_mod = de.last_mod;
                    248:            cd->entry[j].comp_method = de.comp_method;
                    249:            cd->entry[j].comp_size = de.comp_size;
                    250:            cd->entry[j].uncomp_size = de.uncomp_size;
                    251:            cd->entry[j].crc = de.crc;
                    252:        }
                    253:        else {
                    254:            if (_zip_dirent_write(&de, out, 1, &za->error) < 0) {
                    255:                error = 1;
                    256:                break;
                    257:            }
                    258:            /* we just read the local dirent, file is at correct position */
                    259:            if (copy_data(za->zp, cd->entry[j].comp_size, out,
                    260:                          &za->error) < 0) {
                    261:                error = 1;
                    262:                break;
                    263:            }
                    264:        }
                    265: 
                    266:        _zip_dirent_finalize(&de);
                    267:     }
                    268: 
                    269:     free(filelist);
                    270: 
                    271:     if (!error) {
                    272:        if (write_cdir(za, cd, out) < 0)
                    273:            error = 1;
                    274:     }
                    275: 
                    276:     /* pointers in cd entries are owned by za */
                    277:     cd->nentry = 0;
                    278:     _zip_cdir_free(cd);
                    279: 
                    280:     if (error) {
                    281:        _zip_dirent_finalize(&de);
                    282:        fclose(out);
                    283:        remove(temp);
                    284:        free(temp);
                    285:        return -1;
                    286:     }
                    287: 
                    288:     if (fclose(out) != 0) {
                    289:        _zip_error_set(&za->error, ZIP_ER_CLOSE, errno);
                    290:        remove(temp);
                    291:        free(temp);
                    292:        return -1;
                    293:     }
                    294: 
                    295:        if (za->zp) {
                    296:                fclose(za->zp);
                    297:                za->zp = NULL;
                    298:                reopen_on_error = 1;
                    299:     }
                    300:     if (_zip_rename(temp, za->zn) != 0) {
                    301:                _zip_error_set(&za->error, ZIP_ER_RENAME, errno);
                    302:                remove(temp);
                    303:                free(temp);
                    304:                if (reopen_on_error) {
                    305:                /* ignore errors, since we're already in an error case */
                    306:                za->zp = fopen(za->zn, "rb");
                    307:                }
                    308:                return -1;
                    309:        }
                    310:     mask = umask(0);
                    311:     umask(mask);
                    312:     chmod(za->zn, 0666&~mask);
                    313:     if (za->ch_comment)
                    314:         free(za->ch_comment);
                    315: 
                    316:     _zip_free(za);
                    317:        free(temp);
                    318: 
                    319:     return 0;
                    320: }
                    321: 
                    322: 
                    323: 
                    324: static int
                    325: add_data(struct zip *za, struct zip_source *zs, struct zip_dirent *de, FILE *ft)
                    326: {
                    327:     off_t offstart, offend;
                    328:     zip_source_callback cb;
                    329:     void *ud;
                    330:     struct zip_stat st;
                    331: 
                    332:     cb = zs->f;
                    333:     ud = zs->ud;
                    334: 
                    335:     if (cb(ud, &st, sizeof(st), ZIP_SOURCE_STAT) < (ssize_t)sizeof(st)) {
                    336:        ch_set_error(&za->error, cb, ud);
                    337:        return -1;
                    338:     }
                    339: 
                    340:     if (cb(ud, NULL, 0, ZIP_SOURCE_OPEN) < 0) {
                    341:        ch_set_error(&za->error, cb, ud);
                    342:        return -1;
                    343:     }
                    344: 
                    345:     offstart = ftello(ft);
                    346: 
                    347:     if (_zip_dirent_write(de, ft, 1, &za->error) < 0)
                    348:        return -1;
                    349: 
                    350:     if (st.comp_method != ZIP_CM_STORE) {
                    351:        if (add_data_comp(cb, ud, &st, ft, &za->error) < 0)
                    352:            return -1;
                    353:     }
                    354:     else {
                    355:        if (add_data_uncomp(za, cb, ud, &st, ft) < 0)
                    356:            return -1;
                    357:     }
                    358: 
                    359:     if (cb(ud, NULL, 0, ZIP_SOURCE_CLOSE) < 0) {
                    360:        ch_set_error(&za->error, cb, ud);
                    361:        return -1;
                    362:     }
                    363: 
                    364:     offend = ftello(ft);
                    365: 
                    366:     if (fseeko(ft, offstart, SEEK_SET) < 0) {
                    367:        _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
                    368:        return -1;
                    369:     }
                    370: 
                    371:     
                    372:     de->last_mod = st.mtime;
                    373:     de->comp_method = st.comp_method;
                    374:     de->crc = st.crc;
                    375:     de->uncomp_size = st.size;
                    376:     de->comp_size = st.comp_size;
                    377: 
                    378:     if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
                    379:        _zip_dirent_torrent_normalize(de);
                    380: 
                    381:     if (_zip_dirent_write(de, ft, 1, &za->error) < 0)
                    382:        return -1;
                    383: 
                    384:     if (fseeko(ft, offend, SEEK_SET) < 0) {
                    385:        _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
                    386:        return -1;
                    387:     }
                    388: 
                    389:     return 0;
                    390: }
                    391: 
                    392: 
                    393: 
                    394: static int
                    395: add_data_comp(zip_source_callback cb, void *ud, struct zip_stat *st,FILE *ft,
                    396:              struct zip_error *error)
                    397: {
                    398:     char buf[BUFSIZE];
                    399:     ssize_t n;
                    400: 
                    401:     st->comp_size = 0;
                    402:     while ((n=cb(ud, buf, sizeof(buf), ZIP_SOURCE_READ)) > 0) {
                    403:        if (fwrite(buf, 1, n, ft) != (size_t)n) {
                    404:            _zip_error_set(error, ZIP_ER_WRITE, errno);
                    405:            return -1;
                    406:        }
                    407: 
                    408:        st->comp_size += n;
                    409:     }
                    410:     if (n < 0) {
                    411:        ch_set_error(error, cb, ud);
                    412:        return -1;
                    413:     }
                    414: 
                    415:     return 0;
                    416: }
                    417: 
                    418: 
                    419: 
                    420: static int
                    421: add_data_uncomp(struct zip *za, zip_source_callback cb, void *ud,
                    422:                struct zip_stat *st, FILE *ft)
                    423: {
                    424:     char b1[BUFSIZE], b2[BUFSIZE];
                    425:     int end, flush, ret;
                    426:     ssize_t n;
                    427:     size_t n2;
                    428:     z_stream zstr;
                    429:     int mem_level;
                    430: 
                    431:     st->comp_method = ZIP_CM_DEFLATE;
                    432:     st->comp_size = st->size = 0;
                    433:     st->crc = crc32(0, NULL, 0);
                    434: 
                    435:     zstr.zalloc = Z_NULL;
                    436:     zstr.zfree = Z_NULL;
                    437:     zstr.opaque = NULL;
                    438:     zstr.avail_in = 0;
                    439:     zstr.avail_out = 0;
                    440: 
                    441:     if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
                    442:        mem_level = TORRENT_MEM_LEVEL;
                    443:     else
                    444:        mem_level = MAX_MEM_LEVEL;
                    445: 
                    446:     /* -MAX_WBITS: undocumented feature of zlib to _not_ write a zlib header */
                    447:     deflateInit2(&zstr, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, mem_level,
                    448:                 Z_DEFAULT_STRATEGY);
                    449: 
                    450:     zstr.next_out = (Bytef *)b2;
                    451:     zstr.avail_out = sizeof(b2);
                    452:     zstr.next_in = NULL;
                    453:     zstr.avail_in = 0;
                    454: 
                    455:     flush = 0;
                    456:     end = 0;
                    457:     while (!end) {
                    458:        if (zstr.avail_in == 0 && !flush) {
                    459:            if ((n=cb(ud, b1, sizeof(b1), ZIP_SOURCE_READ)) < 0) {
                    460:                ch_set_error(&za->error, cb, ud);
                    461:                deflateEnd(&zstr);
                    462:                return -1;
                    463:            }
                    464:            if (n > 0) {
                    465:                zstr.avail_in = n;
                    466:                zstr.next_in = (Bytef *)b1;
                    467:                st->size += n;
                    468:                st->crc = crc32(st->crc, (Bytef *)b1, n);
                    469:            }
                    470:            else
                    471:                flush = Z_FINISH;
                    472:        }
                    473: 
                    474:        ret = deflate(&zstr, flush);
                    475:        if (ret != Z_OK && ret != Z_STREAM_END) {
                    476:            _zip_error_set(&za->error, ZIP_ER_ZLIB, ret);
                    477:            return -1;
                    478:        }
                    479: 
                    480:        if (zstr.avail_out != sizeof(b2)) {
                    481:            n2 = sizeof(b2) - zstr.avail_out;
                    482: 
                    483:            if (fwrite(b2, 1, n2, ft) != n2) {
                    484:                _zip_error_set(&za->error, ZIP_ER_WRITE, errno);
                    485:                return -1;
                    486:            }
                    487: 
                    488:            zstr.next_out = (Bytef *)b2;
                    489:            zstr.avail_out = sizeof(b2);
                    490:            st->comp_size += n2;
                    491:        }
                    492: 
                    493:        if (ret == Z_STREAM_END) {
                    494:            deflateEnd(&zstr);
                    495:            end = 1;
                    496:        }
                    497:     }
                    498: 
                    499:     return 0;
                    500: }
                    501: 
                    502: 
                    503: 
                    504: static void
                    505: ch_set_error(struct zip_error *error, zip_source_callback cb, void *ud)
                    506: {
                    507:     int e[2];
                    508: 
                    509:     if ((cb(ud, e, sizeof(e), ZIP_SOURCE_ERROR)) < (ssize_t)sizeof(e)) {
                    510:        error->zip_err = ZIP_ER_INTERNAL;
                    511:        error->sys_err = 0;
                    512:     }
                    513:     else {
                    514:        error->zip_err = e[0];
                    515:        error->sys_err = e[1];
                    516:     }
                    517: }
                    518: 
                    519: 
                    520: 
                    521: static int
                    522: copy_data(FILE *fs, off_t len, FILE *ft, struct zip_error *error)
                    523: {
                    524:     char buf[BUFSIZE];
                    525:     int n, nn;
                    526: 
                    527:     if (len == 0)
                    528:        return 0;
                    529: 
                    530:     while (len > 0) {
                    531:        nn = len > sizeof(buf) ? sizeof(buf) : len;
                    532:        if ((n=fread(buf, 1, nn, fs)) < 0) {
                    533:            _zip_error_set(error, ZIP_ER_READ, errno);
                    534:            return -1;
                    535:        }
                    536:        else if (n == 0) {
                    537:            _zip_error_set(error, ZIP_ER_EOF, 0);
                    538:            return -1;
                    539:        }
                    540: 
                    541:        if (fwrite(buf, 1, n, ft) != (size_t)n) {
                    542:            _zip_error_set(error, ZIP_ER_WRITE, errno);
                    543:            return -1;
                    544:        }
                    545: 
                    546:        len -= n;
                    547:     }
                    548: 
                    549:     return 0;
                    550: }
                    551: 
                    552: 
                    553: 
                    554: static int
                    555: write_cdir(struct zip *za, struct zip_cdir *cd, FILE *out)
                    556: {
                    557:     off_t offset;
                    558:     uLong crc;
                    559:     char buf[TORRENT_CRC_LEN+1];
                    560:     
                    561:     if (_zip_cdir_write(cd, out, &za->error) < 0)
                    562:        return -1;
                    563:     
                    564:     if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 0)
                    565:        return 0;
                    566: 
                    567: 
                    568:     /* fix up torrentzip comment */
                    569: 
                    570:     offset = ftello(out);
                    571: 
                    572:     if (_zip_filerange_crc(out, cd->offset, cd->size, &crc, &za->error) < 0)
                    573:        return -1;
                    574: 
                    575:     snprintf(buf, sizeof(buf), "%08lX", (long)crc);
                    576: 
                    577:     if (fseeko(out, offset-TORRENT_CRC_LEN, SEEK_SET) < 0) {
                    578:        _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
                    579:        return -1;
                    580:     }
                    581: 
                    582:     if (fwrite(buf, TORRENT_CRC_LEN, 1, out) != 1) {
                    583:        _zip_error_set(&za->error, ZIP_ER_WRITE, errno);
                    584:        return -1;
                    585:     }
                    586: 
                    587:     return 0;
                    588: }
                    589: 
                    590: 
                    591: 
                    592: static int
                    593: _zip_cdir_set_comment(struct zip_cdir *dest, struct zip *src)
                    594: {
                    595:     if (src->ch_comment_len != -1) {
                    596:        dest->comment = _zip_memdup(src->ch_comment,
                    597:                                    src->ch_comment_len, &src->error);
                    598:        if (dest->comment == NULL)
                    599:            return -1;
                    600:        dest->comment_len = src->ch_comment_len;
                    601:     } else {
                    602:        if (src->cdir && src->cdir->comment) {
                    603:            dest->comment = _zip_memdup(src->cdir->comment,
                    604:                                        src->cdir->comment_len, &src->error);
                    605:            if (dest->comment == NULL)
                    606:                return -1;
                    607:            dest->comment_len = src->cdir->comment_len;
                    608:        }
                    609:     }
                    610: 
                    611:     return 0;
                    612: }
                    613: 
                    614: 
                    615: 
                    616: static int
                    617: _zip_changed(struct zip *za, int *survivorsp)
                    618: {
                    619:     int changed, i, survivors;
                    620: 
                    621:     changed = survivors = 0;
                    622: 
                    623:     if (za->ch_comment_len != -1
                    624:        || za->ch_flags != za->flags)
                    625:        changed = 1;
                    626: 
                    627:     for (i=0; i<za->nentry; i++) {
                    628:        if ((za->entry[i].state != ZIP_ST_UNCHANGED)
                    629:            || (za->entry[i].ch_comment_len != -1))
                    630:            changed = 1;
                    631:        if (za->entry[i].state != ZIP_ST_DELETED)
                    632:            survivors++;
                    633:     }
                    634: 
                    635:     *survivorsp = survivors;
                    636: 
                    637:     return changed;
                    638: }
                    639: 
                    640: 
                    641: 
                    642: static char *
                    643: _zip_create_temp_output(struct zip *za, FILE **outp)
                    644: {
                    645:     char *temp;
                    646:     int tfd;
                    647:     FILE *tfp;
                    648:        int len = strlen(za->zn) + 8;
                    649: 
                    650:     if ((temp=(char *)malloc(len)) == NULL) {
                    651:        _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
                    652:        return NULL;
                    653:     }
                    654: 
                    655:                snprintf(temp, len, "%s.XXXXXX", za->zn);
                    656: 
                    657:     if ((tfd=mkstemp(temp)) == -1) {
                    658:        _zip_error_set(&za->error, ZIP_ER_TMPOPEN, errno);
                    659:        free(temp);
                    660:        return NULL;
                    661:     }
                    662: 
                    663:     if ((tfp=fdopen(tfd, "r+b")) == NULL) {
                    664:        _zip_error_set(&za->error, ZIP_ER_TMPOPEN, errno);
                    665:        close(tfd);
                    666:        remove(temp);
                    667:        free(temp);
                    668:        return NULL;
                    669:     }
                    670: #ifdef PHP_WIN32
                    671:        _setmode(_fileno(tfp), _O_BINARY );
                    672: #endif
                    673: 
                    674:     *outp = tfp;
                    675:     return temp;
                    676: }
                    677: 
                    678: 
                    679: 
                    680: static int
                    681: _zip_torrentzip_cmp(const void *a, const void *b)
                    682: {
                    683:     return strcasecmp(((const struct filelist *)a)->name,
                    684:                      ((const struct filelist *)b)->name);
                    685: }

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