"Fossies" - the Fresh Open Source Software Archive

Member "src/Common/libzip/zip_close.c" (10 Oct 2018, 15895 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "zip_close.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.21_Source_vs_1.22_Source.

    1 /*
    2   zip_close.c -- close zip archive and update changes
    3   Copyright (C) 1999-2017 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 #include "zipint.h"
   36 
   37 #include <stdio.h>
   38 #include <stdlib.h>
   39 #include <string.h>
   40 #ifdef HAVE_STRINGS_H
   41 #include <strings.h>
   42 #endif
   43 #ifdef HAVE_UNISTD_H
   44 #include <unistd.h>
   45 #endif
   46 #include <sys/stat.h>
   47 #include <sys/types.h>
   48 #ifdef _WIN32
   49 #include <fcntl.h>
   50 #include <io.h>
   51 #endif
   52 
   53 
   54 static int add_data(zip_t *, zip_source_t *, zip_dirent_t *);
   55 static int copy_data(zip_t *, zip_uint64_t);
   56 static int copy_source(zip_t *, zip_source_t *, zip_int64_t);
   57 static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t);
   58 
   59 ZIP_EXTERN int
   60 zip_close(zip_t *za) {
   61     zip_uint64_t i, j, survivors, unchanged_offset;
   62     zip_int64_t off;
   63     int error;
   64     zip_filelist_t *filelist;
   65     int changed;
   66 
   67     if (za == NULL)
   68     return -1;
   69 
   70     changed = _zip_changed(za, &survivors);
   71 
   72     /* don't create zip files with no entries */
   73     if (survivors == 0) {
   74     if ((za->open_flags & ZIP_TRUNCATE) || changed) {
   75         if (zip_source_remove(za->src) < 0) {
   76         _zip_error_set_from_source(&za->error, za->src);
   77         return -1;
   78         }
   79     }
   80     zip_discard(za);
   81     return 0;
   82     }
   83 
   84     if (!changed) {
   85     zip_discard(za);
   86     return 0;
   87     }
   88 
   89     if (survivors > za->nentry) {
   90     zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
   91     return -1;
   92     }
   93 
   94     if ((filelist = (zip_filelist_t *)malloc(sizeof(filelist[0]) * (size_t)survivors)) == NULL)
   95     return -1;
   96 
   97     unchanged_offset = ZIP_UINT64_MAX;
   98     /* create list of files with index into original archive  */
   99     for (i = j = 0; i < za->nentry; i++) {
  100     if (za->entry[i].orig != NULL && ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
  101         unchanged_offset = ZIP_MIN(unchanged_offset, za->entry[i].orig->offset);
  102     }
  103     if (za->entry[i].deleted) {
  104         continue;
  105     }
  106 
  107     if (j >= survivors) {
  108         free(filelist);
  109         zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
  110         return -1;
  111     }
  112 
  113     filelist[j].idx = i;
  114     j++;
  115     }
  116     if (j < survivors) {
  117     free(filelist);
  118     zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
  119     return -1;
  120     }
  121 
  122     if ((zip_source_supports(za->src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING)) == 0) {
  123     unchanged_offset = 0;
  124     }
  125     else {
  126     if (unchanged_offset == ZIP_UINT64_MAX) {
  127         /* we're keeping all file data, find the end of the last one */
  128         zip_uint64_t last_index = ZIP_UINT64_MAX;
  129         unchanged_offset = 0;
  130 
  131         for (i = 0; i < za->nentry; i++) {
  132         if (za->entry[i].orig != NULL) {
  133             if (za->entry[i].orig->offset >= unchanged_offset) {
  134             unchanged_offset = za->entry[i].orig->offset;
  135             last_index = i;
  136             }
  137         }
  138         }
  139         if (last_index != ZIP_UINT64_MAX) {
  140         if ((unchanged_offset = _zip_file_get_end(za, last_index, &za->error)) == 0) {
  141             free(filelist);
  142             return -1;
  143         }
  144         }
  145     }
  146     if (unchanged_offset > 0) {
  147         if (zip_source_begin_write_cloning(za->src, unchanged_offset) < 0) {
  148         /* cloning not supported, need to copy everything */
  149         unchanged_offset = 0;
  150         }
  151     }
  152     }
  153     if (unchanged_offset == 0) {
  154     if (zip_source_begin_write(za->src) < 0) {
  155         _zip_error_set_from_source(&za->error, za->src);
  156         free(filelist);
  157         return -1;
  158     }
  159     }
  160 
  161     _zip_progress_start(za->progress);
  162     error = 0;
  163     for (j = 0; j < survivors; j++) {
  164     int new_data;
  165     zip_entry_t *entry;
  166     zip_dirent_t *de;
  167 
  168     _zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j + 1) / (double)survivors);
  169 
  170     i = filelist[j].idx;
  171     entry = za->entry + i;
  172 
  173     if (entry->orig != NULL && entry->orig->offset < unchanged_offset) {
  174         /* already implicitly copied by cloning */
  175         continue;
  176     }
  177 
  178     new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD));
  179 
  180     /* create new local directory entry */
  181     if (entry->changes == NULL) {
  182         if ((entry->changes = _zip_dirent_clone(entry->orig)) == NULL) {
  183         zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
  184         error = 1;
  185         break;
  186         }
  187     }
  188     de = entry->changes;
  189 
  190     if (_zip_read_local_ef(za, i) < 0) {
  191         error = 1;
  192         break;
  193     }
  194 
  195     if ((off = zip_source_tell_write(za->src)) < 0) {
  196         error = 1;
  197         break;
  198     }
  199     de->offset = (zip_uint64_t)off;
  200 
  201     if (new_data) {
  202         zip_source_t *zs;
  203 
  204         zs = NULL;
  205         if (!ZIP_ENTRY_DATA_CHANGED(entry)) {
  206         if ((zs = _zip_source_zip_new(za, za, i, ZIP_FL_UNCHANGED, 0, 0, NULL)) == NULL) {
  207             error = 1;
  208             break;
  209         }
  210         }
  211 
  212         /* add_data writes dirent */
  213         if (add_data(za, zs ? zs : entry->source, de) < 0) {
  214         error = 1;
  215         if (zs)
  216             zip_source_free(zs);
  217         break;
  218         }
  219         if (zs)
  220         zip_source_free(zs);
  221     }
  222     else {
  223         zip_uint64_t offset;
  224 
  225         /* when copying data, all sizes are known -> no data descriptor needed */
  226         de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
  227         if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) {
  228         error = 1;
  229         break;
  230         }
  231         if ((offset = _zip_file_get_offset(za, i, &za->error)) == 0) {
  232         error = 1;
  233         break;
  234         }
  235         if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
  236         _zip_error_set_from_source(&za->error, za->src);
  237         error = 1;
  238         break;
  239         }
  240         if (copy_data(za, de->comp_size) < 0) {
  241         error = 1;
  242         break;
  243         }
  244     }
  245     }
  246 
  247     if (!error) {
  248     if (write_cdir(za, filelist, survivors) < 0)
  249         error = 1;
  250     }
  251 
  252     free(filelist);
  253 
  254     if (!error) {
  255     if (zip_source_commit_write(za->src) != 0) {
  256         _zip_error_set_from_source(&za->error, za->src);
  257         error = 1;
  258     }
  259     }
  260 
  261     _zip_progress_end(za->progress);
  262 
  263     if (error) {
  264     zip_source_rollback_write(za->src);
  265     return -1;
  266     }
  267 
  268     zip_discard(za);
  269 
  270     return 0;
  271 }
  272 
  273 
  274 static int
  275 add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
  276     zip_int64_t offstart, offdata, offend, data_length;
  277     struct zip_stat st;
  278     zip_source_t *src_final, *src_tmp;
  279     int ret;
  280     int is_zip64;
  281     zip_flags_t flags;
  282     zip_int8_t compression_flags;
  283     bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt;
  284 
  285     if (zip_source_stat(src, &st) < 0) {
  286     _zip_error_set_from_source(&za->error, src);
  287     return -1;
  288     }
  289 
  290     if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
  291     st.valid |= ZIP_STAT_COMP_METHOD;
  292     st.comp_method = ZIP_CM_STORE;
  293     }
  294 
  295     if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE)
  296     de->comp_method = st.comp_method;
  297     else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) {
  298     st.valid |= ZIP_STAT_COMP_SIZE;
  299     st.comp_size = st.size;
  300     }
  301     else {
  302     /* we'll recompress */
  303     st.valid &= ~ZIP_STAT_COMP_SIZE;
  304     }
  305 
  306     if ((st.valid & ZIP_STAT_ENCRYPTION_METHOD) == 0) {
  307     st.valid |= ZIP_STAT_ENCRYPTION_METHOD;
  308     st.encryption_method = ZIP_EM_NONE;
  309     }
  310 
  311     flags = ZIP_EF_LOCAL;
  312 
  313     if ((st.valid & ZIP_STAT_SIZE) == 0) {
  314     flags |= ZIP_FL_FORCE_ZIP64;
  315     data_length = -1;
  316     }
  317     else {
  318     de->uncomp_size = st.size;
  319     /* this is technically incorrect (copy_source counts compressed data), but it's the best we have */
  320     data_length = (zip_int64_t)st.size;
  321 
  322     if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
  323         zip_uint64_t max_size;
  324 
  325         switch (ZIP_CM_ACTUAL(de->comp_method)) {
  326         case ZIP_CM_BZIP2:
  327         /* computed by looking at increase of 10 random files of size 1MB when
  328          * compressed with bzip2, rounded up: 1.006 */
  329         max_size = 4269351188u;
  330         break;
  331 
  332         case ZIP_CM_DEFLATE:
  333         /* max deflate size increase: size + ceil(size/16k)*5+6 */
  334         max_size = 4293656963u;
  335         break;
  336 
  337         case ZIP_CM_STORE:
  338         max_size = 0xffffffffu;
  339         break;
  340 
  341         default:
  342         max_size = 0;
  343         }
  344 
  345         if (st.size > max_size) {
  346         flags |= ZIP_FL_FORCE_ZIP64;
  347         }
  348     }
  349     else
  350         de->comp_size = st.comp_size;
  351     }
  352 
  353     if ((offstart = zip_source_tell_write(za->src)) < 0) {
  354     _zip_error_set_from_source(&za->error, za->src);
  355     return -1;
  356     }
  357 
  358     /* as long as we don't support non-seekable output, clear data descriptor bit */
  359     de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
  360     if ((is_zip64 = _zip_dirent_write(za, de, flags)) < 0) {
  361     return -1;
  362     }
  363 
  364     needs_recompress = st.comp_method != ZIP_CM_ACTUAL(de->comp_method);
  365     needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE);
  366     needs_crc = (st.comp_method == ZIP_CM_STORE) || needs_decompress;
  367     needs_compress = needs_recompress && (de->comp_method != ZIP_CM_STORE);
  368 
  369     needs_reencrypt = needs_recompress || (de->changed & ZIP_DIRENT_PASSWORD) || (de->encryption_method != st.encryption_method);
  370     needs_decrypt = needs_reencrypt && (st.encryption_method != ZIP_EM_NONE);
  371     needs_encrypt = needs_reencrypt && (de->encryption_method != ZIP_EM_NONE);
  372 
  373     src_final = src;
  374     zip_source_keep(src_final);
  375 
  376     if (needs_decrypt) {
  377     zip_encryption_implementation impl;
  378 
  379     if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
  380         zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
  381         zip_source_free(src_final);
  382         return -1;
  383     }
  384     if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) {
  385         /* error set by impl */
  386         zip_source_free(src_final);
  387         return -1;
  388     }
  389 
  390     zip_source_free(src_final);
  391     src_final = src_tmp;
  392     }
  393 
  394     if (needs_decompress) {
  395     if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) {
  396         zip_source_free(src_final);
  397         return -1;
  398     }
  399 
  400     zip_source_free(src_final);
  401     src_final = src_tmp;
  402     }
  403 
  404     if (needs_crc) {
  405     if ((src_tmp = zip_source_crc(za, src_final, 0)) == NULL) {
  406         zip_source_free(src_final);
  407         return -1;
  408     }
  409 
  410     zip_source_free(src_final);
  411     src_final = src_tmp;
  412     }
  413 
  414     if (needs_compress) {
  415     if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) {
  416         zip_source_free(src_final);
  417         return -1;
  418     }
  419 
  420     zip_source_free(src_final);
  421     src_final = src_tmp;
  422     }
  423 
  424 
  425     if (needs_encrypt) {
  426     zip_encryption_implementation impl;
  427     const char *password = NULL;
  428 
  429     if (de->password) {
  430         password = de->password;
  431     }
  432     else if (za->default_password) {
  433         password = za->default_password;
  434     }
  435 
  436     if ((impl = _zip_get_encryption_implementation(de->encryption_method, ZIP_CODEC_ENCODE)) == NULL) {
  437         zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
  438         zip_source_free(src_final);
  439         return -1;
  440     }
  441     if ((src_tmp = impl(za, src_final, de->encryption_method, ZIP_CODEC_ENCODE, password)) == NULL) {
  442         /* error set by impl */
  443         zip_source_free(src_final);
  444         return -1;
  445     }
  446 
  447     zip_source_free(src_final);
  448     src_final = src_tmp;
  449     }
  450 
  451 
  452     if ((offdata = zip_source_tell_write(za->src)) < 0) {
  453     _zip_error_set_from_source(&za->error, za->src);
  454     return -1;
  455     }
  456 
  457     ret = copy_source(za, src_final, data_length);
  458 
  459     if (zip_source_stat(src_final, &st) < 0) {
  460     _zip_error_set_from_source(&za->error, src_final);
  461     ret = -1;
  462     }
  463 
  464     if ((compression_flags = zip_source_get_compression_flags(src_final)) < 0) {
  465     _zip_error_set_from_source(&za->error, src_final);
  466     ret = -1;
  467     }
  468 
  469     zip_source_free(src_final);
  470 
  471     if (ret < 0) {
  472     return -1;
  473     }
  474 
  475     if ((offend = zip_source_tell_write(za->src)) < 0) {
  476     _zip_error_set_from_source(&za->error, za->src);
  477     return -1;
  478     }
  479 
  480     if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) {
  481     _zip_error_set_from_source(&za->error, za->src);
  482     return -1;
  483     }
  484 
  485     if ((st.valid & (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) {
  486     zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
  487     return -1;
  488     }
  489 
  490     if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
  491     if (st.valid & ZIP_STAT_MTIME)
  492         de->last_mod = st.mtime;
  493     else
  494         time(&de->last_mod);
  495     }
  496     de->comp_method = st.comp_method;
  497     de->crc = st.crc;
  498     de->uncomp_size = st.size;
  499     de->comp_size = (zip_uint64_t)(offend - offdata);
  500     de->bitflags = (zip_uint16_t)((de->bitflags & (zip_uint16_t)~6) | ((zip_uint8_t)compression_flags << 1));
  501     _zip_dirent_set_version_needed(de, (flags & ZIP_FL_FORCE_ZIP64) != 0);
  502 
  503     if ((ret = _zip_dirent_write(za, de, flags)) < 0)
  504     return -1;
  505 
  506     if (is_zip64 != ret) {
  507     /* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
  508     zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
  509     return -1;
  510     }
  511 
  512     if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
  513     _zip_error_set_from_source(&za->error, za->src);
  514     return -1;
  515     }
  516 
  517     return 0;
  518 }
  519 
  520 
  521 static int
  522 copy_data(zip_t *za, zip_uint64_t len) {
  523     zip_uint8_t buf[BUFSIZE];
  524     size_t n;
  525     double total = (double)len;
  526 
  527     while (len > 0) {
  528     n = len > sizeof(buf) ? sizeof(buf) : len;
  529     if (_zip_read(za->src, buf, n, &za->error) < 0) {
  530         return -1;
  531     }
  532 
  533     if (_zip_write(za, buf, n) < 0) {
  534         return -1;
  535     }
  536 
  537     len -= n;
  538 
  539     _zip_progress_update(za->progress, (total - (double)len) / total);
  540     }
  541 
  542     return 0;
  543 }
  544 
  545 
  546 static int
  547 copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) {
  548     zip_uint8_t buf[BUFSIZE];
  549     zip_int64_t n, current;
  550     int ret;
  551 
  552     if (zip_source_open(src) < 0) {
  553     _zip_error_set_from_source(&za->error, src);
  554     return -1;
  555     }
  556 
  557     ret = 0;
  558     current = 0;
  559     while ((n = zip_source_read(src, buf, sizeof(buf))) > 0) {
  560     if (_zip_write(za, buf, (zip_uint64_t)n) < 0) {
  561         ret = -1;
  562         break;
  563     }
  564     if (n == sizeof(buf) && za->progress && data_length > 0) {
  565         current += n;
  566         _zip_progress_update(za->progress, (double)current / (double)data_length);
  567     }
  568     }
  569 
  570     if (n < 0) {
  571     _zip_error_set_from_source(&za->error, src);
  572     ret = -1;
  573     }
  574 
  575     zip_source_close(src);
  576 
  577     return ret;
  578 }
  579 
  580 static int
  581 write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) {
  582     zip_int64_t cd_start, end, size;
  583 
  584     if ((cd_start = zip_source_tell_write(za->src)) < 0) {
  585     return -1;
  586     }
  587 
  588     if ((size = _zip_cdir_write(za, filelist, survivors)) < 0) {
  589     return -1;
  590     }
  591 
  592     if ((end = zip_source_tell_write(za->src)) < 0) {
  593     return -1;
  594     }
  595 
  596     return 0;
  597 }
  598 
  599 
  600 int
  601 _zip_changed(const zip_t *za, zip_uint64_t *survivorsp) {
  602     int changed;
  603     zip_uint64_t i, survivors;
  604 
  605     changed = 0;
  606     survivors = 0;
  607 
  608     if (za->comment_changed || za->ch_flags != za->flags) {
  609     changed = 1;
  610     }
  611 
  612     for (i = 0; i < za->nentry; i++) {
  613     if (ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
  614         changed = 1;
  615     }
  616     if (!za->entry[i].deleted) {
  617         survivors++;
  618     }
  619     }
  620 
  621     if (survivorsp) {
  622     *survivorsp = survivors;
  623     }
  624 
  625     return changed;
  626 }