diff options
Diffstat (limited to 'src/Common/libzip/zip_close.c')
-rw-r--r-- | src/Common/libzip/zip_close.c | 90 |
1 files changed, 58 insertions, 32 deletions
diff --git a/src/Common/libzip/zip_close.c b/src/Common/libzip/zip_close.c index 8d1a2aa8..6b33cbf5 100644 --- a/src/Common/libzip/zip_close.c +++ b/src/Common/libzip/zip_close.c @@ -45,6 +45,7 @@ static int add_data(zip_t *, zip_source_t *, zip_dirent_t *, zip_uint32_t); static int copy_data(zip_t *, zip_uint64_t); static int copy_source(zip_t *, zip_source_t *, zip_int64_t); +static int torrentzip_compare_names(const void *a, const void *b); static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t); static int write_data_descriptor(zip_t *za, const zip_dirent_t *dirent, int is_zip64); @@ -61,12 +62,12 @@ zip_close(zip_t *za) { changed = _zip_changed(za, &survivors); - /* don't create zip files with no entries */ - if (survivors == 0) { + if (survivors == 0 && !(za->ch_flags & ZIP_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE)) { + /* don't create zip files with no entries */ if ((za->open_flags & ZIP_TRUNCATE) || changed) { if (zip_source_remove(za->src) < 0) { if (!((zip_error_code_zip(zip_source_error(za->src)) == ZIP_ER_REMOVE) && (zip_error_code_system(zip_source_error(za->src)) == ENOENT))) { - _zip_error_set_from_source(&za->error, za->src); + zip_error_set_from_source(&za->error, za->src); return -1; } } @@ -75,7 +76,8 @@ zip_close(zip_t *za) { return 0; } - if (!changed) { + /* Always write empty archive if we are told to keep it, otherwise it wouldn't be created if the file doesn't already exist. */ + if (!changed && survivors > 0) { zip_discard(za); return 0; } @@ -105,6 +107,7 @@ zip_close(zip_t *za) { } filelist[j].idx = i; + filelist[j].name = zip_get_name(za, i, 0); j++; } if (j < survivors) { @@ -113,7 +116,11 @@ zip_close(zip_t *za) { return -1; } - if ((zip_source_supports(za->src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING)) == 0) { + if (ZIP_WANT_TORRENTZIP(za)) { + qsort(filelist, (size_t)survivors, sizeof(filelist[0]), torrentzip_compare_names); + } + + if (ZIP_WANT_TORRENTZIP(za) || (zip_source_supports(za->src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING)) == 0) { unchanged_offset = 0; } else { @@ -146,7 +153,7 @@ zip_close(zip_t *za) { } if (unchanged_offset == 0) { if (zip_source_begin_write(za->src) < 0) { - _zip_error_set_from_source(&za->error, za->src); + zip_error_set_from_source(&za->error, za->src); free(filelist); return -1; } @@ -178,7 +185,7 @@ zip_close(zip_t *za) { continue; } - new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD)); + new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD)) || (ZIP_WANT_TORRENTZIP(za) && !ZIP_IS_TORRENTZIP(za)); /* create new local directory entry */ if (entry->changes == NULL) { @@ -195,8 +202,12 @@ zip_close(zip_t *za) { break; } + if (ZIP_WANT_TORRENTZIP(za)) { + zip_dirent_torrentzip_normalize(entry->changes); + } + if ((off = zip_source_tell_write(za->src)) < 0) { - _zip_error_set_from_source(&za->error, za->src); + zip_error_set_from_source(&za->error, za->src); error = 1; break; } @@ -207,7 +218,7 @@ zip_close(zip_t *za) { zs = NULL; if (!ZIP_ENTRY_DATA_CHANGED(entry)) { - if ((zs = _zip_source_zip_new(za, i, ZIP_FL_UNCHANGED, 0, 0, NULL, &za->error)) == NULL) { + if ((zs = zip_source_zip_file_create(za, i, ZIP_FL_UNCHANGED, 0, -1, NULL, &za->error)) == NULL) { error = 1; break; } @@ -240,7 +251,7 @@ zip_close(zip_t *za) { break; } if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) { - _zip_error_set_from_source(&za->error, za->src); + zip_error_set_from_source(&za->error, za->src); error = 1; break; } @@ -267,7 +278,7 @@ zip_close(zip_t *za) { if (!error) { if (zip_source_commit_write(za->src) != 0) { - _zip_error_set_from_source(&za->error, za->src); + zip_error_set_from_source(&za->error, za->src); error = 1; } _zip_progress_end(za->progress); @@ -296,7 +307,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt; if (zip_source_stat(src, &st) < 0) { - _zip_error_set_from_source(&za->error, src); + zip_error_set_from_source(&za->error, src); return -1; } @@ -324,6 +335,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { flags = ZIP_EF_LOCAL; if ((st.valid & ZIP_STAT_SIZE) == 0) { + /* TODO: not valid for torrentzip */ flags |= ZIP_FL_FORCE_ZIP64; data_length = -1; } @@ -350,6 +362,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { } if (max_compressed_size > 0xffffffffu) { + /* TODO: not valid for torrentzip */ flags |= ZIP_FL_FORCE_ZIP64; } } @@ -360,7 +373,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { } if ((offstart = zip_source_tell_write(za->src)) < 0) { - _zip_error_set_from_source(&za->error, za->src); + zip_error_set_from_source(&za->error, za->src); return -1; } @@ -370,7 +383,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { return -1; } - needs_recompress = st.comp_method != ZIP_CM_ACTUAL(de->comp_method); + needs_recompress = ZIP_WANT_TORRENTZIP(za) || st.comp_method != ZIP_CM_ACTUAL(de->comp_method); needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE); /* in these cases we can compute the CRC ourselves, so we do */ needs_crc = (st.comp_method == ZIP_CM_STORE) || needs_decompress; @@ -397,7 +410,6 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { return -1; } - zip_source_free(src_final); src_final = src_tmp; } @@ -407,7 +419,6 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { return -1; } - zip_source_free(src_final); src_final = src_tmp; } @@ -417,7 +428,6 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { return -1; } - zip_source_free(src_final); src_final = src_tmp; } @@ -427,7 +437,6 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { return -1; } - zip_source_free(src_final); src_final = src_tmp; } @@ -458,11 +467,10 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { zip_stat_init(&st_mtime); st_mtime.valid = ZIP_STAT_MTIME; st_mtime.mtime = de->last_mod; - if ((src_tmp = _zip_source_window_new(src_final, 0, -1, &st_mtime, NULL, NULL, 0, &za->error)) == NULL) { + if ((src_tmp = _zip_source_window_new(src_final, 0, -1, &st_mtime, 0, NULL, NULL, 0, true, &za->error)) == NULL) { zip_source_free(src_final); return -1; } - zip_source_free(src_final); src_final = src_tmp; } } @@ -473,25 +481,24 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { return -1; } - zip_source_free(src_final); src_final = src_tmp; } if ((offdata = zip_source_tell_write(za->src)) < 0) { - _zip_error_set_from_source(&za->error, za->src); + zip_error_set_from_source(&za->error, za->src); return -1; } ret = copy_source(za, src_final, data_length); if (zip_source_stat(src_final, &st) < 0) { - _zip_error_set_from_source(&za->error, src_final); + zip_error_set_from_source(&za->error, src_final); ret = -1; } if (zip_source_get_file_attributes(src_final, &attributes) != 0) { - _zip_error_set_from_source(&za->error, src_final); + zip_error_set_from_source(&za->error, src_final); ret = -1; } @@ -502,12 +509,12 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { } if ((offend = zip_source_tell_write(za->src)) < 0) { - _zip_error_set_from_source(&za->error, za->src); + zip_error_set_from_source(&za->error, za->src); return -1; } if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) { - _zip_error_set_from_source(&za->error, za->src); + zip_error_set_from_source(&za->error, za->src); return -1; } @@ -528,6 +535,10 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { de->comp_size = (zip_uint64_t)(offend - offdata); _zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed); + if (ZIP_WANT_TORRENTZIP(za)) { + zip_dirent_torrentzip_normalize(de); + } + if ((ret = _zip_dirent_write(za, de, flags)) < 0) return -1; @@ -538,7 +549,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { } if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) { - _zip_error_set_from_source(&za->error, za->src); + zip_error_set_from_source(&za->error, za->src); return -1; } @@ -555,7 +566,6 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { static int copy_data(zip_t *za, zip_uint64_t len) { DEFINE_BYTE_ARRAY(buf, BUFSIZE); - size_t n; double total = (double)len; if (!byte_array_init(buf, BUFSIZE)) { @@ -564,7 +574,8 @@ copy_data(zip_t *za, zip_uint64_t len) { } while (len > 0) { - n = len > BUFSIZE ? BUFSIZE : len; + zip_uint64_t n = ZIP_MIN(len, BUFSIZE); + if (_zip_read(za->src, buf, n, &za->error) < 0) { byte_array_fini(buf); return -1; @@ -595,7 +606,7 @@ copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) { int ret; if (zip_source_open(src) < 0) { - _zip_error_set_from_source(&za->error, src); + zip_error_set_from_source(&za->error, src); return -1; } @@ -622,7 +633,7 @@ copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) { } if (n < 0) { - _zip_error_set_from_source(&za->error, src); + zip_error_set_from_source(&za->error, src); ret = -1; } @@ -659,7 +670,7 @@ _zip_changed(const zip_t *za, zip_uint64_t *survivorsp) { changed = 0; survivors = 0; - if (za->comment_changed || za->ch_flags != za->flags) { + if (za->comment_changed || (ZIP_WANT_TORRENTZIP(za) && !ZIP_IS_TORRENTZIP(za))) { changed = 1; } @@ -712,3 +723,18 @@ write_data_descriptor(zip_t *za, const zip_dirent_t *de, int is_zip64) { return ret; } + + +static int torrentzip_compare_names(const void *a, const void *b) { + const char *aname = ((const zip_filelist_t *)a)->name; + const char *bname = ((const zip_filelist_t *)b)->name; + + if (aname == NULL) { + return (bname != NULL) * -1; + } + else if (bname == NULL) { + return 1; + } + + return strcasecmp(aname, bname); +}
\ No newline at end of file |