Annotation of embedaddon/php/ext/zip/lib/zip_close.c, revision 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>