Diff for /embedaddon/php/ext/zip/lib/zip_close.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/21 23:48:05 version 1.1.1.2, 2013/07/22 01:32:11
Line 1 Line 1
 /*  /*
   zip_close.c -- close zip archive and update changes    zip_close.c -- close zip archive and update changes
  Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner  Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner
   
   This file is part of libzip, a library to manipulate ZIP archives.    This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>    The authors can be contacted at <libzip@nih.at>
Line 33 Line 33
   
   
   
   #include "zipint.h"
   
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <errno.h>  #include <errno.h>
   #ifdef HAVE_UNISTD_H
   #include <unistd.h>
   #endif
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/stat.h>  #include <sys/stat.h>
   #ifdef PHP_WIN32
   #include <io.h>
   #include <fcntl.h>
   #endif
   
 #include "zipint.h"  
   
 static int add_data(struct zip *, struct zip_source *, struct zip_dirent *,  static int add_data(struct zip *, struct zip_source *, struct zip_dirent *,
                     FILE *);                      FILE *);
 static int add_data_comp(zip_source_callback, void *, struct zip_stat *,  
                          FILE *, struct zip_error *);  
 static int add_data_uncomp(struct zip *, zip_source_callback, void *,  
                            struct zip_stat *, FILE *);  
 static void ch_set_error(struct zip_error *, zip_source_callback, void *);  
 static int copy_data(FILE *, off_t, FILE *, struct zip_error *);  static int copy_data(FILE *, off_t, FILE *, struct zip_error *);
   static int copy_source(struct zip *, struct zip_source *, FILE *);
 static int write_cdir(struct zip *, struct zip_cdir *, FILE *);  static int write_cdir(struct zip *, struct zip_cdir *, FILE *);
 static int _zip_cdir_set_comment(struct zip_cdir *, struct zip *);  static int _zip_cdir_set_comment(struct zip_cdir *, struct zip *);
 static int _zip_changed(struct zip *, int *);  
 static char *_zip_create_temp_output(struct zip *, FILE **);  static char *_zip_create_temp_output(struct zip *, FILE **);
 static int _zip_torrentzip_cmp(const void *, const void *);  static int _zip_torrentzip_cmp(const void *, const void *);
   
Line 72  zip_close(struct zip *za) Line 74  zip_close(struct zip *za)
     int i, j, error;      int i, j, error;
     char *temp;      char *temp;
     FILE *out;      FILE *out;
   #ifndef PHP_WIN32
     mode_t mask;      mode_t mask;
   #endif
     struct zip_cdir *cd;      struct zip_cdir *cd;
     struct zip_dirent de;      struct zip_dirent de;
     struct filelist *filelist;      struct filelist *filelist;
Line 99  zip_close(struct zip *za) Line 103  zip_close(struct zip *za)
         }          }
         _zip_free(za);          _zip_free(za);
         return 0;          return 0;
    }    }          
   
     if ((filelist=(struct filelist *)malloc(sizeof(filelist[0])*survivors))      if ((filelist=(struct filelist *)malloc(sizeof(filelist[0])*survivors))
         == NULL)          == NULL)
Line 126  zip_close(struct zip *za) Line 130  zip_close(struct zip *za)
         cd->comment_len = TORRENT_SIG_LEN + TORRENT_CRC_LEN;          cd->comment_len = TORRENT_SIG_LEN + TORRENT_CRC_LEN;
     }      }
     else if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, ZIP_FL_UNCHANGED) == 0) {      else if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, ZIP_FL_UNCHANGED) == 0) {
    if (_zip_cdir_set_comment(cd, za) == -1) {        if (_zip_cdir_set_comment(cd, za) == -1) {
        _zip_cdir_free(cd);            _zip_cdir_free(cd);
             free(filelist);              free(filelist);
        return -1;            return -1;
         }
     }      }
     }  
   
     if ((temp=_zip_create_temp_output(za, &out)) == NULL) {      if ((temp=_zip_create_temp_output(za, &out)) == NULL) {
         _zip_cdir_free(cd);          _zip_cdir_free(cd);
Line 160  zip_close(struct zip *za) Line 164  zip_close(struct zip *za)
     for (j=0; j<survivors; j++) {      for (j=0; j<survivors; j++) {
         i = filelist[j].idx;          i = filelist[j].idx;
   
           _zip_dirent_init(&de);
   
         /* create new local directory entry */          /* create new local directory entry */
         if (ZIP_ENTRY_DATA_CHANGED(za->entry+i) || new_torrentzip) {          if (ZIP_ENTRY_DATA_CHANGED(za->entry+i) || new_torrentzip) {
             _zip_dirent_init(&de);  
   
             if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))              if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
                 _zip_dirent_torrent_normalize(&de);                  _zip_dirent_torrent_normalize(&de);
