Rizin
unix-like reverse engineering framework and cli tools
zip_close.c File Reference
#include "zipint.h"
#include <stdio.h>
#include <stdlib.h>

Go to the source code of this file.

Functions

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 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)
 
ZIP_EXTERN int zip_close (zip_t *za)
 
int _zip_changed (const zip_t *za, zip_uint64_t *survivorsp)
 

Function Documentation

◆ _zip_changed()

int _zip_changed ( const zip_t za,
zip_uint64_t survivorsp 
)

Definition at line 655 of file zip_close.c.

655  {
656  int changed;
657  zip_uint64_t i, survivors;
658 
659  changed = 0;
660  survivors = 0;
661 
662  if (za->comment_changed || za->ch_flags != za->flags) {
663  changed = 1;
664  }
665 
666  for (i = 0; i < za->nentry; i++) {
667  if (ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
668  changed = 1;
669  }
670  if (!za->entry[i].deleted) {
671  survivors++;
672  }
673  }
674 
675  if (survivorsp) {
676  *survivorsp = survivors;
677  }
678 
679  return changed;
680 }
lzma_index ** i
Definition: index.h:629
bool deleted
Definition: zipint.h:412
unsigned int flags
Definition: zipint.h:283
unsigned int ch_flags
Definition: zipint.h:284
zip_entry_t * entry
Definition: zipint.h:294
zip_uint64_t nentry
Definition: zipint.h:292
bool comment_changed
Definition: zipint.h:290
uint64_t zip_uint64_t
Definition: zipconf.h:39
#define ZIP_ENTRY_HAS_CHANGES(e)
Definition: zipint.h:477
zip_t * za
Definition: ziptool.c:79

References zip::ch_flags, zip::comment_changed, zip_entry::deleted, zip::entry, zip::flags, i, zip::nentry, za, and ZIP_ENTRY_HAS_CHANGES.

Referenced by zip_close(), and zip_set_archive_flag().

◆ add_data()

static int add_data ( zip_t za,
zip_source_t src,
zip_dirent_t de,
zip_uint32_t  changed 
)
static

Definition at line 288 of file zip_close.c.

