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,3228 @@
|
|
1
|
+
/*-
|
2
|
+
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
|
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
|
+
#include "archive_platform.h"
|
27
|
+
|
28
|
+
#ifdef HAVE_ERRNO_H
|
29
|
+
#include <errno.h>
|
30
|
+
#endif
|
31
|
+
#ifdef HAVE_LIMITS_H
|
32
|
+
#include <limits.h>
|
33
|
+
#endif
|
34
|
+
#ifdef HAVE_STDLIB_H
|
35
|
+
#include <stdlib.h>
|
36
|
+
#endif
|
37
|
+
#ifdef HAVE_STRING_H
|
38
|
+
#include <string.h>
|
39
|
+
#endif
|
40
|
+
#ifdef HAVE_ZLIB_H
|
41
|
+
#include <zlib.h>
|
42
|
+
#endif
|
43
|
+
|
44
|
+
#include "archive.h"
|
45
|
+
#include "archive_entry.h"
|
46
|
+
#include "archive_entry_locale.h"
|
47
|
+
#include "archive_private.h"
|
48
|
+
#include "archive_read_private.h"
|
49
|
+
#include "archive_endian.h"
|
50
|
+
|
51
|
+
|
52
|
+
struct lzx_dec {
|
53
|
+
/* Decoding status. */
|
54
|
+
int state;
|
55
|
+
|
56
|
+
/*
|
57
|
+
* Window to see last decoded data, from 32KBi to 2MBi.
|
58
|
+
*/
|
59
|
+
int w_size;
|
60
|
+
int w_mask;
|
61
|
+
/* Window buffer, which is a loop buffer. */
|
62
|
+
unsigned char *w_buff;
|
63
|
+
/* The insert position to the window. */
|
64
|
+
int w_pos;
|
65
|
+
/* The position where we can copy decoded code from the window. */
|
66
|
+
int copy_pos;
|
67
|
+
/* The length how many bytes we can copy decoded code from
|
68
|
+
* the window. */
|
69
|
+
int copy_len;
|
70
|
+
/* Translation reversal for x86 processor CALL byte sequence(E8).
|
71
|
+
* This is used for LZX only. */
|
72
|
+
uint32_t translation_size;
|
73
|
+
char translation;
|
74
|
+
char block_type;
|
75
|
+
#define VERBATIM_BLOCK 1
|
76
|
+
#define ALIGNED_OFFSET_BLOCK 2
|
77
|
+
#define UNCOMPRESSED_BLOCK 3
|
78
|
+
size_t block_size;
|
79
|
+
size_t block_bytes_avail;
|
80
|
+
/* Repeated offset. */
|
81
|
+
int r0, r1, r2;
|
82
|
+
unsigned char rbytes[4];
|
83
|
+
int rbytes_avail;
|
84
|
+
int length_header;
|
85
|
+
int position_slot;
|
86
|
+
int offset_bits;
|
87
|
+
|
88
|
+
struct lzx_pos_tbl {
|
89
|
+
int base;
|
90
|
+
int footer_bits;
|
91
|
+
} *pos_tbl;
|
92
|
+
/*
|
93
|
+
* Bit stream reader.
|
94
|
+
*/
|
95
|
+
struct lzx_br {
|
96
|
+
#define CACHE_TYPE uint64_t
|
97
|
+
#define CACHE_BITS (8 * sizeof(CACHE_TYPE))
|
98
|
+
/* Cache buffer. */
|
99
|
+
CACHE_TYPE cache_buffer;
|
100
|
+
/* Indicates how many bits avail in cache_buffer. */
|
101
|
+
int cache_avail;
|
102
|
+
unsigned char odd;
|
103
|
+
char have_odd;
|
104
|
+
} br;
|
105
|
+
|
106
|
+
/*
|
107
|
+
* Huffman coding.
|
108
|
+
*/
|
109
|
+
struct huffman {
|
110
|
+
int len_size;
|
111
|
+
int freq[17];
|
112
|
+
unsigned char *bitlen;
|
113
|
+
|
114
|
+
/*
|
115
|
+
* Use a index table. It's faster than searching a huffman
|
116
|
+
* coding tree, which is a binary tree. But a use of a large
|
117
|
+
* index table causes L1 cache read miss many times.
|
118
|
+
*/
|
119
|
+
int max_bits;
|
120
|
+
int tbl_bits;
|
121
|
+
int tree_used;
|
122
|
+
/* Direct access table. */
|
123
|
+
uint16_t *tbl;
|
124
|
+
} at, lt, mt, pt;
|
125
|
+
|
126
|
+
int loop;
|
127
|
+
int error;
|
128
|
+
};
|
129
|
+
|
130
|
+
static const int slots[] = {
|
131
|
+
30, 32, 34, 36, 38, 42, 50, 66, 98, 162, 290
|
132
|
+
};
|
133
|
+
#define SLOT_BASE 15
|
134
|
+
#define SLOT_MAX 21/*->25*/
|
135
|
+
|
136
|
+
struct lzx_stream {
|
137
|
+
const unsigned char *next_in;
|
138
|
+
int64_t avail_in;
|
139
|
+
int64_t total_in;
|
140
|
+
unsigned char *next_out;
|
141
|
+
int64_t avail_out;
|
142
|
+
int64_t total_out;
|
143
|
+
struct lzx_dec *ds;
|
144
|
+
};
|
145
|
+
|
146
|
+
/*
|
147
|
+
* Cabinet file definitions.
|
148
|
+
*/
|
149
|
+
/* CFHEADER offset */
|
150
|
+
#define CFHEADER_signature 0
|
151
|
+
#define CFHEADER_cbCabinet 8
|
152
|
+
#define CFHEADER_coffFiles 16
|
153
|
+
#define CFHEADER_versionMinor 24
|
154
|
+
#define CFHEADER_versionMajor 25
|
155
|
+
#define CFHEADER_cFolders 26
|
156
|
+
#define CFHEADER_cFiles 28
|
157
|
+
#define CFHEADER_flags 30
|
158
|
+
#define CFHEADER_setID 32
|
159
|
+
#define CFHEADER_iCabinet 34
|
160
|
+
#define CFHEADER_cbCFHeader 36
|
161
|
+
#define CFHEADER_cbCFFolder 38
|
162
|
+
#define CFHEADER_cbCFData 39
|
163
|
+
|
164
|
+
/* CFFOLDER offset */
|
165
|
+
#define CFFOLDER_coffCabStart 0
|
166
|
+
#define CFFOLDER_cCFData 4
|
167
|
+
#define CFFOLDER_typeCompress 6
|
168
|
+
#define CFFOLDER_abReserve 8
|
169
|
+
|
170
|
+
/* CFFILE offset */
|
171
|
+
#define CFFILE_cbFile 0
|
172
|
+
#define CFFILE_uoffFolderStart 4
|
173
|
+
#define CFFILE_iFolder 8
|
174
|
+
#define CFFILE_date_time 10
|
175
|
+
#define CFFILE_attribs 14
|
176
|
+
|
177
|
+
/* CFDATA offset */
|
178
|
+
#define CFDATA_csum 0
|
179
|
+
#define CFDATA_cbData 4
|
180
|
+
#define CFDATA_cbUncomp 6
|
181
|
+
|
182
|
+
static const char * const compression_name[] = {
|
183
|
+
"NONE",
|
184
|
+
"MSZIP",
|
185
|
+
"Quantum",
|
186
|
+
"LZX",
|
187
|
+
};
|
188
|
+
|
189
|
+
struct cfdata {
|
190
|
+
/* Sum value of this CFDATA. */
|
191
|
+
uint32_t sum;
|
192
|
+
uint16_t compressed_size;
|
193
|
+
uint16_t compressed_bytes_remaining;
|
194
|
+
uint16_t uncompressed_size;
|
195
|
+
uint16_t uncompressed_bytes_remaining;
|
196
|
+
/* To know how many bytes we have decompressed. */
|
197
|
+
uint16_t uncompressed_avail;
|
198
|
+
/* Offset from the beginning of compressed data of this CFDATA */
|
199
|
+
uint16_t read_offset;
|
200
|
+
int64_t unconsumed;
|
201
|
+
/* To keep memory image of this CFDATA to compute the sum. */
|
202
|
+
size_t memimage_size;
|
203
|
+
unsigned char *memimage;
|
204
|
+
/* Result of calculation of sum. */
|
205
|
+
uint32_t sum_calculated;
|
206
|
+
unsigned char sum_extra[4];
|
207
|
+
int sum_extra_avail;
|
208
|
+
const void *sum_ptr;
|
209
|
+
};
|
210
|
+
|
211
|
+
struct cffolder {
|
212
|
+
uint32_t cfdata_offset_in_cab;
|
213
|
+
uint16_t cfdata_count;
|
214
|
+
uint16_t comptype;
|
215
|
+
#define COMPTYPE_NONE 0x0000
|
216
|
+
#define COMPTYPE_MSZIP 0x0001
|
217
|
+
#define COMPTYPE_QUANTUM 0x0002
|
218
|
+
#define COMPTYPE_LZX 0x0003
|
219
|
+
uint16_t compdata;
|
220
|
+
const char *compname;
|
221
|
+
/* At the time reading CFDATA */
|
222
|
+
struct cfdata cfdata;
|
223
|
+
int cfdata_index;
|
224
|
+
/* Flags to mark progress of decompression. */
|
225
|
+
char decompress_init;
|
226
|
+
};
|
227
|
+
|
228
|
+
struct cffile {
|
229
|
+
uint32_t uncompressed_size;
|
230
|
+
uint32_t offset;
|
231
|
+
time_t mtime;
|
232
|
+
uint16_t folder;
|
233
|
+
#define iFoldCONTINUED_FROM_PREV 0xFFFD
|
234
|
+
#define iFoldCONTINUED_TO_NEXT 0xFFFE
|
235
|
+
#define iFoldCONTINUED_PREV_AND_NEXT 0xFFFF
|
236
|
+
unsigned char attr;
|
237
|
+
#define ATTR_RDONLY 0x01
|
238
|
+
#define ATTR_NAME_IS_UTF 0x80
|
239
|
+
struct archive_string pathname;
|
240
|
+
};
|
241
|
+
|
242
|
+
struct cfheader {
|
243
|
+
/* Total bytes of all file size in a Cabinet. */
|
244
|
+
uint32_t total_bytes;
|
245
|
+
uint32_t files_offset;
|
246
|
+
uint16_t folder_count;
|
247
|
+
uint16_t file_count;
|
248
|
+
uint16_t flags;
|
249
|
+
#define PREV_CABINET 0x0001
|
250
|
+
#define NEXT_CABINET 0x0002
|
251
|
+
#define RESERVE_PRESENT 0x0004
|
252
|
+
uint16_t setid;
|
253
|
+
uint16_t cabinet;
|
254
|
+
/* Version number. */
|
255
|
+
unsigned char major;
|
256
|
+
unsigned char minor;
|
257
|
+
unsigned char cffolder;
|
258
|
+
unsigned char cfdata;
|
259
|
+
/* All folders in a cabinet. */
|
260
|
+
struct cffolder *folder_array;
|
261
|
+
/* All files in a cabinet. */
|
262
|
+
struct cffile *file_array;
|
263
|
+
int file_index;
|
264
|
+
};
|
265
|
+
|
266
|
+
struct cab {
|
267
|
+
/* entry_bytes_remaining is the number of bytes we expect. */
|
268
|
+
int64_t entry_offset;
|
269
|
+
int64_t entry_bytes_remaining;
|
270
|
+
int64_t entry_unconsumed;
|
271
|
+
int64_t entry_compressed_bytes_read;
|
272
|
+
int64_t entry_uncompressed_bytes_read;
|
273
|
+
struct cffolder *entry_cffolder;
|
274
|
+
struct cffile *entry_cffile;
|
275
|
+
struct cfdata *entry_cfdata;
|
276
|
+
|
277
|
+
/* Offset from beginning of a cabinet file. */
|
278
|
+
int64_t cab_offset;
|
279
|
+
struct cfheader cfheader;
|
280
|
+
struct archive_wstring ws;
|
281
|
+
|
282
|
+
/* Flag to mark progress that an archive was read their first header.*/
|
283
|
+
char found_header;
|
284
|
+
char end_of_archive;
|
285
|
+
char end_of_entry;
|
286
|
+
char end_of_entry_cleanup;
|
287
|
+
char read_data_invoked;
|
288
|
+
int64_t bytes_skipped;
|
289
|
+
|
290
|
+
unsigned char *uncompressed_buffer;
|
291
|
+
size_t uncompressed_buffer_size;
|
292
|
+
|
293
|
+
int init_default_conversion;
|
294
|
+
struct archive_string_conv *sconv;
|
295
|
+
struct archive_string_conv *sconv_default;
|
296
|
+
struct archive_string_conv *sconv_utf8;
|
297
|
+
char format_name[64];
|
298
|
+
|
299
|
+
#ifdef HAVE_ZLIB_H
|
300
|
+
z_stream stream;
|
301
|
+
char stream_valid;
|
302
|
+
#endif
|
303
|
+
struct lzx_stream xstrm;
|
304
|
+
};
|
305
|
+
|
306
|
+
static int archive_read_format_cab_bid(struct archive_read *, int);
|
307
|
+
static int archive_read_format_cab_options(struct archive_read *,
|
308
|
+
const char *, const char *);
|
309
|
+
static int archive_read_format_cab_read_header(struct archive_read *,
|
310
|
+
struct archive_entry *);
|
311
|
+
static int archive_read_format_cab_read_data(struct archive_read *,
|
312
|
+
const void **, size_t *, int64_t *);
|
313
|
+
static int archive_read_format_cab_read_data_skip(struct archive_read *);
|
314
|
+
static int archive_read_format_cab_cleanup(struct archive_read *);
|
315
|
+
|
316
|
+
static int cab_skip_sfx(struct archive_read *);
|
317
|
+
static time_t cab_dos_time(const unsigned char *);
|
318
|
+
static int cab_read_data(struct archive_read *, const void **,
|
319
|
+
size_t *, int64_t *);
|
320
|
+
static int cab_read_header(struct archive_read *);
|
321
|
+
static uint32_t cab_checksum_cfdata_4(const void *, size_t bytes, uint32_t);
|
322
|
+
static uint32_t cab_checksum_cfdata(const void *, size_t bytes, uint32_t);
|
323
|
+
static void cab_checksum_update(struct archive_read *, size_t);
|
324
|
+
static int cab_checksum_finish(struct archive_read *);
|
325
|
+
static int cab_next_cfdata(struct archive_read *);
|
326
|
+
static const void *cab_read_ahead_cfdata(struct archive_read *, ssize_t *);
|
327
|
+
static const void *cab_read_ahead_cfdata_none(struct archive_read *, ssize_t *);
|
328
|
+
static const void *cab_read_ahead_cfdata_deflate(struct archive_read *,
|
329
|
+
ssize_t *);
|
330
|
+
static const void *cab_read_ahead_cfdata_lzx(struct archive_read *,
|
331
|
+
ssize_t *);
|
332
|
+
static int64_t cab_consume_cfdata(struct archive_read *, int64_t);
|
333
|
+
static int64_t cab_minimum_consume_cfdata(struct archive_read *, int64_t);
|
334
|
+
static int lzx_decode_init(struct lzx_stream *, int);
|
335
|
+
static int lzx_read_blocks(struct lzx_stream *, int);
|
336
|
+
static int lzx_decode_blocks(struct lzx_stream *, int);
|
337
|
+
static void lzx_decode_free(struct lzx_stream *);
|
338
|
+
static void lzx_translation(struct lzx_stream *, void *, size_t, uint32_t);
|
339
|
+
static void lzx_cleanup_bitstream(struct lzx_stream *);
|
340
|
+
static int lzx_decode(struct lzx_stream *, int);
|
341
|
+
static int lzx_read_pre_tree(struct lzx_stream *);
|
342
|
+
static int lzx_read_bitlen(struct lzx_stream *, struct huffman *, int);
|
343
|
+
static int lzx_huffman_init(struct huffman *, size_t, int);
|
344
|
+
static void lzx_huffman_free(struct huffman *);
|
345
|
+
static int lzx_make_huffman_table(struct huffman *);
|
346
|
+
static inline int lzx_decode_huffman(struct huffman *, unsigned);
|
347
|
+
|
348
|
+
|
349
|
+
int
|
350
|
+
archive_read_support_format_cab(struct archive *_a)
|
351
|
+
{
|
352
|
+
struct archive_read *a = (struct archive_read *)_a;
|
353
|
+
struct cab *cab;
|
354
|
+
int r;
|
355
|
+
|
356
|
+
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
357
|
+
ARCHIVE_STATE_NEW, "archive_read_support_format_cab");
|
358
|
+
|
359
|
+
cab = (struct cab *)calloc(1, sizeof(*cab));
|
360
|
+
if (cab == NULL) {
|
361
|
+
archive_set_error(&a->archive, ENOMEM,
|
362
|
+
"Can't allocate CAB data");
|
363
|
+
return (ARCHIVE_FATAL);
|
364
|
+
}
|
365
|
+
archive_string_init(&cab->ws);
|
366
|
+
archive_wstring_ensure(&cab->ws, 256);
|
367
|
+
|
368
|
+
r = __archive_read_register_format(a,
|
369
|
+
cab,
|
370
|
+
"cab",
|
371
|
+
archive_read_format_cab_bid,
|
372
|
+
archive_read_format_cab_options,
|
373
|
+
archive_read_format_cab_read_header,
|
374
|
+
archive_read_format_cab_read_data,
|
375
|
+
archive_read_format_cab_read_data_skip,
|
376
|
+
NULL,
|
377
|
+
archive_read_format_cab_cleanup,
|
378
|
+
NULL,
|
379
|
+
NULL);
|
380
|
+
|
381
|
+
if (r != ARCHIVE_OK)
|
382
|
+
free(cab);
|
383
|
+
return (ARCHIVE_OK);
|
384
|
+
}
|
385
|
+
|
386
|
+
static int
|
387
|
+
find_cab_magic(const char *p)
|
388
|
+
{
|
389
|
+
switch (p[4]) {
|
390
|
+
case 0:
|
391
|
+
/*
|
392
|
+
* Note: Self-Extraction program has 'MSCF' string in their
|
393
|
+
* program. If we were finding 'MSCF' string only, we got
|
394
|
+
* wrong place for Cabinet header, thus, we have to check
|
395
|
+
* following four bytes which are reserved and must be set
|
396
|
+
* to zero.
|
397
|
+
*/
|
398
|
+
if (memcmp(p, "MSCF\0\0\0\0", 8) == 0)
|
399
|
+
return 0;
|
400
|
+
return 5;
|
401
|
+
case 'F': return 1;
|
402
|
+
case 'C': return 2;
|
403
|
+
case 'S': return 3;
|
404
|
+
case 'M': return 4;
|
405
|
+
default: return 5;
|
406
|
+
}
|
407
|
+
}
|
408
|
+
|
409
|
+
static int
|
410
|
+
archive_read_format_cab_bid(struct archive_read *a, int best_bid)
|
411
|
+
{
|
412
|
+
const char *p;
|
413
|
+
ssize_t bytes_avail, offset, window;
|
414
|
+
|
415
|
+
/* If there's already a better bid than we can ever
|
416
|
+
make, don't bother testing. */
|
417
|
+
if (best_bid > 64)
|
418
|
+
return (-1);
|
419
|
+
|
420
|
+
if ((p = __archive_read_ahead(a, 8, NULL)) == NULL)
|
421
|
+
return (-1);
|
422
|
+
|
423
|
+
if (memcmp(p, "MSCF\0\0\0\0", 8) == 0)
|
424
|
+
return (64);
|
425
|
+
|
426
|
+
/*
|
427
|
+
* Attempt to handle self-extracting archives
|
428
|
+
* by noting a PE header and searching forward
|
429
|
+
* up to 128k for a 'MSCF' marker.
|
430
|
+
*/
|
431
|
+
if (p[0] == 'M' && p[1] == 'Z') {
|
432
|
+
offset = 0;
|
433
|
+
window = 4096;
|
434
|
+
while (offset < (1024 * 128)) {
|
435
|
+
const char *h = __archive_read_ahead(a, offset + window,
|
436
|
+
&bytes_avail);
|
437
|
+
if (h == NULL) {
|
438
|
+
/* Remaining bytes are less than window. */
|
439
|
+
window >>= 1;
|
440
|
+
if (window < 128)
|
441
|
+
return (0);
|
442
|
+
continue;
|
443
|
+
}
|
444
|
+
p = h + offset;
|
445
|
+
while (p + 8 < h + bytes_avail) {
|
446
|
+
int next;
|
447
|
+
if ((next = find_cab_magic(p)) == 0)
|
448
|
+
return (64);
|
449
|
+
p += next;
|
450
|
+
}
|
451
|
+
offset = p - h;
|
452
|
+
}
|
453
|
+
}
|
454
|
+
return (0);
|
455
|
+
}
|
456
|
+
|
457
|
+
static int
|
458
|
+
archive_read_format_cab_options(struct archive_read *a,
|
459
|
+
const char *key, const char *val)
|
460
|
+
{
|
461
|
+
struct cab *cab;
|
462
|
+
int ret = ARCHIVE_FAILED;
|
463
|
+
|
464
|
+
cab = (struct cab *)(a->format->data);
|
465
|
+
if (strcmp(key, "hdrcharset") == 0) {
|
466
|
+
if (val == NULL || val[0] == 0)
|
467
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
468
|
+
"cab: hdrcharset option needs a character-set name");
|
469
|
+
else {
|
470
|
+
cab->sconv = archive_string_conversion_from_charset(
|
471
|
+
&a->archive, val, 0);
|
472
|
+
if (cab->sconv != NULL)
|
473
|
+
ret = ARCHIVE_OK;
|
474
|
+
else
|
475
|
+
ret = ARCHIVE_FATAL;
|
476
|
+
}
|
477
|
+
return (ret);
|
478
|
+
}
|
479
|
+
|
480
|
+
/* Note: The "warn" return is just to inform the options
|
481
|
+
* supervisor that we didn't handle it. It will generate
|
482
|
+
* a suitable error if no one used this option. */
|
483
|
+
return (ARCHIVE_WARN);
|
484
|
+
}
|
485
|
+
|
486
|
+
static int
|
487
|
+
cab_skip_sfx(struct archive_read *a)
|
488
|
+
{
|
489
|
+
const char *p, *q;
|
490
|
+
size_t skip;
|
491
|
+
ssize_t bytes, window;
|
492
|
+
|
493
|
+
window = 4096;
|
494
|
+
for (;;) {
|
495
|
+
const char *h = __archive_read_ahead(a, window, &bytes);
|
496
|
+
if (h == NULL) {
|
497
|
+
/* Remaining size are less than window. */
|
498
|
+
window >>= 1;
|
499
|
+
if (window < 128) {
|
500
|
+
archive_set_error(&a->archive,
|
501
|
+
ARCHIVE_ERRNO_FILE_FORMAT,
|
502
|
+
"Couldn't find out CAB header");
|
503
|
+
return (ARCHIVE_FATAL);
|
504
|
+
}
|
505
|
+
continue;
|
506
|
+
}
|
507
|
+
p = h;
|
508
|
+
q = p + bytes;
|
509
|
+
|
510
|
+
/*
|
511
|
+
* Scan ahead until we find something that looks
|
512
|
+
* like the cab header.
|
513
|
+
*/
|
514
|
+
while (p + 8 < q) {
|
515
|
+
int next;
|
516
|
+
if ((next = find_cab_magic(p)) == 0) {
|
517
|
+
skip = p - h;
|
518
|
+
__archive_read_consume(a, skip);
|
519
|
+
return (ARCHIVE_OK);
|
520
|
+
}
|
521
|
+
p += next;
|
522
|
+
}
|
523
|
+
skip = p - h;
|
524
|
+
__archive_read_consume(a, skip);
|
525
|
+
}
|
526
|
+
}
|
527
|
+
|
528
|
+
static int
|
529
|
+
truncated_error(struct archive_read *a)
|
530
|
+
{
|
531
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
532
|
+
"Truncated CAB header");
|
533
|
+
return (ARCHIVE_FATAL);
|
534
|
+
}
|
535
|
+
|
536
|
+
static ssize_t
|
537
|
+
cab_strnlen(const unsigned char *p, size_t maxlen)
|
538
|
+
{
|
539
|
+
size_t i;
|
540
|
+
|
541
|
+
for (i = 0; i <= maxlen; i++) {
|
542
|
+
if (p[i] == 0)
|
543
|
+
break;
|
544
|
+
}
|
545
|
+
if (i > maxlen)
|
546
|
+
return (-1);/* invalid */
|
547
|
+
return ((ssize_t)i);
|
548
|
+
}
|
549
|
+
|
550
|
+
/* Read bytes as much as remaining. */
|
551
|
+
static const void *
|
552
|
+
cab_read_ahead_remaining(struct archive_read *a, size_t min, ssize_t *avail)
|
553
|
+
{
|
554
|
+
const void *p;
|
555
|
+
|
556
|
+
while (min > 0) {
|
557
|
+
p = __archive_read_ahead(a, min, avail);
|
558
|
+
if (p != NULL)
|
559
|
+
return (p);
|
560
|
+
min--;
|
561
|
+
}
|
562
|
+
return (NULL);
|
563
|
+
}
|
564
|
+
|
565
|
+
/* Convert a path separator '\' -> '/' */
|
566
|
+
static int
|
567
|
+
cab_convert_path_separator_1(struct archive_string *fn, unsigned char attr)
|
568
|
+
{
|
569
|
+
size_t i;
|
570
|
+
int mb;
|
571
|
+
|
572
|
+
/* Easy check if we have '\' in multi-byte string. */
|
573
|
+
mb = 0;
|
574
|
+
for (i = 0; i < archive_strlen(fn); i++) {
|
575
|
+
if (fn->s[i] == '\\') {
|
576
|
+
if (mb) {
|
577
|
+
/* This may be second byte of multi-byte
|
578
|
+
* character. */
|
579
|
+
break;
|
580
|
+
}
|
581
|
+
fn->s[i] = '/';
|
582
|
+
mb = 0;
|
583
|
+
} else if ((fn->s[i] & 0x80) && !(attr & ATTR_NAME_IS_UTF))
|
584
|
+
mb = 1;
|
585
|
+
else
|
586
|
+
mb = 0;
|
587
|
+
}
|
588
|
+
if (i == archive_strlen(fn))
|
589
|
+
return (0);
|
590
|
+
return (-1);
|
591
|
+
}
|
592
|
+
|
593
|
+
/*
|
594
|
+
* Replace a character '\' with '/' in wide character.
|
595
|
+
*/
|
596
|
+
static void
|
597
|
+
cab_convert_path_separator_2(struct cab *cab, struct archive_entry *entry)
|
598
|
+
{
|
599
|
+
const wchar_t *wp;
|
600
|
+
size_t i;
|
601
|
+
|
602
|
+
/* If a conversion to wide character failed, force the replacement. */
|
603
|
+
if ((wp = archive_entry_pathname_w(entry)) != NULL) {
|
604
|
+
archive_wstrcpy(&(cab->ws), wp);
|
605
|
+
for (i = 0; i < archive_strlen(&(cab->ws)); i++) {
|
606
|
+
if (cab->ws.s[i] == L'\\')
|
607
|
+
cab->ws.s[i] = L'/';
|
608
|
+
}
|
609
|
+
archive_entry_copy_pathname_w(entry, cab->ws.s);
|
610
|
+
}
|
611
|
+
}
|
612
|
+
|
613
|
+
/*
|
614
|
+
* Read CFHEADER, CFFOLDER and CFFILE.
|
615
|
+
*/
|
616
|
+
static int
|
617
|
+
cab_read_header(struct archive_read *a)
|
618
|
+
{
|
619
|
+
const unsigned char *p;
|
620
|
+
struct cab *cab;
|
621
|
+
struct cfheader *hd;
|
622
|
+
size_t bytes, used;
|
623
|
+
ssize_t len;
|
624
|
+
int64_t skip;
|
625
|
+
int err, i;
|
626
|
+
int cur_folder, prev_folder;
|
627
|
+
uint32_t offset32;
|
628
|
+
|
629
|
+
a->archive.archive_format = ARCHIVE_FORMAT_CAB;
|
630
|
+
if (a->archive.archive_format_name == NULL)
|
631
|
+
a->archive.archive_format_name = "CAB";
|
632
|
+
|
633
|
+
if ((p = __archive_read_ahead(a, 42, NULL)) == NULL)
|
634
|
+
return (truncated_error(a));
|
635
|
+
|
636
|
+
cab = (struct cab *)(a->format->data);
|
637
|
+
if (cab->found_header == 0 &&
|
638
|
+
p[0] == 'M' && p[1] == 'Z') {
|
639
|
+
/* This is an executable? Must be self-extracting... */
|
640
|
+
err = cab_skip_sfx(a);
|
641
|
+
if (err < ARCHIVE_WARN)
|
642
|
+
return (err);
|
643
|
+
|
644
|
+
/* Re-read header after processing the SFX. */
|
645
|
+
if ((p = __archive_read_ahead(a, 42, NULL)) == NULL)
|
646
|
+
return (truncated_error(a));
|
647
|
+
}
|
648
|
+
|
649
|
+
cab->cab_offset = 0;
|
650
|
+
/*
|
651
|
+
* Read CFHEADER.
|
652
|
+
*/
|
653
|
+
hd = &cab->cfheader;
|
654
|
+
if (p[CFHEADER_signature+0] != 'M' || p[CFHEADER_signature+1] != 'S' ||
|
655
|
+
p[CFHEADER_signature+2] != 'C' || p[CFHEADER_signature+3] != 'F') {
|
656
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
657
|
+
"Couldn't find out CAB header");
|
658
|
+
return (ARCHIVE_FATAL);
|
659
|
+
}
|
660
|
+
hd->total_bytes = archive_le32dec(p + CFHEADER_cbCabinet);
|
661
|
+
hd->files_offset = archive_le32dec(p + CFHEADER_coffFiles);
|
662
|
+
hd->minor = p[CFHEADER_versionMinor];
|
663
|
+
hd->major = p[CFHEADER_versionMajor];
|
664
|
+
hd->folder_count = archive_le16dec(p + CFHEADER_cFolders);
|
665
|
+
if (hd->folder_count == 0)
|
666
|
+
goto invalid;
|
667
|
+
hd->file_count = archive_le16dec(p + CFHEADER_cFiles);
|
668
|
+
if (hd->file_count == 0)
|
669
|
+
goto invalid;
|
670
|
+
hd->flags = archive_le16dec(p + CFHEADER_flags);
|
671
|
+
hd->setid = archive_le16dec(p + CFHEADER_setID);
|
672
|
+
hd->cabinet = archive_le16dec(p + CFHEADER_iCabinet);
|
673
|
+
used = CFHEADER_iCabinet + 2;
|
674
|
+
if (hd->flags & RESERVE_PRESENT) {
|
675
|
+
uint16_t cfheader;
|
676
|
+
cfheader = archive_le16dec(p + CFHEADER_cbCFHeader);
|
677
|
+
if (cfheader > 60000U)
|
678
|
+
goto invalid;
|
679
|
+
hd->cffolder = p[CFHEADER_cbCFFolder];
|
680
|
+
hd->cfdata = p[CFHEADER_cbCFData];
|
681
|
+
used += 4;/* cbCFHeader, cbCFFolder and cbCFData */
|
682
|
+
used += cfheader;/* abReserve */
|
683
|
+
} else
|
684
|
+
hd->cffolder = 0;/* Avoid compiling warning. */
|
685
|
+
if (hd->flags & PREV_CABINET) {
|
686
|
+
/* How many bytes are used for szCabinetPrev. */
|
687
|
+
if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL)
|
688
|
+
return (truncated_error(a));
|
689
|
+
if ((len = cab_strnlen(p + used, 255)) <= 0)
|
690
|
+
goto invalid;
|
691
|
+
used += len + 1;
|
692
|
+
/* How many bytes are used for szDiskPrev. */
|
693
|
+
if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL)
|
694
|
+
return (truncated_error(a));
|
695
|
+
if ((len = cab_strnlen(p + used, 255)) <= 0)
|
696
|
+
goto invalid;
|
697
|
+
used += len + 1;
|
698
|
+
}
|
699
|
+
if (hd->flags & NEXT_CABINET) {
|
700
|
+
/* How many bytes are used for szCabinetNext. */
|
701
|
+
if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL)
|
702
|
+
return (truncated_error(a));
|
703
|
+
if ((len = cab_strnlen(p + used, 255)) <= 0)
|
704
|
+
goto invalid;
|
705
|
+
used += len + 1;
|
706
|
+
/* How many bytes are used for szDiskNext. */
|
707
|
+
if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL)
|
708
|
+
return (truncated_error(a));
|
709
|
+
if ((len = cab_strnlen(p + used, 255)) <= 0)
|
710
|
+
goto invalid;
|
711
|
+
used += len + 1;
|
712
|
+
}
|
713
|
+
__archive_read_consume(a, used);
|
714
|
+
cab->cab_offset += used;
|
715
|
+
used = 0;
|
716
|
+
|
717
|
+
/*
|
718
|
+
* Read CFFOLDER.
|
719
|
+
*/
|
720
|
+
hd->folder_array = (struct cffolder *)calloc(
|
721
|
+
hd->folder_count, sizeof(struct cffolder));
|
722
|
+
if (hd->folder_array == NULL)
|
723
|
+
goto nomem;
|
724
|
+
|
725
|
+
bytes = 8;
|
726
|
+
if (hd->flags & RESERVE_PRESENT)
|
727
|
+
bytes += hd->cffolder;
|
728
|
+
bytes *= hd->folder_count;
|
729
|
+
if ((p = __archive_read_ahead(a, bytes, NULL)) == NULL)
|
730
|
+
return (truncated_error(a));
|
731
|
+
offset32 = 0;
|
732
|
+
for (i = 0; i < hd->folder_count; i++) {
|
733
|
+
struct cffolder *folder = &(hd->folder_array[i]);
|
734
|
+
folder->cfdata_offset_in_cab =
|
735
|
+
archive_le32dec(p + CFFOLDER_coffCabStart);
|
736
|
+
folder->cfdata_count = archive_le16dec(p+CFFOLDER_cCFData);
|
737
|
+
folder->comptype =
|
738
|
+
archive_le16dec(p+CFFOLDER_typeCompress) & 0x0F;
|
739
|
+
folder->compdata =
|
740
|
+
archive_le16dec(p+CFFOLDER_typeCompress) >> 8;
|
741
|
+
/* Get a compression name. */
|
742
|
+
if (folder->comptype <
|
743
|
+
sizeof(compression_name) / sizeof(compression_name[0]))
|
744
|
+
folder->compname = compression_name[folder->comptype];
|
745
|
+
else
|
746
|
+
folder->compname = "UNKNOWN";
|
747
|
+
p += 8;
|
748
|
+
used += 8;
|
749
|
+
if (hd->flags & RESERVE_PRESENT) {
|
750
|
+
p += hd->cffolder;/* abReserve */
|
751
|
+
used += hd->cffolder;
|
752
|
+
}
|
753
|
+
/*
|
754
|
+
* Sanity check if each data is acceptable.
|
755
|
+
*/
|
756
|
+
if (offset32 >= folder->cfdata_offset_in_cab)
|
757
|
+
goto invalid;
|
758
|
+
offset32 = folder->cfdata_offset_in_cab;
|
759
|
+
|
760
|
+
/* Set a request to initialize zlib for the CFDATA of
|
761
|
+
* this folder. */
|
762
|
+
folder->decompress_init = 0;
|
763
|
+
}
|
764
|
+
__archive_read_consume(a, used);
|
765
|
+
cab->cab_offset += used;
|
766
|
+
|
767
|
+
/*
|
768
|
+
* Read CFFILE.
|
769
|
+
*/
|
770
|
+
/* Seek read pointer to the offset of CFFILE if needed. */
|
771
|
+
skip = (int64_t)hd->files_offset - cab->cab_offset;
|
772
|
+
if (skip < 0) {
|
773
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
774
|
+
"Invalid offset of CFFILE %jd < %jd",
|
775
|
+
(intmax_t)hd->files_offset, (intmax_t)cab->cab_offset);
|
776
|
+
return (ARCHIVE_FATAL);
|
777
|
+
}
|
778
|
+
if (skip) {
|
779
|
+
__archive_read_consume(a, skip);
|
780
|
+
cab->cab_offset += skip;
|
781
|
+
}
|
782
|
+
/* Allocate memory for CFDATA */
|
783
|
+
hd->file_array = (struct cffile *)calloc(
|
784
|
+
hd->file_count, sizeof(struct cffile));
|
785
|
+
if (hd->file_array == NULL)
|
786
|
+
goto nomem;
|
787
|
+
|
788
|
+
prev_folder = -1;
|
789
|
+
for (i = 0; i < hd->file_count; i++) {
|
790
|
+
struct cffile *file = &(hd->file_array[i]);
|
791
|
+
ssize_t avail;
|
792
|
+
|
793
|
+
if ((p = __archive_read_ahead(a, 16, NULL)) == NULL)
|
794
|
+
return (truncated_error(a));
|
795
|
+
file->uncompressed_size = archive_le32dec(p + CFFILE_cbFile);
|
796
|
+
file->offset = archive_le32dec(p + CFFILE_uoffFolderStart);
|
797
|
+
file->folder = archive_le16dec(p + CFFILE_iFolder);
|
798
|
+
file->mtime = cab_dos_time(p + CFFILE_date_time);
|
799
|
+
file->attr = (uint8_t)archive_le16dec(p + CFFILE_attribs);
|
800
|
+
__archive_read_consume(a, 16);
|
801
|
+
|
802
|
+
cab->cab_offset += 16;
|
803
|
+
if ((p = cab_read_ahead_remaining(a, 256, &avail)) == NULL)
|
804
|
+
return (truncated_error(a));
|
805
|
+
if ((len = cab_strnlen(p, avail-1)) <= 0)
|
806
|
+
goto invalid;
|
807
|
+
|
808
|
+
/* Copy a pathname. */
|
809
|
+
archive_string_init(&(file->pathname));
|
810
|
+
archive_strncpy(&(file->pathname), p, len);
|
811
|
+
__archive_read_consume(a, len + 1);
|
812
|
+
cab->cab_offset += len + 1;
|
813
|
+
|
814
|
+
/*
|
815
|
+
* Sanity check if each data is acceptable.
|
816
|
+
*/
|
817
|
+
if (file->uncompressed_size > 0x7FFF8000)
|
818
|
+
goto invalid;/* Too large */
|
819
|
+
if ((int64_t)file->offset + (int64_t)file->uncompressed_size
|
820
|
+
> ARCHIVE_LITERAL_LL(0x7FFF8000))
|
821
|
+
goto invalid;/* Too large */
|
822
|
+
switch (file->folder) {
|
823
|
+
case iFoldCONTINUED_TO_NEXT:
|
824
|
+
/* This must be last file in a folder. */
|
825
|
+
if (i != hd->file_count -1)
|
826
|
+
goto invalid;
|
827
|
+
cur_folder = hd->folder_count -1;
|
828
|
+
break;
|
829
|
+
case iFoldCONTINUED_PREV_AND_NEXT:
|
830
|
+
/* This must be only one file in a folder. */
|
831
|
+
if (hd->file_count != 1)
|
832
|
+
goto invalid;
|
833
|
+
/* FALL THROUGH */
|
834
|
+
case iFoldCONTINUED_FROM_PREV:
|
835
|
+
/* This must be first file in a folder. */
|
836
|
+
if (i != 0)
|
837
|
+
goto invalid;
|
838
|
+
prev_folder = cur_folder = 0;
|
839
|
+
offset32 = file->offset;
|
840
|
+
break;
|
841
|
+
default:
|
842
|
+
if (file->folder >= hd->folder_count)
|
843
|
+
goto invalid;
|
844
|
+
cur_folder = file->folder;
|
845
|
+
break;
|
846
|
+
}
|
847
|
+
/* Dot not back track. */
|
848
|
+
if (cur_folder < prev_folder)
|
849
|
+
goto invalid;
|
850
|
+
if (cur_folder != prev_folder)
|
851
|
+
offset32 = 0;
|
852
|
+
prev_folder = cur_folder;
|
853
|
+
|
854
|
+
/* Make sure there are not any blanks from last file
|
855
|
+
* contents. */
|
856
|
+
if (offset32 != file->offset)
|
857
|
+
goto invalid;
|
858
|
+
offset32 += file->uncompressed_size;
|
859
|
+
|
860
|
+
/* CFDATA is available for file contents. */
|
861
|
+
if (file->uncompressed_size > 0 &&
|
862
|
+
hd->folder_array[cur_folder].cfdata_count == 0)
|
863
|
+
goto invalid;
|
864
|
+
}
|
865
|
+
|
866
|
+
if (hd->cabinet != 0 || hd->flags & (PREV_CABINET | NEXT_CABINET)) {
|
867
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
868
|
+
"Multivolume cabinet file is unsupported");
|
869
|
+
return (ARCHIVE_WARN);
|
870
|
+
}
|
871
|
+
return (ARCHIVE_OK);
|
872
|
+
invalid:
|
873
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
874
|
+
"Invalid CAB header");
|
875
|
+
return (ARCHIVE_FATAL);
|
876
|
+
nomem:
|
877
|
+
archive_set_error(&a->archive, ENOMEM,
|
878
|
+
"Can't allocate memory for CAB data");
|
879
|
+
return (ARCHIVE_FATAL);
|
880
|
+
}
|
881
|
+
|
882
|
+
static int
|
883
|
+
archive_read_format_cab_read_header(struct archive_read *a,
|
884
|
+
struct archive_entry *entry)
|
885
|
+
{
|
886
|
+
struct cab *cab;
|
887
|
+
struct cfheader *hd;
|
888
|
+
struct cffolder *prev_folder;
|
889
|
+
struct cffile *file;
|
890
|
+
struct archive_string_conv *sconv;
|
891
|
+
int err = ARCHIVE_OK, r;
|
892
|
+
|
893
|
+
cab = (struct cab *)(a->format->data);
|
894
|
+
if (cab->found_header == 0) {
|
895
|
+
err = cab_read_header(a);
|
896
|
+
if (err < ARCHIVE_WARN)
|
897
|
+
return (err);
|
898
|
+
/* We've found the header. */
|
899
|
+
cab->found_header = 1;
|
900
|
+
}
|
901
|
+
hd = &cab->cfheader;
|
902
|
+
|
903
|
+
if (hd->file_index >= hd->file_count) {
|
904
|
+
cab->end_of_archive = 1;
|
905
|
+
return (ARCHIVE_EOF);
|
906
|
+
}
|
907
|
+
file = &hd->file_array[hd->file_index++];
|
908
|
+
|
909
|
+
cab->end_of_entry = 0;
|
910
|
+
cab->end_of_entry_cleanup = 0;
|
911
|
+
cab->entry_compressed_bytes_read = 0;
|
912
|
+
cab->entry_uncompressed_bytes_read = 0;
|
913
|
+
cab->entry_unconsumed = 0;
|
914
|
+
cab->entry_cffile = file;
|
915
|
+
|
916
|
+
/*
|
917
|
+
* Choose a proper folder.
|
918
|
+
*/
|
919
|
+
prev_folder = cab->entry_cffolder;
|
920
|
+
switch (file->folder) {
|
921
|
+
case iFoldCONTINUED_FROM_PREV:
|
922
|
+
case iFoldCONTINUED_PREV_AND_NEXT:
|
923
|
+
cab->entry_cffolder = &hd->folder_array[0];
|
924
|
+
break;
|
925
|
+
case iFoldCONTINUED_TO_NEXT:
|
926
|
+
cab->entry_cffolder = &hd->folder_array[hd->folder_count-1];
|
927
|
+
break;
|
928
|
+
default:
|
929
|
+
cab->entry_cffolder = &hd->folder_array[file->folder];
|
930
|
+
break;
|
931
|
+
}
|
932
|
+
/* If a cffolder of this file is changed, reset a cfdata to read
|
933
|
+
* file contents from next cfdata. */
|
934
|
+
if (prev_folder != cab->entry_cffolder)
|
935
|
+
cab->entry_cfdata = NULL;
|
936
|
+
|
937
|
+
/* If a pathname is UTF-8, prepare a string conversion object
|
938
|
+
* for UTF-8 and use it. */
|
939
|
+
if (file->attr & ATTR_NAME_IS_UTF) {
|
940
|
+
if (cab->sconv_utf8 == NULL) {
|
941
|
+
cab->sconv_utf8 =
|
942
|
+
archive_string_conversion_from_charset(
|
943
|
+
&(a->archive), "UTF-8", 1);
|
944
|
+
if (cab->sconv_utf8 == NULL)
|
945
|
+
return (ARCHIVE_FATAL);
|
946
|
+
}
|
947
|
+
sconv = cab->sconv_utf8;
|
948
|
+
} else if (cab->sconv != NULL) {
|
949
|
+
/* Choose the conversion specified by the option. */
|
950
|
+
sconv = cab->sconv;
|
951
|
+
} else {
|
952
|
+
/* Choose the default conversion. */
|
953
|
+
if (!cab->init_default_conversion) {
|
954
|
+
cab->sconv_default =
|
955
|
+
archive_string_default_conversion_for_read(
|
956
|
+
&(a->archive));
|
957
|
+
cab->init_default_conversion = 1;
|
958
|
+
}
|
959
|
+
sconv = cab->sconv_default;
|
960
|
+
}
|
961
|
+
|
962
|
+
/*
|
963
|
+
* Set a default value and common data
|
964
|
+
*/
|
965
|
+
r = cab_convert_path_separator_1(&(file->pathname), file->attr);
|
966
|
+
if (archive_entry_copy_pathname_l(entry, file->pathname.s,
|
967
|
+
archive_strlen(&(file->pathname)), sconv) != 0) {
|
968
|
+
if (errno == ENOMEM) {
|
969
|
+
archive_set_error(&a->archive, ENOMEM,
|
970
|
+
"Can't allocate memory for Pathname");
|
971
|
+
return (ARCHIVE_FATAL);
|
972
|
+
}
|
973
|
+
archive_set_error(&a->archive,
|
974
|
+
ARCHIVE_ERRNO_FILE_FORMAT,
|
975
|
+
"Pathname cannot be converted "
|
976
|
+
"from %s to current locale.",
|
977
|
+
archive_string_conversion_charset_name(sconv));
|
978
|
+
err = ARCHIVE_WARN;
|
979
|
+
}
|
980
|
+
if (r < 0) {
|
981
|
+
/* Convert a path separator '\' -> '/' */
|
982
|
+
cab_convert_path_separator_2(cab, entry);
|
983
|
+
}
|
984
|
+
|
985
|
+
archive_entry_set_size(entry, file->uncompressed_size);
|
986
|
+
if (file->attr & ATTR_RDONLY)
|
987
|
+
archive_entry_set_mode(entry, AE_IFREG | 0555);
|
988
|
+
else
|
989
|
+
archive_entry_set_mode(entry, AE_IFREG | 0666);
|
990
|
+
archive_entry_set_mtime(entry, file->mtime, 0);
|
991
|
+
|
992
|
+
cab->entry_bytes_remaining = file->uncompressed_size;
|
993
|
+
cab->entry_offset = 0;
|
994
|
+
/* We don't need compress data. */
|
995
|
+
if (file->uncompressed_size == 0)
|
996
|
+
cab->end_of_entry_cleanup = cab->end_of_entry = 1;
|
997
|
+
|
998
|
+
/* Set up a more descriptive format name. */
|
999
|
+
snprintf(cab->format_name, sizeof(cab->format_name), "CAB %d.%d (%s)",
|
1000
|
+
hd->major, hd->minor, cab->entry_cffolder->compname);
|
1001
|
+
a->archive.archive_format_name = cab->format_name;
|
1002
|
+
|
1003
|
+
return (err);
|
1004
|
+
}
|
1005
|
+
|
1006
|
+
static int
|
1007
|
+
archive_read_format_cab_read_data(struct archive_read *a,
|
1008
|
+
const void **buff, size_t *size, int64_t *offset)
|
1009
|
+
{
|
1010
|
+
struct cab *cab = (struct cab *)(a->format->data);
|
1011
|
+
int r;
|
1012
|
+
|
1013
|
+
switch (cab->entry_cffile->folder) {
|
1014
|
+
case iFoldCONTINUED_FROM_PREV:
|
1015
|
+
case iFoldCONTINUED_TO_NEXT:
|
1016
|
+
case iFoldCONTINUED_PREV_AND_NEXT:
|
1017
|
+
*buff = NULL;
|
1018
|
+
*size = 0;
|
1019
|
+
*offset = 0;
|
1020
|
+
archive_clear_error(&a->archive);
|
1021
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
1022
|
+
"Cannot restore this file split in multivolume.");
|
1023
|
+
return (ARCHIVE_FAILED);
|
1024
|
+
default:
|
1025
|
+
break;
|
1026
|
+
}
|
1027
|
+
if (cab->read_data_invoked == 0) {
|
1028
|
+
if (cab->bytes_skipped) {
|
1029
|
+
if (cab->entry_cfdata == NULL) {
|
1030
|
+
r = cab_next_cfdata(a);
|
1031
|
+
if (r < 0)
|
1032
|
+
return (r);
|
1033
|
+
}
|
1034
|
+
if (cab_consume_cfdata(a, cab->bytes_skipped) < 0)
|
1035
|
+
return (ARCHIVE_FATAL);
|
1036
|
+
cab->bytes_skipped = 0;
|
1037
|
+
}
|
1038
|
+
cab->read_data_invoked = 1;
|
1039
|
+
}
|
1040
|
+
if (cab->entry_unconsumed) {
|
1041
|
+
/* Consume as much as the compressor actually used. */
|
1042
|
+
r = (int)cab_consume_cfdata(a, cab->entry_unconsumed);
|
1043
|
+
cab->entry_unconsumed = 0;
|
1044
|
+
if (r < 0)
|
1045
|
+
return (r);
|
1046
|
+
}
|
1047
|
+
if (cab->end_of_archive || cab->end_of_entry) {
|
1048
|
+
if (!cab->end_of_entry_cleanup) {
|
1049
|
+
/* End-of-entry cleanup done. */
|
1050
|
+
cab->end_of_entry_cleanup = 1;
|
1051
|
+
}
|
1052
|
+
*offset = cab->entry_offset;
|
1053
|
+
*size = 0;
|
1054
|
+
*buff = NULL;
|
1055
|
+
return (ARCHIVE_EOF);
|
1056
|
+
}
|
1057
|
+
|
1058
|
+
return (cab_read_data(a, buff, size, offset));
|
1059
|
+
}
|
1060
|
+
|
1061
|
+
static uint32_t
|
1062
|
+
cab_checksum_cfdata_4(const void *p, size_t bytes, uint32_t seed)
|
1063
|
+
{
|
1064
|
+
const unsigned char *b;
|
1065
|
+
unsigned u32num;
|
1066
|
+
uint32_t sum;
|
1067
|
+
|
1068
|
+
u32num = (unsigned)bytes / 4;
|
1069
|
+
sum = seed;
|
1070
|
+
b = p;
|
1071
|
+
for (;u32num > 0; --u32num) {
|
1072
|
+
sum ^= archive_le32dec(b);
|
1073
|
+
b += 4;
|
1074
|
+
}
|
1075
|
+
return (sum);
|
1076
|
+
}
|
1077
|
+
|
1078
|
+
static uint32_t
|
1079
|
+
cab_checksum_cfdata(const void *p, size_t bytes, uint32_t seed)
|
1080
|
+
{
|
1081
|
+
const unsigned char *b;
|
1082
|
+
uint32_t sum;
|
1083
|
+
uint32_t t;
|
1084
|
+
|
1085
|
+
sum = cab_checksum_cfdata_4(p, bytes, seed);
|
1086
|
+
b = p;
|
1087
|
+
b += bytes & ~3;
|
1088
|
+
t = 0;
|
1089
|
+
switch (bytes & 3) {
|
1090
|
+
case 3:
|
1091
|
+
t |= ((uint32_t)(*b++)) << 16;
|
1092
|
+
/* FALL THROUGH */
|
1093
|
+
case 2:
|
1094
|
+
t |= ((uint32_t)(*b++)) << 8;
|
1095
|
+
/* FALL THROUGH */
|
1096
|
+
case 1:
|
1097
|
+
t |= *b;
|
1098
|
+
/* FALL THROUGH */
|
1099
|
+
default:
|
1100
|
+
break;
|
1101
|
+
}
|
1102
|
+
sum ^= t;
|
1103
|
+
|
1104
|
+
return (sum);
|
1105
|
+
}
|
1106
|
+
|
1107
|
+
static void
|
1108
|
+
cab_checksum_update(struct archive_read *a, size_t bytes)
|
1109
|
+
{
|
1110
|
+
struct cab *cab = (struct cab *)(a->format->data);
|
1111
|
+
struct cfdata *cfdata = cab->entry_cfdata;
|
1112
|
+
const unsigned char *p;
|
1113
|
+
size_t sumbytes;
|
1114
|
+
|
1115
|
+
if (cfdata->sum == 0 || cfdata->sum_ptr == NULL)
|
1116
|
+
return;
|
1117
|
+
/*
|
1118
|
+
* Calculate the sum of this CFDATA.
|
1119
|
+
* Make sure CFDATA must be calculated in four bytes.
|
1120
|
+
*/
|
1121
|
+
p = cfdata->sum_ptr;
|
1122
|
+
sumbytes = bytes;
|
1123
|
+
if (cfdata->sum_extra_avail) {
|
1124
|
+
while (cfdata->sum_extra_avail < 4 && sumbytes > 0) {
|
1125
|
+
cfdata->sum_extra[
|
1126
|
+
cfdata->sum_extra_avail++] = *p++;
|
1127
|
+
sumbytes--;
|
1128
|
+
}
|
1129
|
+
if (cfdata->sum_extra_avail == 4) {
|
1130
|
+
cfdata->sum_calculated = cab_checksum_cfdata_4(
|
1131
|
+
cfdata->sum_extra, 4, cfdata->sum_calculated);
|
1132
|
+
cfdata->sum_extra_avail = 0;
|
1133
|
+
}
|
1134
|
+
}
|
1135
|
+
if (sumbytes) {
|
1136
|
+
int odd = sumbytes & 3;
|
1137
|
+
if ((int)(sumbytes - odd) > 0)
|
1138
|
+
cfdata->sum_calculated = cab_checksum_cfdata_4(
|
1139
|
+
p, sumbytes - odd, cfdata->sum_calculated);
|
1140
|
+
if (odd)
|
1141
|
+
memcpy(cfdata->sum_extra, p + sumbytes - odd, odd);
|
1142
|
+
cfdata->sum_extra_avail = odd;
|
1143
|
+
}
|
1144
|
+
cfdata->sum_ptr = NULL;
|
1145
|
+
}
|
1146
|
+
|
1147
|
+
static int
|
1148
|
+
cab_checksum_finish(struct archive_read *a)
|
1149
|
+
{
|
1150
|
+
struct cab *cab = (struct cab *)(a->format->data);
|
1151
|
+
struct cfdata *cfdata = cab->entry_cfdata;
|
1152
|
+
int l;
|
1153
|
+
|
1154
|
+
/* Do not need to compute a sum. */
|
1155
|
+
if (cfdata->sum == 0)
|
1156
|
+
return (ARCHIVE_OK);
|
1157
|
+
|
1158
|
+
/*
|
1159
|
+
* Calculate the sum of remaining CFDATA.
|
1160
|
+
*/
|
1161
|
+
if (cfdata->sum_extra_avail) {
|
1162
|
+
cfdata->sum_calculated =
|
1163
|
+
cab_checksum_cfdata(cfdata->sum_extra,
|
1164
|
+
cfdata->sum_extra_avail, cfdata->sum_calculated);
|
1165
|
+
cfdata->sum_extra_avail = 0;
|
1166
|
+
}
|
1167
|
+
|
1168
|
+
l = 4;
|
1169
|
+
if (cab->cfheader.flags & RESERVE_PRESENT)
|
1170
|
+
l += cab->cfheader.cfdata;
|
1171
|
+
cfdata->sum_calculated = cab_checksum_cfdata(
|
1172
|
+
cfdata->memimage + CFDATA_cbData, l, cfdata->sum_calculated);
|
1173
|
+
if (cfdata->sum_calculated != cfdata->sum) {
|
1174
|
+
#ifndef DONT_FAIL_ON_CRC_ERROR
|
1175
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
1176
|
+
"Checksum error CFDATA[%d] %" PRIx32 ":%" PRIx32 " in %d bytes",
|
1177
|
+
cab->entry_cffolder->cfdata_index -1,
|
1178
|
+
cfdata->sum, cfdata->sum_calculated,
|
1179
|
+
cfdata->compressed_size);
|
1180
|
+
return (ARCHIVE_FAILED);
|
1181
|
+
#endif
|
1182
|
+
}
|
1183
|
+
return (ARCHIVE_OK);
|
1184
|
+
}
|
1185
|
+
|
1186
|
+
/*
|
1187
|
+
* Read CFDATA if needed.
|
1188
|
+
*/
|
1189
|
+
static int
|
1190
|
+
cab_next_cfdata(struct archive_read *a)
|
1191
|
+
{
|
1192
|
+
struct cab *cab = (struct cab *)(a->format->data);
|
1193
|
+
struct cfdata *cfdata = cab->entry_cfdata;
|
1194
|
+
|
1195
|
+
/* There are remaining bytes in current CFDATA, use it first. */
|
1196
|
+
if (cfdata != NULL && cfdata->uncompressed_bytes_remaining > 0)
|
1197
|
+
return (ARCHIVE_OK);
|
1198
|
+
|
1199
|
+
if (cfdata == NULL) {
|
1200
|
+
int64_t skip;
|
1201
|
+
|
1202
|
+
cab->entry_cffolder->cfdata_index = 0;
|
1203
|
+
|
1204
|
+
/* Seek read pointer to the offset of CFDATA if needed. */
|
1205
|
+
skip = cab->entry_cffolder->cfdata_offset_in_cab
|
1206
|
+
- cab->cab_offset;
|
1207
|
+
if (skip < 0) {
|
1208
|
+
int folder_index;
|
1209
|
+
switch (cab->entry_cffile->folder) {
|
1210
|
+
case iFoldCONTINUED_FROM_PREV:
|
1211
|
+
case iFoldCONTINUED_PREV_AND_NEXT:
|
1212
|
+
folder_index = 0;
|
1213
|
+
break;
|
1214
|
+
case iFoldCONTINUED_TO_NEXT:
|
1215
|
+
folder_index = cab->cfheader.folder_count-1;
|
1216
|
+
break;
|
1217
|
+
default:
|
1218
|
+
folder_index = cab->entry_cffile->folder;
|
1219
|
+
break;
|
1220
|
+
}
|
1221
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
1222
|
+
"Invalid offset of CFDATA in folder(%d) %jd < %jd",
|
1223
|
+
folder_index,
|
1224
|
+
(intmax_t)cab->entry_cffolder->cfdata_offset_in_cab,
|
1225
|
+
(intmax_t)cab->cab_offset);
|
1226
|
+
return (ARCHIVE_FATAL);
|
1227
|
+
}
|
1228
|
+
if (skip > 0) {
|
1229
|
+
if (__archive_read_consume(a, skip) < 0)
|
1230
|
+
return (ARCHIVE_FATAL);
|
1231
|
+
cab->cab_offset =
|
1232
|
+
cab->entry_cffolder->cfdata_offset_in_cab;
|
1233
|
+
}
|
1234
|
+
}
|
1235
|
+
|
1236
|
+
/*
|
1237
|
+
* Read a CFDATA.
|
1238
|
+
*/
|
1239
|
+
if (cab->entry_cffolder->cfdata_index <
|
1240
|
+
cab->entry_cffolder->cfdata_count) {
|
1241
|
+
const unsigned char *p;
|
1242
|
+
int l;
|
1243
|
+
|
1244
|
+
cfdata = &(cab->entry_cffolder->cfdata);
|
1245
|
+
cab->entry_cffolder->cfdata_index++;
|
1246
|
+
cab->entry_cfdata = cfdata;
|
1247
|
+
cfdata->sum_calculated = 0;
|
1248
|
+
cfdata->sum_extra_avail = 0;
|
1249
|
+
cfdata->sum_ptr = NULL;
|
1250
|
+
l = 8;
|
1251
|
+
if (cab->cfheader.flags & RESERVE_PRESENT)
|
1252
|
+
l += cab->cfheader.cfdata;
|
1253
|
+
if ((p = __archive_read_ahead(a, l, NULL)) == NULL)
|
1254
|
+
return (truncated_error(a));
|
1255
|
+
cfdata->sum = archive_le32dec(p + CFDATA_csum);
|
1256
|
+
cfdata->compressed_size = archive_le16dec(p + CFDATA_cbData);
|
1257
|
+
cfdata->compressed_bytes_remaining = cfdata->compressed_size;
|
1258
|
+
cfdata->uncompressed_size =
|
1259
|
+
archive_le16dec(p + CFDATA_cbUncomp);
|
1260
|
+
cfdata->uncompressed_bytes_remaining =
|
1261
|
+
cfdata->uncompressed_size;
|
1262
|
+
cfdata->uncompressed_avail = 0;
|
1263
|
+
cfdata->read_offset = 0;
|
1264
|
+
cfdata->unconsumed = 0;
|
1265
|
+
|
1266
|
+
/*
|
1267
|
+
* Sanity check if data size is acceptable.
|
1268
|
+
*/
|
1269
|
+
if (cfdata->compressed_size == 0 ||
|
1270
|
+
cfdata->compressed_size > (0x8000+6144))
|
1271
|
+
goto invalid;
|
1272
|
+
if (cfdata->uncompressed_size > 0x8000)
|
1273
|
+
goto invalid;
|
1274
|
+
if (cfdata->uncompressed_size == 0) {
|
1275
|
+
switch (cab->entry_cffile->folder) {
|
1276
|
+
case iFoldCONTINUED_PREV_AND_NEXT:
|
1277
|
+
case iFoldCONTINUED_TO_NEXT:
|
1278
|
+
break;
|
1279
|
+
case iFoldCONTINUED_FROM_PREV:
|
1280
|
+
default:
|
1281
|
+
goto invalid;
|
1282
|
+
}
|
1283
|
+
}
|
1284
|
+
/* If CFDATA is not last in a folder, an uncompressed
|
1285
|
+
* size must be 0x8000(32KBi) */
|
1286
|
+
if ((cab->entry_cffolder->cfdata_index <
|
1287
|
+
cab->entry_cffolder->cfdata_count) &&
|
1288
|
+
cfdata->uncompressed_size != 0x8000)
|
1289
|
+
goto invalid;
|
1290
|
+
|
1291
|
+
/* A compressed data size and an uncompressed data size must
|
1292
|
+
* be the same in no compression mode. */
|
1293
|
+
if (cab->entry_cffolder->comptype == COMPTYPE_NONE &&
|
1294
|
+
cfdata->compressed_size != cfdata->uncompressed_size)
|
1295
|
+
goto invalid;
|
1296
|
+
|
1297
|
+
/*
|
1298
|
+
* Save CFDATA image for sum check.
|
1299
|
+
*/
|
1300
|
+
if (cfdata->memimage_size < (size_t)l) {
|
1301
|
+
free(cfdata->memimage);
|
1302
|
+
cfdata->memimage = malloc(l);
|
1303
|
+
if (cfdata->memimage == NULL) {
|
1304
|
+
archive_set_error(&a->archive, ENOMEM,
|
1305
|
+
"Can't allocate memory for CAB data");
|
1306
|
+
return (ARCHIVE_FATAL);
|
1307
|
+
}
|
1308
|
+
cfdata->memimage_size = l;
|
1309
|
+
}
|
1310
|
+
memcpy(cfdata->memimage, p, l);
|
1311
|
+
|
1312
|
+
/* Consume bytes as much as we used. */
|
1313
|
+
__archive_read_consume(a, l);
|
1314
|
+
cab->cab_offset += l;
|
1315
|
+
} else if (cab->entry_cffolder->cfdata_count > 0) {
|
1316
|
+
/* Run out of all CFDATA in a folder. */
|
1317
|
+
cfdata->compressed_size = 0;
|
1318
|
+
cfdata->uncompressed_size = 0;
|
1319
|
+
cfdata->compressed_bytes_remaining = 0;
|
1320
|
+
cfdata->uncompressed_bytes_remaining = 0;
|
1321
|
+
} else {
|
1322
|
+
/* Current folder does not have any CFDATA. */
|
1323
|
+
cfdata = &(cab->entry_cffolder->cfdata);
|
1324
|
+
cab->entry_cfdata = cfdata;
|
1325
|
+
memset(cfdata, 0, sizeof(*cfdata));
|
1326
|
+
}
|
1327
|
+
return (ARCHIVE_OK);
|
1328
|
+
invalid:
|
1329
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
1330
|
+
"Invalid CFDATA");
|
1331
|
+
return (ARCHIVE_FATAL);
|
1332
|
+
}
|
1333
|
+
|
1334
|
+
/*
|
1335
|
+
* Read ahead CFDATA.
|
1336
|
+
*/
|
1337
|
+
static const void *
|
1338
|
+
cab_read_ahead_cfdata(struct archive_read *a, ssize_t *avail)
|
1339
|
+
{
|
1340
|
+
struct cab *cab = (struct cab *)(a->format->data);
|
1341
|
+
int err;
|
1342
|
+
|
1343
|
+
err = cab_next_cfdata(a);
|
1344
|
+
if (err < ARCHIVE_OK) {
|
1345
|
+
*avail = err;
|
1346
|
+
return (NULL);
|
1347
|
+
}
|
1348
|
+
|
1349
|
+
switch (cab->entry_cffolder->comptype) {
|
1350
|
+
case COMPTYPE_NONE:
|
1351
|
+
return (cab_read_ahead_cfdata_none(a, avail));
|
1352
|
+
case COMPTYPE_MSZIP:
|
1353
|
+
return (cab_read_ahead_cfdata_deflate(a, avail));
|
1354
|
+
case COMPTYPE_LZX:
|
1355
|
+
return (cab_read_ahead_cfdata_lzx(a, avail));
|
1356
|
+
default: /* Unsupported compression. */
|
1357
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
1358
|
+
"Unsupported CAB compression : %s",
|
1359
|
+
cab->entry_cffolder->compname);
|
1360
|
+
*avail = ARCHIVE_FAILED;
|
1361
|
+
return (NULL);
|
1362
|
+
}
|
1363
|
+
}
|
1364
|
+
|
1365
|
+
/*
|
1366
|
+
* Read ahead CFDATA as uncompressed data.
|
1367
|
+
*/
|
1368
|
+
static const void *
|
1369
|
+
cab_read_ahead_cfdata_none(struct archive_read *a, ssize_t *avail)
|
1370
|
+
{
|
1371
|
+
struct cab *cab = (struct cab *)(a->format->data);
|
1372
|
+
struct cfdata *cfdata;
|
1373
|
+
const void *d;
|
1374
|
+
|
1375
|
+
cfdata = cab->entry_cfdata;
|
1376
|
+
|
1377
|
+
/*
|
1378
|
+
* Note: '1' here is a performance optimization.
|
1379
|
+
* Recall that the decompression layer returns a count of
|
1380
|
+
* available bytes; asking for more than that forces the
|
1381
|
+
* decompressor to combine reads by copying data.
|
1382
|
+
*/
|
1383
|
+
d = __archive_read_ahead(a, 1, avail);
|
1384
|
+
if (*avail <= 0) {
|
1385
|
+
*avail = truncated_error(a);
|
1386
|
+
return (NULL);
|
1387
|
+
}
|
1388
|
+
if (*avail > cfdata->uncompressed_bytes_remaining)
|
1389
|
+
*avail = cfdata->uncompressed_bytes_remaining;
|
1390
|
+
cfdata->uncompressed_avail = cfdata->uncompressed_size;
|
1391
|
+
cfdata->unconsumed = *avail;
|
1392
|
+
cfdata->sum_ptr = d;
|
1393
|
+
return (d);
|
1394
|
+
}
|
1395
|
+
|
1396
|
+
/*
|
1397
|
+
* Read ahead CFDATA as deflate data.
|
1398
|
+
*/
|
1399
|
+
#ifdef HAVE_ZLIB_H
|
1400
|
+
static const void *
|
1401
|
+
cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
|
1402
|
+
{
|
1403
|
+
struct cab *cab = (struct cab *)(a->format->data);
|
1404
|
+
struct cfdata *cfdata;
|
1405
|
+
const void *d;
|
1406
|
+
int r, mszip;
|
1407
|
+
uint16_t uavail;
|
1408
|
+
char eod = 0;
|
1409
|
+
|
1410
|
+
cfdata = cab->entry_cfdata;
|
1411
|
+
/* If the buffer hasn't been allocated, allocate it now. */
|
1412
|
+
if (cab->uncompressed_buffer == NULL) {
|
1413
|
+
cab->uncompressed_buffer_size = 0x8000;
|
1414
|
+
cab->uncompressed_buffer
|
1415
|
+
= (unsigned char *)malloc(cab->uncompressed_buffer_size);
|
1416
|
+
if (cab->uncompressed_buffer == NULL) {
|
1417
|
+
archive_set_error(&a->archive, ENOMEM,
|
1418
|
+
"No memory for CAB reader");
|
1419
|
+
*avail = ARCHIVE_FATAL;
|
1420
|
+
return (NULL);
|
1421
|
+
}
|
1422
|
+
}
|
1423
|
+
|
1424
|
+
uavail = cfdata->uncompressed_avail;
|
1425
|
+
if (uavail == cfdata->uncompressed_size) {
|
1426
|
+
d = cab->uncompressed_buffer + cfdata->read_offset;
|
1427
|
+
*avail = uavail - cfdata->read_offset;
|
1428
|
+
return (d);
|
1429
|
+
}
|
1430
|
+
|
1431
|
+
if (!cab->entry_cffolder->decompress_init) {
|
1432
|
+
cab->stream.next_in = NULL;
|
1433
|
+
cab->stream.avail_in = 0;
|
1434
|
+
cab->stream.total_in = 0;
|
1435
|
+
cab->stream.next_out = NULL;
|
1436
|
+
cab->stream.avail_out = 0;
|
1437
|
+
cab->stream.total_out = 0;
|
1438
|
+
if (cab->stream_valid)
|
1439
|
+
r = inflateReset(&cab->stream);
|
1440
|
+
else
|
1441
|
+
r = inflateInit2(&cab->stream,
|
1442
|
+
-15 /* Don't check for zlib header */);
|
1443
|
+
if (r != Z_OK) {
|
1444
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
1445
|
+
"Can't initialize deflate decompression.");
|
1446
|
+
*avail = ARCHIVE_FATAL;
|
1447
|
+
return (NULL);
|
1448
|
+
}
|
1449
|
+
/* Stream structure has been set up. */
|
1450
|
+
cab->stream_valid = 1;
|
1451
|
+
/* We've initialized decompression for this stream. */
|
1452
|
+
cab->entry_cffolder->decompress_init = 1;
|
1453
|
+
}
|
1454
|
+
|
1455
|
+
if (cfdata->compressed_bytes_remaining == cfdata->compressed_size)
|
1456
|
+
mszip = 2;
|
1457
|
+
else
|
1458
|
+
mszip = 0;
|
1459
|
+
eod = 0;
|
1460
|
+
cab->stream.total_out = uavail;
|
1461
|
+
/*
|
1462
|
+
* We always uncompress all data in current CFDATA.
|
1463
|
+
*/
|
1464
|
+
while (!eod && cab->stream.total_out < cfdata->uncompressed_size) {
|
1465
|
+
ssize_t bytes_avail;
|
1466
|
+
|
1467
|
+
cab->stream.next_out =
|
1468
|
+
cab->uncompressed_buffer + cab->stream.total_out;
|
1469
|
+
cab->stream.avail_out =
|
1470
|
+
cfdata->uncompressed_size - cab->stream.total_out;
|
1471
|
+
|
1472
|
+
d = __archive_read_ahead(a, 1, &bytes_avail);
|
1473
|
+
if (bytes_avail <= 0) {
|
1474
|
+
*avail = truncated_error(a);
|
1475
|
+
return (NULL);
|
1476
|
+
}
|
1477
|
+
if (bytes_avail > cfdata->compressed_bytes_remaining)
|
1478
|
+
bytes_avail = cfdata->compressed_bytes_remaining;
|
1479
|
+
/*
|
1480
|
+
* A bug in zlib.h: stream.next_in should be marked 'const'
|
1481
|
+
* but isn't (the library never alters data through the
|
1482
|
+
* next_in pointer, only reads it). The result: this ugly
|
1483
|
+
* cast to remove 'const'.
|
1484
|
+
*/
|
1485
|
+
cab->stream.next_in = (Bytef *)(uintptr_t)d;
|
1486
|
+
cab->stream.avail_in = (uInt)bytes_avail;
|
1487
|
+
cab->stream.total_in = 0;
|
1488
|
+
|
1489
|
+
/* Cut out a tow-byte MSZIP signature(0x43, 0x4b). */
|
1490
|
+
if (mszip > 0) {
|
1491
|
+
if (bytes_avail <= 0)
|
1492
|
+
goto nomszip;
|
1493
|
+
if (bytes_avail <= mszip) {
|
1494
|
+
if (mszip == 2) {
|
1495
|
+
if (cab->stream.next_in[0] != 0x43)
|
1496
|
+
goto nomszip;
|
1497
|
+
if (bytes_avail > 1 &&
|
1498
|
+
cab->stream.next_in[1] != 0x4b)
|
1499
|
+
goto nomszip;
|
1500
|
+
} else if (cab->stream.next_in[0] != 0x4b)
|
1501
|
+
goto nomszip;
|
1502
|
+
cfdata->unconsumed = bytes_avail;
|
1503
|
+
cfdata->sum_ptr = d;
|
1504
|
+
if (cab_minimum_consume_cfdata(
|
1505
|
+
a, cfdata->unconsumed) < 0) {
|
1506
|
+
*avail = ARCHIVE_FATAL;
|
1507
|
+
return (NULL);
|
1508
|
+
}
|
1509
|
+
mszip -= (int)bytes_avail;
|
1510
|
+
continue;
|
1511
|
+
}
|
1512
|
+
if (mszip == 1 && cab->stream.next_in[0] != 0x4b)
|
1513
|
+
goto nomszip;
|
1514
|
+
else if (mszip == 2 && (cab->stream.next_in[0] != 0x43 ||
|
1515
|
+
cab->stream.next_in[1] != 0x4b))
|
1516
|
+
goto nomszip;
|
1517
|
+
cab->stream.next_in += mszip;
|
1518
|
+
cab->stream.avail_in -= mszip;
|
1519
|
+
cab->stream.total_in += mszip;
|
1520
|
+
mszip = 0;
|
1521
|
+
}
|
1522
|
+
|
1523
|
+
r = inflate(&cab->stream, 0);
|
1524
|
+
switch (r) {
|
1525
|
+
case Z_OK:
|
1526
|
+
break;
|
1527
|
+
case Z_STREAM_END:
|
1528
|
+
eod = 1;
|
1529
|
+
break;
|
1530
|
+
default:
|
1531
|
+
goto zlibfailed;
|
1532
|
+
}
|
1533
|
+
cfdata->unconsumed = cab->stream.total_in;
|
1534
|
+
cfdata->sum_ptr = d;
|
1535
|
+
if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) {
|
1536
|
+
*avail = ARCHIVE_FATAL;
|
1537
|
+
return (NULL);
|
1538
|
+
}
|
1539
|
+
}
|
1540
|
+
uavail = (uint16_t)cab->stream.total_out;
|
1541
|
+
|
1542
|
+
if (uavail < cfdata->uncompressed_size) {
|
1543
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
1544
|
+
"Invalid uncompressed size (%d < %d)",
|
1545
|
+
uavail, cfdata->uncompressed_size);
|
1546
|
+
*avail = ARCHIVE_FATAL;
|
1547
|
+
return (NULL);
|
1548
|
+
}
|
1549
|
+
|
1550
|
+
/*
|
1551
|
+
* Note: I suspect there is a bug in makecab.exe because, in rare
|
1552
|
+
* case, compressed bytes are still remaining regardless we have
|
1553
|
+
* gotten all uncompressed bytes, which size is recorded in CFDATA,
|
1554
|
+
* as much as we need, and we have to use the garbage so as to
|
1555
|
+
* correctly compute the sum of CFDATA accordingly.
|
1556
|
+
*/
|
1557
|
+
if (cfdata->compressed_bytes_remaining > 0) {
|
1558
|
+
ssize_t bytes_avail;
|
1559
|
+
|
1560
|
+
d = __archive_read_ahead(a, cfdata->compressed_bytes_remaining,
|
1561
|
+
&bytes_avail);
|
1562
|
+
if (bytes_avail <= 0) {
|
1563
|
+
*avail = truncated_error(a);
|
1564
|
+
return (NULL);
|
1565
|
+
}
|
1566
|
+
cfdata->unconsumed = cfdata->compressed_bytes_remaining;
|
1567
|
+
cfdata->sum_ptr = d;
|
1568
|
+
if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) {
|
1569
|
+
*avail = ARCHIVE_FATAL;
|
1570
|
+
return (NULL);
|
1571
|
+
}
|
1572
|
+
}
|
1573
|
+
|
1574
|
+
/*
|
1575
|
+
* Set dictionary data for decompressing of next CFDATA, which
|
1576
|
+
* in the same folder. This is why we always do decompress CFDATA
|
1577
|
+
* even if beginning CFDATA or some of CFDATA are not used in
|
1578
|
+
* skipping file data.
|
1579
|
+
*/
|
1580
|
+
if (cab->entry_cffolder->cfdata_index <
|
1581
|
+
cab->entry_cffolder->cfdata_count) {
|
1582
|
+
r = inflateReset(&cab->stream);
|
1583
|
+
if (r != Z_OK)
|
1584
|
+
goto zlibfailed;
|
1585
|
+
r = inflateSetDictionary(&cab->stream,
|
1586
|
+
cab->uncompressed_buffer, cfdata->uncompressed_size);
|
1587
|
+
if (r != Z_OK)
|
1588
|
+
goto zlibfailed;
|
1589
|
+
}
|
1590
|
+
|
1591
|
+
d = cab->uncompressed_buffer + cfdata->read_offset;
|
1592
|
+
*avail = uavail - cfdata->read_offset;
|
1593
|
+
cfdata->uncompressed_avail = uavail;
|
1594
|
+
|
1595
|
+
return (d);
|
1596
|
+
|
1597
|
+
zlibfailed:
|
1598
|
+
switch (r) {
|
1599
|
+
case Z_MEM_ERROR:
|
1600
|
+
archive_set_error(&a->archive, ENOMEM,
|
1601
|
+
"Out of memory for deflate decompression");
|
1602
|
+
break;
|
1603
|
+
default:
|
1604
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
1605
|
+
"Deflate decompression failed (%d)", r);
|
1606
|
+
break;
|
1607
|
+
}
|
1608
|
+
*avail = ARCHIVE_FATAL;
|
1609
|
+
return (NULL);
|
1610
|
+
nomszip:
|
1611
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
1612
|
+
"CFDATA incorrect(no MSZIP signature)");
|
1613
|
+
*avail = ARCHIVE_FATAL;
|
1614
|
+
return (NULL);
|
1615
|
+
}
|
1616
|
+
|
1617
|
+
#else /* HAVE_ZLIB_H */
|
1618
|
+
|
1619
|
+
static const void *
|
1620
|
+
cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
|
1621
|
+
{
|
1622
|
+
*avail = ARCHIVE_FATAL;
|
1623
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
1624
|
+
"libarchive compiled without deflate support (no libz)");
|
1625
|
+
return (NULL);
|
1626
|
+
}
|
1627
|
+
|
1628
|
+
#endif /* HAVE_ZLIB_H */
|
1629
|
+
|
1630
|
+
static const void *
|
1631
|
+
cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail)
|
1632
|
+
{
|
1633
|
+
struct cab *cab = (struct cab *)(a->format->data);
|
1634
|
+
struct cfdata *cfdata;
|
1635
|
+
const void *d;
|
1636
|
+
int r;
|
1637
|
+
uint16_t uavail;
|
1638
|
+
|
1639
|
+
cfdata = cab->entry_cfdata;
|
1640
|
+
/* If the buffer hasn't been allocated, allocate it now. */
|
1641
|
+
if (cab->uncompressed_buffer == NULL) {
|
1642
|
+
cab->uncompressed_buffer_size = 0x8000;
|
1643
|
+
cab->uncompressed_buffer
|
1644
|
+
= (unsigned char *)malloc(cab->uncompressed_buffer_size);
|
1645
|
+
if (cab->uncompressed_buffer == NULL) {
|
1646
|
+
archive_set_error(&a->archive, ENOMEM,
|
1647
|
+
"No memory for CAB reader");
|
1648
|
+
*avail = ARCHIVE_FATAL;
|
1649
|
+
return (NULL);
|
1650
|
+
}
|
1651
|
+
}
|
1652
|
+
|
1653
|
+
uavail = cfdata->uncompressed_avail;
|
1654
|
+
if (uavail == cfdata->uncompressed_size) {
|
1655
|
+
d = cab->uncompressed_buffer + cfdata->read_offset;
|
1656
|
+
*avail = uavail - cfdata->read_offset;
|
1657
|
+
return (d);
|
1658
|
+
}
|
1659
|
+
|
1660
|
+
if (!cab->entry_cffolder->decompress_init) {
|
1661
|
+
r = lzx_decode_init(&cab->xstrm,
|
1662
|
+
cab->entry_cffolder->compdata);
|
1663
|
+
if (r != ARCHIVE_OK) {
|
1664
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
1665
|
+
"Can't initialize LZX decompression.");
|
1666
|
+
*avail = ARCHIVE_FATAL;
|
1667
|
+
return (NULL);
|
1668
|
+
}
|
1669
|
+
/* We've initialized decompression for this stream. */
|
1670
|
+
cab->entry_cffolder->decompress_init = 1;
|
1671
|
+
}
|
1672
|
+
|
1673
|
+
/* Clean up remaining bits of previous CFDATA. */
|
1674
|
+
lzx_cleanup_bitstream(&cab->xstrm);
|
1675
|
+
cab->xstrm.total_out = uavail;
|
1676
|
+
while (cab->xstrm.total_out < cfdata->uncompressed_size) {
|
1677
|
+
ssize_t bytes_avail;
|
1678
|
+
|
1679
|
+
cab->xstrm.next_out =
|
1680
|
+
cab->uncompressed_buffer + cab->xstrm.total_out;
|
1681
|
+
cab->xstrm.avail_out =
|
1682
|
+
cfdata->uncompressed_size - cab->xstrm.total_out;
|
1683
|
+
|
1684
|
+
d = __archive_read_ahead(a, 1, &bytes_avail);
|
1685
|
+
if (bytes_avail <= 0) {
|
1686
|
+
archive_set_error(&a->archive,
|
1687
|
+
ARCHIVE_ERRNO_FILE_FORMAT,
|
1688
|
+
"Truncated CAB file data");
|
1689
|
+
*avail = ARCHIVE_FATAL;
|
1690
|
+
return (NULL);
|
1691
|
+
}
|
1692
|
+
if (bytes_avail > cfdata->compressed_bytes_remaining)
|
1693
|
+
bytes_avail = cfdata->compressed_bytes_remaining;
|
1694
|
+
|
1695
|
+
cab->xstrm.next_in = d;
|
1696
|
+
cab->xstrm.avail_in = bytes_avail;
|
1697
|
+
cab->xstrm.total_in = 0;
|
1698
|
+
r = lzx_decode(&cab->xstrm,
|
1699
|
+
cfdata->compressed_bytes_remaining == bytes_avail);
|
1700
|
+
switch (r) {
|
1701
|
+
case ARCHIVE_OK:
|
1702
|
+
case ARCHIVE_EOF:
|
1703
|
+
break;
|
1704
|
+
default:
|
1705
|
+
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
1706
|
+
"LZX decompression failed (%d)", r);
|
1707
|
+
*avail = ARCHIVE_FATAL;
|
1708
|
+
return (NULL);
|
1709
|
+
}
|
1710
|
+
cfdata->unconsumed = cab->xstrm.total_in;
|
1711
|
+
cfdata->sum_ptr = d;
|
1712
|
+
if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) {
|
1713
|
+
*avail = ARCHIVE_FATAL;
|
1714
|
+
return (NULL);
|
1715
|
+
}
|
1716
|
+
}
|
1717
|
+
|
1718
|
+
uavail = (uint16_t)cab->xstrm.total_out;
|
1719
|
+
/*
|
1720
|
+
* Make sure a read pointer advances to next CFDATA.
|
1721
|
+
*/
|
1722
|
+
if (cfdata->compressed_bytes_remaining > 0) {
|
1723
|
+
ssize_t bytes_avail;
|
1724
|
+
|
1725
|
+
d = __archive_read_ahead(a, cfdata->compressed_bytes_remaining,
|
1726
|
+
&bytes_avail);
|
1727
|
+
if (bytes_avail <= 0) {
|
1728
|
+
*avail = truncated_error(a);
|
1729
|
+
return (NULL);
|
1730
|
+
}
|
1731
|
+
cfdata->unconsumed = cfdata->compressed_bytes_remaining;
|
1732
|
+
cfdata->sum_ptr = d;
|
1733
|
+
if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) {
|
1734
|
+
*avail = ARCHIVE_FATAL;
|
1735
|
+
return (NULL);
|
1736
|
+
}
|
1737
|
+
}
|
1738
|
+
|
1739
|
+
/*
|
1740
|
+
* Translation reversal of x86 processor CALL byte sequence(E8).
|
1741
|
+
*/
|
1742
|
+
lzx_translation(&cab->xstrm, cab->uncompressed_buffer,
|
1743
|
+
cfdata->uncompressed_size,
|
1744
|
+
(cab->entry_cffolder->cfdata_index-1) * 0x8000);
|
1745
|
+
|
1746
|
+
d = cab->uncompressed_buffer + cfdata->read_offset;
|
1747
|
+
*avail = uavail - cfdata->read_offset;
|
1748
|
+
cfdata->uncompressed_avail = uavail;
|
1749
|
+
|
1750
|
+
return (d);
|
1751
|
+
}
|
1752
|
+
|
1753
|
+
/*
|
1754
|
+
* Consume CFDATA.
|
1755
|
+
* We always decompress CFDATA to consume CFDATA as much as we need
|
1756
|
+
* in uncompressed bytes because all CFDATA in a folder are related
|
1757
|
+
* so we do not skip any CFDATA without decompressing.
|
1758
|
+
* Note: If the folder of a CFFILE is iFoldCONTINUED_PREV_AND_NEXT or
|
1759
|
+
* iFoldCONTINUED_FROM_PREV, we won't decompress because a CFDATA for
|
1760
|
+
* the CFFILE is remaining bytes of previous Multivolume CAB file.
|
1761
|
+
*/
|
1762
|
+
static int64_t
|
1763
|
+
cab_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
|
1764
|
+
{
|
1765
|
+
struct cab *cab = (struct cab *)(a->format->data);
|
1766
|
+
struct cfdata *cfdata;
|
1767
|
+
int64_t cbytes, rbytes;
|
1768
|
+
int err;
|
1769
|
+
|
1770
|
+
rbytes = cab_minimum_consume_cfdata(a, consumed_bytes);
|
1771
|
+
if (rbytes < 0)
|
1772
|
+
return (ARCHIVE_FATAL);
|
1773
|
+
|
1774
|
+
cfdata = cab->entry_cfdata;
|
1775
|
+
while (rbytes > 0) {
|
1776
|
+
ssize_t avail;
|
1777
|
+
|
1778
|
+
if (cfdata->compressed_size == 0) {
|
1779
|
+
archive_set_error(&a->archive,
|
1780
|
+
ARCHIVE_ERRNO_FILE_FORMAT,
|
1781
|
+
"Invalid CFDATA");
|
1782
|
+
return (ARCHIVE_FATAL);
|
1783
|
+
}
|
1784
|
+
cbytes = cfdata->uncompressed_bytes_remaining;
|
1785
|
+
if (cbytes > rbytes)
|
1786
|
+
cbytes = rbytes;
|
1787
|
+
rbytes -= cbytes;
|
1788
|
+
|
1789
|
+
if (cfdata->uncompressed_avail == 0 &&
|
1790
|
+
(cab->entry_cffile->folder == iFoldCONTINUED_PREV_AND_NEXT ||
|
1791
|
+
cab->entry_cffile->folder == iFoldCONTINUED_FROM_PREV)) {
|
1792
|
+
/* We have not read any data yet. */
|
1793
|
+
if (cbytes == cfdata->uncompressed_bytes_remaining) {
|
1794
|
+
/* Skip whole current CFDATA. */
|
1795
|
+
__archive_read_consume(a,
|
1796
|
+
cfdata->compressed_size);
|
1797
|
+
cab->cab_offset += cfdata->compressed_size;
|
1798
|
+
cfdata->compressed_bytes_remaining = 0;
|
1799
|
+
cfdata->uncompressed_bytes_remaining = 0;
|
1800
|
+
err = cab_next_cfdata(a);
|
1801
|
+
if (err < 0)
|
1802
|
+
return (err);
|
1803
|
+
cfdata = cab->entry_cfdata;
|
1804
|
+
if (cfdata->uncompressed_size == 0) {
|
1805
|
+
switch (cab->entry_cffile->folder) {
|
1806
|
+
case iFoldCONTINUED_PREV_AND_NEXT:
|
1807
|
+
case iFoldCONTINUED_TO_NEXT:
|
1808
|
+
case iFoldCONTINUED_FROM_PREV:
|
1809
|
+
rbytes = 0;
|
1810
|
+
break;
|
1811
|
+
default:
|
1812
|
+
break;
|
1813
|
+
}
|
1814
|
+
}
|
1815
|
+
continue;
|
1816
|
+
}
|
1817
|
+
cfdata->read_offset += (uint16_t)cbytes;
|
1818
|
+
cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes;
|
1819
|
+
break;
|
1820
|
+
} else if (cbytes == 0) {
|
1821
|
+
err = cab_next_cfdata(a);
|
1822
|
+
if (err < 0)
|
1823
|
+
return (err);
|
1824
|
+
cfdata = cab->entry_cfdata;
|
1825
|
+
if (cfdata->uncompressed_size == 0) {
|
1826
|
+
switch (cab->entry_cffile->folder) {
|
1827
|
+
case iFoldCONTINUED_PREV_AND_NEXT:
|
1828
|
+
case iFoldCONTINUED_TO_NEXT:
|
1829
|
+
case iFoldCONTINUED_FROM_PREV:
|
1830
|
+
return (ARCHIVE_FATAL);
|
1831
|
+
default:
|
1832
|
+
break;
|
1833
|
+
}
|
1834
|
+
}
|
1835
|
+
continue;
|
1836
|
+
}
|
1837
|
+
while (cbytes > 0) {
|
1838
|
+
(void)cab_read_ahead_cfdata(a, &avail);
|
1839
|
+
if (avail <= 0)
|
1840
|
+
return (ARCHIVE_FATAL);
|
1841
|
+
if (avail > cbytes)
|
1842
|
+
avail = (ssize_t)cbytes;
|
1843
|
+
if (cab_minimum_consume_cfdata(a, avail) < 0)
|
1844
|
+
return (ARCHIVE_FATAL);
|
1845
|
+
cbytes -= avail;
|
1846
|
+
}
|
1847
|
+
}
|
1848
|
+
return (consumed_bytes);
|
1849
|
+
}
|
1850
|
+
|
1851
|
+
/*
|
1852
|
+
* Consume CFDATA as much as we have already gotten and
|
1853
|
+
* compute the sum of CFDATA.
|
1854
|
+
*/
|
1855
|
+
static int64_t
|
1856
|
+
cab_minimum_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
|
1857
|
+
{
|
1858
|
+
struct cab *cab = (struct cab *)(a->format->data);
|
1859
|
+
struct cfdata *cfdata;
|
1860
|
+
int64_t cbytes, rbytes;
|
1861
|
+
int err;
|
1862
|
+
|
1863
|
+
cfdata = cab->entry_cfdata;
|
1864
|
+
rbytes = consumed_bytes;
|
1865
|
+
if (cab->entry_cffolder->comptype == COMPTYPE_NONE) {
|
1866
|
+
if (consumed_bytes < cfdata->unconsumed)
|
1867
|
+
cbytes = consumed_bytes;
|
1868
|
+
else
|
1869
|
+
cbytes = cfdata->unconsumed;
|
1870
|
+
rbytes -= cbytes;
|
1871
|
+
cfdata->read_offset += (uint16_t)cbytes;
|
1872
|
+
cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes;
|
1873
|
+
cfdata->unconsumed -= cbytes;
|
1874
|
+
} else {
|
1875
|
+
cbytes = cfdata->uncompressed_avail - cfdata->read_offset;
|
1876
|
+
if (cbytes > 0) {
|
1877
|
+
if (consumed_bytes < cbytes)
|
1878
|
+
cbytes = consumed_bytes;
|
1879
|
+
rbytes -= cbytes;
|
1880
|
+
cfdata->read_offset += (uint16_t)cbytes;
|
1881
|
+
cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes;
|
1882
|
+
}
|
1883
|
+
|
1884
|
+
if (cfdata->unconsumed) {
|
1885
|
+
cbytes = cfdata->unconsumed;
|
1886
|
+
cfdata->unconsumed = 0;
|
1887
|
+
} else
|
1888
|
+
cbytes = 0;
|
1889
|
+
}
|
1890
|
+
if (cbytes) {
|
1891
|
+
/* Compute the sum. */
|
1892
|
+
cab_checksum_update(a, (size_t)cbytes);
|
1893
|
+
|
1894
|
+
/* Consume as much as the compressor actually used. */
|
1895
|
+
__archive_read_consume(a, cbytes);
|
1896
|
+
cab->cab_offset += cbytes;
|
1897
|
+
cfdata->compressed_bytes_remaining -= (uint16_t)cbytes;
|
1898
|
+
if (cfdata->compressed_bytes_remaining == 0) {
|
1899
|
+
err = cab_checksum_finish(a);
|
1900
|
+
if (err < 0)
|
1901
|
+
return (err);
|
1902
|
+
}
|
1903
|
+
}
|
1904
|
+
return (rbytes);
|
1905
|
+
}
|
1906
|
+
|
1907
|
+
/*
|
1908
|
+
* Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets
|
1909
|
+
* cab->end_of_entry if it consumes all of the data.
|
1910
|
+
*/
|
1911
|
+
static int
|
1912
|
+
cab_read_data(struct archive_read *a, const void **buff,
|
1913
|
+
size_t *size, int64_t *offset)
|
1914
|
+
{
|
1915
|
+
struct cab *cab = (struct cab *)(a->format->data);
|
1916
|
+
ssize_t bytes_avail;
|
1917
|
+
|
1918
|
+
if (cab->entry_bytes_remaining == 0) {
|
1919
|
+
*buff = NULL;
|
1920
|
+
*size = 0;
|
1921
|
+
*offset = cab->entry_offset;
|
1922
|
+
cab->end_of_entry = 1;
|
1923
|
+
return (ARCHIVE_OK);
|
1924
|
+
}
|
1925
|
+
|
1926
|
+
*buff = cab_read_ahead_cfdata(a, &bytes_avail);
|
1927
|
+
if (bytes_avail <= 0) {
|
1928
|
+
*buff = NULL;
|
1929
|
+
*size = 0;
|
1930
|
+
*offset = 0;
|
1931
|
+
if (bytes_avail == 0 &&
|
1932
|
+
cab->entry_cfdata->uncompressed_size == 0) {
|
1933
|
+
/* All of CFDATA in a folder has been handled. */
|
1934
|
+
archive_set_error(&a->archive,
|
1935
|
+
ARCHIVE_ERRNO_FILE_FORMAT, "Invalid CFDATA");
|
1936
|
+
return (ARCHIVE_FATAL);
|
1937
|
+
} else
|
1938
|
+
return ((int)bytes_avail);
|
1939
|
+
}
|
1940
|
+
if (bytes_avail > cab->entry_bytes_remaining)
|
1941
|
+
bytes_avail = (ssize_t)cab->entry_bytes_remaining;
|
1942
|
+
|
1943
|
+
*size = bytes_avail;
|
1944
|
+
*offset = cab->entry_offset;
|
1945
|
+
cab->entry_offset += bytes_avail;
|
1946
|
+
cab->entry_bytes_remaining -= bytes_avail;
|
1947
|
+
if (cab->entry_bytes_remaining == 0)
|
1948
|
+
cab->end_of_entry = 1;
|
1949
|
+
cab->entry_unconsumed = bytes_avail;
|
1950
|
+
if (cab->entry_cffolder->comptype == COMPTYPE_NONE) {
|
1951
|
+
/* Don't consume more than current entry used. */
|
1952
|
+
if (cab->entry_cfdata->unconsumed > cab->entry_unconsumed)
|
1953
|
+
cab->entry_cfdata->unconsumed = cab->entry_unconsumed;
|
1954
|
+
}
|
1955
|
+
return (ARCHIVE_OK);
|
1956
|
+
}
|
1957
|
+
|
1958
|
+
static int
|
1959
|
+
archive_read_format_cab_read_data_skip(struct archive_read *a)
|
1960
|
+
{
|
1961
|
+
struct cab *cab;
|
1962
|
+
int64_t bytes_skipped;
|
1963
|
+
int r;
|
1964
|
+
|
1965
|
+
cab = (struct cab *)(a->format->data);
|
1966
|
+
|
1967
|
+
if (cab->end_of_archive)
|
1968
|
+
return (ARCHIVE_EOF);
|
1969
|
+
|
1970
|
+
if (!cab->read_data_invoked) {
|
1971
|
+
cab->bytes_skipped += cab->entry_bytes_remaining;
|
1972
|
+
cab->entry_bytes_remaining = 0;
|
1973
|
+
/* This entry is finished and done. */
|
1974
|
+
cab->end_of_entry_cleanup = cab->end_of_entry = 1;
|
1975
|
+
return (ARCHIVE_OK);
|
1976
|
+
}
|
1977
|
+
|
1978
|
+
if (cab->entry_unconsumed) {
|
1979
|
+
/* Consume as much as the compressor actually used. */
|
1980
|
+
r = (int)cab_consume_cfdata(a, cab->entry_unconsumed);
|
1981
|
+
cab->entry_unconsumed = 0;
|
1982
|
+
if (r < 0)
|
1983
|
+
return (r);
|
1984
|
+
} else if (cab->entry_cfdata == NULL) {
|
1985
|
+
r = cab_next_cfdata(a);
|
1986
|
+
if (r < 0)
|
1987
|
+
return (r);
|
1988
|
+
}
|
1989
|
+
|
1990
|
+
/* if we've already read to end of data, we're done. */
|
1991
|
+
if (cab->end_of_entry_cleanup)
|
1992
|
+
return (ARCHIVE_OK);
|
1993
|
+
|
1994
|
+
/*
|
1995
|
+
* If the length is at the beginning, we can skip the
|
1996
|
+
* compressed data much more quickly.
|
1997
|
+
*/
|
1998
|
+
bytes_skipped = cab_consume_cfdata(a, cab->entry_bytes_remaining);
|
1999
|
+
if (bytes_skipped < 0)
|
2000
|
+
return (ARCHIVE_FATAL);
|
2001
|
+
|
2002
|
+
/* If the compression type is none(uncompressed), we've already
|
2003
|
+
* consumed data as much as the current entry size. */
|
2004
|
+
if (cab->entry_cffolder->comptype == COMPTYPE_NONE &&
|
2005
|
+
cab->entry_cfdata != NULL)
|
2006
|
+
cab->entry_cfdata->unconsumed = 0;
|
2007
|
+
|
2008
|
+
/* This entry is finished and done. */
|
2009
|
+
cab->end_of_entry_cleanup = cab->end_of_entry = 1;
|
2010
|
+
return (ARCHIVE_OK);
|
2011
|
+
}
|
2012
|
+
|
2013
|
+
static int
|
2014
|
+
archive_read_format_cab_cleanup(struct archive_read *a)
|
2015
|
+
{
|
2016
|
+
struct cab *cab = (struct cab *)(a->format->data);
|
2017
|
+
struct cfheader *hd = &cab->cfheader;
|
2018
|
+
int i;
|
2019
|
+
|
2020
|
+
if (hd->folder_array != NULL) {
|
2021
|
+
for (i = 0; i < hd->folder_count; i++)
|
2022
|
+
free(hd->folder_array[i].cfdata.memimage);
|
2023
|
+
free(hd->folder_array);
|
2024
|
+
}
|
2025
|
+
if (hd->file_array != NULL) {
|
2026
|
+
for (i = 0; i < cab->cfheader.file_count; i++)
|
2027
|
+
archive_string_free(&(hd->file_array[i].pathname));
|
2028
|
+
free(hd->file_array);
|
2029
|
+
}
|
2030
|
+
#ifdef HAVE_ZLIB_H
|
2031
|
+
if (cab->stream_valid)
|
2032
|
+
inflateEnd(&cab->stream);
|
2033
|
+
#endif
|
2034
|
+
lzx_decode_free(&cab->xstrm);
|
2035
|
+
archive_wstring_free(&cab->ws);
|
2036
|
+
free(cab->uncompressed_buffer);
|
2037
|
+
free(cab);
|
2038
|
+
(a->format->data) = NULL;
|
2039
|
+
return (ARCHIVE_OK);
|
2040
|
+
}
|
2041
|
+
|
2042
|
+
/* Convert an MSDOS-style date/time into Unix-style time. */
|
2043
|
+
static time_t
|
2044
|
+
cab_dos_time(const unsigned char *p)
|
2045
|
+
{
|
2046
|
+
int msTime, msDate;
|
2047
|
+
struct tm ts;
|
2048
|
+
|
2049
|
+
msDate = archive_le16dec(p);
|
2050
|
+
msTime = archive_le16dec(p+2);
|
2051
|
+
|
2052
|
+
memset(&ts, 0, sizeof(ts));
|
2053
|
+
ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */
|
2054
|
+
ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */
|
2055
|
+
ts.tm_mday = msDate & 0x1f; /* Day of month. */
|
2056
|
+
ts.tm_hour = (msTime >> 11) & 0x1f;
|
2057
|
+
ts.tm_min = (msTime >> 5) & 0x3f;
|
2058
|
+
ts.tm_sec = (msTime << 1) & 0x3e;
|
2059
|
+
ts.tm_isdst = -1;
|
2060
|
+
return (mktime(&ts));
|
2061
|
+
}
|
2062
|
+
|
2063
|
+
/*****************************************************************
|
2064
|
+
*
|
2065
|
+
* LZX decompression code.
|
2066
|
+
*
|
2067
|
+
*****************************************************************/
|
2068
|
+
|
2069
|
+
/*
|
2070
|
+
* Initialize LZX decoder.
|
2071
|
+
*
|
2072
|
+
* Returns ARCHIVE_OK if initialization was successful.
|
2073
|
+
* Returns ARCHIVE_FAILED if w_bits has unsupported value.
|
2074
|
+
* Returns ARCHIVE_FATAL if initialization failed; memory allocation
|
2075
|
+
* error occurred.
|
2076
|
+
*/
|
2077
|
+
static int
|
2078
|
+
lzx_decode_init(struct lzx_stream *strm, int w_bits)
|
2079
|
+
{
|
2080
|
+
struct lzx_dec *ds;
|
2081
|
+
int slot, w_size, w_slot;
|
2082
|
+
int base, footer;
|
2083
|
+
int base_inc[18];
|
2084
|
+
|
2085
|
+
if (strm->ds == NULL) {
|
2086
|
+
strm->ds = calloc(1, sizeof(*strm->ds));
|
2087
|
+
if (strm->ds == NULL)
|
2088
|
+
return (ARCHIVE_FATAL);
|
2089
|
+
}
|
2090
|
+
ds = strm->ds;
|
2091
|
+
ds->error = ARCHIVE_FAILED;
|
2092
|
+
|
2093
|
+
/* Allow bits from 15(32KBi) up to 21(2MBi) */
|
2094
|
+
if (w_bits < SLOT_BASE || w_bits > SLOT_MAX)
|
2095
|
+
return (ARCHIVE_FAILED);
|
2096
|
+
|
2097
|
+
ds->error = ARCHIVE_FATAL;
|
2098
|
+
|
2099
|
+
/*
|
2100
|
+
* Alloc window
|
2101
|
+
*/
|
2102
|
+
w_size = ds->w_size;
|
2103
|
+
w_slot = slots[w_bits - SLOT_BASE];
|
2104
|
+
ds->w_size = 1U << w_bits;
|
2105
|
+
ds->w_mask = ds->w_size -1;
|
2106
|
+
if (ds->w_buff == NULL || w_size != ds->w_size) {
|
2107
|
+
free(ds->w_buff);
|
2108
|
+
ds->w_buff = malloc(ds->w_size);
|
2109
|
+
if (ds->w_buff == NULL)
|
2110
|
+
return (ARCHIVE_FATAL);
|
2111
|
+
free(ds->pos_tbl);
|
2112
|
+
ds->pos_tbl = malloc(sizeof(ds->pos_tbl[0]) * w_slot);
|
2113
|
+
if (ds->pos_tbl == NULL)
|
2114
|
+
return (ARCHIVE_FATAL);
|
2115
|
+
}
|
2116
|
+
|
2117
|
+
for (footer = 0; footer < 18; footer++)
|
2118
|
+
base_inc[footer] = 1 << footer;
|
2119
|
+
base = footer = 0;
|
2120
|
+
for (slot = 0; slot < w_slot; slot++) {
|
2121
|
+
int n;
|
2122
|
+
if (footer == 0)
|
2123
|
+
base = slot;
|
2124
|
+
else
|
2125
|
+
base += base_inc[footer];
|
2126
|
+
if (footer < 17) {
|
2127
|
+
footer = -2;
|
2128
|
+
for (n = base; n; n >>= 1)
|
2129
|
+
footer++;
|
2130
|
+
if (footer <= 0)
|
2131
|
+
footer = 0;
|
2132
|
+
}
|
2133
|
+
ds->pos_tbl[slot].base = base;
|
2134
|
+
ds->pos_tbl[slot].footer_bits = footer;
|
2135
|
+
}
|
2136
|
+
|
2137
|
+
ds->w_pos = 0;
|
2138
|
+
ds->state = 0;
|
2139
|
+
ds->br.cache_buffer = 0;
|
2140
|
+
ds->br.cache_avail = 0;
|
2141
|
+
ds->r0 = ds->r1 = ds->r2 = 1;
|
2142
|
+
|
2143
|
+
/* Initialize aligned offset tree. */
|
2144
|
+
if (lzx_huffman_init(&(ds->at), 8, 8) != ARCHIVE_OK)
|
2145
|
+
return (ARCHIVE_FATAL);
|
2146
|
+
|
2147
|
+
/* Initialize pre-tree. */
|
2148
|
+
if (lzx_huffman_init(&(ds->pt), 20, 10) != ARCHIVE_OK)
|
2149
|
+
return (ARCHIVE_FATAL);
|
2150
|
+
|
2151
|
+
/* Initialize Main tree. */
|
2152
|
+
if (lzx_huffman_init(&(ds->mt), 256+(w_slot<<3), 16)
|
2153
|
+
!= ARCHIVE_OK)
|
2154
|
+
return (ARCHIVE_FATAL);
|
2155
|
+
|
2156
|
+
/* Initialize Length tree. */
|
2157
|
+
if (lzx_huffman_init(&(ds->lt), 249, 16) != ARCHIVE_OK)
|
2158
|
+
return (ARCHIVE_FATAL);
|
2159
|
+
|
2160
|
+
ds->error = 0;
|
2161
|
+
|
2162
|
+
return (ARCHIVE_OK);
|
2163
|
+
}
|
2164
|
+
|
2165
|
+
/*
|
2166
|
+
* Release LZX decoder.
|
2167
|
+
*/
|
2168
|
+
static void
|
2169
|
+
lzx_decode_free(struct lzx_stream *strm)
|
2170
|
+
{
|
2171
|
+
|
2172
|
+
if (strm->ds == NULL)
|
2173
|
+
return;
|
2174
|
+
free(strm->ds->w_buff);
|
2175
|
+
free(strm->ds->pos_tbl);
|
2176
|
+
lzx_huffman_free(&(strm->ds->at));
|
2177
|
+
lzx_huffman_free(&(strm->ds->pt));
|
2178
|
+
lzx_huffman_free(&(strm->ds->mt));
|
2179
|
+
lzx_huffman_free(&(strm->ds->lt));
|
2180
|
+
free(strm->ds);
|
2181
|
+
strm->ds = NULL;
|
2182
|
+
}
|
2183
|
+
|
2184
|
+
/*
|
2185
|
+
* E8 Call Translation reversal.
|
2186
|
+
*/
|
2187
|
+
static void
|
2188
|
+
lzx_translation(struct lzx_stream *strm, void *p, size_t size, uint32_t offset)
|
2189
|
+
{
|
2190
|
+
struct lzx_dec *ds = strm->ds;
|
2191
|
+
unsigned char *b, *end;
|
2192
|
+
|
2193
|
+
if (!ds->translation || size <= 10)
|
2194
|
+
return;
|
2195
|
+
b = p;
|
2196
|
+
end = b + size - 10;
|
2197
|
+
while (b < end && (b = memchr(b, 0xE8, end - b)) != NULL) {
|
2198
|
+
size_t i = b - (unsigned char *)p;
|
2199
|
+
int32_t cp, displacement, value;
|
2200
|
+
|
2201
|
+
cp = (int32_t)(offset + (uint32_t)i);
|
2202
|
+
value = archive_le32dec(&b[1]);
|
2203
|
+
if (value >= -cp && value < (int32_t)ds->translation_size) {
|
2204
|
+
if (value >= 0)
|
2205
|
+
displacement = value - cp;
|
2206
|
+
else
|
2207
|
+
displacement = value + ds->translation_size;
|
2208
|
+
archive_le32enc(&b[1], (uint32_t)displacement);
|
2209
|
+
}
|
2210
|
+
b += 5;
|
2211
|
+
}
|
2212
|
+
}
|
2213
|
+
|
2214
|
+
/*
|
2215
|
+
* Bit stream reader.
|
2216
|
+
*/
|
2217
|
+
/* Check that the cache buffer has enough bits. */
|
2218
|
+
#define lzx_br_has(br, n) ((br)->cache_avail >= n)
|
2219
|
+
/* Get compressed data by bit. */
|
2220
|
+
#define lzx_br_bits(br, n) \
|
2221
|
+
(((uint32_t)((br)->cache_buffer >> \
|
2222
|
+
((br)->cache_avail - (n)))) & cache_masks[n])
|
2223
|
+
#define lzx_br_bits_forced(br, n) \
|
2224
|
+
(((uint32_t)((br)->cache_buffer << \
|
2225
|
+
((n) - (br)->cache_avail))) & cache_masks[n])
|
2226
|
+
/* Read ahead to make sure the cache buffer has enough compressed data we
|
2227
|
+
* will use.
|
2228
|
+
* True : completed, there is enough data in the cache buffer.
|
2229
|
+
* False : we met that strm->next_in is empty, we have to get following
|
2230
|
+
* bytes. */
|
2231
|
+
#define lzx_br_read_ahead_0(strm, br, n) \
|
2232
|
+
(lzx_br_has((br), (n)) || lzx_br_fillup(strm, br))
|
2233
|
+
/* True : the cache buffer has some bits as much as we need.
|
2234
|
+
* False : there are no enough bits in the cache buffer to be used,
|
2235
|
+
* we have to get following bytes if we could. */
|
2236
|
+
#define lzx_br_read_ahead(strm, br, n) \
|
2237
|
+
(lzx_br_read_ahead_0((strm), (br), (n)) || lzx_br_has((br), (n)))
|
2238
|
+
|
2239
|
+
/* Notify how many bits we consumed. */
|
2240
|
+
#define lzx_br_consume(br, n) ((br)->cache_avail -= (n))
|
2241
|
+
#define lzx_br_consume_unaligned_bits(br) ((br)->cache_avail &= ~0x0f)
|
2242
|
+
|
2243
|
+
#define lzx_br_is_unaligned(br) ((br)->cache_avail & 0x0f)
|
2244
|
+
|
2245
|
+
static const uint32_t cache_masks[] = {
|
2246
|
+
0x00000000, 0x00000001, 0x00000003, 0x00000007,
|
2247
|
+
0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F,
|
2248
|
+
0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF,
|
2249
|
+
0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF,
|
2250
|
+
0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF,
|
2251
|
+
0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF,
|
2252
|
+
0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF,
|
2253
|
+
0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF,
|
2254
|
+
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
|
2255
|
+
};
|
2256
|
+
|
2257
|
+
/*
|
2258
|
+
* Shift away used bits in the cache data and fill it up with following bits.
|
2259
|
+
* Call this when cache buffer does not have enough bits you need.
|
2260
|
+
*
|
2261
|
+
* Returns 1 if the cache buffer is full.
|
2262
|
+
* Returns 0 if the cache buffer is not full; input buffer is empty.
|
2263
|
+
*/
|
2264
|
+
static int
|
2265
|
+
lzx_br_fillup(struct lzx_stream *strm, struct lzx_br *br)
|
2266
|
+
{
|
2267
|
+
/*
|
2268
|
+
* x86 processor family can read misaligned data without an access error.
|
2269
|
+
*/
|
2270
|
+
int n = CACHE_BITS - br->cache_avail;
|
2271
|
+
|
2272
|
+
for (;;) {
|
2273
|
+
switch (n >> 4) {
|
2274
|
+
case 4:
|
2275
|
+
if (strm->avail_in >= 8) {
|
2276
|
+
br->cache_buffer =
|
2277
|
+
((uint64_t)strm->next_in[1]) << 56 |
|
2278
|
+
((uint64_t)strm->next_in[0]) << 48 |
|
2279
|
+
((uint64_t)strm->next_in[3]) << 40 |
|
2280
|
+
((uint64_t)strm->next_in[2]) << 32 |
|
2281
|
+
((uint32_t)strm->next_in[5]) << 24 |
|
2282
|
+
((uint32_t)strm->next_in[4]) << 16 |
|
2283
|
+
((uint32_t)strm->next_in[7]) << 8 |
|
2284
|
+
(uint32_t)strm->next_in[6];
|
2285
|
+
strm->next_in += 8;
|
2286
|
+
strm->avail_in -= 8;
|
2287
|
+
br->cache_avail += 8 * 8;
|
2288
|
+
return (1);
|
2289
|
+
}
|
2290
|
+
break;
|
2291
|
+
case 3:
|
2292
|
+
if (strm->avail_in >= 6) {
|
2293
|
+
br->cache_buffer =
|
2294
|
+
(br->cache_buffer << 48) |
|
2295
|
+
((uint64_t)strm->next_in[1]) << 40 |
|
2296
|
+
((uint64_t)strm->next_in[0]) << 32 |
|
2297
|
+
((uint32_t)strm->next_in[3]) << 24 |
|
2298
|
+
((uint32_t)strm->next_in[2]) << 16 |
|
2299
|
+
((uint32_t)strm->next_in[5]) << 8 |
|
2300
|
+
(uint32_t)strm->next_in[4];
|
2301
|
+
strm->next_in += 6;
|
2302
|
+
strm->avail_in -= 6;
|
2303
|
+
br->cache_avail += 6 * 8;
|
2304
|
+
return (1);
|
2305
|
+
}
|
2306
|
+
break;
|
2307
|
+
case 0:
|
2308
|
+
/* We have enough compressed data in
|
2309
|
+
* the cache buffer.*/
|
2310
|
+
return (1);
|
2311
|
+
default:
|
2312
|
+
break;
|
2313
|
+
}
|
2314
|
+
if (strm->avail_in < 2) {
|
2315
|
+
/* There is not enough compressed data to
|
2316
|
+
* fill up the cache buffer. */
|
2317
|
+
if (strm->avail_in == 1) {
|
2318
|
+
br->odd = *strm->next_in++;
|
2319
|
+
strm->avail_in--;
|
2320
|
+
br->have_odd = 1;
|
2321
|
+
}
|
2322
|
+
return (0);
|
2323
|
+
}
|
2324
|
+
br->cache_buffer =
|
2325
|
+
(br->cache_buffer << 16) |
|
2326
|
+
archive_le16dec(strm->next_in);
|
2327
|
+
strm->next_in += 2;
|
2328
|
+
strm->avail_in -= 2;
|
2329
|
+
br->cache_avail += 16;
|
2330
|
+
n -= 16;
|
2331
|
+
}
|
2332
|
+
}
|
2333
|
+
|
2334
|
+
static void
|
2335
|
+
lzx_br_fixup(struct lzx_stream *strm, struct lzx_br *br)
|
2336
|
+
{
|
2337
|
+
int n = CACHE_BITS - br->cache_avail;
|
2338
|
+
|
2339
|
+
if (br->have_odd && n >= 16 && strm->avail_in > 0) {
|
2340
|
+
br->cache_buffer =
|
2341
|
+
(br->cache_buffer << 16) |
|
2342
|
+
((uint16_t)(*strm->next_in)) << 8 | br->odd;
|
2343
|
+
strm->next_in++;
|
2344
|
+
strm->avail_in--;
|
2345
|
+
br->cache_avail += 16;
|
2346
|
+
br->have_odd = 0;
|
2347
|
+
}
|
2348
|
+
}
|
2349
|
+
|
2350
|
+
static void
|
2351
|
+
lzx_cleanup_bitstream(struct lzx_stream *strm)
|
2352
|
+
{
|
2353
|
+
strm->ds->br.cache_avail = 0;
|
2354
|
+
strm->ds->br.have_odd = 0;
|
2355
|
+
}
|
2356
|
+
|
2357
|
+
/*
|
2358
|
+
* Decode LZX.
|
2359
|
+
*
|
2360
|
+
* 1. Returns ARCHIVE_OK if output buffer or input buffer are empty.
|
2361
|
+
* Please set available buffer and call this function again.
|
2362
|
+
* 2. Returns ARCHIVE_EOF if decompression has been completed.
|
2363
|
+
* 3. Returns ARCHIVE_FAILED if an error occurred; compressed data
|
2364
|
+
* is broken or you do not set 'last' flag properly.
|
2365
|
+
*/
|
2366
|
+
#define ST_RD_TRANSLATION 0
|
2367
|
+
#define ST_RD_TRANSLATION_SIZE 1
|
2368
|
+
#define ST_RD_BLOCK_TYPE 2
|
2369
|
+
#define ST_RD_BLOCK_SIZE 3
|
2370
|
+
#define ST_RD_ALIGNMENT 4
|
2371
|
+
#define ST_RD_R0 5
|
2372
|
+
#define ST_RD_R1 6
|
2373
|
+
#define ST_RD_R2 7
|
2374
|
+
#define ST_COPY_UNCOMP1 8
|
2375
|
+
#define ST_COPY_UNCOMP2 9
|
2376
|
+
#define ST_RD_ALIGNED_OFFSET 10
|
2377
|
+
#define ST_RD_VERBATIM 11
|
2378
|
+
#define ST_RD_PRE_MAIN_TREE_256 12
|
2379
|
+
#define ST_MAIN_TREE_256 13
|
2380
|
+
#define ST_RD_PRE_MAIN_TREE_REM 14
|
2381
|
+
#define ST_MAIN_TREE_REM 15
|
2382
|
+
#define ST_RD_PRE_LENGTH_TREE 16
|
2383
|
+
#define ST_LENGTH_TREE 17
|
2384
|
+
#define ST_MAIN 18
|
2385
|
+
#define ST_LENGTH 19
|
2386
|
+
#define ST_OFFSET 20
|
2387
|
+
#define ST_REAL_POS 21
|
2388
|
+
#define ST_COPY 22
|
2389
|
+
|
2390
|
+
static int
|
2391
|
+
lzx_decode(struct lzx_stream *strm, int last)
|
2392
|
+
{
|
2393
|
+
struct lzx_dec *ds = strm->ds;
|
2394
|
+
int64_t avail_in;
|
2395
|
+
int r;
|
2396
|
+
|
2397
|
+
if (ds->error)
|
2398
|
+
return (ds->error);
|
2399
|
+
|
2400
|
+
avail_in = strm->avail_in;
|
2401
|
+
lzx_br_fixup(strm, &(ds->br));
|
2402
|
+
do {
|
2403
|
+
if (ds->state < ST_MAIN)
|
2404
|
+
r = lzx_read_blocks(strm, last);
|
2405
|
+
else {
|
2406
|
+
int64_t bytes_written = strm->avail_out;
|
2407
|
+
r = lzx_decode_blocks(strm, last);
|
2408
|
+
bytes_written -= strm->avail_out;
|
2409
|
+
strm->next_out += bytes_written;
|
2410
|
+
strm->total_out += bytes_written;
|
2411
|
+
}
|
2412
|
+
} while (r == 100);
|
2413
|
+
strm->total_in += avail_in - strm->avail_in;
|
2414
|
+
return (r);
|
2415
|
+
}
|
2416
|
+
|
2417
|
+
static int
|
2418
|
+
lzx_read_blocks(struct lzx_stream *strm, int last)
|
2419
|
+
{
|
2420
|
+
struct lzx_dec *ds = strm->ds;
|
2421
|
+
struct lzx_br *br = &(ds->br);
|
2422
|
+
int i, r;
|
2423
|
+
|
2424
|
+
for (;;) {
|
2425
|
+
switch (ds->state) {
|
2426
|
+
case ST_RD_TRANSLATION:
|
2427
|
+
if (!lzx_br_read_ahead(strm, br, 1)) {
|
2428
|
+
ds->state = ST_RD_TRANSLATION;
|
2429
|
+
if (last)
|
2430
|
+
goto failed;
|
2431
|
+
return (ARCHIVE_OK);
|
2432
|
+
}
|
2433
|
+
ds->translation = lzx_br_bits(br, 1);
|
2434
|
+
lzx_br_consume(br, 1);
|
2435
|
+
/* FALL THROUGH */
|
2436
|
+
case ST_RD_TRANSLATION_SIZE:
|
2437
|
+
if (ds->translation) {
|
2438
|
+
if (!lzx_br_read_ahead(strm, br, 32)) {
|
2439
|
+
ds->state = ST_RD_TRANSLATION_SIZE;
|
2440
|
+
if (last)
|
2441
|
+
goto failed;
|
2442
|
+
return (ARCHIVE_OK);
|
2443
|
+
}
|
2444
|
+
ds->translation_size = lzx_br_bits(br, 16);
|
2445
|
+
lzx_br_consume(br, 16);
|
2446
|
+
ds->translation_size <<= 16;
|
2447
|
+
ds->translation_size |= lzx_br_bits(br, 16);
|
2448
|
+
lzx_br_consume(br, 16);
|
2449
|
+
}
|
2450
|
+
/* FALL THROUGH */
|
2451
|
+
case ST_RD_BLOCK_TYPE:
|
2452
|
+
if (!lzx_br_read_ahead(strm, br, 3)) {
|
2453
|
+
ds->state = ST_RD_BLOCK_TYPE;
|
2454
|
+
if (last)
|
2455
|
+
goto failed;
|
2456
|
+
return (ARCHIVE_OK);
|
2457
|
+
}
|
2458
|
+
ds->block_type = lzx_br_bits(br, 3);
|
2459
|
+
lzx_br_consume(br, 3);
|
2460
|
+
/* Check a block type. */
|
2461
|
+
switch (ds->block_type) {
|
2462
|
+
case VERBATIM_BLOCK:
|
2463
|
+
case ALIGNED_OFFSET_BLOCK:
|
2464
|
+
case UNCOMPRESSED_BLOCK:
|
2465
|
+
break;
|
2466
|
+
default:
|
2467
|
+
goto failed;/* Invalid */
|
2468
|
+
}
|
2469
|
+
/* FALL THROUGH */
|
2470
|
+
case ST_RD_BLOCK_SIZE:
|
2471
|
+
if (!lzx_br_read_ahead(strm, br, 24)) {
|
2472
|
+
ds->state = ST_RD_BLOCK_SIZE;
|
2473
|
+
if (last)
|
2474
|
+
goto failed;
|
2475
|
+
return (ARCHIVE_OK);
|
2476
|
+
}
|
2477
|
+
ds->block_size = lzx_br_bits(br, 8);
|
2478
|
+
lzx_br_consume(br, 8);
|
2479
|
+
ds->block_size <<= 16;
|
2480
|
+
ds->block_size |= lzx_br_bits(br, 16);
|
2481
|
+
lzx_br_consume(br, 16);
|
2482
|
+
if (ds->block_size == 0)
|
2483
|
+
goto failed;
|
2484
|
+
ds->block_bytes_avail = ds->block_size;
|
2485
|
+
if (ds->block_type != UNCOMPRESSED_BLOCK) {
|
2486
|
+
if (ds->block_type == VERBATIM_BLOCK)
|
2487
|
+
ds->state = ST_RD_VERBATIM;
|
2488
|
+
else
|
2489
|
+
ds->state = ST_RD_ALIGNED_OFFSET;
|
2490
|
+
break;
|
2491
|
+
}
|
2492
|
+
/* FALL THROUGH */
|
2493
|
+
case ST_RD_ALIGNMENT:
|
2494
|
+
/*
|
2495
|
+
* Handle an Uncompressed Block.
|
2496
|
+
*/
|
2497
|
+
/* Skip padding to align following field on
|
2498
|
+
* 16-bit boundary. */
|
2499
|
+
if (lzx_br_is_unaligned(br))
|
2500
|
+
lzx_br_consume_unaligned_bits(br);
|
2501
|
+
else {
|
2502
|
+
if (lzx_br_read_ahead(strm, br, 16))
|
2503
|
+
lzx_br_consume(br, 16);
|
2504
|
+
else {
|
2505
|
+
ds->state = ST_RD_ALIGNMENT;
|
2506
|
+
if (last)
|
2507
|
+
goto failed;
|
2508
|
+
return (ARCHIVE_OK);
|
2509
|
+
}
|
2510
|
+
}
|
2511
|
+
/* Preparation to read repeated offsets R0,R1 and R2. */
|
2512
|
+
ds->rbytes_avail = 0;
|
2513
|
+
ds->state = ST_RD_R0;
|
2514
|
+
/* FALL THROUGH */
|
2515
|
+
case ST_RD_R0:
|
2516
|
+
case ST_RD_R1:
|
2517
|
+
case ST_RD_R2:
|
2518
|
+
do {
|
2519
|
+
uint16_t u16;
|
2520
|
+
/* Drain bits in the cache buffer of
|
2521
|
+
* bit-stream. */
|
2522
|
+
if (lzx_br_has(br, 32)) {
|
2523
|
+
u16 = lzx_br_bits(br, 16);
|
2524
|
+
lzx_br_consume(br, 16);
|
2525
|
+
archive_le16enc(ds->rbytes, u16);
|
2526
|
+
u16 = lzx_br_bits(br, 16);
|
2527
|
+
lzx_br_consume(br, 16);
|
2528
|
+
archive_le16enc(ds->rbytes+2, u16);
|
2529
|
+
ds->rbytes_avail = 4;
|
2530
|
+
} else if (lzx_br_has(br, 16)) {
|
2531
|
+
u16 = lzx_br_bits(br, 16);
|
2532
|
+
lzx_br_consume(br, 16);
|
2533
|
+
archive_le16enc(ds->rbytes, u16);
|
2534
|
+
ds->rbytes_avail = 2;
|
2535
|
+
}
|
2536
|
+
if (ds->rbytes_avail < 4 && ds->br.have_odd) {
|
2537
|
+
ds->rbytes[ds->rbytes_avail++] =
|
2538
|
+
ds->br.odd;
|
2539
|
+
ds->br.have_odd = 0;
|
2540
|
+
}
|
2541
|
+
while (ds->rbytes_avail < 4) {
|
2542
|
+
if (strm->avail_in <= 0) {
|
2543
|
+
if (last)
|
2544
|
+
goto failed;
|
2545
|
+
return (ARCHIVE_OK);
|
2546
|
+
}
|
2547
|
+
ds->rbytes[ds->rbytes_avail++] =
|
2548
|
+
*strm->next_in++;
|
2549
|
+
strm->avail_in--;
|
2550
|
+
}
|
2551
|
+
ds->rbytes_avail = 0;
|
2552
|
+
if (ds->state == ST_RD_R0) {
|
2553
|
+
ds->r0 = archive_le32dec(ds->rbytes);
|
2554
|
+
if (ds->r0 < 0)
|
2555
|
+
goto failed;
|
2556
|
+
ds->state = ST_RD_R1;
|
2557
|
+
} else if (ds->state == ST_RD_R1) {
|
2558
|
+
ds->r1 = archive_le32dec(ds->rbytes);
|
2559
|
+
if (ds->r1 < 0)
|
2560
|
+
goto failed;
|
2561
|
+
ds->state = ST_RD_R2;
|
2562
|
+
} else if (ds->state == ST_RD_R2) {
|
2563
|
+
ds->r2 = archive_le32dec(ds->rbytes);
|
2564
|
+
if (ds->r2 < 0)
|
2565
|
+
goto failed;
|
2566
|
+
/* We've gotten all repeated offsets. */
|
2567
|
+
ds->state = ST_COPY_UNCOMP1;
|
2568
|
+
}
|
2569
|
+
} while (ds->state != ST_COPY_UNCOMP1);
|
2570
|
+
/* FALL THROUGH */
|
2571
|
+
case ST_COPY_UNCOMP1:
|
2572
|
+
/*
|
2573
|
+
* Copy bytes form next_in to next_out directly.
|
2574
|
+
*/
|
2575
|
+
while (ds->block_bytes_avail) {
|
2576
|
+
int l;
|
2577
|
+
|
2578
|
+
if (strm->avail_out <= 0)
|
2579
|
+
/* Output buffer is empty. */
|
2580
|
+
return (ARCHIVE_OK);
|
2581
|
+
if (strm->avail_in <= 0) {
|
2582
|
+
/* Input buffer is empty. */
|
2583
|
+
if (last)
|
2584
|
+
goto failed;
|
2585
|
+
return (ARCHIVE_OK);
|
2586
|
+
}
|
2587
|
+
l = (int)ds->block_bytes_avail;
|
2588
|
+
if (l > ds->w_size - ds->w_pos)
|
2589
|
+
l = ds->w_size - ds->w_pos;
|
2590
|
+
if (l > strm->avail_out)
|
2591
|
+
l = (int)strm->avail_out;
|
2592
|
+
if (l > strm->avail_in)
|
2593
|
+
l = (int)strm->avail_in;
|
2594
|
+
memcpy(strm->next_out, strm->next_in, l);
|
2595
|
+
memcpy(&(ds->w_buff[ds->w_pos]),
|
2596
|
+
strm->next_in, l);
|
2597
|
+
strm->next_in += l;
|
2598
|
+
strm->avail_in -= l;
|
2599
|
+
strm->next_out += l;
|
2600
|
+
strm->avail_out -= l;
|
2601
|
+
strm->total_out += l;
|
2602
|
+
ds->w_pos = (ds->w_pos + l) & ds->w_mask;
|
2603
|
+
ds->block_bytes_avail -= l;
|
2604
|
+
}
|
2605
|
+
/* FALL THROUGH */
|
2606
|
+
case ST_COPY_UNCOMP2:
|
2607
|
+
/* Re-align; skip padding byte. */
|
2608
|
+
if (ds->block_size & 1) {
|
2609
|
+
if (strm->avail_in <= 0) {
|
2610
|
+
/* Input buffer is empty. */
|
2611
|
+
ds->state = ST_COPY_UNCOMP2;
|
2612
|
+
if (last)
|
2613
|
+
goto failed;
|
2614
|
+
return (ARCHIVE_OK);
|
2615
|
+
}
|
2616
|
+
strm->next_in++;
|
2617
|
+
strm->avail_in --;
|
2618
|
+
}
|
2619
|
+
/* This block ended. */
|
2620
|
+
ds->state = ST_RD_BLOCK_TYPE;
|
2621
|
+
return (ARCHIVE_EOF);
|
2622
|
+
/********************/
|
2623
|
+
case ST_RD_ALIGNED_OFFSET:
|
2624
|
+
/*
|
2625
|
+
* Read Aligned offset tree.
|
2626
|
+
*/
|
2627
|
+
if (!lzx_br_read_ahead(strm, br, 3 * ds->at.len_size)) {
|
2628
|
+
ds->state = ST_RD_ALIGNED_OFFSET;
|
2629
|
+
if (last)
|
2630
|
+
goto failed;
|
2631
|
+
return (ARCHIVE_OK);
|
2632
|
+
}
|
2633
|
+
memset(ds->at.freq, 0, sizeof(ds->at.freq));
|
2634
|
+
for (i = 0; i < ds->at.len_size; i++) {
|
2635
|
+
ds->at.bitlen[i] = lzx_br_bits(br, 3);
|
2636
|
+
ds->at.freq[ds->at.bitlen[i]]++;
|
2637
|
+
lzx_br_consume(br, 3);
|
2638
|
+
}
|
2639
|
+
if (!lzx_make_huffman_table(&ds->at))
|
2640
|
+
goto failed;
|
2641
|
+
/* FALL THROUGH */
|
2642
|
+
case ST_RD_VERBATIM:
|
2643
|
+
ds->loop = 0;
|
2644
|
+
/* FALL THROUGH */
|
2645
|
+
case ST_RD_PRE_MAIN_TREE_256:
|
2646
|
+
/*
|
2647
|
+
* Read Pre-tree for first 256 elements of main tree.
|
2648
|
+
*/
|
2649
|
+
if (!lzx_read_pre_tree(strm)) {
|
2650
|
+
ds->state = ST_RD_PRE_MAIN_TREE_256;
|
2651
|
+
if (last)
|
2652
|
+
goto failed;
|
2653
|
+
return (ARCHIVE_OK);
|
2654
|
+
}
|
2655
|
+
if (!lzx_make_huffman_table(&ds->pt))
|
2656
|
+
goto failed;
|
2657
|
+
ds->loop = 0;
|
2658
|
+
/* FALL THROUGH */
|
2659
|
+
case ST_MAIN_TREE_256:
|
2660
|
+
/*
|
2661
|
+
* Get path lengths of first 256 elements of main tree.
|
2662
|
+
*/
|
2663
|
+
r = lzx_read_bitlen(strm, &ds->mt, 256);
|
2664
|
+
if (r < 0)
|
2665
|
+
goto failed;
|
2666
|
+
else if (!r) {
|
2667
|
+
ds->state = ST_MAIN_TREE_256;
|
2668
|
+
if (last)
|
2669
|
+
goto failed;
|
2670
|
+
return (ARCHIVE_OK);
|
2671
|
+
}
|
2672
|
+
ds->loop = 0;
|
2673
|
+
/* FALL THROUGH */
|
2674
|
+
case ST_RD_PRE_MAIN_TREE_REM:
|
2675
|
+
/*
|
2676
|
+
* Read Pre-tree for remaining elements of main tree.
|
2677
|
+
*/
|
2678
|
+
if (!lzx_read_pre_tree(strm)) {
|
2679
|
+
ds->state = ST_RD_PRE_MAIN_TREE_REM;
|
2680
|
+
if (last)
|
2681
|
+
goto failed;
|
2682
|
+
return (ARCHIVE_OK);
|
2683
|
+
}
|
2684
|
+
if (!lzx_make_huffman_table(&ds->pt))
|
2685
|
+
goto failed;
|
2686
|
+
ds->loop = 256;
|
2687
|
+
/* FALL THROUGH */
|
2688
|
+
case ST_MAIN_TREE_REM:
|
2689
|
+
/*
|
2690
|
+
* Get path lengths of remaining elements of main tree.
|
2691
|
+
*/
|
2692
|
+
r = lzx_read_bitlen(strm, &ds->mt, -1);
|
2693
|
+
if (r < 0)
|
2694
|
+
goto failed;
|
2695
|
+
else if (!r) {
|
2696
|
+
ds->state = ST_MAIN_TREE_REM;
|
2697
|
+
if (last)
|
2698
|
+
goto failed;
|
2699
|
+
return (ARCHIVE_OK);
|
2700
|
+
}
|
2701
|
+
if (!lzx_make_huffman_table(&ds->mt))
|
2702
|
+
goto failed;
|
2703
|
+
ds->loop = 0;
|
2704
|
+
/* FALL THROUGH */
|
2705
|
+
case ST_RD_PRE_LENGTH_TREE:
|
2706
|
+
/*
|
2707
|
+
* Read Pre-tree for remaining elements of main tree.
|
2708
|
+
*/
|
2709
|
+
if (!lzx_read_pre_tree(strm)) {
|
2710
|
+
ds->state = ST_RD_PRE_LENGTH_TREE;
|
2711
|
+
if (last)
|
2712
|
+
goto failed;
|
2713
|
+
return (ARCHIVE_OK);
|
2714
|
+
}
|
2715
|
+
if (!lzx_make_huffman_table(&ds->pt))
|
2716
|
+
goto failed;
|
2717
|
+
ds->loop = 0;
|
2718
|
+
/* FALL THROUGH */
|
2719
|
+
case ST_LENGTH_TREE:
|
2720
|
+
/*
|
2721
|
+
* Get path lengths of remaining elements of main tree.
|
2722
|
+
*/
|
2723
|
+
r = lzx_read_bitlen(strm, &ds->lt, -1);
|
2724
|
+
if (r < 0)
|
2725
|
+
goto failed;
|
2726
|
+
else if (!r) {
|
2727
|
+
ds->state = ST_LENGTH_TREE;
|
2728
|
+
if (last)
|
2729
|
+
goto failed;
|
2730
|
+
return (ARCHIVE_OK);
|
2731
|
+
}
|
2732
|
+
if (!lzx_make_huffman_table(&ds->lt))
|
2733
|
+
goto failed;
|
2734
|
+
ds->state = ST_MAIN;
|
2735
|
+
return (100);
|
2736
|
+
}
|
2737
|
+
}
|
2738
|
+
failed:
|
2739
|
+
return (ds->error = ARCHIVE_FAILED);
|
2740
|
+
}
|
2741
|
+
|
2742
|
+
static int
|
2743
|
+
lzx_decode_blocks(struct lzx_stream *strm, int last)
|
2744
|
+
{
|
2745
|
+
struct lzx_dec *ds = strm->ds;
|
2746
|
+
struct lzx_br bre = ds->br;
|
2747
|
+
struct huffman *at = &(ds->at), *lt = &(ds->lt), *mt = &(ds->mt);
|
2748
|
+
const struct lzx_pos_tbl *pos_tbl = ds->pos_tbl;
|
2749
|
+
unsigned char *noutp = strm->next_out;
|
2750
|
+
unsigned char *endp = noutp + strm->avail_out;
|
2751
|
+
unsigned char *w_buff = ds->w_buff;
|
2752
|
+
unsigned char *at_bitlen = at->bitlen;
|
2753
|
+
unsigned char *lt_bitlen = lt->bitlen;
|
2754
|
+
unsigned char *mt_bitlen = mt->bitlen;
|
2755
|
+
size_t block_bytes_avail = ds->block_bytes_avail;
|
2756
|
+
int at_max_bits = at->max_bits;
|
2757
|
+
int lt_max_bits = lt->max_bits;
|
2758
|
+
int mt_max_bits = mt->max_bits;
|
2759
|
+
int c, copy_len = ds->copy_len, copy_pos = ds->copy_pos;
|
2760
|
+
int w_pos = ds->w_pos, w_mask = ds->w_mask, w_size = ds->w_size;
|
2761
|
+
int length_header = ds->length_header;
|
2762
|
+
int offset_bits = ds->offset_bits;
|
2763
|
+
int position_slot = ds->position_slot;
|
2764
|
+
int r0 = ds->r0, r1 = ds->r1, r2 = ds->r2;
|
2765
|
+
int state = ds->state;
|
2766
|
+
char block_type = ds->block_type;
|
2767
|
+
|
2768
|
+
for (;;) {
|
2769
|
+
switch (state) {
|
2770
|
+
case ST_MAIN:
|
2771
|
+
for (;;) {
|
2772
|
+
if (block_bytes_avail == 0) {
|
2773
|
+
/* This block ended. */
|
2774
|
+
ds->state = ST_RD_BLOCK_TYPE;
|
2775
|
+
ds->br = bre;
|
2776
|
+
ds->block_bytes_avail =
|
2777
|
+
block_bytes_avail;
|
2778
|
+
ds->copy_len = copy_len;
|
2779
|
+
ds->copy_pos = copy_pos;
|
2780
|
+
ds->length_header = length_header;
|
2781
|
+
ds->position_slot = position_slot;
|
2782
|
+
ds->r0 = r0; ds->r1 = r1; ds->r2 = r2;
|
2783
|
+
ds->w_pos = w_pos;
|
2784
|
+
strm->avail_out = endp - noutp;
|
2785
|
+
return (ARCHIVE_EOF);
|
2786
|
+
}
|
2787
|
+
if (noutp >= endp)
|
2788
|
+
/* Output buffer is empty. */
|
2789
|
+
goto next_data;
|
2790
|
+
|
2791
|
+
if (!lzx_br_read_ahead(strm, &bre,
|
2792
|
+
mt_max_bits)) {
|
2793
|
+
if (!last)
|
2794
|
+
goto next_data;
|
2795
|
+
/* Remaining bits are less than
|
2796
|
+
* maximum bits(mt.max_bits) but maybe
|
2797
|
+
* it still remains as much as we need,
|
2798
|
+
* so we should try to use it with
|
2799
|
+
* dummy bits. */
|
2800
|
+
c = lzx_decode_huffman(mt,
|
2801
|
+
lzx_br_bits_forced(
|
2802
|
+
&bre, mt_max_bits));
|
2803
|
+
lzx_br_consume(&bre, mt_bitlen[c]);
|
2804
|
+
if (!lzx_br_has(&bre, 0))
|
2805
|
+
goto failed;/* Over read. */
|
2806
|
+
} else {
|
2807
|
+
c = lzx_decode_huffman(mt,
|
2808
|
+
lzx_br_bits(&bre, mt_max_bits));
|
2809
|
+
lzx_br_consume(&bre, mt_bitlen[c]);
|
2810
|
+
}
|
2811
|
+
if (c > UCHAR_MAX)
|
2812
|
+
break;
|
2813
|
+
/*
|
2814
|
+
* 'c' is exactly literal code.
|
2815
|
+
*/
|
2816
|
+
/* Save a decoded code to reference it
|
2817
|
+
* afterward. */
|
2818
|
+
w_buff[w_pos] = c;
|
2819
|
+
w_pos = (w_pos + 1) & w_mask;
|
2820
|
+
/* Store the decoded code to output buffer. */
|
2821
|
+
*noutp++ = c;
|
2822
|
+
block_bytes_avail--;
|
2823
|
+
}
|
2824
|
+
/*
|
2825
|
+
* Get a match code, its length and offset.
|
2826
|
+
*/
|
2827
|
+
c -= UCHAR_MAX + 1;
|
2828
|
+
length_header = c & 7;
|
2829
|
+
position_slot = c >> 3;
|
2830
|
+
/* FALL THROUGH */
|
2831
|
+
case ST_LENGTH:
|
2832
|
+
/*
|
2833
|
+
* Get a length.
|
2834
|
+
*/
|
2835
|
+
if (length_header == 7) {
|
2836
|
+
if (!lzx_br_read_ahead(strm, &bre,
|
2837
|
+
lt_max_bits)) {
|
2838
|
+
if (!last) {
|
2839
|
+
state = ST_LENGTH;
|
2840
|
+
goto next_data;
|
2841
|
+
}
|
2842
|
+
c = lzx_decode_huffman(lt,
|
2843
|
+
lzx_br_bits_forced(
|
2844
|
+
&bre, lt_max_bits));
|
2845
|
+
lzx_br_consume(&bre, lt_bitlen[c]);
|
2846
|
+
if (!lzx_br_has(&bre, 0))
|
2847
|
+
goto failed;/* Over read. */
|
2848
|
+
} else {
|
2849
|
+
c = lzx_decode_huffman(lt,
|
2850
|
+
lzx_br_bits(&bre, lt_max_bits));
|
2851
|
+
lzx_br_consume(&bre, lt_bitlen[c]);
|
2852
|
+
}
|
2853
|
+
copy_len = c + 7 + 2;
|
2854
|
+
} else
|
2855
|
+
copy_len = length_header + 2;
|
2856
|
+
if ((size_t)copy_len > block_bytes_avail)
|
2857
|
+
goto failed;
|
2858
|
+
/*
|
2859
|
+
* Get an offset.
|
2860
|
+
*/
|
2861
|
+
switch (position_slot) {
|
2862
|
+
case 0: /* Use repeated offset 0. */
|
2863
|
+
copy_pos = r0;
|
2864
|
+
state = ST_REAL_POS;
|
2865
|
+
continue;
|
2866
|
+
case 1: /* Use repeated offset 1. */
|
2867
|
+
copy_pos = r1;
|
2868
|
+
/* Swap repeated offset. */
|
2869
|
+
r1 = r0;
|
2870
|
+
r0 = copy_pos;
|
2871
|
+
state = ST_REAL_POS;
|
2872
|
+
continue;
|
2873
|
+
case 2: /* Use repeated offset 2. */
|
2874
|
+
copy_pos = r2;
|
2875
|
+
/* Swap repeated offset. */
|
2876
|
+
r2 = r0;
|
2877
|
+
r0 = copy_pos;
|
2878
|
+
state = ST_REAL_POS;
|
2879
|
+
continue;
|
2880
|
+
default:
|
2881
|
+
offset_bits =
|
2882
|
+
pos_tbl[position_slot].footer_bits;
|
2883
|
+
break;
|
2884
|
+
}
|
2885
|
+
/* FALL THROUGH */
|
2886
|
+
case ST_OFFSET:
|
2887
|
+
/*
|
2888
|
+
* Get the offset, which is a distance from
|
2889
|
+
* current window position.
|
2890
|
+
*/
|
2891
|
+
if (block_type == ALIGNED_OFFSET_BLOCK &&
|
2892
|
+
offset_bits >= 3) {
|
2893
|
+
int offbits = offset_bits - 3;
|
2894
|
+
|
2895
|
+
if (!lzx_br_read_ahead(strm, &bre, offbits)) {
|
2896
|
+
state = ST_OFFSET;
|
2897
|
+
if (last)
|
2898
|
+
goto failed;
|
2899
|
+
goto next_data;
|
2900
|
+
}
|
2901
|
+
copy_pos = lzx_br_bits(&bre, offbits) << 3;
|
2902
|
+
|
2903
|
+
/* Get an aligned number. */
|
2904
|
+
if (!lzx_br_read_ahead(strm, &bre,
|
2905
|
+
offbits + at_max_bits)) {
|
2906
|
+
if (!last) {
|
2907
|
+
state = ST_OFFSET;
|
2908
|
+
goto next_data;
|
2909
|
+
}
|
2910
|
+
lzx_br_consume(&bre, offbits);
|
2911
|
+
c = lzx_decode_huffman(at,
|
2912
|
+
lzx_br_bits_forced(&bre,
|
2913
|
+
at_max_bits));
|
2914
|
+
lzx_br_consume(&bre, at_bitlen[c]);
|
2915
|
+
if (!lzx_br_has(&bre, 0))
|
2916
|
+
goto failed;/* Over read. */
|
2917
|
+
} else {
|
2918
|
+
lzx_br_consume(&bre, offbits);
|
2919
|
+
c = lzx_decode_huffman(at,
|
2920
|
+
lzx_br_bits(&bre, at_max_bits));
|
2921
|
+
lzx_br_consume(&bre, at_bitlen[c]);
|
2922
|
+
}
|
2923
|
+
/* Add an aligned number. */
|
2924
|
+
copy_pos += c;
|
2925
|
+
} else {
|
2926
|
+
if (!lzx_br_read_ahead(strm, &bre,
|
2927
|
+
offset_bits)) {
|
2928
|
+
state = ST_OFFSET;
|
2929
|
+
if (last)
|
2930
|
+
goto failed;
|
2931
|
+
goto next_data;
|
2932
|
+
}
|
2933
|
+
copy_pos = lzx_br_bits(&bre, offset_bits);
|
2934
|
+
lzx_br_consume(&bre, offset_bits);
|
2935
|
+
}
|
2936
|
+
copy_pos += pos_tbl[position_slot].base -2;
|
2937
|
+
|
2938
|
+
/* Update repeated offset LRU queue. */
|
2939
|
+
r2 = r1;
|
2940
|
+
r1 = r0;
|
2941
|
+
r0 = copy_pos;
|
2942
|
+
/* FALL THROUGH */
|
2943
|
+
case ST_REAL_POS:
|
2944
|
+
/*
|
2945
|
+
* Compute a real position in window.
|
2946
|
+
*/
|
2947
|
+
copy_pos = (w_pos - copy_pos) & w_mask;
|
2948
|
+
/* FALL THROUGH */
|
2949
|
+
case ST_COPY:
|
2950
|
+
/*
|
2951
|
+
* Copy several bytes as extracted data from the window
|
2952
|
+
* into the output buffer.
|
2953
|
+
*/
|
2954
|
+
for (;;) {
|
2955
|
+
const unsigned char *s;
|
2956
|
+
int l;
|
2957
|
+
|
2958
|
+
l = copy_len;
|
2959
|
+
if (copy_pos > w_pos) {
|
2960
|
+
if (l > w_size - copy_pos)
|
2961
|
+
l = w_size - copy_pos;
|
2962
|
+
} else {
|
2963
|
+
if (l > w_size - w_pos)
|
2964
|
+
l = w_size - w_pos;
|
2965
|
+
}
|
2966
|
+
if (noutp + l >= endp)
|
2967
|
+
l = (int)(endp - noutp);
|
2968
|
+
s = w_buff + copy_pos;
|
2969
|
+
if (l >= 8 && ((copy_pos + l < w_pos)
|
2970
|
+
|| (w_pos + l < copy_pos))) {
|
2971
|
+
memcpy(w_buff + w_pos, s, l);
|
2972
|
+
memcpy(noutp, s, l);
|
2973
|
+
} else {
|
2974
|
+
unsigned char *d;
|
2975
|
+
int li;
|
2976
|
+
|
2977
|
+
d = w_buff + w_pos;
|
2978
|
+
for (li = 0; li < l; li++)
|
2979
|
+
noutp[li] = d[li] = s[li];
|
2980
|
+
}
|
2981
|
+
noutp += l;
|
2982
|
+
copy_pos = (copy_pos + l) & w_mask;
|
2983
|
+
w_pos = (w_pos + l) & w_mask;
|
2984
|
+
block_bytes_avail -= l;
|
2985
|
+
if (copy_len <= l)
|
2986
|
+
/* A copy of current pattern ended. */
|
2987
|
+
break;
|
2988
|
+
copy_len -= l;
|
2989
|
+
if (noutp >= endp) {
|
2990
|
+
/* Output buffer is empty. */
|
2991
|
+
state = ST_COPY;
|
2992
|
+
goto next_data;
|
2993
|
+
}
|
2994
|
+
}
|
2995
|
+
state = ST_MAIN;
|
2996
|
+
break;
|
2997
|
+
}
|
2998
|
+
}
|
2999
|
+
failed:
|
3000
|
+
return (ds->error = ARCHIVE_FAILED);
|
3001
|
+
next_data:
|
3002
|
+
ds->br = bre;
|
3003
|
+
ds->block_bytes_avail = block_bytes_avail;
|
3004
|
+
ds->copy_len = copy_len;
|
3005
|
+
ds->copy_pos = copy_pos;
|
3006
|
+
ds->length_header = length_header;
|
3007
|
+
ds->offset_bits = offset_bits;
|
3008
|
+
ds->position_slot = position_slot;
|
3009
|
+
ds->r0 = r0; ds->r1 = r1; ds->r2 = r2;
|
3010
|
+
ds->state = state;
|
3011
|
+
ds->w_pos = w_pos;
|
3012
|
+
strm->avail_out = endp - noutp;
|
3013
|
+
return (ARCHIVE_OK);
|
3014
|
+
}
|
3015
|
+
|
3016
|
+
static int
|
3017
|
+
lzx_read_pre_tree(struct lzx_stream *strm)
|
3018
|
+
{
|
3019
|
+
struct lzx_dec *ds = strm->ds;
|
3020
|
+
struct lzx_br *br = &(ds->br);
|
3021
|
+
int i;
|
3022
|
+
|
3023
|
+
if (ds->loop == 0)
|
3024
|
+
memset(ds->pt.freq, 0, sizeof(ds->pt.freq));
|
3025
|
+
for (i = ds->loop; i < ds->pt.len_size; i++) {
|
3026
|
+
if (!lzx_br_read_ahead(strm, br, 4)) {
|
3027
|
+
ds->loop = i;
|
3028
|
+
return (0);
|
3029
|
+
}
|
3030
|
+
ds->pt.bitlen[i] = lzx_br_bits(br, 4);
|
3031
|
+
ds->pt.freq[ds->pt.bitlen[i]]++;
|
3032
|
+
lzx_br_consume(br, 4);
|
3033
|
+
}
|
3034
|
+
ds->loop = i;
|
3035
|
+
return (1);
|
3036
|
+
}
|
3037
|
+
|
3038
|
+
/*
|
3039
|
+
* Read a bunch of bit-lengths from pre-tree.
|
3040
|
+
*/
|
3041
|
+
static int
|
3042
|
+
lzx_read_bitlen(struct lzx_stream *strm, struct huffman *d, int end)
|
3043
|
+
{
|
3044
|
+
struct lzx_dec *ds = strm->ds;
|
3045
|
+
struct lzx_br *br = &(ds->br);
|
3046
|
+
int c, i, j, ret, same;
|
3047
|
+
unsigned rbits;
|
3048
|
+
|
3049
|
+
i = ds->loop;
|
3050
|
+
if (i == 0)
|
3051
|
+
memset(d->freq, 0, sizeof(d->freq));
|
3052
|
+
ret = 0;
|
3053
|
+
if (end < 0)
|
3054
|
+
end = d->len_size;
|
3055
|
+
while (i < end) {
|
3056
|
+
ds->loop = i;
|
3057
|
+
if (!lzx_br_read_ahead(strm, br, ds->pt.max_bits))
|
3058
|
+
goto getdata;
|
3059
|
+
rbits = lzx_br_bits(br, ds->pt.max_bits);
|
3060
|
+
c = lzx_decode_huffman(&(ds->pt), rbits);
|
3061
|
+
switch (c) {
|
3062
|
+
case 17:/* several zero lengths, from 4 to 19. */
|
3063
|
+
if (!lzx_br_read_ahead(strm, br, ds->pt.bitlen[c]+4))
|
3064
|
+
goto getdata;
|
3065
|
+
lzx_br_consume(br, ds->pt.bitlen[c]);
|
3066
|
+
same = lzx_br_bits(br, 4) + 4;
|
3067
|
+
if (i + same > end)
|
3068
|
+
return (-1);/* Invalid */
|
3069
|
+
lzx_br_consume(br, 4);
|
3070
|
+
for (j = 0; j < same; j++)
|
3071
|
+
d->bitlen[i++] = 0;
|
3072
|
+
break;
|
3073
|
+
case 18:/* many zero lengths, from 20 to 51. */
|
3074
|
+
if (!lzx_br_read_ahead(strm, br, ds->pt.bitlen[c]+5))
|
3075
|
+
goto getdata;
|
3076
|
+
lzx_br_consume(br, ds->pt.bitlen[c]);
|
3077
|
+
same = lzx_br_bits(br, 5) + 20;
|
3078
|
+
if (i + same > end)
|
3079
|
+
return (-1);/* Invalid */
|
3080
|
+
lzx_br_consume(br, 5);
|
3081
|
+
memset(d->bitlen + i, 0, same);
|
3082
|
+
i += same;
|
3083
|
+
break;
|
3084
|
+
case 19:/* a few same lengths. */
|
3085
|
+
if (!lzx_br_read_ahead(strm, br,
|
3086
|
+
ds->pt.bitlen[c]+1+ds->pt.max_bits))
|
3087
|
+
goto getdata;
|
3088
|
+
lzx_br_consume(br, ds->pt.bitlen[c]);
|
3089
|
+
same = lzx_br_bits(br, 1) + 4;
|
3090
|
+
if (i + same > end)
|
3091
|
+
return (-1);
|
3092
|
+
lzx_br_consume(br, 1);
|
3093
|
+
rbits = lzx_br_bits(br, ds->pt.max_bits);
|
3094
|
+
c = lzx_decode_huffman(&(ds->pt), rbits);
|
3095
|
+
lzx_br_consume(br, ds->pt.bitlen[c]);
|
3096
|
+
c = (d->bitlen[i] - c + 17) % 17;
|
3097
|
+
if (c < 0)
|
3098
|
+
return (-1);/* Invalid */
|
3099
|
+
for (j = 0; j < same; j++)
|
3100
|
+
d->bitlen[i++] = c;
|
3101
|
+
d->freq[c] += same;
|
3102
|
+
break;
|
3103
|
+
default:
|
3104
|
+
lzx_br_consume(br, ds->pt.bitlen[c]);
|
3105
|
+
c = (d->bitlen[i] - c + 17) % 17;
|
3106
|
+
if (c < 0)
|
3107
|
+
return (-1);/* Invalid */
|
3108
|
+
d->freq[c]++;
|
3109
|
+
d->bitlen[i++] = c;
|
3110
|
+
break;
|
3111
|
+
}
|
3112
|
+
}
|
3113
|
+
ret = 1;
|
3114
|
+
getdata:
|
3115
|
+
ds->loop = i;
|
3116
|
+
return (ret);
|
3117
|
+
}
|
3118
|
+
|
3119
|
+
static int
|
3120
|
+
lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
|
3121
|
+
{
|
3122
|
+
|
3123
|
+
if (hf->bitlen == NULL || hf->len_size != (int)len_size) {
|
3124
|
+
free(hf->bitlen);
|
3125
|
+
hf->bitlen = calloc(len_size, sizeof(hf->bitlen[0]));
|
3126
|
+
if (hf->bitlen == NULL)
|
3127
|
+
return (ARCHIVE_FATAL);
|
3128
|
+
hf->len_size = (int)len_size;
|
3129
|
+
} else
|
3130
|
+
memset(hf->bitlen, 0, len_size * sizeof(hf->bitlen[0]));
|
3131
|
+
if (hf->tbl == NULL) {
|
3132
|
+
hf->tbl = malloc(((size_t)1 << tbl_bits) * sizeof(hf->tbl[0]));
|
3133
|
+
if (hf->tbl == NULL)
|
3134
|
+
return (ARCHIVE_FATAL);
|
3135
|
+
hf->tbl_bits = tbl_bits;
|
3136
|
+
}
|
3137
|
+
return (ARCHIVE_OK);
|
3138
|
+
}
|
3139
|
+
|
3140
|
+
static void
|
3141
|
+
lzx_huffman_free(struct huffman *hf)
|
3142
|
+
{
|
3143
|
+
free(hf->bitlen);
|
3144
|
+
free(hf->tbl);
|
3145
|
+
}
|
3146
|
+
|
3147
|
+
/*
|
3148
|
+
* Make a huffman coding table.
|
3149
|
+
*/
|
3150
|
+
static int
|
3151
|
+
lzx_make_huffman_table(struct huffman *hf)
|
3152
|
+
{
|
3153
|
+
uint16_t *tbl;
|
3154
|
+
const unsigned char *bitlen;
|
3155
|
+
int bitptn[17], weight[17];
|
3156
|
+
int i, maxbits = 0, ptn, tbl_size, w;
|
3157
|
+
int len_avail;
|
3158
|
+
|
3159
|
+
/*
|
3160
|
+
* Initialize bit patterns.
|
3161
|
+
*/
|
3162
|
+
ptn = 0;
|
3163
|
+
for (i = 1, w = 1 << 15; i <= 16; i++, w >>= 1) {
|
3164
|
+
bitptn[i] = ptn;
|
3165
|
+
weight[i] = w;
|
3166
|
+
if (hf->freq[i]) {
|
3167
|
+
ptn += hf->freq[i] * w;
|
3168
|
+
maxbits = i;
|
3169
|
+
}
|
3170
|
+
}
|
3171
|
+
if ((ptn & 0xffff) != 0 || maxbits > hf->tbl_bits)
|
3172
|
+
return (0);/* Invalid */
|
3173
|
+
|
3174
|
+
hf->max_bits = maxbits;
|
3175
|
+
|
3176
|
+
/*
|
3177
|
+
* Cut out extra bits which we won't house in the table.
|
3178
|
+
* This preparation reduces the same calculation in the for-loop
|
3179
|
+
* making the table.
|
3180
|
+
*/
|
3181
|
+
if (maxbits < 16) {
|
3182
|
+
int ebits = 16 - maxbits;
|
3183
|
+
for (i = 1; i <= maxbits; i++) {
|
3184
|
+
bitptn[i] >>= ebits;
|
3185
|
+
weight[i] >>= ebits;
|
3186
|
+
}
|
3187
|
+
}
|
3188
|
+
|
3189
|
+
/*
|
3190
|
+
* Make the table.
|
3191
|
+
*/
|
3192
|
+
tbl_size = 1 << hf->tbl_bits;
|
3193
|
+
tbl = hf->tbl;
|
3194
|
+
bitlen = hf->bitlen;
|
3195
|
+
len_avail = hf->len_size;
|
3196
|
+
hf->tree_used = 0;
|
3197
|
+
for (i = 0; i < len_avail; i++) {
|
3198
|
+
uint16_t *p;
|
3199
|
+
int len, cnt;
|
3200
|
+
|
3201
|
+
if (bitlen[i] == 0)
|
3202
|
+
continue;
|
3203
|
+
/* Get a bit pattern */
|
3204
|
+
len = bitlen[i];
|
3205
|
+
if (len > tbl_size)
|
3206
|
+
return (0);
|
3207
|
+
ptn = bitptn[len];
|
3208
|
+
cnt = weight[len];
|
3209
|
+
/* Calculate next bit pattern */
|
3210
|
+
if ((bitptn[len] = ptn + cnt) > tbl_size)
|
3211
|
+
return (0);/* Invalid */
|
3212
|
+
/* Update the table */
|
3213
|
+
p = &(tbl[ptn]);
|
3214
|
+
while (--cnt >= 0)
|
3215
|
+
p[cnt] = (uint16_t)i;
|
3216
|
+
}
|
3217
|
+
return (1);
|
3218
|
+
}
|
3219
|
+
|
3220
|
+
static inline int
|
3221
|
+
lzx_decode_huffman(struct huffman *hf, unsigned rbits)
|
3222
|
+
{
|
3223
|
+
int c;
|
3224
|
+
c = hf->tbl[rbits];
|
3225
|
+
if (c < hf->len_size)
|
3226
|
+
return (c);
|
3227
|
+
return (0);
|
3228
|
+
}
|