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>