Line 188  zip_close(struct zip *za) Line 193  zip_close(struct zip *za)
         }          }
         else {          else {
             /* copy existing directory entries */              /* copy existing directory entries */
            if (fseeko(za->zp, za->cdir->entry[i].offset, SEEK_SET) != 0) {            if ((NULL == za->zp) || (fseeko(za->zp, za->cdir->entry[i].offset, SEEK_SET) != 0)) {
                 _zip_error_set(&za->error, ZIP_ER_SEEK, errno);                  _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
                 error = 1;                  error = 1;
                 break;                  break;
Line 198  zip_close(struct zip *za) Line 203  zip_close(struct zip *za)
                 error = 1;                  error = 1;
                 break;                  break;
             }              }
            memcpy(cd->entry+j, za->cdir->entry+i, sizeof(cd->entry[j]));            memcpy(cd->entry+j, za->cdir->entry+i, sizeof(cd->entry[j]));
 
             if (de.bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {              if (de.bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
                 de.crc = za->cdir->entry[i].crc;                  de.crc = za->cdir->entry[i].crc;
                 de.comp_size = za->cdir->entry[i].comp_size;                  de.comp_size = za->cdir->entry[i].comp_size;
Line 220  zip_close(struct zip *za) Line 224  zip_close(struct zip *za)
             cd->entry[j].filename_len = de.filename_len;              cd->entry[j].filename_len = de.filename_len;
         }          }
   
           if (za->entry[i].ch_extra_len != -1) {
               free(de.extrafield);
               if ((de.extrafield=malloc(za->entry[i].ch_extra_len)) == NULL) {
                   error = 1;
                   break;
               }
               memcpy(de.extrafield, za->entry[i].ch_extra, za->entry[i].ch_extra_len);
               de.extrafield_len = za->entry[i].ch_extra_len;
               /* as the rest of cd entries, its malloc/free is done by za */
               /* TODO unsure if this should also be set in the CD --
                * not done for now
               cd->entry[j].extrafield = za->entry[i].ch_extra;
               cd->entry[j].extrafield_len = za->entry[i].ch_extra_len;
               */
           }
   
         if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 0          if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 0
             && za->entry[i].ch_comment_len != -1) {              && za->entry[i].ch_comment_len != -1) {
             /* as the rest of cd entries, its malloc/free is done by za */              /* as the rest of cd entries, its malloc/free is done by za */
Line 234  zip_close(struct zip *za) Line 254  zip_close(struct zip *za)
   
             zs = NULL;              zs = NULL;
             if (!ZIP_ENTRY_DATA_CHANGED(za->entry+i)) {              if (!ZIP_ENTRY_DATA_CHANGED(za->entry+i)) {
                        if ((zs=zip_source_zip(za, za, i, ZIP_FL_RECOMPRESS, 0, -1)) == NULL) {                if ((zs=zip_source_zip(za, za, i, ZIP_FL_RECOMPRESS, 0, -1))
                                error = 1;                    == NULL) {
                                break;                    error = 1;
                }                    break;
                 }
             }              }
   
             if (add_data(za, zs ? zs : za->entry[i].source, &de, out) < 0) {              if (add_data(za, zs ? zs : za->entry[i].source, &de, out) < 0) {
                 error = 1;                  error = 1;
                   if (zs)
                       zip_source_free(zs);
                 break;                  break;
             }              }
               if (zs)
                   zip_source_free(zs);
               
             cd->entry[j].last_mod = de.last_mod;              cd->entry[j].last_mod = de.last_mod;
             cd->entry[j].comp_method = de.comp_method;              cd->entry[j].comp_method = de.comp_method;
             cd->entry[j].comp_size = de.comp_size;              cd->entry[j].comp_size = de.comp_size;
Line 291  zip_close(struct zip *za) Line 317  zip_close(struct zip *za)
         free(temp);          free(temp);
         return -1;          return -1;
     }      }
    
        if (za->zp) {    if (za->zp) {
                fclose(za->zp);        fclose(za->zp);
                za->zp = NULL;        za->zp = NULL;
                reopen_on_error = 1;        reopen_on_error = 1;
     }      }
     if (_zip_rename(temp, za->zn) != 0) {      if (_zip_rename(temp, za->zn) != 0) {
                _zip_error_set(&za->error, ZIP_ER_RENAME, errno);        _zip_error_set(&za->error, ZIP_ER_RENAME, errno);
                remove(temp);        remove(temp);
                free(temp);        free(temp);
                if (reopen_on_error) {        if (reopen_on_error) {
                /* ignore errors, since we're already in an error case */            /* ignore errors, since we're already in an error case */
                za->zp = fopen(za->zn, "rb");            za->zp = fopen(za->zn, "rb");
                } 
                return -1; 
         }          }
           return -1;
       }
   #ifndef PHP_WIN32
     mask = umask(0);      mask = umask(0);
     umask(mask);      umask(mask);
     chmod(za->zn, 0666&~mask);      chmod(za->zn, 0666&~mask);
    if (za->ch_comment)#endif
        free(za->ch_comment); 
   
     _zip_free(za);      _zip_free(za);
         free(temp);          free(temp);
Line 322  zip_close(struct zip *za) Line 348  zip_close(struct zip *za)
   
   
 static int  static int
add_data(struct zip *za, struct zip_source *zs, struct zip_dirent *de, FILE *ft)add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de,
          FILE *ft)
 {  {
    off_t offstart, offend;    off_t offstart, offdata, offend;
    zip_source_callback cb; 
    void *ud; 
     struct zip_stat st;      struct zip_stat st;
    struct zip_source *s2;
    cb = zs->f;    zip_compression_implementation comp_impl;
    ud = zs->ud;    int ret;
    
    if (cb(ud, &st, sizeof(st), ZIP_SOURCE_STAT) < (ssize_t)sizeof(st)) {    if (zip_source_stat(src, &st) < 0) {
        ch_set_error(&za->error, cb, ud);        _zip_error_set_from_source(&za->error, src);
         return -1;          return -1;
     }      }
   
     if (cb(ud, NULL, 0, ZIP_SOURCE_OPEN) < 0) {  
         ch_set_error(&za->error, cb, ud);  
         return -1;  
     }  
   
     offstart = ftello(ft);      offstart = ftello(ft);
   
     if (_zip_dirent_write(de, ft, 1, &za->error) < 0)      if (_zip_dirent_write(de, ft, 1, &za->error) < 0)
         return -1;          return -1;
   
    if (st.comp_method != ZIP_CM_STORE) {    if ((s2=zip_source_crc(za, src, 0)) == NULL) {
        if (add_data_comp(cb, ud, &st, ft, &za->error) < 0)        zip_source_pop(s2);
            return -1;        return -1;
     }      }
    else {    
        if (add_data_uncomp(za, cb, ud, &st, ft) < 0)    /* XXX: deflate 0-byte files for torrentzip? */
     if (((st.valid & ZIP_STAT_COMP_METHOD) == 0
          || st.comp_method == ZIP_CM_STORE)
         && ((st.valid & ZIP_STAT_SIZE) == 0 || st.size != 0)) {
         comp_impl = NULL;
         if ((comp_impl=zip_get_compression_implementation(ZIP_CM_DEFLATE))
             == NULL) {
             _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
             zip_source_pop(s2);
             return -1;              return -1;
           }
           if ((s2=comp_impl(za, s2, ZIP_CM_DEFLATE, ZIP_CODEC_ENCODE))
               == NULL) {
               /* XXX: set error? */
               zip_source_pop(s2);
               return -1;
           }
     }      }
       else
           s2 = src;
   
    if (cb(ud, NULL, 0, ZIP_SOURCE_CLOSE) < 0) {    offdata = ftello(ft);
        ch_set_error(&za->error, cb, ud);        
        return -1;    ret = copy_source(za, s2, ft);
         
     if (zip_source_stat(s2, &st) < 0)
         ret = -1;
     
     while (s2 != src) {
         if ((s2=zip_source_pop(s2)) == NULL) {
             /* XXX: set erorr */
             ret = -1;
             break;
         }
     }      }
   
       if (ret < 0)
           return -1;
   
     offend = ftello(ft);      offend = ftello(ft);
   
     if (fseeko(ft, offstart, SEEK_SET) < 0) {      if (fseeko(ft, offstart, SEEK_SET) < 0) {
Line 368  add_data(struct zip *za, struct zip_source *zs, struct Line 418  add_data(struct zip *za, struct zip_source *zs, struct
         return -1;          return -1;
     }      }
   
       
     de->last_mod = st.mtime;      de->last_mod = st.mtime;
     de->comp_method = st.comp_method;      de->comp_method = st.comp_method;
     de->crc = st.crc;      de->crc = st.crc;
     de->uncomp_size = st.size;      de->uncomp_size = st.size;
    de->comp_size = st.comp_size;    de->comp_size = offend - offdata;
   
     if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))      if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
         _zip_dirent_torrent_normalize(de);          _zip_dirent_torrent_normalize(de);
   
     if (_zip_dirent_write(de, ft, 1, &za->error) < 0)      if (_zip_dirent_write(de, ft, 1, &za->error) < 0)
         return -1;          return -1;
    
     if (fseeko(ft, offend, SEEK_SET) < 0) {      if (fseeko(ft, offend, SEEK_SET) < 0) {
         _zip_error_set(&za->error, ZIP_ER_SEEK, errno);          _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
         return -1;          return -1;
Line 392  add_data(struct zip *za, struct zip_source *zs, struct Line 441  add_data(struct zip *za, struct zip_source *zs, struct
   
   
 static int  static int
 add_data_comp(zip_source_callback cb, void *ud, struct zip_stat *st,FILE *ft,  
               struct zip_error *error)  
 {  
     char buf[BUFSIZE];  
     ssize_t n;  
   
     st->comp_size = 0;  
     while ((n=cb(ud, buf, sizeof(buf), ZIP_SOURCE_READ)) > 0) {  
         if (fwrite(buf, 1, n, ft) != (size_t)n) {  
             _zip_error_set(error, ZIP_ER_WRITE, errno);  
             return -1;  
         }  
   
         st->comp_size += n;  
     }  
     if (n < 0) {  
         ch_set_error(error, cb, ud);  
         return -1;  
     }  
   
     return 0;  
 }  
   
   
   
 static int  
 add_data_uncomp(struct zip *za, zip_source_callback cb, void *ud,  
                 struct zip_stat *st, FILE *ft)  
 {  
     char b1[BUFSIZE], b2[BUFSIZE];  
     int end, flush, ret;  
     ssize_t n;  
     size_t n2;  
     z_stream zstr;  
     int mem_level;  
   
     st->comp_method = ZIP_CM_DEFLATE;  
     st->comp_size = st->size = 0;  
     st->crc = crc32(0, NULL, 0);  
   
     zstr.zalloc = Z_NULL;  
     zstr.zfree = Z_NULL;  
     zstr.opaque = NULL;  
     zstr.avail_in = 0;  
     zstr.avail_out = 0;  
   
     if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))  
         mem_level = TORRENT_MEM_LEVEL;  
     else  
         mem_level = MAX_MEM_LEVEL;  
   
     /* -MAX_WBITS: undocumented feature of zlib to _not_ write a zlib header */  
     deflateInit2(&zstr, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, mem_level,  
                  Z_DEFAULT_STRATEGY);  
   
     zstr.next_out = (Bytef *)b2;  
     zstr.avail_out = sizeof(b2);  
     zstr.next_in = NULL;  
     zstr.avail_in = 0;  
   
     flush = 0;  
     end = 0;  
     while (!end) {  
         if (zstr.avail_in == 0 && !flush) {  
             if ((n=cb(ud, b1, sizeof(b1), ZIP_SOURCE_READ)) < 0) {  
                 ch_set_error(&za->error, cb, ud);  
                 deflateEnd(&zstr);  
                 return -1;  
             }  
             if (n > 0) {  
                 zstr.avail_in = n;  
                 zstr.next_in = (Bytef *)b1;  
                 st->size += n;  
                 st->crc = crc32(st->crc, (Bytef *)b1, n);  
             }  
             else  
                 flush = Z_FINISH;  
         }  
   
         ret = deflate(&zstr, flush);  
         if (ret != Z_OK && ret != Z_STREAM_END) {  
             _zip_error_set(&za->error, ZIP_ER_ZLIB, ret);  
             return -1;  
         }  
   
         if (zstr.avail_out != sizeof(b2)) {  
             n2 = sizeof(b2) - zstr.avail_out;  
   
             if (fwrite(b2, 1, n2, ft) != n2) {  
                 _zip_error_set(&za->error, ZIP_ER_WRITE, errno);  
                 return -1;  
             }  
   
             zstr.next_out = (Bytef *)b2;  
             zstr.avail_out = sizeof(b2);  
             st->comp_size += n2;  
         }  
   
         if (ret == Z_STREAM_END) {  
             deflateEnd(&zstr);  
             end = 1;  
         }  
     }  
   
     return 0;  
 }  
   
   
   
 static void  
 ch_set_error(struct zip_error *error, zip_source_callback cb, void *ud)  
 {  
     int e[2];  
   
     if ((cb(ud, e, sizeof(e), ZIP_SOURCE_ERROR)) < (ssize_t)sizeof(e)) {  
         error->zip_err = ZIP_ER_INTERNAL;  
         error->sys_err = 0;  
     }  
     else {  
         error->zip_err = e[0];  
         error->sys_err = e[1];  
     }  
 }  
   
   
   
 static int  
 copy_data(FILE *fs, off_t len, FILE *ft, struct zip_error *error)  copy_data(FILE *fs, off_t len, FILE *ft, struct zip_error *error)
 {  {
     char buf[BUFSIZE];      char buf[BUFSIZE];
Line 552  copy_data(FILE *fs, off_t len, FILE *ft, struct zip_er Line 474  copy_data(FILE *fs, off_t len, FILE *ft, struct zip_er
   
   
 static int  static int
   copy_source(struct zip *za, struct zip_source *src, FILE *ft)
   {
       char buf[BUFSIZE];
       zip_int64_t n;
       int ret;
   
       if (zip_source_open(src) < 0) {
           _zip_error_set_from_source(&za->error, src);
           return -1;
       }
   
       ret = 0;
       while ((n=zip_source_read(src, buf, sizeof(buf))) > 0) {
           if (fwrite(buf, 1, n, ft) != (size_t)n) {
               _zip_error_set(&za->error, ZIP_ER_WRITE, errno);
               ret = -1;
               break;
           }
       }
       
       if (n < 0) {
           if (ret == 0)
               _zip_error_set_from_source(&za->error, src);
           ret = -1;
       }   
   
       zip_source_close(src);
       
       return ret;
   }
   
   
   
   static int
 write_cdir(struct zip *za, struct zip_cdir *cd, FILE *out)  write_cdir(struct zip *za, struct zip_cdir *cd, FILE *out)
 {  {
     off_t offset;      off_t offset;
Line 613  _zip_cdir_set_comment(struct zip_cdir *dest, struct zi Line 569  _zip_cdir_set_comment(struct zip_cdir *dest, struct zi
   
   
   
static intint
 _zip_changed(struct zip *za, int *survivorsp)  _zip_changed(struct zip *za, int *survivorsp)
 {  {
     int changed, i, survivors;      int changed, i, survivors;
Line 626  _zip_changed(struct zip *za, int *survivorsp) Line 582  _zip_changed(struct zip *za, int *survivorsp)
   
     for (i=0; i<za->nentry; i++) {      for (i=0; i<za->nentry; i++) {
         if ((za->entry[i].state != ZIP_ST_UNCHANGED)          if ((za->entry[i].state != ZIP_ST_UNCHANGED)
               || (za->entry[i].ch_extra_len != -1)
             || (za->entry[i].ch_comment_len != -1))              || (za->entry[i].ch_comment_len != -1))
             changed = 1;              changed = 1;
         if (za->entry[i].state != ZIP_ST_DELETED)          if (za->entry[i].state != ZIP_ST_DELETED)
             survivors++;              survivors++;
     }      }
   
    *survivorsp = survivors;    if (survivorsp)
         *survivorsp = survivors;
   
     return changed;      return changed;
 }  }
Line 668  _zip_create_temp_output(struct zip *za, FILE **outp) Line 626  _zip_create_temp_output(struct zip *za, FILE **outp)
         return NULL;          return NULL;
     }      }
 #ifdef PHP_WIN32  #ifdef PHP_WIN32
       /*
         According to Pierre Joye, Windows in some environments per
         default creates text files, so force binary mode.
       */
         _setmode(_fileno(tfp), _O_BINARY );          _setmode(_fileno(tfp), _O_BINARY );
 #endif  #endif
   

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


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