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

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

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