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,1756 @@
|
|
|
1
|
+
/*-
|
|
2
|
+
* Copyright (c) 2003-2011 Tim Kientzle
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* Redistribution and use in source and binary forms, with or without
|
|
6
|
+
* modification, are permitted provided that the following conditions
|
|
7
|
+
* are met:
|
|
8
|
+
* 1. Redistributions of source code must retain the above copyright
|
|
9
|
+
* notice, this list of conditions and the following disclaimer.
|
|
10
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
|
11
|
+
* notice, this list of conditions and the following disclaimer in the
|
|
12
|
+
* documentation and/or other materials provided with the distribution.
|
|
13
|
+
*
|
|
14
|
+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
|
15
|
+
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
16
|
+
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
17
|
+
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
18
|
+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
19
|
+
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
20
|
+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
21
|
+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
22
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
23
|
+
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/*
|
|
27
|
+
* This file contains the "essential" portions of the read API, that
|
|
28
|
+
* is, stuff that will probably always be used by any client that
|
|
29
|
+
* actually needs to read an archive. Optional pieces have been, as
|
|
30
|
+
* far as possible, separated out into separate files to avoid
|
|
31
|
+
* needlessly bloating statically-linked clients.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
#include "archive_platform.h"
|
|
35
|
+
__FBSDID("$FreeBSD: head/lib/libarchive/archive_read.c 201157 2009-12-29 05:30:23Z kientzle $");
|
|
36
|
+
|
|
37
|
+
#ifdef HAVE_ERRNO_H
|
|
38
|
+
#include <errno.h>
|
|
39
|
+
#endif
|
|
40
|
+
#include <stdio.h>
|
|
41
|
+
#ifdef HAVE_STDLIB_H
|
|
42
|
+
#include <stdlib.h>
|
|
43
|
+
#endif
|
|
44
|
+
#ifdef HAVE_STRING_H
|
|
45
|
+
#include <string.h>
|
|
46
|
+
#endif
|
|
47
|
+
#ifdef HAVE_UNISTD_H
|
|
48
|
+
#include <unistd.h>
|
|
49
|
+
#endif
|
|
50
|
+
|
|
51
|
+
#include "archive.h"
|
|
52
|
+
#include "archive_entry.h"
|
|
53
|
+
#include "archive_private.h"
|
|
54
|
+
#include "archive_read_private.h"
|
|
55
|
+
|
|
56
|
+
#define minimum(a, b) (a < b ? a : b)
|
|
57
|
+
|
|
58
|
+
static int choose_filters(struct archive_read *);
|
|
59
|
+
static int choose_format(struct archive_read *);
|
|
60
|
+
static int close_filters(struct archive_read *);
|
|
61
|
+
static int64_t _archive_filter_bytes(struct archive *, int);
|
|
62
|
+
static int _archive_filter_code(struct archive *, int);
|
|
63
|
+
static const char *_archive_filter_name(struct archive *, int);
|
|
64
|
+
static int _archive_filter_count(struct archive *);
|
|
65
|
+
static int _archive_read_close(struct archive *);
|
|
66
|
+
static int _archive_read_data_block(struct archive *,
|
|
67
|
+
const void **, size_t *, int64_t *);
|
|
68
|
+
static int _archive_read_free(struct archive *);
|
|
69
|
+
static int _archive_read_next_header(struct archive *,
|
|
70
|
+
struct archive_entry **);
|
|
71
|
+
static int _archive_read_next_header2(struct archive *,
|
|
72
|
+
struct archive_entry *);
|
|
73
|
+
static int64_t advance_file_pointer(struct archive_read_filter *, int64_t);
|
|
74
|
+
|
|
75
|
+
static const struct archive_vtable
|
|
76
|
+
archive_read_vtable = {
|
|
77
|
+
.archive_filter_bytes = _archive_filter_bytes,
|
|
78
|
+
.archive_filter_code = _archive_filter_code,
|
|
79
|
+
.archive_filter_name = _archive_filter_name,
|
|
80
|
+
.archive_filter_count = _archive_filter_count,
|
|
81
|
+
.archive_read_data_block = _archive_read_data_block,
|
|
82
|
+
.archive_read_next_header = _archive_read_next_header,
|
|
83
|
+
.archive_read_next_header2 = _archive_read_next_header2,
|
|
84
|
+
.archive_free = _archive_read_free,
|
|
85
|
+
.archive_close = _archive_read_close,
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/*
|
|
89
|
+
* Allocate, initialize and return a struct archive object.
|
|
90
|
+
*/
|
|
91
|
+
struct archive *
|
|
92
|
+
archive_read_new(void)
|
|
93
|
+
{
|
|
94
|
+
struct archive_read *a;
|
|
95
|
+
|
|
96
|
+
a = (struct archive_read *)calloc(1, sizeof(*a));
|
|
97
|
+
if (a == NULL)
|
|
98
|
+
return (NULL);
|
|
99
|
+
a->archive.magic = ARCHIVE_READ_MAGIC;
|
|
100
|
+
|
|
101
|
+
a->archive.state = ARCHIVE_STATE_NEW;
|
|
102
|
+
a->entry = archive_entry_new2(&a->archive);
|
|
103
|
+
a->archive.vtable = &archive_read_vtable;
|
|
104
|
+
|
|
105
|
+
a->passphrases.last = &a->passphrases.first;
|
|
106
|
+
|
|
107
|
+
return (&a->archive);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/*
|
|
111
|
+
* Record the do-not-extract-to file. This belongs in archive_read_extract.c.
|
|
112
|
+
*/
|
|
113
|
+
void
|
|
114
|
+
archive_read_extract_set_skip_file(struct archive *_a, la_int64_t d,
|
|
115
|
+
la_int64_t i)
|
|
116
|
+
{
|
|
117
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
118
|
+
|
|
119
|
+
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
|
120
|
+
ARCHIVE_STATE_ANY, "archive_read_extract_set_skip_file"))
|
|
121
|
+
return;
|
|
122
|
+
a->skip_file_set = 1;
|
|
123
|
+
a->skip_file_dev = d;
|
|
124
|
+
a->skip_file_ino = i;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/*
|
|
128
|
+
* Open the archive
|
|
129
|
+
*/
|
|
130
|
+
int
|
|
131
|
+
archive_read_open(struct archive *a, void *client_data,
|
|
132
|
+
archive_open_callback *client_opener, archive_read_callback *client_reader,
|
|
133
|
+
archive_close_callback *client_closer)
|
|
134
|
+
{
|
|
135
|
+
/* Old archive_read_open() is just a thin shell around
|
|
136
|
+
* archive_read_open1. */
|
|
137
|
+
archive_read_set_open_callback(a, client_opener);
|
|
138
|
+
archive_read_set_read_callback(a, client_reader);
|
|
139
|
+
archive_read_set_close_callback(a, client_closer);
|
|
140
|
+
archive_read_set_callback_data(a, client_data);
|
|
141
|
+
return archive_read_open1(a);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
int
|
|
146
|
+
archive_read_open2(struct archive *a, void *client_data,
|
|
147
|
+
archive_open_callback *client_opener,
|
|
148
|
+
archive_read_callback *client_reader,
|
|
149
|
+
archive_skip_callback *client_skipper,
|
|
150
|
+
archive_close_callback *client_closer)
|
|
151
|
+
{
|
|
152
|
+
/* Old archive_read_open2() is just a thin shell around
|
|
153
|
+
* archive_read_open1. */
|
|
154
|
+
archive_read_set_callback_data(a, client_data);
|
|
155
|
+
archive_read_set_open_callback(a, client_opener);
|
|
156
|
+
archive_read_set_read_callback(a, client_reader);
|
|
157
|
+
archive_read_set_skip_callback(a, client_skipper);
|
|
158
|
+
archive_read_set_close_callback(a, client_closer);
|
|
159
|
+
return archive_read_open1(a);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
static ssize_t
|
|
163
|
+
client_read_proxy(struct archive_read_filter *self, const void **buff)
|
|
164
|
+
{
|
|
165
|
+
ssize_t r;
|
|
166
|
+
r = (self->archive->client.reader)(&self->archive->archive,
|
|
167
|
+
self->data, buff);
|
|
168
|
+
return (r);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
static int64_t
|
|
172
|
+
client_skip_proxy(struct archive_read_filter *self, int64_t request)
|
|
173
|
+
{
|
|
174
|
+
if (request < 0)
|
|
175
|
+
__archive_errx(1, "Negative skip requested.");
|
|
176
|
+
if (request == 0)
|
|
177
|
+
return 0;
|
|
178
|
+
|
|
179
|
+
if (self->archive->client.skipper != NULL) {
|
|
180
|
+
/* Seek requests over 1GiB are broken down into
|
|
181
|
+
* multiple seeks. This avoids overflows when the
|
|
182
|
+
* requests get passed through 32-bit arguments. */
|
|
183
|
+
int64_t skip_limit = (int64_t)1 << 30;
|
|
184
|
+
int64_t total = 0;
|
|
185
|
+
for (;;) {
|
|
186
|
+
int64_t get, ask = request;
|
|
187
|
+
if (ask > skip_limit)
|
|
188
|
+
ask = skip_limit;
|
|
189
|
+
get = (self->archive->client.skipper)
|
|
190
|
+
(&self->archive->archive, self->data, ask);
|
|
191
|
+
total += get;
|
|
192
|
+
if (get == 0 || get == request)
|
|
193
|
+
return (total);
|
|
194
|
+
if (get > request)
|
|
195
|
+
return ARCHIVE_FATAL;
|
|
196
|
+
request -= get;
|
|
197
|
+
}
|
|
198
|
+
} else if (self->archive->client.seeker != NULL
|
|
199
|
+
&& request > 64 * 1024) {
|
|
200
|
+
/* If the client provided a seeker but not a skipper,
|
|
201
|
+
* we can use the seeker to skip forward.
|
|
202
|
+
*
|
|
203
|
+
* Note: This isn't always a good idea. The client
|
|
204
|
+
* skipper is allowed to skip by less than requested
|
|
205
|
+
* if it needs to maintain block alignment. The
|
|
206
|
+
* seeker is not allowed to play such games, so using
|
|
207
|
+
* the seeker here may be a performance loss compared
|
|
208
|
+
* to just reading and discarding. That's why we
|
|
209
|
+
* only do this for skips of over 64k.
|
|
210
|
+
*/
|
|
211
|
+
int64_t before = self->position;
|
|
212
|
+
int64_t after = (self->archive->client.seeker)
|
|
213
|
+
(&self->archive->archive, self->data, request, SEEK_CUR);
|
|
214
|
+
if (after != before + request)
|
|
215
|
+
return ARCHIVE_FATAL;
|
|
216
|
+
return after - before;
|
|
217
|
+
}
|
|
218
|
+
return 0;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
static int64_t
|
|
222
|
+
client_seek_proxy(struct archive_read_filter *self, int64_t offset, int whence)
|
|
223
|
+
{
|
|
224
|
+
/* DO NOT use the skipper here! If we transparently handled
|
|
225
|
+
* forward seek here by using the skipper, that will break
|
|
226
|
+
* other libarchive code that assumes a successful forward
|
|
227
|
+
* seek means it can also seek backwards.
|
|
228
|
+
*/
|
|
229
|
+
if (self->archive->client.seeker == NULL) {
|
|
230
|
+
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
|
|
231
|
+
"Current client reader does not support seeking a device");
|
|
232
|
+
return (ARCHIVE_FAILED);
|
|
233
|
+
}
|
|
234
|
+
return (self->archive->client.seeker)(&self->archive->archive,
|
|
235
|
+
self->data, offset, whence);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
static int
|
|
239
|
+
read_client_close_proxy(struct archive_read *a)
|
|
240
|
+
{
|
|
241
|
+
int r = ARCHIVE_OK, r2;
|
|
242
|
+
unsigned int i;
|
|
243
|
+
|
|
244
|
+
if (a->client.closer == NULL)
|
|
245
|
+
return (r);
|
|
246
|
+
for (i = 0; i < a->client.nodes; i++)
|
|
247
|
+
{
|
|
248
|
+
r2 = (a->client.closer)
|
|
249
|
+
((struct archive *)a, a->client.dataset[i].data);
|
|
250
|
+
if (r > r2)
|
|
251
|
+
r = r2;
|
|
252
|
+
}
|
|
253
|
+
return (r);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
static int
|
|
257
|
+
client_close_proxy(struct archive_read_filter *self)
|
|
258
|
+
{
|
|
259
|
+
return read_client_close_proxy(self->archive);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
static int
|
|
263
|
+
client_open_proxy(struct archive_read_filter *self)
|
|
264
|
+
{
|
|
265
|
+
int r = ARCHIVE_OK;
|
|
266
|
+
if (self->archive->client.opener != NULL)
|
|
267
|
+
r = (self->archive->client.opener)(
|
|
268
|
+
(struct archive *)self->archive, self->data);
|
|
269
|
+
return (r);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
static int
|
|
273
|
+
client_switch_proxy(struct archive_read_filter *self, unsigned int iindex)
|
|
274
|
+
{
|
|
275
|
+
int r1 = ARCHIVE_OK, r2 = ARCHIVE_OK;
|
|
276
|
+
void *data2 = NULL;
|
|
277
|
+
|
|
278
|
+
/* Don't do anything if already in the specified data node */
|
|
279
|
+
if (self->archive->client.cursor == iindex)
|
|
280
|
+
return (ARCHIVE_OK);
|
|
281
|
+
|
|
282
|
+
self->archive->client.cursor = iindex;
|
|
283
|
+
data2 = self->archive->client.dataset[self->archive->client.cursor].data;
|
|
284
|
+
if (self->archive->client.switcher != NULL)
|
|
285
|
+
{
|
|
286
|
+
r1 = r2 = (self->archive->client.switcher)
|
|
287
|
+
((struct archive *)self->archive, self->data, data2);
|
|
288
|
+
self->data = data2;
|
|
289
|
+
}
|
|
290
|
+
else
|
|
291
|
+
{
|
|
292
|
+
/* Attempt to call close and open instead */
|
|
293
|
+
if (self->archive->client.closer != NULL)
|
|
294
|
+
r1 = (self->archive->client.closer)
|
|
295
|
+
((struct archive *)self->archive, self->data);
|
|
296
|
+
self->data = data2;
|
|
297
|
+
r2 = client_open_proxy(self);
|
|
298
|
+
}
|
|
299
|
+
return (r1 < r2) ? r1 : r2;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
int
|
|
303
|
+
archive_read_set_open_callback(struct archive *_a,
|
|
304
|
+
archive_open_callback *client_opener)
|
|
305
|
+
{
|
|
306
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
307
|
+
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
|
308
|
+
"archive_read_set_open_callback");
|
|
309
|
+
a->client.opener = client_opener;
|
|
310
|
+
return ARCHIVE_OK;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
int
|
|
314
|
+
archive_read_set_read_callback(struct archive *_a,
|
|
315
|
+
archive_read_callback *client_reader)
|
|
316
|
+
{
|
|
317
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
318
|
+
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
|
319
|
+
"archive_read_set_read_callback");
|
|
320
|
+
a->client.reader = client_reader;
|
|
321
|
+
return ARCHIVE_OK;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
int
|
|
325
|
+
archive_read_set_skip_callback(struct archive *_a,
|
|
326
|
+
archive_skip_callback *client_skipper)
|
|
327
|
+
{
|
|
328
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
329
|
+
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
|
330
|
+
"archive_read_set_skip_callback");
|
|
331
|
+
a->client.skipper = client_skipper;
|
|
332
|
+
return ARCHIVE_OK;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
int
|
|
336
|
+
archive_read_set_seek_callback(struct archive *_a,
|
|
337
|
+
archive_seek_callback *client_seeker)
|
|
338
|
+
{
|
|
339
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
340
|
+
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
|
341
|
+
"archive_read_set_seek_callback");
|
|
342
|
+
a->client.seeker = client_seeker;
|
|
343
|
+
return ARCHIVE_OK;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
int
|
|
347
|
+
archive_read_set_close_callback(struct archive *_a,
|
|
348
|
+
archive_close_callback *client_closer)
|
|
349
|
+
{
|
|
350
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
351
|
+
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
|
352
|
+
"archive_read_set_close_callback");
|
|
353
|
+
a->client.closer = client_closer;
|
|
354
|
+
return ARCHIVE_OK;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
int
|
|
358
|
+
archive_read_set_switch_callback(struct archive *_a,
|
|
359
|
+
archive_switch_callback *client_switcher)
|
|
360
|
+
{
|
|
361
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
362
|
+
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
|
363
|
+
"archive_read_set_switch_callback");
|
|
364
|
+
a->client.switcher = client_switcher;
|
|
365
|
+
return ARCHIVE_OK;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
int
|
|
369
|
+
archive_read_set_callback_data(struct archive *_a, void *client_data)
|
|
370
|
+
{
|
|
371
|
+
return archive_read_set_callback_data2(_a, client_data, 0);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
int
|
|
375
|
+
archive_read_set_callback_data2(struct archive *_a, void *client_data,
|
|
376
|
+
unsigned int iindex)
|
|
377
|
+
{
|
|
378
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
379
|
+
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
|
380
|
+
"archive_read_set_callback_data2");
|
|
381
|
+
|
|
382
|
+
if (a->client.nodes == 0)
|
|
383
|
+
{
|
|
384
|
+
a->client.dataset = (struct archive_read_data_node *)
|
|
385
|
+
calloc(1, sizeof(*a->client.dataset));
|
|
386
|
+
if (a->client.dataset == NULL)
|
|
387
|
+
{
|
|
388
|
+
archive_set_error(&a->archive, ENOMEM,
|
|
389
|
+
"No memory.");
|
|
390
|
+
return ARCHIVE_FATAL;
|
|
391
|
+
}
|
|
392
|
+
a->client.nodes = 1;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (iindex > a->client.nodes - 1)
|
|
396
|
+
{
|
|
397
|
+
archive_set_error(&a->archive, EINVAL,
|
|
398
|
+
"Invalid index specified.");
|
|
399
|
+
return ARCHIVE_FATAL;
|
|
400
|
+
}
|
|
401
|
+
a->client.dataset[iindex].data = client_data;
|
|
402
|
+
a->client.dataset[iindex].begin_position = -1;
|
|
403
|
+
a->client.dataset[iindex].total_size = -1;
|
|
404
|
+
return ARCHIVE_OK;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
int
|
|
408
|
+
archive_read_add_callback_data(struct archive *_a, void *client_data,
|
|
409
|
+
unsigned int iindex)
|
|
410
|
+
{
|
|
411
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
412
|
+
void *p;
|
|
413
|
+
unsigned int i;
|
|
414
|
+
|
|
415
|
+
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
|
416
|
+
"archive_read_add_callback_data");
|
|
417
|
+
if (iindex > a->client.nodes) {
|
|
418
|
+
archive_set_error(&a->archive, EINVAL,
|
|
419
|
+
"Invalid index specified.");
|
|
420
|
+
return ARCHIVE_FATAL;
|
|
421
|
+
}
|
|
422
|
+
p = realloc(a->client.dataset, sizeof(*a->client.dataset)
|
|
423
|
+
* (++(a->client.nodes)));
|
|
424
|
+
if (p == NULL) {
|
|
425
|
+
archive_set_error(&a->archive, ENOMEM,
|
|
426
|
+
"No memory.");
|
|
427
|
+
return ARCHIVE_FATAL;
|
|
428
|
+
}
|
|
429
|
+
a->client.dataset = (struct archive_read_data_node *)p;
|
|
430
|
+
for (i = a->client.nodes - 1; i > iindex; i--) {
|
|
431
|
+
a->client.dataset[i].data = a->client.dataset[i-1].data;
|
|
432
|
+
a->client.dataset[i].begin_position = -1;
|
|
433
|
+
a->client.dataset[i].total_size = -1;
|
|
434
|
+
}
|
|
435
|
+
a->client.dataset[iindex].data = client_data;
|
|
436
|
+
a->client.dataset[iindex].begin_position = -1;
|
|
437
|
+
a->client.dataset[iindex].total_size = -1;
|
|
438
|
+
return ARCHIVE_OK;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
int
|
|
442
|
+
archive_read_append_callback_data(struct archive *_a, void *client_data)
|
|
443
|
+
{
|
|
444
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
445
|
+
return archive_read_add_callback_data(_a, client_data, a->client.nodes);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
int
|
|
449
|
+
archive_read_prepend_callback_data(struct archive *_a, void *client_data)
|
|
450
|
+
{
|
|
451
|
+
return archive_read_add_callback_data(_a, client_data, 0);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
static const struct archive_read_filter_vtable
|
|
455
|
+
none_reader_vtable = {
|
|
456
|
+
.read = client_read_proxy,
|
|
457
|
+
.close = client_close_proxy,
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
int
|
|
461
|
+
archive_read_open1(struct archive *_a)
|
|
462
|
+
{
|
|
463
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
464
|
+
struct archive_read_filter *filter, *tmp;
|
|
465
|
+
int slot, e = ARCHIVE_OK;
|
|
466
|
+
|
|
467
|
+
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
|
468
|
+
"archive_read_open");
|
|
469
|
+
archive_clear_error(&a->archive);
|
|
470
|
+
|
|
471
|
+
if (a->client.reader == NULL) {
|
|
472
|
+
archive_set_error(&a->archive, EINVAL,
|
|
473
|
+
"No reader function provided to archive_read_open");
|
|
474
|
+
a->archive.state = ARCHIVE_STATE_FATAL;
|
|
475
|
+
return (ARCHIVE_FATAL);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/* Open data source. */
|
|
479
|
+
if (a->client.opener != NULL) {
|
|
480
|
+
e = (a->client.opener)(&a->archive, a->client.dataset[0].data);
|
|
481
|
+
if (e != 0) {
|
|
482
|
+
/* If the open failed, call the closer to clean up. */
|
|
483
|
+
read_client_close_proxy(a);
|
|
484
|
+
return (e);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
filter = calloc(1, sizeof(*filter));
|
|
489
|
+
if (filter == NULL)
|
|
490
|
+
return (ARCHIVE_FATAL);
|
|
491
|
+
filter->bidder = NULL;
|
|
492
|
+
filter->upstream = NULL;
|
|
493
|
+
filter->archive = a;
|
|
494
|
+
filter->data = a->client.dataset[0].data;
|
|
495
|
+
filter->vtable = &none_reader_vtable;
|
|
496
|
+
filter->name = "none";
|
|
497
|
+
filter->code = ARCHIVE_FILTER_NONE;
|
|
498
|
+
filter->can_skip = 1;
|
|
499
|
+
filter->can_seek = 1;
|
|
500
|
+
|
|
501
|
+
a->client.dataset[0].begin_position = 0;
|
|
502
|
+
if (!a->filter || !a->bypass_filter_bidding)
|
|
503
|
+
{
|
|
504
|
+
a->filter = filter;
|
|
505
|
+
/* Build out the input pipeline. */
|
|
506
|
+
e = choose_filters(a);
|
|
507
|
+
if (e < ARCHIVE_WARN) {
|
|
508
|
+
a->archive.state = ARCHIVE_STATE_FATAL;
|
|
509
|
+
return (ARCHIVE_FATAL);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
else
|
|
513
|
+
{
|
|
514
|
+
/* Need to add "NONE" type filter at the end of the filter chain */
|
|
515
|
+
tmp = a->filter;
|
|
516
|
+
while (tmp->upstream)
|
|
517
|
+
tmp = tmp->upstream;
|
|
518
|
+
tmp->upstream = filter;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (!a->format)
|
|
522
|
+
{
|
|
523
|
+
slot = choose_format(a);
|
|
524
|
+
if (slot < 0) {
|
|
525
|
+
close_filters(a);
|
|
526
|
+
a->archive.state = ARCHIVE_STATE_FATAL;
|
|
527
|
+
return (ARCHIVE_FATAL);
|
|
528
|
+
}
|
|
529
|
+
a->format = &(a->formats[slot]);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
a->archive.state = ARCHIVE_STATE_HEADER;
|
|
533
|
+
|
|
534
|
+
/* Ensure libarchive starts from the first node in a multivolume set */
|
|
535
|
+
client_switch_proxy(a->filter, 0);
|
|
536
|
+
return (e);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/*
|
|
540
|
+
* Allow each registered stream transform to bid on whether
|
|
541
|
+
* it wants to handle this stream. Repeat until we've finished
|
|
542
|
+
* building the pipeline.
|
|
543
|
+
*/
|
|
544
|
+
|
|
545
|
+
/* We won't build a filter pipeline with more stages than this. */
|
|
546
|
+
#define MAX_NUMBER_FILTERS 25
|
|
547
|
+
|
|
548
|
+
static int
|
|
549
|
+
choose_filters(struct archive_read *a)
|
|
550
|
+
{
|
|
551
|
+
int number_bidders, i, bid, best_bid, number_filters;
|
|
552
|
+
struct archive_read_filter_bidder *bidder, *best_bidder;
|
|
553
|
+
struct archive_read_filter *filter;
|
|
554
|
+
ssize_t avail;
|
|
555
|
+
int r;
|
|
556
|
+
|
|
557
|
+
for (number_filters = 0; number_filters < MAX_NUMBER_FILTERS; ++number_filters) {
|
|
558
|
+
number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
|
|
559
|
+
|
|
560
|
+
best_bid = 0;
|
|
561
|
+
best_bidder = NULL;
|
|
562
|
+
|
|
563
|
+
bidder = a->bidders;
|
|
564
|
+
for (i = 0; i < number_bidders; i++, bidder++) {
|
|
565
|
+
if (bidder->vtable == NULL)
|
|
566
|
+
continue;
|
|
567
|
+
bid = (bidder->vtable->bid)(bidder, a->filter);
|
|
568
|
+
if (bid > best_bid) {
|
|
569
|
+
best_bid = bid;
|
|
570
|
+
best_bidder = bidder;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/* If no bidder, we're done. */
|
|
575
|
+
if (best_bidder == NULL) {
|
|
576
|
+
/* Verify the filter by asking it for some data. */
|
|
577
|
+
__archive_read_filter_ahead(a->filter, 1, &avail);
|
|
578
|
+
if (avail < 0) {
|
|
579
|
+
__archive_read_free_filters(a);
|
|
580
|
+
return (ARCHIVE_FATAL);
|
|
581
|
+
}
|
|
582
|
+
return (ARCHIVE_OK);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
filter
|
|
586
|
+
= (struct archive_read_filter *)calloc(1, sizeof(*filter));
|
|
587
|
+
if (filter == NULL)
|
|
588
|
+
return (ARCHIVE_FATAL);
|
|
589
|
+
filter->bidder = best_bidder;
|
|
590
|
+
filter->archive = a;
|
|
591
|
+
filter->upstream = a->filter;
|
|
592
|
+
a->filter = filter;
|
|
593
|
+
r = (best_bidder->vtable->init)(a->filter);
|
|
594
|
+
if (r != ARCHIVE_OK) {
|
|
595
|
+
__archive_read_free_filters(a);
|
|
596
|
+
return (ARCHIVE_FATAL);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
|
600
|
+
"Input requires too many filters for decoding");
|
|
601
|
+
return (ARCHIVE_FATAL);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
int
|
|
605
|
+
__archive_read_header(struct archive_read *a, struct archive_entry *entry)
|
|
606
|
+
{
|
|
607
|
+
if (!a->filter->vtable->read_header)
|
|
608
|
+
return (ARCHIVE_OK);
|
|
609
|
+
return a->filter->vtable->read_header(a->filter, entry);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/*
|
|
613
|
+
* Read header of next entry.
|
|
614
|
+
*/
|
|
615
|
+
static int
|
|
616
|
+
_archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
|
|
617
|
+
{
|
|
618
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
619
|
+
int r1 = ARCHIVE_OK, r2;
|
|
620
|
+
|
|
621
|
+
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
|
622
|
+
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
|
|
623
|
+
"archive_read_next_header");
|
|
624
|
+
|
|
625
|
+
archive_entry_clear(entry);
|
|
626
|
+
archive_clear_error(&a->archive);
|
|
627
|
+
|
|
628
|
+
/*
|
|
629
|
+
* If client didn't consume entire data, skip any remainder
|
|
630
|
+
* (This is especially important for GNU incremental directories.)
|
|
631
|
+
*/
|
|
632
|
+
if (a->archive.state == ARCHIVE_STATE_DATA) {
|
|
633
|
+
r1 = archive_read_data_skip(&a->archive);
|
|
634
|
+
if (r1 == ARCHIVE_EOF)
|
|
635
|
+
archive_set_error(&a->archive, EIO,
|
|
636
|
+
"Premature end-of-file.");
|
|
637
|
+
if (r1 == ARCHIVE_EOF || r1 == ARCHIVE_FATAL) {
|
|
638
|
+
a->archive.state = ARCHIVE_STATE_FATAL;
|
|
639
|
+
return (ARCHIVE_FATAL);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/* Record start-of-header offset in uncompressed stream. */
|
|
644
|
+
a->header_position = a->filter->position;
|
|
645
|
+
|
|
646
|
+
++_a->file_count;
|
|
647
|
+
r2 = (a->format->read_header)(a, entry);
|
|
648
|
+
|
|
649
|
+
/*
|
|
650
|
+
* EOF and FATAL are persistent at this layer. By
|
|
651
|
+
* modifying the state, we guarantee that future calls to
|
|
652
|
+
* read a header or read data will fail.
|
|
653
|
+
*/
|
|
654
|
+
switch (r2) {
|
|
655
|
+
case ARCHIVE_EOF:
|
|
656
|
+
a->archive.state = ARCHIVE_STATE_EOF;
|
|
657
|
+
--_a->file_count;/* Revert a file counter. */
|
|
658
|
+
break;
|
|
659
|
+
case ARCHIVE_OK:
|
|
660
|
+
a->archive.state = ARCHIVE_STATE_DATA;
|
|
661
|
+
break;
|
|
662
|
+
case ARCHIVE_WARN:
|
|
663
|
+
a->archive.state = ARCHIVE_STATE_DATA;
|
|
664
|
+
break;
|
|
665
|
+
case ARCHIVE_RETRY:
|
|
666
|
+
break;
|
|
667
|
+
case ARCHIVE_FATAL:
|
|
668
|
+
a->archive.state = ARCHIVE_STATE_FATAL;
|
|
669
|
+
break;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
__archive_reset_read_data(&a->archive);
|
|
673
|
+
|
|
674
|
+
a->data_start_node = a->client.cursor;
|
|
675
|
+
/* EOF always wins; otherwise return the worst error. */
|
|
676
|
+
return (r2 < r1 || r2 == ARCHIVE_EOF) ? r2 : r1;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
static int
|
|
680
|
+
_archive_read_next_header(struct archive *_a, struct archive_entry **entryp)
|
|
681
|
+
{
|
|
682
|
+
int ret;
|
|
683
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
684
|
+
*entryp = NULL;
|
|
685
|
+
ret = _archive_read_next_header2(_a, a->entry);
|
|
686
|
+
*entryp = a->entry;
|
|
687
|
+
return ret;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
/*
|
|
691
|
+
* Allow each registered format to bid on whether it wants to handle
|
|
692
|
+
* the next entry. Return index of winning bidder.
|
|
693
|
+
*/
|
|
694
|
+
static int
|
|
695
|
+
choose_format(struct archive_read *a)
|
|
696
|
+
{
|
|
697
|
+
int slots;
|
|
698
|
+
int i;
|
|
699
|
+
int bid, best_bid;
|
|
700
|
+
int best_bid_slot;
|
|
701
|
+
|
|
702
|
+
slots = sizeof(a->formats) / sizeof(a->formats[0]);
|
|
703
|
+
best_bid = -1;
|
|
704
|
+
best_bid_slot = -1;
|
|
705
|
+
|
|
706
|
+
/* Set up a->format for convenience of bidders. */
|
|
707
|
+
a->format = &(a->formats[0]);
|
|
708
|
+
for (i = 0; i < slots; i++, a->format++) {
|
|
709
|
+
if (a->format->bid) {
|
|
710
|
+
bid = (a->format->bid)(a, best_bid);
|
|
711
|
+
if (bid == ARCHIVE_FATAL)
|
|
712
|
+
return (ARCHIVE_FATAL);
|
|
713
|
+
if (a->filter->position != 0)
|
|
714
|
+
__archive_read_seek(a, 0, SEEK_SET);
|
|
715
|
+
if ((bid > best_bid) || (best_bid_slot < 0)) {
|
|
716
|
+
best_bid = bid;
|
|
717
|
+
best_bid_slot = i;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/*
|
|
723
|
+
* There were no bidders; this is a serious programmer error
|
|
724
|
+
* and demands a quick and definitive abort.
|
|
725
|
+
*/
|
|
726
|
+
if (best_bid_slot < 0) {
|
|
727
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
|
728
|
+
"No formats registered");
|
|
729
|
+
return (ARCHIVE_FATAL);
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/*
|
|
733
|
+
* There were bidders, but no non-zero bids; this means we
|
|
734
|
+
* can't support this stream.
|
|
735
|
+
*/
|
|
736
|
+
if (best_bid < 1) {
|
|
737
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
|
738
|
+
"Unrecognized archive format");
|
|
739
|
+
return (ARCHIVE_FATAL);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
return (best_bid_slot);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
/*
|
|
746
|
+
* Return the file offset (within the uncompressed data stream) where
|
|
747
|
+
* the last header started.
|
|
748
|
+
*/
|
|
749
|
+
la_int64_t
|
|
750
|
+
archive_read_header_position(struct archive *_a)
|
|
751
|
+
{
|
|
752
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
753
|
+
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
|
754
|
+
ARCHIVE_STATE_ANY, "archive_read_header_position");
|
|
755
|
+
return (a->header_position);
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
/*
|
|
759
|
+
* Returns 1 if the archive contains at least one encrypted entry.
|
|
760
|
+
* If the archive format not support encryption at all
|
|
761
|
+
* ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned.
|
|
762
|
+
* If for any other reason (e.g. not enough data read so far)
|
|
763
|
+
* we cannot say whether there are encrypted entries, then
|
|
764
|
+
* ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
|
|
765
|
+
* In general, this function will return values below zero when the
|
|
766
|
+
* reader is uncertain or totally incapable of encryption support.
|
|
767
|
+
* When this function returns 0 you can be sure that the reader
|
|
768
|
+
* supports encryption detection but no encrypted entries have
|
|
769
|
+
* been found yet.
|
|
770
|
+
*
|
|
771
|
+
* NOTE: If the metadata/header of an archive is also encrypted, you
|
|
772
|
+
* cannot rely on the number of encrypted entries. That is why this
|
|
773
|
+
* function does not return the number of encrypted entries but#
|
|
774
|
+
* just shows that there are some.
|
|
775
|
+
*/
|
|
776
|
+
int
|
|
777
|
+
archive_read_has_encrypted_entries(struct archive *_a)
|
|
778
|
+
{
|
|
779
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
780
|
+
int format_supports_encryption = archive_read_format_capabilities(_a)
|
|
781
|
+
& (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA | ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
|
|
782
|
+
|
|
783
|
+
if (!_a || !format_supports_encryption) {
|
|
784
|
+
/* Format in general doesn't support encryption */
|
|
785
|
+
return ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
/* A reader potentially has read enough data now. */
|
|
789
|
+
if (a->format && a->format->has_encrypted_entries) {
|
|
790
|
+
return (a->format->has_encrypted_entries)(a);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
/* For any other reason we cannot say how many entries are there. */
|
|
794
|
+
return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/*
|
|
798
|
+
* Returns a bitmask of capabilities that are supported by the archive format reader.
|
|
799
|
+
* If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned.
|
|
800
|
+
*/
|
|
801
|
+
int
|
|
802
|
+
archive_read_format_capabilities(struct archive *_a)
|
|
803
|
+
{
|
|
804
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
805
|
+
if (a && a->format && a->format->format_capabilties) {
|
|
806
|
+
return (a->format->format_capabilties)(a);
|
|
807
|
+
}
|
|
808
|
+
return ARCHIVE_READ_FORMAT_CAPS_NONE;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/*
|
|
812
|
+
* Read data from an archive entry, using a read(2)-style interface.
|
|
813
|
+
* This is a convenience routine that just calls
|
|
814
|
+
* archive_read_data_block and copies the results into the client
|
|
815
|
+
* buffer, filling any gaps with zero bytes. Clients using this
|
|
816
|
+
* API can be completely ignorant of sparse-file issues; sparse files
|
|
817
|
+
* will simply be padded with nulls.
|
|
818
|
+
*
|
|
819
|
+
* DO NOT intermingle calls to this function and archive_read_data_block
|
|
820
|
+
* to read a single entry body.
|
|
821
|
+
*/
|
|
822
|
+
la_ssize_t
|
|
823
|
+
archive_read_data(struct archive *_a, void *buff, size_t s)
|
|
824
|
+
{
|
|
825
|
+
struct archive *a = (struct archive *)_a;
|
|
826
|
+
char *dest;
|
|
827
|
+
const void *read_buf;
|
|
828
|
+
size_t bytes_read;
|
|
829
|
+
size_t len;
|
|
830
|
+
int r;
|
|
831
|
+
|
|
832
|
+
bytes_read = 0;
|
|
833
|
+
dest = (char *)buff;
|
|
834
|
+
|
|
835
|
+
while (s > 0) {
|
|
836
|
+
if (a->read_data_offset == a->read_data_output_offset &&
|
|
837
|
+
a->read_data_remaining == 0) {
|
|
838
|
+
read_buf = a->read_data_block;
|
|
839
|
+
a->read_data_is_posix_read = 1;
|
|
840
|
+
a->read_data_requested = s;
|
|
841
|
+
r = archive_read_data_block(a, &read_buf,
|
|
842
|
+
&a->read_data_remaining, &a->read_data_offset);
|
|
843
|
+
a->read_data_block = read_buf;
|
|
844
|
+
if (r == ARCHIVE_EOF)
|
|
845
|
+
return (bytes_read);
|
|
846
|
+
/*
|
|
847
|
+
* Error codes are all negative, so the status
|
|
848
|
+
* return here cannot be confused with a valid
|
|
849
|
+
* byte count. (ARCHIVE_OK is zero.)
|
|
850
|
+
*/
|
|
851
|
+
if (r < ARCHIVE_OK)
|
|
852
|
+
return (r);
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
if (a->read_data_offset < a->read_data_output_offset) {
|
|
856
|
+
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
|
|
857
|
+
"Encountered out-of-order sparse blocks");
|
|
858
|
+
return (ARCHIVE_RETRY);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/* Compute the amount of zero padding needed. */
|
|
862
|
+
if (a->read_data_output_offset + (int64_t)s <
|
|
863
|
+
a->read_data_offset) {
|
|
864
|
+
len = s;
|
|
865
|
+
} else if (a->read_data_output_offset <
|
|
866
|
+
a->read_data_offset) {
|
|
867
|
+
len = (size_t)(a->read_data_offset -
|
|
868
|
+
a->read_data_output_offset);
|
|
869
|
+
} else
|
|
870
|
+
len = 0;
|
|
871
|
+
|
|
872
|
+
/* Add zeroes. */
|
|
873
|
+
memset(dest, 0, len);
|
|
874
|
+
s -= len;
|
|
875
|
+
a->read_data_output_offset += len;
|
|
876
|
+
dest += len;
|
|
877
|
+
bytes_read += len;
|
|
878
|
+
|
|
879
|
+
/* Copy data if there is any space left. */
|
|
880
|
+
if (s > 0) {
|
|
881
|
+
len = a->read_data_remaining;
|
|
882
|
+
if (len > s)
|
|
883
|
+
len = s;
|
|
884
|
+
if (len) {
|
|
885
|
+
memcpy(dest, a->read_data_block, len);
|
|
886
|
+
s -= len;
|
|
887
|
+
a->read_data_block += len;
|
|
888
|
+
a->read_data_remaining -= len;
|
|
889
|
+
a->read_data_output_offset += len;
|
|
890
|
+
a->read_data_offset += len;
|
|
891
|
+
dest += len;
|
|
892
|
+
bytes_read += len;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
a->read_data_is_posix_read = 0;
|
|
897
|
+
a->read_data_requested = 0;
|
|
898
|
+
return (bytes_read);
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
/*
|
|
902
|
+
* Reset the read_data_* variables, used for starting a new entry.
|
|
903
|
+
*/
|
|
904
|
+
void __archive_reset_read_data(struct archive * a)
|
|
905
|
+
{
|
|
906
|
+
a->read_data_output_offset = 0;
|
|
907
|
+
a->read_data_remaining = 0;
|
|
908
|
+
a->read_data_is_posix_read = 0;
|
|
909
|
+
a->read_data_requested = 0;
|
|
910
|
+
|
|
911
|
+
/* extra resets, from rar.c */
|
|
912
|
+
a->read_data_block = NULL;
|
|
913
|
+
a->read_data_offset = 0;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
/*
|
|
917
|
+
* Skip over all remaining data in this entry.
|
|
918
|
+
*/
|
|
919
|
+
int
|
|
920
|
+
archive_read_data_skip(struct archive *_a)
|
|
921
|
+
{
|
|
922
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
923
|
+
int r;
|
|
924
|
+
const void *buff;
|
|
925
|
+
size_t size;
|
|
926
|
+
int64_t offset;
|
|
927
|
+
|
|
928
|
+
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA,
|
|
929
|
+
"archive_read_data_skip");
|
|
930
|
+
|
|
931
|
+
if (a->format->read_data_skip != NULL)
|
|
932
|
+
r = (a->format->read_data_skip)(a);
|
|
933
|
+
else {
|
|
934
|
+
while ((r = archive_read_data_block(&a->archive,
|
|
935
|
+
&buff, &size, &offset))
|
|
936
|
+
== ARCHIVE_OK)
|
|
937
|
+
;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
if (r == ARCHIVE_EOF)
|
|
941
|
+
r = ARCHIVE_OK;
|
|
942
|
+
|
|
943
|
+
a->archive.state = ARCHIVE_STATE_HEADER;
|
|
944
|
+
return (r);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
la_int64_t
|
|
948
|
+
archive_seek_data(struct archive *_a, int64_t offset, int whence)
|
|
949
|
+
{
|
|
950
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
951
|
+
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA,
|
|
952
|
+
"archive_seek_data_block");
|
|
953
|
+
|
|
954
|
+
if (a->format->seek_data == NULL) {
|
|
955
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
|
956
|
+
"Internal error: "
|
|
957
|
+
"No format_seek_data_block function registered");
|
|
958
|
+
return (ARCHIVE_FATAL);
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
return (a->format->seek_data)(a, offset, whence);
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
/*
|
|
965
|
+
* Read the next block of entry data from the archive.
|
|
966
|
+
* This is a zero-copy interface; the client receives a pointer,
|
|
967
|
+
* size, and file offset of the next available block of data.
|
|
968
|
+
*
|
|
969
|
+
* Returns ARCHIVE_OK if the operation is successful, ARCHIVE_EOF if
|
|
970
|
+
* the end of entry is encountered.
|
|
971
|
+
*/
|
|
972
|
+
static int
|
|
973
|
+
_archive_read_data_block(struct archive *_a,
|
|
974
|
+
const void **buff, size_t *size, int64_t *offset)
|
|
975
|
+
{
|
|
976
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
977
|
+
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA,
|
|
978
|
+
"archive_read_data_block");
|
|
979
|
+
|
|
980
|
+
if (a->format->read_data == NULL) {
|
|
981
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
|
982
|
+
"Internal error: "
|
|
983
|
+
"No format->read_data function registered");
|
|
984
|
+
return (ARCHIVE_FATAL);
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
return (a->format->read_data)(a, buff, size, offset);
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
static int
|
|
991
|
+
close_filters(struct archive_read *a)
|
|
992
|
+
{
|
|
993
|
+
struct archive_read_filter *f = a->filter;
|
|
994
|
+
int r = ARCHIVE_OK;
|
|
995
|
+
/* Close each filter in the pipeline. */
|
|
996
|
+
while (f != NULL) {
|
|
997
|
+
struct archive_read_filter *t = f->upstream;
|
|
998
|
+
if (!f->closed && f->vtable != NULL) {
|
|
999
|
+
int r1 = (f->vtable->close)(f);
|
|
1000
|
+
f->closed = 1;
|
|
1001
|
+
if (r1 < r)
|
|
1002
|
+
r = r1;
|
|
1003
|
+
}
|
|
1004
|
+
free(f->buffer);
|
|
1005
|
+
f->buffer = NULL;
|
|
1006
|
+
f = t;
|
|
1007
|
+
}
|
|
1008
|
+
return r;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
void
|
|
1012
|
+
__archive_read_free_filters(struct archive_read *a)
|
|
1013
|
+
{
|
|
1014
|
+
/* Make sure filters are closed and their buffers are freed */
|
|
1015
|
+
close_filters(a);
|
|
1016
|
+
|
|
1017
|
+
while (a->filter != NULL) {
|
|
1018
|
+
struct archive_read_filter *t = a->filter->upstream;
|
|
1019
|
+
free(a->filter);
|
|
1020
|
+
a->filter = t;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
/*
|
|
1025
|
+
* return the count of # of filters in use
|
|
1026
|
+
*/
|
|
1027
|
+
static int
|
|
1028
|
+
_archive_filter_count(struct archive *_a)
|
|
1029
|
+
{
|
|
1030
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
1031
|
+
struct archive_read_filter *p = a->filter;
|
|
1032
|
+
int count = 0;
|
|
1033
|
+
while(p) {
|
|
1034
|
+
count++;
|
|
1035
|
+
p = p->upstream;
|
|
1036
|
+
}
|
|
1037
|
+
return count;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
/*
|
|
1041
|
+
* Close the file and all I/O.
|
|
1042
|
+
*/
|
|
1043
|
+
static int
|
|
1044
|
+
_archive_read_close(struct archive *_a)
|
|
1045
|
+
{
|
|
1046
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
1047
|
+
int r = ARCHIVE_OK, r1 = ARCHIVE_OK;
|
|
1048
|
+
|
|
1049
|
+
archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC,
|
|
1050
|
+
ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_close");
|
|
1051
|
+
if (a->archive.state == ARCHIVE_STATE_CLOSED)
|
|
1052
|
+
return (ARCHIVE_OK);
|
|
1053
|
+
archive_clear_error(&a->archive);
|
|
1054
|
+
a->archive.state = ARCHIVE_STATE_CLOSED;
|
|
1055
|
+
|
|
1056
|
+
/* TODO: Clean up the formatters. */
|
|
1057
|
+
|
|
1058
|
+
/* Release the filter objects. */
|
|
1059
|
+
r1 = close_filters(a);
|
|
1060
|
+
if (r1 < r)
|
|
1061
|
+
r = r1;
|
|
1062
|
+
|
|
1063
|
+
return (r);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
/*
|
|
1067
|
+
* Release memory and other resources.
|
|
1068
|
+
*/
|
|
1069
|
+
static int
|
|
1070
|
+
_archive_read_free(struct archive *_a)
|
|
1071
|
+
{
|
|
1072
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
1073
|
+
struct archive_read_passphrase *p;
|
|
1074
|
+
int i, n;
|
|
1075
|
+
int slots;
|
|
1076
|
+
int r = ARCHIVE_OK;
|
|
1077
|
+
|
|
1078
|
+
if (_a == NULL)
|
|
1079
|
+
return (ARCHIVE_OK);
|
|
1080
|
+
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
|
1081
|
+
ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_free");
|
|
1082
|
+
if (a->archive.state != ARCHIVE_STATE_CLOSED
|
|
1083
|
+
&& a->archive.state != ARCHIVE_STATE_FATAL)
|
|
1084
|
+
r = archive_read_close(&a->archive);
|
|
1085
|
+
|
|
1086
|
+
/* Call cleanup functions registered by optional components. */
|
|
1087
|
+
if (a->cleanup_archive_extract != NULL)
|
|
1088
|
+
r = (a->cleanup_archive_extract)(a);
|
|
1089
|
+
|
|
1090
|
+
/* Cleanup format-specific data. */
|
|
1091
|
+
slots = sizeof(a->formats) / sizeof(a->formats[0]);
|
|
1092
|
+
for (i = 0; i < slots; i++) {
|
|
1093
|
+
a->format = &(a->formats[i]);
|
|
1094
|
+
if (a->formats[i].cleanup)
|
|
1095
|
+
(a->formats[i].cleanup)(a);
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
/* Free the filters */
|
|
1099
|
+
__archive_read_free_filters(a);
|
|
1100
|
+
|
|
1101
|
+
/* Release the bidder objects. */
|
|
1102
|
+
n = sizeof(a->bidders)/sizeof(a->bidders[0]);
|
|
1103
|
+
for (i = 0; i < n; i++) {
|
|
1104
|
+
if (a->bidders[i].vtable == NULL ||
|
|
1105
|
+
a->bidders[i].vtable->free == NULL)
|
|
1106
|
+
continue;
|
|
1107
|
+
(a->bidders[i].vtable->free)(&a->bidders[i]);
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
/* Release passphrase list. */
|
|
1111
|
+
p = a->passphrases.first;
|
|
1112
|
+
while (p != NULL) {
|
|
1113
|
+
struct archive_read_passphrase *np = p->next;
|
|
1114
|
+
|
|
1115
|
+
/* A passphrase should be cleaned. */
|
|
1116
|
+
memset(p->passphrase, 0, strlen(p->passphrase));
|
|
1117
|
+
free(p->passphrase);
|
|
1118
|
+
free(p);
|
|
1119
|
+
p = np;
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
archive_string_free(&a->archive.error_string);
|
|
1123
|
+
archive_entry_free(a->entry);
|
|
1124
|
+
a->archive.magic = 0;
|
|
1125
|
+
__archive_clean(&a->archive);
|
|
1126
|
+
free(a->client.dataset);
|
|
1127
|
+
free(a);
|
|
1128
|
+
return (r);
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
static struct archive_read_filter *
|
|
1132
|
+
get_filter(struct archive *_a, int n)
|
|
1133
|
+
{
|
|
1134
|
+
struct archive_read *a = (struct archive_read *)_a;
|
|
1135
|
+
struct archive_read_filter *f = a->filter;
|
|
1136
|
+
/* We use n == -1 for 'the last filter', which is always the
|
|
1137
|
+
* client proxy. */
|
|
1138
|
+
if (n == -1 && f != NULL) {
|
|
1139
|
+
struct archive_read_filter *last = f;
|
|
1140
|
+
f = f->upstream;
|
|
1141
|
+
while (f != NULL) {
|
|
1142
|
+
last = f;
|
|
1143
|
+
f = f->upstream;
|
|
1144
|
+
}
|
|
1145
|
+
return (last);
|
|
1146
|
+
}
|
|
1147
|
+
if (n < 0)
|
|
1148
|
+
return NULL;
|
|
1149
|
+
while (n > 0 && f != NULL) {
|
|
1150
|
+
f = f->upstream;
|
|
1151
|
+
--n;
|
|
1152
|
+
}
|
|
1153
|
+
return (f);
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
static int
|
|
1157
|
+
_archive_filter_code(struct archive *_a, int n)
|
|
1158
|
+
{
|
|
1159
|
+
struct archive_read_filter *f = get_filter(_a, n);
|
|
1160
|
+
return f == NULL ? -1 : f->code;
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
static const char *
|
|
1164
|
+
_archive_filter_name(struct archive *_a, int n)
|
|
1165
|
+
{
|
|
1166
|
+
struct archive_read_filter *f = get_filter(_a, n);
|
|
1167
|
+
return f != NULL ? f->name : NULL;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
static int64_t
|
|
1171
|
+
_archive_filter_bytes(struct archive *_a, int n)
|
|
1172
|
+
{
|
|
1173
|
+
struct archive_read_filter *f = get_filter(_a, n);
|
|
1174
|
+
return f == NULL ? -1 : f->position;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
/*
|
|
1178
|
+
* Used internally by read format handlers to register their bid and
|
|
1179
|
+
* initialization functions.
|
|
1180
|
+
*/
|
|
1181
|
+
int
|
|
1182
|
+
__archive_read_register_format(struct archive_read *a,
|
|
1183
|
+
void *format_data,
|
|
1184
|
+
const char *name,
|
|
1185
|
+
int (*bid)(struct archive_read *, int),
|
|
1186
|
+
int (*options)(struct archive_read *, const char *, const char *),
|
|
1187
|
+
int (*read_header)(struct archive_read *, struct archive_entry *),
|
|
1188
|
+
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
|
|
1189
|
+
int (*read_data_skip)(struct archive_read *),
|
|
1190
|
+
int64_t (*seek_data)(struct archive_read *, int64_t, int),
|
|
1191
|
+
int (*cleanup)(struct archive_read *),
|
|
1192
|
+
int (*format_capabilities)(struct archive_read *),
|
|
1193
|
+
int (*has_encrypted_entries)(struct archive_read *))
|
|
1194
|
+
{
|
|
1195
|
+
int i, number_slots;
|
|
1196
|
+
|
|
1197
|
+
archive_check_magic(&a->archive,
|
|
1198
|
+
ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
|
1199
|
+
"__archive_read_register_format");
|
|
1200
|
+
|
|
1201
|
+
number_slots = sizeof(a->formats) / sizeof(a->formats[0]);
|
|
1202
|
+
|
|
1203
|
+
for (i = 0; i < number_slots; i++) {
|
|
1204
|
+
if (a->formats[i].bid == bid)
|
|
1205
|
+
return (ARCHIVE_WARN); /* We've already installed */
|
|
1206
|
+
if (a->formats[i].bid == NULL) {
|
|
1207
|
+
a->formats[i].bid = bid;
|
|
1208
|
+
a->formats[i].options = options;
|
|
1209
|
+
a->formats[i].read_header = read_header;
|
|
1210
|
+
a->formats[i].read_data = read_data;
|
|
1211
|
+
a->formats[i].read_data_skip = read_data_skip;
|
|
1212
|
+
a->formats[i].seek_data = seek_data;
|
|
1213
|
+
a->formats[i].cleanup = cleanup;
|
|
1214
|
+
a->formats[i].data = format_data;
|
|
1215
|
+
a->formats[i].name = name;
|
|
1216
|
+
a->formats[i].format_capabilties = format_capabilities;
|
|
1217
|
+
a->formats[i].has_encrypted_entries = has_encrypted_entries;
|
|
1218
|
+
return (ARCHIVE_OK);
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
archive_set_error(&a->archive, ENOMEM,
|
|
1223
|
+
"Not enough slots for format registration");
|
|
1224
|
+
return (ARCHIVE_FATAL);
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
/*
|
|
1228
|
+
* Used internally by decompression routines to register their bid and
|
|
1229
|
+
* initialization functions.
|
|
1230
|
+
*/
|
|
1231
|
+
int
|
|
1232
|
+
__archive_read_register_bidder(struct archive_read *a,
|
|
1233
|
+
void *bidder_data,
|
|
1234
|
+
const char *name,
|
|
1235
|
+
const struct archive_read_filter_bidder_vtable *vtable)
|
|
1236
|
+
{
|
|
1237
|
+
struct archive_read_filter_bidder *bidder;
|
|
1238
|
+
int i, number_slots;
|
|
1239
|
+
|
|
1240
|
+
archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC,
|
|
1241
|
+
ARCHIVE_STATE_NEW, "__archive_read_register_bidder");
|
|
1242
|
+
|
|
1243
|
+
number_slots = sizeof(a->bidders) / sizeof(a->bidders[0]);
|
|
1244
|
+
|
|
1245
|
+
for (i = 0; i < number_slots; i++) {
|
|
1246
|
+
if (a->bidders[i].vtable != NULL)
|
|
1247
|
+
continue;
|
|
1248
|
+
memset(a->bidders + i, 0, sizeof(a->bidders[0]));
|
|
1249
|
+
bidder = (a->bidders + i);
|
|
1250
|
+
bidder->data = bidder_data;
|
|
1251
|
+
bidder->name = name;
|
|
1252
|
+
bidder->vtable = vtable;
|
|
1253
|
+
if (bidder->vtable->bid == NULL || bidder->vtable->init == NULL) {
|
|
1254
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
|
1255
|
+
"Internal error: "
|
|
1256
|
+
"no bid/init for filter bidder");
|
|
1257
|
+
return (ARCHIVE_FATAL);
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
return (ARCHIVE_OK);
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
archive_set_error(&a->archive, ENOMEM,
|
|
1264
|
+
"Not enough slots for filter registration");
|
|
1265
|
+
return (ARCHIVE_FATAL);
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
/*
|
|
1269
|
+
* The next section implements the peek/consume internal I/O
|
|
1270
|
+
* system used by archive readers. This system allows simple
|
|
1271
|
+
* read-ahead for consumers while preserving zero-copy operation
|
|
1272
|
+
* most of the time.
|
|
1273
|
+
*
|
|
1274
|
+
* The two key operations:
|
|
1275
|
+
* * The read-ahead function returns a pointer to a block of data
|
|
1276
|
+
* that satisfies a minimum request.
|
|
1277
|
+
* * The consume function advances the file pointer.
|
|
1278
|
+
*
|
|
1279
|
+
* In the ideal case, filters generate blocks of data
|
|
1280
|
+
* and __archive_read_ahead() just returns pointers directly into
|
|
1281
|
+
* those blocks. Then __archive_read_consume() just bumps those
|
|
1282
|
+
* pointers. Only if your request would span blocks does the I/O
|
|
1283
|
+
* layer use a copy buffer to provide you with a contiguous block of
|
|
1284
|
+
* data.
|
|
1285
|
+
*
|
|
1286
|
+
* A couple of useful idioms:
|
|
1287
|
+
* * "I just want some data." Ask for 1 byte and pay attention to
|
|
1288
|
+
* the "number of bytes available" from __archive_read_ahead().
|
|
1289
|
+
* Consume whatever you actually use.
|
|
1290
|
+
* * "I want to output a large block of data." As above, ask for 1 byte,
|
|
1291
|
+
* emit all that's available (up to whatever limit you have), consume
|
|
1292
|
+
* it all, then repeat until you're done. This effectively means that
|
|
1293
|
+
* you're passing along the blocks that came from your provider.
|
|
1294
|
+
* * "I want to peek ahead by a large amount." Ask for 4k or so, then
|
|
1295
|
+
* double and repeat until you get an error or have enough. Note
|
|
1296
|
+
* that the I/O layer will likely end up expanding its copy buffer
|
|
1297
|
+
* to fit your request, so use this technique cautiously. This
|
|
1298
|
+
* technique is used, for example, by some of the format tasting
|
|
1299
|
+
* code that has uncertain look-ahead needs.
|
|
1300
|
+
*/
|
|
1301
|
+
|
|
1302
|
+
/*
|
|
1303
|
+
* Looks ahead in the input stream:
|
|
1304
|
+
* * If 'avail' pointer is provided, that returns number of bytes available
|
|
1305
|
+
* in the current buffer, which may be much larger than requested.
|
|
1306
|
+
* * If end-of-file, *avail gets set to zero.
|
|
1307
|
+
* * If error, *avail gets error code.
|
|
1308
|
+
* * If request can be met, returns pointer to data.
|
|
1309
|
+
* * If minimum request cannot be met, returns NULL.
|
|
1310
|
+
*
|
|
1311
|
+
* Note: If you just want "some data", ask for 1 byte and pay attention
|
|
1312
|
+
* to *avail, which will have the actual amount available. If you
|
|
1313
|
+
* know exactly how many bytes you need, just ask for that and treat
|
|
1314
|
+
* a NULL return as an error.
|
|
1315
|
+
*
|
|
1316
|
+
* Important: This does NOT move the file pointer. See
|
|
1317
|
+
* __archive_read_consume() below.
|
|
1318
|
+
*/
|
|
1319
|
+
const void *
|
|
1320
|
+
__archive_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
|
|
1321
|
+
{
|
|
1322
|
+
return (__archive_read_filter_ahead(a->filter, min, avail));
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
const void *
|
|
1326
|
+
__archive_read_filter_ahead(struct archive_read_filter *filter,
|
|
1327
|
+
size_t min, ssize_t *avail)
|
|
1328
|
+
{
|
|
1329
|
+
ssize_t bytes_read;
|
|
1330
|
+
size_t tocopy;
|
|
1331
|
+
|
|
1332
|
+
if (filter->fatal) {
|
|
1333
|
+
if (avail)
|
|
1334
|
+
*avail = ARCHIVE_FATAL;
|
|
1335
|
+
return (NULL);
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
/*
|
|
1339
|
+
* Keep pulling more data until we can satisfy the request.
|
|
1340
|
+
*/
|
|
1341
|
+
for (;;) {
|
|
1342
|
+
|
|
1343
|
+
/*
|
|
1344
|
+
* If we can satisfy from the copy buffer (and the
|
|
1345
|
+
* copy buffer isn't empty), we're done. In particular,
|
|
1346
|
+
* note that min == 0 is a perfectly well-defined
|
|
1347
|
+
* request.
|
|
1348
|
+
*/
|
|
1349
|
+
if (filter->avail >= min && filter->avail > 0) {
|
|
1350
|
+
if (avail != NULL)
|
|
1351
|
+
*avail = filter->avail;
|
|
1352
|
+
return (filter->next);
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
/*
|
|
1356
|
+
* We can satisfy directly from client buffer if everything
|
|
1357
|
+
* currently in the copy buffer is still in the client buffer.
|
|
1358
|
+
*/
|
|
1359
|
+
if (filter->client_total >= filter->client_avail + filter->avail
|
|
1360
|
+
&& filter->client_avail + filter->avail >= min) {
|
|
1361
|
+
/* "Roll back" to client buffer. */
|
|
1362
|
+
filter->client_avail += filter->avail;
|
|
1363
|
+
filter->client_next -= filter->avail;
|
|
1364
|
+
/* Copy buffer is now empty. */
|
|
1365
|
+
filter->avail = 0;
|
|
1366
|
+
filter->next = filter->buffer;
|
|
1367
|
+
/* Return data from client buffer. */
|
|
1368
|
+
if (avail != NULL)
|
|
1369
|
+
*avail = filter->client_avail;
|
|
1370
|
+
return (filter->client_next);
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
/* Move data forward in copy buffer if necessary. */
|
|
1374
|
+
if (filter->next > filter->buffer &&
|
|
1375
|
+
filter->next + min > filter->buffer + filter->buffer_size) {
|
|
1376
|
+
if (filter->avail > 0)
|
|
1377
|
+
memmove(filter->buffer, filter->next,
|
|
1378
|
+
filter->avail);
|
|
1379
|
+
filter->next = filter->buffer;
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
/* If we've used up the client data, get more. */
|
|
1383
|
+
if (filter->client_avail <= 0) {
|
|
1384
|
+
if (filter->end_of_file) {
|
|
1385
|
+
if (avail != NULL)
|
|
1386
|
+
*avail = 0;
|
|
1387
|
+
return (NULL);
|
|
1388
|
+
}
|
|
1389
|
+
bytes_read = (filter->vtable->read)(filter,
|
|
1390
|
+
&filter->client_buff);
|
|
1391
|
+
if (bytes_read < 0) { /* Read error. */
|
|
1392
|
+
filter->client_total = filter->client_avail = 0;
|
|
1393
|
+
filter->client_next =
|
|
1394
|
+
filter->client_buff = NULL;
|
|
1395
|
+
filter->fatal = 1;
|
|
1396
|
+
if (avail != NULL)
|
|
1397
|
+
*avail = ARCHIVE_FATAL;
|
|
1398
|
+
return (NULL);
|
|
1399
|
+
}
|
|
1400
|
+
if (bytes_read == 0) {
|
|
1401
|
+
/* Check for another client object first */
|
|
1402
|
+
if (filter->archive->client.cursor !=
|
|
1403
|
+
filter->archive->client.nodes - 1) {
|
|
1404
|
+
if (client_switch_proxy(filter,
|
|
1405
|
+
filter->archive->client.cursor + 1)
|
|
1406
|
+
== ARCHIVE_OK)
|
|
1407
|
+
continue;
|
|
1408
|
+
}
|
|
1409
|
+
/* Premature end-of-file. */
|
|
1410
|
+
filter->client_total = filter->client_avail = 0;
|
|
1411
|
+
filter->client_next =
|
|
1412
|
+
filter->client_buff = NULL;
|
|
1413
|
+
filter->end_of_file = 1;
|
|
1414
|
+
/* Return whatever we do have. */
|
|
1415
|
+
if (avail != NULL)
|
|
1416
|
+
*avail = filter->avail;
|
|
1417
|
+
return (NULL);
|
|
1418
|
+
}
|
|
1419
|
+
filter->client_total = bytes_read;
|
|
1420
|
+
filter->client_avail = filter->client_total;
|
|
1421
|
+
filter->client_next = filter->client_buff;
|
|
1422
|
+
} else {
|
|
1423
|
+
/*
|
|
1424
|
+
* We can't satisfy the request from the copy
|
|
1425
|
+
* buffer or the existing client data, so we
|
|
1426
|
+
* need to copy more client data over to the
|
|
1427
|
+
* copy buffer.
|
|
1428
|
+
*/
|
|
1429
|
+
|
|
1430
|
+
/* Ensure the buffer is big enough. */
|
|
1431
|
+
if (min > filter->buffer_size) {
|
|
1432
|
+
size_t s, t;
|
|
1433
|
+
char *p;
|
|
1434
|
+
|
|
1435
|
+
/* Double the buffer; watch for overflow. */
|
|
1436
|
+
s = t = filter->buffer_size;
|
|
1437
|
+
if (s == 0)
|
|
1438
|
+
s = min;
|
|
1439
|
+
while (s < min) {
|
|
1440
|
+
t *= 2;
|
|
1441
|
+
if (t <= s) { /* Integer overflow! */
|
|
1442
|
+
archive_set_error(
|
|
1443
|
+
&filter->archive->archive,
|
|
1444
|
+
ENOMEM,
|
|
1445
|
+
"Unable to allocate copy"
|
|
1446
|
+
" buffer");
|
|
1447
|
+
filter->fatal = 1;
|
|
1448
|
+
if (avail != NULL)
|
|
1449
|
+
*avail = ARCHIVE_FATAL;
|
|
1450
|
+
return (NULL);
|
|
1451
|
+
}
|
|
1452
|
+
s = t;
|
|
1453
|
+
}
|
|
1454
|
+
/* Now s >= min, so allocate a new buffer. */
|
|
1455
|
+
p = (char *)malloc(s);
|
|
1456
|
+
if (p == NULL) {
|
|
1457
|
+
archive_set_error(
|
|
1458
|
+
&filter->archive->archive,
|
|
1459
|
+
ENOMEM,
|
|
1460
|
+
"Unable to allocate copy buffer");
|
|
1461
|
+
filter->fatal = 1;
|
|
1462
|
+
if (avail != NULL)
|
|
1463
|
+
*avail = ARCHIVE_FATAL;
|
|
1464
|
+
return (NULL);
|
|
1465
|
+
}
|
|
1466
|
+
/* Move data into newly-enlarged buffer. */
|
|
1467
|
+
if (filter->avail > 0)
|
|
1468
|
+
memmove(p, filter->next, filter->avail);
|
|
1469
|
+
free(filter->buffer);
|
|
1470
|
+
filter->next = filter->buffer = p;
|
|
1471
|
+
filter->buffer_size = s;
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
/* We can add client data to copy buffer. */
|
|
1475
|
+
/* First estimate: copy to fill rest of buffer. */
|
|
1476
|
+
tocopy = (filter->buffer + filter->buffer_size)
|
|
1477
|
+
- (filter->next + filter->avail);
|
|
1478
|
+
/* Don't waste time buffering more than we need to. */
|
|
1479
|
+
if (tocopy + filter->avail > min)
|
|
1480
|
+
tocopy = min - filter->avail;
|
|
1481
|
+
/* Don't copy more than is available. */
|
|
1482
|
+
if (tocopy > filter->client_avail)
|
|
1483
|
+
tocopy = filter->client_avail;
|
|
1484
|
+
|
|
1485
|
+
memcpy(filter->next + filter->avail,
|
|
1486
|
+
filter->client_next, tocopy);
|
|
1487
|
+
/* Remove this data from client buffer. */
|
|
1488
|
+
filter->client_next += tocopy;
|
|
1489
|
+
filter->client_avail -= tocopy;
|
|
1490
|
+
/* add it to copy buffer. */
|
|
1491
|
+
filter->avail += tocopy;
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
/*
|
|
1497
|
+
* Move the file pointer forward.
|
|
1498
|
+
*/
|
|
1499
|
+
int64_t
|
|
1500
|
+
__archive_read_consume(struct archive_read *a, int64_t request)
|
|
1501
|
+
{
|
|
1502
|
+
return (__archive_read_filter_consume(a->filter, request));
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
int64_t
|
|
1506
|
+
__archive_read_filter_consume(struct archive_read_filter * filter,
|
|
1507
|
+
int64_t request)
|
|
1508
|
+
{
|
|
1509
|
+
int64_t skipped;
|
|
1510
|
+
|
|
1511
|
+
if (request < 0)
|
|
1512
|
+
return ARCHIVE_FATAL;
|
|
1513
|
+
if (request == 0)
|
|
1514
|
+
return 0;
|
|
1515
|
+
|
|
1516
|
+
skipped = advance_file_pointer(filter, request);
|
|
1517
|
+
if (skipped == request)
|
|
1518
|
+
return (skipped);
|
|
1519
|
+
/* We hit EOF before we satisfied the skip request. */
|
|
1520
|
+
if (skipped < 0) /* Map error code to 0 for error message below. */
|
|
1521
|
+
skipped = 0;
|
|
1522
|
+
archive_set_error(&filter->archive->archive,
|
|
1523
|
+
ARCHIVE_ERRNO_MISC,
|
|
1524
|
+
"Truncated input file (needed %jd bytes, only %jd available)",
|
|
1525
|
+
(intmax_t)request, (intmax_t)skipped);
|
|
1526
|
+
return (ARCHIVE_FATAL);
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
/*
|
|
1530
|
+
* Advance the file pointer by the amount requested.
|
|
1531
|
+
* Returns the amount actually advanced, which may be less than the
|
|
1532
|
+
* request if EOF is encountered first.
|
|
1533
|
+
* Returns a negative value if there's an I/O error.
|
|
1534
|
+
*/
|
|
1535
|
+
static int64_t
|
|
1536
|
+
advance_file_pointer(struct archive_read_filter *filter, int64_t request)
|
|
1537
|
+
{
|
|
1538
|
+
int64_t bytes_skipped, total_bytes_skipped = 0;
|
|
1539
|
+
ssize_t bytes_read;
|
|
1540
|
+
size_t min;
|
|
1541
|
+
|
|
1542
|
+
if (filter->fatal)
|
|
1543
|
+
return (-1);
|
|
1544
|
+
|
|
1545
|
+
/* Use up the copy buffer first. */
|
|
1546
|
+
if (filter->avail > 0) {
|
|
1547
|
+
min = (size_t)minimum(request, (int64_t)filter->avail);
|
|
1548
|
+
filter->next += min;
|
|
1549
|
+
filter->avail -= min;
|
|
1550
|
+
request -= min;
|
|
1551
|
+
filter->position += min;
|
|
1552
|
+
total_bytes_skipped += min;
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
/* Then use up the client buffer. */
|
|
1556
|
+
if (filter->client_avail > 0) {
|
|
1557
|
+
min = (size_t)minimum(request, (int64_t)filter->client_avail);
|
|
1558
|
+
filter->client_next += min;
|
|
1559
|
+
filter->client_avail -= min;
|
|
1560
|
+
request -= min;
|
|
1561
|
+
filter->position += min;
|
|
1562
|
+
total_bytes_skipped += min;
|
|
1563
|
+
}
|
|
1564
|
+
if (request == 0)
|
|
1565
|
+
return (total_bytes_skipped);
|
|
1566
|
+
|
|
1567
|
+
/* If there's an optimized skip function, use it. */
|
|
1568
|
+
if (filter->can_skip != 0) {
|
|
1569
|
+
bytes_skipped = client_skip_proxy(filter, request);
|
|
1570
|
+
if (bytes_skipped < 0) { /* error */
|
|
1571
|
+
filter->fatal = 1;
|
|
1572
|
+
return (bytes_skipped);
|
|
1573
|
+
}
|
|
1574
|
+
filter->position += bytes_skipped;
|
|
1575
|
+
total_bytes_skipped += bytes_skipped;
|
|
1576
|
+
request -= bytes_skipped;
|
|
1577
|
+
if (request == 0)
|
|
1578
|
+
return (total_bytes_skipped);
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
/* Use ordinary reads as necessary to complete the request. */
|
|
1582
|
+
for (;;) {
|
|
1583
|
+
bytes_read = (filter->vtable->read)(filter, &filter->client_buff);
|
|
1584
|
+
if (bytes_read < 0) {
|
|
1585
|
+
filter->client_buff = NULL;
|
|
1586
|
+
filter->fatal = 1;
|
|
1587
|
+
return (bytes_read);
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
if (bytes_read == 0) {
|
|
1591
|
+
if (filter->archive->client.cursor !=
|
|
1592
|
+
filter->archive->client.nodes - 1) {
|
|
1593
|
+
if (client_switch_proxy(filter,
|
|
1594
|
+
filter->archive->client.cursor + 1)
|
|
1595
|
+
== ARCHIVE_OK)
|
|
1596
|
+
continue;
|
|
1597
|
+
}
|
|
1598
|
+
filter->client_buff = NULL;
|
|
1599
|
+
filter->end_of_file = 1;
|
|
1600
|
+
return (total_bytes_skipped);
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
if (bytes_read >= request) {
|
|
1604
|
+
filter->client_next =
|
|
1605
|
+
((const char *)filter->client_buff) + request;
|
|
1606
|
+
filter->client_avail = (size_t)(bytes_read - request);
|
|
1607
|
+
filter->client_total = bytes_read;
|
|
1608
|
+
total_bytes_skipped += request;
|
|
1609
|
+
filter->position += request;
|
|
1610
|
+
return (total_bytes_skipped);
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
filter->position += bytes_read;
|
|
1614
|
+
total_bytes_skipped += bytes_read;
|
|
1615
|
+
request -= bytes_read;
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
/**
|
|
1620
|
+
* Returns ARCHIVE_FAILED if seeking isn't supported.
|
|
1621
|
+
*/
|
|
1622
|
+
int64_t
|
|
1623
|
+
__archive_read_seek(struct archive_read *a, int64_t offset, int whence)
|
|
1624
|
+
{
|
|
1625
|
+
return __archive_read_filter_seek(a->filter, offset, whence);
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
int64_t
|
|
1629
|
+
__archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset,
|
|
1630
|
+
int whence)
|
|
1631
|
+
{
|
|
1632
|
+
struct archive_read_client *client;
|
|
1633
|
+
int64_t r;
|
|
1634
|
+
unsigned int cursor;
|
|
1635
|
+
|
|
1636
|
+
if (filter->closed || filter->fatal)
|
|
1637
|
+
return (ARCHIVE_FATAL);
|
|
1638
|
+
if (filter->can_seek == 0)
|
|
1639
|
+
return (ARCHIVE_FAILED);
|
|
1640
|
+
|
|
1641
|
+
client = &(filter->archive->client);
|
|
1642
|
+
switch (whence) {
|
|
1643
|
+
case SEEK_CUR:
|
|
1644
|
+
/* Adjust the offset and use SEEK_SET instead */
|
|
1645
|
+
offset += filter->position;
|
|
1646
|
+
__LA_FALLTHROUGH;
|
|
1647
|
+
case SEEK_SET:
|
|
1648
|
+
cursor = 0;
|
|
1649
|
+
while (1)
|
|
1650
|
+
{
|
|
1651
|
+
if (client->dataset[cursor].begin_position < 0 ||
|
|
1652
|
+
client->dataset[cursor].total_size < 0 ||
|
|
1653
|
+
client->dataset[cursor].begin_position +
|
|
1654
|
+
client->dataset[cursor].total_size - 1 > offset ||
|
|
1655
|
+
cursor + 1 >= client->nodes)
|
|
1656
|
+
break;
|
|
1657
|
+
r = client->dataset[cursor].begin_position +
|
|
1658
|
+
client->dataset[cursor].total_size;
|
|
1659
|
+
client->dataset[++cursor].begin_position = r;
|
|
1660
|
+
}
|
|
1661
|
+
while (1) {
|
|
1662
|
+
r = client_switch_proxy(filter, cursor);
|
|
1663
|
+
if (r != ARCHIVE_OK)
|
|
1664
|
+
return r;
|
|
1665
|
+
if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0)
|
|
1666
|
+
return r;
|
|
1667
|
+
client->dataset[cursor].total_size = r;
|
|
1668
|
+
if (client->dataset[cursor].begin_position +
|
|
1669
|
+
client->dataset[cursor].total_size - 1 > offset ||
|
|
1670
|
+
cursor + 1 >= client->nodes)
|
|
1671
|
+
break;
|
|
1672
|
+
r = client->dataset[cursor].begin_position +
|
|
1673
|
+
client->dataset[cursor].total_size;
|
|
1674
|
+
client->dataset[++cursor].begin_position = r;
|
|
1675
|
+
}
|
|
1676
|
+
offset -= client->dataset[cursor].begin_position;
|
|
1677
|
+
if (offset < 0
|
|
1678
|
+
|| offset > client->dataset[cursor].total_size)
|
|
1679
|
+
return ARCHIVE_FATAL;
|
|
1680
|
+
if ((r = client_seek_proxy(filter, offset, SEEK_SET)) < 0)
|
|
1681
|
+
return r;
|
|
1682
|
+
break;
|
|
1683
|
+
|
|
1684
|
+
case SEEK_END:
|
|
1685
|
+
cursor = 0;
|
|
1686
|
+
while (1) {
|
|
1687
|
+
if (client->dataset[cursor].begin_position < 0 ||
|
|
1688
|
+
client->dataset[cursor].total_size < 0 ||
|
|
1689
|
+
cursor + 1 >= client->nodes)
|
|
1690
|
+
break;
|
|
1691
|
+
r = client->dataset[cursor].begin_position +
|
|
1692
|
+
client->dataset[cursor].total_size;
|
|
1693
|
+
client->dataset[++cursor].begin_position = r;
|
|
1694
|
+
}
|
|
1695
|
+
while (1) {
|
|
1696
|
+
r = client_switch_proxy(filter, cursor);
|
|
1697
|
+
if (r != ARCHIVE_OK)
|
|
1698
|
+
return r;
|
|
1699
|
+
if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0)
|
|
1700
|
+
return r;
|
|
1701
|
+
client->dataset[cursor].total_size = r;
|
|
1702
|
+
r = client->dataset[cursor].begin_position +
|
|
1703
|
+
client->dataset[cursor].total_size;
|
|
1704
|
+
if (cursor + 1 >= client->nodes)
|
|
1705
|
+
break;
|
|
1706
|
+
client->dataset[++cursor].begin_position = r;
|
|
1707
|
+
}
|
|
1708
|
+
while (1) {
|
|
1709
|
+
if (r + offset >=
|
|
1710
|
+
client->dataset[cursor].begin_position)
|
|
1711
|
+
break;
|
|
1712
|
+
offset += client->dataset[cursor].total_size;
|
|
1713
|
+
if (cursor == 0)
|
|
1714
|
+
break;
|
|
1715
|
+
cursor--;
|
|
1716
|
+
r = client->dataset[cursor].begin_position +
|
|
1717
|
+
client->dataset[cursor].total_size;
|
|
1718
|
+
}
|
|
1719
|
+
offset = (r + offset) - client->dataset[cursor].begin_position;
|
|
1720
|
+
if ((r = client_switch_proxy(filter, cursor)) != ARCHIVE_OK)
|
|
1721
|
+
return r;
|
|
1722
|
+
r = client_seek_proxy(filter, offset, SEEK_SET);
|
|
1723
|
+
if (r < ARCHIVE_OK)
|
|
1724
|
+
return r;
|
|
1725
|
+
break;
|
|
1726
|
+
|
|
1727
|
+
default:
|
|
1728
|
+
return (ARCHIVE_FATAL);
|
|
1729
|
+
}
|
|
1730
|
+
r += client->dataset[cursor].begin_position;
|
|
1731
|
+
|
|
1732
|
+
if (r >= 0) {
|
|
1733
|
+
/*
|
|
1734
|
+
* Ouch. Clearing the buffer like this hurts, especially
|
|
1735
|
+
* at bid time. A lot of our efficiency at bid time comes
|
|
1736
|
+
* from having bidders reuse the data we've already read.
|
|
1737
|
+
*
|
|
1738
|
+
* TODO: If the seek request is in data we already
|
|
1739
|
+
* have, then don't call the seek callback.
|
|
1740
|
+
*
|
|
1741
|
+
* TODO: Zip seeks to end-of-file at bid time. If
|
|
1742
|
+
* other formats also start doing this, we may need to
|
|
1743
|
+
* find a way for clients to fudge the seek offset to
|
|
1744
|
+
* a block boundary.
|
|
1745
|
+
*
|
|
1746
|
+
* Hmmm... If whence was SEEK_END, we know the file
|
|
1747
|
+
* size is (r - offset). Can we use that to simplify
|
|
1748
|
+
* the TODO items above?
|
|
1749
|
+
*/
|
|
1750
|
+
filter->avail = filter->client_avail = 0;
|
|
1751
|
+
filter->next = filter->buffer;
|
|
1752
|
+
filter->position = r;
|
|
1753
|
+
filter->end_of_file = 0;
|
|
1754
|
+
}
|
|
1755
|
+
return r;
|
|
1756
|
+
}
|