288  {
289  zip_int64_t offstart, offdata, offend, data_length;
290  zip_stat_t st;
291  zip_file_attributes_t attributes;
292  zip_source_t *src_final, *src_tmp;
293  int ret;
294  int is_zip64;
296  bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt;
297 
298  if (zip_source_stat(src, &st) < 0) {
300  return -1;
301  }
302 
303  if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
306  }
307 
309  de->comp_method = st.comp_method;
310  else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) {
312  st.comp_size = st.size;
313  }
314  else {
315  /* we'll recompress */
316  st.valid &= ~ZIP_STAT_COMP_SIZE;
317  }
318 
319  if ((st.valid & ZIP_STAT_ENCRYPTION_METHOD) == 0) {
322  }
323 
325 
326  if ((st.valid & ZIP_STAT_SIZE) == 0) {
328  data_length = -1;
329  }
330  else {
331  de->uncomp_size = st.size;
332  /* this is technically incorrect (copy_source counts compressed data), but it's the best we have */
333  data_length = (zip_int64_t)st.size;
334 
335  if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
336  zip_uint64_t max_compressed_size;
337  zip_uint16_t compression_method = ZIP_CM_ACTUAL(de->comp_method);
338 
339  if (compression_method == ZIP_CM_STORE) {
340  max_compressed_size = st.size;
341  }
342  else {
343  zip_compression_algorithm_t *algorithm = _zip_get_compression_algorithm(compression_method, true);
344  if (algorithm == NULL) {
345  max_compressed_size = ZIP_UINT64_MAX;
346  }
347  else {
348  max_compressed_size = algorithm->maximum_compressed_size(st.size);
349  }
350  }
351 
352  if (max_compressed_size > 0xffffffffu) {
354  }
355  }
356  else {
357  de->comp_size = st.comp_size;
358  data_length = (zip_int64_t)st.comp_size;
359  }
360  }
361 
362  if ((offstart = zip_source_tell_write(za->src)) < 0) {
364  return -1;
365  }
366 
367  /* as long as we don't support non-seekable output, clear data descriptor bit */
369  if ((is_zip64 = _zip_dirent_write(za, de, flags)) < 0) {
370  return -1;
371  }
372 
373  needs_recompress = st.comp_method != ZIP_CM_ACTUAL(de->comp_method);
374  needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE);
375  /* in these cases we can compute the CRC ourselves, so we do */
376  needs_crc = (st.comp_method == ZIP_CM_STORE) || needs_decompress;
377  needs_compress = needs_recompress && (de->comp_method != ZIP_CM_STORE);
378 
379  needs_reencrypt = needs_recompress || (de->changed & ZIP_DIRENT_PASSWORD) || (de->encryption_method != st.encryption_method);
380  needs_decrypt = needs_reencrypt && (st.encryption_method != ZIP_EM_NONE);
381  needs_encrypt = needs_reencrypt && (de->encryption_method != ZIP_EM_NONE);
382 
383  src_final = src;
384  zip_source_keep(src_final);
385 
386  if (needs_decrypt) {
388 
391  zip_source_free(src_final);
392  return -1;
393  }
394  if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) {
395  /* error set by impl */
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_decompress) {
405  if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == 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_crc) {
415  if ((src_tmp = zip_source_crc_create(src_final, 0, &za->error)) == 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  if (needs_compress) {
425  if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) {
426  zip_source_free(src_final);
427  return -1;
428  }
429 
430  zip_source_free(src_final);
431  src_final = src_tmp;
432  }
433 
434 
435  if (needs_encrypt) {
437  const char *password = NULL;
438 
439  if (de->password) {
440  password = de->password;
441  }
442  else if (za->default_password) {
443  password = za->default_password;
444  }
445 
448  zip_source_free(src_final);
449  return -1;
450  }
451 
454 
455  /* PKWare encryption uses last_mod, make sure it gets the right value. */
456  if (de->changed & ZIP_DIRENT_LAST_MOD) {
457  zip_stat_t st_mtime;
458  zip_stat_init(&st_mtime);
459  st_mtime.valid = ZIP_STAT_MTIME;
460  st_mtime.mtime = de->last_mod;
461  if ((src_tmp = _zip_source_window_new(src_final, 0, -1, &st_mtime, NULL, NULL, 0, &za->error)) == NULL) {
462  zip_source_free(src_final);
463  return -1;
464  }
465  zip_source_free(src_final);
466  src_final = src_tmp;
467  }
468  }
469 
470  if ((src_tmp = impl(za, src_final, de->encryption_method, ZIP_CODEC_ENCODE, password)) == NULL) {
471  /* error set by impl */
472  zip_source_free(src_final);
473  return -1;
474  }
475 
476  zip_source_free(src_final);
477  src_final = src_tmp;
478  }
479 
480 
481  if ((offdata = zip_source_tell_write(za->src)) < 0) {
483  return -1;
484  }
485 
486  ret = copy_source(za, src_final, data_length);
487 
488  if (zip_source_stat(src_final, &st) < 0) {
489  _zip_error_set_from_source(&za->error, src_final);
490  ret = -1;
491  }
492 
493  if (zip_source_get_file_attributes(src_final, &attributes) != 0) {
494  _zip_error_set_from_source(&za->error, src_final);
495  ret = -1;
496  }
497 
498  zip_source_free(src_final);
499 
500  if (ret < 0) {
501  return -1;
502  }
503 
504  if ((offend = zip_source_tell_write(za->src)) < 0) {
506  return -1;
507  }
508 
509  if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) {
511  return -1;
512  }
513 
516  return -1;
517  }
518 
519  if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
520  if (st.valid & ZIP_STAT_MTIME)
521  de->last_mod = st.mtime;
522  else
523  time(&de->last_mod);
524  }
525  de->comp_method = st.comp_method;
526  de->crc = st.crc;
527  de->uncomp_size = st.size;
528  de->comp_size = (zip_uint64_t)(offend - offdata);
529  _zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed);
530 
531  if ((ret = _zip_dirent_write(za, de, flags)) < 0)
532  return -1;
533 
534  if (is_zip64 != ret) {
535  /* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
537  return -1;
538  }
539 
540  if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
542  return -1;
543  }
544 
546  if (write_data_descriptor(za, de, is_zip64) < 0) {
547  return -1;
548  }
549  }
550 
551  return 0;
552 }
lzma_index * src
Definition: index.h:567
#define NULL
Definition: cris-opc.c:27
#define ZIP_ER_INTERNAL
Definition: zip.h:125
ZIP_EXTERN void zip_error_set(zip_error_t *_Nullable, int, int)
Definition: zip_error.c:126
#define ZIP_CM_STORE
Definition: zip.h:149
ZIP_EXTERN int zip_source_seek_write(zip_source_t *_Nonnull, zip_int64_t, int)
#define ZIP_STAT_SIZE
Definition: zip.h:292
#define ZIP_EM_TRAD_PKWARE
Definition: zip.h:178
#define ZIP_STAT_COMP_METHOD
Definition: zip.h:296
ZIP_EXTERN int zip_source_get_file_attributes(zip_source_t *_Nonnull, zip_file_attributes_t *_Nonnull)
ZIP_EXTERN void zip_stat_init(zip_stat_t *_Nonnull)
Definition: zip_stat_init.c:40
#define ZIP_ER_ENCRNOTSUPP
Definition: zip.h:129
ZIP_EXTERN int zip_source_stat(zip_source_t *_Nonnull, zip_stat_t *_Nonnull)
#define ZIP_STAT_ENCRYPTION_METHOD
Definition: zip.h:297
#define ZIP_STAT_COMP_SIZE
Definition: zip.h:293
#define ZIP_EM_NONE
Definition: zip.h:177
ZIP_EXTERN zip_int64_t zip_source_tell_write(zip_source_t *_Nonnull)
#define ZIP_STAT_MTIME
Definition: zip.h:294
zip_uint32_t zip_flags_t
Definition: zip.h:347
ZIP_EXTERN void zip_source_free(zip_source_t *_Nullable)
#define ZIP_STAT_CRC
Definition: zip.h:295
ZIP_EXTERN void zip_source_keep(zip_source_t *_Nonnull)
static static fork const void static count static fd const char const char static newpath char char char static envp time
Definition: sflib.h:42
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
zip_uint64_t(* maximum_compressed_size)(zip_uint64_t uncompressed_size)
Definition: zipint.h:126
zip_uint16_t bitflags
Definition: zipint.h:335
time_t last_mod
Definition: zipint.h:337
zip_uint64_t uncomp_size
Definition: zipint.h:340
zip_uint32_t crc
Definition: zipint.h:338
char * password
Definition: zipint.h:351
zip_int32_t comp_method
Definition: zipint.h:336
zip_uint64_t comp_size
Definition: zipint.h:339
zip_uint32_t changed
Definition: zipint.h:327
zip_uint16_t encryption_method
Definition: zipint.h:350
zip_uint16_t compression_level
Definition: zipint.h:349
Definition: zip.h:300
time_t mtime
Definition: zip.h:306
zip_uint16_t encryption_method
Definition: zip.h:309
zip_uint64_t valid
Definition: zip.h:301
zip_uint16_t comp_method
Definition: zip.h:308
zip_uint64_t comp_size
Definition: zip.h:305
zip_uint32_t crc
Definition: zip.h:307
zip_uint64_t size
Definition: zip.h:304
zip_error_t error
Definition: zipint.h:281
zip_source_t * src
Definition: zipint.h:279
char * default_password
Definition: zipint.h:286
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
#define SEEK_SET
Definition: zip.c:88
static int copy_source(zip_t *, zip_source_t *, zip_int64_t)
Definition: zip_close.c:592
static int write_data_descriptor(zip_t *za, const zip_dirent_t *dirent, int is_zip64)
Definition: zip_close.c:683
void _zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes, bool force_zip64, zip_uint32_t changed)
Definition: zip_dirent.c:1117
int _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
Definition: zip_dirent.c:765
void _zip_error_set_from_source(zip_error_t *err, zip_source_t *src)
Definition: zip_error.c:135
zip_encryption_implementation _zip_get_encryption_implementation(zip_uint16_t em, int operation)
zip_compression_algorithm_t * _zip_get_compression_algorithm(zip_int32_t method, bool compress)
zip_source_t * zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t method)
zip_source_t * zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t method, int compression_flags)
zip_source_t * zip_source_crc_create(zip_source_t *src, int validate, zip_error_t *error)
zip_source_t * _zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_int64_t length, zip_stat_t *st, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error)
uint16_t zip_uint16_t
Definition: zipconf.h:35
#define ZIP_UINT64_MAX
Definition: zipconf.h:55
int64_t zip_int64_t
Definition: zipconf.h:38
#define ZIP_CODEC_ENCODE
Definition: zipint.h:108
#define ZIP_DIRENT_PASSWORD
Definition: zipint.h:323
zip_source_t *(* zip_encryption_implementation)(zip_t *, zip_source_t *, zip_uint16_t, int, const char *)
Definition: zipint.h:110
#define ZIP_EF_LOCAL
Definition: zipint.h:243
#define ZIP_CM_IS_DEFAULT(x)
Definition: zipint.h:82
#define ZIP_FL_FORCE_ZIP64
Definition: zipint.h:247
#define ZIP_CM_ACTUAL(x)
Definition: zipint.h:83
#define ZIP_CODEC_DECODE
Definition: zipint.h:107
#define ZIP_GPBF_DATA_DESCRIPTOR
Definition: zipint.h:237
#define ZIP_DIRENT_LAST_MOD
Definition: zipint.h:321

References _zip_dirent_apply_attributes(), _zip_dirent_write(), _zip_error_set_from_source(), _zip_get_compression_algorithm(), _zip_get_encryption_implementation(), _zip_source_window_new(), zip_dirent::bitflags, zip_dirent::changed, zip_stat::comp_method, zip_dirent::comp_method, zip_stat::comp_size, zip_dirent::comp_size, zip_dirent::compression_level, copy_source(), zip_stat::crc, zip_dirent::crc, zip::default_password, zip_stat::encryption_method, zip_dirent::encryption_method, zip::error, flags, if(), zip_dirent::last_mod, zip_compression_algorithm::maximum_compressed_size, zip_stat::mtime, NULL, zip_dirent::password, SEEK_SET, zip_stat::size, zip::src, src, time, zip_dirent::uncomp_size, zip_stat::valid, write_data_descriptor(), za, ZIP_CM_ACTUAL, ZIP_CM_IS_DEFAULT, ZIP_CM_STORE, ZIP_CODEC_DECODE, ZIP_CODEC_ENCODE, ZIP_DIRENT_LAST_MOD, ZIP_DIRENT_PASSWORD, ZIP_EF_LOCAL, ZIP_EM_NONE, ZIP_EM_TRAD_PKWARE, ZIP_ER_ENCRNOTSUPP, ZIP_ER_INTERNAL, zip_error_set(), ZIP_FL_FORCE_ZIP64, ZIP_GPBF_DATA_DESCRIPTOR, zip_source_compress(), zip_source_crc_create(), zip_source_decompress(), zip_source_free(), zip_source_get_file_attributes(), zip_source_keep(), zip_source_seek_write(), zip_source_stat(), zip_source_tell_write(), ZIP_STAT_COMP_METHOD, ZIP_STAT_COMP_SIZE, ZIP_STAT_CRC, ZIP_STAT_ENCRYPTION_METHOD, zip_stat_init(), ZIP_STAT_MTIME, ZIP_STAT_SIZE, and ZIP_UINT64_MAX.

Referenced by zip_close().

◆ copy_data()

static int copy_data ( zip_t za,
zip_uint64_t  len 
)
static

Definition at line 556 of file zip_close.c.

556  {
558  size_t n;
559  double total = (double)len;
560 
561  if (!byte_array_init(buf, BUFSIZE)) {
563  return -1;
564  }
565 
566  while (len > 0) {
567  n = len > BUFSIZE ? BUFSIZE : len;
568  if (_zip_read(za->src, buf, n, &za->error) < 0) {
570  return -1;
571  }
572 
573  if (_zip_write(za, buf, n) < 0) {
575  return -1;
576  }
577 
578  len -= n;
579 
580  if (_zip_progress_update(za->progress, (total - (double)len) / total) != 0) {
582  return -1;
583  }
584  }
585 
587  return 0;
588 }
size_t len
Definition: 6502dis.c:15
voidpf void * buf
Definition: ioapi.h:138
#define ZIP_ER_MEMORY
Definition: zip.h:119
#define ZIP_ER_CANCELLED
Definition: zip.h:137
int n
Definition: mipsasm.c:19
#define BUFSIZE
zip_progress_t * progress
Definition: zipint.h:302
int _zip_write(zip_t *za, const void *data, zip_uint64_t length)
Definition: zip_io_util.c:121
int _zip_read(zip_source_t *src, zip_uint8_t *b, zip_uint64_t length, zip_error_t *error)
Definition: zip_io_util.c:40
int _zip_progress_update(zip_progress_t *progress, double sub_current)
Definition: zip_progress.c:184
#define byte_array_fini(buf)
Definition: zipint.h:440
#define byte_array_init(buf, size)
Definition: zipint.h:439
#define DEFINE_BYTE_ARRAY(buf, size)
Definition: zipint.h:438

References _zip_progress_update(), _zip_read(), _zip_write(), BUFSIZE, byte_array_fini, byte_array_init, DEFINE_BYTE_ARRAY, zip::error, len, n, zip::progress, zip::src, za, ZIP_ER_CANCELLED, ZIP_ER_MEMORY, and zip_error_set().

Referenced by zip_close().

◆ copy_source()

static int copy_source ( zip_t za,
zip_source_t src,
zip_int64_t  data_length 
)
static

Definition at line 592 of file zip_close.c.

592  {
594  zip_int64_t n, current;
595  int ret;
596 
597  if (zip_source_open(src) < 0) {
599  return -1;
600  }
601 
602  if (!byte_array_init(buf, BUFSIZE)) {
604  return -1;
605  }
606 
607  ret = 0;
608  current = 0;
609  while ((n = zip_source_read(src, buf, BUFSIZE)) > 0) {
610  if (_zip_write(za, buf, (zip_uint64_t)n) < 0) {
611  ret = -1;
612  break;
613  }
614  if (n == BUFSIZE && za->progress && data_length > 0) {
615  current += n;
616  if (_zip_progress_update(za->progress, (double)current / (double)data_length) != 0) {
618  ret = -1;
619  break;
620  }
621  }
622  }
623 
624  if (n < 0) {
626  ret = -1;
627  }
628 
630 
632 
633  return ret;
634 }
ZIP_EXTERN int zip_source_close(zip_source_t *_Nonnull)
ZIP_EXTERN zip_int64_t zip_source_read(zip_source_t *_Nonnull, void *_Nonnull, zip_uint64_t)
ZIP_EXTERN int zip_source_open(zip_source_t *_Nonnull)

References _zip_error_set_from_source(), _zip_progress_update(), _zip_write(), BUFSIZE, byte_array_fini, byte_array_init, DEFINE_BYTE_ARRAY, zip::error, n, zip::progress, src, za, ZIP_ER_CANCELLED, ZIP_ER_MEMORY, zip_error_set(), zip_source_close(), zip_source_open(), and zip_source_read().

Referenced by add_data().

◆ write_cdir()

static int write_cdir ( zip_t za,
const zip_filelist_t filelist,
zip_uint64_t  survivors 
)
static

Definition at line 637 of file zip_close.c.

637  {
638  if (zip_source_tell_write(za->src) < 0) {
639  return -1;
640  }
641 
642  if (_zip_cdir_write(za, filelist, survivors) < 0) {
643  return -1;
644  }
645 
646  if (zip_source_tell_write(za->src) < 0) {
647  return -1;
648  }
649 
650  return 0;
651 }
zip_int64_t _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors)
Definition: zip_dirent.c:121

References _zip_cdir_write(), zip::src, za, and zip_source_tell_write().

Referenced by zip_close().

◆ write_data_descriptor()

static int write_data_descriptor ( zip_t za,
const zip_dirent_t dirent,
int  is_zip64 
)
static

Definition at line 683 of file zip_close.c.

683  {
685  int ret = 0;
686 
687  if (buffer == NULL) {
689  return -1;
690  }
691 
693  _zip_buffer_put_32(buffer, de->crc);
694  if (is_zip64) {
695  _zip_buffer_put_64(buffer, de->comp_size);
696  _zip_buffer_put_64(buffer, de->uncomp_size);
697  }
698  else {
699  _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
700  _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
701  }
702 
703  if (!_zip_buffer_ok(buffer)) {
705  ret = -1;
706  }
707  else {
709  }
710 
712 
713  return ret;
714 }
Definition: buffer.h:15
zip_uint8_t * _zip_buffer_data(zip_buffer_t *buffer)
Definition: zip_buffer.c:40
zip_buffer_t * _zip_buffer_new(zip_uint8_t *data, zip_uint64_t size)
Definition: zip_buffer.c:146
void _zip_buffer_free(zip_buffer_t *buffer)
Definition: zip_buffer.c:46
bool _zip_buffer_ok(zip_buffer_t *buffer)
Definition: zip_buffer.c:198
int _zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i)
Definition: zip_buffer.c:262
int _zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i)
Definition: zip_buffer.c:245
zip_uint64_t _zip_buffer_offset(zip_buffer_t *buffer)
Definition: zip_buffer.c:192
int _zip_buffer_put(zip_buffer_t *buffer, const void *src, size_t length)
Definition: zip_buffer.c:217
uint32_t zip_uint32_t
Definition: zipconf.h:37
#define DATADES_MAGIC
Definition: zipint.h:54
#define MAX_DATA_DESCRIPTOR_LENGTH
Definition: zipint.h:68

References _zip_buffer_data(), _zip_buffer_free(), _zip_buffer_new(), _zip_buffer_offset(), _zip_buffer_ok(), _zip_buffer_put(), _zip_buffer_put_32(), _zip_buffer_put_64(), _zip_write(), zip_dirent::comp_size, zip_dirent::crc, DATADES_MAGIC, zip::error, MAX_DATA_DESCRIPTOR_LENGTH, NULL, zip_dirent::uncomp_size, za, ZIP_ER_INTERNAL, ZIP_ER_MEMORY, and zip_error_set().

Referenced by add_data(), and zip_close().

◆ zip_close()

ZIP_EXTERN int zip_close ( zip_t za)

Definition at line 52 of file zip_close.c.

52  {
53  zip_uint64_t i, j, survivors, unchanged_offset;
55  int error;
56  zip_filelist_t *filelist;
57  int changed;
58 
59  if (za == NULL)
60  return -1;
61 
62  changed = _zip_changed(za, &survivors);
63 
64  /* don't create zip files with no entries */
65  if (survivors == 0) {
66  if ((za->open_flags & ZIP_TRUNCATE) || changed) {
67  if (zip_source_remove(za->src) < 0) {
70  return -1;
71  }
72  }
73  }
74  zip_discard(za);
75  return 0;
76  }
77 
78  if (!changed) {
79  zip_discard(za);
80  return 0;
81  }
82 
83  if (survivors > za->nentry) {
85  return -1;
86  }
87 
88  if ((filelist = (zip_filelist_t *)malloc(sizeof(filelist[0]) * (size_t)survivors)) == NULL)
89  return -1;
90 
91  unchanged_offset = ZIP_UINT64_MAX;
92  /* create list of files with index into original archive */
93  for (i = j = 0; i < za->nentry; i++) {
94  if (za->entry[i].orig != NULL && ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
95  unchanged_offset = ZIP_MIN(unchanged_offset, za->entry[i].orig->offset);
96  }
97  if (za->entry[i].deleted) {
98  continue;
99  }
100 
101  if (j >= survivors) {
102  free(filelist);
104  return -1;
105  }
106 
107  filelist[j].idx = i;
108  j++;
109  }
110  if (j < survivors) {
111  free(filelist);
113  return -1;
114  }
115 
117  unchanged_offset = 0;
118  }
119  else {
120  if (unchanged_offset == ZIP_UINT64_MAX) {
121  /* we're keeping all file data, find the end of the last one */
122  zip_uint64_t last_index = ZIP_UINT64_MAX;
123  unchanged_offset = 0;
124 
125  for (i = 0; i < za->nentry; i++) {
126  if (za->entry[i].orig != NULL) {
127  if (za->entry[i].orig->offset >= unchanged_offset) {
128  unchanged_offset = za->entry[i].orig->offset;
129  last_index = i;
130  }
131  }
132  }
133  if (last_index != ZIP_UINT64_MAX) {
134  if ((unchanged_offset = _zip_file_get_end(za, last_index, &za->error)) == 0) {
135  free(filelist);
136  return -1;
137  }
138  }
139  }
140  if (unchanged_offset > 0) {
141  if (zip_source_begin_write_cloning(za->src, unchanged_offset) < 0) {
142  /* cloning not supported, need to copy everything */
143  unchanged_offset = 0;
144  }
145  }
146  }
147  if (unchanged_offset == 0) {
148  if (zip_source_begin_write(za->src) < 0) {
150  free(filelist);
151  return -1;
152  }
153  }
154 
155  if (_zip_progress_start(za->progress) != 0) {
158  free(filelist);
159  return -1;
160  }
161  error = 0;
162  for (j = 0; j < survivors; j++) {
163  int new_data;
165  zip_dirent_t *de;
166 
167  if (_zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j + 1) / (double)survivors) != 0) {
169  error = 1;
170  break;
171  }
172 
173  i = filelist[j].idx;
174  entry = za->entry + i;
175 
176  if (entry->orig != NULL && entry->orig->offset < unchanged_offset) {
177  /* already implicitly copied by cloning */
178  continue;
179  }
180 
182 
183  /* create new local directory entry */
184  if (entry->changes == NULL) {
185  if ((entry->changes = _zip_dirent_clone(entry->orig)) == NULL) {
187  error = 1;
188  break;
189  }
190  }
191  de = entry->changes;
192 
193  if (_zip_read_local_ef(za, i) < 0) {
194  error = 1;
195  break;
196  }
197 
198  if ((off = zip_source_tell_write(za->src)) < 0) {
200  error = 1;
201  break;
202  }
203  de->offset = (zip_uint64_t)off;
204 
205  if (new_data) {
206  zip_source_t *zs;
207 
208  zs = NULL;
210  if ((zs = _zip_source_zip_new(za, i, ZIP_FL_UNCHANGED, 0, 0, NULL, &za->error)) == NULL) {
211  error = 1;
212  break;
213  }
214  }
215 
216  /* add_data writes dirent */
217  if (add_data(za, zs ? zs : entry->source, de, entry->changes ? entry->changes->changed : 0) < 0) {
218  error = 1;
219  if (zs)
220  zip_source_free(zs);
221  break;
222  }
223  if (zs)
224  zip_source_free(zs);
225  }
226  else {
228 
230  /* when copying data, all sizes are known -> no data descriptor needed */
231  /* except for PKWare encryption, where removing the data descriptor breaks password validation */
233  }
234  if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) {
235  error = 1;
236  break;
237  }
238  if ((offset = _zip_file_get_offset(za, i, &za->error)) == 0) {
239  error = 1;
240  break;
241  }
244  error = 1;
245  break;
246  }
247  if (copy_data(za, de->comp_size) < 0) {
248  error = 1;
249  break;
250  }
251 
253  if (write_data_descriptor(za, de, _zip_dirent_needs_zip64(de, 0)) < 0) {
254  error = 1;
255  break;
256  }
257  }
258  }
259  }
260 
261  if (!error) {
262  if (write_cdir(za, filelist, survivors) < 0)
263  error = 1;
264  }
265 
266  free(filelist);
267 
268  if (!error) {
269  if (zip_source_commit_write(za->src) != 0) {
271  error = 1;
272  }
274  }
275 
276  if (error) {
278  return -1;
279  }
280 
281  zip_discard(za);
282 
283  return 0;
284 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf uLong offset
Definition: ioapi.h:144
ZIP_EXTERN void zip_source_rollback_write(zip_source_t *_Nonnull)
ZIP_EXTERN int zip_source_commit_write(zip_source_t *_Nonnull)
ZIP_EXTERN int zip_error_code_system(const zip_error_t *_Nonnull)
Definition: zip_error.c:40
ZIP_EXTERN int zip_source_seek(zip_source_t *_Nonnull, zip_int64_t, int)
#define ZIP_FL_LOCAL
Definition: zip.h:85
#define ZIP_ER_REMOVE
Definition: zip.h:127
ZIP_EXTERN zip_error_t *_Nonnull zip_source_error(zip_source_t *_Nonnull)
#define ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd)
Definition: zip.h:243
ZIP_EXTERN void zip_discard(zip_t *_Nonnull)
Definition: zip_discard.c:45
@ ZIP_SOURCE_BEGIN_WRITE_CLONING
Definition: zip.h:237
ZIP_EXTERN int zip_source_begin_write(zip_source_t *_Nonnull)
#define ZIP_TRUNCATE
Definition: zip.h:70
ZIP_EXTERN int zip_error_code_zip(const zip_error_t *_Nonnull)
Definition: zip_error.c:46
#define ZIP_FL_UNCHANGED
Definition: zip.h:79
ZIP_EXTERN int zip_source_begin_write_cloning(zip_source_t *_Nonnull, zip_uint64_t)
void * malloc(size_t size)
Definition: malloc.c:123
int off
Definition: pal.c:13
#define ENOENT
Definition: sftypes.h:112
Definition: zipcmp.c:77
zip_uint64_t offset
Definition: zipint.h:347
Definition: zipint.h:408
zip_dirent_t * orig
Definition: zipint.h:409
zip_uint64_t idx
Definition: zipint.h:458
unsigned int open_flags
Definition: zipint.h:280
void error(const char *msg)
Definition: untgz.c:593
int _zip_changed(const zip_t *za, zip_uint64_t *survivorsp)
Definition: zip_close.c:655
static int add_data(zip_t *, zip_source_t *, zip_dirent_t *, zip_uint32_t)
Definition: zip_close.c:288
static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t)
Definition: zip_close.c:637
static int copy_data(zip_t *, zip_uint64_t)
Definition: zip_close.c:556
zip_dirent_t * _zip_dirent_clone(const zip_dirent_t *sde)
Definition: zip_dirent.c:215
bool _zip_dirent_needs_zip64(const zip_dirent_t *de, zip_flags_t flags)
Definition: zip_dirent.c:296
int _zip_read_local_ef(zip_t *za, zip_uint64_t idx)
zip_uint64_t _zip_file_get_end(const zip_t *za, zip_uint64_t index, zip_error_t *error)
zip_uint64_t _zip_file_get_offset(const zip_t *za, zip_uint64_t idx, zip_error_t *error)
int _zip_progress_subrange(zip_progress_t *progress, double start, double end)
Definition: zip_progress.c:172
void _zip_progress_end(zip_progress_t *progress)
Definition: zip_progress.c:68
int _zip_progress_start(zip_progress_t *progress)
Definition: zip_progress.c:151
int zip_source_remove(zip_source_t *src)
zip_int64_t zip_source_supports(zip_source_t *src)
zip_source_t * _zip_source_zip_new(zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_uint64_t len, const char *password, zip_error_t *error)
#define ZIP_ENTRY_DATA_CHANGED(x)
Definition: zipint.h:476
#define ZIP_DIRENT_COMP_METHOD
Definition: zipint.h:316
#define ZIP_MIN(a, b)
Definition: zipint.h:473
#define ZIP_ENTRY_CHANGED(e, f)
Definition: zipint.h:475
#define ZIP_DIRENT_ENCRYPTION_METHOD
Definition: zipint.h:322

