libarchive-static 1.0.6 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/extconf.rb +2 -9
- data/ext/libarchive-0.1.1/ext/archive_read_support_compression.c +6 -6
- data/ext/libarchive-0.1.1/ext/archive_read_support_compression.o +0 -0
- data/ext/libarchive-0.1.1/ext/archive_read_support_format.o +0 -0
- data/ext/libarchive-0.1.1/ext/archive_write_open_rb_str.c +1 -1
- data/ext/libarchive-0.1.1/ext/archive_write_open_rb_str.o +0 -0
- data/ext/libarchive-0.1.1/ext/archive_write_set_compression.c +5 -5
- data/ext/libarchive-0.1.1/ext/archive_write_set_compression.o +0 -0
- data/ext/libarchive-0.1.1/ext/config.h +23 -0
- data/ext/libarchive-0.1.1/ext/config.log +230 -0
- data/ext/libarchive-0.1.1/ext/config.status +671 -0
- data/ext/libarchive-0.1.1/ext/libarchive.c +1 -1
- data/ext/libarchive-0.1.1/ext/libarchive.o +0 -0
- data/ext/libarchive-0.1.1/ext/libarchive_archive.c +7 -7
- data/ext/libarchive-0.1.1/ext/libarchive_archive.o +0 -0
- data/ext/libarchive-0.1.1/ext/libarchive_entry.c +6 -0
- data/ext/libarchive-0.1.1/ext/libarchive_entry.o +0 -0
- data/ext/libarchive-0.1.1/ext/libarchive_reader.c +6 -4
- data/ext/libarchive-0.1.1/ext/libarchive_reader.o +0 -0
- data/ext/libarchive-0.1.1/ext/libarchive_ruby.so +0 -0
- data/ext/libarchive-0.1.1/ext/libarchive_win32.h +1 -1
- data/ext/libarchive-0.1.1/ext/libarchive_writer.c +2 -2
- data/ext/libarchive-0.1.1/ext/libarchive_writer.o +0 -0
- data/ext/libarchive-3.6.2/Makefile.in +16892 -0
- data/ext/libarchive-3.6.2/build/autoconf/ax_append_compile_flags.m4 +67 -0
- data/ext/libarchive-3.6.2/build/autoconf/ax_append_flag.m4 +71 -0
- data/ext/libarchive-3.6.2/build/autoconf/ax_check_compile_flag.m4 +74 -0
- data/ext/libarchive-3.6.2/build/autoconf/ax_require_defined.m4 +37 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/build/autoconf/check_stdcall_func.m4 +0 -0
- data/ext/libarchive-3.6.2/build/autoconf/compile +348 -0
- data/ext/libarchive-3.6.2/build/autoconf/config.guess +1754 -0
- data/ext/libarchive-3.6.2/build/autoconf/config.rpath +696 -0
- data/ext/libarchive-3.6.2/build/autoconf/config.sub +1890 -0
- data/ext/libarchive-3.6.2/build/autoconf/depcomp +791 -0
- data/ext/libarchive-3.6.2/build/autoconf/iconv.m4 +271 -0
- data/ext/libarchive-3.6.2/build/autoconf/install-sh +541 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/build/autoconf/la_uid_t.m4 +0 -0
- data/ext/libarchive-3.6.2/build/autoconf/lib-ld.m4 +109 -0
- data/ext/libarchive-3.6.2/build/autoconf/lib-link.m4 +777 -0
- data/ext/libarchive-3.6.2/build/autoconf/lib-prefix.m4 +224 -0
- data/ext/libarchive-3.6.2/build/autoconf/ltmain.sh +11251 -0
- data/ext/libarchive-3.6.2/build/autoconf/m4_ax_compile_check_sizeof.m4 +115 -0
- data/ext/libarchive-3.6.2/build/autoconf/missing +215 -0
- data/ext/libarchive-3.6.2/build/autoconf/test-driver +153 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/build/pkgconfig/libarchive.pc.in +4 -1
- data/ext/libarchive-3.6.2/config.h.in +1504 -0
- data/ext/libarchive-3.6.2/configure +25558 -0
- data/ext/libarchive-3.6.2/libarchive/archive.h +1212 -0
- data/ext/libarchive-3.6.2/libarchive/archive_acl.c +2097 -0
- data/ext/libarchive-3.6.2/libarchive/archive_acl_private.h +83 -0
- data/ext/libarchive-3.6.2/libarchive/archive_blake2.h +197 -0
- data/ext/libarchive-3.6.2/libarchive/archive_blake2_impl.h +161 -0
- data/ext/libarchive-3.6.2/libarchive/archive_blake2s_ref.c +369 -0
- data/ext/libarchive-3.6.2/libarchive/archive_blake2sp_ref.c +361 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_check_magic.c +63 -22
- data/ext/libarchive-3.6.2/libarchive/archive_cmdline.c +227 -0
- data/ext/libarchive-3.6.2/libarchive/archive_cmdline_private.h +47 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_crc32.h +17 -0
- data/ext/libarchive-3.6.2/libarchive/archive_cryptor.c +534 -0
- data/ext/libarchive-3.6.2/libarchive/archive_cryptor_private.h +188 -0
- data/ext/libarchive-3.6.2/libarchive/archive_digest.c +1505 -0
- data/ext/libarchive-3.6.2/libarchive/archive_digest_private.h +416 -0
- data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_darwin.c +559 -0
- data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_freebsd.c +712 -0
- data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_linux.c +760 -0
- data/ext/libarchive-3.6.2/libarchive/archive_disk_acl_sunos.c +824 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_endian.h +48 -15
- data/ext/libarchive-3.6.2/libarchive/archive_entry.c +2149 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry.h +305 -106
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_copy_bhfi.c +5 -4
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_copy_stat.c +9 -3
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_link_resolver.c +104 -62
- data/ext/libarchive-3.6.2/libarchive/archive_entry_locale.h +92 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_private.h +65 -49
- data/ext/libarchive-3.6.2/libarchive/archive_entry_sparse.c +156 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_stat.c +6 -6
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_strmode.c +1 -1
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_entry_xattr.c +4 -6
- data/ext/libarchive-3.6.2/libarchive/archive_getdate.c +1165 -0
- data/ext/libarchive-3.6.2/libarchive/archive_getdate.h +39 -0
- data/ext/libarchive-3.6.2/libarchive/archive_hmac.c +334 -0
- data/ext/libarchive-3.6.2/libarchive/archive_hmac_private.h +117 -0
- data/ext/libarchive-3.6.2/libarchive/archive_match.c +1875 -0
- data/ext/libarchive-3.6.2/libarchive/archive_openssl_evp_private.h +53 -0
- data/ext/libarchive-3.6.2/libarchive/archive_openssl_hmac_private.h +54 -0
- data/ext/libarchive-3.6.2/libarchive/archive_options.c +218 -0
- data/ext/libarchive-3.6.2/libarchive/archive_options_private.h +51 -0
- data/ext/libarchive-3.6.2/libarchive/archive_pack_dev.c +337 -0
- data/ext/libarchive-3.6.2/libarchive/archive_pack_dev.h +49 -0
- data/ext/libarchive-3.6.2/libarchive/archive_pathmatch.c +463 -0
- data/ext/libarchive-3.6.2/libarchive/archive_pathmatch.h +52 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_platform.h +77 -9
- data/ext/libarchive-3.6.2/libarchive/archive_platform_acl.h +55 -0
- data/ext/libarchive-3.6.2/libarchive/archive_platform_xattr.h +47 -0
- data/ext/libarchive-3.6.2/libarchive/archive_ppmd7.c +1168 -0
- data/ext/libarchive-3.6.2/libarchive/archive_ppmd7_private.h +119 -0
- data/ext/libarchive-3.6.2/libarchive/archive_ppmd8.c +1287 -0
- data/ext/libarchive-3.6.2/libarchive/archive_ppmd8_private.h +148 -0
- data/ext/libarchive-3.6.2/libarchive/archive_ppmd_private.h +151 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_private.h +74 -18
- data/ext/libarchive-3.6.2/libarchive/archive_random.c +272 -0
- data/ext/libarchive-3.6.2/libarchive/archive_random_private.h +36 -0
- data/ext/libarchive-3.6.2/libarchive/archive_rb.c +709 -0
- data/ext/libarchive-3.6.2/libarchive/archive_rb.h +113 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read.c +1756 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_add_passphrase.c +190 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_append_filter.c +204 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_data_into_fd.c +64 -18
- data/ext/libarchive-3.6.2/libarchive/archive_read_disk_entry_from_file.c +1086 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_disk_posix.c +2732 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_disk_private.h +40 -4
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_disk_set_standard_lookup.c +21 -11
- data/ext/libarchive-3.6.2/libarchive/archive_read_disk_windows.c +2479 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_extract.c +60 -0
- data/ext/{libarchive-2.8.4/libarchive/archive_read_extract.c → libarchive-3.6.2/libarchive/archive_read_extract2.c} +34 -61
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_open_fd.c +70 -49
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_open_file.c +38 -23
- data/ext/libarchive-3.6.2/libarchive/archive_read_open_filename.c +586 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_open_memory.c +58 -28
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_private.h +127 -59
- data/ext/libarchive-3.6.2/libarchive/archive_read_set_format.c +117 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_set_options.c +133 -0
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_all.c → libarchive-3.6.2/libarchive/archive_read_support_filter_all.c} +35 -10
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_by_code.c +83 -0
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_bzip2.c → libarchive-3.6.2/libarchive/archive_read_support_filter_bzip2.c} +38 -26
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_compress.c → libarchive-3.6.2/libarchive/archive_read_support_filter_compress.c} +52 -44
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_grzip.c +112 -0
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_gzip.c → libarchive-3.6.2/libarchive/archive_read_support_filter_gzip.c} +108 -37
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_lrzip.c +122 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_lz4.c +742 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_lzop.c +499 -0
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_none.c → libarchive-3.6.2/libarchive/archive_read_support_filter_none.c} +15 -3
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_program.c → libarchive-3.6.2/libarchive/archive_read_support_filter_program.c} +114 -77
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_rpm.c → libarchive-3.6.2/libarchive/archive_read_support_filter_rpm.c} +31 -31
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_uu.c → libarchive-3.6.2/libarchive/archive_read_support_filter_uu.c} +141 -85
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_compression_xz.c → libarchive-3.6.2/libarchive/archive_read_support_filter_xz.c} +369 -284
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_filter_zstd.c +297 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_7zip.c +3900 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_all.c +89 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_ar.c +126 -72
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_by_code.c +92 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_cab.c +3228 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_cpio.c +1104 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_empty.c +14 -11
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_iso9660.c +990 -541
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_lha.c +2916 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_mtree.c +2150 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_rar.c +3797 -0
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_rar5.c +4251 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_raw.c +38 -31
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_tar.c +1157 -629
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_warc.c +848 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_read_support_format_xar.c +439 -258
- data/ext/libarchive-3.6.2/libarchive/archive_read_support_format_zip.c +4270 -0
- data/ext/libarchive-3.6.2/libarchive/archive_string.c +4240 -0
- data/ext/libarchive-3.6.2/libarchive/archive_string.h +243 -0
- data/ext/libarchive-3.6.2/libarchive/archive_string_composition.h +2292 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_string_sprintf.c +44 -16
- data/ext/libarchive-3.6.2/libarchive/archive_util.c +655 -0
- data/ext/libarchive-3.6.2/libarchive/archive_version_details.c +151 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_virtual.c +85 -16
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_windows.c +214 -541
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_windows.h +74 -106
- data/ext/libarchive-3.6.2/libarchive/archive_write.c +828 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter.c +72 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_b64encode.c +304 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_by_name.c +77 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_bzip2.c +401 -0
- data/ext/{libarchive-2.8.4/libarchive/archive_write_set_compression_compress.c → libarchive-3.6.2/libarchive/archive_write_add_filter_compress.c} +86 -131
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_grzip.c +135 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_gzip.c +442 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_lrzip.c +197 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_lz4.c +700 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_lzop.c +478 -0
- data/ext/{libarchive-2.8.4/libarchive/archive_read_support_format_all.c → libarchive-3.6.2/libarchive/archive_write_add_filter_none.c} +11 -11
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_program.c +391 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_uuencode.c +295 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_xz.c +545 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_add_filter_zstd.c +418 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_disk_posix.c +4711 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_disk_private.h +9 -2
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_disk_set_standard_lookup.c +30 -29
- data/ext/libarchive-3.6.2/libarchive/archive_write_disk_windows.c +2842 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_fd.c +15 -10
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_file.c +15 -9
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_filename.c +128 -20
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_open_memory.c +7 -18
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_private.h +72 -29
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format.c +56 -3
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_7zip.c +2322 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_ar.c +54 -34
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_by_name.c +20 -2
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio.c +11 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio_binary.c +610 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio_newc.c +457 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_cpio_odc.c +500 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_filter_by_ext.c +142 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_gnutar.c +755 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_iso9660.c +8165 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_mtree.c +2217 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_pax.c +1049 -387
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_private.h +42 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_raw.c +125 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_shar.c +62 -47
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/archive_write_set_format_ustar.c +279 -108
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_v7tar.c +638 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_warc.c +453 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_xar.c +3259 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_format_zip.c +1704 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_options.c +130 -0
- data/ext/libarchive-3.6.2/libarchive/archive_write_set_passphrase.c +95 -0
- data/ext/libarchive-3.6.2/libarchive/archive_xxhash.h +48 -0
- data/ext/libarchive-3.6.2/libarchive/config_freebsd.h +271 -0
- data/ext/{libarchive-2.8.4 → libarchive-3.6.2}/libarchive/filter_fork.h +10 -5
- data/ext/{libarchive-2.8.4/libarchive/filter_fork.c → libarchive-3.6.2/libarchive/filter_fork_posix.c} +98 -19
- data/ext/libarchive-3.6.2/libarchive/filter_fork_windows.c +236 -0
- data/ext/libarchive-3.6.2/libarchive/xxhash.c +525 -0
- data/ext/libarchive-static-makefile +144 -80
- data/ext/libarchive-static-wrapper-makefile +1 -1
- data/ext/zlib-1.2.13/Makefile.in +404 -0
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/adler32.c +51 -34
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/compress.c +27 -21
- data/ext/zlib-1.2.13/configure +922 -0
- data/ext/zlib-1.2.13/crc32.c +1125 -0
- data/ext/zlib-1.2.13/crc32.h +9446 -0
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/deflate.c +842 -459
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/deflate.h +37 -33
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/gzclose.c +0 -0
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/gzguts.h +103 -16
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/gzlib.c +155 -53
- data/ext/zlib-1.2.13/gzread.c +650 -0
- data/ext/zlib-1.2.13/gzwrite.c +677 -0
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/infback.c +24 -12
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/inffast.c +49 -66
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/inffast.h +0 -0
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/inffixed.h +3 -3
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/inflate.c +209 -94
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/inflate.h +9 -5
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/inftrees.c +24 -50
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/inftrees.h +1 -1
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/trees.c +135 -198
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/trees.h +0 -0
- data/ext/zlib-1.2.13/uncompr.c +93 -0
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/zconf.h +182 -63
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/zlib.h +617 -295
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/zutil.c +50 -41
- data/ext/{zlib-1.2.5 → zlib-1.2.13}/zutil.h +83 -82
- metadata +241 -133
- data/ext/libarchive-0.1.1/libarchive.c +0 -1762
- data/ext/libarchive-2.8.4/Makefile.in +0 -7076
- data/ext/libarchive-2.8.4/build/autoconf/compile +0 -143
- data/ext/libarchive-2.8.4/build/autoconf/config.guess +0 -1502
- data/ext/libarchive-2.8.4/build/autoconf/config.sub +0 -1708
- data/ext/libarchive-2.8.4/build/autoconf/depcomp +0 -630
- data/ext/libarchive-2.8.4/build/autoconf/install-sh +0 -291
- data/ext/libarchive-2.8.4/build/autoconf/ltmain.sh +0 -8406
- data/ext/libarchive-2.8.4/build/autoconf/missing +0 -376
- data/ext/libarchive-2.8.4/config.h.in +0 -772
- data/ext/libarchive-2.8.4/configure +0 -17916
- data/ext/libarchive-2.8.4/libarchive/archive.h +0 -741
- data/ext/libarchive-2.8.4/libarchive/archive_entry.c +0 -2202
- data/ext/libarchive-2.8.4/libarchive/archive_hash.h +0 -281
- data/ext/libarchive-2.8.4/libarchive/archive_read.c +0 -1249
- data/ext/libarchive-2.8.4/libarchive/archive_read_disk.c +0 -198
- data/ext/libarchive-2.8.4/libarchive/archive_read_disk_entry_from_file.c +0 -570
- data/ext/libarchive-2.8.4/libarchive/archive_read_open_filename.c +0 -272
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_cpio.c +0 -777
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_mtree.c +0 -1304
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_zip.c +0 -903
- data/ext/libarchive-2.8.4/libarchive/archive_string.c +0 -453
- data/ext/libarchive-2.8.4/libarchive/archive_string.h +0 -148
- data/ext/libarchive-2.8.4/libarchive/archive_util.c +0 -391
- data/ext/libarchive-2.8.4/libarchive/archive_write.c +0 -466
- data/ext/libarchive-2.8.4/libarchive/archive_write_disk.c +0 -2628
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_bzip2.c +0 -408
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_gzip.c +0 -477
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_none.c +0 -257
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_program.c +0 -347
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_xz.c +0 -438
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_cpio.c +0 -344
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_cpio_newc.c +0 -295
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_mtree.c +0 -1050
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_zip.c +0 -667
- data/ext/libarchive-2.8.4/libarchive/config_freebsd.h +0 -154
- data/ext/libarchive-2.8.4/libarchive/filter_fork_windows.c +0 -113
- data/ext/zlib-1.2.5/Makefile.in +0 -257
- data/ext/zlib-1.2.5/configure +0 -596
- data/ext/zlib-1.2.5/crc32.c +0 -442
- data/ext/zlib-1.2.5/crc32.h +0 -441
- data/ext/zlib-1.2.5/example.c +0 -565
- data/ext/zlib-1.2.5/gzread.c +0 -653
- data/ext/zlib-1.2.5/gzwrite.c +0 -531
- data/ext/zlib-1.2.5/minigzip.c +0 -440
- data/ext/zlib-1.2.5/uncompr.c +0 -59
|
@@ -0,0 +1,2732 @@
|
|
|
1
|
+
/*-
|
|
2
|
+
* Copyright (c) 2003-2009 Tim Kientzle
|
|
3
|
+
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
|
|
4
|
+
* All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Redistribution and use in source and binary forms, with or without
|
|
7
|
+
* modification, are permitted provided that the following conditions
|
|
8
|
+
* are met:
|
|
9
|
+
* 1. Redistributions of source code must retain the above copyright
|
|
10
|
+
* notice, this list of conditions and the following disclaimer
|
|
11
|
+
* in this position and unchanged.
|
|
12
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
|
13
|
+
* notice, this list of conditions and the following disclaimer in the
|
|
14
|
+
* documentation and/or other materials provided with the distribution.
|
|
15
|
+
*
|
|
16
|
+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
|
17
|
+
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
18
|
+
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
19
|
+
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
20
|
+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
21
|
+
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
22
|
+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
23
|
+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
24
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
25
|
+
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/* This is the tree-walking code for POSIX systems. */
|
|
29
|
+
#if !defined(_WIN32) || defined(__CYGWIN__)
|
|
30
|
+
|
|
31
|
+
#include "archive_platform.h"
|
|
32
|
+
__FBSDID("$FreeBSD$");
|
|
33
|
+
|
|
34
|
+
#ifdef HAVE_SYS_PARAM_H
|
|
35
|
+
#include <sys/param.h>
|
|
36
|
+
#endif
|
|
37
|
+
#ifdef HAVE_SYS_STAT_H
|
|
38
|
+
#include <sys/stat.h>
|
|
39
|
+
#endif
|
|
40
|
+
#ifdef HAVE_SYS_STATFS_H
|
|
41
|
+
#include <sys/statfs.h>
|
|
42
|
+
#endif
|
|
43
|
+
#ifdef HAVE_SYS_STATVFS_H
|
|
44
|
+
#include <sys/statvfs.h>
|
|
45
|
+
#endif
|
|
46
|
+
#ifdef HAVE_SYS_TIME_H
|
|
47
|
+
#include <sys/time.h>
|
|
48
|
+
#endif
|
|
49
|
+
#ifdef HAVE_LINUX_MAGIC_H
|
|
50
|
+
#include <linux/magic.h>
|
|
51
|
+
#endif
|
|
52
|
+
#ifdef HAVE_LINUX_FS_H
|
|
53
|
+
#include <linux/fs.h>
|
|
54
|
+
#elif HAVE_SYS_MOUNT_H
|
|
55
|
+
#include <sys/mount.h>
|
|
56
|
+
#endif
|
|
57
|
+
/*
|
|
58
|
+
* Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
|
|
59
|
+
* As the include guards don't agree, the order of include is important.
|
|
60
|
+
*/
|
|
61
|
+
#ifdef HAVE_LINUX_EXT2_FS_H
|
|
62
|
+
#include <linux/ext2_fs.h> /* for Linux file flags */
|
|
63
|
+
#endif
|
|
64
|
+
#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
|
|
65
|
+
#include <ext2fs/ext2_fs.h> /* Linux file flags, broken on Cygwin */
|
|
66
|
+
#endif
|
|
67
|
+
#ifdef HAVE_DIRECT_H
|
|
68
|
+
#include <direct.h>
|
|
69
|
+
#endif
|
|
70
|
+
#ifdef HAVE_DIRENT_H
|
|
71
|
+
#include <dirent.h>
|
|
72
|
+
#endif
|
|
73
|
+
#ifdef HAVE_ERRNO_H
|
|
74
|
+
#include <errno.h>
|
|
75
|
+
#endif
|
|
76
|
+
#ifdef HAVE_FCNTL_H
|
|
77
|
+
#include <fcntl.h>
|
|
78
|
+
#endif
|
|
79
|
+
#ifdef HAVE_LIMITS_H
|
|
80
|
+
#include <limits.h>
|
|
81
|
+
#endif
|
|
82
|
+
#ifdef HAVE_STDLIB_H
|
|
83
|
+
#include <stdlib.h>
|
|
84
|
+
#endif
|
|
85
|
+
#ifdef HAVE_STRING_H
|
|
86
|
+
#include <string.h>
|
|
87
|
+
#endif
|
|
88
|
+
#ifdef HAVE_UNISTD_H
|
|
89
|
+
#include <unistd.h>
|
|
90
|
+
#endif
|
|
91
|
+
#ifdef HAVE_SYS_IOCTL_H
|
|
92
|
+
#include <sys/ioctl.h>
|
|
93
|
+
#endif
|
|
94
|
+
|
|
95
|
+
#include "archive.h"
|
|
96
|
+
#include "archive_string.h"
|
|
97
|
+
#include "archive_entry.h"
|
|
98
|
+
#include "archive_private.h"
|
|
99
|
+
#include "archive_read_disk_private.h"
|
|
100
|
+
|
|
101
|
+
#ifndef HAVE_FCHDIR
|
|
102
|
+
#error fchdir function required.
|
|
103
|
+
#endif
|
|
104
|
+
#ifndef O_BINARY
|
|
105
|
+
#define O_BINARY 0
|
|
106
|
+
#endif
|
|
107
|
+
#ifndef O_CLOEXEC
|
|
108
|
+
#define O_CLOEXEC 0
|
|
109
|
+
#endif
|
|
110
|
+
|
|
111
|
+
#if defined(__hpux) && !defined(HAVE_DIRFD)
|
|
112
|
+
#define dirfd(x) ((x)->__dd_fd)
|
|
113
|
+
#define HAVE_DIRFD
|
|
114
|
+
#endif
|
|
115
|
+
|
|
116
|
+
/*-
|
|
117
|
+
* This is a new directory-walking system that addresses a number
|
|
118
|
+
* of problems I've had with fts(3). In particular, it has no
|
|
119
|
+
* pathname-length limits (other than the size of 'int'), handles
|
|
120
|
+
* deep logical traversals, uses considerably less memory, and has
|
|
121
|
+
* an opaque interface (easier to modify in the future).
|
|
122
|
+
*
|
|
123
|
+
* Internally, it keeps a single list of "tree_entry" items that
|
|
124
|
+
* represent filesystem objects that require further attention.
|
|
125
|
+
* Non-directories are not kept in memory: they are pulled from
|
|
126
|
+
* readdir(), returned to the client, then freed as soon as possible.
|
|
127
|
+
* Any directory entry to be traversed gets pushed onto the stack.
|
|
128
|
+
*
|
|
129
|
+
* There is surprisingly little information that needs to be kept for
|
|
130
|
+
* each item on the stack. Just the name, depth (represented here as the
|
|
131
|
+
* string length of the parent directory's pathname), and some markers
|
|
132
|
+
* indicating how to get back to the parent (via chdir("..") for a
|
|
133
|
+
* regular dir or via fchdir(2) for a symlink).
|
|
134
|
+
*/
|
|
135
|
+
/*
|
|
136
|
+
* TODO:
|
|
137
|
+
* 1) Loop checking.
|
|
138
|
+
* 3) Arbitrary logical traversals by closing/reopening intermediate fds.
|
|
139
|
+
*/
|
|
140
|
+
|
|
141
|
+
struct restore_time {
|
|
142
|
+
const char *name;
|
|
143
|
+
time_t mtime;
|
|
144
|
+
long mtime_nsec;
|
|
145
|
+
time_t atime;
|
|
146
|
+
long atime_nsec;
|
|
147
|
+
mode_t filetype;
|
|
148
|
+
int noatime;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
struct tree_entry {
|
|
152
|
+
int depth;
|
|
153
|
+
struct tree_entry *next;
|
|
154
|
+
struct tree_entry *parent;
|
|
155
|
+
struct archive_string name;
|
|
156
|
+
size_t dirname_length;
|
|
157
|
+
int64_t dev;
|
|
158
|
+
int64_t ino;
|
|
159
|
+
int flags;
|
|
160
|
+
int filesystem_id;
|
|
161
|
+
/* How to return back to the parent of a symlink. */
|
|
162
|
+
int symlink_parent_fd;
|
|
163
|
+
/* How to restore time of a directory. */
|
|
164
|
+
struct restore_time restore_time;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
struct filesystem {
|
|
168
|
+
int64_t dev;
|
|
169
|
+
int synthetic;
|
|
170
|
+
int remote;
|
|
171
|
+
int noatime;
|
|
172
|
+
#if defined(USE_READDIR_R)
|
|
173
|
+
size_t name_max;
|
|
174
|
+
#endif
|
|
175
|
+
long incr_xfer_size;
|
|
176
|
+
long max_xfer_size;
|
|
177
|
+
long min_xfer_size;
|
|
178
|
+
long xfer_align;
|
|
179
|
+
|
|
180
|
+
/*
|
|
181
|
+
* Buffer used for reading file contents.
|
|
182
|
+
*/
|
|
183
|
+
/* Exactly allocated memory pointer. */
|
|
184
|
+
unsigned char *allocation_ptr;
|
|
185
|
+
/* Pointer adjusted to the filesystem alignment . */
|
|
186
|
+
unsigned char *buff;
|
|
187
|
+
size_t buff_size;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
/* Definitions for tree_entry.flags bitmap. */
|
|
191
|
+
#define isDir 1 /* This entry is a regular directory. */
|
|
192
|
+
#define isDirLink 2 /* This entry is a symbolic link to a directory. */
|
|
193
|
+
#define needsFirstVisit 4 /* This is an initial entry. */
|
|
194
|
+
#define needsDescent 8 /* This entry needs to be previsited. */
|
|
195
|
+
#define needsOpen 16 /* This is a directory that needs to be opened. */
|
|
196
|
+
#define needsAscent 32 /* This entry needs to be postvisited. */
|
|
197
|
+
|
|
198
|
+
/*
|
|
199
|
+
* Local data for this package.
|
|
200
|
+
*/
|
|
201
|
+
struct tree {
|
|
202
|
+
struct tree_entry *stack;
|
|
203
|
+
struct tree_entry *current;
|
|
204
|
+
DIR *d;
|
|
205
|
+
#define INVALID_DIR_HANDLE NULL
|
|
206
|
+
struct dirent *de;
|
|
207
|
+
#if defined(USE_READDIR_R)
|
|
208
|
+
struct dirent *dirent;
|
|
209
|
+
size_t dirent_allocated;
|
|
210
|
+
#endif
|
|
211
|
+
int flags;
|
|
212
|
+
int visit_type;
|
|
213
|
+
/* Error code from last failed operation. */
|
|
214
|
+
int tree_errno;
|
|
215
|
+
|
|
216
|
+
/* Dynamically-sized buffer for holding path */
|
|
217
|
+
struct archive_string path;
|
|
218
|
+
|
|
219
|
+
/* Last path element */
|
|
220
|
+
const char *basename;
|
|
221
|
+
/* Leading dir length */
|
|
222
|
+
size_t dirname_length;
|
|
223
|
+
|
|
224
|
+
int depth;
|
|
225
|
+
int openCount;
|
|
226
|
+
int maxOpenCount;
|
|
227
|
+
int initial_dir_fd;
|
|
228
|
+
int working_dir_fd;
|
|
229
|
+
|
|
230
|
+
struct stat lst;
|
|
231
|
+
struct stat st;
|
|
232
|
+
int descend;
|
|
233
|
+
int nlink;
|
|
234
|
+
/* How to restore time of a file. */
|
|
235
|
+
struct restore_time restore_time;
|
|
236
|
+
|
|
237
|
+
struct entry_sparse {
|
|
238
|
+
int64_t length;
|
|
239
|
+
int64_t offset;
|
|
240
|
+
} *sparse_list, *current_sparse;
|
|
241
|
+
int sparse_count;
|
|
242
|
+
int sparse_list_size;
|
|
243
|
+
|
|
244
|
+
char initial_symlink_mode;
|
|
245
|
+
char symlink_mode;
|
|
246
|
+
struct filesystem *current_filesystem;
|
|
247
|
+
struct filesystem *filesystem_table;
|
|
248
|
+
int initial_filesystem_id;
|
|
249
|
+
int current_filesystem_id;
|
|
250
|
+
int max_filesystem_id;
|
|
251
|
+
int allocated_filesystem;
|
|
252
|
+
|
|
253
|
+
int entry_fd;
|
|
254
|
+
int entry_eof;
|
|
255
|
+
int64_t entry_remaining_bytes;
|
|
256
|
+
int64_t entry_total;
|
|
257
|
+
unsigned char *entry_buff;
|
|
258
|
+
size_t entry_buff_size;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
/* Definitions for tree.flags bitmap. */
|
|
262
|
+
#define hasStat 16 /* The st entry is valid. */
|
|
263
|
+
#define hasLstat 32 /* The lst entry is valid. */
|
|
264
|
+
#define onWorkingDir 64 /* We are on the working dir where we are
|
|
265
|
+
* reading directory entry at this time. */
|
|
266
|
+
#define needsRestoreTimes 128
|
|
267
|
+
#define onInitialDir 256 /* We are on the initial dir. */
|
|
268
|
+
|
|
269
|
+
static int
|
|
270
|
+
tree_dir_next_posix(struct tree *t);
|
|
271
|
+
|
|
272
|
+
#ifdef HAVE_DIRENT_D_NAMLEN
|
|
273
|
+
/* BSD extension; avoids need for a strlen() call. */
|
|
274
|
+
#define D_NAMELEN(dp) (dp)->d_namlen
|
|
275
|
+
#else
|
|
276
|
+
#define D_NAMELEN(dp) (strlen((dp)->d_name))
|
|
277
|
+
#endif
|
|
278
|
+
|
|
279
|
+
/* Initiate/terminate a tree traversal. */
|
|
280
|
+
static struct tree *tree_open(const char *, int, int);
|
|
281
|
+
static struct tree *tree_reopen(struct tree *, const char *, int);
|
|
282
|
+
static void tree_close(struct tree *);
|
|
283
|
+
static void tree_free(struct tree *);
|
|
284
|
+
static void tree_push(struct tree *, const char *, int, int64_t, int64_t,
|
|
285
|
+
struct restore_time *);
|
|
286
|
+
static int tree_enter_initial_dir(struct tree *);
|
|
287
|
+
static int tree_enter_working_dir(struct tree *);
|
|
288
|
+
static int tree_current_dir_fd(struct tree *);
|
|
289
|
+
|
|
290
|
+
/*
|
|
291
|
+
* tree_next() returns Zero if there is no next entry, non-zero if
|
|
292
|
+
* there is. Note that directories are visited three times.
|
|
293
|
+
* Directories are always visited first as part of enumerating their
|
|
294
|
+
* parent; that is a "regular" visit. If tree_descend() is invoked at
|
|
295
|
+
* that time, the directory is added to a work list and will
|
|
296
|
+
* subsequently be visited two more times: once just after descending
|
|
297
|
+
* into the directory ("postdescent") and again just after ascending
|
|
298
|
+
* back to the parent ("postascent").
|
|
299
|
+
*
|
|
300
|
+
* TREE_ERROR_DIR is returned if the descent failed (because the
|
|
301
|
+
* directory couldn't be opened, for instance). This is returned
|
|
302
|
+
* instead of TREE_POSTDESCENT/TREE_POSTASCENT. TREE_ERROR_DIR is not a
|
|
303
|
+
* fatal error, but it does imply that the relevant subtree won't be
|
|
304
|
+
* visited. TREE_ERROR_FATAL is returned for an error that left the
|
|
305
|
+
* traversal completely hosed. Right now, this is only returned for
|
|
306
|
+
* chdir() failures during ascent.
|
|
307
|
+
*/
|
|
308
|
+
#define TREE_REGULAR 1
|
|
309
|
+
#define TREE_POSTDESCENT 2
|
|
310
|
+
#define TREE_POSTASCENT 3
|
|
311
|
+
#define TREE_ERROR_DIR -1
|
|
312
|
+
#define TREE_ERROR_FATAL -2
|
|
313
|
+
|
|
314
|
+
static int tree_next(struct tree *);
|
|
315
|
+
|
|
316
|
+
/*
|
|
317
|
+
* Return information about the current entry.
|
|
318
|
+
*/
|
|
319
|
+
|
|
320
|
+
/*
|
|
321
|
+
* The current full pathname, length of the full pathname, and a name
|
|
322
|
+
* that can be used to access the file. Because tree does use chdir
|
|
323
|
+
* extensively, the access path is almost never the same as the full
|
|
324
|
+
* current path.
|
|
325
|
+
*
|
|
326
|
+
* TODO: On platforms that support it, use openat()-style operations
|
|
327
|
+
* to eliminate the chdir() operations entirely while still supporting
|
|
328
|
+
* arbitrarily deep traversals. This makes access_path troublesome to
|
|
329
|
+
* support, of course, which means we'll need a rich enough interface
|
|
330
|
+
* that clients can function without it. (In particular, we'll need
|
|
331
|
+
* tree_current_open() that returns an open file descriptor.)
|
|
332
|
+
*
|
|
333
|
+
*/
|
|
334
|
+
static const char *tree_current_path(struct tree *);
|
|
335
|
+
static const char *tree_current_access_path(struct tree *);
|
|
336
|
+
|
|
337
|
+
/*
|
|
338
|
+
* Request the lstat() or stat() data for the current path. Since the
|
|
339
|
+
* tree package needs to do some of this anyway, and caches the
|
|
340
|
+
* results, you should take advantage of it here if you need it rather
|
|
341
|
+
* than make a redundant stat() or lstat() call of your own.
|
|
342
|
+
*/
|
|
343
|
+
static const struct stat *tree_current_stat(struct tree *);
|
|
344
|
+
static const struct stat *tree_current_lstat(struct tree *);
|
|
345
|
+
static int tree_current_is_symblic_link_target(struct tree *);
|
|
346
|
+
|
|
347
|
+
/* The following functions use tricks to avoid a certain number of
|
|
348
|
+
* stat()/lstat() calls. */
|
|
349
|
+
/* "is_physical_dir" is equivalent to S_ISDIR(tree_current_lstat()->st_mode) */
|
|
350
|
+
static int tree_current_is_physical_dir(struct tree *);
|
|
351
|
+
/* "is_dir" is equivalent to S_ISDIR(tree_current_stat()->st_mode) */
|
|
352
|
+
static int tree_current_is_dir(struct tree *);
|
|
353
|
+
static int update_current_filesystem(struct archive_read_disk *a,
|
|
354
|
+
int64_t dev);
|
|
355
|
+
static int setup_current_filesystem(struct archive_read_disk *);
|
|
356
|
+
static int tree_target_is_same_as_parent(struct tree *, const struct stat *);
|
|
357
|
+
|
|
358
|
+
static int _archive_read_disk_open(struct archive *, const char *);
|
|
359
|
+
static int _archive_read_free(struct archive *);
|
|
360
|
+
static int _archive_read_close(struct archive *);
|
|
361
|
+
static int _archive_read_data_block(struct archive *,
|
|
362
|
+
const void **, size_t *, int64_t *);
|
|
363
|
+
static int _archive_read_next_header(struct archive *,
|
|
364
|
+
struct archive_entry **);
|
|
365
|
+
static int _archive_read_next_header2(struct archive *,
|
|
366
|
+
struct archive_entry *);
|
|
367
|
+
static const char *trivial_lookup_gname(void *, int64_t gid);
|
|
368
|
+
static const char *trivial_lookup_uname(void *, int64_t uid);
|
|
369
|
+
static int setup_sparse(struct archive_read_disk *, struct archive_entry *);
|
|
370
|
+
static int close_and_restore_time(int fd, struct tree *,
|
|
371
|
+
struct restore_time *);
|
|
372
|
+
static int open_on_current_dir(struct tree *, const char *, int);
|
|
373
|
+
static int tree_dup(int);
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
static const struct archive_vtable
|
|
377
|
+
archive_read_disk_vtable = {
|
|
378
|
+
.archive_free = _archive_read_free,
|
|
379
|
+
.archive_close = _archive_read_close,
|
|
380
|
+
.archive_read_data_block = _archive_read_data_block,
|
|
381
|
+
.archive_read_next_header = _archive_read_next_header,
|
|
382
|
+
.archive_read_next_header2 = _archive_read_next_header2,
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
const char *
|
|
386
|
+
archive_read_disk_gname(struct archive *_a, la_int64_t gid)
|
|
387
|
+
{
|
|
388
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
389
|
+
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
|
390
|
+
ARCHIVE_STATE_ANY, "archive_read_disk_gname"))
|
|
391
|
+
return (NULL);
|
|
392
|
+
if (a->lookup_gname == NULL)
|
|
393
|
+
return (NULL);
|
|
394
|
+
return ((*a->lookup_gname)(a->lookup_gname_data, gid));
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const char *
|
|
398
|
+
archive_read_disk_uname(struct archive *_a, la_int64_t uid)
|
|
399
|
+
{
|
|
400
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
401
|
+
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
|
402
|
+
ARCHIVE_STATE_ANY, "archive_read_disk_uname"))
|
|
403
|
+
return (NULL);
|
|
404
|
+
if (a->lookup_uname == NULL)
|
|
405
|
+
return (NULL);
|
|
406
|
+
return ((*a->lookup_uname)(a->lookup_uname_data, uid));
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
int
|
|
410
|
+
archive_read_disk_set_gname_lookup(struct archive *_a,
|
|
411
|
+
void *private_data,
|
|
412
|
+
const char * (*lookup_gname)(void *private, la_int64_t gid),
|
|
413
|
+
void (*cleanup_gname)(void *private))
|
|
414
|
+
{
|
|
415
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
416
|
+
archive_check_magic(&a->archive, ARCHIVE_READ_DISK_MAGIC,
|
|
417
|
+
ARCHIVE_STATE_ANY, "archive_read_disk_set_gname_lookup");
|
|
418
|
+
|
|
419
|
+
if (a->cleanup_gname != NULL && a->lookup_gname_data != NULL)
|
|
420
|
+
(a->cleanup_gname)(a->lookup_gname_data);
|
|
421
|
+
|
|
422
|
+
a->lookup_gname = lookup_gname;
|
|
423
|
+
a->cleanup_gname = cleanup_gname;
|
|
424
|
+
a->lookup_gname_data = private_data;
|
|
425
|
+
return (ARCHIVE_OK);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
int
|
|
429
|
+
archive_read_disk_set_uname_lookup(struct archive *_a,
|
|
430
|
+
void *private_data,
|
|
431
|
+
const char * (*lookup_uname)(void *private, la_int64_t uid),
|
|
432
|
+
void (*cleanup_uname)(void *private))
|
|
433
|
+
{
|
|
434
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
435
|
+
archive_check_magic(&a->archive, ARCHIVE_READ_DISK_MAGIC,
|
|
436
|
+
ARCHIVE_STATE_ANY, "archive_read_disk_set_uname_lookup");
|
|
437
|
+
|
|
438
|
+
if (a->cleanup_uname != NULL && a->lookup_uname_data != NULL)
|
|
439
|
+
(a->cleanup_uname)(a->lookup_uname_data);
|
|
440
|
+
|
|
441
|
+
a->lookup_uname = lookup_uname;
|
|
442
|
+
a->cleanup_uname = cleanup_uname;
|
|
443
|
+
a->lookup_uname_data = private_data;
|
|
444
|
+
return (ARCHIVE_OK);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/*
|
|
448
|
+
* Create a new archive_read_disk object and initialize it with global state.
|
|
449
|
+
*/
|
|
450
|
+
struct archive *
|
|
451
|
+
archive_read_disk_new(void)
|
|
452
|
+
{
|
|
453
|
+
struct archive_read_disk *a;
|
|
454
|
+
|
|
455
|
+
a = (struct archive_read_disk *)calloc(1, sizeof(*a));
|
|
456
|
+
if (a == NULL)
|
|
457
|
+
return (NULL);
|
|
458
|
+
a->archive.magic = ARCHIVE_READ_DISK_MAGIC;
|
|
459
|
+
a->archive.state = ARCHIVE_STATE_NEW;
|
|
460
|
+
a->archive.vtable = &archive_read_disk_vtable;
|
|
461
|
+
a->entry = archive_entry_new2(&a->archive);
|
|
462
|
+
a->lookup_uname = trivial_lookup_uname;
|
|
463
|
+
a->lookup_gname = trivial_lookup_gname;
|
|
464
|
+
a->flags = ARCHIVE_READDISK_MAC_COPYFILE;
|
|
465
|
+
a->open_on_current_dir = open_on_current_dir;
|
|
466
|
+
a->tree_current_dir_fd = tree_current_dir_fd;
|
|
467
|
+
a->tree_enter_working_dir = tree_enter_working_dir;
|
|
468
|
+
return (&a->archive);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
static int
|
|
472
|
+
_archive_read_free(struct archive *_a)
|
|
473
|
+
{
|
|
474
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
475
|
+
int r;
|
|
476
|
+
|
|
477
|
+
if (_a == NULL)
|
|
478
|
+
return (ARCHIVE_OK);
|
|
479
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
|
480
|
+
ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_free");
|
|
481
|
+
|
|
482
|
+
if (a->archive.state != ARCHIVE_STATE_CLOSED)
|
|
483
|
+
r = _archive_read_close(&a->archive);
|
|
484
|
+
else
|
|
485
|
+
r = ARCHIVE_OK;
|
|
486
|
+
|
|
487
|
+
tree_free(a->tree);
|
|
488
|
+
if (a->cleanup_gname != NULL && a->lookup_gname_data != NULL)
|
|
489
|
+
(a->cleanup_gname)(a->lookup_gname_data);
|
|
490
|
+
if (a->cleanup_uname != NULL && a->lookup_uname_data != NULL)
|
|
491
|
+
(a->cleanup_uname)(a->lookup_uname_data);
|
|
492
|
+
archive_string_free(&a->archive.error_string);
|
|
493
|
+
archive_entry_free(a->entry);
|
|
494
|
+
a->archive.magic = 0;
|
|
495
|
+
__archive_clean(&a->archive);
|
|
496
|
+
free(a);
|
|
497
|
+
return (r);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
static int
|
|
501
|
+
_archive_read_close(struct archive *_a)
|
|
502
|
+
{
|
|
503
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
504
|
+
|
|
505
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
|
506
|
+
ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_close");
|
|
507
|
+
|
|
508
|
+
if (a->archive.state != ARCHIVE_STATE_FATAL)
|
|
509
|
+
a->archive.state = ARCHIVE_STATE_CLOSED;
|
|
510
|
+
|
|
511
|
+
tree_close(a->tree);
|
|
512
|
+
|
|
513
|
+
return (ARCHIVE_OK);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
static void
|
|
517
|
+
setup_symlink_mode(struct archive_read_disk *a, char symlink_mode,
|
|
518
|
+
int follow_symlinks)
|
|
519
|
+
{
|
|
520
|
+
a->symlink_mode = symlink_mode;
|
|
521
|
+
a->follow_symlinks = follow_symlinks;
|
|
522
|
+
if (a->tree != NULL) {
|
|
523
|
+
a->tree->initial_symlink_mode = a->symlink_mode;
|
|
524
|
+
a->tree->symlink_mode = a->symlink_mode;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
int
|
|
529
|
+
archive_read_disk_set_symlink_logical(struct archive *_a)
|
|
530
|
+
{
|
|
531
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
532
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
|
533
|
+
ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_logical");
|
|
534
|
+
setup_symlink_mode(a, 'L', 1);
|
|
535
|
+
return (ARCHIVE_OK);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
int
|
|
539
|
+
archive_read_disk_set_symlink_physical(struct archive *_a)
|
|
540
|
+
{
|
|
541
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
542
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
|
543
|
+
ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_physical");
|
|
544
|
+
setup_symlink_mode(a, 'P', 0);
|
|
545
|
+
return (ARCHIVE_OK);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
int
|
|
549
|
+
archive_read_disk_set_symlink_hybrid(struct archive *_a)
|
|
550
|
+
{
|
|
551
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
552
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
|
553
|
+
ARCHIVE_STATE_ANY, "archive_read_disk_set_symlink_hybrid");
|
|
554
|
+
setup_symlink_mode(a, 'H', 1);/* Follow symlinks initially. */
|
|
555
|
+
return (ARCHIVE_OK);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
int
|
|
559
|
+
archive_read_disk_set_atime_restored(struct archive *_a)
|
|
560
|
+
{
|
|
561
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
562
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
|
563
|
+
ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime");
|
|
564
|
+
#ifdef HAVE_UTIMES
|
|
565
|
+
a->flags |= ARCHIVE_READDISK_RESTORE_ATIME;
|
|
566
|
+
if (a->tree != NULL)
|
|
567
|
+
a->tree->flags |= needsRestoreTimes;
|
|
568
|
+
return (ARCHIVE_OK);
|
|
569
|
+
#else
|
|
570
|
+
/* Display warning and unset flag */
|
|
571
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
|
572
|
+
"Cannot restore access time on this system");
|
|
573
|
+
a->flags &= ~ARCHIVE_READDISK_RESTORE_ATIME;
|
|
574
|
+
return (ARCHIVE_WARN);
|
|
575
|
+
#endif
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
int
|
|
579
|
+
archive_read_disk_set_behavior(struct archive *_a, int flags)
|
|
580
|
+
{
|
|
581
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
582
|
+
int r = ARCHIVE_OK;
|
|
583
|
+
|
|
584
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
|
585
|
+
ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump");
|
|
586
|
+
|
|
587
|
+
a->flags = flags;
|
|
588
|
+
|
|
589
|
+
if (flags & ARCHIVE_READDISK_RESTORE_ATIME)
|
|
590
|
+
r = archive_read_disk_set_atime_restored(_a);
|
|
591
|
+
else {
|
|
592
|
+
if (a->tree != NULL)
|
|
593
|
+
a->tree->flags &= ~needsRestoreTimes;
|
|
594
|
+
}
|
|
595
|
+
return (r);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/*
|
|
599
|
+
* Trivial implementations of gname/uname lookup functions.
|
|
600
|
+
* These are normally overridden by the client, but these stub
|
|
601
|
+
* versions ensure that we always have something that works.
|
|
602
|
+
*/
|
|
603
|
+
static const char *
|
|
604
|
+
trivial_lookup_gname(void *private_data, int64_t gid)
|
|
605
|
+
{
|
|
606
|
+
(void)private_data; /* UNUSED */
|
|
607
|
+
(void)gid; /* UNUSED */
|
|
608
|
+
return (NULL);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
static const char *
|
|
612
|
+
trivial_lookup_uname(void *private_data, int64_t uid)
|
|
613
|
+
{
|
|
614
|
+
(void)private_data; /* UNUSED */
|
|
615
|
+
(void)uid; /* UNUSED */
|
|
616
|
+
return (NULL);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/*
|
|
620
|
+
* Allocate memory for the reading buffer adjusted to the filesystem
|
|
621
|
+
* alignment.
|
|
622
|
+
*/
|
|
623
|
+
static int
|
|
624
|
+
setup_suitable_read_buffer(struct archive_read_disk *a)
|
|
625
|
+
{
|
|
626
|
+
struct tree *t = a->tree;
|
|
627
|
+
struct filesystem *cf = t->current_filesystem;
|
|
628
|
+
size_t asize;
|
|
629
|
+
size_t s;
|
|
630
|
+
|
|
631
|
+
if (cf->allocation_ptr == NULL) {
|
|
632
|
+
/* If we couldn't get a filesystem alignment,
|
|
633
|
+
* we use 4096 as default value but we won't use
|
|
634
|
+
* O_DIRECT to open() and openat() operations. */
|
|
635
|
+
long xfer_align = (cf->xfer_align == -1)?4096:cf->xfer_align;
|
|
636
|
+
|
|
637
|
+
if (cf->max_xfer_size != -1)
|
|
638
|
+
asize = cf->max_xfer_size + xfer_align;
|
|
639
|
+
else {
|
|
640
|
+
long incr = cf->incr_xfer_size;
|
|
641
|
+
/* Some platform does not set a proper value to
|
|
642
|
+
* incr_xfer_size.*/
|
|
643
|
+
if (incr < 0)
|
|
644
|
+
incr = cf->min_xfer_size;
|
|
645
|
+
if (cf->min_xfer_size < 0) {
|
|
646
|
+
incr = xfer_align;
|
|
647
|
+
asize = xfer_align;
|
|
648
|
+
} else
|
|
649
|
+
asize = cf->min_xfer_size;
|
|
650
|
+
|
|
651
|
+
/* Increase a buffer size up to 64K bytes in
|
|
652
|
+
* a proper increment size. */
|
|
653
|
+
while (asize < 1024*64)
|
|
654
|
+
asize += incr;
|
|
655
|
+
/* Take a margin to adjust to the filesystem
|
|
656
|
+
* alignment. */
|
|
657
|
+
asize += xfer_align;
|
|
658
|
+
}
|
|
659
|
+
cf->allocation_ptr = malloc(asize);
|
|
660
|
+
if (cf->allocation_ptr == NULL) {
|
|
661
|
+
archive_set_error(&a->archive, ENOMEM,
|
|
662
|
+
"Couldn't allocate memory");
|
|
663
|
+
a->archive.state = ARCHIVE_STATE_FATAL;
|
|
664
|
+
return (ARCHIVE_FATAL);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/*
|
|
668
|
+
* Calculate proper address for the filesystem.
|
|
669
|
+
*/
|
|
670
|
+
s = (uintptr_t)cf->allocation_ptr;
|
|
671
|
+
s %= xfer_align;
|
|
672
|
+
if (s > 0)
|
|
673
|
+
s = xfer_align - s;
|
|
674
|
+
|
|
675
|
+
/*
|
|
676
|
+
* Set a read buffer pointer in the proper alignment of
|
|
677
|
+
* the current filesystem.
|
|
678
|
+
*/
|
|
679
|
+
cf->buff = cf->allocation_ptr + s;
|
|
680
|
+
cf->buff_size = asize - xfer_align;
|
|
681
|
+
}
|
|
682
|
+
return (ARCHIVE_OK);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
static int
|
|
686
|
+
_archive_read_data_block(struct archive *_a, const void **buff,
|
|
687
|
+
size_t *size, int64_t *offset)
|
|
688
|
+
{
|
|
689
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
690
|
+
struct tree *t = a->tree;
|
|
691
|
+
int r;
|
|
692
|
+
ssize_t bytes;
|
|
693
|
+
int64_t sparse_bytes;
|
|
694
|
+
size_t buffbytes;
|
|
695
|
+
int empty_sparse_region = 0;
|
|
696
|
+
|
|
697
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
|
|
698
|
+
"archive_read_data_block");
|
|
699
|
+
|
|
700
|
+
if (t->entry_eof || t->entry_remaining_bytes <= 0) {
|
|
701
|
+
r = ARCHIVE_EOF;
|
|
702
|
+
goto abort_read_data;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
/*
|
|
706
|
+
* Open the current file.
|
|
707
|
+
*/
|
|
708
|
+
if (t->entry_fd < 0) {
|
|
709
|
+
int flags = O_RDONLY | O_BINARY | O_CLOEXEC;
|
|
710
|
+
|
|
711
|
+
/*
|
|
712
|
+
* Eliminate or reduce cache effects if we can.
|
|
713
|
+
*
|
|
714
|
+
* Carefully consider this to be enabled.
|
|
715
|
+
*/
|
|
716
|
+
#if defined(O_DIRECT) && 0/* Disabled for now */
|
|
717
|
+
if (t->current_filesystem->xfer_align != -1 &&
|
|
718
|
+
t->nlink == 1)
|
|
719
|
+
flags |= O_DIRECT;
|
|
720
|
+
#endif
|
|
721
|
+
#if defined(O_NOATIME)
|
|
722
|
+
/*
|
|
723
|
+
* Linux has O_NOATIME flag; use it if we need.
|
|
724
|
+
*/
|
|
725
|
+
if ((t->flags & needsRestoreTimes) != 0 &&
|
|
726
|
+
t->restore_time.noatime == 0)
|
|
727
|
+
flags |= O_NOATIME;
|
|
728
|
+
#endif
|
|
729
|
+
t->entry_fd = open_on_current_dir(t,
|
|
730
|
+
tree_current_access_path(t), flags);
|
|
731
|
+
__archive_ensure_cloexec_flag(t->entry_fd);
|
|
732
|
+
#if defined(O_NOATIME)
|
|
733
|
+
/*
|
|
734
|
+
* When we did open the file with O_NOATIME flag,
|
|
735
|
+
* if successful, set 1 to t->restore_time.noatime
|
|
736
|
+
* not to restore an atime of the file later.
|
|
737
|
+
* if failed by EPERM, retry it without O_NOATIME flag.
|
|
738
|
+
*/
|
|
739
|
+
if (flags & O_NOATIME) {
|
|
740
|
+
if (t->entry_fd >= 0)
|
|
741
|
+
t->restore_time.noatime = 1;
|
|
742
|
+
else if (errno == EPERM)
|
|
743
|
+
flags &= ~O_NOATIME;
|
|
744
|
+
}
|
|
745
|
+
#endif
|
|
746
|
+
if (t->entry_fd < 0) {
|
|
747
|
+
archive_set_error(&a->archive, errno,
|
|
748
|
+
"Couldn't open %s", tree_current_path(t));
|
|
749
|
+
r = ARCHIVE_FAILED;
|
|
750
|
+
tree_enter_initial_dir(t);
|
|
751
|
+
goto abort_read_data;
|
|
752
|
+
}
|
|
753
|
+
tree_enter_initial_dir(t);
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/*
|
|
757
|
+
* Allocate read buffer if not allocated.
|
|
758
|
+
*/
|
|
759
|
+
if (t->current_filesystem->allocation_ptr == NULL) {
|
|
760
|
+
r = setup_suitable_read_buffer(a);
|
|
761
|
+
if (r != ARCHIVE_OK) {
|
|
762
|
+
a->archive.state = ARCHIVE_STATE_FATAL;
|
|
763
|
+
goto abort_read_data;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
t->entry_buff = t->current_filesystem->buff;
|
|
767
|
+
t->entry_buff_size = t->current_filesystem->buff_size;
|
|
768
|
+
|
|
769
|
+
buffbytes = t->entry_buff_size;
|
|
770
|
+
if ((int64_t)buffbytes > t->current_sparse->length)
|
|
771
|
+
buffbytes = t->current_sparse->length;
|
|
772
|
+
|
|
773
|
+
if (t->current_sparse->length == 0)
|
|
774
|
+
empty_sparse_region = 1;
|
|
775
|
+
|
|
776
|
+
/*
|
|
777
|
+
* Skip hole.
|
|
778
|
+
* TODO: Should we consider t->current_filesystem->xfer_align?
|
|
779
|
+
*/
|
|
780
|
+
if (t->current_sparse->offset > t->entry_total) {
|
|
781
|
+
if (lseek(t->entry_fd,
|
|
782
|
+
(off_t)t->current_sparse->offset, SEEK_SET) < 0) {
|
|
783
|
+
archive_set_error(&a->archive, errno, "Seek error");
|
|
784
|
+
r = ARCHIVE_FATAL;
|
|
785
|
+
a->archive.state = ARCHIVE_STATE_FATAL;
|
|
786
|
+
goto abort_read_data;
|
|
787
|
+
}
|
|
788
|
+
sparse_bytes = t->current_sparse->offset - t->entry_total;
|
|
789
|
+
t->entry_remaining_bytes -= sparse_bytes;
|
|
790
|
+
t->entry_total += sparse_bytes;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
/*
|
|
794
|
+
* Read file contents.
|
|
795
|
+
*/
|
|
796
|
+
if (buffbytes > 0) {
|
|
797
|
+
bytes = read(t->entry_fd, t->entry_buff, buffbytes);
|
|
798
|
+
if (bytes < 0) {
|
|
799
|
+
archive_set_error(&a->archive, errno, "Read error");
|
|
800
|
+
r = ARCHIVE_FATAL;
|
|
801
|
+
a->archive.state = ARCHIVE_STATE_FATAL;
|
|
802
|
+
goto abort_read_data;
|
|
803
|
+
}
|
|
804
|
+
} else
|
|
805
|
+
bytes = 0;
|
|
806
|
+
/*
|
|
807
|
+
* Return an EOF unless we've read a leading empty sparse region, which
|
|
808
|
+
* is used to represent fully-sparse files.
|
|
809
|
+
*/
|
|
810
|
+
if (bytes == 0 && !empty_sparse_region) {
|
|
811
|
+
/* Get EOF */
|
|
812
|
+
t->entry_eof = 1;
|
|
813
|
+
r = ARCHIVE_EOF;
|
|
814
|
+
goto abort_read_data;
|
|
815
|
+
}
|
|
816
|
+
*buff = t->entry_buff;
|
|
817
|
+
*size = bytes;
|
|
818
|
+
*offset = t->entry_total;
|
|
819
|
+
t->entry_total += bytes;
|
|
820
|
+
t->entry_remaining_bytes -= bytes;
|
|
821
|
+
if (t->entry_remaining_bytes == 0) {
|
|
822
|
+
/* Close the current file descriptor */
|
|
823
|
+
close_and_restore_time(t->entry_fd, t, &t->restore_time);
|
|
824
|
+
t->entry_fd = -1;
|
|
825
|
+
t->entry_eof = 1;
|
|
826
|
+
}
|
|
827
|
+
t->current_sparse->offset += bytes;
|
|
828
|
+
t->current_sparse->length -= bytes;
|
|
829
|
+
if (t->current_sparse->length == 0 && !t->entry_eof)
|
|
830
|
+
t->current_sparse++;
|
|
831
|
+
return (ARCHIVE_OK);
|
|
832
|
+
|
|
833
|
+
abort_read_data:
|
|
834
|
+
*buff = NULL;
|
|
835
|
+
*size = 0;
|
|
836
|
+
*offset = t->entry_total;
|
|
837
|
+
if (t->entry_fd >= 0) {
|
|
838
|
+
/* Close the current file descriptor */
|
|
839
|
+
close_and_restore_time(t->entry_fd, t, &t->restore_time);
|
|
840
|
+
t->entry_fd = -1;
|
|
841
|
+
}
|
|
842
|
+
return (r);
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
static int
|
|
846
|
+
next_entry(struct archive_read_disk *a, struct tree *t,
|
|
847
|
+
struct archive_entry *entry)
|
|
848
|
+
{
|
|
849
|
+
const struct stat *st; /* info to use for this entry */
|
|
850
|
+
const struct stat *lst;/* lstat() information */
|
|
851
|
+
const char *name;
|
|
852
|
+
int delayed, delayed_errno, descend, r;
|
|
853
|
+
struct archive_string delayed_str;
|
|
854
|
+
|
|
855
|
+
delayed = ARCHIVE_OK;
|
|
856
|
+
delayed_errno = 0;
|
|
857
|
+
archive_string_init(&delayed_str);
|
|
858
|
+
|
|
859
|
+
st = NULL;
|
|
860
|
+
lst = NULL;
|
|
861
|
+
t->descend = 0;
|
|
862
|
+
do {
|
|
863
|
+
switch (tree_next(t)) {
|
|
864
|
+
case TREE_ERROR_FATAL:
|
|
865
|
+
archive_set_error(&a->archive, t->tree_errno,
|
|
866
|
+
"%s: Unable to continue traversing directory tree",
|
|
867
|
+
tree_current_path(t));
|
|
868
|
+
a->archive.state = ARCHIVE_STATE_FATAL;
|
|
869
|
+
tree_enter_initial_dir(t);
|
|
870
|
+
return (ARCHIVE_FATAL);
|
|
871
|
+
case TREE_ERROR_DIR:
|
|
872
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
|
873
|
+
"%s: Couldn't visit directory",
|
|
874
|
+
tree_current_path(t));
|
|
875
|
+
tree_enter_initial_dir(t);
|
|
876
|
+
return (ARCHIVE_FAILED);
|
|
877
|
+
case 0:
|
|
878
|
+
tree_enter_initial_dir(t);
|
|
879
|
+
return (ARCHIVE_EOF);
|
|
880
|
+
case TREE_POSTDESCENT:
|
|
881
|
+
case TREE_POSTASCENT:
|
|
882
|
+
break;
|
|
883
|
+
case TREE_REGULAR:
|
|
884
|
+
lst = tree_current_lstat(t);
|
|
885
|
+
if (lst == NULL) {
|
|
886
|
+
if (errno == ENOENT && t->depth > 0) {
|
|
887
|
+
delayed = ARCHIVE_WARN;
|
|
888
|
+
delayed_errno = errno;
|
|
889
|
+
if (delayed_str.length == 0) {
|
|
890
|
+
archive_string_sprintf(&delayed_str,
|
|
891
|
+
"%s", tree_current_path(t));
|
|
892
|
+
} else {
|
|
893
|
+
archive_string_sprintf(&delayed_str,
|
|
894
|
+
" %s", tree_current_path(t));
|
|
895
|
+
}
|
|
896
|
+
} else {
|
|
897
|
+
archive_set_error(&a->archive, errno,
|
|
898
|
+
"%s: Cannot stat",
|
|
899
|
+
tree_current_path(t));
|
|
900
|
+
tree_enter_initial_dir(t);
|
|
901
|
+
return (ARCHIVE_FAILED);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
break;
|
|
905
|
+
}
|
|
906
|
+
} while (lst == NULL);
|
|
907
|
+
|
|
908
|
+
#ifdef __APPLE__
|
|
909
|
+
if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) {
|
|
910
|
+
/* If we're using copyfile(), ignore "._XXX" files. */
|
|
911
|
+
const char *bname = strrchr(tree_current_path(t), '/');
|
|
912
|
+
if (bname == NULL)
|
|
913
|
+
bname = tree_current_path(t);
|
|
914
|
+
else
|
|
915
|
+
++bname;
|
|
916
|
+
if (bname[0] == '.' && bname[1] == '_')
|
|
917
|
+
return (ARCHIVE_RETRY);
|
|
918
|
+
}
|
|
919
|
+
#endif
|
|
920
|
+
|
|
921
|
+
archive_entry_copy_pathname(entry, tree_current_path(t));
|
|
922
|
+
/*
|
|
923
|
+
* Perform path matching.
|
|
924
|
+
*/
|
|
925
|
+
if (a->matching) {
|
|
926
|
+
r = archive_match_path_excluded(a->matching, entry);
|
|
927
|
+
if (r < 0) {
|
|
928
|
+
archive_set_error(&(a->archive), errno,
|
|
929
|
+
"Failed : %s", archive_error_string(a->matching));
|
|
930
|
+
return (r);
|
|
931
|
+
}
|
|
932
|
+
if (r) {
|
|
933
|
+
if (a->excluded_cb_func)
|
|
934
|
+
a->excluded_cb_func(&(a->archive),
|
|
935
|
+
a->excluded_cb_data, entry);
|
|
936
|
+
return (ARCHIVE_RETRY);
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
/*
|
|
941
|
+
* Distinguish 'L'/'P'/'H' symlink following.
|
|
942
|
+
*/
|
|
943
|
+
switch(t->symlink_mode) {
|
|
944
|
+
case 'H':
|
|
945
|
+
/* 'H': After the first item, rest like 'P'. */
|
|
946
|
+
t->symlink_mode = 'P';
|
|
947
|
+
/* 'H': First item (from command line) like 'L'. */
|
|
948
|
+
/* FALLTHROUGH */
|
|
949
|
+
case 'L':
|
|
950
|
+
/* 'L': Do descend through a symlink to dir. */
|
|
951
|
+
descend = tree_current_is_dir(t);
|
|
952
|
+
/* 'L': Follow symlinks to files. */
|
|
953
|
+
a->symlink_mode = 'L';
|
|
954
|
+
a->follow_symlinks = 1;
|
|
955
|
+
/* 'L': Archive symlinks as targets, if we can. */
|
|
956
|
+
st = tree_current_stat(t);
|
|
957
|
+
if (st != NULL && !tree_target_is_same_as_parent(t, st))
|
|
958
|
+
break;
|
|
959
|
+
/* If stat fails, we have a broken symlink;
|
|
960
|
+
* in that case, don't follow the link. */
|
|
961
|
+
/* FALLTHROUGH */
|
|
962
|
+
default:
|
|
963
|
+
/* 'P': Don't descend through a symlink to dir. */
|
|
964
|
+
descend = tree_current_is_physical_dir(t);
|
|
965
|
+
/* 'P': Don't follow symlinks to files. */
|
|
966
|
+
a->symlink_mode = 'P';
|
|
967
|
+
a->follow_symlinks = 0;
|
|
968
|
+
/* 'P': Archive symlinks as symlinks. */
|
|
969
|
+
st = lst;
|
|
970
|
+
break;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
if (update_current_filesystem(a, st->st_dev) != ARCHIVE_OK) {
|
|
974
|
+
a->archive.state = ARCHIVE_STATE_FATAL;
|
|
975
|
+
tree_enter_initial_dir(t);
|
|
976
|
+
return (ARCHIVE_FATAL);
|
|
977
|
+
}
|
|
978
|
+
if (t->initial_filesystem_id == -1)
|
|
979
|
+
t->initial_filesystem_id = t->current_filesystem_id;
|
|
980
|
+
if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) {
|
|
981
|
+
if (t->initial_filesystem_id != t->current_filesystem_id)
|
|
982
|
+
descend = 0;
|
|
983
|
+
}
|
|
984
|
+
t->descend = descend;
|
|
985
|
+
|
|
986
|
+
/*
|
|
987
|
+
* Honor nodump flag.
|
|
988
|
+
* If the file is marked with nodump flag, do not return this entry.
|
|
989
|
+
*/
|
|
990
|
+
if (a->flags & ARCHIVE_READDISK_HONOR_NODUMP) {
|
|
991
|
+
#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
|
|
992
|
+
if (st->st_flags & UF_NODUMP)
|
|
993
|
+
return (ARCHIVE_RETRY);
|
|
994
|
+
#elif (defined(FS_IOC_GETFLAGS) && defined(FS_NODUMP_FL) && \
|
|
995
|
+
defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
|
|
996
|
+
(defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) && \
|
|
997
|
+
defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
|
|
998
|
+
if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) {
|
|
999
|
+
int stflags;
|
|
1000
|
+
|
|
1001
|
+
t->entry_fd = open_on_current_dir(t,
|
|
1002
|
+
tree_current_access_path(t),
|
|
1003
|
+
O_RDONLY | O_NONBLOCK | O_CLOEXEC);
|
|
1004
|
+
__archive_ensure_cloexec_flag(t->entry_fd);
|
|
1005
|
+
if (t->entry_fd >= 0) {
|
|
1006
|
+
r = ioctl(t->entry_fd,
|
|
1007
|
+
#ifdef FS_IOC_GETFLAGS
|
|
1008
|
+
FS_IOC_GETFLAGS,
|
|
1009
|
+
#else
|
|
1010
|
+
EXT2_IOC_GETFLAGS,
|
|
1011
|
+
#endif
|
|
1012
|
+
&stflags);
|
|
1013
|
+
#ifdef FS_NODUMP_FL
|
|
1014
|
+
if (r == 0 && (stflags & FS_NODUMP_FL) != 0)
|
|
1015
|
+
#else
|
|
1016
|
+
if (r == 0 && (stflags & EXT2_NODUMP_FL) != 0)
|
|
1017
|
+
#endif
|
|
1018
|
+
return (ARCHIVE_RETRY);
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
#endif
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
archive_entry_copy_stat(entry, st);
|
|
1025
|
+
|
|
1026
|
+
/* Save the times to be restored. This must be in before
|
|
1027
|
+
* calling archive_read_disk_descend() or any chance of it,
|
|
1028
|
+
* especially, invoking a callback. */
|
|
1029
|
+
t->restore_time.mtime = archive_entry_mtime(entry);
|
|
1030
|
+
t->restore_time.mtime_nsec = archive_entry_mtime_nsec(entry);
|
|
1031
|
+
t->restore_time.atime = archive_entry_atime(entry);
|
|
1032
|
+
t->restore_time.atime_nsec = archive_entry_atime_nsec(entry);
|
|
1033
|
+
t->restore_time.filetype = archive_entry_filetype(entry);
|
|
1034
|
+
t->restore_time.noatime = t->current_filesystem->noatime;
|
|
1035
|
+
|
|
1036
|
+
/*
|
|
1037
|
+
* Perform time matching.
|
|
1038
|
+
*/
|
|
1039
|
+
if (a->matching) {
|
|
1040
|
+
r = archive_match_time_excluded(a->matching, entry);
|
|
1041
|
+
if (r < 0) {
|
|
1042
|
+
archive_set_error(&(a->archive), errno,
|
|
1043
|
+
"Failed : %s", archive_error_string(a->matching));
|
|
1044
|
+
return (r);
|
|
1045
|
+
}
|
|
1046
|
+
if (r) {
|
|
1047
|
+
if (a->excluded_cb_func)
|
|
1048
|
+
a->excluded_cb_func(&(a->archive),
|
|
1049
|
+
a->excluded_cb_data, entry);
|
|
1050
|
+
return (ARCHIVE_RETRY);
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
/* Lookup uname/gname */
|
|
1055
|
+
name = archive_read_disk_uname(&(a->archive), archive_entry_uid(entry));
|
|
1056
|
+
if (name != NULL)
|
|
1057
|
+
archive_entry_copy_uname(entry, name);
|
|
1058
|
+
name = archive_read_disk_gname(&(a->archive), archive_entry_gid(entry));
|
|
1059
|
+
if (name != NULL)
|
|
1060
|
+
archive_entry_copy_gname(entry, name);
|
|
1061
|
+
|
|
1062
|
+
/*
|
|
1063
|
+
* Perform owner matching.
|
|
1064
|
+
*/
|
|
1065
|
+
if (a->matching) {
|
|
1066
|
+
r = archive_match_owner_excluded(a->matching, entry);
|
|
1067
|
+
if (r < 0) {
|
|
1068
|
+
archive_set_error(&(a->archive), errno,
|
|
1069
|
+
"Failed : %s", archive_error_string(a->matching));
|
|
1070
|
+
return (r);
|
|
1071
|
+
}
|
|
1072
|
+
if (r) {
|
|
1073
|
+
if (a->excluded_cb_func)
|
|
1074
|
+
a->excluded_cb_func(&(a->archive),
|
|
1075
|
+
a->excluded_cb_data, entry);
|
|
1076
|
+
return (ARCHIVE_RETRY);
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
/*
|
|
1081
|
+
* Invoke a meta data filter callback.
|
|
1082
|
+
*/
|
|
1083
|
+
if (a->metadata_filter_func) {
|
|
1084
|
+
if (!a->metadata_filter_func(&(a->archive),
|
|
1085
|
+
a->metadata_filter_data, entry))
|
|
1086
|
+
return (ARCHIVE_RETRY);
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
/*
|
|
1090
|
+
* Populate the archive_entry with metadata from the disk.
|
|
1091
|
+
*/
|
|
1092
|
+
archive_entry_copy_sourcepath(entry, tree_current_access_path(t));
|
|
1093
|
+
r = archive_read_disk_entry_from_file(&(a->archive), entry,
|
|
1094
|
+
t->entry_fd, st);
|
|
1095
|
+
|
|
1096
|
+
if (r == ARCHIVE_OK) {
|
|
1097
|
+
r = delayed;
|
|
1098
|
+
if (r != ARCHIVE_OK) {
|
|
1099
|
+
archive_string_sprintf(&delayed_str, ": %s",
|
|
1100
|
+
"File removed before we read it");
|
|
1101
|
+
archive_set_error(&(a->archive), delayed_errno,
|
|
1102
|
+
"%s", delayed_str.s);
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
archive_string_free(&delayed_str);
|
|
1106
|
+
|
|
1107
|
+
return (r);
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
static int
|
|
1111
|
+
_archive_read_next_header(struct archive *_a, struct archive_entry **entryp)
|
|
1112
|
+
{
|
|
1113
|
+
int ret;
|
|
1114
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
1115
|
+
*entryp = NULL;
|
|
1116
|
+
ret = _archive_read_next_header2(_a, a->entry);
|
|
1117
|
+
*entryp = a->entry;
|
|
1118
|
+
return ret;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
static int
|
|
1122
|
+
_archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
|
|
1123
|
+
{
|
|
1124
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
1125
|
+
struct tree *t;
|
|
1126
|
+
int r;
|
|
1127
|
+
|
|
1128
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
|
1129
|
+
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
|
|
1130
|
+
"archive_read_next_header2");
|
|
1131
|
+
|
|
1132
|
+
t = a->tree;
|
|
1133
|
+
if (t->entry_fd >= 0) {
|
|
1134
|
+
close_and_restore_time(t->entry_fd, t, &t->restore_time);
|
|
1135
|
+
t->entry_fd = -1;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
archive_entry_clear(entry);
|
|
1139
|
+
|
|
1140
|
+
for (;;) {
|
|
1141
|
+
r = next_entry(a, t, entry);
|
|
1142
|
+
if (t->entry_fd >= 0) {
|
|
1143
|
+
close(t->entry_fd);
|
|
1144
|
+
t->entry_fd = -1;
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
if (r == ARCHIVE_RETRY) {
|
|
1148
|
+
archive_entry_clear(entry);
|
|
1149
|
+
continue;
|
|
1150
|
+
}
|
|
1151
|
+
break;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
/* Return to the initial directory. */
|
|
1155
|
+
tree_enter_initial_dir(t);
|
|
1156
|
+
|
|
1157
|
+
/*
|
|
1158
|
+
* EOF and FATAL are persistent at this layer. By
|
|
1159
|
+
* modifying the state, we guarantee that future calls to
|
|
1160
|
+
* read a header or read data will fail.
|
|
1161
|
+
*/
|
|
1162
|
+
switch (r) {
|
|
1163
|
+
case ARCHIVE_EOF:
|
|
1164
|
+
a->archive.state = ARCHIVE_STATE_EOF;
|
|
1165
|
+
break;
|
|
1166
|
+
case ARCHIVE_OK:
|
|
1167
|
+
case ARCHIVE_WARN:
|
|
1168
|
+
/* Overwrite the sourcepath based on the initial directory. */
|
|
1169
|
+
archive_entry_copy_sourcepath(entry, tree_current_path(t));
|
|
1170
|
+
t->entry_total = 0;
|
|
1171
|
+
if (archive_entry_filetype(entry) == AE_IFREG) {
|
|
1172
|
+
t->nlink = archive_entry_nlink(entry);
|
|
1173
|
+
t->entry_remaining_bytes = archive_entry_size(entry);
|
|
1174
|
+
t->entry_eof = (t->entry_remaining_bytes == 0)? 1: 0;
|
|
1175
|
+
if (!t->entry_eof &&
|
|
1176
|
+
setup_sparse(a, entry) != ARCHIVE_OK)
|
|
1177
|
+
return (ARCHIVE_FATAL);
|
|
1178
|
+
} else {
|
|
1179
|
+
t->entry_remaining_bytes = 0;
|
|
1180
|
+
t->entry_eof = 1;
|
|
1181
|
+
}
|
|
1182
|
+
a->archive.state = ARCHIVE_STATE_DATA;
|
|
1183
|
+
break;
|
|
1184
|
+
case ARCHIVE_RETRY:
|
|
1185
|
+
break;
|
|
1186
|
+
case ARCHIVE_FATAL:
|
|
1187
|
+
a->archive.state = ARCHIVE_STATE_FATAL;
|
|
1188
|
+
break;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
__archive_reset_read_data(&a->archive);
|
|
1192
|
+
return (r);
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
static int
|
|
1196
|
+
setup_sparse(struct archive_read_disk *a, struct archive_entry *entry)
|
|
1197
|
+
{
|
|
1198
|
+
struct tree *t = a->tree;
|
|
1199
|
+
int64_t length, offset;
|
|
1200
|
+
int i;
|
|
1201
|
+
|
|
1202
|
+
t->sparse_count = archive_entry_sparse_reset(entry);
|
|
1203
|
+
if (t->sparse_count+1 > t->sparse_list_size) {
|
|
1204
|
+
free(t->sparse_list);
|
|
1205
|
+
t->sparse_list_size = t->sparse_count + 1;
|
|
1206
|
+
t->sparse_list = malloc(sizeof(t->sparse_list[0]) *
|
|
1207
|
+
t->sparse_list_size);
|
|
1208
|
+
if (t->sparse_list == NULL) {
|
|
1209
|
+
t->sparse_list_size = 0;
|
|
1210
|
+
archive_set_error(&a->archive, ENOMEM,
|
|
1211
|
+
"Can't allocate data");
|
|
1212
|
+
a->archive.state = ARCHIVE_STATE_FATAL;
|
|
1213
|
+
return (ARCHIVE_FATAL);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
for (i = 0; i < t->sparse_count; i++) {
|
|
1217
|
+
archive_entry_sparse_next(entry, &offset, &length);
|
|
1218
|
+
t->sparse_list[i].offset = offset;
|
|
1219
|
+
t->sparse_list[i].length = length;
|
|
1220
|
+
}
|
|
1221
|
+
if (i == 0) {
|
|
1222
|
+
t->sparse_list[i].offset = 0;
|
|
1223
|
+
t->sparse_list[i].length = archive_entry_size(entry);
|
|
1224
|
+
} else {
|
|
1225
|
+
t->sparse_list[i].offset = archive_entry_size(entry);
|
|
1226
|
+
t->sparse_list[i].length = 0;
|
|
1227
|
+
}
|
|
1228
|
+
t->current_sparse = t->sparse_list;
|
|
1229
|
+
|
|
1230
|
+
return (ARCHIVE_OK);
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
int
|
|
1234
|
+
archive_read_disk_set_matching(struct archive *_a, struct archive *_ma,
|
|
1235
|
+
void (*_excluded_func)(struct archive *, void *, struct archive_entry *),
|
|
1236
|
+
void *_client_data)
|
|
1237
|
+
{
|
|
1238
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
1239
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
|
1240
|
+
ARCHIVE_STATE_ANY, "archive_read_disk_set_matching");
|
|
1241
|
+
a->matching = _ma;
|
|
1242
|
+
a->excluded_cb_func = _excluded_func;
|
|
1243
|
+
a->excluded_cb_data = _client_data;
|
|
1244
|
+
return (ARCHIVE_OK);
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
int
|
|
1248
|
+
archive_read_disk_set_metadata_filter_callback(struct archive *_a,
|
|
1249
|
+
int (*_metadata_filter_func)(struct archive *, void *,
|
|
1250
|
+
struct archive_entry *), void *_client_data)
|
|
1251
|
+
{
|
|
1252
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
1253
|
+
|
|
1254
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY,
|
|
1255
|
+
"archive_read_disk_set_metadata_filter_callback");
|
|
1256
|
+
|
|
1257
|
+
a->metadata_filter_func = _metadata_filter_func;
|
|
1258
|
+
a->metadata_filter_data = _client_data;
|
|
1259
|
+
return (ARCHIVE_OK);
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
int
|
|
1263
|
+
archive_read_disk_can_descend(struct archive *_a)
|
|
1264
|
+
{
|
|
1265
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
1266
|
+
struct tree *t = a->tree;
|
|
1267
|
+
|
|
1268
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
|
1269
|
+
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
|
|
1270
|
+
"archive_read_disk_can_descend");
|
|
1271
|
+
|
|
1272
|
+
return (t->visit_type == TREE_REGULAR && t->descend);
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
/*
|
|
1276
|
+
* Called by the client to mark the directory just returned from
|
|
1277
|
+
* tree_next() as needing to be visited.
|
|
1278
|
+
*/
|
|
1279
|
+
int
|
|
1280
|
+
archive_read_disk_descend(struct archive *_a)
|
|
1281
|
+
{
|
|
1282
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
1283
|
+
struct tree *t = a->tree;
|
|
1284
|
+
|
|
1285
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
|
1286
|
+
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
|
|
1287
|
+
"archive_read_disk_descend");
|
|
1288
|
+
|
|
1289
|
+
if (!archive_read_disk_can_descend(_a))
|
|
1290
|
+
return (ARCHIVE_OK);
|
|
1291
|
+
|
|
1292
|
+
/*
|
|
1293
|
+
* We must not treat the initial specified path as a physical dir,
|
|
1294
|
+
* because if we do then we will try and ascend out of it by opening
|
|
1295
|
+
* ".." which is (a) wrong and (b) causes spurious permissions errors
|
|
1296
|
+
* if ".." is not readable by us. Instead, treat it as if it were a
|
|
1297
|
+
* symlink. (This uses an extra fd, but it can only happen once at the
|
|
1298
|
+
* top level of a traverse.) But we can't necessarily assume t->st is
|
|
1299
|
+
* valid here (though t->lst is), which complicates the logic a
|
|
1300
|
+
* little.
|
|
1301
|
+
*/
|
|
1302
|
+
if (tree_current_is_physical_dir(t)) {
|
|
1303
|
+
tree_push(t, t->basename, t->current_filesystem_id,
|
|
1304
|
+
t->lst.st_dev, t->lst.st_ino, &t->restore_time);
|
|
1305
|
+
if (t->stack->parent->parent != NULL)
|
|
1306
|
+
t->stack->flags |= isDir;
|
|
1307
|
+
else
|
|
1308
|
+
t->stack->flags |= isDirLink;
|
|
1309
|
+
} else if (tree_current_is_dir(t)) {
|
|
1310
|
+
tree_push(t, t->basename, t->current_filesystem_id,
|
|
1311
|
+
t->st.st_dev, t->st.st_ino, &t->restore_time);
|
|
1312
|
+
t->stack->flags |= isDirLink;
|
|
1313
|
+
}
|
|
1314
|
+
t->descend = 0;
|
|
1315
|
+
return (ARCHIVE_OK);
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
int
|
|
1319
|
+
archive_read_disk_open(struct archive *_a, const char *pathname)
|
|
1320
|
+
{
|
|
1321
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
1322
|
+
|
|
1323
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
|
1324
|
+
ARCHIVE_STATE_NEW | ARCHIVE_STATE_CLOSED,
|
|
1325
|
+
"archive_read_disk_open");
|
|
1326
|
+
archive_clear_error(&a->archive);
|
|
1327
|
+
|
|
1328
|
+
return (_archive_read_disk_open(_a, pathname));
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
int
|
|
1332
|
+
archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname)
|
|
1333
|
+
{
|
|
1334
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
1335
|
+
struct archive_string path;
|
|
1336
|
+
int ret;
|
|
1337
|
+
|
|
1338
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
|
1339
|
+
ARCHIVE_STATE_NEW | ARCHIVE_STATE_CLOSED,
|
|
1340
|
+
"archive_read_disk_open_w");
|
|
1341
|
+
archive_clear_error(&a->archive);
|
|
1342
|
+
|
|
1343
|
+
/* Make a char string from a wchar_t string. */
|
|
1344
|
+
archive_string_init(&path);
|
|
1345
|
+
if (archive_string_append_from_wcs(&path, pathname,
|
|
1346
|
+
wcslen(pathname)) != 0) {
|
|
1347
|
+
if (errno == ENOMEM)
|
|
1348
|
+
archive_set_error(&a->archive, ENOMEM,
|
|
1349
|
+
"Can't allocate memory");
|
|
1350
|
+
else
|
|
1351
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
|
1352
|
+
"Can't convert a path to a char string");
|
|
1353
|
+
a->archive.state = ARCHIVE_STATE_FATAL;
|
|
1354
|
+
ret = ARCHIVE_FATAL;
|
|
1355
|
+
} else
|
|
1356
|
+
ret = _archive_read_disk_open(_a, path.s);
|
|
1357
|
+
|
|
1358
|
+
archive_string_free(&path);
|
|
1359
|
+
return (ret);
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
static int
|
|
1363
|
+
_archive_read_disk_open(struct archive *_a, const char *pathname)
|
|
1364
|
+
{
|
|
1365
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
1366
|
+
|
|
1367
|
+
if (a->tree != NULL)
|
|
1368
|
+
a->tree = tree_reopen(a->tree, pathname,
|
|
1369
|
+
a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
|
|
1370
|
+
else
|
|
1371
|
+
a->tree = tree_open(pathname, a->symlink_mode,
|
|
1372
|
+
a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
|
|
1373
|
+
if (a->tree == NULL) {
|
|
1374
|
+
archive_set_error(&a->archive, ENOMEM,
|
|
1375
|
+
"Can't allocate tar data");
|
|
1376
|
+
a->archive.state = ARCHIVE_STATE_FATAL;
|
|
1377
|
+
return (ARCHIVE_FATAL);
|
|
1378
|
+
}
|
|
1379
|
+
a->archive.state = ARCHIVE_STATE_HEADER;
|
|
1380
|
+
|
|
1381
|
+
return (ARCHIVE_OK);
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
/*
|
|
1385
|
+
* Return a current filesystem ID which is index of the filesystem entry
|
|
1386
|
+
* you've visited through archive_read_disk.
|
|
1387
|
+
*/
|
|
1388
|
+
int
|
|
1389
|
+
archive_read_disk_current_filesystem(struct archive *_a)
|
|
1390
|
+
{
|
|
1391
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
1392
|
+
|
|
1393
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
|
|
1394
|
+
"archive_read_disk_current_filesystem");
|
|
1395
|
+
|
|
1396
|
+
return (a->tree->current_filesystem_id);
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
static int
|
|
1400
|
+
update_current_filesystem(struct archive_read_disk *a, int64_t dev)
|
|
1401
|
+
{
|
|
1402
|
+
struct tree *t = a->tree;
|
|
1403
|
+
int i, fid;
|
|
1404
|
+
|
|
1405
|
+
if (t->current_filesystem != NULL &&
|
|
1406
|
+
t->current_filesystem->dev == dev)
|
|
1407
|
+
return (ARCHIVE_OK);
|
|
1408
|
+
|
|
1409
|
+
for (i = 0; i < t->max_filesystem_id; i++) {
|
|
1410
|
+
if (t->filesystem_table[i].dev == dev) {
|
|
1411
|
+
/* There is the filesystem ID we've already generated. */
|
|
1412
|
+
t->current_filesystem_id = i;
|
|
1413
|
+
t->current_filesystem = &(t->filesystem_table[i]);
|
|
1414
|
+
return (ARCHIVE_OK);
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
/*
|
|
1419
|
+
* This is the new filesystem which we have to generate a new ID for.
|
|
1420
|
+
*/
|
|
1421
|
+
fid = t->max_filesystem_id++;
|
|
1422
|
+
if (t->max_filesystem_id > t->allocated_filesystem) {
|
|
1423
|
+
size_t s;
|
|
1424
|
+
void *p;
|
|
1425
|
+
|
|
1426
|
+
s = t->max_filesystem_id * 2;
|
|
1427
|
+
p = realloc(t->filesystem_table,
|
|
1428
|
+
s * sizeof(*t->filesystem_table));
|
|
1429
|
+
if (p == NULL) {
|
|
1430
|
+
archive_set_error(&a->archive, ENOMEM,
|
|
1431
|
+
"Can't allocate tar data");
|
|
1432
|
+
return (ARCHIVE_FATAL);
|
|
1433
|
+
}
|
|
1434
|
+
t->filesystem_table = (struct filesystem *)p;
|
|
1435
|
+
t->allocated_filesystem = s;
|
|
1436
|
+
}
|
|
1437
|
+
t->current_filesystem_id = fid;
|
|
1438
|
+
t->current_filesystem = &(t->filesystem_table[fid]);
|
|
1439
|
+
t->current_filesystem->dev = dev;
|
|
1440
|
+
t->current_filesystem->allocation_ptr = NULL;
|
|
1441
|
+
t->current_filesystem->buff = NULL;
|
|
1442
|
+
|
|
1443
|
+
/* Setup the current filesystem properties which depend on
|
|
1444
|
+
* platform specific. */
|
|
1445
|
+
return (setup_current_filesystem(a));
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
/*
|
|
1449
|
+
* Returns 1 if current filesystem is generated filesystem, 0 if it is not
|
|
1450
|
+
* or -1 if it is unknown.
|
|
1451
|
+
*/
|
|
1452
|
+
int
|
|
1453
|
+
archive_read_disk_current_filesystem_is_synthetic(struct archive *_a)
|
|
1454
|
+
{
|
|
1455
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
1456
|
+
|
|
1457
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
|
|
1458
|
+
"archive_read_disk_current_filesystem");
|
|
1459
|
+
|
|
1460
|
+
return (a->tree->current_filesystem->synthetic);
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
/*
|
|
1464
|
+
* Returns 1 if current filesystem is remote filesystem, 0 if it is not
|
|
1465
|
+
* or -1 if it is unknown.
|
|
1466
|
+
*/
|
|
1467
|
+
int
|
|
1468
|
+
archive_read_disk_current_filesystem_is_remote(struct archive *_a)
|
|
1469
|
+
{
|
|
1470
|
+
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
|
1471
|
+
|
|
1472
|
+
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
|
|
1473
|
+
"archive_read_disk_current_filesystem");
|
|
1474
|
+
|
|
1475
|
+
return (a->tree->current_filesystem->remote);
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
#if defined(_PC_REC_INCR_XFER_SIZE) && defined(_PC_REC_MAX_XFER_SIZE) &&\
|
|
1479
|
+
defined(_PC_REC_MIN_XFER_SIZE) && defined(_PC_REC_XFER_ALIGN)
|
|
1480
|
+
static int
|
|
1481
|
+
get_xfer_size(struct tree *t, int fd, const char *path)
|
|
1482
|
+
{
|
|
1483
|
+
t->current_filesystem->xfer_align = -1;
|
|
1484
|
+
errno = 0;
|
|
1485
|
+
if (fd >= 0) {
|
|
1486
|
+
t->current_filesystem->incr_xfer_size =
|
|
1487
|
+
fpathconf(fd, _PC_REC_INCR_XFER_SIZE);
|
|
1488
|
+
t->current_filesystem->max_xfer_size =
|
|
1489
|
+
fpathconf(fd, _PC_REC_MAX_XFER_SIZE);
|
|
1490
|
+
t->current_filesystem->min_xfer_size =
|
|
1491
|
+
fpathconf(fd, _PC_REC_MIN_XFER_SIZE);
|
|
1492
|
+
t->current_filesystem->xfer_align =
|
|
1493
|
+
fpathconf(fd, _PC_REC_XFER_ALIGN);
|
|
1494
|
+
} else if (path != NULL) {
|
|
1495
|
+
t->current_filesystem->incr_xfer_size =
|
|
1496
|
+
pathconf(path, _PC_REC_INCR_XFER_SIZE);
|
|
1497
|
+
t->current_filesystem->max_xfer_size =
|
|
1498
|
+
pathconf(path, _PC_REC_MAX_XFER_SIZE);
|
|
1499
|
+
t->current_filesystem->min_xfer_size =
|
|
1500
|
+
pathconf(path, _PC_REC_MIN_XFER_SIZE);
|
|
1501
|
+
t->current_filesystem->xfer_align =
|
|
1502
|
+
pathconf(path, _PC_REC_XFER_ALIGN);
|
|
1503
|
+
}
|
|
1504
|
+
/* At least we need an alignment size. */
|
|
1505
|
+
if (t->current_filesystem->xfer_align == -1)
|
|
1506
|
+
return ((errno == EINVAL)?1:-1);
|
|
1507
|
+
else
|
|
1508
|
+
return (0);
|
|
1509
|
+
}
|
|
1510
|
+
#else
|
|
1511
|
+
static int
|
|
1512
|
+
get_xfer_size(struct tree *t, int fd, const char *path)
|
|
1513
|
+
{
|
|
1514
|
+
(void)t; /* UNUSED */
|
|
1515
|
+
(void)fd; /* UNUSED */
|
|
1516
|
+
(void)path; /* UNUSED */
|
|
1517
|
+
return (1);/* Not supported */
|
|
1518
|
+
}
|
|
1519
|
+
#endif
|
|
1520
|
+
|
|
1521
|
+
#if defined(HAVE_STATVFS)
|
|
1522
|
+
static inline __LA_UNUSED void
|
|
1523
|
+
set_statvfs_transfer_size(struct filesystem *fs, const struct statvfs *sfs)
|
|
1524
|
+
{
|
|
1525
|
+
fs->xfer_align = sfs->f_frsize > 0 ? (long)sfs->f_frsize : -1;
|
|
1526
|
+
fs->max_xfer_size = -1;
|
|
1527
|
+
#if defined(HAVE_STRUCT_STATVFS_F_IOSIZE)
|
|
1528
|
+
fs->min_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
|
|
1529
|
+
fs->incr_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
|
|
1530
|
+
#else
|
|
1531
|
+
fs->min_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
|
|
1532
|
+
fs->incr_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
|
|
1533
|
+
#endif
|
|
1534
|
+
}
|
|
1535
|
+
#endif
|
|
1536
|
+
|
|
1537
|
+
#if defined(HAVE_STRUCT_STATFS)
|
|
1538
|
+
static inline __LA_UNUSED void
|
|
1539
|
+
set_statfs_transfer_size(struct filesystem *fs, const struct statfs *sfs)
|
|
1540
|
+
{
|
|
1541
|
+
fs->xfer_align = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
|
|
1542
|
+
fs->max_xfer_size = -1;
|
|
1543
|
+
#if defined(HAVE_STRUCT_STATFS_F_IOSIZE)
|
|
1544
|
+
fs->min_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
|
|
1545
|
+
fs->incr_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
|
|
1546
|
+
#else
|
|
1547
|
+
fs->min_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
|
|
1548
|
+
fs->incr_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
|
|
1549
|
+
#endif
|
|
1550
|
+
}
|
|
1551
|
+
#endif
|
|
1552
|
+
|
|
1553
|
+
#if defined(HAVE_STRUCT_STATFS) && defined(HAVE_STATFS) && \
|
|
1554
|
+
defined(HAVE_FSTATFS) && defined(MNT_LOCAL) && !defined(ST_LOCAL)
|
|
1555
|
+
|
|
1556
|
+
/*
|
|
1557
|
+
* Gather current filesystem properties on FreeBSD, OpenBSD and Mac OS X.
|
|
1558
|
+
*/
|
|
1559
|
+
static int
|
|
1560
|
+
setup_current_filesystem(struct archive_read_disk *a)
|
|
1561
|
+
{
|
|
1562
|
+
struct tree *t = a->tree;
|
|
1563
|
+
struct statfs sfs;
|
|
1564
|
+
#if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC)
|
|
1565
|
+
/* TODO: configure should set GETVFSBYNAME_ARG_TYPE to make
|
|
1566
|
+
* this accurate; some platforms have both and we need the one that's
|
|
1567
|
+
* used by getvfsbyname()
|
|
1568
|
+
*
|
|
1569
|
+
* Then the following would become:
|
|
1570
|
+
* #if defined(GETVFSBYNAME_ARG_TYPE)
|
|
1571
|
+
* GETVFSBYNAME_ARG_TYPE vfc;
|
|
1572
|
+
* #endif
|
|
1573
|
+
*/
|
|
1574
|
+
# if defined(HAVE_STRUCT_XVFSCONF)
|
|
1575
|
+
struct xvfsconf vfc;
|
|
1576
|
+
# else
|
|
1577
|
+
struct vfsconf vfc;
|
|
1578
|
+
# endif
|
|
1579
|
+
#endif
|
|
1580
|
+
int r, xr = 0;
|
|
1581
|
+
#if !defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
|
|
1582
|
+
long nm;
|
|
1583
|
+
#endif
|
|
1584
|
+
|
|
1585
|
+
t->current_filesystem->synthetic = -1;
|
|
1586
|
+
t->current_filesystem->remote = -1;
|
|
1587
|
+
if (tree_current_is_symblic_link_target(t)) {
|
|
1588
|
+
#if defined(HAVE_OPENAT)
|
|
1589
|
+
/*
|
|
1590
|
+
* Get file system statistics on any directory
|
|
1591
|
+
* where current is.
|
|
1592
|
+
*/
|
|
1593
|
+
int fd = openat(tree_current_dir_fd(t),
|
|
1594
|
+
tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
|
|
1595
|
+
__archive_ensure_cloexec_flag(fd);
|
|
1596
|
+
if (fd < 0) {
|
|
1597
|
+
archive_set_error(&a->archive, errno,
|
|
1598
|
+
"openat failed");
|
|
1599
|
+
return (ARCHIVE_FAILED);
|
|
1600
|
+
}
|
|
1601
|
+
r = fstatfs(fd, &sfs);
|
|
1602
|
+
if (r == 0)
|
|
1603
|
+
xr = get_xfer_size(t, fd, NULL);
|
|
1604
|
+
close(fd);
|
|
1605
|
+
#else
|
|
1606
|
+
if (tree_enter_working_dir(t) != 0) {
|
|
1607
|
+
archive_set_error(&a->archive, errno, "fchdir failed");
|
|
1608
|
+
return (ARCHIVE_FAILED);
|
|
1609
|
+
}
|
|
1610
|
+
r = statfs(tree_current_access_path(t), &sfs);
|
|
1611
|
+
if (r == 0)
|
|
1612
|
+
xr = get_xfer_size(t, -1, tree_current_access_path(t));
|
|
1613
|
+
#endif
|
|
1614
|
+
} else {
|
|
1615
|
+
r = fstatfs(tree_current_dir_fd(t), &sfs);
|
|
1616
|
+
if (r == 0)
|
|
1617
|
+
xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
|
|
1618
|
+
}
|
|
1619
|
+
if (r == -1 || xr == -1) {
|
|
1620
|
+
archive_set_error(&a->archive, errno, "statfs failed");
|
|
1621
|
+
return (ARCHIVE_FAILED);
|
|
1622
|
+
} else if (xr == 1) {
|
|
1623
|
+
/* pathconf(_PC_REX_*) operations are not supported. */
|
|
1624
|
+
set_statfs_transfer_size(t->current_filesystem, &sfs);
|
|
1625
|
+
}
|
|
1626
|
+
if (sfs.f_flags & MNT_LOCAL)
|
|
1627
|
+
t->current_filesystem->remote = 0;
|
|
1628
|
+
else
|
|
1629
|
+
t->current_filesystem->remote = 1;
|
|
1630
|
+
|
|
1631
|
+
#if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC)
|
|
1632
|
+
r = getvfsbyname(sfs.f_fstypename, &vfc);
|
|
1633
|
+
if (r == -1) {
|
|
1634
|
+
archive_set_error(&a->archive, errno, "getvfsbyname failed");
|
|
1635
|
+
return (ARCHIVE_FAILED);
|
|
1636
|
+
}
|
|
1637
|
+
if (vfc.vfc_flags & VFCF_SYNTHETIC)
|
|
1638
|
+
t->current_filesystem->synthetic = 1;
|
|
1639
|
+
else
|
|
1640
|
+
t->current_filesystem->synthetic = 0;
|
|
1641
|
+
#endif
|
|
1642
|
+
|
|
1643
|
+
#if defined(MNT_NOATIME)
|
|
1644
|
+
if (sfs.f_flags & MNT_NOATIME)
|
|
1645
|
+
t->current_filesystem->noatime = 1;
|
|
1646
|
+
else
|
|
1647
|
+
#endif
|
|
1648
|
+
t->current_filesystem->noatime = 0;
|
|
1649
|
+
|
|
1650
|
+
#if defined(USE_READDIR_R)
|
|
1651
|
+
/* Set maximum filename length. */
|
|
1652
|
+
#if defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
|
|
1653
|
+
t->current_filesystem->name_max = sfs.f_namemax;
|
|
1654
|
+
#else
|
|
1655
|
+
# if defined(_PC_NAME_MAX)
|
|
1656
|
+
/* Mac OS X does not have f_namemax in struct statfs. */
|
|
1657
|
+
if (tree_current_is_symblic_link_target(t)) {
|
|
1658
|
+
if (tree_enter_working_dir(t) != 0) {
|
|
1659
|
+
archive_set_error(&a->archive, errno, "fchdir failed");
|
|
1660
|
+
return (ARCHIVE_FAILED);
|
|
1661
|
+
}
|
|
1662
|
+
nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX);
|
|
1663
|
+
} else
|
|
1664
|
+
nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX);
|
|
1665
|
+
# else
|
|
1666
|
+
nm = -1;
|
|
1667
|
+
# endif
|
|
1668
|
+
if (nm == -1)
|
|
1669
|
+
t->current_filesystem->name_max = NAME_MAX;
|
|
1670
|
+
else
|
|
1671
|
+
t->current_filesystem->name_max = nm;
|
|
1672
|
+
#endif
|
|
1673
|
+
#endif /* USE_READDIR_R */
|
|
1674
|
+
return (ARCHIVE_OK);
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
#elif (defined(HAVE_STATVFS) || defined(HAVE_FSTATVFS)) && defined(ST_LOCAL)
|
|
1678
|
+
|
|
1679
|
+
/*
|
|
1680
|
+
* Gather current filesystem properties on NetBSD
|
|
1681
|
+
*/
|
|
1682
|
+
static int
|
|
1683
|
+
setup_current_filesystem(struct archive_read_disk *a)
|
|
1684
|
+
{
|
|
1685
|
+
struct tree *t = a->tree;
|
|
1686
|
+
struct statvfs svfs;
|
|
1687
|
+
int r, xr = 0;
|
|
1688
|
+
|
|
1689
|
+
t->current_filesystem->synthetic = -1;
|
|
1690
|
+
if (tree_enter_working_dir(t) != 0) {
|
|
1691
|
+
archive_set_error(&a->archive, errno, "fchdir failed");
|
|
1692
|
+
return (ARCHIVE_FAILED);
|
|
1693
|
+
}
|
|
1694
|
+
if (tree_current_is_symblic_link_target(t)) {
|
|
1695
|
+
r = statvfs(tree_current_access_path(t), &svfs);
|
|
1696
|
+
if (r == 0)
|
|
1697
|
+
xr = get_xfer_size(t, -1, tree_current_access_path(t));
|
|
1698
|
+
} else {
|
|
1699
|
+
#ifdef HAVE_FSTATVFS
|
|
1700
|
+
r = fstatvfs(tree_current_dir_fd(t), &svfs);
|
|
1701
|
+
if (r == 0)
|
|
1702
|
+
xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
|
|
1703
|
+
#else
|
|
1704
|
+
r = statvfs(".", &svfs);
|
|
1705
|
+
if (r == 0)
|
|
1706
|
+
xr = get_xfer_size(t, -1, ".");
|
|
1707
|
+
#endif
|
|
1708
|
+
}
|
|
1709
|
+
if (r == -1 || xr == -1) {
|
|
1710
|
+
t->current_filesystem->remote = -1;
|
|
1711
|
+
archive_set_error(&a->archive, errno, "statvfs failed");
|
|
1712
|
+
return (ARCHIVE_FAILED);
|
|
1713
|
+
} else if (xr == 1) {
|
|
1714
|
+
/* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN
|
|
1715
|
+
* for pathconf() function. */
|
|
1716
|
+
set_statvfs_transfer_size(t->current_filesystem, &svfs);
|
|
1717
|
+
}
|
|
1718
|
+
if (svfs.f_flag & ST_LOCAL)
|
|
1719
|
+
t->current_filesystem->remote = 0;
|
|
1720
|
+
else
|
|
1721
|
+
t->current_filesystem->remote = 1;
|
|
1722
|
+
|
|
1723
|
+
#if defined(ST_NOATIME)
|
|
1724
|
+
if (svfs.f_flag & ST_NOATIME)
|
|
1725
|
+
t->current_filesystem->noatime = 1;
|
|
1726
|
+
else
|
|
1727
|
+
#endif
|
|
1728
|
+
t->current_filesystem->noatime = 0;
|
|
1729
|
+
|
|
1730
|
+
/* Set maximum filename length. */
|
|
1731
|
+
t->current_filesystem->name_max = svfs.f_namemax;
|
|
1732
|
+
return (ARCHIVE_OK);
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
#elif defined(HAVE_SYS_STATFS_H) && defined(HAVE_LINUX_MAGIC_H) &&\
|
|
1736
|
+
defined(HAVE_STATFS) && defined(HAVE_FSTATFS)
|
|
1737
|
+
/*
|
|
1738
|
+
* Note: statfs is deprecated since LSB 3.2
|
|
1739
|
+
*/
|
|
1740
|
+
|
|
1741
|
+
#ifndef CIFS_SUPER_MAGIC
|
|
1742
|
+
#define CIFS_SUPER_MAGIC 0xFF534D42
|
|
1743
|
+
#endif
|
|
1744
|
+
#ifndef DEVFS_SUPER_MAGIC
|
|
1745
|
+
#define DEVFS_SUPER_MAGIC 0x1373
|
|
1746
|
+
#endif
|
|
1747
|
+
|
|
1748
|
+
/*
|
|
1749
|
+
* Gather current filesystem properties on Linux
|
|
1750
|
+
*/
|
|
1751
|
+
static int
|
|
1752
|
+
setup_current_filesystem(struct archive_read_disk *a)
|
|
1753
|
+
{
|
|
1754
|
+
struct tree *t = a->tree;
|
|
1755
|
+
struct statfs sfs;
|
|
1756
|
+
#if defined(HAVE_STATVFS)
|
|
1757
|
+
struct statvfs svfs;
|
|
1758
|
+
#endif
|
|
1759
|
+
int r, vr = 0, xr = 0;
|
|
1760
|
+
|
|
1761
|
+
if (tree_current_is_symblic_link_target(t)) {
|
|
1762
|
+
#if defined(HAVE_OPENAT)
|
|
1763
|
+
/*
|
|
1764
|
+
* Get file system statistics on any directory
|
|
1765
|
+
* where current is.
|
|
1766
|
+
*/
|
|
1767
|
+
int fd = openat(tree_current_dir_fd(t),
|
|
1768
|
+
tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
|
|
1769
|
+
__archive_ensure_cloexec_flag(fd);
|
|
1770
|
+
if (fd < 0) {
|
|
1771
|
+
archive_set_error(&a->archive, errno,
|
|
1772
|
+
"openat failed");
|
|
1773
|
+
return (ARCHIVE_FAILED);
|
|
1774
|
+
}
|
|
1775
|
+
#if defined(HAVE_FSTATVFS)
|
|
1776
|
+
vr = fstatvfs(fd, &svfs);/* for f_flag, mount flags */
|
|
1777
|
+
#endif
|
|
1778
|
+
r = fstatfs(fd, &sfs);
|
|
1779
|
+
if (r == 0)
|
|
1780
|
+
xr = get_xfer_size(t, fd, NULL);
|
|
1781
|
+
close(fd);
|
|
1782
|
+
#else
|
|
1783
|
+
if (tree_enter_working_dir(t) != 0) {
|
|
1784
|
+
archive_set_error(&a->archive, errno, "fchdir failed");
|
|
1785
|
+
return (ARCHIVE_FAILED);
|
|
1786
|
+
}
|
|
1787
|
+
#if defined(HAVE_STATVFS)
|
|
1788
|
+
vr = statvfs(tree_current_access_path(t), &svfs);
|
|
1789
|
+
#endif
|
|
1790
|
+
r = statfs(tree_current_access_path(t), &sfs);
|
|
1791
|
+
if (r == 0)
|
|
1792
|
+
xr = get_xfer_size(t, -1, tree_current_access_path(t));
|
|
1793
|
+
#endif
|
|
1794
|
+
} else {
|
|
1795
|
+
#ifdef HAVE_FSTATFS
|
|
1796
|
+
#if defined(HAVE_FSTATVFS)
|
|
1797
|
+
vr = fstatvfs(tree_current_dir_fd(t), &svfs);
|
|
1798
|
+
#endif
|
|
1799
|
+
r = fstatfs(tree_current_dir_fd(t), &sfs);
|
|
1800
|
+
if (r == 0)
|
|
1801
|
+
xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
|
|
1802
|
+
#else
|
|
1803
|
+
if (tree_enter_working_dir(t) != 0) {
|
|
1804
|
+
archive_set_error(&a->archive, errno, "fchdir failed");
|
|
1805
|
+
return (ARCHIVE_FAILED);
|
|
1806
|
+
}
|
|
1807
|
+
#if defined(HAVE_STATVFS)
|
|
1808
|
+
vr = statvfs(".", &svfs);
|
|
1809
|
+
#endif
|
|
1810
|
+
r = statfs(".", &sfs);
|
|
1811
|
+
if (r == 0)
|
|
1812
|
+
xr = get_xfer_size(t, -1, ".");
|
|
1813
|
+
#endif
|
|
1814
|
+
}
|
|
1815
|
+
if (r == -1 || xr == -1 || vr == -1) {
|
|
1816
|
+
t->current_filesystem->synthetic = -1;
|
|
1817
|
+
t->current_filesystem->remote = -1;
|
|
1818
|
+
archive_set_error(&a->archive, errno, "statfs failed");
|
|
1819
|
+
return (ARCHIVE_FAILED);
|
|
1820
|
+
} else if (xr == 1) {
|
|
1821
|
+
/* pathconf(_PC_REX_*) operations are not supported. */
|
|
1822
|
+
#if defined(HAVE_STATVFS)
|
|
1823
|
+
set_statvfs_transfer_size(t->current_filesystem, &svfs);
|
|
1824
|
+
#else
|
|
1825
|
+
set_statfs_transfer_size(t->current_filesystem, &sfs);
|
|
1826
|
+
#endif
|
|
1827
|
+
}
|
|
1828
|
+
switch (sfs.f_type) {
|
|
1829
|
+
case AFS_SUPER_MAGIC:
|
|
1830
|
+
case CIFS_SUPER_MAGIC:
|
|
1831
|
+
case CODA_SUPER_MAGIC:
|
|
1832
|
+
case NCP_SUPER_MAGIC:/* NetWare */
|
|
1833
|
+
case NFS_SUPER_MAGIC:
|
|
1834
|
+
case SMB_SUPER_MAGIC:
|
|
1835
|
+
t->current_filesystem->remote = 1;
|
|
1836
|
+
t->current_filesystem->synthetic = 0;
|
|
1837
|
+
break;
|
|
1838
|
+
case DEVFS_SUPER_MAGIC:
|
|
1839
|
+
case PROC_SUPER_MAGIC:
|
|
1840
|
+
case USBDEVICE_SUPER_MAGIC:
|
|
1841
|
+
t->current_filesystem->remote = 0;
|
|
1842
|
+
t->current_filesystem->synthetic = 1;
|
|
1843
|
+
break;
|
|
1844
|
+
default:
|
|
1845
|
+
t->current_filesystem->remote = 0;
|
|
1846
|
+
t->current_filesystem->synthetic = 0;
|
|
1847
|
+
break;
|
|
1848
|
+
}
|
|
1849
|
+
|
|
1850
|
+
#if defined(ST_NOATIME)
|
|
1851
|
+
#if defined(HAVE_STATVFS)
|
|
1852
|
+
if (svfs.f_flag & ST_NOATIME)
|
|
1853
|
+
#else
|
|
1854
|
+
if (sfs.f_flags & ST_NOATIME)
|
|
1855
|
+
#endif
|
|
1856
|
+
t->current_filesystem->noatime = 1;
|
|
1857
|
+
else
|
|
1858
|
+
#endif
|
|
1859
|
+
t->current_filesystem->noatime = 0;
|
|
1860
|
+
|
|
1861
|
+
#if defined(USE_READDIR_R)
|
|
1862
|
+
/* Set maximum filename length. */
|
|
1863
|
+
t->current_filesystem->name_max = sfs.f_namelen;
|
|
1864
|
+
#endif
|
|
1865
|
+
return (ARCHIVE_OK);
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
#elif defined(HAVE_SYS_STATVFS_H) &&\
|
|
1869
|
+
(defined(HAVE_STATVFS) || defined(HAVE_FSTATVFS))
|
|
1870
|
+
|
|
1871
|
+
/*
|
|
1872
|
+
* Gather current filesystem properties on other posix platform.
|
|
1873
|
+
*/
|
|
1874
|
+
static int
|
|
1875
|
+
setup_current_filesystem(struct archive_read_disk *a)
|
|
1876
|
+
{
|
|
1877
|
+
struct tree *t = a->tree;
|
|
1878
|
+
struct statvfs svfs;
|
|
1879
|
+
int r, xr = 0;
|
|
1880
|
+
|
|
1881
|
+
t->current_filesystem->synthetic = -1;/* Not supported */
|
|
1882
|
+
t->current_filesystem->remote = -1;/* Not supported */
|
|
1883
|
+
if (tree_current_is_symblic_link_target(t)) {
|
|
1884
|
+
#if defined(HAVE_OPENAT)
|
|
1885
|
+
/*
|
|
1886
|
+
* Get file system statistics on any directory
|
|
1887
|
+
* where current is.
|
|
1888
|
+
*/
|
|
1889
|
+
int fd = openat(tree_current_dir_fd(t),
|
|
1890
|
+
tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
|
|
1891
|
+
__archive_ensure_cloexec_flag(fd);
|
|
1892
|
+
if (fd < 0) {
|
|
1893
|
+
archive_set_error(&a->archive, errno,
|
|
1894
|
+
"openat failed");
|
|
1895
|
+
return (ARCHIVE_FAILED);
|
|
1896
|
+
}
|
|
1897
|
+
r = fstatvfs(fd, &svfs);
|
|
1898
|
+
if (r == 0)
|
|
1899
|
+
xr = get_xfer_size(t, fd, NULL);
|
|
1900
|
+
close(fd);
|
|
1901
|
+
#else
|
|
1902
|
+
if (tree_enter_working_dir(t) != 0) {
|
|
1903
|
+
archive_set_error(&a->archive, errno, "fchdir failed");
|
|
1904
|
+
return (ARCHIVE_FAILED);
|
|
1905
|
+
}
|
|
1906
|
+
r = statvfs(tree_current_access_path(t), &svfs);
|
|
1907
|
+
if (r == 0)
|
|
1908
|
+
xr = get_xfer_size(t, -1, tree_current_access_path(t));
|
|
1909
|
+
#endif
|
|
1910
|
+
} else {
|
|
1911
|
+
#ifdef HAVE_FSTATVFS
|
|
1912
|
+
r = fstatvfs(tree_current_dir_fd(t), &svfs);
|
|
1913
|
+
if (r == 0)
|
|
1914
|
+
xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
|
|
1915
|
+
#else
|
|
1916
|
+
if (tree_enter_working_dir(t) != 0) {
|
|
1917
|
+
archive_set_error(&a->archive, errno, "fchdir failed");
|
|
1918
|
+
return (ARCHIVE_FAILED);
|
|
1919
|
+
}
|
|
1920
|
+
r = statvfs(".", &svfs);
|
|
1921
|
+
if (r == 0)
|
|
1922
|
+
xr = get_xfer_size(t, -1, ".");
|
|
1923
|
+
#endif
|
|
1924
|
+
}
|
|
1925
|
+
if (r == -1 || xr == -1) {
|
|
1926
|
+
t->current_filesystem->synthetic = -1;
|
|
1927
|
+
t->current_filesystem->remote = -1;
|
|
1928
|
+
archive_set_error(&a->archive, errno, "statvfs failed");
|
|
1929
|
+
return (ARCHIVE_FAILED);
|
|
1930
|
+
} else if (xr == 1) {
|
|
1931
|
+
/* pathconf(_PC_REX_*) operations are not supported. */
|
|
1932
|
+
set_statvfs_transfer_size(t->current_filesystem, &svfs);
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
#if defined(ST_NOATIME)
|
|
1936
|
+
if (svfs.f_flag & ST_NOATIME)
|
|
1937
|
+
t->current_filesystem->noatime = 1;
|
|
1938
|
+
else
|
|
1939
|
+
#endif
|
|
1940
|
+
t->current_filesystem->noatime = 0;
|
|
1941
|
+
|
|
1942
|
+
#if defined(USE_READDIR_R)
|
|
1943
|
+
/* Set maximum filename length. */
|
|
1944
|
+
t->current_filesystem->name_max = svfs.f_namemax;
|
|
1945
|
+
#endif
|
|
1946
|
+
return (ARCHIVE_OK);
|
|
1947
|
+
}
|
|
1948
|
+
|
|
1949
|
+
#else
|
|
1950
|
+
|
|
1951
|
+
/*
|
|
1952
|
+
* Generic: Gather current filesystem properties.
|
|
1953
|
+
* TODO: Is this generic function really needed?
|
|
1954
|
+
*/
|
|
1955
|
+
static int
|
|
1956
|
+
setup_current_filesystem(struct archive_read_disk *a)
|
|
1957
|
+
{
|
|
1958
|
+
struct tree *t = a->tree;
|
|
1959
|
+
#if defined(_PC_NAME_MAX) && defined(USE_READDIR_R)
|
|
1960
|
+
long nm;
|
|
1961
|
+
#endif
|
|
1962
|
+
t->current_filesystem->synthetic = -1;/* Not supported */
|
|
1963
|
+
t->current_filesystem->remote = -1;/* Not supported */
|
|
1964
|
+
t->current_filesystem->noatime = 0;
|
|
1965
|
+
(void)get_xfer_size(t, -1, ".");/* Dummy call to avoid build error. */
|
|
1966
|
+
t->current_filesystem->xfer_align = -1;/* Unknown */
|
|
1967
|
+
t->current_filesystem->max_xfer_size = -1;
|
|
1968
|
+
t->current_filesystem->min_xfer_size = -1;
|
|
1969
|
+
t->current_filesystem->incr_xfer_size = -1;
|
|
1970
|
+
|
|
1971
|
+
#if defined(USE_READDIR_R)
|
|
1972
|
+
/* Set maximum filename length. */
|
|
1973
|
+
# if defined(_PC_NAME_MAX)
|
|
1974
|
+
if (tree_current_is_symblic_link_target(t)) {
|
|
1975
|
+
if (tree_enter_working_dir(t) != 0) {
|
|
1976
|
+
archive_set_error(&a->archive, errno, "fchdir failed");
|
|
1977
|
+
return (ARCHIVE_FAILED);
|
|
1978
|
+
}
|
|
1979
|
+
nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX);
|
|
1980
|
+
} else
|
|
1981
|
+
nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX);
|
|
1982
|
+
if (nm == -1)
|
|
1983
|
+
# endif /* _PC_NAME_MAX */
|
|
1984
|
+
/*
|
|
1985
|
+
* Some systems (HP-UX or others?) incorrectly defined
|
|
1986
|
+
* NAME_MAX macro to be a smaller value.
|
|
1987
|
+
*/
|
|
1988
|
+
# if defined(NAME_MAX) && NAME_MAX >= 255
|
|
1989
|
+
t->current_filesystem->name_max = NAME_MAX;
|
|
1990
|
+
# else
|
|
1991
|
+
/* No way to get a trusted value of maximum filename
|
|
1992
|
+
* length. */
|
|
1993
|
+
t->current_filesystem->name_max = PATH_MAX;
|
|
1994
|
+
# endif /* NAME_MAX */
|
|
1995
|
+
# if defined(_PC_NAME_MAX)
|
|
1996
|
+
else
|
|
1997
|
+
t->current_filesystem->name_max = nm;
|
|
1998
|
+
# endif /* _PC_NAME_MAX */
|
|
1999
|
+
#endif /* USE_READDIR_R */
|
|
2000
|
+
return (ARCHIVE_OK);
|
|
2001
|
+
}
|
|
2002
|
+
|
|
2003
|
+
#endif
|
|
2004
|
+
|
|
2005
|
+
static int
|
|
2006
|
+
close_and_restore_time(int fd, struct tree *t, struct restore_time *rt)
|
|
2007
|
+
{
|
|
2008
|
+
#ifndef HAVE_UTIMES
|
|
2009
|
+
(void)t; /* UNUSED */
|
|
2010
|
+
(void)rt; /* UNUSED */
|
|
2011
|
+
return (close(fd));
|
|
2012
|
+
#else
|
|
2013
|
+
#if defined(HAVE_FUTIMENS) && !defined(__CYGWIN__)
|
|
2014
|
+
struct timespec timespecs[2];
|
|
2015
|
+
#endif
|
|
2016
|
+
struct timeval times[2];
|
|
2017
|
+
|
|
2018
|
+
if ((t->flags & needsRestoreTimes) == 0 || rt->noatime) {
|
|
2019
|
+
if (fd >= 0)
|
|
2020
|
+
return (close(fd));
|
|
2021
|
+
else
|
|
2022
|
+
return (0);
|
|
2023
|
+
}
|
|
2024
|
+
|
|
2025
|
+
#if defined(HAVE_FUTIMENS) && !defined(__CYGWIN__)
|
|
2026
|
+
timespecs[1].tv_sec = rt->mtime;
|
|
2027
|
+
timespecs[1].tv_nsec = rt->mtime_nsec;
|
|
2028
|
+
|
|
2029
|
+
timespecs[0].tv_sec = rt->atime;
|
|
2030
|
+
timespecs[0].tv_nsec = rt->atime_nsec;
|
|
2031
|
+
/* futimens() is defined in POSIX.1-2008. */
|
|
2032
|
+
if (futimens(fd, timespecs) == 0)
|
|
2033
|
+
return (close(fd));
|
|
2034
|
+
#endif
|
|
2035
|
+
|
|
2036
|
+
times[1].tv_sec = rt->mtime;
|
|
2037
|
+
times[1].tv_usec = rt->mtime_nsec / 1000;
|
|
2038
|
+
|
|
2039
|
+
times[0].tv_sec = rt->atime;
|
|
2040
|
+
times[0].tv_usec = rt->atime_nsec / 1000;
|
|
2041
|
+
|
|
2042
|
+
#if !defined(HAVE_FUTIMENS) && defined(HAVE_FUTIMES) && !defined(__CYGWIN__)
|
|
2043
|
+
if (futimes(fd, times) == 0)
|
|
2044
|
+
return (close(fd));
|
|
2045
|
+
#endif
|
|
2046
|
+
close(fd);
|
|
2047
|
+
#if defined(HAVE_FUTIMESAT)
|
|
2048
|
+
if (futimesat(tree_current_dir_fd(t), rt->name, times) == 0)
|
|
2049
|
+
return (0);
|
|
2050
|
+
#endif
|
|
2051
|
+
#ifdef HAVE_LUTIMES
|
|
2052
|
+
if (lutimes(rt->name, times) != 0)
|
|
2053
|
+
#else
|
|
2054
|
+
if (AE_IFLNK != rt->filetype && utimes(rt->name, times) != 0)
|
|
2055
|
+
#endif
|
|
2056
|
+
return (-1);
|
|
2057
|
+
#endif
|
|
2058
|
+
return (0);
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
static int
|
|
2062
|
+
open_on_current_dir(struct tree *t, const char *path, int flags)
|
|
2063
|
+
{
|
|
2064
|
+
#ifdef HAVE_OPENAT
|
|
2065
|
+
return (openat(tree_current_dir_fd(t), path, flags));
|
|
2066
|
+
#else
|
|
2067
|
+
if (tree_enter_working_dir(t) != 0)
|
|
2068
|
+
return (-1);
|
|
2069
|
+
return (open(path, flags));
|
|
2070
|
+
#endif
|
|
2071
|
+
}
|
|
2072
|
+
|
|
2073
|
+
static int
|
|
2074
|
+
tree_dup(int fd)
|
|
2075
|
+
{
|
|
2076
|
+
int new_fd;
|
|
2077
|
+
#ifdef F_DUPFD_CLOEXEC
|
|
2078
|
+
static volatile int can_dupfd_cloexec = 1;
|
|
2079
|
+
|
|
2080
|
+
if (can_dupfd_cloexec) {
|
|
2081
|
+
new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
|
|
2082
|
+
if (new_fd != -1)
|
|
2083
|
+
return (new_fd);
|
|
2084
|
+
/* Linux 2.6.18 - 2.6.23 declare F_DUPFD_CLOEXEC,
|
|
2085
|
+
* but it cannot be used. So we have to try dup(). */
|
|
2086
|
+
/* We won't try F_DUPFD_CLOEXEC. */
|
|
2087
|
+
can_dupfd_cloexec = 0;
|
|
2088
|
+
}
|
|
2089
|
+
#endif /* F_DUPFD_CLOEXEC */
|
|
2090
|
+
new_fd = dup(fd);
|
|
2091
|
+
__archive_ensure_cloexec_flag(new_fd);
|
|
2092
|
+
return (new_fd);
|
|
2093
|
+
}
|
|
2094
|
+
|
|
2095
|
+
/*
|
|
2096
|
+
* Add a directory path to the current stack.
|
|
2097
|
+
*/
|
|
2098
|
+
static void
|
|
2099
|
+
tree_push(struct tree *t, const char *path, int filesystem_id,
|
|
2100
|
+
int64_t dev, int64_t ino, struct restore_time *rt)
|
|
2101
|
+
{
|
|
2102
|
+
struct tree_entry *te;
|
|
2103
|
+
|
|
2104
|
+
te = calloc(1, sizeof(*te));
|
|
2105
|
+
if (te == NULL)
|
|
2106
|
+
__archive_errx(1, "Out of memory");
|
|
2107
|
+
te->next = t->stack;
|
|
2108
|
+
te->parent = t->current;
|
|
2109
|
+
if (te->parent)
|
|
2110
|
+
te->depth = te->parent->depth + 1;
|
|
2111
|
+
t->stack = te;
|
|
2112
|
+
archive_string_init(&te->name);
|
|
2113
|
+
te->symlink_parent_fd = -1;
|
|
2114
|
+
archive_strcpy(&te->name, path);
|
|
2115
|
+
te->flags = needsDescent | needsOpen | needsAscent;
|
|
2116
|
+
te->filesystem_id = filesystem_id;
|
|
2117
|
+
te->dev = dev;
|
|
2118
|
+
te->ino = ino;
|
|
2119
|
+
te->dirname_length = t->dirname_length;
|
|
2120
|
+
te->restore_time.name = te->name.s;
|
|
2121
|
+
if (rt != NULL) {
|
|
2122
|
+
te->restore_time.mtime = rt->mtime;
|
|
2123
|
+
te->restore_time.mtime_nsec = rt->mtime_nsec;
|
|
2124
|
+
te->restore_time.atime = rt->atime;
|
|
2125
|
+
te->restore_time.atime_nsec = rt->atime_nsec;
|
|
2126
|
+
te->restore_time.filetype = rt->filetype;
|
|
2127
|
+
te->restore_time.noatime = rt->noatime;
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
|
|
2131
|
+
/*
|
|
2132
|
+
* Append a name to the current dir path.
|
|
2133
|
+
*/
|
|
2134
|
+
static void
|
|
2135
|
+
tree_append(struct tree *t, const char *name, size_t name_length)
|
|
2136
|
+
{
|
|
2137
|
+
size_t size_needed;
|
|
2138
|
+
|
|
2139
|
+
t->path.s[t->dirname_length] = '\0';
|
|
2140
|
+
t->path.length = t->dirname_length;
|
|
2141
|
+
/* Strip trailing '/' from name, unless entire name is "/". */
|
|
2142
|
+
while (name_length > 1 && name[name_length - 1] == '/')
|
|
2143
|
+
name_length--;
|
|
2144
|
+
|
|
2145
|
+
/* Resize pathname buffer as needed. */
|
|
2146
|
+
size_needed = name_length + t->dirname_length + 2;
|
|
2147
|
+
archive_string_ensure(&t->path, size_needed);
|
|
2148
|
+
/* Add a separating '/' if it's needed. */
|
|
2149
|
+
if (t->dirname_length > 0 && t->path.s[archive_strlen(&t->path)-1] != '/')
|
|
2150
|
+
archive_strappend_char(&t->path, '/');
|
|
2151
|
+
t->basename = t->path.s + archive_strlen(&t->path);
|
|
2152
|
+
archive_strncat(&t->path, name, name_length);
|
|
2153
|
+
t->restore_time.name = t->basename;
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
/*
|
|
2157
|
+
* Open a directory tree for traversal.
|
|
2158
|
+
*/
|
|
2159
|
+
static struct tree *
|
|
2160
|
+
tree_open(const char *path, int symlink_mode, int restore_time)
|
|
2161
|
+
{
|
|
2162
|
+
struct tree *t;
|
|
2163
|
+
|
|
2164
|
+
if ((t = calloc(1, sizeof(*t))) == NULL)
|
|
2165
|
+
return (NULL);
|
|
2166
|
+
archive_string_init(&t->path);
|
|
2167
|
+
archive_string_ensure(&t->path, 31);
|
|
2168
|
+
t->initial_symlink_mode = symlink_mode;
|
|
2169
|
+
return (tree_reopen(t, path, restore_time));
|
|
2170
|
+
}
|
|
2171
|
+
|
|
2172
|
+
static struct tree *
|
|
2173
|
+
tree_reopen(struct tree *t, const char *path, int restore_time)
|
|
2174
|
+
{
|
|
2175
|
+
#if defined(O_PATH)
|
|
2176
|
+
/* Linux */
|
|
2177
|
+
const int o_flag = O_PATH;
|
|
2178
|
+
#elif defined(O_SEARCH)
|
|
2179
|
+
/* SunOS */
|
|
2180
|
+
const int o_flag = O_SEARCH;
|
|
2181
|
+
#elif defined(__FreeBSD__) && defined(O_EXEC)
|
|
2182
|
+
/* FreeBSD */
|
|
2183
|
+
const int o_flag = O_EXEC;
|
|
2184
|
+
#endif
|
|
2185
|
+
|
|
2186
|
+
t->flags = (restore_time != 0)?needsRestoreTimes:0;
|
|
2187
|
+
t->flags |= onInitialDir;
|
|
2188
|
+
t->visit_type = 0;
|
|
2189
|
+
t->tree_errno = 0;
|
|
2190
|
+
t->dirname_length = 0;
|
|
2191
|
+
t->depth = 0;
|
|
2192
|
+
t->descend = 0;
|
|
2193
|
+
t->current = NULL;
|
|
2194
|
+
t->d = INVALID_DIR_HANDLE;
|
|
2195
|
+
t->symlink_mode = t->initial_symlink_mode;
|
|
2196
|
+
archive_string_empty(&t->path);
|
|
2197
|
+
t->entry_fd = -1;
|
|
2198
|
+
t->entry_eof = 0;
|
|
2199
|
+
t->entry_remaining_bytes = 0;
|
|
2200
|
+
t->initial_filesystem_id = -1;
|
|
2201
|
+
|
|
2202
|
+
/* First item is set up a lot like a symlink traversal. */
|
|
2203
|
+
tree_push(t, path, 0, 0, 0, NULL);
|
|
2204
|
+
t->stack->flags = needsFirstVisit;
|
|
2205
|
+
t->maxOpenCount = t->openCount = 1;
|
|
2206
|
+
t->initial_dir_fd = open(".", O_RDONLY | O_CLOEXEC);
|
|
2207
|
+
#if defined(O_PATH) || defined(O_SEARCH) || \
|
|
2208
|
+
(defined(__FreeBSD__) && defined(O_EXEC))
|
|
2209
|
+
/*
|
|
2210
|
+
* Most likely reason to fail opening "." is that it's not readable,
|
|
2211
|
+
* so try again for execute. The consequences of not opening this are
|
|
2212
|
+
* unhelpful and unnecessary errors later.
|
|
2213
|
+
*/
|
|
2214
|
+
if (t->initial_dir_fd < 0)
|
|
2215
|
+
t->initial_dir_fd = open(".", o_flag | O_CLOEXEC);
|
|
2216
|
+
#endif
|
|
2217
|
+
__archive_ensure_cloexec_flag(t->initial_dir_fd);
|
|
2218
|
+
t->working_dir_fd = tree_dup(t->initial_dir_fd);
|
|
2219
|
+
return (t);
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
static int
|
|
2223
|
+
tree_descent(struct tree *t)
|
|
2224
|
+
{
|
|
2225
|
+
int flag, new_fd, r = 0;
|
|
2226
|
+
|
|
2227
|
+
t->dirname_length = archive_strlen(&t->path);
|
|
2228
|
+
flag = O_RDONLY | O_CLOEXEC;
|
|
2229
|
+
#if defined(O_DIRECTORY)
|
|
2230
|
+
flag |= O_DIRECTORY;
|
|
2231
|
+
#endif
|
|
2232
|
+
new_fd = open_on_current_dir(t, t->stack->name.s, flag);
|
|
2233
|
+
__archive_ensure_cloexec_flag(new_fd);
|
|
2234
|
+
if (new_fd < 0) {
|
|
2235
|
+
t->tree_errno = errno;
|
|
2236
|
+
r = TREE_ERROR_DIR;
|
|
2237
|
+
} else {
|
|
2238
|
+
t->depth++;
|
|
2239
|
+
/* If it is a link, set up fd for the ascent. */
|
|
2240
|
+
if (t->stack->flags & isDirLink) {
|
|
2241
|
+
t->stack->symlink_parent_fd = t->working_dir_fd;
|
|
2242
|
+
t->openCount++;
|
|
2243
|
+
if (t->openCount > t->maxOpenCount)
|
|
2244
|
+
t->maxOpenCount = t->openCount;
|
|
2245
|
+
} else
|
|
2246
|
+
close(t->working_dir_fd);
|
|
2247
|
+
/* Renew the current working directory. */
|
|
2248
|
+
t->working_dir_fd = new_fd;
|
|
2249
|
+
t->flags &= ~onWorkingDir;
|
|
2250
|
+
}
|
|
2251
|
+
return (r);
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2254
|
+
/*
|
|
2255
|
+
* We've finished a directory; ascend back to the parent.
|
|
2256
|
+
*/
|
|
2257
|
+
static int
|
|
2258
|
+
tree_ascend(struct tree *t)
|
|
2259
|
+
{
|
|
2260
|
+
struct tree_entry *te;
|
|
2261
|
+
int new_fd, r = 0, prev_dir_fd;
|
|
2262
|
+
|
|
2263
|
+
te = t->stack;
|
|
2264
|
+
prev_dir_fd = t->working_dir_fd;
|
|
2265
|
+
if (te->flags & isDirLink)
|
|
2266
|
+
new_fd = te->symlink_parent_fd;
|
|
2267
|
+
else {
|
|
2268
|
+
new_fd = open_on_current_dir(t, "..", O_RDONLY | O_CLOEXEC);
|
|
2269
|
+
__archive_ensure_cloexec_flag(new_fd);
|
|
2270
|
+
}
|
|
2271
|
+
if (new_fd < 0) {
|
|
2272
|
+
t->tree_errno = errno;
|
|
2273
|
+
r = TREE_ERROR_FATAL;
|
|
2274
|
+
} else {
|
|
2275
|
+
/* Renew the current working directory. */
|
|
2276
|
+
t->working_dir_fd = new_fd;
|
|
2277
|
+
t->flags &= ~onWorkingDir;
|
|
2278
|
+
/* Current directory has been changed, we should
|
|
2279
|
+
* close an fd of previous working directory. */
|
|
2280
|
+
close_and_restore_time(prev_dir_fd, t, &te->restore_time);
|
|
2281
|
+
if (te->flags & isDirLink) {
|
|
2282
|
+
t->openCount--;
|
|
2283
|
+
te->symlink_parent_fd = -1;
|
|
2284
|
+
}
|
|
2285
|
+
t->depth--;
|
|
2286
|
+
}
|
|
2287
|
+
return (r);
|
|
2288
|
+
}
|
|
2289
|
+
|
|
2290
|
+
/*
|
|
2291
|
+
* Return to the initial directory where tree_open() was performed.
|
|
2292
|
+
*/
|
|
2293
|
+
static int
|
|
2294
|
+
tree_enter_initial_dir(struct tree *t)
|
|
2295
|
+
{
|
|
2296
|
+
int r = 0;
|
|
2297
|
+
|
|
2298
|
+
if ((t->flags & onInitialDir) == 0) {
|
|
2299
|
+
r = fchdir(t->initial_dir_fd);
|
|
2300
|
+
if (r == 0) {
|
|
2301
|
+
t->flags &= ~onWorkingDir;
|
|
2302
|
+
t->flags |= onInitialDir;
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
return (r);
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
/*
|
|
2309
|
+
* Restore working directory of directory traversals.
|
|
2310
|
+
*/
|
|
2311
|
+
static int
|
|
2312
|
+
tree_enter_working_dir(struct tree *t)
|
|
2313
|
+
{
|
|
2314
|
+
int r = 0;
|
|
2315
|
+
|
|
2316
|
+
/*
|
|
2317
|
+
* Change the current directory if really needed.
|
|
2318
|
+
* Sometimes this is unneeded when we did not do
|
|
2319
|
+
* descent.
|
|
2320
|
+
*/
|
|
2321
|
+
if (t->depth > 0 && (t->flags & onWorkingDir) == 0) {
|
|
2322
|
+
r = fchdir(t->working_dir_fd);
|
|
2323
|
+
if (r == 0) {
|
|
2324
|
+
t->flags &= ~onInitialDir;
|
|
2325
|
+
t->flags |= onWorkingDir;
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
2328
|
+
return (r);
|
|
2329
|
+
}
|
|
2330
|
+
|
|
2331
|
+
static int
|
|
2332
|
+
tree_current_dir_fd(struct tree *t)
|
|
2333
|
+
{
|
|
2334
|
+
return (t->working_dir_fd);
|
|
2335
|
+
}
|
|
2336
|
+
|
|
2337
|
+
/*
|
|
2338
|
+
* Pop the working stack.
|
|
2339
|
+
*/
|
|
2340
|
+
static void
|
|
2341
|
+
tree_pop(struct tree *t)
|
|
2342
|
+
{
|
|
2343
|
+
struct tree_entry *te;
|
|
2344
|
+
|
|
2345
|
+
t->path.s[t->dirname_length] = '\0';
|
|
2346
|
+
t->path.length = t->dirname_length;
|
|
2347
|
+
if (t->stack == t->current && t->current != NULL)
|
|
2348
|
+
t->current = t->current->parent;
|
|
2349
|
+
te = t->stack;
|
|
2350
|
+
t->stack = te->next;
|
|
2351
|
+
t->dirname_length = te->dirname_length;
|
|
2352
|
+
t->basename = t->path.s + t->dirname_length;
|
|
2353
|
+
while (t->basename[0] == '/')
|
|
2354
|
+
t->basename++;
|
|
2355
|
+
archive_string_free(&te->name);
|
|
2356
|
+
free(te);
|
|
2357
|
+
}
|
|
2358
|
+
|
|
2359
|
+
/*
|
|
2360
|
+
* Get the next item in the tree traversal.
|
|
2361
|
+
*/
|
|
2362
|
+
static int
|
|
2363
|
+
tree_next(struct tree *t)
|
|
2364
|
+
{
|
|
2365
|
+
int r;
|
|
2366
|
+
|
|
2367
|
+
while (t->stack != NULL) {
|
|
2368
|
+
/* If there's an open dir, get the next entry from there. */
|
|
2369
|
+
if (t->d != INVALID_DIR_HANDLE) {
|
|
2370
|
+
r = tree_dir_next_posix(t);
|
|
2371
|
+
if (r == 0)
|
|
2372
|
+
continue;
|
|
2373
|
+
return (r);
|
|
2374
|
+
}
|
|
2375
|
+
|
|
2376
|
+
if (t->stack->flags & needsFirstVisit) {
|
|
2377
|
+
/* Top stack item needs a regular visit. */
|
|
2378
|
+
t->current = t->stack;
|
|
2379
|
+
tree_append(t, t->stack->name.s,
|
|
2380
|
+
archive_strlen(&(t->stack->name)));
|
|
2381
|
+
/* t->dirname_length = t->path_length; */
|
|
2382
|
+
/* tree_pop(t); */
|
|
2383
|
+
t->stack->flags &= ~needsFirstVisit;
|
|
2384
|
+
return (t->visit_type = TREE_REGULAR);
|
|
2385
|
+
} else if (t->stack->flags & needsDescent) {
|
|
2386
|
+
/* Top stack item is dir to descend into. */
|
|
2387
|
+
t->current = t->stack;
|
|
2388
|
+
tree_append(t, t->stack->name.s,
|
|
2389
|
+
archive_strlen(&(t->stack->name)));
|
|
2390
|
+
t->stack->flags &= ~needsDescent;
|
|
2391
|
+
r = tree_descent(t);
|
|
2392
|
+
if (r != 0) {
|
|
2393
|
+
tree_pop(t);
|
|
2394
|
+
t->visit_type = r;
|
|
2395
|
+
} else
|
|
2396
|
+
t->visit_type = TREE_POSTDESCENT;
|
|
2397
|
+
return (t->visit_type);
|
|
2398
|
+
} else if (t->stack->flags & needsOpen) {
|
|
2399
|
+
t->stack->flags &= ~needsOpen;
|
|
2400
|
+
r = tree_dir_next_posix(t);
|
|
2401
|
+
if (r == 0)
|
|
2402
|
+
continue;
|
|
2403
|
+
return (r);
|
|
2404
|
+
} else if (t->stack->flags & needsAscent) {
|
|
2405
|
+
/* Top stack item is dir and we're done with it. */
|
|
2406
|
+
r = tree_ascend(t);
|
|
2407
|
+
tree_pop(t);
|
|
2408
|
+
t->visit_type = r != 0 ? r : TREE_POSTASCENT;
|
|
2409
|
+
return (t->visit_type);
|
|
2410
|
+
} else {
|
|
2411
|
+
/* Top item on stack is dead. */
|
|
2412
|
+
tree_pop(t);
|
|
2413
|
+
t->flags &= ~hasLstat;
|
|
2414
|
+
t->flags &= ~hasStat;
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2417
|
+
return (t->visit_type = 0);
|
|
2418
|
+
}
|
|
2419
|
+
|
|
2420
|
+
static int
|
|
2421
|
+
tree_dir_next_posix(struct tree *t)
|
|
2422
|
+
{
|
|
2423
|
+
int r;
|
|
2424
|
+
const char *name;
|
|
2425
|
+
size_t namelen;
|
|
2426
|
+
|
|
2427
|
+
if (t->d == NULL) {
|
|
2428
|
+
#if defined(USE_READDIR_R)
|
|
2429
|
+
size_t dirent_size;
|
|
2430
|
+
#endif
|
|
2431
|
+
|
|
2432
|
+
#if defined(HAVE_FDOPENDIR)
|
|
2433
|
+
t->d = fdopendir(tree_dup(t->working_dir_fd));
|
|
2434
|
+
#else /* HAVE_FDOPENDIR */
|
|
2435
|
+
if (tree_enter_working_dir(t) == 0) {
|
|
2436
|
+
t->d = opendir(".");
|
|
2437
|
+
#ifdef HAVE_DIRFD
|
|
2438
|
+
__archive_ensure_cloexec_flag(dirfd(t->d));
|
|
2439
|
+
#endif
|
|
2440
|
+
}
|
|
2441
|
+
#endif /* HAVE_FDOPENDIR */
|
|
2442
|
+
if (t->d == NULL) {
|
|
2443
|
+
r = tree_ascend(t); /* Undo "chdir" */
|
|
2444
|
+
tree_pop(t);
|
|
2445
|
+
t->tree_errno = errno;
|
|
2446
|
+
t->visit_type = r != 0 ? r : TREE_ERROR_DIR;
|
|
2447
|
+
return (t->visit_type);
|
|
2448
|
+
}
|
|
2449
|
+
#if defined(USE_READDIR_R)
|
|
2450
|
+
dirent_size = offsetof(struct dirent, d_name) +
|
|
2451
|
+
t->filesystem_table[t->current->filesystem_id].name_max + 1;
|
|
2452
|
+
if (t->dirent == NULL || t->dirent_allocated < dirent_size) {
|
|
2453
|
+
free(t->dirent);
|
|
2454
|
+
t->dirent = malloc(dirent_size);
|
|
2455
|
+
if (t->dirent == NULL) {
|
|
2456
|
+
closedir(t->d);
|
|
2457
|
+
t->d = INVALID_DIR_HANDLE;
|
|
2458
|
+
(void)tree_ascend(t);
|
|
2459
|
+
tree_pop(t);
|
|
2460
|
+
t->tree_errno = ENOMEM;
|
|
2461
|
+
t->visit_type = TREE_ERROR_DIR;
|
|
2462
|
+
return (t->visit_type);
|
|
2463
|
+
}
|
|
2464
|
+
t->dirent_allocated = dirent_size;
|
|
2465
|
+
}
|
|
2466
|
+
#endif /* USE_READDIR_R */
|
|
2467
|
+
}
|
|
2468
|
+
for (;;) {
|
|
2469
|
+
errno = 0;
|
|
2470
|
+
#if defined(USE_READDIR_R)
|
|
2471
|
+
r = readdir_r(t->d, t->dirent, &t->de);
|
|
2472
|
+
#ifdef _AIX
|
|
2473
|
+
/* Note: According to the man page, return value 9 indicates
|
|
2474
|
+
* that the readdir_r was not successful and the error code
|
|
2475
|
+
* is set to the global errno variable. And then if the end
|
|
2476
|
+
* of directory entries was reached, the return value is 9
|
|
2477
|
+
* and the third parameter is set to NULL and errno is
|
|
2478
|
+
* unchanged. */
|
|
2479
|
+
if (r == 9)
|
|
2480
|
+
r = errno;
|
|
2481
|
+
#endif /* _AIX */
|
|
2482
|
+
if (r != 0 || t->de == NULL) {
|
|
2483
|
+
#else
|
|
2484
|
+
t->de = readdir(t->d);
|
|
2485
|
+
if (t->de == NULL) {
|
|
2486
|
+
r = errno;
|
|
2487
|
+
#endif
|
|
2488
|
+
closedir(t->d);
|
|
2489
|
+
t->d = INVALID_DIR_HANDLE;
|
|
2490
|
+
if (r != 0) {
|
|
2491
|
+
t->tree_errno = r;
|
|
2492
|
+
t->visit_type = TREE_ERROR_DIR;
|
|
2493
|
+
return (t->visit_type);
|
|
2494
|
+
} else
|
|
2495
|
+
return (0);
|
|
2496
|
+
}
|
|
2497
|
+
name = t->de->d_name;
|
|
2498
|
+
namelen = D_NAMELEN(t->de);
|
|
2499
|
+
t->flags &= ~hasLstat;
|
|
2500
|
+
t->flags &= ~hasStat;
|
|
2501
|
+
if (name[0] == '.' && name[1] == '\0')
|
|
2502
|
+
continue;
|
|
2503
|
+
if (name[0] == '.' && name[1] == '.' && name[2] == '\0')
|
|
2504
|
+
continue;
|
|
2505
|
+
tree_append(t, name, namelen);
|
|
2506
|
+
return (t->visit_type = TREE_REGULAR);
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
|
|
2510
|
+
|
|
2511
|
+
/*
|
|
2512
|
+
* Get the stat() data for the entry just returned from tree_next().
|
|
2513
|
+
*/
|
|
2514
|
+
static const struct stat *
|
|
2515
|
+
tree_current_stat(struct tree *t)
|
|
2516
|
+
{
|
|
2517
|
+
if (!(t->flags & hasStat)) {
|
|
2518
|
+
#ifdef HAVE_FSTATAT
|
|
2519
|
+
if (fstatat(tree_current_dir_fd(t),
|
|
2520
|
+
tree_current_access_path(t), &t->st, 0) != 0)
|
|
2521
|
+
#else
|
|
2522
|
+
if (tree_enter_working_dir(t) != 0)
|
|
2523
|
+
return NULL;
|
|
2524
|
+
if (la_stat(tree_current_access_path(t), &t->st) != 0)
|
|
2525
|
+
#endif
|
|
2526
|
+
return NULL;
|
|
2527
|
+
t->flags |= hasStat;
|
|
2528
|
+
}
|
|
2529
|
+
return (&t->st);
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
/*
|
|
2533
|
+
* Get the lstat() data for the entry just returned from tree_next().
|
|
2534
|
+
*/
|
|
2535
|
+
static const struct stat *
|
|
2536
|
+
tree_current_lstat(struct tree *t)
|
|
2537
|
+
{
|
|
2538
|
+
if (!(t->flags & hasLstat)) {
|
|
2539
|
+
#ifdef HAVE_FSTATAT
|
|
2540
|
+
if (fstatat(tree_current_dir_fd(t),
|
|
2541
|
+
tree_current_access_path(t), &t->lst,
|
|
2542
|
+
AT_SYMLINK_NOFOLLOW) != 0)
|
|
2543
|
+
#else
|
|
2544
|
+
if (tree_enter_working_dir(t) != 0)
|
|
2545
|
+
return NULL;
|
|
2546
|
+
if (lstat(tree_current_access_path(t), &t->lst) != 0)
|
|
2547
|
+
#endif
|
|
2548
|
+
return NULL;
|
|
2549
|
+
t->flags |= hasLstat;
|
|
2550
|
+
}
|
|
2551
|
+
return (&t->lst);
|
|
2552
|
+
}
|
|
2553
|
+
|
|
2554
|
+
/*
|
|
2555
|
+
* Test whether current entry is a dir or link to a dir.
|
|
2556
|
+
*/
|
|
2557
|
+
static int
|
|
2558
|
+
tree_current_is_dir(struct tree *t)
|
|
2559
|
+
{
|
|
2560
|
+
const struct stat *st;
|
|
2561
|
+
/*
|
|
2562
|
+
* If we already have lstat() info, then try some
|
|
2563
|
+
* cheap tests to determine if this is a dir.
|
|
2564
|
+
*/
|
|
2565
|
+
if (t->flags & hasLstat) {
|
|
2566
|
+
/* If lstat() says it's a dir, it must be a dir. */
|
|
2567
|
+
st = tree_current_lstat(t);
|
|
2568
|
+
if (st == NULL)
|
|
2569
|
+
return 0;
|
|
2570
|
+
if (S_ISDIR(st->st_mode))
|
|
2571
|
+
return 1;
|
|
2572
|
+
/* Not a dir; might be a link to a dir. */
|
|
2573
|
+
/* If it's not a link, then it's not a link to a dir. */
|
|
2574
|
+
if (!S_ISLNK(st->st_mode))
|
|
2575
|
+
return 0;
|
|
2576
|
+
/*
|
|
2577
|
+
* It's a link, but we don't know what it's a link to,
|
|
2578
|
+
* so we'll have to use stat().
|
|
2579
|
+
*/
|
|
2580
|
+
}
|
|
2581
|
+
|
|
2582
|
+
st = tree_current_stat(t);
|
|
2583
|
+
/* If we can't stat it, it's not a dir. */
|
|
2584
|
+
if (st == NULL)
|
|
2585
|
+
return 0;
|
|
2586
|
+
/* Use the definitive test. Hopefully this is cached. */
|
|
2587
|
+
return (S_ISDIR(st->st_mode));
|
|
2588
|
+
}
|
|
2589
|
+
|
|
2590
|
+
/*
|
|
2591
|
+
* Test whether current entry is a physical directory. Usually, we
|
|
2592
|
+
* already have at least one of stat() or lstat() in memory, so we
|
|
2593
|
+
* use tricks to try to avoid an extra trip to the disk.
|
|
2594
|
+
*/
|
|
2595
|
+
static int
|
|
2596
|
+
tree_current_is_physical_dir(struct tree *t)
|
|
2597
|
+
{
|
|
2598
|
+
const struct stat *st;
|
|
2599
|
+
|
|
2600
|
+
/*
|
|
2601
|
+
* If stat() says it isn't a dir, then it's not a dir.
|
|
2602
|
+
* If stat() data is cached, this check is free, so do it first.
|
|
2603
|
+
*/
|
|
2604
|
+
if (t->flags & hasStat) {
|
|
2605
|
+
st = tree_current_stat(t);
|
|
2606
|
+
if (st == NULL)
|
|
2607
|
+
return (0);
|
|
2608
|
+
if (!S_ISDIR(st->st_mode))
|
|
2609
|
+
return (0);
|
|
2610
|
+
}
|
|
2611
|
+
|
|
2612
|
+
/*
|
|
2613
|
+
* Either stat() said it was a dir (in which case, we have
|
|
2614
|
+
* to determine whether it's really a link to a dir) or
|
|
2615
|
+
* stat() info wasn't available. So we use lstat(), which
|
|
2616
|
+
* hopefully is already cached.
|
|
2617
|
+
*/
|
|
2618
|
+
|
|
2619
|
+
st = tree_current_lstat(t);
|
|
2620
|
+
/* If we can't stat it, it's not a dir. */
|
|
2621
|
+
if (st == NULL)
|
|
2622
|
+
return 0;
|
|
2623
|
+
/* Use the definitive test. Hopefully this is cached. */
|
|
2624
|
+
return (S_ISDIR(st->st_mode));
|
|
2625
|
+
}
|
|
2626
|
+
|
|
2627
|
+
/*
|
|
2628
|
+
* Test whether the same file has been in the tree as its parent.
|
|
2629
|
+
*/
|
|
2630
|
+
static int
|
|
2631
|
+
tree_target_is_same_as_parent(struct tree *t, const struct stat *st)
|
|
2632
|
+
{
|
|
2633
|
+
struct tree_entry *te;
|
|
2634
|
+
|
|
2635
|
+
for (te = t->current->parent; te != NULL; te = te->parent) {
|
|
2636
|
+
if (te->dev == (int64_t)st->st_dev &&
|
|
2637
|
+
te->ino == (int64_t)st->st_ino)
|
|
2638
|
+
return (1);
|
|
2639
|
+
}
|
|
2640
|
+
return (0);
|
|
2641
|
+
}
|
|
2642
|
+
|
|
2643
|
+
/*
|
|
2644
|
+
* Test whether the current file is symbolic link target and
|
|
2645
|
+
* on the other filesystem.
|
|
2646
|
+
*/
|
|
2647
|
+
static int
|
|
2648
|
+
tree_current_is_symblic_link_target(struct tree *t)
|
|
2649
|
+
{
|
|
2650
|
+
static const struct stat *lst, *st;
|
|
2651
|
+
|
|
2652
|
+
lst = tree_current_lstat(t);
|
|
2653
|
+
st = tree_current_stat(t);
|
|
2654
|
+
return (st != NULL && lst != NULL &&
|
|
2655
|
+
(int64_t)st->st_dev == t->current_filesystem->dev &&
|
|
2656
|
+
st->st_dev != lst->st_dev);
|
|
2657
|
+
}
|
|
2658
|
+
|
|
2659
|
+
/*
|
|
2660
|
+
* Return the access path for the entry just returned from tree_next().
|
|
2661
|
+
*/
|
|
2662
|
+
static const char *
|
|
2663
|
+
tree_current_access_path(struct tree *t)
|
|
2664
|
+
{
|
|
2665
|
+
return (t->basename);
|
|
2666
|
+
}
|
|
2667
|
+
|
|
2668
|
+
/*
|
|
2669
|
+
* Return the full path for the entry just returned from tree_next().
|
|
2670
|
+
*/
|
|
2671
|
+
static const char *
|
|
2672
|
+
tree_current_path(struct tree *t)
|
|
2673
|
+
{
|
|
2674
|
+
return (t->path.s);
|
|
2675
|
+
}
|
|
2676
|
+
|
|
2677
|
+
/*
|
|
2678
|
+
* Terminate the traversal.
|
|
2679
|
+
*/
|
|
2680
|
+
static void
|
|
2681
|
+
tree_close(struct tree *t)
|
|
2682
|
+
{
|
|
2683
|
+
|
|
2684
|
+
if (t == NULL)
|
|
2685
|
+
return;
|
|
2686
|
+
if (t->entry_fd >= 0) {
|
|
2687
|
+
close_and_restore_time(t->entry_fd, t, &t->restore_time);
|
|
2688
|
+
t->entry_fd = -1;
|
|
2689
|
+
}
|
|
2690
|
+
/* Close the handle of readdir(). */
|
|
2691
|
+
if (t->d != INVALID_DIR_HANDLE) {
|
|
2692
|
+
closedir(t->d);
|
|
2693
|
+
t->d = INVALID_DIR_HANDLE;
|
|
2694
|
+
}
|
|
2695
|
+
/* Release anything remaining in the stack. */
|
|
2696
|
+
while (t->stack != NULL) {
|
|
2697
|
+
if (t->stack->flags & isDirLink)
|
|
2698
|
+
close(t->stack->symlink_parent_fd);
|
|
2699
|
+
tree_pop(t);
|
|
2700
|
+
}
|
|
2701
|
+
if (t->working_dir_fd >= 0) {
|
|
2702
|
+
close(t->working_dir_fd);
|
|
2703
|
+
t->working_dir_fd = -1;
|
|
2704
|
+
}
|
|
2705
|
+
if (t->initial_dir_fd >= 0) {
|
|
2706
|
+
close(t->initial_dir_fd);
|
|
2707
|
+
t->initial_dir_fd = -1;
|
|
2708
|
+
}
|
|
2709
|
+
}
|
|
2710
|
+
|
|
2711
|
+
/*
|
|
2712
|
+
* Release any resources.
|
|
2713
|
+
*/
|
|
2714
|
+
static void
|
|
2715
|
+
tree_free(struct tree *t)
|
|
2716
|
+
{
|
|
2717
|
+
int i;
|
|
2718
|
+
|
|
2719
|
+
if (t == NULL)
|
|
2720
|
+
return;
|
|
2721
|
+
archive_string_free(&t->path);
|
|
2722
|
+
#if defined(USE_READDIR_R)
|
|
2723
|
+
free(t->dirent);
|
|
2724
|
+
#endif
|
|
2725
|
+
free(t->sparse_list);
|
|
2726
|
+
for (i = 0; i < t->max_filesystem_id; i++)
|
|
2727
|
+
free(t->filesystem_table[i].allocation_ptr);
|
|
2728
|
+
free(t->filesystem_table);
|
|
2729
|
+
free(t);
|
|
2730
|
+
}
|
|
2731
|
+
|
|
2732
|
+
#endif
|