aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ObsoleteFiles.inc18
-rw-r--r--contrib/libarchive/COPYING4
-rw-r--r--contrib/libarchive/FREEBSD-Xlist2
-rw-r--r--contrib/libarchive/NEWS97
-rw-r--r--contrib/libarchive/README37
-rw-r--r--contrib/libarchive/cpio/bsdcpio.165
-rw-r--r--contrib/libarchive/cpio/cmdline.c21
-rw-r--r--contrib/libarchive/cpio/cpio.c162
-rw-r--r--contrib/libarchive/cpio/cpio.h8
-rw-r--r--contrib/libarchive/cpio/test/main.c775
-rw-r--r--contrib/libarchive/cpio/test/test.h98
-rw-r--r--contrib/libarchive/cpio/test/test_0.c14
-rw-r--r--contrib/libarchive/cpio/test/test_basic.c49
-rw-r--r--contrib/libarchive/cpio/test/test_format_newc.c45
-rw-r--r--contrib/libarchive/cpio/test/test_option_0.c92
-rw-r--r--contrib/libarchive/cpio/test/test_option_c.c20
-rw-r--r--contrib/libarchive/cpio/test/test_option_t.c31
-rw-r--r--contrib/libarchive/cpio/test/test_option_u.c6
-rw-r--r--contrib/libarchive/cpio/test/test_owner_parse.c11
-rw-r--r--contrib/libarchive/libarchive/archive.h517
-rw-r--r--contrib/libarchive/libarchive/archive_acl.c1267
-rw-r--r--contrib/libarchive/libarchive/archive_acl_private.h87
-rw-r--r--contrib/libarchive/libarchive/archive_check_magic.c80
-rw-r--r--contrib/libarchive/libarchive/archive_crc32.h12
-rw-r--r--contrib/libarchive/libarchive/archive_crypto.c1427
-rw-r--r--contrib/libarchive/libarchive/archive_crypto_private.h376
-rw-r--r--contrib/libarchive/libarchive/archive_entry.3337
-rw-r--r--contrib/libarchive/libarchive/archive_entry.c1335
-rw-r--r--contrib/libarchive/libarchive/archive_entry.h238
-rw-r--r--contrib/libarchive/libarchive/archive_entry_acl.3233
-rw-r--r--contrib/libarchive/libarchive/archive_entry_copy_stat.c8
-rw-r--r--contrib/libarchive/libarchive/archive_entry_link_resolver.c161
-rw-r--r--contrib/libarchive/libarchive/archive_entry_linkify.3224
-rw-r--r--contrib/libarchive/libarchive/archive_entry_locale.h88
-rw-r--r--contrib/libarchive/libarchive/archive_entry_paths.3151
-rw-r--r--contrib/libarchive/libarchive/archive_entry_perms.3207
-rw-r--r--contrib/libarchive/libarchive/archive_entry_private.h86
-rw-r--r--contrib/libarchive/libarchive/archive_entry_sparse.c156
-rw-r--r--contrib/libarchive/libarchive/archive_entry_stat.3272
-rw-r--r--contrib/libarchive/libarchive/archive_entry_stat.c4
-rw-r--r--contrib/libarchive/libarchive/archive_entry_time.3127
-rw-r--r--contrib/libarchive/libarchive/archive_hash.h309
-rw-r--r--contrib/libarchive/libarchive/archive_options.c198
-rw-r--r--contrib/libarchive/libarchive/archive_options_private.h (renamed from usr.bin/cpio/config_freebsd.h)50
-rw-r--r--contrib/libarchive/libarchive/archive_ppmd7.c1164
-rw-r--r--contrib/libarchive/libarchive/archive_ppmd7_private.h119
-rw-r--r--contrib/libarchive/libarchive/archive_ppmd_private.h158
-rw-r--r--contrib/libarchive/libarchive/archive_private.h48
-rw-r--r--contrib/libarchive/libarchive/archive_rb.c701
-rw-r--r--contrib/libarchive/libarchive/archive_rb.h100
-rw-r--r--contrib/libarchive/libarchive/archive_read.3696
-rw-r--r--contrib/libarchive/libarchive/archive_read.c923
-rw-r--r--contrib/libarchive/libarchive/archive_read_data.3128
-rw-r--r--contrib/libarchive/libarchive/archive_read_data_into_fd.c82
-rw-r--r--contrib/libarchive/libarchive/archive_read_disk.331
-rw-r--r--contrib/libarchive/libarchive/archive_read_disk.c198
-rw-r--r--contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c561
-rw-r--r--contrib/libarchive/libarchive/archive_read_disk_posix.c2313
-rw-r--r--contrib/libarchive/libarchive/archive_read_disk_private.h13
-rw-r--r--contrib/libarchive/libarchive/archive_read_disk_set_standard_lookup.c28
-rw-r--r--contrib/libarchive/libarchive/archive_read_extract.3135
-rw-r--r--contrib/libarchive/libarchive/archive_read_extract.c11
-rw-r--r--contrib/libarchive/libarchive/archive_read_filter.3127
-rw-r--r--contrib/libarchive/libarchive/archive_read_format.3175
-rw-r--r--contrib/libarchive/libarchive/archive_read_free.391
-rw-r--r--contrib/libarchive/libarchive/archive_read_header.389
-rw-r--r--contrib/libarchive/libarchive/archive_read_new.357
-rw-r--r--contrib/libarchive/libarchive/archive_read_open.3231
-rw-r--r--contrib/libarchive/libarchive/archive_read_open_fd.c87
-rw-r--r--contrib/libarchive/libarchive/archive_read_open_file.c44
-rw-r--r--contrib/libarchive/libarchive/archive_read_open_filename.c431
-rw-r--r--contrib/libarchive/libarchive/archive_read_open_memory.c77
-rw-r--r--contrib/libarchive/libarchive/archive_read_private.h55
-rw-r--r--contrib/libarchive/libarchive/archive_read_set_options.3207
-rw-r--r--contrib/libarchive/libarchive/archive_read_set_options.c156
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_filter_all.c (renamed from contrib/libarchive/libarchive/archive_read_support_compression_all.c)31
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_filter_bzip2.c (renamed from contrib/libarchive/libarchive/archive_read_support_compression_bzip2.c)29
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_filter_compress.c (renamed from contrib/libarchive/libarchive/archive_read_support_compression_compress.c)40
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_filter_gzip.c (renamed from contrib/libarchive/libarchive/archive_read_support_compression_gzip.c)35
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_filter_none.c (renamed from contrib/libarchive/libarchive/archive_read_support_compression_none.c)16
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_filter_program.c (renamed from contrib/libarchive/libarchive/archive_read_support_compression_program.c)31
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_filter_rpm.c (renamed from contrib/libarchive/libarchive/archive_read_support_compression_rpm.c)33
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_filter_uu.c (renamed from contrib/libarchive/libarchive/archive_read_support_compression_uu.c)85
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_filter_xz.c (renamed from contrib/libarchive/libarchive/archive_read_support_compression_xz.c)455
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_7zip.c3706
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_all.c38
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_ar.c143
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_by_code.c74
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_cab.c3323
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_cpio.c600
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_empty.c20
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_iso9660.c450
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_lha.c2747
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_mtree.c632
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_rar.c2576
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_raw.c58
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_tar.c1180
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_xar.c422
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_zip.c1247
-rw-r--r--contrib/libarchive/libarchive/archive_string.c4304
-rw-r--r--contrib/libarchive/libarchive/archive_string.h178
-rw-r--r--contrib/libarchive/libarchive/archive_string_composition.h1351
-rw-r--r--contrib/libarchive/libarchive/archive_string_sprintf.c50
-rw-r--r--contrib/libarchive/libarchive/archive_util.374
-rw-r--r--contrib/libarchive/libarchive/archive_util.c499
-rw-r--r--contrib/libarchive/libarchive/archive_virtual.c59
-rw-r--r--contrib/libarchive/libarchive/archive_write.3546
-rw-r--r--contrib/libarchive/libarchive/archive_write.c581
-rw-r--r--contrib/libarchive/libarchive/archive_write_add_filter_bzip2.c338
-rw-r--r--contrib/libarchive/libarchive/archive_write_add_filter_compress.c (renamed from contrib/libarchive/libarchive/archive_write_set_compression_compress.c)199
-rw-r--r--contrib/libarchive/libarchive/archive_write_add_filter_gzip.c360
-rw-r--r--contrib/libarchive/libarchive/archive_write_add_filter_none.c43
-rw-r--r--contrib/libarchive/libarchive/archive_write_add_filter_program.c327
-rw-r--r--contrib/libarchive/libarchive/archive_write_add_filter_xz.c505
-rw-r--r--contrib/libarchive/libarchive/archive_write_blocksize.3112
-rw-r--r--contrib/libarchive/libarchive/archive_write_data.360
-rw-r--r--contrib/libarchive/libarchive/archive_write_disk.346
-rw-r--r--contrib/libarchive/libarchive/archive_write_disk_posix.c (renamed from contrib/libarchive/libarchive/archive_write_disk.c)916
-rw-r--r--contrib/libarchive/libarchive/archive_write_disk_set_standard_lookup.c12
-rw-r--r--contrib/libarchive/libarchive/archive_write_filter.398
-rw-r--r--contrib/libarchive/libarchive/archive_write_finish_entry.374
-rw-r--r--contrib/libarchive/libarchive/archive_write_format.398
-rw-r--r--contrib/libarchive/libarchive/archive_write_free.381
-rw-r--r--contrib/libarchive/libarchive/archive_write_header.371
-rw-r--r--contrib/libarchive/libarchive/archive_write_new.356
-rw-r--r--contrib/libarchive/libarchive/archive_write_open.3233
-rw-r--r--contrib/libarchive/libarchive/archive_write_open_filename.c106
-rw-r--r--contrib/libarchive/libarchive/archive_write_open_memory.c12
-rw-r--r--contrib/libarchive/libarchive/archive_write_private.h64
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_compression_bzip2.c408
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_compression_gzip.c477
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_compression_none.c257
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_compression_program.c347
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_compression_xz.c439
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format.c6
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_7zip.c2313
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_ar.c58
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_by_name.c10
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_cpio.c317
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_cpio_newc.c338
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_gnutar.c761
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_iso9660.c8117
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_mtree.c1117
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_pax.c1191
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_shar.c91
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_ustar.c349
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_xar.c3182
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_zip.c336
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_options.3437
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_options.c130
-rw-r--r--contrib/libarchive/libarchive/libarchive-formats.56
-rw-r--r--contrib/libarchive/libarchive/libarchive.3139
-rw-r--r--contrib/libarchive/libarchive/libarchive_changes.3341
-rw-r--r--contrib/libarchive/libarchive/libarchive_internals.36
-rw-r--r--contrib/libarchive/libarchive/tar.5198
-rw-r--r--contrib/libarchive/libarchive/test/main.c767
-rw-r--r--contrib/libarchive/libarchive/test/read_open_memory.c98
-rw-r--r--contrib/libarchive/libarchive/test/test.h96
-rw-r--r--contrib/libarchive/libarchive/test/test_acl_freebsd.c4
-rw-r--r--contrib/libarchive/libarchive/test/test_acl_nfs4.c291
-rw-r--r--contrib/libarchive/libarchive/test/test_acl_pax.c265
-rw-r--r--contrib/libarchive/libarchive/test/test_acl_pax.tar.uu117
-rw-r--r--contrib/libarchive/libarchive/test/test_acl_posix1e.c (renamed from contrib/libarchive/libarchive/test/test_acl_basic.c)66
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_api_feature.c28
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_clear_error.c42
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_crypto.c145
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_read_close_twice.c43
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_read_close_twice_open_fd.c47
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_read_close_twice_open_filename.c47
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_read_next_header_empty.c111
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_read_next_header_raw.c65
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_read_open2.c109
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_read_set_filter_option.c55
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_read_set_format_option.c67
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_read_set_option.c69
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_read_set_options.c126
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_read_support.c98
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_set_error.c51
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_string.c344
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_string_conversion.c629
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_string_conversion.txt.Z.uu2605
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_write_set_filter_option.c55
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_write_set_format_option.c67
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_write_set_option.c69
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_write_set_options.c126
-rw-r--r--contrib/libarchive/libarchive/test/test_bad_fd.c10
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_bzip2.c10
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_cpio.c4
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_gtar.c12
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_gzip.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_lzip.c141
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_lzip_1.tlz.uu10
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_lzip_2.tlz.uu9
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_lzma.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_mac-1.tar.Z.uu38
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_mac-2.tar.Z.uu19
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_mac.c212
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_pax_libarchive_2x.c146
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_pax_libarchive_2x.tar.Z.uu15
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_solaris_pax_sparse.c188
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_solaris_pax_sparse_1.pax.Z.uu53
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_solaris_pax_sparse_2.pax.Z.uu53
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_solaris_tar_acl.c4
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_tar_hardlink.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_xz.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_zip.c367
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_zip_2.zip.uu2
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_zip_3.zip.uu18
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_zip_4.zip.uu25
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_zip_5.zip.uu242
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_zip_6.zip.uu10
-rw-r--r--contrib/libarchive/libarchive/test/test_compat_zip_7.xps.uu357
-rw-r--r--contrib/libarchive/libarchive/test/test_empty_write.c12
-rw-r--r--contrib/libarchive/libarchive/test/test_entry.c157
-rw-r--r--contrib/libarchive/libarchive/test/test_extattr_freebsd.c5
-rw-r--r--contrib/libarchive/libarchive/test/test_filter_count.c75
-rw-r--r--contrib/libarchive/libarchive/test/test_fuzz.c67
-rw-r--r--contrib/libarchive/libarchive/test/test_fuzz.cab.uu49
-rw-r--r--contrib/libarchive/libarchive/test/test_fuzz.lzh.uu152
-rw-r--r--contrib/libarchive/libarchive/test/test_gnutar_filename_encoding.c414
-rw-r--r--contrib/libarchive/libarchive/test/test_open_failure.c38
-rw-r--r--contrib/libarchive/libarchive/test/test_open_fd.c10
-rw-r--r--contrib/libarchive/libarchive/test/test_open_file.c6
-rw-r--r--contrib/libarchive/libarchive/test/test_open_filename.c103
-rw-r--r--contrib/libarchive/libarchive/test/test_pax_filename_encoding.c296
-rw-r--r--contrib/libarchive/libarchive/test/test_read_compress_program.c12
-rw-r--r--contrib/libarchive/libarchive/test/test_read_data_large.c32
-rw-r--r--contrib/libarchive/libarchive/test/test_read_disk.c6
-rw-r--r--contrib/libarchive/libarchive/test/test_read_disk_directory_traversals.c1060
-rw-r--r--contrib/libarchive/libarchive/test/test_read_disk_entry_from_file.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_extract.c10
-rw-r--r--contrib/libarchive/libarchive/test/test_read_file_nonexistent.c2
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip.c703
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_bcj2_bzip2.7z.uu319
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_bcj2_copy_1.7z.uu614
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_bcj2_copy_2.7z.uu615
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_bcj2_copy_lzma.7z.uu568
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_bcj2_deflate.7z.uu313
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_bcj2_lzma1_1.7z.uu287
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_bcj2_lzma1_2.7z.uu240
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_bcj2_lzma2_1.7z.uu287
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_bcj2_lzma2_2.7z.uu240
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_bcj_bzip2.7z.uu281
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_bcj_copy.7z.uu613
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_bcj_deflate.7z.uu275
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_bcj_lzma1.7z.uu245
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_bcj_lzma2.7z.uu245
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_bzip2.7z.uu37
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_copy.7z.uu7
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_copy_2.7z.uu11
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_deflate.7z.uu36
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_delta_lzma1.7z.uu280
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_delta_lzma2.7z.uu280
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_empty_archive.7z.uu4
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_empty_file.7z.uu5
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_lzma1.7z.uu37
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_lzma1_2.7z.uu8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_lzma1_lzma2.7z.uu10
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_lzma2.7z.uu37
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_ppmd.7z.uu235
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_symbolic_name.7z.uu8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_ar.c13
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cab.c281
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cab_1.cab.uu9
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cab_2.cab.uu9
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cab_3.cab.uu10
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cab_filename.c164
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cab_filename_cp932.cab.uu7
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_afio.c115
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_bin.c21
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_bin_Z.c9
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_bin_be.c4
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_bin_bz2.c6
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_bin_gz.c10
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_bin_lzip.c61
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_bin_lzma.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_bin_xz.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_filename.c874
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_filename_cp866.cpio.uu15
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_filename_eucjp.cpio.uu15
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_filename_koi8r.cpio.uu15
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_filename_utf8_jp.cpio.uu15
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_filename_utf8_ru.cpio.uu15
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_odc.c10
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_svr4_gzip.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_cpio_svr4c_Z.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_empty.c10
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_gtar_filename.c512
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_gtar_filename_cp866.tar.Z.uu10
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_gtar_filename_eucjp.tar.Z.uu10
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_gtar_filename_koi8r.tar.Z.uu10
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_gtar_gz.c9
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_gtar_lzma.c12
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_gtar_sparse.c26
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_iso_Z.c16
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_iso_joliet_by_nero.iso.Z.uu64
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_iso_multi_extent.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_iso_xorriso.c213
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_iso_xorriso.iso.Z.uu61
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_isojoliet_bz2.c12
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_isojoliet_long.c10
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_isojoliet_rr.c10
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_isojoliet_versioned.c83
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_isorr_bz2.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_isorr_ce.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_isorr_new_bz2.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_isorr_rr_moved.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_isozisofs_bz2.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_lha.c278
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_lha_filename.c218
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_lha_filename_cp932.lzh.uu7
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_lha_header0.lzh.uu11
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_lha_header1.lzh.uu13
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_lha_header2.lzh.uu13
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_lha_header3.lzh.uu16
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_lha_lh0.lzh.uu13
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_lha_lh6.lzh.uu13
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_lha_lh7.lzh.uu13
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_lha_withjunk.lzh.uu13
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_mtree.c175
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_mtree.mtree.uu10
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_mtree_nomagic.mtree.uu11
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_pax_bz2.c5
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_rar.c867
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_rar.rar.uu11
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_rar_binary_data.rar.uu24041
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_rar_compress_best.rar.uu274
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_rar_compress_normal.rar.uu328
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_rar_multi_lzss_blocks.rar.uu444
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_rar_noeof.rar.uu5
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_rar_ppmd_lzss_conversion.rar.uu3930
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_rar_sfx.exe.uu2215
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_rar_subblock.rar.uu7
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_rar_unicode.rar.uu17
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_rar_windows.rar.uu22
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_raw.c12
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_tar.c20
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_tar_empty_filename.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_tar_filename.c363
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_tar_filename_koi8r.tar.Z.uu14
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_tbz.c7
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_tgz.c9
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_tlz.c9
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_txz.c9
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_tz.c9
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_ustar_filename.c512
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_ustar_filename_cp866.tar.Z.uu8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_ustar_filename_eucjp.tar.Z.uu9
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_ustar_filename_koi8r.tar.Z.uu8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_xar.c19
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_zip.c283
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_zip.zip.uu2
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_zip_filename.c1162
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_zip_filename_cp866.zip.uu10
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_zip_filename_cp932.zip.uu9
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_zip_filename_koi8r.zip.uu10
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_zip_filename_utf8_jp.zip.uu15
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_zip_filename_utf8_ru.zip.uu11
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_zip_filename_utf8_ru2.zip.uu11
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_zip_length_at_end.zip.uu8
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_zip_symlink.zip.uu10
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_zip_ux.zip.uu7
-rw-r--r--contrib/libarchive/libarchive/test/test_read_large.c17
-rw-r--r--contrib/libarchive/libarchive/test/test_read_pax_truncated.c166
-rw-r--r--contrib/libarchive/libarchive/test/test_read_position.c84
-rw-r--r--contrib/libarchive/libarchive/test/test_read_truncated.c72
-rw-r--r--contrib/libarchive/libarchive/test/test_read_truncated_filter.c132
-rw-r--r--contrib/libarchive/libarchive/test/test_read_uu.c71
-rw-r--r--contrib/libarchive/libarchive/test/test_sparse_basic.c464
-rw-r--r--contrib/libarchive/libarchive/test/test_tar_filenames.c30
-rw-r--r--contrib/libarchive/libarchive/test/test_tar_large.c37
-rw-r--r--contrib/libarchive/libarchive/test/test_ustar_filename_encoding.c414
-rw-r--r--contrib/libarchive/libarchive/test/test_ustar_filenames.c18
-rw-r--r--contrib/libarchive/libarchive/test/test_write_compress.c37
-rw-r--r--contrib/libarchive/libarchive/test/test_write_compress_bzip2.c92
-rw-r--r--contrib/libarchive/libarchive/test/test_write_compress_gzip.c90
-rw-r--r--contrib/libarchive/libarchive/test/test_write_compress_lzip.c247
-rw-r--r--contrib/libarchive/libarchive/test/test_write_compress_lzma.c85
-rw-r--r--contrib/libarchive/libarchive/test/test_write_compress_program.c29
-rw-r--r--contrib/libarchive/libarchive/test/test_write_compress_xz.c84
-rw-r--r--contrib/libarchive/libarchive/test/test_write_disk.c107
-rw-r--r--contrib/libarchive/libarchive/test/test_write_disk_failures.c13
-rw-r--r--contrib/libarchive/libarchive/test/test_write_disk_hardlink.c12
-rw-r--r--contrib/libarchive/libarchive/test/test_write_disk_lookup.c156
-rw-r--r--contrib/libarchive/libarchive/test/test_write_disk_perms.c10
-rw-r--r--contrib/libarchive/libarchive/test/test_write_disk_secure.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_write_disk_sparse.c4
-rw-r--r--contrib/libarchive/libarchive/test/test_write_disk_symlink.c2
-rw-r--r--contrib/libarchive/libarchive/test/test_write_disk_times.c2
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_7zip.c816
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_ar.c51
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_cpio.c122
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_cpio_empty.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_cpio_newc.c7
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_cpio_odc.c6
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_gnutar.c236
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_iso9660.c937
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_iso9660_boot.c276
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_iso9660_empty.c202
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_iso9660_filename.c468
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_iso9660_zisofs.c819
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_mtree.c32
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_mtree_fflags.c134
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_pax.c59
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_shar_empty.c8
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_tar.c87
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_tar_empty.c26
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_tar_sparse.c305
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_tar_ustar.c37
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_xar.c312
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_xar_empty.c120
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_zip.c189
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_zip_empty.c36
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_zip_no_compression.c48
-rw-r--r--contrib/libarchive/libarchive/test/test_write_open_memory.c42
-rw-r--r--contrib/libarchive/libarchive/test/test_zip_filename_encoding.c543
-rw-r--r--contrib/libarchive/libarchive_fe/line_reader.c60
-rw-r--r--contrib/libarchive/libarchive_fe/matching.c57
-rw-r--r--contrib/libarchive/libarchive_fe/pathmatch.c2
-rw-r--r--contrib/libarchive/tar/bsdtar.151
-rw-r--r--contrib/libarchive/tar/bsdtar.c134
-rw-r--r--contrib/libarchive/tar/bsdtar.h17
-rw-r--r--contrib/libarchive/tar/bsdtar_platform.h4
-rw-r--r--contrib/libarchive/tar/cmdline.c98
-rw-r--r--contrib/libarchive/tar/getdate.c2
-rw-r--r--contrib/libarchive/tar/read.c79
-rw-r--r--contrib/libarchive/tar/subst.c53
-rw-r--r--contrib/libarchive/tar/test/main.c679
-rw-r--r--contrib/libarchive/tar/test/test.h99
-rw-r--r--contrib/libarchive/tar/test/test_0.c14
-rw-r--r--contrib/libarchive/tar/test/test_basic.c112
-rw-r--r--contrib/libarchive/tar/test/test_option_C_upper.c149
-rw-r--r--contrib/libarchive/tar/test/test_option_H_upper.c92
-rw-r--r--contrib/libarchive/tar/test/test_option_L_upper.c92
-rw-r--r--contrib/libarchive/tar/test/test_option_O_upper.c87
-rw-r--r--contrib/libarchive/tar/test/test_option_T_upper.c62
-rw-r--r--contrib/libarchive/tar/test/test_option_U_upper.c159
-rw-r--r--contrib/libarchive/tar/test/test_option_X_upper.c145
-rw-r--r--contrib/libarchive/tar/test/test_option_b.c74
-rw-r--r--contrib/libarchive/tar/test/test_option_exclude.c142
-rw-r--r--contrib/libarchive/tar/test/test_option_gid_gname.c88
-rw-r--r--contrib/libarchive/tar/test/test_option_k.c107
-rw-r--r--contrib/libarchive/tar/test/test_option_keep_newer_files.c56
-rw-r--r--contrib/libarchive/tar/test/test_option_keep_newer_files.tar.Z.uu7
-rw-r--r--contrib/libarchive/tar/test/test_option_n.c61
-rw-r--r--contrib/libarchive/tar/test/test_option_newer_than.c75
-rw-r--r--contrib/libarchive/tar/test/test_option_q.c26
-rw-r--r--contrib/libarchive/tar/test/test_option_r.c95
-rw-r--r--contrib/libarchive/tar/test/test_option_s.c212
-rw-r--r--contrib/libarchive/tar/test/test_option_s.tar.Z.uu16
-rw-r--r--contrib/libarchive/tar/test/test_option_uid_uname.c80
-rw-r--r--contrib/libarchive/tar/test/test_patterns.c10
-rw-r--r--contrib/libarchive/tar/test/test_print_longpath.c54
-rw-r--r--contrib/libarchive/tar/test/test_print_longpath.tar.Z.uu24
-rw-r--r--contrib/libarchive/tar/test/test_strip_components.c80
-rw-r--r--contrib/libarchive/tar/test/test_symlink_dir.c34
-rw-r--r--contrib/libarchive/tar/tree.c71
-rw-r--r--contrib/libarchive/tar/util.c46
-rw-r--r--contrib/libarchive/tar/write.c207
-rw-r--r--lib/libarchive/Makefile413
-rw-r--r--lib/libarchive/config_freebsd.h332
-rw-r--r--lib/libarchive/test/Makefile67
-rw-r--r--usr.bin/ar/ar.c4
-rw-r--r--usr.bin/cpio/Makefile9
-rw-r--r--usr.bin/cpio/test/Makefile1
-rw-r--r--usr.bin/tar/Makefile8
-rw-r--r--usr.bin/tar/config_freebsd.h82
-rw-r--r--usr.bin/tar/test/Makefile19
470 files changed, 125568 insertions, 13523 deletions
diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
index 26e2130652c8..57db01238aec 100644
--- a/ObsoleteFiles.inc
+++ b/ObsoleteFiles.inc
@@ -38,6 +38,24 @@
# xargs -n1 | sort | uniq -d;
# done
+# 20120225: libarchive 3.0.3
+OLD_FILES+=man/man3/archive_read_data_into_buffer.3.gz \
+ man/man3/archive_read_support_compression_all.3.gz \
+ man/man3/archive_read_support_compression_bzip2.3.gz \
+ man/man3/archive_read_support_compression_compress.3.gz \
+ man/man3/archive_read_support_compression_gzip.3.gz \
+ man/man3/archive_read_support_compression_lzma.3.gz \
+ man/man3/archive_read_support_compression_none.3.gz \
+ man/man3/archive_read_support_compression_program.3.gz \
+ man/man3/archive_read_support_compression_program_signature.3.gz \
+ man/man3/archive_read_support_compression_xz.3.gz \
+ man/man3/archive_write_set_callbacks.3.gz \
+ man/man3/archive_write_set_compression_bzip2.3.gz \
+ man/man3/archive_write_set_compression_compress.3.gz \
+ man/man3/archive_write_set_compression_gzip.3.gz \
+ man/man3/archive_write_set_compression_none.3.gz \
+ man/man3/archive_write_set_compression_program.3.gz
+OLD_LIBS+=usr/lib/libarchive.so.5
# 20120113: removal of wtmpcvt(1)
OLD_FILES+=usr/bin/wtmpcvt
OLD_FILES+=usr/share/man/man1/wtmpcvt.1.gz
diff --git a/contrib/libarchive/COPYING b/contrib/libarchive/COPYING
index 9dbf49dbf21c..b25880600230 100644
--- a/contrib/libarchive/COPYING
+++ b/contrib/libarchive/COPYING
@@ -16,8 +16,8 @@ the actual statements in the files are controlling.
a 3-clause UC Regents copyright; please read the individual source
files for details:
libarchive/archive_entry.c
- libarchive/archive_read_support_compression_compress.c
- libarchive/archive_write_set_compression_compress.c
+ libarchive/archive_read_support_filter_compress.c
+ libarchive/archive_write_set_filter_compress.c
libarchive/mtree.5
tar/matching.c
diff --git a/contrib/libarchive/FREEBSD-Xlist b/contrib/libarchive/FREEBSD-Xlist
index b87a53b0c5e1..c1ccceeada8c 100644
--- a/contrib/libarchive/FREEBSD-Xlist
+++ b/contrib/libarchive/FREEBSD-Xlist
@@ -15,8 +15,10 @@ doc
examples
libarchive/CMakeLists.txt
libarchive/archive_entry_copy_bhfi.c
+libarchive/archive_read_disk_windows.c
libarchive/archive_windows.c
libarchive/archive_windows.h
+libarchive/archive_write_disk_windows.c
libarchive/config_freebsd.h
libarchive/filter_fork_windows.c
libarchive/mtree.5
diff --git a/contrib/libarchive/NEWS b/contrib/libarchive/NEWS
index 4a25fe37d99b..e9811b5b4bce 100644
--- a/contrib/libarchive/NEWS
+++ b/contrib/libarchive/NEWS
@@ -1,27 +1,80 @@
-Feb 05, 2011: Fix issue 134: Improve handling of open failures
-Dec 06, 2010: Fix issue 119: Relax ISO verification
-Dec 06, 2010: Fix issue 121: mtree parsing
-Dec 05, 2010: Fix extraction of GNU tar 'D' directory entries
-Dec 05, 2010: Be less demanding in LZMA/XZ compression tests
-Jun 30, 2010: libarchive 2.8.4 released
-Jun 30, 2010: Improved reliability of hash function detection
-Jun 30, 2010: Fix issues on ancient FreeBSD, QNX, ancient NetBSD and Minix
-
-Mar 14, 2010: libarchive 2.8.3 released
-Mar 14, 2010: Symlink dereference fix for Linux broke the build there; corrected.
-
-Mar 14, 2010: libarchive 2.8.2 released
-Mar 12, 2010: Fix NULL deference for short self-extracting zip archives.
+Jan 10, 2012: Issue 223: Skip atime tests if atime not supported
+Jan 09, 2012: Issue 222: Errors saving sparse files to pax archives
+Jan 09, 2012: Issue 221: allow archive_*_free(NULL)
+Dec 31, 2011: Issue 212: configure script on Solaris
+Dec 30, 2011: Issue 218: empty contents extracting Zip files with bsdcpio
+Dec 30, 2011: Issue 217: fix compile warning
+Dec 30, 2011: Issue 216: truncated filenames in listings
+Dec 28, 2011: Issue 210: memory leak on Windows
+Dec 28, 2011: Issue 206: fix hardlink tests on Windows 2000
+Dec 27, 2011: Issue 208: Don't hang when using external compression
+ program on Windows
+
+Dec 24, 2011: libarchive 3.0.2 released
+Dec 23, 2011: Various fixes merged from FreeBSD
+Dec 23, 2011: Symlink support in Zip reader and writer
+Dec 23, 2011: Robustness fixes to 7Zip reader
+
+Nov 27, 2011: libarchive 3.0.1b released
+
+Nov 26, 2011: 7Zip reader
+Nov 26, 2011: Small fixes to ISO and Zip to improve robustness with corrupted input
+Nov 24, 2011: Improve streaming Zip reader's support for uncompressed entries
+Nov 20, 2011: New seeking Zip reader supports SFX Zip archives
+Nov 20, 2011: Build fixes on Windows
+
+Nov 13, 2011: libarchive 3.0.0a released
+
+Nov 06, 2011: Update shared-library version calculations for libarchive 3.x
+Sep 04, 2011: Fix tar -s; follow GNU tar for controlling hardlink/symlink substitutions
+Aug 18, 2011: Fix reading ISO images built by NetBSD's mkisofs
+Aug 15, 2011: Old archive_read_support_compression_XXX functions are deprecated and
+ will disappear in libarchive 4.0.
+Jun 26, 2011: RAR reader
+Jun 16, 2011: Add tar:compat-2x option to emulate broken libarchive 2.x
+ handling of pax UTF-8 headers
+Apr 25, 2011: Refactor read_open() into a collection of single-item setters;
+ support the old interfaces as wrappers
+Apr 12, 2011: Split disk writer into separate POSIX and Windows implementations
+Apr 10, 2011: Improvements to character translations on Windows.
+Mar 30, 2011: More work to return errors instead of calling abort()
+Mar 23, 2011: Add charset option to many writers to control MBCS filenames
+Mar 17, 2011: Overhauled support for per-format extension options
+Mar 17, 2011: Track character set used for mbcs strings, support
+ translating to/from user-specified locale
+Mar 09, 2011: Recognize mtree files without requiring a signature
+Mar 06, 2011: Use iconv to convert to/from Unicode instead of making bad
+ assumptions about the C90 character set translation functions
+Feb 17, 2011: Fixes for AIX, TRU64, and other platforms
+Dec 22, 2010: CAB reader
+Dec 20, 2010: LHA/LZH reader
+Jul 03, 2010: minitar example demonstrates archive_read_disk directory traversal
+Jun 29, 2010: Many improvements to ISO reader compatibility
+Jun 26, 2010: Use larger buffers when copy files into an archive
+Jun 18, 2010: Reimplement Mac OS extensions in libarchive
+Jun 09, 2010: archive_read_disk now supports traversals
+May 28, 2010: XAR writer
+May 16, 2010: Fix ^T handling; don't exit on interrupted reads and writes
+May 09, 2010: Improved detection of platform-specific crypto support
+May 04, 2010: lzip read and write filters
+May 01, 2010: New options: tar --gid --gname --uid --uname
+Apr 28, 2010: Use Red-black tree for ISO reader/writer to improve performance
+Apr 17, 2010: Minimal writer for legacy GNU tar format
Mar 12, 2010: Don't dereference symlinks on Linux when reading ACLs.
-Mar 07, 2010: Better detection of SHA2 support for old OpenSSL versions.
-Mar 07, 2010: Fix parsing of input files for bsdtar -T.
-Mar 07, 2010: Do not leak setup_xattr into the global namespace.
-
-Mar 06, 2010: libarchive 2.8.1 released
Mar 06, 2010: Fix build when an older libarchive is already installed
-Mar 03, 2010: Use O_BINARY opening files in bsdtar
-Mar 02, 2010: Include missing archive_crc32.h
-Mar 01, 2010: Correctly include iconv.h required by libxml2.
+Feb 28, 2010: Relax handling of state failures; misuse by clients now generally
+ results in a sticky ARCHIVE_FATAL rather than a visit to abort()
+Feb 25, 2010: ISO writer
+Feb 21, 2010: Split many man pages into smaller chunks.
+Feb 21, 2010: Performance: Cheat on block sizes when reading archives from disk.
+Feb 21, 2010: Use int64_t instead of off_t, dev_t, ino_t, uid_t, and gid_t
+Feb 20, 2010: Document new ACL functions.
+Feb 19, 2010: Support multiple write filters
+Feb 07, 2010: Remove some legacy libarchive 1.x APIs
+Feb 04, 2010: Read afio headers
+Feb 02, 2010: Archive sparse files compatibly with GNU tar
+Feb 01, 2010: Integrate Apple extensions for Mac OS extended attributes into bsdtar
+Jan 31, 2010: Support cpio -V
Feb 04, 2010: libarchive 2.8.0 released
Jan 17, 2010: Fix error handling for 'echo nonexistent | cpio -o'
diff --git a/contrib/libarchive/README b/contrib/libarchive/README
index 03e47e85497e..69238386f6e1 100644
--- a/contrib/libarchive/README
+++ b/contrib/libarchive/README
@@ -13,8 +13,6 @@ This distribution bundle includes the following components:
essentially the same functionality
* examples: Some small example programs that you may find useful.
* examples/minitar: a compact sample demonstrating use of libarchive.
- I use this for testing link pollution; it should produce a very
- small executable file on most systems.
* contrib: Various items sent to me by third parties;
please contact the authors with any questions.
@@ -51,16 +49,11 @@ The manual pages above are provided in the 'doc' directory in
a number of different formats.
You should also read the copious comments in "archive.h" and the
-source code for the sample programs for more details. Please let me
+source code for the sample programs for more details. Please let us
know about any errors or omissions you find.
-Currently, the library automatically detects and reads the following:
- * gzip compression
- * bzip2 compression
- * compress/LZW compression
- * lzma and xz compression
- * GNU tar format (including GNU long filenames, long link names, and
- sparse files)
+Currently, the library automatically detects and reads the following fomats:
+ * GNU tar format (including GNU long filenames, long link names, and sparse files)
* Solaris 9 extended tar format (including ACLs)
* Old V7 tar archives
* POSIX ustar
@@ -73,22 +66,40 @@ Currently, the library automatically detects and reads the following:
* ZIP archives (with uncompressed or "deflate" compressed entries)
* GNU and BSD 'ar' archives
* 'mtree' format
-
-The library can write:
+ * Microsoft CAB format
+ * LHA and LZH archives
+ * RAR archives
+ * XAR archives
+
+The library also detects and handles any of the following before evaluating the archive:
+ * uuencoded files
+ * files with RPM wrapper
* gzip compression
* bzip2 compression
* compress/LZW compression
- * lzma and xz compression
+ * lzma, lzip, and xz compression
+
+The library can create archives in any of the following formats:
* POSIX ustar
* POSIX pax interchange format
* "restricted" pax format, which will create ustar archives except for
entries that require pax extensions (for long filenames, ACLs, etc).
+ * Old GNU tar format
* POSIX octet-oriented cpio
* SVR4 "newc" cpio
* shar archives
* ZIP archives (with uncompressed or "deflate" compressed entries)
* GNU and BSD 'ar' archives
* 'mtree' format
+ * ISO9660 format
+ * XAR archives
+
+When creating archives, the result can be filtered with any of the following:
+ * uuencode
+ * gzip compression
+ * bzip2 compression
+ * compress/LZW compression
+ * lzma, lzip, and xz compression
Notes about the library architecture:
diff --git a/contrib/libarchive/cpio/bsdcpio.1 b/contrib/libarchive/cpio/bsdcpio.1
index 789ce74e1c48..1355130c5911 100644
--- a/contrib/libarchive/cpio/bsdcpio.1
+++ b/contrib/libarchive/cpio/bsdcpio.1
@@ -24,8 +24,8 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 5, 2010
-.Dt BSDCPIO 1
+.Dd December 21, 2007
+.Dt CPIO 1
.Os
.Sh NAME
.Nm cpio
@@ -59,7 +59,7 @@ is a mode indicator from the following list:
.Bl -tag -compact -width indent
.It Fl i
Input.
-Read an archive from standard input (unless overriden) and extract the
+Read an archive from standard input (unless overridden) and extract the
contents to disk or (if the
.Fl t
option is specified)
@@ -69,7 +69,7 @@ one of the patterns will be extracted.
.It Fl o
Output.
Read a list of filenames from standard input and produce a new archive
-on standard output (unless overriden) containing the specified items.
+on standard output (unless overridden) containing the specified items.
.It Fl p
Pass-through.
Read a list of filenames from standard input and copy the files to the
@@ -80,7 +80,7 @@ specified directory.
Unless specifically stated otherwise, options are applicable in
all operating modes.
.Bl -tag -width indent
-.It Fl 0
+.It Fl 0 , Fl Fl null
Read filenames separated by NUL characters instead of newlines.
This is necessary if any of the filenames being read might contain newlines.
.It Fl A
@@ -102,8 +102,8 @@ bytes.
(o mode only)
Use the old POSIX portable character format.
Equivalent to
-.Fl -format Ar odc .
-.It Fl d
+.Fl Fl format Ar odc .
+.It Fl d , Fl Fl make-directories
(i and p modes)
Create directories as necessary.
.It Fl E Ar file
@@ -111,14 +111,14 @@ Create directories as necessary.
Read list of file name patterns from
.Ar file
to list and extract.
-.It Fl F Ar file
+.It Fl F Ar file , Fl Fl file Ar file
Read archive from or write archive to
.Ar file .
.It Fl f Ar pattern
(i mode only)
Ignore files that match
.Ar pattern .
-.It Fl -format Ar format
+.It Fl H Ar format , Fl Fl format Ar format
(o mode only)
Produce the output archive in the specified format.
Supported formats include:
@@ -145,24 +145,21 @@ for more complete information about the
formats currently supported by the underlying
.Xr libarchive 3
library.
-.It Fl H Ar format
-Synonym for
-.Fl -format .
-.It Fl h , Fl -help
+.It Fl h , Fl Fl help
Print usage information.
.It Fl I Ar file
Read archive from
.Ar file .
-.It Fl i
+.It Fl i , Fl Fl extract
Input mode.
See above for description.
-.It Fl -insecure
+.It Fl Fl insecure
(i and p mode only)
Disable security checks during extraction or copying.
This allows extraction via symbolic links and path names containing
.Sq ..
in the name.
-.It Fl J
+.It Fl J , Fl Fl xz
(o mode only)
Compress the file with xz-compatible compression before writing it.
In input mode, this option is ignored; xz compression is recognized
@@ -175,20 +172,20 @@ Synonym for
All symbolic links will be followed.
Normally, symbolic links are archived and copied as symbolic links.
With this option, the target of the link will be archived or copied instead.
-.It Fl l
+.It Fl l , Fl Fl link
(p mode only)
Create links from the target directory to the original files,
instead of copying.
-.It Fl lzma
+.It Fl Fl lzma
(o mode only)
Compress the file with lzma-compatible compression before writing it.
In input mode, this option is ignored; lzma compression is recognized
automatically on input.
-.It Fl m
+.It Fl m , Fl Fl preserve-modification-time
(i and p modes)
Set file modification time on created files to match
those in the source.
-.It Fl n
+.It Fl n , Fl Fl numeric-uid-gid
(i mode, only with
.Fl t )
Display numeric uid and gid.
@@ -197,26 +194,26 @@ By default,
displays the user and group names when they are provided in the
archive, or looks up the user and group names in the system
password database.
-.It Fl no-preserve-owner
+.It Fl Fl no-preserve-owner
(i mode only)
Do not attempt to restore file ownership.
This is the default when run by non-root users.
.It Fl O Ar file
Write archive to
.Ar file .
-.It Fl o
+.It Fl o , Fl Fl create
Output mode.
See above for description.
-.It Fl p
+.It Fl p , Fl Fl pass-through
Pass-through mode.
See above for description.
-.It Fl preserve-owner
+.It Fl Fl preserve-owner
(i mode only)
Restore file ownership.
This is the default when run by the root user.
-.It Fl -quiet
+.It Fl Fl quiet
Suppress unnecessary messages.
-.It Fl R Oo user Oc Ns Oo : Oc Ns Oo group Oc
+.It Fl R Oo user Oc Ns Oo : Oc Ns Oo group Oc , Fl Fl owner Oo user Oc Ns Oo : Oc Ns Oo group Oc
Set the owner and/or group on files in the output.
If group is specified with no user
(for example,
@@ -244,20 +241,24 @@ containing the name of the file and a line is read from
If the line read is blank, the file is skipped.
If the line contains a single period, the file is processed normally.
Otherwise, the line is taken to be the new name of the file.
-.It Fl t
+.It Fl t , Fl Fl list
(i mode only)
List the contents of the archive to stdout;
do not restore the contents to disk.
-.It Fl u
+.It Fl u , Fl Fl unconditional
(i and p modes)
Unconditionally overwrite existing files.
Ordinarily, an older file will not overwrite a newer file on disk.
-.It Fl v
+.It Fl V , Fl Fl dot
+Print a dot to stderr for each file as it is processed.
+Superseded by
+.Fl v .
+.It Fl v , Fl Fl verbose
Print the name of each file to stderr as it is processed.
With
.Fl t ,
provide a detailed listing of each file.
-.It Fl -version
+.It Fl Fl version
Print the program version information and exit.
.It Fl y
(o mode only)
@@ -275,6 +276,8 @@ Compress the archive with gzip-compatible compression before writing it.
In input mode, this option is ignored;
gzip compression is recognized automatically on input.
.El
+.Sh EXIT STATUS
+.Ex -std
.Sh ENVIRONMENT
The following environment variables affect the execution of
.Nm :
@@ -290,8 +293,6 @@ See
.Xr environ 7
for more information.
.El
-.Sh EXIT STATUS
-.Ex -std
.Sh EXAMPLES
The
.Nm
diff --git a/contrib/libarchive/cpio/cmdline.c b/contrib/libarchive/cpio/cmdline.c
index 687fa62cb6d7..a9cb33ce9192 100644
--- a/contrib/libarchive/cpio/cmdline.c
+++ b/contrib/libarchive/cpio/cmdline.c
@@ -51,7 +51,7 @@ __FBSDID("$FreeBSD$");
/*
* Short options for cpio. Please keep this sorted.
*/
-static const char *short_options = "0AaBC:cdE:F:f:H:hI:iJjLlmnO:opR:rtuvW:yZz";
+static const char *short_options = "0AaBC:cdE:F:f:H:hI:iJjLlmnO:opR:rtuVvW:yZz";
/*
* Long options for cpio. Please keep this sorted.
@@ -62,6 +62,7 @@ static const struct option {
int equivalent; /* Equivalent short option. */
} cpio_longopts[] = {
{ "create", 0, 'o' },
+ { "dot", 0, 'V' },
{ "extract", 0, 'i' },
{ "file", 1, 'F' },
{ "format", 1, 'H' },
@@ -109,7 +110,7 @@ cpio_getopt(struct cpio *cpio)
int opt = '?';
int required = 0;
- cpio->optarg = NULL;
+ cpio->argument = NULL;
/* First time through, initialize everything. */
if (state == state_start) {
@@ -188,7 +189,7 @@ cpio_getopt(struct cpio *cpio)
long_prefix = "-W "; /* For clearer errors. */
} else {
state = state_next_word;
- cpio->optarg = opt_word;
+ cpio->argument = opt_word;
}
}
}
@@ -202,7 +203,7 @@ cpio_getopt(struct cpio *cpio)
p = strchr(opt_word, '=');
if (p != NULL) {
optlength = (size_t)(p - opt_word);
- cpio->optarg = (char *)(uintptr_t)(p + 1);
+ cpio->argument = (char *)(uintptr_t)(p + 1);
} else {
optlength = strlen(opt_word);
}
@@ -241,9 +242,9 @@ cpio_getopt(struct cpio *cpio)
/* We've found a unique match; does it need an argument? */
if (match->required) {
/* Argument required: get next word if necessary. */
- if (cpio->optarg == NULL) {
- cpio->optarg = *cpio->argv;
- if (cpio->optarg == NULL) {
+ if (cpio->argument == NULL) {
+ cpio->argument = *cpio->argv;
+ if (cpio->argument == NULL) {
lafe_warnc(0,
"Option %s%s requires an argument",
long_prefix, match->name);
@@ -254,7 +255,7 @@ cpio_getopt(struct cpio *cpio)
}
} else {
/* Argument forbidden: fail if there is one. */
- if (cpio->optarg != NULL) {
+ if (cpio->argument != NULL) {
lafe_warnc(0,
"Option %s%s does not allow an argument",
long_prefix, match->name);
@@ -340,7 +341,7 @@ owner_parse(const char *spec, int *uid, int *gid)
} else {
char *end;
errno = 0;
- *uid = strtoul(user, &end, 10);
+ *uid = (int)strtoul(user, &end, 10);
if (errno || *end != '\0') {
snprintf(errbuff, sizeof(errbuff),
"Couldn't lookup user ``%s''", user);
@@ -358,7 +359,7 @@ owner_parse(const char *spec, int *uid, int *gid)
} else {
char *end;
errno = 0;
- *gid = strtoul(g, &end, 10);
+ *gid = (int)strtoul(g, &end, 10);
if (errno || *end != '\0') {
snprintf(errbuff, sizeof(errbuff),
"Couldn't lookup group ``%s''", g);
diff --git a/contrib/libarchive/cpio/cpio.c b/contrib/libarchive/cpio/cpio.c
index cd81050e1531..3e7446108441 100644
--- a/contrib/libarchive/cpio/cpio.c
+++ b/contrib/libarchive/cpio/cpio.c
@@ -50,9 +50,15 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_GRP_H
#include <grp.h>
#endif
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
@@ -69,9 +75,6 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
#ifdef HAVE_TIME_H
#include <time.h>
#endif
@@ -116,6 +119,7 @@ static void mode_in(struct cpio *);
static void mode_list(struct cpio *);
static void mode_out(struct cpio *);
static void mode_pass(struct cpio *, const char *);
+static const char *remove_leading_slash(const char *);
static int restore_time(struct cpio *, struct archive_entry *,
const char *, int fd);
static void usage(void);
@@ -136,20 +140,34 @@ main(int argc, char *argv[])
cpio->buff = buff;
cpio->buff_size = sizeof(buff);
+#if defined(HAVE_SIGACTION) && defined(SIGPIPE)
+ { /* Ignore SIGPIPE signals. */
+ struct sigaction sa;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &sa, NULL);
+ }
+#endif
+
/* Need lafe_progname before calling lafe_warnc. */
if (*argv == NULL)
lafe_progname = "bsdcpio";
else {
#if defined(_WIN32) && !defined(__CYGWIN__)
lafe_progname = strrchr(*argv, '\\');
-#else
- lafe_progname = strrchr(*argv, '/');
+ if (strrchr(*argv, '/') > lafe_progname)
#endif
+ lafe_progname = strrchr(*argv, '/');
if (lafe_progname != NULL)
lafe_progname++;
else
lafe_progname = *argv;
}
+#if HAVE_SETLOCALE
+ if (setlocale(LC_ALL, "") == NULL)
+ lafe_warnc(0, "Failed to set default locale");
+#endif
cpio->uid_override = -1;
cpio->gid_override = -1;
@@ -187,9 +205,9 @@ main(int argc, char *argv[])
cpio->bytes_per_block = 5120;
break;
case 'C': /* NetBSD/OpenBSD */
- cpio->bytes_per_block = atoi(cpio->optarg);
+ cpio->bytes_per_block = atoi(cpio->argument);
if (cpio->bytes_per_block <= 0)
- lafe_errc(1, 0, "Invalid blocksize %s", cpio->optarg);
+ lafe_errc(1, 0, "Invalid blocksize %s", cpio->argument);
break;
case 'c': /* POSIX 1997 */
cpio->format = "odc";
@@ -199,22 +217,22 @@ main(int argc, char *argv[])
break;
case 'E': /* NetBSD/OpenBSD */
lafe_include_from_file(&cpio->matching,
- cpio->optarg, cpio->option_null);
+ cpio->argument, cpio->option_null);
break;
case 'F': /* NetBSD/OpenBSD/GNU cpio */
- cpio->filename = cpio->optarg;
+ cpio->filename = cpio->argument;
break;
case 'f': /* POSIX 1997 */
- lafe_exclude(&cpio->matching, cpio->optarg);
+ lafe_exclude(&cpio->matching, cpio->argument);
break;
case 'H': /* GNU cpio (also --format) */
- cpio->format = cpio->optarg;
+ cpio->format = cpio->argument;
break;
case 'h':
long_help();
break;
case 'I': /* NetBSD/OpenBSD */
- cpio->filename = cpio->optarg;
+ cpio->filename = cpio->argument;
break;
case 'i': /* POSIX 1997 */
if (cpio->mode != '\0')
@@ -251,7 +269,7 @@ main(int argc, char *argv[])
cpio->extract_flags &= ~ARCHIVE_EXTRACT_OWNER;
break;
case 'O': /* GNU cpio */
- cpio->filename = cpio->optarg;
+ cpio->filename = cpio->argument;
break;
case 'o': /* POSIX 1997 */
if (cpio->mode != '\0')
@@ -275,7 +293,7 @@ main(int argc, char *argv[])
case 'R': /* GNU cpio, also --owner */
/* TODO: owner_parse should return uname/gname
* also; use that to set [ug]name_override. */
- errmsg = owner_parse(cpio->optarg, &uid, &gid);
+ errmsg = owner_parse(cpio->argument, &uid, &gid);
if (errmsg) {
lafe_warnc(-1, "%s", errmsg);
usage();
@@ -302,6 +320,9 @@ main(int argc, char *argv[])
case 'v': /* POSIX 1997 */
cpio->verbose++;
break;
+ case 'V': /* GNU cpio */
+ cpio->dot++;
+ break;
case OPTION_VERSION: /* GNU convention */
version();
break;
@@ -345,6 +366,12 @@ main(int argc, char *argv[])
/* -l requires -p */
if (cpio->option_link && cpio->mode != 'p')
lafe_errc(1, 0, "Option -l requires -p");
+ /* -v overrides -V */
+ if (cpio->dot && cpio->verbose)
+ cpio->dot = 0;
+ /* -v overrides -V */
+ if (cpio->dot && cpio->verbose)
+ cpio->dot = 0;
/* TODO: Flag other nonsensical combinations. */
switch (cpio->mode) {
@@ -402,7 +429,7 @@ static const char *long_help_msg =
"First option must be a mode specifier:\n"
" -i Input -o Output -p Pass\n"
"Common Options:\n"
- " -v Verbose\n"
+ " -v Verbose filenames -V one dot per file\n"
"Create: %p -o [options] < [list of files] > [archive]\n"
" -J,-y,-z,--lzma Compress archive with xz/bzip2/gzip/lzma\n"
" --format {odc|newc|ustar} Select archive format\n"
@@ -451,7 +478,7 @@ version(void)
{
fprintf(stdout,"bsdcpio %s -- %s\n",
BSDCPIO_VERSION_STRING,
- archive_version());
+ archive_version_string());
exit(0);
}
@@ -533,6 +560,8 @@ mode_out(struct cpio *cpio)
}
r = archive_write_close(cpio->archive);
+ if (cpio->dot)
+ fprintf(stderr, "\n");
if (r != ARCHIVE_OK)
lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
@@ -543,7 +572,50 @@ mode_out(struct cpio *cpio)
fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
blocks == 1 ? "block" : "blocks");
}
- archive_write_finish(cpio->archive);
+ archive_write_free(cpio->archive);
+}
+
+static const char *
+remove_leading_slash(const char *p)
+{
+ const char *rp;
+
+ /* Remove leading "//./" or "//?/" or "//?/UNC/"
+ * (absolute path prefixes used by Windows API) */
+ if ((p[0] == '/' || p[0] == '\\') &&
+ (p[1] == '/' || p[1] == '\\') &&
+ (p[2] == '.' || p[2] == '?') &&
+ (p[3] == '/' || p[3] == '\\'))
+ {
+ if (p[2] == '?' &&
+ (p[4] == 'U' || p[4] == 'u') &&
+ (p[5] == 'N' || p[5] == 'n') &&
+ (p[6] == 'C' || p[6] == 'c') &&
+ (p[7] == '/' || p[7] == '\\'))
+ p += 8;
+ else
+ p += 4;
+ }
+ do {
+ rp = p;
+ /* Remove leading drive letter from archives created
+ * on Windows. */
+ if (((p[0] >= 'a' && p[0] <= 'z') ||
+ (p[0] >= 'A' && p[0] <= 'Z')) &&
+ p[1] == ':') {
+ p += 2;
+ }
+ /* Remove leading "/../", "//", etc. */
+ while (p[0] == '/' || p[0] == '\\') {
+ if (p[1] == '.' && p[2] == '.' &&
+ (p[3] == '/' || p[3] == '\\')) {
+ p += 3; /* Remove "/..", leave "/"
+ * for next pass. */
+ } else
+ p += 1; /* Remove "/". */
+ }
+ } while (rp != p);
+ return (p);
}
/*
@@ -557,7 +629,6 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
const char *destpath;
struct archive_entry *entry, *spare;
size_t len;
- const char *p;
int r;
/*
@@ -611,10 +682,7 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
"Can't allocate path buffer");
}
strcpy(cpio->pass_destpath, cpio->destdir);
- p = srcpath;
- while (p[0] == '/')
- ++p;
- strcat(cpio->pass_destpath, p);
+ strcat(cpio->pass_destpath, remove_leading_slash(srcpath));
destpath = cpio->pass_destpath;
}
if (cpio->option_rename)
@@ -656,6 +724,8 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
/* Print out the destination name to the user. */
if (cpio->verbose)
fprintf(stderr,"%s", destpath);
+ if (cpio->dot)
+ fprintf(stderr, ".");
/*
* Option_link only makes sense in pass mode and for
@@ -725,7 +795,7 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
if (r == ARCHIVE_FATAL)
exit(1);
- if (r >= ARCHIVE_WARN && fd >= 0) {
+ if (r >= ARCHIVE_WARN && archive_entry_size(entry) > 0 && fd >= 0) {
bytes_read = read(fd, cpio->buff, cpio->buff_size);
while (bytes_read > 0) {
r = archive_write_data(cpio->archive,
@@ -825,7 +895,7 @@ mode_in(struct cpio *cpio)
a = archive_read_new();
if (a == NULL)
lafe_errc(1, 0, "Couldn't allocate archive object");
- archive_read_support_compression_all(a);
+ archive_read_support_filter_all(a);
archive_read_support_format_all(a);
if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block))
@@ -849,7 +919,9 @@ mode_in(struct cpio *cpio)
if (destpath == NULL)
continue;
if (cpio->verbose)
- fprintf(stdout, "%s\n", destpath);
+ fprintf(stderr, "%s\n", destpath);
+ if (cpio->dot)
+ fprintf(stderr, ".");
if (cpio->uid_override >= 0)
archive_entry_set_uid(entry, cpio->uid_override);
if (cpio->gid_override >= 0)
@@ -859,13 +931,16 @@ mode_in(struct cpio *cpio)
fprintf(stderr, "%s: %s\n",
archive_entry_pathname(entry),
archive_error_string(ext));
- } else if (archive_entry_size(entry) > 0) {
+ } else if (!archive_entry_size_is_set(entry)
+ || archive_entry_size(entry) > 0) {
r = extract_data(a, ext);
if (r != ARCHIVE_OK)
cpio->return_value = 1;
}
}
r = archive_read_close(a);
+ if (cpio->dot)
+ fprintf(stderr, "\n");
if (r != ARCHIVE_OK)
lafe_errc(1, 0, "%s", archive_error_string(a));
r = archive_write_close(ext);
@@ -877,8 +952,8 @@ mode_in(struct cpio *cpio)
fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
blocks == 1 ? "block" : "blocks");
}
- archive_read_finish(a);
- archive_write_finish(ext);
+ archive_read_free(a);
+ archive_write_free(ext);
exit(cpio->return_value);
}
@@ -892,7 +967,7 @@ extract_data(struct archive *ar, struct archive *aw)
int r;
size_t size;
const void *block;
- off_t offset;
+ int64_t offset;
for (;;) {
r = archive_read_data_block(ar, &block, &size, &offset);
@@ -922,7 +997,7 @@ mode_list(struct cpio *cpio)
a = archive_read_new();
if (a == NULL)
lafe_errc(1, 0, "Couldn't allocate archive object");
- archive_read_support_compression_all(a);
+ archive_read_support_filter_all(a);
archive_read_support_format_all(a);
if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block))
@@ -952,7 +1027,7 @@ mode_list(struct cpio *cpio)
fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
blocks == 1 ? "block" : "blocks");
}
- archive_read_finish(a);
+ archive_read_free(a);
exit(0);
}
@@ -989,11 +1064,11 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
/* Use uname if it's present, else lookup name from uid. */
uname = archive_entry_uname(entry);
if (uname == NULL)
- uname = lookup_uname(cpio, archive_entry_uid(entry));
+ uname = lookup_uname(cpio, (uid_t)archive_entry_uid(entry));
/* Use gname if it's present, else lookup name from gid. */
gname = archive_entry_gname(entry);
if (gname == NULL)
- gname = lookup_gname(cpio, archive_entry_gid(entry));
+ gname = lookup_gname(cpio, (uid_t)archive_entry_gid(entry));
}
/* Print device number or file size. */
@@ -1075,6 +1150,8 @@ mode_pass(struct cpio *cpio, const char *destdir)
archive_entry_linkresolver_free(cpio->linkresolver);
r = archive_write_close(cpio->archive);
+ if (cpio->dot)
+ fprintf(stderr, "\n");
if (r != ARCHIVE_OK)
lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
@@ -1086,7 +1163,7 @@ mode_pass(struct cpio *cpio, const char *destdir)
blocks == 1 ? "block" : "blocks");
}
- archive_write_finish(cpio->archive);
+ archive_write_free(cpio->archive);
}
/*
@@ -1102,12 +1179,24 @@ cpio_rename(const char *name)
static char buff[1024];
FILE *t;
char *p, *ret;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ FILE *to;
+ t = fopen("CONIN$", "r");
+ if (t == NULL)
+ return (name);
+ to = fopen("CONOUT$", "w");
+ if (to == NULL)
+ return (name);
+ fprintf(to, "%s (Enter/./(new name))? ", name);
+ fclose(to);
+#else
t = fopen("/dev/tty", "r+");
if (t == NULL)
return (name);
fprintf(t, "%s (Enter/./(new name))? ", name);
fflush(t);
+#endif
p = fgets(buff, sizeof(buff), t);
fclose(t);
@@ -1260,8 +1349,9 @@ lookup_gname_helper(struct cpio *cpio, const char **name, id_t id)
const char *
cpio_i64toa(int64_t n0)
{
- // 2^64 =~ 1.8 * 10^19, so 20 decimal digits suffice.
- // We also need 1 byte for '-' and 1 for '\0'.
+ /* 2^64 =~ 1.8 * 10^19, so 20 decimal digits suffice.
+ * We also need 1 byte for '-' and 1 for '\0'.
+ */
static char buff[22];
int64_t n = n0 < 0 ? -n0 : n0;
char *p = buff + sizeof(buff);
diff --git a/contrib/libarchive/cpio/cpio.h b/contrib/libarchive/cpio/cpio.h
index 2d5b548f4ae3..7c56d3c1da48 100644
--- a/contrib/libarchive/cpio/cpio.h
+++ b/contrib/libarchive/cpio/cpio.h
@@ -43,18 +43,18 @@
*/
struct cpio {
/* Option parsing */
- const char *optarg;
+ const char *argument;
/* Options */
const char *filename;
- char mode; /* -i -o -p */
- char compress; /* -j, -y, or -z */
+ int mode; /* -i -o -p */
+ int compress; /* -j, -y, or -z */
const char *format; /* -H format */
int bytes_per_block; /* -b block_size */
int verbose; /* -v */
+ int dot; /* -V */
int quiet; /* --quiet */
int extract_flags; /* Flags for extract operation */
- char symlink_mode; /* H or L, per BSD conventions */
const char *compress_program;
int option_append; /* -A, only relevant for -o */
int option_atime_restore; /* -a */
diff --git a/contrib/libarchive/cpio/test/main.c b/contrib/libarchive/cpio/test/main.c
index bca4c963934f..d4ed99c88201 100644
--- a/contrib/libarchive/cpio/test/main.c
+++ b/contrib/libarchive/cpio/test/main.c
@@ -24,8 +24,18 @@
*/
#include "test.h"
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
#include <errno.h>
+#ifdef HAVE_ICONV_H
+#include <iconv.h>
+#endif
+#include <limits.h>
#include <locale.h>
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
#include <stdarg.h>
#include <time.h>
@@ -40,8 +50,10 @@ __FBSDID("$FreeBSD$");
#define KNOWNREF "test_option_f.cpio.uu"
#define ENVBASE "BSDCPIO" /* Prefix for environment variables. */
#define PROGRAM "bsdcpio" /* Name of program being tested. */
-#undef LIBRARY /* Not testing a library. */
-#undef EXTRA_DUMP /* How to dump extra data */
+#define PROGRAM_ALIAS "cpio" /* Generic alias for program */
+#undef LIBRARY /* Not testing a library. */
+#undef EXTRA_DUMP /* How to dump extra data */
+#undef EXTRA_ERRNO /* How to dump errno */
/* How to generate extra version info. */
#define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "")
@@ -78,6 +90,7 @@ __FBSDID("$FreeBSD$");
#endif
#if !defined(__BORLANDC__)
#define access _access
+#undef chdir
#define chdir _chdir
#endif
#ifndef fileno
@@ -150,7 +163,7 @@ my_GetFileInformationByName(const char *path, BY_HANDLE_FILE_INFORMATION *bhfi)
memset(bhfi, 0, sizeof(*bhfi));
h = CreateFile(path, FILE_READ_ATTRIBUTES, 0, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE)
return (0);
r = GetFileInformationByHandle(h, bhfi);
@@ -179,6 +192,8 @@ invalid_parameter_handler(const wchar_t * expression,
static int dump_on_failure = 0;
/* Default is to remove temp dirs and log data for successful tests. */
static int keep_temp_files = 0;
+/* Default is to run the specified tests once and report errors. */
+static int until_failure = 0;
/* Default is to just report pass/fail for each test. */
static int verbosity = 0;
#define VERBOSITY_SUMMARY_ONLY -1 /* -q */
@@ -236,10 +251,14 @@ void
failure(const char *fmt, ...)
{
va_list ap;
- va_start(ap, fmt);
- vsprintf(msgbuff, fmt, ap);
- va_end(ap);
- nextmsg = msgbuff;
+ if (fmt == NULL) {
+ nextmsg = NULL;
+ } else {
+ va_start(ap, fmt);
+ vsprintf(msgbuff, fmt, ap);
+ va_end(ap);
+ nextmsg = msgbuff;
+ }
}
/*
@@ -251,15 +270,14 @@ failure(const char *fmt, ...)
* pass __FILE__, __LINE__ directly into the function instead of using
* this hook. I suspect this machinery is used so rarely that we
* would be better off just removing it entirely. That would simplify
- * the code here noticably.
+ * the code here noticeably.
*/
-static const char *test_filename;
-static int test_line;
-static void *test_extra;
-void assertion_setup(const char *filename, int line)
+static const char *skipping_filename;
+static int skipping_line;
+void skipping_setup(const char *filename, int line)
{
- test_filename = filename;
- test_line = line;
+ skipping_filename = filename;
+ skipping_line = line;
}
/* Called at the beginning of each assert() function. */
@@ -286,6 +304,7 @@ static struct line {
int count;
int skip;
} failed_lines[10000];
+const char *failed_filename;
/* Count this failure, setup up log destination and handle initial report. */
static void
@@ -295,19 +314,16 @@ failure_start(const char *filename, int line, const char *fmt, ...)
/* Record another failure for this line. */
++failures;
- /* test_filename = filename; */
+ failed_filename = filename;
failed_lines[line].count++;
/* Determine whether to log header to console. */
switch (verbosity) {
- case VERBOSITY_FULL:
- log_console = 1;
- break;
case VERBOSITY_LIGHT_REPORT:
log_console = (failed_lines[line].count < 2);
break;
default:
- log_console = 0;
+ log_console = (verbosity >= VERBOSITY_FULL);
}
/* Log file:line header for this failure */
@@ -343,14 +359,16 @@ failure_finish(void *extra)
{
(void)extra; /* UNUSED (maybe) */
#ifdef EXTRA_DUMP
- if (extra != NULL)
+ if (extra != NULL) {
+ logprintf(" errno: %d\n", EXTRA_ERRNO(extra));
logprintf(" detail: %s\n", EXTRA_DUMP(extra));
+ }
#endif
if (dump_on_failure) {
fprintf(stderr,
" *** forcing core dump so failure can be debugged ***\n");
- *(char *)(NULL) = 0;
+ abort();
exit(1);
}
}
@@ -365,12 +383,15 @@ test_skipping(const char *fmt, ...)
va_start(ap, fmt);
vsprintf(buff, fmt, ap);
va_end(ap);
+ /* Use failure() message if set. */
+ msg = nextmsg;
+ nextmsg = NULL;
/* failure_start() isn't quite right, but is awfully convenient. */
- failure_start(test_filename, test_line, "SKIPPING: %s", buff);
+ failure_start(skipping_filename, skipping_line, "SKIPPING: %s", buff);
--failures; /* Undo failures++ in failure_start() */
/* Don't failure_finish() here. */
/* Mark as skip, so doesn't count as failed test. */
- failed_lines[test_line].skip = 1;
+ failed_lines[skipping_line].skip = 1;
++skips;
}
@@ -421,13 +442,102 @@ assertion_equal_int(const char *file, int line,
return (0);
}
-static void strdump(const char *e, const char *p)
+/*
+ * Utility to convert a single UTF-8 sequence.
+ */
+static int
+_utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
+{
+ static const char utf8_count[256] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 00 - 0F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 10 - 1F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20 - 2F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30 - 3F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40 - 4F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 50 - 5F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60 - 6F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 70 - 7F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 80 - 8F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 90 - 9F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* A0 - AF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* B0 - BF */
+ 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* C0 - CF */
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* D0 - DF */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,/* E0 - EF */
+ 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0 - FF */
+ };
+ int ch;
+ int cnt;
+ uint32_t wc;
+
+ *pwc = 0;
+
+ /* Sanity check. */
+ if (n == 0)
+ return (0);
+ /*
+ * Decode 1-4 bytes depending on the value of the first byte.
+ */
+ ch = (unsigned char)*s;
+ if (ch == 0)
+ return (0); /* Standard: return 0 for end-of-string. */
+ cnt = utf8_count[ch];
+
+ /* Invalide sequence or there are not plenty bytes. */
+ if (n < (size_t)cnt)
+ return (-1);
+
+ /* Make a Unicode code point from a single UTF-8 sequence. */
+ switch (cnt) {
+ case 1: /* 1 byte sequence. */
+ *pwc = ch & 0x7f;
+ return (cnt);
+ case 2: /* 2 bytes sequence. */
+ if ((s[1] & 0xc0) != 0x80) return (-1);
+ *pwc = ((ch & 0x1f) << 6) | (s[1] & 0x3f);
+ return (cnt);
+ case 3: /* 3 bytes sequence. */
+ if ((s[1] & 0xc0) != 0x80) return (-1);
+ if ((s[2] & 0xc0) != 0x80) return (-1);
+ wc = ((ch & 0x0f) << 12)
+ | ((s[1] & 0x3f) << 6)
+ | (s[2] & 0x3f);
+ if (wc < 0x800)
+ return (-1);/* Overlong sequence. */
+ break;
+ case 4: /* 4 bytes sequence. */
+ if (n < 4)
+ return (-1);
+ if ((s[1] & 0xc0) != 0x80) return (-1);
+ if ((s[2] & 0xc0) != 0x80) return (-1);
+ if ((s[3] & 0xc0) != 0x80) return (-1);
+ wc = ((ch & 0x07) << 18)
+ | ((s[1] & 0x3f) << 12)
+ | ((s[2] & 0x3f) << 6)
+ | (s[3] & 0x3f);
+ if (wc < 0x10000)
+ return (-1);/* Overlong sequence. */
+ break;
+ default:
+ return (-1);
+ }
+
+ /* The code point larger than 0x10FFFF is not leagal
+ * Unicode values. */
+ if (wc > 0x10FFFF)
+ return (-1);
+ /* Correctly gets a Unicode, returns used bytes. */
+ *pwc = wc;
+ return (cnt);
+}
+
+static void strdump(const char *e, const char *p, int ewidth, int utf8)
{
const char *q = p;
- logprintf(" %s = ", e);
+ logprintf(" %*s = ", ewidth, e);
if (p == NULL) {
- logprintf("NULL");
+ logprintf("NULL\n");
return;
}
logprintf("\"");
@@ -446,7 +556,37 @@ static void strdump(const char *e, const char *p)
}
}
logprintf("\"");
- logprintf(" (length %d)\n", q == NULL ? -1 : (int)strlen(q));
+ logprintf(" (length %d)", q == NULL ? -1 : (int)strlen(q));
+
+ /*
+ * If the current string is UTF-8, dump its code points.
+ */
+ if (utf8) {
+ size_t len;
+ uint32_t uc;
+ int n;
+ int cnt = 0;
+
+ p = q;
+ len = strlen(p);
+ logprintf(" [");
+ while ((n = _utf8_to_unicode(&uc, p, len)) > 0) {
+ if (p != q)
+ logprintf(" ");
+ logprintf("%04X", uc);
+ p += n;
+ len -= n;
+ cnt++;
+ }
+ logprintf("]");
+ logprintf(" (count %d", cnt);
+ if (n < 0) {
+ logprintf(",unknown %d bytes", len);
+ }
+ logprintf(")");
+
+ }
+ logprintf("\n");
}
/* Verify two strings are equal, dump them if not. */
@@ -454,14 +594,20 @@ int
assertion_equal_string(const char *file, int line,
const char *v1, const char *e1,
const char *v2, const char *e2,
- void *extra)
+ void *extra, int utf8)
{
+ int l1, l2;
+
assertion_count(file, line);
if (v1 == v2 || (v1 != NULL && v2 != NULL && strcmp(v1, v2) == 0))
return (1);
failure_start(file, line, "%s != %s", e1, e2);
- strdump(e1, v1);
- strdump(e2, v2);
+ l1 = strlen(e1);
+ l2 = strlen(e2);
+ if (l1 < l2)
+ l1 = l2;
+ strdump(e1, v1, l1, utf8);
+ strdump(e2, v2, l1, utf8);
failure_finish(extra);
return (0);
}
@@ -513,7 +659,9 @@ assertion_equal_wstring(const char *file, int line,
void *extra)
{
assertion_count(file, line);
- if (v1 == v2 || wcscmp(v1, v2) == 0)
+ if (v1 == v2)
+ return (1);
+ if (v1 != NULL && v2 != NULL && wcscmp(v1, v2) == 0)
return (1);
failure_start(file, line, "%s != %s", e1, e2);
wcsdump(e1, v1);
@@ -592,9 +740,9 @@ assertion_equal_mem(const char *file, int line,
offset += 16;
}
logprintf(" Dump of %s\n", e1);
- hexdump(v1, v2, l < 64 ? l : 64, offset);
+ hexdump(v1, v2, l < 128 ? l : 128, offset);
logprintf(" Dump of %s\n", e2);
- hexdump(v2, v1, l < 64 ? l : 64, offset);
+ hexdump(v2, v1, l < 128 ? l : 128, offset);
logprintf("\n");
failure_finish(extra);
return (0);
@@ -602,29 +750,24 @@ assertion_equal_mem(const char *file, int line,
/* Verify that the named file exists and is empty. */
int
-assertion_empty_file(const char *f1fmt, ...)
+assertion_empty_file(const char *filename, int line, const char *f1)
{
char buff[1024];
- char f1[1024];
struct stat st;
- va_list ap;
ssize_t s;
FILE *f;
- assertion_count(test_filename, test_line);
- va_start(ap, f1fmt);
- vsprintf(f1, f1fmt, ap);
- va_end(ap);
+ assertion_count(filename, line);
if (stat(f1, &st) != 0) {
- failure_start(test_filename, test_line, "Stat failed: %s", f1);
+ failure_start(filename, line, "Stat failed: %s", f1);
failure_finish(NULL);
return (0);
}
if (st.st_size == 0)
return (1);
- failure_start(test_filename, test_line, "File should be empty: %s", f1);
+ failure_start(filename, line, "File should be empty: %s", f1);
logprintf(" File size: %d\n", (int)st.st_size);
logprintf(" Contents:\n");
f = fopen(f1, "rb");
@@ -643,24 +786,19 @@ assertion_empty_file(const char *f1fmt, ...)
/* Verify that the named file exists and is not empty. */
int
-assertion_non_empty_file(const char *f1fmt, ...)
+assertion_non_empty_file(const char *filename, int line, const char *f1)
{
- char f1[1024];
struct stat st;
- va_list ap;
- assertion_count(test_filename, test_line);
- va_start(ap, f1fmt);
- vsprintf(f1, f1fmt, ap);
- va_end(ap);
+ assertion_count(filename, line);
if (stat(f1, &st) != 0) {
- failure_start(test_filename, test_line, "Stat failed: %s", f1);
+ failure_start(filename, line, "Stat failed: %s", f1);
failure_finish(NULL);
return (0);
}
if (st.st_size == 0) {
- failure_start(test_filename, test_line, "File empty: %s", f1);
+ failure_start(filename, line, "File empty: %s", f1);
failure_finish(NULL);
return (0);
}
@@ -670,19 +808,14 @@ assertion_non_empty_file(const char *f1fmt, ...)
/* Verify that two files have the same contents. */
/* TODO: hexdump the first bytes that actually differ. */
int
-assertion_equal_file(const char *fn1, const char *f2pattern, ...)
+assertion_equal_file(const char *filename, int line, const char *fn1, const char *fn2)
{
- char fn2[1024];
- va_list ap;
char buff1[1024];
char buff2[1024];
FILE *f1, *f2;
int n1, n2;
- assertion_count(test_filename, test_line);
- va_start(ap, f2pattern);
- vsprintf(fn2, f2pattern, ap);
- va_end(ap);
+ assertion_count(filename, line);
f1 = fopen(fn1, "rb");
f2 = fopen(fn2, "rb");
@@ -701,24 +834,18 @@ assertion_equal_file(const char *fn1, const char *f2pattern, ...)
}
fclose(f1);
fclose(f2);
- failure_start(test_filename, test_line, "Files not identical");
+ failure_start(filename, line, "Files not identical");
logprintf(" file1=\"%s\"\n", fn1);
logprintf(" file2=\"%s\"\n", fn2);
- failure_finish(test_extra);
+ failure_finish(NULL);
return (0);
}
/* Verify that the named file does exist. */
int
-assertion_file_exists(const char *fpattern, ...)
+assertion_file_exists(const char *filename, int line, const char *f)
{
- char f[1024];
- va_list ap;
-
- assertion_count(test_filename, test_line);
- va_start(ap, fpattern);
- vsprintf(f, fpattern, ap);
- va_end(ap);
+ assertion_count(filename, line);
#if defined(_WIN32) && !defined(__CYGWIN__)
if (!_access(f, 0))
@@ -727,22 +854,16 @@ assertion_file_exists(const char *fpattern, ...)
if (!access(f, F_OK))
return (1);
#endif
- failure_start(test_filename, test_line, "File should exist: %s", f);
- failure_finish(test_extra);
+ failure_start(filename, line, "File should exist: %s", f);
+ failure_finish(NULL);
return (0);
}
/* Verify that the named file doesn't exist. */
int
-assertion_file_not_exists(const char *fpattern, ...)
+assertion_file_not_exists(const char *filename, int line, const char *f)
{
- char f[1024];
- va_list ap;
-
- assertion_count(test_filename, test_line);
- va_start(ap, fpattern);
- vsprintf(f, fpattern, ap);
- va_end(ap);
+ assertion_count(filename, line);
#if defined(_WIN32) && !defined(__CYGWIN__)
if (_access(f, 0))
@@ -751,31 +872,26 @@ assertion_file_not_exists(const char *fpattern, ...)
if (access(f, F_OK))
return (1);
#endif
- failure_start(test_filename, test_line, "File should not exist: %s", f);
- failure_finish(test_extra);
+ failure_start(filename, line, "File should not exist: %s", f);
+ failure_finish(NULL);
return (0);
}
/* Compare the contents of a file to a block of memory. */
int
-assertion_file_contents(const void *buff, int s, const char *fpattern, ...)
+assertion_file_contents(const char *filename, int line, const void *buff, int s, const char *fn)
{
- char fn[1024];
- va_list ap;
char *contents;
FILE *f;
int n;
- assertion_count(test_filename, test_line);
- va_start(ap, fpattern);
- vsprintf(fn, fpattern, ap);
- va_end(ap);
+ assertion_count(filename, line);
f = fopen(fn, "rb");
if (f == NULL) {
- failure_start(test_filename, test_line,
+ failure_start(filename, line,
"File should exist: %s", fn);
- failure_finish(test_extra);
+ failure_finish(NULL);
return (0);
}
contents = malloc(s * 2);
@@ -785,34 +901,34 @@ assertion_file_contents(const void *buff, int s, const char *fpattern, ...)
free(contents);
return (1);
}
- failure_start(test_filename, test_line, "File contents don't match");
+ failure_start(filename, line, "File contents don't match");
logprintf(" file=\"%s\"\n", fn);
if (n > 0)
hexdump(contents, buff, n > 512 ? 512 : n, 0);
else {
logprintf(" File empty, contents should be:\n");
- hexdump(buff, NULL, s > 512 ? 512 : n, 0);
+ hexdump(buff, NULL, s > 512 ? 512 : s, 0);
}
- failure_finish(test_extra);
+ failure_finish(NULL);
free(contents);
return (0);
}
/* Check the contents of a text file, being tolerant of line endings. */
int
-assertion_text_file_contents(const char *buff, const char *fn)
+assertion_text_file_contents(const char *filename, int line, const char *buff, const char *fn)
{
char *contents;
const char *btxt, *ftxt;
FILE *f;
int n, s;
- assertion_count(test_filename, test_line);
+ assertion_count(filename, line);
f = fopen(fn, "r");
if (f == NULL) {
- failure_start(test_filename, test_line,
+ failure_start(filename, line,
"File doesn't exist: %s", fn);
- failure_finish(test_extra);
+ failure_finish(NULL);
return (0);
}
s = strlen(buff);
@@ -842,19 +958,122 @@ assertion_text_file_contents(const char *buff, const char *fn)
free(contents);
return (1);
}
- failure_start(test_filename, test_line, "Contents don't match");
+ failure_start(filename, line, "Contents don't match");
logprintf(" file=\"%s\"\n", fn);
- if (n > 0)
+ if (n > 0) {
hexdump(contents, buff, n, 0);
- else {
+ logprintf(" expected\n", fn);
+ hexdump(buff, contents, s, 0);
+ } else {
logprintf(" File empty, contents should be:\n");
hexdump(buff, NULL, s, 0);
}
- failure_finish(test_extra);
+ failure_finish(NULL);
free(contents);
return (0);
}
+/* Verify that a text file contains the specified lines, regardless of order */
+/* This could be more efficient if we sorted both sets of lines, etc, but
+ * since this is used only for testing and only ever deals with a dozen or so
+ * lines at a time, this relatively crude approach is just fine. */
+int
+assertion_file_contains_lines_any_order(const char *file, int line,
+ const char *pathname, const char *lines[])
+{
+ char *buff;
+ size_t buff_size;
+ size_t expected_count, actual_count, i, j;
+ char **expected;
+ char *p, **actual;
+ char c;
+ int expected_failure = 0, actual_failure = 0;
+
+ assertion_count(file, line);
+
+ buff = slurpfile(&buff_size, "%s", pathname);
+ if (buff == NULL) {
+ failure_start(pathname, line, "Can't read file: %s", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+
+ /* Make a copy of the provided lines and count up the expected file size. */
+ expected_count = 0;
+ for (i = 0; lines[i] != NULL; ++i) {
+ }
+ expected_count = i;
+ expected = malloc(sizeof(char *) * expected_count);
+ for (i = 0; lines[i] != NULL; ++i) {
+ expected[i] = strdup(lines[i]);
+ }
+
+ /* Break the file into lines */
+ actual_count = 0;
+ for (c = '\0', p = buff; p < buff + buff_size; ++p) {
+ if (*p == '\x0d' || *p == '\x0a')
+ *p = '\0';
+ if (c == '\0' && *p != '\0')
+ ++actual_count;
+ c = *p;
+ }
+ actual = malloc(sizeof(char *) * actual_count);
+ for (j = 0, p = buff; p < buff + buff_size; p += 1 + strlen(p)) {
+ if (*p != '\0') {
+ actual[j] = p;
+ ++j;
+ }
+ }
+
+ /* Erase matching lines from both lists */
+ for (i = 0; i < expected_count; ++i) {
+ if (expected[i] == NULL)
+ continue;
+ for (j = 0; j < actual_count; ++j) {
+ if (actual[j] == NULL)
+ continue;
+ if (strcmp(expected[i], actual[j]) == 0) {
+ free(expected[i]);
+ expected[i] = NULL;
+ actual[j] = NULL;
+ break;
+ }
+ }
+ }
+
+ /* If there's anything left, it's a failure */
+ for (i = 0; i < expected_count; ++i) {
+ if (expected[i] != NULL)
+ ++expected_failure;
+ }
+ for (j = 0; j < actual_count; ++j) {
+ if (actual[j] != NULL)
+ ++actual_failure;
+ }
+ if (expected_failure == 0 && actual_failure == 0) {
+ free(buff);
+ free(expected);
+ free(actual);
+ return (1);
+ }
+ failure_start(file, line, "File doesn't match: %s", pathname);
+ for (i = 0; i < expected_count; ++i) {
+ if (expected[i] != NULL) {
+ logprintf(" Expected but not present: %s\n", expected[i]);
+ free(expected[i]);
+ }
+ }
+ for (j = 0; j < actual_count; ++j) {
+ if (actual[j] != NULL)
+ logprintf(" Present but not expected: %s\n", actual[j]);
+ }
+ failure_finish(NULL);
+ free(buff);
+ free(expected);
+ free(actual);
+ return (0);
+}
+
/* Test that two paths point to the same file. */
/* As a side-effect, asserts that both files exist. */
static int
@@ -944,8 +1163,11 @@ assertion_file_time(const char *file, int line,
ftime.dwHighDateTime = 0;
assertion_count(file, line);
+ /* Note: FILE_FLAG_BACKUP_SEMANTICS applies to open
+ * a directory file. If not, CreateFile() will fail when
+ * the pathname is a directory. */
h = CreateFile(pathname, FILE_READ_ATTRIBUTES, 0, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE) {
failure_start(file, line, "Can't access %s\n", pathname);
failure_finish(NULL);
@@ -1010,14 +1232,14 @@ assertion_file_time(const char *file, int line,
time_t now = time(NULL);
if (filet < now - 10 || filet > now + 1) {
failure_start(file, line,
- "File %s has %ctime %ld, %ld seconds ago\n",
+ "File %s has %ctime %lld, %lld seconds ago\n",
pathname, type, filet, now - filet);
failure_finish(NULL);
return (0);
}
} else if (filet != t || filet_nsec != nsec) {
failure_start(file, line,
- "File %s has %ctime %ld.%09ld, expected %ld.%09ld",
+ "File %s has %ctime %lld.%09lld, expected %lld.%09lld",
pathname, type, filet, filet_nsec, t, nsec);
failure_finish(NULL);
return (0);
@@ -1094,7 +1316,7 @@ assertion_file_nlinks(const char *file, int line,
assertion_count(file, line);
r = lstat(pathname, &st);
- if (r == 0 && st.st_nlink == nlinks)
+ if (r == 0 && (int)st.st_nlink == nlinks)
return (1);
failure_start(file, line, "File %s has %d links, expected %d",
pathname, st.st_nlink, nlinks);
@@ -1158,7 +1380,7 @@ assertion_is_dir(const char *file, int line, const char *pathname, int mode)
/* Windows doesn't handle permissions the same way as POSIX,
* so just ignore the mode tests. */
/* TODO: Can we do better here? */
- if (mode >= 0 && mode != (st.st_mode & 07777)) {
+ if (mode >= 0 && (mode_t)mode != (st.st_mode & 07777)) {
failure_start(file, line, "Dir %s has wrong mode", pathname);
logprintf(" Expected: 0%3o\n", mode);
logprintf(" Found: 0%3o\n", st.st_mode & 07777);
@@ -1191,7 +1413,7 @@ assertion_is_reg(const char *file, int line, const char *pathname, int mode)
/* Windows doesn't handle permissions the same way as POSIX,
* so just ignore the mode tests. */
/* TODO: Can we do better here? */
- if (mode >= 0 && mode != (st.st_mode & 07777)) {
+ if (mode >= 0 && (mode_t)mode != (st.st_mode & 07777)) {
failure_start(file, line, "File %s has wrong mode", pathname);
logprintf(" Expected: 0%3o\n", mode);
logprintf(" Found: 0%3o\n", st.st_mode & 07777);
@@ -1390,6 +1612,110 @@ assertion_umask(const char *file, int line, int mask)
return (1);
}
+/* Set times, report failures. */
+int
+assertion_utimes(const char *file, int line,
+ const char *pathname, long at, long at_nsec, long mt, long mt_nsec)
+{
+ int r;
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#define WINTIME(sec, nsec) ((Int32x32To64(sec, 10000000) + EPOC_TIME)\
+ + (((nsec)/1000)*10))
+ HANDLE h;
+ ULARGE_INTEGER wintm;
+ FILETIME fatime, fmtime;
+ FILETIME *pat, *pmt;
+
+ assertion_count(file, line);
+ h = CreateFileA(pathname,GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (h == INVALID_HANDLE_VALUE) {
+ failure_start(file, line, "Can't access %s\n", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+
+ if (at > 0 || at_nsec > 0) {
+ wintm.QuadPart = WINTIME(at, at_nsec);
+ fatime.dwLowDateTime = wintm.LowPart;
+ fatime.dwHighDateTime = wintm.HighPart;
+ pat = &fatime;
+ } else
+ pat = NULL;
+ if (mt > 0 || mt_nsec > 0) {
+ wintm.QuadPart = WINTIME(mt, mt_nsec);
+ fmtime.dwLowDateTime = wintm.LowPart;
+ fmtime.dwHighDateTime = wintm.HighPart;
+ pmt = &fmtime;
+ } else
+ pmt = NULL;
+ if (pat != NULL || pmt != NULL)
+ r = SetFileTime(h, NULL, pat, pmt);
+ else
+ r = 1;
+ CloseHandle(h);
+ if (r == 0) {
+ failure_start(file, line, "Can't SetFileTime %s\n", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+ return (1);
+#else /* defined(_WIN32) && !defined(__CYGWIN__) */
+ struct stat st;
+ struct timeval times[2];
+
+#if !defined(__FreeBSD__)
+ mt_nsec = at_nsec = 0; /* Generic POSIX only has whole seconds. */
+#endif
+ if (mt == 0 && mt_nsec == 0 && at == 0 && at_nsec == 0)
+ return (1);
+
+ r = lstat(pathname, &st);
+ if (r < 0) {
+ failure_start(file, line, "Can't stat %s\n", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+
+ if (mt == 0 && mt_nsec == 0) {
+ mt = st.st_mtime;
+#if defined(__FreeBSD__)
+ mt_nsec = st.st_mtimespec.tv_nsec;
+ /* FreeBSD generally only stores to microsecond res, so round. */
+ mt_nsec = (mt_nsec / 1000) * 1000;
+#endif
+ }
+ if (at == 0 && at_nsec == 0) {
+ at = st.st_atime;
+#if defined(__FreeBSD__)
+ at_nsec = st.st_atimespec.tv_nsec;
+ /* FreeBSD generally only stores to microsecond res, so round. */
+ at_nsec = (at_nsec / 1000) * 1000;
+#endif
+ }
+
+ times[1].tv_sec = mt;
+ times[1].tv_usec = mt_nsec / 1000;
+
+ times[0].tv_sec = at;
+ times[0].tv_usec = at_nsec / 1000;
+
+#ifdef HAVE_LUTIMES
+ r = lutimes(pathname, times);
+#else
+ r = utimes(pathname, times);
+#endif
+ if (r < 0) {
+ failure_start(file, line, "Can't utimes %s\n", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+ return (1);
+#endif /* defined(_WIN32) && !defined(__CYGWIN__) */
+}
+
/*
*
* UTILITIES for use by tests.
@@ -1615,6 +1941,27 @@ extract_reference_file(const char *name)
fclose(in);
}
+int
+is_LargeInode(const char *file)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ BY_HANDLE_FILE_INFORMATION bhfi;
+ int r;
+
+ r = my_GetFileInformationByName(file, &bhfi);
+ if (r != 0)
+ return (0);
+ return (bhfi.nFileIndexHigh & 0x0000FFFFUL);
+#else
+ struct stat st;
+ int64_t ino;
+
+ if (stat(file, &st) < 0)
+ return (0);
+ ino = (int64_t)st.st_ino;
+ return (ino > 0xffffffff);
+#endif
+}
/*
*
* TEST management
@@ -1644,7 +1991,7 @@ struct { void (*func)(void); const char *name; int failures; } tests[] = {
* Summarize repeated failures in the just-completed test.
*/
static void
-test_summarize(const char *filename, int failed)
+test_summarize(int failed)
{
unsigned int i;
@@ -1663,9 +2010,10 @@ test_summarize(const char *filename, int failed)
for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) {
if (failed_lines[i].count > 1 && !failed_lines[i].skip)
logprintf("%s:%d: Summary: Failed %d times\n",
- filename, i, failed_lines[i].count);
+ failed_filename, i, failed_lines[i].count);
}
/* Clear the failure history for the next file. */
+ failed_filename = NULL;
memset(failed_lines, 0, sizeof(failed_lines));
}
@@ -1675,6 +2023,7 @@ test_summarize(const char *filename, int failed)
static int
test_run(int i, const char *tmpdir)
{
+ char workdir[1024];
char logfilename[64];
int failures_before = failures;
int oldumask;
@@ -1701,11 +2050,12 @@ test_run(int i, const char *tmpdir)
logfile = fopen(logfilename, "w");
fprintf(logfile, "%s\n\n", tests[i].name);
/* Chdir() to a work dir for this specific test. */
- if (!assertMakeDir(tests[i].name, 0755)
- || !assertChdir(tests[i].name)) {
+ snprintf(workdir, sizeof(workdir), "%s/%s", tmpdir, tests[i].name);
+ testworkdir = workdir;
+ if (!assertMakeDir(testworkdir, 0755)
+ || !assertChdir(testworkdir)) {
fprintf(stderr,
- "ERROR: Can't chdir to work dir %s/%s\n",
- tmpdir, tests[i].name);
+ "ERROR: Can't chdir to work dir %s\n", testworkdir);
exit(1);
}
/* Explicitly reset the locale before each test. */
@@ -1719,6 +2069,7 @@ test_run(int i, const char *tmpdir)
/*
* Clean up and report afterwards.
*/
+ testworkdir = NULL;
/* Restore umask */
umask(oldumask);
/* Reset locale. */
@@ -1731,7 +2082,7 @@ test_run(int i, const char *tmpdir)
}
/* Report per-test summaries. */
tests[i].failures = failures - failures_before;
- test_summarize(test_filename, tests[i].failures);
+ test_summarize(tests[i].failures);
/* Close the per-test log file. */
fclose(logfile);
logfile = NULL;
@@ -1791,6 +2142,7 @@ usage(const char *program)
printf(" -q Quiet.\n");
printf(" -r <dir> Path to dir containing reference files.\n");
printf(" Default: Current directory.\n");
+ printf(" -u Keep running specifies tests until one fails.\n");
printf(" -v Verbose.\n");
printf("Available tests:\n");
for (i = 0; i < limit; i++)
@@ -1817,7 +2169,11 @@ get_refdir(const char *d)
}
/* Get the current dir. */
+#ifdef PATH_MAX
+ pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
+#else
pwd = getcwd(NULL, 0);
+#endif
while (pwd[strlen(pwd) - 1] == '\n')
pwd[strlen(pwd) - 1] = '\0';
@@ -1844,6 +2200,14 @@ get_refdir(const char *d)
strncat(tried, buff, sizeof(tried) - strlen(tried) - 1);
strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1);
+#if defined(PROGRAM_ALIAS)
+ snprintf(buff, sizeof(buff), "%s/%s/test", pwd, PROGRAM_ALIAS);
+ p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
+ if (p != NULL) goto success;
+ strncat(tried, buff, sizeof(tried) - strlen(tried) - 1);
+ strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1);
+#endif
+
if (memcmp(pwd, "/usr/obj", 8) == 0) {
snprintf(buff, sizeof(buff), "%s", pwd + 8);
p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
@@ -1876,16 +2240,26 @@ int
main(int argc, char **argv)
{
static const int limit = sizeof(tests) / sizeof(tests[0]);
- int i, tests_run = 0, tests_failed = 0, option;
+ int i = 0, j = 0, start, end, tests_run = 0, tests_failed = 0, option;
time_t now;
char *refdir_alloc = NULL;
const char *progname;
+ char **saved_argv;
const char *tmp, *option_arg, *p;
- char tmpdir[256];
+ char tmpdir[256], *pwd, *testprogdir, *tmp2 = NULL;
char tmpdir_timestamp[256];
(void)argc; /* UNUSED */
+ /* Get the current dir. */
+#ifdef PATH_MAX
+ pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
+#else
+ pwd = getcwd(NULL, 0);
+#endif
+ while (pwd[strlen(pwd) - 1] == '\n')
+ pwd[strlen(pwd) - 1] = '\0';
+
#if defined(HAVE__CrtSetReportMode)
/* To stop to run the default invalid parameter handler. */
_set_invalid_parameter_handler(invalid_parameter_handler);
@@ -1898,11 +2272,44 @@ main(int argc, char **argv)
* tree.
*/
progname = p = argv[0];
+ if ((testprogdir = (char *)malloc(strlen(progname) + 1)) == NULL)
+ {
+ fprintf(stderr, "ERROR: Out of memory.");
+ exit(1);
+ }
+ strcpy(testprogdir, progname);
while (*p != '\0') {
/* Support \ or / dir separators for Windows compat. */
if (*p == '/' || *p == '\\')
+ {
progname = p + 1;
+ i = j;
+ }
++p;
+ j++;
+ }
+ testprogdir[i] = '\0';
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ if (testprogdir[0] != '/' && testprogdir[0] != '\\' &&
+ !(((testprogdir[0] >= 'a' && testprogdir[0] <= 'z') ||
+ (testprogdir[0] >= 'A' && testprogdir[0] <= 'Z')) &&
+ testprogdir[1] == ':' &&
+ (testprogdir[2] == '/' || testprogdir[2] == '\\')))
+#else
+ if (testprogdir[0] != '/')
+#endif
+ {
+ /* Fixup path for relative directories. */
+ if ((testprogdir = (char *)realloc(testprogdir,
+ strlen(pwd) + 1 + strlen(testprogdir) + 1)) == NULL)
+ {
+ fprintf(stderr, "ERROR: Out of memory.");
+ exit(1);
+ }
+ memmove(testprogdir + strlen(pwd) + 1, testprogdir,
+ strlen(testprogdir));
+ memcpy(testprogdir, pwd, strlen(pwd));
+ testprogdir[strlen(pwd)] = '/';
}
#ifdef PROGRAM
@@ -1967,6 +2374,7 @@ main(int argc, char **argv)
#ifdef PROGRAM
testprogfile = option_arg;
#else
+ fprintf(stderr, "-p option not permitted\n");
usage(progname);
#endif
break;
@@ -1976,10 +2384,15 @@ main(int argc, char **argv)
case 'r':
refdir = option_arg;
break;
+ case 'u':
+ until_failure++;
+ break;
case 'v':
verbosity++;
break;
default:
+ fprintf(stderr, "Unrecognized option '%c'\n",
+ option);
usage(progname);
}
}
@@ -1990,7 +2403,19 @@ main(int argc, char **argv)
*/
#ifdef PROGRAM
if (testprogfile == NULL)
- usage(progname);
+ {
+ if ((tmp2 = (char *)malloc(strlen(testprogdir) + 1 +
+ strlen(PROGRAM) + 1)) == NULL)
+ {
+ fprintf(stderr, "ERROR: Out of memory.");
+ exit(1);
+ }
+ strcpy(tmp2, testprogdir);
+ strcat(tmp2, "/");
+ strcat(tmp2, PROGRAM);
+ testprogfile = tmp2;
+ }
+
{
char *testprg;
#if defined(_WIN32) && !defined(__CYGWIN__)
@@ -2011,6 +2436,16 @@ main(int argc, char **argv)
}
#endif
+#if !defined(_WIN32) && defined(SIGPIPE)
+ { /* Ignore SIGPIPE signals */
+ struct sigaction sa;
+ sa.sa_handler = SIG_IGN;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sigaction(SIGPIPE, &sa, NULL);
+ }
+#endif
+
/*
* Create a temp directory for the following tests.
* Include the time the tests started as part of the name,
@@ -2063,42 +2498,88 @@ main(int argc, char **argv)
/*
* Run some or all of the individual tests.
*/
- if (*argv == NULL) {
- /* Default: Run all tests. */
- for (i = 0; i < limit; i++) {
- if (test_run(i, tmpdir))
- tests_failed++;
- tests_run++;
- }
- } else {
- while (*(argv) != NULL) {
- if (**argv >= '0' && **argv <= '9') {
- i = atoi(*argv);
- if (i < 0 || i >= limit) {
- printf("*** INVALID Test %s\n", *argv);
- free(refdir_alloc);
- usage(progname);
- /* usage() never returns */
+ saved_argv = argv;
+ do {
+ argv = saved_argv;
+ if (*argv == NULL) {
+ /* Default: Run all tests. */
+ for (i = 0; i < limit; i++) {
+ tests_run++;
+ if (test_run(i, tmpdir)) {
+ tests_failed++;
+ if (until_failure)
+ goto finish;
}
- } else {
- for (i = 0; i < limit; ++i) {
- if (strcmp(*argv, tests[i].name) == 0)
- break;
+ }
+ } else {
+ while (*(argv) != NULL) {
+ if (**argv >= '0' && **argv <= '9') {
+ char *vp = *argv;
+ start = 0;
+ while (*vp >= '0' && *vp <= '9') {
+ start *= 10;
+ start += *vp - '0';
+ ++vp;
+ }
+ if (*vp == '\0') {
+ end = start;
+ } else if (*vp == '-') {
+ ++vp;
+ if (*vp == '\0') {
+ end = limit - 1;
+ } else {
+ end = 0;
+ while (*vp >= '0' && *vp <= '9') {
+ end *= 10;
+ end += *vp - '0';
+ ++vp;
+ }
+ }
+ } else {
+ printf("*** INVALID Test %s\n", *argv);
+ free(refdir_alloc);
+ usage(progname);
+ return (1);
+ }
+ if (start < 0 || end >= limit || start > end) {
+ printf("*** INVALID Test %s\n", *argv);
+ free(refdir_alloc);
+ usage(progname);
+ return (1);
+ }
+ } else {
+ for (start = 0; start < limit; ++start) {
+ if (strcmp(*argv, tests[start].name) == 0)
+ break;
+ }
+ end = start;
+ if (start >= limit) {
+ printf("*** INVALID Test ``%s''\n",
+ *argv);
+ free(refdir_alloc);
+ usage(progname);
+ /* usage() never returns */
+ }
}
- if (i >= limit) {
- printf("*** INVALID Test ``%s''\n",
- *argv);
- free(refdir_alloc);
- usage(progname);
- /* usage() never returns */
+ while (start <= end) {
+ tests_run++;
+ if (test_run(start, tmpdir)) {
+ tests_failed++;
+ if (until_failure)
+ goto finish;
+ }
+ ++start;
}
+ argv++;
}
- if (test_run(i, tmpdir))
- tests_failed++;
- tests_run++;
- argv++;
}
- }
+ } while (until_failure);
+
+finish:
+ /* Must be freed after all tests run */
+ free(tmp2);
+ free(testprogdir);
+ free(pwd);
/*
* Report summary statistics.
diff --git a/contrib/libarchive/cpio/test/test.h b/contrib/libarchive/cpio/test/test.h
index 8b1352a1aaee..fdecb3e7cbb7 100644
--- a/contrib/libarchive/cpio/test/test.h
+++ b/contrib/libarchive/cpio/test/test.h
@@ -48,9 +48,6 @@
#include <sys/types.h> /* Windows requires this before sys/stat.h */
#include <sys/stat.h>
-#ifdef USE_DMALLOC
-#include <dmalloc.h>
-#endif
#if HAVE_DIRENT_H
#include <dirent.h>
#endif
@@ -63,6 +60,9 @@
#ifdef HAVE_IO_H
#include <io.h>
#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -83,13 +83,9 @@
/* Windows (including Visual Studio and MinGW but not Cygwin) */
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include "../cpio_windows.h"
#if !defined(__BORLANDC__)
#define strdup _strdup
#endif
-#define LOCALE_DE "deu"
-#else
-#define LOCALE_DE "de_DE.UTF-8"
#endif
/* Visual Studio */
@@ -97,13 +93,11 @@
#define snprintf sprintf_s
#endif
-/* Cygwin */
-#if defined(__CYGWIN__)
-/* Cygwin-1.7.x is lazy about populating nlinks, so don't
- * expect it to be accurate. */
-# define NLINKS_INACCURATE_FOR_DIRS
+#if defined(__BORLANDC__)
+#pragma warn -8068 /* Constant out of range in comparison. */
#endif
+/* Haiku OS and QNX */
#if defined(__HAIKU__) || defined(__QNXNTO__)
/* Haiku and QNX have typedefs in stdint.h (needed for int64_t) */
#include <stdint.h>
@@ -139,24 +133,24 @@
assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
/* Assert two strings are the same. Reports value of each one if not. */
#define assertEqualString(v1,v2) \
- assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
+ assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 0)
+#define assertEqualUTF8String(v1,v2) \
+ assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 1)
/* As above, but v1 and v2 are wchar_t * */
#define assertEqualWString(v1,v2) \
assertion_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
/* As above, but raw blocks of bytes. */
#define assertEqualMem(v1, v2, l) \
assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL)
-/* Assert two files are the same; allow printf-style expansion of second name.
- * See below for comments about variable arguments here...
- */
-#define assertEqualFile \
- assertion_setup(__FILE__, __LINE__);assertion_equal_file
-/* Assert that a file is empty; supports printf-style arguments. */
-#define assertEmptyFile \
- assertion_setup(__FILE__, __LINE__);assertion_empty_file
-/* Assert that a file is not empty; supports printf-style arguments. */
-#define assertNonEmptyFile \
- assertion_setup(__FILE__, __LINE__);assertion_non_empty_file
+/* Assert two files are the same. */
+#define assertEqualFile(f1, f2) \
+ assertion_equal_file(__FILE__, __LINE__, (f1), (f2))
+/* Assert that a file is empty. */
+#define assertEmptyFile(pathname) \
+ assertion_empty_file(__FILE__, __LINE__, (pathname))
+/* Assert that a file is not empty. */
+#define assertNonEmptyFile(pathname) \
+ assertion_non_empty_file(__FILE__, __LINE__, (pathname))
#define assertFileAtime(pathname, sec, nsec) \
assertion_file_atime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileAtimeRecent(pathname) \
@@ -166,14 +160,14 @@
#define assertFileBirthtimeRecent(pathname) \
assertion_file_birthtime_recent(__FILE__, __LINE__, pathname)
/* Assert that a file exists; supports printf-style arguments. */
-#define assertFileExists \
- assertion_setup(__FILE__, __LINE__);assertion_file_exists
-/* Assert that a file exists; supports printf-style arguments. */
-#define assertFileNotExists \
- assertion_setup(__FILE__, __LINE__);assertion_file_not_exists
-/* Assert that file contents match a string; supports printf-style arguments. */
-#define assertFileContents \
- assertion_setup(__FILE__, __LINE__);assertion_file_contents
+#define assertFileExists(pathname) \
+ assertion_file_exists(__FILE__, __LINE__, pathname)
+/* Assert that a file exists. */
+#define assertFileNotExists(pathname) \
+ assertion_file_not_exists(__FILE__, __LINE__, pathname)
+/* Assert that file contents match a string. */
+#define assertFileContents(data, data_size, pathname) \
+ assertion_file_contents(__FILE__, __LINE__, data, data_size, pathname)
#define assertFileMtime(pathname, sec, nsec) \
assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
#define assertFileMtimeRecent(pathname) \
@@ -182,8 +176,10 @@
assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks)
#define assertFileSize(pathname, size) \
assertion_file_size(__FILE__, __LINE__, pathname, size)
-#define assertTextFileContents \
- assertion_setup(__FILE__, __LINE__);assertion_text_file_contents
+#define assertTextFileContents(text, pathname) \
+ assertion_text_file_contents(__FILE__, __LINE__, text, pathname)
+#define assertFileContainsLinesAnyOrder(pathname, lines) \
+ assertion_file_contains_lines_any_order(__FILE__, __LINE__, pathname, lines)
#define assertIsDir(pathname, mode) \
assertion_is_dir(__FILE__, __LINE__, pathname, mode)
#define assertIsHardlink(path1, path2) \
@@ -205,6 +201,8 @@
assertion_make_symlink(__FILE__, __LINE__, newfile, linkto)
#define assertUmask(mask) \
assertion_umask(__FILE__, __LINE__, mask)
+#define assertUtimes(pathname, atime, atime_nsec, mtime, mtime_nsec) \
+ assertion_utimes(__FILE__, __LINE__, pathname, atime, atime_nsec, mtime, mtime_nsec)
/*
* This would be simple with C99 variadic macros, but I don't want to
@@ -213,28 +211,29 @@
* but effective.
*/
#define skipping \
- assertion_setup(__FILE__, __LINE__);test_skipping
+ skipping_setup(__FILE__, __LINE__);test_skipping
/* Function declarations. These are defined in test_utility.c. */
void failure(const char *fmt, ...);
int assertion_assert(const char *, int, int, const char *, void *);
int assertion_chdir(const char *, int, const char *);
-int assertion_empty_file(const char *, ...);
-int assertion_equal_file(const char *, const char *, ...);
+int assertion_empty_file(const char *, int, const char *);
+int assertion_equal_file(const char *, int, const char *, const char *);
int assertion_equal_int(const char *, int, long long, const char *, long long, const char *, void *);
int assertion_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *);
-int assertion_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *);
+int assertion_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *, int);
int assertion_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
int assertion_file_atime(const char *, int, const char *, long, long);
int assertion_file_atime_recent(const char *, int, const char *);
int assertion_file_birthtime(const char *, int, const char *, long, long);
int assertion_file_birthtime_recent(const char *, int, const char *);
-int assertion_file_contents(const void *, int, const char *, ...);
-int assertion_file_exists(const char *, ...);
+int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **);
+int assertion_file_contents(const char *, int, const void *, int, const char *);
+int assertion_file_exists(const char *, int, const char *);
int assertion_file_mtime(const char *, int, const char *, long, long);
int assertion_file_mtime_recent(const char *, int, const char *);
int assertion_file_nlinks(const char *, int, const char *, int);
-int assertion_file_not_exists(const char *, ...);
+int assertion_file_not_exists(const char *, int, const char *);
int assertion_file_size(const char *, int, const char *, long);
int assertion_is_dir(const char *, int, const char *, int);
int assertion_is_hardlink(const char *, int, const char *, const char *);
@@ -245,11 +244,12 @@ int assertion_make_dir(const char *, int, const char *, int);
int assertion_make_file(const char *, int, const char *, int, const char *);
int assertion_make_hardlink(const char *, int, const char *newpath, const char *);
int assertion_make_symlink(const char *, int, const char *newpath, const char *);
-int assertion_non_empty_file(const char *, ...);
-int assertion_text_file_contents(const char *buff, const char *f);
+int assertion_non_empty_file(const char *, int, const char *);
+int assertion_text_file_contents(const char *, int, const char *buff, const char *f);
int assertion_umask(const char *, int, int);
-void assertion_setup(const char *, int);
+int assertion_utimes(const char *, int, const char *, long, long, long, long );
+void skipping_setup(const char *, int);
void test_skipping(const char *fmt, ...);
/* Like sprintf, then system() */
@@ -267,6 +267,9 @@ int canGzip(void);
/* Return true if this platform can run the "gunzip" program. */
int canGunzip(void);
+/* Return true if the file has large i-node number(>0xffffffff). */
+int is_LargeInode(const char *);
+
/* Suck file into string allocated via malloc(). Call free() when done. */
/* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
char *slurpfile(size_t *, const char *fmt, ...);
@@ -274,6 +277,9 @@ char *slurpfile(size_t *, const char *fmt, ...);
/* Extracts named reference file to the current directory. */
void extract_reference_file(const char *);
+/* Path to working directory for current test */
+const char *testworkdir;
+
/*
* Special interfaces for program test harness.
*/
@@ -283,3 +289,7 @@ const char *testprogfile;
/* Name of exe to use in printf-formatted command strings. */
/* On Windows, this includes leading/trailing quotes. */
const char *testprog;
+
+#ifdef USE_DMALLOC
+#include <dmalloc.h>
+#endif
diff --git a/contrib/libarchive/cpio/test/test_0.c b/contrib/libarchive/cpio/test/test_0.c
index 75a1437fd70e..fa52def7eaf3 100644
--- a/contrib/libarchive/cpio/test/test_0.c
+++ b/contrib/libarchive/cpio/test/test_0.c
@@ -40,15 +40,23 @@ DEFINE_TEST(test_0)
struct stat st;
failure("File %s does not exist?!", testprogfile);
- if (!assertEqualInt(0, stat(testprogfile, &st)))
+ if (!assertEqualInt(0, stat(testprogfile, &st))) {
+ fprintf(stderr,
+ "\nFile %s does not exist; aborting test.\n\n",
+ testprog);
exit(1);
+ }
failure("%s is not executable?!", testprogfile);
- if (!assert((st.st_mode & 0111) != 0))
+ if (!assert((st.st_mode & 0111) != 0)) {
+ fprintf(stderr,
+ "\nFile %s not executable; aborting test.\n\n",
+ testprog);
exit(1);
+ }
/*
- * Try to succesfully run the program; this requires that
+ * Try to successfully run the program; this requires that
* we know some option that will succeed.
*/
if (0 == systemf("%s --version >" DEV_NULL, testprog)) {
diff --git a/contrib/libarchive/cpio/test/test_basic.c b/contrib/libarchive/cpio/test/test_basic.c
index 3a3fae820bc6..fa3fdb530da7 100644
--- a/contrib/libarchive/cpio/test/test_basic.c
+++ b/contrib/libarchive/cpio/test/test_basic.c
@@ -33,12 +33,15 @@ verify_files(const char *msg)
*/
/* Regular file with 2 links. */
+ failure(msg);
assertIsReg("file", 0644);
failure(msg);
assertFileSize("file", 10);
+ failure(msg);
assertFileNLinks("file", 2);
/* Another name for the same file. */
+ failure(msg);
assertIsHardlink("linkfile", "file");
/* Symlink */
@@ -46,8 +49,11 @@ verify_files(const char *msg)
assertIsSymlink("symlink", "file");
/* Another file with 1 link and different permissions. */
+ failure(msg);
assertIsReg("file2", 0777);
+ failure(msg);
assertFileSize("file2", 10);
+ failure(msg);
assertFileNLinks("file2", 1);
/* dir */
@@ -58,7 +64,7 @@ static void
basic_cpio(const char *target,
const char *pack_options,
const char *unpack_options,
- const char *se)
+ const char *se, const char *se2)
{
int r;
@@ -87,7 +93,7 @@ basic_cpio(const char *target,
/* Verify stderr. */
failure("Error invoking %s -i %s in dir %s", testprog, unpack_options, target);
- assertTextFileContents(se, "unpack.err");
+ assertTextFileContents(se2, "unpack.err");
verify_files(pack_options);
@@ -125,6 +131,7 @@ DEFINE_TEST(test_basic)
{
FILE *filelist;
const char *msg;
+ char result[1024];
assertUmask(0);
@@ -132,28 +139,56 @@ DEFINE_TEST(test_basic)
* Create an assortment of files on disk.
*/
filelist = fopen("filelist", "w");
+ memset(result, 0, sizeof(result));
/* File with 10 bytes content. */
assertMakeFile("file", 0644, "1234567890");
fprintf(filelist, "file\n");
+ if (is_LargeInode("file"))
+ strncat(result,
+ "bsdcpio: file: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result));
/* hardlink to above file. */
assertMakeHardlink("linkfile", "file");
fprintf(filelist, "linkfile\n");
+ if (is_LargeInode("linkfile"))
+ strncat(result,
+ "bsdcpio: linkfile: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result));
/* Symlink to above file. */
if (canSymlink()) {
assertMakeSymlink("symlink", "file");
fprintf(filelist, "symlink\n");
+ if (is_LargeInode("symlink"))
+ strncat(result,
+ "bsdcpio: symlink: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result));
}
/* Another file with different permissions. */
assertMakeFile("file2", 0777, "1234567890");
fprintf(filelist, "file2\n");
+ if (is_LargeInode("file2"))
+ strncat(result,
+ "bsdcpio: file2: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result));
/* Directory. */
assertMakeDir("dir", 0775);
fprintf(filelist, "dir\n");
+ if (is_LargeInode("dir"))
+ strncat(result,
+ "bsdcpio: dir: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result));
+ strncat(result, "2 blocks\n", sizeof(result) - strlen(result));
+
/* All done. */
fclose(filelist);
@@ -161,12 +196,12 @@ DEFINE_TEST(test_basic)
/* Archive/dearchive with a variety of options. */
msg = canSymlink() ? "2 blocks\n" : "1 block\n";
- basic_cpio("copy", "", "", msg);
- basic_cpio("copy_odc", "--format=odc", "", msg);
- basic_cpio("copy_newc", "-H newc", "", "2 blocks\n");
- basic_cpio("copy_cpio", "-H odc", "", msg);
+ basic_cpio("copy", "", "", msg, msg);
+ basic_cpio("copy_odc", "--format=odc", "", msg, msg);
+ basic_cpio("copy_newc", "-H newc", "", result, "2 blocks\n");
+ basic_cpio("copy_cpio", "-H odc", "", msg, msg);
msg = canSymlink() ? "9 blocks\n" : "8 blocks\n";
- basic_cpio("copy_ustar", "-H ustar", "", msg);
+ basic_cpio("copy_ustar", "-H ustar", "", msg, msg);
/* Copy in one step using -p */
passthrough("passthrough");
diff --git a/contrib/libarchive/cpio/test/test_format_newc.c b/contrib/libarchive/cpio/test/test_format_newc.c
index eb87c312066e..4ee901bc4e34 100644
--- a/contrib/libarchive/cpio/test/test_format_newc.c
+++ b/contrib/libarchive/cpio/test/test_format_newc.c
@@ -68,6 +68,16 @@ from_hex(const char *p, size_t l)
return (r);
}
+#if !defined(_WIN32) || defined(__CYGWIN__)
+static int
+nlinks(const char *p)
+{
+ struct stat st;
+ assertEqualInt(0, stat(p, &st));
+ return st.st_nlink;
+}
+#endif
+
DEFINE_TEST(test_format_newc)
{
FILE *list;
@@ -77,6 +87,7 @@ DEFINE_TEST(test_format_newc)
time_t t, t2, now;
char *p, *e;
size_t s, fs, ns;
+ char result[1024];
assertUmask(0);
@@ -111,6 +122,29 @@ DEFINE_TEST(test_format_newc)
assertMakeDir("dir", 0775);
fprintf(list, "dir\n");
+ /* Setup result message. */
+ memset(result, 0, sizeof(result));
+ if (is_LargeInode("file1"))
+ strncat(result,
+ "bsdcpio: file1: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result) -1);
+ if (canSymlink() && is_LargeInode("symlink"))
+ strncat(result,
+ "bsdcpio: symlink: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result) -1);
+ if (is_LargeInode("dir"))
+ strncat(result,
+ "bsdcpio: dir: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result) -1);
+ if (is_LargeInode("hardlink"))
+ strncat(result,
+ "bsdcpio: hardlink: large inode number truncated: "
+ "Numerical result out of range\n",
+ sizeof(result) - strlen(result) -1);
+
/* Record some facts about what we just created: */
now = time(NULL); /* They were all created w/in last two seconds. */
@@ -123,10 +157,11 @@ DEFINE_TEST(test_format_newc)
/* Verify that nothing went to stderr. */
if (canSymlink()) {
- assertTextFileContents("2 blocks\n", "newc.err");
+ strncat(result, "2 blocks\n", sizeof(result) - strlen(result));
} else {
- assertTextFileContents("1 block\n", "newc.err");
+ strncat(result, "1 block\n", sizeof(result) - strlen(result));
}
+ assertTextFileContents(result, "newc.err");
/* Verify that stdout is a well-formed cpio file in "newc" format. */
p = slurpfile(&s, "newc.out");
@@ -216,10 +251,10 @@ DEFINE_TEST(test_format_newc)
/* Mode: sgid bit sometimes propagates from parent dirs, ignore it. */
assertEqualInt(040775, from_hex(e + 14, 8) & ~02000);
#endif
- assertEqualInt(from_hex(e + 22, 8), uid); /* uid */
+ assertEqualInt(uid, from_hex(e + 22, 8)); /* uid */
assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */
-#ifndef NLINKS_INACCURATE_FOR_DIRS
- assertEqualMem(e + 38, "00000002", 8); /* nlink */
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ assertEqualInt(nlinks("dir"), from_hex(e + 38, 8)); /* nlinks */
#endif
t2 = from_hex(e + 46, 8); /* mtime */
failure("First entry created at t=0x%08x this entry created at t2=0x%08x", t, t2);
diff --git a/contrib/libarchive/cpio/test/test_option_0.c b/contrib/libarchive/cpio/test/test_option_0.c
new file mode 100644
index 000000000000..bc4aecd2afc2
--- /dev/null
+++ b/contrib/libarchive/cpio/test/test_option_0.c
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 2003-2010 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_option_0)
+{
+ FILE *filelist;
+ int r;
+
+ assertUmask(0);
+
+ /* Create a few files. */
+ assertMakeFile("file1", 0644, "1234567890");
+ assertMakeFile("file2", 0644, "1234567890");
+ assertMakeFile("file3", 0644, "1234567890");
+ assertMakeFile("file4", 0644, "1234567890");
+
+ /* Create a file list of filenames with varying end-of-line. */
+ filelist = fopen("filelist", "wb");
+ assertEqualInt(fwrite("file1\x0a", 1, 6, filelist), 6);
+ assertEqualInt(fwrite("file2\x0d", 1, 6, filelist), 6);
+ assertEqualInt(fwrite("file3\x0a\x0d", 1, 7, filelist), 7);
+ assertEqualInt(fwrite("file4", 1, 5, filelist), 5);
+ fclose(filelist);
+
+ /* Create a file list of null-delimited names. */
+ filelist = fopen("filelistNull", "wb");
+ assertEqualInt(fwrite("file1\0", 1, 6, filelist), 6);
+ assertEqualInt(fwrite("file2\0", 1, 6, filelist), 6);
+ assertEqualInt(fwrite("file3\0", 1, 6, filelist), 6);
+ assertEqualInt(fwrite("file4", 1, 5, filelist), 5);
+ fclose(filelist);
+
+ assertUmask(022);
+
+ /* Pack up using the file list with text line endings. */
+ r = systemf("%s -o < filelist > archive 2> stderr1.txt", testprog);
+ assertEqualInt(r, 0);
+
+ /* Extract into a new dir. */
+ assertMakeDir("copy", 0775);
+ assertChdir("copy");
+ r = systemf("%s -i < ../archive > stdout3.txt 2> stderr3.txt", testprog);
+ assertEqualInt(r, 0);
+
+ /* Verify the files. */
+ assertIsReg("file1", 0644);
+ assertIsReg("file2", 0644);
+ assertIsReg("file3", 0644);
+ assertIsReg("file4", 0644);
+
+ assertChdir("..");
+
+ /* Pack up using the file list with nulls. */
+ r = systemf("%s -o0 < filelistNull > archiveNull 2> stderr2.txt", testprog);
+ assertEqualInt(r, 0);
+
+ /* Extract into a new dir. */
+ assertMakeDir("copyNull", 0775);
+ assertChdir("copyNull");
+ r = systemf("%s -i < ../archiveNull > stdout4.txt 2> stderr4.txt", testprog);
+ assertEqualInt(r, 0);
+
+ /* Verify the files. */
+ assertIsReg("file1", 0644);
+ assertIsReg("file2", 0644);
+ assertIsReg("file3", 0644);
+ assertIsReg("file4", 0644);
+}
diff --git a/contrib/libarchive/cpio/test/test_option_c.c b/contrib/libarchive/cpio/test/test_option_c.c
index 63dcdbd53d46..a634be10ba7c 100644
--- a/contrib/libarchive/cpio/test/test_option_c.c
+++ b/contrib/libarchive/cpio/test/test_option_c.c
@@ -51,6 +51,16 @@ from_octal(const char *p, size_t l)
return (r);
}
+#if !defined(_WIN32) || defined(__CYGWIN__)
+static int
+nlinks(const char *p)
+{
+ struct stat st;
+ assertEqualInt(0, stat(p, &st));
+ return st.st_nlink;
+}
+#endif
+
DEFINE_TEST(test_option_c)
{
FILE *filelist;
@@ -181,17 +191,19 @@ DEFINE_TEST(test_option_c)
/* Group members bits and others bits do not work. */
assertEqualMem(e + 18, "040777", 6); /* Mode */
#else
- /* Accept 042775 to accomodate systems where sgid bit propagates. */
+ /* Accept 042775 to accommodate systems where sgid bit propagates. */
if (memcmp(e + 18, "042775", 6) != 0)
assertEqualMem(e + 18, "040775", 6); /* Mode */
#endif
- assertEqualInt(from_octal(e + 24, 6), uid); /* uid */
+ assertEqualInt(uid, from_octal(e + 24, 6)); /* uid */
/* Gid should be same as first entry. */
assert(is_octal(e + 30, 6)); /* gid */
assertEqualInt(gid, from_octal(e + 30, 6));
-#ifndef NLINKS_INACCURATE_FOR_DIRS
- assertEqualMem(e + 36, "000002", 6); /* Nlink */
+
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ assertEqualInt(nlinks("dir"), from_octal(e + 36, 6)); /* Nlink */
#endif
+
t = from_octal(e + 48, 11); /* mtime */
assert(t <= now); /* File wasn't created in future. */
assert(t >= now - 2); /* File was created w/in last 2 secs. */
diff --git a/contrib/libarchive/cpio/test/test_option_t.c b/contrib/libarchive/cpio/test/test_option_t.c
index 4427bb3a6cd7..6bcaee3c87ce 100644
--- a/contrib/libarchive/cpio/test/test_option_t.c
+++ b/contrib/libarchive/cpio/test/test_option_t.c
@@ -25,11 +25,17 @@
#include "test.h"
__FBSDID("$FreeBSD$");
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
DEFINE_TEST(test_option_t)
{
char *p;
int r;
+ time_t mtime;
+ char date[32];
+ char date2[32];
/* List reference archive, make sure the TOC is correct. */
extract_reference_file("test_option_t.cpio");
@@ -75,17 +81,20 @@ DEFINE_TEST(test_option_t)
/* Since -n uses numeric UID/GID, this part should be the
* same on every system. */
assertEqualMem(p, "-rw-r--r-- 1 1000 1000 0 ",42);
- /* Date varies depending on local timezone. */
- if (memcmp(p + 42, "Dec 31 1969", 12) == 0) {
- /* East of Greenwich we get Dec 31, 1969. */
- } else {
- /* West of Greenwich get Jan 1, 1970 */
- assertEqualMem(p + 42, "Jan ", 4);
- /* Some systems format "Jan 01", some "Jan 1" */
- assert(p[46] == ' ' || p[46] == '0');
- assertEqualMem(p + 47, "1 1970 ", 8);
- }
- assertEqualMem(p + 54, " file", 5);
+
+ /* Date varies depending on local timezone and locale. */
+ mtime = 1;
+#ifdef HAVE_LOCALE_H
+ setlocale(LC_ALL, "");
+#endif
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ strftime(date2, sizeof(date), "%b %d %Y", localtime(&mtime));
+ _snprintf(date, sizeof(date)-1, "%12s file", date2);
+#else
+ strftime(date2, sizeof(date), "%b %e %Y", localtime(&mtime));
+ snprintf(date, sizeof(date)-1, "%12s file", date2);
+#endif
+ assertEqualMem(p + 42, date, strlen(date));
free(p);
/* But "-n" without "-t" is an error. */
diff --git a/contrib/libarchive/cpio/test/test_option_u.c b/contrib/libarchive/cpio/test/test_option_u.c
index 08058aa45396..b377def020fb 100644
--- a/contrib/libarchive/cpio/test/test_option_u.c
+++ b/contrib/libarchive/cpio/test/test_option_u.c
@@ -41,7 +41,7 @@ DEFINE_TEST(test_option_u)
assertMakeFile("f", 0644, "a");
/* Copy the file to the "copy" dir. */
- r = systemf("echo f | %s -pd copy >copy.out 2>copy.err",
+ r = systemf("echo f| %s -pd copy >copy.out 2>copy.err",
testprog);
assertEqualInt(r, 0);
@@ -60,7 +60,7 @@ DEFINE_TEST(test_option_u)
assertEqualInt(0, utime("f", &times));
/* Copy the file to the "copy" dir. */
- r = systemf("echo f | %s -pd copy >copy.out 2>copy.err",
+ r = systemf("echo f| %s -pd copy >copy.out 2>copy.err",
testprog);
assertEqualInt(r, 0);
@@ -70,7 +70,7 @@ DEFINE_TEST(test_option_u)
assertEqualMem(p, "a", 1);
/* Copy the file to the "copy" dir with -u (force) */
- r = systemf("echo f | %s -pud copy >copy.out 2>copy.err",
+ r = systemf("echo f| %s -pud copy >copy.out 2>copy.err",
testprog);
assertEqualInt(r, 0);
diff --git a/contrib/libarchive/cpio/test/test_owner_parse.c b/contrib/libarchive/cpio/test/test_owner_parse.c
index d07724e0e776..a9f605398e36 100644
--- a/contrib/libarchive/cpio/test/test_owner_parse.c
+++ b/contrib/libarchive/cpio/test/test_owner_parse.c
@@ -30,9 +30,8 @@ __FBSDID("$FreeBSD$");
#if !defined(_WIN32)
#define ROOT "root"
-static int root_uids[] = { 0 };
-/* Solaris 9 root has gid 1 (other) */
-static int root_gids[] = { 0, 1 };
+static const int root_uids[] = { 0 };
+static const int root_gids[] = { 0, 1 };
#elif defined(__CYGWIN__)
/* On cygwin, the Administrator user most likely exists (unless
* it has been renamed or is in a non-English localization), but
@@ -43,13 +42,13 @@ static int root_gids[] = { 0, 1 };
* Use CreateWellKnownSID() and LookupAccountName()?
*/
#define ROOT "Administrator"
-static int root_uids[] = { 500 };
-static int root_gids[] = { 513, 545, 544 };
+static const int root_uids[] = { 500 };
+static const int root_gids[] = { 513, 545, 544 };
#endif
#if defined(ROOT)
static int
-int_in_list(int i, int *l, size_t n)
+int_in_list(int i, const int *l, size_t n)
{
while (n-- > 0)
if (*l++ == i)
diff --git a/contrib/libarchive/libarchive/archive.h b/contrib/libarchive/libarchive/archive.h
index bac93f01fd4d..8a85377d7e79 100644
--- a/contrib/libarchive/libarchive/archive.h
+++ b/contrib/libarchive/libarchive/archive.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2003-2010 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,6 +28,10 @@
#ifndef ARCHIVE_H_INCLUDED
#define ARCHIVE_H_INCLUDED
+#include <sys/stat.h>
+#include <stddef.h> /* for wchar_t */
+#include <stdio.h> /* For FILE * */
+
/*
* Note: archive.h is for use outside of libarchive; the configuration
* headers (config.h, archive_platform.h, etc.) are purely internal.
@@ -36,22 +40,15 @@
* platform macros.
*/
#if defined(__BORLANDC__) && __BORLANDC__ >= 0x560
-# define __LA_STDINT_H <stdint.h>
-#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__)
-# define __LA_STDINT_H <inttypes.h>
-#endif
-
-#include <sys/stat.h>
-#include <sys/types.h> /* Linux requires this for off_t */
-#ifdef __LA_STDINT_H
-# include __LA_STDINT_H /* int64_t, etc. */
+# include <stdint.h>
+#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__) && !defined(_SCO_DS)
+# include <inttypes.h>
#endif
-#include <stdio.h> /* For FILE * */
/* Get appropriate definitions of standard POSIX-style types. */
/* These should match the types used in 'struct stat' */
#if defined(_WIN32) && !defined(__CYGWIN__)
-#define __LA_INT64_T __int64
+# define __LA_INT64_T __int64
# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
# define __LA_SSIZE_T ssize_t
# elif defined(_WIN64)
@@ -67,11 +64,15 @@
# define __LA_GID_T short
# endif
#else
-#include <unistd.h> /* ssize_t, uid_t, and gid_t */
-#define __LA_INT64_T int64_t
-#define __LA_SSIZE_T ssize_t
-#define __LA_UID_T uid_t
-#define __LA_GID_T gid_t
+# include <unistd.h> /* ssize_t, uid_t, and gid_t */
+# if defined(_SCO_DS)
+# define __LA_INT64_T long long
+# else
+# define __LA_INT64_T int64_t
+# endif
+# define __LA_SSIZE_T ssize_t
+# define __LA_UID_T uid_t
+# define __LA_GID_T gid_t
#endif
/*
@@ -88,7 +89,7 @@
# endif
# else
# ifdef __GNUC__
-# define __LA_DECL __attribute__((dllimport)) extern
+# define __LA_DECL
# else
# define __LA_DECL __declspec(dllimport)
# endif
@@ -98,7 +99,7 @@
# define __LA_DECL
#endif
-#if defined(__GNUC__) && __GNUC__ >= 3
+#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__MINGW32__)
#define __LA_PRINTF(fmtarg, firstvararg) \
__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
#else
@@ -123,50 +124,18 @@ extern "C" {
* easy to compare versions at build time: for version a.b.c, the
* version number is printf("%d%03d%03d",a,b,c). For example, if you
* know your application requires version 2.12.108 or later, you can
- * assert that ARCHIVE_VERSION >= 2012108.
- *
- * This single-number format was introduced with libarchive 1.9.0 in
- * the libarchive 1.x family and libarchive 2.2.4 in the libarchive
- * 2.x family. The following may be useful if you really want to do
- * feature detection for earlier libarchive versions (which defined
- * ARCHIVE_API_VERSION and ARCHIVE_API_FEATURE instead):
- *
- * #ifndef ARCHIVE_VERSION_NUMBER
- * #define ARCHIVE_VERSION_NUMBER \
- * (ARCHIVE_API_VERSION * 1000000 + ARCHIVE_API_FEATURE * 1000)
- * #endif
+ * assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
-#define ARCHIVE_VERSION_NUMBER 2008005
+/* Note: Compiler will complain if this does not match archive_entry.h! */
+#define ARCHIVE_VERSION_NUMBER 3000003
__LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_STRING "libarchive 2.8.5"
+#define ARCHIVE_VERSION_STRING "libarchive 3.0.3"
__LA_DECL const char * archive_version_string(void);
-#if ARCHIVE_VERSION_NUMBER < 3000000
-/*
- * Deprecated; these are older names that will be removed in favor of
- * the simpler definitions above.
- */
-#define ARCHIVE_VERSION_STAMP ARCHIVE_VERSION_NUMBER
-__LA_DECL int archive_version_stamp(void);
-#define ARCHIVE_LIBRARY_VERSION ARCHIVE_VERSION_STRING
-__LA_DECL const char * archive_version(void);
-#define ARCHIVE_API_VERSION (ARCHIVE_VERSION_NUMBER / 1000000)
-__LA_DECL int archive_api_version(void);
-#define ARCHIVE_API_FEATURE ((ARCHIVE_VERSION_NUMBER / 1000) % 1000)
-__LA_DECL int archive_api_feature(void);
-#endif
-
-#if ARCHIVE_VERSION_NUMBER < 3000000
-/* This should never have been here in the first place. */
-/* Legacy of old tar assumptions, will be removed in libarchive 3.0. */
-#define ARCHIVE_BYTES_PER_RECORD 512
-#define ARCHIVE_DEFAULT_BYTES_PER_BLOCK 10240
-#endif
-
/* Declare our basic types. */
struct archive;
struct archive_entry;
@@ -210,48 +179,56 @@ struct archive_entry;
typedef __LA_SSIZE_T archive_read_callback(struct archive *,
void *_client_data, const void **_buffer);
-/* Skips at most request bytes from archive and returns the skipped amount */
-#if ARCHIVE_VERSION_NUMBER < 2000000
-/* Libarchive 1.0 used ssize_t for the return, which is only 32 bits
- * on most 32-bit platforms; not large enough. */
-typedef __LA_SSIZE_T archive_skip_callback(struct archive *,
- void *_client_data, size_t request);
-#elif ARCHIVE_VERSION_NUMBER < 3000000
-/* Libarchive 2.0 used off_t here, but that is a bad idea on Linux and a
- * few other platforms where off_t varies with build settings. */
-typedef off_t archive_skip_callback(struct archive *,
- void *_client_data, off_t request);
-#else
-/* Libarchive 3.0 uses int64_t here, which is actually guaranteed to be
- * 64 bits on every platform. */
+/* Skips at most request bytes from archive and returns the skipped amount.
+ * This may skip fewer bytes than requested; it may even skip zero bytes.
+ * If you do skip fewer bytes than requested, libarchive will invoke your
+ * read callback and discard data as necessary to make up the full skip.
+ */
typedef __LA_INT64_T archive_skip_callback(struct archive *,
void *_client_data, __LA_INT64_T request);
-#endif
+
+/* Seeks to specified location in the file and returns the position.
+ * Whence values are SEEK_SET, SEEK_CUR, SEEK_END from stdio.h.
+ * Return ARCHIVE_FATAL if the seek fails for any reason.
+ */
+typedef __LA_INT64_T archive_seek_callback(struct archive *,
+ void *_client_data, __LA_INT64_T offset, int whence);
/* Returns size actually written, zero on EOF, -1 on error. */
typedef __LA_SSIZE_T archive_write_callback(struct archive *,
void *_client_data,
const void *_buffer, size_t _length);
-#if ARCHIVE_VERSION_NUMBER < 3000000
-/* Open callback is actually never needed; remove it in libarchive 3.0. */
typedef int archive_open_callback(struct archive *, void *_client_data);
-#endif
typedef int archive_close_callback(struct archive *, void *_client_data);
/*
- * Codes for archive_compression.
+ * Codes to identify various stream filters.
*/
-#define ARCHIVE_COMPRESSION_NONE 0
-#define ARCHIVE_COMPRESSION_GZIP 1
-#define ARCHIVE_COMPRESSION_BZIP2 2
-#define ARCHIVE_COMPRESSION_COMPRESS 3
-#define ARCHIVE_COMPRESSION_PROGRAM 4
-#define ARCHIVE_COMPRESSION_LZMA 5
-#define ARCHIVE_COMPRESSION_XZ 6
-#define ARCHIVE_COMPRESSION_UU 7
-#define ARCHIVE_COMPRESSION_RPM 8
+#define ARCHIVE_FILTER_NONE 0
+#define ARCHIVE_FILTER_GZIP 1
+#define ARCHIVE_FILTER_BZIP2 2
+#define ARCHIVE_FILTER_COMPRESS 3
+#define ARCHIVE_FILTER_PROGRAM 4
+#define ARCHIVE_FILTER_LZMA 5
+#define ARCHIVE_FILTER_XZ 6
+#define ARCHIVE_FILTER_UU 7
+#define ARCHIVE_FILTER_RPM 8
+#define ARCHIVE_FILTER_LZIP 9
+
+#if ARCHIVE_VERSION_NUMBER < 4000000
+#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE
+#define ARCHIVE_COMPRESSION_GZIP ARCHIVE_FILTER_GZIP
+#define ARCHIVE_COMPRESSION_BZIP2 ARCHIVE_FILTER_BZIP2
+#define ARCHIVE_COMPRESSION_COMPRESS ARCHIVE_FILTER_COMPRESS
+#define ARCHIVE_COMPRESSION_PROGRAM ARCHIVE_FILTER_PROGRAM
+#define ARCHIVE_COMPRESSION_LZMA ARCHIVE_FILTER_LZMA
+#define ARCHIVE_COMPRESSION_XZ ARCHIVE_FILTER_XZ
+#define ARCHIVE_COMPRESSION_UU ARCHIVE_FILTER_UU
+#define ARCHIVE_COMPRESSION_RPM ARCHIVE_FILTER_RPM
+#define ARCHIVE_COMPRESSION_LZIP ARCHIVE_FILTER_LZIP
+#endif
/*
* Codes returned by archive_format.
@@ -265,7 +242,7 @@ typedef int archive_close_callback(struct archive *, void *_client_data);
* will change the format code to indicate the extended format that
* was used). In other cases, it's because different tools have
* modified the archive and so different parts of the archive
- * actually have slightly different formts. (Both tar and cpio store
+ * actually have slightly different formats. (Both tar and cpio store
* format codes in each entry, so it is quite possible for each
* entry to be in a different format.)
*/
@@ -276,6 +253,7 @@ typedef int archive_close_callback(struct archive *, void *_client_data);
#define ARCHIVE_FORMAT_CPIO_BIN_BE (ARCHIVE_FORMAT_CPIO | 3)
#define ARCHIVE_FORMAT_CPIO_SVR4_NOCRC (ARCHIVE_FORMAT_CPIO | 4)
#define ARCHIVE_FORMAT_CPIO_SVR4_CRC (ARCHIVE_FORMAT_CPIO | 5)
+#define ARCHIVE_FORMAT_CPIO_AFIO_LARGE (ARCHIVE_FORMAT_CPIO | 6)
#define ARCHIVE_FORMAT_SHAR 0x20000
#define ARCHIVE_FORMAT_SHAR_BASE (ARCHIVE_FORMAT_SHAR | 1)
#define ARCHIVE_FORMAT_SHAR_DUMP (ARCHIVE_FORMAT_SHAR | 2)
@@ -294,6 +272,10 @@ typedef int archive_close_callback(struct archive *, void *_client_data);
#define ARCHIVE_FORMAT_MTREE 0x80000
#define ARCHIVE_FORMAT_RAW 0x90000
#define ARCHIVE_FORMAT_XAR 0xA0000
+#define ARCHIVE_FORMAT_LHA 0xB0000
+#define ARCHIVE_FORMAT_CAB 0xC0000
+#define ARCHIVE_FORMAT_RAR 0xD0000
+#define ARCHIVE_FORMAT_7ZIP 0xE0000
/*-
* Basic outline for reading an archive:
@@ -316,40 +298,81 @@ __LA_DECL struct archive *archive_read_new(void);
* support_compression_bzip2(). The "all" functions provide the
* obvious shorthand.
*/
-__LA_DECL int archive_read_support_compression_all(struct archive *);
-__LA_DECL int archive_read_support_compression_bzip2(struct archive *);
-__LA_DECL int archive_read_support_compression_compress(struct archive *);
-__LA_DECL int archive_read_support_compression_gzip(struct archive *);
-__LA_DECL int archive_read_support_compression_lzma(struct archive *);
-__LA_DECL int archive_read_support_compression_none(struct archive *);
-__LA_DECL int archive_read_support_compression_program(struct archive *,
+
+#if ARCHIVE_VERSION_NUMBER < 4000000
+__LA_DECL int archive_read_support_compression_all(struct archive *);
+__LA_DECL int archive_read_support_compression_bzip2(struct archive *);
+__LA_DECL int archive_read_support_compression_compress(struct archive *);
+__LA_DECL int archive_read_support_compression_gzip(struct archive *);
+__LA_DECL int archive_read_support_compression_lzip(struct archive *);
+__LA_DECL int archive_read_support_compression_lzma(struct archive *);
+__LA_DECL int archive_read_support_compression_none(struct archive *);
+__LA_DECL int archive_read_support_compression_program(struct archive *,
+ const char *command);
+__LA_DECL int archive_read_support_compression_program_signature
+ (struct archive *, const char *,
+ const void * /* match */, size_t);
+
+__LA_DECL int archive_read_support_compression_rpm(struct archive *);
+__LA_DECL int archive_read_support_compression_uu(struct archive *);
+__LA_DECL int archive_read_support_compression_xz(struct archive *);
+#endif
+
+__LA_DECL int archive_read_support_filter_all(struct archive *);
+__LA_DECL int archive_read_support_filter_bzip2(struct archive *);
+__LA_DECL int archive_read_support_filter_compress(struct archive *);
+__LA_DECL int archive_read_support_filter_gzip(struct archive *);
+__LA_DECL int archive_read_support_filter_lzip(struct archive *);
+__LA_DECL int archive_read_support_filter_lzma(struct archive *);
+__LA_DECL int archive_read_support_filter_none(struct archive *);
+__LA_DECL int archive_read_support_filter_program(struct archive *,
const char *command);
-__LA_DECL int archive_read_support_compression_program_signature
- (struct archive *, const char *,
+__LA_DECL int archive_read_support_filter_program_signature
+ (struct archive *, const char *,
const void * /* match */, size_t);
-__LA_DECL int archive_read_support_compression_rpm(struct archive *);
-__LA_DECL int archive_read_support_compression_uu(struct archive *);
-__LA_DECL int archive_read_support_compression_xz(struct archive *);
-
-__LA_DECL int archive_read_support_format_all(struct archive *);
-__LA_DECL int archive_read_support_format_ar(struct archive *);
-__LA_DECL int archive_read_support_format_cpio(struct archive *);
-__LA_DECL int archive_read_support_format_empty(struct archive *);
-__LA_DECL int archive_read_support_format_gnutar(struct archive *);
-__LA_DECL int archive_read_support_format_iso9660(struct archive *);
-__LA_DECL int archive_read_support_format_mtree(struct archive *);
-__LA_DECL int archive_read_support_format_raw(struct archive *);
-__LA_DECL int archive_read_support_format_tar(struct archive *);
-__LA_DECL int archive_read_support_format_xar(struct archive *);
-__LA_DECL int archive_read_support_format_zip(struct archive *);
-
-
-/* Open the archive using callbacks for archive I/O. */
-__LA_DECL int archive_read_open(struct archive *, void *_client_data,
+__LA_DECL int archive_read_support_filter_rpm(struct archive *);
+__LA_DECL int archive_read_support_filter_uu(struct archive *);
+__LA_DECL int archive_read_support_filter_xz(struct archive *);
+
+__LA_DECL int archive_read_support_format_7zip(struct archive *);
+__LA_DECL int archive_read_support_format_all(struct archive *);
+__LA_DECL int archive_read_support_format_ar(struct archive *);
+__LA_DECL int archive_read_support_format_by_code(struct archive *, int);
+__LA_DECL int archive_read_support_format_cab(struct archive *);
+__LA_DECL int archive_read_support_format_cpio(struct archive *);
+__LA_DECL int archive_read_support_format_empty(struct archive *);
+__LA_DECL int archive_read_support_format_gnutar(struct archive *);
+__LA_DECL int archive_read_support_format_iso9660(struct archive *);
+__LA_DECL int archive_read_support_format_lha(struct archive *);
+__LA_DECL int archive_read_support_format_mtree(struct archive *);
+__LA_DECL int archive_read_support_format_rar(struct archive *);
+__LA_DECL int archive_read_support_format_raw(struct archive *);
+__LA_DECL int archive_read_support_format_tar(struct archive *);
+__LA_DECL int archive_read_support_format_xar(struct archive *);
+__LA_DECL int archive_read_support_format_zip(struct archive *);
+
+/* Set various callbacks. */
+__LA_DECL int archive_read_set_open_callback(struct archive *,
+ archive_open_callback *);
+__LA_DECL int archive_read_set_read_callback(struct archive *,
+ archive_read_callback *);
+__LA_DECL int archive_read_set_seek_callback(struct archive *,
+ archive_seek_callback *);
+__LA_DECL int archive_read_set_skip_callback(struct archive *,
+ archive_skip_callback *);
+__LA_DECL int archive_read_set_close_callback(struct archive *,
+ archive_close_callback *);
+/* The callback data is provided to all of the callbacks above. */
+__LA_DECL int archive_read_set_callback_data(struct archive *, void *);
+/* Opening freezes the callbacks. */
+__LA_DECL int archive_read_open1(struct archive *);
+
+/* Convenience wrappers around the above. */
+__LA_DECL int archive_read_open(struct archive *, void *_client_data,
archive_open_callback *, archive_read_callback *,
archive_close_callback *);
-__LA_DECL int archive_read_open2(struct archive *, void *_client_data,
+__LA_DECL int archive_read_open2(struct archive *, void *_client_data,
archive_open_callback *, archive_read_callback *,
archive_skip_callback *, archive_close_callback *);
@@ -359,30 +382,32 @@ __LA_DECL int archive_read_open2(struct archive *, void *_client_data,
* accept a block size handle tape blocking correctly.
*/
/* Use this if you know the filename. Note: NULL indicates stdin. */
-__LA_DECL int archive_read_open_filename(struct archive *,
+__LA_DECL int archive_read_open_filename(struct archive *,
const char *_filename, size_t _block_size);
+__LA_DECL int archive_read_open_filename_w(struct archive *,
+ const wchar_t *_filename, size_t _block_size);
/* archive_read_open_file() is a deprecated synonym for ..._open_filename(). */
-__LA_DECL int archive_read_open_file(struct archive *,
+__LA_DECL int archive_read_open_file(struct archive *,
const char *_filename, size_t _block_size);
/* Read an archive that's stored in memory. */
-__LA_DECL int archive_read_open_memory(struct archive *,
+__LA_DECL int archive_read_open_memory(struct archive *,
void * buff, size_t size);
/* A more involved version that is only used for internal testing. */
-__LA_DECL int archive_read_open_memory2(struct archive *a, void *buff,
+__LA_DECL int archive_read_open_memory2(struct archive *a, void *buff,
size_t size, size_t read_size);
/* Read an archive that's already open, using the file descriptor. */
-__LA_DECL int archive_read_open_fd(struct archive *, int _fd,
+__LA_DECL int archive_read_open_fd(struct archive *, int _fd,
size_t _block_size);
/* Read an archive that's already open, using a FILE *. */
/* Note: DO NOT use this with tape drives. */
-__LA_DECL int archive_read_open_FILE(struct archive *, FILE *_file);
+__LA_DECL int archive_read_open_FILE(struct archive *, FILE *_file);
/* Parses and returns next entry header. */
-__LA_DECL int archive_read_next_header(struct archive *,
+__LA_DECL int archive_read_next_header(struct archive *,
struct archive_entry **);
/* Parses and returns next entry header using the archive_entry passed in */
-__LA_DECL int archive_read_next_header2(struct archive *,
+__LA_DECL int archive_read_next_header2(struct archive *,
struct archive_entry *);
/*
@@ -401,14 +426,8 @@ __LA_DECL __LA_SSIZE_T archive_read_data(struct archive *,
* the desired size of the block. The API does guarantee that offsets will
* be strictly increasing and that returned blocks will not overlap.
*/
-#if ARCHIVE_VERSION_NUMBER < 3000000
-__LA_DECL int archive_read_data_block(struct archive *a,
- const void **buff, size_t *size, off_t *offset);
-#else
-__LA_DECL int archive_read_data_block(struct archive *a,
- const void **buff, size_t *size,
- __LA_INT64_T *offset);
-#endif
+__LA_DECL int archive_read_data_block(struct archive *a,
+ const void **buff, size_t *size, __LA_INT64_T *offset);
/*-
* Some convenience functions that are built on archive_read_data:
@@ -416,23 +435,27 @@ __LA_DECL int archive_read_data_block(struct archive *a,
* 'into_buffer': writes data into memory buffer that you provide
* 'into_fd': writes data to specified filedes
*/
-__LA_DECL int archive_read_data_skip(struct archive *);
-__LA_DECL int archive_read_data_into_buffer(struct archive *,
- void *buffer, __LA_SSIZE_T len);
-__LA_DECL int archive_read_data_into_fd(struct archive *, int fd);
+__LA_DECL int archive_read_data_skip(struct archive *);
+__LA_DECL int archive_read_data_into_fd(struct archive *, int fd);
/*
* Set read options.
*/
-/* Apply option string to the format only. */
-__LA_DECL int archive_read_set_format_options(struct archive *_a,
- const char *s);
-/* Apply option string to the filter only. */
-__LA_DECL int archive_read_set_filter_options(struct archive *_a,
- const char *s);
+/* Apply option to the format only. */
+__LA_DECL int archive_read_set_format_option(struct archive *_a,
+ const char *m, const char *o,
+ const char *v);
+/* Apply option to the filter only. */
+__LA_DECL int archive_read_set_filter_option(struct archive *_a,
+ const char *m, const char *o,
+ const char *v);
+/* Apply option to both the format and the filter. */
+__LA_DECL int archive_read_set_option(struct archive *_a,
+ const char *m, const char *o,
+ const char *v);
/* Apply option string to both the format and the filter. */
-__LA_DECL int archive_read_set_options(struct archive *_a,
- const char *s);
+__LA_DECL int archive_read_set_options(struct archive *_a,
+ const char *opts);
/*-
* Convenience function to recreate the current entry (whose header
@@ -477,10 +500,13 @@ __LA_DECL int archive_read_set_options(struct archive *_a,
#define ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER (0x0800)
/* Detect blocks of 0 and write holes instead. */
#define ARCHIVE_EXTRACT_SPARSE (0x1000)
+/* Default: Do not restore Mac extended metadata. */
+/* This has no effect except on Mac OS. */
+#define ARCHIVE_EXTRACT_MAC_METADATA (0x2000)
-__LA_DECL int archive_read_extract(struct archive *, struct archive_entry *,
+__LA_DECL int archive_read_extract(struct archive *, struct archive_entry *,
int flags);
-__LA_DECL int archive_read_extract2(struct archive *, struct archive_entry *,
+__LA_DECL int archive_read_extract2(struct archive *, struct archive_entry *,
struct archive * /* dest */);
__LA_DECL void archive_read_extract_set_progress_callback(struct archive *,
void (*_progress_func)(void *), void *_user_data);
@@ -488,7 +514,7 @@ __LA_DECL void archive_read_extract_set_progress_callback(struct archive *,
/* Record the dev/ino of a file that will not be written. This is
* generally set to the dev/ino of the archive being read. */
__LA_DECL void archive_read_extract_set_skip_file(struct archive *,
- dev_t, ino_t);
+ __LA_INT64_T, __LA_INT64_T);
/* Close the file and release most resources. */
__LA_DECL int archive_read_close(struct archive *);
@@ -502,7 +528,7 @@ __LA_DECL int archive_read_finish(struct archive *);
/*-
* To create an archive:
- * 1) Ask archive_write_new for a archive writer object.
+ * 1) Ask archive_write_new for an archive writer object.
* 2) Set any global properties. In particular, you should set
* the compression and format to use.
* 3) Call archive_write_open to open the file (most people
@@ -516,85 +542,93 @@ __LA_DECL int archive_read_finish(struct archive *);
* 6) archive_write_free to cleanup the writer and release resources
*/
__LA_DECL struct archive *archive_write_new(void);
-__LA_DECL int archive_write_set_bytes_per_block(struct archive *,
+__LA_DECL int archive_write_set_bytes_per_block(struct archive *,
int bytes_per_block);
-__LA_DECL int archive_write_get_bytes_per_block(struct archive *);
+__LA_DECL int archive_write_get_bytes_per_block(struct archive *);
/* XXX This is badly misnamed; suggestions appreciated. XXX */
-__LA_DECL int archive_write_set_bytes_in_last_block(struct archive *,
+__LA_DECL int archive_write_set_bytes_in_last_block(struct archive *,
int bytes_in_last_block);
-__LA_DECL int archive_write_get_bytes_in_last_block(struct archive *);
+__LA_DECL int archive_write_get_bytes_in_last_block(struct archive *);
/* The dev/ino of a file that won't be archived. This is used
* to avoid recursively adding an archive to itself. */
-__LA_DECL int archive_write_set_skip_file(struct archive *, dev_t, ino_t);
-
-__LA_DECL int archive_write_set_compression_bzip2(struct archive *);
-__LA_DECL int archive_write_set_compression_compress(struct archive *);
-__LA_DECL int archive_write_set_compression_gzip(struct archive *);
-__LA_DECL int archive_write_set_compression_lzma(struct archive *);
-__LA_DECL int archive_write_set_compression_none(struct archive *);
-__LA_DECL int archive_write_set_compression_program(struct archive *,
+__LA_DECL int archive_write_set_skip_file(struct archive *,
+ __LA_INT64_T, __LA_INT64_T);
+
+#if ARCHIVE_VERSION_NUMBER < 4000000
+__LA_DECL int archive_write_set_compression_bzip2(struct archive *);
+__LA_DECL int archive_write_set_compression_compress(struct archive *);
+__LA_DECL int archive_write_set_compression_gzip(struct archive *);
+__LA_DECL int archive_write_set_compression_lzip(struct archive *);
+__LA_DECL int archive_write_set_compression_lzma(struct archive *);
+__LA_DECL int archive_write_set_compression_none(struct archive *);
+__LA_DECL int archive_write_set_compression_program(struct archive *,
+ const char *cmd);
+__LA_DECL int archive_write_set_compression_xz(struct archive *);
+#endif
+
+__LA_DECL int archive_write_add_filter_bzip2(struct archive *);
+__LA_DECL int archive_write_add_filter_compress(struct archive *);
+__LA_DECL int archive_write_add_filter_gzip(struct archive *);
+__LA_DECL int archive_write_add_filter_lzip(struct archive *);
+__LA_DECL int archive_write_add_filter_lzma(struct archive *);
+__LA_DECL int archive_write_add_filter_none(struct archive *);
+__LA_DECL int archive_write_add_filter_program(struct archive *,
const char *cmd);
-__LA_DECL int archive_write_set_compression_xz(struct archive *);
+__LA_DECL int archive_write_add_filter_xz(struct archive *);
+
+
/* A convenience function to set the format based on the code or name. */
-__LA_DECL int archive_write_set_format(struct archive *, int format_code);
-__LA_DECL int archive_write_set_format_by_name(struct archive *,
+__LA_DECL int archive_write_set_format(struct archive *, int format_code);
+__LA_DECL int archive_write_set_format_by_name(struct archive *,
const char *name);
/* To minimize link pollution, use one or more of the following. */
-__LA_DECL int archive_write_set_format_ar_bsd(struct archive *);
-__LA_DECL int archive_write_set_format_ar_svr4(struct archive *);
-__LA_DECL int archive_write_set_format_cpio(struct archive *);
-__LA_DECL int archive_write_set_format_cpio_newc(struct archive *);
-__LA_DECL int archive_write_set_format_mtree(struct archive *);
+__LA_DECL int archive_write_set_format_7zip(struct archive *);
+__LA_DECL int archive_write_set_format_ar_bsd(struct archive *);
+__LA_DECL int archive_write_set_format_ar_svr4(struct archive *);
+__LA_DECL int archive_write_set_format_cpio(struct archive *);
+__LA_DECL int archive_write_set_format_cpio_newc(struct archive *);
+__LA_DECL int archive_write_set_format_gnutar(struct archive *);
+__LA_DECL int archive_write_set_format_iso9660(struct archive *);
+__LA_DECL int archive_write_set_format_mtree(struct archive *);
/* TODO: int archive_write_set_format_old_tar(struct archive *); */
-__LA_DECL int archive_write_set_format_pax(struct archive *);
-__LA_DECL int archive_write_set_format_pax_restricted(struct archive *);
-__LA_DECL int archive_write_set_format_shar(struct archive *);
-__LA_DECL int archive_write_set_format_shar_dump(struct archive *);
-__LA_DECL int archive_write_set_format_ustar(struct archive *);
-__LA_DECL int archive_write_set_format_zip(struct archive *);
-__LA_DECL int archive_write_open(struct archive *, void *,
+__LA_DECL int archive_write_set_format_pax(struct archive *);
+__LA_DECL int archive_write_set_format_pax_restricted(struct archive *);
+__LA_DECL int archive_write_set_format_shar(struct archive *);
+__LA_DECL int archive_write_set_format_shar_dump(struct archive *);
+__LA_DECL int archive_write_set_format_ustar(struct archive *);
+__LA_DECL int archive_write_set_format_xar(struct archive *);
+__LA_DECL int archive_write_set_format_zip(struct archive *);
+__LA_DECL int archive_write_open(struct archive *, void *,
archive_open_callback *, archive_write_callback *,
archive_close_callback *);
-__LA_DECL int archive_write_open_fd(struct archive *, int _fd);
-__LA_DECL int archive_write_open_filename(struct archive *, const char *_file);
+__LA_DECL int archive_write_open_fd(struct archive *, int _fd);
+__LA_DECL int archive_write_open_filename(struct archive *, const char *_file);
+__LA_DECL int archive_write_open_filename_w(struct archive *,
+ const wchar_t *_file);
/* A deprecated synonym for archive_write_open_filename() */
-__LA_DECL int archive_write_open_file(struct archive *, const char *_file);
-__LA_DECL int archive_write_open_FILE(struct archive *, FILE *);
+__LA_DECL int archive_write_open_file(struct archive *, const char *_file);
+__LA_DECL int archive_write_open_FILE(struct archive *, FILE *);
/* _buffSize is the size of the buffer, _used refers to a variable that
* will be updated after each write into the buffer. */
-__LA_DECL int archive_write_open_memory(struct archive *,
+__LA_DECL int archive_write_open_memory(struct archive *,
void *_buffer, size_t _buffSize, size_t *_used);
/*
* Note that the library will truncate writes beyond the size provided
* to archive_write_header or pad if the provided data is short.
*/
-__LA_DECL int archive_write_header(struct archive *,
+__LA_DECL int archive_write_header(struct archive *,
struct archive_entry *);
-#if ARCHIVE_VERSION_NUMBER < 2000000
-/* This was erroneously declared to return "int" in libarchive 1.x. */
-__LA_DECL int archive_write_data(struct archive *,
- const void *, size_t);
-#else
-/* Libarchive 2.0 and later return ssize_t here. */
-__LA_DECL __LA_SSIZE_T archive_write_data(struct archive *,
+__LA_DECL __LA_SSIZE_T archive_write_data(struct archive *,
const void *, size_t);
-#endif
-#if ARCHIVE_VERSION_NUMBER < 3000000
-/* Libarchive 1.x and 2.x use off_t for the argument, but that's not
- * stable on Linux. */
-__LA_DECL __LA_SSIZE_T archive_write_data_block(struct archive *,
- const void *, size_t, off_t);
-#else
-/* Libarchive 3.0 uses explicit int64_t to ensure consistent 64-bit support. */
+/* This interface is currently only available for archive_write_disk handles. */
__LA_DECL __LA_SSIZE_T archive_write_data_block(struct archive *,
const void *, size_t, __LA_INT64_T);
-#endif
+
__LA_DECL int archive_write_finish_entry(struct archive *);
__LA_DECL int archive_write_close(struct archive *);
-
/* This can fail if the archive wasn't already closed, in which case
* archive_write_free() will implicitly call archive_write_close(). */
__LA_DECL int archive_write_free(struct archive *);
@@ -606,16 +640,21 @@ __LA_DECL int archive_write_finish(struct archive *);
/*
* Set write options.
*/
-/* Apply option string to the format only. */
-__LA_DECL int archive_write_set_format_options(struct archive *_a,
- const char *s);
-/* Apply option string to the compressor only. */
-__LA_DECL int archive_write_set_compressor_options(struct archive *_a,
- const char *s);
-/* Apply option string to both the format and the compressor. */
-__LA_DECL int archive_write_set_options(struct archive *_a,
- const char *s);
-
+/* Apply option to the format only. */
+__LA_DECL int archive_write_set_format_option(struct archive *_a,
+ const char *m, const char *o,
+ const char *v);
+/* Apply option to the filter only. */
+__LA_DECL int archive_write_set_filter_option(struct archive *_a,
+ const char *m, const char *o,
+ const char *v);
+/* Apply option to both the format and the filter. */
+__LA_DECL int archive_write_set_option(struct archive *_a,
+ const char *m, const char *o,
+ const char *v);
+/* Apply option string to both the format and the filter. */
+__LA_DECL int archive_write_set_options(struct archive *_a,
+ const char *opts);
/*-
* ARCHIVE_WRITE_DISK API
@@ -635,8 +674,8 @@ __LA_DECL int archive_write_set_options(struct archive *_a,
*/
__LA_DECL struct archive *archive_write_disk_new(void);
/* This file will not be overwritten. */
-__LA_DECL int archive_write_disk_set_skip_file(struct archive *,
- dev_t, ino_t);
+__LA_DECL int archive_write_disk_set_skip_file(struct archive *,
+ __LA_INT64_T, __LA_INT64_T);
/* Set flags to control how the next item gets created.
* This accepts a bitmask of ARCHIVE_EXTRACT_XXX flags defined above. */
__LA_DECL int archive_write_disk_set_options(struct archive *,
@@ -664,14 +703,16 @@ __LA_DECL int archive_write_disk_set_standard_lookup(struct archive *);
* your needs, you can write your own and register them. Be sure to
* include a cleanup function if you have allocated private data.
*/
-__LA_DECL int archive_write_disk_set_group_lookup(struct archive *,
- void * /* private_data */,
- __LA_GID_T (*)(void *, const char *, __LA_GID_T),
- void (* /* cleanup */)(void *));
-__LA_DECL int archive_write_disk_set_user_lookup(struct archive *,
- void * /* private_data */,
- __LA_UID_T (*)(void *, const char *, __LA_UID_T),
- void (* /* cleanup */)(void *));
+__LA_DECL int archive_write_disk_set_group_lookup(struct archive *,
+ void * /* private_data */,
+ __LA_INT64_T (*)(void *, const char *, __LA_INT64_T),
+ void (* /* cleanup */)(void *));
+__LA_DECL int archive_write_disk_set_user_lookup(struct archive *,
+ void * /* private_data */,
+ __LA_INT64_T (*)(void *, const char *, __LA_INT64_T),
+ void (* /* cleanup */)(void *));
+__LA_DECL __LA_INT64_T archive_write_disk_gid(struct archive *, const char *, __LA_INT64_T);
+__LA_DECL __LA_INT64_T archive_write_disk_uid(struct archive *, const char *, __LA_INT64_T);
/*
* ARCHIVE_READ_DISK API
@@ -692,32 +733,64 @@ __LA_DECL int archive_read_disk_entry_from_file(struct archive *,
struct archive_entry *, int /* fd */, const struct stat *);
/* Look up gname for gid or uname for uid. */
/* Default implementations are very, very stupid. */
-__LA_DECL const char *archive_read_disk_gname(struct archive *, __LA_GID_T);
-__LA_DECL const char *archive_read_disk_uname(struct archive *, __LA_UID_T);
+__LA_DECL const char *archive_read_disk_gname(struct archive *, __LA_INT64_T);
+__LA_DECL const char *archive_read_disk_uname(struct archive *, __LA_INT64_T);
/* "Standard" implementation uses getpwuid_r, getgrgid_r and caches the
* results for performance. */
__LA_DECL int archive_read_disk_set_standard_lookup(struct archive *);
/* You can install your own lookups if you like. */
__LA_DECL int archive_read_disk_set_gname_lookup(struct archive *,
void * /* private_data */,
- const char *(* /* lookup_fn */)(void *, __LA_GID_T),
+ const char *(* /* lookup_fn */)(void *, __LA_INT64_T),
void (* /* cleanup_fn */)(void *));
__LA_DECL int archive_read_disk_set_uname_lookup(struct archive *,
void * /* private_data */,
- const char *(* /* lookup_fn */)(void *, __LA_UID_T),
+ const char *(* /* lookup_fn */)(void *, __LA_INT64_T),
void (* /* cleanup_fn */)(void *));
+/* Start traversal. */
+__LA_DECL int archive_read_disk_open(struct archive *, const char *);
+__LA_DECL int archive_read_disk_open_w(struct archive *, const wchar_t *);
+/*
+ * Request that current entry be visited. If you invoke it on every
+ * directory, you'll get a physical traversal. This is ignored if the
+ * current entry isn't a directory or a link to a directory. So, if
+ * you invoke this on every returned path, you'll get a full logical
+ * traversal.
+ */
+__LA_DECL int archive_read_disk_descend(struct archive *);
+__LA_DECL int archive_read_disk_current_filesystem(struct archive *);
+__LA_DECL int archive_read_disk_current_filesystem_is_synthetic(struct archive *);
+__LA_DECL int archive_read_disk_current_filesystem_is_remote(struct archive *);
+/* Request that the access time of the entry visited by travesal be restored. */
+__LA_DECL int archive_read_disk_set_atime_restored(struct archive *);
/*
* Accessor functions to read/set various information in
* the struct archive object:
*/
-/* Bytes written after compression or read before decompression. */
+
+/* Number of filters in the current filter pipeline. */
+/* Filter #0 is the one closest to the format, -1 is a synonym for the
+ * last filter, which is always the pseudo-filter that wraps the
+ * client callbacks. */
+__LA_DECL int archive_filter_count(struct archive *);
+__LA_DECL __LA_INT64_T archive_filter_bytes(struct archive *, int);
+__LA_DECL int archive_filter_code(struct archive *, int);
+__LA_DECL const char * archive_filter_name(struct archive *, int);
+
+#if ARCHIVE_VERSION_NUMBER < 4000000
+/* These don't properly handle multiple filters, so are deprecated and
+ * will eventually be removed. */
+/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, -1); */
__LA_DECL __LA_INT64_T archive_position_compressed(struct archive *);
-/* Bytes written to compressor or read from decompressor. */
+/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, 0); */
__LA_DECL __LA_INT64_T archive_position_uncompressed(struct archive *);
-
+/* As of libarchive 3.0, this is an alias for archive_filter_name(a, 0); */
__LA_DECL const char *archive_compression_name(struct archive *);
+/* As of libarchive 3.0, this is an alias for archive_filter_code(a, 0); */
__LA_DECL int archive_compression(struct archive *);
+#endif
+
__LA_DECL int archive_errno(struct archive *);
__LA_DECL const char *archive_error_string(struct archive *);
__LA_DECL const char *archive_format_name(struct archive *);
diff --git a/contrib/libarchive/libarchive/archive_acl.c b/contrib/libarchive/libarchive/archive_acl.c
new file mode 100644
index 000000000000..fbf029894436
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_acl.c
@@ -0,0 +1,1267 @@
+/*-
+ * Copyright (c) 2003-2010 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_WCHAR_H
+#include <wchar.h>
+#endif
+
+#include "archive_acl_private.h"
+#include "archive_entry.h"
+#include "archive_private.h"
+
+#undef max
+#define max(a, b) ((a)>(b)?(a):(b))
+
+#ifndef HAVE_WMEMCMP
+/* Good enough for simple equality testing, but not for sorting. */
+#define wmemcmp(a,b,i) memcmp((a), (b), (i) * sizeof(wchar_t))
+#endif
+
+static int acl_special(struct archive_acl *acl,
+ int type, int permset, int tag);
+static struct archive_acl_entry *acl_new_entry(struct archive_acl *acl,
+ int type, int permset, int tag, int id);
+static int archive_acl_add_entry_len_l(struct archive_acl *acl,
+ int type, int permset, int tag, int id, const char *name,
+ size_t len, struct archive_string_conv *sc);
+static int isint_w(const wchar_t *start, const wchar_t *end, int *result);
+static int ismode_w(const wchar_t *start, const wchar_t *end, int *result);
+static void next_field_w(const wchar_t **wp, const wchar_t **start,
+ const wchar_t **end, wchar_t *sep);
+static int prefix_w(const wchar_t *start, const wchar_t *end,
+ const wchar_t *test);
+static void append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
+ const wchar_t *wname, int perm, int id);
+static void append_id_w(wchar_t **wp, int id);
+static int isint(const char *start, const char *end, int *result);
+static int ismode(const char *start, const char *end, int *result);
+static void next_field(const char **p, const char **start,
+ const char **end, char *sep);
+static int prefix_c(const char *start, const char *end,
+ const char *test);
+static void append_entry(char **p, const char *prefix, int tag,
+ const char *name, int perm, int id);
+static void append_id(char **p, int id);
+
+void
+archive_acl_clear(struct archive_acl *acl)
+{
+ struct archive_acl_entry *ap;
+
+ while (acl->acl_head != NULL) {
+ ap = acl->acl_head->next;
+ archive_mstring_clean(&acl->acl_head->name);
+ free(acl->acl_head);
+ acl->acl_head = ap;
+ }
+ if (acl->acl_text_w != NULL) {
+ free(acl->acl_text_w);
+ acl->acl_text_w = NULL;
+ }
+ if (acl->acl_text != NULL) {
+ free(acl->acl_text);
+ acl->acl_text = NULL;
+ }
+ acl->acl_p = NULL;
+ acl->acl_state = 0; /* Not counting. */
+}
+
+void
+archive_acl_copy(struct archive_acl *dest, struct archive_acl *src)
+{
+ struct archive_acl_entry *ap, *ap2;
+
+ archive_acl_clear(dest);
+
+ dest->mode = src->mode;
+ ap = src->acl_head;
+ while (ap != NULL) {
+ ap2 = acl_new_entry(dest,
+ ap->type, ap->permset, ap->tag, ap->id);
+ if (ap2 != NULL)
+ archive_mstring_copy(&ap2->name, &ap->name);
+ ap = ap->next;
+ }
+}
+
+int
+archive_acl_add_entry(struct archive_acl *acl,
+ int type, int permset, int tag, int id, const char *name)
+{
+ struct archive_acl_entry *ap;
+
+ if (acl_special(acl, type, permset, tag) == 0)
+ return ARCHIVE_OK;
+ ap = acl_new_entry(acl, type, permset, tag, id);
+ if (ap == NULL) {
+ /* XXX Error XXX */
+ return ARCHIVE_FAILED;
+ }
+ if (name != NULL && *name != '\0')
+ archive_mstring_copy_mbs(&ap->name, name);
+ else
+ archive_mstring_clean(&ap->name);
+ return ARCHIVE_OK;
+}
+
+int
+archive_acl_add_entry_w_len(struct archive_acl *acl,
+ int type, int permset, int tag, int id, const wchar_t *name, size_t len)
+{
+ struct archive_acl_entry *ap;
+
+ if (acl_special(acl, type, permset, tag) == 0)
+ return ARCHIVE_OK;
+ ap = acl_new_entry(acl, type, permset, tag, id);
+ if (ap == NULL) {
+ /* XXX Error XXX */
+ return ARCHIVE_FAILED;
+ }
+ if (name != NULL && *name != L'\0' && len > 0)
+ archive_mstring_copy_wcs_len(&ap->name, name, len);
+ else
+ archive_mstring_clean(&ap->name);
+ return ARCHIVE_OK;
+}
+
+static int
+archive_acl_add_entry_len_l(struct archive_acl *acl,
+ int type, int permset, int tag, int id, const char *name, size_t len,
+ struct archive_string_conv *sc)
+{
+ struct archive_acl_entry *ap;
+ int r;
+
+ if (acl_special(acl, type, permset, tag) == 0)
+ return ARCHIVE_OK;
+ ap = acl_new_entry(acl, type, permset, tag, id);
+ if (ap == NULL) {
+ /* XXX Error XXX */
+ return ARCHIVE_FAILED;
+ }
+ if (name != NULL && *name != '\0' && len > 0) {
+ r = archive_mstring_copy_mbs_len_l(&ap->name, name, len, sc);
+ } else {
+ r = 0;
+ archive_mstring_clean(&ap->name);
+ }
+ if (r == 0)
+ return (ARCHIVE_OK);
+ else if (errno == ENOMEM)
+ return (ARCHIVE_FATAL);
+ else
+ return (ARCHIVE_WARN);
+}
+
+/*
+ * If this ACL entry is part of the standard POSIX permissions set,
+ * store the permissions in the stat structure and return zero.
+ */
+static int
+acl_special(struct archive_acl *acl, int type, int permset, int tag)
+{
+ if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS
+ && ((permset & ~007) == 0)) {
+ switch (tag) {
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
+ acl->mode &= ~0700;
+ acl->mode |= (permset & 7) << 6;
+ return (0);
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+ acl->mode &= ~0070;
+ acl->mode |= (permset & 7) << 3;
+ return (0);
+ case ARCHIVE_ENTRY_ACL_OTHER:
+ acl->mode &= ~0007;
+ acl->mode |= permset & 7;
+ return (0);
+ }
+ }
+ return (1);
+}
+
+/*
+ * Allocate and populate a new ACL entry with everything but the
+ * name.
+ */
+static struct archive_acl_entry *
+acl_new_entry(struct archive_acl *acl,
+ int type, int permset, int tag, int id)
+{
+ struct archive_acl_entry *ap, *aq;
+
+ /* Type argument must be a valid NFS4 or POSIX.1e type.
+ * The type must agree with anything already set and
+ * the permset must be compatible. */
+ if (type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ if (acl->acl_types & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ return (NULL);
+ }
+ if (permset &
+ ~(ARCHIVE_ENTRY_ACL_PERMS_NFS4
+ | ARCHIVE_ENTRY_ACL_INHERITANCE_NFS4)) {
+ return (NULL);
+ }
+ } else if (type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) {
+ if (acl->acl_types & ~ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) {
+ return (NULL);
+ }
+ if (permset & ~ARCHIVE_ENTRY_ACL_PERMS_POSIX1E) {
+ return (NULL);
+ }
+ } else {
+ return (NULL);
+ }
+
+ /* Verify the tag is valid and compatible with NFS4 or POSIX.1e. */
+ switch (tag) {
+ case ARCHIVE_ENTRY_ACL_USER:
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
+ case ARCHIVE_ENTRY_ACL_GROUP:
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+ /* Tags valid in both NFS4 and POSIX.1e */
+ break;
+ case ARCHIVE_ENTRY_ACL_MASK:
+ case ARCHIVE_ENTRY_ACL_OTHER:
+ /* Tags valid only in POSIX.1e. */
+ if (type & ~ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) {
+ return (NULL);
+ }
+ break;
+ case ARCHIVE_ENTRY_ACL_EVERYONE:
+ /* Tags valid only in NFS4. */
+ if (type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ return (NULL);
+ }
+ break;
+ default:
+ /* No other values are valid. */
+ return (NULL);
+ }
+
+ if (acl->acl_text_w != NULL) {
+ free(acl->acl_text_w);
+ acl->acl_text_w = NULL;
+ }
+ if (acl->acl_text != NULL) {
+ free(acl->acl_text);
+ acl->acl_text = NULL;
+ }
+
+ /* If there's a matching entry already in the list, overwrite it. */
+ ap = acl->acl_head;
+ aq = NULL;
+ while (ap != NULL) {
+ if (ap->type == type && ap->tag == tag && ap->id == id) {
+ ap->permset = permset;
+ return (ap);
+ }
+ aq = ap;
+ ap = ap->next;
+ }
+
+ /* Add a new entry to the end of the list. */
+ ap = (struct archive_acl_entry *)malloc(sizeof(*ap));
+ if (ap == NULL)
+ return (NULL);
+ memset(ap, 0, sizeof(*ap));
+ if (aq == NULL)
+ acl->acl_head = ap;
+ else
+ aq->next = ap;
+ ap->type = type;
+ ap->tag = tag;
+ ap->id = id;
+ ap->permset = permset;
+ acl->acl_types |= type;
+ return (ap);
+}
+
+/*
+ * Return a count of entries matching "want_type".
+ */
+int
+archive_acl_count(struct archive_acl *acl, int want_type)
+{
+ int count;
+ struct archive_acl_entry *ap;
+
+ count = 0;
+ ap = acl->acl_head;
+ while (ap != NULL) {
+ if ((ap->type & want_type) != 0)
+ count++;
+ ap = ap->next;
+ }
+
+ if (count > 0 && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0))
+ count += 3;
+ return (count);
+}
+
+/*
+ * Prepare for reading entries from the ACL data. Returns a count
+ * of entries matching "want_type", or zero if there are no
+ * non-extended ACL entries of that type.
+ */
+int
+archive_acl_reset(struct archive_acl *acl, int want_type)
+{
+ int count, cutoff;
+
+ count = archive_acl_count(acl, want_type);
+
+ /*
+ * If the only entries are the three standard ones,
+ * then don't return any ACL data. (In this case,
+ * client can just use chmod(2) to set permissions.)
+ */
+ if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
+ cutoff = 3;
+ else
+ cutoff = 0;
+
+ if (count > cutoff)
+ acl->acl_state = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ else
+ acl->acl_state = 0;
+ acl->acl_p = acl->acl_head;
+ return (count);
+}
+
+
+/*
+ * Return the next ACL entry in the list. Fake entries for the
+ * standard permissions and include them in the returned list.
+ */
+int
+archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type, int *type,
+ int *permset, int *tag, int *id, const char **name)
+{
+ *name = NULL;
+ *id = -1;
+
+ /*
+ * The acl_state is either zero (no entries available), -1
+ * (reading from list), or an entry type (retrieve that type
+ * from ae_stat.aest_mode).
+ */
+ if (acl->acl_state == 0)
+ return (ARCHIVE_WARN);
+
+ /* The first three access entries are special. */
+ if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
+ switch (acl->acl_state) {
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
+ *permset = (acl->mode >> 6) & 7;
+ *type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+ *tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ acl->acl_state = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ return (ARCHIVE_OK);
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+ *permset = (acl->mode >> 3) & 7;
+ *type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+ *tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ acl->acl_state = ARCHIVE_ENTRY_ACL_OTHER;
+ return (ARCHIVE_OK);
+ case ARCHIVE_ENTRY_ACL_OTHER:
+ *permset = acl->mode & 7;
+ *type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+ *tag = ARCHIVE_ENTRY_ACL_OTHER;
+ acl->acl_state = -1;
+ acl->acl_p = acl->acl_head;
+ return (ARCHIVE_OK);
+ default:
+ break;
+ }
+ }
+
+ while (acl->acl_p != NULL && (acl->acl_p->type & want_type) == 0)
+ acl->acl_p = acl->acl_p->next;
+ if (acl->acl_p == NULL) {
+ acl->acl_state = 0;
+ *type = 0;
+ *permset = 0;
+ *tag = 0;
+ *id = -1;
+ *name = NULL;
+ return (ARCHIVE_EOF); /* End of ACL entries. */
+ }
+ *type = acl->acl_p->type;
+ *permset = acl->acl_p->permset;
+ *tag = acl->acl_p->tag;
+ *id = acl->acl_p->id;
+ if (archive_mstring_get_mbs(a, &acl->acl_p->name, name) != 0)
+ *name = NULL;
+ acl->acl_p = acl->acl_p->next;
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Generate a text version of the ACL. The flags parameter controls
+ * the style of the generated ACL.
+ */
+const wchar_t *
+archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags)
+{
+ int count;
+ size_t length;
+ const wchar_t *wname;
+ const wchar_t *prefix;
+ wchar_t separator;
+ struct archive_acl_entry *ap;
+ int id;
+ wchar_t *wp;
+
+ if (acl->acl_text_w != NULL) {
+ free (acl->acl_text_w);
+ acl->acl_text_w = NULL;
+ }
+
+ separator = L',';
+ count = 0;
+ length = 0;
+ ap = acl->acl_head;
+ while (ap != NULL) {
+ if ((ap->type & flags) != 0) {
+ count++;
+ if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) &&
+ (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT))
+ length += 8; /* "default:" */
+ length += 5; /* tag name */
+ length += 1; /* colon */
+ if (archive_mstring_get_wcs(a, &ap->name, &wname) == 0 &&
+ wname != NULL)
+ length += wcslen(wname);
+ else
+ length += sizeof(uid_t) * 3 + 1;
+ length ++; /* colon */
+ length += 3; /* rwx */
+ length += 1; /* colon */
+ length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1;
+ length ++; /* newline */
+ }
+ ap = ap->next;
+ }
+
+ if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) {
+ length += 10; /* "user::rwx\n" */
+ length += 11; /* "group::rwx\n" */
+ length += 11; /* "other::rwx\n" */
+ }
+
+ if (count == 0)
+ return (NULL);
+
+ /* Now, allocate the string and actually populate it. */
+ wp = acl->acl_text_w = (wchar_t *)malloc(length * sizeof(wchar_t));
+ if (wp == NULL)
+ __archive_errx(1, "No memory to generate the text version of the ACL");
+ count = 0;
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
+ append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL,
+ acl->mode & 0700, -1);
+ *wp++ = ',';
+ append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL,
+ acl->mode & 0070, -1);
+ *wp++ = ',';
+ append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL,
+ acl->mode & 0007, -1);
+ count += 3;
+
+ ap = acl->acl_head;
+ while (ap != NULL) {
+ if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0 &&
+ archive_mstring_get_wcs(a, &ap->name, &wname) == 0) {
+ *wp++ = separator;
+ if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
+ id = ap->id;
+ else
+ id = -1;
+ append_entry_w(&wp, NULL, ap->tag, wname,
+ ap->permset, id);
+ count++;
+ }
+ ap = ap->next;
+ }
+ }
+
+
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) {
+ if (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT)
+ prefix = L"default:";
+ else
+ prefix = NULL;
+ ap = acl->acl_head;
+ count = 0;
+ while (ap != NULL) {
+ if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0 &&
+ archive_mstring_get_wcs(a, &ap->name, &wname) == 0) {
+ if (count > 0)
+ *wp++ = separator;
+ if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
+ id = ap->id;
+ else
+ id = -1;
+ append_entry_w(&wp, prefix, ap->tag,
+ wname, ap->permset, id);
+ count ++;
+ }
+ ap = ap->next;
+ }
+ }
+
+ return (acl->acl_text_w);
+}
+
+
+static void
+append_id_w(wchar_t **wp, int id)
+{
+ if (id < 0)
+ id = 0;
+ if (id > 9)
+ append_id_w(wp, id / 10);
+ *(*wp)++ = L"0123456789"[id % 10];
+}
+
+static void
+append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
+ const wchar_t *wname, int perm, int id)
+{
+ if (prefix != NULL) {
+ wcscpy(*wp, prefix);
+ *wp += wcslen(*wp);
+ }
+ switch (tag) {
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
+ wname = NULL;
+ id = -1;
+ /* FALLTHROUGH */
+ case ARCHIVE_ENTRY_ACL_USER:
+ wcscpy(*wp, L"user");
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+ wname = NULL;
+ id = -1;
+ /* FALLTHROUGH */
+ case ARCHIVE_ENTRY_ACL_GROUP:
+ wcscpy(*wp, L"group");
+ break;
+ case ARCHIVE_ENTRY_ACL_MASK:
+ wcscpy(*wp, L"mask");
+ wname = NULL;
+ id = -1;
+ break;
+ case ARCHIVE_ENTRY_ACL_OTHER:
+ wcscpy(*wp, L"other");
+ wname = NULL;
+ id = -1;
+ break;
+ }
+ *wp += wcslen(*wp);
+ *(*wp)++ = L':';
+ if (wname != NULL) {
+ wcscpy(*wp, wname);
+ *wp += wcslen(*wp);
+ } else if (tag == ARCHIVE_ENTRY_ACL_USER
+ || tag == ARCHIVE_ENTRY_ACL_GROUP) {
+ append_id_w(wp, id);
+ id = -1;
+ }
+ *(*wp)++ = L':';
+ *(*wp)++ = (perm & 0444) ? L'r' : L'-';
+ *(*wp)++ = (perm & 0222) ? L'w' : L'-';
+ *(*wp)++ = (perm & 0111) ? L'x' : L'-';
+ if (id != -1) {
+ *(*wp)++ = L':';
+ append_id_w(wp, id);
+ }
+ **wp = L'\0';
+}
+
+int
+archive_acl_text_l(struct archive_acl *acl, int flags,
+ const char **acl_text, size_t *acl_text_len,
+ struct archive_string_conv *sc)
+{
+ int count;
+ size_t length;
+ const char *name;
+ const char *prefix;
+ char separator;
+ struct archive_acl_entry *ap;
+ size_t len;
+ int id, r;
+ char *p;
+
+ if (acl->acl_text != NULL) {
+ free (acl->acl_text);
+ acl->acl_text = NULL;
+ }
+
+ *acl_text = NULL;
+ if (acl_text_len != NULL)
+ *acl_text_len = 0;
+ separator = ',';
+ count = 0;
+ length = 0;
+ ap = acl->acl_head;
+ while (ap != NULL) {
+ if ((ap->type & flags) != 0) {
+ count++;
+ if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) &&
+ (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT))
+ length += 8; /* "default:" */
+ length += 5; /* tag name */
+ length += 1; /* colon */
+ r = archive_mstring_get_mbs_l(
+ &ap->name, &name, &len, sc);
+ if (r != 0)
+ return (-1);
+ if (len > 0 && name != NULL)
+ length += len;
+ else
+ length += sizeof(uid_t) * 3 + 1;
+ length ++; /* colon */
+ length += 3; /* rwx */
+ length += 1; /* colon */
+ length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1;
+ length ++; /* newline */
+ }
+ ap = ap->next;
+ }
+
+ if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) {
+ length += 10; /* "user::rwx\n" */
+ length += 11; /* "group::rwx\n" */
+ length += 11; /* "other::rwx\n" */
+ }
+
+ if (count == 0)
+ return (0);
+
+ /* Now, allocate the string and actually populate it. */
+ p = acl->acl_text = (char *)malloc(length);
+ if (p == NULL)
+ __archive_errx(1, "No memory to generate the text version of the ACL");
+ count = 0;
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
+ append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL,
+ acl->mode & 0700, -1);
+ *p++ = ',';
+ append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL,
+ acl->mode & 0070, -1);
+ *p++ = ',';
+ append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL,
+ acl->mode & 0007, -1);
+ count += 3;
+
+ for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
+ if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) == 0)
+ continue;
+ r = archive_mstring_get_mbs_l(
+ &ap->name, &name, &len, sc);
+ if (r != 0)
+ return (-1);
+ *p++ = separator;
+ if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
+ id = ap->id;
+ else
+ id = -1;
+ append_entry(&p, NULL, ap->tag, name,
+ ap->permset, id);
+ count++;
+ }
+ }
+
+
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) {
+ if (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT)
+ prefix = "default:";
+ else
+ prefix = NULL;
+ count = 0;
+ for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
+ if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) == 0)
+ continue;
+ r = archive_mstring_get_mbs_l(
+ &ap->name, &name, &len, sc);
+ if (r != 0)
+ return (-1);
+ if (count > 0)
+ *p++ = separator;
+ if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
+ id = ap->id;
+ else
+ id = -1;
+ append_entry(&p, prefix, ap->tag,
+ name, ap->permset, id);
+ count ++;
+ }
+ }
+
+ *acl_text = acl->acl_text;
+ if (acl_text_len != NULL)
+ *acl_text_len = strlen(acl->acl_text);
+ return (0);
+}
+
+static void
+append_id(char **p, int id)
+{
+ if (id < 0)
+ id = 0;
+ if (id > 9)
+ append_id(p, id / 10);
+ *(*p)++ = "0123456789"[id % 10];
+}
+
+static void
+append_entry(char **p, const char *prefix, int tag,
+ const char *name, int perm, int id)
+{
+ if (prefix != NULL) {
+ strcpy(*p, prefix);
+ *p += strlen(*p);
+ }
+ switch (tag) {
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
+ name = NULL;
+ id = -1;
+ /* FALLTHROUGH */
+ case ARCHIVE_ENTRY_ACL_USER:
+ strcpy(*p, "user");
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+ name = NULL;
+ id = -1;
+ /* FALLTHROUGH */
+ case ARCHIVE_ENTRY_ACL_GROUP:
+ strcpy(*p, "group");
+ break;
+ case ARCHIVE_ENTRY_ACL_MASK:
+ strcpy(*p, "mask");
+ name = NULL;
+ id = -1;
+ break;
+ case ARCHIVE_ENTRY_ACL_OTHER:
+ strcpy(*p, "other");
+ name = NULL;
+ id = -1;
+ break;
+ }
+ *p += strlen(*p);
+ *(*p)++ = ':';
+ if (name != NULL) {
+ strcpy(*p, name);
+ *p += strlen(*p);
+ } else if (tag == ARCHIVE_ENTRY_ACL_USER
+ || tag == ARCHIVE_ENTRY_ACL_GROUP) {
+ append_id(p, id);
+ id = -1;
+ }
+ *(*p)++ = ':';
+ *(*p)++ = (perm & 0444) ? 'r' : '-';
+ *(*p)++ = (perm & 0222) ? 'w' : '-';
+ *(*p)++ = (perm & 0111) ? 'x' : '-';
+ if (id != -1) {
+ *(*p)++ = ':';
+ append_id(p, id);
+ }
+ **p = '\0';
+}
+
+/*
+ * Parse a textual ACL. This automatically recognizes and supports
+ * extensions described above. The 'type' argument is used to
+ * indicate the type that should be used for any entries not
+ * explicitly marked as "default:".
+ */
+int
+archive_acl_parse_w(struct archive_acl *acl,
+ const wchar_t *text, int default_type)
+{
+ struct {
+ const wchar_t *start;
+ const wchar_t *end;
+ } field[4], name;
+
+ int fields, n;
+ int type, tag, permset, id;
+ wchar_t sep;
+
+ while (text != NULL && *text != L'\0') {
+ /*
+ * Parse the fields out of the next entry,
+ * advance 'text' to start of next entry.
+ */
+ fields = 0;
+ do {
+ const wchar_t *start, *end;
+ next_field_w(&text, &start, &end, &sep);
+ if (fields < 4) {
+ field[fields].start = start;
+ field[fields].end = end;
+ }
+ ++fields;
+ } while (sep == L':');
+
+ /* Set remaining fields to blank. */
+ for (n = fields; n < 4; ++n)
+ field[n].start = field[n].end = NULL;
+
+ /* Check for a numeric ID in field 1 or 3. */
+ id = -1;
+ isint_w(field[1].start, field[1].end, &id);
+ /* Field 3 is optional. */
+ if (id == -1 && fields > 3)
+ isint_w(field[3].start, field[3].end, &id);
+
+ /*
+ * Solaris extension: "defaultuser::rwx" is the
+ * default ACL corresponding to "user::rwx", etc.
+ */
+ if (field[0].end - field[0].start > 7
+ && wmemcmp(field[0].start, L"default", 7) == 0) {
+ type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
+ field[0].start += 7;
+ } else
+ type = default_type;
+
+ name.start = name.end = NULL;
+ if (prefix_w(field[0].start, field[0].end, L"user")) {
+ if (!ismode_w(field[2].start, field[2].end, &permset))
+ return (ARCHIVE_WARN);
+ if (id != -1 || field[1].start < field[1].end) {
+ tag = ARCHIVE_ENTRY_ACL_USER;
+ name = field[1];
+ } else
+ tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ } else if (prefix_w(field[0].start, field[0].end, L"group")) {
+ if (!ismode_w(field[2].start, field[2].end, &permset))
+ return (ARCHIVE_WARN);
+ if (id != -1 || field[1].start < field[1].end) {
+ tag = ARCHIVE_ENTRY_ACL_GROUP;
+ name = field[1];
+ } else
+ tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ } else if (prefix_w(field[0].start, field[0].end, L"other")) {
+ if (fields == 2
+ && field[1].start < field[1].end
+ && ismode_w(field[1].start, field[1].end, &permset)) {
+ /* This is Solaris-style "other:rwx" */
+ } else if (fields == 3
+ && field[1].start == field[1].end
+ && field[2].start < field[2].end
+ && ismode_w(field[2].start, field[2].end, &permset)) {
+ /* This is FreeBSD-style "other::rwx" */
+ } else
+ return (ARCHIVE_WARN);
+ tag = ARCHIVE_ENTRY_ACL_OTHER;
+ } else if (prefix_w(field[0].start, field[0].end, L"mask")) {
+ if (fields == 2
+ && field[1].start < field[1].end
+ && ismode_w(field[1].start, field[1].end, &permset)) {
+ /* This is Solaris-style "mask:rwx" */
+ } else if (fields == 3
+ && field[1].start == field[1].end
+ && field[2].start < field[2].end
+ && ismode_w(field[2].start, field[2].end, &permset)) {
+ /* This is FreeBSD-style "mask::rwx" */
+ } else
+ return (ARCHIVE_WARN);
+ tag = ARCHIVE_ENTRY_ACL_MASK;
+ } else
+ return (ARCHIVE_WARN);
+
+ /* Add entry to the internal list. */
+ archive_acl_add_entry_w_len(acl, type, permset,
+ tag, id, name.start, name.end - name.start);
+ }
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Parse a string to a positive decimal integer. Returns true if
+ * the string is non-empty and consists only of decimal digits,
+ * false otherwise.
+ */
+static int
+isint_w(const wchar_t *start, const wchar_t *end, int *result)
+{
+ int n = 0;
+ if (start >= end)
+ return (0);
+ while (start < end) {
+ if (*start < '0' || *start > '9')
+ return (0);
+ if (n > (INT_MAX / 10) ||
+ (n == INT_MAX / 10 && (*start - '0') > INT_MAX % 10)) {
+ n = INT_MAX;
+ } else {
+ n *= 10;
+ n += *start - '0';
+ }
+ start++;
+ }
+ *result = n;
+ return (1);
+}
+
+/*
+ * Parse a string as a mode field. Returns true if
+ * the string is non-empty and consists only of mode characters,
+ * false otherwise.
+ */
+static int
+ismode_w(const wchar_t *start, const wchar_t *end, int *permset)
+{
+ const wchar_t *p;
+
+ if (start >= end)
+ return (0);
+ p = start;
+ *permset = 0;
+ while (p < end) {
+ switch (*p++) {
+ case 'r': case 'R':
+ *permset |= ARCHIVE_ENTRY_ACL_READ;
+ break;
+ case 'w': case 'W':
+ *permset |= ARCHIVE_ENTRY_ACL_WRITE;
+ break;
+ case 'x': case 'X':
+ *permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
+ break;
+ case '-':
+ break;
+ default:
+ return (0);
+ }
+ }
+ return (1);
+}
+
+/*
+ * Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]". *wp is updated
+ * to point to just after the separator. *start points to the first
+ * character of the matched text and *end just after the last
+ * character of the matched identifier. In particular *end - *start
+ * is the length of the field body, not including leading or trailing
+ * whitespace.
+ */
+static void
+next_field_w(const wchar_t **wp, const wchar_t **start,
+ const wchar_t **end, wchar_t *sep)
+{
+ /* Skip leading whitespace to find start of field. */
+ while (**wp == L' ' || **wp == L'\t' || **wp == L'\n') {
+ (*wp)++;
+ }
+ *start = *wp;
+
+ /* Scan for the separator. */
+ while (**wp != L'\0' && **wp != L',' && **wp != L':' &&
+ **wp != L'\n') {
+ (*wp)++;
+ }
+ *sep = **wp;
+
+ /* Trim trailing whitespace to locate end of field. */
+ *end = *wp - 1;
+ while (**end == L' ' || **end == L'\t' || **end == L'\n') {
+ (*end)--;
+ }
+ (*end)++;
+
+ /* Adjust scanner location. */
+ if (**wp != L'\0')
+ (*wp)++;
+}
+
+/*
+ * Return true if the characters [start...end) are a prefix of 'test'.
+ * This makes it easy to handle the obvious abbreviations: 'u' for 'user', etc.
+ */
+static int
+prefix_w(const wchar_t *start, const wchar_t *end, const wchar_t *test)
+{
+ if (start == end)
+ return (0);
+
+ if (*start++ != *test++)
+ return (0);
+
+ while (start < end && *start++ == *test++)
+ ;
+
+ if (start < end)
+ return (0);
+
+ return (1);
+}
+
+/*
+ * Parse a textual ACL. This automatically recognizes and supports
+ * extensions described above. The 'type' argument is used to
+ * indicate the type that should be used for any entries not
+ * explicitly marked as "default:".
+ */
+int
+archive_acl_parse_l(struct archive_acl *acl,
+ const char *text, int default_type, struct archive_string_conv *sc)
+{
+ struct {
+ const char *start;
+ const char *end;
+ } field[4], name;
+
+ int fields, n, r, ret = ARCHIVE_OK;
+ int type, tag, permset, id;
+ char sep;
+
+ while (text != NULL && *text != '\0') {
+ /*
+ * Parse the fields out of the next entry,
+ * advance 'text' to start of next entry.
+ */
+ fields = 0;
+ do {
+ const char *start, *end;
+ next_field(&text, &start, &end, &sep);
+ if (fields < 4) {
+ field[fields].start = start;
+ field[fields].end = end;
+ }
+ ++fields;
+ } while (sep == ':');
+
+ /* Set remaining fields to blank. */
+ for (n = fields; n < 4; ++n)
+ field[n].start = field[n].end = NULL;
+
+ /* Check for a numeric ID in field 1 or 3. */
+ id = -1;
+ isint(field[1].start, field[1].end, &id);
+ /* Field 3 is optional. */
+ if (id == -1 && fields > 3)
+ isint(field[3].start, field[3].end, &id);
+
+ /*
+ * Solaris extension: "defaultuser::rwx" is the
+ * default ACL corresponding to "user::rwx", etc.
+ */
+ if (field[0].end - field[0].start > 7
+ && memcmp(field[0].start, "default", 7) == 0) {
+ type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
+ field[0].start += 7;
+ } else
+ type = default_type;
+
+ name.start = name.end = NULL;
+ if (prefix_c(field[0].start, field[0].end, "user")) {
+ if (!ismode(field[2].start, field[2].end, &permset))
+ return (ARCHIVE_WARN);
+ if (id != -1 || field[1].start < field[1].end) {
+ tag = ARCHIVE_ENTRY_ACL_USER;
+ name = field[1];
+ } else
+ tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ } else if (prefix_c(field[0].start, field[0].end, "group")) {
+ if (!ismode(field[2].start, field[2].end, &permset))
+ return (ARCHIVE_WARN);
+ if (id != -1 || field[1].start < field[1].end) {
+ tag = ARCHIVE_ENTRY_ACL_GROUP;
+ name = field[1];
+ } else
+ tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ } else if (prefix_c(field[0].start, field[0].end, "other")) {
+ if (fields == 2
+ && field[1].start < field[1].end
+ && ismode(field[1].start, field[1].end, &permset)) {
+ /* This is Solaris-style "other:rwx" */
+ } else if (fields == 3
+ && field[1].start == field[1].end
+ && field[2].start < field[2].end
+ && ismode(field[2].start, field[2].end, &permset)) {
+ /* This is FreeBSD-style "other::rwx" */
+ } else
+ return (ARCHIVE_WARN);
+ tag = ARCHIVE_ENTRY_ACL_OTHER;
+ } else if (prefix_c(field[0].start, field[0].end, "mask")) {
+ if (fields == 2
+ && field[1].start < field[1].end
+ && ismode(field[1].start, field[1].end, &permset)) {
+ /* This is Solaris-style "mask:rwx" */
+ } else if (fields == 3
+ && field[1].start == field[1].end
+ && field[2].start < field[2].end
+ && ismode(field[2].start, field[2].end, &permset)) {
+ /* This is FreeBSD-style "mask::rwx" */
+ } else
+ return (ARCHIVE_WARN);
+ tag = ARCHIVE_ENTRY_ACL_MASK;
+ } else
+ return (ARCHIVE_WARN);
+
+ /* Add entry to the internal list. */
+ r = archive_acl_add_entry_len_l(acl, type, permset,
+ tag, id, name.start, name.end - name.start, sc);
+ if (r < ARCHIVE_WARN)
+ return (r);
+ if (r != ARCHIVE_OK)
+ ret = ARCHIVE_WARN;
+ }
+ return (ret);
+}
+
+/*
+ * Parse a string to a positive decimal integer. Returns true if
+ * the string is non-empty and consists only of decimal digits,
+ * false otherwise.
+ */
+static int
+isint(const char *start, const char *end, int *result)
+{
+ int n = 0;
+ if (start >= end)
+ return (0);
+ while (start < end) {
+ if (*start < '0' || *start > '9')
+ return (0);
+ if (n > (INT_MAX / 10) ||
+ (n == INT_MAX / 10 && (*start - '0') > INT_MAX % 10)) {
+ n = INT_MAX;
+ } else {
+ n *= 10;
+ n += *start - '0';
+ }
+ start++;
+ }
+ *result = n;
+ return (1);
+}
+
+/*
+ * Parse a string as a mode field. Returns true if
+ * the string is non-empty and consists only of mode characters,
+ * false otherwise.
+ */
+static int
+ismode(const char *start, const char *end, int *permset)
+{
+ const char *p;
+
+ if (start >= end)
+ return (0);
+ p = start;
+ *permset = 0;
+ while (p < end) {
+ switch (*p++) {
+ case 'r': case 'R':
+ *permset |= ARCHIVE_ENTRY_ACL_READ;
+ break;
+ case 'w': case 'W':
+ *permset |= ARCHIVE_ENTRY_ACL_WRITE;
+ break;
+ case 'x': case 'X':
+ *permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
+ break;
+ case '-':
+ break;
+ default:
+ return (0);
+ }
+ }
+ return (1);
+}
+
+/*
+ * Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]". *wp is updated
+ * to point to just after the separator. *start points to the first
+ * character of the matched text and *end just after the last
+ * character of the matched identifier. In particular *end - *start
+ * is the length of the field body, not including leading or trailing
+ * whitespace.
+ */
+static void
+next_field(const char **p, const char **start,
+ const char **end, char *sep)
+{
+ /* Skip leading whitespace to find start of field. */
+ while (**p == ' ' || **p == '\t' || **p == '\n') {
+ (*p)++;
+ }
+ *start = *p;
+
+ /* Scan for the separator. */
+ while (**p != '\0' && **p != ',' && **p != ':' && **p != '\n') {
+ (*p)++;
+ }
+ *sep = **p;
+
+ /* Trim trailing whitespace to locate end of field. */
+ *end = *p - 1;
+ while (**end == ' ' || **end == '\t' || **end == '\n') {
+ (*end)--;
+ }
+ (*end)++;
+
+ /* Adjust scanner location. */
+ if (**p != '\0')
+ (*p)++;
+}
+
+/*
+ * Return true if the characters [start...end) are a prefix of 'test'.
+ * This makes it easy to handle the obvious abbreviations: 'u' for 'user', etc.
+ */
+static int
+prefix_c(const char *start, const char *end, const char *test)
+{
+ if (start == end)
+ return (0);
+
+ if (*start++ != *test++)
+ return (0);
+
+ while (start < end && *start++ == *test++)
+ ;
+
+ if (start < end)
+ return (0);
+
+ return (1);
+}
diff --git a/contrib/libarchive/libarchive/archive_acl_private.h b/contrib/libarchive/libarchive/archive_acl_private.h
new file mode 100644
index 000000000000..1421adbf8a23
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_acl_private.h
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 2003-2010 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
+#ifndef ARCHIVE_ACL_PRIVATE_H_INCLUDED
+#define ARCHIVE_ACL_PRIVATE_H_INCLUDED
+
+#include "archive_string.h"
+
+struct archive_acl_entry {
+ struct archive_acl_entry *next;
+ int type; /* E.g., access or default */
+ int tag; /* E.g., user/group/other/mask */
+ int permset; /* r/w/x bits */
+ int id; /* uid/gid for user/group */
+ struct archive_mstring name; /* uname/gname */
+};
+
+struct archive_acl {
+ mode_t mode;
+ struct archive_acl_entry *acl_head;
+ struct archive_acl_entry *acl_p;
+ int acl_state; /* See acl_next for details. */
+ wchar_t *acl_text_w;
+ char *acl_text;
+ int acl_types;
+};
+
+void archive_acl_clear(struct archive_acl *);
+void archive_acl_copy(struct archive_acl *, struct archive_acl *);
+int archive_acl_count(struct archive_acl *, int);
+int archive_acl_reset(struct archive_acl *, int);
+int archive_acl_next(struct archive *, struct archive_acl *, int,
+ int *, int *, int *, int *, const char **);
+
+int archive_acl_add_entry(struct archive_acl *, int, int, int, int, const char *);
+int archive_acl_add_entry_w_len(struct archive_acl *,
+ int, int, int, int, const wchar_t *, size_t);
+int archive_acl_add_entry_len(struct archive_acl *,
+ int, int, int, int, const char *, size_t);
+
+const wchar_t *archive_acl_text_w(struct archive *, struct archive_acl *, int);
+int archive_acl_text_l(struct archive_acl *, int, const char **, size_t *,
+ struct archive_string_conv *);
+
+/*
+ * Private ACL parser. This is private because it handles some
+ * very weird formats that clients should not be messing with.
+ * Clients should only deal with their platform-native formats.
+ * Because of the need to support many formats cleanly, new arguments
+ * are likely to get added on a regular basis. Clients who try to use
+ * this interface are likely to be surprised when it changes.
+ */
+int archive_acl_parse_w(struct archive_acl *,
+ const wchar_t *, int /* type */);
+int archive_acl_parse_l(struct archive_acl *,
+ const char *, int /* type */,
+ struct archive_string_conv *);
+
+#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
diff --git a/contrib/libarchive/libarchive/archive_check_magic.c b/contrib/libarchive/libarchive/archive_check_magic.c
index 1381a186be83..93c7a4fed357 100644
--- a/contrib/libarchive/libarchive/archive_check_magic.c
+++ b/contrib/libarchive/libarchive/archive_check_magic.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2003-2010 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -86,49 +86,89 @@ state_name(unsigned s)
}
}
+static const char *
+archive_handle_type_name(unsigned m)
+{
+ switch (m) {
+ case ARCHIVE_WRITE_MAGIC: return ("archive_write");
+ case ARCHIVE_READ_MAGIC: return ("archive_read");
+ case ARCHIVE_WRITE_DISK_MAGIC: return ("archive_write_disk");
+ case ARCHIVE_READ_DISK_MAGIC: return ("archive_read_disk");
+ default: return NULL;
+ }
+}
-static void
-write_all_states(unsigned int states)
+
+static char *
+write_all_states(char *buff, unsigned int states)
{
unsigned int lowbit;
+ buff[0] = '\0';
+
/* A trick for computing the lowest set bit. */
while ((lowbit = states & (1 + ~states)) != 0) {
states &= ~lowbit; /* Clear the low bit. */
- errmsg(state_name(lowbit));
+ strcat(buff, state_name(lowbit));
if (states != 0)
- errmsg("/");
+ strcat(buff, "/");
}
+ return buff;
}
/*
- * Check magic value and current state; bail if it isn't valid.
+ * Check magic value and current state.
+ * Magic value mismatches are fatal and result in calls to abort().
+ * State mismatches return ARCHIVE_FATAL.
+ * Otherwise, returns ARCHIVE_OK.
*
* This is designed to catch serious programming errors that violate
* the libarchive API.
*/
-void
+int
__archive_check_magic(struct archive *a, unsigned int magic,
unsigned int state, const char *function)
{
- if (a->magic != magic) {
- errmsg("INTERNAL ERROR: Function ");
+ char states1[64];
+ char states2[64];
+ const char *handle_type;
+
+ /*
+ * If this isn't some form of archive handle,
+ * then the library user has screwed up so bad that
+ * we don't even have a reliable way to report an error.
+ */
+ handle_type = archive_handle_type_name(a->magic);
+
+ if (!handle_type) {
+ errmsg("PROGRAMMER ERROR: Function ");
errmsg(function);
- errmsg(" invoked with invalid struct archive structure.\n");
+ errmsg(" invoked with invalid archive handle.\n");
diediedie();
}
- if (state == ARCHIVE_STATE_ANY)
- return;
+ if (a->magic != magic) {
+ archive_set_error(a, -1,
+ "PROGRAMMER ERROR: Function '%s' invoked"
+ " on '%s' archive object, which is not supported.",
+ function,
+ handle_type);
+ a->state = ARCHIVE_STATE_FATAL;
+ return (ARCHIVE_FATAL);
+ }
if ((a->state & state) == 0) {
- errmsg("INTERNAL ERROR: Function '");
- errmsg(function);
- errmsg("' invoked with archive structure in state '");
- write_all_states(a->state);
- errmsg("', should be in state '");
- write_all_states(state);
- errmsg("'\n");
- diediedie();
+ /* If we're already FATAL, don't overwrite the error. */
+ if (a->state != ARCHIVE_STATE_FATAL)
+ archive_set_error(a, -1,
+ "INTERNAL ERROR: Function '%s' invoked with"
+ " archive structure in state '%s',"
+ " should be in state '%s'",
+ function,
+ write_all_states(states1, a->state),
+ write_all_states(states2, state));
+ a->state = ARCHIVE_STATE_FATAL;
+ return (ARCHIVE_FATAL);
}
+ return ARCHIVE_OK;
}
diff --git a/contrib/libarchive/libarchive/archive_crc32.h b/contrib/libarchive/libarchive/archive_crc32.h
index 771575476d98..0a947077056e 100644
--- a/contrib/libarchive/libarchive/archive_crc32.h
+++ b/contrib/libarchive/libarchive/archive_crc32.h
@@ -60,6 +60,18 @@ crc32(unsigned long crc, const void *_p, size_t len)
}
crc = crc ^ 0xffffffffUL;
+ /* A use of this loop is about 20% - 30% faster than
+ * no use version in any optimization option of gcc. */
+ for (;len >= 8; len -= 8) {
+ crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+ crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+ crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+ crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+ crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+ crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+ crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+ crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+ }
while (len--)
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
return (crc ^ 0xffffffffUL);
diff --git a/contrib/libarchive/libarchive/archive_crypto.c b/contrib/libarchive/libarchive/archive_crypto.c
new file mode 100644
index 000000000000..2caf57169296
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_crypto.c
@@ -0,0 +1,1427 @@
+/*-
+* Copyright (c) 2003-2007 Tim Kientzle
+* Copyright (c) 2011 Andres Mejia
+* Copyright (c) 2011 Michihiro NAKAJIMA
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "archive_platform.h"
+
+#include "archive.h"
+#include "archive_crypto_private.h"
+
+/* In particular, force the configure probe to break if it tries
+ * to test a combination of OpenSSL and libmd. */
+#if defined(ARCHIVE_CRYPTO_OPENSSL) && defined(ARCHIVE_CRYPTO_LIBMD)
+#error Cannot use both OpenSSL and libmd.
+#endif
+
+/*
+ * Message digest functions for Windows platform.
+ */
+#if defined(ARCHIVE_CRYPTO_MD5_WIN) ||\
+ defined(ARCHIVE_CRYPTO_SHA1_WIN) ||\
+ defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\
+ defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\
+ defined(ARCHIVE_CRYPTO_SHA512_WIN)
+
+/*
+ * Initialize a Message digest.
+ */
+static int
+win_crypto_init(Digest_CTX *ctx, ALG_ID algId)
+{
+
+ ctx->valid = 0;
+ if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL,
+ PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+ if (GetLastError() != (DWORD)NTE_BAD_KEYSET)
+ return (ARCHIVE_FAILED);
+ if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL,
+ PROV_RSA_FULL, CRYPT_NEWKEYSET))
+ return (ARCHIVE_FAILED);
+ }
+
+ if (!CryptCreateHash(ctx->cryptProv, algId, 0, 0, &ctx->hash)) {
+ CryptReleaseContext(ctx->cryptProv, 0);
+ return (ARCHIVE_FAILED);
+ }
+
+ ctx->valid = 1;
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Update a Message digest.
+ */
+static int
+win_crypto_Update(Digest_CTX *ctx, const unsigned char *buf, size_t len)
+{
+
+ if (!ctx->valid)
+ return (ARCHIVE_FAILED);
+
+ CryptHashData(ctx->hash,
+ (unsigned char *)(uintptr_t)buf,
+ (DWORD)len, 0);
+ return (ARCHIVE_OK);
+}
+
+static int
+win_crypto_Final(unsigned char *buf, size_t bufsize, Digest_CTX *ctx)
+{
+ DWORD siglen = bufsize;
+
+ if (!ctx->valid)
+ return (ARCHIVE_FAILED);
+
+ CryptGetHashParam(ctx->hash, HP_HASHVAL, buf, &siglen, 0);
+ CryptDestroyHash(ctx->hash);
+ CryptReleaseContext(ctx->cryptProv, 0);
+ ctx->valid = 0;
+ return (ARCHIVE_OK);
+}
+
+#endif /* defined(ARCHIVE_CRYPTO_*_WIN) */
+
+
+/* MD5 implementations */
+#if defined(ARCHIVE_CRYPTO_MD5_LIBC)
+
+static int
+__archive_libc_md5init(archive_md5_ctx *ctx)
+{
+ MD5Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc_md5update(archive_md5_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ MD5Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc_md5final(archive_md5_ctx *ctx, void *md)
+{
+ MD5Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_MD5_LIBMD)
+
+static int
+__archive_libmd_md5init(archive_md5_ctx *ctx)
+{
+ MD5Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libmd_md5update(archive_md5_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ MD5Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libmd_md5final(archive_md5_ctx *ctx, void *md)
+{
+ MD5Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM)
+
+static int
+__archive_libsystem_md5init(archive_md5_ctx *ctx)
+{
+ CC_MD5_Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libsystem_md5update(archive_md5_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ CC_MD5_Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libsystem_md5final(archive_md5_ctx *ctx, void *md)
+{
+ CC_MD5_Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_MD5_NETTLE)
+
+static int
+__archive_nettle_md5init(archive_md5_ctx *ctx)
+{
+ md5_init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_nettle_md5update(archive_md5_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ md5_update(ctx, insize, indata);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_nettle_md5final(archive_md5_ctx *ctx, void *md)
+{
+ md5_digest(ctx, MD5_DIGEST_SIZE, md);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL)
+
+static int
+__archive_openssl_md5init(archive_md5_ctx *ctx)
+{
+ EVP_DigestInit(ctx, EVP_md5());
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_openssl_md5update(archive_md5_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ EVP_DigestUpdate(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_openssl_md5final(archive_md5_ctx *ctx, void *md)
+{
+ /* HACK: archive_write_set_format_xar.c is finalizing empty contexts, so
+ * this is meant to cope with that. Real fix is probably to fix
+ * archive_write_set_format_xar.c
+ */
+ if (ctx->digest)
+ EVP_DigestFinal(ctx, md, NULL);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
+
+static int
+__archive_windowsapi_md5init(archive_md5_ctx *ctx)
+{
+ return (win_crypto_init(ctx, CALG_MD5));
+}
+
+static int
+__archive_windowsapi_md5update(archive_md5_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ return (win_crypto_Update(ctx, indata, insize));
+}
+
+static int
+__archive_windowsapi_md5final(archive_md5_ctx *ctx, void *md)
+{
+ return (win_crypto_Final(md, 16, ctx));
+}
+
+#else
+
+static int
+__archive_stub_md5init(archive_md5_ctx *ctx)
+{
+ (void)ctx; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+static int
+__archive_stub_md5update(archive_md5_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ (void)ctx; /* UNUSED */
+ (void)indata; /* UNUSED */
+ (void)insize; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+static int
+__archive_stub_md5final(archive_md5_ctx *ctx, void *md)
+{
+ (void)ctx; /* UNUSED */
+ (void)md; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+#endif
+
+/* RIPEMD160 implementations */
+#if defined(ARCHIVE_CRYPTO_RMD160_LIBC)
+
+static int
+__archive_libc_ripemd160init(archive_rmd160_ctx *ctx)
+{
+ RMD160Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ RMD160Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc_ripemd160final(archive_rmd160_ctx *ctx, void *md)
+{
+ RMD160Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD)
+
+static int
+__archive_libmd_ripemd160init(archive_rmd160_ctx *ctx)
+{
+ RIPEMD160_Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libmd_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ RIPEMD160_Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libmd_ripemd160final(archive_rmd160_ctx *ctx, void *md)
+{
+ RIPEMD160_Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE)
+
+static int
+__archive_nettle_ripemd160init(archive_rmd160_ctx *ctx)
+{
+ ripemd160_init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_nettle_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ ripemd160_update(ctx, insize, indata);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_nettle_ripemd160final(archive_rmd160_ctx *ctx, void *md)
+{
+ ripemd160_digest(ctx, RIPEMD160_DIGEST_SIZE, md);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL)
+
+static int
+__archive_openssl_ripemd160init(archive_rmd160_ctx *ctx)
+{
+ EVP_DigestInit(ctx, EVP_ripemd160());
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_openssl_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ EVP_DigestUpdate(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_openssl_ripemd160final(archive_rmd160_ctx *ctx, void *md)
+{
+ EVP_DigestFinal(ctx, md, NULL);
+ return (ARCHIVE_OK);
+}
+
+#else
+
+static int
+__archive_stub_ripemd160init(archive_rmd160_ctx *ctx)
+{
+ (void)ctx; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+static int
+__archive_stub_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ (void)ctx; /* UNUSED */
+ (void)indata; /* UNUSED */
+ (void)insize; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+static int
+__archive_stub_ripemd160final(archive_rmd160_ctx *ctx, void *md)
+{
+ (void)ctx; /* UNUSED */
+ (void)md; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+#endif
+
+/* SHA1 implementations */
+#if defined(ARCHIVE_CRYPTO_SHA1_LIBC)
+
+static int
+__archive_libc_sha1init(archive_sha1_ctx *ctx)
+{
+ SHA1Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc_sha1update(archive_sha1_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ SHA1Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc_sha1final(archive_sha1_ctx *ctx, void *md)
+{
+ SHA1Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA1_LIBMD)
+
+static int
+__archive_libmd_sha1init(archive_sha1_ctx *ctx)
+{
+ SHA1_Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libmd_sha1update(archive_sha1_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ SHA1_Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libmd_sha1final(archive_sha1_ctx *ctx, void *md)
+{
+ SHA1_Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM)
+
+static int
+__archive_libsystem_sha1init(archive_sha1_ctx *ctx)
+{
+ CC_SHA1_Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libsystem_sha1update(archive_sha1_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ CC_SHA1_Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libsystem_sha1final(archive_sha1_ctx *ctx, void *md)
+{
+ CC_SHA1_Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE)
+
+static int
+__archive_nettle_sha1init(archive_sha1_ctx *ctx)
+{
+ sha1_init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_nettle_sha1update(archive_sha1_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ sha1_update(ctx, insize, indata);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_nettle_sha1final(archive_sha1_ctx *ctx, void *md)
+{
+ sha1_digest(ctx, SHA1_DIGEST_SIZE, md);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL)
+
+static int
+__archive_openssl_sha1init(archive_sha1_ctx *ctx)
+{
+ EVP_DigestInit(ctx, EVP_sha1());
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_openssl_sha1update(archive_sha1_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ EVP_DigestUpdate(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_openssl_sha1final(archive_sha1_ctx *ctx, void *md)
+{
+ /* HACK: archive_write_set_format_xar.c is finalizing empty contexts, so
+ * this is meant to cope with that. Real fix is probably to fix
+ * archive_write_set_format_xar.c
+ */
+ if (ctx->digest)
+ EVP_DigestFinal(ctx, md, NULL);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
+
+static int
+__archive_windowsapi_sha1init(archive_sha1_ctx *ctx)
+{
+ return (win_crypto_init(ctx, CALG_SHA1));
+}
+
+static int
+__archive_windowsapi_sha1update(archive_sha1_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ return (win_crypto_Update(ctx, indata, insize));
+}
+
+static int
+__archive_windowsapi_sha1final(archive_sha1_ctx *ctx, void *md)
+{
+ return (win_crypto_Final(md, 20, ctx));
+}
+
+#else
+
+static int
+__archive_stub_sha1init(archive_sha1_ctx *ctx)
+{
+ (void)ctx; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+static int
+__archive_stub_sha1update(archive_sha1_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ (void)ctx; /* UNUSED */
+ (void)indata; /* UNUSED */
+ (void)insize; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+static int
+__archive_stub_sha1final(archive_sha1_ctx *ctx, void *md)
+{
+ (void)ctx; /* UNUSED */
+ (void)md; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+#endif
+
+/* SHA256 implementations */
+#if defined(ARCHIVE_CRYPTO_SHA256_LIBC)
+
+static int
+__archive_libc_sha256init(archive_sha256_ctx *ctx)
+{
+ SHA256_Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc_sha256update(archive_sha256_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ SHA256_Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc_sha256final(archive_sha256_ctx *ctx, void *md)
+{
+ SHA256_Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC2)
+
+static int
+__archive_libc2_sha256init(archive_sha256_ctx *ctx)
+{
+ SHA256Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc2_sha256update(archive_sha256_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ SHA256Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc2_sha256final(archive_sha256_ctx *ctx, void *md)
+{
+ SHA256Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC3)
+
+static int
+__archive_libc3_sha256init(archive_sha256_ctx *ctx)
+{
+ SHA256Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc3_sha256update(archive_sha256_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ SHA256Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc3_sha256final(archive_sha256_ctx *ctx, void *md)
+{
+ SHA256Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA256_LIBMD)
+
+static int
+__archive_libmd_sha256init(archive_sha256_ctx *ctx)
+{
+ SHA256_Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libmd_sha256update(archive_sha256_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ SHA256_Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libmd_sha256final(archive_sha256_ctx *ctx, void *md)
+{
+ SHA256_Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM)
+
+static int
+__archive_libsystem_sha256init(archive_sha256_ctx *ctx)
+{
+ CC_SHA256_Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libsystem_sha256update(archive_sha256_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ CC_SHA256_Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libsystem_sha256final(archive_sha256_ctx *ctx, void *md)
+{
+ CC_SHA256_Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE)
+
+static int
+__archive_nettle_sha256init(archive_sha256_ctx *ctx)
+{
+ sha256_init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_nettle_sha256update(archive_sha256_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ sha256_update(ctx, insize, indata);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_nettle_sha256final(archive_sha256_ctx *ctx, void *md)
+{
+ sha256_digest(ctx, SHA256_DIGEST_SIZE, md);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL)
+
+static int
+__archive_openssl_sha256init(archive_sha256_ctx *ctx)
+{
+ EVP_DigestInit(ctx, EVP_sha256());
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_openssl_sha256update(archive_sha256_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ EVP_DigestUpdate(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_openssl_sha256final(archive_sha256_ctx *ctx, void *md)
+{
+ EVP_DigestFinal(ctx, md, NULL);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
+
+static int
+__archive_windowsapi_sha256init(archive_sha256_ctx *ctx)
+{
+ return (win_crypto_init(ctx, CALG_SHA_256));
+}
+
+static int
+__archive_windowsapi_sha256update(archive_sha256_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ return (win_crypto_Update(ctx, indata, insize));
+}
+
+static int
+__archive_windowsapi_sha256final(archive_sha256_ctx *ctx, void *md)
+{
+ return (win_crypto_Final(md, 32, ctx));
+}
+
+#else
+
+static int
+__archive_stub_sha256init(archive_sha256_ctx *ctx)
+{
+ (void)ctx; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+static int
+__archive_stub_sha256update(archive_sha256_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ (void)ctx; /* UNUSED */
+ (void)indata; /* UNUSED */
+ (void)insize; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+static int
+__archive_stub_sha256final(archive_sha256_ctx *ctx, void *md)
+{
+ (void)ctx; /* UNUSED */
+ (void)md; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+#endif
+
+/* SHA384 implementations */
+#if defined(ARCHIVE_CRYPTO_SHA384_LIBC)
+
+static int
+__archive_libc_sha384init(archive_sha384_ctx *ctx)
+{
+ SHA384_Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc_sha384update(archive_sha384_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ SHA384_Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc_sha384final(archive_sha384_ctx *ctx, void *md)
+{
+ SHA384_Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC2)
+
+static int
+__archive_libc2_sha384init(archive_sha384_ctx *ctx)
+{
+ SHA384Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc2_sha384update(archive_sha384_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ SHA384Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc2_sha384final(archive_sha384_ctx *ctx, void *md)
+{
+ SHA384Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC3)
+
+static int
+__archive_libc3_sha384init(archive_sha384_ctx *ctx)
+{
+ SHA384Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc3_sha384update(archive_sha384_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ SHA384Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc3_sha384final(archive_sha384_ctx *ctx, void *md)
+{
+ SHA384Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM)
+
+static int
+__archive_libsystem_sha384init(archive_sha384_ctx *ctx)
+{
+ CC_SHA384_Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libsystem_sha384update(archive_sha384_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ CC_SHA384_Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libsystem_sha384final(archive_sha384_ctx *ctx, void *md)
+{
+ CC_SHA384_Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE)
+
+static int
+__archive_nettle_sha384init(archive_sha384_ctx *ctx)
+{
+ sha384_init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_nettle_sha384update(archive_sha384_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ sha384_update(ctx, insize, indata);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_nettle_sha384final(archive_sha384_ctx *ctx, void *md)
+{
+ sha384_digest(ctx, SHA384_DIGEST_SIZE, md);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL)
+
+static int
+__archive_openssl_sha384init(archive_sha384_ctx *ctx)
+{
+ EVP_DigestInit(ctx, EVP_sha384());
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_openssl_sha384update(archive_sha384_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ EVP_DigestUpdate(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_openssl_sha384final(archive_sha384_ctx *ctx, void *md)
+{
+ EVP_DigestFinal(ctx, md, NULL);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
+
+static int
+__archive_windowsapi_sha384init(archive_sha384_ctx *ctx)
+{
+ return (win_crypto_init(ctx, CALG_SHA_384));
+}
+
+static int
+__archive_windowsapi_sha384update(archive_sha384_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ return (win_crypto_Update(ctx, indata, insize));
+}
+
+static int
+__archive_windowsapi_sha384final(archive_sha384_ctx *ctx, void *md)
+{
+ return (win_crypto_Final(md, 48, ctx));
+}
+
+#else
+
+static int
+__archive_stub_sha384init(archive_sha384_ctx *ctx)
+{
+ (void)ctx; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+static int
+__archive_stub_sha384update(archive_sha384_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ (void)ctx; /* UNUSED */
+ (void)indata; /* UNUSED */
+ (void)insize; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+static int
+__archive_stub_sha384final(archive_sha384_ctx *ctx, void *md)
+{
+ (void)ctx; /* UNUSED */
+ (void)md; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+#endif
+
+/* SHA512 implementations */
+#if defined(ARCHIVE_CRYPTO_SHA512_LIBC)
+
+static int
+__archive_libc_sha512init(archive_sha512_ctx *ctx)
+{
+ SHA512_Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc_sha512update(archive_sha512_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ SHA512_Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc_sha512final(archive_sha512_ctx *ctx, void *md)
+{
+ SHA512_Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC2)
+
+static int
+__archive_libc2_sha512init(archive_sha512_ctx *ctx)
+{
+ SHA512Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc2_sha512update(archive_sha512_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ SHA512Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc2_sha512final(archive_sha512_ctx *ctx, void *md)
+{
+ SHA512Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC3)
+
+static int
+__archive_libc3_sha512init(archive_sha512_ctx *ctx)
+{
+ SHA512Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc3_sha512update(archive_sha512_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ SHA512Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libc3_sha512final(archive_sha512_ctx *ctx, void *md)
+{
+ SHA512Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA512_LIBMD)
+
+static int
+__archive_libmd_sha512init(archive_sha512_ctx *ctx)
+{
+ SHA512_Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libmd_sha512update(archive_sha512_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ SHA512_Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libmd_sha512final(archive_sha512_ctx *ctx, void *md)
+{
+ SHA512_Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
+
+static int
+__archive_libsystem_sha512init(archive_sha512_ctx *ctx)
+{
+ CC_SHA512_Init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libsystem_sha512update(archive_sha512_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ CC_SHA512_Update(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_libsystem_sha512final(archive_sha512_ctx *ctx, void *md)
+{
+ CC_SHA512_Final(md, ctx);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
+
+static int
+__archive_nettle_sha512init(archive_sha512_ctx *ctx)
+{
+ sha512_init(ctx);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_nettle_sha512update(archive_sha512_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ sha512_update(ctx, insize, indata);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_nettle_sha512final(archive_sha512_ctx *ctx, void *md)
+{
+ sha512_digest(ctx, SHA512_DIGEST_SIZE, md);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
+
+static int
+__archive_openssl_sha512init(archive_sha512_ctx *ctx)
+{
+ EVP_DigestInit(ctx, EVP_sha512());
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_openssl_sha512update(archive_sha512_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ EVP_DigestUpdate(ctx, indata, insize);
+ return (ARCHIVE_OK);
+}
+
+static int
+__archive_openssl_sha512final(archive_sha512_ctx *ctx, void *md)
+{
+ EVP_DigestFinal(ctx, md, NULL);
+ return (ARCHIVE_OK);
+}
+
+#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
+
+static int
+__archive_windowsapi_sha512init(archive_sha512_ctx *ctx)
+{
+ return (win_crypto_init(ctx, CALG_SHA_512));
+}
+
+static int
+__archive_windowsapi_sha512update(archive_sha512_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ return (win_crypto_Update(ctx, indata, insize));
+}
+
+static int
+__archive_windowsapi_sha512final(archive_sha512_ctx *ctx, void *md)
+{
+ return (win_crypto_Final(md, 64, ctx));
+}
+
+#else
+
+static int
+__archive_stub_sha512init(archive_sha512_ctx *ctx)
+{
+ (void)ctx; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+static int
+__archive_stub_sha512update(archive_sha512_ctx *ctx, const void *indata,
+ size_t insize)
+{
+ (void)ctx; /* UNUSED */
+ (void)indata; /* UNUSED */
+ (void)insize; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+static int
+__archive_stub_sha512final(archive_sha512_ctx *ctx, void *md)
+{
+ (void)ctx; /* UNUSED */
+ (void)md; /* UNUSED */
+ return (ARCHIVE_FAILED);
+}
+
+#endif
+
+/* NOTE: Crypto functions are set based on availability and by the following
+ * order of preference.
+ * 1. libc
+ * 2. libc2
+ * 3. libc3
+ * 4. libSystem
+ * 5. OpenSSL
+ * 6. Windows API
+ */
+const struct archive_crypto __archive_crypto =
+{
+/* MD5 */
+#if defined(ARCHIVE_CRYPTO_MD5_LIBC)
+ &__archive_libc_md5init,
+ &__archive_libc_md5update,
+ &__archive_libc_md5final,
+#elif defined(ARCHIVE_CRYPTO_MD5_LIBMD)
+ &__archive_libmd_md5init,
+ &__archive_libmd_md5update,
+ &__archive_libmd_md5final,
+#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM)
+ &__archive_libsystem_md5init,
+ &__archive_libsystem_md5update,
+ &__archive_libsystem_md5final,
+#elif defined(ARCHIVE_CRYPTO_MD5_NETTLE)
+ &__archive_nettle_md5init,
+ &__archive_nettle_md5update,
+ &__archive_nettle_md5final,
+#elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL)
+ &__archive_openssl_md5init,
+ &__archive_openssl_md5update,
+ &__archive_openssl_md5final,
+#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
+ &__archive_windowsapi_md5init,
+ &__archive_windowsapi_md5update,
+ &__archive_windowsapi_md5final,
+#elif !defined(ARCHIVE_MD5_COMPILE_TEST)
+ &__archive_stub_md5init,
+ &__archive_stub_md5update,
+ &__archive_stub_md5final,
+#endif
+
+/* RIPEMD160 */
+#if defined(ARCHIVE_CRYPTO_RMD160_LIBC)
+ &__archive_libc_ripemd160init,
+ &__archive_libc_ripemd160update,
+ &__archive_libc_ripemd160final,
+#elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD)
+ &__archive_libmd_ripemd160init,
+ &__archive_libmd_ripemd160update,
+ &__archive_libmd_ripemd160final,
+#elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE)
+ &__archive_nettle_ripemd160init,
+ &__archive_nettle_ripemd160update,
+ &__archive_nettle_ripemd160final,
+#elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL)
+ &__archive_openssl_ripemd160init,
+ &__archive_openssl_ripemd160update,
+ &__archive_openssl_ripemd160final,
+#elif !defined(ARCHIVE_RMD160_COMPILE_TEST)
+ &__archive_stub_ripemd160init,
+ &__archive_stub_ripemd160update,
+ &__archive_stub_ripemd160final,
+#endif
+
+/* SHA1 */
+#if defined(ARCHIVE_CRYPTO_SHA1_LIBC)
+ &__archive_libc_sha1init,
+ &__archive_libc_sha1update,
+ &__archive_libc_sha1final,
+#elif defined(ARCHIVE_CRYPTO_SHA1_LIBMD)
+ &__archive_libmd_sha1init,
+ &__archive_libmd_sha1update,
+ &__archive_libmd_sha1final,
+#elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM)
+ &__archive_libsystem_sha1init,
+ &__archive_libsystem_sha1update,
+ &__archive_libsystem_sha1final,
+#elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE)
+ &__archive_nettle_sha1init,
+ &__archive_nettle_sha1update,
+ &__archive_nettle_sha1final,
+#elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL)
+ &__archive_openssl_sha1init,
+ &__archive_openssl_sha1update,
+ &__archive_openssl_sha1final,
+#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
+ &__archive_windowsapi_sha1init,
+ &__archive_windowsapi_sha1update,
+ &__archive_windowsapi_sha1final,
+#elif !defined(ARCHIVE_SHA1_COMPILE_TEST)
+ &__archive_stub_sha1init,
+ &__archive_stub_sha1update,
+ &__archive_stub_sha1final,
+#endif
+
+/* SHA256 */
+#if defined(ARCHIVE_CRYPTO_SHA256_LIBC)
+ &__archive_libc_sha256init,
+ &__archive_libc_sha256update,
+ &__archive_libc_sha256final,
+#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC2)
+ &__archive_libc2_sha256init,
+ &__archive_libc2_sha256update,
+ &__archive_libc2_sha256final,
+#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC3)
+ &__archive_libc3_sha256init,
+ &__archive_libc3_sha256update,
+ &__archive_libc3_sha256final,
+#elif defined(ARCHIVE_CRYPTO_SHA256_LIBMD)
+ &__archive_libmd_sha256init,
+ &__archive_libmd_sha256update,
+ &__archive_libmd_sha256final,
+#elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM)
+ &__archive_libsystem_sha256init,
+ &__archive_libsystem_sha256update,
+ &__archive_libsystem_sha256final,
+#elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE)
+ &__archive_nettle_sha256init,
+ &__archive_nettle_sha256update,
+ &__archive_nettle_sha256final,
+#elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL)
+ &__archive_openssl_sha256init,
+ &__archive_openssl_sha256update,
+ &__archive_openssl_sha256final,
+#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
+ &__archive_windowsapi_sha256init,
+ &__archive_windowsapi_sha256update,
+ &__archive_windowsapi_sha256final,
+#elif !defined(ARCHIVE_SHA256_COMPILE_TEST)
+ &__archive_stub_sha256init,
+ &__archive_stub_sha256update,
+ &__archive_stub_sha256final,
+#endif
+
+/* SHA384 */
+#if defined(ARCHIVE_CRYPTO_SHA384_LIBC)
+ &__archive_libc_sha384init,
+ &__archive_libc_sha384update,
+ &__archive_libc_sha384final,
+#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC2)
+ &__archive_libc2_sha384init,
+ &__archive_libc2_sha384update,
+ &__archive_libc2_sha384final,
+#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC3)
+ &__archive_libc3_sha384init,
+ &__archive_libc3_sha384update,
+ &__archive_libc3_sha384final,
+#elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM)
+ &__archive_libsystem_sha384init,
+ &__archive_libsystem_sha384update,
+ &__archive_libsystem_sha384final,
+#elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE)
+ &__archive_nettle_sha384init,
+ &__archive_nettle_sha384update,
+ &__archive_nettle_sha384final,
+#elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL)
+ &__archive_openssl_sha384init,
+ &__archive_openssl_sha384update,
+ &__archive_openssl_sha384final,
+#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
+ &__archive_windowsapi_sha384init,
+ &__archive_windowsapi_sha384update,
+ &__archive_windowsapi_sha384final,
+#elif !defined(ARCHIVE_SHA384_COMPILE_TEST)
+ &__archive_stub_sha384init,
+ &__archive_stub_sha384update,
+ &__archive_stub_sha384final,
+#endif
+
+/* SHA512 */
+#if defined(ARCHIVE_CRYPTO_SHA512_LIBC)
+ &__archive_libc_sha512init,
+ &__archive_libc_sha512update,
+ &__archive_libc_sha512final
+#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC2)
+ &__archive_libc2_sha512init,
+ &__archive_libc2_sha512update,
+ &__archive_libc2_sha512final
+#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC3)
+ &__archive_libc3_sha512init,
+ &__archive_libc3_sha512update,
+ &__archive_libc3_sha512final
+#elif defined(ARCHIVE_CRYPTO_SHA512_LIBMD)
+ &__archive_libmd_sha512init,
+ &__archive_libmd_sha512update,
+ &__archive_libmd_sha512final
+#elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
+ &__archive_libsystem_sha512init,
+ &__archive_libsystem_sha512update,
+ &__archive_libsystem_sha512final
+#elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
+ &__archive_nettle_sha512init,
+ &__archive_nettle_sha512update,
+ &__archive_nettle_sha512final,
+#elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
+ &__archive_openssl_sha512init,
+ &__archive_openssl_sha512update,
+ &__archive_openssl_sha512final
+#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
+ &__archive_windowsapi_sha512init,
+ &__archive_windowsapi_sha512update,
+ &__archive_windowsapi_sha512final
+#elif !defined(ARCHIVE_SHA512_COMPILE_TEST)
+ &__archive_stub_sha512init,
+ &__archive_stub_sha512update,
+ &__archive_stub_sha512final
+#endif
+};
diff --git a/contrib/libarchive/libarchive/archive_crypto_private.h b/contrib/libarchive/libarchive/archive_crypto_private.h
new file mode 100644
index 000000000000..f8b1fb3c3f54
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_crypto_private.h
@@ -0,0 +1,376 @@
+/*-
+* Copyright (c) 2003-2007 Tim Kientzle
+* Copyright (c) 2011 Andres Mejia
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
+#ifndef ARCHIVE_CRYPTO_PRIVATE_H_INCLUDED
+#define ARCHIVE_CRYPTO_PRIVATE_H_INCLUDED
+
+/*
+ * Crypto support in various Operating Systems:
+ *
+ * NetBSD:
+ * - MD5 and SHA1 in libc: without _ after algorithm name
+ * - SHA2 in libc: with _ after algorithm name
+ *
+ * OpenBSD:
+ * - MD5, SHA1 and SHA2 in libc: without _ after algorithm name
+ * - OpenBSD 4.4 and earlier have SHA2 in libc with _ after algorithm name
+ *
+ * DragonFly and FreeBSD:
+ * - MD5 libmd: without _ after algorithm name
+ * - SHA1, SHA256 and SHA512 in libmd: with _ after algorithm name
+ *
+ * Mac OS X (10.4 and later):
+ * - MD5, SHA1 and SHA2 in libSystem: with CC_ prefix and _ after algorithm name
+ *
+ * OpenSSL:
+ * - MD5, SHA1 and SHA2 in libcrypto: with _ after algorithm name
+ *
+ * Windows:
+ * - MD5, SHA1 and SHA2 in archive_crypto.c using Windows crypto API
+ */
+
+/* libc crypto headers */
+#if defined(ARCHIVE_CRYPTO_MD5_LIBC)
+#include <md5.h>
+#endif
+#if defined(ARCHIVE_CRYPTO_RMD160_LIBC)
+#include <rmd160.h>
+#endif
+#if defined(ARCHIVE_CRYPTO_SHA1_LIBC)
+#include <sha1.h>
+#endif
+#if defined(ARCHIVE_CRYPTO_SHA256_LIBC) ||\
+ defined(ARCHIVE_CRYPTO_SHA256_LIBC2) ||\
+ defined(ARCHIVE_CRYPTO_SHA256_LIBC3) ||\
+ defined(ARCHIVE_CRYPTO_SHA384_LIBC) ||\
+ defined(ARCHIVE_CRYPTO_SHA384_LIBC2) ||\
+ defined(ARCHIVE_CRYPTO_SHA384_LIBC3) ||\
+ defined(ARCHIVE_CRYPTO_SHA512_LIBC) ||\
+ defined(ARCHIVE_CRYPTO_SHA512_LIBC2) ||\
+ defined(ARCHIVE_CRYPTO_SHA512_LIBC3)
+#include <sha2.h>
+#endif
+
+/* libmd crypto headers */
+#if defined(ARCHIVE_CRYPTO_MD5_LIBMD) ||\
+ defined(ARCHIVE_CRYPTO_RMD160_LIBMD) ||\
+ defined(ARCHIVE_CRYPTO_SHA1_LIBMD) ||\
+ defined(ARCHIVE_CRYPTO_SHA256_LIBMD) ||\
+ defined(ARCHIVE_CRYPTO_SHA512_LIBMD)
+#define ARCHIVE_CRYPTO_LIBMD 1
+#endif
+
+#if defined(ARCHIVE_CRYPTO_MD5_LIBMD)
+#include <md5.h>
+#endif
+#if defined(ARCHIVE_CRYPTO_RMD160_LIBMD)
+#include <ripemd.h>
+#endif
+#if defined(ARCHIVE_CRYPTO_SHA1_LIBMD)
+#include <sha.h>
+#endif
+#if defined(ARCHIVE_CRYPTO_SHA256_LIBMD)
+#include <sha256.h>
+#endif
+#if defined(ARCHIVE_CRYPTO_SHA512_LIBMD)
+#include <sha512.h>
+#endif
+
+/* libSystem crypto headers */
+#if defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM) ||\
+ defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM) ||\
+ defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM) ||\
+ defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) ||\
+ defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
+#include <CommonCrypto/CommonDigest.h>
+#endif
+
+/* Nettle crypto headers */
+#if defined(ARCHIVE_CRYPTO_MD5_NETTLE)
+#include <nettle/md5.h>
+#endif
+#if defined(ARCHIVE_CRYPTO_RMD160_NETTLE)
+#include <nettle/ripemd160.h>
+#endif
+#if defined(ARCHIVE_CRYPTO_SHA1_NETTLE) ||\
+ defined(ARCHIVE_CRYPTO_SHA256_NETTLE) ||\
+ defined(ARCHIVE_CRYPTO_SHA384_NETTLE) ||\
+ defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
+#include <nettle/sha.h>
+#endif
+
+/* OpenSSL crypto headers */
+#if defined(ARCHIVE_CRYPTO_MD5_OPENSSL) ||\
+ defined(ARCHIVE_CRYPTO_RMD160_OPENSSL) ||\
+ defined(ARCHIVE_CRYPTO_SHA1_OPENSSL) ||\
+ defined(ARCHIVE_CRYPTO_SHA256_OPENSSL) ||\
+ defined(ARCHIVE_CRYPTO_SHA384_OPENSSL) ||\
+ defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
+#define ARCHIVE_CRYPTO_OPENSSL 1
+#include <openssl/evp.h>
+#endif
+
+/* Windows crypto headers */
+#if defined(ARCHIVE_CRYPTO_MD5_WIN) ||\
+ defined(ARCHIVE_CRYPTO_SHA1_WIN) ||\
+ defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\
+ defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\
+ defined(ARCHIVE_CRYPTO_SHA512_WIN)
+#include <wincrypt.h>
+typedef struct {
+ int valid;
+ HCRYPTPROV cryptProv;
+ HCRYPTHASH hash;
+} Digest_CTX;
+#endif
+
+/* typedefs */
+#if defined(ARCHIVE_CRYPTO_MD5_LIBC)
+typedef MD5_CTX archive_md5_ctx;
+#elif defined(ARCHIVE_CRYPTO_MD5_LIBMD)
+typedef MD5_CTX archive_md5_ctx;
+#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM)
+typedef CC_MD5_CTX archive_md5_ctx;
+#elif defined(ARCHIVE_CRYPTO_MD5_NETTLE)
+typedef struct md5_ctx archive_md5_ctx;
+#elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL)
+typedef EVP_MD_CTX archive_md5_ctx;
+#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
+typedef Digest_CTX archive_md5_ctx;
+#else
+typedef unsigned char archive_md5_ctx;
+#endif
+
+#if defined(ARCHIVE_CRYPTO_RMD160_LIBC)
+typedef RMD160_CTX archive_rmd160_ctx;
+#elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD)
+typedef RIPEMD160_CTX archive_rmd160_ctx;
+#elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE)
+typedef struct ripemd160_ctx archive_rmd160_ctx;
+#elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL)
+typedef EVP_MD_CTX archive_rmd160_ctx;
+#else
+typedef unsigned char archive_rmd160_ctx;
+#endif
+
+#if defined(ARCHIVE_CRYPTO_SHA1_LIBC)
+typedef SHA1_CTX archive_sha1_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA1_LIBMD)
+typedef SHA1_CTX archive_sha1_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM)
+typedef CC_SHA1_CTX archive_sha1_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE)
+typedef struct sha1_ctx archive_sha1_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL)
+typedef EVP_MD_CTX archive_sha1_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
+typedef Digest_CTX archive_sha1_ctx;
+#else
+typedef unsigned char archive_sha1_ctx;
+#endif
+
+#if defined(ARCHIVE_CRYPTO_SHA256_LIBC)
+typedef SHA256_CTX archive_sha256_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC2)
+typedef SHA256_CTX archive_sha256_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC3)
+typedef SHA2_CTX archive_sha256_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA256_LIBMD)
+typedef SHA256_CTX archive_sha256_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM)
+typedef CC_SHA256_CTX archive_sha256_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE)
+typedef struct sha256_ctx archive_sha256_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL)
+typedef EVP_MD_CTX archive_sha256_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
+typedef Digest_CTX archive_sha256_ctx;
+#else
+typedef unsigned char archive_sha256_ctx;
+#endif
+
+#if defined(ARCHIVE_CRYPTO_SHA384_LIBC)
+typedef SHA384_CTX archive_sha384_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC2)
+typedef SHA384_CTX archive_sha384_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC3)
+typedef SHA2_CTX archive_sha384_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM)
+typedef CC_SHA512_CTX archive_sha384_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE)
+typedef struct sha384_ctx archive_sha384_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL)
+typedef EVP_MD_CTX archive_sha384_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
+typedef Digest_CTX archive_sha384_ctx;
+#else
+typedef unsigned char archive_sha384_ctx;
+#endif
+
+#if defined(ARCHIVE_CRYPTO_SHA512_LIBC)
+typedef SHA512_CTX archive_sha512_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC2)
+typedef SHA512_CTX archive_sha512_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC3)
+typedef SHA2_CTX archive_sha512_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA512_LIBMD)
+typedef SHA512_CTX archive_sha512_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
+typedef CC_SHA512_CTX archive_sha512_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
+typedef struct sha512_ctx archive_sha512_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
+typedef EVP_MD_CTX archive_sha512_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
+typedef Digest_CTX archive_sha512_ctx;
+#else
+typedef unsigned char archive_sha512_ctx;
+#endif
+
+/* defines */
+#if defined(ARCHIVE_CRYPTO_MD5_LIBC) ||\
+ defined(ARCHIVE_CRYPTO_MD5_LIBMD) || \
+ defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM) ||\
+ defined(ARCHIVE_CRYPTO_MD5_NETTLE) ||\
+ defined(ARCHIVE_CRYPTO_MD5_OPENSSL) ||\
+ defined(ARCHIVE_CRYPTO_MD5_WIN)
+#define ARCHIVE_HAS_MD5
+#endif
+#define archive_md5_init(ctx)\
+ __archive_crypto.md5init(ctx)
+#define archive_md5_final(ctx, md)\
+ __archive_crypto.md5final(ctx, md)
+#define archive_md5_update(ctx, buf, n)\
+ __archive_crypto.md5update(ctx, buf, n)
+
+#if defined(ARCHIVE_CRYPTO_RMD160_LIBC) ||\
+ defined(ARCHIVE_CRYPTO_RMD160_NETTLE) ||\
+ defined(ARCHIVE_CRYPTO_RMD160_OPENSSL)
+#define ARCHIVE_HAS_RMD160
+#endif
+#define archive_rmd160_init(ctx)\
+ __archive_crypto.rmd160init(ctx)
+#define archive_rmd160_final(ctx, md)\
+ __archive_crypto.rmd160final(ctx, md)
+#define archive_rmd160_update(ctx, buf, n)\
+ __archive_crypto.rmd160update(ctx, buf, n)
+
+#if defined(ARCHIVE_CRYPTO_SHA1_LIBC) ||\
+ defined(ARCHIVE_CRYPTO_SHA1_LIBMD) || \
+ defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM) ||\
+ defined(ARCHIVE_CRYPTO_SHA1_NETTLE) ||\
+ defined(ARCHIVE_CRYPTO_SHA1_OPENSSL) ||\
+ defined(ARCHIVE_CRYPTO_SHA1_WIN)
+#define ARCHIVE_HAS_SHA1
+#endif
+#define archive_sha1_init(ctx)\
+ __archive_crypto.sha1init(ctx)
+#define archive_sha1_final(ctx, md)\
+ __archive_crypto.sha1final(ctx, md)
+#define archive_sha1_update(ctx, buf, n)\
+ __archive_crypto.sha1update(ctx, buf, n)
+
+#if defined(ARCHIVE_CRYPTO_SHA256_LIBC) ||\
+ defined(ARCHIVE_CRYPTO_SHA256_LIBC2) ||\
+ defined(ARCHIVE_CRYPTO_SHA256_LIBC3) ||\
+ defined(ARCHIVE_CRYPTO_SHA256_LIBMD) ||\
+ defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM) ||\
+ defined(ARCHIVE_CRYPTO_SHA256_NETTLE) ||\
+ defined(ARCHIVE_CRYPTO_SHA256_OPENSSL) ||\
+ defined(ARCHIVE_CRYPTO_SHA256_WIN)
+#define ARCHIVE_HAS_SHA256
+#endif
+#define archive_sha256_init(ctx)\
+ __archive_crypto.sha256init(ctx)
+#define archive_sha256_final(ctx, md)\
+ __archive_crypto.sha256final(ctx, md)
+#define archive_sha256_update(ctx, buf, n)\
+ __archive_crypto.sha256update(ctx, buf, n)
+
+#if defined(ARCHIVE_CRYPTO_SHA384_LIBC) ||\
+ defined(ARCHIVE_CRYPTO_SHA384_LIBC2) ||\
+ defined(ARCHIVE_CRYPTO_SHA384_LIBC3) ||\
+ defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) ||\
+ defined(ARCHIVE_CRYPTO_SHA384_NETTLE) ||\
+ defined(ARCHIVE_CRYPTO_SHA384_OPENSSL) ||\
+ defined(ARCHIVE_CRYPTO_SHA384_WIN)
+#define ARCHIVE_HAS_SHA384
+#endif
+#define archive_sha384_init(ctx)\
+ __archive_crypto.sha384init(ctx)
+#define archive_sha384_final(ctx, md)\
+ __archive_crypto.sha384final(ctx, md)
+#define archive_sha384_update(ctx, buf, n)\
+ __archive_crypto.sha384update(ctx, buf, n)
+
+#if defined(ARCHIVE_CRYPTO_SHA512_LIBC) ||\
+ defined(ARCHIVE_CRYPTO_SHA512_LIBC2) ||\
+ defined(ARCHIVE_CRYPTO_SHA512_LIBC3) ||\
+ defined(ARCHIVE_CRYPTO_SHA512_LIBMD) ||\
+ defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM) ||\
+ defined(ARCHIVE_CRYPTO_SHA512_NETTLE) ||\
+ defined(ARCHIVE_CRYPTO_SHA512_OPENSSL) ||\
+ defined(ARCHIVE_CRYPTO_SHA512_WIN)
+#define ARCHIVE_HAS_SHA512
+#endif
+#define archive_sha512_init(ctx)\
+ __archive_crypto.sha512init(ctx)
+#define archive_sha512_final(ctx, md)\
+ __archive_crypto.sha512final(ctx, md)
+#define archive_sha512_update(ctx, buf, n)\
+ __archive_crypto.sha512update(ctx, buf, n)
+
+/* Minimal interface to crypto functionality for internal use in libarchive */
+struct archive_crypto
+{
+ /* Message Digest */
+ int (*md5init)(archive_md5_ctx *ctx);
+ int (*md5update)(archive_md5_ctx *, const void *, size_t);
+ int (*md5final)(archive_md5_ctx *, void *);
+ int (*rmd160init)(archive_rmd160_ctx *);
+ int (*rmd160update)(archive_rmd160_ctx *, const void *, size_t);
+ int (*rmd160final)(archive_rmd160_ctx *, void *);
+ int (*sha1init)(archive_sha1_ctx *);
+ int (*sha1update)(archive_sha1_ctx *, const void *, size_t);
+ int (*sha1final)(archive_sha1_ctx *, void *);
+ int (*sha256init)(archive_sha256_ctx *);
+ int (*sha256update)(archive_sha256_ctx *, const void *, size_t);
+ int (*sha256final)(archive_sha256_ctx *, void *);
+ int (*sha384init)(archive_sha384_ctx *);
+ int (*sha384update)(archive_sha384_ctx *, const void *, size_t);
+ int (*sha384final)(archive_sha384_ctx *, void *);
+ int (*sha512init)(archive_sha512_ctx *);
+ int (*sha512update)(archive_sha512_ctx *, const void *, size_t);
+ int (*sha512final)(archive_sha512_ctx *, void *);
+};
+
+extern const struct archive_crypto __archive_crypto;
+
+#endif
diff --git a/contrib/libarchive/libarchive/archive_entry.3 b/contrib/libarchive/libarchive/archive_entry.3
index 35cb38546d7a..521494551264 100644
--- a/contrib/libarchive/libarchive/archive_entry.3
+++ b/contrib/libarchive/libarchive/archive_entry.3
@@ -1,4 +1,5 @@
.\" Copyright (c) 2003-2007 Tim Kientzle
+.\" Copyright (c) 2010 Joerg Sonnenberger
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -24,267 +25,25 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 12, 2008
+.Dd Feburary 22, 2010
.Dt ARCHIVE_ENTRY 3
.Os
.Sh NAME
-.Nm archive_entry_acl_add_entry ,
-.Nm archive_entry_acl_add_entry_w ,
-.Nm archive_entry_acl_clear ,
-.Nm archive_entry_acl_count ,
-.Nm archive_entry_acl_next ,
-.Nm archive_entry_acl_next_w ,
-.Nm archive_entry_acl_reset ,
-.Nm archive_entry_acl_text_w ,
-.Nm archive_entry_atime ,
-.Nm archive_entry_atime_nsec ,
.Nm archive_entry_clear ,
.Nm archive_entry_clone ,
-.Nm archive_entry_copy_fflags_text ,
-.Nm archive_entry_copy_fflags_text_w ,
-.Nm archive_entry_copy_gname ,
-.Nm archive_entry_copy_gname_w ,
-.Nm archive_entry_copy_hardlink ,
-.Nm archive_entry_copy_hardlink_w ,
-.Nm archive_entry_copy_link ,
-.Nm archive_entry_copy_link_w ,
-.Nm archive_entry_copy_pathname_w ,
-.Nm archive_entry_copy_sourcepath ,
-.Nm archive_entry_copy_stat ,
-.Nm archive_entry_copy_symlink ,
-.Nm archive_entry_copy_symlink_w ,
-.Nm archive_entry_copy_uname ,
-.Nm archive_entry_copy_uname_w ,
-.Nm archive_entry_dev ,
-.Nm archive_entry_devmajor ,
-.Nm archive_entry_devminor ,
-.Nm archive_entry_filetype ,
-.Nm archive_entry_fflags ,
-.Nm archive_entry_fflags_text ,
.Nm archive_entry_free ,
-.Nm archive_entry_gid ,
-.Nm archive_entry_gname ,
-.Nm archive_entry_hardlink ,
-.Nm archive_entry_ino ,
-.Nm archive_entry_mode ,
-.Nm archive_entry_mtime ,
-.Nm archive_entry_mtime_nsec ,
-.Nm archive_entry_nlink ,
.Nm archive_entry_new ,
-.Nm archive_entry_pathname ,
-.Nm archive_entry_pathname_w ,
-.Nm archive_entry_rdev ,
-.Nm archive_entry_rdevmajor ,
-.Nm archive_entry_rdevminor ,
-.Nm archive_entry_set_atime ,
-.Nm archive_entry_set_ctime ,
-.Nm archive_entry_set_dev ,
-.Nm archive_entry_set_devmajor ,
-.Nm archive_entry_set_devminor ,
-.Nm archive_entry_set_filetype ,
-.Nm archive_entry_set_fflags ,
-.Nm archive_entry_set_gid ,
-.Nm archive_entry_set_gname ,
-.Nm archive_entry_set_hardlink ,
-.Nm archive_entry_set_link ,
-.Nm archive_entry_set_mode ,
-.Nm archive_entry_set_mtime ,
-.Nm archive_entry_set_pathname ,
-.Nm archive_entry_set_rdevmajor ,
-.Nm archive_entry_set_rdevminor ,
-.Nm archive_entry_set_size ,
-.Nm archive_entry_set_symlink ,
-.Nm archive_entry_set_uid ,
-.Nm archive_entry_set_uname ,
-.Nm archive_entry_size ,
-.Nm archive_entry_sourcepath ,
-.Nm archive_entry_stat ,
-.Nm archive_entry_symlink ,
-.Nm archive_entry_uid ,
-.Nm archive_entry_uname
-.Nd functions for manipulating archive entry descriptions
+.Nd functions for managing archive entry descriptions
.Sh SYNOPSIS
.In archive_entry.h
-.Ft void
-.Fo archive_entry_acl_add_entry
-.Fa "struct archive_entry *"
-.Fa "int type"
-.Fa "int permset"
-.Fa "int tag"
-.Fa "int qual"
-.Fa "const char *name"
-.Fc
-.Ft void
-.Fo archive_entry_acl_add_entry_w
-.Fa "struct archive_entry *"
-.Fa "int type"
-.Fa "int permset"
-.Fa "int tag"
-.Fa "int qual"
-.Fa "const wchar_t *name"
-.Fc
-.Ft void
-.Fn archive_entry_acl_clear "struct archive_entry *"
-.Ft int
-.Fn archive_entry_acl_count "struct archive_entry *" "int type"
-.Ft int
-.Fo archive_entry_acl_next
-.Fa "struct archive_entry *"
-.Fa "int want_type"
-.Fa "int *type"
-.Fa "int *permset"
-.Fa "int *tag"
-.Fa "int *qual"
-.Fa "const char **name"
-.Fc
-.Ft int
-.Fo archive_entry_acl_next_w
-.Fa "struct archive_entry *"
-.Fa "int want_type"
-.Fa "int *type"
-.Fa "int *permset"
-.Fa "int *tag"
-.Fa "int *qual"
-.Fa "const wchar_t **name"
-.Fc
-.Ft int
-.Fn archive_entry_acl_reset "struct archive_entry *" "int want_type"
-.Ft const wchar_t *
-.Fn archive_entry_acl_text_w "struct archive_entry *" "int flags"
-.Ft time_t
-.Fn archive_entry_atime "struct archive_entry *"
-.Ft long
-.Fn archive_entry_atime_nsec "struct archive_entry *"
.Ft "struct archive_entry *"
.Fn archive_entry_clear "struct archive_entry *"
.Ft struct archive_entry *
.Fn archive_entry_clone "struct archive_entry *"
-.Ft const char * *
-.Fn archive_entry_copy_fflags_text_w "struct archive_entry *" "const char *"
-.Ft const wchar_t *
-.Fn archive_entry_copy_fflags_text_w "struct archive_entry *" "const wchar_t *"
-.Ft void
-.Fn archive_entry_copy_gname "struct archive_entry *" "const char *"
-.Ft void
-.Fn archive_entry_copy_gname_w "struct archive_entry *" "const wchar_t *"
-.Ft void
-.Fn archive_entry_copy_hardlink "struct archive_entry *" "const char *"
-.Ft void
-.Fn archive_entry_copy_hardlink_w "struct archive_entry *" "const wchar_t *"
-.Ft void
-.Fn archive_entry_copy_sourcepath "struct archive_entry *" "const char *"
-.Ft void
-.Fn archive_entry_copy_pathname_w "struct archive_entry *" "const wchar_t *"
-.Ft void
-.Fn archive_entry_copy_stat "struct archive_entry *" "const struct stat *"
-.Ft void
-.Fn archive_entry_copy_symlink "struct archive_entry *" "const char *"
-.Ft void
-.Fn archive_entry_copy_symlink_w "struct archive_entry *" "const wchar_t *"
-.Ft void
-.Fn archive_entry_copy_uname "struct archive_entry *" "const char *"
-.Ft void
-.Fn archive_entry_copy_uname_w "struct archive_entry *" "const wchar_t *"
-.Ft dev_t
-.Fn archive_entry_dev "struct archive_entry *"
-.Ft dev_t
-.Fn archive_entry_devmajor "struct archive_entry *"
-.Ft dev_t
-.Fn archive_entry_devminor "struct archive_entry *"
-.Ft mode_t
-.Fn archive_entry_filetype "struct archive_entry *"
-.Ft void
-.Fo archive_entry_fflags
-.Fa "struct archive_entry *"
-.Fa "unsigned long *set"
-.Fa "unsigned long *clear"
-.Fc
-.Ft const char *
-.Fn archive_entry_fflags_text "struct archive_entry *"
.Ft void
.Fn archive_entry_free "struct archive_entry *"
-.Ft const char *
-.Fn archive_entry_gname "struct archive_entry *"
-.Ft const char *
-.Fn archive_entry_hardlink "struct archive_entry *"
-.Ft ino_t
-.Fn archive_entry_ino "struct archive_entry *"
-.Ft mode_t
-.Fn archive_entry_mode "struct archive_entry *"
-.Ft time_t
-.Fn archive_entry_mtime "struct archive_entry *"
-.Ft long
-.Fn archive_entry_mtime_nsec "struct archive_entry *"
-.Ft unsigned int
-.Fn archive_entry_nlink "struct archive_entry *"
.Ft struct archive_entry *
.Fn archive_entry_new "void"
-.Ft const char *
-.Fn archive_entry_pathname "struct archive_entry *"
-.Ft const wchar_t *
-.Fn archive_entry_pathname_w "struct archive_entry *"
-.Ft dev_t
-.Fn archive_entry_rdev "struct archive_entry *"
-.Ft dev_t
-.Fn archive_entry_rdevmajor "struct archive_entry *"
-.Ft dev_t
-.Fn archive_entry_rdevminor "struct archive_entry *"
-.Ft void
-.Fn archive_entry_set_dev "struct archive_entry *" "dev_t"
-.Ft void
-.Fn archive_entry_set_devmajor "struct archive_entry *" "dev_t"
-.Ft void
-.Fn archive_entry_set_devminor "struct archive_entry *" "dev_t"
-.Ft void
-.Fn archive_entry_set_filetype "struct archive_entry *" "unsigned int"
-.Ft void
-.Fo archive_entry_set_fflags
-.Fa "struct archive_entry *"
-.Fa "unsigned long set"
-.Fa "unsigned long clear"
-.Fc
-.Ft void
-.Fn archive_entry_set_gid "struct archive_entry *" "gid_t"
-.Ft void
-.Fn archive_entry_set_gname "struct archive_entry *" "const char *"
-.Ft void
-.Fn archive_entry_set_hardlink "struct archive_entry *" "const char *"
-.Ft void
-.Fn archive_entry_set_ino "struct archive_entry *" "unsigned long"
-.Ft void
-.Fn archive_entry_set_link "struct archive_entry *" "const char *"
-.Ft void
-.Fn archive_entry_set_mode "struct archive_entry *" "mode_t"
-.Ft void
-.Fn archive_entry_set_mtime "struct archive_entry *" "time_t" "long nanos"
-.Ft void
-.Fn archive_entry_set_nlink "struct archive_entry *" "unsigned int"
-.Ft void
-.Fn archive_entry_set_pathname "struct archive_entry *" "const char *"
-.Ft void
-.Fn archive_entry_set_rdev "struct archive_entry *" "dev_t"
-.Ft void
-.Fn archive_entry_set_rdevmajor "struct archive_entry *" "dev_t"
-.Ft void
-.Fn archive_entry_set_rdevminor "struct archive_entry *" "dev_t"
-.Ft void
-.Fn archive_entry_set_size "struct archive_entry *" "int64_t"
-.Ft void
-.Fn archive_entry_set_symlink "struct archive_entry *" "const char *"
-.Ft void
-.Fn archive_entry_set_uid "struct archive_entry *" "uid_t"
-.Ft void
-.Fn archive_entry_set_uname "struct archive_entry *" "const char *"
-.Ft int64_t
-.Fn archive_entry_size "struct archive_entry *"
-.Ft const char *
-.Fn archive_entry_sourcepath "struct archive_entry *"
-.Ft const struct stat *
-.Fn archive_entry_stat "struct archive_entry *"
-.Ft const char *
-.Fn archive_entry_symlink "struct archive_entry *"
-.Ft const char *
-.Fn archive_entry_uname "struct archive_entry *"
.Sh DESCRIPTION
These functions create and manipulate data objects that
represent entries within an archive.
@@ -320,8 +79,24 @@ Allocate and return a blank
.Tn struct archive_entry
object.
.El
-.Ss Set and Get Functions
-Most of the functions here set or read entries in an object.
+.Ss Function groups
+Due to high number of functions, the accessor functions can be found in
+man pages grouped by the purpose.
+.Bl -tag -width ".Xr archive_entry_perms 3"
+.It Xr archive_entry_acl 3
+Access Control List manipulation
+.It Xr archive_entry_paths 3
+Path name manipulation
+.It Xr archive_entry_perms 3
+User, group and mode manipulation
+.It Xr archive_entry_stat 3
+Functions not in the other groups and copying to/from
+.Vt struct stat .
+.It Xr archive_entry_time 3
+Time field manipulation
+.El
+.Pp
+Most of the functions set or read entries in an object.
Such functions have one of the following forms:
.Bl -tag -compact -width indent
.It Fn archive_entry_set_XXXX
@@ -350,75 +125,15 @@ Similarly, if you store a wide string and then store a
narrow string for the same data, the previously-set wide string will
be discarded in favor of the new data.
.Pp
-There are a few set/get functions that merit additional description:
-.Bl -tag -compact -width indent
-.It Fn archive_entry_set_link
-This function sets the symlink field if it is already set.
-Otherwise, it sets the hardlink field.
-.El
-.Ss File Flags
-File flags are transparently converted between a bitmap
-representation and a textual format.
-For example, if you set the bitmap and ask for text, the library
-will build a canonical text format.
-However, if you set a text format and request a text format,
-you will get back the same text, even if it is ill-formed.
-If you need to canonicalize a textual flags string, you should first set the
-text form, then request the bitmap form, then use that to set the bitmap form.
-Setting the bitmap format will clear the internal text representation
-and force it to be reconstructed when you next request the text form.
-.Pp
-The bitmap format consists of two integers, one containing bits
-that should be set, the other specifying bits that should be
-cleared.
-Bits not mentioned in either bitmap will be ignored.
-Usually, the bitmap of bits to be cleared will be set to zero.
-In unusual circumstances, you can force a fully-specified set
-of file flags by setting the bitmap of flags to clear to the complement
-of the bitmap of flags to set.
-(This differs from
-.Xr fflagstostr 3 ,
-which only includes names for set bits.)
-Converting a bitmap to a textual string is a platform-specific
-operation; bits that are not meaningful on the current platform
-will be ignored.
-.Pp
-The canonical text format is a comma-separated list of flag names.
-The
-.Fn archive_entry_copy_fflags_text
-and
-.Fn archive_entry_copy_fflags_text_w
-functions parse the provided text and sets the internal bitmap values.
-This is a platform-specific operation; names that are not meaningful
-on the current platform will be ignored.
-The function returns a pointer to the start of the first name that was not
-recognized, or NULL if every name was recognized.
-Note that every name--including names that follow an unrecognized name--will
-be evaluated, and the bitmaps will be set to reflect every name that is
-recognized.
-(In particular, this differs from
-.Xr strtofflags 3 ,
-which stops parsing at the first unrecognized name.)
-.Ss ACL Handling
-XXX This needs serious help.
-XXX
-.Pp
-An
-.Dq Access Control List
-(ACL) is a list of permissions that grant access to particular users or
-groups beyond what would normally be provided by standard POSIX mode bits.
-The ACL handling here addresses some deficiencies in the POSIX.1e draft 17 ACL
-specification.
-In particular, POSIX.1e draft 17 specifies several different formats, but
-none of those formats include both textual user/group names and numeric
-UIDs/GIDs.
-.Pp
-XXX explain ACL stuff XXX
.\" .Sh EXAMPLE
.\" .Sh RETURN VALUES
.\" .Sh ERRORS
.Sh SEE ALSO
-.Xr archive 3
+.Xr archive 3 ,
+.Xr archive_entry_acl 3 ,
+.Xr archive_entry_paths 3 ,
+.Xr archive_entry_perms 3 ,
+.Xr archive_entry_time 3
.Sh HISTORY
The
.Nm libarchive
diff --git a/contrib/libarchive/libarchive/archive_entry.c b/contrib/libarchive/libarchive/archive_entry.c
index 1202a8a28297..f723a4d17a0c 100644
--- a/contrib/libarchive/libarchive/archive_entry.c
+++ b/contrib/libarchive/libarchive/archive_entry.c
@@ -39,6 +39,9 @@ __FBSDID("$FreeBSD$");
#include <sys/sysmacros.h>
#define HAVE_MAJOR
#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
@@ -68,13 +71,12 @@ __FBSDID("$FreeBSD$");
#endif
#include "archive.h"
+#include "archive_acl_private.h"
#include "archive_entry.h"
+#include "archive_entry_locale.h"
#include "archive_private.h"
#include "archive_entry_private.h"
-#undef max
-#define max(a, b) ((a)>(b)?(a):(b))
-
#if !defined(HAVE_MAJOR) && !defined(major)
/* Replacement for major/minor/makedev. */
#define major(x) ((int)(0x00ff & ((x) >> 8)))
@@ -98,39 +100,26 @@ __FBSDID("$FreeBSD$");
#define ae_makedev(maj, min) makedev((maj), (min))
#endif
-static void aes_clean(struct aes *);
-static void aes_copy(struct aes *dest, struct aes *src);
-static const char * aes_get_mbs(struct aes *);
-static const wchar_t * aes_get_wcs(struct aes *);
-static int aes_set_mbs(struct aes *, const char *mbs);
-static int aes_copy_mbs(struct aes *, const char *mbs);
-/* static void aes_set_wcs(struct aes *, const wchar_t *wcs); */
-static int aes_copy_wcs(struct aes *, const wchar_t *wcs);
-static int aes_copy_wcs_len(struct aes *, const wchar_t *wcs, size_t);
+/*
+ * This adjustment is needed to support the following idiom for adding
+ * 1000ns to the stored time:
+ * archive_entry_set_atime(archive_entry_atime(),
+ * archive_entry_atime_nsec() + 1000)
+ * The additional if() here compensates for ambiguity in the C standard,
+ * which permits two possible interpretations of a % b when a is negative.
+ */
+#define FIX_NS(t,ns) \
+ do { \
+ t += ns / 1000000000; \
+ ns %= 1000000000; \
+ if (ns < 0) { --t; ns += 1000000000; } \
+ } while (0)
static char * ae_fflagstostr(unsigned long bitset, unsigned long bitclear);
static const wchar_t *ae_wcstofflags(const wchar_t *stringp,
unsigned long *setp, unsigned long *clrp);
static const char *ae_strtofflags(const char *stringp,
unsigned long *setp, unsigned long *clrp);
-static void append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
- const wchar_t *wname, int perm, int id);
-static void append_id_w(wchar_t **wp, int id);
-
-static int acl_special(struct archive_entry *entry,
- int type, int permset, int tag);
-static struct ae_acl *acl_new_entry(struct archive_entry *entry,
- int type, int permset, int tag, int id);
-static int isint_w(const wchar_t *start, const wchar_t *end, int *result);
-static int ismode_w(const wchar_t *start, const wchar_t *end, int *result);
-static void next_field_w(const wchar_t **wp, const wchar_t **start,
- const wchar_t **end, wchar_t *sep);
-static int prefix_w(const wchar_t *start, const wchar_t *end,
- const wchar_t *test);
-static void
-archive_entry_acl_add_entry_w_len(struct archive_entry *entry, int type,
- int permset, int tag, int id, const wchar_t *name, size_t);
-
#ifndef HAVE_WCSCPY
static wchar_t * wcscpy(wchar_t *s1, const wchar_t *s2)
@@ -154,214 +143,6 @@ static size_t wcslen(const wchar_t *s)
/* Good enough for simple equality testing, but not for sorting. */
#define wmemcmp(a,b,i) memcmp((a), (b), (i) * sizeof(wchar_t))
#endif
-#ifndef HAVE_WMEMCPY
-#define wmemcpy(a,b,i) (wchar_t *)memcpy((a), (b), (i) * sizeof(wchar_t))
-#endif
-
-static void
-aes_clean(struct aes *aes)
-{
- if (aes->aes_wcs) {
- free((wchar_t *)(uintptr_t)aes->aes_wcs);
- aes->aes_wcs = NULL;
- }
- archive_string_free(&(aes->aes_mbs));
- archive_string_free(&(aes->aes_utf8));
- aes->aes_set = 0;
-}
-
-static void
-aes_copy(struct aes *dest, struct aes *src)
-{
- wchar_t *wp;
-
- dest->aes_set = src->aes_set;
- archive_string_copy(&(dest->aes_mbs), &(src->aes_mbs));
- archive_string_copy(&(dest->aes_utf8), &(src->aes_utf8));
-
- if (src->aes_wcs != NULL) {
- wp = (wchar_t *)malloc((wcslen(src->aes_wcs) + 1)
- * sizeof(wchar_t));
- if (wp == NULL)
- __archive_errx(1, "No memory for aes_copy()");
- wcscpy(wp, src->aes_wcs);
- dest->aes_wcs = wp;
- }
-}
-
-static const char *
-aes_get_utf8(struct aes *aes)
-{
- if (aes->aes_set & AES_SET_UTF8)
- return (aes->aes_utf8.s);
- if ((aes->aes_set & AES_SET_WCS)
- && archive_strappend_w_utf8(&(aes->aes_utf8), aes->aes_wcs) != NULL) {
- aes->aes_set |= AES_SET_UTF8;
- return (aes->aes_utf8.s);
- }
- return (NULL);
-}
-
-static const char *
-aes_get_mbs(struct aes *aes)
-{
- /* If we already have an MBS form, return that immediately. */
- if (aes->aes_set & AES_SET_MBS)
- return (aes->aes_mbs.s);
- /* If there's a WCS form, try converting with the native locale. */
- if ((aes->aes_set & AES_SET_WCS)
- && archive_strappend_w_mbs(&(aes->aes_mbs), aes->aes_wcs) != NULL) {
- aes->aes_set |= AES_SET_MBS;
- return (aes->aes_mbs.s);
- }
- /* We'll use UTF-8 for MBS if all else fails. */
- return (aes_get_utf8(aes));
-}
-
-static const wchar_t *
-aes_get_wcs(struct aes *aes)
-{
- wchar_t *w;
- size_t r;
-
- /* Return WCS form if we already have it. */
- if (aes->aes_set & AES_SET_WCS)
- return (aes->aes_wcs);
-
- if (aes->aes_set & AES_SET_MBS) {
- /* Try converting MBS to WCS using native locale. */
- /*
- * No single byte will be more than one wide character,
- * so this length estimate will always be big enough.
- */
- size_t wcs_length = aes->aes_mbs.length;
-
- w = (wchar_t *)malloc((wcs_length + 1) * sizeof(wchar_t));
- if (w == NULL)
- __archive_errx(1, "No memory for aes_get_wcs()");
- r = mbstowcs(w, aes->aes_mbs.s, wcs_length);
- if (r != (size_t)-1 && r != 0) {
- w[r] = 0;
- aes->aes_set |= AES_SET_WCS;
- return (aes->aes_wcs = w);
- }
- free(w);
- }
-
- if (aes->aes_set & AES_SET_UTF8) {
- /* Try converting UTF8 to WCS. */
- aes->aes_wcs = __archive_string_utf8_w(&(aes->aes_utf8));
- if (aes->aes_wcs != NULL)
- aes->aes_set |= AES_SET_WCS;
- return (aes->aes_wcs);
- }
- return (NULL);
-}
-
-static int
-aes_set_mbs(struct aes *aes, const char *mbs)
-{
- return (aes_copy_mbs(aes, mbs));
-}
-
-static int
-aes_copy_mbs(struct aes *aes, const char *mbs)
-{
- if (mbs == NULL) {
- aes->aes_set = 0;
- return (0);
- }
- aes->aes_set = AES_SET_MBS; /* Only MBS form is set now. */
- archive_strcpy(&(aes->aes_mbs), mbs);
- archive_string_empty(&(aes->aes_utf8));
- if (aes->aes_wcs) {
- free((wchar_t *)(uintptr_t)aes->aes_wcs);
- aes->aes_wcs = NULL;
- }
- return (0);
-}
-
-/*
- * The 'update' form tries to proactively update all forms of
- * this string (WCS and MBS) and returns an error if any of
- * them fail. This is used by the 'pax' handler, for instance,
- * to detect and report character-conversion failures early while
- * still allowing clients to get potentially useful values from
- * the more tolerant lazy conversions. (get_mbs and get_wcs will
- * strive to give the user something useful, so you can get hopefully
- * usable values even if some of the character conversions are failing.)
- */
-static int
-aes_update_utf8(struct aes *aes, const char *utf8)
-{
- if (utf8 == NULL) {
- aes->aes_set = 0;
- return (1); /* Succeeded in clearing everything. */
- }
-
- /* Save the UTF8 string. */
- archive_strcpy(&(aes->aes_utf8), utf8);
-
- /* Empty the mbs and wcs strings. */
- archive_string_empty(&(aes->aes_mbs));
- if (aes->aes_wcs) {
- free((wchar_t *)(uintptr_t)aes->aes_wcs);
- aes->aes_wcs = NULL;
- }
-
- aes->aes_set = AES_SET_UTF8; /* Only UTF8 is set now. */
-
- /* TODO: We should just do a direct UTF-8 to MBS conversion
- * here. That would be faster, use less space, and give the
- * same information. (If a UTF-8 to MBS conversion succeeds,
- * then UTF-8->WCS and Unicode->MBS conversions will both
- * succeed.) */
-
- /* Try converting UTF8 to WCS, return false on failure. */
- aes->aes_wcs = __archive_string_utf8_w(&(aes->aes_utf8));
- if (aes->aes_wcs == NULL)
- return (0);
- aes->aes_set = AES_SET_UTF8 | AES_SET_WCS; /* Both UTF8 and WCS set. */
-
- /* Try converting WCS to MBS, return false on failure. */
- if (archive_strappend_w_mbs(&(aes->aes_mbs), aes->aes_wcs) == NULL)
- return (0);
- aes->aes_set = AES_SET_UTF8 | AES_SET_WCS | AES_SET_MBS;
-
- /* All conversions succeeded. */
- return (1);
-}
-
-static int
-aes_copy_wcs(struct aes *aes, const wchar_t *wcs)
-{
- return aes_copy_wcs_len(aes, wcs, wcs == NULL ? 0 : wcslen(wcs));
-}
-
-static int
-aes_copy_wcs_len(struct aes *aes, const wchar_t *wcs, size_t len)
-{
- wchar_t *w;
-
- if (wcs == NULL) {
- aes->aes_set = 0;
- return (0);
- }
- aes->aes_set = AES_SET_WCS; /* Only WCS form set. */
- archive_string_empty(&(aes->aes_mbs));
- archive_string_empty(&(aes->aes_utf8));
- if (aes->aes_wcs) {
- free((wchar_t *)(uintptr_t)aes->aes_wcs);
- aes->aes_wcs = NULL;
- }
- w = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
- if (w == NULL)
- __archive_errx(1, "No memory for aes_copy_wcs()");
- wmemcpy(w, wcs, len);
- w[len] = L'\0';
- aes->aes_wcs = w;
- return (0);
-}
/****************************************************************************
*
@@ -374,15 +155,17 @@ archive_entry_clear(struct archive_entry *entry)
{
if (entry == NULL)
return (NULL);
- aes_clean(&entry->ae_fflags_text);
- aes_clean(&entry->ae_gname);
- aes_clean(&entry->ae_hardlink);
- aes_clean(&entry->ae_pathname);
- aes_clean(&entry->ae_sourcepath);
- aes_clean(&entry->ae_symlink);
- aes_clean(&entry->ae_uname);
- archive_entry_acl_clear(entry);
+ archive_mstring_clean(&entry->ae_fflags_text);
+ archive_mstring_clean(&entry->ae_gname);
+ archive_mstring_clean(&entry->ae_hardlink);
+ archive_mstring_clean(&entry->ae_pathname);
+ archive_mstring_clean(&entry->ae_sourcepath);
+ archive_mstring_clean(&entry->ae_symlink);
+ archive_mstring_clean(&entry->ae_uname);
+ archive_entry_copy_mac_metadata(entry, NULL, 0);
+ archive_acl_clear(&entry->acl);
archive_entry_xattr_clear(entry);
+ archive_entry_sparse_clear(entry);
free(entry->stat);
memset(entry, 0, sizeof(*entry));
return entry;
@@ -392,36 +175,38 @@ struct archive_entry *
archive_entry_clone(struct archive_entry *entry)
{
struct archive_entry *entry2;
- struct ae_acl *ap, *ap2;
struct ae_xattr *xp;
+ struct ae_sparse *sp;
+ size_t s;
+ const void *p;
/* Allocate new structure and copy over all of the fields. */
- entry2 = (struct archive_entry *)malloc(sizeof(*entry2));
+ /* TODO: Should we copy the archive over? Or require a new archive
+ * as an argument? */
+ entry2 = archive_entry_new2(entry->archive);
if (entry2 == NULL)
return (NULL);
- memset(entry2, 0, sizeof(*entry2));
entry2->ae_stat = entry->ae_stat;
entry2->ae_fflags_set = entry->ae_fflags_set;
entry2->ae_fflags_clear = entry->ae_fflags_clear;
- aes_copy(&entry2->ae_fflags_text, &entry->ae_fflags_text);
- aes_copy(&entry2->ae_gname, &entry->ae_gname);
- aes_copy(&entry2->ae_hardlink, &entry->ae_hardlink);
- aes_copy(&entry2->ae_pathname, &entry->ae_pathname);
- aes_copy(&entry2->ae_sourcepath, &entry->ae_sourcepath);
- aes_copy(&entry2->ae_symlink, &entry->ae_symlink);
+ /* TODO: XXX If clone can have a different archive, what do we do here if
+ * character sets are different? XXX */
+ archive_mstring_copy(&entry2->ae_fflags_text, &entry->ae_fflags_text);
+ archive_mstring_copy(&entry2->ae_gname, &entry->ae_gname);
+ archive_mstring_copy(&entry2->ae_hardlink, &entry->ae_hardlink);
+ archive_mstring_copy(&entry2->ae_pathname, &entry->ae_pathname);
+ archive_mstring_copy(&entry2->ae_sourcepath, &entry->ae_sourcepath);
+ archive_mstring_copy(&entry2->ae_symlink, &entry->ae_symlink);
entry2->ae_set = entry->ae_set;
- aes_copy(&entry2->ae_uname, &entry->ae_uname);
+ archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname);
/* Copy ACL data over. */
- ap = entry->acl_head;
- while (ap != NULL) {
- ap2 = acl_new_entry(entry2,
- ap->type, ap->permset, ap->tag, ap->id);
- if (ap2 != NULL)
- aes_copy(&ap2->name, &ap->name);
- ap = ap->next;
- }
+ archive_acl_copy(&entry2->acl, &entry->acl);
+
+ /* Copy Mac OS metadata. */
+ p = archive_entry_mac_metadata(entry, &s);
+ archive_entry_copy_mac_metadata(entry2, p, s);
/* Copy xattr data over. */
xp = entry->xattr_head;
@@ -431,6 +216,14 @@ archive_entry_clone(struct archive_entry *entry)
xp = xp->next;
}
+ /* Copy sparse data over. */
+ sp = entry->sparse_head;
+ while (sp != NULL) {
+ archive_entry_sparse_add_entry(entry2,
+ sp->offset, sp->length);
+ sp = sp->next;
+ }
+
return (entry2);
}
@@ -444,12 +237,19 @@ archive_entry_free(struct archive_entry *entry)
struct archive_entry *
archive_entry_new(void)
{
+ return archive_entry_new2(NULL);
+}
+
+struct archive_entry *
+archive_entry_new2(struct archive *a)
+{
struct archive_entry *entry;
entry = (struct archive_entry *)malloc(sizeof(*entry));
if (entry == NULL)
return (NULL);
memset(entry, 0, sizeof(*entry));
+ entry->archive = a;
return (entry);
}
@@ -521,6 +321,12 @@ archive_entry_dev(struct archive_entry *entry)
return (entry->ae_stat.aest_dev);
}
+int
+archive_entry_dev_is_set(struct archive_entry *entry)
+{
+ return (entry->ae_set & AE_SET_DEV);
+}
+
dev_t
archive_entry_devmajor(struct archive_entry *entry)
{
@@ -542,7 +348,7 @@ archive_entry_devminor(struct archive_entry *entry)
mode_t
archive_entry_filetype(struct archive_entry *entry)
{
- return (AE_IFMT & entry->ae_stat.aest_mode);
+ return (AE_IFMT & entry->acl.mode);
}
void
@@ -568,8 +374,8 @@ archive_entry_fflags_text(struct archive_entry *entry)
const char *f;
char *p;
- f = aes_get_mbs(&entry->ae_fflags_text);
- if (f != NULL)
+ if (archive_mstring_get_mbs(entry->archive,
+ &entry->ae_fflags_text, &f) == 0 && f != NULL)
return (f);
if (entry->ae_fflags_set == 0 && entry->ae_fflags_clear == 0)
@@ -579,13 +385,15 @@ archive_entry_fflags_text(struct archive_entry *entry)
if (p == NULL)
return (NULL);
- aes_copy_mbs(&entry->ae_fflags_text, p);
+ archive_mstring_copy_mbs(&entry->ae_fflags_text, p);
free(p);
- f = aes_get_mbs(&entry->ae_fflags_text);
- return (f);
+ if (archive_mstring_get_mbs(entry->archive,
+ &entry->ae_fflags_text, &f) == 0)
+ return (f);
+ return (NULL);
}
-gid_t
+int64_t
archive_entry_gid(struct archive_entry *entry)
{
return (entry->ae_stat.aest_gid);
@@ -594,37 +402,72 @@ archive_entry_gid(struct archive_entry *entry)
const char *
archive_entry_gname(struct archive_entry *entry)
{
- return (aes_get_mbs(&entry->ae_gname));
+ const char *p;
+ if (archive_mstring_get_mbs(entry->archive, &entry->ae_gname, &p) == 0)
+ return (p);
+ return (NULL);
}
const wchar_t *
archive_entry_gname_w(struct archive_entry *entry)
{
- return (aes_get_wcs(&entry->ae_gname));
+ const wchar_t *p;
+ if (archive_mstring_get_wcs(entry->archive, &entry->ae_gname, &p) == 0)
+ return (p);
+ return (NULL);
+}
+
+int
+_archive_entry_gname_l(struct archive_entry *entry,
+ const char **p, size_t *len, struct archive_string_conv *sc)
+{
+ return (archive_mstring_get_mbs_l(&entry->ae_gname, p, len, sc));
}
const char *
archive_entry_hardlink(struct archive_entry *entry)
{
- if (entry->ae_set & AE_SET_HARDLINK)
- return (aes_get_mbs(&entry->ae_hardlink));
+ const char *p;
+ if ((entry->ae_set & AE_SET_HARDLINK) && archive_mstring_get_mbs(
+ entry->archive, &entry->ae_hardlink, &p) == 0)
+ return (p);
return (NULL);
}
const wchar_t *
archive_entry_hardlink_w(struct archive_entry *entry)
{
- if (entry->ae_set & AE_SET_HARDLINK)
- return (aes_get_wcs(&entry->ae_hardlink));
+ const wchar_t *p;
+ if ((entry->ae_set & AE_SET_HARDLINK) && archive_mstring_get_wcs(
+ entry->archive, &entry->ae_hardlink, &p) == 0)
+ return (p);
return (NULL);
}
-ino_t
+int
+_archive_entry_hardlink_l(struct archive_entry *entry,
+ const char **p, size_t *len, struct archive_string_conv *sc)
+{
+ if ((entry->ae_set & AE_SET_HARDLINK) == 0) {
+ *p = NULL;
+ *len = 0;
+ return (0);
+ }
+ return (archive_mstring_get_mbs_l(&entry->ae_hardlink, p, len, sc));
+}
+
+int64_t
archive_entry_ino(struct archive_entry *entry)
{
return (entry->ae_stat.aest_ino);
}
+int
+archive_entry_ino_is_set(struct archive_entry *entry)
+{
+ return (entry->ae_set & AE_SET_INO);
+}
+
int64_t
archive_entry_ino64(struct archive_entry *entry)
{
@@ -634,7 +477,7 @@ archive_entry_ino64(struct archive_entry *entry)
mode_t
archive_entry_mode(struct archive_entry *entry)
{
- return (entry->ae_stat.aest_mode);
+ return (entry->acl.mode);
}
time_t
@@ -664,13 +507,34 @@ archive_entry_nlink(struct archive_entry *entry)
const char *
archive_entry_pathname(struct archive_entry *entry)
{
- return (aes_get_mbs(&entry->ae_pathname));
+ const char *p;
+ if (archive_mstring_get_mbs(
+ entry->archive, &entry->ae_pathname, &p) == 0)
+ return (p);
+ return (NULL);
}
const wchar_t *
archive_entry_pathname_w(struct archive_entry *entry)
{
- return (aes_get_wcs(&entry->ae_pathname));
+ const wchar_t *p;
+ if (archive_mstring_get_wcs(
+ entry->archive, &entry->ae_pathname, &p) == 0)
+ return (p);
+ return (NULL);
+}
+
+int
+_archive_entry_pathname_l(struct archive_entry *entry,
+ const char **p, size_t *len, struct archive_string_conv *sc)
+{
+ return (archive_mstring_get_mbs_l(&entry->ae_pathname, p, len, sc));
+}
+
+mode_t
+archive_entry_perm(struct archive_entry *entry)
+{
+ return (~AE_IFMT & entry->acl.mode);
}
dev_t
@@ -716,26 +580,56 @@ archive_entry_size_is_set(struct archive_entry *entry)
const char *
archive_entry_sourcepath(struct archive_entry *entry)
{
- return (aes_get_mbs(&entry->ae_sourcepath));
+ const char *p;
+ if (archive_mstring_get_mbs(
+ entry->archive, &entry->ae_sourcepath, &p) == 0)
+ return (p);
+ return (NULL);
+}
+
+const wchar_t *
+archive_entry_sourcepath_w(struct archive_entry *entry)
+{
+ const wchar_t *p;
+ if (archive_mstring_get_wcs(
+ entry->archive, &entry->ae_sourcepath, &p) == 0)
+ return (p);
+ return (NULL);
}
const char *
archive_entry_symlink(struct archive_entry *entry)
{
- if (entry->ae_set & AE_SET_SYMLINK)
- return (aes_get_mbs(&entry->ae_symlink));
+ const char *p;
+ if ((entry->ae_set & AE_SET_SYMLINK) && archive_mstring_get_mbs(
+ entry->archive, &entry->ae_symlink, &p) == 0)
+ return (p);
return (NULL);
}
const wchar_t *
archive_entry_symlink_w(struct archive_entry *entry)
{
- if (entry->ae_set & AE_SET_SYMLINK)
- return (aes_get_wcs(&entry->ae_symlink));
+ const wchar_t *p;
+ if ((entry->ae_set & AE_SET_SYMLINK) && archive_mstring_get_wcs(
+ entry->archive, &entry->ae_symlink, &p) == 0)
+ return (p);
return (NULL);
}
-uid_t
+int
+_archive_entry_symlink_l(struct archive_entry *entry,
+ const char **p, size_t *len, struct archive_string_conv *sc)
+{
+ if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
+ *p = NULL;
+ *len = 0;
+ return (0);
+ }
+ return (archive_mstring_get_mbs_l( &entry->ae_symlink, p, len, sc));
+}
+
+int64_t
archive_entry_uid(struct archive_entry *entry)
{
return (entry->ae_stat.aest_uid);
@@ -744,13 +638,26 @@ archive_entry_uid(struct archive_entry *entry)
const char *
archive_entry_uname(struct archive_entry *entry)
{
- return (aes_get_mbs(&entry->ae_uname));
+ const char *p;
+ if (archive_mstring_get_mbs(entry->archive, &entry->ae_uname, &p) == 0)
+ return (p);
+ return (NULL);
}
const wchar_t *
archive_entry_uname_w(struct archive_entry *entry)
{
- return (aes_get_wcs(&entry->ae_uname));
+ const wchar_t *p;
+ if (archive_mstring_get_wcs(entry->archive, &entry->ae_uname, &p) == 0)
+ return (p);
+ return (NULL);
+}
+
+int
+_archive_entry_uname_l(struct archive_entry *entry,
+ const char **p, size_t *len, struct archive_string_conv *sc)
+{
+ return (archive_mstring_get_mbs_l(&entry->ae_uname, p, len, sc));
}
/*
@@ -761,15 +668,15 @@ void
archive_entry_set_filetype(struct archive_entry *entry, unsigned int type)
{
entry->stat_valid = 0;
- entry->ae_stat.aest_mode &= ~AE_IFMT;
- entry->ae_stat.aest_mode |= AE_IFMT & type;
+ entry->acl.mode &= ~AE_IFMT;
+ entry->acl.mode |= AE_IFMT & type;
}
void
archive_entry_set_fflags(struct archive_entry *entry,
unsigned long set, unsigned long clear)
{
- aes_clean(&entry->ae_fflags_text);
+ archive_mstring_clean(&entry->ae_fflags_text);
entry->ae_fflags_set = set;
entry->ae_fflags_clear = clear;
}
@@ -778,7 +685,7 @@ const char *
archive_entry_copy_fflags_text(struct archive_entry *entry,
const char *flags)
{
- aes_copy_mbs(&entry->ae_fflags_text, flags);
+ archive_mstring_copy_mbs(&entry->ae_fflags_text, flags);
return (ae_strtofflags(flags,
&entry->ae_fflags_set, &entry->ae_fflags_clear));
}
@@ -787,13 +694,13 @@ const wchar_t *
archive_entry_copy_fflags_text_w(struct archive_entry *entry,
const wchar_t *flags)
{
- aes_copy_wcs(&entry->ae_fflags_text, flags);
+ archive_mstring_copy_wcs(&entry->ae_fflags_text, flags);
return (ae_wcstofflags(flags,
&entry->ae_fflags_set, &entry->ae_fflags_clear));
}
void
-archive_entry_set_gid(struct archive_entry *entry, gid_t g)
+archive_entry_set_gid(struct archive_entry *entry, int64_t g)
{
entry->stat_valid = 0;
entry->ae_stat.aest_gid = g;
@@ -802,31 +709,42 @@ archive_entry_set_gid(struct archive_entry *entry, gid_t g)
void
archive_entry_set_gname(struct archive_entry *entry, const char *name)
{
- aes_set_mbs(&entry->ae_gname, name);
+ archive_mstring_copy_mbs(&entry->ae_gname, name);
}
void
archive_entry_copy_gname(struct archive_entry *entry, const char *name)
{
- aes_copy_mbs(&entry->ae_gname, name);
+ archive_mstring_copy_mbs(&entry->ae_gname, name);
}
void
archive_entry_copy_gname_w(struct archive_entry *entry, const wchar_t *name)
{
- aes_copy_wcs(&entry->ae_gname, name);
+ archive_mstring_copy_wcs(&entry->ae_gname, name);
}
int
archive_entry_update_gname_utf8(struct archive_entry *entry, const char *name)
{
- return (aes_update_utf8(&entry->ae_gname, name));
+ if (archive_mstring_update_utf8(entry->archive,
+ &entry->ae_gname, name) == 0)
+ return (1);
+ return (0);
+}
+
+int
+_archive_entry_copy_gname_l(struct archive_entry *entry,
+ const char *name, size_t len, struct archive_string_conv *sc)
+{
+ return (archive_mstring_copy_mbs_len_l(&entry->ae_gname, name, len, sc));
}
void
-archive_entry_set_ino(struct archive_entry *entry, unsigned long ino)
+archive_entry_set_ino(struct archive_entry *entry, int64_t ino)
{
entry->stat_valid = 0;
+ entry->ae_set |= AE_SET_INO;
entry->ae_stat.aest_ino = ino;
}
@@ -834,13 +752,14 @@ void
archive_entry_set_ino64(struct archive_entry *entry, int64_t ino)
{
entry->stat_valid = 0;
+ entry->ae_set |= AE_SET_INO;
entry->ae_stat.aest_ino = ino;
}
void
archive_entry_set_hardlink(struct archive_entry *entry, const char *target)
{
- aes_set_mbs(&entry->ae_hardlink, target);
+ archive_mstring_copy_mbs(&entry->ae_hardlink, target);
if (target != NULL)
entry->ae_set |= AE_SET_HARDLINK;
else
@@ -850,7 +769,7 @@ archive_entry_set_hardlink(struct archive_entry *entry, const char *target)
void
archive_entry_copy_hardlink(struct archive_entry *entry, const char *target)
{
- aes_copy_mbs(&entry->ae_hardlink, target);
+ archive_mstring_copy_mbs(&entry->ae_hardlink, target);
if (target != NULL)
entry->ae_set |= AE_SET_HARDLINK;
else
@@ -860,7 +779,7 @@ archive_entry_copy_hardlink(struct archive_entry *entry, const char *target)
void
archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target)
{
- aes_copy_wcs(&entry->ae_hardlink, target);
+ archive_mstring_copy_wcs(&entry->ae_hardlink, target);
if (target != NULL)
entry->ae_set |= AE_SET_HARDLINK;
else
@@ -874,12 +793,31 @@ archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *targ
entry->ae_set |= AE_SET_HARDLINK;
else
entry->ae_set &= ~AE_SET_HARDLINK;
- return (aes_update_utf8(&entry->ae_hardlink, target));
+ if (archive_mstring_update_utf8(entry->archive,
+ &entry->ae_hardlink, target) == 0)
+ return (1);
+ return (0);
+}
+
+int
+_archive_entry_copy_hardlink_l(struct archive_entry *entry,
+ const char *target, size_t len, struct archive_string_conv *sc)
+{
+ int r;
+
+ r = archive_mstring_copy_mbs_len_l(&entry->ae_hardlink,
+ target, len, sc);
+ if (target != NULL && r == 0)
+ entry->ae_set |= AE_SET_HARDLINK;
+ else
+ entry->ae_set &= ~AE_SET_HARDLINK;
+ return (r);
}
void
archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns)
{
+ FIX_NS(t, ns);
entry->stat_valid = 0;
entry->ae_set |= AE_SET_ATIME;
entry->ae_stat.aest_atime = t;
@@ -894,11 +832,12 @@ archive_entry_unset_atime(struct archive_entry *entry)
}
void
-archive_entry_set_birthtime(struct archive_entry *entry, time_t m, long ns)
+archive_entry_set_birthtime(struct archive_entry *entry, time_t t, long ns)
{
+ FIX_NS(t, ns);
entry->stat_valid = 0;
entry->ae_set |= AE_SET_BIRTHTIME;
- entry->ae_stat.aest_birthtime = m;
+ entry->ae_stat.aest_birthtime = t;
entry->ae_stat.aest_birthtime_nsec = ns;
}
@@ -912,6 +851,7 @@ archive_entry_unset_birthtime(struct archive_entry *entry)
void
archive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns)
{
+ FIX_NS(t, ns);
entry->stat_valid = 0;
entry->ae_set |= AE_SET_CTIME;
entry->ae_stat.aest_ctime = t;
@@ -929,6 +869,7 @@ void
archive_entry_set_dev(struct archive_entry *entry, dev_t d)
{
entry->stat_valid = 0;
+ entry->ae_set |= AE_SET_DEV;
entry->ae_stat.aest_dev_is_broken_down = 0;
entry->ae_stat.aest_dev = d;
}
@@ -937,6 +878,7 @@ void
archive_entry_set_devmajor(struct archive_entry *entry, dev_t m)
{
entry->stat_valid = 0;
+ entry->ae_set |= AE_SET_DEV;
entry->ae_stat.aest_dev_is_broken_down = 1;
entry->ae_stat.aest_devmajor = m;
}
@@ -945,6 +887,7 @@ void
archive_entry_set_devminor(struct archive_entry *entry, dev_t m)
{
entry->stat_valid = 0;
+ entry->ae_set |= AE_SET_DEV;
entry->ae_stat.aest_dev_is_broken_down = 1;
entry->ae_stat.aest_devminor = m;
}
@@ -954,9 +897,9 @@ void
archive_entry_set_link(struct archive_entry *entry, const char *target)
{
if (entry->ae_set & AE_SET_SYMLINK)
- aes_set_mbs(&entry->ae_symlink, target);
+ archive_mstring_copy_mbs(&entry->ae_symlink, target);
else
- aes_set_mbs(&entry->ae_hardlink, target);
+ archive_mstring_copy_mbs(&entry->ae_hardlink, target);
}
/* Set symlink if symlink is already set, else set hardlink. */
@@ -964,9 +907,9 @@ void
archive_entry_copy_link(struct archive_entry *entry, const char *target)
{
if (entry->ae_set & AE_SET_SYMLINK)
- aes_copy_mbs(&entry->ae_symlink, target);
+ archive_mstring_copy_mbs(&entry->ae_symlink, target);
else
- aes_copy_mbs(&entry->ae_hardlink, target);
+ archive_mstring_copy_mbs(&entry->ae_hardlink, target);
}
/* Set symlink if symlink is already set, else set hardlink. */
@@ -974,33 +917,53 @@ void
archive_entry_copy_link_w(struct archive_entry *entry, const wchar_t *target)
{
if (entry->ae_set & AE_SET_SYMLINK)
- aes_copy_wcs(&entry->ae_symlink, target);
+ archive_mstring_copy_wcs(&entry->ae_symlink, target);
else
- aes_copy_wcs(&entry->ae_hardlink, target);
+ archive_mstring_copy_wcs(&entry->ae_hardlink, target);
}
int
archive_entry_update_link_utf8(struct archive_entry *entry, const char *target)
{
+ int r;
+ if (entry->ae_set & AE_SET_SYMLINK)
+ r = archive_mstring_update_utf8(entry->archive,
+ &entry->ae_symlink, target);
+ else
+ r = archive_mstring_update_utf8(entry->archive,
+ &entry->ae_hardlink, target);
+ return ((r == 0)? 1: 0);
+}
+
+int
+_archive_entry_copy_link_l(struct archive_entry *entry,
+ const char *target, size_t len, struct archive_string_conv *sc)
+{
+ int r;
+
if (entry->ae_set & AE_SET_SYMLINK)
- return (aes_update_utf8(&entry->ae_symlink, target));
+ r = archive_mstring_copy_mbs_len_l(&entry->ae_symlink,
+ target, len, sc);
else
- return (aes_update_utf8(&entry->ae_hardlink, target));
+ r = archive_mstring_copy_mbs_len_l(&entry->ae_hardlink,
+ target, len, sc);
+ return (r);
}
void
archive_entry_set_mode(struct archive_entry *entry, mode_t m)
{
entry->stat_valid = 0;
- entry->ae_stat.aest_mode = m;
+ entry->acl.mode = m;
}
void
-archive_entry_set_mtime(struct archive_entry *entry, time_t m, long ns)
+archive_entry_set_mtime(struct archive_entry *entry, time_t t, long ns)
{
+ FIX_NS(t, ns);
entry->stat_valid = 0;
entry->ae_set |= AE_SET_MTIME;
- entry->ae_stat.aest_mtime = m;
+ entry->ae_stat.aest_mtime = t;
entry->ae_stat.aest_mtime_nsec = ns;
}
@@ -1021,33 +984,44 @@ archive_entry_set_nlink(struct archive_entry *entry, unsigned int nlink)
void
archive_entry_set_pathname(struct archive_entry *entry, const char *name)
{
- aes_set_mbs(&entry->ae_pathname, name);
+ archive_mstring_copy_mbs(&entry->ae_pathname, name);
}
void
archive_entry_copy_pathname(struct archive_entry *entry, const char *name)
{
- aes_copy_mbs(&entry->ae_pathname, name);
+ archive_mstring_copy_mbs(&entry->ae_pathname, name);
}
void
archive_entry_copy_pathname_w(struct archive_entry *entry, const wchar_t *name)
{
- aes_copy_wcs(&entry->ae_pathname, name);
+ archive_mstring_copy_wcs(&entry->ae_pathname, name);
}
int
archive_entry_update_pathname_utf8(struct archive_entry *entry, const char *name)
{
- return (aes_update_utf8(&entry->ae_pathname, name));
+ if (archive_mstring_update_utf8(entry->archive,
+ &entry->ae_pathname, name) == 0)
+ return (1);
+ return (0);
+}
+
+int
+_archive_entry_copy_pathname_l(struct archive_entry *entry,
+ const char *name, size_t len, struct archive_string_conv *sc)
+{
+ return (archive_mstring_copy_mbs_len_l(&entry->ae_pathname,
+ name, len, sc));
}
void
archive_entry_set_perm(struct archive_entry *entry, mode_t p)
{
entry->stat_valid = 0;
- entry->ae_stat.aest_mode &= AE_IFMT;
- entry->ae_stat.aest_mode |= ~AE_IFMT & p;
+ entry->acl.mode &= AE_IFMT;
+ entry->acl.mode |= ~AE_IFMT & p;
}
void
@@ -1092,13 +1066,19 @@ archive_entry_unset_size(struct archive_entry *entry)
void
archive_entry_copy_sourcepath(struct archive_entry *entry, const char *path)
{
- aes_set_mbs(&entry->ae_sourcepath, path);
+ archive_mstring_copy_mbs(&entry->ae_sourcepath, path);
+}
+
+void
+archive_entry_copy_sourcepath_w(struct archive_entry *entry, const wchar_t *path)
+{
+ archive_mstring_copy_wcs(&entry->ae_sourcepath, path);
}
void
archive_entry_set_symlink(struct archive_entry *entry, const char *linkname)
{
- aes_set_mbs(&entry->ae_symlink, linkname);
+ archive_mstring_copy_mbs(&entry->ae_symlink, linkname);
if (linkname != NULL)
entry->ae_set |= AE_SET_SYMLINK;
else
@@ -1108,7 +1088,7 @@ archive_entry_set_symlink(struct archive_entry *entry, const char *linkname)
void
archive_entry_copy_symlink(struct archive_entry *entry, const char *linkname)
{
- aes_copy_mbs(&entry->ae_symlink, linkname);
+ archive_mstring_copy_mbs(&entry->ae_symlink, linkname);
if (linkname != NULL)
entry->ae_set |= AE_SET_SYMLINK;
else
@@ -1118,7 +1098,7 @@ archive_entry_copy_symlink(struct archive_entry *entry, const char *linkname)
void
archive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linkname)
{
- aes_copy_wcs(&entry->ae_symlink, linkname);
+ archive_mstring_copy_wcs(&entry->ae_symlink, linkname);
if (linkname != NULL)
entry->ae_set |= AE_SET_SYMLINK;
else
@@ -1132,11 +1112,29 @@ archive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkn
entry->ae_set |= AE_SET_SYMLINK;
else
entry->ae_set &= ~AE_SET_SYMLINK;
- return (aes_update_utf8(&entry->ae_symlink, linkname));
+ if (archive_mstring_update_utf8(entry->archive,
+ &entry->ae_symlink, linkname) == 0)
+ return (1);
+ return (0);
+}
+
+int
+_archive_entry_copy_symlink_l(struct archive_entry *entry,
+ const char *linkname, size_t len, struct archive_string_conv *sc)
+{
+ int r;
+
+ r = archive_mstring_copy_mbs_len_l(&entry->ae_symlink,
+ linkname, len, sc);
+ if (linkname != NULL && r == 0)
+ entry->ae_set |= AE_SET_SYMLINK;
+ else
+ entry->ae_set &= ~AE_SET_SYMLINK;
+ return (r);
}
void
-archive_entry_set_uid(struct archive_entry *entry, uid_t u)
+archive_entry_set_uid(struct archive_entry *entry, int64_t u)
{
entry->stat_valid = 0;
entry->ae_stat.aest_uid = u;
@@ -1145,25 +1143,60 @@ archive_entry_set_uid(struct archive_entry *entry, uid_t u)
void
archive_entry_set_uname(struct archive_entry *entry, const char *name)
{
- aes_set_mbs(&entry->ae_uname, name);
+ archive_mstring_copy_mbs(&entry->ae_uname, name);
}
void
archive_entry_copy_uname(struct archive_entry *entry, const char *name)
{
- aes_copy_mbs(&entry->ae_uname, name);
+ archive_mstring_copy_mbs(&entry->ae_uname, name);
}
void
archive_entry_copy_uname_w(struct archive_entry *entry, const wchar_t *name)
{
- aes_copy_wcs(&entry->ae_uname, name);
+ archive_mstring_copy_wcs(&entry->ae_uname, name);
}
int
archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name)
{
- return (aes_update_utf8(&entry->ae_uname, name));
+ if (archive_mstring_update_utf8(entry->archive,
+ &entry->ae_uname, name) == 0)
+ return (1);
+ return (0);
+}
+
+int
+_archive_entry_copy_uname_l(struct archive_entry *entry,
+ const char *name, size_t len, struct archive_string_conv *sc)
+{
+ return (archive_mstring_copy_mbs_len_l(&entry->ae_uname,
+ name, len, sc));
+}
+
+const void *
+archive_entry_mac_metadata(struct archive_entry *entry, size_t *s)
+{
+ *s = entry->mac_metadata_size;
+ return entry->mac_metadata;
+}
+
+void
+archive_entry_copy_mac_metadata(struct archive_entry *entry,
+ const void *p, size_t s)
+{
+ free(entry->mac_metadata);
+ if (p == NULL || s == 0) {
+ entry->mac_metadata = NULL;
+ entry->mac_metadata_size = 0;
+ } else {
+ entry->mac_metadata_size = s;
+ entry->mac_metadata = malloc(s);
+ if (entry->mac_metadata == NULL)
+ abort();
+ memcpy(entry->mac_metadata, p, s);
+ }
}
/*
@@ -1175,148 +1208,37 @@ archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name)
* uninitiated.
*/
+struct archive_acl *
+archive_entry_acl(struct archive_entry *entry)
+{
+ return &entry->acl;
+}
+
void
archive_entry_acl_clear(struct archive_entry *entry)
{
- struct ae_acl *ap;
-
- while (entry->acl_head != NULL) {
- ap = entry->acl_head->next;
- aes_clean(&entry->acl_head->name);
- free(entry->acl_head);
- entry->acl_head = ap;
- }
- if (entry->acl_text_w != NULL) {
- free(entry->acl_text_w);
- entry->acl_text_w = NULL;
- }
- entry->acl_p = NULL;
- entry->acl_state = 0; /* Not counting. */
+ archive_acl_clear(&entry->acl);
}
/*
* Add a single ACL entry to the internal list of ACL data.
*/
-void
+int
archive_entry_acl_add_entry(struct archive_entry *entry,
int type, int permset, int tag, int id, const char *name)
{
- struct ae_acl *ap;
-
- if (acl_special(entry, type, permset, tag) == 0)
- return;
- ap = acl_new_entry(entry, type, permset, tag, id);
- if (ap == NULL) {
- /* XXX Error XXX */
- return;
- }
- if (name != NULL && *name != '\0')
- aes_copy_mbs(&ap->name, name);
- else
- aes_clean(&ap->name);
+ return archive_acl_add_entry(&entry->acl, type, permset, tag, id, name);
}
/*
* As above, but with a wide-character name.
*/
-void
+int
archive_entry_acl_add_entry_w(struct archive_entry *entry,
int type, int permset, int tag, int id, const wchar_t *name)
{
- archive_entry_acl_add_entry_w_len(entry, type, permset, tag, id, name, wcslen(name));
-}
-
-static void
-archive_entry_acl_add_entry_w_len(struct archive_entry *entry,
- int type, int permset, int tag, int id, const wchar_t *name, size_t len)
-{
- struct ae_acl *ap;
-
- if (acl_special(entry, type, permset, tag) == 0)
- return;
- ap = acl_new_entry(entry, type, permset, tag, id);
- if (ap == NULL) {
- /* XXX Error XXX */
- return;
- }
- if (name != NULL && *name != L'\0' && len > 0)
- aes_copy_wcs_len(&ap->name, name, len);
- else
- aes_clean(&ap->name);
-}
-
-/*
- * If this ACL entry is part of the standard POSIX permissions set,
- * store the permissions in the stat structure and return zero.
- */
-static int
-acl_special(struct archive_entry *entry, int type, int permset, int tag)
-{
- if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
- switch (tag) {
- case ARCHIVE_ENTRY_ACL_USER_OBJ:
- entry->ae_stat.aest_mode &= ~0700;
- entry->ae_stat.aest_mode |= (permset & 7) << 6;
- return (0);
- case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
- entry->ae_stat.aest_mode &= ~0070;
- entry->ae_stat.aest_mode |= (permset & 7) << 3;
- return (0);
- case ARCHIVE_ENTRY_ACL_OTHER:
- entry->ae_stat.aest_mode &= ~0007;
- entry->ae_stat.aest_mode |= permset & 7;
- return (0);
- }
- }
- return (1);
-}
-
-/*
- * Allocate and populate a new ACL entry with everything but the
- * name.
- */
-static struct ae_acl *
-acl_new_entry(struct archive_entry *entry,
- int type, int permset, int tag, int id)
-{
- struct ae_acl *ap, *aq;
-
- if (type != ARCHIVE_ENTRY_ACL_TYPE_ACCESS &&
- type != ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)
- return (NULL);
- if (entry->acl_text_w != NULL) {
- free(entry->acl_text_w);
- entry->acl_text_w = NULL;
- }
-
- /* XXX TODO: More sanity-checks on the arguments XXX */
-
- /* If there's a matching entry already in the list, overwrite it. */
- ap = entry->acl_head;
- aq = NULL;
- while (ap != NULL) {
- if (ap->type == type && ap->tag == tag && ap->id == id) {
- ap->permset = permset;
- return (ap);
- }
- aq = ap;
- ap = ap->next;
- }
-
- /* Add a new entry to the end of the list. */
- ap = (struct ae_acl *)malloc(sizeof(*ap));
- if (ap == NULL)
- return (NULL);
- memset(ap, 0, sizeof(*ap));
- if (aq == NULL)
- entry->acl_head = ap;
- else
- aq->next = ap;
- ap->type = type;
- ap->tag = tag;
- ap->id = id;
- ap->permset = permset;
- return (ap);
+ return archive_acl_add_entry_w_len(&entry->acl,
+ type, permset, tag, id, name, wcslen(name));
}
/*
@@ -1325,20 +1247,7 @@ acl_new_entry(struct archive_entry *entry,
int
archive_entry_acl_count(struct archive_entry *entry, int want_type)
{
- int count;
- struct ae_acl *ap;
-
- count = 0;
- ap = entry->acl_head;
- while (ap != NULL) {
- if ((ap->type & want_type) != 0)
- count++;
- ap = ap->next;
- }
-
- if (count > 0 && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0))
- count += 3;
- return (count);
+ return archive_acl_count(&entry->acl, want_type);
}
/*
@@ -1349,93 +1258,18 @@ archive_entry_acl_count(struct archive_entry *entry, int want_type)
int
archive_entry_acl_reset(struct archive_entry *entry, int want_type)
{
- int count, cutoff;
-
- count = archive_entry_acl_count(entry, want_type);
-
- /*
- * If the only entries are the three standard ones,
- * then don't return any ACL data. (In this case,
- * client can just use chmod(2) to set permissions.)
- */
- if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
- cutoff = 3;
- else
- cutoff = 0;
-
- if (count > cutoff)
- entry->acl_state = ARCHIVE_ENTRY_ACL_USER_OBJ;
- else
- entry->acl_state = 0;
- entry->acl_p = entry->acl_head;
- return (count);
+ return archive_acl_reset(&entry->acl, want_type);
}
/*
* Return the next ACL entry in the list. Fake entries for the
* standard permissions and include them in the returned list.
*/
-
int
archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
int *permset, int *tag, int *id, const char **name)
{
- *name = NULL;
- *id = -1;
-
- /*
- * The acl_state is either zero (no entries available), -1
- * (reading from list), or an entry type (retrieve that type
- * from ae_stat.aest_mode).
- */
- if (entry->acl_state == 0)
- return (ARCHIVE_WARN);
-
- /* The first three access entries are special. */
- if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
- switch (entry->acl_state) {
- case ARCHIVE_ENTRY_ACL_USER_OBJ:
- *permset = (entry->ae_stat.aest_mode >> 6) & 7;
- *type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
- *tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
- entry->acl_state = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
- return (ARCHIVE_OK);
- case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
- *permset = (entry->ae_stat.aest_mode >> 3) & 7;
- *type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
- *tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
- entry->acl_state = ARCHIVE_ENTRY_ACL_OTHER;
- return (ARCHIVE_OK);
- case ARCHIVE_ENTRY_ACL_OTHER:
- *permset = entry->ae_stat.aest_mode & 7;
- *type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
- *tag = ARCHIVE_ENTRY_ACL_OTHER;
- entry->acl_state = -1;
- entry->acl_p = entry->acl_head;
- return (ARCHIVE_OK);
- default:
- break;
- }
- }
-
- while (entry->acl_p != NULL && (entry->acl_p->type & want_type) == 0)
- entry->acl_p = entry->acl_p->next;
- if (entry->acl_p == NULL) {
- entry->acl_state = 0;
- *type = 0;
- *permset = 0;
- *tag = 0;
- *id = -1;
- *name = NULL;
- return (ARCHIVE_EOF); /* End of ACL entries. */
- }
- *type = entry->acl_p->type;
- *permset = entry->acl_p->permset;
- *tag = entry->acl_p->tag;
- *id = entry->acl_p->id;
- *name = aes_get_mbs(&entry->acl_p->name);
- entry->acl_p = entry->acl_p->next;
- return (ARCHIVE_OK);
+ return archive_acl_next(entry->archive, &entry->acl, want_type, type, permset, tag, id, name);
}
/*
@@ -1445,412 +1279,27 @@ archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
const wchar_t *
archive_entry_acl_text_w(struct archive_entry *entry, int flags)
{
- int count;
- size_t length;
- const wchar_t *wname;
- const wchar_t *prefix;
- wchar_t separator;
- struct ae_acl *ap;
- int id;
- wchar_t *wp;
-
- if (entry->acl_text_w != NULL) {
- free (entry->acl_text_w);
- entry->acl_text_w = NULL;
- }
-
- separator = L',';
- count = 0;
- length = 0;
- ap = entry->acl_head;
- while (ap != NULL) {
- if ((ap->type & flags) != 0) {
- count++;
- if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) &&
- (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT))
- length += 8; /* "default:" */
- length += 5; /* tag name */
- length += 1; /* colon */
- wname = aes_get_wcs(&ap->name);
- if (wname != NULL)
- length += wcslen(wname);
- else
- length += sizeof(uid_t) * 3 + 1;
- length ++; /* colon */
- length += 3; /* rwx */
- length += 1; /* colon */
- length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1;
- length ++; /* newline */
- }
- ap = ap->next;
- }
-
- if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) {
- length += 10; /* "user::rwx\n" */
- length += 11; /* "group::rwx\n" */
- length += 11; /* "other::rwx\n" */
- }
-
- if (count == 0)
- return (NULL);
-
- /* Now, allocate the string and actually populate it. */
- wp = entry->acl_text_w = (wchar_t *)malloc(length * sizeof(wchar_t));
- if (wp == NULL)
- __archive_errx(1, "No memory to generate the text version of the ACL");
- count = 0;
- if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
- append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL,
- entry->ae_stat.aest_mode & 0700, -1);
- *wp++ = ',';
- append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL,
- entry->ae_stat.aest_mode & 0070, -1);
- *wp++ = ',';
- append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL,
- entry->ae_stat.aest_mode & 0007, -1);
- count += 3;
-
- ap = entry->acl_head;
- while (ap != NULL) {
- if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
- wname = aes_get_wcs(&ap->name);
- *wp++ = separator;
- if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
- id = ap->id;
- else
- id = -1;
- append_entry_w(&wp, NULL, ap->tag, wname,
- ap->permset, id);
- count++;
- }
- ap = ap->next;
- }
- }
-
-
- if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) {
- if (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT)
- prefix = L"default:";
- else
- prefix = NULL;
- ap = entry->acl_head;
- count = 0;
- while (ap != NULL) {
- if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) {
- wname = aes_get_wcs(&ap->name);
- if (count > 0)
- *wp++ = separator;
- if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
- id = ap->id;
- else
- id = -1;
- append_entry_w(&wp, prefix, ap->tag,
- wname, ap->permset, id);
- count ++;
- }
- ap = ap->next;
- }
- }
-
- return (entry->acl_text_w);
-}
-
-static void
-append_id_w(wchar_t **wp, int id)
-{
- if (id < 0)
- id = 0;
- if (id > 9)
- append_id_w(wp, id / 10);
- *(*wp)++ = L"0123456789"[id % 10];
+ return archive_acl_text_w(entry->archive, &entry->acl, flags);
}
-static void
-append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
- const wchar_t *wname, int perm, int id)
+const char *
+archive_entry_acl_text(struct archive_entry *entry, int flags)
{
- if (prefix != NULL) {
- wcscpy(*wp, prefix);
- *wp += wcslen(*wp);
- }
- switch (tag) {
- case ARCHIVE_ENTRY_ACL_USER_OBJ:
- wname = NULL;
- id = -1;
- /* FALLTHROUGH */
- case ARCHIVE_ENTRY_ACL_USER:
- wcscpy(*wp, L"user");
- break;
- case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
- wname = NULL;
- id = -1;
- /* FALLTHROUGH */
- case ARCHIVE_ENTRY_ACL_GROUP:
- wcscpy(*wp, L"group");
- break;
- case ARCHIVE_ENTRY_ACL_MASK:
- wcscpy(*wp, L"mask");
- wname = NULL;
- id = -1;
- break;
- case ARCHIVE_ENTRY_ACL_OTHER:
- wcscpy(*wp, L"other");
- wname = NULL;
- id = -1;
- break;
- }
- *wp += wcslen(*wp);
- *(*wp)++ = L':';
- if (wname != NULL) {
- wcscpy(*wp, wname);
- *wp += wcslen(*wp);
- } else if (tag == ARCHIVE_ENTRY_ACL_USER
- || tag == ARCHIVE_ENTRY_ACL_GROUP) {
- append_id_w(wp, id);
- id = -1;
- }
- *(*wp)++ = L':';
- *(*wp)++ = (perm & 0444) ? L'r' : L'-';
- *(*wp)++ = (perm & 0222) ? L'w' : L'-';
- *(*wp)++ = (perm & 0111) ? L'x' : L'-';
- if (id != -1) {
- *(*wp)++ = L':';
- append_id_w(wp, id);
- }
- **wp = L'\0';
+ const char *p;
+ if (archive_acl_text_l(&entry->acl, flags, &p, NULL, NULL) != 0
+ && errno == ENOMEM)
+ return (NULL);
+ return (p);
}
-/*
- * Parse a textual ACL. This automatically recognizes and supports
- * extensions described above. The 'type' argument is used to
- * indicate the type that should be used for any entries not
- * explicitly marked as "default:".
- */
int
-__archive_entry_acl_parse_w(struct archive_entry *entry,
- const wchar_t *text, int default_type)
-{
- struct {
- const wchar_t *start;
- const wchar_t *end;
- } field[4], name;
-
- int fields, n;
- int type, tag, permset, id;
- wchar_t sep;
-
- while (text != NULL && *text != L'\0') {
- /*
- * Parse the fields out of the next entry,
- * advance 'text' to start of next entry.
- */
- fields = 0;
- do {
- const wchar_t *start, *end;
- next_field_w(&text, &start, &end, &sep);
- if (fields < 4) {
- field[fields].start = start;
- field[fields].end = end;
- }
- ++fields;
- } while (sep == L':');
-
- /* Set remaining fields to blank. */
- for (n = fields; n < 4; ++n)
- field[n].start = field[n].end = NULL;
-
- /* Check for a numeric ID in field 1 or 3. */
- id = -1;
- isint_w(field[1].start, field[1].end, &id);
- /* Field 3 is optional. */
- if (id == -1 && fields > 3)
- isint_w(field[3].start, field[3].end, &id);
-
- /*
- * Solaris extension: "defaultuser::rwx" is the
- * default ACL corresponding to "user::rwx", etc.
- */
- if (field[0].end - field[0].start > 7
- && wmemcmp(field[0].start, L"default", 7) == 0) {
- type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
- field[0].start += 7;
- } else
- type = default_type;
-
- name.start = name.end = NULL;
- if (prefix_w(field[0].start, field[0].end, L"user")) {
- if (!ismode_w(field[2].start, field[2].end, &permset))
- return (ARCHIVE_WARN);
- if (id != -1 || field[1].start < field[1].end) {
- tag = ARCHIVE_ENTRY_ACL_USER;
- name = field[1];
- } else
- tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
- } else if (prefix_w(field[0].start, field[0].end, L"group")) {
- if (!ismode_w(field[2].start, field[2].end, &permset))
- return (ARCHIVE_WARN);
- if (id != -1 || field[1].start < field[1].end) {
- tag = ARCHIVE_ENTRY_ACL_GROUP;
- name = field[1];
- } else
- tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
- } else if (prefix_w(field[0].start, field[0].end, L"other")) {
- if (fields == 2
- && field[1].start < field[1].end
- && ismode_w(field[1].start, field[1].end, &permset)) {
- /* This is Solaris-style "other:rwx" */
- } else if (fields == 3
- && field[1].start == field[1].end
- && field[2].start < field[2].end
- && ismode_w(field[2].start, field[2].end, &permset)) {
- /* This is FreeBSD-style "other::rwx" */
- } else
- return (ARCHIVE_WARN);
- tag = ARCHIVE_ENTRY_ACL_OTHER;
- } else if (prefix_w(field[0].start, field[0].end, L"mask")) {
- if (fields == 2
- && field[1].start < field[1].end
- && ismode_w(field[1].start, field[1].end, &permset)) {
- /* This is Solaris-style "mask:rwx" */
- } else if (fields == 3
- && field[1].start == field[1].end
- && field[2].start < field[2].end
- && ismode_w(field[2].start, field[2].end, &permset)) {
- /* This is FreeBSD-style "mask::rwx" */
- } else
- return (ARCHIVE_WARN);
- tag = ARCHIVE_ENTRY_ACL_MASK;
- } else
- return (ARCHIVE_WARN);
-
- /* Add entry to the internal list. */
- archive_entry_acl_add_entry_w_len(entry, type, permset,
- tag, id, name.start, name.end - name.start);
- }
- return (ARCHIVE_OK);
-}
-
-/*
- * Parse a string to a positive decimal integer. Returns true if
- * the string is non-empty and consists only of decimal digits,
- * false otherwise.
- */
-static int
-isint_w(const wchar_t *start, const wchar_t *end, int *result)
-{
- int n = 0;
- if (start >= end)
- return (0);
- while (start < end) {
- if (*start < '0' || *start > '9')
- return (0);
- if (n > (INT_MAX / 10))
- n = INT_MAX;
- else {
- n *= 10;
- n += *start - '0';
- }
- start++;
- }
- *result = n;
- return (1);
-}
-
-/*
- * Parse a string as a mode field. Returns true if
- * the string is non-empty and consists only of mode characters,
- * false otherwise.
- */
-static int
-ismode_w(const wchar_t *start, const wchar_t *end, int *permset)
+_archive_entry_acl_text_l(struct archive_entry *entry, int flags,
+ const char **acl_text, size_t *len, struct archive_string_conv *sc)
{
- const wchar_t *p;
-
- if (start >= end)
- return (0);
- p = start;
- *permset = 0;
- while (p < end) {
- switch (*p++) {
- case 'r': case 'R':
- *permset |= ARCHIVE_ENTRY_ACL_READ;
- break;
- case 'w': case 'W':
- *permset |= ARCHIVE_ENTRY_ACL_WRITE;
- break;
- case 'x': case 'X':
- *permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
- break;
- case '-':
- break;
- default:
- return (0);
- }
- }
- return (1);
+ return (archive_acl_text_l(&entry->acl, flags, acl_text, len, sc));
}
/*
- * Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]". *wp is updated
- * to point to just after the separator. *start points to the first
- * character of the matched text and *end just after the last
- * character of the matched identifier. In particular *end - *start
- * is the length of the field body, not including leading or trailing
- * whitespace.
- */
-static void
-next_field_w(const wchar_t **wp, const wchar_t **start,
- const wchar_t **end, wchar_t *sep)
-{
- /* Skip leading whitespace to find start of field. */
- while (**wp == L' ' || **wp == L'\t' || **wp == L'\n') {
- (*wp)++;
- }
- *start = *wp;
-
- /* Scan for the separator. */
- while (**wp != L'\0' && **wp != L',' && **wp != L':' &&
- **wp != L'\n') {
- (*wp)++;
- }
- *sep = **wp;
-
- /* Trim trailing whitespace to locate end of field. */
- *end = *wp - 1;
- while (**end == L' ' || **end == L'\t' || **end == L'\n') {
- (*end)--;
- }
- (*end)++;
-
- /* Adjust scanner location. */
- if (**wp != L'\0')
- (*wp)++;
-}
-
-/*
- * Return true if the characters [start...end) are a prefix of 'test'.
- * This makes it easy to handle the obvious abbreviations: 'u' for 'user', etc.
- */
-static int
-prefix_w(const wchar_t *start, const wchar_t *end, const wchar_t *test)
-{
- if (start == end)
- return (0);
-
- if (*start++ != *test++)
- return (0);
-
- while (start < end && *start++ == *test++)
- ;
-
- if (start < end)
- return (0);
-
- return (1);
-}
-
-
-/*
* Following code is modified from UC Berkeley sources, and
* is subject to the following copyright notice.
*/
diff --git a/contrib/libarchive/libarchive/archive_entry.h b/contrib/libarchive/libarchive/archive_entry.h
index 7ed2dde2c426..50b0d85e8d3d 100644
--- a/contrib/libarchive/libarchive/archive_entry.h
+++ b/contrib/libarchive/libarchive/archive_entry.h
@@ -28,6 +28,9 @@
#ifndef ARCHIVE_ENTRY_H_INCLUDED
#define ARCHIVE_ENTRY_H_INCLUDED
+/* Note: Compiler will complain if this does not match archive.h! */
+#define ARCHIVE_VERSION_NUMBER 3000003
+
/*
* Note: archive_entry.h is for use outside of libarchive; the
* configuration headers (config.h, archive_platform.h, etc.) are
@@ -49,30 +52,31 @@
#if defined(_WIN32) && !defined(__CYGWIN__)
#define __LA_INT64_T __int64
# if defined(__BORLANDC__)
-# define __LA_UID_T uid_t
-# define __LA_GID_T gid_t
+# define __LA_UID_T uid_t /* Remove in libarchive 3.2 */
+# define __LA_GID_T gid_t /* Remove in libarchive 3.2 */
# define __LA_DEV_T dev_t
# define __LA_MODE_T mode_t
# else
-# define __LA_UID_T short
-# define __LA_GID_T short
+# define __LA_UID_T short /* Remove in libarchive 3.2 */
+# define __LA_GID_T short /* Remove in libarchive 3.2 */
# define __LA_DEV_T unsigned int
# define __LA_MODE_T unsigned short
# endif
#else
#include <unistd.h>
-#define __LA_INT64_T int64_t
-#define __LA_UID_T uid_t
-#define __LA_GID_T gid_t
-#define __LA_DEV_T dev_t
-#define __LA_MODE_T mode_t
+# if defined(_SCO_DS)
+# define __LA_INT64_T long long
+# else
+# define __LA_INT64_T int64_t
+# endif
+# define __LA_UID_T uid_t /* Remove in libarchive 3.2 */
+# define __LA_GID_T gid_t /* Remove in libarchive 3.2 */
+# define __LA_DEV_T dev_t
+# define __LA_MODE_T mode_t
#endif
/*
- * XXX Is this defined for all Windows compilers? If so, in what
- * header? It would be nice to remove the __LA_INO_T indirection and
- * just use plain ino_t everywhere. Likewise for the other types just
- * above.
+ * Remove this for libarchive 3.2, since ino_t is no longer used.
*/
#define __LA_INO_T ino_t
@@ -91,7 +95,7 @@
# endif
# else
# ifdef __GNUC__
-# define __LA_DECL __attribute__((dllimport)) extern
+# define __LA_DECL
# else
# define __LA_DECL __declspec(dllimport)
# endif
@@ -121,6 +125,7 @@ extern "C" {
* applications (e.g., a package manager could attach special
* package-management attributes to each entry).
*/
+struct archive;
struct archive_entry;
/*
@@ -164,6 +169,15 @@ __LA_DECL void archive_entry_free(struct archive_entry *);
__LA_DECL struct archive_entry *archive_entry_new(void);
/*
+ * This form of archive_entry_new2() will pull character-set
+ * conversion information from the specified archive handle. The
+ * older archive_entry_new(void) form is equivalent to calling
+ * archive_entry_new2(NULL) and will result in the use of an internal
+ * default character-set conversion.
+ */
+__LA_DECL struct archive_entry *archive_entry_new2(struct archive *);
+
+/*
* Retrieve fields from an archive_entry.
*
* There are a number of implicit conversions among these fields. For
@@ -192,6 +206,7 @@ __LA_DECL time_t archive_entry_ctime(struct archive_entry *);
__LA_DECL long archive_entry_ctime_nsec(struct archive_entry *);
__LA_DECL int archive_entry_ctime_is_set(struct archive_entry *);
__LA_DECL dev_t archive_entry_dev(struct archive_entry *);
+__LA_DECL int archive_entry_dev_is_set(struct archive_entry *);
__LA_DECL dev_t archive_entry_devmajor(struct archive_entry *);
__LA_DECL dev_t archive_entry_devminor(struct archive_entry *);
__LA_DECL __LA_MODE_T archive_entry_filetype(struct archive_entry *);
@@ -199,13 +214,14 @@ __LA_DECL void archive_entry_fflags(struct archive_entry *,
unsigned long * /* set */,
unsigned long * /* clear */);
__LA_DECL const char *archive_entry_fflags_text(struct archive_entry *);
-__LA_DECL __LA_GID_T archive_entry_gid(struct archive_entry *);
+__LA_DECL __LA_INT64_T archive_entry_gid(struct archive_entry *);
__LA_DECL const char *archive_entry_gname(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_gname_w(struct archive_entry *);
__LA_DECL const char *archive_entry_hardlink(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_hardlink_w(struct archive_entry *);
-__LA_DECL __LA_INO_T archive_entry_ino(struct archive_entry *);
+__LA_DECL __LA_INT64_T archive_entry_ino(struct archive_entry *);
__LA_DECL __LA_INT64_T archive_entry_ino64(struct archive_entry *);
+__LA_DECL int archive_entry_ino_is_set(struct archive_entry *);
__LA_DECL __LA_MODE_T archive_entry_mode(struct archive_entry *);
__LA_DECL time_t archive_entry_mtime(struct archive_entry *);
__LA_DECL long archive_entry_mtime_nsec(struct archive_entry *);
@@ -213,35 +229,34 @@ __LA_DECL int archive_entry_mtime_is_set(struct archive_entry *);
__LA_DECL unsigned int archive_entry_nlink(struct archive_entry *);
__LA_DECL const char *archive_entry_pathname(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_pathname_w(struct archive_entry *);
+__LA_DECL __LA_MODE_T archive_entry_perm(struct archive_entry *);
__LA_DECL dev_t archive_entry_rdev(struct archive_entry *);
__LA_DECL dev_t archive_entry_rdevmajor(struct archive_entry *);
__LA_DECL dev_t archive_entry_rdevminor(struct archive_entry *);
__LA_DECL const char *archive_entry_sourcepath(struct archive_entry *);
+__LA_DECL const wchar_t *archive_entry_sourcepath_w(struct archive_entry *);
__LA_DECL __LA_INT64_T archive_entry_size(struct archive_entry *);
__LA_DECL int archive_entry_size_is_set(struct archive_entry *);
__LA_DECL const char *archive_entry_strmode(struct archive_entry *);
__LA_DECL const char *archive_entry_symlink(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_symlink_w(struct archive_entry *);
-__LA_DECL __LA_UID_T archive_entry_uid(struct archive_entry *);
+__LA_DECL __LA_INT64_T archive_entry_uid(struct archive_entry *);
__LA_DECL const char *archive_entry_uname(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *);
/*
* Set fields in an archive_entry.
*
- * Note that string 'set' functions do not copy the string, only the pointer.
- * In contrast, 'copy' functions do copy the object pointed to.
- *
- * Note: As of libarchive 2.4, 'set' functions do copy the string and
- * are therefore exact synonyms for the 'copy' versions. The 'copy'
- * names will be retired in libarchive 3.0.
+ * Note: Before libarchive 2.4, there were 'set' and 'copy' versions
+ * of the string setters. 'copy' copied the actual string, 'set' just
+ * stored the pointer. In libarchive 2.4 and later, strings are
+ * always copied.
*/
__LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long);
__LA_DECL void archive_entry_unset_atime(struct archive_entry *);
#if defined(_WIN32) && !defined(__CYGWIN__)
-__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *,
- BY_HANDLE_FILE_INFORMATION *);
+__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, BY_HANDLE_FILE_INFORMATION *);
#endif
__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long);
__LA_DECL void archive_entry_unset_birthtime(struct archive_entry *);
@@ -259,7 +274,7 @@ __LA_DECL const char *archive_entry_copy_fflags_text(struct archive_entry *,
const char *);
__LA_DECL const wchar_t *archive_entry_copy_fflags_text_w(struct archive_entry *,
const wchar_t *);
-__LA_DECL void archive_entry_set_gid(struct archive_entry *, __LA_GID_T);
+__LA_DECL void archive_entry_set_gid(struct archive_entry *, __LA_INT64_T);
__LA_DECL void archive_entry_set_gname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_gname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *);
@@ -268,12 +283,7 @@ __LA_DECL void archive_entry_set_hardlink(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_hardlink_utf8(struct archive_entry *, const char *);
-#if ARCHIVE_VERSION_NUMBER >= 3000000
-/* Starting with libarchive 3.0, this will be synonym for ino64. */
__LA_DECL void archive_entry_set_ino(struct archive_entry *, __LA_INT64_T);
-#else
-__LA_DECL void archive_entry_set_ino(struct archive_entry *, unsigned long);
-#endif
__LA_DECL void archive_entry_set_ino64(struct archive_entry *, __LA_INT64_T);
__LA_DECL void archive_entry_set_link(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_link(struct archive_entry *, const char *);
@@ -294,11 +304,12 @@ __LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, dev_t);
__LA_DECL void archive_entry_set_size(struct archive_entry *, __LA_INT64_T);
__LA_DECL void archive_entry_unset_size(struct archive_entry *);
__LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_copy_sourcepath_w(struct archive_entry *, const wchar_t *);
__LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_symlink(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_symlink_utf8(struct archive_entry *, const char *);
-__LA_DECL void archive_entry_set_uid(struct archive_entry *, __LA_UID_T);
+__LA_DECL void archive_entry_set_uid(struct archive_entry *, __LA_INT64_T);
__LA_DECL void archive_entry_set_uname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *);
@@ -315,6 +326,15 @@ __LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char
__LA_DECL const struct stat *archive_entry_stat(struct archive_entry *);
__LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat *);
+/*
+ * Storage for Mac OS-specific AppleDouble metadata information.
+ * Apple-format tar files store a separate binary blob containing
+ * encoded metadata with ACL, extended attributes, etc.
+ * This provides a place to store that blob.
+ */
+
+__LA_DECL const void * archive_entry_mac_metadata(struct archive_entry *, size_t *);
+__LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const void *, size_t);
/*
* ACL routines. This used to simply store and return text-format ACL
@@ -326,32 +346,95 @@ __LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat
*
* This last point, in particular, forces me to implement a reasonably
* complete set of ACL support routines.
- *
- * TODO: Extend this to support NFSv4/NTFS permissions. That should
- * allow full ACL support on Mac OS, in particular, which uses
- * POSIX.1e-style interfaces to manipulate NFSv4/NTFS permissions.
*/
/*
- * Permission bits mimic POSIX.1e. Note that I've not followed POSIX.1e's
- * "permset"/"perm" abstract type nonsense. A permset is just a simple
- * bitmap, following long-standing Unix tradition.
+ * Permission bits.
*/
-#define ARCHIVE_ENTRY_ACL_EXECUTE 1
-#define ARCHIVE_ENTRY_ACL_WRITE 2
-#define ARCHIVE_ENTRY_ACL_READ 4
+#define ARCHIVE_ENTRY_ACL_EXECUTE 0x00000001
+#define ARCHIVE_ENTRY_ACL_WRITE 0x00000002
+#define ARCHIVE_ENTRY_ACL_READ 0x00000004
+#define ARCHIVE_ENTRY_ACL_READ_DATA 0x00000008
+#define ARCHIVE_ENTRY_ACL_LIST_DIRECTORY 0x00000008
+#define ARCHIVE_ENTRY_ACL_WRITE_DATA 0x00000010
+#define ARCHIVE_ENTRY_ACL_ADD_FILE 0x00000010
+#define ARCHIVE_ENTRY_ACL_APPEND_DATA 0x00000020
+#define ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY 0x00000020
+#define ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS 0x00000040
+#define ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS 0x00000080
+#define ARCHIVE_ENTRY_ACL_DELETE_CHILD 0x00000100
+#define ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES 0x00000200
+#define ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES 0x00000400
+#define ARCHIVE_ENTRY_ACL_DELETE 0x00000800
+#define ARCHIVE_ENTRY_ACL_READ_ACL 0x00001000
+#define ARCHIVE_ENTRY_ACL_WRITE_ACL 0x00002000
+#define ARCHIVE_ENTRY_ACL_WRITE_OWNER 0x00004000
+#define ARCHIVE_ENTRY_ACL_SYNCHRONIZE 0x00008000
+
+#define ARCHIVE_ENTRY_ACL_PERMS_POSIX1E \
+ (ARCHIVE_ENTRY_ACL_EXECUTE \
+ | ARCHIVE_ENTRY_ACL_WRITE \
+ | ARCHIVE_ENTRY_ACL_READ)
+
+#define ARCHIVE_ENTRY_ACL_PERMS_NFS4 \
+ (ARCHIVE_ENTRY_ACL_EXECUTE \
+ | ARCHIVE_ENTRY_ACL_READ_DATA \
+ | ARCHIVE_ENTRY_ACL_LIST_DIRECTORY \
+ | ARCHIVE_ENTRY_ACL_WRITE_DATA \
+ | ARCHIVE_ENTRY_ACL_ADD_FILE \
+ | ARCHIVE_ENTRY_ACL_APPEND_DATA \
+ | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY \
+ | ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS \
+ | ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS \
+ | ARCHIVE_ENTRY_ACL_DELETE_CHILD \
+ | ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES \
+ | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES \
+ | ARCHIVE_ENTRY_ACL_DELETE \
+ | ARCHIVE_ENTRY_ACL_READ_ACL \
+ | ARCHIVE_ENTRY_ACL_WRITE_ACL \
+ | ARCHIVE_ENTRY_ACL_WRITE_OWNER \
+ | ARCHIVE_ENTRY_ACL_SYNCHRONIZE)
-/* We need to be able to specify either or both of these. */
-#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 256
-#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 512
+/*
+ * Inheritance values (NFS4 ACLs only); included in permset.
+ */
+#define ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT 0x02000000
+#define ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT 0x04000000
+#define ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT 0x08000000
+#define ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY 0x10000000
+#define ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS 0x20000000
+#define ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS 0x40000000
+
+#define ARCHIVE_ENTRY_ACL_INHERITANCE_NFS4 \
+ (ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT \
+ | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT \
+ | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT \
+ | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY \
+ | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS \
+ | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS)
+
+/* We need to be able to specify combinations of these. */
+#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 256 /* POSIX.1e only */
+#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 512 /* POSIX.1e only */
+#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 1024 /* NFS4 only */
+#define ARCHIVE_ENTRY_ACL_TYPE_DENY 2048 /* NFS4 only */
+#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 4096 /* NFS4 only */
+#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 8192 /* NFS4 only */
+#define ARCHIVE_ENTRY_ACL_TYPE_POSIX1E (ARCHIVE_ENTRY_ACL_TYPE_ACCESS \
+ | ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)
+#define ARCHIVE_ENTRY_ACL_TYPE_NFS4 (ARCHIVE_ENTRY_ACL_TYPE_ALLOW \
+ | ARCHIVE_ENTRY_ACL_TYPE_DENY \
+ | ARCHIVE_ENTRY_ACL_TYPE_AUDIT \
+ | ARCHIVE_ENTRY_ACL_TYPE_ALARM)
/* Tag values mimic POSIX.1e */
#define ARCHIVE_ENTRY_ACL_USER 10001 /* Specified user. */
#define ARCHIVE_ENTRY_ACL_USER_OBJ 10002 /* User who owns the file. */
#define ARCHIVE_ENTRY_ACL_GROUP 10003 /* Specified group. */
#define ARCHIVE_ENTRY_ACL_GROUP_OBJ 10004 /* Group who owns the file. */
-#define ARCHIVE_ENTRY_ACL_MASK 10005 /* Modify group access. */
-#define ARCHIVE_ENTRY_ACL_OTHER 10006 /* Public. */
+#define ARCHIVE_ENTRY_ACL_MASK 10005 /* Modify group access (POSIX.1e only) */
+#define ARCHIVE_ENTRY_ACL_OTHER 10006 /* Public (POSIX.1e only) */
+#define ARCHIVE_ENTRY_ACL_EVERYONE 10107 /* Everyone (NFS4 only) */
/*
* Set the ACL by clearing it and adding entries one at a time.
@@ -363,17 +446,17 @@ __LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat
* default and access information in a single ACL list.
*/
__LA_DECL void archive_entry_acl_clear(struct archive_entry *);
-__LA_DECL void archive_entry_acl_add_entry(struct archive_entry *,
+__LA_DECL int archive_entry_acl_add_entry(struct archive_entry *,
int /* type */, int /* permset */, int /* tag */,
int /* qual */, const char * /* name */);
-__LA_DECL void archive_entry_acl_add_entry_w(struct archive_entry *,
+__LA_DECL int archive_entry_acl_add_entry_w(struct archive_entry *,
int /* type */, int /* permset */, int /* tag */,
int /* qual */, const wchar_t * /* name */);
/*
* To retrieve the ACL, first "reset", then repeatedly ask for the
* "next" entry. The want_type parameter allows you to request only
- * access entries or only default entries.
+ * certain types of entries.
*/
__LA_DECL int archive_entry_acl_reset(struct archive_entry *, int /* want_type */);
__LA_DECL int archive_entry_acl_next(struct archive_entry *, int /* want_type */,
@@ -387,36 +470,29 @@ __LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type
* Construct a text-format ACL. The flags argument is a bitmask that
* can include any of the following:
*
- * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include access entries.
- * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include default entries.
+ * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries.
+ * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries.
+ * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - Include NFS4 entries.
* ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in
- * each ACL entry. (As used by 'star'.)
+ * each ACL entry. ('star' introduced this for POSIX.1e, this flag
+ * also applies to NFS4.)
* ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each
- * default ACL entry.
+ * default ACL entry, as used in old Solaris ACLs.
*/
#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024
#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048
__LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *,
int /* flags */);
+__LA_DECL const char *archive_entry_acl_text(struct archive_entry *,
+ int /* flags */);
/* Return a count of entries matching 'want_type' */
__LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */);
-/*
- * Private ACL parser. This is private because it handles some
- * very weird formats that clients should not be messing with.
- * Clients should only deal with their platform-native formats.
- * Because of the need to support many formats cleanly, new arguments
- * are likely to get added on a regular basis. Clients who try to use
- * this interface are likely to be surprised when it changes.
- *
- * You were warned!
- *
- * TODO: Move this declaration out of the public header and into
- * a private header. Warnings above are silly.
- */
-__LA_DECL int __archive_entry_acl_parse_w(struct archive_entry *,
- const wchar_t *, int /* type */);
+/* Return an opaque ACL object. */
+/* There's not yet anything clients can actually do with this... */
+struct archive_acl;
+__LA_DECL struct archive_acl *archive_entry_acl(struct archive_entry *);
/*
* extended attributes
@@ -438,6 +514,24 @@ __LA_DECL int archive_entry_xattr_next(struct archive_entry *,
const char ** /* name */, const void ** /* value */, size_t *);
/*
+ * sparse
+ */
+
+__LA_DECL void archive_entry_sparse_clear(struct archive_entry *);
+__LA_DECL void archive_entry_sparse_add_entry(struct archive_entry *,
+ __LA_INT64_T /* offset */, __LA_INT64_T /* length */);
+
+/*
+ * To retrieve the xattr list, first "reset", then repeatedly ask for the
+ * "next" entry.
+ */
+
+__LA_DECL int archive_entry_sparse_count(struct archive_entry *);
+__LA_DECL int archive_entry_sparse_reset(struct archive_entry *);
+__LA_DECL int archive_entry_sparse_next(struct archive_entry *,
+ __LA_INT64_T * /* offset */, __LA_INT64_T * /* length */);
+
+/*
* Utility to match up hardlinks.
*
* The 'struct archive_entry_linkresolver' is a cache of archive entries
@@ -449,7 +543,7 @@ __LA_DECL int archive_entry_xattr_next(struct archive_entry *,
* be written.
* 4. Call archive_entry_linkify(resolver, NULL) until
* no more entries are returned.
- * 5. Call archive_entry_link_resolver_free(resolver) to free resources.
+ * 5. Call archive_entry_linkresolver_free(resolver) to free resources.
*
* The entries returned have their hardlink and size fields updated
* appropriately. If an entry is passed in that does not refer to
@@ -499,7 +593,7 @@ struct archive_entry_linkresolver;
* linkify(l2) => l1
* linkify(NULL) => l2 (at end, you retrieve remaining links)
* As the name suggests, this strategy is used by newer cpio variants.
- * It's noticably more complex for the archiver, slightly more complex
+ * It's noticeably more complex for the archiver, slightly more complex
* for the dearchiver than the tar strategy, but makes it straightforward
* to restore a file using any link by simply continuing to scan until
* you see a link that is stored with a body. In contrast, the tar
@@ -513,6 +607,8 @@ __LA_DECL void archive_entry_linkresolver_set_strategy(
__LA_DECL void archive_entry_linkresolver_free(struct archive_entry_linkresolver *);
__LA_DECL void archive_entry_linkify(struct archive_entry_linkresolver *,
struct archive_entry **, struct archive_entry **);
+__LA_DECL struct archive_entry *archive_entry_partial_links(
+ struct archive_entry_linkresolver *res, unsigned int *links);
#ifdef __cplusplus
}
diff --git a/contrib/libarchive/libarchive/archive_entry_acl.3 b/contrib/libarchive/libarchive/archive_entry_acl.3
new file mode 100644
index 000000000000..8c4f0cd64ef1
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_entry_acl.3
@@ -0,0 +1,233 @@
+.\" Copyright (c) 2010 Joerg Sonnenberger
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd February 21, 2010
+.Dt ARCHIVE_ENTRY_ACL 3
+.Os
+.Sh NAME
+.Nm archive_entry_acl_add_entry ,
+.Nm archive_entry_acl_add_entry_w ,
+.Nm archive_entry_acl_clear ,
+.Nm archive_entry_acl_count ,
+.Nm archive_entry_acl_next ,
+.Nm archive_entry_acl_next_w ,
+.Nm archive_entry_acl_reset ,
+.Nm archive_entry_acl_text_w
+.Nd functions for manipulating Access Control Lists in archive entry descriptions
+.Sh SYNOPSIS
+.In archive_entry.h
+.Ft void
+.Fo archive_entry_acl_add_entry
+.Fa "struct archive_entry *a"
+.Fa "int type"
+.Fa "int permset"
+.Fa "int tag"
+.Fa "int qualifier"
+.Fa "const char *name"
+.Fc
+.Ft void
+.Fo archive_entry_acl_add_entry_w
+.Fa "struct archive_entry *a"
+.Fa "int type"
+.Fa "int permset"
+.Fa "int tag"
+.Fa "int qualifier"
+.Fa "const wchar_t *name"
+.Fc
+.Ft void
+.Fn archive_entry_acl_clear "struct archive_entry *a"
+.Ft int
+.Fn archive_entry_acl_count "struct archive_entry *a" "int type"
+.Ft int
+.Fo archive_entry_acl_next
+.Fa "struct archive_entry *a"
+.Fa "int type"
+.Fa "int *ret_type"
+.Fa "int *ret_permset"
+.Fa "int *ret_tag"
+.Fa "int *ret_qual"
+.Fa "const char **ret_name"
+.Fc
+.Ft int
+.Fo archive_entry_acl_next_w
+.Fa "struct archive_entry *a"
+.Fa "int type"
+.Fa "int *ret_type"
+.Fa "int *ret_permset"
+.Fa "int *ret_tag"
+.Fa "int *ret_qual"
+.Fa "const wchar_t **ret_name"
+.Fc
+.Ft int
+.Fn archive_entry_acl_reset "struct archive_entry *a" "int type"
+.Ft const wchar_t *
+.Fn archive_entry_acl_text_w "struct archive_entry *a" "int flags"
+.\" enum?
+.Sh DESCRIPTION
+An
+.Dq Access Control List
+is a generalisation of the classic Unix permission system.
+The ACL interface of
+.Nm libarchive
+is derived from the POSIX.1e draft, but restricted to simplify dealing
+with practical implementations in various Operating Systems and archive formats.
+.Pp
+An ACL consists of a number of independent entries.
+Each entry specifies the permission set as bitmask of basic permissions.
+Valid permissions are:
+.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_EXECUTE"
+.It Dv ARCHIVE_ENTRY_ACL_EXECUTE
+.It Dv ARCHIVE_ENTRY_ACL_WRITE
+.It Dv ARCHIVE_ENTRY_ACL_READ
+.El
+The permissions correspond to the normal Unix permissions.
+.Pp
+The tag specifies the principal to which the permission applies.
+Valid values are:
+.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ"
+.It Dv ARCHIVE_ENTRY_ACL_USER
+The user specified by the name field.
+.It Dv ARCHIVE_ENTRY_ACL_USER_OBJ
+The owner of the file.
+.It Dv ARCHIVE_ENTRY_ACL_GROUP
+The group specied by the name field.
+.It Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ
+The group who owns the file.
+.It Dv ARCHIVE_ENTRY_ACL_MASK
+The maximum permissions to be obtained via group permissions.
+.It Dv ARCHIVE_ENTRY_ACL_OTHER
+Any principal who doesn't have a user or group entry.
+.El
+The principals
+.Dv ARCHIVE_ENTRY_ACL_USER_OBJ ,
+.Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ
+and
+.Dv ARCHIVE_ENTRY_ACL_OTHER
+are equivalent to user, group and other in the classic Unix permission
+model and specify non-extended ACL entries.
+.Pp
+All files have an access ACL
+.Pq Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS .
+This specifies the permissions required for access to the file itself.
+Directories have an additional ACL
+.Pq Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT ,
+which controls the initial access ACL for newly created directory entries.
+.Pp
+.Fn archive_entry_acl_add_entry
+and
+.Fn archive_entry_acl_add_entry_w
+add a single ACL entry.
+For the access ACL and non-extended principals, the classic Unix permissions
+are updated.
+.Pp
+.Fn archive_entry_acl_clear
+removes all ACL entries and resets the enumeration pointer.
+.Pp
+.Fn archive_entry_acl_count
+counts the ACL entries that have the given type mask.
+.Fa type
+can be the bitwise-or of
+.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
+and
+.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT .
+If
+.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
+is included and at least one extended ACL entry is found,
+the three non-extened ACLs are added.
+.Pp
+.Fn archive_entry_acl_next
+and
+.Fn archive_entry_acl_next_w
+return the next entry of the ACL list.
+This functions may only be called after
+.Fn archive_entry_acl_reset
+has indicated the presence of extended ACL entries.
+.Pp
+.Fn archive_entry_acl_reset
+prepare reading the list of ACL entries with
+.Fn archive_entry_acl_next
+or
+.Fn archive_entry_acl_next_w .
+The function returns either 0, if no non-extended ACLs are found.
+In this case, the access permissions should be obtained by
+.Xr archive_entry_mode 3
+or set using
+.Xr chmod 2 .
+Otherwise, the function returns the same value as
+.Fn archive_entry_acl_count .
+.Pp
+.Fn archive_entry_acl_text_w
+converts the ACL entries for the given type mask into a wide string.
+In addition to the normal type flags,
+.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
+and
+.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
+can be specified to further customize the result.
+The returned long string is valid until the next call to
+.Fn archive_entry_acl_clear ,
+.Fn archive_entry_acl_add_entry ,
+.Fn archive_entry_acl_add_entry_w
+or
+.Fn archive_entry_acl_text_w .
+.Sh RETURN VALUES
+.Fn archive_entry_acl_count
+and
+.Fn archive_entry_acl_reset
+returns the number of ACL entries that match the given type mask.
+If the type mask includes
+.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
+and at least one extended ACL entry exists, the three classic Unix
+permissions are counted.
+.Pp
+.Fn archive_entry_acl_next
+and
+.Fn archive_entry_acl_next_w
+return
+.Dv ARCHIVE_OK
+on success,
+.Dv ARCHIVE_EOF
+if no more ACL entries exist
+and
+.Dv ARCHIVE_WARN
+if
+.Fn archive_entry_acl_reset
+has not been called first.
+.Pp
+.Fn archive_entry_text_w
+returns a wide string representation of the ACL entrise matching the
+given type mask.
+The returned long string is valid until the next call to
+.Fn archive_entry_acl_clear ,
+.Fn archive_entry_acl_add_entry ,
+.Fn archive_entry_acl_add_entry_w
+or
+.Fn archive_entry_acl_text_w .
+.Sh SEE ALSO
+.Xr archive 3 ,
+.Xr archive_entry 3
+.Sh BUGS
+.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
+and
+.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
+are not documented.
diff --git a/contrib/libarchive/libarchive/archive_entry_copy_stat.c b/contrib/libarchive/libarchive/archive_entry_copy_stat.c
index 615d3b0b168b..c4ed217281a7 100644
--- a/contrib/libarchive/libarchive/archive_entry_copy_stat.c
+++ b/contrib/libarchive/libarchive/archive_entry_copy_stat.c
@@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
#include <sys/stat.h>
#endif
+#include "archive.h"
#include "archive_entry.h"
void
@@ -59,12 +60,13 @@ archive_entry_copy_stat(struct archive_entry *entry, const struct stat *st)
archive_entry_set_atime(entry, st->st_atime, 0);
archive_entry_set_ctime(entry, st->st_ctime, 0);
archive_entry_set_mtime(entry, st->st_mtime, 0);
-#if HAVE_STRUCT_STAT_ST_BIRTHTIME
- archive_entry_set_birthtime(entry, st->st_birthtime, 0);
-#endif
#endif
#if HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC
archive_entry_set_birthtime(entry, st->st_birthtime, st->st_birthtimespec.tv_nsec);
+#elif HAVE_STRUCT_STAT_ST_BIRTHTIME
+ archive_entry_set_birthtime(entry, st->st_birthtime, 0);
+#else
+ archive_entry_unset_birthtime(entry);
#endif
archive_entry_set_dev(entry, st->st_dev);
archive_entry_set_gid(entry, st->st_gid);
diff --git a/contrib/libarchive/libarchive/archive_entry_link_resolver.c b/contrib/libarchive/libarchive/archive_entry_link_resolver.c
index a5eb624b6107..9ec0b65d605b 100644
--- a/contrib/libarchive/libarchive/archive_entry_link_resolver.c
+++ b/contrib/libarchive/libarchive/archive_entry_link_resolver.c
@@ -70,10 +70,10 @@ __FBSDID("$FreeBSD$");
struct links_entry {
struct links_entry *next;
struct links_entry *previous;
- int links; /* # links not yet seen */
- int hash;
struct archive_entry *canonical;
struct archive_entry *entry;
+ size_t hash;
+ unsigned int links; /* # links not yet seen */
};
struct archive_entry_linkresolver {
@@ -84,32 +84,37 @@ struct archive_entry_linkresolver {
int strategy;
};
+#define NEXT_ENTRY_DEFERRED 1
+#define NEXT_ENTRY_PARTIAL 2
+#define NEXT_ENTRY_ALL (NEXT_ENTRY_DEFERRED | NEXT_ENTRY_PARTIAL)
+
static struct links_entry *find_entry(struct archive_entry_linkresolver *,
struct archive_entry *);
static void grow_hash(struct archive_entry_linkresolver *);
static struct links_entry *insert_entry(struct archive_entry_linkresolver *,
struct archive_entry *);
-static struct links_entry *next_entry(struct archive_entry_linkresolver *);
+static struct links_entry *next_entry(struct archive_entry_linkresolver *,
+ int);
struct archive_entry_linkresolver *
archive_entry_linkresolver_new(void)
{
struct archive_entry_linkresolver *res;
- size_t i;
- res = malloc(sizeof(struct archive_entry_linkresolver));
+ /* Check for positive power-of-two */
+ if (links_cache_initial_size == 0 ||
+ (links_cache_initial_size & (links_cache_initial_size - 1)) != 0)
+ return (NULL);
+
+ res = calloc(1, sizeof(struct archive_entry_linkresolver));
if (res == NULL)
return (NULL);
- memset(res, 0, sizeof(struct archive_entry_linkresolver));
res->number_buckets = links_cache_initial_size;
- res->buckets = malloc(res->number_buckets *
- sizeof(res->buckets[0]));
+ res->buckets = calloc(res->number_buckets, sizeof(res->buckets[0]));
if (res->buckets == NULL) {
free(res);
return (NULL);
}
- for (i = 0; i < res->number_buckets; i++)
- res->buckets[i] = NULL;
return (res);
}
@@ -120,6 +125,11 @@ archive_entry_linkresolver_set_strategy(struct archive_entry_linkresolver *res,
int fmtbase = fmt & ARCHIVE_FORMAT_BASE_MASK;
switch (fmtbase) {
+ case ARCHIVE_FORMAT_7ZIP:
+ case ARCHIVE_FORMAT_AR:
+ case ARCHIVE_FORMAT_ZIP:
+ res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO;
+ break;
case ARCHIVE_FORMAT_CPIO:
switch (fmt) {
case ARCHIVE_FORMAT_CPIO_SVR4_NOCRC:
@@ -134,11 +144,14 @@ archive_entry_linkresolver_set_strategy(struct archive_entry_linkresolver *res,
case ARCHIVE_FORMAT_MTREE:
res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_MTREE;
break;
+ case ARCHIVE_FORMAT_ISO9660:
+ case ARCHIVE_FORMAT_SHAR:
case ARCHIVE_FORMAT_TAR:
+ case ARCHIVE_FORMAT_XAR:
res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_TAR;
break;
default:
- res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_TAR;
+ res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO;
break;
}
}
@@ -151,12 +164,9 @@ archive_entry_linkresolver_free(struct archive_entry_linkresolver *res)
if (res == NULL)
return;
- if (res->buckets != NULL) {
- while ((le = next_entry(res)) != NULL)
- archive_entry_free(le->entry);
- free(res->buckets);
- res->buckets = NULL;
- }
+ while ((le = next_entry(res, NEXT_ENTRY_ALL)) != NULL)
+ archive_entry_free(le->entry);
+ free(res->buckets);
free(res);
}
@@ -170,7 +180,7 @@ archive_entry_linkify(struct archive_entry_linkresolver *res,
*f = NULL; /* Default: Don't return a second entry. */
if (*e == NULL) {
- le = next_entry(res);
+ le = next_entry(res, NEXT_ENTRY_DEFERRED);
if (le != NULL) {
*e = le->entry;
le->entry = NULL;
@@ -249,7 +259,7 @@ find_entry(struct archive_entry_linkresolver *res,
struct archive_entry *entry)
{
struct links_entry *le;
- int hash, bucket;
+ size_t hash, bucket;
dev_t dev;
int64_t ino;
@@ -261,16 +271,12 @@ find_entry(struct archive_entry_linkresolver *res,
res->spare = NULL;
}
- /* If the links cache overflowed and got flushed, don't bother. */
- if (res->buckets == NULL)
- return (NULL);
-
dev = archive_entry_dev(entry);
ino = archive_entry_ino64(entry);
- hash = (int)(dev ^ ino);
+ hash = (size_t)(dev ^ ino);
/* Try to locate this entry in the links cache. */
- bucket = hash % res->number_buckets;
+ bucket = hash & (res->number_buckets - 1);
for (le = res->buckets[bucket]; le != NULL; le = le->next) {
if (le->hash == hash
&& dev == archive_entry_dev(le->canonical)
@@ -301,7 +307,7 @@ find_entry(struct archive_entry_linkresolver *res,
}
static struct links_entry *
-next_entry(struct archive_entry_linkresolver *res)
+next_entry(struct archive_entry_linkresolver *res, int mode)
{
struct links_entry *le;
size_t bucket;
@@ -309,22 +315,27 @@ next_entry(struct archive_entry_linkresolver *res)
/* Free a held entry. */
if (res->spare != NULL) {
archive_entry_free(res->spare->canonical);
+ archive_entry_free(res->spare->entry);
free(res->spare);
res->spare = NULL;
}
- /* If the links cache overflowed and got flushed, don't bother. */
- if (res->buckets == NULL)
- return (NULL);
-
/* Look for next non-empty bucket in the links cache. */
for (bucket = 0; bucket < res->number_buckets; bucket++) {
- le = res->buckets[bucket];
- if (le != NULL) {
+ for (le = res->buckets[bucket]; le != NULL; le = le->next) {
+ if (le->entry != NULL &&
+ (mode & NEXT_ENTRY_DEFERRED) == 0)
+ continue;
+ if (le->entry == NULL &&
+ (mode & NEXT_ENTRY_PARTIAL) == 0)
+ continue;
/* Remove it from this hash bucket. */
if (le->next != NULL)
le->next->previous = le->previous;
- res->buckets[bucket] = le->next;
+ if (le->previous != NULL)
+ le->previous->next = le->next;
+ else
+ res->buckets[bucket] = le->next;
res->number_entries--;
/* Defer freeing this entry. */
res->spare = le;
@@ -339,13 +350,12 @@ insert_entry(struct archive_entry_linkresolver *res,
struct archive_entry *entry)
{
struct links_entry *le;
- int hash, bucket;
+ size_t hash, bucket;
/* Add this entry to the links cache. */
- le = malloc(sizeof(struct links_entry));
+ le = calloc(1, sizeof(struct links_entry));
if (le == NULL)
return (NULL);
- memset(le, 0, sizeof(*le));
le->canonical = archive_entry_clone(entry);
/* If the links cache is getting too full, enlarge the hash table. */
@@ -353,7 +363,7 @@ insert_entry(struct archive_entry_linkresolver *res,
grow_hash(res);
hash = archive_entry_dev(entry) ^ archive_entry_ino64(entry);
- bucket = hash % res->number_buckets;
+ bucket = hash & (res->number_buckets - 1);
/* If we could allocate the entry, record it. */
if (res->buckets[bucket] != NULL)
@@ -376,30 +386,59 @@ grow_hash(struct archive_entry_linkresolver *res)
/* Try to enlarge the bucket list. */
new_size = res->number_buckets * 2;
- new_buckets = malloc(new_size * sizeof(struct links_entry *));
-
- if (new_buckets != NULL) {
- memset(new_buckets, 0,
- new_size * sizeof(struct links_entry *));
- for (i = 0; i < res->number_buckets; i++) {
- while (res->buckets[i] != NULL) {
- /* Remove entry from old bucket. */
- le = res->buckets[i];
- res->buckets[i] = le->next;
-
- /* Add entry to new bucket. */
- bucket = le->hash % new_size;
-
- if (new_buckets[bucket] != NULL)
- new_buckets[bucket]->previous =
- le;
- le->next = new_buckets[bucket];
- le->previous = NULL;
- new_buckets[bucket] = le;
- }
+ if (new_size < res->number_buckets)
+ return;
+ new_buckets = calloc(new_size, sizeof(struct links_entry *));
+
+ if (new_buckets == NULL)
+ return;
+
+ for (i = 0; i < res->number_buckets; i++) {
+ while (res->buckets[i] != NULL) {
+ /* Remove entry from old bucket. */
+ le = res->buckets[i];
+ res->buckets[i] = le->next;
+
+ /* Add entry to new bucket. */
+ bucket = le->hash & (new_size - 1);
+
+ if (new_buckets[bucket] != NULL)
+ new_buckets[bucket]->previous = le;
+ le->next = new_buckets[bucket];
+ le->previous = NULL;
+ new_buckets[bucket] = le;
}
- free(res->buckets);
- res->buckets = new_buckets;
- res->number_buckets = new_size;
}
+ free(res->buckets);
+ res->buckets = new_buckets;
+ res->number_buckets = new_size;
+}
+
+struct archive_entry *
+archive_entry_partial_links(struct archive_entry_linkresolver *res,
+ unsigned int *links)
+{
+ struct archive_entry *e;
+ struct links_entry *le;
+
+ /* Free a held entry. */
+ if (res->spare != NULL) {
+ archive_entry_free(res->spare->canonical);
+ archive_entry_free(res->spare->entry);
+ free(res->spare);
+ res->spare = NULL;
+ }
+
+ le = next_entry(res, NEXT_ENTRY_PARTIAL);
+ if (le != NULL) {
+ e = le->canonical;
+ if (links != NULL)
+ *links = le->links;
+ le->canonical = NULL;
+ } else {
+ e = NULL;
+ if (links != NULL)
+ *links = 0;
+ }
+ return (e);
}
diff --git a/contrib/libarchive/libarchive/archive_entry_linkify.3 b/contrib/libarchive/libarchive/archive_entry_linkify.3
new file mode 100644
index 000000000000..a34b095e7474
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_entry_linkify.3
@@ -0,0 +1,224 @@
+.\" Copyright (c) 2010 Joerg Sonnenberger
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd February 20, 2010
+.Dt ARCHIVE_ENTRY_LINKIFY 3
+.Os
+.Sh NAME
+.Nm archive_entry_linkresolver ,
+.Nm archive_entry_linkresolver_new ,
+.Nm archive_entry_linkresolver_set_strategy ,
+.Nm archive_entry_linkresolver_free ,
+.Nm archive_entry_linkify
+.Nd hardlink resolver functions
+.Sh LIBRARY
+.Lb libarchive
+.Sh SYNOPSIS
+.In archive_entry.h
+.Ft struct archive_entry_linkresolver *
+.Fn archive_entry_linkresolver_new void
+.Ft void
+.Fo archive_entry_linkresolver_set_strategy
+.Fa "struct archive_entry_linkresolver *resolver"
+.Fa "int format"
+.Fc
+.Ft void
+.Fo archive_entry_linkresolver_free
+.Fa "struct archive_entry_linkresolver *resolver"
+.Fc
+.Ft void
+.Fo archive_entry_linkify
+.Fa "struct archive_entry_linkresolver *resolver"
+.Fa "struct archive_entry **entry"
+.Fa "struct archive_entry **sparse"
+.Fc
+.Sh DESCRIPTION
+Programs that want to create archives have to deal with hardlinks.
+Hardlinks are handled in different ways by the archive formats.
+The basic strategies are:
+.Bl -enum
+.It
+Ignore hardlinks and store the body for each reference (old cpio, zip).
+.It
+Store the body the first time an inode is seen (ustar, pax).
+.It
+Store the body the last time an inode is seen (new cpio).
+.El
+.Pp
+The
+.Nm
+functions help by providing a unified interface and handling the complexity
+behind the scene.
+.Pp
+The
+.Nm
+functions assume that
+.Vt archive_entry
+instances have valid nlinks, inode and device values.
+The inode and device value is used to match entries.
+The nlinks value is used to determined if all references have been found and
+if the internal references can be recycled.
+.Pp
+The
+.Fn archive_entry_linkresolver_new
+function allocates a new link resolver.
+The instance can be freed using
+.Fn archive_entry_linkresolver_free .
+All deferred entries are flushed and the internal storage is freed.
+.Pp
+The
+.Fn archive_entry_linkresolver_set_strategy
+function selects the optimal hardlink strategy for the given format.
+The format code can be obtained from
+.Xr archive_format 3 .
+The function can be called more than once, but it is recommended to
+flush all deferred entries first.
+.Pp
+The
+.Fn archive_entry_linkify
+function is the core of
+.Nm .
+The
+.Fn entry
+argument points to the
+.Vt archive_entry
+that should be written.
+Depending on the strategy one of the following actions is taken:
+.Bl -enum
+.It
+For the simple archive formats
+.Va *entry
+is left unmodified and
+.Va *sparse
+is set to
+.Dv NULL .
+.It
+For tar like archive formats,
+.Va *sparse
+is set to
+.Dv NULL .
+If
+.Va *entry
+is
+.Dv NULL ,
+no action is taken.
+If the hardlink count of
+.Va *entry
+is larger than 1 and the file type is a regular file or symbolic link,
+the internal list is searched for a matching inode.
+If such an inode is found, the link count is decremented and the file size
+of
+.Va *entry
+is set to 0 to notify that no body should be written.
+If no such inode is found, a copy of the entry is added to the internal cache
+with a link count reduced by one.
+.It
+For new cpio like archive formats a value for
+.Va *entry
+of
+.Dv NULL
+is used to flush deferred entries.
+In that case
+.Va *entry
+is set to an arbitrary deferred entry and the entry itself is removed from the
+internal list.
+If the internal list is empty,
+.Va *entry
+is set to
+.Dv NULL .
+In either case,
+.Va *sparse
+is set to
+.Dv NULL
+and the function returns.
+If the hardlink count of
+.Va *entry
+is one or the file type is a directory or device,
+.Va *sparse
+is set to
+.Dv NULL
+and no further action is taken.
+Otherwise, the internal list is searched for a matching inode.
+If such an inode is not found, the entry is added to the internal list,
+both
+.Va *entry
+and
+.Va *sparse
+are set to
+.Dv NULL
+and the function returns.
+If such an inode is found, the link count is decremented.
+If it remains larger than one, the existing entry on the internal list
+is swapped with
+.Va *entry
+after retaining the link count.
+The existing entry is returned in
+.Va *entry .
+If the link count reached one, the new entry is also removed from the
+internal list and returned in
+.Va *sparse .
+Otherwise
+.Va *sparse
+is set to
+.Dv NULL .
+.El
+.Pp
+The general usage is therefore:
+.Bl -enum
+.It
+For each new archive entry, call
+.Fn archive_entry_linkify .
+.It
+Keep in mind that the entries returned may have a size of 0 now.
+.It
+If
+.Va *entry
+is not
+.Dv NULL ,
+archive it.
+.It
+If
+.Va *sparse
+is not
+.Dv NULL ,
+archive it.
+.It
+After all entries have been written to disk, call
+.Fn archive_entry_linkify
+with
+.Va *entry
+set to
+.Dv NULL
+and archive the returned entry as long as it is not
+.Dv NULL .
+.El
+.Sh RETURN VALUES
+.Fn archive_entry_linkresolver_new
+returns
+.Dv NULL
+on
+.Xr malloc 3
+failures.
+.Sh SEE ALSO
+.Xr archive_entry 3
diff --git a/contrib/libarchive/libarchive/archive_entry_locale.h b/contrib/libarchive/libarchive/archive_entry_locale.h
new file mode 100644
index 000000000000..02e024ae20c1
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_entry_locale.h
@@ -0,0 +1,88 @@
+/*-
+ * Copyright (c) 2011 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
+#ifndef ARCHIVE_ENTRY_LOCALE_H_INCLUDED
+#define ARCHIVE_ENTRY_LOCALE_H_INCLUDED
+
+struct archive_entry;
+struct archive_string_conv;
+
+/*
+ * Utility functions to set and get entry attributes by translating
+ * character-set. These are designed for use in format readers and writers.
+ *
+ * The return code and interface of these are quite different from other
+ * functions for archive_entry defined in archive_entry.h.
+ * Common return code are:
+ * Return 0 if the string conversion succeeded.
+ * Return -1 if the string conversion failed.
+ */
+
+#define archive_entry_gname_l _archive_entry_gname_l
+int _archive_entry_gname_l(struct archive_entry *,
+ const char **, size_t *, struct archive_string_conv *);
+#define archive_entry_hardlink_l _archive_entry_hardlink_l
+int _archive_entry_hardlink_l(struct archive_entry *,
+ const char **, size_t *, struct archive_string_conv *);
+#define archive_entry_pathname_l _archive_entry_pathname_l
+int _archive_entry_pathname_l(struct archive_entry *,
+ const char **, size_t *, struct archive_string_conv *);
+#define archive_entry_symlink_l _archive_entry_symlink_l
+int _archive_entry_symlink_l(struct archive_entry *,
+ const char **, size_t *, struct archive_string_conv *);
+#define archive_entry_uname_l _archive_entry_uname_l
+int _archive_entry_uname_l(struct archive_entry *,
+ const char **, size_t *, struct archive_string_conv *);
+#define archive_entry_acl_text_l _archive_entry_acl_text_l
+int _archive_entry_acl_text_l(struct archive_entry *, int,
+ const char **, size_t *, struct archive_string_conv *);
+
+
+#define archive_entry_copy_gname_l _archive_entry_copy_gname_l
+int _archive_entry_copy_gname_l(struct archive_entry *,
+ const char *, size_t, struct archive_string_conv *);
+#define archive_entry_copy_hardlink_l _archive_entry_copy_hardlink_l
+int _archive_entry_copy_hardlink_l(struct archive_entry *,
+ const char *, size_t, struct archive_string_conv *);
+#define archive_entry_copy_link_l _archive_entry_copy_link_l
+int _archive_entry_copy_link_l(struct archive_entry *,
+ const char *, size_t, struct archive_string_conv *);
+#define archive_entry_copy_pathname_l _archive_entry_copy_pathname_l
+int _archive_entry_copy_pathname_l(struct archive_entry *,
+ const char *, size_t, struct archive_string_conv *);
+#define archive_entry_copy_symlink_l _archive_entry_copy_symlink_l
+int _archive_entry_copy_symlink_l(struct archive_entry *,
+ const char *, size_t, struct archive_string_conv *);
+#define archive_entry_copy_uname_l _archive_entry_copy_uname_l
+int _archive_entry_copy_uname_l(struct archive_entry *,
+ const char *, size_t, struct archive_string_conv *);
+
+#endif /* ARCHIVE_ENTRY_LOCALE_H_INCLUDED */
diff --git a/contrib/libarchive/libarchive/archive_entry_paths.3 b/contrib/libarchive/libarchive/archive_entry_paths.3
new file mode 100644
index 000000000000..621f65518e1d
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_entry_paths.3
@@ -0,0 +1,151 @@
+.\" Copyright (c) 2010 Joerg Sonnenberger
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd February 22, 2010
+.Dt ARCHIVE_ENTRY_PATHS 3
+.Os
+.Sh NAME
+.Nm archive_entry_hardlink ,
+.Nm archive_entry_hardlink_w ,
+.Nm archive_entry_set_hardlink ,
+.Nm archive_entry_copy_hardlink ,
+.Nm archive_entry_copy_hardlink_w ,
+.Nm archve_entry_update_hardlink_utf8 ,
+.Nm archive_entry_set_link ,
+.Nm archive_entry_copy_link ,
+.Nm archive_entry_copy_link_w ,
+.Nm archve_entry_update_link_utf8 ,
+.Nm archive_entry_pathname ,
+.Nm archive_entry_pathname_w ,
+.Nm archive_entry_set_pathname ,
+.Nm archive_entry_copy_pathname ,
+.Nm archive_entry_copy_pathname_w ,
+.Nm archve_entry_update_pathname_utf8 ,
+.Nm archive_entry_sourcepath ,
+.Nm archive_entry_copy_sourcepath ,
+.Nm archive_entry_symlink,
+.Nm archive_entry_symlink_w,
+.Nm archive_entry_set_symlink ,
+.Nm archive_entry_copy_symlink ,
+.Nm archive_entry_copy_symlink_w ,
+.Nm archve_entry_update_symlink_utf8
+.Nd functions for manipulating path names in archive entry descriptions
+.Sh SYNOPSIS
+.In archive_entry.h
+.Ft const char *
+.Fn archive_entry_hardlink "struct archive_entry *a"
+.Ft const wchar_t *
+.Fn archive_entry_hardlink_w "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_hardlink "struct archive_entry *a" "const char *path"
+.Ft void
+.Fn archive_entry_copy_hardlink "struct archive_entry *a" "const char *path"
+.Ft void
+.Fn archive_entry_copy_hardlink_w "struct archive_entry *a "const wchar_t *path"
+.Ft int
+.Fn archive_entry_update_hardlink_utf8 "struct archive_entry *a" "const char *path"
+.Ft void
+.Fn archive_entry_set_link "struct archive_entry *a" "const char *path"
+.Ft void
+.Fn archive_entry_copy_link "struct archive_entry *a" " const char *path"
+.Ft void
+.Fn archive_entry_copy_link_w "struct archive_entry *a" " const wchar_t *path"
+.Ft int
+.Fn archive_entry_update_link_utf8 "struct archive_entry *a" " const char *path"
+.Ft const char *
+.Fn archive_entry_pathname "struct archive_entry *a"
+.Ft const wchar_t *
+.Fn archive_entry_pathname_w "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_pathname "struct archive_entry *a" "const char *path"
+.Ft void
+.Fn archive_entry_copy_pathname "struct archive_entry *a" "const char *path"
+.Ft void
+.Fn archive_entry_copy_pathname_w "struct archive_entry *a" "const wchar_t *path"
+.Ft int
+.Fn archive_entry_update_pathname_utf8 "struct archive_entry *a" "const char *path"
+.Ft const char *
+.Fn archive_entry_sourcepath "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_copy_sourcepath "struct archive_entry *a" "const char *path"
+.Ft const char *
+.Fn archive_entry_symlink "struct archive_entry *a"
+.Ft const wchar_t *
+.Fn archive_entry_symlink_w "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_symlink "struct archive_entry *a" "const char *path"
+.Ft void
+.Fn archive_entry_copy_symlink "struct archive_entry *a" "const char *path"
+.Ft void
+.Fn archive_entry_copy_symlink_w "struct archive_entry *a" "const wchar_t *path"
+.Ft int
+.Fn archive_entry_update_symlink_utf8 "struct archive_entry *a" "const char *path"
+.Sh DESCRIPTION
+Path names supported by
+.Xr archive_entry 3 :
+.Bl -tag -width "sourcepath" -compact
+.It hardlink
+Destination of the hardlink.
+.It link
+Update only.
+For a symlink, update the destination.
+Otherwise, make the entry a hardlink and alter
+the destination for that.
+.It pathname
+Path in the archive
+.It sourcepath
+Path on the disk for use by
+.Xr archive_read_disk 3 .
+.It symlink
+Destination of the symbolic link.
+.El
+.Pp
+Path names can be provided in one of three different ways:
+.Bl -tag -width "wchar_t *"
+.It char *
+Multibyte strings in the current locale.
+.It wchar_t *
+Wide character strings in the current locale.
+The accessor functions are named
+.Fn XXX_w .
+.It UTF-8
+Unicode strings encoded as UTF-8.
+This are convience functions to update both the multibyte and wide
+character strings at the same time.
+.El
+.Pp
+The sourcepath is a pure filesystem concept and never stored in an
+archive directly.
+.Pp
+For that reason, it is only available as multibyte string.
+The link path is a convience function for conditionally setting
+hardlink or symlink destination.
+It doesn't have a corresponding get accessor function.
+.Pp
+.Fn archive_entry_set_XXX
+is an alias for
+.Fn archive_entry_copy_XXX .
+.Sh SEE ALSO
+.Xr archive 3 ,
+.Xr archive_entry 3
diff --git a/contrib/libarchive/libarchive/archive_entry_perms.3 b/contrib/libarchive/libarchive/archive_entry_perms.3
new file mode 100644
index 000000000000..164af9731dc7
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_entry_perms.3
@@ -0,0 +1,207 @@
+.\" Copyright (c) 2003-2007 Tim Kientzle
+.\" Copyright (c) 2010 Joerg Sonnenberger
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd February 22, 2010
+.Dt ARCHIVE_ENTRY_PERMS 3
+.Os
+.Sh NAME
+.Nm archive_entry_gid ,
+.Nm archive_entry_set_gid ,
+.Nm archive_entry_uid ,
+.Nm archive_entry_set_uid ,
+.Nm archive_entry_perm ,
+.Nm archive_entry_set_perm ,
+.Nm archive_entry_strmode ,
+.Nm archive_entry_uname
+.Nm archive_entry_uname_w
+.Nm archive_entry_set_uname ,
+.Nm archive_entry_copy_uname ,
+.Nm archive_entry_copy_uname_w ,
+.Nm archive_entry_update_uname_utf8 ,
+.Nm archive_entry_gname ,
+.Nm archive_entry_gname_w ,
+.Nm archive_entry_set_gname ,
+.Nm archive_entry_copy_gname ,
+.Nm archive_entry_copy_gname_w ,
+.Nm archive_entry_update_gname_utf8 ,
+.Nm archive_entry_fflags ,
+.Nm archive_entry_fflags_text ,
+.Nm archive_entry_set_fflags ,
+.Nm archive_entry_copy_fflags_text ,
+.Nm archive_entry_copy_fflags_text_w
+.Nd functions for manipulating ownership and permissions in archive entry descriptions
+.Sh SYNOPSIS
+.In archive_entry.h
+.Ft gid_t
+.Fn archive_entry_gid "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_gid "struct archive_entry *a" "gid_t gid"
+.Ft uid_t
+.Fn archive_entry_uid "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_uid "struct archive_entry *a" "uid_t uid"
+.Ft mode_t
+.Fn archive_entry_perm "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_perm "struct archive_entry *a" "mode_t mode"
+.Ft const char *
+.Fn archive_entry_strmode "struct archive_entry *a"
+.Ft const char *
+.Fn archive_entry_gname "struct archive_entry *a"
+.Ft const wchar_t *
+.Fn archive_entry_gname_w "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_gname "struct archive_entry *a" "const char *a"
+.Ft void
+.Fn archive_entry_copy_gname "struct archive_entry *a" "const char *name"
+.Ft void
+.Fn archive_entry_copy_gname_w "struct archive_entry *a" "const wchar_t *name"
+.Ft int
+.Fn archive_entry_update_gname_utf8 "struct archive_entry *a" "const char *name"
+.Ft const char *
+.Fn archive_entry_uname "struct archive_entry *a"
+.Ft const wchar_t *
+.Fn archive_entry_uname_w "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_uname "struct archive_entry *a" "const char *name"
+.Ft void
+.Fn archive_entry_copy_uname "struct archive_entry *a" "const char *name"
+.Ft void
+.Fn archive_entry_copy_uname_w "struct archive_entry *a" "const wchar_t *name"
+.Ft int
+.Fn archive_entry_update_uname_utf8 "struct archive_entry *a" "const char *name"
+.Ft void
+.Fo archive_entry_fflags
+.Fa "struct archive_entry *a"
+.Fa "unsigned long *set_bits"
+.Fa "unsigned long *clear_bits"
+.Fc
+.Ft const char *
+.Fn archive_entry_fflags_text "struct archive_entry *a"
+.Ft void
+.Fo archive_entry_set_fflags
+.Fa "struct archive_entry *a"
+.Fa "unsigned long set_bits"
+.Fa "unsigned long clear_bits"
+.Fc
+.Ft const char *
+.Fn archive_entry_copy_fflags_text "struct archive_entry *a" "const char *text"
+.Ft const wchar_t *
+.Fn archive_entry_copy_fflags_text_w "struct archive_entry *a" "const wchar_t *text"
+.Sh DESCRIPTION
+.Ss User id, group id and mode
+The functions
+.Fn archive_entry_uid ,
+.Fn archive_entry_gid ,
+and
+.Fn archive_entry_perm
+can be used to extract the user id, group id and permission from the given entry.
+The corresponding functions
+.Fn archive_entry_set_uid ,
+.Fn archive_entry_set_gid ,
+and
+.Fn archive_entry_set_perm
+store the given user id, group id and permission in the entry.
+The permission is also set as side effect of calling
+.Fn archive_entry_set_mode .
+.Pp
+.Fn archive_entry_strmode
+returns a string representation of the permission as used by the long mode of
+.Xr ls 1 .
+.Ss User and group name
+User and group names can be provided in one of three different ways:
+.Bl -tag -width "wchar_t *"
+.It char *
+Multibyte strings in the current locale.
+.It wchar_t *
+Wide character strings in the current locale.
+The accessor functions are named
+.Fn XXX_w .
+.It UTF-8
+Unicode strings encoded as UTF-8.
+This are convience functions to update both the multibyte and wide
+character strings at the same time.
+.El
+.Pp
+.Fn archive_entry_set_XXX
+is an alias for
+.Fn archive_entry_copy_XXX .
+.Ss File Flags
+File flags are transparently converted between a bitmap
+representation and a textual format.
+For example, if you set the bitmap and ask for text, the library
+will build a canonical text format.
+However, if you set a text format and request a text format,
+you will get back the same text, even if it is ill-formed.
+If you need to canonicalize a textual flags string, you should first set the
+text form, then request the bitmap form, then use that to set the bitmap form.
+Setting the bitmap format will clear the internal text representation
+and force it to be reconstructed when you next request the text form.
+.Pp
+The bitmap format consists of two integers, one containing bits
+that should be set, the other specifying bits that should be
+cleared.
+Bits not mentioned in either bitmap will be ignored.
+Usually, the bitmap of bits to be cleared will be set to zero.
+In unusual circumstances, you can force a fully-specified set
+of file flags by setting the bitmap of flags to clear to the complement
+of the bitmap of flags to set.
+(This differs from
+.Xr fflagstostr 3 ,
+which only includes names for set bits.)
+Converting a bitmap to a textual string is a platform-specific
+operation; bits that are not meaningful on the current platform
+will be ignored.
+.Pp
+The canonical text format is a comma-separated list of flag names.
+The
+.Fn archive_entry_copy_fflags_text
+and
+.Fn archive_entry_copy_fflags_text_w
+functions parse the provided text and sets the internal bitmap values.
+This is a platform-specific operation; names that are not meaningful
+on the current platform will be ignored.
+The function returns a pointer to the start of the first name that was not
+recognized, or NULL if every name was recognized.
+Note that every name \(em including names that follow an unrecognized
+name \(em will be evaluated, and the bitmaps will be set to reflect
+every name that is recognized.
+(In particular, this differs from
+.Xr strtofflags 3 ,
+which stops parsing at the first unrecognized name.)
+.Sh SEE ALSO
+.Xr archive 3 ,
+.Xr archive_entry 3 ,
+.Xr archive_entry_acl 3 ,
+.Xr archive_read_disk 3 ,
+.Xr archive_write_disk 3
+.Sh BUGS
+The platform types
+.Vt uid_t
+and
+.Vt gid_t
+are often 16 or 32 bit wide.
+In this case it is possible that the ids can not be correctly restored
+from archives and get truncated.
diff --git a/contrib/libarchive/libarchive/archive_entry_private.h b/contrib/libarchive/libarchive/archive_entry_private.h
index d59021c24875..fba85ba05b28 100644
--- a/contrib/libarchive/libarchive/archive_entry_private.h
+++ b/contrib/libarchive/libarchive/archive_entry_private.h
@@ -32,36 +32,9 @@
#ifndef ARCHIVE_ENTRY_PRIVATE_H_INCLUDED
#define ARCHIVE_ENTRY_PRIVATE_H_INCLUDED
+#include "archive_acl_private.h"
#include "archive_string.h"
-/*
- * Handle wide character (i.e., Unicode) and non-wide character
- * strings transparently.
- */
-
-struct aes {
- struct archive_string aes_mbs;
- struct archive_string aes_utf8;
- const wchar_t *aes_wcs;
- /* Bitmap of which of the above are valid. Because we're lazy
- * about malloc-ing and reusing the underlying storage, we
- * can't rely on NULL pointers to indicate whether a string
- * has been set. */
- int aes_set;
-#define AES_SET_MBS 1
-#define AES_SET_UTF8 2
-#define AES_SET_WCS 4
-};
-
-struct ae_acl {
- struct ae_acl *next;
- int type; /* E.g., access or default */
- int tag; /* E.g., user/group/other/mask */
- int permset; /* r/w/x bits */
- int id; /* uid/gid for user/group */
- struct aes name; /* uname/gname */
-};
-
struct ae_xattr {
struct ae_xattr *next;
@@ -70,6 +43,13 @@ struct ae_xattr {
size_t size;
};
+struct ae_sparse {
+ struct ae_sparse *next;
+
+ int64_t offset;
+ int64_t length;
+};
+
/*
* Description of an archive entry.
*
@@ -91,6 +71,8 @@ struct ae_xattr {
* TODO: Design a good API for handling sparse files.
*/
struct archive_entry {
+ struct archive *archive;
+
/*
* Note that ae_stat.st_mode & AE_IFMT can be 0!
*
@@ -101,10 +83,15 @@ struct archive_entry {
*/
/*
- * Read archive_entry_copy_stat.c for an explanation of why I
- * don't just use "struct stat" instead of "struct aest" here
- * and why I have this odd pointer to a separately-allocated
- * struct stat.
+ * We have a "struct aest" for holding file metadata rather than just
+ * a "struct stat" because on some platforms the "struct stat" has
+ * fields which are too narrow to hold the range of possible values;
+ * we don't want to lose information if we read an archive and write
+ * out another (e.g., in "tar -cf new.tar @old.tar").
+ *
+ * The "stat" pointer points to some form of platform-specific struct
+ * stat; it is declared as a void * rather than a struct stat * as
+ * some platforms have multiple varieties of stat structures.
*/
void *stat;
int stat_valid; /* Set to 0 whenever a field in aest changes. */
@@ -118,12 +105,11 @@ struct archive_entry {
uint32_t aest_mtime_nsec;
int64_t aest_birthtime;
uint32_t aest_birthtime_nsec;
- gid_t aest_gid;
+ int64_t aest_gid;
int64_t aest_ino;
- mode_t aest_mode;
uint32_t aest_nlink;
uint64_t aest_size;
- uid_t aest_uid;
+ int64_t aest_uid;
/*
* Because converting between device codes and
* major/minor values is platform-specific and
@@ -150,35 +136,41 @@ struct archive_entry {
#define AE_SET_MTIME 16
#define AE_SET_BIRTHTIME 32
#define AE_SET_SIZE 64
+#define AE_SET_INO 128
+#define AE_SET_DEV 256
/*
* Use aes here so that we get transparent mbs<->wcs conversions.
*/
- struct aes ae_fflags_text; /* Text fflags per fflagstostr(3) */
+ struct archive_mstring ae_fflags_text; /* Text fflags per fflagstostr(3) */
unsigned long ae_fflags_set; /* Bitmap fflags */
unsigned long ae_fflags_clear;
- struct aes ae_gname; /* Name of owning group */
- struct aes ae_hardlink; /* Name of target for hardlink */
- struct aes ae_pathname; /* Name of entry */
- struct aes ae_symlink; /* symlink contents */
- struct aes ae_uname; /* Name of owner */
+ struct archive_mstring ae_gname; /* Name of owning group */
+ struct archive_mstring ae_hardlink; /* Name of target for hardlink */
+ struct archive_mstring ae_pathname; /* Name of entry */
+ struct archive_mstring ae_symlink; /* symlink contents */
+ struct archive_mstring ae_uname; /* Name of owner */
/* Not used within libarchive; useful for some clients. */
- struct aes ae_sourcepath; /* Path this entry is sourced from. */
+ struct archive_mstring ae_sourcepath; /* Path this entry is sourced from. */
+
+ void *mac_metadata;
+ size_t mac_metadata_size;
/* ACL support. */
- struct ae_acl *acl_head;
- struct ae_acl *acl_p;
- int acl_state; /* See acl_next for details. */
- wchar_t *acl_text_w;
+ struct archive_acl acl;
/* extattr support. */
struct ae_xattr *xattr_head;
struct ae_xattr *xattr_p;
+ /* sparse support. */
+ struct ae_sparse *sparse_head;
+ struct ae_sparse *sparse_tail;
+ struct ae_sparse *sparse_p;
+
/* Miscellaneous. */
char strmode[12];
};
-
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
diff --git a/contrib/libarchive/libarchive/archive_entry_sparse.c b/contrib/libarchive/libarchive/archive_entry_sparse.c
new file mode 100644
index 000000000000..10c54474a379
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_entry_sparse.c
@@ -0,0 +1,156 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2010-2011 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#include "archive.h"
+#include "archive_entry.h"
+#include "archive_private.h"
+#include "archive_entry_private.h"
+
+/*
+ * sparse handling
+ */
+
+void
+archive_entry_sparse_clear(struct archive_entry *entry)
+{
+ struct ae_sparse *sp;
+
+ while (entry->sparse_head != NULL) {
+ sp = entry->sparse_head->next;
+ free(entry->sparse_head);
+ entry->sparse_head = sp;
+ }
+ entry->sparse_tail = NULL;
+}
+
+void
+archive_entry_sparse_add_entry(struct archive_entry *entry,
+ int64_t offset, int64_t length)
+{
+ struct ae_sparse *sp;
+
+ if (offset < 0 || length < 0)
+ /* Invalid value */
+ return;
+ if (offset + length < 0 ||
+ offset + length > archive_entry_size(entry))
+ /* A value of "length" parameter is too large. */
+ return;
+ if ((sp = entry->sparse_tail) != NULL) {
+ if (sp->offset + sp->length > offset)
+ /* Invalid value. */
+ return;
+ if (sp->offset + sp->length == offset) {
+ if (sp->offset + sp->length + length < 0)
+ /* A value of "length" parameter is
+ * too large. */
+ return;
+ /* Expand existing sparse block size. */
+ sp->length += length;
+ return;
+ }
+ }
+
+ if ((sp = (struct ae_sparse *)malloc(sizeof(*sp))) == NULL)
+ /* XXX Error XXX */
+ return;
+
+ sp->offset = offset;
+ sp->length = length;
+ sp->next = NULL;
+
+ if (entry->sparse_head == NULL)
+ entry->sparse_head = entry->sparse_tail = sp;
+ else {
+ /* Add a new sparse block to the tail of list. */
+ if (entry->sparse_tail != NULL)
+ entry->sparse_tail->next = sp;
+ entry->sparse_tail = sp;
+ }
+}
+
+
+/*
+ * returns number of the sparse entries
+ */
+int
+archive_entry_sparse_count(struct archive_entry *entry)
+{
+ struct ae_sparse *sp;
+ int count = 0;
+
+ for (sp = entry->sparse_head; sp != NULL; sp = sp->next)
+ count++;
+
+ /*
+ * Sanity check if this entry is exactly sparse.
+ * If amount of sparse blocks is just one and it indicates the whole
+ * file data, we should remove it and return zero.
+ */
+ if (count == 1) {
+ sp = entry->sparse_head;
+ if (sp->offset == 0 &&
+ sp->length >= archive_entry_size(entry)) {
+ count = 0;
+ archive_entry_sparse_clear(entry);
+ }
+ }
+
+ return (count);
+}
+
+int
+archive_entry_sparse_reset(struct archive_entry * entry)
+{
+ entry->sparse_p = entry->sparse_head;
+
+ return archive_entry_sparse_count(entry);
+}
+
+int
+archive_entry_sparse_next(struct archive_entry * entry,
+ int64_t *offset, int64_t *length)
+{
+ if (entry->sparse_p) {
+ *offset = entry->sparse_p->offset;
+ *length = entry->sparse_p->length;
+
+ entry->sparse_p = entry->sparse_p->next;
+
+ return (ARCHIVE_OK);
+ } else {
+ *offset = 0;
+ *length = 0;
+ return (ARCHIVE_WARN);
+ }
+}
+
+/*
+ * end of sparse handling
+ */
diff --git a/contrib/libarchive/libarchive/archive_entry_stat.3 b/contrib/libarchive/libarchive/archive_entry_stat.3
new file mode 100644
index 000000000000..36a7efb2322a
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_entry_stat.3
@@ -0,0 +1,272 @@
+.\" Copyright (c) 2010 Joerg Sonnenberger
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd May 12, 2008
+.Dt ARCHIVE_ENTRY 3
+.Os
+.Sh NAME
+.Nm archive_entry_stat ,
+.Nm archive_entry_copy_stat ,
+.Nm archive_entry_filetype ,
+.Nm archive_entry_set_filetype ,
+.Nm archive_entry_mode ,
+.Nm archive_entry_set_mode ,
+.Nm archive_entry_size ,
+.Nm archive_entry_size_is_set ,
+.Nm archive_entry_set_size ,
+.Nm archive_entry_unset_size ,
+.Nm archive_entry_dev ,
+.Nm archive_entry_set_dev ,
+.Nm archive_entry_dev_is_set ,
+.Nm archive_entry_devmajor ,
+.Nm archive_entry_set_devmajor ,
+.Nm archive_entry_devminor ,
+.Nm archive_entry_set_devminor ,
+.Nm archive_entry_ino ,
+.Nm archive_entry_set_ino ,
+.Nm archive_entry_ino_is_set ,
+.Nm archive_entry_ino64 ,
+.Nm archive_entry_set_ino64 ,
+.Nm archive_entry_nlink ,
+.Nm archive_entry_rdev ,
+.Nm archive_entry_set_rdev ,
+.Nm archive_entry_rdevmajor ,
+.Nm archive_entry_set_rdevmajor ,
+.Nm archive_entry_rdevminor ,
+.Nm archive_entry_set_rdevminor ,
+.Nd accessor functions for manipulating archive entry descriptions
+.Sh SYNOPSIS
+.In archive_entry.h
+.Ft const struct stat *
+.Fn archive_entry_stat "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_copy_stat "struct archive_entry *a" "const struct stat *sb"
+.Ft mode_t
+.Fn archive_entry_filetype "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_filetype "struct archive_entry *a" "unsigned int type"
+.Ft mode_t
+.Fn archive_entry_mode "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_mode "struct archive_entry *a" "mode_t mode"
+.Ft int64_t
+.Fn archive_entry_size "struct archive_entry *a"
+.Ft int
+.Fn archive_entry_size_is_set "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_size "struct archive_entry *a" "int64_t size"
+.Ft void
+.Fn archive_entry_unset_size "struct archive_entry *a"
+.Ft dev_t
+.Fn archive_entry_dev "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_dev "struct archive_entry *a" "dev_t dev"
+.Ft int
+.Fn archive_entry_dev_is_set "struct archive_entry *a"
+.Ft dev_t
+.Fn archive_entry_devmajor "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_devmajor "struct archive_entry *a" "dev_t major"
+.Ft dev_t
+.Fn archive_entry_devminor "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_devminor "struct archive_entry *a" "dev_t minor"
+.Ft ino_t
+.Fn archive_entry_ino "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_ino "struct archive_entry *a" "unsigned long ino"
+.Ft int
+.Fn archive_entry_ino_is_set "struct archive_entry *a"
+.Ft int64_t
+.Fn archive_entry_ino64 "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_ino64 "struct archive_entry *a" "int64_t ino"
+.Ft unsigned int
+.Fn archive_entry_nlink "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_nlink "struct archive_entry *a" "unsigned int count"
+.Ft dev_t
+.Fn archive_entry_rdev "struct archive_entry *a"
+.Ft dev_t
+.Fn archive_entry_rdevmajor "struct archive_entry *a"
+.Ft dev_t
+.Fn archive_entry_rdevminor "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_rdev "struct archive_entry *a" "dev_t dev"
+.Ft void
+.Fn archive_entry_set_rdevmajor "struct archive_entry *a" "dev_t major"
+.Ft void
+.Fn archive_entry_set_rdevminor "struct archive_entry *a" "dev_t minor"
+.Sh DESCRIPTION
+.Ss Copying to and from Vt struct stat
+The function
+.Fn archive_entry_stat
+converts the various fields stored in the archive entry to the format
+used by
+.Xr stat 2 .
+The return value remains valid until either
+.Fn archive_entry_clear
+or
+.Fn archive_entry_free
+is called.
+It is not affected by calls to the set accessor functions.
+It currently sets the following values in
+.Vt struct stat :
+.Vt st_atime ,
+.Vt st_ctime ,
+.Vt st_dev ,
+.Vt st_gid ,
+.Vt st_ino ,
+.Vt st_mode ,
+.Vt st_mtime ,
+.Vt st_nlink ,
+.Vt st_rdev ,
+.Vt st_size ,
+.Vt st_uid .
+In addition,
+.Vt st_birthtime
+and high-precision information for time-related fields
+will be included on platforms that support it.
+.Pp
+The function
+.Fn archive_entry_copy_stat
+copies fields from the platform's
+.Vt struct stat .
+Fields not provided by
+.Vt struct stat
+are unchanged.
+.Ss General accessor functions
+The functions
+.Fn archive_entry_filetype
+and
+.Fn archive_entry_set_filetype
+get respectively set the filetype.
+The file type is one of the following constants:
+.Bl -tag -width "AE_IFSOCK" -compact -offset indent
+.It AE_IFREG
+Regular file
+.It AE_IFLNK
+Symbolic link
+.It AE_IFSOCK
+Socket
+.It AE_IFCHR
+Character device
+.It AE_IFBLK
+Block device
+.It AE_IFDIR
+Directory
+.It AE_IFIFO
+Named pipe (fifo)
+.El
+Not all file types are supported by all platforms.
+The constants used by
+.Xr stat 2
+may have different numeric values from the
+corresponding constants above.
+.Pp
+The functions
+.Fn archive_entry_mode
+and
+.Fn archive_entry_set_mode
+get/set a combination of file type and permissions and provide the
+equivalent of
+.Va st_mode .
+Use of
+.Fn archive_entry_filetype
+and
+.Fn archive_entry_perm
+for getting and
+.Fn archive_entry_set_filetype
+and
+.Fn archive_entry_set_perm
+for setting is recommended.
+.Pp
+The function
+.Fn archive_entry_size
+returns the file size, if it has been set, and 0 otherwise.
+.Fn archive_entry_size
+can be used to query that status.
+.Fn archive_entry_set_size
+and
+.Fn archive_entry_unset_size
+set and unset the size, respectively.
+.Pp
+The number of references (hardlinks) can be obtained by calling
+.Fn archive_entry_nlinks
+and set with
+.Fn archive_entry_set_nlinks .
+.Ss Identifying unique files
+The functions
+.Fn archive_entry_dev
+and
+.Fn archive_entry_ino64
+are used by
+.Xr archive_entry_linkify 3
+to find hardlinks.
+The pair of device and inode is suppossed to identify hardlinked files.
+.Pp
+The device major and minor number can be obtained independently using
+.Fn archive_entry_devmajor
+and
+.Fn archive_entry_devminor .
+The device can be set either via
+.Fn archive_entry_set_dev
+or by the combination of major and minor number using
+.Fn archive_entry_set_devmajor
+and
+.Fn archive_entry_set_devminor .
+.Pp
+The inode number can be obtained using
+.Fn archive_entry_ino .
+This is a legacy interface that uses the platform
+.Vt ino_t ,
+which may be very small.
+To set the inode number,
+.Fn archive_entry_set_ino64
+is the preferred interface.
+.Ss Accessor functions for block and character devices
+Block and character devices are characterised either using a device number
+or a pair of major and minor number.
+The combined device number can be obtained with
+.Fn archive_device_rdev
+and set with
+.Fn archive_device_set_rdev .
+The major and minor numbers are accessed by
+.Fn archive_device_rdevmajor ,
+.Fn archive_device_rdevminor
+.Fn archive_device_set_rdevmajor
+and
+.Fn archive_device_set_rdevminor .
+.Pp
+The process of splitting the combined device number into major and
+minor number and the reverse process of combing them differs between
+platforms.
+Some archive formats use the combined form, while other formats use
+the split form.
+.Sh SEE ALSO
+.Xr archive 3 ,
+.Xr archive_entry_acl 3 ,
+.Xr archive_entry_perms 3 ,
+.Xr archive_entry_time 3 ,
+.Xr stat 2
diff --git a/contrib/libarchive/libarchive/archive_entry_stat.c b/contrib/libarchive/libarchive/archive_entry_stat.c
index cdaeac3429a1..2edc5d200754 100644
--- a/contrib/libarchive/libarchive/archive_entry_stat.c
+++ b/contrib/libarchive/libarchive/archive_entry_stat.c
@@ -41,7 +41,7 @@ archive_entry_stat(struct archive_entry *entry)
{
struct stat *st;
if (entry->stat == NULL) {
- entry->stat = malloc(sizeof(*st));
+ entry->stat = calloc(1, sizeof(*st));
if (entry->stat == NULL)
return (NULL);
entry->stat_valid = 0;
@@ -110,7 +110,7 @@ archive_entry_stat(struct archive_entry *entry)
/*
* TODO: On Linux, store 32 or 64 here depending on whether
* the cached stat structure is a stat32 or a stat64. This
- * will allow us to support both variants interchangably.
+ * will allow us to support both variants interchangeably.
*/
entry->stat_valid = 1;
diff --git a/contrib/libarchive/libarchive/archive_entry_time.3 b/contrib/libarchive/libarchive/archive_entry_time.3
new file mode 100644
index 000000000000..85a8209e89c0
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_entry_time.3
@@ -0,0 +1,127 @@
+.\" Copyright (c) 2003-2007 Tim Kientzle
+.\" Copyright (c) 2010 Joerg Sonnenberger
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/lib/libarchive/archive_entry.3,v 1.18 2008/05/26 17:00:22 kientzle Exp $
+.\"
+.Dd February 21, 2010
+.Dt ARCHIVE_ENTRY_TIME 3
+.Os
+.Sh NAME
+.Nm archive_entry_atime ,
+.Nm archive_entry_atime_nsec ,
+.Nm archive_entry_atime_is_set ,
+.Nm archive_entry_set_atime ,
+.Nm archive_entry_unset_atime ,
+.Nm archive_entry_birthtime ,
+.Nm archive_entry_birthtime_nsec ,
+.Nm archive_entry_birthtime_is_set ,
+.Nm archive_entry_set_birthtime ,
+.Nm archive_entry_unset_birthtime ,
+.Nm archive_entry_ctime ,
+.Nm archive_entry_ctime_nsec ,
+.Nm archive_entry_ctime_is_set ,
+.Nm archive_entry_set_ctime ,
+.Nm archive_entry_unset_ctime ,
+.Nm archive_entry_mtime ,
+.Nm archive_entry_mtime_nsec ,
+.Nm archive_entry_mtime_is_set ,
+.Nm archive_entry_set_mtime ,
+.Nm archive_entry_unset_mtime ,
+.Nd functions for manipulating times in archive entry descriptions
+.Sh SYNOPSIS
+.In archive_entry.h
+.Ft time_t
+.Fn archive_entry_atime "struct archive_entry *a"
+.Ft long
+.Fn archive_entry_atime_nsec "struct archive_entry *a"
+.Ft int
+.Fn archive_entry_atime_is_set "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_atime "struct archive_entry *a" "time_t sec" "long nanosec"
+.Ft void
+.Fn archive_entry_unset_atime "struct archive_entry *a"
+.Ft time_t
+.Fn archive_entry_birthtime "struct archive_entry *a"
+.Ft long
+.Fn archive_entry_birthtime_nsec "struct archive_entry *a"
+.Ft int
+.Fn archive_entry_birthtime_is_set "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_birthtime "struct archive_entry *a" "time_t sec" "long nanosec"
+.Ft void
+.Fn archive_entry_unset_birthtime "struct archive_entry *a"
+.Ft time_t
+.Fn archive_entry_ctime "struct archive_entry *a"
+.Ft long
+.Fn archive_entry_ctime_nsec "struct archive_entry *a"
+.Ft int
+.Fn archive_entry_ctime_is_set "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_ctime "struct archive_entry *a" "time_t sec" "long nanosec"
+.Ft void
+.Fn archive_entry_unset_ctime "struct archive_entry *a"
+.Ft time_t
+.Fn archive_entry_mtime "struct archive_entry *a"
+.Ft long
+.Fn archive_entry_mtime_nsec "struct archive_entry *a"
+.Ft int
+.Fn archive_entry_mtime_is_set "struct archive_entry *a"
+.Ft void
+.Fn archive_entry_set_mtime "struct archive_entry *a" "time_t sec" "long nanosec"
+.Ft void
+.Fn archive_entry_unset_mtime "struct archive_entry *a"
+.Sh DESCRIPTION
+These functions create and manipulate the time fields in an
+.Vt archive_entry .
+Supported time fields are atime (access time), birthtime (creation time),
+ctime (last time an inode property was changed) and mtime (modification time).
+.Pp
+.Xr libarchive 3
+provides a high-resolution interface.
+The timestamps are truncated automatically depending on the archive format
+(for archiving) or the filesystem capabilities (for restoring).
+.Pp
+All timestamp fields are optional.
+The
+.Fn XXX_unset
+functions can be used to mark the corresponding field as missing.
+The current state can be queried using
+.Fn XXX_is_set .
+Unset time fields have a second and nanosecond field of 0.
+.Sh SEE ALSO
+.Xr archive 3 ,
+.Xr archive_entry 3
+.Sh HISTORY
+The
+.Nm libarchive
+library first appeared in
+.Fx 5.3 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm libarchive
+library was written by
+.An Tim Kientzle Aq kientzle@acm.org .
+.\" .Sh BUGS
diff --git a/contrib/libarchive/libarchive/archive_hash.h b/contrib/libarchive/libarchive/archive_hash.h
deleted file mode 100644
index 43f398c5f1e5..000000000000
--- a/contrib/libarchive/libarchive/archive_hash.h
+++ /dev/null
@@ -1,309 +0,0 @@
-/*-
- * Copyright (c) 2009 Joerg Sonnenberger
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-/*
- * Hash function support in various Operating Systems:
- *
- * NetBSD:
- * - MD5 and SHA1 in libc: without _ after algorithm name
- * - SHA2 in libc: with _ after algorithm name
- *
- * OpenBSD:
- * - MD5, SHA1 and SHA2 in libc: without _ after algorithm name
- * - OpenBSD 4.4 and earlier have SHA2 in libc with _ after algorithm name
- *
- * DragonFly and FreeBSD (XXX not used yet):
- * - MD5 and SHA1 in libmd: without _ after algorithm name
- * - SHA256: with _ after algorithm name
- *
- * Mac OS X (10.4 and later):
- * - MD5, SHA1 and SHA2 in libSystem: with CC_ prefix and _ after algorithm name
- *
- * OpenSSL:
- * - MD5, SHA1 and SHA2 in libcrypto: with _ after algorithm name
- *
- * Windows:
- * - MD5, SHA1 and SHA2 in archive_windows.c: without algorithm name
- * and with __la_ prefix.
- */
-#if defined(ARCHIVE_HASH_MD5_WIN) ||\
- defined(ARCHIVE_HASH_SHA1_WIN) || defined(ARCHIVE_HASH_SHA256_WIN) ||\
- defined(ARCHIVE_HASH_SHA384_WIN) || defined(ARCHIVE_HASH_SHA512_WIN)
-#include <wincrypt.h>
-typedef struct {
- int valid;
- HCRYPTPROV cryptProv;
- HCRYPTHASH hash;
-} Digest_CTX;
-extern void __la_hash_Init(Digest_CTX *, ALG_ID);
-extern void __la_hash_Final(unsigned char *, size_t, Digest_CTX *);
-extern void __la_hash_Update(Digest_CTX *, const unsigned char *, size_t);
-#endif
-
-#if defined(ARCHIVE_HASH_MD5_LIBC)
-# include <md5.h>
-# define ARCHIVE_HAS_MD5
-typedef MD5_CTX archive_md5_ctx;
-# define archive_md5_init(ctx) MD5Init(ctx)
-# define archive_md5_final(ctx, buf) MD5Final(buf, ctx)
-# define archive_md5_update(ctx, buf, n) MD5Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_MD5_LIBMD)
-# include <md5.h>
-# define ARCHIVE_HAS_MD5
-typedef MD5_CTX archive_md5_ctx;
-# define archive_md5_init(ctx) MD5Init(ctx)
-# define archive_md5_final(ctx, buf) MD5Final(buf, ctx)
-# define archive_md5_update(ctx, buf, n) MD5Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_MD5_LIBSYSTEM)
-# include <CommonCrypto/CommonDigest.h>
-# define ARCHIVE_HAS_MD5
-typedef CC_MD5_CTX archive_md5_ctx;
-# define archive_md5_init(ctx) CC_MD5_Init(ctx)
-# define archive_md5_final(ctx, buf) CC_MD5_Final(buf, ctx)
-# define archive_md5_update(ctx, buf, n) CC_MD5_Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_MD5_OPENSSL)
-# include <openssl/md5.h>
-# define ARCHIVE_HAS_MD5
-typedef MD5_CTX archive_md5_ctx;
-# define archive_md5_init(ctx) MD5_Init(ctx)
-# define archive_md5_final(ctx, buf) MD5_Final(buf, ctx)
-# define archive_md5_update(ctx, buf, n) MD5_Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_MD5_WIN)
-# define ARCHIVE_HAS_MD5
-# define MD5_DIGEST_LENGTH 16
-typedef Digest_CTX archive_md5_ctx;
-# define archive_md5_init(ctx) __la_hash_Init(ctx, CALG_MD5)
-# define archive_md5_final(ctx, buf) __la_hash_Final(buf, MD5_DIGEST_LENGTH, ctx)
-# define archive_md5_update(ctx, buf, n) __la_hash_Update(ctx, buf, n)
-#endif
-
-#if defined(ARCHIVE_HASH_RMD160_LIBC)
-# include <rmd160.h>
-# define ARCHIVE_HAS_RMD160
-typedef RMD160_CTX archive_rmd160_ctx;
-# define archive_rmd160_init(ctx) RMD160Init(ctx)
-# define archive_rmd160_final(ctx, buf) RMD160Final(buf, ctx)
-# define archive_rmd160_update(ctx, buf, n) RMD160Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_RMD160_OPENSSL)
-# include <openssl/ripemd.h>
-# define ARCHIVE_HAS_RMD160
-typedef RIPEMD160_CTX archive_rmd160_ctx;
-# define archive_rmd160_init(ctx) RIPEMD160_Init(ctx)
-# define archive_rmd160_final(ctx, buf) RIPEMD160_Final(buf, ctx)
-# define archive_rmd160_update(ctx, buf, n) RIPEMD160_Update(ctx, buf, n)
-#endif
-
-#if defined(ARCHIVE_HASH_SHA1_LIBC)
-# include <sha1.h>
-# define ARCHIVE_HAS_SHA1
-typedef SHA1_CTX archive_sha1_ctx;
-# define archive_sha1_init(ctx) SHA1Init(ctx)
-# define archive_sha1_final(ctx, buf) SHA1Final(buf, ctx)
-# define archive_sha1_update(ctx, buf, n) SHA1Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA1_LIBMD)
-# include <sha.h>
-# define ARCHIVE_HAS_SHA1
-typedef SHA1_CTX archive_sha1_ctx;
-# define archive_sha1_init(ctx) SHA1_Init(ctx)
-# define archive_sha1_final(ctx, buf) SHA1_Final(buf, ctx)
-# define archive_sha1_update(ctx, buf, n) SHA1_Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA1_LIBSYSTEM)
-# include <CommonCrypto/CommonDigest.h>
-# define ARCHIVE_HAS_SHA1
-typedef CC_SHA1_CTX archive_sha1_ctx;
-# define archive_sha1_init(ctx) CC_SHA1_Init(ctx)
-# define archive_sha1_final(ctx, buf) CC_SHA1_Final(buf, ctx)
-# define archive_sha1_update(ctx, buf, n) CC_SHA1_Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA1_OPENSSL)
-# include <openssl/sha.h>
-# define ARCHIVE_HAS_SHA1
-typedef SHA_CTX archive_sha1_ctx;
-# define archive_sha1_init(ctx) SHA1_Init(ctx)
-# define archive_sha1_final(ctx, buf) SHA1_Final(buf, ctx)
-# define archive_sha1_update(ctx, buf, n) SHA1_Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA1_WIN)
-# define ARCHIVE_HAS_SHA1
-# define SHA1_DIGEST_LENGTH 20
-typedef Digest_CTX archive_sha1_ctx;
-# define archive_sha1_init(ctx) __la_hash_Init(ctx, CALG_SHA1)
-# define archive_sha1_final(ctx, buf) __la_hash_Final(buf, SHA1_DIGEST_LENGTH, ctx)
-# define archive_sha1_update(ctx, buf, n) __la_hash_Update(ctx, buf, n)
-#endif
-
-#if defined(ARCHIVE_HASH_SHA256_LIBC)
-# include <sha2.h>
-# define ARCHIVE_HAS_SHA256
-typedef SHA256_CTX archive_sha256_ctx;
-# define archive_sha256_init(ctx) SHA256_Init(ctx)
-# define archive_sha256_final(ctx, buf) SHA256_Final(buf, ctx)
-# define archive_sha256_update(ctx, buf, n) SHA256_Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA256_LIBC2)
-# include <sha2.h>
-# define ARCHIVE_HAS_SHA256
-typedef SHA256_CTX archive_sha256_ctx;
-# define archive_sha256_init(ctx) SHA256Init(ctx)
-# define archive_sha256_final(ctx, buf) SHA256Final(buf, ctx)
-# define archive_sha256_update(ctx, buf, n) SHA256Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA256_LIBC3)
-# include <sha2.h>
-# define ARCHIVE_HAS_SHA256
-typedef SHA2_CTX archive_sha256_ctx;
-# define archive_sha256_init(ctx) SHA256Init(ctx)
-# define archive_sha256_final(ctx, buf) SHA256Final(buf, ctx)
-# define archive_sha256_update(ctx, buf, n) SHA256Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA256_LIBMD)
-# include <sha256.h>
-# define ARCHIVE_HAS_SHA256
-typedef SHA256_CTX archive_sha256_ctx;
-# define archive_sha256_init(ctx) SHA256_Init(ctx)
-# define archive_sha256_final(ctx, buf) SHA256_Final(buf, ctx)
-# define archive_sha256_update(ctx, buf, n) SHA256_Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA256_LIBSYSTEM)
-# include <CommonCrypto/CommonDigest.h>
-# define ARCHIVE_HAS_SHA256
-typedef CC_SHA256_CTX archive_shs256_ctx;
-# define archive_shs256_init(ctx) CC_SHA256_Init(ctx)
-# define archive_shs256_final(ctx, buf) CC_SHA256_Final(buf, ctx)
-# define archive_shs256_update(ctx, buf, n) CC_SHA256_Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA256_OPENSSL)
-# include <openssl/sha.h>
-# define ARCHIVE_HAS_SHA256
-typedef SHA256_CTX archive_sha256_ctx;
-# define archive_sha256_init(ctx) SHA256_Init(ctx)
-# define archive_sha256_final(ctx, buf) SHA256_Final(buf, ctx)
-# define archive_sha256_update(ctx, buf, n) SHA256_Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA256_WIN)
-# define ARCHIVE_HAS_SHA256
-# define SHA256_DIGEST_LENGTH 32
-typedef Digest_CTX archive_sha256_ctx;
-# define archive_sha256_init(ctx) __la_hash_Init(ctx, CALG_SHA_256)
-# define archive_sha256_final(ctx, buf) __la_hash_Final(buf, SHA256_DIGEST_LENGTH, ctx)
-# define archive_sha256_update(ctx, buf, n) __la_hash_Update(ctx, buf, n)
-#endif
-
-#if defined(ARCHIVE_HASH_SHA384_LIBC)
-# include <sha2.h>
-# define ARCHIVE_HAS_SHA384
-typedef SHA384_CTX archive_sha384_ctx;
-# define archive_sha384_init(ctx) SHA384_Init(ctx)
-# define archive_sha384_final(ctx, buf) SHA384_Final(buf, ctx)
-# define archive_sha384_update(ctx, buf, n) SHA384_Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA384_LIBC2)
-# include <sha2.h>
-# define ARCHIVE_HAS_SHA384
-typedef SHA384_CTX archive_sha384_ctx;
-# define archive_sha384_init(ctx) SHA384Init(ctx)
-# define archive_sha384_final(ctx, buf) SHA384Final(buf, ctx)
-# define archive_sha384_update(ctx, buf, n) SHA384Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA384_LIBC3)
-# include <sha2.h>
-# define ARCHIVE_HAS_SHA384
-typedef SHA2_CTX archive_sha384_ctx;
-# define archive_sha384_init(ctx) SHA384Init(ctx)
-# define archive_sha384_final(ctx, buf) SHA384Final(buf, ctx)
-# define archive_sha384_update(ctx, buf, n) SHA384Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA384_LIBSYSTEM)
-# include <CommonCrypto/CommonDigest.h>
-# define ARCHIVE_HAS_SHA384
-typedef CC_SHA512_CTX archive_shs384_ctx;
-# define archive_shs384_init(ctx) CC_SHA384_Init(ctx)
-# define archive_shs384_final(ctx, buf) CC_SHA384_Final(buf, ctx)
-# define archive_shs384_update(ctx, buf, n) CC_SHA384_Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA384_OPENSSL)
-# include <openssl/sha.h>
-# define ARCHIVE_HAS_SHA384
-typedef SHA512_CTX archive_sha384_ctx;
-# define archive_sha384_init(ctx) SHA384_Init(ctx)
-# define archive_sha384_final(ctx, buf) SHA384_Final(buf, ctx)
-# define archive_sha384_update(ctx, buf, n) SHA384_Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA384_WIN)
-# define ARCHIVE_HAS_SHA384
-# define SHA384_DIGEST_LENGTH 48
-typedef Digest_CTX archive_sha384_ctx;
-# define archive_sha384_init(ctx) __la_hash_Init(ctx, CALG_SHA_384)
-# define archive_sha384_final(ctx, buf) __la_hash_Final(buf, SHA384_DIGEST_LENGTH, ctx)
-# define archive_sha384_update(ctx, buf, n) __la_hash_Update(ctx, buf, n)
-#endif
-
-#if defined(ARCHIVE_HASH_SHA512_LIBC)
-# include <sha2.h>
-# define ARCHIVE_HAS_SHA512
-typedef SHA512_CTX archive_sha512_ctx;
-# define archive_sha512_init(ctx) SHA512_Init(ctx)
-# define archive_sha512_final(ctx, buf) SHA512_Final(buf, ctx)
-# define archive_sha512_update(ctx, buf, n) SHA512_Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA512_LIBC2)
-# include <sha2.h>
-# define ARCHIVE_HAS_SHA512
-typedef SHA512_CTX archive_sha512_ctx;
-# define archive_sha512_init(ctx) SHA512Init(ctx)
-# define archive_sha512_final(ctx, buf) SHA512Final(buf, ctx)
-# define archive_sha512_update(ctx, buf, n) SHA512Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA512_LIBC3)
-# include <sha2.h>
-# define ARCHIVE_HAS_SHA512
-typedef SHA2_CTX archive_sha512_ctx;
-# define archive_sha512_init(ctx) SHA512Init(ctx)
-# define archive_sha512_final(ctx, buf) SHA512Final(buf, ctx)
-# define archive_sha512_update(ctx, buf, n) SHA512Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA512_LIBMD)
-# include <sha512.h>
-# define ARCHIVE_HAS_SHA512
-typedef SHA512_CTX archive_sha512_ctx;
-# define archive_sha512_init(ctx) SHA512_Init(ctx)
-# define archive_sha512_final(ctx, buf) SHA512_Final(buf, ctx)
-# define archive_sha512_update(ctx, buf, n) SHA512_Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA512_LIBSYSTEM)
-# include <CommonCrypto/CommonDigest.h>
-# define ARCHIVE_HAS_SHA512
-typedef CC_SHA512_CTX archive_shs512_ctx;
-# define archive_shs512_init(ctx) CC_SHA512_Init(ctx)
-# define archive_shs512_final(ctx, buf) CC_SHA512_Final(buf, ctx)
-# define archive_shs512_update(ctx, buf, n) CC_SHA512_Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA512_OPENSSL)
-# include <openssl/sha.h>
-# define ARCHIVE_HAS_SHA512
-typedef SHA512_CTX archive_sha512_ctx;
-# define archive_sha512_init(ctx) SHA512_Init(ctx)
-# define archive_sha512_final(ctx, buf) SHA512_Final(buf, ctx)
-# define archive_sha512_update(ctx, buf, n) SHA512_Update(ctx, buf, n)
-#elif defined(ARCHIVE_HASH_SHA512_WIN)
-# define ARCHIVE_HAS_SHA512
-# define SHA512_DIGEST_LENGTH 64
-typedef Digest_CTX archive_sha512_ctx;
-# define archive_sha512_init(ctx) __la_hash_Init(ctx, CALG_SHA_512)
-# define archive_sha512_final(ctx, buf) __la_hash_Final(buf, SHA512_DIGEST_LENGTH, ctx)
-# define archive_sha512_update(ctx, buf, n) __la_hash_Update(ctx, buf, n)
-#endif
diff --git a/contrib/libarchive/libarchive/archive_options.c b/contrib/libarchive/libarchive/archive_options.c
new file mode 100644
index 000000000000..08a348fb3034
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_options.c
@@ -0,0 +1,198 @@
+/*-
+ * Copyright (c) 2011 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#include "archive_options_private.h"
+
+static const char *
+parse_option(const char **str,
+ const char **mod, const char **opt, const char **val);
+
+int
+_archive_set_option(struct archive *a,
+ const char *m, const char *o, const char *v,
+ int magic, const char *fn, option_handler use_option)
+{
+ const char *mp, *op, *vp;
+ int r;
+
+ archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn);
+
+ mp = m != NULL && m[0] == '\0' ? NULL : m;
+ op = o != NULL && o[0] == '\0' ? NULL : o;
+ vp = v != NULL && v[0] == '\0' ? NULL : v;
+
+ if (op == NULL && vp == NULL)
+ return (ARCHIVE_OK);
+ if (op == NULL) {
+ archive_set_error(a, ARCHIVE_ERRNO_MISC, "Empty option");
+ return (ARCHIVE_FAILED);
+ }
+
+ r = use_option(a, mp, op, vp);
+ if (r == ARCHIVE_WARN - 1) {
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Unknown module name: `%s'", mp);
+ return (ARCHIVE_FAILED);
+ }
+ if (r == ARCHIVE_WARN) {
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Undefined option: `%s%s%s%s%s%s'",
+ vp?"":"!", mp?mp:"", mp?":":"", op, vp?"=":"", vp?vp:"");
+ return (ARCHIVE_FAILED);
+ }
+ return (r);
+}
+
+int
+_archive_set_either_option(struct archive *a, const char *m, const char *o, const char *v,
+ option_handler use_format_option, option_handler use_filter_option)
+{
+ int r1, r2;
+
+ if (o == NULL && v == NULL)
+ return (ARCHIVE_OK);
+ if (o == NULL)
+ return (ARCHIVE_FAILED);
+
+ r1 = use_format_option(a, m, o, v);
+ if (r1 == ARCHIVE_FATAL)
+ return (ARCHIVE_FATAL);
+
+ r2 = use_filter_option(a, m, o, v);
+ if (r2 == ARCHIVE_FATAL)
+ return (ARCHIVE_FATAL);
+
+ return r1 > r2 ? r1 : r2;
+}
+
+int
+_archive_set_options(struct archive *a, const char *options,
+ int magic, const char *fn, option_handler use_option)
+{
+ int allok = 1, anyok = 0, r;
+ char *data;
+ const char *s, *mod, *opt, *val;
+
+ archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn);
+
+ if (options == NULL || options[0] == '\0')
+ return ARCHIVE_OK;
+
+ data = (char *)malloc(strlen(options) + 1);
+ strcpy(data, options);
+ s = (const char *)data;
+
+ do {
+ mod = opt = val = NULL;
+
+ parse_option(&s, &mod, &opt, &val);
+
+ r = use_option(a, mod, opt, val);
+ if (r == ARCHIVE_FATAL) {
+ free(data);
+ return (ARCHIVE_FATAL);
+ }
+ if (r == ARCHIVE_FAILED && mod != NULL) {
+ free(data);
+ return (ARCHIVE_FAILED);
+ }
+ if (r == ARCHIVE_WARN - 1) {
+ /* The module name is wrong. */
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Unknown module name: `%s'", mod);
+ free(data);
+ return (ARCHIVE_FAILED);
+ }
+ if (r == ARCHIVE_WARN) {
+ /* The option name is wrong. No-one used this. */
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Undefined option: `%s%s%s'",
+ mod?mod:"", mod?":":"", opt);
+ free(data);
+ return (ARCHIVE_FAILED);
+ }
+ if (r == ARCHIVE_OK)
+ anyok = 1;
+ else
+ allok = 0;
+ } while (s != NULL);
+
+ free(data);
+ return allok ? ARCHIVE_OK : anyok ? ARCHIVE_WARN : ARCHIVE_FAILED;
+}
+
+static const char *
+parse_option(const char **s, const char **m, const char **o, const char **v)
+{
+ const char *end, *mod, *opt, *val;
+ char *p;
+
+ end = NULL;
+ mod = NULL;
+ opt = *s;
+ val = "1";
+
+ p = strchr(opt, ',');
+
+ if (p != NULL) {
+ *p = '\0';
+ end = ((const char *)p) + 1;
+ }
+
+ if (0 == strlen(opt)) {
+ *s = end;
+ *m = NULL;
+ *o = NULL;
+ *v = NULL;
+ return end;
+ }
+
+ p = strchr(opt, ':');
+ if (p != NULL) {
+ *p = '\0';
+ mod = opt;
+ opt = ++p;
+ }
+
+ p = strchr(opt, '=');
+ if (p != NULL) {
+ *p = '\0';
+ val = ++p;
+ } else if (opt[0] == '!') {
+ ++opt;
+ val = NULL;
+ }
+
+ *s = end;
+ *m = mod;
+ *o = opt;
+ *v = val;
+
+ return end;
+}
+
diff --git a/usr.bin/cpio/config_freebsd.h b/contrib/libarchive/libarchive/archive_options_private.h
index bf24b9ec9f27..6ef0165aff68 100644
--- a/usr.bin/cpio/config_freebsd.h
+++ b/contrib/libarchive/libarchive/archive_options_private.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2011 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -21,37 +21,27 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
*/
-/* A hand-tooled configuration for FreeBSD. */
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#include "archive_private.h"
+
+typedef int (*option_handler)(struct archive *a,
+ const char *mod, const char *opt, const char *val);
+
+int
+_archive_set_option(struct archive *a,
+ const char *mod, const char *opt, const char *val,
+ int magic, const char *fn, option_handler use_option);
-#include <sys/param.h> /* __FreeBSD_version */
+int
+_archive_set_options(struct archive *a, const char *options,
+ int magic, const char *fn, option_handler use_option);
-#define HAVE_DIRENT_H 1
-#define HAVE_ERRNO_H 1
-#define HAVE_FCNTL_H 1
-#define HAVE_FUTIMES 1
-#define HAVE_GRP_H 1
-#define HAVE_LIBARCHIVE 1
-#define HAVE_LINK 1
-#define HAVE_LSTAT 1
-#define HAVE_LUTIMES 1
-#define HAVE_PWD_H 1
-#define HAVE_READLINK 1
-#define HAVE_STDARG_H 1
-#define HAVE_STDLIB_H 1
-#define HAVE_STRING_H 1
-#define HAVE_SYMLINK 1
-#define HAVE_SYS_CDEFS_H 1
-#define HAVE_SYS_STAT_H 1
-#define HAVE_SYS_TIME_H 1
-#define HAVE_TIME_H 1
-#define HAVE_UINTMAX_T 1
-#define HAVE_UNISTD_H 1
-#define HAVE_UNSIGNED_LONG_LONG 1
-#define HAVE_UTIME_H 1
-#define HAVE_UTIMES 1
-#define HAVE_WCSCMP 1
+int
+_archive_set_either_option(struct archive *a,
+ const char *m, const char *o, const char *v,
+ option_handler use_format_option, option_handler use_filter_option);
diff --git a/contrib/libarchive/libarchive/archive_ppmd7.c b/contrib/libarchive/libarchive/archive_ppmd7.c
new file mode 100644
index 000000000000..b2e8c3a34922
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_ppmd7.c
@@ -0,0 +1,1164 @@
+/* Ppmd7.c -- PPMdH codec
+2010-03-12 : Igor Pavlov : Public domain
+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
+
+#include "archive_platform.h"
+
+#include <memory.h>
+
+#include "archive_ppmd7_private.h"
+
+#ifdef PPMD_32BIT
+ #define Ppmd7_GetPtr(p, ptr) (ptr)
+ #define Ppmd7_GetContext(p, ptr) (ptr)
+ #define Ppmd7_GetStats(p, ctx) ((ctx)->Stats)
+#else
+ #define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
+ #define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs)))
+ #define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats)))
+#endif
+
+#define Ppmd7_GetBinSumm(p) \
+ &p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \
+ p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \
+ (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \
+ 2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \
+ ((p->RunLength >> 26) & 0x20)]
+
+#define kTopValue (1 << 24)
+#define MAX_FREQ 124
+#define UNIT_SIZE 12
+
+#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
+#define U2I(nu) (p->Units2Indx[(nu) - 1])
+#define I2U(indx) (p->Indx2Units[indx])
+
+#ifdef PPMD_32BIT
+ #define REF(ptr) (ptr)
+#else
+ #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
+#endif
+
+#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))
+
+#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))
+#define STATS(ctx) Ppmd7_GetStats(p, ctx)
+#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx)
+#define SUFFIX(ctx) CTX((ctx)->Suffix)
+
+static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
+static const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
+
+typedef CPpmd7_Context * CTX_PTR;
+
+struct CPpmd7_Node_;
+
+typedef
+ #ifdef PPMD_32BIT
+ struct CPpmd7_Node_ *
+ #else
+ UInt32
+ #endif
+ CPpmd7_Node_Ref;
+
+typedef struct CPpmd7_Node_
+{
+ UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */
+ UInt16 NU;
+ CPpmd7_Node_Ref Next; /* must be at offset >= 4 */
+ CPpmd7_Node_Ref Prev;
+} CPpmd7_Node;
+
+#ifdef PPMD_32BIT
+ #define NODE(ptr) (ptr)
+#else
+ #define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs)))
+#endif
+
+static void Ppmd7_Update1(CPpmd7 *p);
+static void Ppmd7_Update1_0(CPpmd7 *p);
+static void Ppmd7_Update2(CPpmd7 *p);
+static void Ppmd7_UpdateBin(CPpmd7 *p);
+static CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked,
+ UInt32 *scale);
+
+/* ----------- Base ----------- */
+
+static void Ppmd7_Construct(CPpmd7 *p)
+{
+ unsigned i, k, m;
+
+ p->Base = 0;
+
+ for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
+ {
+ unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
+ do { p->Units2Indx[k++] = (Byte)i; } while(--step);
+ p->Indx2Units[i] = (Byte)k;
+ }
+
+ p->NS2BSIndx[0] = (0 << 1);
+ p->NS2BSIndx[1] = (1 << 1);
+ memset(p->NS2BSIndx + 2, (2 << 1), 9);
+ memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);
+
+ for (i = 0; i < 3; i++)
+ p->NS2Indx[i] = (Byte)i;
+ for (m = i, k = 1; i < 256; i++)
+ {
+ p->NS2Indx[i] = (Byte)m;
+ if (--k == 0)
+ k = (++m) - 2;
+ }
+
+ memset(p->HB2Flag, 0, 0x40);
+ memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
+}
+
+static void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc)
+{
+ alloc->Free(alloc, p->Base);
+ p->Size = 0;
+ p->Base = 0;
+}
+
+static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)
+{
+ if (p->Base == 0 || p->Size != size)
+ {
+ Ppmd7_Free(p, alloc);
+ p->AlignOffset =
+ #ifdef PPMD_32BIT
+ (4 - size) & 3;
+ #else
+ 4 - (size & 3);
+ #endif
+ if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size
+ #ifndef PPMD_32BIT
+ + UNIT_SIZE
+ #endif
+ )) == 0)
+ return False;
+ p->Size = size;
+ }
+ return True;
+}
+
+static void InsertNode(CPpmd7 *p, void *node, unsigned indx)
+{
+ *((CPpmd_Void_Ref *)node) = p->FreeList[indx];
+ p->FreeList[indx] = REF(node);
+}
+
+static void *RemoveNode(CPpmd7 *p, unsigned indx)
+{
+ CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]);
+ p->FreeList[indx] = *node;
+ return node;
+}
+
+static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
+{
+ unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
+ ptr = (Byte *)ptr + U2B(I2U(newIndx));
+ if (I2U(i = U2I(nu)) != nu)
+ {
+ unsigned k = I2U(--i);
+ InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);
+ }
+ InsertNode(p, ptr, i);
+}
+
+static void GlueFreeBlocks(CPpmd7 *p)
+{
+ #ifdef PPMD_32BIT
+ CPpmd7_Node headItem;
+ CPpmd7_Node_Ref head = &headItem;
+ #else
+ CPpmd7_Node_Ref head = p->AlignOffset + p->Size;
+ #endif
+
+ CPpmd7_Node_Ref n = head;
+ unsigned i;
+
+ p->GlueCount = 255;
+
+ /* create doubly-linked list of free blocks */
+ for (i = 0; i < PPMD_NUM_INDEXES; i++)
+ {
+ UInt16 nu = I2U(i);
+ CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i];
+ p->FreeList[i] = 0;
+ while (next != 0)
+ {
+ CPpmd7_Node *node = NODE(next);
+ node->Next = n;
+ n = NODE(n)->Prev = next;
+ next = *(const CPpmd7_Node_Ref *)node;
+ node->Stamp = 0;
+ node->NU = (UInt16)nu;
+ }
+ }
+ NODE(head)->Stamp = 1;
+ NODE(head)->Next = n;
+ NODE(n)->Prev = head;
+ if (p->LoUnit != p->HiUnit)
+ ((CPpmd7_Node *)p->LoUnit)->Stamp = 1;
+
+ /* Glue free blocks */
+ while (n != head)
+ {
+ CPpmd7_Node *node = NODE(n);
+ UInt32 nu = (UInt32)node->NU;
+ for (;;)
+ {
+ CPpmd7_Node *node2 = NODE(n) + nu;
+ nu += node2->NU;
+ if (node2->Stamp != 0 || nu >= 0x10000)
+ break;
+ NODE(node2->Prev)->Next = node2->Next;
+ NODE(node2->Next)->Prev = node2->Prev;
+ node->NU = (UInt16)nu;
+ }
+ n = node->Next;
+ }
+
+ /* Fill lists of free blocks */
+ for (n = NODE(head)->Next; n != head;)
+ {
+ CPpmd7_Node *node = NODE(n);
+ unsigned nu;
+ CPpmd7_Node_Ref next = node->Next;
+ for (nu = node->NU; nu > 128; nu -= 128, node += 128)
+ InsertNode(p, node, PPMD_NUM_INDEXES - 1);
+ if (I2U(i = U2I(nu)) != nu)
+ {
+ unsigned k = I2U(--i);
+ InsertNode(p, node + k, nu - k - 1);
+ }
+ InsertNode(p, node, i);
+ n = next;
+ }
+}
+
+static void *AllocUnitsRare(CPpmd7 *p, unsigned indx)
+{
+ unsigned i;
+ void *retVal;
+ if (p->GlueCount == 0)
+ {
+ GlueFreeBlocks(p);
+ if (p->FreeList[indx] != 0)
+ return RemoveNode(p, indx);
+ }
+ i = indx;
+ do
+ {
+ if (++i == PPMD_NUM_INDEXES)
+ {
+ UInt32 numBytes = U2B(I2U(indx));
+ p->GlueCount--;
+ return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);
+ }
+ }
+ while (p->FreeList[i] == 0);
+ retVal = RemoveNode(p, i);
+ SplitBlock(p, retVal, i, indx);
+ return retVal;
+}
+
+static void *AllocUnits(CPpmd7 *p, unsigned indx)
+{
+ UInt32 numBytes;
+ if (p->FreeList[indx] != 0)
+ return RemoveNode(p, indx);
+ numBytes = U2B(I2U(indx));
+ if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))
+ {
+ void *retVal = p->LoUnit;
+ p->LoUnit += numBytes;
+ return retVal;
+ }
+ return AllocUnitsRare(p, indx);
+}
+
+#define MyMem12Cpy(dest, src, num) \
+ { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
+ do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); }
+
+static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
+{
+ unsigned i0 = U2I(oldNU);
+ unsigned i1 = U2I(newNU);
+ if (i0 == i1)
+ return oldPtr;
+ if (p->FreeList[i1] != 0)
+ {
+ void *ptr = RemoveNode(p, i1);
+ MyMem12Cpy(ptr, oldPtr, newNU);
+ InsertNode(p, oldPtr, i0);
+ return ptr;
+ }
+ SplitBlock(p, oldPtr, i0, i1);
+ return oldPtr;
+}
+
+#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
+
+static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
+{
+ (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
+ (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
+}
+
+static void RestartModel(CPpmd7 *p)
+{
+ unsigned i, k, m;
+
+ memset(p->FreeList, 0, sizeof(p->FreeList));
+ p->Text = p->Base + p->AlignOffset;
+ p->HiUnit = p->Text + p->Size;
+ p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;
+ p->GlueCount = 0;
+
+ p->OrderFall = p->MaxOrder;
+ p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
+ p->PrevSuccess = 0;
+
+ p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
+ p->MinContext->Suffix = 0;
+ p->MinContext->NumStats = 256;
+ p->MinContext->SummFreq = 256 + 1;
+ p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
+ p->LoUnit += U2B(256 / 2);
+ p->MinContext->Stats = REF(p->FoundState);
+ for (i = 0; i < 256; i++)
+ {
+ CPpmd_State *s = &p->FoundState[i];
+ s->Symbol = (Byte)i;
+ s->Freq = 1;
+ SetSuccessor(s, 0);
+ }
+
+ for (i = 0; i < 128; i++)
+ for (k = 0; k < 8; k++)
+ {
+ UInt16 *dest = p->BinSumm[i] + k;
+ UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2));
+ for (m = 0; m < 64; m += 8)
+ dest[m] = val;
+ }
+
+ for (i = 0; i < 25; i++)
+ for (k = 0; k < 16; k++)
+ {
+ CPpmd_See *s = &p->See[i][k];
+ s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4));
+ s->Count = 4;
+ }
+}
+
+static void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)
+{
+ p->MaxOrder = maxOrder;
+ RestartModel(p);
+ p->DummySee.Shift = PPMD_PERIOD_BITS;
+ p->DummySee.Summ = 0; /* unused */
+ p->DummySee.Count = 64; /* unused */
+}
+
+static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)
+{
+ CPpmd_State upState;
+ CTX_PTR c = p->MinContext;
+ CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
+ CPpmd_State *ps[PPMD7_MAX_ORDER];
+ unsigned numPs = 0;
+
+ if (!skip)
+ ps[numPs++] = p->FoundState;
+
+ while (c->Suffix)
+ {
+ CPpmd_Void_Ref successor;
+ CPpmd_State *s;
+ c = SUFFIX(c);
+ if (c->NumStats != 1)
+ {
+ for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);
+ }
+ else
+ s = ONE_STATE(c);
+ successor = SUCCESSOR(s);
+ if (successor != upBranch)
+ {
+ c = CTX(successor);
+ if (numPs == 0)
+ return c;
+ break;
+ }
+ ps[numPs++] = s;
+ }
+
+ upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch);
+ SetSuccessor(&upState, upBranch + 1);
+
+ if (c->NumStats == 1)
+ upState.Freq = ONE_STATE(c)->Freq;
+ else
+ {
+ UInt32 cf, s0;
+ CPpmd_State *s;
+ for (s = STATS(c); s->Symbol != upState.Symbol; s++);
+ cf = s->Freq - 1;
+ s0 = c->SummFreq - c->NumStats - cf;
+ upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0))));
+ }
+
+ do
+ {
+ /* Create Child */
+ CTX_PTR c1; /* = AllocContext(p); */
+ if (p->HiUnit != p->LoUnit)
+ c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);
+ else if (p->FreeList[0] != 0)
+ c1 = (CTX_PTR)RemoveNode(p, 0);
+ else
+ {
+ c1 = (CTX_PTR)AllocUnitsRare(p, 0);
+ if (!c1)
+ return NULL;
+ }
+ c1->NumStats = 1;
+ *ONE_STATE(c1) = upState;
+ c1->Suffix = REF(c);
+ SetSuccessor(ps[--numPs], REF(c1));
+ c = c1;
+ }
+ while (numPs != 0);
+
+ return c;
+}
+
+static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)
+{
+ CPpmd_State tmp = *t1;
+ *t1 = *t2;
+ *t2 = tmp;
+}
+
+static void UpdateModel(CPpmd7 *p)
+{
+ CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);
+ CTX_PTR c;
+ unsigned s0, ns;
+
+ if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)
+ {
+ c = SUFFIX(p->MinContext);
+
+ if (c->NumStats == 1)
+ {
+ CPpmd_State *s = ONE_STATE(c);
+ if (s->Freq < 32)
+ s->Freq++;
+ }
+ else
+ {
+ CPpmd_State *s = STATS(c);
+ if (s->Symbol != p->FoundState->Symbol)
+ {
+ do { s++; } while (s->Symbol != p->FoundState->Symbol);
+ if (s[0].Freq >= s[-1].Freq)
+ {
+ SwapStates(&s[0], &s[-1]);
+ s--;
+ }
+ }
+ if (s->Freq < MAX_FREQ - 9)
+ {
+ s->Freq += 2;
+ c->SummFreq += 2;
+ }
+ }
+ }
+
+ if (p->OrderFall == 0)
+ {
+ p->MinContext = p->MaxContext = CreateSuccessors(p, True);
+ if (p->MinContext == 0)
+ {
+ RestartModel(p);
+ return;
+ }
+ SetSuccessor(p->FoundState, REF(p->MinContext));
+ return;
+ }
+
+ *p->Text++ = p->FoundState->Symbol;
+ successor = REF(p->Text);
+ if (p->Text >= p->UnitsStart)
+ {
+ RestartModel(p);
+ return;
+ }
+
+ if (fSuccessor)
+ {
+ if (fSuccessor <= successor)
+ {
+ CTX_PTR cs = CreateSuccessors(p, False);
+ if (cs == NULL)
+ {
+ RestartModel(p);
+ return;
+ }
+ fSuccessor = REF(cs);
+ }
+ if (--p->OrderFall == 0)
+ {
+ successor = fSuccessor;
+ p->Text -= (p->MaxContext != p->MinContext);
+ }
+ }
+ else
+ {
+ SetSuccessor(p->FoundState, successor);
+ fSuccessor = REF(p->MinContext);
+ }
+
+ s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1);
+
+ for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c))
+ {
+ unsigned ns1;
+ UInt32 cf, sf;
+ if ((ns1 = c->NumStats) != 1)
+ {
+ if ((ns1 & 1) == 0)
+ {
+ /* Expand for one UNIT */
+ unsigned oldNU = ns1 >> 1;
+ unsigned i = U2I(oldNU);
+ if (i != U2I(oldNU + 1))
+ {
+ void *ptr = AllocUnits(p, i + 1);
+ void *oldPtr;
+ if (!ptr)
+ {
+ RestartModel(p);
+ return;
+ }
+ oldPtr = STATS(c);
+ MyMem12Cpy(ptr, oldPtr, oldNU);
+ InsertNode(p, oldPtr, i);
+ c->Stats = STATS_REF(ptr);
+ }
+ }
+ c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1)));
+ }
+ else
+ {
+ CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0);
+ if (!s)
+ {
+ RestartModel(p);
+ return;
+ }
+ *s = *ONE_STATE(c);
+ c->Stats = REF(s);
+ if (s->Freq < MAX_FREQ / 4 - 1)
+ s->Freq <<= 1;
+ else
+ s->Freq = MAX_FREQ - 4;
+ c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3));
+ }
+ cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6);
+ sf = (UInt32)s0 + c->SummFreq;
+ if (cf < 6 * sf)
+ {
+ cf = 1 + (cf > sf) + (cf >= 4 * sf);
+ c->SummFreq += 3;
+ }
+ else
+ {
+ cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
+ c->SummFreq = (UInt16)(c->SummFreq + cf);
+ }
+ {
+ CPpmd_State *s = STATS(c) + ns1;
+ SetSuccessor(s, successor);
+ s->Symbol = p->FoundState->Symbol;
+ s->Freq = (Byte)cf;
+ c->NumStats = (UInt16)(ns1 + 1);
+ }
+ }
+ p->MaxContext = p->MinContext = CTX(fSuccessor);
+}
+
+static void Rescale(CPpmd7 *p)
+{
+ unsigned i, adder, sumFreq, escFreq;
+ CPpmd_State *stats = STATS(p->MinContext);
+ CPpmd_State *s = p->FoundState;
+ {
+ CPpmd_State tmp = *s;
+ for (; s != stats; s--)
+ s[0] = s[-1];
+ *s = tmp;
+ }
+ escFreq = p->MinContext->SummFreq - s->Freq;
+ s->Freq += 4;
+ adder = (p->OrderFall != 0);
+ s->Freq = (Byte)((s->Freq + adder) >> 1);
+ sumFreq = s->Freq;
+
+ i = p->MinContext->NumStats - 1;
+ do
+ {
+ escFreq -= (++s)->Freq;
+ s->Freq = (Byte)((s->Freq + adder) >> 1);
+ sumFreq += s->Freq;
+ if (s[0].Freq > s[-1].Freq)
+ {
+ CPpmd_State *s1 = s;
+ CPpmd_State tmp = *s1;
+ do
+ s1[0] = s1[-1];
+ while (--s1 != stats && tmp.Freq > s1[-1].Freq);
+ *s1 = tmp;
+ }
+ }
+ while (--i);
+
+ if (s->Freq == 0)
+ {
+ unsigned numStats = p->MinContext->NumStats;
+ unsigned n0, n1;
+ do { i++; } while ((--s)->Freq == 0);
+ escFreq += i;
+ p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i);
+ if (p->MinContext->NumStats == 1)
+ {
+ CPpmd_State tmp = *stats;
+ do
+ {
+ tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1));
+ escFreq >>= 1;
+ }
+ while (escFreq > 1);
+ InsertNode(p, stats, U2I(((numStats + 1) >> 1)));
+ *(p->FoundState = ONE_STATE(p->MinContext)) = tmp;
+ return;
+ }
+ n0 = (numStats + 1) >> 1;
+ n1 = (p->MinContext->NumStats + 1) >> 1;
+ if (n0 != n1)
+ p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
+ }
+ p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
+ p->FoundState = STATS(p->MinContext);
+}
+
+static CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
+{
+ CPpmd_See *see;
+ unsigned nonMasked = p->MinContext->NumStats - numMasked;
+ if (p->MinContext->NumStats != 256)
+ {
+ see = p->See[p->NS2Indx[nonMasked - 1]] +
+ (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +
+ 2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +
+ 4 * (numMasked > nonMasked) +
+ p->HiBitsFlag;
+ {
+ unsigned r = (see->Summ >> see->Shift);
+ see->Summ = (UInt16)(see->Summ - r);
+ *escFreq = r + (r == 0);
+ }
+ }
+ else
+ {
+ see = &p->DummySee;
+ *escFreq = 1;
+ }
+ return see;
+}
+
+static void NextContext(CPpmd7 *p)
+{
+ CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
+ if (p->OrderFall == 0 && (Byte *)c > p->Text)
+ p->MinContext = p->MaxContext = c;
+ else
+ UpdateModel(p);
+}
+
+static void Ppmd7_Update1(CPpmd7 *p)
+{
+ CPpmd_State *s = p->FoundState;
+ s->Freq += 4;
+ p->MinContext->SummFreq += 4;
+ if (s[0].Freq > s[-1].Freq)
+ {
+ SwapStates(&s[0], &s[-1]);
+ p->FoundState = --s;
+ if (s->Freq > MAX_FREQ)
+ Rescale(p);
+ }
+ NextContext(p);
+}
+
+static void Ppmd7_Update1_0(CPpmd7 *p)
+{
+ p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq);
+ p->RunLength += p->PrevSuccess;
+ p->MinContext->SummFreq += 4;
+ if ((p->FoundState->Freq += 4) > MAX_FREQ)
+ Rescale(p);
+ NextContext(p);
+}
+
+static void Ppmd7_UpdateBin(CPpmd7 *p)
+{
+ p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0));
+ p->PrevSuccess = 1;
+ p->RunLength++;
+ NextContext(p);
+}
+
+static void Ppmd7_Update2(CPpmd7 *p)
+{
+ p->MinContext->SummFreq += 4;
+ if ((p->FoundState->Freq += 4) > MAX_FREQ)
+ Rescale(p);
+ p->RunLength = p->InitRL;
+ UpdateModel(p);
+}
+
+/* ---------- Decode ---------- */
+
+static Bool Ppmd_RangeDec_Init(CPpmd7z_RangeDec *p)
+{
+ unsigned i;
+ p->Low = p->Bottom = 0;
+ p->Range = 0xFFFFFFFF;
+ for (i = 0; i < 4; i++)
+ p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
+ return (p->Code < 0xFFFFFFFF);
+}
+
+static Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
+{
+ if (p->Stream->Read((void *)p->Stream) != 0)
+ return False;
+ return Ppmd_RangeDec_Init(p);
+}
+
+static Bool PpmdRAR_RangeDec_Init(CPpmd7z_RangeDec *p)
+{
+ if (!Ppmd_RangeDec_Init(p))
+ return False;
+ p->Bottom = 0x8000;
+ return True;
+}
+
+static UInt32 Range_GetThreshold(void *pp, UInt32 total)
+{
+ CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
+ return (p->Code - p->Low) / (p->Range /= total);
+}
+
+static void Range_Normalize(CPpmd7z_RangeDec *p)
+{
+ while (1)
+ {
+ if((p->Low ^ (p->Low + p->Range)) >= kTopValue)
+ {
+ if(p->Range >= p->Bottom)
+ break;
+ else
+ p->Range = -p->Low & (p->Bottom - 1);
+ }
+ p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
+ p->Range <<= 8;
+ p->Low <<= 8;
+ }
+}
+
+static void Range_Decode_7z(void *pp, UInt32 start, UInt32 size)
+{
+ CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
+ p->Code -= start * p->Range;
+ p->Range *= size;
+ Range_Normalize(p);
+}
+
+static void Range_Decode_RAR(void *pp, UInt32 start, UInt32 size)
+{
+ CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
+ p->Low += start * p->Range;
+ p->Range *= size;
+ Range_Normalize(p);
+}
+
+static UInt32 Range_DecodeBit_7z(void *pp, UInt32 size0)
+{
+ CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
+ UInt32 newBound = (p->Range >> 14) * size0;
+ UInt32 symbol;
+ if (p->Code < newBound)
+ {
+ symbol = 0;
+ p->Range = newBound;
+ }
+ else
+ {
+ symbol = 1;
+ p->Code -= newBound;
+ p->Range -= newBound;
+ }
+ Range_Normalize(p);
+ return symbol;
+}
+
+static UInt32 Range_DecodeBit_RAR(void *pp, UInt32 size0)
+{
+ CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
+ UInt32 bit, value = p->p.GetThreshold(p, PPMD_BIN_SCALE);
+ if(value < size0)
+ {
+ bit = 0;
+ p->p.Decode(p, 0, size0);
+ }
+ else
+ {
+ bit = 1;
+ p->p.Decode(p, size0, PPMD_BIN_SCALE - size0);
+ }
+ return bit;
+}
+
+static void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
+{
+ p->p.GetThreshold = Range_GetThreshold;
+ p->p.Decode = Range_Decode_7z;
+ p->p.DecodeBit = Range_DecodeBit_7z;
+}
+
+static void PpmdRAR_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
+{
+ p->p.GetThreshold = Range_GetThreshold;
+ p->p.Decode = Range_Decode_RAR;
+ p->p.DecodeBit = Range_DecodeBit_RAR;
+}
+
+#define MASK(sym) ((signed char *)charMask)[sym]
+
+static int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc)
+{
+ size_t charMask[256 / sizeof(size_t)];
+ if (p->MinContext->NumStats != 1)
+ {
+ CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
+ unsigned i;
+ UInt32 count, hiCnt;
+ if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
+ {
+ Byte symbol;
+ rc->Decode(rc, 0, s->Freq);
+ p->FoundState = s;
+ symbol = s->Symbol;
+ Ppmd7_Update1_0(p);
+ return symbol;
+ }
+ p->PrevSuccess = 0;
+ i = p->MinContext->NumStats - 1;
+ do
+ {
+ if ((hiCnt += (++s)->Freq) > count)
+ {
+ Byte symbol;
+ rc->Decode(rc, hiCnt - s->Freq, s->Freq);
+ p->FoundState = s;
+ symbol = s->Symbol;
+ Ppmd7_Update1(p);
+ return symbol;
+ }
+ }
+ while (--i);
+ if (count >= p->MinContext->SummFreq)
+ return -2;
+ p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
+ rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt);
+ PPMD_SetAllBitsIn256Bytes(charMask);
+ MASK(s->Symbol) = 0;
+ i = p->MinContext->NumStats - 1;
+ do { MASK((--s)->Symbol) = 0; } while (--i);
+ }
+ else
+ {
+ UInt16 *prob = Ppmd7_GetBinSumm(p);
+ if (rc->DecodeBit(rc, *prob) == 0)
+ {
+ Byte symbol;
+ *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
+ symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
+ Ppmd7_UpdateBin(p);
+ return symbol;
+ }
+ *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
+ p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
+ PPMD_SetAllBitsIn256Bytes(charMask);
+ MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;
+ p->PrevSuccess = 0;
+ }
+ for (;;)
+ {
+ CPpmd_State *ps[256], *s;
+ UInt32 freqSum, count, hiCnt;
+ CPpmd_See *see;
+ unsigned i, num, numMasked = p->MinContext->NumStats;
+ do
+ {
+ p->OrderFall++;
+ if (!p->MinContext->Suffix)
+ return -1;
+ p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
+ }
+ while (p->MinContext->NumStats == numMasked);
+ hiCnt = 0;
+ s = Ppmd7_GetStats(p, p->MinContext);
+ i = 0;
+ num = p->MinContext->NumStats - numMasked;
+ do
+ {
+ int k = (int)(MASK(s->Symbol));
+ hiCnt += (s->Freq & k);
+ ps[i] = s++;
+ i -= k;
+ }
+ while (i != num);
+
+ see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);
+ freqSum += hiCnt;
+ count = rc->GetThreshold(rc, freqSum);
+
+ if (count < hiCnt)
+ {
+ Byte symbol;
+ CPpmd_State **pps = ps;
+ for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
+ s = *pps;
+ rc->Decode(rc, hiCnt - s->Freq, s->Freq);
+ Ppmd_See_Update(see);
+ p->FoundState = s;
+ symbol = s->Symbol;
+ Ppmd7_Update2(p);
+ return symbol;
+ }
+ if (count >= freqSum)
+ return -2;
+ rc->Decode(rc, hiCnt, freqSum - hiCnt);
+ see->Summ = (UInt16)(see->Summ + freqSum);
+ do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
+ }
+}
+
+/* ---------- Encode ---------- Ppmd7Enc.c */
+
+#define kTopValue (1 << 24)
+
+static void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p)
+{
+ p->Low = 0;
+ p->Range = 0xFFFFFFFF;
+ p->Cache = 0;
+ p->CacheSize = 1;
+}
+
+static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)
+{
+ if ((UInt32)p->Low < (UInt32)0xFF000000 || (unsigned)(p->Low >> 32) != 0)
+ {
+ Byte temp = p->Cache;
+ do
+ {
+ p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32)));
+ temp = 0xFF;
+ }
+ while(--p->CacheSize != 0);
+ p->Cache = (Byte)((UInt32)p->Low >> 24);
+ }
+ p->CacheSize++;
+ p->Low = (UInt32)p->Low << 8;
+}
+
+static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total)
+{
+ p->Low += start * (p->Range /= total);
+ p->Range *= size;
+ while (p->Range < kTopValue)
+ {
+ p->Range <<= 8;
+ RangeEnc_ShiftLow(p);
+ }
+}
+
+static void RangeEnc_EncodeBit_0(CPpmd7z_RangeEnc *p, UInt32 size0)
+{
+ p->Range = (p->Range >> 14) * size0;
+ while (p->Range < kTopValue)
+ {
+ p->Range <<= 8;
+ RangeEnc_ShiftLow(p);
+ }
+}
+
+static void RangeEnc_EncodeBit_1(CPpmd7z_RangeEnc *p, UInt32 size0)
+{
+ UInt32 newBound = (p->Range >> 14) * size0;
+ p->Low += newBound;
+ p->Range -= newBound;
+ while (p->Range < kTopValue)
+ {
+ p->Range <<= 8;
+ RangeEnc_ShiftLow(p);
+ }
+}
+
+static void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p)
+{
+ unsigned i;
+ for (i = 0; i < 5; i++)
+ RangeEnc_ShiftLow(p);
+}
+
+
+#define MASK(sym) ((signed char *)charMask)[sym]
+
+static void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol)
+{
+ size_t charMask[256 / sizeof(size_t)];
+ if (p->MinContext->NumStats != 1)
+ {
+ CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
+ UInt32 sum;
+ unsigned i;
+ if (s->Symbol == symbol)
+ {
+ RangeEnc_Encode(rc, 0, s->Freq, p->MinContext->SummFreq);
+ p->FoundState = s;
+ Ppmd7_Update1_0(p);
+ return;
+ }
+ p->PrevSuccess = 0;
+ sum = s->Freq;
+ i = p->MinContext->NumStats - 1;
+ do
+ {
+ if ((++s)->Symbol == symbol)
+ {
+ RangeEnc_Encode(rc, sum, s->Freq, p->MinContext->SummFreq);
+ p->FoundState = s;
+ Ppmd7_Update1(p);
+ return;
+ }
+ sum += s->Freq;
+ }
+ while (--i);
+
+ p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
+ PPMD_SetAllBitsIn256Bytes(charMask);
+ MASK(s->Symbol) = 0;
+ i = p->MinContext->NumStats - 1;
+ do { MASK((--s)->Symbol) = 0; } while (--i);
+ RangeEnc_Encode(rc, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq);
+ }
+ else
+ {
+ UInt16 *prob = Ppmd7_GetBinSumm(p);
+ CPpmd_State *s = Ppmd7Context_OneState(p->MinContext);
+ if (s->Symbol == symbol)
+ {
+ RangeEnc_EncodeBit_0(rc, *prob);
+ *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
+ p->FoundState = s;
+ Ppmd7_UpdateBin(p);
+ return;
+ }
+ else
+ {
+ RangeEnc_EncodeBit_1(rc, *prob);
+ *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
+ p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
+ PPMD_SetAllBitsIn256Bytes(charMask);
+ MASK(s->Symbol) = 0;
+ p->PrevSuccess = 0;
+ }
+ }
+ for (;;)
+ {
+ UInt32 escFreq;
+ CPpmd_See *see;
+ CPpmd_State *s;
+ UInt32 sum;
+ unsigned i, numMasked = p->MinContext->NumStats;
+ do
+ {
+ p->OrderFall++;
+ if (!p->MinContext->Suffix)
+ return; /* EndMarker (symbol = -1) */
+ p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
+ }
+ while (p->MinContext->NumStats == numMasked);
+
+ see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq);
+ s = Ppmd7_GetStats(p, p->MinContext);
+ sum = 0;
+ i = p->MinContext->NumStats;
+ do
+ {
+ int cur = s->Symbol;
+ if (cur == symbol)
+ {
+ UInt32 low = sum;
+ CPpmd_State *s1 = s;
+ do
+ {
+ sum += (s->Freq & (int)(MASK(s->Symbol)));
+ s++;
+ }
+ while (--i);
+ RangeEnc_Encode(rc, low, s1->Freq, sum + escFreq);
+ Ppmd_See_Update(see);
+ p->FoundState = s1;
+ Ppmd7_Update2(p);
+ return;
+ }
+ sum += (s->Freq & (int)(MASK(cur)));
+ MASK(cur) = 0;
+ s++;
+ }
+ while (--i);
+
+ RangeEnc_Encode(rc, sum, escFreq, sum + escFreq);
+ see->Summ = (UInt16)(see->Summ + sum + escFreq);
+ }
+}
+
+const IPpmd7 __archive_ppmd7_functions =
+{
+ &Ppmd7_Construct,
+ &Ppmd7_Alloc,
+ &Ppmd7_Free,
+ &Ppmd7_Init,
+ &Ppmd7z_RangeDec_CreateVTable,
+ &PpmdRAR_RangeDec_CreateVTable,
+ &Ppmd7z_RangeDec_Init,
+ &PpmdRAR_RangeDec_Init,
+ &Ppmd7_DecodeSymbol,
+ &Ppmd7z_RangeEnc_Init,
+ &Ppmd7z_RangeEnc_FlushData,
+ &Ppmd7_EncodeSymbol
+};
diff --git a/contrib/libarchive/libarchive/archive_ppmd7_private.h b/contrib/libarchive/libarchive/archive_ppmd7_private.h
new file mode 100644
index 000000000000..3a6b9eb4190f
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_ppmd7_private.h
@@ -0,0 +1,119 @@
+/* Ppmd7.h -- PPMdH compression codec
+2010-03-12 : Igor Pavlov : Public domain
+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
+
+/* This code supports virtual RangeDecoder and includes the implementation
+of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H.
+If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */
+
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
+#ifndef ARCHIVE_PPMD7_PRIVATE_H_INCLUDED
+#define ARCHIVE_PPMD7_PRIVATE_H_INCLUDED
+
+#include "archive_ppmd_private.h"
+
+#define PPMD7_MIN_ORDER 2
+#define PPMD7_MAX_ORDER 64
+
+#define PPMD7_MIN_MEM_SIZE (1 << 11)
+#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3)
+
+struct CPpmd7_Context_;
+
+typedef
+ #ifdef PPMD_32BIT
+ struct CPpmd7_Context_ *
+ #else
+ UInt32
+ #endif
+ CPpmd7_Context_Ref;
+
+typedef struct CPpmd7_Context_
+{
+ UInt16 NumStats;
+ UInt16 SummFreq;
+ CPpmd_State_Ref Stats;
+ CPpmd7_Context_Ref Suffix;
+} CPpmd7_Context;
+
+#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)
+
+typedef struct
+{
+ CPpmd7_Context *MinContext, *MaxContext;
+ CPpmd_State *FoundState;
+ unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag;
+ Int32 RunLength, InitRL; /* must be 32-bit at least */
+
+ UInt32 Size;
+ UInt32 GlueCount;
+ Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
+ UInt32 AlignOffset;
+
+ Byte Indx2Units[PPMD_NUM_INDEXES];
+ Byte Units2Indx[128];
+ CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
+ Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
+ CPpmd_See DummySee, See[25][16];
+ UInt16 BinSumm[128][64];
+} CPpmd7;
+
+/* ---------- Decode ---------- */
+
+typedef struct
+{
+ UInt32 (*GetThreshold)(void *p, UInt32 total);
+ void (*Decode)(void *p, UInt32 start, UInt32 size);
+ UInt32 (*DecodeBit)(void *p, UInt32 size0);
+} IPpmd7_RangeDec;
+
+typedef struct
+{
+ IPpmd7_RangeDec p;
+ UInt32 Range;
+ UInt32 Code;
+ UInt32 Low;
+ UInt32 Bottom;
+ IByteIn *Stream;
+} CPpmd7z_RangeDec;
+
+/* ---------- Encode ---------- */
+
+typedef struct
+{
+ UInt64 Low;
+ UInt32 Range;
+ Byte Cache;
+ UInt64 CacheSize;
+ IByteOut *Stream;
+} CPpmd7z_RangeEnc;
+
+typedef struct
+{
+ /* Base Functions */
+ void (*Ppmd7_Construct)(CPpmd7 *p);
+ Bool (*Ppmd7_Alloc)(CPpmd7 *p, UInt32 size, ISzAlloc *alloc);
+ void (*Ppmd7_Free)(CPpmd7 *p, ISzAlloc *alloc);
+ void (*Ppmd7_Init)(CPpmd7 *p, unsigned maxOrder);
+ #define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
+
+ /* Decode Functions */
+ void (*Ppmd7z_RangeDec_CreateVTable)(CPpmd7z_RangeDec *p);
+ void (*PpmdRAR_RangeDec_CreateVTable)(CPpmd7z_RangeDec *p);
+ Bool (*Ppmd7z_RangeDec_Init)(CPpmd7z_RangeDec *p);
+ Bool (*PpmdRAR_RangeDec_Init)(CPpmd7z_RangeDec *p);
+ #define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
+ int (*Ppmd7_DecodeSymbol)(CPpmd7 *p, IPpmd7_RangeDec *rc);
+
+ /* Encode Functions */
+ void (*Ppmd7z_RangeEnc_Init)(CPpmd7z_RangeEnc *p);
+ void (*Ppmd7z_RangeEnc_FlushData)(CPpmd7z_RangeEnc *p);
+
+ void (*Ppmd7_EncodeSymbol)(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol);
+} IPpmd7;
+
+extern const IPpmd7 __archive_ppmd7_functions;
+#endif
diff --git a/contrib/libarchive/libarchive/archive_ppmd_private.h b/contrib/libarchive/libarchive/archive_ppmd_private.h
new file mode 100644
index 000000000000..e78bde594059
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_ppmd_private.h
@@ -0,0 +1,158 @@
+/* Ppmd.h -- PPMD codec common code
+2010-03-12 : Igor Pavlov : Public domain
+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
+
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
+#ifndef ARCHIVE_PPMD_PRIVATE_H_INCLUDED
+#define ARCHIVE_PPMD_PRIVATE_H_INCLUDED
+
+#include <stddef.h>
+
+#include "archive_read_private.h"
+
+/*** Begin defined in Types.h ***/
+
+#if !defined(ZCONF_H)
+typedef unsigned char Byte;
+#endif
+typedef short Int16;
+typedef unsigned short UInt16;
+
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef long Int32;
+typedef unsigned long UInt32;
+#else
+typedef int Int32;
+typedef unsigned int UInt32;
+#endif
+
+#ifdef _SZ_NO_INT_64
+
+/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
+ NOTES: Some code will work incorrectly in that case! */
+
+typedef long Int64;
+typedef unsigned long UInt64;
+
+#else
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef __int64 Int64;
+typedef unsigned __int64 UInt64;
+#define UINT64_CONST(n) n
+#else
+typedef long long int Int64;
+typedef unsigned long long int UInt64;
+#define UINT64_CONST(n) n ## ULL
+#endif
+
+#endif
+
+typedef int Bool;
+#define True 1
+#define False 0
+
+/* The following interfaces use first parameter as pointer to structure */
+
+typedef struct
+{
+ struct archive_read *a;
+ Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
+} IByteIn;
+
+typedef struct
+{
+ struct archive_write *a;
+ void (*Write)(void *p, Byte b);
+} IByteOut;
+
+
+typedef struct
+{
+ void *(*Alloc)(void *p, size_t size);
+ void (*Free)(void *p, void *address); /* address can be 0 */
+} ISzAlloc;
+
+/*** End defined in Types.h ***/
+/*** Begin defined in CpuArch.h ***/
+
+#if defined(_M_IX86) || defined(__i386__)
+#define MY_CPU_X86
+#endif
+
+#if defined(MY_CPU_X86) || defined(_M_ARM)
+#define MY_CPU_32BIT
+#endif
+
+#ifdef MY_CPU_32BIT
+#define PPMD_32BIT
+#endif
+
+/*** End defined in CpuArch.h ***/
+
+#define PPMD_INT_BITS 7
+#define PPMD_PERIOD_BITS 7
+#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS))
+
+#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift))
+#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2)
+#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob))
+#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob))
+
+#define PPMD_N1 4
+#define PPMD_N2 4
+#define PPMD_N3 4
+#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)
+#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)
+
+/* SEE-contexts for PPM-contexts with masked symbols */
+typedef struct
+{
+ UInt16 Summ; /* Freq */
+ Byte Shift; /* Speed of Freq change; low Shift is for fast change */
+ Byte Count; /* Count to next change of Shift */
+} CPpmd_See;
+
+#define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \
+ { (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); }
+
+typedef struct
+{
+ Byte Symbol;
+ Byte Freq;
+ UInt16 SuccessorLow;
+ UInt16 SuccessorHigh;
+} CPpmd_State;
+
+typedef
+ #ifdef PPMD_32BIT
+ CPpmd_State *
+ #else
+ UInt32
+ #endif
+ CPpmd_State_Ref;
+
+typedef
+ #ifdef PPMD_32BIT
+ void *
+ #else
+ UInt32
+ #endif
+ CPpmd_Void_Ref;
+
+typedef
+ #ifdef PPMD_32BIT
+ Byte *
+ #else
+ UInt32
+ #endif
+ CPpmd_Byte_Ref;
+
+#define PPMD_SetAllBitsIn256Bytes(p) \
+ { unsigned j; for (j = 0; j < 256 / sizeof(p[0]); j += 8) { \
+ p[j+7] = p[j+6] = p[j+5] = p[j+4] = p[j+3] = p[j+2] = p[j+1] = p[j+0] = ~(size_t)0; }}
+
+#endif
diff --git a/contrib/libarchive/libarchive/archive_private.h b/contrib/libarchive/libarchive/archive_private.h
index dc83048a592a..eb4f12296111 100644
--- a/contrib/libarchive/libarchive/archive_private.h
+++ b/contrib/libarchive/libarchive/archive_private.h
@@ -32,6 +32,10 @@
#ifndef ARCHIVE_PRIVATE_H_INCLUDED
#define ARCHIVE_PRIVATE_H_INCLUDED
+#if HAVE_ICONV_H
+#include <iconv.h>
+#endif
+
#include "archive.h"
#include "archive_string.h"
@@ -47,14 +51,13 @@
#define ARCHIVE_WRITE_DISK_MAGIC (0xc001b0c5U)
#define ARCHIVE_READ_DISK_MAGIC (0xbadb0c5U)
-#define ARCHIVE_STATE_ANY 0xFFFFU
#define ARCHIVE_STATE_NEW 1U
#define ARCHIVE_STATE_HEADER 2U
#define ARCHIVE_STATE_DATA 4U
-#define ARCHIVE_STATE_DATA_END 8U
#define ARCHIVE_STATE_EOF 0x10U
#define ARCHIVE_STATE_CLOSED 0x20U
#define ARCHIVE_STATE_FATAL 0x8000U
+#define ARCHIVE_STATE_ANY (0xFFFFU & ~ARCHIVE_STATE_FATAL)
struct archive_vtable {
int (*archive_close)(struct archive *);
@@ -65,9 +68,23 @@ struct archive_vtable {
ssize_t (*archive_write_data)(struct archive *,
const void *, size_t);
ssize_t (*archive_write_data_block)(struct archive *,
- const void *, size_t, off_t);
+ const void *, size_t, int64_t);
+
+ int (*archive_read_next_header)(struct archive *,
+ struct archive_entry **);
+ int (*archive_read_next_header2)(struct archive *,
+ struct archive_entry *);
+ int (*archive_read_data_block)(struct archive *,
+ const void **, size_t *, int64_t *);
+
+ int (*archive_filter_count)(struct archive *);
+ int64_t (*archive_filter_bytes)(struct archive *, int);
+ int (*archive_filter_code)(struct archive *, int);
+ const char * (*archive_filter_name)(struct archive *, int);
};
+struct archive_string_conv;
+
struct archive {
/*
* The magic/state values are used to sanity-check the
@@ -90,26 +107,35 @@ struct archive {
int compression_code; /* Currently active compression. */
const char *compression_name;
- /* Position in UNCOMPRESSED data stream. */
- int64_t file_position;
- /* Position in COMPRESSED data stream. */
- int64_t raw_position;
/* Number of file entries processed. */
int file_count;
int archive_error_number;
const char *error;
struct archive_string error_string;
+
+ char *current_code;
+ unsigned current_codepage; /* Current ACP(ANSI CodePage). */
+ unsigned current_oemcp; /* Current OEMCP(OEM CodePage). */
+ struct archive_string_conv *sconv;
};
-/* Check magic value and state; exit if it isn't valid. */
-void __archive_check_magic(struct archive *, unsigned int magic,
+/* Check magic value and state; return(ARCHIVE_FATAL) if it isn't valid. */
+int __archive_check_magic(struct archive *, unsigned int magic,
unsigned int state, const char *func);
+#define archive_check_magic(a, expected_magic, allowed_states, function_name) \
+ do { \
+ int magic_test = __archive_check_magic((a), (expected_magic), \
+ (allowed_states), (function_name)); \
+ if (magic_test == ARCHIVE_FATAL) \
+ return ARCHIVE_FATAL; \
+ } while (0)
void __archive_errx(int retvalue, const char *msg) __LA_DEAD;
-int __archive_parse_options(const char *p, const char *fn,
- int keysize, char *key, int valsize, char *val);
+int __archive_mktemp(const char *tmpdir);
+
+int __archive_clean(struct archive *);
#define err_combine(a,b) ((a) < (b) ? (a) : (b))
diff --git a/contrib/libarchive/libarchive/archive_rb.c b/contrib/libarchive/libarchive/archive_rb.c
new file mode 100644
index 000000000000..70bf7e6d3379
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_rb.c
@@ -0,0 +1,701 @@
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas <matt@3am-software.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Based on: NetBSD: rb.c,v 1.6 2010/04/30 13:58:09 joerg Exp
+ */
+
+#include "archive_platform.h"
+
+#include <stddef.h>
+
+#include "archive_rb.h"
+
+/* Keep in sync with archive_rb.h */
+#define RB_DIR_LEFT 0
+#define RB_DIR_RIGHT 1
+#define RB_DIR_OTHER 1
+#define rb_left rb_nodes[RB_DIR_LEFT]
+#define rb_right rb_nodes[RB_DIR_RIGHT]
+
+#define RB_FLAG_POSITION 0x2
+#define RB_FLAG_RED 0x1
+#define RB_FLAG_MASK (RB_FLAG_POSITION|RB_FLAG_RED)
+#define RB_FATHER(rb) \
+ ((struct archive_rb_node *)((rb)->rb_info & ~RB_FLAG_MASK))
+#define RB_SET_FATHER(rb, father) \
+ ((void)((rb)->rb_info = (uintptr_t)(father)|((rb)->rb_info & RB_FLAG_MASK)))
+
+#define RB_SENTINEL_P(rb) ((rb) == NULL)
+#define RB_LEFT_SENTINEL_P(rb) RB_SENTINEL_P((rb)->rb_left)
+#define RB_RIGHT_SENTINEL_P(rb) RB_SENTINEL_P((rb)->rb_right)
+#define RB_FATHER_SENTINEL_P(rb) RB_SENTINEL_P(RB_FATHER((rb)))
+#define RB_CHILDLESS_P(rb) \
+ (RB_SENTINEL_P(rb) || (RB_LEFT_SENTINEL_P(rb) && RB_RIGHT_SENTINEL_P(rb)))
+#define RB_TWOCHILDREN_P(rb) \
+ (!RB_SENTINEL_P(rb) && !RB_LEFT_SENTINEL_P(rb) && !RB_RIGHT_SENTINEL_P(rb))
+
+#define RB_POSITION(rb) \
+ (((rb)->rb_info & RB_FLAG_POSITION) ? RB_DIR_RIGHT : RB_DIR_LEFT)
+#define RB_RIGHT_P(rb) (RB_POSITION(rb) == RB_DIR_RIGHT)
+#define RB_LEFT_P(rb) (RB_POSITION(rb) == RB_DIR_LEFT)
+#define RB_RED_P(rb) (!RB_SENTINEL_P(rb) && ((rb)->rb_info & RB_FLAG_RED) != 0)
+#define RB_BLACK_P(rb) (RB_SENTINEL_P(rb) || ((rb)->rb_info & RB_FLAG_RED) == 0)
+#define RB_MARK_RED(rb) ((void)((rb)->rb_info |= RB_FLAG_RED))
+#define RB_MARK_BLACK(rb) ((void)((rb)->rb_info &= ~RB_FLAG_RED))
+#define RB_INVERT_COLOR(rb) ((void)((rb)->rb_info ^= RB_FLAG_RED))
+#define RB_ROOT_P(rbt, rb) ((rbt)->rbt_root == (rb))
+#define RB_SET_POSITION(rb, position) \
+ ((void)((position) ? ((rb)->rb_info |= RB_FLAG_POSITION) : \
+ ((rb)->rb_info &= ~RB_FLAG_POSITION)))
+#define RB_ZERO_PROPERTIES(rb) ((void)((rb)->rb_info &= ~RB_FLAG_MASK))
+#define RB_COPY_PROPERTIES(dst, src) \
+ ((void)((dst)->rb_info ^= ((dst)->rb_info ^ (src)->rb_info) & RB_FLAG_MASK))
+#define RB_SWAP_PROPERTIES(a, b) do { \
+ uintptr_t xorinfo = ((a)->rb_info ^ (b)->rb_info) & RB_FLAG_MASK; \
+ (a)->rb_info ^= xorinfo; \
+ (b)->rb_info ^= xorinfo; \
+ } while (/*CONSTCOND*/ 0)
+
+static void __archive_rb_tree_insert_rebalance(struct archive_rb_tree *,
+ struct archive_rb_node *);
+static void __archive_rb_tree_removal_rebalance(struct archive_rb_tree *,
+ struct archive_rb_node *, unsigned int);
+
+#define RB_SENTINEL_NODE NULL
+
+#define T 1
+#define F 0
+
+void
+__archive_rb_tree_init(struct archive_rb_tree *rbt,
+ const struct archive_rb_tree_ops *ops)
+{
+ rbt->rbt_ops = ops;
+ *((struct archive_rb_node **)&rbt->rbt_root) = RB_SENTINEL_NODE;
+}
+
+struct archive_rb_node *
+__archive_rb_tree_find_node(struct archive_rb_tree *rbt, const void *key)
+{
+ archive_rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
+ struct archive_rb_node *parent = rbt->rbt_root;
+
+ while (!RB_SENTINEL_P(parent)) {
+ const signed int diff = (*compare_key)(parent, key);
+ if (diff == 0)
+ return parent;
+ parent = parent->rb_nodes[diff > 0];
+ }
+
+ return NULL;
+}
+
+struct archive_rb_node *
+__archive_rb_tree_find_node_geq(struct archive_rb_tree *rbt, const void *key)
+{
+ archive_rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
+ struct archive_rb_node *parent = rbt->rbt_root;
+ struct archive_rb_node *last = NULL;
+
+ while (!RB_SENTINEL_P(parent)) {
+ const signed int diff = (*compare_key)(parent, key);
+ if (diff == 0)
+ return parent;
+ if (diff < 0)
+ last = parent;
+ parent = parent->rb_nodes[diff > 0];
+ }
+
+ return last;
+}
+
+struct archive_rb_node *
+__archive_rb_tree_find_node_leq(struct archive_rb_tree *rbt, const void *key)
+{
+ archive_rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
+ struct archive_rb_node *parent = rbt->rbt_root;
+ struct archive_rb_node *last = NULL;
+
+ while (!RB_SENTINEL_P(parent)) {
+ const signed int diff = (*compare_key)(parent, key);
+ if (diff == 0)
+ return parent;
+ if (diff > 0)
+ last = parent;
+ parent = parent->rb_nodes[diff > 0];
+ }
+
+ return last;
+}
+
+int
+__archive_rb_tree_insert_node(struct archive_rb_tree *rbt,
+ struct archive_rb_node *self)
+{
+ archive_rbto_compare_nodes_fn compare_nodes = rbt->rbt_ops->rbto_compare_nodes;
+ struct archive_rb_node *parent, *tmp;
+ unsigned int position;
+ int rebalance;
+
+ tmp = rbt->rbt_root;
+ /*
+ * This is a hack. Because rbt->rbt_root is just a
+ * struct archive_rb_node *, just like rb_node->rb_nodes[RB_DIR_LEFT],
+ * we can use this fact to avoid a lot of tests for root and know
+ * that even at root, updating
+ * RB_FATHER(rb_node)->rb_nodes[RB_POSITION(rb_node)] will
+ * update rbt->rbt_root.
+ */
+ parent = (struct archive_rb_node *)(void *)&rbt->rbt_root;
+ position = RB_DIR_LEFT;
+
+ /*
+ * Find out where to place this new leaf.
+ */
+ while (!RB_SENTINEL_P(tmp)) {
+ const signed int diff = (*compare_nodes)(tmp, self);
+ if (diff == 0) {
+ /*
+ * Node already exists; don't insert.
+ */
+ return F;
+ }
+ parent = tmp;
+ position = (diff > 0);
+ tmp = parent->rb_nodes[position];
+ }
+
+ /*
+ * Initialize the node and insert as a leaf into the tree.
+ */
+ RB_SET_FATHER(self, parent);
+ RB_SET_POSITION(self, position);
+ if (parent == (struct archive_rb_node *)(void *)&rbt->rbt_root) {
+ RB_MARK_BLACK(self); /* root is always black */
+ rebalance = F;
+ } else {
+ /*
+ * All new nodes are colored red. We only need to rebalance
+ * if our parent is also red.
+ */
+ RB_MARK_RED(self);
+ rebalance = RB_RED_P(parent);
+ }
+ self->rb_left = parent->rb_nodes[position];
+ self->rb_right = parent->rb_nodes[position];
+ parent->rb_nodes[position] = self;
+
+ /*
+ * Rebalance tree after insertion
+ */
+ if (rebalance)
+ __archive_rb_tree_insert_rebalance(rbt, self);
+
+ return T;
+}
+
+/*
+ * Swap the location and colors of 'self' and its child @ which. The child
+ * can not be a sentinel node. This is our rotation function. However,
+ * since it preserves coloring, it great simplifies both insertion and
+ * removal since rotation almost always involves the exchanging of colors
+ * as a separate step.
+ */
+/*ARGSUSED*/
+static void
+__archive_rb_tree_reparent_nodes(
+ struct archive_rb_node *old_father, const unsigned int which)
+{
+ const unsigned int other = which ^ RB_DIR_OTHER;
+ struct archive_rb_node * const grandpa = RB_FATHER(old_father);
+ struct archive_rb_node * const old_child = old_father->rb_nodes[which];
+ struct archive_rb_node * const new_father = old_child;
+ struct archive_rb_node * const new_child = old_father;
+
+ /*
+ * Exchange descendant linkages.
+ */
+ grandpa->rb_nodes[RB_POSITION(old_father)] = new_father;
+ new_child->rb_nodes[which] = old_child->rb_nodes[other];
+ new_father->rb_nodes[other] = new_child;
+
+ /*
+ * Update ancestor linkages
+ */
+ RB_SET_FATHER(new_father, grandpa);
+ RB_SET_FATHER(new_child, new_father);
+
+ /*
+ * Exchange properties between new_father and new_child. The only
+ * change is that new_child's position is now on the other side.
+ */
+ RB_SWAP_PROPERTIES(new_father, new_child);
+ RB_SET_POSITION(new_child, other);
+
+ /*
+ * Make sure to reparent the new child to ourself.
+ */
+ if (!RB_SENTINEL_P(new_child->rb_nodes[which])) {
+ RB_SET_FATHER(new_child->rb_nodes[which], new_child);
+ RB_SET_POSITION(new_child->rb_nodes[which], which);
+ }
+
+}
+
+static void
+__archive_rb_tree_insert_rebalance(struct archive_rb_tree *rbt,
+ struct archive_rb_node *self)
+{
+ struct archive_rb_node * father = RB_FATHER(self);
+ struct archive_rb_node * grandpa;
+ struct archive_rb_node * uncle;
+ unsigned int which;
+ unsigned int other;
+
+ for (;;) {
+ /*
+ * We are red and our parent is red, therefore we must have a
+ * grandfather and he must be black.
+ */
+ grandpa = RB_FATHER(father);
+ which = (father == grandpa->rb_right);
+ other = which ^ RB_DIR_OTHER;
+ uncle = grandpa->rb_nodes[other];
+
+ if (RB_BLACK_P(uncle))
+ break;
+
+ /*
+ * Case 1: our uncle is red
+ * Simply invert the colors of our parent and
+ * uncle and make our grandparent red. And
+ * then solve the problem up at his level.
+ */
+ RB_MARK_BLACK(uncle);
+ RB_MARK_BLACK(father);
+ if (RB_ROOT_P(rbt, grandpa)) {
+ /*
+ * If our grandpa is root, don't bother
+ * setting him to red, just return.
+ */
+ return;
+ }
+ RB_MARK_RED(grandpa);
+ self = grandpa;
+ father = RB_FATHER(self);
+ if (RB_BLACK_P(father)) {
+ /*
+ * If our greatgrandpa is black, we're done.
+ */
+ return;
+ }
+ }
+
+ /*
+ * Case 2&3: our uncle is black.
+ */
+ if (self == father->rb_nodes[other]) {
+ /*
+ * Case 2: we are on the same side as our uncle
+ * Swap ourselves with our parent so this case
+ * becomes case 3. Basically our parent becomes our
+ * child.
+ */
+ __archive_rb_tree_reparent_nodes(father, other);
+ }
+ /*
+ * Case 3: we are opposite a child of a black uncle.
+ * Swap our parent and grandparent. Since our grandfather
+ * is black, our father will become black and our new sibling
+ * (former grandparent) will become red.
+ */
+ __archive_rb_tree_reparent_nodes(grandpa, which);
+
+ /*
+ * Final step: Set the root to black.
+ */
+ RB_MARK_BLACK(rbt->rbt_root);
+}
+
+static void
+__archive_rb_tree_prune_node(struct archive_rb_tree *rbt,
+ struct archive_rb_node *self, int rebalance)
+{
+ const unsigned int which = RB_POSITION(self);
+ struct archive_rb_node *father = RB_FATHER(self);
+
+ /*
+ * Since we are childless, we know that self->rb_left is pointing
+ * to the sentinel node.
+ */
+ father->rb_nodes[which] = self->rb_left;
+
+ /*
+ * Rebalance if requested.
+ */
+ if (rebalance)
+ __archive_rb_tree_removal_rebalance(rbt, father, which);
+}
+
+/*
+ * When deleting an interior node
+ */
+static void
+__archive_rb_tree_swap_prune_and_rebalance(struct archive_rb_tree *rbt,
+ struct archive_rb_node *self, struct archive_rb_node *standin)
+{
+ const unsigned int standin_which = RB_POSITION(standin);
+ unsigned int standin_other = standin_which ^ RB_DIR_OTHER;
+ struct archive_rb_node *standin_son;
+ struct archive_rb_node *standin_father = RB_FATHER(standin);
+ int rebalance = RB_BLACK_P(standin);
+
+ if (standin_father == self) {
+ /*
+ * As a child of self, any children would be opposite of
+ * our parent.
+ */
+ standin_son = standin->rb_nodes[standin_which];
+ } else {
+ /*
+ * Since we aren't a child of self, any children would be
+ * on the same side as our parent.
+ */
+ standin_son = standin->rb_nodes[standin_other];
+ }
+
+ if (RB_RED_P(standin_son)) {
+ /*
+ * We know we have a red child so if we flip it to black
+ * we don't have to rebalance.
+ */
+ RB_MARK_BLACK(standin_son);
+ rebalance = F;
+
+ if (standin_father != self) {
+ /*
+ * Change the son's parentage to point to his grandpa.
+ */
+ RB_SET_FATHER(standin_son, standin_father);
+ RB_SET_POSITION(standin_son, standin_which);
+ }
+ }
+
+ if (standin_father == self) {
+ /*
+ * If we are about to delete the standin's father, then when
+ * we call rebalance, we need to use ourselves as our father.
+ * Otherwise remember our original father. Also, since we are
+ * our standin's father we only need to reparent the standin's
+ * brother.
+ *
+ * | R --> S |
+ * | Q S --> Q T |
+ * | t --> |
+ *
+ * Have our son/standin adopt his brother as his new son.
+ */
+ standin_father = standin;
+ } else {
+ /*
+ * | R --> S . |
+ * | / \ | T --> / \ | / |
+ * | ..... | S --> ..... | T |
+ *
+ * Sever standin's connection to his father.
+ */
+ standin_father->rb_nodes[standin_which] = standin_son;
+ /*
+ * Adopt the far son.
+ */
+ standin->rb_nodes[standin_other] = self->rb_nodes[standin_other];
+ RB_SET_FATHER(standin->rb_nodes[standin_other], standin);
+ /*
+ * Use standin_other because we need to preserve standin_which
+ * for the removal_rebalance.
+ */
+ standin_other = standin_which;
+ }
+
+ /*
+ * Move the only remaining son to our standin. If our standin is our
+ * son, this will be the only son needed to be moved.
+ */
+ standin->rb_nodes[standin_other] = self->rb_nodes[standin_other];
+ RB_SET_FATHER(standin->rb_nodes[standin_other], standin);
+
+ /*
+ * Now copy the result of self to standin and then replace
+ * self with standin in the tree.
+ */
+ RB_COPY_PROPERTIES(standin, self);
+ RB_SET_FATHER(standin, RB_FATHER(self));
+ RB_FATHER(standin)->rb_nodes[RB_POSITION(standin)] = standin;
+
+ if (rebalance)
+ __archive_rb_tree_removal_rebalance(rbt, standin_father, standin_which);
+}
+
+/*
+ * We could do this by doing
+ * __archive_rb_tree_node_swap(rbt, self, which);
+ * __archive_rb_tree_prune_node(rbt, self, F);
+ *
+ * But it's more efficient to just evaluate and recolor the child.
+ */
+static void
+__archive_rb_tree_prune_blackred_branch(
+ struct archive_rb_node *self, unsigned int which)
+{
+ struct archive_rb_node *father = RB_FATHER(self);
+ struct archive_rb_node *son = self->rb_nodes[which];
+
+ /*
+ * Remove ourselves from the tree and give our former child our
+ * properties (position, color, root).
+ */
+ RB_COPY_PROPERTIES(son, self);
+ father->rb_nodes[RB_POSITION(son)] = son;
+ RB_SET_FATHER(son, father);
+}
+/*
+ *
+ */
+void
+__archive_rb_tree_remove_node(struct archive_rb_tree *rbt,
+ struct archive_rb_node *self)
+{
+ struct archive_rb_node *standin;
+ unsigned int which;
+
+ /*
+ * In the following diagrams, we (the node to be removed) are S. Red
+ * nodes are lowercase. T could be either red or black.
+ *
+ * Remember the major axiom of the red-black tree: the number of
+ * black nodes from the root to each leaf is constant across all
+ * leaves, only the number of red nodes varies.
+ *
+ * Thus removing a red leaf doesn't require any other changes to a
+ * red-black tree. So if we must remove a node, attempt to rearrange
+ * the tree so we can remove a red node.
+ *
+ * The simplest case is a childless red node or a childless root node:
+ *
+ * | T --> T | or | R --> * |
+ * | s --> * |
+ */
+ if (RB_CHILDLESS_P(self)) {
+ const int rebalance = RB_BLACK_P(self) && !RB_ROOT_P(rbt, self);
+ __archive_rb_tree_prune_node(rbt, self, rebalance);
+ return;
+ }
+ if (!RB_TWOCHILDREN_P(self)) {
+ /*
+ * The next simplest case is the node we are deleting is
+ * black and has one red child.
+ *
+ * | T --> T --> T |
+ * | S --> R --> R |
+ * | r --> s --> * |
+ */
+ which = RB_LEFT_SENTINEL_P(self) ? RB_DIR_RIGHT : RB_DIR_LEFT;
+ __archive_rb_tree_prune_blackred_branch(self, which);
+ return;
+ }
+
+ /*
+ * We invert these because we prefer to remove from the inside of
+ * the tree.
+ */
+ which = RB_POSITION(self) ^ RB_DIR_OTHER;
+
+ /*
+ * Let's find the node closes to us opposite of our parent
+ * Now swap it with ourself, "prune" it, and rebalance, if needed.
+ */
+ standin = __archive_rb_tree_iterate(rbt, self, which);
+ __archive_rb_tree_swap_prune_and_rebalance(rbt, self, standin);
+}
+
+static void
+__archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt,
+ struct archive_rb_node *parent, unsigned int which)
+{
+
+ while (RB_BLACK_P(parent->rb_nodes[which])) {
+ unsigned int other = which ^ RB_DIR_OTHER;
+ struct archive_rb_node *brother = parent->rb_nodes[other];
+
+ /*
+ * For cases 1, 2a, and 2b, our brother's children must
+ * be black and our father must be black
+ */
+ if (RB_BLACK_P(parent)
+ && RB_BLACK_P(brother->rb_left)
+ && RB_BLACK_P(brother->rb_right)) {
+ if (RB_RED_P(brother)) {
+ /*
+ * Case 1: Our brother is red, swap its
+ * position (and colors) with our parent.
+ * This should now be case 2b (unless C or E
+ * has a red child which is case 3; thus no
+ * explicit branch to case 2b).
+ *
+ * B -> D
+ * A d -> b E
+ * C E -> A C
+ */
+ __archive_rb_tree_reparent_nodes(parent, other);
+ brother = parent->rb_nodes[other];
+ } else {
+ /*
+ * Both our parent and brother are black.
+ * Change our brother to red, advance up rank
+ * and go through the loop again.
+ *
+ * B -> *B
+ * *A D -> A d
+ * C E -> C E
+ */
+ RB_MARK_RED(brother);
+ if (RB_ROOT_P(rbt, parent))
+ return; /* root == parent == black */
+ which = RB_POSITION(parent);
+ parent = RB_FATHER(parent);
+ continue;
+ }
+ }
+ /*
+ * Avoid an else here so that case 2a above can hit either
+ * case 2b, 3, or 4.
+ */
+ if (RB_RED_P(parent)
+ && RB_BLACK_P(brother)
+ && RB_BLACK_P(brother->rb_left)
+ && RB_BLACK_P(brother->rb_right)) {
+ /*
+ * We are black, our father is red, our brother and
+ * both nephews are black. Simply invert/exchange the
+ * colors of our father and brother (to black and red
+ * respectively).
+ *
+ * | f --> F |
+ * | * B --> * b |
+ * | N N --> N N |
+ */
+ RB_MARK_BLACK(parent);
+ RB_MARK_RED(brother);
+ break; /* We're done! */
+ } else {
+ /*
+ * Our brother must be black and have at least one
+ * red child (it may have two).
+ */
+ if (RB_BLACK_P(brother->rb_nodes[other])) {
+ /*
+ * Case 3: our brother is black, our near
+ * nephew is red, and our far nephew is black.
+ * Swap our brother with our near nephew.
+ * This result in a tree that matches case 4.
+ * (Our father could be red or black).
+ *
+ * | F --> F |
+ * | x B --> x B |
+ * | n --> n |
+ */
+ __archive_rb_tree_reparent_nodes(brother, which);
+ brother = parent->rb_nodes[other];
+ }
+ /*
+ * Case 4: our brother is black and our far nephew
+ * is red. Swap our father and brother locations and
+ * change our far nephew to black. (these can be
+ * done in either order so we change the color first).
+ * The result is a valid red-black tree and is a
+ * terminal case. (again we don't care about the
+ * father's color)
+ *
+ * If the father is red, we will get a red-black-black
+ * tree:
+ * | f -> f --> b |
+ * | B -> B --> F N |
+ * | n -> N --> |
+ *
+ * If the father is black, we will get an all black
+ * tree:
+ * | F -> F --> B |
+ * | B -> B --> F N |
+ * | n -> N --> |
+ *
+ * If we had two red nephews, then after the swap,
+ * our former father would have a red grandson.
+ */
+ RB_MARK_BLACK(brother->rb_nodes[other]);
+ __archive_rb_tree_reparent_nodes(parent, other);
+ break; /* We're done! */
+ }
+ }
+}
+
+struct archive_rb_node *
+__archive_rb_tree_iterate(struct archive_rb_tree *rbt,
+ struct archive_rb_node *self, const unsigned int direction)
+{
+ const unsigned int other = direction ^ RB_DIR_OTHER;
+
+ if (self == NULL) {
+ self = rbt->rbt_root;
+ if (RB_SENTINEL_P(self))
+ return NULL;
+ while (!RB_SENTINEL_P(self->rb_nodes[direction]))
+ self = self->rb_nodes[direction];
+ return self;
+ }
+ /*
+ * We can't go any further in this direction. We proceed up in the
+ * opposite direction until our parent is in direction we want to go.
+ */
+ if (RB_SENTINEL_P(self->rb_nodes[direction])) {
+ while (!RB_ROOT_P(rbt, self)) {
+ if (other == (unsigned int)RB_POSITION(self))
+ return RB_FATHER(self);
+ self = RB_FATHER(self);
+ }
+ return NULL;
+ }
+
+ /*
+ * Advance down one in current direction and go down as far as possible
+ * in the opposite direction.
+ */
+ self = self->rb_nodes[direction];
+ while (!RB_SENTINEL_P(self->rb_nodes[other]))
+ self = self->rb_nodes[other];
+ return self;
+}
diff --git a/contrib/libarchive/libarchive/archive_rb.h b/contrib/libarchive/libarchive/archive_rb.h
new file mode 100644
index 000000000000..4562e9ebc41b
--- /dev/null
+++ b/contrib/libarchive/libarchive/archive_rb.h
@@ -0,0 +1,100 @@
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas <matt@3am-software.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Based on NetBSD: rb.h,v 1.13 2009/08/16 10:57:01 yamt Exp
+ */
+#ifndef ARCHIVE_RB_H_
+#define ARCHIVE_RB_H_
+
+struct archive_rb_node {
+ struct archive_rb_node *rb_nodes[2];
+ /*
+ * rb_info contains the two flags and the parent back pointer.
+ * We put the two flags in the low two bits since we know that
+ * rb_node will have an alignment of 4 or 8 bytes.
+ */
+ uintptr_t rb_info;
+};
+
+#define ARCHIVE_RB_DIR_LEFT 0
+#define ARCHIVE_RB_DIR_RIGHT 1
+
+#define ARCHIVE_RB_TREE_MIN(T) \
+ __archive_rb_tree_iterate((T), NULL, ARCHIVE_RB_DIR_LEFT)
+#define ARCHIVE_RB_TREE_MAX(T) \
+ __archive_rb_tree_iterate((T), NULL, ARCHIVE_RB_DIR_RIGHT)
+#define ARCHIVE_RB_TREE_FOREACH(N, T) \
+ for ((N) = ARCHIVE_RB_TREE_MIN(T); (N); \
+ (N) = __archive_rb_tree_iterate((T), (N), ARCHIVE_RB_DIR_RIGHT))
+#define ARCHIVE_RB_TREE_FOREACH_REVERSE(N, T) \
+ for ((N) = ARCHIVE_RB_TREE_MAX(T); (N); \
+ (N) = __archive_rb_tree_iterate((T), (N), ARCHIVE_RB_DIR_LEFT))
+
+/*
+ * archive_rbto_compare_nodes_fn:
+ * return a positive value if the first node < the second node.
+ * return a negative value if the first node > the second node.
+ * return 0 if they are considered same.
+ *
+ * archive_rbto_compare_key_fn:
+ * return a positive value if the node < the key.
+ * return a negative value if the node > the key.
+ * return 0 if they are considered same.
+ */
+
+typedef signed int (*const archive_rbto_compare_nodes_fn)(const struct archive_rb_node *,
+ const struct archive_rb_node *);
+typedef signed int (*const archive_rbto_compare_key_fn)(const struct archive_rb_node *,
+ const void *);
+
+struct archive_rb_tree_ops {
+ archive_rbto_compare_nodes_fn