References _zip_changed(), _zip_dirent_clone(), _zip_dirent_needs_zip64(), _zip_dirent_write(), _zip_error_set_from_source(), _zip_file_get_end(), _zip_file_get_offset(), _zip_progress_end(), _zip_progress_start(), _zip_progress_subrange(), _zip_read_local_ef(), _zip_source_zip_new(), add_data(), zip_dirent::bitflags, zip_dirent::comp_size, copy_data(), zip_entry::deleted, zip_dirent::encryption_method, ENOENT, zip::entry, zip::error, error(), free(), i, zip_filelist::idx, malloc(), zip::nentry, NULL, off, zip_dirent::offset, zip::open_flags, zip_entry::orig, zip::progress, SEEK_SET, zip::src, write_cdir(), write_data_descriptor(), za, ZIP_DIRENT_COMP_METHOD, ZIP_DIRENT_ENCRYPTION_METHOD, zip_discard(), ZIP_EM_TRAD_PKWARE, ZIP_ENTRY_CHANGED, ZIP_ENTRY_DATA_CHANGED, ZIP_ENTRY_HAS_CHANGES, ZIP_ER_CANCELLED, ZIP_ER_INTERNAL, ZIP_ER_MEMORY, ZIP_ER_REMOVE, zip_error_code_system(), zip_error_code_zip(), zip_error_set(), ZIP_FL_LOCAL, ZIP_FL_UNCHANGED, ZIP_GPBF_DATA_DESCRIPTOR, ZIP_MIN, zip_source_begin_write(), ZIP_SOURCE_BEGIN_WRITE_CLONING, zip_source_begin_write_cloning(), zip_source_commit_write(), zip_source_error(), zip_source_free(), ZIP_SOURCE_MAKE_COMMAND_BITMASK, zip_source_remove(), zip_source_rollback_write(), zip_source_seek(), zip_source_supports(), zip_source_tell_write(), ZIP_TRUNCATE, and ZIP_UINT64_MAX.

Referenced by add_from_zip(), compare_zip(), LLVMFuzzerTestOneInput(), main(), merge_zip(), rz_io_zip_alloc_zipfileobj(), rz_io_zip_flush_file(), rz_io_zip_get_by_file_idx(), rz_io_zip_get_files(), rz_io_zip_slurp_file(), and zin_close().