aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Matuska <mm@FreeBSD.org>2013-03-21 18:59:02 +0000
committerMartin Matuska <mm@FreeBSD.org>2013-03-21 18:59:02 +0000
commit6a316f322a46b3e531726dd2a7de63b9e245878d (patch)
tree45c2c8840d99cc81725a3970fd3beee587313cf5
parent81418b36c02b6434acd4b8ae4cfb8c80a3742fd4 (diff)
downloadsrc-6a316f322a46b3e531726dd2a7de63b9e245878d.tar.gz
src-6a316f322a46b3e531726dd2a7de63b9e245878d.zip
Update libarchive's vendor dist to version 3.1.2 from release branch.
Git branch: release Git commit: 19f23e191f9d3e1dd2a518735046100419965804 Obtained from: https://github.com/libarchive/libarchive.git
Notes
Notes: svn path=/vendor/libarchive/dist/; revision=248590
-rw-r--r--CMakeLists.txt317
-rw-r--r--Makefile.am215
-rw-r--r--NEWS27
-rw-r--r--README2
-rw-r--r--build/README.txt35
-rwxr-xr-xbuild/autogen.sh5
-rw-r--r--build/bump-version.sh2
-rw-r--r--build/cmake/FindLibGCC.cmake22
-rw-r--r--build/cmake/FindNettle.cmake23
-rw-r--r--build/cmake/FindPCREPOSIX.cmake34
-rw-r--r--build/cmake/LibarchiveCheckCSourceCompiles.cmake106
-rw-r--r--build/cmake/LibarchiveCheckCSourceRuns.cmake102
-rw-r--r--build/cmake/config.h.in42
-rwxr-xr-xbuild/makerelease.sh1
-rw-r--r--build/version2
-rw-r--r--configure.ac266
-rw-r--r--cpio/bsdcpio.112
-rw-r--r--cpio/cmdline.c5
-rw-r--r--cpio/cpio.c79
-rw-r--r--cpio/cpio.h8
-rw-r--r--cpio/test/CMakeLists.txt18
-rw-r--r--cpio/test/main.c245
-rw-r--r--cpio/test/test.h22
-rw-r--r--cpio/test/test_basic.c12
-rw-r--r--cpio/test/test_extract.cpio.Z.uu7
-rw-r--r--cpio/test/test_extract.cpio.bz2.uu7
-rw-r--r--cpio/test/test_extract.cpio.grz.uu7
-rw-r--r--cpio/test/test_extract.cpio.gz.uu7
-rw-r--r--cpio/test/test_extract.cpio.lrz.uu8
-rw-r--r--cpio/test/test_extract.cpio.lz.uu6
-rw-r--r--cpio/test/test_extract.cpio.lzma.uu6
-rw-r--r--cpio/test/test_extract.cpio.lzo.uu9
-rw-r--r--cpio/test/test_extract.cpio.xz.uu7
-rw-r--r--cpio/test/test_extract_cpio_Z.c42
-rw-r--r--cpio/test/test_extract_cpio_bz2.c48
-rw-r--r--cpio/test/test_extract_cpio_grz.c48
-rw-r--r--cpio/test/test_extract_cpio_gz.c48
-rw-r--r--cpio/test/test_extract_cpio_lrz.c48
-rw-r--r--cpio/test/test_extract_cpio_lz.c48
-rw-r--r--cpio/test/test_extract_cpio_lzma.c48
-rw-r--r--cpio/test/test_extract_cpio_lzo.c48
-rw-r--r--cpio/test/test_extract_cpio_xz.c48
-rw-r--r--cpio/test/test_format_newc.c4
-rw-r--r--cpio/test/test_option_b64encode.c54
-rw-r--r--cpio/test/test_option_grzip.c52
-rw-r--r--cpio/test/test_option_lrzip.c52
-rw-r--r--cpio/test/test_option_lzop.c56
-rw-r--r--cpio/test/test_option_uuencode.c54
-rw-r--r--cpio/test/test_option_xz.c57
-rw-r--r--cpio/test/test_option_y.c5
-rw-r--r--cpio/test/test_option_z.c5
-rw-r--r--doc/update.sh2
-rw-r--r--examples/minitar/minitar.c12
-rw-r--r--examples/untar.c4
-rw-r--r--libarchive/CMakeLists.txt18
-rw-r--r--libarchive/archive.h163
-rw-r--r--libarchive/archive_cmdline.c227
-rw-r--r--libarchive/archive_cmdline_private.h47
-rw-r--r--libarchive/archive_crypto.c8
-rw-r--r--libarchive/archive_entry.c3
-rw-r--r--libarchive/archive_entry.h2
-rw-r--r--libarchive/archive_entry_link_resolver.c3
-rw-r--r--libarchive/archive_match.c11
-rw-r--r--libarchive/archive_options.c15
-rw-r--r--libarchive/archive_ppmd7.c2
-rw-r--r--libarchive/archive_private.h1
-rw-r--r--libarchive/archive_rb.c8
-rw-r--r--libarchive/archive_read.c409
-rw-r--r--libarchive/archive_read_append_filter.c198
-rw-r--r--libarchive/archive_read_disk_entry_from_file.c293
-rw-r--r--libarchive/archive_read_disk_posix.c96
-rw-r--r--libarchive/archive_read_disk_windows.c22
-rw-r--r--libarchive/archive_read_extract.c2
-rw-r--r--libarchive/archive_read_open_fd.c3
-rw-r--r--libarchive/archive_read_open_file.c4
-rw-r--r--libarchive/archive_read_open_filename.c163
-rw-r--r--libarchive/archive_read_private.h40
-rw-r--r--libarchive/archive_read_set_format.c105
-rw-r--r--libarchive/archive_read_support_filter_all.c8
-rw-r--r--libarchive/archive_read_support_filter_bzip2.c9
-rw-r--r--libarchive/archive_read_support_filter_compress.c3
-rw-r--r--libarchive/archive_read_support_filter_grzip.c121
-rw-r--r--libarchive/archive_read_support_filter_gzip.c21
-rw-r--r--libarchive/archive_read_support_filter_lrzip.c132
-rw-r--r--libarchive/archive_read_support_filter_lzop.c486
-rw-r--r--libarchive/archive_read_support_filter_program.c188
-rw-r--r--libarchive/archive_read_support_filter_rpm.c3
-rw-r--r--libarchive/archive_read_support_filter_uu.c28
-rw-r--r--libarchive/archive_read_support_filter_xz.c33
-rw-r--r--libarchive/archive_read_support_format_7zip.c66
-rw-r--r--libarchive/archive_read_support_format_ar.c1
-rw-r--r--libarchive/archive_read_support_format_cab.c55
-rw-r--r--libarchive/archive_read_support_format_cpio.c1
-rw-r--r--libarchive/archive_read_support_format_empty.c1
-rw-r--r--libarchive/archive_read_support_format_iso9660.c404
-rw-r--r--libarchive/archive_read_support_format_lha.c17
-rw-r--r--libarchive/archive_read_support_format_mtree.c214
-rw-r--r--libarchive/archive_read_support_format_rar.c358
-rw-r--r--libarchive/archive_read_support_format_raw.c3
-rw-r--r--libarchive/archive_read_support_format_tar.c96
-rw-r--r--libarchive/archive_read_support_format_xar.c1
-rw-r--r--libarchive/archive_read_support_format_zip.c525
-rw-r--r--libarchive/archive_string.c76
-rw-r--r--libarchive/archive_util.c45
-rw-r--r--libarchive/archive_virtual.c7
-rw-r--r--libarchive/archive_windows.c39
-rw-r--r--libarchive/archive_windows.h14
-rw-r--r--libarchive/archive_write.c6
-rw-r--r--libarchive/archive_write_add_filter.c6
-rw-r--r--libarchive/archive_write_add_filter_b64encode.c314
-rw-r--r--libarchive/archive_write_add_filter_by_name.c75
-rw-r--r--libarchive/archive_write_add_filter_bzip2.c159
-rw-r--r--libarchive/archive_write_add_filter_compress.c4
-rw-r--r--libarchive/archive_write_add_filter_grzip.c135
-rw-r--r--libarchive/archive_write_add_filter_gzip.c188
-rw-r--r--libarchive/archive_write_add_filter_lrzip.c192
-rw-r--r--libarchive/archive_write_add_filter_lzop.c486
-rw-r--r--libarchive/archive_write_add_filter_program.c241
-rw-r--r--libarchive/archive_write_add_filter_uuencode.c305
-rw-r--r--libarchive/archive_write_add_filter_xz.c18
-rw-r--r--libarchive/archive_write_disk_acl.c249
-rw-r--r--libarchive/archive_write_disk_posix.c1252
-rw-r--r--libarchive/archive_write_disk_private.h5
-rw-r--r--libarchive/archive_write_disk_windows.c2
-rw-r--r--libarchive/archive_write_free.313
-rw-r--r--libarchive/archive_write_open_filename.c7
-rw-r--r--libarchive/archive_write_private.h9
-rw-r--r--libarchive/archive_write_set_format_7zip.c74
-rw-r--r--libarchive/archive_write_set_format_ar.c2
-rw-r--r--libarchive/archive_write_set_format_by_name.c4
-rw-r--r--libarchive/archive_write_set_format_iso9660.c118
-rw-r--r--libarchive/archive_write_set_format_mtree.c1562
-rw-r--r--libarchive/archive_write_set_format_pax.c10
-rw-r--r--libarchive/archive_write_set_format_v7tar.c661
-rw-r--r--libarchive/archive_write_set_format_xar.c12
-rw-r--r--libarchive/archive_write_set_format_zip.c68
-rw-r--r--libarchive/archive_write_set_options.c2
-rw-r--r--libarchive/filter_fork.h2
-rw-r--r--libarchive/filter_fork_posix.c238
-rw-r--r--libarchive/filter_fork_windows.c139
-rw-r--r--libarchive/libarchive-formats.52
-rw-r--r--libarchive/test/CMakeLists.txt57
-rw-r--r--libarchive/test/main.c266
-rw-r--r--libarchive/test/test.h30
-rw-r--r--libarchive/test/test_acl_freebsd_nfs4.c547
-rw-r--r--libarchive/test/test_acl_freebsd_posix1e.c265
-rw-r--r--libarchive/test/test_acl_nfs4.c7
-rw-r--r--libarchive/test/test_acl_pax.c2
-rw-r--r--libarchive/test/test_acl_posix1e.c2
-rw-r--r--libarchive/test/test_archive_clear_error.c2
-rw-r--r--libarchive/test/test_archive_cmdline.c141
-rw-r--r--libarchive/test/test_archive_read_close_twice.c2
-rw-r--r--libarchive/test/test_archive_read_close_twice_open_fd.c2
-rw-r--r--libarchive/test/test_archive_read_close_twice_open_filename.c2
-rw-r--r--libarchive/test/test_archive_read_multiple_data_objects.c372
-rw-r--r--libarchive/test/test_archive_read_set_filter_option.c2
-rw-r--r--libarchive/test/test_archive_read_set_format_option.c2
-rw-r--r--libarchive/test/test_archive_read_set_option.c2
-rw-r--r--libarchive/test/test_archive_read_set_options.c2
-rw-r--r--libarchive/test/test_archive_set_error.c2
-rw-r--r--libarchive/test/test_archive_write_add_filter_by_name.c194
-rw-r--r--libarchive/test/test_archive_write_set_filter_option.c4
-rw-r--r--libarchive/test/test_archive_write_set_format_by_name.c285
-rw-r--r--libarchive/test/test_archive_write_set_format_option.c2
-rw-r--r--libarchive/test/test_archive_write_set_option.c4
-rw-r--r--libarchive/test/test_archive_write_set_options.c4
-rw-r--r--libarchive/test/test_compat_bzip2.c8
-rw-r--r--libarchive/test/test_compat_cpio.c2
-rw-r--r--libarchive/test/test_compat_gtar.c2
-rw-r--r--libarchive/test/test_compat_gzip.c4
-rw-r--r--libarchive/test/test_compat_lzip.c4
-rw-r--r--libarchive/test/test_compat_lzma.c4
-rw-r--r--libarchive/test/test_compat_lzop.c131
-rw-r--r--libarchive/test/test_compat_lzop_1.tar.lzo.uu30
-rw-r--r--libarchive/test/test_compat_lzop_2.tar.lzo.uu39
-rw-r--r--libarchive/test/test_compat_lzop_3.tar.lzo.uu32
-rw-r--r--libarchive/test/test_compat_mac.c4
-rw-r--r--libarchive/test/test_compat_tar_hardlink.c2
-rw-r--r--libarchive/test/test_compat_uudecode.c63
-rw-r--r--libarchive/test/test_compat_xz.c4
-rw-r--r--libarchive/test/test_compat_zip.c2
-rw-r--r--libarchive/test/test_empty_write.c20
-rw-r--r--libarchive/test/test_entry.c22
-rw-r--r--libarchive/test/test_filter_count.c9
-rw-r--r--libarchive/test/test_fuzz.c329
-rw-r--r--libarchive/test/test_open_failure.c16
-rw-r--r--libarchive/test/test_open_fd.c5
-rw-r--r--libarchive/test/test_open_file.c2
-rw-r--r--libarchive/test/test_open_filename.c4
-rw-r--r--libarchive/test/test_pax_filename_encoding.c4
-rw-r--r--libarchive/test/test_rar_multivolume_multiple_files.part1.rar.uu163
-rw-r--r--libarchive/test/test_rar_multivolume_multiple_files.part2.rar.uu163
-rw-r--r--libarchive/test/test_rar_multivolume_multiple_files.part3.rar.uu163
-rw-r--r--libarchive/test/test_rar_multivolume_multiple_files.part4.rar.uu163
-rw-r--r--libarchive/test/test_rar_multivolume_multiple_files.part5.rar.uu163
-rw-r--r--libarchive/test/test_rar_multivolume_multiple_files.part6.rar.uu117
-rw-r--r--libarchive/test/test_rar_multivolume_single_file.part1.rar.uu159
-rw-r--r--libarchive/test/test_rar_multivolume_single_file.part2.rar.uu159
-rw-r--r--libarchive/test/test_rar_multivolume_single_file.part3.rar.uu146
-rw-r--r--libarchive/test/test_rar_multivolume_uncompressed_files.part01.rar.uu299
-rw-r--r--libarchive/test/test_rar_multivolume_uncompressed_files.part02.rar.uu299
-rw-r--r--libarchive/test/test_rar_multivolume_uncompressed_files.part03.rar.uu299
-rw-r--r--libarchive/test/test_rar_multivolume_uncompressed_files.part04.rar.uu299
-rw-r--r--libarchive/test/test_rar_multivolume_uncompressed_files.part05.rar.uu299
-rw-r--r--libarchive/test/test_rar_multivolume_uncompressed_files.part06.rar.uu299
-rw-r--r--libarchive/test/test_rar_multivolume_uncompressed_files.part07.rar.uu299
-rw-r--r--libarchive/test/test_rar_multivolume_uncompressed_files.part08.rar.uu299
-rw-r--r--libarchive/test/test_rar_multivolume_uncompressed_files.part09.rar.uu299
-rw-r--r--libarchive/test/test_rar_multivolume_uncompressed_files.part10.rar.uu75
-rw-r--r--libarchive/test/test_read_data_large.c2
-rw-r--r--libarchive/test/test_read_disk.c3
-rw-r--r--libarchive/test/test_read_extract.c2
-rw-r--r--libarchive/test/test_read_filter_grzip.c67
-rw-r--r--libarchive/test/test_read_filter_grzip.tar.grz.uu8
-rw-r--r--libarchive/test/test_read_filter_lrzip.c67
-rw-r--r--libarchive/test/test_read_filter_lrzip.tar.lrz.uu10
-rw-r--r--libarchive/test/test_read_filter_lzop.c74
-rw-r--r--libarchive/test/test_read_filter_lzop.tar.lzo.uu11
-rw-r--r--libarchive/test/test_read_filter_lzop_multiple_parts.c72
-rw-r--r--libarchive/test/test_read_filter_lzop_multiple_parts.tar.lzo.uu89
-rw-r--r--libarchive/test/test_read_filter_program.c83
-rw-r--r--libarchive/test/test_read_filter_program_signature.c103
-rw-r--r--libarchive/test/test_read_filter_uudecode.c178
-rw-r--r--libarchive/test/test_read_format_7zip.c111
-rw-r--r--libarchive/test/test_read_format_ar.c2
-rw-r--r--libarchive/test/test_read_format_cab.c11
-rw-r--r--libarchive/test/test_read_format_cab_filename.c4
-rw-r--r--libarchive/test/test_read_format_cpio_afio.c7
-rw-r--r--libarchive/test/test_read_format_cpio_bin.c2
-rw-r--r--libarchive/test/test_read_format_cpio_bin_Z.c8
-rw-r--r--libarchive/test/test_read_format_cpio_bin_be.c2
-rw-r--r--libarchive/test/test_read_format_cpio_bin_bz2.c2
-rw-r--r--libarchive/test/test_read_format_cpio_bin_gz.c4
-rw-r--r--libarchive/test/test_read_format_cpio_bin_lzip.c2
-rw-r--r--libarchive/test/test_read_format_cpio_bin_lzma.c2
-rw-r--r--libarchive/test/test_read_format_cpio_bin_xz.c2
-rw-r--r--libarchive/test/test_read_format_cpio_filename.c32
-rw-r--r--libarchive/test/test_read_format_cpio_odc.c2
-rw-r--r--libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c4
-rw-r--r--libarchive/test/test_read_format_cpio_svr4_gzip.c4
-rw-r--r--libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c4
-rw-r--r--libarchive/test/test_read_format_cpio_svr4c_Z.c6
-rw-r--r--libarchive/test/test_read_format_empty.c2
-rw-r--r--libarchive/test/test_read_format_gtar_gz.c4
-rw-r--r--libarchive/test/test_read_format_gtar_lzma.c2
-rw-r--r--libarchive/test/test_read_format_iso_Z.c8
-rw-r--r--libarchive/test/test_read_format_iso_multi_extent.c2
-rw-r--r--libarchive/test/test_read_format_iso_xorriso.c2
-rw-r--r--libarchive/test/test_read_format_isojoliet_bz2.c2
-rw-r--r--libarchive/test/test_read_format_isojoliet_long.c2
-rw-r--r--libarchive/test/test_read_format_isojoliet_rr.c2
-rw-r--r--libarchive/test/test_read_format_isojoliet_versioned.c2
-rw-r--r--libarchive/test/test_read_format_isorr_bz2.c2
-rw-r--r--libarchive/test/test_read_format_isorr_ce.c2
-rw-r--r--libarchive/test/test_read_format_isorr_new_bz2.c2
-rw-r--r--libarchive/test/test_read_format_isorr_rr_moved.c2
-rw-r--r--libarchive/test/test_read_format_isozisofs_bz2.c2
-rw-r--r--libarchive/test/test_read_format_lha.c2
-rw-r--r--libarchive/test/test_read_format_lha_filename.c6
-rw-r--r--libarchive/test/test_read_format_mtree.c301
-rw-r--r--libarchive/test/test_read_format_mtree_nomagic2.mtree.uu10
-rw-r--r--libarchive/test/test_read_format_mtree_nomagic3.mtree.uu10
-rw-r--r--libarchive/test/test_read_format_pax_bz2.c2
-rw-r--r--libarchive/test/test_read_format_rar.c2796
-rw-r--r--libarchive/test/test_read_format_rar_multivolume.part0001.rar.uu1337
-rw-r--r--libarchive/test/test_read_format_rar_multivolume.part0002.rar.uu1337
-rw-r--r--libarchive/test/test_read_format_rar_multivolume.part0003.rar.uu1337
-rw-r--r--libarchive/test/test_read_format_rar_multivolume.part0004.rar.uu208
-rw-r--r--libarchive/test/test_read_format_tar.c22
-rw-r--r--libarchive/test/test_read_format_tar_empty_filename.c2
-rw-r--r--libarchive/test/test_read_format_tbz.c2
-rw-r--r--libarchive/test/test_read_format_tgz.c4
-rw-r--r--libarchive/test/test_read_format_tlz.c2
-rw-r--r--libarchive/test/test_read_format_txz.c2
-rw-r--r--libarchive/test/test_read_format_tz.c6
-rw-r--r--libarchive/test/test_read_format_xar.c4
-rw-r--r--libarchive/test/test_read_format_zip.c4
-rw-r--r--libarchive/test/test_read_format_zip_comment_stored.c66
-rw-r--r--libarchive/test/test_read_format_zip_comment_stored_1.zip.uu12
-rw-r--r--libarchive/test/test_read_format_zip_comment_stored_2.zip.uu548
-rw-r--r--libarchive/test/test_read_format_zip_filename.c38
-rw-r--r--libarchive/test/test_read_format_zip_mac_metadata.c118
-rw-r--r--libarchive/test/test_read_format_zip_mac_metadata.zip.uu17
-rw-r--r--libarchive/test/test_read_format_zip_sfx.c59
-rw-r--r--libarchive/test/test_read_format_zip_sfx.uu34
-rw-r--r--libarchive/test/test_read_large_splitted_rar_aa.uu892
-rw-r--r--libarchive/test/test_read_large_splitted_rar_ab.uu892
-rw-r--r--libarchive/test/test_read_large_splitted_rar_ac.uu892
-rw-r--r--libarchive/test/test_read_large_splitted_rar_ad.uu892
-rw-r--r--libarchive/test/test_read_large_splitted_rar_ae.uu375
-rw-r--r--libarchive/test/test_read_pax_truncated.c2
-rw-r--r--libarchive/test/test_read_set_format.c220
-rw-r--r--libarchive/test/test_read_splitted_rar_aa.uu6
-rw-r--r--libarchive/test/test_read_splitted_rar_ab.uu6
-rw-r--r--libarchive/test/test_read_splitted_rar_ac.uu6
-rw-r--r--libarchive/test/test_read_splitted_rar_ad.uu4
-rw-r--r--libarchive/test/test_read_truncated.c2
-rw-r--r--libarchive/test/test_read_truncated_filter.c75
-rw-r--r--libarchive/test/test_sparse_basic.c6
-rw-r--r--libarchive/test/test_splitted_rar_seek_support_aa.uu159
-rw-r--r--libarchive/test/test_splitted_rar_seek_support_ab.uu159
-rw-r--r--libarchive/test/test_splitted_rar_seek_support_ac.uu141
-rw-r--r--libarchive/test/test_tar_filenames.c2
-rw-r--r--libarchive/test/test_ustar_filenames.c2
-rw-r--r--libarchive/test/test_write_disk_appledouble.c212
-rw-r--r--libarchive/test/test_write_disk_appledouble.cpio.gz.uu12
-rw-r--r--libarchive/test/test_write_disk_hfs_compression.c278
-rw-r--r--libarchive/test/test_write_disk_hfs_compression.tgz.uu1800
-rw-r--r--libarchive/test/test_write_disk_mac_metadata.c194
-rw-r--r--libarchive/test/test_write_disk_mac_metadata.tar.gz.uu14
-rw-r--r--libarchive/test/test_write_disk_no_hfs_compression.c231
-rw-r--r--libarchive/test/test_write_disk_no_hfs_compression.tgz.uu1765
-rw-r--r--libarchive/test/test_write_disk_sparse.c14
-rw-r--r--libarchive/test/test_write_filter_b64encode.c173
-rw-r--r--libarchive/test/test_write_filter_bzip2.c276
-rw-r--r--libarchive/test/test_write_filter_compress.c97
-rw-r--r--libarchive/test/test_write_filter_gzip.c272
-rw-r--r--libarchive/test/test_write_filter_gzip_timestamp.c118
-rw-r--r--libarchive/test/test_write_filter_lrzip.c131
-rw-r--r--libarchive/test/test_write_filter_lzip.c255
-rw-r--r--libarchive/test/test_write_filter_lzma.c259
-rw-r--r--libarchive/test/test_write_filter_lzop.c267
-rw-r--r--libarchive/test/test_write_filter_program.c124
-rw-r--r--libarchive/test/test_write_filter_uuencode.c173
-rw-r--r--libarchive/test/test_write_filter_xz.c265
-rw-r--r--libarchive/test/test_write_format_7zip.c304
-rw-r--r--libarchive/test/test_write_format_7zip_empty.c299
-rw-r--r--libarchive/test/test_write_format_7zip_large.c174
-rw-r--r--libarchive/test/test_write_format_ar.c6
-rw-r--r--libarchive/test/test_write_format_cpio.c4
-rw-r--r--libarchive/test/test_write_format_cpio_empty.c2
-rw-r--r--libarchive/test/test_write_format_cpio_newc.c2
-rw-r--r--libarchive/test/test_write_format_cpio_odc.c2
-rw-r--r--libarchive/test/test_write_format_gnutar.c2
-rw-r--r--libarchive/test/test_write_format_iso9660.c2
-rw-r--r--libarchive/test/test_write_format_iso9660_boot.c2
-rw-r--r--libarchive/test/test_write_format_iso9660_empty.c4
-rw-r--r--libarchive/test/test_write_format_iso9660_filename.c8
-rw-r--r--libarchive/test/test_write_format_iso9660_zisofs.c15
-rw-r--r--libarchive/test/test_write_format_mtree.c2
-rw-r--r--libarchive/test/test_write_format_mtree_absolute_path.c99
-rw-r--r--libarchive/test/test_write_format_mtree_classic.c194
-rw-r--r--libarchive/test/test_write_format_mtree_classic_indent.c196
-rw-r--r--libarchive/test/test_write_format_mtree_fflags.c1
-rw-r--r--libarchive/test/test_write_format_mtree_no_separator.c103
-rw-r--r--libarchive/test/test_write_format_mtree_quoted_filename.c86
-rw-r--r--libarchive/test/test_write_format_pax.c2
-rw-r--r--libarchive/test/test_write_format_shar_empty.c2
-rw-r--r--libarchive/test/test_write_format_tar.c2
-rw-r--r--libarchive/test/test_write_format_tar_empty.c4
-rw-r--r--libarchive/test/test_write_format_tar_sparse.c6
-rw-r--r--libarchive/test/test_write_format_tar_ustar.c2
-rw-r--r--libarchive/test/test_write_format_tar_v7tar.c259
-rw-r--r--libarchive/test/test_write_format_xar.c2
-rw-r--r--libarchive/test/test_write_format_xar_empty.c2
-rw-r--r--libarchive/test/test_write_format_zip.c2
-rw-r--r--libarchive/test/test_write_format_zip_empty.c2
-rw-r--r--libarchive/test/test_write_format_zip_no_compression.c2
-rw-r--r--libarchive/test/test_write_open_memory.c6
-rw-r--r--libarchive/test/test_write_zip_set_compression_store.c308
-rw-r--r--tar/CMakeLists.txt1
-rw-r--r--tar/bsdtar.191
-rw-r--r--tar/bsdtar.c187
-rw-r--r--tar/bsdtar.h36
-rw-r--r--tar/cmdline.c16
-rw-r--r--tar/creation_set.c314
-rw-r--r--tar/read.c36
-rw-r--r--tar/subst.c8
-rw-r--r--tar/test/CMakeLists.txt23
-rw-r--r--tar/test/main.c246
-rw-r--r--tar/test/test.h22
-rw-r--r--tar/test/test_basic.c6
-rw-r--r--tar/test/test_copy.c7
-rw-r--r--tar/test/test_extract.tar.Z.uu9
-rw-r--r--tar/test/test_extract.tar.bz2.uu7
-rw-r--r--tar/test/test_extract.tar.grz.uu7
-rw-r--r--tar/test/test_extract.tar.gz.uu7
-rw-r--r--tar/test/test_extract.tar.lrz.uu9
-rw-r--r--tar/test/test_extract.tar.lz.uu7
-rw-r--r--tar/test/test_extract.tar.lzma.uu7
-rw-r--r--tar/test/test_extract.tar.lzo.uu9
-rw-r--r--tar/test/test_extract.tar.xz.uu8
-rw-r--r--tar/test/test_extract_tar_Z.c42
-rw-r--r--tar/test/test_extract_tar_bz2.c48
-rw-r--r--tar/test/test_extract_tar_grz.c48
-rw-r--r--tar/test/test_extract_tar_gz.c48
-rw-r--r--tar/test/test_extract_tar_lrz.c48
-rw-r--r--tar/test/test_extract_tar_lz.c48
-rw-r--r--tar/test/test_extract_tar_lzma.c48
-rw-r--r--tar/test/test_extract_tar_lzo.c48
-rw-r--r--tar/test/test_extract_tar_xz.c48
-rw-r--r--tar/test/test_option_a.c110
-rw-r--r--tar/test/test_option_b64encode.c54
-rw-r--r--tar/test/test_option_grzip.c52
-rw-r--r--tar/test/test_option_j.c56
-rw-r--r--tar/test/test_option_lrzip.c52
-rw-r--r--tar/test/test_option_lzma.c57
-rw-r--r--tar/test/test_option_lzop.c55
-rw-r--r--tar/test/test_option_newer_than.c7
-rw-r--r--tar/test/test_option_older_than.c85
-rw-r--r--tar/test/test_option_r.c7
-rw-r--r--tar/test/test_option_uuencode.c54
-rw-r--r--tar/test/test_option_xz.c57
-rw-r--r--tar/test/test_option_z.c55
-rw-r--r--tar/test/test_stdio.c2
-rw-r--r--tar/test/test_windows.c19
-rw-r--r--tar/util.c24
-rw-r--r--tar/write.c152
-rw-r--r--test_utils/test_utils.c124
-rw-r--r--test_utils/test_utils.h39
410 files changed, 43402 insertions, 3134 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5cc5d605c05c..2cdb9fb48585 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -63,8 +63,8 @@ SET(LIBARCHIVE_VERSION_STRING "${VERSION}")
# libarchive 2.8 == interface version 10 = 2 + 8
# libarchive 2.9 == interface version 11 = 2 + 9
# libarchive 3.0 == interface version 12
-# libarchive 3.x == interface version 12 + x
-math(EXPR INTERFACE_VERSION "12 + ${_minor}")
+# libarchive 3.1 == interface version 13
+math(EXPR INTERFACE_VERSION "13 + ${_minor}")
# Set SOVERSION == Interface version
# ?? Should there be more here ??
@@ -151,27 +151,55 @@ OPTION(ENABLE_XATTR "Enable extended attribute support" ON)
OPTION(ENABLE_ACL "Enable ACL support" ON)
OPTION(ENABLE_ICONV "Enable iconv support" ON)
OPTION(ENABLE_TEST "Enable unit and regression tests" ON)
+SET(POSIX_REGEX_LIB "AUTO" CACHE STRING "Choose what library should provide POSIX regular expression support")
+SET(ENABLE_SAFESEH "AUTO" CACHE STRING "Enable use of /SAFESEH linker flag (MSVC only)")
+SET(WINDOWS_VERSION "" CACHE STRING "Set Windows version to use (Windows only)")
IF(ENABLE_TEST)
ENABLE_TESTING()
ENDIF(ENABLE_TEST)
IF(WIN32)
- IF(MSVC60)
- SET(WINVER 0x0400)
- ELSE()
+ IF(WINDOWS_VERSION STREQUAL "WIN8")
+ SET(WINVER 0x0602)
+ ELSEIF(WINDOWS_VERSION STREQUAL "WIN7")
+ SET(WINVER 0x0601)
+ ELSEIF(WINDOWS_VERSION STREQUAL "WS08")
+ SET(WINVER 0x0600)
+ ELSEIF(WINDOWS_VERSION STREQUAL "VISTA")
+ SET(WINVER 0x0600)
+ ELSEIF(WINDOWS_VERSION STREQUAL "WS03")
+ SET(WINVER 0x0502)
+ ELSEIF(WINDOWS_VERSION STREQUAL "WINXP")
+ SET(WINVER 0x0501)
+ ELSE(WINDOWS_VERSION STREQUAL "WIN8")
+ # The default is to use Windows 2000 API.
SET(WINVER 0x0500)
- ENDIF()
+ ENDIF(WINDOWS_VERSION STREQUAL "WIN8")
SET(_WIN32_WINNT ${WINVER})
ENDIF(WIN32)
+IF(MSVC)
+ IF(ENABLE_SAFESEH STREQUAL "YES")
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH")
+ SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH")
+ SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH")
+ SET(CMAKE_REQUIRED_LINKER_FLAGS "/SAFESEH")
+ ELSEIF(ENABLE_SAFESEH STREQUAL "NO")
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO")
+ SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO")
+ SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO")
+ SET(CMAKE_REQUIRED_LINKER_FLAGS "/SAFESEH:NO")
+ ENDIF(ENABLE_SAFESEH STREQUAL "YES")
+ENDIF(MSVC)
+
IF("${CMAKE_C_PLATFORM_ID}" MATCHES "^(HP-UX)$")
ADD_DEFINITIONS(-D_XOPEN_SOURCE=500) # Ask wchar.h for mbstate_t
ENDIF()
#
-INCLUDE(CheckCSourceCompiles)
-INCLUDE(CheckCSourceRuns)
+INCLUDE(LibarchiveCheckCSourceCompiles)
+INCLUDE(LibarchiveCheckCSourceRuns)
INCLUDE(CheckFileOffsetBits)
INCLUDE(CheckFuncs)
INCLUDE(CheckHeaderDirent)
@@ -235,9 +263,9 @@ MACRO (TRY_MACRO_FOR_LIBRARY INCLUDES LIBRARIES
ENDIF(NOT "${PREV_VAR_WITH_LIB}" STREQUAL "${LIBRARIES}")
# Check if the library can be used with the macro.
IF("${TRY_TYPE}" MATCHES "COMPILES")
- CHECK_C_SOURCE_COMPILES("${SAMPLE_SOURCE}" ${VAR})
+ LIBARCHIVE_CHECK_C_SOURCE_COMPILES("${SAMPLE_SOURCE}" ${VAR})
ELSEIF("${TRY_TYPE}" MATCHES "RUNS")
- CHECK_C_SOURCE_RUNS("${SAMPLE_SOURCE}" ${VAR})
+ LIBARCHIVE_CHECK_C_SOURCE_RUNS("${SAMPLE_SOURCE}" ${VAR})
ELSE("${TRY_TYPE}" MATCHES "COMPILES")
MESSAGE(FATAL_ERROR "UNKNOWN KEYWORD \"${TRY_TYPE}\" FOR TRY_TYPE")
ENDIF("${TRY_TYPE}" MATCHES "COMPILES")
@@ -366,6 +394,30 @@ ELSEIF(LZMADEC_FOUND)
INCLUDE_DIRECTORIES(${LZMADEC_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${LZMADEC_LIBRARIES})
ENDIF(LZMA_FOUND)
+#
+# Find LZO2
+#
+IF (LZO2_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(LZO2_FIND_QUIETLY TRUE)
+ENDIF (LZO2_INCLUDE_DIR)
+
+FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h)
+FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2)
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR)
+IF(LZO2_FOUND)
+ SET(HAVE_LIBLZO2 1)
+ SET(HAVE_LZO_LZOCONF_H 1)
+ SET(HAVE_LZO_LZO1X_H 1)
+ INCLUDE_DIRECTORIES(${LZO2_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${LZO2_LIBRARY})
+ #
+ # TODO: test for static library.
+ #
+ENDIF(LZO2_FOUND)
+MARK_AS_ADVANCED(CLEAR LZO2_INCLUDE_DIR)
+MARK_AS_ADVANCED(CLEAR LZO2_LIBRARY)
#
# Check headers
@@ -392,7 +444,7 @@ LA_CHECK_INCLUDE_FILE("dlfcn.h" HAVE_DLFCN_H)
LA_CHECK_INCLUDE_FILE("errno.h" HAVE_ERRNO_H)
LA_CHECK_INCLUDE_FILE("ext2fs/ext2_fs.h" HAVE_EXT2FS_EXT2_FS_H)
-CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h>
+LIBARCHIVE_CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h>
#include <ext2fs/ext2_fs.h>
int main(void) { return EXT2_IOC_GETFLAGS; }" HAVE_WORKING_EXT2_IOC_GETFLAGS)
@@ -414,6 +466,7 @@ LA_CHECK_INCLUDE_FILE("process.h" HAVE_PROCESS_H)
LA_CHECK_INCLUDE_FILE("pwd.h" HAVE_PWD_H)
LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H)
LA_CHECK_INCLUDE_FILE("signal.h" HAVE_SIGNAL_H)
+LA_CHECK_INCLUDE_FILE("spawn.h" HAVE_SPAWN_H)
LA_CHECK_INCLUDE_FILE("stdarg.h" HAVE_STDARG_H)
LA_CHECK_INCLUDE_FILE("stdint.h" HAVE_STDINT_H)
LA_CHECK_INCLUDE_FILE("stdlib.h" HAVE_STDLIB_H)
@@ -454,7 +507,7 @@ FOREACH (it ${_HEADER})
SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n")
ENDFOREACH (it)
-CHECK_C_SOURCE_COMPILES(
+LIBARCHIVE_CHECK_C_SOURCE_COMPILES(
"#define __EXTENSIONS__ 1
${_INCLUDE_FILES}
int main() { return 0;}"
@@ -464,16 +517,17 @@ CHECK_C_SOURCE_COMPILES(
# Find Nettle
#
IF(ENABLE_NETTLE)
- CHECK_LIBRARY_EXISTS(nettle "nettle_sha1_digest" "" NETTLE_FOUND)
+ FIND_PACKAGE(Nettle)
IF(NETTLE_FOUND)
- CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
- SET(CMAKE_REQUIRED_LIBRARIES "nettle")
- FIND_LIBRARY(NETTLE_LIBRARY NAMES nettle)
- LIST(APPEND ADDITIONAL_LIBS ${NETTLE_LIBRARY})
- CMAKE_POP_CHECK_STATE() # Restore the state of the variables
- ELSE(NETTLE_FOUND)
- SET(ENABLE_NETTLE OFF)
+ SET(HAVE_LIBNETTLE 1)
+ SET(HAVE_NETTLE_MD5_H 1)
+ SET(HAVE_NETTLE_RIPEMD160_H 1)
+ SET(HAVE_NETTLE_SHA_H 1)
+ INCLUDE_DIRECTORIES(${NETTLE_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${NETTLE_LIBRARIES})
ENDIF(NETTLE_FOUND)
+ MARK_AS_ADVANCED(CLEAR NETTLE_INCLUDE_DIR)
+ MARK_AS_ADVANCED(CLEAR NETTLE_LIBRARIES)
ENDIF(ENABLE_NETTLE)
#
@@ -487,14 +541,16 @@ ELSE()
ENDIF()
# FreeBSD libmd
-CHECK_LIBRARY_EXISTS(md "MD5Init" "" LIBMD_FOUND)
-IF(LIBMD_FOUND)
- CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
- SET(CMAKE_REQUIRED_LIBRARIES "md")
- FIND_LIBRARY(LIBMD_LIBRARY NAMES md)
- LIST(APPEND ADDITIONAL_LIBS ${LIBMD_LIBRARY})
- CMAKE_POP_CHECK_STATE() # Restore the state of the variables
-ENDIF(LIBMD_FOUND)
+IF(NOT OPENSSL_FOUND)
+ CHECK_LIBRARY_EXISTS(md "MD5Init" "" LIBMD_FOUND)
+ IF(LIBMD_FOUND)
+ CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
+ SET(CMAKE_REQUIRED_LIBRARIES "md")
+ FIND_LIBRARY(LIBMD_LIBRARY NAMES md)
+ LIST(APPEND ADDITIONAL_LIBS ${LIBMD_LIBRARY})
+ CMAKE_POP_CHECK_STATE() # Restore the state of the variables
+ ENDIF(LIBMD_FOUND)
+ENDIF(NOT OPENSSL_FOUND)
#
# How to prove that CRYPTO functions, which have several names on various
@@ -502,13 +558,8 @@ ENDIF(LIBMD_FOUND)
# required libraries.
#
MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
- IF(HAVE_SYS_TYPES_H)
- SET(CRYPTO_HEADER_CONFIG "#define HAVE_SYS_TYPES_H 1\n")
- ELSE(HAVE_SYS_TYPES_H)
- SET(CRYPTO_HEADER_CONFIG "")
- ENDIF(HAVE_SYS_TYPES_H)
-
FOREACH(ALGORITHM ${ALGORITHMS})
+ IF(NOT ARCHIVE_CRYPTO_${ALGORITHM})
STRING(TOLOWER "${ALGORITHM}" lower_algorithm)
STRING(TOUPPER "${ALGORITHM}" algorithm)
IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND NOT OPENSSL_FOUND)
@@ -521,7 +572,7 @@ MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
# Probe the local implementation for whether this
# crypto implementation is available on this platform.
SET(TRY_CRYPTO_REQUIRED_INCLUDES
- "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_CURRENT_SOURCE_DIR}/libarchive;${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp")
+ "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive;${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp")
SET(TRY_CRYPTO_REQUIRED_LIBS)
IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND)
SET(TRY_CRYPTO_REQUIRED_INCLUDES
@@ -529,6 +580,8 @@ MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
SET(TRY_CRYPTO_REQUIRED_LIBS
"-DLINK_LIBRARIES:STRING=${OPENSSL_LIBRARIES}")
ELSEIF("${IMPLEMENTATION}" MATCHES "^NETTLE$" AND NETTLE_FOUND)
+ SET(TRY_CRYPTO_REQUIRED_INCLUDES
+ "${TRY_CRYPTO_REQUIRED_INCLUDES};${NETTLE_INCLUDE_DIR}")
SET(TRY_CRYPTO_REQUIRED_LIBS
"-DLINK_LIBRARIES:STRING=${NETTLE_LIBRARY}")
ELSEIF("${IMPLEMENTATION}" MATCHES "^LIBMD$" AND LIBMD_FOUND)
@@ -536,10 +589,15 @@ MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
"-DLINK_LIBRARIES:STRING=${LIBMD_LIBRARY}")
ENDIF("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND)
+ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h)
+ FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h"
+ CONFDEFS_H)
FILE(READ "${CMAKE_CURRENT_SOURCE_DIR}/libarchive/archive_crypto.c"
ARCHIVE_CRYPTO_C)
- SET(SOURCE "
+ SET(SOURCE "${CONFDEFS_H}
+
#define ARCHIVE_${algorithm}_COMPILE_TEST
#define ARCHIVE_CRYPTO_${algorithm}_${IMPLEMENTATION}
#define PLATFORM_CONFIG_H \"check_crypto_md.h\"
@@ -561,10 +619,16 @@ main(int argc, char **argv)
FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c" "${SOURCE}")
MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}")
+ IF(CMAKE_REQUIRED_LINKER_FLAGS)
+ SET(CHECK_CRYPTO_ADD_LINKER_FLAGS
+ "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS}")
+ ELSE(CMAKE_REQUIRED_LINKER_FLAGS)
+ SET(CHECK_CRYPTO_ADD_LINKER_FLAGS)
+ ENDIF(CMAKE_REQUIRED_LINKER_FLAGS)
TRY_COMPILE(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c
- CMAKE_FLAGS
+ CMAKE_FLAGS ${CHECK_CRYPTO_ADD_LINKER_FLAGS}
"${TRY_CRYPTO_REQUIRED_LIBS}"
"${TRY_CRYPTO_REQUIRED_INCLUDES}"
OUTPUT_VARIABLE OUTPUT)
@@ -572,6 +636,7 @@ main(int argc, char **argv)
# Inform user whether or not we found it; if not, log why we didn't.
IF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} -- found")
+ SET(ARCHIVE_CRYPTO_${ALGORITHM} 1)
ELSE (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} -- not found")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
@@ -590,6 +655,7 @@ main(int argc, char **argv)
LIST(REMOVE_DUPLICATES ADDITIONAL_LIBS)
ENDIF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND)
ENDIF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
+ ENDIF(NOT ARCHIVE_CRYPTO_${ALGORITHM})
ENDFOREACH(ALGORITHM ${ALGORITHMS})
ENDMACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
@@ -605,6 +671,7 @@ ENDMACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
MACRO(CHECK_CRYPTO_WIN CRYPTO_LIST)
IF(WIN32 AND NOT CYGWIN)
FOREACH(CRYPTO ${CRYPTO_LIST})
+ IF(NOT ARCHIVE_CRYPTO_${CRYPTO})
IF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN)
STRING(TOUPPER "${CRYPTO}" crypto)
SET(ALGID "")
@@ -624,9 +691,14 @@ MACRO(CHECK_CRYPTO_WIN CRYPTO_LIST)
SET(ALGID "CALG_SHA_512")
ENDIF ("${CRYPTO}" MATCHES "^SHA512$")
- SET(SOURCE "#define ${crypto}_COMPILE_TEST
-#define _WIN32_WINNT ${_WIN32_WINNT}
-#define WINVER ${WINVER}
+ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h)
+ FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h"
+ CONFDEFS_H)
+
+ SET(SOURCE "${CONFDEFS_H}
+
+#define ${crypto}_COMPILE_TEST
#include <windows.h>
#include <wincrypt.h>
@@ -641,15 +713,22 @@ main(int argc, char **argv)
FILE(WRITE "${SOURCE_FILE}" "${SOURCE}")
MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN")
+ IF(CMAKE_REQUIRED_LINKER_FLAGS)
+ SET(CHECK_CRYPTO_WIN_ADD_LINKER_FLAGS
+ "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS}")
+ ELSE(CMAKE_REQUIRED_LINKER_FLAGS)
+ SET(CHECK_CRYPTO_WIN_ADD_LINKER_FLAGS)
+ ENDIF(CMAKE_REQUIRED_LINKER_FLAGS)
TRY_COMPILE(ARCHIVE_CRYPTO_${CRYPTO}_WIN
${CMAKE_BINARY_DIR}
${SOURCE_FILE}
- CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_CURRENT_SOURCE_DIR}/libarchive"
+ CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive" ${CHECK_CRYPTO_WIN_ADD_LINKER_FLAGS}
OUTPUT_VARIABLE OUTPUT)
IF (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
MESSAGE(STATUS
"Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- found")
+ SET(ARCHIVE_CRYPTO_${CRYPTO} 1)
ELSE (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
MESSAGE(STATUS
"Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- not found")
@@ -661,6 +740,7 @@ main(int argc, char **argv)
ENDIF (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
ENDIF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN)
+ ENDIF(NOT ARCHIVE_CRYPTO_${CRYPTO})
ENDFOREACH(CRYPTO)
ENDIF(WIN32 AND NOT CYGWIN)
ENDMACRO(CHECK_CRYPTO_WIN CRYPTO_LIST)
@@ -688,7 +768,7 @@ MACRO(CHECK_ICONV LIB TRY_ICONV_CONST)
SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /WX")
ENDIF (MSVC)
#
- CHECK_C_SOURCE_COMPILES(
+ LIBARCHIVE_CHECK_C_SOURCE_COMPILES(
"#include <stdlib.h>
#include <iconv.h>
int main() {
@@ -841,49 +921,112 @@ ELSE(LIBXML2_FOUND)
ENDIF(LIBXML2_FOUND)
MARK_AS_ADVANCED(CLEAR LIBXML2_INCLUDE_DIR)
MARK_AS_ADVANCED(CLEAR LIBXML2_LIBRARIES)
+
#
-# Find Libregex
+# POSIX Regular Expression support
#
-FIND_PATH(REGEX_INCLUDE_DIR regex.h)
-IF(REGEX_INCLUDE_DIR)
- CHECK_FUNCTION_EXISTS_GLIBC(regcomp HAVE_REGCOMP_LIBC)
+IF(POSIX_REGEX_LIB MATCHES "^(AUTO|LIBC|LIBREGEX)$")
#
- # If libc does not provide regex, find libregex.
+ # If PCREPOSIX is not found or not requested, try using regex
+ # from libc or libregex
#
- IF(NOT HAVE_REGCOMP_LIBC)
- CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
- FIND_LIBRARY(REGEX_LIBRARY regex)
- IF(REGEX_LIBRARY)
- SET(CMAKE_REQUIRED_LIBRARIES ${REGEX_LIBRARY})
- CHECK_FUNCTION_EXISTS_GLIBC(regcomp HAVE_REGCOMP_LIBREGEX)
- IF(HAVE_REGCOMP_LIBREGEX)
- LIST(APPEND ADDITIONAL_LIBS ${REGEX_LIBRARY})
- #
- # If regex.h is not found, retry looking for regex.h at
- # REGEX_INCLUDE_DIR
- #
- IF(NOT HAVE_REGEX_H)
- UNSET(HAVE_REGEX_H CACHE)
- INCLUDE_DIRECTORIES(${REGEX_INCLUDE_DIR})
- SET(CMAKE_REQUIRED_INCLUDES ${REGEX_INCLUDE_DIR})
- LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H)
- ENDIF(NOT HAVE_REGEX_H)
- # Test if a macro is needed for the library.
- TRY_MACRO_FOR_LIBRARY(
- "${REGEX_INCLUDE_DIR}" "${REGEX_LIBRARY}"
- COMPILES
- "#include <stddef.h>\n#include <regex.h>\nint main() {regex_t r;return regcomp(&r, \"\", 0);}"
- "USE_REGEX_DLL;USE_REGEX_STATIC")
- IF(USE_REGEX_DLL)
- ADD_DEFINITIONS(-DUSE_REGEX_DLL)
- ELSEIF(USE_REGEX_STATIC)
- ADD_DEFINITIONS(-DUSE_REGEX_STATIC)
- ENDIF(USE_REGEX_DLL)
- ENDIF(HAVE_REGCOMP_LIBREGEX)
- ENDIF(REGEX_LIBRARY)
- CMAKE_POP_CHECK_STATE() # Restore the state of the variables
- ENDIF(NOT HAVE_REGCOMP_LIBC)
-ENDIF(REGEX_INCLUDE_DIR)
+ FIND_PATH(REGEX_INCLUDE_DIR regex.h)
+ IF(REGEX_INCLUDE_DIR)
+ CHECK_FUNCTION_EXISTS_GLIBC(regcomp HAVE_REGCOMP_LIBC)
+ #
+ # If libc does not provide regex, find libregex.
+ #
+ IF(NOT HAVE_REGCOMP_LIBC)
+ CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
+ FIND_LIBRARY(REGEX_LIBRARY regex)
+ IF(REGEX_LIBRARY)
+ SET(CMAKE_REQUIRED_LIBRARIES ${REGEX_LIBRARY})
+ CHECK_FUNCTION_EXISTS_GLIBC(regcomp HAVE_REGCOMP_LIBREGEX)
+ IF(HAVE_REGCOMP_LIBREGEX)
+ LIST(APPEND ADDITIONAL_LIBS ${REGEX_LIBRARY})
+ #
+ # If regex.h is not found, retry looking for regex.h at
+ # REGEX_INCLUDE_DIR
+ #
+ IF(NOT HAVE_REGEX_H)
+ UNSET(HAVE_REGEX_H CACHE)
+ INCLUDE_DIRECTORIES(${REGEX_INCLUDE_DIR})
+ SET(CMAKE_REQUIRED_INCLUDES ${REGEX_INCLUDE_DIR})
+ LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H)
+ ENDIF(NOT HAVE_REGEX_H)
+ # Test if a macro is needed for the library.
+ TRY_MACRO_FOR_LIBRARY(
+ "${REGEX_INCLUDE_DIR}" "${REGEX_LIBRARY}"
+ COMPILES
+ "#include <stddef.h>\n#include <regex.h>\nint main() {regex_t r;return regcomp(&r, \"\", 0);}"
+ "USE_REGEX_DLL;USE_REGEX_STATIC")
+ IF(USE_REGEX_DLL)
+ ADD_DEFINITIONS(-DUSE_REGEX_DLL)
+ ELSEIF(USE_REGEX_STATIC)
+ ADD_DEFINITIONS(-DUSE_REGEX_STATIC)
+ ENDIF(USE_REGEX_DLL)
+ ENDIF(HAVE_REGCOMP_LIBREGEX)
+ ENDIF(REGEX_LIBRARY)
+ CMAKE_POP_CHECK_STATE() # Restore the state of the variables
+ ENDIF(NOT HAVE_REGCOMP_LIBC)
+ ENDIF(REGEX_INCLUDE_DIR)
+ IF(HAVE_REGCOMP_LIBC OR HAVE_REGCOMP_LIBREGEX)
+ SET(FOUND_POSIX_REGEX_LIB 1)
+ ENDIF(HAVE_REGCOMP_LIBC OR HAVE_REGCOMP_LIBREGEX)
+ENDIF(POSIX_REGEX_LIB MATCHES "^(AUTO|LIBC|LIBREGEX)$")
+
+IF(NOT FOUND_POSIX_REGEX_LIB AND POSIX_REGEX_LIB MATCHES "^(AUTO|LIBPCREPOSIX)$")
+ #
+ # If requested, try finding library for PCREPOSIX
+ #
+ FIND_PACKAGE(LibGCC)
+ FIND_PACKAGE(PCREPOSIX)
+ IF(PCREPOSIX_FOUND)
+ INCLUDE_DIRECTORIES(${PCRE_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${PCREPOSIX_LIBRARIES})
+ # Test if a macro is needed for the library.
+ TRY_MACRO_FOR_LIBRARY(
+ "${PCRE_INCLUDE_DIR}" "${PCREPOSIX_LIBRARIES}"
+ COMPILES
+ "#include <pcreposix.h>\nint main() {regex_t r;return regcomp(&r, \"\", 0);}"
+ "WITHOUT_PCRE_STATIC;PCRE_STATIC")
+ IF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC)
+ ADD_DEFINITIONS(-DPCRE_STATIC)
+ ELSEIF(NOT WITHOUT_PCRE_STATIC AND NOT PCRE_STATIC AND PCRE_FOUND)
+ # Determine if pcre static libraries are to be used.
+ LIST(APPEND ADDITIONAL_LIBS ${PCRE_LIBRARIES})
+ SET(TMP_LIBRARIES ${PCREPOSIX_LIBRARIES} ${PCRE_LIBRARIES})
+ MESSAGE(STATUS "trying again with -lpcre included")
+ TRY_MACRO_FOR_LIBRARY(
+ "${PCRE_INCLUDE_DIR}" "${TMP_LIBRARIES}"
+ COMPILES
+ "#include <pcreposix.h>\nint main() {regex_t r;return regcomp(&r, \"\", 0);}"
+ "WITHOUT_PCRE_STATIC;PCRE_STATIC")
+ IF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC)
+ ADD_DEFINITIONS(-DPCRE_STATIC)
+ ELSEIF(NOT WITHOUT_PCRE_STATIC AND NOT PCRE_STATIC AND MSVC AND LIBGCC_FOUND)
+ # When doing a Visual Studio build using pcre static libraries
+ # built using the mingw toolchain, -lgcc is needed to resolve
+ # ___chkstk_ms.
+ MESSAGE(STATUS "Visual Studio build detected, trying again with -lgcc included")
+ LIST(APPEND ADDITIONAL_LIBS ${LIBGCC_LIBRARIES})
+ SET(TMP_LIBRARIES ${PCREPOSIX_LIBRARIES} ${PCRE_LIBRARIES} ${LIBGCC_LIBRARIES})
+ TRY_MACRO_FOR_LIBRARY(
+ "${PCRE_INCLUDE_DIR}" "${TMP_LIBRARIES}"
+ COMPILES
+ "#include <pcreposix.h>\nint main() {regex_t r;return regcomp(&r, \"\", 0);}"
+ "WITHOUT_PCRE_STATIC;PCRE_STATIC")
+ IF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC)
+ ADD_DEFINITIONS(-DPCRE_STATIC)
+ ENDIF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC)
+ ENDIF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC)
+ ENDIF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC)
+ ENDIF(PCREPOSIX_FOUND)
+ MARK_AS_ADVANCED(CLEAR PCRE_INCLUDE_DIR)
+ MARK_AS_ADVANCED(CLEAR PCREPOSIX_LIBRARIES)
+ MARK_AS_ADVANCED(CLEAR PCRE_LIBRARIES)
+ MARK_AS_ADVANCED(CLEAR LIBGCC_LIBRARIES)
+ENDIF(NOT FOUND_POSIX_REGEX_LIB AND POSIX_REGEX_LIB MATCHES "^(AUTO|LIBPCREPOSIX)$")
#
# Check functions
@@ -902,6 +1045,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(chflags HAVE_CHFLAGS)
CHECK_FUNCTION_EXISTS_GLIBC(chown HAVE_CHOWN)
CHECK_FUNCTION_EXISTS_GLIBC(chroot HAVE_CHROOT)
CHECK_FUNCTION_EXISTS_GLIBC(ctime_r HAVE_CTIME_R)
+CHECK_FUNCTION_EXISTS_GLIBC(dirfd HAVE_DIRFD)
CHECK_FUNCTION_EXISTS_GLIBC(fchdir HAVE_FCHDIR)
CHECK_FUNCTION_EXISTS_GLIBC(fchflags HAVE_FCHFLAGS)
CHECK_FUNCTION_EXISTS_GLIBC(fchmod HAVE_FCHMOD)
@@ -942,6 +1086,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(nl_langinfo HAVE_NL_LANGINFO)
CHECK_FUNCTION_EXISTS_GLIBC(openat HAVE_OPENAT)
CHECK_FUNCTION_EXISTS_GLIBC(pipe HAVE_PIPE)
CHECK_FUNCTION_EXISTS_GLIBC(poll HAVE_POLL)
+CHECK_FUNCTION_EXISTS_GLIBC(posix_spawnp HAVE_POSIX_SPAWNP)
CHECK_FUNCTION_EXISTS_GLIBC(readlink HAVE_READLINK)
CHECK_FUNCTION_EXISTS_GLIBC(select HAVE_SELECT)
CHECK_FUNCTION_EXISTS_GLIBC(setenv HAVE_SETENV)
@@ -986,14 +1131,14 @@ CMAKE_POP_CHECK_STATE() # Restore the state of the variables
# Make sure we have the POSIX version of readdir_r, not the
# older 2-argument version.
-CHECK_C_SOURCE_COMPILES(
+LIBARCHIVE_CHECK_C_SOURCE_COMPILES(
"#include <dirent.h>\nint main() {DIR *d = opendir(\".\"); struct dirent e,*r; return readdir_r(d,&e,&r);}"
HAVE_READDIR_R)
# Only detect readlinkat() if we also have AT_FDCWD in unistd.h.
# NOTE: linux requires fcntl.h for AT_FDCWD.
-CHECK_C_SOURCE_COMPILES(
+LIBARCHIVE_CHECK_C_SOURCE_COMPILES(
"#include <fcntl.h>\n#include <unistd.h>\nint main() {char buf[10]; return readlinkat(AT_FDCWD, \"\", buf, 0);}"
HAVE_READLINKAT)
@@ -1002,10 +1147,10 @@ CHECK_C_SOURCE_COMPILES(
# of interest and verify that the result can be linked.
# CHECK_FUNCTION_EXISTS doesn't accept a header argument,
# CHECK_SYMBOL_EXISTS doesn't test linkage.
-CHECK_C_SOURCE_COMPILES(
+LIBARCHIVE_CHECK_C_SOURCE_COMPILES(
"#include <sys/mkdev.h>\nint main() { return major(256); }"
MAJOR_IN_MKDEV)
-CHECK_C_SOURCE_COMPILES(
+LIBARCHIVE_CHECK_C_SOURCE_COMPILES(
"#include <sys/sysmacros.h>\nint main() { return major(256); }"
MAJOR_IN_SYSMACROS)
@@ -1301,6 +1446,8 @@ IF(ENABLE_ACL)
CHECK_FUNCTION_EXISTS(acl_get_perm_np HAVE_ACL_GET_PERM_NP)
CHECK_FUNCTION_EXISTS(acl_get_link HAVE_ACL_GET_LINK)
CHECK_FUNCTION_EXISTS(acl_get_link_np HAVE_ACL_GET_LINK_NP)
+ CHECK_FUNCTION_EXISTS(acl_is_trivial_np HAVE_ACL_IS_TRIVIAL_NP)
+ CHECK_FUNCTION_EXISTS(acl_set_link_np HAVE_ACL_SET_LINK_NP)
# MacOS has an acl.h that isn't POSIX. It can be detected by
# checking for ACL_USER
diff --git a/Makefile.am b/Makefile.am
index 6ac9a4e44dae..3fa2d22b6de6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -90,6 +90,8 @@ libarchive_la_SOURCES= \
libarchive/archive_acl.c \
libarchive/archive_acl_private.h \
libarchive/archive_check_magic.c \
+ libarchive/archive_cmdline.c \
+ libarchive/archive_cmdline_private.h \
libarchive/archive_crc32.h \
libarchive/archive_crypto.c \
libarchive/archive_crypto_private.h \
@@ -118,6 +120,7 @@ libarchive_la_SOURCES= \
libarchive/archive_rb.c \
libarchive/archive_rb.h \
libarchive/archive_read.c \
+ libarchive/archive_read_append_filter.c \
libarchive/archive_read_data_into_fd.c \
libarchive/archive_read_disk_entry_from_file.c \
libarchive/archive_read_disk_posix.c \
@@ -129,11 +132,15 @@ libarchive_la_SOURCES= \
libarchive/archive_read_open_filename.c \
libarchive/archive_read_open_memory.c \
libarchive/archive_read_private.h \
+ libarchive/archive_read_set_format.c \
libarchive/archive_read_set_options.c \
libarchive/archive_read_support_filter_all.c \
libarchive/archive_read_support_filter_bzip2.c \
libarchive/archive_read_support_filter_compress.c \
+ libarchive/archive_read_support_filter_grzip.c \
libarchive/archive_read_support_filter_gzip.c \
+ libarchive/archive_read_support_filter_lrzip.c \
+ libarchive/archive_read_support_filter_lzop.c \
libarchive/archive_read_support_filter_none.c \
libarchive/archive_read_support_filter_program.c \
libarchive/archive_read_support_filter_rpm.c \
@@ -161,6 +168,7 @@ libarchive_la_SOURCES= \
libarchive/archive_util.c \
libarchive/archive_virtual.c \
libarchive/archive_write.c \
+ libarchive/archive_write_disk_acl.c \
libarchive/archive_write_disk_posix.c \
libarchive/archive_write_disk_private.h \
libarchive/archive_write_disk_set_standard_lookup.c \
@@ -170,11 +178,17 @@ libarchive_la_SOURCES= \
libarchive/archive_write_open_memory.c \
libarchive/archive_write_private.h \
libarchive/archive_write_add_filter.c \
- libarchive/archive_write_add_filter_bzip2.c \
- libarchive/archive_write_add_filter_compress.c \
+ libarchive/archive_write_add_filter_b64encode.c \
+ libarchive/archive_write_add_filter_by_name.c \
+ libarchive/archive_write_add_filter_bzip2.c \
+ libarchive/archive_write_add_filter_compress.c \
+ libarchive/archive_write_add_filter_grzip.c \
libarchive/archive_write_add_filter_gzip.c \
+ libarchive/archive_write_add_filter_lrzip.c \
+ libarchive/archive_write_add_filter_lzop.c \
libarchive/archive_write_add_filter_none.c \
- libarchive/archive_write_add_filter_program.c \
+ libarchive/archive_write_add_filter_program.c \
+ libarchive/archive_write_add_filter_uuencode.c \
libarchive/archive_write_add_filter_xz.c \
libarchive/archive_write_set_format.c \
libarchive/archive_write_set_format_7zip.c \
@@ -187,12 +201,13 @@ libarchive_la_SOURCES= \
libarchive/archive_write_set_format_pax.c \
libarchive/archive_write_set_format_shar.c \
libarchive/archive_write_set_format_ustar.c \
+ libarchive/archive_write_set_format_v7tar.c \
libarchive/archive_write_set_format_gnutar.c \
libarchive/archive_write_set_format_xar.c \
libarchive/archive_write_set_format_zip.c \
libarchive/archive_write_set_options.c \
libarchive/config_freebsd.h \
- libarchive/filter_fork.c \
+ libarchive/filter_fork_posix.c \
libarchive/filter_fork.h
if INC_WINDOWS_FILES
@@ -220,14 +235,32 @@ libarchive_man_MANS= \
libarchive/archive_entry_stat.3 \
libarchive/archive_entry_time.3 \
libarchive/archive_read.3 \
+ libarchive/archive_read_data.3 \
libarchive/archive_read_disk.3 \
+ libarchive/archive_read_extract.3 \
+ libarchive/archive_read_filter.3 \
+ libarchive/archive_read_format.3 \
+ libarchive/archive_read_free.3 \
+ libarchive/archive_read_header.3 \
+ libarchive/archive_read_new.3 \
+ libarchive/archive_read_open.3 \
libarchive/archive_read_set_options.3 \
libarchive/archive_util.3 \
libarchive/archive_write.3 \
+ libarchive/archive_write_blocksize.3 \
+ libarchive/archive_write_data.3 \
libarchive/archive_write_disk.3 \
+ libarchive/archive_write_filter.3 \
+ libarchive/archive_write_finish_entry.3 \
+ libarchive/archive_write_format.3 \
+ libarchive/archive_write_free.3 \
+ libarchive/archive_write_header.3 \
+ libarchive/archive_write_new.3 \
+ libarchive/archive_write_open.3 \
libarchive/archive_write_set_options.3 \
libarchive/cpio.5 \
libarchive/libarchive.3 \
+ libarchive/libarchive_changes.3 \
libarchive/libarchive_internals.3 \
libarchive/libarchive-formats.5 \
libarchive/mtree.5 \
@@ -245,6 +278,11 @@ libarchive_EXTRA_DIST= \
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = build/pkgconfig/libarchive.pc
+# Sources needed by all test programs
+test_utils_SOURCES= \
+ test_utils/test_utils.c \
+ test_utils/test_utils.h
+
#
#
# libarchive_test program
@@ -252,15 +290,18 @@ pkgconfig_DATA = build/pkgconfig/libarchive.pc
#
libarchive_test_SOURCES= \
$(libarchive_la_SOURCES) \
+ $(test_utils_SOURCES) \
libarchive/test/main.c \
libarchive/test/read_open_memory.c \
libarchive/test/test.h \
- libarchive/test/test_acl_freebsd.c \
+ libarchive/test/test_acl_freebsd_posix1e.c \
+ libarchive/test/test_acl_freebsd_nfs4.c \
libarchive/test/test_acl_nfs4.c \
libarchive/test/test_acl_pax.c \
libarchive/test/test_acl_posix1e.c \
libarchive/test/test_archive_api_feature.c \
libarchive/test/test_archive_clear_error.c \
+ libarchive/test/test_archive_cmdline.c \
libarchive/test/test_archive_crypto.c \
libarchive/test/test_archive_getdate.c \
libarchive/test/test_archive_match_owner.c \
@@ -270,6 +311,7 @@ libarchive_test_SOURCES= \
libarchive/test/test_archive_read_close_twice.c \
libarchive/test/test_archive_read_close_twice_open_fd.c \
libarchive/test/test_archive_read_close_twice_open_filename.c \
+ libarchive/test/test_archive_read_multiple_data_objects.c \
libarchive/test/test_archive_read_next_header_empty.c \
libarchive/test/test_archive_read_next_header_raw.c \
libarchive/test/test_archive_read_open2.c \
@@ -281,7 +323,9 @@ libarchive_test_SOURCES= \
libarchive/test/test_archive_set_error.c \
libarchive/test/test_archive_string.c \
libarchive/test/test_archive_string_conversion.c \
+ libarchive/test/test_archive_write_add_filter_by_name.c \
libarchive/test/test_archive_write_set_filter_option.c \
+ libarchive/test/test_archive_write_set_format_by_name.c \
libarchive/test/test_archive_write_set_format_option.c \
libarchive/test/test_archive_write_set_option.c \
libarchive/test/test_archive_write_set_options.c \
@@ -292,11 +336,13 @@ libarchive_test_SOURCES= \
libarchive/test/test_compat_gzip.c \
libarchive/test/test_compat_lzip.c \
libarchive/test/test_compat_lzma.c \
+ libarchive/test/test_compat_lzop.c \
libarchive/test/test_compat_mac.c \
libarchive/test/test_compat_pax_libarchive_2x.c \
libarchive/test/test_compat_solaris_tar_acl.c \
libarchive/test/test_compat_solaris_pax_sparse.c \
libarchive/test/test_compat_tar_hardlink.c \
+ libarchive/test/test_compat_uudecode.c \
libarchive/test/test_compat_xz.c \
libarchive/test/test_compat_zip.c \
libarchive/test/test_empty_write.c \
@@ -312,13 +358,19 @@ libarchive_test_SOURCES= \
libarchive/test/test_open_file.c \
libarchive/test/test_open_filename.c \
libarchive/test/test_pax_filename_encoding.c \
- libarchive/test/test_read_compress_program.c \
libarchive/test/test_read_data_large.c \
libarchive/test/test_read_disk.c \
libarchive/test/test_read_disk_directory_traversals.c \
libarchive/test/test_read_disk_entry_from_file.c \
libarchive/test/test_read_extract.c \
libarchive/test/test_read_file_nonexistent.c \
+ libarchive/test/test_read_filter_grzip.c \
+ libarchive/test/test_read_filter_lrzip.c \
+ libarchive/test/test_read_filter_lzop.c \
+ libarchive/test/test_read_filter_lzop_multiple_parts.c \
+ libarchive/test/test_read_filter_program.c \
+ libarchive/test/test_read_filter_program_signature.c \
+ libarchive/test/test_read_filter_uudecode.c \
libarchive/test/test_read_format_7zip.c \
libarchive/test/test_read_format_ar.c \
libarchive/test/test_read_format_cab.c \
@@ -372,35 +424,49 @@ libarchive_test_SOURCES= \
libarchive/test/test_read_format_ustar_filename.c \
libarchive/test/test_read_format_xar.c \
libarchive/test/test_read_format_zip.c \
+ libarchive/test/test_read_format_zip_comment_stored.c \
libarchive/test/test_read_format_zip_filename.c \
+ libarchive/test/test_read_format_zip_mac_metadata.c \
+ libarchive/test/test_read_format_zip_sfx.c \
libarchive/test/test_read_large.c \
libarchive/test/test_read_pax_truncated.c \
libarchive/test/test_read_position.c \
+ libarchive/test/test_read_set_format.c \
libarchive/test/test_read_truncated.c \
libarchive/test/test_read_truncated_filter.c \
- libarchive/test/test_read_uu.c \
libarchive/test/test_sparse_basic.c \
libarchive/test/test_tar_filenames.c \
libarchive/test/test_tar_large.c \
libarchive/test/test_ustar_filenames.c \
libarchive/test/test_ustar_filename_encoding.c \
- libarchive/test/test_write_compress.c \
- libarchive/test/test_write_compress_bzip2.c \
- libarchive/test/test_write_compress_gzip.c \
- libarchive/test/test_write_compress_lzip.c \
- libarchive/test/test_write_compress_lzma.c \
- libarchive/test/test_write_compress_program.c \
- libarchive/test/test_write_compress_xz.c \
libarchive/test/test_write_disk.c \
+ libarchive/test/test_write_disk_appledouble.c \
libarchive/test/test_write_disk_failures.c \
libarchive/test/test_write_disk_hardlink.c \
+ libarchive/test/test_write_disk_hfs_compression.c \
libarchive/test/test_write_disk_lookup.c \
+ libarchive/test/test_write_disk_mac_metadata.c \
+ libarchive/test/test_write_disk_no_hfs_compression.c \
libarchive/test/test_write_disk_perms.c \
libarchive/test/test_write_disk_secure.c \
libarchive/test/test_write_disk_sparse.c \
libarchive/test/test_write_disk_symlink.c \
libarchive/test/test_write_disk_times.c \
+ libarchive/test/test_write_filter_b64encode.c \
+ libarchive/test/test_write_filter_bzip2.c \
+ libarchive/test/test_write_filter_compress.c \
+ libarchive/test/test_write_filter_gzip.c \
+ libarchive/test/test_write_filter_gzip_timestamp.c \
+ libarchive/test/test_write_filter_lrzip.c \
+ libarchive/test/test_write_filter_lzip.c \
+ libarchive/test/test_write_filter_lzma.c \
+ libarchive/test/test_write_filter_lzop.c \
+ libarchive/test/test_write_filter_program.c \
+ libarchive/test/test_write_filter_uuencode.c \
+ libarchive/test/test_write_filter_xz.c \
libarchive/test/test_write_format_7zip.c \
+ libarchive/test/test_write_format_7zip_empty.c \
+ libarchive/test/test_write_format_7zip_large.c \
libarchive/test/test_write_format_ar.c \
libarchive/test/test_write_format_cpio.c \
libarchive/test/test_write_format_cpio_empty.c \
@@ -413,22 +479,29 @@ libarchive_test_SOURCES= \
libarchive/test/test_write_format_iso9660_filename.c \
libarchive/test/test_write_format_iso9660_zisofs.c \
libarchive/test/test_write_format_mtree.c \
+ libarchive/test/test_write_format_mtree_absolute_path.c \
+ libarchive/test/test_write_format_mtree_classic.c \
+ libarchive/test/test_write_format_mtree_classic_indent.c\
libarchive/test/test_write_format_mtree_fflags.c \
+ libarchive/test/test_write_format_mtree_no_separator.c \
+ libarchive/test/test_write_format_mtree_quoted_filename.c\
libarchive/test/test_write_format_pax.c \
libarchive/test/test_write_format_shar_empty.c \
libarchive/test/test_write_format_tar.c \
libarchive/test/test_write_format_tar_empty.c \
libarchive/test/test_write_format_tar_sparse.c \
libarchive/test/test_write_format_tar_ustar.c \
+ libarchive/test/test_write_format_tar_v7tar.c \
libarchive/test/test_write_format_xar.c \
libarchive/test/test_write_format_xar_empty.c \
libarchive/test/test_write_format_zip.c \
libarchive/test/test_write_format_zip_empty.c \
libarchive/test/test_write_format_zip_no_compression.c \
libarchive/test/test_write_open_memory.c \
+ libarchive/test/test_write_zip_set_compression_store.c \
libarchive/test/test_zip_filename_encoding.c
-libarchive_test_CPPFLAGS= -I$(top_srcdir)/libarchive -I$(top_builddir)/libarchive/test -DLIBARCHIVE_STATIC $(PLATFORMCPPFLAGS)
+libarchive_test_CPPFLAGS= -I$(top_srcdir)/libarchive -I$(top_srcdir)/test_utils -I$(top_builddir)/libarchive/test -DLIBARCHIVE_STATIC $(PLATFORMCPPFLAGS)
libarchive_test_LDADD= $(LTLIBICONV)
# The "list.h" file just lists all of the tests defined in all of the sources.
@@ -437,7 +510,7 @@ libarchive_test_LDADD= $(LTLIBICONV)
libarchive/test/list.h: Makefile
cat $(top_srcdir)/libarchive/test/test_*.c | grep DEFINE_TEST > libarchive/test/list.h
-libarchive_TESTS_ENVIRONMENT= LIBARCHIVE_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/libarchive/test
+libarchive_TESTS_ENVIRONMENT= LIBARCHIVE_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/libarchive/test LRZIP=NOCONFIG
libarchive_test_EXTRA_DIST=\
libarchive/test/list.h \
@@ -454,6 +527,9 @@ libarchive_test_EXTRA_DIST=\
libarchive/test/test_compat_lzma_1.tlz.uu \
libarchive/test/test_compat_lzma_2.tlz.uu \
libarchive/test/test_compat_lzma_3.tlz.uu \
+ libarchive/test/test_compat_lzop_1.tar.lzo.uu \
+ libarchive/test/test_compat_lzop_2.tar.lzo.uu \
+ libarchive/test/test_compat_lzop_3.tar.lzo.uu \
libarchive/test/test_compat_mac-1.tar.Z.uu \
libarchive/test/test_compat_mac-2.tar.Z.uu \
libarchive/test/test_compat_pax_libarchive_2x.tar.Z.uu \
@@ -473,6 +549,29 @@ libarchive_test_EXTRA_DIST=\
libarchive/test/test_fuzz.cab.uu \
libarchive/test/test_fuzz.lzh.uu \
libarchive/test/test_pax_filename_encoding.tar.uu \
+ libarchive/test/test_rar_multivolume_multiple_files.part1.rar.uu \
+ libarchive/test/test_rar_multivolume_multiple_files.part2.rar.uu \
+ libarchive/test/test_rar_multivolume_multiple_files.part3.rar.uu \
+ libarchive/test/test_rar_multivolume_multiple_files.part4.rar.uu \
+ libarchive/test/test_rar_multivolume_multiple_files.part5.rar.uu \
+ libarchive/test/test_rar_multivolume_multiple_files.part6.rar.uu \
+ libarchive/test/test_rar_multivolume_single_file.part1.rar.uu \
+ libarchive/test/test_rar_multivolume_single_file.part2.rar.uu \
+ libarchive/test/test_rar_multivolume_single_file.part3.rar.uu \
+ libarchive/test/test_rar_multivolume_uncompressed_files.part01.rar.uu \
+ libarchive/test/test_rar_multivolume_uncompressed_files.part02.rar.uu \
+ libarchive/test/test_rar_multivolume_uncompressed_files.part03.rar.uu \
+ libarchive/test/test_rar_multivolume_uncompressed_files.part04.rar.uu \
+ libarchive/test/test_rar_multivolume_uncompressed_files.part05.rar.uu \
+ libarchive/test/test_rar_multivolume_uncompressed_files.part06.rar.uu \
+ libarchive/test/test_rar_multivolume_uncompressed_files.part07.rar.uu \
+ libarchive/test/test_rar_multivolume_uncompressed_files.part08.rar.uu \
+ libarchive/test/test_rar_multivolume_uncompressed_files.part09.rar.uu \
+ libarchive/test/test_rar_multivolume_uncompressed_files.part10.rar.uu \
+ libarchive/test/test_read_filter_grzip.tar.grz.uu \
+ libarchive/test/test_read_filter_lrzip.tar.lrz.uu \
+ libarchive/test/test_read_filter_lzop.tar.lzo.uu \
+ libarchive/test/test_read_filter_lzop_multiple_parts.tar.lzo.uu \
libarchive/test/test_read_format_7zip_bcj_bzip2.7z.uu \
libarchive/test/test_read_format_7zip_bcj_copy.7z.uu \
libarchive/test/test_read_format_7zip_bcj_deflate.7z.uu \
@@ -547,11 +646,17 @@ libarchive_test_EXTRA_DIST=\
libarchive/test/test_read_format_lha_withjunk.lzh.uu \
libarchive/test/test_read_format_mtree.mtree.uu \
libarchive/test/test_read_format_mtree_nomagic.mtree.uu \
+ libarchive/test/test_read_format_mtree_nomagic2.mtree.uu \
+ libarchive/test/test_read_format_mtree_nomagic3.mtree.uu \
libarchive/test/test_read_format_rar.rar.uu \
libarchive/test/test_read_format_rar_binary_data.rar.uu \
libarchive/test/test_read_format_rar_compress_best.rar.uu \
libarchive/test/test_read_format_rar_compress_normal.rar.uu \
libarchive/test/test_read_format_rar_multi_lzss_blocks.rar.uu \
+ libarchive/test/test_read_format_rar_multivolume.part0001.rar.uu\
+ libarchive/test/test_read_format_rar_multivolume.part0002.rar.uu\
+ libarchive/test/test_read_format_rar_multivolume.part0003.rar.uu\
+ libarchive/test/test_read_format_rar_multivolume.part0004.rar.uu\
libarchive/test/test_read_format_rar_noeof.rar.uu \
libarchive/test/test_read_format_rar_ppmd_lzss_conversion.rar.uu\
libarchive/test/test_read_format_rar_sfx.exe.uu \
@@ -566,6 +671,8 @@ libarchive_test_EXTRA_DIST=\
libarchive/test/test_read_format_ustar_filename_eucjp.tar.Z.uu \
libarchive/test/test_read_format_ustar_filename_koi8r.tar.Z.uu \
libarchive/test/test_read_format_zip.zip.uu \
+ libarchive/test/test_read_format_zip_comment_stored_1.zip.uu \
+ libarchive/test/test_read_format_zip_comment_stored_2.zip.uu \
libarchive/test/test_read_format_zip_filename_cp866.zip.uu \
libarchive/test/test_read_format_zip_filename_cp932.zip.uu \
libarchive/test/test_read_format_zip_filename_koi8r.zip.uu \
@@ -573,8 +680,26 @@ libarchive_test_EXTRA_DIST=\
libarchive/test/test_read_format_zip_filename_utf8_ru2.zip.uu \
libarchive/test/test_read_format_zip_filename_utf8_ru.zip.uu \
libarchive/test/test_read_format_zip_length_at_end.zip.uu \
+ libarchive/test/test_read_format_zip_mac_metadata.zip.uu \
+ libarchive/test/test_read_format_zip_sfx.uu \
libarchive/test/test_read_format_zip_symlink.zip.uu \
libarchive/test/test_read_format_zip_ux.zip.uu \
+ libarchive/test/test_read_large_splitted_rar_aa.uu \
+ libarchive/test/test_read_large_splitted_rar_ab.uu \
+ libarchive/test/test_read_large_splitted_rar_ac.uu \
+ libarchive/test/test_read_large_splitted_rar_ad.uu \
+ libarchive/test/test_read_large_splitted_rar_ae.uu \
+ libarchive/test/test_read_splitted_rar_aa.uu \
+ libarchive/test/test_read_splitted_rar_ab.uu \
+ libarchive/test/test_read_splitted_rar_ac.uu \
+ libarchive/test/test_read_splitted_rar_ad.uu \
+ libarchive/test/test_splitted_rar_seek_support_aa.uu \
+ libarchive/test/test_splitted_rar_seek_support_ab.uu \
+ libarchive/test/test_splitted_rar_seek_support_ac.uu \
+ libarchive/test/test_write_disk_appledouble.cpio.gz.uu \
+ libarchive/test/test_write_disk_hfs_compression.tgz.uu \
+ libarchive/test/test_write_disk_mac_metadata.tar.gz.uu \
+ libarchive/test/test_write_disk_no_hfs_compression.tgz.uu \
libarchive/test/CMakeLists.txt \
libarchive/test/README
@@ -600,6 +725,7 @@ bsdtar_SOURCES= \
tar/bsdtar.h \
tar/bsdtar_platform.h \
tar/cmdline.c \
+ tar/creation_set.c \
tar/read.c \
tar/subst.c \
tar/util.c \
@@ -646,12 +772,22 @@ endif
#
bsdtar_test_SOURCES= \
+ $(test_utils_SOURCES) \
tar/test/main.c \
tar/test/test.h \
tar/test/test_0.c \
tar/test/test_basic.c \
tar/test/test_copy.c \
tar/test/test_empty_mtree.c \
+ tar/test/test_extract_tar_Z.c \
+ tar/test/test_extract_tar_bz2.c \
+ tar/test/test_extract_tar_grz.c \
+ tar/test/test_extract_tar_gz.c \
+ tar/test/test_extract_tar_lrz.c \
+ tar/test/test_extract_tar_lz.c \
+ tar/test/test_extract_tar_lzma.c \
+ tar/test/test_extract_tar_lzo.c \
+ tar/test/test_extract_tar_xz.c \
tar/test/test_format_newc.c \
tar/test/test_help.c \
tar/test/test_option_C_upper.c \
@@ -661,18 +797,29 @@ bsdtar_test_SOURCES= \
tar/test/test_option_T_upper.c \
tar/test/test_option_U_upper.c \
tar/test/test_option_X_upper.c \
+ tar/test/test_option_a.c \
tar/test/test_option_b.c \
+ tar/test/test_option_b64encode.c \
tar/test/test_option_exclude.c \
tar/test/test_option_gid_gname.c \
+ tar/test/test_option_grzip.c \
+ tar/test/test_option_j.c \
tar/test/test_option_k.c \
tar/test/test_option_keep_newer_files.c \
+ tar/test/test_option_lrzip.c \
+ tar/test/test_option_lzma.c \
+ tar/test/test_option_lzop.c \
tar/test/test_option_n.c \
tar/test/test_option_newer_than.c \
tar/test/test_option_nodump.c \
+ tar/test/test_option_older_than.c \
tar/test/test_option_q.c \
tar/test/test_option_r.c \
tar/test/test_option_s.c \
tar/test/test_option_uid_uname.c \
+ tar/test/test_option_uuencode.c \
+ tar/test/test_option_xz.c \
+ tar/test/test_option_z.c \
tar/test/test_patterns.c \
tar/test/test_print_longpath.c \
tar/test/test_stdio.c \
@@ -683,6 +830,7 @@ bsdtar_test_SOURCES= \
bsdtar_test_CPPFLAGS=\
-I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe \
+ -I$(top_srcdir)/test_utils \
-I$(top_srcdir)/tar -I$(top_builddir)/tar/test \
$(PLATFORMCPPFLAGS)
@@ -699,6 +847,15 @@ endif
bsdtar_test_EXTRA_DIST= \
tar/test/list.h \
+ tar/test/test_extract.tar.Z.uu \
+ tar/test/test_extract.tar.bz2.uu \
+ tar/test/test_extract.tar.grz.uu \
+ tar/test/test_extract.tar.gz.uu \
+ tar/test/test_extract.tar.lrz.uu \
+ tar/test/test_extract.tar.lz.uu \
+ tar/test/test_extract.tar.lzma.uu \
+ tar/test/test_extract.tar.lzo.uu \
+ tar/test/test_extract.tar.xz.uu \
tar/test/test_option_keep_newer_files.tar.Z.uu \
tar/test/test_option_s.tar.Z.uu \
tar/test/test_patterns_2.tar.uu \
@@ -763,12 +920,22 @@ endif
#
bsdcpio_test_SOURCES= \
+ $(test_utils_SOURCES) \
cpio/cmdline.c \
cpio/test/main.c \
cpio/test/test.h \
cpio/test/test_0.c \
cpio/test/test_basic.c \
cpio/test/test_cmdline.c \
+ cpio/test/test_extract_cpio_Z.c \
+ cpio/test/test_extract_cpio_bz2.c \
+ cpio/test/test_extract_cpio_grz.c \
+ cpio/test/test_extract_cpio_gz.c \
+ cpio/test/test_extract_cpio_lrz.c \
+ cpio/test/test_extract_cpio_lz.c \
+ cpio/test/test_extract_cpio_lzma.c \
+ cpio/test/test_extract_cpio_lzo.c \
+ cpio/test/test_extract_cpio_xz.c \
cpio/test/test_format_newc.c \
cpio/test/test_gcpio_compat.c \
cpio/test/test_option_0.c \
@@ -778,16 +945,22 @@ bsdcpio_test_SOURCES= \
cpio/test/test_option_L_upper.c \
cpio/test/test_option_Z_upper.c \
cpio/test/test_option_a.c \
+ cpio/test/test_option_b64encode.c \
cpio/test/test_option_c.c \
cpio/test/test_option_d.c \
cpio/test/test_option_f.c \
+ cpio/test/test_option_grzip.c \
cpio/test/test_option_help.c \
cpio/test/test_option_l.c \
+ cpio/test/test_option_lrzip.c \
cpio/test/test_option_lzma.c \
+ cpio/test/test_option_lzop.c \
cpio/test/test_option_m.c \
cpio/test/test_option_t.c \
cpio/test/test_option_u.c \
+ cpio/test/test_option_uuencode.c \
cpio/test/test_option_version.c \
+ cpio/test/test_option_xz.c \
cpio/test/test_option_y.c \
cpio/test/test_option_z.c \
cpio/test/test_owner_parse.c \
@@ -796,6 +969,7 @@ bsdcpio_test_SOURCES= \
bsdcpio_test_CPPFLAGS= \
-I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe \
+ -I$(top_srcdir)/test_utils \
-I$(top_srcdir)/cpio -I$(top_builddir)/cpio/test \
$(PLATFORMCPPFLAGS)
bsdcpio_test_LDADD=libarchive_fe.la
@@ -813,6 +987,15 @@ endif
bsdcpio_test_EXTRA_DIST= \
cpio/test/list.h \
+ cpio/test/test_extract.cpio.Z.uu \
+ cpio/test/test_extract.cpio.bz2.uu \
+ cpio/test/test_extract.cpio.grz.uu \
+ cpio/test/test_extract.cpio.gz.uu \
+ cpio/test/test_extract.cpio.lrz.uu \
+ cpio/test/test_extract.cpio.lz.uu \
+ cpio/test/test_extract.cpio.lzma.uu \
+ cpio/test/test_extract.cpio.lzo.uu \
+ cpio/test/test_extract.cpio.xz.uu \
cpio/test/test_gcpio_compat_ref.bin.uu \
cpio/test/test_gcpio_compat_ref.crc.uu \
cpio/test/test_gcpio_compat_ref.newc.uu \
diff --git a/NEWS b/NEWS
index 5c280685f68f..107d4da0f11e 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,30 @@
+Feb 09, 2013: libarchive 3.1.2 released
+
+Jan 28, 2013: libarchive's new website moved to http://www.libarchive.org.
+
+Jan 13, 2013: libarchive 3.1.1 released
+
+Jan 13, 2013: libarchive 3.1.0 released
+
+Dec 07, 2012: Implement functions to manually set the format and filters used.
+
+Nov 11, 2012: Add support for __MACOSX directory in Zip archives, which resource
+ forks are stored in.
+
+Oct 20, 2012: Add support for writing v7 tar format.
+
+Oct 09, 2012: Add support for grzip compression.
+
+Oct 07, 2012: Introduce b64encode filter.
+Oct 07, 2012: Introduce uuencode filter.
+
+Oct 06, 2012: Add support for lzop.
+
+Sep 27, 2012: Implement function used to seek within data blocks.
+ (Currently only supported for uncompressed RAR archives).
+
+Apr 22, 2012: Add basic archive read and write filter support for lrzip.
+
Mar 27, 2012: libarchive 3.0.4 released
Feb 05, 2012: libarchive development now hosted at GitHub.
diff --git a/README b/README
index 4ffc3b75364f..1c974fde2202 100644
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
README for libarchive bundle.
Questions? Issues?
- * http://libarchive.github.com/ is the home for ongoing
+ * http://www.libarchive.org is the home for ongoing
libarchive development, including documentation, and
links to the libarchive mailing lists.
* To report an issue, use the issue tracker at
diff --git a/build/README.txt b/build/README.txt
new file mode 100644
index 000000000000..ce8e1a32a577
--- /dev/null
+++ b/build/README.txt
@@ -0,0 +1,35 @@
+Notes on making a new release of libarchive
+===========================================
+
+The following serves as a guide for libarchive developers on the general
+process to be followed when making a new release of libarchive.
+
+* Update build/version with the version number of the release to be made.
+* If the library's ABI has changed, the library's soname major version *MUST*
+ be updated. Update configure.ac and CMakeLists.txt appropriately.
+ - For configure.ac, the variable ARCHIVE_INTERFACE needs to be updated.
+ - For CMakeLists.txt, the variable INTERFACE_VERSION needs to be updated.
+* Update the entries in the NEWS file accordingly.
+* Run `build/makerelease.sh` from the top source directory. Running this script
+ will do the following.
+ - Removes all Makefile.am development build specific CFLAGS from
+ Makefile.am.
+ - Update configure scripts and header files with the appropriate version
+ number from build/version.
+ - Rebuild the documentation directory.
+ - Runs a full cmake build and test.
+ - Runs a full autotools build and test.
+ - Builds the .tar.gz and .zip distribution files.
+* Commit all changed files into git.
+ - This should be build/version, NEWS, and the files edited by running
+ build/makerelease.sh.
+* Tag the release appropriately. The tag should also have an appropriate
+ message.
+ - The git command is as follows:
+ $ git tag -m "Libarchive <version>" v<version>
+ Replace <version> with the version to be released.
+* Copy all the generated wiki files and commit them into the libarchive.wiki
+ repository. Overwrite any preexisting files with the same name (these files
+ are always autogenerated from the libarchive release after every release).
+* Update the libarchive.org website accordingly.
+* Make an announcement to the libarchive-announce mailing list.
diff --git a/build/autogen.sh b/build/autogen.sh
index d82a401f920c..e73162465d2a 100755
--- a/build/autogen.sh
+++ b/build/autogen.sh
@@ -48,6 +48,11 @@ perl -p -i -e "s/^(#define\tARCHIVE_VERSION_STRING).*/\$1 \"libarchive $VS\"/" l
perl -p -i -e 's/(m4_define\(\[LIBARCHIVE_VERSION_S\]),.*\)/$1,['"$VS"'])/' configure.ac
perl -p -i -e 's/(m4_define\(\[LIBARCHIVE_VERSION_N\]),.*\)/$1,['"$VN"'])/' configure.ac
+# Remove developer CFLAGS if a release build is being made
+if [ -n "${MAKE_LIBARCHIVE_RELEASE}" ]; then
+ perl -p -i -e "s/^(DEV_CFLAGS.*)/# \$1/" Makefile.am
+fi
+
set -xe
aclocal -I build/autoconf
diff --git a/build/bump-version.sh b/build/bump-version.sh
index 0304cf3fb329..eec42354fd47 100644
--- a/build/bump-version.sh
+++ b/build/bump-version.sh
@@ -31,6 +31,6 @@ echo $ANNOUNCE
# Add a version notice to NEWS
mv NEWS NEWS.bak
chmod +w NEWS.bak
-echo > NEWS
echo $ANNOUNCE >> NEWS
+echo >> NEWS
cat NEWS.bak >> NEWS
diff --git a/build/cmake/FindLibGCC.cmake b/build/cmake/FindLibGCC.cmake
new file mode 100644
index 000000000000..5883ff802642
--- /dev/null
+++ b/build/cmake/FindLibGCC.cmake
@@ -0,0 +1,22 @@
+# - Find libgcc
+# Find the libgcc library.
+#
+# LIBGCC_LIBRARIES - List of libraries when using libgcc
+# LIBGCC_FOUND - True if libgcc found.
+
+IF (LIBGCC_LIBRARY)
+ # Already in cache, be silent
+ SET(LIBGCC_FIND_QUIETLY TRUE)
+ENDIF (LIBGCC_LIBRARY)
+
+FIND_LIBRARY(LIBGCC_LIBRARY NAMES gcc libgcc)
+
+# handle the QUIETLY and REQUIRED arguments and set LIBGCC_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBGCC DEFAULT_MSG LIBGCC_LIBRARY)
+
+IF(LIBGCC_FOUND)
+ SET(LIBGCC_LIBRARIES ${LIBGCC_LIBRARY})
+ SET(HAVE_LIBGCC 1)
+ENDIF(LIBGCC_FOUND)
diff --git a/build/cmake/FindNettle.cmake b/build/cmake/FindNettle.cmake
new file mode 100644
index 000000000000..54ec9f5d39b5
--- /dev/null
+++ b/build/cmake/FindNettle.cmake
@@ -0,0 +1,23 @@
+# - Find Nettle
+# Find the Nettle include directory and library
+#
+# NETTLE_INCLUDE_DIR - where to find <nettle/sha.h>, etc.
+# NETTLE_LIBRARIES - List of libraries when using libnettle.
+# NETTLE_FOUND - True if libnettle found.
+
+IF (NETTLE_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(NETTLE_FIND_QUIETLY TRUE)
+ENDIF (NETTLE_INCLUDE_DIR)
+
+FIND_PATH(NETTLE_INCLUDE_DIR nettle/md5.h nettle/ripemd160.h nettle/sha.h)
+FIND_LIBRARY(NETTLE_LIBRARY NAMES nettle libnettle)
+
+# handle the QUIETLY and REQUIRED arguments and set NETTLE_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(NETTLE DEFAULT_MSG NETTLE_LIBRARY NETTLE_INCLUDE_DIR)
+
+IF(NETTLE_FOUND)
+ SET(NETTLE_LIBRARIES ${NETTLE_LIBRARY})
+ENDIF(NETTLE_FOUND)
diff --git a/build/cmake/FindPCREPOSIX.cmake b/build/cmake/FindPCREPOSIX.cmake
new file mode 100644
index 000000000000..56cc17eacb47
--- /dev/null
+++ b/build/cmake/FindPCREPOSIX.cmake
@@ -0,0 +1,34 @@
+# - Find pcreposix
+# Find the native PCRE and PCREPOSIX include and libraries
+#
+# PCRE_INCLUDE_DIR - where to find pcreposix.h, etc.
+# PCREPOSIX_LIBRARIES - List of libraries when using libpcreposix.
+# PCRE_LIBRARIES - List of libraries when using libpcre.
+# PCREPOSIX_FOUND - True if libpcreposix found.
+# PCRE_FOUND - True if libpcre found.
+
+IF (PCRE_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(PCRE_FIND_QUIETLY TRUE)
+ENDIF (PCRE_INCLUDE_DIR)
+
+FIND_PATH(PCRE_INCLUDE_DIR pcreposix.h)
+FIND_LIBRARY(PCREPOSIX_LIBRARY NAMES pcreposix libpcreposix)
+FIND_LIBRARY(PCRE_LIBRARY NAMES pcre libpcre)
+
+# handle the QUIETLY and REQUIRED arguments and set PCREPOSIX_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCREPOSIX DEFAULT_MSG PCREPOSIX_LIBRARY PCRE_INCLUDE_DIR)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE DEFAULT_MSG PCRE_LIBRARY)
+
+IF(PCREPOSIX_FOUND)
+ SET(PCREPOSIX_LIBRARIES ${PCREPOSIX_LIBRARY})
+ SET(HAVE_LIBPCREPOSIX 1)
+ SET(HAVE_PCREPOSIX_H 1)
+ENDIF(PCREPOSIX_FOUND)
+
+IF(PCRE_FOUND)
+ SET(PCRE_LIBRARIES ${PCRE_LIBRARY})
+ SET(HAVE_LIBPCRE 1)
+ENDIF(PCRE_FOUND)
diff --git a/build/cmake/LibarchiveCheckCSourceCompiles.cmake b/build/cmake/LibarchiveCheckCSourceCompiles.cmake
new file mode 100644
index 000000000000..6b6f59334da4
--- /dev/null
+++ b/build/cmake/LibarchiveCheckCSourceCompiles.cmake
@@ -0,0 +1,106 @@
+# - Check if given C source compiles and links into an executable
+# CHECK_C_SOURCE_COMPILES(<code> <var> [FAIL_REGEX <fail-regex>])
+# <code> - source code to try to compile, must define 'main'
+# <var> - variable to store whether the source code compiled
+# <fail-regex> - fail if test output matches this regex
+# The following variables may be set before calling this macro to
+# modify the way the check is run:
+#
+# CMAKE_REQUIRED_FLAGS = string of compile command line flags
+# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
+# CMAKE_REQUIRED_INCLUDES = list of include directories
+# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
+
+#=============================================================================
+# Copyright 2005-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+#
+# Extra arguments added by libarchive
+# CMAKE_REQUIRED_LINKER_FLAGS = string of linker command line flags
+#
+
+include(CMakeExpandImportedTargets)
+
+
+macro(LIBARCHIVE_CHECK_C_SOURCE_COMPILES SOURCE VAR)
+ if("${VAR}" MATCHES "^${VAR}$")
+ set(_FAIL_REGEX)
+ set(_key)
+ foreach(arg ${ARGN})
+ if("${arg}" MATCHES "^(FAIL_REGEX)$")
+ set(_key "${arg}")
+ elseif(_key)
+ list(APPEND _${_key} "${arg}")
+ else()
+ message(FATAL_ERROR "Unknown argument:\n ${arg}\n")
+ endif()
+ endforeach()
+ set(MACRO_CHECK_FUNCTION_DEFINITIONS
+ "-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
+ if(CMAKE_REQUIRED_LIBRARIES)
+ # this one translates potentially used imported library targets to their files on disk
+ CMAKE_EXPAND_IMPORTED_TARGETS(_ADJUSTED_CMAKE_REQUIRED_LIBRARIES LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CONFIGURATION "${CMAKE_TRY_COMPILE_CONFIGURATION}")
+ set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES
+ "-DLINK_LIBRARIES:STRING=${_ADJUSTED_CMAKE_REQUIRED_LIBRARIES}")
+ else()
+ set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES)
+ endif()
+ if(CMAKE_REQUIRED_INCLUDES)
+ set(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES
+ "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
+ else()
+ set(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES)
+ endif()
+ if(CMAKE_REQUIRED_LINKER_FLAGS)
+ set(CHECK_C_SOURCE_COMPILES_ADD_LINKER_FLAGS
+ "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS}")
+ else()
+ set(CHECK_C_SOURCE_COMPILES_ADD_LINKER_FLAGS)
+ endif()
+ file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c"
+ "${SOURCE}\n")
+
+ message(STATUS "Performing Test ${VAR}")
+ try_compile(${VAR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c
+ COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+ CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} ${CHECK_C_SOURCE_COMPILES_ADD_LINKER_FLAGS}
+ "${CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES}"
+ "${CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}"
+ OUTPUT_VARIABLE OUTPUT)
+
+ foreach(_regex ${_FAIL_REGEX})
+ if("${OUTPUT}" MATCHES "${_regex}")
+ set(${VAR} 0)
+ endif()
+ endforeach()
+
+ if(${VAR})
+ set(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
+ message(STATUS "Performing Test ${VAR} - Success")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Performing C SOURCE FILE Test ${VAR} succeded with the following output:\n"
+ "${OUTPUT}\n"
+ "Source file was:\n${SOURCE}\n")
+ else()
+ message(STATUS "Performing Test ${VAR} - Failed")
+ set(${VAR} "" CACHE INTERNAL "Test ${VAR}")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Performing C SOURCE FILE Test ${VAR} failed with the following output:\n"
+ "${OUTPUT}\n"
+ "Source file was:\n${SOURCE}\n")
+ endif()
+ endif()
+endmacro()
+
diff --git a/build/cmake/LibarchiveCheckCSourceRuns.cmake b/build/cmake/LibarchiveCheckCSourceRuns.cmake
new file mode 100644
index 000000000000..498f52265aca
--- /dev/null
+++ b/build/cmake/LibarchiveCheckCSourceRuns.cmake
@@ -0,0 +1,102 @@
+# - Check if the given C source code compiles and runs.
+# CHECK_C_SOURCE_RUNS(<code> <var>)
+# <code> - source code to try to compile
+# <var> - variable to store the result
+# (1 for success, empty for failure)
+# The following variables may be set before calling this macro to
+# modify the way the check is run:
+#
+# CMAKE_REQUIRED_FLAGS = string of compile command line flags
+# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
+# CMAKE_REQUIRED_INCLUDES = list of include directories
+# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
+
+#=============================================================================
+# Copyright 2006-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+#
+# Extra arguments added by libarchive
+# CMAKE_REQUIRED_LINKER_FLAGS = string of linker command line flags
+#
+
+include(CMakeExpandImportedTargets)
+
+
+macro(LIBARCHIVE_CHECK_C_SOURCE_RUNS SOURCE VAR)
+ if("${VAR}" MATCHES "^${VAR}$")
+ set(MACRO_CHECK_FUNCTION_DEFINITIONS
+ "-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
+ if(CMAKE_REQUIRED_LIBRARIES)
+ # this one translates potentially used imported library targets to their files on disk
+ CMAKE_EXPAND_IMPORTED_TARGETS(_ADJUSTED_CMAKE_REQUIRED_LIBRARIES LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CONFIGURATION "${CMAKE_TRY_COMPILE_CONFIGURATION}")
+ set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES
+ "-DLINK_LIBRARIES:STRING=${_ADJUSTED_CMAKE_REQUIRED_LIBRARIES}")
+ else()
+ set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES)
+ endif()
+ if(CMAKE_REQUIRED_INCLUDES)
+ set(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES
+ "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
+ else()
+ set(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES)
+ endif()
+ if(CMAKE_REQUIRED_LINKER_FLAGS)
+ set(CHECK_C_SOURCE_COMPILES_ADD_LINKER_FLAGS
+ "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS}")
+ else()
+ set(CHECK_C_SOURCE_COMPILES_ADD_LINKER_FLAGS)
+ endif()
+ file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c"
+ "${SOURCE}\n")
+
+ message(STATUS "Performing Test ${VAR}")
+ try_run(${VAR}_EXITCODE ${VAR}_COMPILED
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c
+ COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+ CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} ${CHECK_C_SOURCE_COMPILES_ADD_LINKER_FLAGS}
+ -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH}
+ "${CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES}"
+ "${CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}"
+ COMPILE_OUTPUT_VARIABLE OUTPUT)
+ # if it did not compile make the return value fail code of 1
+ if(NOT ${VAR}_COMPILED)
+ set(${VAR}_EXITCODE 1)
+ endif()
+ # if the return value was 0 then it worked
+ if("${${VAR}_EXITCODE}" EQUAL 0)
+ set(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
+ message(STATUS "Performing Test ${VAR} - Success")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Performing C SOURCE FILE Test ${VAR} succeded with the following output:\n"
+ "${OUTPUT}\n"
+ "Return value: ${${VAR}}\n"
+ "Source file was:\n${SOURCE}\n")
+ else()
+ if(CMAKE_CROSSCOMPILING AND "${${VAR}_EXITCODE}" MATCHES "FAILED_TO_RUN")
+ set(${VAR} "${${VAR}_EXITCODE}")
+ else()
+ set(${VAR} "" CACHE INTERNAL "Test ${VAR}")
+ endif()
+
+ message(STATUS "Performing Test ${VAR} - Failed")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Performing C SOURCE FILE Test ${VAR} failed with the following output:\n"
+ "${OUTPUT}\n"
+ "Return value: ${${VAR}_EXITCODE}\n"
+ "Source file was:\n${SOURCE}\n")
+
+ endif()
+ endif()
+endmacro()
+
diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in
index b56d2535b6d7..c04314ee5e32 100644
--- a/build/cmake/config.h.in
+++ b/build/cmake/config.h.in
@@ -390,6 +390,9 @@ typedef uint64_t uintmax_t;
*/
#cmakedefine HAVE_DIRENT_H 1
+/* Define to 1 if you have the `dirfd' function. */
+#cmakedefine HAVE_DIRFD 1
+
/* Define to 1 if you have the <dlfcn.h> header file. */
#cmakedefine HAVE_DLFCN_H 1
@@ -576,12 +579,27 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the `expat' library (-lexpat). */
#cmakedefine HAVE_LIBEXPAT 1
+/* Define to 1 if you have the `gcc' library (-lgcc). */
+#cmakedefine HAVE_LIBGCC 1
+
/* Define to 1 if you have the `lzma' library (-llzma). */
#cmakedefine HAVE_LIBLZMA 1
/* Define to 1 if you have the `lzmadec' library (-llzmadec). */
#cmakedefine HAVE_LIBLZMADEC 1
+/* Define to 1 if you have the `lzo2' library (-llzo2). */
+#cmakedefine HAVE_LIBLZO2 1
+
+/* Define to 1 if you have the `nettle' library (-lnettle). */
+#cmakedefine HAVE_LIBNETTLE 1
+
+/* Define to 1 if you have the `pcre' library (-lpcre). */
+#cmakedefine HAVE_LIBPCRE 1
+
+/* Define to 1 if you have the `pcreposix' library (-lpcreposix). */
+#cmakedefine HAVE_LIBPCREPOSIX 1
+
/* Define to 1 if you have the `xml2' library (-lxml2). */
#cmakedefine HAVE_LIBXML2 1
@@ -661,6 +679,12 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <lzma.h> header file. */
#cmakedefine HAVE_LZMA_H 1
+/* Define to 1 if you have the <lzo/lzo1x.h> header file. */
+#cmakedefine HAVE_LZO_LZO1X_H 1
+
+/* Define to 1 if you have the <lzo/lzoconf.h> header file. */
+#cmakedefine HAVE_LZO_LZOCONF_H 1
+
/* Define to 1 if you have the `mbrtowc' function. */
#cmakedefine HAVE_MBRTOWC 1
@@ -685,6 +709,15 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
#cmakedefine HAVE_NDIR_H 1
+/* Define to 1 if you have the <nettle/md5.h> header file. */
+#cmakedefine HAVE_NETTLE_MD5_H 1
+
+/* Define to 1 if you have the <nettle/ripemd160.h> header file. */
+#cmakedefine HAVE_NETTLE_RIPEMD160_H 1
+
+/* Define to 1 if you have the <nettle/sha.h> header file. */
+#cmakedefine HAVE_NETTLE_SHA_H 1
+
/* Define to 1 if you have the `nl_langinfo' function. */
#cmakedefine HAVE_NL_LANGINFO 1
@@ -694,6 +727,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <paths.h> header file. */
#cmakedefine HAVE_PATHS_H 1
+/* Define to 1 if you have the <pcreposix.h> header file. */
+#cmakedefine HAVE_PCREPOSIX_H 1
+
/* Define to 1 if you have the `pipe' function. */
#cmakedefine HAVE_PIPE 1
@@ -703,6 +739,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <poll.h> header file. */
#cmakedefine HAVE_POLL_H 1
+/* Define to 1 if you have the `posix_spawnp' function. */
+#cmakedefine HAVE_POSIX_SPAWNP 1
+
/* Define to 1 if you have the <process.h> header file. */
#cmakedefine HAVE_PROCESS_H 1
@@ -736,6 +775,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <signal.h> header file. */
#cmakedefine HAVE_SIGNAL_H 1
+/* Define to 1 if you have the <spawn.h> header file. */
+#cmakedefine HAVE_SPAWN_H 1
+
/* Define to 1 if you have the `statfs' function. */
#cmakedefine HAVE_STATFS 1
diff --git a/build/makerelease.sh b/build/makerelease.sh
index a8aa23b026c0..f2869dfca5ed 100755
--- a/build/makerelease.sh
+++ b/build/makerelease.sh
@@ -46,6 +46,7 @@ rm -rf _cmtest
#
# Construct and verify the autoconf build system
#
+export MAKE_LIBARCHIVE_RELEASE="1"
/bin/sh build/autogen.sh
# Get the newest config.guess/config.sub from savannah.gnu.org
diff --git a/build/version b/build/version
index f0f9f2611ac4..937b126a2ede 100644
--- a/build/version
+++ b/build/version
@@ -1 +1 @@
-3000004
+3001002
diff --git a/configure.ac b/configure.ac
index 4993c2595a39..73944d3e0754 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,8 +4,8 @@ dnl First, define all of the version numbers up front.
dnl In particular, this allows the version macro to be used in AC_INIT
dnl These first two version numbers are updated automatically on each release.
-m4_define([LIBARCHIVE_VERSION_S],[3.0.4])
-m4_define([LIBARCHIVE_VERSION_N],[3000004])
+m4_define([LIBARCHIVE_VERSION_S],[3.1.2])
+m4_define([LIBARCHIVE_VERSION_N],[3001002])
dnl bsdtar and bsdcpio versioning tracks libarchive
m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S())
@@ -26,6 +26,7 @@ AC_CONFIG_AUX_DIR([build/autoconf])
AC_CONFIG_MACRO_DIR([build/autoconf])
# Must follow AC_CONFIG macros above...
AM_INIT_AUTOMAKE()
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
# Libtool's "interface version" can be computed from the libarchive version.
@@ -36,8 +37,8 @@ ARCHIVE_MINOR=$(( (LIBARCHIVE_VERSION_N() / 1000) % 1000 ))
# Libarchive 2.8 == libtool interface 10 = 2 + 8
# Libarchive 2.9 == libtool interface 11 = 2 + 8
# Libarchive 3.0 == libtool interface 12
-# Libarchive 3.x == libtool interface 12 + x
-ARCHIVE_INTERFACE=`echo $((12 + ${ARCHIVE_MINOR}))`
+# Libarchive 3.1 == libtool interface 13
+ARCHIVE_INTERFACE=`echo $((13 + ${ARCHIVE_MINOR}))`
# Libarchive revision is bumped on any source change === libtool revision
ARCHIVE_REVISION=$(( LIBARCHIVE_VERSION_N() % 1000 ))
# Libarchive minor is bumped on any interface addition === libtool age
@@ -217,10 +218,10 @@ AS_VAR_IF([ac_cv_have_decl_EXT2_IOC_GETFLAGS], [yes],
AC_CHECK_HEADERS([inttypes.h io.h langinfo.h limits.h])
AC_CHECK_HEADERS([linux/fiemap.h linux/fs.h linux/magic.h linux/types.h])
-AC_CHECK_HEADERS([locale.h paths.h poll.h pwd.h regex.h signal.h stdarg.h])
-AC_CHECK_HEADERS([stdint.h stdlib.h string.h])
-AC_CHECK_HEADERS([sys/acl.h sys/cdefs.h sys/extattr.h sys/ioctl.h])
-AC_CHECK_HEADERS([sys/mkdev.h sys/mount.h])
+AC_CHECK_HEADERS([locale.h paths.h poll.h pwd.h signal.h spawn.h])
+AC_CHECK_HEADERS([stdarg.h stdint.h stdlib.h string.h])
+AC_CHECK_HEADERS([sys/acl.h sys/cdefs.h sys/extattr.h])
+AC_CHECK_HEADERS([sys/ioctl.h sys/mkdev.h sys/mount.h])
AC_CHECK_HEADERS([sys/param.h sys/poll.h sys/select.h sys/statfs.h sys/statvfs.h])
AC_CHECK_HEADERS([sys/time.h sys/utime.h sys/utsname.h sys/vfs.h])
AC_CHECK_HEADERS([time.h unistd.h utime.h wchar.h wctype.h])
@@ -246,7 +247,29 @@ AC_ARG_WITH([bz2lib],
if test "x$with_bz2lib" != "xno"; then
AC_CHECK_HEADERS([bzlib.h])
- AC_CHECK_LIB(bz2,BZ2_bzDecompressInit)
+ case "$host_os" in
+ *mingw* | *cygwin*)
+ dnl AC_CHECK_LIB cannot be used on the Windows port of libbz2, therefore
+ dnl use AC_LINK_IFELSE.
+ AC_MSG_CHECKING([for BZ2_bzDecompressInit in -lbz2])
+ old_LIBS="$LIBS"
+ LIBS="-lbz2 $LIBS"
+ AC_LINK_IFELSE(
+ [AC_LANG_SOURCE(#include <bzlib.h>
+ int main() { return BZ2_bzDecompressInit(NULL, 0, 0); })],
+ [ac_cv_lib_bz2_BZ2_bzDecompressInit=yes],
+ [ac_cv_lib_bz2_BZ2_bzDecompressInit=no])
+ LIBS="$old_LIBS"
+ AC_MSG_RESULT($ac_cv_lib_bz2_BZ2_bzDecompressInit)
+ if test "x$ac_cv_lib_bz2_BZ2_bzDecompressInit" = xyes; then
+ AC_DEFINE([HAVE_LIBBZ2], [1], [Define to 1 if you have the `bz2' library (-lbz2).])
+ LIBS="-lbz2 $LIBS"
+ fi
+ ;;
+ *)
+ AC_CHECK_LIB(bz2,BZ2_bzDecompressInit)
+ ;;
+ esac
fi
AC_ARG_WITH([lzmadec],
@@ -284,6 +307,14 @@ if test "x$with_lzma" != "xno"; then
AC_CHECK_LIB(lzma,lzma_stream_decoder)
fi
+AC_ARG_WITH([lzo2],
+ AS_HELP_STRING([--without-lzo2], [Don't build support for lzop through liblzo2]))
+
+if test "x$with_lzo2" != "xno"; then
+ AC_CHECK_HEADERS([lzo/lzoconf.h lzo/lzo1x.h])
+ AC_CHECK_LIB(lzo2,lzo1x_decompress_safe)
+fi
+
AC_ARG_WITH([nettle],
AS_HELP_STRING([--without-nettle], [Don't build with crypto support from Nettle]))
AC_ARG_WITH([openssl],
@@ -315,12 +346,61 @@ if test "x$ac_cv_header_libxml_xmlreader_h" != "xyes"; then
fi
fi
-AC_ARG_WITH([libregex],
- AS_HELP_STRING([--without-libregex], [Don't build support for regex through libregex]))
-
-if test "x$with_libregex" != "xno"; then
+AC_ARG_ENABLE([posix-regex-lib],
+ [AS_HELP_STRING([--enable-posix-regex-lib],
+ [choose what library to use for POSIX regular expression support (default: auto)])
+ AS_HELP_STRING([--enable-posix-regex-lib=libc], [use libc POSIX regular expression support])
+ AS_HELP_STRING([--enable-posix-regex-lib=libregex], [use libregex POSIX regular expression support])
+ AS_HELP_STRING([--enable-posix-regex-lib=libpcreposix], [use libpcreposix POSIX regular expression support])
+ AS_HELP_STRING([--disable-posix-regex-lib], [don't enable POSIX regular expression support])],
+ [], [enable_posix_regex_lib=auto])
+
+posix_regex_lib_found=
+if test "$enable_posix_regex_lib" = "auto" || test "$enable_posix_regex_lib" = "libc" || test "$enable_posix_regex_lib" = "libregex"; then
+ AC_CHECK_HEADERS([regex.h])
if test "x$ac_cv_header_regex_h" != "xno"; then
- AC_CHECK_FUNC(regcomp, , [AC_CHECK_LIB(regex,regcomp)])
+ AC_CHECK_FUNC(regcomp)
+ if test "x$ac_cv_func_regcomp" = xyes; then
+ posix_regex_lib_found=1
+ else
+ AC_CHECK_LIB(regex,regcomp)
+ if test "x$ac_cv_lib_regex_regcomp" = xyes; then
+ posix_regex_lib_found=1
+ fi
+ fi
+ fi
+fi
+if test -z $posix_regex_lib_found && (test "$enable_posix_regex_lib" = "auto" || test "$enable_posix_regex_lib" = "libpcreposix"); then
+ AC_CHECK_HEADERS([pcreposix.h])
+ AC_CHECK_LIB(pcreposix,regcomp)
+ if test "x$ac_cv_lib_pcreposix_regcomp" != xyes; then
+ AC_MSG_NOTICE(trying libpcreposix check again with libpcre)
+ unset ac_cv_lib_pcreposix_regcomp
+ AC_CHECK_LIB(pcre,pcre_exec)
+ AC_CHECK_LIB(pcreposix,regcomp)
+ if test "x$ac_cv_lib_pcre_pcre_exec" = xyes && test "x$ac_cv_lib_pcreposix_regcomp" = xyes; then
+ AC_MSG_CHECKING(if PCRE_STATIC needs to be defined)
+ AC_LINK_IFELSE(
+ [AC_LANG_SOURCE(#include <pcreposix.h>
+ int main() { return regcomp(NULL, NULL, 0); })],
+ [without_pcre_static=yes],
+ [without_pcre_static=no])
+ AC_LINK_IFELSE(
+ [AC_LANG_SOURCE(#define PCRE_STATIC
+ #include <pcreposix.h>
+ int main() { return regcomp(NULL, NULL, 0); })],
+ [with_pcre_static=yes],
+ [with_pcre_static=no])
+ if test "x$without_pcre_static" != xyes && test "x$with_pcre_static" = xyes; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE([PCRE_STATIC], [1], [Define to 1 if PCRE_STATIC needs to be defined.])
+ elif test "x$without_pcre_static" = xyes || test "x$with_pcre_static" = xyes; then
+ AC_MSG_RESULT(no)
+ fi
+ posix_regex_lib_found=1
+ fi
+ else
+ posix_regex_lib_found=1
fi
fi
@@ -432,7 +512,7 @@ AC_FUNC_VPRINTF
# To avoid necessity for including windows.h or special forward declaration
# workarounds, we use 'void *' for 'struct SECURITY_ATTRIBUTES *'
AC_CHECK_STDCALL_FUNC([CreateHardLinkA],[const char *, const char *, void *])
-AC_CHECK_FUNCS([chflags chown chroot ctime_r])
+AC_CHECK_FUNCS([chflags chown chroot ctime_r dirfd])
AC_CHECK_FUNCS([fchdir fchflags fchmod fchown fcntl fdopendir fork])
AC_CHECK_FUNCS([fstat fstatat fstatfs fstatvfs ftruncate])
AC_CHECK_FUNCS([futimens futimes futimesat])
@@ -441,7 +521,7 @@ AC_CHECK_FUNCS([getpwnam_r getpwuid_r getvfsbyname gmtime_r])
AC_CHECK_FUNCS([lchflags lchmod lchown link localtime_r lstat lutimes])
AC_CHECK_FUNCS([mbrtowc memmove memset])
AC_CHECK_FUNCS([mkdir mkfifo mknod mkstemp])
-AC_CHECK_FUNCS([nl_langinfo openat pipe poll readlink readlinkat])
+AC_CHECK_FUNCS([nl_langinfo openat pipe poll posix_spawnp readlink readlinkat])
AC_CHECK_FUNCS([select setenv setlocale sigaction statfs statvfs])
AC_CHECK_FUNCS([strchr strdup strerror strncpy_s strrchr symlink timegm])
AC_CHECK_FUNCS([tzset unsetenv utime utimensat utimes vfork])
@@ -553,10 +633,8 @@ AC_SYS_LARGEFILE
dnl NOTE: Crypto checks must run last.
AC_DEFUN([CRYPTO_CHECK], [
if test "$found_$1" != yes; then
- saved_LIBS="$LIBS"
saved_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive"
- LIBS="$LIBS $mdLIBS $4"
touch "check_crypto_md.h"
AC_MSG_CHECKING([support for ARCHIVE_CRYPTO_$1_$2])
AC_LINK_IFELSE([AC_LANG_SOURCE([
@@ -578,63 +656,133 @@ main(int argc, char **argv)
])],
[ AC_MSG_RESULT([yes])
found_$1=yes
- if [[ -n "$4" ]]; then
- # The .$4 avoids -e, which doesn't work on Solaris 10
- # The _$mdLIBS allows .$4 to match at beginning of string <sigh>
- test -n "$(echo _$mdLIBS | $GREP .$4)" || mdLIBS="$mdLIBS $4"
- fi
+ found_$2=yes
AC_DEFINE(ARCHIVE_CRYPTO_$1_$2, 1, [ $1 via ARCHIVE_CRYPTO_$1_$2 supported.])
],
[ AC_MSG_RESULT([no])])
- LIBS="$saved_LIBS"
CPPFLAGS="$saved_CPPFLAGS"
rm "check_crypto_md.h"
fi
])
-CRYPTO_CHECK(MD5, LIBC, md5)
-CRYPTO_CHECK(MD5, LIBSYSTEM, md5)
-CRYPTO_CHECK(RMD160, LIBC, rmd160)
-CRYPTO_CHECK(SHA1, LIBC, sha1)
-CRYPTO_CHECK(SHA1, LIBSYSTEM, sha1)
-CRYPTO_CHECK(SHA256, LIBC, sha256)
-CRYPTO_CHECK(SHA256, LIBC2, sha256)
-CRYPTO_CHECK(SHA256, LIBC3, sha256)
-CRYPTO_CHECK(SHA256, LIBSYSTEM, sha256)
-CRYPTO_CHECK(SHA384, LIBC, sha384)
-CRYPTO_CHECK(SHA384, LIBC2, sha384)
-CRYPTO_CHECK(SHA384, LIBC3, sha384)
-CRYPTO_CHECK(SHA384, LIBSYSTEM, sha384)
-CRYPTO_CHECK(SHA512, LIBC, sha512)
-CRYPTO_CHECK(SHA512, LIBC2, sha512)
-CRYPTO_CHECK(SHA512, LIBC3, sha512)
-CRYPTO_CHECK(SHA512, LIBSYSTEM, sha512)
+AC_DEFUN([CRYPTO_CHECK_WIN], [
+ if test "$found_$1" != yes; then
+ AC_MSG_CHECKING([support for ARCHIVE_CRYPTO_$1_WIN])
+ AC_LINK_IFELSE([AC_LANG_SOURCE([
+#define ARCHIVE_$1_COMPILE_TEST
+#include <windows.h>
+#include <wincrypt.h>
+
+int
+main(int argc, char **argv)
+{
+ (void)argc;
+ (void)argv;
+
+ return ($2);
+}
+])],
+ [ AC_MSG_RESULT([yes])
+ found_$1=yes
+ found_WIN=yes
+ AC_DEFINE(ARCHIVE_CRYPTO_$1_WIN, 1, [ $1 via ARCHIVE_CRYPTO_$1_WIN supported.])
+ ],
+ [ AC_MSG_RESULT([no])])
+ fi
+])
+
+case "$host_os" in
+ *mingw* | *cygwin*)
+ ;;
+ *)
+ CRYPTO_CHECK(MD5, LIBC, md5)
+ CRYPTO_CHECK(MD5, LIBSYSTEM, md5)
+ CRYPTO_CHECK(RMD160, LIBC, rmd160)
+ CRYPTO_CHECK(SHA1, LIBC, sha1)
+ CRYPTO_CHECK(SHA1, LIBSYSTEM, sha1)
+ CRYPTO_CHECK(SHA256, LIBC, sha256)
+ CRYPTO_CHECK(SHA256, LIBC2, sha256)
+ CRYPTO_CHECK(SHA256, LIBC3, sha256)
+ CRYPTO_CHECK(SHA256, LIBSYSTEM, sha256)
+ CRYPTO_CHECK(SHA384, LIBC, sha384)
+ CRYPTO_CHECK(SHA384, LIBC2, sha384)
+ CRYPTO_CHECK(SHA384, LIBC3, sha384)
+ CRYPTO_CHECK(SHA384, LIBSYSTEM, sha384)
+ CRYPTO_CHECK(SHA512, LIBC, sha512)
+ CRYPTO_CHECK(SHA512, LIBC2, sha512)
+ CRYPTO_CHECK(SHA512, LIBC3, sha512)
+ CRYPTO_CHECK(SHA512, LIBSYSTEM, sha512)
+ ;;
+esac
if test "x$with_nettle" != "xno"; then
- CRYPTO_CHECK(MD5, NETTLE, md5, -lnettle)
- CRYPTO_CHECK(RMD160, NETTLE, rmd160, -lnettle)
- CRYPTO_CHECK(SHA1, NETTLE, sha1, -lnettle)
- CRYPTO_CHECK(SHA256, NETTLE, sha256, -lnettle)
- CRYPTO_CHECK(SHA384, NETTLE, sha384, -lnettle)
- CRYPTO_CHECK(SHA512, NETTLE, sha512, -lnettle)
+ AC_CHECK_HEADERS([nettle/md5.h nettle/ripemd160.h nettle/sha.h])
+ saved_LIBS=$LIBS
+ AC_CHECK_LIB(nettle,main)
+ CRYPTO_CHECK(MD5, NETTLE, md5)
+ CRYPTO_CHECK(RMD160, NETTLE, rmd160)
+ CRYPTO_CHECK(SHA1, NETTLE, sha1)
+ CRYPTO_CHECK(SHA256, NETTLE, sha256)
+ CRYPTO_CHECK(SHA384, NETTLE, sha384)
+ CRYPTO_CHECK(SHA512, NETTLE, sha512)
+ if test "x$found_NETTLE" != "xyes"; then
+ LIBS=$saved_LIBS
+ fi
fi
if test "x$with_openssl" != "xno"; then
- CRYPTO_CHECK(MD5, OPENSSL, md5, -lcrypto)
- CRYPTO_CHECK(RMD160, OPENSSL, rmd160, -lcrypto)
- CRYPTO_CHECK(SHA1, OPENSSL, sha1, -lcrypto)
- CRYPTO_CHECK(SHA256, OPENSSL, sha256, -lcrypto)
- CRYPTO_CHECK(SHA384, OPENSSL, sha384, -lcrypto)
- CRYPTO_CHECK(SHA512, OPENSSL, sha512, -lcrypto)
+ AC_CHECK_HEADERS([openssl/evp.h])
+ saved_LIBS=$LIBS
+ case "$host_os" in
+ *mingw* | *cygwin*)
+ case "$host_cpu" in
+ x86_64)
+ AC_CHECK_LIB(eay64,main)
+ if test "x$ac_cv_lib_eay64_main" != "xyes"; then
+ AC_CHECK_LIB(eay32,main)
+ fi
+ ;;
+ *)
+ AC_CHECK_LIB(eay32,main)
+ ;;
+ esac
+ ;;
+ *)
+ AC_CHECK_LIB(crypto,main)
+ ;;
+ esac
+ CRYPTO_CHECK(MD5, OPENSSL, md5)
+ CRYPTO_CHECK(RMD160, OPENSSL, rmd160)
+ CRYPTO_CHECK(SHA1, OPENSSL, sha1)
+ CRYPTO_CHECK(SHA256, OPENSSL, sha256)
+ CRYPTO_CHECK(SHA384, OPENSSL, sha384)
+ CRYPTO_CHECK(SHA512, OPENSSL, sha512)
+ if test "x$found_OPENSSL" != "xyes"; then
+ LIBS=$saved_LIBS
+ fi
fi
# Probe libmd AFTER OpenSSL/libcrypto.
# The two are incompatible and OpenSSL is more complete.
-CRYPTO_CHECK(MD5, LIBMD, md5, -lmd)
-CRYPTO_CHECK(RMD160, LIBMD, rmd160, -lmd)
-CRYPTO_CHECK(SHA1, LIBMD, sha1, -lmd)
-CRYPTO_CHECK(SHA256, LIBMD, sha256, -lmd)
-CRYPTO_CHECK(SHA512, LIBMD, sha512, -lmd)
+AC_CHECK_HEADERS([md5.h ripemd.h sha.h sha256.h sha512.h])
+saved_LIBS=$LIBS
+AC_CHECK_LIB(md,main)
+CRYPTO_CHECK(MD5, LIBMD, md5)
+CRYPTO_CHECK(RMD160, LIBMD, rmd160)
+CRYPTO_CHECK(SHA1, LIBMD, sha1)
+CRYPTO_CHECK(SHA256, LIBMD, sha256)
+CRYPTO_CHECK(SHA512, LIBMD, sha512)
+if test "x$found_LIBMD" != "xyes"; then
+ LIBS=$saved_LIBS
+fi
-LIBS="$LIBS $mdLIBS"
+case "$host_os" in
+ *mingw* | *cygwin*)
+ CRYPTO_CHECK_WIN(MD5, CALG_MD5)
+ CRYPTO_CHECK_WIN(SHA1, CALG_SHA1)
+ CRYPTO_CHECK_WIN(SHA256, CALG_SHA_256)
+ CRYPTO_CHECK_WIN(SHA384, CALG_SHA_384)
+ CRYPTO_CHECK_WIN(SHA512, CALG_SHA_512)
+ ;;
+esac
AC_OUTPUT
diff --git a/cpio/bsdcpio.1 b/cpio/bsdcpio.1
index 5611b20e9aea..b3d0d40a21ad 100644
--- a/cpio/bsdcpio.1
+++ b/cpio/bsdcpio.1
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 24, 2011
+.Dd October 7, 2012
.Dt CPIO 1
.Os
.Sh NAME
@@ -176,11 +176,21 @@ With this option, the target of the link will be archived or copied instead.
(p mode only)
Create links from the target directory to the original files,
instead of copying.
+.It Fl Fl lrzip
+(o mode only)
+Compress the resulting archive with
+.Xr lrzip 1 .
+In input mode, this option is ignored.
.It Fl Fl lzma
(o mode only)
Compress the file with lzma-compatible compression before writing it.
In input mode, this option is ignored; lzma compression is recognized
automatically on input.
+.It Fl Fl lzop
+(o mode only)
+Compress the resulting archive with
+.Xr lzop 1 .
+In input mode, this option is ignored.
.It Fl m , Fl Fl preserve-modification-time
(i and p modes)
Set file modification time on created files to match
diff --git a/cpio/cmdline.c b/cpio/cmdline.c
index 438c27cf6a77..0121fd13937f 100644
--- a/cpio/cmdline.c
+++ b/cpio/cmdline.c
@@ -61,16 +61,20 @@ static const struct option {
int required; /* 1 if this option requires an argument */
int equivalent; /* Equivalent short option. */
} cpio_longopts[] = {
+ { "b64encode", 0, OPTION_B64ENCODE },
{ "create", 0, 'o' },
{ "dot", 0, 'V' },
{ "extract", 0, 'i' },
{ "file", 1, 'F' },
{ "format", 1, 'H' },
+ { "grzip", 0, OPTION_GRZIP },
{ "help", 0, 'h' },
{ "insecure", 0, OPTION_INSECURE },
{ "link", 0, 'l' },
{ "list", 0, 't' },
+ { "lrzip", 0, OPTION_LRZIP },
{ "lzma", 0, OPTION_LZMA },
+ { "lzop", 0, OPTION_LZOP },
{ "make-directories", 0, 'd' },
{ "no-preserve-owner", 0, OPTION_NO_PRESERVE_OWNER },
{ "null", 0, '0' },
@@ -81,6 +85,7 @@ static const struct option {
{ "preserve-owner", 0, OPTION_PRESERVE_OWNER },
{ "quiet", 0, OPTION_QUIET },
{ "unconditional", 0, 'u' },
+ { "uuencode", 0, OPTION_UUENCODE },
{ "verbose", 0, 'v' },
{ "version", 0, OPTION_VERSION },
{ "xz", 0, 'J' },
diff --git a/cpio/cpio.c b/cpio/cpio.c
index 7095b6207e4f..6f57d95d616e 100644
--- a/cpio/cpio.c
+++ b/cpio/cpio.c
@@ -207,6 +207,9 @@ main(int argc, char *argv[])
case 'B': /* POSIX 1997 */
cpio->bytes_per_block = 5120;
break;
+ case OPTION_B64ENCODE:
+ cpio->add_filter = opt;
+ break;
case 'C': /* NetBSD/OpenBSD */
cpio->bytes_per_block = atoi(cpio->argument);
if (cpio->bytes_per_block <= 0)
@@ -234,6 +237,9 @@ main(int argc, char *argv[])
lafe_errc(1, 0, "Error : %s",
archive_error_string(cpio->matching));
break;
+ case OPTION_GRZIP:
+ cpio->compress = opt;
+ break;
case 'H': /* GNU cpio (also --format) */
cpio->format = cpio->argument;
break;
@@ -265,7 +271,9 @@ main(int argc, char *argv[])
case 'l': /* POSIX 1997 */
cpio->option_link = 1;
break;
+ case OPTION_LRZIP:
case OPTION_LZMA: /* GNU tar, others */
+ case OPTION_LZOP: /* GNU tar, others */
cpio->compress = opt;
break;
case 'm': /* POSIX 1997 */
@@ -326,6 +334,9 @@ main(int argc, char *argv[])
cpio->extract_flags
&= ~ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER;
break;
+ case OPTION_UUENCODE:
+ cpio->add_filter = opt;
+ break;
case 'v': /* POSIX 1997 */
cpio->verbose++;
break;
@@ -417,6 +428,7 @@ main(int argc, char *argv[])
archive_match_free(cpio->matching);
free_cache(cpio->gname_cache);
free_cache(cpio->uname_cache);
+ free(cpio->destdir);
return (cpio->return_value);
}
@@ -516,27 +528,49 @@ mode_out(struct cpio *cpio)
if (cpio->archive == NULL)
lafe_errc(1, 0, "Failed to allocate archive object");
switch (cpio->compress) {
+ case OPTION_GRZIP:
+ r = archive_write_add_filter_grzip(cpio->archive);
+ break;
case 'J':
- r = archive_write_set_compression_xz(cpio->archive);
+ r = archive_write_add_filter_xz(cpio->archive);
+ break;
+ case OPTION_LRZIP:
+ r = archive_write_add_filter_lrzip(cpio->archive);
break;
case OPTION_LZMA:
- r = archive_write_set_compression_lzma(cpio->archive);
+ r = archive_write_add_filter_lzma(cpio->archive);
+ break;
+ case OPTION_LZOP:
+ r = archive_write_add_filter_lzop(cpio->archive);
break;
case 'j': case 'y':
- r = archive_write_set_compression_bzip2(cpio->archive);
+ r = archive_write_add_filter_bzip2(cpio->archive);
break;
case 'z':
- r = archive_write_set_compression_gzip(cpio->archive);
+ r = archive_write_add_filter_gzip(cpio->archive);
break;
case 'Z':
- r = archive_write_set_compression_compress(cpio->archive);
+ r = archive_write_add_filter_compress(cpio->archive);
break;
default:
- r = archive_write_set_compression_none(cpio->archive);
+ r = archive_write_add_filter_none(cpio->archive);
break;
}
if (r < ARCHIVE_WARN)
lafe_errc(1, 0, "Requested compression not available");
+ switch (cpio->add_filter) {
+ case 0:
+ r = ARCHIVE_OK;
+ break;
+ case OPTION_B64ENCODE:
+ r = archive_write_add_filter_b64encode(cpio->archive);
+ break;
+ case OPTION_UUENCODE:
+ r = archive_write_add_filter_uuencode(cpio->archive);
+ break;
+ }
+ if (r < ARCHIVE_WARN)
+ lafe_errc(1, 0, "Requested filter not available");
r = archive_write_set_format_by_name(cpio->archive, cpio->format);
if (r != ARCHIVE_OK)
lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
@@ -548,7 +582,7 @@ mode_out(struct cpio *cpio)
/*
* The main loop: Copy each file into the output archive.
*/
- r = archive_write_open_file(cpio->archive, cpio->filename);
+ r = archive_write_open_filename(cpio->archive, cpio->filename);
if (r != ARCHIVE_OK)
lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
lr = lafe_line_reader("-", cpio->option_null);
@@ -577,7 +611,7 @@ mode_out(struct cpio *cpio)
if (!cpio->quiet) {
int64_t blocks =
- (archive_position_uncompressed(cpio->archive) + 511)
+ (archive_filter_bytes(cpio->archive, 0) + 511)
/ 512;
fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
blocks == 1 ? "block" : "blocks");
@@ -806,18 +840,21 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
exit(1);
if (r >= ARCHIVE_WARN && archive_entry_size(entry) > 0 && fd >= 0) {
- bytes_read = read(fd, cpio->buff, cpio->buff_size);
+ bytes_read = read(fd, cpio->buff, (unsigned)cpio->buff_size);
while (bytes_read > 0) {
- r = archive_write_data(cpio->archive,
+ ssize_t bytes_write;
+ bytes_write = archive_write_data(cpio->archive,
cpio->buff, bytes_read);
- if (r < 0)
+ if (bytes_write < 0)
lafe_errc(1, archive_errno(cpio->archive),
"%s", archive_error_string(cpio->archive));
- if (r < bytes_read) {
+ if (bytes_write < bytes_read) {
lafe_warnc(0,
- "Truncated write; file may have grown while being archived.");
+ "Truncated write; file may have "
+ "grown while being archived.");
}
- bytes_read = read(fd, cpio->buff, cpio->buff_size);
+ bytes_read = read(fd, cpio->buff,
+ (unsigned)cpio->buff_size);
}
}
@@ -908,7 +945,8 @@ mode_in(struct cpio *cpio)
archive_read_support_filter_all(a);
archive_read_support_format_all(a);
- if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block))
+ if (archive_read_open_filename(a, cpio->filename,
+ cpio->bytes_per_block))
lafe_errc(1, archive_errno(a),
"%s", archive_error_string(a));
for (;;) {
@@ -957,7 +995,7 @@ mode_in(struct cpio *cpio)
if (r != ARCHIVE_OK)
lafe_errc(1, 0, "%s", archive_error_string(ext));
if (!cpio->quiet) {
- int64_t blocks = (archive_position_uncompressed(a) + 511)
+ int64_t blocks = (archive_filter_bytes(a, 0) + 511)
/ 512;
fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
blocks == 1 ? "block" : "blocks");
@@ -988,7 +1026,7 @@ extract_data(struct archive *ar, struct archive *aw)
"%s", archive_error_string(ar));
exit(1);
}
- r = archive_write_data_block(aw, block, size, offset);
+ r = (int)archive_write_data_block(aw, block, size, offset);
if (r != ARCHIVE_OK) {
lafe_warnc(archive_errno(aw),
"%s", archive_error_string(aw));
@@ -1010,7 +1048,8 @@ mode_list(struct cpio *cpio)
archive_read_support_filter_all(a);
archive_read_support_format_all(a);
- if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block))
+ if (archive_read_open_filename(a, cpio->filename,
+ cpio->bytes_per_block))
lafe_errc(1, archive_errno(a),
"%s", archive_error_string(a));
for (;;) {
@@ -1032,7 +1071,7 @@ mode_list(struct cpio *cpio)
if (r != ARCHIVE_OK)
lafe_errc(1, 0, "%s", archive_error_string(a));
if (!cpio->quiet) {
- int64_t blocks = (archive_position_uncompressed(a) + 511)
+ int64_t blocks = (archive_filter_bytes(a, 0) + 511)
/ 512;
fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
blocks == 1 ? "block" : "blocks");
@@ -1167,7 +1206,7 @@ mode_pass(struct cpio *cpio, const char *destdir)
if (!cpio->quiet) {
int64_t blocks =
- (archive_position_uncompressed(cpio->archive) + 511)
+ (archive_filter_bytes(cpio->archive, 0) + 511)
/ 512;
fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
blocks == 1 ? "block" : "blocks");
diff --git a/cpio/cpio.h b/cpio/cpio.h
index 7e276bdbaf79..3e951ce7403e 100644
--- a/cpio/cpio.h
+++ b/cpio/cpio.h
@@ -44,6 +44,7 @@ struct cpio {
const char *argument;
/* Options */
+ int add_filter; /* --uuencode */
const char *filename;
int mode; /* -i -o -p */
int compress; /* -j, -y, or -z */
@@ -96,11 +97,16 @@ const char *owner_parse(const char *, int *, int *);
/* Fake short equivalents for long options that otherwise lack them. */
enum {
- OPTION_INSECURE = 1,
+ OPTION_B64ENCODE = 1,
+ OPTION_GRZIP,
+ OPTION_INSECURE,
+ OPTION_LRZIP,
OPTION_LZMA,
+ OPTION_LZOP,
OPTION_NO_PRESERVE_OWNER,
OPTION_PRESERVE_OWNER,
OPTION_QUIET,
+ OPTION_UUENCODE,
OPTION_VERSION
};
diff --git a/cpio/test/CMakeLists.txt b/cpio/test/CMakeLists.txt
index a06ae0496ec4..09ca2c7d96b3 100644
--- a/cpio/test/CMakeLists.txt
+++ b/cpio/test/CMakeLists.txt
@@ -7,11 +7,21 @@ IF(ENABLE_CPIO AND ENABLE_TEST)
SET(bsdcpio_test_SOURCES
../cmdline.c
../../libarchive_fe/err.c
+ ../../test_utils/test_utils.c
main.c
test.h
test_0.c
test_basic.c
test_cmdline.c
+ test_extract_cpio_Z
+ test_extract_cpio_bz2
+ test_extract_cpio_grz
+ test_extract_cpio_gz
+ test_extract_cpio_lrz
+ test_extract_cpio_lz
+ test_extract_cpio_lzma
+ test_extract_cpio_lzo
+ test_extract_cpio_xz
test_format_newc.c
test_gcpio_compat.c
test_option_0.c
@@ -21,16 +31,22 @@ IF(ENABLE_CPIO AND ENABLE_TEST)
test_option_L_upper.c
test_option_Z_upper.c
test_option_a.c
+ test_option_b64encode.c
test_option_c.c
test_option_d.c
test_option_f.c
+ test_option_grzip.c
test_option_help.c
test_option_l.c
+ test_option_lrzip.c
test_option_lzma.c
+ test_option_lzop.c
test_option_m.c
test_option_t.c
test_option_u.c
+ test_option_uuencode.c
test_option_version.c
+ test_option_xz.c
test_option_y.c
test_option_z.c
test_owner_parse.c
@@ -65,6 +81,8 @@ IF(ENABLE_CPIO AND ENABLE_TEST)
ENDMACRO (DEFINE_TEST _testname)
INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h)
+ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/test_utils)
# Experimental new test handling
ADD_CUSTOM_TARGET(run_bsdcpio_test
diff --git a/cpio/test/main.c b/cpio/test/main.c
index e190123d5c83..d4c6e5c3388c 100644
--- a/cpio/test/main.c
+++ b/cpio/test/main.c
@@ -24,6 +24,7 @@
*/
#include "test.h"
+#include "test_utils.h"
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
@@ -91,6 +92,7 @@ __FBSDID("$FreeBSD: src/usr.bin/cpio/test/main.c,v 1.3 2008/08/24 04:58:22 kient
*/
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <io.h>
+#include <direct.h>
#include <windows.h>
#ifndef F_OK
#define F_OK (0)
@@ -389,7 +391,6 @@ failure_finish(void *extra)
fprintf(stderr,
" *** forcing core dump so failure can be debugged ***\n");
abort();
- exit(1);
}
}
@@ -622,8 +623,8 @@ assertion_equal_string(const char *file, int line,
if (v1 == v2 || (v1 != NULL && v2 != NULL && strcmp(v1, v2) == 0))
return (1);
failure_start(file, line, "%s != %s", e1, e2);
- l1 = strlen(e1);
- l2 = strlen(e2);
+ l1 = (int)strlen(e1);
+ l2 = (int)strlen(e2);
if (l1 < l2)
l1 = l2;
strdump(e1, v1, l1, utf8);
@@ -746,6 +747,8 @@ assertion_equal_mem(const char *file, int line,
assertion_count(file, line);
if (v1 == v2 || (v1 != NULL && v2 != NULL && memcmp(v1, v2, l) == 0))
return (1);
+ if (v1 == NULL || v2 == NULL)
+ return (0);
failure_start(file, line, "%s != %s", e1, e2);
logprintf(" size %s = %d\n", ld, (int)l);
@@ -839,9 +842,14 @@ assertion_equal_file(const char *filename, int line, const char *fn1, const char
f1 = fopen(fn1, "rb");
f2 = fopen(fn2, "rb");
+ if (f1 == NULL || f2 == NULL) {
+ if (f1) fclose(f1);
+ if (f2) fclose(f2);
+ return (0);
+ }
for (;;) {
- n1 = fread(buff1, 1, sizeof(buff1), f1);
- n2 = fread(buff2, 1, sizeof(buff2), f2);
+ n1 = (int)fread(buff1, 1, sizeof(buff1), f1);
+ n2 = (int)fread(buff2, 1, sizeof(buff2), f2);
if (n1 != n2)
break;
if (n1 == 0 && n2 == 0) {
@@ -915,7 +923,7 @@ assertion_file_contents(const char *filename, int line, const void *buff, int s,
return (0);
}
contents = malloc(s * 2);
- n = fread(contents, 1, s * 2, f);
+ n = (int)fread(contents, 1, s * 2, f);
fclose(f);
if (n == s && memcmp(buff, contents, s) == 0) {
free(contents);
@@ -951,9 +959,9 @@ assertion_text_file_contents(const char *filename, int line, const char *buff, c
failure_finish(NULL);
return (0);
}
- s = strlen(buff);
+ s = (int)strlen(buff);
contents = malloc(s * 2 + 128);
- n = fread(contents, 1, s * 2 + 128 - 1, f);
+ n = (int)fread(contents, 1, s * 2 + 128 - 1, f);
if (n >= 0)
contents[n] = '\0';
fclose(f);
@@ -1004,8 +1012,8 @@ assertion_file_contains_lines_any_order(const char *file, int line,
char *buff;
size_t buff_size;
size_t expected_count, actual_count, i, j;
- char **expected;
- char *p, **actual;
+ char **expected = NULL;
+ char *p, **actual = NULL;
char c;
int expected_failure = 0, actual_failure = 0;
@@ -1018,14 +1026,21 @@ assertion_file_contains_lines_any_order(const char *file, int line,
return (0);
}
- /* Make a copy of the provided lines and count up the expected file size. */
- expected_count = 0;
+ /* Make a copy of the provided lines and count up the expected
+ * file size. */
for (i = 0; lines[i] != NULL; ++i) {
}
expected_count = i;
- expected = malloc(sizeof(char *) * expected_count);
- for (i = 0; lines[i] != NULL; ++i) {
- expected[i] = strdup(lines[i]);
+ if (expected_count) {
+ expected = malloc(sizeof(char *) * expected_count);
+ if (expected == NULL) {
+ failure_start(pathname, line, "Can't allocate memory");
+ failure_finish(NULL);
+ return (0);
+ }
+ for (i = 0; lines[i] != NULL; ++i) {
+ expected[i] = strdup(lines[i]);
+ }
}
/* Break the file into lines */
@@ -1037,11 +1052,19 @@ assertion_file_contains_lines_any_order(const char *file, int line,
++actual_count;
c = *p;
}
- actual = malloc(sizeof(char *) * actual_count);
- for (j = 0, p = buff; p < buff + buff_size; p += 1 + strlen(p)) {
- if (*p != '\0') {
- actual[j] = p;
- ++j;
+ if (actual_count) {
+ actual = calloc(sizeof(char *), actual_count);
+ if (actual == NULL) {
+ failure_start(pathname, line, "Can't allocate memory");
+ failure_finish(NULL);
+ free(expected);
+ return (0);
+ }
+ for (j = 0, p = buff; p < buff + buff_size; p += 1 + strlen(p)) {
+ if (*p != '\0') {
+ actual[j] = p;
+ ++j;
+ }
}
}
@@ -1176,11 +1199,11 @@ assertion_file_time(const char *file, int line,
#if defined(_WIN32) && !defined(__CYGWIN__)
#define EPOC_TIME (116444736000000000ULL)
- FILETIME ftime, fbirthtime, fatime, fmtime;
+ FILETIME fxtime, fbirthtime, fatime, fmtime;
ULARGE_INTEGER wintm;
HANDLE h;
- ftime.dwLowDateTime = 0;
- ftime.dwHighDateTime = 0;
+ fxtime.dwLowDateTime = 0;
+ fxtime.dwHighDateTime = 0;
assertion_count(file, line);
/* Note: FILE_FLAG_BACKUP_SEMANTICS applies to open
@@ -1195,9 +1218,9 @@ assertion_file_time(const char *file, int line,
}
r = GetFileTime(h, &fbirthtime, &fatime, &fmtime);
switch (type) {
- case 'a': ftime = fatime; break;
- case 'b': ftime = fbirthtime; break;
- case 'm': ftime = fmtime; break;
+ case 'a': fxtime = fatime; break;
+ case 'b': fxtime = fbirthtime; break;
+ case 'm': fxtime = fmtime; break;
}
CloseHandle(h);
if (r == 0) {
@@ -1205,8 +1228,8 @@ assertion_file_time(const char *file, int line,
failure_finish(NULL);
return (0);
}
- wintm.LowPart = ftime.dwLowDateTime;
- wintm.HighPart = ftime.dwHighDateTime;
+ wintm.LowPart = fxtime.dwLowDateTime;
+ wintm.HighPart = fxtime.dwHighDateTime;
filet = (wintm.QuadPart - EPOC_TIME) / 10000000;
filet_nsec = ((wintm.QuadPart - EPOC_TIME) % 10000000) * 100;
nsec = (nsec / 100) * 100; /* Round the request */
@@ -1834,15 +1857,45 @@ canSymlink(void)
return (value);
}
-/*
- * Can this platform run the gzip program?
- */
/* Platform-dependent options for hiding the output of a subcommand. */
#if defined(_WIN32) && !defined(__CYGWIN__)
static const char *redirectArgs = ">NUL 2>NUL"; /* Win32 cmd.exe */
#else
static const char *redirectArgs = ">/dev/null 2>/dev/null"; /* POSIX 'sh' */
#endif
+/*
+ * Can this platform run the bzip2 program?
+ */
+int
+canBzip2(void)
+{
+ static int tested = 0, value = 0;
+ if (!tested) {
+ tested = 1;
+ if (systemf("bzip2 -d -V %s", redirectArgs) == 0)
+ value = 1;
+ }
+ return (value);
+}
+
+/*
+ * Can this platform run the grzip program?
+ */
+int
+canGrzip(void)
+{
+ static int tested = 0, value = 0;
+ if (!tested) {
+ tested = 1;
+ if (systemf("grzip -V %s", redirectArgs) == 0)
+ value = 1;
+ }
+ return (value);
+}
+
+/*
+ * Can this platform run the gzip program?
+ */
int
canGzip(void)
{
@@ -1856,15 +1909,75 @@ canGzip(void)
}
/*
- * Can this platform run the gunzip program?
+ * Can this platform run the lrzip program?
+ */
+int
+canLrzip(void)
+{
+ static int tested = 0, value = 0;
+ if (!tested) {
+ tested = 1;
+ if (systemf("lrzip -V %s", redirectArgs) == 0)
+ value = 1;
+ }
+ return (value);
+}
+
+/*
+ * Can this platform run the lzip program?
+ */
+int
+canLzip(void)
+{
+ static int tested = 0, value = 0;
+ if (!tested) {
+ tested = 1;
+ if (systemf("lzip -V %s", redirectArgs) == 0)
+ value = 1;
+ }
+ return (value);
+}
+
+/*
+ * Can this platform run the lzma program?
*/
int
-canGunzip(void)
+canLzma(void)
{
static int tested = 0, value = 0;
if (!tested) {
tested = 1;
- if (systemf("gunzip -V %s", redirectArgs) == 0)
+ if (systemf("lzma -V %s", redirectArgs) == 0)
+ value = 1;
+ }
+ return (value);
+}
+
+/*
+ * Can this platform run the lzop program?
+ */
+int
+canLzop(void)
+{
+ static int tested = 0, value = 0;
+ if (!tested) {
+ tested = 1;
+ if (systemf("lzop -V %s", redirectArgs) == 0)
+ value = 1;
+ }
+ return (value);
+}
+
+/*
+ * Can this platform run the xz program?
+ */
+int
+canXz(void)
+{
+ static int tested = 0, value = 0;
+ if (!tested) {
+ tested = 1;
+ if (systemf("xz -V %s", redirectArgs) == 0)
value = 1;
}
return (value);
@@ -2124,7 +2237,7 @@ is_LargeInode(const char *file)
/* Use "list.h" to create a list of all tests (functions and names). */
#undef DEFINE_TEST
#define DEFINE_TEST(n) { n, #n, 0 },
-struct { void (*func)(void); const char *name; int failures; } tests[] = {
+struct test_list_t tests[] = {
#include "list.h"
};
@@ -2377,65 +2490,6 @@ success:
return strdup(buff);
}
-static int
-get_test_set(int *test_set, int limit, const char *test)
-{
- int start, end;
- int idx = 0;
-
- if (test == NULL) {
- /* Default: Run all tests. */
- for (;idx < limit; idx++)
- test_set[idx] = idx;
- return (limit);
- }
- if (*test >= '0' && *test <= '9') {
- const char *vp = test;
- start = 0;
- while (*vp >= '0' && *vp <= '9') {
- start *= 10;
- start += *vp - '0';
- ++vp;
- }
- if (*vp == '\0') {
- end = start;
- } else if (*vp == '-') {
- ++vp;
- if (*vp == '\0') {
- end = limit - 1;
- } else {
- end = 0;
- while (*vp >= '0' && *vp <= '9') {
- end *= 10;
- end += *vp - '0';
- ++vp;
- }
- }
- } else
- return (-1);
- if (start < 0 || end >= limit || start > end)
- return (-1);
- while (start <= end)
- test_set[idx++] = start++;
- } else {
- size_t len = strlen(test);
- for (start = 0; start < limit; ++start) {
- const char *name = tests[start].name;
- const char *p;
-
- while ((p = strchr(name, test[0])) != NULL) {
- if (strncmp(p, test, len) == 0) {
- test_set[idx++] = start;
- break;
- } else
- name = p + 1;
- }
-
- }
- }
- return ((idx == 0)?-1:idx);
-}
-
int
main(int argc, char **argv)
{
@@ -2720,10 +2774,11 @@ main(int argc, char **argv)
do {
int test_num;
- test_num = get_test_set(test_set, limit, *argv);
+ test_num = get_test_set(test_set, limit, *argv, tests);
if (test_num < 0) {
printf("*** INVALID Test %s\n", *argv);
free(refdir_alloc);
+ free(testprogdir);
usage(progname);
return (1);
}
diff --git a/cpio/test/test.h b/cpio/test/test.h
index d57a861dcb0b..666bba0e8b30 100644
--- a/cpio/test/test.h
+++ b/cpio/test/test.h
@@ -266,11 +266,29 @@ void sleepUntilAfter(time_t);
/* Return true if this platform can create symlinks. */
int canSymlink(void);
+/* Return true if this platform can run the "bzip2" program. */
+int canBzip2(void);
+
+/* Return true if this platform can run the "grzip" program. */
+int canGrzip(void);
+
/* Return true if this platform can run the "gzip" program. */
int canGzip(void);
-/* Return true if this platform can run the "gunzip" program. */
-int canGunzip(void);
+/* Return true if this platform can run the "lrzip" program. */
+int canLrzip(void);
+
+/* Return true if this platform can run the "lzip" program. */
+int canLzip(void);
+
+/* Return true if this platform can run the "lzma" program. */
+int canLzma(void);
+
+/* Return true if this platform can run the "lzop" program. */
+int canLzop(void);
+
+/* Return true if this platform can run the "xz" program. */
+int canXz(void);
/* Return true if this filesystem can handle nodump flags. */
int canNodump(void);
diff --git a/cpio/test/test_basic.c b/cpio/test/test_basic.c
index c40813e9a26f..7213062e8d20 100644
--- a/cpio/test/test_basic.c
+++ b/cpio/test/test_basic.c
@@ -148,7 +148,7 @@ DEFINE_TEST(test_basic)
strncat(result,
"bsdcpio: file: large inode number truncated: "
"Numerical result out of range\n",
- sizeof(result) - strlen(result));
+ sizeof(result) - strlen(result) -1);
/* hardlink to above file. */
assertMakeHardlink("linkfile", "file");
@@ -157,7 +157,7 @@ DEFINE_TEST(test_basic)
strncat(result,
"bsdcpio: linkfile: large inode number truncated: "
"Numerical result out of range\n",
- sizeof(result) - strlen(result));
+ sizeof(result) - strlen(result) -1);
/* Symlink to above file. */
if (canSymlink()) {
@@ -167,7 +167,7 @@ DEFINE_TEST(test_basic)
strncat(result,
"bsdcpio: symlink: large inode number truncated: "
"Numerical result out of range\n",
- sizeof(result) - strlen(result));
+ sizeof(result) - strlen(result) -1);
}
/* Another file with different permissions. */
@@ -177,7 +177,7 @@ DEFINE_TEST(test_basic)
strncat(result,
"bsdcpio: file2: large inode number truncated: "
"Numerical result out of range\n",
- sizeof(result) - strlen(result));
+ sizeof(result) - strlen(result) -1);
/* Directory. */
assertMakeDir("dir", 0775);
@@ -186,8 +186,8 @@ DEFINE_TEST(test_basic)
strncat(result,
"bsdcpio: dir: large inode number truncated: "
"Numerical result out of range\n",
- sizeof(result) - strlen(result));
- strncat(result, "2 blocks\n", sizeof(result) - strlen(result));
+ sizeof(result) - strlen(result) -1);
+ strncat(result, "2 blocks\n", sizeof(result) - strlen(result) -1);
/* All done. */
fclose(filelist);
diff --git a/cpio/test/test_extract.cpio.Z.uu b/cpio/test/test_extract.cpio.Z.uu
new file mode 100644
index 000000000000..e520a341628f
--- /dev/null
+++ b/cpio/test/test_extract.cpio.Z.uu
@@ -0,0 +1,7 @@
+begin 664 test_extract.cpio.Z
+M'YV0,&X$'`B#!@P8,0XJC)$0A@T;!A'>J+%PHL*%%P_&D`%CAHP;!F7,B*C0
+M1L:+(LVD85,F!H`Q;]S0*2-S#H@W9D"H9!G#A8*!`@46U)A11L.'$6-8U+CT
+M8D.G'#V"A"&#!L6+)D\>3+FRC(R7,6?6O)ESIU>?0`EJ7<N6[=.V:V/,@$M%
+A2I`D3(I("<$7@-^_@`,+'DRXL.'#B!,K7LRXL>/'D!4#
+`
+end
diff --git a/cpio/test/test_extract.cpio.bz2.uu b/cpio/test/test_extract.cpio.bz2.uu
new file mode 100644
index 000000000000..228a95775b88
--- /dev/null
+++ b/cpio/test/test_extract.cpio.bz2.uu
@@ -0,0 +1,7 @@
+begin 664 test_extract.cpio.bz2
+M0EIH.3%!629365?=.4@``#G_@G*0(`#@`7^`(B04``LEC```!"``E`E(>I,H
+M::'J&@_4C3:@E$AD#0&@&@%"E;V/1!XIP>#C9T[41`4PQ1A`@S*4F&BD@B0T
+MBA$$-:\/@BQGNKU1G@%#`G+N0R%$JTHG(XBRB%1$V8F4#F_IWT=S4+ERVL(?
+40V!'@1L4+AO_B[DBG"A(*^Z<I```
+`
+end
diff --git a/cpio/test/test_extract.cpio.grz.uu b/cpio/test/test_extract.cpio.grz.uu
new file mode 100644
index 000000000000..19045a9ddeee
--- /dev/null
+++ b/cpio/test/test_extract.cpio.grz.uu
@@ -0,0 +1,7 @@
+begin 644 test_extract.cpio.grz
+M1U)::7!)20`"!#HI``(``*P-```&`0``"````&X````B%2.02C`PK`#__..F
+MI;8=99?N!6`:IQJ:XU/T"`W`B"?N/D9-0K6VN/D\.2>0,#J&)3G"\^YE?X_'
+M_K._F':0[`DL%IQ=<,Z-JH>V$S,?.[`&42C7]J^XQ@9OY!Z$!$^JLQPKZU[:
+/!M,+.$MY:Y(HS<<]U`&`
+`
+end
diff --git a/cpio/test/test_extract.cpio.gz.uu b/cpio/test/test_extract.cpio.gz.uu
new file mode 100644
index 000000000000..7ddccad64e5c
--- /dev/null
+++ b/cpio/test/test_extract.cpio.gz.uu
@@ -0,0 +1,7 @@
+begin 664 test_extract.cpio.gz
+M'XL("`5X<E```W1E<W1?97AT<F%C="YC<&EO`#,P-P!!`Q,#`T,#$#`$4F9F
+M(*ZYJ0&,-(#)&A@:&1@;F9L8&!F;@/EF!C!@9)R6F9-JR)"<GU>2FE=2K)"?
+MI@`6T>,R0+?$B$A+3$RQ6F*$88D1PA*"P!"[J#$2)R3(T=/'-4A149%AF`,`
+(305ZBP`"````
+`
+end
diff --git a/cpio/test/test_extract.cpio.lrz.uu b/cpio/test/test_extract.cpio.lrz.uu
new file mode 100644
index 000000000000..563f7971040c
--- /dev/null
+++ b/cpio/test/test_extract.cpio.lrz.uu
@@ -0,0 +1,8 @@
+begin 664 test_extract.cpio.lrz
+M3%):20`&``(``````````%T````!`0```@$`$`,`````#@`#`````"\``QH`
+M&@````!W``$G`&4``#,``2(``0``#0$````U<-`Y!F$`MP$````8#=\$8#<1
+MR/BL39$D4M>["H7&@4%L/4*_(*VGB*YU>?RX.9]HL86'.A)H@Y;Z\^$?M^8_
+M!/-;62G.*7*A&A!_ENZ8$7]O-M7_.FTRC%BCGC95:6'9ZH3)QSCR4RX42P!`
+/-E>/7"L[:OY"/A924S4$
+`
+end
diff --git a/cpio/test/test_extract.cpio.lz.uu b/cpio/test/test_extract.cpio.lz.uu
new file mode 100644
index 000000000000..67e41e92f16c
--- /dev/null
+++ b/cpio/test/test_extract.cpio.lz.uu
@@ -0,0 +1,6 @@
+begin 664 test_extract.cpio.lz
+M3%I)4`$,`!@-WP1@-Q'(^*Q-D212U[L*A<:!06P]0K\@K:>(KG5Y_+@YGVBQ
+MA8<Z$FB#EOKSX1^WYC\$\UM9*<XI<J$:$'^B>;_>8N3MLP="$0SJ#QKYB?@8
+G]@'$$7\&W^T*+9?6B=?__M$G@$T%>HL``@```````($`````````
+`
+end
diff --git a/cpio/test/test_extract.cpio.lzma.uu b/cpio/test/test_extract.cpio.lzma.uu
new file mode 100644
index 000000000000..449403e9293b
--- /dev/null
+++ b/cpio/test/test_extract.cpio.lzma.uu
@@ -0,0 +1,6 @@
+begin 664 test_extract.cpio.lzma
+M70``@`#__________P`8#=\$8#<1R/BL39$D4M>["H7&@4%L/4*_(*VGB*YU
+M>?RX.9]HL86'.A)H@Y;Z\^$?M^8_!/-;62G.*7*A&A!_HGF_WF+D[;.+!OW3
+:T_2I)V(;K[FNL#'W%T+L;ATS`A*3__[1Z```
+`
+end
diff --git a/cpio/test/test_extract.cpio.lzo.uu b/cpio/test/test_extract.cpio.lzo.uu
new file mode 100644
index 000000000000..8ce87c798ce2
--- /dev/null
+++ b/cpio/test/test_extract.cpio.lzo.uu
@@ -0,0 +1,9 @@
+begin 664 test_extract.cpio.lzo
+MB4Q:3P`-"AH*$#`@8`E``04#```!``"!M%!R>-T`````$71E<W1?97AT<F%C
+M="YC<&EOOH$+9````@````"DIR,^[`HP-S`W,#<P,#0P,#$P8``#,3$P,#8V
+M>`$#-S4P,#`QE`!@`7`#"C`P,3(P,S(W-#`R,S2!`C:4`'````(R,V9I;&4Q
+M`&-O;G1E;G1S(&]F((8"+@HOD0$R(`:1`31J$#`P+I$!,B^1`3(HD`%L$3L,
+M`+P<+HH`,3,I1``(5%)!24Q%4B$A(0`@JP````$`````````````````````
+*````$0``````````
+`
+end
diff --git a/cpio/test/test_extract.cpio.xz.uu b/cpio/test/test_extract.cpio.xz.uu
new file mode 100644
index 000000000000..5c593cfebca2
--- /dev/null
+++ b/cpio/test/test_extract.cpio.xz.uu
@@ -0,0 +1,7 @@
+begin 664 test_extract.cpio.xz
+M_3=Z6%H```3FUK1&`@`A`18```!T+^6CX`'_`&%=`!@-WP1@-Q'(^*Q-D212
+MU[L*A<:!06P]0K\@K:>(KG5Y_+@YGVBQA8<Z$FB#EOKSX1^WYC\$\UM9*<XI
+M<J$:$'^B>;_>8N3MLXL&_=/3]*DG8ANON:ZP,?<70NQN'3"CP@``````J9FA
+=#1$]4L<``7V`!`````?M;4JQQ&?[`@`````$65H`
+`
+end
diff --git a/cpio/test/test_extract_cpio_Z.c b/cpio/test/test_extract_cpio_Z.c
new file mode 100644
index 000000000000..f908fc5b84f5
--- /dev/null
+++ b/cpio/test/test_extract_cpio_Z.c
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_extract_cpio_Z)
+{
+ const char *reffile = "test_extract.cpio.Z";
+
+ extract_reference_file(reffile);
+ assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
+ testprog, reffile));
+
+ assertFileExists("file1");
+ assertTextFileContents("contents of file1.\n", "file1");
+ assertFileExists("file2");
+ assertTextFileContents("contents of file2.\n", "file2");
+ assertEmptyFile("test.out");
+ assertTextFileContents("1 block\n", "test.err");
+}
diff --git a/cpio/test/test_extract_cpio_bz2.c b/cpio/test/test_extract_cpio_bz2.c
new file mode 100644
index 000000000000..9525e63ae906
--- /dev/null
+++ b/cpio/test/test_extract_cpio_bz2.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_extract_cpio_bz2)
+{
+ const char *reffile = "test_extract.cpio.bz2";
+ int f;
+
+ extract_reference_file(reffile);
+ f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
+ if (f == 0 || canBzip2()) {
+ assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
+ testprog, reffile));
+
+ assertFileExists("file1");
+ assertTextFileContents("contents of file1.\n", "file1");
+ assertFileExists("file2");
+ assertTextFileContents("contents of file2.\n", "file2");
+ assertEmptyFile("test.out");
+ assertTextFileContents("1 block\n", "test.err");
+ } else {
+ skipping("It seems bzip2 is not supported on this platform");
+ }
+}
diff --git a/cpio/test/test_extract_cpio_grz.c b/cpio/test/test_extract_cpio_grz.c
new file mode 100644
index 000000000000..f1a080597e34
--- /dev/null
+++ b/cpio/test/test_extract_cpio_grz.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_extract_cpio_grz)
+{
+ const char *reffile = "test_extract.cpio.grz";
+ int f;
+
+ extract_reference_file(reffile);
+ f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
+ if (f == 0 || canGrzip()) {
+ assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
+ testprog, reffile));
+
+ assertFileExists("file1");
+ assertTextFileContents("contents of file1.\n", "file1");
+ assertFileExists("file2");
+ assertTextFileContents("contents of file2.\n", "file2");
+ assertEmptyFile("test.out");
+ assertTextFileContents("1 block\n", "test.err");
+ } else {
+ skipping("It seems grzip is not supported on this platform");
+ }
+}
diff --git a/cpio/test/test_extract_cpio_gz.c b/cpio/test/test_extract_cpio_gz.c
new file mode 100644
index 000000000000..19cee510c857
--- /dev/null
+++ b/cpio/test/test_extract_cpio_gz.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_extract_cpio_gz)
+{
+ const char *reffile = "test_extract.cpio.gz";
+ int f;
+
+ extract_reference_file(reffile);
+ f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
+ if (f == 0 || canGzip()) {
+ assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
+ testprog, reffile));
+
+ assertFileExists("file1");
+ assertTextFileContents("contents of file1.\n", "file1");
+ assertFileExists("file2");
+ assertTextFileContents("contents of file2.\n", "file2");
+ assertEmptyFile("test.out");
+ assertTextFileContents("1 block\n", "test.err");
+ } else {
+ skipping("It seems gzip is not supported on this platform");
+ }
+}
diff --git a/cpio/test/test_extract_cpio_lrz.c b/cpio/test/test_extract_cpio_lrz.c
new file mode 100644
index 000000000000..67667585e431
--- /dev/null
+++ b/cpio/test/test_extract_cpio_lrz.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_extract_cpio_lrz)
+{
+ const char *reffile = "test_extract.cpio.lrz";
+ int f;
+
+ extract_reference_file(reffile);
+ f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
+ if (f == 0 || canLrzip()) {
+ assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
+ testprog, reffile));
+
+ assertFileExists("file1");
+ assertTextFileContents("contents of file1.\n", "file1");
+ assertFileExists("file2");
+ assertTextFileContents("contents of file2.\n", "file2");
+ assertEmptyFile("test.out");
+ assertTextFileContents("1 block\n", "test.err");
+ } else {
+ skipping("It seems lrzip is not supported on this platform");
+ }
+}
diff --git a/cpio/test/test_extract_cpio_lz.c b/cpio/test/test_extract_cpio_lz.c
new file mode 100644
index 000000000000..4454e7b191e9
--- /dev/null
+++ b/cpio/test/test_extract_cpio_lz.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_extract_cpio_lz)
+{
+ const char *reffile = "test_extract.cpio.lz";
+ int f;
+
+ extract_reference_file(reffile);
+ f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
+ if (f == 0 || canLzip()) {
+ assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
+ testprog, reffile));
+
+ assertFileExists("file1");
+ assertTextFileContents("contents of file1.\n", "file1");
+ assertFileExists("file2");
+ assertTextFileContents("contents of file2.\n", "file2");
+ assertEmptyFile("test.out");
+ assertTextFileContents("1 block\n", "test.err");
+ } else {
+ skipping("It seems lzip is not supported on this platform");
+ }
+}
diff --git a/cpio/test/test_extract_cpio_lzma.c b/cpio/test/test_extract_cpio_lzma.c
new file mode 100644
index 000000000000..ae630d6119d8
--- /dev/null
+++ b/cpio/test/test_extract_cpio_lzma.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_extract_cpio_lzma)
+{
+ const char *reffile = "test_extract.cpio.lzma";
+ int f;
+
+ extract_reference_file(reffile);
+ f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
+ if (f == 0 || canLzma()) {
+ assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
+ testprog, reffile));
+
+ assertFileExists("file1");
+ assertTextFileContents("contents of file1.\n", "file1");
+ assertFileExists("file2");
+ assertTextFileContents("contents of file2.\n", "file2");
+ assertEmptyFile("test.out");
+ assertTextFileContents("1 block\n", "test.err");
+ } else {
+ skipping("It seems lzma is not supported on this platform");
+ }
+}
diff --git a/cpio/test/test_extract_cpio_lzo.c b/cpio/test/test_extract_cpio_lzo.c
new file mode 100644
index 000000000000..f351ba7a79aa
--- /dev/null
+++ b/cpio/test/test_extract_cpio_lzo.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_extract_cpio_lzo)
+{
+ const char *reffile = "test_extract.cpio.lrz";
+ int f;
+
+ extract_reference_file(reffile);
+ f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
+ if (f == 0 || canLzop()) {
+ assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
+ testprog, reffile));
+
+ assertFileExists("file1");
+ assertTextFileContents("contents of file1.\n", "file1");
+ assertFileExists("file2");
+ assertTextFileContents("contents of file2.\n", "file2");
+ assertEmptyFile("test.out");
+ assertTextFileContents("1 block\n", "test.err");
+ } else {
+ skipping("It seems lzop is not supported on this platform");
+ }
+}
diff --git a/cpio/test/test_extract_cpio_xz.c b/cpio/test/test_extract_cpio_xz.c
new file mode 100644
index 000000000000..60f1b5a9de84
--- /dev/null
+++ b/cpio/test/test_extract_cpio_xz.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_extract_cpio_xz)
+{
+ const char *reffile = "test_extract.cpio.xz";
+ int f;
+
+ extract_reference_file(reffile);
+ f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
+ if (f == 0 || canXz()) {
+ assertEqualInt(0, systemf("%s -i < %s >test.out 2>test.err",
+ testprog, reffile));
+
+ assertFileExists("file1");
+ assertTextFileContents("contents of file1.\n", "file1");
+ assertFileExists("file2");
+ assertTextFileContents("contents of file2.\n", "file2");
+ assertEmptyFile("test.out");
+ assertTextFileContents("1 block\n", "test.err");
+ } else {
+ skipping("It seems xz is not supported on this platform");
+ }
+}
diff --git a/cpio/test/test_format_newc.c b/cpio/test/test_format_newc.c
index ced62a639e7a..d2daa46ab71c 100644
--- a/cpio/test/test_format_newc.c
+++ b/cpio/test/test_format_newc.c
@@ -157,9 +157,9 @@ DEFINE_TEST(test_format_newc)
/* Verify that nothing went to stderr. */
if (canSymlink()) {
- strncat(result, "2 blocks\n", sizeof(result) - strlen(result));
+ strncat(result, "2 blocks\n", sizeof(result) - strlen(result) -1);
} else {
- strncat(result, "1 block\n", sizeof(result) - strlen(result));
+ strncat(result, "1 block\n", sizeof(result) - strlen(result) -1);
}
assertTextFileContents(result, "newc.err");
diff --git a/cpio/test/test_option_b64encode.c b/cpio/test/test_option_b64encode.c
new file mode 100644
index 000000000000..8f6b4157c01c
--- /dev/null
+++ b/cpio/test/test_option_b64encode.c
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_option_b64encode)
+{
+ char *p;
+ size_t s;
+
+ /* Create a file. */
+ assertMakeFile("f", 0644, "a");
+
+ /* Archive it with compress compression and uuencode. */
+ assertEqualInt(0,
+ systemf("echo f | %s -o -Z --b64encode >archive.out 2>archive.err",
+ testprog));
+ /* Check that the archive file has an uuencode signature. */
+ p = slurpfile(&s, "archive.out");
+ assert(s > 2);
+ assertEqualMem(p, "begin-base64 644", 16);
+
+ /* Archive it with uuencode only. */
+ assertEqualInt(0,
+ systemf("echo f | %s -o --b64encode >archive.out 2>archive.err",
+ testprog));
+ /* Check that the archive file has an uuencode signature. */
+ p = slurpfile(&s, "archive.out");
+ assert(s > 2);
+ assertEqualMem(p, "begin-base64 644", 16);
+}
diff --git a/cpio/test/test_option_grzip.c b/cpio/test/test_option_grzip.c
new file mode 100644
index 000000000000..dfce2e064e07
--- /dev/null
+++ b/cpio/test/test_option_grzip.c
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_option_grzip)
+{
+ char *p;
+ size_t s;
+
+ if (!canGrzip()) {
+ skipping("grzip is not supported on this platform");
+ return;
+ }
+
+ /* Create a file. */
+ assertMakeFile("f", 0644, "a");
+
+ /* Archive it with grzip compression. */
+ assertEqualInt(0,
+ systemf("echo f | %s -o --grzip >archive.out 2>archive.err",
+ testprog));
+ p = slurpfile(&s, "archive.err");
+ p[s] = '\0';
+ /* Check that the archive file has an grzip signature. */
+ p = slurpfile(&s, "archive.out");
+ assert(s > 2);
+ assertEqualMem(p, "GRZipII\x00\x02\x04:)", 12);
+}
diff --git a/cpio/test/test_option_lrzip.c b/cpio/test/test_option_lrzip.c
new file mode 100644
index 000000000000..a84f75157a4c
--- /dev/null
+++ b/cpio/test/test_option_lrzip.c
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_option_lrzip)
+{
+ char *p;
+ size_t s;
+
+ if (!canLrzip()) {
+ skipping("lrzip is not supported on this platform");
+ return;
+ }
+
+ /* Create a file. */
+ assertMakeFile("f", 0644, "a");
+
+ /* Archive it with lrzip compression. */
+ assertEqualInt(0,
+ systemf("echo f | %s -o --lrzip >archive.out 2>archive.err",
+ testprog));
+ p = slurpfile(&s, "archive.err");
+ p[s] = '\0';
+ /* Check that the archive file has an lzma signature. */
+ p = slurpfile(&s, "archive.out");
+ assert(s > 2);
+ assertEqualMem(p, "LRZI\x00", 5);
+}
diff --git a/cpio/test/test_option_lzop.c b/cpio/test/test_option_lzop.c
new file mode 100644
index 000000000000..9f1666e9c5b9
--- /dev/null
+++ b/cpio/test/test_option_lzop.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_option_lzop)
+{
+ char *p;
+ int r;
+ size_t s;
+
+ /* Create a file. */
+ assertMakeFile("f", 0644, "a");
+
+ /* Archive it with lzop compression. */
+ r = systemf("echo f | %s -o --lzop >archive.out 2>archive.err",
+ testprog);
+ p = slurpfile(&s, "archive.err");
+ p[s] = '\0';
+ if (r != 0) {
+ if (!canLzop()) {
+ skipping("lzop is not supported on this platform");
+ return;
+ }
+ failure("--lzop option is broken");
+ assertEqualInt(r, 0);
+ return;
+ }
+ /* Check that the archive file has an lzma signature. */
+ p = slurpfile(&s, "archive.out");
+ assert(s > 2);
+ assertEqualMem(p, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", 9);
+}
diff --git a/cpio/test/test_option_uuencode.c b/cpio/test/test_option_uuencode.c
new file mode 100644
index 000000000000..ecf354f8f391
--- /dev/null
+++ b/cpio/test/test_option_uuencode.c
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_option_uuencode)
+{
+ char *p;
+ size_t s;
+
+ /* Create a file. */
+ assertMakeFile("f", 0644, "a");
+
+ /* Archive it with compress compression and uuencode. */
+ assertEqualInt(0,
+ systemf("echo f | %s -o -Z --uuencode >archive.out 2>archive.err",
+ testprog));
+ /* Check that the archive file has an uuencode signature. */
+ p = slurpfile(&s, "archive.out");
+ assert(s > 2);
+ assertEqualMem(p, "begin 644", 9);
+
+ /* Archive it with uuencode only. */
+ assertEqualInt(0,
+ systemf("echo f | %s -o --uuencode >archive.out 2>archive.err",
+ testprog));
+ /* Check that the archive file has an uuencode signature. */
+ p = slurpfile(&s, "archive.out");
+ assert(s > 2);
+ assertEqualMem(p, "begin 644", 9);
+}
diff --git a/cpio/test/test_option_xz.c b/cpio/test/test_option_xz.c
new file mode 100644
index 000000000000..02b5dfaad4a1
--- /dev/null
+++ b/cpio/test/test_option_xz.c
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_option_xz)
+{
+ char *p;
+ int r;
+ size_t s;
+
+ /* Create a file. */
+ assertMakeFile("f", 0644, "a");
+
+ /* Archive it with xz compression. */
+ r = systemf("echo f | %s -o --xz >archive.out 2>archive.err",
+ testprog);
+ p = slurpfile(&s, "archive.err");
+ p[s] = '\0';
+ if (r != 0) {
+ if (strstr(p, "compression not available") != NULL) {
+ skipping("This version of bsdcpio was compiled "
+ "without xz support");
+ return;
+ }
+ failure("--xz option is broken");
+ assertEqualInt(r, 0);
+ return;
+ }
+ /* Check that the archive file has an xz signature. */
+ p = slurpfile(&s, "archive.out");
+ assert(s > 2);
+ assertEqualMem(p, "\xFD\x37\x7A\x58\x5A\x00", 6);
+}
diff --git a/cpio/test/test_option_y.c b/cpio/test/test_option_y.c
index 58734966ce6a..54f270b81e0f 100644
--- a/cpio/test/test_option_y.c
+++ b/cpio/test/test_option_y.c
@@ -40,9 +40,8 @@ DEFINE_TEST(test_option_y)
p = slurpfile(&s, "archive.err");
p[s] = '\0';
if (r != 0) {
- if (strstr(p, "compression not available") != NULL) {
- skipping("This version of bsdcpio was compiled "
- "without bzip2 support");
+ if (!canBzip2()) {
+ skipping("bzip2 is not supported on this platform");
return;
}
failure("-y option is broken");
diff --git a/cpio/test/test_option_z.c b/cpio/test/test_option_z.c
index 91d37ac1983a..0b68a42babbf 100644
--- a/cpio/test/test_option_z.c
+++ b/cpio/test/test_option_z.c
@@ -40,9 +40,8 @@ DEFINE_TEST(test_option_z)
p = slurpfile(&s, "archive.err");
p[s] = '\0';
if (r != 0) {
- if (strstr(p, "compression not available") != NULL) {
- skipping("This version of bsdcpio was compiled "
- "without gzip support");
+ if (!canGzip()) {
+ skipping("gzip is not supported on this platform");
return;
}
failure("-z option is broken");
diff --git a/doc/update.sh b/doc/update.sh
index 1994eb3a76f7..1038da133f77 100644
--- a/doc/update.sh
+++ b/doc/update.sh
@@ -1,5 +1,7 @@
#!/bin/sh
+set -e
+
#
# Simple script to repopulate the 'doc' tree from
# the mdoc man pages stored in each project.
diff --git a/examples/minitar/minitar.c b/examples/minitar/minitar.c
index 2d6d4208a22a..0ff6263ebf84 100644
--- a/examples/minitar/minitar.c
+++ b/examples/minitar/minitar.c
@@ -231,27 +231,27 @@ create(const char *filename, int compress, const char **argv)
switch (compress) {
#ifndef NO_BZIP2_CREATE
case 'j': case 'y':
- archive_write_set_compression_bzip2(a);
+ archive_write_add_filter_bzip2(a);
break;
#endif
#ifndef NO_COMPRESS_CREATE
case 'Z':
- archive_write_set_compression_compress(a);
+ archive_write_add_filter_compress(a);
break;
#endif
#ifndef NO_GZIP_CREATE
case 'z':
- archive_write_set_compression_gzip(a);
+ archive_write_add_filter_gzip(a);
break;
#endif
default:
- archive_write_set_compression_none(a);
+ archive_write_add_filter_none(a);
break;
}
archive_write_set_format_ustar(a);
if (strcmp(filename, "-") == 0)
filename = NULL;
- archive_write_open_file(a, filename);
+ archive_write_open_filename(a, filename);
disk = archive_read_disk_new();
#ifndef NO_LOOKUP
@@ -361,7 +361,7 @@ extract(const char *filename, int do_extract, int flags)
#endif
if (filename != NULL && strcmp(filename, "-") == 0)
filename = NULL;
- if ((r = archive_read_open_file(a, filename, 10240))) {
+ if ((r = archive_read_open_filename(a, filename, 10240))) {
errmsg(archive_error_string(a));
errmsg("\n");
exit(r);
diff --git a/examples/untar.c b/examples/untar.c
index c027f7735b87..b22d8361a012 100644
--- a/examples/untar.c
+++ b/examples/untar.c
@@ -158,8 +158,8 @@ extract(const char *filename, int do_extract, int flags)
*/
if (filename != NULL && strcmp(filename, "-") == 0)
filename = NULL;
- if ((r = archive_read_open_file(a, filename, 10240)))
- fail("archive_read_open_file()",
+ if ((r = archive_read_open_filename(a, filename, 10240)))
+ fail("archive_read_open_filename()",
archive_error_string(a), r);
for (;;) {
r = archive_read_next_header(a, &entry);
diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt
index 73d9baf01e87..ecb0409bd9d8 100644
--- a/libarchive/CMakeLists.txt
+++ b/libarchive/CMakeLists.txt
@@ -15,6 +15,9 @@ SET(include_HEADERS
SET(libarchive_SOURCES
archive_acl.c
archive_check_magic.c
+ archive_cmdline.c
+ archive_cmdline_private.h
+ archive_crc32.h
archive_crypto.c
archive_crypto_private.h
archive_endian.h
@@ -42,6 +45,7 @@ SET(libarchive_SOURCES
archive_rb.c
archive_rb.h
archive_read.c
+ archive_read_append_filter.c
archive_read_data_into_fd.c
archive_read_disk_entry_from_file.c
archive_read_disk_posix.c
@@ -53,11 +57,15 @@ SET(libarchive_SOURCES
archive_read_open_filename.c
archive_read_open_memory.c
archive_read_private.h
+ archive_read_set_format.c
archive_read_set_options.c
archive_read_support_filter_all.c
archive_read_support_filter_bzip2.c
archive_read_support_filter_compress.c
archive_read_support_filter_gzip.c
+ archive_read_support_filter_grzip.c
+ archive_read_support_filter_lrzip.c
+ archive_read_support_filter_lzop.c
archive_read_support_filter_none.c
archive_read_support_filter_program.c
archive_read_support_filter_rpm.c
@@ -85,6 +93,7 @@ SET(libarchive_SOURCES
archive_util.c
archive_virtual.c
archive_write.c
+ archive_write_disk_acl.c
archive_write_disk_posix.c
archive_write_disk_private.h
archive_write_disk_set_standard_lookup.c
@@ -94,11 +103,17 @@ SET(libarchive_SOURCES
archive_write_open_filename.c
archive_write_open_memory.c
archive_write_add_filter.c
+ archive_write_add_filter_b64encode.c
+ archive_write_add_filter_by_name.c
archive_write_add_filter_bzip2.c
archive_write_add_filter_compress.c
+ archive_write_add_filter_grzip.c
archive_write_add_filter_gzip.c
+ archive_write_add_filter_lrzip.c
+ archive_write_add_filter_lzop.c
archive_write_add_filter_none.c
archive_write_add_filter_program.c
+ archive_write_add_filter_uuencode.c
archive_write_add_filter_xz.c
archive_write_set_format.c
archive_write_set_format_7zip.c
@@ -112,10 +127,11 @@ SET(libarchive_SOURCES
archive_write_set_format_pax.c
archive_write_set_format_shar.c
archive_write_set_format_ustar.c
+ archive_write_set_format_v7tar.c
archive_write_set_format_xar.c
archive_write_set_format_zip.c
archive_write_set_options.c
- filter_fork.c
+ filter_fork_posix.c
filter_fork.h
)
diff --git a/libarchive/archive.h b/libarchive/archive.h
index d5316ca93065..f56bc38e5b43 100644
--- a/libarchive/archive.h
+++ b/libarchive/archive.h
@@ -97,6 +97,12 @@
#define __LA_PRINTF(fmtarg, firstvararg) /* nothing */
#endif
+#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1
+# define __LA_DEPRECATED __attribute__((deprecated))
+#else
+# define __LA_DEPRECATED
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -118,13 +124,13 @@ extern "C" {
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
-#define ARCHIVE_VERSION_NUMBER 3000004
+#define ARCHIVE_VERSION_NUMBER 3001002
__LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_STRING "libarchive 3.0.4"
+#define ARCHIVE_VERSION_STRING "libarchive 3.1.2"
__LA_DECL const char * archive_version_string(void);
/* Declare our basic types. */
@@ -194,6 +200,13 @@ typedef int archive_open_callback(struct archive *, void *_client_data);
typedef int archive_close_callback(struct archive *, void *_client_data);
+/* Switches from one client data object to the next/prev client data object.
+ * This is useful for reading from different data blocks such as a set of files
+ * that make up one large file.
+ */
+typedef int archive_switch_callback(struct archive *, void *_client_data1,
+ void *_client_data2);
+
/*
* Codes to identify various stream filters.
*/
@@ -207,6 +220,9 @@ typedef int archive_close_callback(struct archive *, void *_client_data);
#define ARCHIVE_FILTER_UU 7
#define ARCHIVE_FILTER_RPM 8
#define ARCHIVE_FILTER_LZIP 9
+#define ARCHIVE_FILTER_LRZIP 10
+#define ARCHIVE_FILTER_LZOP 11
+#define ARCHIVE_FILTER_GRZIP 12
#if ARCHIVE_VERSION_NUMBER < 4000000
#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE
@@ -219,6 +235,7 @@ typedef int archive_close_callback(struct archive *, void *_client_data);
#define ARCHIVE_COMPRESSION_UU ARCHIVE_FILTER_UU
#define ARCHIVE_COMPRESSION_RPM ARCHIVE_FILTER_RPM
#define ARCHIVE_COMPRESSION_LZIP ARCHIVE_FILTER_LZIP
+#define ARCHIVE_COMPRESSION_LRZIP ARCHIVE_FILTER_LRZIP
#endif
/*
@@ -291,37 +308,49 @@ __LA_DECL struct archive *archive_read_new(void);
*/
#if ARCHIVE_VERSION_NUMBER < 4000000
-__LA_DECL int archive_read_support_compression_all(struct archive *);
-__LA_DECL int archive_read_support_compression_bzip2(struct archive *);
-__LA_DECL int archive_read_support_compression_compress(struct archive *);
-__LA_DECL int archive_read_support_compression_gzip(struct archive *);
-__LA_DECL int archive_read_support_compression_lzip(struct archive *);
-__LA_DECL int archive_read_support_compression_lzma(struct archive *);
-__LA_DECL int archive_read_support_compression_none(struct archive *);
+__LA_DECL int archive_read_support_compression_all(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_bzip2(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_compress(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_gzip(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_lzip(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_lzma(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_none(struct archive *)
+ __LA_DEPRECATED;
__LA_DECL int archive_read_support_compression_program(struct archive *,
- const char *command);
+ const char *command) __LA_DEPRECATED;
__LA_DECL int archive_read_support_compression_program_signature
(struct archive *, const char *,
- const void * /* match */, size_t);
-
-__LA_DECL int archive_read_support_compression_rpm(struct archive *);
-__LA_DECL int archive_read_support_compression_uu(struct archive *);
-__LA_DECL int archive_read_support_compression_xz(struct archive *);
+ const void * /* match */, size_t) __LA_DEPRECATED;
+
+__LA_DECL int archive_read_support_compression_rpm(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_uu(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_xz(struct archive *)
+ __LA_DEPRECATED;
#endif
__LA_DECL int archive_read_support_filter_all(struct archive *);
__LA_DECL int archive_read_support_filter_bzip2(struct archive *);
__LA_DECL int archive_read_support_filter_compress(struct archive *);
__LA_DECL int archive_read_support_filter_gzip(struct archive *);
+__LA_DECL int archive_read_support_filter_grzip(struct archive *);
+__LA_DECL int archive_read_support_filter_lrzip(struct archive *);
__LA_DECL int archive_read_support_filter_lzip(struct archive *);
__LA_DECL int archive_read_support_filter_lzma(struct archive *);
+__LA_DECL int archive_read_support_filter_lzop(struct archive *);
__LA_DECL int archive_read_support_filter_none(struct archive *);
__LA_DECL int archive_read_support_filter_program(struct archive *,
const char *command);
__LA_DECL int archive_read_support_filter_program_signature
- (struct archive *, const char *,
+ (struct archive *, const char * /* cmd */,
const void * /* match */, size_t);
-
__LA_DECL int archive_read_support_filter_rpm(struct archive *);
__LA_DECL int archive_read_support_filter_uu(struct archive *);
__LA_DECL int archive_read_support_filter_xz(struct archive *);
@@ -343,6 +372,17 @@ __LA_DECL int archive_read_support_format_tar(struct archive *);
__LA_DECL int archive_read_support_format_xar(struct archive *);
__LA_DECL int archive_read_support_format_zip(struct archive *);
+/* Functions to manually set the format and filters to be used. This is
+ * useful to bypass the bidding process when the format and filters to use
+ * is known in advance.
+ */
+__LA_DECL int archive_read_set_format(struct archive *, int);
+__LA_DECL int archive_read_append_filter(struct archive *, int);
+__LA_DECL int archive_read_append_filter_program(struct archive *,
+ const char *);
+__LA_DECL int archive_read_append_filter_program_signature
+ (struct archive *, const char *, const void * /* match */, size_t);
+
/* Set various callbacks. */
__LA_DECL int archive_read_set_open_callback(struct archive *,
archive_open_callback *);
@@ -354,8 +394,23 @@ __LA_DECL int archive_read_set_skip_callback(struct archive *,
archive_skip_callback *);
__LA_DECL int archive_read_set_close_callback(struct archive *,
archive_close_callback *);
-/* The callback data is provided to all of the callbacks above. */
+/* Callback used to switch between one data object to the next */
+__LA_DECL int archive_read_set_switch_callback(struct archive *,
+ archive_switch_callback *);
+
+/* This sets the first data object. */
__LA_DECL int archive_read_set_callback_data(struct archive *, void *);
+/* This sets data object at specified index */
+__LA_DECL int archive_read_set_callback_data2(struct archive *, void *,
+ unsigned int);
+/* This adds a data object at the specified index. */
+__LA_DECL int archive_read_add_callback_data(struct archive *, void *,
+ unsigned int);
+/* This appends a data object to the end of list */
+__LA_DECL int archive_read_append_callback_data(struct archive *, void *);
+/* This prepends a data object to the beginning of list */
+__LA_DECL int archive_read_prepend_callback_data(struct archive *, void *);
+
/* Opening freezes the callbacks. */
__LA_DECL int archive_read_open1(struct archive *);
@@ -375,11 +430,15 @@ __LA_DECL int archive_read_open2(struct archive *, void *_client_data,
/* Use this if you know the filename. Note: NULL indicates stdin. */
__LA_DECL int archive_read_open_filename(struct archive *,
const char *_filename, size_t _block_size);
+/* Use this for reading multivolume files by filenames.
+ * NOTE: Must be NULL terminated. Sorting is NOT done. */
+__LA_DECL int archive_read_open_filenames(struct archive *,
+ const char **_filenames, size_t _block_size);
__LA_DECL int archive_read_open_filename_w(struct archive *,
const wchar_t *_filename, size_t _block_size);
/* archive_read_open_file() is a deprecated synonym for ..._open_filename(). */
__LA_DECL int archive_read_open_file(struct archive *,
- const char *_filename, size_t _block_size);
+ const char *_filename, size_t _block_size) __LA_DEPRECATED;
/* Read an archive that's stored in memory. */
__LA_DECL int archive_read_open_memory(struct archive *,
void * buff, size_t size);
@@ -411,6 +470,9 @@ __LA_DECL __LA_INT64_T archive_read_header_position(struct archive *);
__LA_DECL __LA_SSIZE_T archive_read_data(struct archive *,
void *, size_t);
+/* Seek within the body of an entry. Similar to lseek(2). */
+__LA_DECL __LA_INT64_T archive_seek_data(struct archive *, __LA_INT64_T, int);
+
/*
* A zero-copy version of archive_read_data that also exposes the file offset
* of each returned block. Note that the client has no way to specify
@@ -494,6 +556,12 @@ __LA_DECL int archive_read_set_options(struct archive *_a,
/* Default: Do not restore Mac extended metadata. */
/* This has no effect except on Mac OS. */
#define ARCHIVE_EXTRACT_MAC_METADATA (0x2000)
+/* Default: Use HFS+ compression if it was compressed. */
+/* This has no effect except on Mac OS v10.6 or later. */
+#define ARCHIVE_EXTRACT_NO_HFS_COMPRESSION (0x4000)
+/* Default: Do not use HFS+ compression if it was not compressed. */
+/* This has no effect except on Mac OS v10.6 or later. */
+#define ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED (0x8000)
__LA_DECL int archive_read_extract(struct archive *, struct archive_entry *,
int flags);
@@ -514,7 +582,7 @@ __LA_DECL int archive_read_close(struct archive *);
__LA_DECL int archive_read_free(struct archive *);
#if ARCHIVE_VERSION_NUMBER < 4000000
/* Synonym for archive_read_free() for backwards compatibility. */
-__LA_DECL int archive_read_finish(struct archive *);
+__LA_DECL int archive_read_finish(struct archive *) __LA_DEPRECATED;
#endif
/*-
@@ -547,27 +615,41 @@ __LA_DECL int archive_write_set_skip_file(struct archive *,
__LA_INT64_T, __LA_INT64_T);
#if ARCHIVE_VERSION_NUMBER < 4000000
-__LA_DECL int archive_write_set_compression_bzip2(struct archive *);
-__LA_DECL int archive_write_set_compression_compress(struct archive *);
-__LA_DECL int archive_write_set_compression_gzip(struct archive *);
-__LA_DECL int archive_write_set_compression_lzip(struct archive *);
-__LA_DECL int archive_write_set_compression_lzma(struct archive *);
-__LA_DECL int archive_write_set_compression_none(struct archive *);
+__LA_DECL int archive_write_set_compression_bzip2(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_compress(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_gzip(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_lzip(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_lzma(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_none(struct archive *)
+ __LA_DEPRECATED;
__LA_DECL int archive_write_set_compression_program(struct archive *,
- const char *cmd);
-__LA_DECL int archive_write_set_compression_xz(struct archive *);
+ const char *cmd) __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_xz(struct archive *)
+ __LA_DEPRECATED;
#endif
/* A convenience function to set the filter based on the code. */
__LA_DECL int archive_write_add_filter(struct archive *, int filter_code);
+__LA_DECL int archive_write_add_filter_by_name(struct archive *,
+ const char *name);
+__LA_DECL int archive_write_add_filter_b64encode(struct archive *);
__LA_DECL int archive_write_add_filter_bzip2(struct archive *);
__LA_DECL int archive_write_add_filter_compress(struct archive *);
+__LA_DECL int archive_write_add_filter_grzip(struct archive *);
__LA_DECL int archive_write_add_filter_gzip(struct archive *);
+__LA_DECL int archive_write_add_filter_lrzip(struct archive *);
__LA_DECL int archive_write_add_filter_lzip(struct archive *);
__LA_DECL int archive_write_add_filter_lzma(struct archive *);
+__LA_DECL int archive_write_add_filter_lzop(struct archive *);
__LA_DECL int archive_write_add_filter_none(struct archive *);
__LA_DECL int archive_write_add_filter_program(struct archive *,
const char *cmd);
+__LA_DECL int archive_write_add_filter_uuencode(struct archive *);
__LA_DECL int archive_write_add_filter_xz(struct archive *);
@@ -584,14 +666,18 @@ __LA_DECL int archive_write_set_format_cpio_newc(struct archive *);
__LA_DECL int archive_write_set_format_gnutar(struct archive *);
__LA_DECL int archive_write_set_format_iso9660(struct archive *);
__LA_DECL int archive_write_set_format_mtree(struct archive *);
+__LA_DECL int archive_write_set_format_mtree_classic(struct archive *);
/* TODO: int archive_write_set_format_old_tar(struct archive *); */
__LA_DECL int archive_write_set_format_pax(struct archive *);
__LA_DECL int archive_write_set_format_pax_restricted(struct archive *);
__LA_DECL int archive_write_set_format_shar(struct archive *);
__LA_DECL int archive_write_set_format_shar_dump(struct archive *);
__LA_DECL int archive_write_set_format_ustar(struct archive *);
+__LA_DECL int archive_write_set_format_v7tar(struct archive *);
__LA_DECL int archive_write_set_format_xar(struct archive *);
__LA_DECL int archive_write_set_format_zip(struct archive *);
+__LA_DECL int archive_write_zip_set_compression_deflate(struct archive *);
+__LA_DECL int archive_write_zip_set_compression_store(struct archive *);
__LA_DECL int archive_write_open(struct archive *, void *,
archive_open_callback *, archive_write_callback *,
archive_close_callback *);
@@ -600,7 +686,8 @@ __LA_DECL int archive_write_open_filename(struct archive *, const char *_file);
__LA_DECL int archive_write_open_filename_w(struct archive *,
const wchar_t *_file);
/* A deprecated synonym for archive_write_open_filename() */
-__LA_DECL int archive_write_open_file(struct archive *, const char *_file);
+__LA_DECL int archive_write_open_file(struct archive *, const char *_file)
+ __LA_DEPRECATED;
__LA_DECL int archive_write_open_FILE(struct archive *, FILE *);
/* _buffSize is the size of the buffer, _used refers to a variable that
* will be updated after each write into the buffer. */
@@ -622,12 +709,16 @@ __LA_DECL __LA_SSIZE_T archive_write_data_block(struct archive *,
__LA_DECL int archive_write_finish_entry(struct archive *);
__LA_DECL int archive_write_close(struct archive *);
+/* Marks the archive as FATAL so that a subsequent free() operation
+ * won't try to close() cleanly. Provides a fast abort capability
+ * when the client discovers that things have gone wrong. */
+__LA_DECL int archive_write_fail(struct archive *);
/* This can fail if the archive wasn't already closed, in which case
* archive_write_free() will implicitly call archive_write_close(). */
__LA_DECL int archive_write_free(struct archive *);
#if ARCHIVE_VERSION_NUMBER < 4000000
/* Synonym for archive_write_free() for backwards compatibility. */
-__LA_DECL int archive_write_finish(struct archive *);
+__LA_DECL int archive_write_finish(struct archive *) __LA_DEPRECATED;
#endif
/*
@@ -806,13 +897,17 @@ __LA_DECL const char * archive_filter_name(struct archive *, int);
/* These don't properly handle multiple filters, so are deprecated and
* will eventually be removed. */
/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, -1); */
-__LA_DECL __LA_INT64_T archive_position_compressed(struct archive *);
+__LA_DECL __LA_INT64_T archive_position_compressed(struct archive *)
+ __LA_DEPRECATED;
/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, 0); */
-__LA_DECL __LA_INT64_T archive_position_uncompressed(struct archive *);
+__LA_DECL __LA_INT64_T archive_position_uncompressed(struct archive *)
+ __LA_DEPRECATED;
/* As of libarchive 3.0, this is an alias for archive_filter_name(a, 0); */
-__LA_DECL const char *archive_compression_name(struct archive *);
+__LA_DECL const char *archive_compression_name(struct archive *)
+ __LA_DEPRECATED;
/* As of libarchive 3.0, this is an alias for archive_filter_code(a, 0); */
-__LA_DECL int archive_compression(struct archive *);
+__LA_DECL int archive_compression(struct archive *)
+ __LA_DEPRECATED;
#endif
__LA_DECL int archive_errno(struct archive *);
diff --git a/libarchive/archive_cmdline.c b/libarchive/archive_cmdline.c
new file mode 100644
index 000000000000..7d3bac53bb5c
--- /dev/null
+++ b/libarchive/archive_cmdline.c
@@ -0,0 +1,227 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#include "archive.h"
+#include "archive_cmdline_private.h"
+#include "archive_string.h"
+
+static int cmdline_set_path(struct archive_cmdline *, const char *);
+static int cmdline_add_arg(struct archive_cmdline *, const char *);
+
+static ssize_t
+extract_quotation(struct archive_string *as, const char *p)
+{
+ const char *s;
+
+ for (s = p + 1; *s;) {
+ if (*s == '\\') {
+ if (s[1] != '\0') {
+ archive_strappend_char(as, s[1]);
+ s += 2;
+ } else
+ s++;
+ } else if (*s == '"')
+ break;
+ else {
+ archive_strappend_char(as, s[0]);
+ s++;
+ }
+ }
+ if (*s != '"')
+ return (ARCHIVE_FAILED);/* Invalid sequence. */
+ return ((ssize_t)(s + 1 - p));
+}
+
+static ssize_t
+get_argument(struct archive_string *as, const char *p)
+{
+ const char *s = p;
+
+ archive_string_empty(as);
+
+ /* Skip beginning space characters. */
+ while (*s != '\0' && *s == ' ')
+ s++;
+ /* Copy non-space characters. */
+ while (*s != '\0' && *s != ' ') {
+ if (*s == '\\') {
+ if (s[1] != '\0') {
+ archive_strappend_char(as, s[1]);
+ s += 2;
+ } else {
+ s++;/* Ignore this character.*/
+ break;
+ }
+ } else if (*s == '"') {
+ ssize_t q = extract_quotation(as, s);
+ if (q < 0)
+ return (ARCHIVE_FAILED);/* Invalid sequence. */
+ s += q;
+ } else {
+ archive_strappend_char(as, s[0]);
+ s++;
+ }
+ }
+ return ((ssize_t)(s - p));
+}
+
+/*
+ * Set up command line arguments.
+ * Returns ARChIVE_OK if everything okey.
+ * Returns ARChIVE_FAILED if there is a lack of the `"' terminator or an
+ * empty command line.
+ * Returns ARChIVE_FATAL if no memory.
+ */
+int
+__archive_cmdline_parse(struct archive_cmdline *data, const char *cmd)
+{
+ struct archive_string as;
+ const char *p;
+ ssize_t al;
+ int r;
+
+ archive_string_init(&as);
+
+ /* Get first argument as a command path. */
+ al = get_argument(&as, cmd);
+ if (al < 0) {
+ r = ARCHIVE_FAILED;/* Invalid sequence. */
+ goto exit_function;
+ }
+ if (archive_strlen(&as) == 0) {
+ r = ARCHIVE_FAILED;/* An empty command path. */
+ goto exit_function;
+ }
+ r = cmdline_set_path(data, as.s);
+ if (r != ARCHIVE_OK)
+ goto exit_function;
+ p = strrchr(as.s, '/');
+ if (p == NULL)
+ p = as.s;
+ else
+ p++;
+ r = cmdline_add_arg(data, p);
+ if (r != ARCHIVE_OK)
+ goto exit_function;
+ cmd += al;
+
+ for (;;) {
+ al = get_argument(&as, cmd);
+ if (al < 0) {
+ r = ARCHIVE_FAILED;/* Invalid sequence. */
+ goto exit_function;
+ }
+ if (al == 0)
+ break;
+ cmd += al;
+ if (archive_strlen(&as) == 0 && *cmd == '\0')
+ break;
+ r = cmdline_add_arg(data, as.s);
+ if (r != ARCHIVE_OK)
+ goto exit_function;
+ }
+ r = ARCHIVE_OK;
+exit_function:
+ archive_string_free(&as);
+ return (r);
+}
+
+/*
+ * Set the program path.
+ */
+static int
+cmdline_set_path(struct archive_cmdline *data, const char *path)
+{
+ char *newptr;
+
+ newptr = realloc(data->path, strlen(path) + 1);
+ if (newptr == NULL)
+ return (ARCHIVE_FATAL);
+ data->path = newptr;
+ strcpy(data->path, path);
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Add a argument for the program.
+ */
+static int
+cmdline_add_arg(struct archive_cmdline *data, const char *arg)
+{
+ char **newargv;
+
+ if (data->path == NULL)
+ return (ARCHIVE_FAILED);
+
+ newargv = realloc(data->argv, (data->argc + 2) * sizeof(char *));
+ if (newargv == NULL)
+ return (ARCHIVE_FATAL);
+ data->argv = newargv;
+ data->argv[data->argc] = strdup(arg);
+ if (data->argv[data->argc] == NULL)
+ return (ARCHIVE_FATAL);
+ /* Set the terminator of argv. */
+ data->argv[++data->argc] = NULL;
+ return (ARCHIVE_OK);
+}
+
+struct archive_cmdline *
+__archive_cmdline_allocate(void)
+{
+ return (struct archive_cmdline *)
+ calloc(1, sizeof(struct archive_cmdline));
+}
+
+/*
+ * Release the resources.
+ */
+int
+__archive_cmdline_free(struct archive_cmdline *data)
+{
+
+ if (data) {
+ free(data->path);
+ if (data->argv != NULL) {
+ int i;
+ for (i = 0; data->argv[i] != NULL; i++)
+ free(data->argv[i]);
+ free(data->argv);
+ }
+ free(data);
+ }
+ return (ARCHIVE_OK);
+}
+
diff --git a/libarchive/archive_cmdline_private.h b/libarchive/archive_cmdline_private.h
new file mode 100644
index 000000000000..4e409e814817
--- /dev/null
+++ b/libarchive/archive_cmdline_private.h
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __LIBARCHIVE_BUILD
+#ifndef __LIBARCHIVE_TEST
+#error This header is only to be used internally to libarchive.
+#endif
+#endif
+
+#ifndef ARCHIVE_CMDLINE_PRIVATE_H
+#define ARCHIVE_CMDLINE_PRIVATE_H
+
+struct archive_cmdline {
+ char *path;
+ char **argv;
+ int argc;
+};
+
+struct archive_cmdline *__archive_cmdline_allocate(void);
+int __archive_cmdline_parse(struct archive_cmdline *, const char *);
+int __archive_cmdline_free(struct archive_cmdline *);
+
+#endif
diff --git a/libarchive/archive_crypto.c b/libarchive/archive_crypto.c
index 2caf57169296..85aba3ae27cd 100644
--- a/libarchive/archive_crypto.c
+++ b/libarchive/archive_crypto.c
@@ -90,7 +90,7 @@ win_crypto_Update(Digest_CTX *ctx, const unsigned char *buf, size_t len)
static int
win_crypto_Final(unsigned char *buf, size_t bufsize, Digest_CTX *ctx)
{
- DWORD siglen = bufsize;
+ DWORD siglen = (DWORD)bufsize;
if (!ctx->valid)
return (ARCHIVE_FAILED);
@@ -1222,8 +1222,10 @@ __archive_stub_sha512final(archive_sha512_ctx *ctx, void *md)
* 2. libc2
* 3. libc3
* 4. libSystem
- * 5. OpenSSL
- * 6. Windows API
+ * 5. Nettle
+ * 6. OpenSSL
+ * 7. libmd
+ * 8. Windows API
*/
const struct archive_crypto __archive_crypto =
{
diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c
index b531c77d2126..386e51d473e8 100644
--- a/libarchive/archive_entry.c
+++ b/libarchive/archive_entry.c
@@ -1449,6 +1449,9 @@ static struct flag {
{ "nouunlnk", L"nouunlnk", UF_NOUNLINK, 0 },
{ "nouunlink", L"nouunlink", UF_NOUNLINK, 0 },
#endif
+#ifdef UF_COMPRESSED
+ { "nocompressed",L"nocompressed", UF_COMPRESSED, 0 },
+#endif
#ifdef EXT2_UNRM_FL
{ "nouunlink", L"nouunlink", EXT2_UNRM_FL, 0},
#endif
diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h
index 5fd7cab0dc3f..a9050652e6a4 100644
--- a/libarchive/archive_entry.h
+++ b/libarchive/archive_entry.h
@@ -29,7 +29,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
-#define ARCHIVE_VERSION_NUMBER 3000004
+#define ARCHIVE_VERSION_NUMBER 3001002
/*
* Note: archive_entry.h is for use outside of libarchive; the
diff --git a/libarchive/archive_entry_link_resolver.c b/libarchive/archive_entry_link_resolver.c
index 07f0d362e48c..c7d59497a7cf 100644
--- a/libarchive/archive_entry_link_resolver.c
+++ b/libarchive/archive_entry_link_resolver.c
@@ -244,6 +244,9 @@ archive_entry_linkify(struct archive_entry_linkresolver *res,
* for future use.
*/
le = insert_entry(res, *e);
+ if (le == NULL)
+ /* XXX We should return an error code XXX */
+ return;
le->entry = *e;
*e = NULL;
}
diff --git a/libarchive/archive_match.c b/libarchive/archive_match.c
index 6b533e6ba94d..6b6be9cb20b5 100644
--- a/libarchive/archive_match.c
+++ b/libarchive/archive_match.c
@@ -1376,6 +1376,7 @@ add_entry(struct archive_match *a, int flag,
archive_mstring_copy_wcs(&(f->pathname), pathname);
a->exclusion_tree.rbt_ops = &rb_ops_wcs;
#else
+ (void)rb_ops_wcs;
pathname = archive_entry_pathname(entry);
if (pathname == NULL) {
free(f);
@@ -1515,6 +1516,7 @@ time_excluded(struct archive_match *a, struct archive_entry *entry)
pathname = archive_entry_pathname_w(entry);
a->exclusion_tree.rbt_ops = &rb_ops_wcs;
#else
+ (void)rb_ops_wcs;
pathname = archive_entry_pathname(entry);
a->exclusion_tree.rbt_ops = &rb_ops_mbs;
#endif
@@ -1675,13 +1677,16 @@ add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
unsigned i;
if (ids->count + 1 >= ids->size) {
+ void *p;
+
if (ids->size == 0)
ids->size = 8;
else
ids->size *= 2;
- ids->ids = realloc(ids->ids, sizeof(*ids->ids) * ids->size);
- if (ids->ids == NULL)
+ p = realloc(ids->ids, sizeof(*ids->ids) * ids->size);
+ if (p == NULL)
return (error_nomem(a));
+ ids->ids = (int64_t *)p;
}
/* Find an insert point. */
@@ -1709,7 +1714,7 @@ match_owner_id(struct id_array *ids, int64_t id)
unsigned b, m, t;
t = 0;
- b = ids->count;
+ b = (unsigned)ids->count;
while (t < b) {
m = (t + b)>>1;
if (ids->ids[m] == id)
diff --git a/libarchive/archive_options.c b/libarchive/archive_options.c
index 08a348fb3034..8af623931f01 100644
--- a/libarchive/archive_options.c
+++ b/libarchive/archive_options.c
@@ -87,6 +87,8 @@ _archive_set_either_option(struct archive *a, const char *m, const char *o, cons
if (r2 == ARCHIVE_FATAL)
return (ARCHIVE_FATAL);
+ if (r2 == ARCHIVE_WARN - 1)
+ return r1;
return r1 > r2 ? r1 : r2;
}
@@ -94,7 +96,7 @@ int
_archive_set_options(struct archive *a, const char *options,
int magic, const char *fn, option_handler use_option)
{
- int allok = 1, anyok = 0, r;
+ int allok = 1, anyok = 0, ignore_mod_err = 0, r;
char *data;
const char *s, *mod, *opt, *val;
@@ -111,6 +113,15 @@ _archive_set_options(struct archive *a, const char *options,
mod = opt = val = NULL;
parse_option(&s, &mod, &opt, &val);
+ if (mod == NULL && opt != NULL &&
+ strcmp("__ignore_wrong_module_name__", opt) == 0) {
+ /* Ignore module name error */
+ if (val != NULL) {
+ ignore_mod_err = 1;
+ anyok = 1;
+ }
+ continue;
+ }
r = use_option(a, mod, opt, val);
if (r == ARCHIVE_FATAL) {
@@ -122,6 +133,8 @@ _archive_set_options(struct archive *a, const char *options,
return (ARCHIVE_FAILED);
}
if (r == ARCHIVE_WARN - 1) {
+ if (ignore_mod_err)
+ continue;
/* The module name is wrong. */
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unknown module name: `%s'", mod);
diff --git a/libarchive/archive_ppmd7.c b/libarchive/archive_ppmd7.c
index 13a258188a61..fe0b0318cc05 100644
--- a/libarchive/archive_ppmd7.c
+++ b/libarchive/archive_ppmd7.c
@@ -990,7 +990,7 @@ static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)
p->Cache = (Byte)((UInt32)p->Low >> 24);
}
p->CacheSize++;
- p->Low = (UInt32)p->Low << 8;
+ p->Low = ((UInt32)p->Low << 8) & 0xFFFFFFFF;
}
static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total)
diff --git a/libarchive/archive_private.h b/libarchive/archive_private.h
index 470f50051e70..30d472fcda0f 100644
--- a/libarchive/archive_private.h
+++ b/libarchive/archive_private.h
@@ -134,6 +134,7 @@ int __archive_check_magic(struct archive *, unsigned int magic,
void __archive_errx(int retvalue, const char *msg) __LA_DEAD;
+void __archive_ensure_cloexec_flag(int fd);
int __archive_mktemp(const char *tmpdir);
int __archive_clean(struct archive *);
diff --git a/libarchive/archive_rb.c b/libarchive/archive_rb.c
index 70bf7e6d3379..5b5da2034497 100644
--- a/libarchive/archive_rb.c
+++ b/libarchive/archive_rb.c
@@ -237,6 +237,8 @@ __archive_rb_tree_reparent_nodes(
struct archive_rb_node * const new_father = old_child;
struct archive_rb_node * const new_child = old_father;
+ if (new_father == NULL)
+ return;
/*
* Exchange descendant linkages.
*/
@@ -552,6 +554,8 @@ __archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt,
unsigned int other = which ^ RB_DIR_OTHER;
struct archive_rb_node *brother = parent->rb_nodes[other];
+ if (brother == NULL)
+ return;/* The tree may be broken. */
/*
* For cases 1, 2a, and 2b, our brother's children must
* be black and our father must be black
@@ -573,6 +577,8 @@ __archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt,
*/
__archive_rb_tree_reparent_nodes(parent, other);
brother = parent->rb_nodes[other];
+ if (brother == NULL)
+ return;/* The tree may be broken. */
} else {
/*
* Both our parent and brother are black.
@@ -656,6 +662,8 @@ __archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt,
* If we had two red nephews, then after the swap,
* our former father would have a red grandson.
*/
+ if (brother->rb_nodes[other] == NULL)
+ return;/* The tree may be broken. */
RB_MARK_BLACK(brother->rb_nodes[other]);
__archive_rb_tree_reparent_nodes(parent, other);
break; /* We're done! */
diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c
index e99906f825ae..048c316c52d4 100644
--- a/libarchive/archive_read.c
+++ b/libarchive/archive_read.c
@@ -57,8 +57,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read.c 201157 2009-12-29 05:30:2
static int choose_filters(struct archive_read *);
static int choose_format(struct archive_read *);
-static void free_filters(struct archive_read *);
-static int close_filters(struct archive_read *);
static struct archive_vtable *archive_read_vtable(void);
static int64_t _archive_filter_bytes(struct archive *, int);
static int _archive_filter_code(struct archive *, int);
@@ -194,8 +192,8 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request)
int64_t get, ask = request;
if (ask > skip_limit)
ask = skip_limit;
- get = (self->archive->client.skipper)(&self->archive->archive,
- self->data, ask);
+ get = (self->archive->client.skipper)
+ (&self->archive->archive, self->data, ask);
if (get == 0)
return (total);
request -= get;
@@ -215,8 +213,8 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request)
* only do this for skips of over 64k.
*/
int64_t before = self->position;
- int64_t after = (self->archive->client.seeker)(&self->archive->archive,
- self->data, request, SEEK_CUR);
+ int64_t after = (self->archive->client.seeker)
+ (&self->archive->archive, self->data, request, SEEK_CUR);
if (after != before + request)
return ARCHIVE_FATAL;
return after - before;
@@ -241,14 +239,64 @@ client_seek_proxy(struct archive_read_filter *self, int64_t offset, int whence)
static int
client_close_proxy(struct archive_read_filter *self)
{
- int r = ARCHIVE_OK;
+ int r = ARCHIVE_OK, r2;
+ unsigned int i;
+
+ if (self->archive->client.closer == NULL)
+ return (r);
+ for (i = 0; i < self->archive->client.nodes; i++)
+ {
+ r2 = (self->archive->client.closer)
+ ((struct archive *)self->archive,
+ self->archive->client.dataset[i].data);
+ if (r > r2)
+ r = r2;
+ }
+ return (r);
+}
- if (self->archive->client.closer != NULL)
- r = (self->archive->client.closer)((struct archive *)self->archive,
- self->data);
+static int
+client_open_proxy(struct archive_read_filter *self)
+{
+ int r = ARCHIVE_OK;
+ if (self->archive->client.opener != NULL)
+ r = (self->archive->client.opener)(
+ (struct archive *)self->archive, self->data);
return (r);
}
+static int
+client_switch_proxy(struct archive_read_filter *self, unsigned int iindex)
+{
+ int r1 = ARCHIVE_OK, r2 = ARCHIVE_OK;
+ void *data2 = NULL;
+
+ /* Don't do anything if already in the specified data node */
+ if (self->archive->client.cursor == iindex)
+ return (ARCHIVE_OK);
+
+ self->archive->client.cursor = iindex;
+ data2 = self->archive->client.dataset[self->archive->client.cursor].data;
+ if (self->archive->client.switcher != NULL)
+ {
+ r1 = r2 = (self->archive->client.switcher)
+ ((struct archive *)self->archive, self->data, data2);
+ self->data = data2;
+ }
+ else
+ {
+ /* Attempt to call close and open instead */
+ if (self->archive->client.closer != NULL)
+ r1 = (self->archive->client.closer)
+ ((struct archive *)self->archive, self->data);
+ self->data = data2;
+ if (self->archive->client.opener != NULL)
+ r2 = (self->archive->client.opener)
+ ((struct archive *)self->archive, self->data);
+ }
+ return (r1 < r2) ? r1 : r2;
+}
+
int
archive_read_set_open_callback(struct archive *_a,
archive_open_callback *client_opener)
@@ -305,21 +353,109 @@ archive_read_set_close_callback(struct archive *_a,
}
int
+archive_read_set_switch_callback(struct archive *_a,
+ archive_switch_callback *client_switcher)
+{
+ struct archive_read *a = (struct archive_read *)_a;
+ archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
+ "archive_read_set_switch_callback");
+ a->client.switcher = client_switcher;
+ return ARCHIVE_OK;
+}
+
+int
archive_read_set_callback_data(struct archive *_a, void *client_data)
{
+ return archive_read_set_callback_data2(_a, client_data, 0);
+}
+
+int
+archive_read_set_callback_data2(struct archive *_a, void *client_data,
+ unsigned int iindex)
+{
struct archive_read *a = (struct archive_read *)_a;
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
- "archive_read_set_callback_data");
- a->client.data = client_data;
+ "archive_read_set_callback_data2");
+
+ if (a->client.nodes == 0)
+ {
+ a->client.dataset = (struct archive_read_data_node *)
+ calloc(1, sizeof(*a->client.dataset));
+ if (a->client.dataset == NULL)
+ {
+ archive_set_error(&a->archive, ENOMEM,
+ "No memory.");
+ return ARCHIVE_FATAL;
+ }
+ a->client.nodes = 1;
+ }
+
+ if (iindex > a->client.nodes - 1)
+ {
+ archive_set_error(&a->archive, EINVAL,
+ "Invalid index specified.");
+ return ARCHIVE_FATAL;
+ }
+ a->client.dataset[iindex].data = client_data;
+ a->client.dataset[iindex].begin_position = -1;
+ a->client.dataset[iindex].total_size = -1;
+ return ARCHIVE_OK;
+}
+
+int
+archive_read_add_callback_data(struct archive *_a, void *client_data,
+ unsigned int iindex)
+{
+ struct archive_read *a = (struct archive_read *)_a;
+ void *p;
+ unsigned int i;
+
+ archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
+ "archive_read_add_callback_data");
+ if (iindex > a->client.nodes) {
+ archive_set_error(&a->archive, EINVAL,
+ "Invalid index specified.");
+ return ARCHIVE_FATAL;
+ }
+ p = realloc(a->client.dataset, sizeof(*a->client.dataset)
+ * (++(a->client.nodes)));
+ if (p == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "No memory.");
+ return ARCHIVE_FATAL;
+ }
+ a->client.dataset = (struct archive_read_data_node *)p;
+ for (i = a->client.nodes - 1; i > iindex && i > 0; i--) {
+ a->client.dataset[i].data = a->client.dataset[i-1].data;
+ a->client.dataset[i].begin_position = -1;
+ a->client.dataset[i].total_size = -1;
+ }
+ a->client.dataset[iindex].data = client_data;
+ a->client.dataset[iindex].begin_position = -1;
+ a->client.dataset[iindex].total_size = -1;
return ARCHIVE_OK;
}
int
+archive_read_append_callback_data(struct archive *_a, void *client_data)
+{
+ struct archive_read *a = (struct archive_read *)_a;
+ return archive_read_add_callback_data(_a, client_data, a->client.nodes);
+}
+
+int
+archive_read_prepend_callback_data(struct archive *_a, void *client_data)
+{
+ return archive_read_add_callback_data(_a, client_data, 0);
+}
+
+int
archive_read_open1(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
- struct archive_read_filter *filter;
+ struct archive_read_filter *filter, *tmp;
int slot, e;
+ unsigned int i;
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
"archive_read_open");
@@ -334,11 +470,14 @@ archive_read_open1(struct archive *_a)
/* Open data source. */
if (a->client.opener != NULL) {
- e =(a->client.opener)(&a->archive, a->client.data);
+ e = (a->client.opener)(&a->archive, a->client.dataset[0].data);
if (e != 0) {
/* If the open failed, call the closer to clean up. */
- if (a->client.closer)
- (a->client.closer)(&a->archive, a->client.data);
+ if (a->client.closer) {
+ for (i = 0; i < a->client.nodes; i++)
+ (a->client.closer)(&a->archive,
+ a->client.dataset[i].data);
+ }
return (e);
}
}
@@ -349,31 +488,51 @@ archive_read_open1(struct archive *_a)
filter->bidder = NULL;
filter->upstream = NULL;
filter->archive = a;
- filter->data = a->client.data;
+ filter->data = a->client.dataset[0].data;
+ filter->open = client_open_proxy;
filter->read = client_read_proxy;
filter->skip = client_skip_proxy;
filter->seek = client_seek_proxy;
filter->close = client_close_proxy;
+ filter->sswitch = client_switch_proxy;
filter->name = "none";
- filter->code = ARCHIVE_COMPRESSION_NONE;
- a->filter = filter;
+ filter->code = ARCHIVE_FILTER_NONE;
- /* Build out the input pipeline. */
- e = choose_filters(a);
- if (e < ARCHIVE_WARN) {
- a->archive.state = ARCHIVE_STATE_FATAL;
- return (ARCHIVE_FATAL);
+ a->client.dataset[0].begin_position = 0;
+ if (!a->filter || !a->bypass_filter_bidding)
+ {
+ a->filter = filter;
+ /* Build out the input pipeline. */
+ e = choose_filters(a);
+ if (e < ARCHIVE_WARN) {
+ a->archive.state = ARCHIVE_STATE_FATAL;
+ return (ARCHIVE_FATAL);
+ }
+ }
+ else
+ {
+ /* Need to add "NONE" type filter at the end of the filter chain */
+ tmp = a->filter;
+ while (tmp->upstream)
+ tmp = tmp->upstream;
+ tmp->upstream = filter;
}
- slot = choose_format(a);
- if (slot < 0) {
- close_filters(a);
- a->archive.state = ARCHIVE_STATE_FATAL;
- return (ARCHIVE_FATAL);
+ if (!a->format)
+ {
+ slot = choose_format(a);
+ if (slot < 0) {
+ __archive_read_close_filters(a);
+ a->archive.state = ARCHIVE_STATE_FATAL;
+ return (ARCHIVE_FATAL);
+ }
+ a->format = &(a->formats[slot]);
}
- a->format = &(a->formats[slot]);
a->archive.state = ARCHIVE_STATE_HEADER;
+
+ /* Ensure libarchive starts from the first node in a multivolume set */
+ client_switch_proxy(a->filter, 0);
return (e);
}
@@ -413,8 +572,8 @@ choose_filters(struct archive_read *a)
/* Verify the filter by asking it for some data. */
__archive_read_filter_ahead(a->filter, 1, &avail);
if (avail < 0) {
- close_filters(a);
- free_filters(a);
+ __archive_read_close_filters(a);
+ __archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
a->archive.compression_name = a->filter->name;
@@ -432,8 +591,8 @@ choose_filters(struct archive_read *a)
a->filter = filter;
r = (best_bidder->init)(a->filter);
if (r != ARCHIVE_OK) {
- close_filters(a);
- free_filters(a);
+ __archive_read_close_filters(a);
+ __archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
}
@@ -501,6 +660,9 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
a->read_data_output_offset = 0;
a->read_data_remaining = 0;
+ a->read_data_is_posix_read = 0;
+ a->read_data_requested = 0;
+ a->data_start_node = a->client.cursor;
/* EOF always wins; otherwise return the worst error. */
return (r2 < r1 || r2 == ARCHIVE_EOF) ? r2 : r1;
}
@@ -611,6 +773,8 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
while (s > 0) {
if (a->read_data_remaining == 0) {
read_buf = a->read_data_block;
+ a->read_data_is_posix_read = 1;
+ a->read_data_requested = s;
r = _archive_read_data_block(&a->archive, &read_buf,
&a->read_data_remaining, &a->read_data_offset);
a->read_data_block = read_buf;
@@ -664,6 +828,8 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
bytes_read += len;
}
}
+ a->read_data_is_posix_read = 0;
+ a->read_data_requested = 0;
return (bytes_read);
}
@@ -698,6 +864,23 @@ archive_read_data_skip(struct archive *_a)
return (r);
}
+int64_t
+archive_seek_data(struct archive *_a, int64_t offset, int whence)
+{
+ struct archive_read *a = (struct archive_read *)_a;
+ archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA,
+ "archive_seek_data_block");
+
+ if (a->format->seek_data == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Internal error: "
+ "No format_seek_data_block function registered");
+ return (ARCHIVE_FATAL);
+ }
+
+ return (a->format->seek_data)(a, offset, whence);
+}
+
/*
* Read the next block of entry data from the archive.
* This is a zero-copy interface; the client receives a pointer,
@@ -724,8 +907,8 @@ _archive_read_data_block(struct archive *_a,
return (a->format->read_data)(a, buff, size, offset);
}
-static int
-close_filters(struct archive_read *a)
+int
+__archive_read_close_filters(struct archive_read *a)
{
struct archive_read_filter *f = a->filter;
int r = ARCHIVE_OK;
@@ -745,8 +928,8 @@ close_filters(struct archive_read *a)
return r;
}
-static void
-free_filters(struct archive_read *a)
+void
+__archive_read_free_filters(struct archive_read *a)
{
while (a->filter != NULL) {
struct archive_read_filter *t = a->filter->upstream;
@@ -790,7 +973,7 @@ _archive_read_close(struct archive *_a)
/* TODO: Clean up the formatters. */
/* Release the filter objects. */
- r1 = close_filters(a);
+ r1 = __archive_read_close_filters(a);
if (r1 < r)
r = r1;
@@ -829,7 +1012,7 @@ _archive_read_free(struct archive *_a)
}
/* Free the filters */
- free_filters(a);
+ __archive_read_free_filters(a);
/* Release the bidder objects. */
n = sizeof(a->bidders)/sizeof(a->bidders[0]);
@@ -846,6 +1029,7 @@ _archive_read_free(struct archive *_a)
archive_entry_free(a->entry);
a->archive.magic = 0;
__archive_clean(&a->archive);
+ free(a->client.dataset);
free(a);
return (r);
}
@@ -855,7 +1039,8 @@ get_filter(struct archive *_a, int n)
{
struct archive_read *a = (struct archive_read *)_a;
struct archive_read_filter *f = a->filter;
- /* We use n == -1 for 'the last filter', which is always the client proxy. */
+ /* We use n == -1 for 'the last filter', which is always the
+ * client proxy. */
if (n == -1 && f != NULL) {
struct archive_read_filter *last = f;
f = f->upstream;
@@ -908,6 +1093,7 @@ __archive_read_register_format(struct archive_read *a,
int (*read_header)(struct archive_read *, struct archive_entry *),
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
int (*read_data_skip)(struct archive_read *),
+ int64_t (*seek_data)(struct archive_read *, int64_t, int),
int (*cleanup)(struct archive_read *))
{
int i, number_slots;
@@ -927,6 +1113,7 @@ __archive_read_register_format(struct archive_read *a,
a->formats[i].read_header = read_header;
a->formats[i].read_data = read_data;
a->formats[i].read_data_skip = read_data_skip;
+ a->formats[i].seek_data = seek_data;
a->formats[i].cleanup = cleanup;
a->formats[i].data = format_data;
a->formats[i].name = name;
@@ -1073,7 +1260,8 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
if (filter->next > filter->buffer &&
filter->next + min > filter->buffer + filter->buffer_size) {
if (filter->avail > 0)
- memmove(filter->buffer, filter->next, filter->avail);
+ memmove(filter->buffer, filter->next,
+ filter->avail);
filter->next = filter->buffer;
}
@@ -1088,15 +1276,26 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
&filter->client_buff);
if (bytes_read < 0) { /* Read error. */
filter->client_total = filter->client_avail = 0;
- filter->client_next = filter->client_buff = NULL;
+ filter->client_next =
+ filter->client_buff = NULL;
filter->fatal = 1;
if (avail != NULL)
*avail = ARCHIVE_FATAL;
return (NULL);
}
- if (bytes_read == 0) { /* Premature end-of-file. */
+ if (bytes_read == 0) {
+ /* Check for another client object first */
+ if (filter->archive->client.cursor !=
+ filter->archive->client.nodes - 1) {
+ if (client_switch_proxy(filter,
+ filter->archive->client.cursor + 1)
+ == ARCHIVE_OK)
+ continue;
+ }
+ /* Premature end-of-file. */
filter->client_total = filter->client_avail = 0;
- filter->client_next = filter->client_buff = NULL;
+ filter->client_next =
+ filter->client_buff = NULL;
filter->end_of_file = 1;
/* Return whatever we do have. */
if (avail != NULL)
@@ -1106,9 +1305,7 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
filter->client_total = bytes_read;
filter->client_avail = filter->client_total;
filter->client_next = filter->client_buff;
- }
- else
- {
+ } else {
/*
* We can't satisfy the request from the copy
* buffer or the existing client data, so we
@@ -1129,9 +1326,10 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
t *= 2;
if (t <= s) { /* Integer overflow! */
archive_set_error(
- &filter->archive->archive,
- ENOMEM,
- "Unable to allocate copy buffer");
+ &filter->archive->archive,
+ ENOMEM,
+ "Unable to allocate copy"
+ " buffer");
filter->fatal = 1;
if (avail != NULL)
*avail = ARCHIVE_FATAL;
@@ -1170,8 +1368,8 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
if (tocopy > filter->client_avail)
tocopy = filter->client_avail;
- memcpy(filter->next + filter->avail, filter->client_next,
- tocopy);
+ memcpy(filter->next + filter->avail,
+ filter->client_next, tocopy);
/* Remove this data from client buffer. */
filter->client_next += tocopy;
filter->client_avail -= tocopy;
@@ -1274,6 +1472,13 @@ advance_file_pointer(struct archive_read_filter *filter, int64_t request)
}
if (bytes_read == 0) {
+ if (filter->archive->client.cursor !=
+ filter->archive->client.nodes - 1) {
+ if (client_switch_proxy(filter,
+ filter->archive->client.cursor + 1)
+ == ARCHIVE_OK)
+ continue;
+ }
filter->client_buff = NULL;
filter->end_of_file = 1;
return (total_bytes_skipped);
@@ -1305,15 +1510,109 @@ __archive_read_seek(struct archive_read *a, int64_t offset, int whence)
}
int64_t
-__archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset, int whence)
+__archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset,
+ int whence)
{
+ struct archive_read_client *client;
int64_t r;
+ unsigned int cursor;
if (filter->closed || filter->fatal)
return (ARCHIVE_FATAL);
if (filter->seek == NULL)
return (ARCHIVE_FAILED);
- r = filter->seek(filter, offset, whence);
+
+ client = &(filter->archive->client);
+ switch (whence) {
+ case SEEK_CUR:
+ /* Adjust the offset and use SEEK_SET instead */
+ offset += filter->position;
+ case SEEK_SET:
+ cursor = 0;
+ while (1)
+ {
+ if (client->dataset[cursor].begin_position < 0 ||
+ client->dataset[cursor].total_size < 0 ||
+ client->dataset[cursor].begin_position +
+ client->dataset[cursor].total_size - 1 > offset ||
+ cursor + 1 >= client->nodes)
+ break;
+ r = client->dataset[cursor].begin_position +
+ client->dataset[cursor].total_size;
+ client->dataset[++cursor].begin_position = r;
+ }
+ while (1) {
+ r = client_switch_proxy(filter, cursor);
+ if (r != ARCHIVE_OK)
+ return r;
+ if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0)
+ return r;
+ client->dataset[cursor].total_size = r;
+ if (client->dataset[cursor].begin_position +
+ client->dataset[cursor].total_size - 1 > offset ||
+ cursor + 1 >= client->nodes)
+ break;
+ r = client->dataset[cursor].begin_position +
+ client->dataset[cursor].total_size;
+ client->dataset[++cursor].begin_position = r;
+ }
+ offset -= client->dataset[cursor].begin_position;
+ if (offset < 0)
+ offset = 0;
+ else if (offset > client->dataset[cursor].total_size - 1)
+ offset = client->dataset[cursor].total_size - 1;
+ if ((r = client_seek_proxy(filter, offset, SEEK_SET)) < 0)
+ return r;
+ break;
+
+ case SEEK_END:
+ cursor = 0;
+ while (1) {
+ if (client->dataset[cursor].begin_position < 0 ||
+ client->dataset[cursor].total_size < 0 ||
+ cursor + 1 >= client->nodes)
+ break;
+ r = client->dataset[cursor].begin_position +
+ client->dataset[cursor].total_size;
+ client->dataset[++cursor].begin_position = r;
+ }
+ while (1) {
+ r = client_switch_proxy(filter, cursor);
+ if (r != ARCHIVE_OK)
+ return r;
+ if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0)
+ return r;
+ client->dataset[cursor].total_size = r;
+ r = client->dataset[cursor].begin_position +
+ client->dataset[cursor].total_size;
+ if (cursor + 1 >= client->nodes)
+ break;
+ client->dataset[++cursor].begin_position = r;
+ }
+ while (1) {
+ if (r + offset >=
+ client->dataset[cursor].begin_position)
+ break;
+ offset += client->dataset[cursor].total_size;
+ if (cursor == 0)
+ break;
+ cursor--;
+ r = client->dataset[cursor].begin_position +
+ client->dataset[cursor].total_size;
+ }
+ offset = (r + offset) - client->dataset[cursor].begin_position;
+ if ((r = client_switch_proxy(filter, cursor)) != ARCHIVE_OK)
+ return r;
+ r = client_seek_proxy(filter, offset, SEEK_SET);
+ if (r < ARCHIVE_OK)
+ return r;
+ break;
+
+ default:
+ return (ARCHIVE_FATAL);
+ }
+ r += client->dataset[cursor].begin_position;
+
if (r >= 0) {
/*
* Ouch. Clearing the buffer like this hurts, especially
diff --git a/libarchive/archive_read_append_filter.c b/libarchive/archive_read_append_filter.c
new file mode 100644
index 000000000000..017d7c68a4b3
--- /dev/null
+++ b/libarchive/archive_read_append_filter.c
@@ -0,0 +1,198 @@
+/*-
+ * Copyright (c) 2003-2012 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+int
+archive_read_append_filter(struct archive *_a, int code)
+{
+ int r1, r2, number_bidders, i;
+ char str[20];
+ struct archive_read_filter_bidder *bidder;
+ struct archive_read_filter *filter;
+ struct archive_read *a = (struct archive_read *)_a;
+
+ r1 = r2 = (ARCHIVE_OK);
+ switch (code)
+ {
+ case ARCHIVE_FILTER_NONE:
+ /* No filter to add, so do nothing.
+ * NOTE: An initial "NONE" type filter is always set at the end of the
+ * filter chain.
+ */
+ r1 = (ARCHIVE_OK);
+ break;
+ case ARCHIVE_FILTER_GZIP:
+ strcpy(str, "gzip");
+ r1 = archive_read_support_filter_gzip(_a);
+ break;
+ case ARCHIVE_FILTER_BZIP2:
+ strcpy(str, "bzip2");
+ r1 = archive_read_support_filter_bzip2(_a);
+ break;
+ case ARCHIVE_FILTER_COMPRESS:
+ strcpy(str, "compress (.Z)");
+ r1 = archive_read_support_filter_compress(_a);
+ break;
+ case ARCHIVE_FILTER_PROGRAM:
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Cannot append program filter using archive_read_append_filter");
+ return (ARCHIVE_FATAL);
+ case ARCHIVE_FILTER_LZMA:
+ strcpy(str, "lzma");
+ r1 = archive_read_support_filter_lzma(_a);
+ break;
+ case ARCHIVE_FILTER_XZ:
+ strcpy(str, "xz");
+ r1 = archive_read_support_filter_xz(_a);
+ break;
+ case ARCHIVE_FILTER_UU:
+ strcpy(str, "uu");
+ r1 = archive_read_support_filter_uu(_a);
+ break;
+ case ARCHIVE_FILTER_RPM:
+ strcpy(str, "rpm");
+ r1 = archive_read_support_filter_rpm(_a);
+ break;
+ case ARCHIVE_FILTER_LZIP:
+ strcpy(str, "lzip");
+ r1 = archive_read_support_filter_lzip(_a);
+ break;
+ case ARCHIVE_FILTER_LRZIP:
+ strcpy(str, "lrzip");
+ r1 = archive_read_support_filter_lrzip(_a);
+ break;
+ default:
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Invalid filter code specified");
+ return (ARCHIVE_FATAL);
+ }
+
+ if (code != ARCHIVE_FILTER_NONE)
+ {
+ number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
+
+ bidder = a->bidders;
+ for (i = 0; i < number_bidders; i++, bidder++)
+ {
+ if (!bidder->name || !strcmp(bidder->name, str))
+ break;
+ }
+ if (!bidder->name || strcmp(bidder->name, str))
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Internal error: Unable to append filter");
+ return (ARCHIVE_FATAL);
+ }
+
+ filter
+ = (struct archive_read_filter *)calloc(1, sizeof(*filter));
+ if (filter == NULL)
+ {
+ archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ return (ARCHIVE_FATAL);
+ }
+ filter->bidder = bidder;
+ filter->archive = a;
+ filter->upstream = a->filter;
+ a->filter = filter;
+ r2 = (bidder->init)(a->filter);
+ if (r2 != ARCHIVE_OK) {
+ __archive_read_close_filters(a);
+ __archive_read_free_filters(a);
+ return (ARCHIVE_FATAL);
+ }
+ }
+
+ a->bypass_filter_bidding = 1;
+ return (r1 < r2) ? r1 : r2;
+}
+
+int
+archive_read_append_filter_program(struct archive *_a, const char *cmd)
+{
+ return (archive_read_append_filter_program_signature(_a, cmd, NULL, 0));
+}
+
+int
+archive_read_append_filter_program_signature(struct archive *_a,
+ const char *cmd, const void *signature, size_t signature_len)
+{
+ int r, number_bidders, i;
+ struct archive_read_filter_bidder *bidder;
+ struct archive_read_filter *filter;
+ struct archive_read *a = (struct archive_read *)_a;
+
+ if (archive_read_support_filter_program_signature(_a, cmd, signature,
+ signature_len) != (ARCHIVE_OK))
+ return (ARCHIVE_FATAL);
+
+ number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
+
+ bidder = a->bidders;
+ for (i = 0; i < number_bidders; i++, bidder++)
+ {
+ /* Program bidder name set to filter name after initialization */
+ if (bidder->data && !bidder->name)
+ break;
+ }
+ if (!bidder->data)
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Internal error: Unable to append program filter");
+ return (ARCHIVE_FATAL);
+ }
+
+ filter
+ = (struct archive_read_filter *)calloc(1, sizeof(*filter));
+ if (filter == NULL)
+ {
+ archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ return (ARCHIVE_FATAL);
+ }
+ filter->bidder = bidder;
+ filter->archive = a;
+ filter->upstream = a->filter;
+ a->filter = filter;
+ r = (bidder->init)(a->filter);
+ if (r != ARCHIVE_OK) {
+ __archive_read_close_filters(a);
+ __archive_read_free_filters(a);
+ return (ARCHIVE_FATAL);
+ }
+ bidder->name = a->filter->name;
+
+ a->bypass_filter_bidding = 1;
+ return r;
+}
diff --git a/libarchive/archive_read_disk_entry_from_file.c b/libarchive/archive_read_disk_entry_from_file.c
index a43c0adf9c2a..e984aaadbeab 100644
--- a/libarchive/archive_read_disk_entry_from_file.c
+++ b/libarchive/archive_read_disk_entry_from_file.c
@@ -49,8 +49,10 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
-#ifdef HAVE_SYS_XATTR_H
+#if defined(HAVE_SYS_XATTR_H)
#include <sys/xattr.h>
+#elif defined(HAVE_ATTR_XATTR_H)
+#include <attr/xattr.h>
#endif
#ifdef HAVE_SYS_EA_H
#include <sys/ea.h>
@@ -58,9 +60,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
#ifdef HAVE_ACL_LIBACL_H
#include <acl/libacl.h>
#endif
-#ifdef HAVE_ATTR_XATTR_H
-#include <attr/xattr.h>
-#endif
#ifdef HAVE_COPYFILE_H
#include <copyfile.h>
#endif
@@ -104,6 +103,10 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
#include "archive_private.h"
#include "archive_read_disk_private.h"
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
/*
* Linux and FreeBSD plug this obvious hole in POSIX.1e in
* different ways.
@@ -114,7 +117,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
#define ACL_GET_PERM acl_get_perm_np
#endif
-static int setup_acls_posix1e(struct archive_read_disk *,
+static int setup_acls(struct archive_read_disk *,
struct archive_entry *, int *fd);
static int setup_mac_metadata(struct archive_read_disk *,
struct archive_entry *, int *fd);
@@ -168,15 +171,16 @@ archive_read_disk_entry_from_file(struct archive *_a,
st = &s;
}
archive_entry_copy_stat(entry, st);
- /* Lookup uname/gname */
- name = archive_read_disk_uname(_a, archive_entry_uid(entry));
- if (name != NULL)
- archive_entry_copy_uname(entry, name);
- name = archive_read_disk_gname(_a, archive_entry_gid(entry));
- if (name != NULL)
- archive_entry_copy_gname(entry, name);
}
+ /* Lookup uname/gname */
+ name = archive_read_disk_uname(_a, archive_entry_uid(entry));
+ if (name != NULL)
+ archive_entry_copy_uname(entry, name);
+ name = archive_read_disk_gname(_a, archive_entry_gid(entry));
+ if (name != NULL)
+ archive_entry_copy_gname(entry, name);
+
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
/* On FreeBSD, we get flags for free with the stat. */
/* TODO: Does this belong in copy_stat()? */
@@ -192,12 +196,14 @@ archive_read_disk_entry_from_file(struct archive *_a,
if (fd < 0) {
if (a->tree != NULL)
fd = a->open_on_current_dir(a->tree, path,
- O_RDONLY | O_NONBLOCK);
+ O_RDONLY | O_NONBLOCK | O_CLOEXEC);
else
- fd = open(path, O_RDONLY | O_NONBLOCK);
+ fd = open(path, O_RDONLY | O_NONBLOCK |
+ O_CLOEXEC);
+ __archive_ensure_cloexec_flag(fd);
}
if (fd >= 0) {
- unsigned long stflags;
+ int stflags;
r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
if (r == 0 && stflags != 0)
archive_entry_set_fflags(entry, stflags, 0);
@@ -244,7 +250,7 @@ archive_read_disk_entry_from_file(struct archive *_a,
}
#endif /* HAVE_READLINK || HAVE_READLINKAT */
- r = setup_acls_posix1e(a, entry, &fd);
+ r = setup_acls(a, entry, &fd);
r1 = setup_xattrs(a, entry, &fd);
if (r1 < r)
r = r1;
@@ -285,9 +291,10 @@ setup_mac_metadata(struct archive_read_disk *a,
int copyfile_flags = COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR;
struct stat copyfile_stat;
int ret = ARCHIVE_OK;
- void *buff;
+ void *buff = NULL;
int have_attrs;
- const char *name, *tempdir, *tempfile = NULL;
+ const char *name, *tempdir;
+ struct archive_string tempfile;
(void)fd; /* UNUSED */
name = archive_entry_sourcepath(entry);
@@ -322,25 +329,28 @@ setup_mac_metadata(struct archive_read_disk *a,
tempdir = getenv("TMPDIR");
if (tempdir == NULL)
tempdir = _PATH_TMP;
- tempfile = tempnam(tempdir, "tar.md.");
+ archive_string_init(&tempfile);
+ archive_strcpy(&tempfile, tempdir);
+ archive_strcat(&tempfile, "tar.md.XXXXXX");
+ tempfd = mkstemp(tempfile.s);
+ if (tempfd < 0) {
+ archive_set_error(&a->archive, errno,
+ "Could not open extended attribute file");
+ ret = ARCHIVE_WARN;
+ goto cleanup;
+ }
+ __archive_ensure_cloexec_flag(tempfd);
/* XXX I wish copyfile() could pack directly to a memory
* buffer; that would avoid the temp file here. For that
* matter, it would be nice if fcopyfile() actually worked,
* that would reduce the many open/close races here. */
- if (copyfile(name, tempfile, 0, copyfile_flags | COPYFILE_PACK)) {
+ if (copyfile(name, tempfile.s, 0, copyfile_flags | COPYFILE_PACK)) {
archive_set_error(&a->archive, errno,
"Could not pack extended attributes");
ret = ARCHIVE_WARN;
goto cleanup;
}
- tempfd = open(tempfile, O_RDONLY);
- if (tempfd < 0) {
- archive_set_error(&a->archive, errno,
- "Could not open extended attribute file");
- ret = ARCHIVE_WARN;
- goto cleanup;
- }
if (fstat(tempfd, &copyfile_stat)) {
archive_set_error(&a->archive, errno,
"Could not check size of extended attributes");
@@ -363,10 +373,12 @@ setup_mac_metadata(struct archive_read_disk *a,
archive_entry_copy_mac_metadata(entry, buff, copyfile_stat.st_size);
cleanup:
- if (tempfd >= 0)
+ if (tempfd >= 0) {
close(tempfd);
- if (tempfile != NULL)
- unlink(tempfile);
+ unlink(tempfile.s);
+ }
+ archive_string_free(&tempfile);
+ free(buff);
return (ret);
}
@@ -387,16 +399,19 @@ setup_mac_metadata(struct archive_read_disk *a,
#endif
-#ifdef HAVE_POSIX_ACL
-static void setup_acl_posix1e(struct archive_read_disk *a,
+#if defined(HAVE_POSIX_ACL) && defined(ACL_TYPE_NFS4)
+static int translate_acl(struct archive_read_disk *a,
struct archive_entry *entry, acl_t acl, int archive_entry_acl_type);
static int
-setup_acls_posix1e(struct archive_read_disk *a,
+setup_acls(struct archive_read_disk *a,
struct archive_entry *entry, int *fd)
{
const char *accpath;
acl_t acl;
+#if HAVE_ACL_IS_TRIVIAL_NP
+ int r;
+#endif
accpath = archive_entry_sourcepath(entry);
if (accpath == NULL)
@@ -404,15 +419,33 @@ setup_acls_posix1e(struct archive_read_disk *a,
archive_entry_acl_clear(entry);
- if (*fd < 0 && a->tree != NULL &&
- (a->follow_symlinks || archive_entry_filetype(entry) != AE_IFLNK)){
- *fd = a->open_on_current_dir(a->tree, accpath,
- O_RDONLY | O_NONBLOCK);
- if (*fd < 0) {
- archive_set_error(&a->archive, errno,
- "Couldn't access %s", accpath);
- return (ARCHIVE_FAILED);
- }
+ /* Try NFS4 ACL first. */
+ if (*fd >= 0)
+ acl = acl_get_fd(*fd);
+#if HAVE_ACL_GET_LINK_NP
+ else if (!a->follow_symlinks)
+ acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
+#else
+ else if ((!a->follow_symlinks)
+ && (archive_entry_filetype(entry) == AE_IFLNK))
+ /* We can't get the ACL of a symlink, so we assume it can't
+ have one. */
+ acl = NULL;
+#endif
+ else
+ acl = acl_get_file(accpath, ACL_TYPE_NFS4);
+#if HAVE_ACL_IS_TRIVIAL_NP
+ /* Ignore "trivial" ACLs that just mirror the file mode. */
+ acl_is_trivial_np(acl, &r);
+ if (r) {
+ acl_free(acl);
+ acl = NULL;
+ }
+#endif
+ if (acl != NULL) {
+ translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
+ acl_free(acl);
+ return (ARCHIVE_OK);
}
/* Retrieve access ACL from file. */
@@ -431,7 +464,7 @@ setup_acls_posix1e(struct archive_read_disk *a,
else
acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
if (acl != NULL) {
- setup_acl_posix1e(a, entry, acl,
+ translate_acl(a, entry, acl,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
acl_free(acl);
}
@@ -440,7 +473,7 @@ setup_acls_posix1e(struct archive_read_disk *a,
if (S_ISDIR(archive_entry_mode(entry))) {
acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
if (acl != NULL) {
- setup_acl_posix1e(a, entry, acl,
+ translate_acl(a, entry, acl,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
acl_free(acl);
}
@@ -449,68 +482,180 @@ setup_acls_posix1e(struct archive_read_disk *a,
}
/*
- * Translate POSIX.1e ACL into libarchive internal structure.
+ * Translate system ACL into libarchive internal structure.
*/
-static void
-setup_acl_posix1e(struct archive_read_disk *a,
- struct archive_entry *entry, acl_t acl, int archive_entry_acl_type)
+
+static struct {
+ int archive_perm;
+ int platform_perm;
+} acl_perm_map[] = {
+ {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
+ {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
+ {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
+ {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
+ {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
+ {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
+ {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
+ {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
+ {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
+ {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
+ {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
+};
+
+static struct {
+ int archive_inherit;
+ int platform_inherit;
+} acl_inherit_map[] = {
+ {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
+};
+
+static int
+translate_acl(struct archive_read_disk *a,
+ struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
{
acl_tag_t acl_tag;
+ acl_entry_type_t acl_type;
+ acl_flagset_t acl_flagset;
acl_entry_t acl_entry;
acl_permset_t acl_permset;
+ int brand, i, r, entry_acl_type;
int s, ae_id, ae_tag, ae_perm;
const char *ae_name;
+
+ // FreeBSD "brands" ACLs as POSIX.1e or NFSv4
+ // Make sure the "brand" on this ACL is consistent
+ // with the default_entry_acl_type bits provided.
+ acl_get_brand_np(acl, &brand);
+ switch (brand) {
+ case ACL_BRAND_POSIX:
+ switch (default_entry_acl_type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+ case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+ break;
+ default:
+ // XXX set warning message?
+ return ARCHIVE_FAILED;
+ }
+ break;
+ case ACL_BRAND_NFS4:
+ if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ // XXX set warning message?
+ return ARCHIVE_FAILED;
+ }
+ break;
+ default:
+ // XXX set warning message?
+ return ARCHIVE_FAILED;
+ break;
+ }
+
+
s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
while (s == 1) {
ae_id = -1;
ae_name = NULL;
+ ae_perm = 0;
acl_get_tag_type(acl_entry, &acl_tag);
- if (acl_tag == ACL_USER) {
+ switch (acl_tag) {
+ case ACL_USER:
ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
ae_name = archive_read_disk_uname(&a->archive, ae_id);
ae_tag = ARCHIVE_ENTRY_ACL_USER;
- } else if (acl_tag == ACL_GROUP) {
+ break;
+ case ACL_GROUP:
ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry);
ae_name = archive_read_disk_gname(&a->archive, ae_id);
ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
- } else if (acl_tag == ACL_MASK) {
+ break;
+ case ACL_MASK:
ae_tag = ARCHIVE_ENTRY_ACL_MASK;
- } else if (acl_tag == ACL_USER_OBJ) {
+ break;
+ case ACL_USER_OBJ:
ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
- } else if (acl_tag == ACL_GROUP_OBJ) {
+ break;
+ case ACL_GROUP_OBJ:
ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
- } else if (acl_tag == ACL_OTHER) {
+ break;
+ case ACL_OTHER:
ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
- } else {
+ break;
+ case ACL_EVERYONE:
+ ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
+ break;
+ default:
/* Skip types that libarchive can't support. */
+ s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
continue;
}
- acl_get_permset(acl_entry, &acl_permset);
- ae_perm = 0;
+ // XXX acl type maps to allow/deny/audit/YYYY bits
+ // XXX acl_get_entry_type_np on FreeBSD returns EINVAL for
+ // non-NFSv4 ACLs
+ entry_acl_type = default_entry_acl_type;
+ r = acl_get_entry_type_np(acl_entry, &acl_type);
+ if (r == 0) {
+ switch (acl_type) {
+ case ACL_ENTRY_TYPE_ALLOW:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+ break;
+ case ACL_ENTRY_TYPE_DENY:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+ break;
+ case ACL_ENTRY_TYPE_AUDIT:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
+ break;
+ case ACL_ENTRY_TYPE_ALARM:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
+ break;
+ }
+ }
+
/*
- * acl_get_perm() is spelled differently on different
- * platforms; see above.
+ * Libarchive stores "flag" (NFSv4 inheritance bits)
+ * in the ae_perm bitmap.
*/
- if (ACL_GET_PERM(acl_permset, ACL_EXECUTE))
- ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE;
- if (ACL_GET_PERM(acl_permset, ACL_READ))
- ae_perm |= ARCHIVE_ENTRY_ACL_READ;
- if (ACL_GET_PERM(acl_permset, ACL_WRITE))
- ae_perm |= ARCHIVE_ENTRY_ACL_WRITE;
+ acl_get_flagset_np(acl_entry, &acl_flagset);
+ for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
+ if (acl_get_flag_np(acl_flagset,
+ acl_inherit_map[i].platform_inherit))
+ ae_perm |= acl_inherit_map[i].archive_inherit;
- archive_entry_acl_add_entry(entry,
- archive_entry_acl_type, ae_perm, ae_tag,
- ae_id, ae_name);
+ }
+
+ acl_get_permset(acl_entry, &acl_permset);
+ for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
+ /*
+ * acl_get_perm() is spelled differently on different
+ * platforms; see above.
+ */
+ if (ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm))
+ ae_perm |= acl_perm_map[i].archive_perm;
+ }
+
+ archive_entry_acl_add_entry(entry, entry_acl_type,
+ ae_perm, ae_tag,
+ ae_id, ae_name);
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
}
+ return (ARCHIVE_OK);
}
#else
static int
-setup_acls_posix1e(struct archive_read_disk *a,
+setup_acls(struct archive_read_disk *a,
struct archive_entry *entry, int *fd)
{
(void)a; /* UNUSED */
@@ -901,16 +1046,19 @@ setup_sparse(struct archive_read_disk *a,
path = archive_entry_pathname(entry);
if (a->tree != NULL)
*fd = a->open_on_current_dir(a->tree, path,
- O_RDONLY | O_NONBLOCK);
+ O_RDONLY | O_NONBLOCK | O_CLOEXEC);
else
- *fd = open(path, O_RDONLY | O_NONBLOCK);
+ *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
if (*fd < 0) {
archive_set_error(&a->archive, errno,
"Can't open `%s'", path);
return (ARCHIVE_FAILED);
}
+ __archive_ensure_cloexec_flag(*fd);
}
+ /* Initialize buffer to avoid the error valgrind complains about. */
+ memset(buff, 0, sizeof(buff));
count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe);
fm = (struct fiemap *)buff;
fm->fm_start = 0;
@@ -1012,12 +1160,13 @@ setup_sparse(struct archive_read_disk *a,
if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
return (ARCHIVE_OK);
- *fd = open(path, O_RDONLY | O_NONBLOCK);
+ *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
if (*fd < 0) {
archive_set_error(&a->archive, errno,
"Can't open `%s'", path);
return (ARCHIVE_FAILED);
}
+ __archive_ensure_cloexec_flag(*fd);
initial_off = 0;
}
diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c
index 698600e9b151..a13dbbf812cf 100644
--- a/libarchive/archive_read_disk_posix.c
+++ b/libarchive/archive_read_disk_posix.c
@@ -105,6 +105,9 @@ __FBSDID("$FreeBSD$");
#ifndef O_BINARY
#define O_BINARY 0
#endif
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
/*-
* This is a new directory-walking system that addresses a number
@@ -361,6 +364,7 @@ static int setup_sparse(struct archive_read_disk *, struct archive_entry *);
static int close_and_restore_time(int fd, struct tree *,
struct restore_time *);
static int open_on_current_dir(struct tree *, const char *, int);
+static int tree_dup(int);
static struct archive_vtable *
@@ -717,7 +721,7 @@ _archive_read_data_block(struct archive *_a, const void **buff,
* Open the current file.
*/
if (t->entry_fd < 0) {
- int flags = O_RDONLY | O_BINARY;
+ int flags = O_RDONLY | O_BINARY | O_CLOEXEC;
/*
* Eliminate or reduce cache effects if we can.
@@ -740,6 +744,7 @@ _archive_read_data_block(struct archive *_a, const void **buff,
#endif
t->entry_fd = open_on_current_dir(t,
tree_current_access_path(t), flags);
+ __archive_ensure_cloexec_flag(t->entry_fd);
#if defined(O_NOATIME)
/*
* When we did open the file with O_NOATIME flag,
@@ -984,10 +989,12 @@ next_entry(struct archive_read_disk *a, struct tree *t,
#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) &&\
defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) {
- unsigned long stflags;
+ int stflags;
t->entry_fd = open_on_current_dir(t,
- tree_current_access_path(t), O_RDONLY | O_NONBLOCK);
+ tree_current_access_path(t),
+ O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(t->entry_fd);
if (t->entry_fd >= 0) {
r = ioctl(t->entry_fd, EXT2_IOC_GETFLAGS,
&stflags);
@@ -1359,15 +1366,17 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
fid = t->max_filesystem_id++;
if (t->max_filesystem_id > t->allocated_filesytem) {
size_t s;
+ void *p;
s = t->max_filesystem_id * 2;
- t->filesystem_table = realloc(t->filesystem_table,
- s * sizeof(*t->filesystem_table));
- if (t->filesystem_table == NULL) {
+ p = realloc(t->filesystem_table,
+ s * sizeof(*t->filesystem_table));
+ if (p == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate tar data");
return (ARCHIVE_FATAL);
}
+ t->filesystem_table = (struct filesystem *)p;
t->allocated_filesytem = s;
}
t->current_filesystem_id = fid;
@@ -1482,7 +1491,8 @@ setup_current_filesystem(struct archive_read_disk *a)
* where current is.
*/
int fd = openat(tree_current_dir_fd(t),
- tree_current_access_path(t), O_RDONLY);
+ tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(fd);
if (fd < 0) {
archive_set_error(&a->archive, errno,
"openat failed");
@@ -1660,7 +1670,8 @@ setup_current_filesystem(struct archive_read_disk *a)
* where current is.
*/
int fd = openat(tree_current_dir_fd(t),
- tree_current_access_path(t), O_RDONLY);
+ tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(fd);
if (fd < 0) {
archive_set_error(&a->archive, errno,
"openat failed");
@@ -1768,7 +1779,8 @@ setup_current_filesystem(struct archive_read_disk *a)
* where current is.
*/
int fd = openat(tree_current_dir_fd(t),
- tree_current_access_path(t), O_RDONLY);
+ tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(fd);
if (fd < 0) {
archive_set_error(&a->archive, errno,
"openat failed");
@@ -1889,7 +1901,8 @@ static int
close_and_restore_time(int fd, struct tree *t, struct restore_time *rt)
{
#ifndef HAVE_UTIMES
- (void)a; /* UNUSED */
+ (void)t; /* UNUSED */
+ (void)rt; /* UNUSED */
return (close(fd));
#else
#if defined(HAVE_FUTIMENS) && !defined(__CYGWIN__)
@@ -1952,6 +1965,28 @@ open_on_current_dir(struct tree *t, const char *path, int flags)
#endif
}
+static int
+tree_dup(int fd)
+{
+ int new_fd;
+#ifdef F_DUPFD_CLOEXEC
+ static volatile int can_dupfd_cloexec = 1;
+
+ if (can_dupfd_cloexec) {
+ new_fd = fcntl(fd, F_DUPFD_CLOEXEC);
+ if (new_fd != -1)
+ return (new_fd);
+ /* Linux 2.6.18 - 2.6.23 declare F_DUPFD_CLOEXEC,
+ * but it cannot be used. So we have to try dup(). */
+ /* We won't try F_DUPFD_CLOEXEC. */
+ can_dupfd_cloexec = 0;
+ }
+#endif /* F_DUPFD_CLOEXEC */
+ new_fd = dup(fd);
+ __archive_ensure_cloexec_flag(new_fd);
+ return (new_fd);
+}
+
/*
* Add a directory path to the current stack.
*/
@@ -2052,8 +2087,9 @@ tree_reopen(struct tree *t, const char *path, int restore_time)
tree_push(t, path, 0, 0, 0, NULL);
t->stack->flags = needsFirstVisit;
t->maxOpenCount = t->openCount = 1;
- t->initial_dir_fd = open(".", O_RDONLY);
- t->working_dir_fd = dup(t->initial_dir_fd);
+ t->initial_dir_fd = open(".", O_RDONLY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(t->initial_dir_fd);
+ t->working_dir_fd = tree_dup(t->initial_dir_fd);
return (t);
}
@@ -2063,11 +2099,12 @@ tree_descent(struct tree *t)
int flag, new_fd, r = 0;
t->dirname_length = archive_strlen(&t->path);
- flag = O_RDONLY;
+ flag = O_RDONLY | O_CLOEXEC;
#if defined(O_DIRECTORY)
flag |= O_DIRECTORY;
#endif
new_fd = open_on_current_dir(t, t->stack->name.s, flag);
+ __archive_ensure_cloexec_flag(new_fd);
if (new_fd < 0) {
t->tree_errno = errno;
r = TREE_ERROR_DIR;
@@ -2101,8 +2138,10 @@ tree_ascend(struct tree *t)
prev_dir_fd = t->working_dir_fd;
if (te->flags & isDirLink)
new_fd = te->symlink_parent_fd;
- else
- new_fd = open_on_current_dir(t, "..", O_RDONLY);
+ else {
+ new_fd = open_on_current_dir(t, "..", O_RDONLY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(new_fd);
+ }
if (new_fd < 0) {
t->tree_errno = errno;
r = TREE_ERROR_FATAL;
@@ -2265,11 +2304,16 @@ tree_dir_next_posix(struct tree *t)
#endif
#if defined(HAVE_FDOPENDIR)
- if ((t->d = fdopendir(dup(t->working_dir_fd))) == NULL) {
-#else
- if (tree_enter_working_dir(t) != 0 ||
- (t->d = opendir(".")) == NULL) {
+ t->d = fdopendir(tree_dup(t->working_dir_fd));
+#else /* HAVE_FDOPENDIR */
+ if (tree_enter_working_dir(t) == 0) {
+ t->d = opendir(".");
+#if HAVE_DIRFD || defined(dirfd)
+ __archive_ensure_cloexec_flag(dirfd(t->d));
#endif
+ }
+#endif /* HAVE_FDOPENDIR */
+ if (t->d == NULL) {
r = tree_ascend(t); /* Undo "chdir" */
tree_pop(t);
t->tree_errno = errno;
@@ -2296,11 +2340,21 @@ tree_dir_next_posix(struct tree *t)
#endif /* HAVE_READDIR_R */
}
for (;;) {
+ errno = 0;
#if defined(HAVE_READDIR_R)
r = readdir_r(t->d, t->dirent, &t->de);
+#ifdef _AIX
+ /* Note: According to the man page, return value 9 indicates
+ * that the readdir_r was not successful and the error code
+ * is set to the global errno variable. And then if the end
+ * of directory entries was reached, the return value is 9
+ * and the third parameter is set to NULL and errno is
+ * unchanged. */
+ if (r == 9)
+ r = errno;
+#endif /* _AIX */
if (r != 0 || t->de == NULL) {
#else
- errno = 0;
t->de = readdir(t->d);
if (t->de == NULL) {
r = errno;
@@ -2391,7 +2445,7 @@ tree_current_is_dir(struct tree *t)
return 1;
/* Not a dir; might be a link to a dir. */
/* If it's not a link, then it's not a link to a dir. */
- if (!S_ISLNK(tree_current_lstat(t)->st_mode))
+ if (!S_ISLNK(st->st_mode))
return 0;
/*
* It's a link, but we don't know what it's a link to,
diff --git a/libarchive/archive_read_disk_windows.c b/libarchive/archive_read_disk_windows.c
index 6b6108ab1b0c..9c5420d80e77 100644
--- a/libarchive/archive_read_disk_windows.c
+++ b/libarchive/archive_read_disk_windows.c
@@ -597,7 +597,7 @@ start_next_async_read(struct archive_read_disk *a, struct tree *t)
} else
ResetEvent(olp->ol.hEvent);
- buffbytes = olp->buff_size;
+ buffbytes = (DWORD)olp->buff_size;
if (buffbytes > t->current_sparse->length)
buffbytes = (DWORD)t->current_sparse->length;
@@ -669,7 +669,7 @@ _archive_read_data_block(struct archive *_a, const void **buff,
struct tree *t = a->tree;
struct la_overlapped *olp;
DWORD bytes_transferred;
- int r;
+ int r = ARCHIVE_FATAL;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
"archive_read_data_block");
@@ -698,7 +698,7 @@ _archive_read_data_block(struct archive *_a, const void **buff,
olp = &(t->ol[t->ol_idx_done]);
t->ol_idx_done = (t->ol_idx_done + 1) % MAX_OVERLAPPED;
if (olp->bytes_transferred)
- bytes_transferred = olp->bytes_transferred;
+ bytes_transferred = (DWORD)olp->bytes_transferred;
else if (!GetOverlappedResult(t->entry_fh, &(olp->ol),
&bytes_transferred, TRUE)) {
la_dosmaperr(GetLastError());
@@ -1208,7 +1208,7 @@ _archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname)
a->tree = tree_open(pathname, a->symlink_mode, a->restore_time);
if (a->tree == NULL) {
archive_set_error(&a->archive, ENOMEM,
- "Can't allocate direcotry traversal data");
+ "Can't allocate directory traversal data");
a->archive.state = ARCHIVE_STATE_FATAL;
return (ARCHIVE_FATAL);
}
@@ -1257,16 +1257,18 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
fid = t->max_filesystem_id++;
if (t->max_filesystem_id > t->allocated_filesytem) {
size_t s;
+ void *p;
s = t->max_filesystem_id * 2;
- t->filesystem_table = realloc(t->filesystem_table,
- s * sizeof(*t->filesystem_table));
- if (t->filesystem_table == NULL) {
+ p = realloc(t->filesystem_table,
+ s * sizeof(*t->filesystem_table));
+ if (p == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate tar data");
return (ARCHIVE_FATAL);
}
- t->allocated_filesytem = s;
+ t->filesystem_table = (struct filesystem *)p;
+ t->allocated_filesytem = (int)s;
}
t->current_filesystem_id = fid;
t->current_filesystem = &(t->filesystem_table[fid]);
@@ -2040,7 +2042,7 @@ tree_free(struct tree *t)
free(t->filesystem_table);
for (i = 0; i < MAX_OVERLAPPED; i++) {
if (t->ol[i].buff)
- VirtualFree(t->ol[i].buff, t->ol[i].buff_size, MEM_DECOMMIT);
+ VirtualFree(t->ol[i].buff, 0, MEM_RELEASE);
CloseHandle(t->ol[i].ol.hEvent);
}
free(t);
@@ -2234,7 +2236,7 @@ setup_sparse_from_disk(struct archive_read_disk *a,
ret = DeviceIoControl(handle,
FSCTL_QUERY_ALLOCATED_RANGES,
&range, sizeof(range), outranges,
- outranges_size, &retbytes, NULL);
+ (DWORD)outranges_size, &retbytes, NULL);
if (ret == 0 && GetLastError() == ERROR_MORE_DATA) {
free(outranges);
outranges_size *= 2;
diff --git a/libarchive/archive_read_extract.c b/libarchive/archive_read_extract.c
index aad8ac5168df..795f2abea847 100644
--- a/libarchive/archive_read_extract.c
+++ b/libarchive/archive_read_extract.c
@@ -154,7 +154,7 @@ copy_data(struct archive *ar, struct archive *aw)
return (ARCHIVE_OK);
if (r != ARCHIVE_OK)
return (r);
- r = archive_write_data_block(aw, buff, size, offset);
+ r = (int)archive_write_data_block(aw, buff, size, offset);
if (r < ARCHIVE_WARN)
r = ARCHIVE_WARN;
if (r != ARCHIVE_OK) {
diff --git a/libarchive/archive_read_open_fd.c b/libarchive/archive_read_open_fd.c
index 7972841976b6..e0f95bf41b65 100644
--- a/libarchive/archive_read_open_fd.c
+++ b/libarchive/archive_read_open_fd.c
@@ -119,7 +119,8 @@ file_read(struct archive *a, void *client_data, const void **buff)
if (bytes_read < 0) {
if (errno == EINTR)
continue;
- archive_set_error(a, errno, "Error reading fd %d", mine->fd);
+ archive_set_error(a, errno, "Error reading fd %d",
+ mine->fd);
}
return (bytes_read);
}
diff --git a/libarchive/archive_read_open_file.c b/libarchive/archive_read_open_file.c
index b1aac0a7cbf0..3a33c258ee70 100644
--- a/libarchive/archive_read_open_file.c
+++ b/libarchive/archive_read_open_file.c
@@ -108,11 +108,11 @@ static ssize_t
file_read(struct archive *a, void *client_data, const void **buff)
{
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
- ssize_t bytes_read;
+ size_t bytes_read;
*buff = mine->buffer;
bytes_read = fread(mine->buffer, 1, mine->block_size, mine->f);
- if (bytes_read < 0) {
+ if (bytes_read < mine->block_size && ferror(mine->f)) {
archive_set_error(a, errno, "Error reading file");
}
return (bytes_read);
diff --git a/libarchive/archive_read_open_filename.c b/libarchive/archive_read_open_filename.c
index 69c44ea7e676..fefcd904d2c4 100644
--- a/libarchive/archive_read_open_filename.c
+++ b/libarchive/archive_read_open_filename.c
@@ -60,11 +60,15 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_open_filename.c 201093 2009
#endif
#include "archive.h"
+#include "archive_private.h"
#include "archive_string.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
struct read_file_data {
int fd;
@@ -79,9 +83,10 @@ struct read_file_data {
} filename; /* Must be last! */
};
+static int file_open(struct archive *, void *);
static int file_close(struct archive *, void *);
-static int file_open_filename(struct archive *, enum fnt_e, const void *,
- size_t);
+static int file_close2(struct archive *, void *);
+static int file_switch(struct archive *, void *, void *);
static ssize_t file_read(struct archive *, void *, const void **buff);
static int64_t file_seek(struct archive *, void *, int64_t request, int);
static int64_t file_skip(struct archive *, void *, int64_t request);
@@ -98,26 +103,76 @@ int
archive_read_open_filename(struct archive *a, const char *filename,
size_t block_size)
{
- enum fnt_e filename_type;
+ const char *filenames[2] = { filename, NULL };
+ return archive_read_open_filenames(a, filenames, block_size);
+}
+
+int
+archive_read_open_filenames(struct archive *a, const char **filenames,
+ size_t block_size)
+{
+ struct read_file_data *mine;
+ const char *filename = NULL;
+ if (filenames)
+ filename = *(filenames++);
- if (filename == NULL || filename[0] == '\0') {
- filename_type = FNT_STDIN;
- } else
- filename_type = FNT_MBS;
- return (file_open_filename(a, filename_type, filename, block_size));
+ archive_clear_error(a);
+ do
+ {
+ if (filename == NULL)
+ filename = "";
+ mine = (struct read_file_data *)calloc(1,
+ sizeof(*mine) + strlen(filename));
+ if (mine == NULL)
+ goto no_memory;
+ strcpy(mine->filename.m, filename);
+ mine->block_size = block_size;
+ mine->fd = -1;
+ mine->buffer = NULL;
+ mine->st_mode = mine->use_lseek = 0;
+ if (filename == NULL || filename[0] == '\0') {
+ mine->filename_type = FNT_STDIN;
+ } else
+ mine->filename_type = FNT_MBS;
+ if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK))
+ return (ARCHIVE_FATAL);
+ if (filenames == NULL)
+ break;
+ filename = *(filenames++);
+ } while (filename != NULL && filename[0] != '\0');
+ archive_read_set_open_callback(a, file_open);
+ archive_read_set_read_callback(a, file_read);
+ archive_read_set_skip_callback(a, file_skip);
+ archive_read_set_close_callback(a, file_close);
+ archive_read_set_switch_callback(a, file_switch);
+ archive_read_set_seek_callback(a, file_seek);
+
+ return (archive_read_open1(a));
+no_memory:
+ archive_set_error(a, ENOMEM, "No memory");
+ return (ARCHIVE_FATAL);
}
int
archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename,
size_t block_size)
{
- enum fnt_e filename_type;
+ struct read_file_data *mine = (struct read_file_data *)calloc(1,
+ sizeof(*mine) + wcslen(wfilename) * sizeof(wchar_t));
+ if (!mine)
+ {
+ archive_set_error(a, ENOMEM, "No memory");
+ return (ARCHIVE_FATAL);
+ }
+ mine->fd = -1;
+ mine->block_size = block_size;
if (wfilename == NULL || wfilename[0] == L'\0') {
- filename_type = FNT_STDIN;
+ mine->filename_type = FNT_STDIN;
} else {
#if defined(_WIN32) && !defined(__CYGWIN__)
- filename_type = FNT_WCS;
+ mine->filename_type = FNT_WCS;
+ wcscpy(mine->filename.w, wfilename);
#else
/*
* POSIX system does not support a wchar_t interface for
@@ -125,7 +180,6 @@ archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename,
* filename to multi-byte one and use it.
*/
struct archive_string fn;
- int r;
archive_string_init(&fn);
if (archive_string_append_from_wcs(&fn, wfilename,
@@ -138,22 +192,31 @@ archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename,
"Failed to convert a wide-character"
" filename to a multi-byte filename");
archive_string_free(&fn);
+ free(mine);
return (ARCHIVE_FATAL);
}
- r = file_open_filename(a, FNT_MBS, fn.s, block_size);
+ mine->filename_type = FNT_MBS;
+ strcpy(mine->filename.m, fn.s);
archive_string_free(&fn);
- return (r);
#endif
}
- return (file_open_filename(a, filename_type, wfilename, block_size));
+ if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK))
+ return (ARCHIVE_FATAL);
+ archive_read_set_open_callback(a, file_open);
+ archive_read_set_read_callback(a, file_read);
+ archive_read_set_skip_callback(a, file_skip);
+ archive_read_set_close_callback(a, file_close);
+ archive_read_set_switch_callback(a, file_switch);
+ archive_read_set_seek_callback(a, file_seek);
+
+ return (archive_read_open1(a));
}
static int
-file_open_filename(struct archive *a, enum fnt_e filename_type,
- const void *_filename, size_t block_size)
+file_open(struct archive *a, void *client_data)
{
struct stat st;
- struct read_file_data *mine;
+ struct read_file_data *mine = (struct read_file_data *)client_data;
void *buffer;
const char *filename = NULL;
const wchar_t *wfilename = NULL;
@@ -168,7 +231,7 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
#endif
archive_clear_error(a);
- if (filename_type == FNT_STDIN) {
+ if (mine->filename_type == FNT_STDIN) {
/* We used to delegate stdin support by
* directly calling archive_read_open_fd(a,0,block_size)
* here, but that doesn't (and shouldn't) handle the
@@ -183,9 +246,10 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
setmode(0, O_BINARY);
#endif
filename = "";
- } else if (filename_type == FNT_MBS) {
- filename = (const char *)_filename;
- fd = open(filename, O_RDONLY | O_BINARY);
+ } else if (mine->filename_type == FNT_MBS) {
+ filename = mine->filename.m;
+ fd = open(filename, O_RDONLY | O_BINARY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(fd);
if (fd < 0) {
archive_set_error(a, errno,
"Failed to open '%s'", filename);
@@ -193,7 +257,7 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
}
} else {
#if defined(_WIN32) && !defined(__CYGWIN__)
- wfilename = (const wchar_t *)_filename;
+ wfilename = mine->filename.w;
fd = _wopen(wfilename, O_RDONLY | O_BINARY);
if (fd < 0 && errno == ENOENT) {
wchar_t *fullpath;
@@ -215,7 +279,7 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
#endif
}
if (fstat(fd, &st) != 0) {
- if (filename_type == FNT_WCS)
+ if (mine->filename_type == FNT_WCS)
archive_set_error(a, errno, "Can't stat '%S'",
wfilename);
else
@@ -280,50 +344,32 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
#endif
/* TODO: Add an "is_tape_like" variable and appropriate tests. */
- if (filename_type == FNT_WCS)
- mine = (struct read_file_data *)calloc(1,
- sizeof(*mine) + wcslen(wfilename) * sizeof(wchar_t));
- else
- mine = (struct read_file_data *)calloc(1,
- sizeof(*mine) + strlen(filename));
/* Disk-like devices prefer power-of-two block sizes. */
/* Use provided block_size as a guide so users have some control. */
if (is_disk_like) {
size_t new_block_size = 64 * 1024;
- while (new_block_size < block_size
+ while (new_block_size < mine->block_size
&& new_block_size < 64 * 1024 * 1024)
new_block_size *= 2;
- block_size = new_block_size;
+ mine->block_size = new_block_size;
}
- buffer = malloc(block_size);
+ buffer = malloc(mine->block_size);
if (mine == NULL || buffer == NULL) {
archive_set_error(a, ENOMEM, "No memory");
free(mine);
free(buffer);
return (ARCHIVE_FATAL);
}
- if (filename_type == FNT_WCS)
- wcscpy(mine->filename.w, wfilename);
- else
- strcpy(mine->filename.m, filename);
- mine->filename_type = filename_type;
- mine->block_size = block_size;
mine->buffer = buffer;
mine->fd = fd;
/* Remember mode so close can decide whether to flush. */
mine->st_mode = st.st_mode;
/* Disk-like inputs can use lseek(). */
- if (is_disk_like) {
- archive_read_set_seek_callback(a, file_seek);
+ if (is_disk_like)
mine->use_lseek = 1;
- }
- archive_read_set_read_callback(a, file_read);
- archive_read_set_skip_callback(a, file_skip);
- archive_read_set_close_callback(a, file_close);
- archive_read_set_callback_data(a, mine);
- return (archive_read_open1(a));
+ return (ARCHIVE_OK);
}
static ssize_t
@@ -401,9 +447,7 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request)
/* TODO: Deal with case where off_t isn't 64 bits.
* This shouldn't be a problem on Linux or other POSIX
* systems, since the configuration logic for libarchive
- * tries to obtain a 64-bit off_t. It's still an issue
- * on Windows, though, so it might suffice to just use
- * _lseeki64() on Windows.
+ * tries to obtain a 64-bit off_t.
*/
if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0 &&
(new_offset = lseek(mine->fd, request, SEEK_CUR)) >= 0)
@@ -475,7 +519,7 @@ file_seek(struct archive *a, void *client_data, int64_t request, int whence)
}
static int
-file_close(struct archive *a, void *client_data)
+file_close2(struct archive *a, void *client_data)
{
struct read_file_data *mine = (struct read_file_data *)client_data;
@@ -508,6 +552,23 @@ file_close(struct archive *a, void *client_data)
close(mine->fd);
}
free(mine->buffer);
+ mine->buffer = NULL;
+ mine->fd = -1;
+ return (ARCHIVE_OK);
+}
+
+static int
+file_close(struct archive *a, void *client_data)
+{
+ struct read_file_data *mine = (struct read_file_data *)client_data;
+ file_close2(a, client_data);
free(mine);
return (ARCHIVE_OK);
}
+
+static int
+file_switch(struct archive *a, void *client_data1, void *client_data2)
+{
+ file_close2(a, client_data1);
+ return file_open(a, client_data2);
+}
diff --git a/libarchive/archive_read_private.h b/libarchive/archive_read_private.h
index 445c557f39c2..8a6c859a8a14 100644
--- a/libarchive/archive_read_private.h
+++ b/libarchive/archive_read_private.h
@@ -58,6 +58,8 @@ struct archive_read_filter;
struct archive_read_filter_bidder {
/* Configuration data for the bidder. */
void *data;
+ /* Name of the filter */
+ const char *name;
/* Taste the upstream filter to see if we handle this. */
int (*bid)(struct archive_read_filter_bidder *,
struct archive_read_filter *);
@@ -82,6 +84,8 @@ struct archive_read_filter {
struct archive_read_filter_bidder *bidder; /* My bidder. */
struct archive_read_filter *upstream; /* Who I read from. */
struct archive_read *archive; /* Associated archive. */
+ /* Open a block for reading */
+ int (*open)(struct archive_read_filter *self);
/* Return next block. */
ssize_t (*read)(struct archive_read_filter *, const void **);
/* Skip forward this many bytes. */
@@ -90,6 +94,8 @@ struct archive_read_filter {
int64_t (*seek)(struct archive_read_filter *self, int64_t offset, int whence);
/* Close (just this filter) and free(self). */
int (*close)(struct archive_read_filter *self);
+ /* Function that handles switching from reading one block to the next/prev */
+ int (*sswitch)(struct archive_read_filter *self, unsigned int iindex);
/* My private data. */
void *data;
@@ -118,13 +124,22 @@ struct archive_read_filter {
* transformation filters. This will probably break the API/ABI and
* so should be deferred at least until libarchive 3.0.
*/
+struct archive_read_data_node {
+ int64_t begin_position;
+ int64_t total_size;
+ void *data;
+};
struct archive_read_client {
archive_open_callback *opener;
archive_read_callback *reader;
archive_skip_callback *skipper;
archive_seek_callback *seeker;
archive_close_callback *closer;
- void *data;
+ archive_switch_callback *switcher;
+ unsigned int nodes;
+ unsigned int cursor;
+ int64_t position;
+ struct archive_read_data_node *dataset;
};
struct archive_read {
@@ -146,18 +161,33 @@ struct archive_read {
int64_t read_data_output_offset;
size_t read_data_remaining;
- /* Callbacks to open/read/write/close client archive stream. */
+ /*
+ * Used by formats/filters to determine the amount of data
+ * requested from a call to archive_read_data(). This is only
+ * useful when the format/filter has seek support.
+ */
+ char read_data_is_posix_read;
+ size_t read_data_requested;
+
+ /* Callbacks to open/read/write/close client archive streams. */
struct archive_read_client client;
/* Registered filter bidders. */
- struct archive_read_filter_bidder bidders[9];
+ struct archive_read_filter_bidder bidders[14];
/* Last filter in chain */
struct archive_read_filter *filter;
+ /* Whether to bypass filter bidding process */
+ int bypass_filter_bidding;
+
/* File offset of beginning of most recently-read header. */
int64_t header_position;
+ /* Nodes and offsets of compressed data block */
+ unsigned int data_start_node;
+ unsigned int data_end_node;
+
/*
* Format detection is mostly the same as compression
* detection, with one significant difference: The bidders
@@ -175,6 +205,7 @@ struct archive_read {
int (*read_header)(struct archive_read *, struct archive_entry *);
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *);
int (*read_data_skip)(struct archive_read *);
+ int64_t (*seek_data)(struct archive_read *, int64_t, int);
int (*cleanup)(struct archive_read *);
} formats[16];
struct archive_format_descriptor *format; /* Active format. */
@@ -194,6 +225,7 @@ int __archive_read_register_format(struct archive_read *a,
int (*read_header)(struct archive_read *, struct archive_entry *),
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
int (*read_data_skip)(struct archive_read *),
+ int64_t (*seek_data)(struct archive_read *, int64_t, int),
int (*cleanup)(struct archive_read *));
int __archive_read_get_bidder(struct archive_read *a,
@@ -207,4 +239,6 @@ int64_t __archive_read_filter_seek(struct archive_read_filter *, int64_t, int);
int64_t __archive_read_consume(struct archive_read *, int64_t);
int64_t __archive_read_filter_consume(struct archive_read_filter *, int64_t);
int __archive_read_program(struct archive_read_filter *, const char *);
+void __archive_read_free_filters(struct archive_read *);
+int __archive_read_close_filters(struct archive_read *);
#endif
diff --git a/libarchive/archive_read_set_format.c b/libarchive/archive_read_set_format.c
new file mode 100644
index 000000000000..190f4369d248
--- /dev/null
+++ b/libarchive/archive_read_set_format.c
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 2003-2012 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+int
+archive_read_set_format(struct archive *_a, int code)
+{
+ int r1, r2, slots, i;
+ char str[10];
+ struct archive_read *a = (struct archive_read *)_a;
+
+ if ((r1 = archive_read_support_format_by_code(_a, code)) < (ARCHIVE_OK))
+ return r1;
+
+ r1 = r2 = (ARCHIVE_OK);
+ if (a->format)
+ r2 = (ARCHIVE_WARN);
+ switch (code & ARCHIVE_FORMAT_BASE_MASK)
+ {
+ case ARCHIVE_FORMAT_7ZIP:
+ strcpy(str, "7zip");
+ break;
+ case ARCHIVE_FORMAT_AR:
+ strcpy(str, "ar");
+ break;
+ case ARCHIVE_FORMAT_CAB:
+ strcpy(str, "cab");
+ break;
+ case ARCHIVE_FORMAT_CPIO:
+ strcpy(str, "cpio");
+ break;
+ case ARCHIVE_FORMAT_ISO9660:
+ strcpy(str, "iso9660");
+ break;
+ case ARCHIVE_FORMAT_LHA:
+ strcpy(str, "lha");
+ break;
+ case ARCHIVE_FORMAT_MTREE:
+ strcpy(str, "mtree");
+ break;
+ case ARCHIVE_FORMAT_RAR:
+ strcpy(str, "rar");
+ break;
+ case ARCHIVE_FORMAT_TAR:
+ strcpy(str, "tar");
+ break;
+ case ARCHIVE_FORMAT_XAR:
+ strcpy(str, "xar");
+ break;
+ case ARCHIVE_FORMAT_ZIP:
+ strcpy(str, "zip");
+ break;
+ default:
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Invalid format code specified");
+ return (ARCHIVE_FATAL);
+ }
+
+ slots = sizeof(a->formats) / sizeof(a->formats[0]);
+ a->format = &(a->formats[0]);
+ for (i = 0; i < slots; i++, a->format++) {
+ if (!a->format->name || !strcmp(a->format->name, str))
+ break;
+ }
+ if (!a->format->name || strcmp(a->format->name, str))
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Internal error: Unable to set format");
+ r1 = (ARCHIVE_FATAL);
+ }
+
+ return (r1 < r2) ? r1 : r2;
+}
diff --git a/libarchive/archive_read_support_filter_all.c b/libarchive/archive_read_support_filter_all.c
index 733d86298434..b778cfb79215 100644
--- a/libarchive/archive_read_support_filter_all.c
+++ b/libarchive/archive_read_support_filter_all.c
@@ -48,7 +48,7 @@ archive_read_support_filter_all(struct archive *a)
archive_read_support_filter_bzip2(a);
/* The decompress code doesn't use an outside library. */
archive_read_support_filter_compress(a);
- /* Gzip decompress falls back to "gunzip" command-line. */
+ /* Gzip decompress falls back to "gzip -d" command-line. */
archive_read_support_filter_gzip(a);
/* Lzip falls back to "unlzip" command-line program. */
archive_read_support_filter_lzip(a);
@@ -63,6 +63,12 @@ archive_read_support_filter_all(struct archive *a)
archive_read_support_filter_uu(a);
/* The decode code doesn't use an outside library. */
archive_read_support_filter_rpm(a);
+ /* The decode code always uses "lrzip -q -d" command-line. */
+ archive_read_support_filter_lrzip(a);
+ /* Lzop decompress falls back to "lzop -d" command-line. */
+ archive_read_support_filter_lzop(a);
+ /* The decode code always uses "grzip -d" command-line. */
+ archive_read_support_filter_grzip(a);
/* Note: We always return ARCHIVE_OK here, even if some of the
* above return ARCHIVE_WARN. The intent here is to enable
diff --git a/libarchive/archive_read_support_filter_bzip2.c b/libarchive/archive_read_support_filter_bzip2.c
index 8d5bd1c4aca6..3885a7cf6153 100644
--- a/libarchive/archive_read_support_filter_bzip2.c
+++ b/libarchive/archive_read_support_filter_bzip2.c
@@ -94,6 +94,7 @@ archive_read_support_filter_bzip2(struct archive *_a)
return (ARCHIVE_FATAL);
reader->data = NULL;
+ reader->name = "bzip2";
reader->bid = bzip2_reader_bid;
reader->init = bzip2_reader_init;
reader->options = NULL;
@@ -102,7 +103,7 @@ archive_read_support_filter_bzip2(struct archive *_a)
return (ARCHIVE_OK);
#else
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
- "Using external bunzip2 program");
+ "Using external bzip2 program");
return (ARCHIVE_WARN);
#endif
}
@@ -170,11 +171,11 @@ bzip2_reader_init(struct archive_read_filter *self)
{
int r;
- r = __archive_read_program(self, "bunzip2");
+ r = __archive_read_program(self, "bzip2 -d");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
- self->code = ARCHIVE_COMPRESSION_BZIP2;
+ self->code = ARCHIVE_FILTER_BZIP2;
self->name = "bzip2";
return (r);
}
@@ -192,7 +193,7 @@ bzip2_reader_init(struct archive_read_filter *self)
void *out_block;
struct private_data *state;
- self->code = ARCHIVE_COMPRESSION_BZIP2;
+ self->code = ARCHIVE_FILTER_BZIP2;
self->name = "bzip2";
state = (struct private_data *)calloc(sizeof(*state), 1);
diff --git a/libarchive/archive_read_support_filter_compress.c b/libarchive/archive_read_support_filter_compress.c
index 1b8530004fbb..3f5d1f37eab3 100644
--- a/libarchive/archive_read_support_filter_compress.c
+++ b/libarchive/archive_read_support_filter_compress.c
@@ -163,6 +163,7 @@ archive_read_support_filter_compress(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
+ bidder->name = "compress (.Z)";
bidder->bid = compress_bidder_bid;
bidder->init = compress_bidder_init;
bidder->options = NULL;
@@ -212,7 +213,7 @@ compress_bidder_init(struct archive_read_filter *self)
void *out_block;
int code;
- self->code = ARCHIVE_COMPRESSION_COMPRESS;
+ self->code = ARCHIVE_FILTER_COMPRESS;
self->name = "compress (.Z)";
state = (struct private_data *)calloc(sizeof(*state), 1);
diff --git a/libarchive/archive_read_support_filter_grzip.c b/libarchive/archive_read_support_filter_grzip.c
new file mode 100644
index 000000000000..84c86aeb4386
--- /dev/null
+++ b/libarchive/archive_read_support_filter_grzip.c
@@ -0,0 +1,121 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+static const unsigned char grzip_magic[] = {
+ 0x47, 0x52, 0x5a, 0x69, 0x70, 0x49, 0x49, 0x00,
+ 0x02, 0x04, 0x3a, 0x29 };
+
+static int grzip_bidder_bid(struct archive_read_filter_bidder *,
+ struct archive_read_filter *);
+static int grzip_bidder_init(struct archive_read_filter *);
+
+
+static int
+grzip_reader_free(struct archive_read_filter_bidder *self)
+{
+ (void)self; /* UNUSED */
+ return (ARCHIVE_OK);
+}
+
+int
+archive_read_support_filter_grzip(struct archive *_a)
+{
+ struct archive_read *a = (struct archive_read *)_a;
+ struct archive_read_filter_bidder *reader;
+
+ archive_check_magic(_a, ARCHIVE_READ_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_read_support_filter_grzip");
+
+ if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+
+ reader->data = NULL;
+ reader->bid = grzip_bidder_bid;
+ reader->init = grzip_bidder_init;
+ reader->options = NULL;
+ reader->free = grzip_reader_free;
+ /* This filter always uses an external program. */
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "Using external grzip program for grzip decompression");
+ return (ARCHIVE_WARN);
+}
+
+/*
+ * Bidder just verifies the header and returns the number of verified bits.
+ */
+static int
+grzip_bidder_bid(struct archive_read_filter_bidder *self,
+ struct archive_read_filter *filter)
+{
+ const unsigned char *p;
+ ssize_t avail;
+
+ (void)self; /* UNUSED */
+
+ p = __archive_read_filter_ahead(filter, sizeof(grzip_magic), &avail);
+ if (p == NULL || avail == 0)
+ return (0);
+
+ if (memcmp(p, grzip_magic, sizeof(grzip_magic)))
+ return (0);
+
+ return (sizeof(grzip_magic) * 8);
+}
+
+static int
+grzip_bidder_init(struct archive_read_filter *self)
+{
+ int r;
+
+ r = __archive_read_program(self, "grzip -d");
+ /* Note: We set the format here even if __archive_read_program()
+ * above fails. We do, after all, know what the format is
+ * even if we weren't able to read it. */
+ self->code = ARCHIVE_FILTER_GRZIP;
+ self->name = "grzip";
+ return (r);
+}
diff --git a/libarchive/archive_read_support_filter_gzip.c b/libarchive/archive_read_support_filter_gzip.c
index f6d5595f0b6b..fa8c675de124 100644
--- a/libarchive/archive_read_support_filter_gzip.c
+++ b/libarchive/archive_read_support_filter_gzip.c
@@ -72,7 +72,7 @@ static int gzip_filter_close(struct archive_read_filter *);
*
* TODO: If zlib is unavailable, gzip_bidder_init() should
* use the compress_program framework to try to fire up an external
- * gunzip program.
+ * gzip program.
*/
static int gzip_bidder_bid(struct archive_read_filter_bidder *,
struct archive_read_filter *);
@@ -100,6 +100,7 @@ archive_read_support_filter_gzip(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
+ bidder->name = "gzip";
bidder->bid = gzip_bidder_bid;
bidder->init = gzip_bidder_init;
bidder->options = NULL;
@@ -109,7 +110,7 @@ archive_read_support_filter_gzip(struct archive *_a)
return (ARCHIVE_OK);
#else
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
- "Using external gunzip program");
+ "Using external gzip program");
return (ARCHIVE_WARN);
#endif
}
@@ -121,7 +122,7 @@ archive_read_support_filter_gzip(struct archive *_a)
* number of bytes in header. If pbits is non-NULL, it receives a
* count of bits verified, suitable for use by bidder.
*/
-static int
+static ssize_t
peek_at_header(struct archive_read_filter *filter, int *pbits)
{
const unsigned char *p;
@@ -223,7 +224,7 @@ gzip_bidder_bid(struct archive_read_filter_bidder *self,
/*
* If we don't have the library on this system, we can't do the
- * decompression directly. We can, however, try to run gunzip
+ * decompression directly. We can, however, try to run "gzip -d"
* in case that's available.
*/
static int
@@ -231,11 +232,11 @@ gzip_bidder_init(struct archive_read_filter *self)
{
int r;
- r = __archive_read_program(self, "gunzip");
+ r = __archive_read_program(self, "gzip -d");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
- self->code = ARCHIVE_COMPRESSION_GZIP;
+ self->code = ARCHIVE_FILTER_GZIP;
self->name = "gzip";
return (r);
}
@@ -252,7 +253,7 @@ gzip_bidder_init(struct archive_read_filter *self)
static const size_t out_block_size = 64 * 1024;
void *out_block;
- self->code = ARCHIVE_COMPRESSION_GZIP;
+ self->code = ARCHIVE_FILTER_GZIP;
self->name = "gzip";
state = (struct private_data *)calloc(sizeof(*state), 1);
@@ -299,7 +300,7 @@ consume_header(struct archive_read_filter *self)
/* Initialize compression library. */
state->stream.next_in = (unsigned char *)(uintptr_t)
__archive_read_filter_ahead(self->upstream, 1, &avail);
- state->stream.avail_in = avail;
+ state->stream.avail_in = (uInt)avail;
ret = inflateInit2(&(state->stream),
-15 /* Don't check for zlib header */);
@@ -380,7 +381,7 @@ gzip_filter_read(struct archive_read_filter *self, const void **p)
/* Empty our output buffer. */
state->stream.next_out = state->out_block;
- state->stream.avail_out = state->out_block_size;
+ state->stream.avail_out = (uInt)state->out_block_size;
/* Try to fill the output buffer. */
while (state->stream.avail_out > 0 && !state->eof) {
@@ -407,7 +408,7 @@ gzip_filter_read(struct archive_read_filter *self, const void **p)
"truncated gzip input");
return (ARCHIVE_FATAL);
}
- state->stream.avail_in = avail_in;
+ state->stream.avail_in = (uInt)avail_in;
/* Decompress and consume some of that data. */
ret = inflate(&(state->stream), 0);
diff --git a/libarchive/archive_read_support_filter_lrzip.c b/libarchive/archive_read_support_filter_lrzip.c
new file mode 100644
index 000000000000..c82a8e2f13ea
--- /dev/null
+++ b/libarchive/archive_read_support_filter_lrzip.c
@@ -0,0 +1,132 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+#define LRZIP_HEADER_MAGIC "LRZI"
+#define LRZIP_HEADER_MAGIC_LEN 4
+
+static int lrzip_bidder_bid(struct archive_read_filter_bidder *,
+ struct archive_read_filter *);
+static int lrzip_bidder_init(struct archive_read_filter *);
+
+
+static int
+lrzip_reader_free(struct archive_read_filter_bidder *self)
+{
+ (void)self; /* UNUSED */
+ return (ARCHIVE_OK);
+}
+
+int
+archive_read_support_filter_lrzip(struct archive *_a)
+{
+ struct archive_read *a = (struct archive_read *)_a;
+ struct archive_read_filter_bidder *reader;
+
+ archive_check_magic(_a, ARCHIVE_READ_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_read_support_filter_lrzip");
+
+ if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+
+ reader->data = NULL;
+ reader->name = "lrzip";
+ reader->bid = lrzip_bidder_bid;
+ reader->init = lrzip_bidder_init;
+ reader->options = NULL;
+ reader->free = lrzip_reader_free;
+ /* This filter always uses an external program. */
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "Using external lrzip program for lrzip decompression");
+ return (ARCHIVE_WARN);
+}
+
+/*
+ * Bidder just verifies the header and returns the number of verified bits.
+ */
+static int
+lrzip_bidder_bid(struct archive_read_filter_bidder *self,
+ struct archive_read_filter *filter)
+{
+ const unsigned char *p;
+ ssize_t avail, len;
+ int i;
+
+ (void)self; /* UNUSED */
+ /* Start by looking at the first six bytes of the header, which
+ * is all fixed layout. */
+ len = 6;
+ p = __archive_read_filter_ahead(filter, len, &avail);
+ if (p == NULL || avail == 0)
+ return (0);
+
+ if (memcmp(p, LRZIP_HEADER_MAGIC, LRZIP_HEADER_MAGIC_LEN))
+ return (0);
+
+ /* current major version is always 0, verify this */
+ if (p[LRZIP_HEADER_MAGIC_LEN])
+ return 0;
+ /* support only v0.6+ lrzip for sanity */
+ i = p[LRZIP_HEADER_MAGIC_LEN + 1];
+ if ((i < 6) || (i > 10))
+ return 0;
+
+ return (int)len;
+}
+
+static int
+lrzip_bidder_init(struct archive_read_filter *self)
+{
+ int r;
+
+ r = __archive_read_program(self, "lrzip -d -q");
+ /* Note: We set the format here even if __archive_read_program()
+ * above fails. We do, after all, know what the format is
+ * even if we weren't able to read it. */
+ self->code = ARCHIVE_FILTER_LRZIP;
+ self->name = "lrzip";
+ return (r);
+}
diff --git a/libarchive/archive_read_support_filter_lzop.c b/libarchive/archive_read_support_filter_lzop.c
new file mode 100644
index 000000000000..713af31e99f0
--- /dev/null
+++ b/libarchive/archive_read_support_filter_lzop.c
@@ -0,0 +1,486 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_LZO_LZOCONF_H
+#include <lzo/lzoconf.h>
+#endif
+#ifdef HAVE_LZO_LZO1X_H
+#include <lzo/lzo1x.h>
+#endif
+#ifdef HAVE_ZLIB_H
+#include <zlib.h> /* for crc32 and adler32 */
+#endif
+
+#include "archive.h"
+#if !defined(HAVE_ZLIB_H) &&\
+ defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
+#include "archive_crc32.h"
+#endif
+#include "archive_endian.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+#ifndef HAVE_ZLIB_H
+#define adler32 lzo_adler32
+#endif
+
+#define LZOP_HEADER_MAGIC "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a"
+#define LZOP_HEADER_MAGIC_LEN 9
+
+#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
+struct read_lzop {
+ unsigned char *out_block;
+ size_t out_block_size;
+ int64_t total_out;
+ int flags;
+ uint32_t compressed_cksum;
+ uint32_t uncompressed_cksum;
+ size_t compressed_size;
+ size_t uncompressed_size;
+ size_t unconsumed_bytes;
+ char in_stream;
+ char eof; /* True = found end of compressed data. */
+};
+
+#define FILTER 0x0800
+#define CRC32_HEADER 0x1000
+#define EXTRA_FIELD 0x0040
+#define ADLER32_UNCOMPRESSED 0x0001
+#define ADLER32_COMPRESSED 0x0002
+#define CRC32_UNCOMPRESSED 0x0100
+#define CRC32_COMPRESSED 0x0200
+#define MAX_BLOCK_SIZE (64 * 1024 * 1024)
+
+static ssize_t lzop_filter_read(struct archive_read_filter *, const void **);
+static int lzop_filter_close(struct archive_read_filter *);
+#endif
+
+static int lzop_bidder_bid(struct archive_read_filter_bidder *,
+ struct archive_read_filter *);
+static int lzop_bidder_init(struct archive_read_filter *);
+
+int
+archive_read_support_filter_lzop(struct archive *_a)
+{
+ struct archive_read *a = (struct archive_read *)_a;
+ struct archive_read_filter_bidder *reader;
+
+ archive_check_magic(_a, ARCHIVE_READ_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_read_support_filter_lzop");
+
+ if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+
+ reader->data = NULL;
+ reader->bid = lzop_bidder_bid;
+ reader->init = lzop_bidder_init;
+ reader->options = NULL;
+ reader->free = NULL;
+ /* Signal the extent of lzop support with the return value here. */
+#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
+ return (ARCHIVE_OK);
+#else
+ /* Return ARCHIVE_WARN since this always uses an external program. */
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "Using external lzop program for lzop decompression");
+ return (ARCHIVE_WARN);
+#endif
+}
+
+/*
+ * Bidder just verifies the header and returns the number of verified bits.
+ */
+static int
+lzop_bidder_bid(struct archive_read_filter_bidder *self,
+ struct archive_read_filter *filter)
+{
+ const unsigned char *p;
+ ssize_t avail;
+
+ (void)self; /* UNUSED */
+
+ p = __archive_read_filter_ahead(filter, LZOP_HEADER_MAGIC_LEN, &avail);
+ if (p == NULL || avail == 0)
+ return (0);
+
+ if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN))
+ return (0);
+
+ return (LZOP_HEADER_MAGIC_LEN * 8);
+}
+
+#if !defined(HAVE_LZO_LZOCONF_H) || !defined(HAVE_LZO_LZO1X_H)
+/*
+ * If we don't have the library on this system, we can't do the
+ * decompression directly. We can, however, try to run "lzop -d"
+ * in case that's available.
+ */
+static int
+lzop_bidder_init(struct archive_read_filter *self)
+{
+ int r;
+
+ r = __archive_read_program(self, "lzop -d");
+ /* Note: We set the format here even if __archive_read_program()
+ * above fails. We do, after all, know what the format is
+ * even if we weren't able to read it. */
+ self->code = ARCHIVE_FILTER_LZOP;
+ self->name = "lzop";
+ return (r);
+}
+#else
+/*
+ * Initialize the filter object.
+ */
+static int
+lzop_bidder_init(struct archive_read_filter *self)
+{
+ struct read_lzop *state;
+
+ self->code = ARCHIVE_FILTER_LZOP;
+ self->name = "lzop";
+
+ state = (struct read_lzop *)calloc(sizeof(*state), 1);
+ if (state == NULL) {
+ archive_set_error(&self->archive->archive, ENOMEM,
+ "Can't allocate data for lzop decompression");
+ return (ARCHIVE_FATAL);
+ }
+
+ self->data = state;
+ self->read = lzop_filter_read;
+ self->skip = NULL; /* not supported */
+ self->close = lzop_filter_close;
+
+ return (ARCHIVE_OK);
+}
+
+static int
+consume_header(struct archive_read_filter *self)
+{
+ struct read_lzop *state = (struct read_lzop *)self->data;
+ const unsigned char *p, *_p;
+ unsigned checksum, flags, len, method, version;
+
+ /*
+ * Check LZOP magic code.
+ */
+ p = __archive_read_filter_ahead(self->upstream,
+ LZOP_HEADER_MAGIC_LEN, NULL);
+ if (p == NULL)
+ return (ARCHIVE_EOF);
+
+ if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN))
+ return (ARCHIVE_EOF);
+ __archive_read_filter_consume(self->upstream,
+ LZOP_HEADER_MAGIC_LEN);
+
+ p = __archive_read_filter_ahead(self->upstream, 29, NULL);
+ if (p == NULL)
+ goto truncated;
+ _p = p;
+ version = archive_be16dec(p);
+ p += 4;/* version(2 bytes) + library version(2 bytes) */
+
+ if (version >= 0x940) {
+ unsigned reqversion = archive_be16dec(p); p += 2;
+ if (reqversion < 0x900) {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC, "Invalid required version");
+ return (ARCHIVE_FAILED);
+ }
+ }
+
+ method = *p++;
+ if (method < 1 || method > 3) {
+ archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
+ "Unsupported method");
+ return (ARCHIVE_FAILED);
+ }
+
+ if (version >= 0x940) {
+ unsigned level = *p++;
+ if (method == 1 && level == 0) level = 3;
+ if (method == 2 && level == 0) level = 1;
+ if (method == 3 && level == 0) level = 9;
+ if (level < 1 && level > 9) {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC, "Invalid level");
+ return (ARCHIVE_FAILED);
+ }
+ }
+
+ flags = archive_be32dec(p); p += 4;
+
+ if (flags & FILTER)
+ p += 4; /* Skip filter */
+ p += 4; /* Skip mode */
+ if (version >= 0x940)
+ p += 8; /* Skip mtime */
+ else
+ p += 4; /* Skip mtime */
+ len = *p++; /* Read filename length */
+ len += p - _p;
+ /* Make sure we have all bytes we need to calculate checksum. */
+ p = __archive_read_filter_ahead(self->upstream, len + 4, NULL);
+ if (p == NULL)
+ goto truncated;
+ if (flags & CRC32_HEADER)
+ checksum = crc32(crc32(0, NULL, 0), p, len);
+ else
+ checksum = adler32(adler32(0, NULL, 0), p, len);
+ if (archive_be32dec(p + len) != checksum)
+ goto corrupted;
+ __archive_read_filter_consume(self->upstream, len + 4);
+ if (flags & EXTRA_FIELD) {
+ /* Skip extra field */
+ p = __archive_read_filter_ahead(self->upstream, 4, NULL);
+ if (p == NULL)
+ goto truncated;
+ len = archive_be32dec(p);
+ __archive_read_filter_consume(self->upstream, len + 4 + 4);
+ }
+ state->flags = flags;
+ state->in_stream = 1;
+ return (ARCHIVE_OK);
+truncated:
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data");
+ return (ARCHIVE_FAILED);
+corrupted:
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header");
+ return (ARCHIVE_FAILED);
+}
+
+static int
+consume_block_info(struct archive_read_filter *self)
+{
+ struct read_lzop *state = (struct read_lzop *)self->data;
+ const unsigned char *p;
+ unsigned flags = state->flags;
+
+ p = __archive_read_filter_ahead(self->upstream, 4, NULL);
+ if (p == NULL)
+ goto truncated;
+ state->uncompressed_size = archive_be32dec(p);
+ __archive_read_filter_consume(self->upstream, 4);
+ if (state->uncompressed_size == 0)
+ return (ARCHIVE_EOF);
+ if (state->uncompressed_size > MAX_BLOCK_SIZE)
+ goto corrupted;
+
+ p = __archive_read_filter_ahead(self->upstream, 4, NULL);
+ if (p == NULL)
+ goto truncated;
+ state->compressed_size = archive_be32dec(p);
+ __archive_read_filter_consume(self->upstream, 4);
+ if (state->compressed_size > state->uncompressed_size)
+ goto corrupted;
+
+ if (flags & (CRC32_UNCOMPRESSED | ADLER32_UNCOMPRESSED)) {
+ p = __archive_read_filter_ahead(self->upstream, 4, NULL);
+ if (p == NULL)
+ goto truncated;
+ state->compressed_cksum = state->uncompressed_cksum =
+ archive_be32dec(p);
+ __archive_read_filter_consume(self->upstream, 4);
+ }
+ if ((flags & (CRC32_COMPRESSED | ADLER32_COMPRESSED)) &&
+ state->compressed_size < state->uncompressed_size) {
+ p = __archive_read_filter_ahead(self->upstream, 4, NULL);
+ if (p == NULL)
+ goto truncated;
+ state->compressed_cksum = archive_be32dec(p);
+ __archive_read_filter_consume(self->upstream, 4);
+ }
+ return (ARCHIVE_OK);
+truncated:
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data");
+ return (ARCHIVE_FAILED);
+corrupted:
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header");
+ return (ARCHIVE_FAILED);
+}
+
+static ssize_t
+lzop_filter_read(struct archive_read_filter *self, const void **p)
+{
+ struct read_lzop *state = (struct read_lzop *)self->data;
+ const void *b;
+ lzo_uint out_size;
+ uint32_t cksum;
+ int ret, r;
+
+ if (state->unconsumed_bytes) {
+ __archive_read_filter_consume(self->upstream,
+ state->unconsumed_bytes);
+ state->unconsumed_bytes = 0;
+ }
+ if (state->eof)
+ return (0);
+
+ for (;;) {
+ if (!state->in_stream) {
+ ret = consume_header(self);
+ if (ret < ARCHIVE_OK)
+ return (ret);
+ if (ret == ARCHIVE_EOF) {
+ state->eof = 1;
+ return (0);
+ }
+ }
+ ret = consume_block_info(self);
+ if (ret < ARCHIVE_OK)
+ return (ret);
+ if (ret == ARCHIVE_EOF)
+ state->in_stream = 0;
+ else
+ break;
+ }
+
+ if (state->out_block == NULL ||
+ state->out_block_size < state->uncompressed_size) {
+ void *new_block;
+
+ new_block = realloc(state->out_block, state->uncompressed_size);
+ if (new_block == NULL) {
+ archive_set_error(&self->archive->archive, ENOMEM,
+ "Can't allocate data for lzop decompression");
+ return (ARCHIVE_FATAL);
+ }
+ state->out_block = new_block;
+ state->out_block_size = state->uncompressed_size;
+ }
+
+ b = __archive_read_filter_ahead(self->upstream,
+ state->compressed_size, NULL);
+ if (b == NULL) {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data");
+ return (ARCHIVE_FATAL);
+ }
+ if (state->flags & CRC32_COMPRESSED)
+ cksum = crc32(crc32(0, NULL, 0), b, state->compressed_size);
+ else if (state->flags & ADLER32_COMPRESSED)
+ cksum = adler32(adler32(0, NULL, 0), b, state->compressed_size);
+ else
+ cksum = state->compressed_cksum;
+ if (cksum != state->compressed_cksum) {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC, "Corrupted data");
+ return (ARCHIVE_FATAL);
+ }
+
+ /*
+ * If the both uncompressed size and compressed size are the same,
+ * we do not decompress this block.
+ */
+ if (state->uncompressed_size == state->compressed_size) {
+ *p = b;
+ state->total_out += state->compressed_size;
+ state->unconsumed_bytes = state->compressed_size;
+ return ((ssize_t)state->uncompressed_size);
+ }
+
+ /*
+ * Drive lzo uncompresison.
+ */
+ out_size = (lzo_uint)state->uncompressed_size;
+ r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size,
+ state->out_block, &out_size, NULL);
+ switch (r) {
+ case LZO_E_OK:
+ if (out_size == state->uncompressed_size)
+ break;
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC, "Corrupted data");
+ return (ARCHIVE_FATAL);
+ case LZO_E_OUT_OF_MEMORY:
+ archive_set_error(&self->archive->archive, ENOMEM,
+ "lzop decompression failed: out of memory");
+ return (ARCHIVE_FATAL);
+ default:
+ archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
+ "lzop decompression failed: %d", r);
+ return (ARCHIVE_FATAL);
+ }
+
+ if (state->flags & CRC32_UNCOMPRESSED)
+ cksum = crc32(crc32(0, NULL, 0), state->out_block,
+ state->uncompressed_size);
+ else if (state->flags & ADLER32_UNCOMPRESSED)
+ cksum = adler32(adler32(0, NULL, 0), state->out_block,
+ state->uncompressed_size);
+ else
+ cksum = state->uncompressed_cksum;
+ if (cksum != state->uncompressed_cksum) {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC, "Corrupted data");
+ return (ARCHIVE_FATAL);
+ }
+
+ __archive_read_filter_consume(self->upstream, state->compressed_size);
+ *p = state->out_block;
+ state->total_out += out_size;
+ return ((ssize_t)out_size);
+}
+
+/*
+ * Clean up the decompressor.
+ */
+static int
+lzop_filter_close(struct archive_read_filter *self)
+{
+ struct read_lzop *state = (struct read_lzop *)self->data;
+
+ free(state->out_block);
+ free(state);
+ return (ARCHIVE_OK);
+}
+
+#endif
diff --git a/libarchive/archive_read_support_filter_program.c b/libarchive/archive_read_support_filter_program.c
index b05eb03424d7..66dc2f424f85 100644
--- a/libarchive/archive_read_support_filter_program.c
+++ b/libarchive/archive_read_support_filter_program.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2007 Joerg Sonnenberger
+ * Copyright (c) 2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -53,7 +54,9 @@ __FBSDID("$FreeBSD$");
#include "archive.h"
#include "archive_private.h"
+#include "archive_string.h"
#include "archive_read_private.h"
+#include "filter_fork.h"
#if ARCHIVE_VERSION_NUMBER < 4000000
@@ -79,50 +82,13 @@ archive_read_support_filter_program(struct archive *a, const char *cmd)
return (archive_read_support_filter_program_signature(a, cmd, NULL, 0));
}
-
-/* This capability is only available on POSIX systems. */
-#if (!defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
- !(defined(HAVE_FORK) || defined(HAVE_VFORK))) && (!defined(_WIN32) || defined(__CYGWIN__))
-
-/*
- * On non-Posix systems, allow the program to build, but choke if
- * this function is actually invoked.
- */
-int
-archive_read_support_filter_program_signature(struct archive *_a,
- const char *cmd, const void *signature, size_t signature_len)
-{
- (void)_a; /* UNUSED */
- (void)cmd; /* UNUSED */
- (void)signature; /* UNUSED */
- (void)signature_len; /* UNUSED */
-
- archive_set_error(_a, -1,
- "External compression programs not supported on this platform");
- return (ARCHIVE_FATAL);
-}
-
-int
-__archive_read_program(struct archive_read_filter *self, const char *cmd)
-{
- (void)self; /* UNUSED */
- (void)cmd; /* UNUSED */
-
- archive_set_error(&self->archive->archive, -1,
- "External compression programs not supported on this platform");
- return (ARCHIVE_FATAL);
-}
-
-#else
-
-#include "filter_fork.h"
-
/*
* The bidder object stores the command and the signature to watch for.
* The 'inhibit' entry here is used to ensure that unchecked filters never
* bid twice in the same pipeline.
*/
struct program_bidder {
+ char *description;
char *cmd;
void *signature;
size_t signature_len;
@@ -138,8 +104,12 @@ static int program_bidder_free(struct archive_read_filter_bidder *);
* The actual filter needs to track input and output data.
*/
struct program_filter {
- char *description;
+ struct archive_string description;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ HANDLE child;
+#else
pid_t child;
+#endif
int exit_status;
int waitpid_return;
int child_stdin, child_stdout;
@@ -151,6 +121,29 @@ struct program_filter {
static ssize_t program_filter_read(struct archive_read_filter *,
const void **);
static int program_filter_close(struct archive_read_filter *);
+static void free_state(struct program_bidder *);
+
+static int
+set_bidder_signature(struct archive_read_filter_bidder *bidder,
+ struct program_bidder *state, const void *signature, size_t signature_len)
+{
+
+ if (signature != NULL && signature_len > 0) {
+ state->signature_len = signature_len;
+ state->signature = malloc(signature_len);
+ memcpy(state->signature, signature, signature_len);
+ }
+
+ /*
+ * Fill in the bidder object.
+ */
+ bidder->data = state;
+ bidder->bid = program_bidder_bid;
+ bidder->init = program_bidder_init;
+ bidder->options = NULL;
+ bidder->free = program_bidder_free;
+ return (ARCHIVE_OK);
+}
int
archive_read_support_filter_program_signature(struct archive *_a,
@@ -169,37 +162,40 @@ archive_read_support_filter_program_signature(struct archive *_a,
/*
* Allocate our private state.
*/
- state = (struct program_bidder *)calloc(sizeof (*state), 1);
+ state = (struct program_bidder *)calloc(1, sizeof (*state));
if (state == NULL)
- return (ARCHIVE_FATAL);
+ goto memerr;
state->cmd = strdup(cmd);
- if (signature != NULL && signature_len > 0) {
- state->signature_len = signature_len;
- state->signature = malloc(signature_len);
- memcpy(state->signature, signature, signature_len);
- }
+ if (state->cmd == NULL)
+ goto memerr;
- /*
- * Fill in the bidder object.
- */
- bidder->data = state;
- bidder->bid = program_bidder_bid;
- bidder->init = program_bidder_init;
- bidder->options = NULL;
- bidder->free = program_bidder_free;
- return (ARCHIVE_OK);
+ return set_bidder_signature(bidder, state, signature, signature_len);
+memerr:
+ free_state(state);
+ archive_set_error(_a, ENOMEM, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
}
static int
program_bidder_free(struct archive_read_filter_bidder *self)
{
struct program_bidder *state = (struct program_bidder *)self->data;
- free(state->cmd);
- free(state->signature);
- free(self->data);
+
+ free_state(state);
return (ARCHIVE_OK);
}
+static void
+free_state(struct program_bidder *state)
+{
+
+ if (state) {
+ free(state->cmd);
+ free(state->signature);
+ free(state);
+ }
+}
+
/*
* If we do have a signature, bid only if that matches.
*
@@ -258,6 +254,9 @@ child_stop(struct archive_read_filter *self, struct program_filter *state)
state->waitpid_return
= waitpid(state->child, &state->exit_status, 0);
} while (state->waitpid_return == -1 && errno == EINTR);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ CloseHandle(state->child);
+#endif
state->child = 0;
}
@@ -310,11 +309,35 @@ child_read(struct archive_read_filter *self, char *buf, size_t buf_len)
struct program_filter *state = self->data;
ssize_t ret, requested, avail;
const char *p;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ HANDLE handle = (HANDLE)_get_osfhandle(state->child_stdout);
+#endif
requested = buf_len > SSIZE_MAX ? SSIZE_MAX : buf_len;
for (;;) {
do {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Avoid infinity wait.
+ * Note: If there is no data in the pipe, ReadFile()
+ * called in read() never returns and so we won't
+ * write remaining encoded data to the pipe.
+ * Note: This way may cause performance problem.
+ * we are looking forward to great code to resolve
+ * this. */
+ DWORD pipe_avail = -1;
+ int cnt = 2;
+
+ while (PeekNamedPipe(handle, NULL, 0, NULL,
+ &pipe_avail, NULL) != 0 && pipe_avail == 0 &&
+ cnt--)
+ Sleep(5);
+ if (pipe_avail == 0) {
+ ret = -1;
+ errno = EAGAIN;
+ break;
+ }
+#endif
ret = read(state->child_stdout, buf, requested);
} while (ret == -1 && errno == EINTR);
@@ -376,38 +399,57 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd)
struct program_filter *state;
static const size_t out_buf_len = 65536;
char *out_buf;
- char *description;
const char *prefix = "Program: ";
+ pid_t child;
+ size_t l;
+ l = strlen(prefix) + strlen(cmd) + 1;
state = (struct program_filter *)calloc(1, sizeof(*state));
out_buf = (char *)malloc(out_buf_len);
- description = (char *)malloc(strlen(prefix) + strlen(cmd) + 1);
- if (state == NULL || out_buf == NULL || description == NULL) {
+ if (state == NULL || out_buf == NULL ||
+ archive_string_ensure(&state->description, l) == NULL) {
archive_set_error(&self->archive->archive, ENOMEM,
"Can't allocate input data");
- free(state);
+ if (state != NULL) {
+ archive_string_free(&state->description);
+ free(state);
+ }
free(out_buf);
- free(description);
return (ARCHIVE_FATAL);
}
+ archive_strcpy(&state->description, prefix);
+ archive_strcat(&state->description, cmd);
- self->code = ARCHIVE_COMPRESSION_PROGRAM;
- state->description = description;
- strcpy(state->description, prefix);
- strcat(state->description, cmd);
- self->name = state->description;
+ self->code = ARCHIVE_FILTER_PROGRAM;
+ self->name = state->description.s;
state->out_buf = out_buf;
state->out_buf_len = out_buf_len;
- if ((state->child = __archive_create_child(cmd,
- &state->child_stdin, &state->child_stdout)) == -1) {
+ child = __archive_create_child(cmd, &state->child_stdin,
+ &state->child_stdout);
+ if (child == -1) {
+ free(state->out_buf);
+ free(state);
+ archive_set_error(&self->archive->archive, EINVAL,
+ "Can't initialize filter; unable to run program \"%s\"",
+ cmd);
+ return (ARCHIVE_FATAL);
+ }
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ state->child = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, child);
+ if (state->child == NULL) {
+ child_stop(self, state);
free(state->out_buf);
free(state);
archive_set_error(&self->archive->archive, EINVAL,
- "Can't initialize filter; unable to run program \"%s\"", cmd);
+ "Can't initialize filter; unable to run program \"%s\"",
+ cmd);
return (ARCHIVE_FATAL);
}
+#else
+ state->child = child;
+#endif
self->data = state;
self->read = program_filter_read;
@@ -467,10 +509,8 @@ program_filter_close(struct archive_read_filter *self)
/* Release our private data. */
free(state->out_buf);
- free(state->description);
+ archive_string_free(&state->description);
free(state);
return (e);
}
-
-#endif /* !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL) */
diff --git a/libarchive/archive_read_support_filter_rpm.c b/libarchive/archive_read_support_filter_rpm.c
index 1b3e124204f1..e7e58e51f3b0 100644
--- a/libarchive/archive_read_support_filter_rpm.c
+++ b/libarchive/archive_read_support_filter_rpm.c
@@ -85,6 +85,7 @@ archive_read_support_filter_rpm(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
+ bidder->name = "rpm";
bidder->bid = rpm_bidder_bid;
bidder->init = rpm_bidder_init;
bidder->options = NULL;
@@ -137,7 +138,7 @@ rpm_bidder_init(struct archive_read_filter *self)
{
struct rpm *rpm;
- self->code = ARCHIVE_COMPRESSION_RPM;
+ self->code = ARCHIVE_FILTER_RPM;
self->name = "rpm";
self->read = rpm_filter_read;
self->skip = NULL; /* not supported */
diff --git a/libarchive/archive_read_support_filter_uu.c b/libarchive/archive_read_support_filter_uu.c
index a75ef756081b..471771b6f469 100644
--- a/libarchive/archive_read_support_filter_uu.c
+++ b/libarchive/archive_read_support_filter_uu.c
@@ -56,6 +56,7 @@ struct uudecode {
#define ST_READ_UU 1
#define ST_UUEND 2
#define ST_READ_BASE64 3
+#define ST_IGNORE 4
};
static int uudecode_bidder_bid(struct archive_read_filter_bidder *,
@@ -88,6 +89,7 @@ archive_read_support_filter_uu(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
+ bidder->name = "uu";
bidder->bid = uudecode_bidder_bid;
bidder->init = uudecode_bidder_init;
bidder->options = NULL;
@@ -377,7 +379,7 @@ uudecode_bidder_init(struct archive_read_filter *self)
void *out_buff;
void *in_buff;
- self->code = ARCHIVE_COMPRESSION_UU;
+ self->code = ARCHIVE_FILTER_UU;
self->name = "uu";
self->read = uudecode_filter_read;
self->skip = NULL; /* not supported */
@@ -470,6 +472,10 @@ read_more:
total = 0;
out = uudecode->out_buff;
ravail = avail_in;
+ if (uudecode->state == ST_IGNORE) {
+ used = avail_in;
+ goto finish;
+ }
if (uudecode->in_cnt) {
/*
* If there is remaining data which is saved by
@@ -485,12 +491,18 @@ read_more:
uudecode->in_cnt = 0;
}
for (;used < avail_in; d += llen, used += llen) {
- int l, body;
+ int64_t l, body;
b = d;
len = get_line(b, avail_in - used, &nl);
if (len < 0) {
/* Non-ascii character is found. */
+ if (uudecode->state == ST_FIND_HEAD &&
+ (uudecode->total > 0 || total > 0)) {
+ uudecode->state = ST_IGNORE;
+ used = avail_in;
+ goto finish;
+ }
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_MISC,
"Insufficient compressed data");
@@ -507,7 +519,7 @@ read_more:
return (ARCHIVE_FATAL);
if (uudecode->in_buff != b)
memmove(uudecode->in_buff, b, len);
- uudecode->in_cnt = len;
+ uudecode->in_cnt = (int)len;
if (total == 0) {
/* Do not return 0; it means end-of-file.
* We should try to read bytes more. */
@@ -545,7 +557,7 @@ read_more:
break;
case ST_READ_UU:
if (total + len * 2 > OUT_BUFF_SIZE)
- break;
+ goto finish;
body = len - nl;
if (!uuchar[*b] || body <= 0) {
archive_set_error(&self->archive->archive,
@@ -611,7 +623,7 @@ read_more:
break;
case ST_READ_BASE64:
if (total + len * 2 > OUT_BUFF_SIZE)
- break;
+ goto finish;
l = len - nl;
if (l >= 3 && b[0] == '=' && b[1] == '=' &&
b[2] == '=') {
@@ -657,8 +669,10 @@ read_more:
break;
}
}
-
- __archive_read_filter_consume(self->upstream, ravail);
+finish:
+ if (ravail < avail_in)
+ used -= avail_in - ravail;
+ __archive_read_filter_consume(self->upstream, used);
*buff = uudecode->out_buff;
uudecode->total += total;
diff --git a/libarchive/archive_read_support_filter_xz.c b/libarchive/archive_read_support_filter_xz.c
index cf762a46d984..15824b1d0974 100644
--- a/libarchive/archive_read_support_filter_xz.c
+++ b/libarchive/archive_read_support_filter_xz.c
@@ -136,6 +136,7 @@ archive_read_support_filter_xz(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
+ bidder->name = "xz";
bidder->bid = xz_bidder_bid;
bidder->init = xz_bidder_init;
bidder->options = NULL;
@@ -144,7 +145,7 @@ archive_read_support_filter_xz(struct archive *_a)
return (ARCHIVE_OK);
#else
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
- "Using external unxz program for xz decompression");
+ "Using external xz program for xz decompression");
return (ARCHIVE_WARN);
#endif
}
@@ -170,6 +171,7 @@ archive_read_support_filter_lzma(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
+ bidder->name = "lzma";
bidder->bid = lzma_bidder_bid;
bidder->init = lzma_bidder_init;
bidder->options = NULL;
@@ -180,7 +182,7 @@ archive_read_support_filter_lzma(struct archive *_a)
return (ARCHIVE_OK);
#else
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
- "Using external unlzma program for lzma decompression");
+ "Using external lzma program for lzma decompression");
return (ARCHIVE_WARN);
#endif
}
@@ -207,6 +209,7 @@ archive_read_support_filter_lzip(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
+ bidder->name = "lzip";
bidder->bid = lzip_bidder_bid;
bidder->init = lzip_bidder_init;
bidder->options = NULL;
@@ -415,7 +418,7 @@ lzip_bidder_bid(struct archive_read_filter_bidder *self,
static int
xz_bidder_init(struct archive_read_filter *self)
{
- self->code = ARCHIVE_COMPRESSION_XZ;
+ self->code = ARCHIVE_FILTER_XZ;
self->name = "xz";
return (xz_lzma_bidder_init(self));
}
@@ -423,7 +426,7 @@ xz_bidder_init(struct archive_read_filter *self)
static int
lzma_bidder_init(struct archive_read_filter *self)
{
- self->code = ARCHIVE_COMPRESSION_LZMA;
+ self->code = ARCHIVE_FILTER_LZMA;
self->name = "lzma";
return (xz_lzma_bidder_init(self));
}
@@ -431,7 +434,7 @@ lzma_bidder_init(struct archive_read_filter *self)
static int
lzip_bidder_init(struct archive_read_filter *self)
{
- self->code = ARCHIVE_COMPRESSION_LZIP;
+ self->code = ARCHIVE_FILTER_LZIP;
self->name = "lzip";
return (xz_lzma_bidder_init(self));
}
@@ -518,7 +521,7 @@ xz_lzma_bidder_init(struct archive_read_filter *self)
state->stream.avail_out = state->out_block_size;
state->crc32 = 0;
- if (self->code == ARCHIVE_COMPRESSION_LZIP) {
+ if (self->code == ARCHIVE_FILTER_LZIP) {
/*
* We have to read a lzip header and use it to initialize
* compression library, thus we cannot initialize the
@@ -530,7 +533,7 @@ xz_lzma_bidder_init(struct archive_read_filter *self)
state->in_stream = 1;
/* Initialize compression library. */
- if (self->code == ARCHIVE_COMPRESSION_XZ)
+ if (self->code == ARCHIVE_FILTER_XZ)
ret = lzma_stream_decoder(&(state->stream),
LZMA_MEMLIMIT,/* memlimit */
LZMA_CONCATENATED);
@@ -730,7 +733,7 @@ xz_filter_read(struct archive_read_filter *self, const void **p)
*p = NULL;
else {
*p = state->out_block;
- if (self->code == ARCHIVE_COMPRESSION_LZIP) {
+ if (self->code == ARCHIVE_FILTER_LZIP) {
state->crc32 = lzma_crc32(state->out_block,
decompressed, state->crc32);
if (state->eof) {
@@ -778,7 +781,7 @@ lzma_bidder_init(struct archive_read_filter *self)
struct private_data *state;
ssize_t ret, avail_in;
- self->code = ARCHIVE_COMPRESSION_LZMA;
+ self->code = ARCHIVE_FILTER_LZMA;
self->name = "lzma";
state = (struct private_data *)calloc(sizeof(*state), 1);
@@ -941,11 +944,11 @@ lzma_bidder_init(struct archive_read_filter *self)
{
int r;
- r = __archive_read_program(self, "unlzma");
+ r = __archive_read_program(self, "lzma -d -qq");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
- self->code = ARCHIVE_COMPRESSION_LZMA;
+ self->code = ARCHIVE_FILTER_LZMA;
self->name = "lzma";
return (r);
}
@@ -958,11 +961,11 @@ xz_bidder_init(struct archive_read_filter *self)
{
int r;
- r = __archive_read_program(self, "unxz");
+ r = __archive_read_program(self, "xz -d -qq");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
- self->code = ARCHIVE_COMPRESSION_XZ;
+ self->code = ARCHIVE_FILTER_XZ;
self->name = "xz";
return (r);
}
@@ -972,11 +975,11 @@ lzip_bidder_init(struct archive_read_filter *self)
{
int r;
- r = __archive_read_program(self, "unlzip");
+ r = __archive_read_program(self, "lzip -d -q");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
- self->code = ARCHIVE_COMPRESSION_LZIP;
+ self->code = ARCHIVE_FILTER_LZIP;
self->name = "lzip";
return (r);
}
diff --git a/libarchive/archive_read_support_format_7zip.c b/libarchive/archive_read_support_format_7zip.c
index 39a46ed579b9..194b8d51c96a 100644
--- a/libarchive/archive_read_support_format_7zip.c
+++ b/libarchive/archive_read_support_format_7zip.c
@@ -409,6 +409,7 @@ archive_read_support_format_7zip(struct archive *_a)
archive_read_format_7zip_read_header,
archive_read_format_7zip_read_data,
archive_read_format_7zip_read_data_skip,
+ NULL,
archive_read_format_7zip_cleanup);
if (r != ARCHIVE_OK)
@@ -684,8 +685,8 @@ archive_read_format_7zip_read_header(struct archive_read *a,
symname[symsize] = '\0';
archive_entry_copy_symlink(entry,
(const char *)symname);
- free(symname);
}
+ free(symname);
archive_entry_set_size(entry, 0);
}
@@ -709,16 +710,15 @@ archive_read_format_7zip_read_data(struct archive_read *a,
if (zip->pack_stream_bytes_unconsumed)
read_consume(a);
+ *offset = zip->entry_offset;
+ *size = 0;
+ *buff = NULL;
/*
* If we hit end-of-entry last time, clean up and return
* ARCHIVE_EOF this time.
*/
- if (zip->end_of_entry) {
- *offset = zip->entry_offset;
- *size = 0;
- *buff = NULL;
+ if (zip->end_of_entry)
return (ARCHIVE_EOF);
- }
bytes = read_stream(a, buff,
(size_t)zip->entry_bytes_remaining, 0);
@@ -736,7 +736,8 @@ archive_read_format_7zip_read_data(struct archive_read *a,
/* Update checksum */
if ((zip->entry->flg & CRC32_IS_SET) && bytes)
- zip->entry_crc32 = crc32(zip->entry_crc32, *buff, bytes);
+ zip->entry_crc32 = crc32(zip->entry_crc32, *buff,
+ (unsigned)bytes);
/* If we hit the end, swallow any end-of-data marker. */
if (zip->end_of_entry) {
@@ -1363,9 +1364,9 @@ decompress(struct archive_read *a, struct _7zip *zip,
#ifdef HAVE_ZLIB_H
case _7Z_DEFLATE:
zip->stream.next_in = (Bytef *)(uintptr_t)t_next_in;
- zip->stream.avail_in = t_avail_in;
+ zip->stream.avail_in = (uInt)t_avail_in;
zip->stream.next_out = t_next_out;
- zip->stream.avail_out = t_avail_out;
+ zip->stream.avail_out = (uInt)t_avail_out;
r = inflate(&(zip->stream), 0);
switch (r) {
case Z_STREAM_END: /* Found end of stream. */
@@ -1607,9 +1608,10 @@ read_Digests(struct archive_read *a, struct _7z_digests *d, size_t num)
const unsigned char *p;
unsigned i;
+ if (num == 0)
+ return (-1);
memset(d, 0, sizeof(*d));
-
d->defineds = malloc(num);
if (d->defineds == NULL)
return (-1);
@@ -2687,7 +2689,7 @@ header_bytes(struct archive_read *a, size_t rbytes)
}
/* Update checksum */
- zip->header_crc32 = crc32(zip->header_crc32, p, rbytes);
+ zip->header_crc32 = crc32(zip->header_crc32, p, (unsigned)rbytes);
return (p);
}
@@ -2966,16 +2968,19 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
* Expand the uncompressed buffer up to
* the minimum size.
*/
- zip->uncompressed_buffer_size = minimum + 1023;
- zip->uncompressed_buffer_size &= ~0x3ff;
- zip->uncompressed_buffer =
- realloc(zip->uncompressed_buffer,
- zip->uncompressed_buffer_size);
- if (zip->uncompressed_buffer == NULL) {
+ void *p;
+ size_t new_size;
+
+ new_size = minimum + 1023;
+ new_size &= ~0x3ff;
+ p = realloc(zip->uncompressed_buffer, new_size);
+ if (p == NULL) {
archive_set_error(&a->archive, ENOMEM,
"No memory for 7-Zip decompression");
return (ARCHIVE_FATAL);
}
+ zip->uncompressed_buffer = (unsigned char *)p;
+ zip->uncompressed_buffer_size = new_size;
}
/*
* Move unconsumed bytes to the head.
@@ -3095,7 +3100,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size,
{
struct _7zip *zip = (struct _7zip *)a->format->data;
uint64_t skip_bytes = 0;
- int r;
+ ssize_t r;
if (zip->uncompressed_buffer_bytes_remaining == 0) {
if (zip->pack_stream_inbytes_remaining > 0) {
@@ -3346,8 +3351,10 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
for (i = 0; i < 3; i++) {
const struct _7z_coder *coder = scoder[i];
- if ((r = seek_pack(a)) < 0)
+ if ((r = seek_pack(a)) < 0) {
+ free(b[0]); free(b[1]); free(b[2]);
return (r);
+ }
if (sunpack[i] == (uint64_t)-1)
zip->folder_outbytes_remaining =
@@ -3356,13 +3363,16 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
zip->folder_outbytes_remaining = sunpack[i];
r = init_decompression(a, zip, coder, NULL);
- if (r != ARCHIVE_OK)
+ if (r != ARCHIVE_OK) {
+ free(b[0]); free(b[1]); free(b[2]);
return (ARCHIVE_FATAL);
+ }
/* Allocate memory for the decorded data of a sub
* stream. */
b[i] = malloc((size_t)zip->folder_outbytes_remaining);
if (b[i] == NULL) {
+ free(b[0]); free(b[1]); free(b[2]);
archive_set_error(&a->archive, ENOMEM,
"No memory for 7-Zip decompression");
return (ARCHIVE_FATAL);
@@ -3370,14 +3380,18 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
/* Extract a sub stream. */
while (zip->pack_stream_inbytes_remaining > 0) {
- r = extract_pack_stream(a, 0);
- if (r < 0)
+ r = (int)extract_pack_stream(a, 0);
+ if (r < 0) {
+ free(b[0]); free(b[1]); free(b[2]);
return (r);
+ }
bytes = get_uncompressed_data(a, &buff,
zip->uncompressed_buffer_bytes_remaining,
0);
- if (bytes < 0)
+ if (bytes < 0) {
+ free(b[0]); free(b[1]); free(b[2]);
return ((int)bytes);
+ }
memcpy(b[i]+s[i], buff, bytes);
s[i] += bytes;
if (zip->pack_stream_bytes_unconsumed)
@@ -3557,7 +3571,7 @@ x86_Convert(struct _7zip *zip, uint8_t *data, size_t size)
}
zip->bcj_prevPosT = prevPosT;
zip->bcj_prevMask = prevMask;
- zip->bcj_ip += bufferPos;
+ zip->bcj_ip += (uint32_t)bufferPos;
return (bufferPos);
}
@@ -3701,7 +3715,7 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize)
((uint32_t)v[1] << 16) |
((uint32_t)v[2] << 8) |
((uint32_t)v[3])) -
- ((uint32_t)zip->bcj2_outPos + outPos + 4);
+ ((uint32_t)zip->bcj2_outPos + (uint32_t)outPos + 4);
out[0] = (uint8_t)dest;
out[1] = (uint8_t)(dest >> 8);
out[2] = (uint8_t)(dest >> 16);
@@ -3716,7 +3730,7 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize)
*/
zip->odd_bcj_size = 4 -i;
for (; i < 4; i++) {
- j = i - 4 + zip->odd_bcj_size;
+ j = i - 4 + (unsigned)zip->odd_bcj_size;
zip->odd_bcj[j] = out[i];
}
break;
diff --git a/libarchive/archive_read_support_format_ar.c b/libarchive/archive_read_support_format_ar.c
index 9feb547dbbea..40be18c0cce2 100644
--- a/libarchive/archive_read_support_format_ar.c
+++ b/libarchive/archive_read_support_format_ar.c
@@ -121,6 +121,7 @@ archive_read_support_format_ar(struct archive *_a)
archive_read_format_ar_read_header,
archive_read_format_ar_read_data,
archive_read_format_ar_skip,
+ NULL,
archive_read_format_ar_cleanup);
if (r != ARCHIVE_OK) {
diff --git a/libarchive/archive_read_support_format_cab.c b/libarchive/archive_read_support_format_cab.c
index aa0152a17140..3c9f94ca6ba3 100644
--- a/libarchive/archive_read_support_format_cab.c
+++ b/libarchive/archive_read_support_format_cab.c
@@ -382,6 +382,7 @@ archive_read_support_format_cab(struct archive *_a)
archive_read_format_cab_read_header,
archive_read_format_cab_read_data,
archive_read_format_cab_read_data_skip,
+ NULL,
archive_read_format_cab_cleanup);
if (r != ARCHIVE_OK)
@@ -539,7 +540,7 @@ truncated_error(struct archive_read *a)
return (ARCHIVE_FATAL);
}
-static int
+static ssize_t
cab_strnlen(const unsigned char *p, size_t maxlen)
{
size_t i;
@@ -550,7 +551,7 @@ cab_strnlen(const unsigned char *p, size_t maxlen)
}
if (i > maxlen)
return (-1);/* invalid */
- return (i);
+ return ((ssize_t)i);
}
/* Read bytes as much as remaining. */
@@ -626,8 +627,9 @@ cab_read_header(struct archive_read *a)
struct cab *cab;
struct cfheader *hd;
size_t bytes, used;
+ ssize_t len;
int64_t skip;
- int err, i, len;
+ int err, i;
int cur_folder, prev_folder;
uint32_t offset32;
@@ -1066,13 +1068,13 @@ static uint32_t
cab_checksum_cfdata_4(const void *p, size_t bytes, uint32_t seed)
{
const unsigned char *b;
- int u32num;
+ unsigned u32num;
uint32_t sum;
- u32num = bytes / 4;
+ u32num = (unsigned)bytes / 4;
sum = seed;
b = p;
- while (--u32num >= 0) {
+ for (;u32num > 0; --u32num) {
sum ^= archive_le32dec(b);
b += 4;
}
@@ -1485,7 +1487,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
* cast to remove 'const'.
*/
cab->stream.next_in = (Bytef *)(uintptr_t)d;
- cab->stream.avail_in = bytes_avail;
+ cab->stream.avail_in = (uInt)bytes_avail;
cab->stream.total_in = 0;
/* Cut out a tow-byte MSZIP signature(0x43, 0x4b). */
@@ -1506,7 +1508,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
*avail = ARCHIVE_FATAL;
return (NULL);
}
- mszip -= bytes_avail;
+ mszip -= (int)bytes_avail;
continue;
}
if (mszip == 1 && cab->stream.next_in[0] != 0x4b)
@@ -1935,7 +1937,7 @@ cab_read_data(struct archive_read *a, const void **buff,
ARCHIVE_ERRNO_FILE_FORMAT, "Invalid CFDATA");
return (ARCHIVE_FATAL);
} else
- return (bytes_avail);
+ return ((int)bytes_avail);
}
if (bytes_avail > cab->entry_bytes_remaining)
bytes_avail = (ssize_t)cab->entry_bytes_remaining;
@@ -2001,7 +2003,8 @@ archive_read_format_cab_read_data_skip(struct archive_read *a)
/* If the compression type is none(uncompressed), we've already
* consumed data as much as the current entry size. */
- if (cab->entry_cffolder->comptype == COMPTYPE_NONE)
+ if (cab->entry_cffolder->comptype == COMPTYPE_NONE &&
+ cab->entry_cfdata != NULL)
cab->entry_cfdata->unconsumed = 0;
/* This entry is finished and done. */
@@ -2198,7 +2201,7 @@ lzx_translation(struct lzx_stream *strm, void *p, size_t size, uint32_t offset)
size_t i = b - (unsigned char *)p;
int32_t cp, displacement, value;
- cp = offset + i;
+ cp = (int32_t)(offset + (uint32_t)i);
value = archive_le32dec(&b[1]);
if (value >= -cp && value < (int32_t)ds->translation_size) {
if (value >= 0)
@@ -2584,7 +2587,7 @@ lzx_read_blocks(struct lzx_stream *strm, int last)
goto failed;
return (ARCHIVE_OK);
}
- l = ds->block_bytes_avail;
+ l = (int)ds->block_bytes_avail;
if (l > ds->w_size - ds->w_pos)
l = ds->w_size - ds->w_pos;
if (l > strm->avail_out)
@@ -2746,8 +2749,8 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
struct lzx_br bre = ds->br;
struct huffman *at = &(ds->at), *lt = &(ds->lt), *mt = &(ds->mt);
const struct lzx_pos_tbl *pos_tbl = ds->pos_tbl;
- unsigned char *outp = strm->next_out;
- unsigned char *endp = outp + strm->avail_out;
+ unsigned char *noutp = strm->next_out;
+ unsigned char *endp = noutp + strm->avail_out;
unsigned char *w_buff = ds->w_buff;
unsigned char *at_bitlen = at->bitlen;
unsigned char *lt_bitlen = lt->bitlen;
@@ -2781,10 +2784,10 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
ds->position_slot = position_slot;
ds->r0 = r0; ds->r1 = r1; ds->r2 = r2;
ds->w_pos = w_pos;
- strm->avail_out = endp - outp;
+ strm->avail_out = endp - noutp;
return (ARCHIVE_EOF);
}
- if (outp >= endp)
+ if (noutp >= endp)
/* Output buffer is empty. */
goto next_data;
@@ -2818,7 +2821,7 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
w_buff[w_pos] = c;
w_pos = (w_pos + 1) & w_mask;
/* Store the decoded code to output buffer. */
- *outp++ = c;
+ *noutp++ = c;
block_bytes_avail--;
}
/*
@@ -2963,22 +2966,22 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
if (l > w_size - w_pos)
l = w_size - w_pos;
}
- if (outp + l >= endp)
- l = endp - outp;
+ if (noutp + l >= endp)
+ l = (int)(endp - noutp);
s = w_buff + copy_pos;
if (l >= 8 && ((copy_pos + l < w_pos)
|| (w_pos + l < copy_pos))) {
memcpy(w_buff + w_pos, s, l);
- memcpy(outp, s, l);
+ memcpy(noutp, s, l);
} else {
unsigned char *d;
int li;
d = w_buff + w_pos;
for (li = 0; li < l; li++)
- outp[li] = d[li] = s[li];
+ noutp[li] = d[li] = s[li];
}
- outp += l;
+ noutp += l;
copy_pos = (copy_pos + l) & w_mask;
w_pos = (w_pos + l) & w_mask;
block_bytes_avail -= l;
@@ -2986,7 +2989,7 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
/* A copy of current pattern ended. */
break;
copy_len -= l;
- if (outp >= endp) {
+ if (noutp >= endp) {
/* Output buffer is empty. */
state = ST_COPY;
goto next_data;
@@ -3009,7 +3012,7 @@ next_data:
ds->r0 = r0; ds->r1 = r1; ds->r2 = r2;
ds->state = state;
ds->w_pos = w_pos;
- strm->avail_out = endp - outp;
+ strm->avail_out = endp - noutp;
return (ARCHIVE_OK);
}
@@ -3126,7 +3129,7 @@ lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
hf->bitlen = calloc(len_size, sizeof(hf->bitlen[0]));
if (hf->bitlen == NULL)
return (ARCHIVE_FATAL);
- hf->len_size = len_size;
+ hf->len_size = (int)len_size;
} else
memset(hf->bitlen, 0, len_size * sizeof(hf->bitlen[0]));
if (hf->tbl == NULL) {
@@ -3134,7 +3137,7 @@ lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
bits = tbl_bits;
else
bits = HTBL_BITS;
- hf->tbl = malloc((1 << bits) * sizeof(hf->tbl[0]));
+ hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0]));
if (hf->tbl == NULL)
return (ARCHIVE_FATAL);
hf->tbl_bits = tbl_bits;
diff --git a/libarchive/archive_read_support_format_cpio.c b/libarchive/archive_read_support_format_cpio.c
index ff29e1ffd973..819f4a4f531e 100644
--- a/libarchive/archive_read_support_format_cpio.c
+++ b/libarchive/archive_read_support_format_cpio.c
@@ -242,6 +242,7 @@ archive_read_support_format_cpio(struct archive *_a)
archive_read_format_cpio_read_header,
archive_read_format_cpio_read_data,
archive_read_format_cpio_skip,
+ NULL,
archive_read_format_cpio_cleanup);
if (r != ARCHIVE_OK)
diff --git a/libarchive/archive_read_support_format_empty.c b/libarchive/archive_read_support_format_empty.c
index 3dc2196cb99e..366073820975 100644
--- a/libarchive/archive_read_support_format_empty.c
+++ b/libarchive/archive_read_support_format_empty.c
@@ -53,6 +53,7 @@ archive_read_support_format_empty(struct archive *_a)
archive_read_format_empty_read_header,
archive_read_format_empty_read_data,
NULL,
+ NULL,
NULL);
return (r);
diff --git a/libarchive/archive_read_support_format_iso9660.c b/libarchive/archive_read_support_format_iso9660.c
index d38c7cfe7e42..914bc71dfed5 100644
--- a/libarchive/archive_read_support_format_iso9660.c
+++ b/libarchive/archive_read_support_format_iso9660.c
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2009 Andreas Henriksson <andreas@fatal.se>
- * Copyright (c) 2009-2011 Michihiro NAKAJIMA
+ * Copyright (c) 2009-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -374,6 +374,8 @@ struct iso9660 {
size_t utf16be_path_len;
unsigned char *utf16be_previous_path;
size_t utf16be_previous_path_len;
+ /* Null buufer used in bidder to improve its performance. */
+ unsigned char null[2048];
};
static int archive_read_format_iso9660_bid(struct archive_read *, int);
@@ -475,6 +477,7 @@ archive_read_support_format_iso9660(struct archive *_a)
archive_read_format_iso9660_read_header,
archive_read_format_iso9660_read_data,
archive_read_format_iso9660_read_data_skip,
+ NULL,
archive_read_format_iso9660_cleanup);
if (r != ARCHIVE_OK) {
@@ -588,6 +591,23 @@ archive_read_format_iso9660_options(struct archive_read *a,
}
static int
+isNull(struct iso9660 *iso9660, const unsigned char *h, unsigned offset,
+unsigned bytes)
+{
+
+ while (bytes >= sizeof(iso9660->null)) {
+ if (!memcmp(iso9660->null, h + offset, sizeof(iso9660->null)))
+ return (0);
+ offset += sizeof(iso9660->null);
+ bytes -= sizeof(iso9660->null);
+ }
+ if (bytes)
+ return memcmp(iso9660->null, h + offset, bytes) == 0;
+ else
+ return (1);
+}
+
+static int
isBootRecord(struct iso9660 *iso9660, const unsigned char *h)
{
(void)iso9660; /* UNUSED */
@@ -632,8 +652,6 @@ isVolumePartition(struct iso9660 *iso9660, const unsigned char *h)
static int
isVDSetTerminator(struct iso9660 *iso9660, const unsigned char *h)
{
- int i;
-
(void)iso9660; /* UNUSED */
/* Type of the Volume Descriptor Set Terminator must be 255. */
@@ -645,9 +663,8 @@ isVDSetTerminator(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
- for (i = 7; i < 2048; ++i)
- if (h[i] != 0)
- return (0);
+ if (!isNull(iso9660, h, 7, 2048-7))
+ return (0);
return (1);
}
@@ -708,7 +725,6 @@ isSVD(struct iso9660 *iso9660, const unsigned char *h)
ssize_t logical_block_size;
int32_t volume_block;
int32_t location;
- int i;
(void)iso9660; /* UNUSED */
@@ -717,15 +733,12 @@ isSVD(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
- for (i = 0; i < SVD_reserved1_size; ++i)
- if (h[SVD_reserved1_offset + i] != 0)
- return (0);
- for (i = 0; i < SVD_reserved2_size; ++i)
- if (h[SVD_reserved2_offset + i] != 0)
- return (0);
- for (i = 0; i < SVD_reserved3_size; ++i)
- if (h[SVD_reserved3_offset + i] != 0)
- return (0);
+ if (!isNull(iso9660, h, SVD_reserved1_offset, SVD_reserved1_size))
+ return (0);
+ if (!isNull(iso9660, h, SVD_reserved2_offset, SVD_reserved2_size))
+ return (0);
+ if (!isNull(iso9660, h, SVD_reserved3_offset, SVD_reserved3_size))
+ return (0);
/* File structure version must be 1 for ISO9660/ECMA119. */
if (h[SVD_file_structure_version_offset] != 1)
@@ -771,7 +784,6 @@ isEVD(struct iso9660 *iso9660, const unsigned char *h)
ssize_t logical_block_size;
int32_t volume_block;
int32_t location;
- int i;
(void)iso9660; /* UNUSED */
@@ -788,14 +800,12 @@ isEVD(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
- for (i = 0; i < PVD_reserved2_size; ++i)
- if (h[PVD_reserved2_offset + i] != 0)
- return (0);
+ if (!isNull(iso9660, h, PVD_reserved2_offset, PVD_reserved2_size))
+ return (0);
/* Reserved field must be 0. */
- for (i = 0; i < PVD_reserved3_size; ++i)
- if (h[PVD_reserved3_offset + i] != 0)
- return (0);
+ if (!isNull(iso9660, h, PVD_reserved3_offset, PVD_reserved3_size))
+ return (0);
/* Logical block size must be > 0. */
/* I've looked at Ecma 119 and can't find any stronger
@@ -830,14 +840,12 @@ isEVD(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
- for (i = 0; i < PVD_reserved4_size; ++i)
- if (h[PVD_reserved4_offset + i] != 0)
- return (0);
+ if (!isNull(iso9660, h, PVD_reserved4_offset, PVD_reserved4_size))
+ return (0);
/* Reserved field must be 0. */
- for (i = 0; i < PVD_reserved5_size; ++i)
- if (h[PVD_reserved5_offset + i] != 0)
- return (0);
+ if (!isNull(iso9660, h, PVD_reserved5_offset, PVD_reserved5_size))
+ return (0);
/* Read Root Directory Record in Volume Descriptor. */
p = h + PVD_root_directory_record_offset;
@@ -869,14 +877,12 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
- for (i = 0; i < PVD_reserved2_size; ++i)
- if (h[PVD_reserved2_offset + i] != 0)
- return (0);
+ if (!isNull(iso9660, h, PVD_reserved2_offset, PVD_reserved2_size))
+ return (0);
/* Reserved field must be 0. */
- for (i = 0; i < PVD_reserved3_size; ++i)
- if (h[PVD_reserved3_offset + i] != 0)
- return (0);
+ if (!isNull(iso9660, h, PVD_reserved3_offset, PVD_reserved3_size))
+ return (0);
/* Logical block size must be > 0. */
/* I've looked at Ecma 119 and can't find any stronger
@@ -919,9 +925,8 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
- for (i = 0; i < PVD_reserved5_size; ++i)
- if (h[PVD_reserved5_offset + i] != 0)
- return (0);
+ if (!isNull(iso9660, h, PVD_reserved5_offset, PVD_reserved5_size))
+ return (0);
/* XXX TODO: Check other values for sanity; reject more
* malformed PVDs. XXX */
@@ -934,8 +939,10 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h)
if (!iso9660->primary.location) {
iso9660->logical_block_size = logical_block_size;
iso9660->volume_block = volume_block;
- iso9660->volume_size = logical_block_size * (uint64_t)volume_block;
- iso9660->primary.location = archive_le32dec(p + DR_extent_offset);
+ iso9660->volume_size =
+ logical_block_size * (uint64_t)volume_block;
+ iso9660->primary.location =
+ archive_le32dec(p + DR_extent_offset);
iso9660->primary.size = archive_le32dec(p + DR_size_offset);
}
@@ -951,6 +958,12 @@ read_children(struct archive_read *a, struct file_info *parent)
size_t step, skip_size;
iso9660 = (struct iso9660 *)(a->format->data);
+ /* flush any remaining bytes from the last round to ensure
+ * we're positioned */
+ if (iso9660->entry_bytes_unconsumed) {
+ __archive_read_consume(a, iso9660->entry_bytes_unconsumed);
+ iso9660->entry_bytes_unconsumed = 0;
+ }
if (iso9660->current_position > parent->offset) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Ignoring out-of-order directory (%s) %jd > %jd",
@@ -1060,101 +1073,112 @@ read_children(struct archive_read *a, struct file_info *parent)
}
static int
-archive_read_format_iso9660_read_header(struct archive_read *a,
- struct archive_entry *entry)
+choose_volume(struct archive_read *a, struct iso9660 *iso9660)
{
- struct iso9660 *iso9660;
struct file_info *file;
- int r, rd_r = ARCHIVE_OK;
-
- iso9660 = (struct iso9660 *)(a->format->data);
+ int64_t skipsize;
+ struct vd *vd;
+ const void *block;
+ char seenJoliet;
- if (!a->archive.archive_format) {
- a->archive.archive_format = ARCHIVE_FORMAT_ISO9660;
- a->archive.archive_format_name = "ISO9660";
+ vd = &(iso9660->primary);
+ if (!iso9660->opt_support_joliet)
+ iso9660->seenJoliet = 0;
+ if (iso9660->seenJoliet &&
+ vd->location > iso9660->joliet.location)
+ /* This condition is unlikely; by way of caution. */
+ vd = &(iso9660->joliet);
+
+ skipsize = LOGICAL_BLOCK_SIZE * vd->location;
+ skipsize = __archive_read_consume(a, skipsize);
+ if (skipsize < 0)
+ return ((int)skipsize);
+ iso9660->current_position = skipsize;
+
+ block = __archive_read_ahead(a, vd->size, NULL);
+ if (block == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Failed to read full block when scanning "
+ "ISO9660 directory list");
+ return (ARCHIVE_FATAL);
}
- if (iso9660->current_position == 0) {
- int64_t skipsize;
- struct vd *vd;
- const void *block;
- char seenJoliet;
-
- vd = &(iso9660->primary);
- if (!iso9660->opt_support_joliet)
- iso9660->seenJoliet = 0;
- if (iso9660->seenJoliet &&
- vd->location > iso9660->joliet.location)
- /* This condition is unlikely; by way of caution. */
- vd = &(iso9660->joliet);
+ /*
+ * While reading Root Directory, flag seenJoliet must be zero to
+ * avoid converting special name 0x00(Current Directory) and
+ * next byte to UCS2.
+ */
+ seenJoliet = iso9660->seenJoliet;/* Save flag. */
+ iso9660->seenJoliet = 0;
+ file = parse_file_info(a, NULL, block);
+ if (file == NULL)
+ return (ARCHIVE_FATAL);
+ iso9660->seenJoliet = seenJoliet;
+
+ /*
+ * If the iso image has both RockRidge and Joliet, we preferentially
+ * use RockRidge Extensions rather than Joliet ones.
+ */
+ if (vd == &(iso9660->primary) && iso9660->seenRockridge
+ && iso9660->seenJoliet)
+ iso9660->seenJoliet = 0;
+ if (vd == &(iso9660->primary) && !iso9660->seenRockridge
+ && iso9660->seenJoliet) {
+ /* Switch reading data from primary to joliet. */
+ vd = &(iso9660->joliet);
skipsize = LOGICAL_BLOCK_SIZE * vd->location;
+ skipsize -= iso9660->current_position;
skipsize = __archive_read_consume(a, skipsize);
if (skipsize < 0)
return ((int)skipsize);
- iso9660->current_position = skipsize;
+ iso9660->current_position += skipsize;
block = __archive_read_ahead(a, vd->size, NULL);
if (block == NULL) {
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_MISC,
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Failed to read full block when scanning "
"ISO9660 directory list");
return (ARCHIVE_FATAL);
}
-
- /*
- * While reading Root Directory, flag seenJoliet
- * must be zero to avoid converting special name
- * 0x00(Current Directory) and next byte to UCS2.
- */
- seenJoliet = iso9660->seenJoliet;/* Save flag. */
iso9660->seenJoliet = 0;
file = parse_file_info(a, NULL, block);
if (file == NULL)
return (ARCHIVE_FATAL);
iso9660->seenJoliet = seenJoliet;
- if (vd == &(iso9660->primary) && iso9660->seenRockridge
- && iso9660->seenJoliet)
- /*
- * If iso image has RockRidge and Joliet,
- * we use RockRidge Extensions.
- */
- iso9660->seenJoliet = 0;
- if (vd == &(iso9660->primary) && !iso9660->seenRockridge
- && iso9660->seenJoliet) {
- /* Switch reading data from primary to joliet. */
- vd = &(iso9660->joliet);
- skipsize = LOGICAL_BLOCK_SIZE * vd->location;
- skipsize -= iso9660->current_position;
- skipsize = __archive_read_consume(a, skipsize);
- if (skipsize < 0)
- return ((int)skipsize);
- iso9660->current_position += skipsize;
-
- block = __archive_read_ahead(a, vd->size, NULL);
- if (block == NULL) {
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_MISC,
- "Failed to read full block when scanning "
- "ISO9660 directory list");
- return (ARCHIVE_FATAL);
- }
- iso9660->seenJoliet = 0;
- file = parse_file_info(a, NULL, block);
- if (file == NULL)
- return (ARCHIVE_FATAL);
- iso9660->seenJoliet = seenJoliet;
- }
- /* Store the root directory in the pending list. */
- if (add_entry(a, iso9660, file) != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
- if (iso9660->seenRockridge) {
- a->archive.archive_format =
- ARCHIVE_FORMAT_ISO9660_ROCKRIDGE;
- a->archive.archive_format_name =
- "ISO9660 with Rockridge extensions";
- }
+ }
+
+ /* Store the root directory in the pending list. */
+ if (add_entry(a, iso9660, file) != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+ if (iso9660->seenRockridge) {
+ a->archive.archive_format = ARCHIVE_FORMAT_ISO9660_ROCKRIDGE;
+ a->archive.archive_format_name =
+ "ISO9660 with Rockridge extensions";
+ }
+
+ return (ARCHIVE_OK);
+}
+
+static int
+archive_read_format_iso9660_read_header(struct archive_read *a,
+ struct archive_entry *entry)
+{
+ struct iso9660 *iso9660;
+ struct file_info *file;
+ int r, rd_r = ARCHIVE_OK;
+
+ iso9660 = (struct iso9660 *)(a->format->data);
+
+ if (!a->archive.archive_format) {
+ a->archive.archive_format = ARCHIVE_FORMAT_ISO9660;
+ a->archive.archive_format_name = "ISO9660";
+ }
+
+ if (iso9660->current_position == 0) {
+ r = choose_volume(a, iso9660);
+ if (r != ARCHIVE_OK)
+ return (r);
}
file = NULL;/* Eliminate a warning. */
@@ -1227,14 +1251,14 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
}
iso9660->entry_bytes_remaining = file->size;
- iso9660->entry_sparse_offset = 0; /* Offset for sparse-file-aware clients. */
+ /* Offset for sparse-file-aware clients. */
+ iso9660->entry_sparse_offset = 0;
if (file->offset + file->size > iso9660->volume_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"File is beyond end-of-media: %s",
archive_entry_pathname(entry));
iso9660->entry_bytes_remaining = 0;
- iso9660->entry_sparse_offset = 0;
return (ARCHIVE_WARN);
}
@@ -1286,36 +1310,33 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
iso9660->previous_pathname.s);
archive_entry_unset_size(entry);
iso9660->entry_bytes_remaining = 0;
- iso9660->entry_sparse_offset = 0;
return (rd_r);
}
- /* Except for the hardlink case above, if the offset of the
- * next entry is before our current position, we can't seek
- * backwards to extract it, so issue a warning. Note that
- * this can only happen if this entry was added to the heap
- * after we passed this offset, that is, only if the directory
- * mentioning this entry is later than the body of the entry.
- * Such layouts are very unusual; most ISO9660 writers lay out
- * and record all directory information first, then store
- * all file bodies. */
- /* TODO: Someday, libarchive's I/O core will support optional
- * seeking. When that day comes, this code should attempt to
- * seek and only return the error if the seek fails. That
- * will give us support for whacky ISO images that require
- * seeking while retaining the ability to read almost all ISO
- * images in a streaming fashion. */
if ((file->mode & AE_IFMT) != AE_IFDIR &&
file->offset < iso9660->current_position) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Ignoring out-of-order file @%jx (%s) %jd < %jd",
- (intmax_t)file->number,
- iso9660->pathname.s,
- (intmax_t)file->offset,
- (intmax_t)iso9660->current_position);
- iso9660->entry_bytes_remaining = 0;
- iso9660->entry_sparse_offset = 0;
- return (ARCHIVE_WARN);
+ int64_t r64;
+
+ r64 = __archive_read_seek(a, file->offset, SEEK_SET);
+ if (r64 != (int64_t)file->offset) {
+ /* We can't seek backwards to extract it, so issue
+ * a warning. Note that this can only happen if
+ * this entry was added to the heap after we passed
+ * this offset, that is, only if the directory
+ * mentioning this entry is later than the body of
+ * the entry. Such layouts are very unusual; most
+ * ISO9660 writers lay out and record all directory
+ * information first, then store all file bodies. */
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Ignoring out-of-order file @%jx (%s) %jd < %jd",
+ (intmax_t)file->number,
+ iso9660->pathname.s,
+ (intmax_t)file->offset,
+ (intmax_t)iso9660->current_position);
+ iso9660->entry_bytes_remaining = 0;
+ return (ARCHIVE_WARN);
+ }
+ iso9660->current_position = (uint64_t)r64;
}
/* Initialize zisofs variables. */
@@ -1356,7 +1377,6 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
archive_entry_set_nlink(entry, 2 + file->subdirs);
/* Directory data has been read completely. */
iso9660->entry_bytes_remaining = 0;
- iso9660->entry_sparse_offset = 0;
}
if (rd_r != ARCHIVE_OK)
@@ -1426,7 +1446,7 @@ zisofs_read_data(struct archive_read *a,
zisofs->block_pointers_size = xsize;
/* Allocate uncompressed data buffer. */
- xsize = 1UL << zisofs->pz_log2_bs;
+ xsize = (size_t)1UL << zisofs->pz_log2_bs;
if (zisofs->uncompressed_buffer_size < xsize) {
if (zisofs->uncompressed_buffer != NULL)
free(zisofs->uncompressed_buffer);
@@ -1563,9 +1583,10 @@ zisofs_read_data(struct archive_read *a,
if (avail > zisofs->block_avail)
zisofs->stream.avail_in = zisofs->block_avail;
else
- zisofs->stream.avail_in = avail;
+ zisofs->stream.avail_in = (uInt)avail;
zisofs->stream.next_out = zisofs->uncompressed_buffer;
- zisofs->stream.avail_out = zisofs->uncompressed_buffer_size;
+ zisofs->stream.avail_out =
+ (uInt)zisofs->uncompressed_buffer_size;
r = inflate(&zisofs->stream, 0);
switch (r) {
@@ -1580,7 +1601,7 @@ zisofs_read_data(struct archive_read *a,
uncompressed_size =
zisofs->uncompressed_buffer_size - zisofs->stream.avail_out;
avail -= zisofs->stream.next_in - p;
- zisofs->block_avail -= zisofs->stream.next_in - p;
+ zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p);
}
next_data:
bytes_read -= avail;
@@ -1590,7 +1611,7 @@ next_data:
iso9660->entry_sparse_offset += uncompressed_size;
iso9660->entry_bytes_remaining -= bytes_read;
iso9660->current_position += bytes_read;
- zisofs->pz_offset += bytes_read;
+ zisofs->pz_offset += (uint32_t)bytes_read;
iso9660->entry_bytes_unconsumed += bytes_read;
return (ARCHIVE_OK);
@@ -1873,9 +1894,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
if (iso9660->opt_support_rockridge) {
if (parent == NULL && rr_end - rr_start >= 7) {
p = rr_start;
- if (p[0] == 'S' && p[1] == 'P'
- && p[2] == 7 && p[3] == 1
- && p[4] == 0xBE && p[5] == 0xEF) {
+ if (memcmp(p, "SP\x07\x01\xbe\xef", 6) == 0) {
/*
* SP extension stores the suspOffset
* (Number of bytes to skip between
@@ -1935,6 +1954,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
if (iso9660->seenRockridge) {
if (parent != NULL && parent->parent == NULL &&
(flags & 0x02) && iso9660->rr_moved == NULL &&
+ file->name.s &&
(strcmp(file->name.s, "rr_moved") == 0 ||
strcmp(file->name.s, ".rr_moved") == 0)) {
iso9660->rr_moved = file;
@@ -2067,14 +2087,9 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
int data_length = p[2] - 4;
int version = p[3];
- /*
- * Yes, each 'if' here does test p[0] again.
- * Otherwise, the fall-through handling to catch
- * unsupported extensions doesn't work.
- */
switch(p[0]) {
case 'C':
- if (p[0] == 'C' && p[1] == 'E') {
+ if (p[1] == 'E') {
if (version == 1 && data_length == 24) {
/*
* CE extension comprises:
@@ -2092,53 +2107,42 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
!= ARCHIVE_OK)
return (ARCHIVE_FATAL);
}
- break;
}
- if (p[0] == 'C' && p[1] == 'L') {
+ else if (p[1] == 'L') {
if (version == 1 && data_length == 8) {
file->cl_offset = (uint64_t)
iso9660->logical_block_size *
(uint64_t)archive_le32dec(data);
iso9660->seenRockridge = 1;
}
- break;
}
- /* FALLTHROUGH */
+ break;
case 'N':
- if (p[0] == 'N' && p[1] == 'M') {
+ if (p[1] == 'M') {
if (version == 1) {
parse_rockridge_NM1(file,
data, data_length);
iso9660->seenRockridge = 1;
}
- break;
}
- /* FALLTHROUGH */
+ break;
case 'P':
- if (p[0] == 'P' && p[1] == 'D') {
- /*
- * PD extension is padding;
- * contents are always ignored.
- */
- break;
- }
- if (p[0] == 'P' && p[1] == 'L') {
- /*
- * PL extension won't appear;
- * contents are always ignored.
- */
- break;
- }
- if (p[0] == 'P' && p[1] == 'N') {
+ /*
+ * PD extension is padding;
+ * contents are always ignored.
+ *
+ * PL extension won't appear;
+ * contents are always ignored.
+ */
+ if (p[1] == 'N') {
if (version == 1 && data_length == 16) {
file->rdev = toi(data,4);
file->rdev <<= 32;
file->rdev |= toi(data + 8, 4);
iso9660->seenRockridge = 1;
}
- break;
}
- if (p[0] == 'P' && p[1] == 'X') {
+ else if (p[1] == 'X') {
/*
* PX extension comprises:
* 8 bytes for mode,
@@ -2165,35 +2169,31 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
= toi(data + 32, 4);
iso9660->seenRockridge = 1;
}
- break;
}
- /* FALLTHROUGH */
+ break;
case 'R':
- if (p[0] == 'R' && p[1] == 'E' && version == 1) {
+ if (p[1] == 'E' && version == 1) {
file->re = 1;
iso9660->seenRockridge = 1;
- break;
}
- if (p[0] == 'R' && p[1] == 'R' && version == 1) {
+ else if (p[1] == 'R' && version == 1) {
/*
* RR extension comprises:
* one byte flag value
* This extension is obsolete,
* so contents are always ignored.
*/
- break;
}
- /* FALLTHROUGH */
+ break;
case 'S':
- if (p[0] == 'S' && p[1] == 'L') {
+ if (p[1] == 'L') {
if (version == 1) {
parse_rockridge_SL1(file,
data, data_length);
iso9660->seenRockridge = 1;
}
- break;
}
- if (p[0] == 'S' && p[1] == 'T'
+ else if (p[1] == 'T'
&& data_length == 0 && version == 1) {
/*
* ST extension marks end of this
@@ -2208,32 +2208,27 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
iso9660->seenRockridge = 0;
return (ARCHIVE_OK);
}
+ break;
case 'T':
- if (p[0] == 'T' && p[1] == 'F') {
+ if (p[1] == 'F') {
if (version == 1) {
parse_rockridge_TF1(file,
data, data_length);
iso9660->seenRockridge = 1;
}
- break;
}
- /* FALLTHROUGH */
+ break;
case 'Z':
- if (p[0] == 'Z' && p[1] == 'F') {
+ if (p[1] == 'F') {
if (version == 1)
parse_rockridge_ZF1(file,
data, data_length);
- break;
}
- /* FALLTHROUGH */
+ break;
default:
- /* The FALLTHROUGHs above leave us here for
- * any unsupported extension. */
break;
}
-
-
p += p[2];
}
return (ARCHIVE_OK);
@@ -2893,8 +2888,9 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
fatal_rr:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Failed to connect 'CL' pointer to 'RE' rr_moved pointer of"
- "Rockridge extensions");
+ "Failed to connect 'CL' pointer to 'RE' rr_moved pointer of "
+ "Rockridge extensions: current position = %jd, CL offset = %jd",
+ (intmax_t)iso9660->current_position, (intmax_t)file->cl_offset);
return (ARCHIVE_FATAL);
}
@@ -3226,10 +3222,12 @@ dump_isodirrec(FILE *out, const unsigned char *isodirrec)
fprintf(out, " ilv %d,",
toi(isodirrec + DR_interleave_offset, DR_interleave_size));
fprintf(out, " seq %d,",
- toi(isodirrec + DR_volume_sequence_number_offset, DR_volume_sequence_number_size));
+ toi(isodirrec + DR_volume_sequence_number_offset,
+ DR_volume_sequence_number_size));
fprintf(out, " nl %d:",
toi(isodirrec + DR_name_len_offset, DR_name_len_size));
fprintf(out, " `%.*s'",
- toi(isodirrec + DR_name_len_offset, DR_name_len_size), isodirrec + DR_name_offset);
+ toi(isodirrec + DR_name_len_offset, DR_name_len_size),
+ isodirrec + DR_name_offset);
}
#endif
diff --git a/libarchive/archive_read_support_format_lha.c b/libarchive/archive_read_support_format_lha.c
index a92b072ab60e..f702949fb8c1 100644
--- a/libarchive/archive_read_support_format_lha.c
+++ b/libarchive/archive_read_support_format_lha.c
@@ -272,7 +272,7 @@ static int lha_skip_sfx(struct archive_read *);
static time_t lha_dos_time(const unsigned char *);
static time_t lha_win_time(uint64_t, long *);
static unsigned char lha_calcsum(unsigned char, const void *,
- int, int);
+ int, size_t);
static int lha_parse_linkname(struct archive_string *,
struct archive_string *);
static int lha_read_data_none(struct archive_read *, const void **,
@@ -319,6 +319,7 @@ archive_read_support_format_lha(struct archive *_a)
archive_read_format_lha_read_header,
archive_read_format_lha_read_data,
archive_read_format_lha_read_data_skip,
+ NULL,
archive_read_format_lha_cleanup);
if (r != ARCHIVE_OK)
@@ -1634,7 +1635,7 @@ lha_parse_linkname(struct archive_string *linkname,
struct archive_string *pathname)
{
char * linkptr;
- int symlen;
+ size_t symlen;
linkptr = strchr(pathname->s, '|');
if (linkptr != NULL) {
@@ -1689,12 +1690,12 @@ lha_win_time(uint64_t wintime, long *ns)
}
static unsigned char
-lha_calcsum(unsigned char sum, const void *pp, int offset, int size)
+lha_calcsum(unsigned char sum, const void *pp, int offset, size_t size)
{
unsigned char const *p = (unsigned char const *)pp;
p += offset;
- while (--size >= 0)
+ for (;size > 0; --size)
sum += *p++;
return (sum);
}
@@ -2019,7 +2020,7 @@ lzh_copy_from_window(struct lzh_stream *strm, struct lzh_dec *ds)
copy_bytes = (size_t)strm->avail_out;
memcpy(strm->next_out,
ds->w_buff + ds->copy_pos, copy_bytes);
- ds->copy_pos += copy_bytes;
+ ds->copy_pos += (int)copy_bytes;
} else {
if (ds->w_remaining <= strm->avail_out)
copy_bytes = ds->w_remaining;
@@ -2027,7 +2028,7 @@ lzh_copy_from_window(struct lzh_stream *strm, struct lzh_dec *ds)
copy_bytes = (size_t)strm->avail_out;
memcpy(strm->next_out,
ds->w_buff + ds->w_size - ds->w_remaining, copy_bytes);
- ds->w_remaining -= copy_bytes;
+ ds->w_remaining -= (int)copy_bytes;
}
strm->next_out += copy_bytes;
strm->avail_out -= copy_bytes;
@@ -2481,7 +2482,7 @@ lzh_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
bits = tbl_bits;
else
bits = HTBL_BITS;
- hf->tbl = malloc((1 << bits) * sizeof(hf->tbl[0]));
+ hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0]));
if (hf->tbl == NULL)
return (ARCHIVE_FATAL);
}
@@ -2491,7 +2492,7 @@ lzh_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
if (hf->tree == NULL)
return (ARCHIVE_FATAL);
}
- hf->len_size = len_size;
+ hf->len_size = (int)len_size;
hf->tbl_bits = tbl_bits;
return (ARCHIVE_OK);
}
diff --git a/libarchive/archive_read_support_format_mtree.c b/libarchive/archive_read_support_format_mtree.c
index 6fb57629197f..c4e7021a869b 100644
--- a/libarchive/archive_read_support_format_mtree.c
+++ b/libarchive/archive_read_support_format_mtree.c
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2008 Joerg Sonnenberger
- * Copyright (c) 2011 Michihiro NAKAJIMA
+ * Copyright (c) 2011-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -55,6 +55,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
#ifndef O_BINARY
#define O_BINARY 0
#endif
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
#define MTREE_HAS_DEVICE 0x0001
#define MTREE_HAS_FFLAGS 0x0002
@@ -69,6 +72,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
#define MTREE_HAS_UNAME 0x0400
#define MTREE_HAS_OPTIONAL 0x0800
+#define MTREE_HAS_NOCHANGE 0x1000 /* FreeBSD specific */
struct mtree_option {
struct mtree_option *next;
@@ -103,6 +107,7 @@ struct mtree {
static int bid_keycmp(const char *, const char *, ssize_t);
static int cleanup(struct archive_read *);
+static int detect_form(struct archive_read *, int *);
static int mtree_bid(struct archive_read *, int);
static int parse_file(struct archive_read *, struct archive_entry *,
struct mtree *, struct mtree_entry *, int *);
@@ -200,7 +205,7 @@ archive_read_support_format_mtree(struct archive *_a)
mtree->fd = -1;
r = __archive_read_register_format(a, mtree, "mtree",
- mtree_bid, NULL, read_header, read_data, skip, cleanup);
+ mtree_bid, NULL, read_header, read_data, skip, NULL, cleanup);
if (r != ARCHIVE_OK)
free(mtree);
@@ -349,7 +354,7 @@ bid_keycmp(const char *p, const char *key, ssize_t len)
* Returns the length of a detected keyword.
* Returns 0 if any keywords were not found.
*/
-static ssize_t
+static int
bid_keyword(const char *p, ssize_t len)
{
static const char *keys_c[] = {
@@ -368,7 +373,7 @@ bid_keyword(const char *p, ssize_t len)
"md5", "md5digest", "mode", NULL
};
static const char *keys_no[] = {
- "nlink", "optional", NULL
+ "nlink", "nochange", "optional", NULL
};
static const char *keys_r[] = {
"rmd160", "rmd160digest", NULL
@@ -419,7 +424,7 @@ bid_keyword(const char *p, ssize_t len)
* When "unset" is specified, expects a set of "<space characters>keyword".
*/
static int
-bid_keyword_list(const char *p, ssize_t len, int unset)
+bid_keyword_list(const char *p, ssize_t len, int unset, int last_is_path)
{
int l;
int keycnt = 0;
@@ -437,8 +442,10 @@ bid_keyword_list(const char *p, ssize_t len, int unset)
break;
if (p[0] == '\\' && (p[1] == '\n' || p[1] == '\r'))
break;
- if (!blank) /* No blank character. */
+ if (!blank && !last_is_path) /* No blank character. */
return (-1);
+ if (last_is_path && len == 0)
+ return (keycnt);
if (unset) {
l = bid_keycmp(p, "all", len);
@@ -473,7 +480,7 @@ bid_keyword_list(const char *p, ssize_t len, int unset)
}
static int
-bid_entry(const char *p, ssize_t len)
+bid_entry(const char *p, ssize_t len, ssize_t nl, int *last_is_path)
{
int f = 0;
static const unsigned char safe_char[256] = {
@@ -500,22 +507,60 @@ bid_entry(const char *p, ssize_t len)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
};
+ ssize_t ll = len;
+ const char *pp = p;
+ *last_is_path = 0;
/*
* Skip the path-name which is quoted.
*/
- while (len > 0 && *p != ' ' && *p != '\t') {
- if (!safe_char[*(const unsigned char *)p])
- return (-1);
- ++p;
- --len;
+ while (ll > 0 && *pp != ' ' &&*pp != '\t' && *pp != '\r' &&
+ *pp != '\n') {
+ if (!safe_char[*(const unsigned char *)pp]) {
+ f = 0;
+ break;
+ }
+ ++pp;
+ --ll;
++f;
}
- /* If a path-name was not found, returns error. */
- if (f == 0)
- return (-1);
+ /* If a path-name was not found at the first, try to check
+ * a mtree format ``NetBSD's mtree -D'' creates, which
+ * places the path-name at the last. */
+ if (f == 0) {
+ const char *pb = p + len - nl;
+ int name_len = 0;
+ int slash;
+
+ /* Do not accept multi lines for form D. */
+ if (pb-2 >= p &&
+ pb[-1] == '\\' && (pb[-2] == ' ' || pb[-2] == '\t'))
+ return (-1);
+ if (pb-1 >= p && pb[-1] == '\\')
+ return (-1);
- return (bid_keyword_list(p, len, 0));
+ slash = 0;
+ while (p <= --pb && *pb != ' ' && *pb != '\t') {
+ if (!safe_char[*(const unsigned char *)pb])
+ return (-1);
+ name_len++;
+ /* The pathname should have a slash in this
+ * format. */
+ if (*pb == '/')
+ slash = 1;
+ }
+ if (name_len == 0 || slash == 0)
+ return (-1);
+ /* If '/' is placed at the first in this field, this is not
+ * a valid filename. */
+ if (pb[1] == '/')
+ return (-1);
+ ll = len - nl - name_len;
+ pp = p;
+ *last_is_path = 1;
+ }
+
+ return (bid_keyword_list(pp, ll, 0, *last_is_path));
}
#define MAX_BID_ENTRY 3
@@ -525,14 +570,11 @@ mtree_bid(struct archive_read *a, int best_bid)
{
const char *signature = "#mtree";
const char *p;
- ssize_t avail, ravail;
- ssize_t len, nl;
- int detected_bytes = 0, entry_cnt = 0, multiline = 0;
(void)best_bid; /* UNUSED */
/* Now let's look at the actual header and see if it matches. */
- p = __archive_read_ahead(a, strlen(signature), &avail);
+ p = __archive_read_ahead(a, strlen(signature), NULL);
if (p == NULL)
return (-1);
@@ -542,6 +584,24 @@ mtree_bid(struct archive_read *a, int best_bid)
/*
* There is not a mtree signature. Let's try to detect mtree format.
*/
+ return (detect_form(a, NULL));
+}
+
+static int
+detect_form(struct archive_read *a, int *is_form_d)
+{
+ const char *p;
+ ssize_t avail, ravail;
+ ssize_t detected_bytes = 0, len, nl;
+ int entry_cnt = 0, multiline = 0;
+ int form_D = 0;/* The archive is generated by `NetBSD mtree -D'
+ * (In this source we call it `form D') . */
+
+ if (is_form_d != NULL)
+ *is_form_d = 0;
+ p = __archive_read_ahead(a, 1, &avail);
+ if (p == NULL)
+ return (-1);
ravail = avail;
for (;;) {
len = next_line(a, &p, &avail, &ravail, &nl);
@@ -566,7 +626,7 @@ mtree_bid(struct archive_read *a, int best_bid)
} else {
/* A continuance line; the terminal
* character of previous line was '\' character. */
- if (bid_keyword_list(p, len, 0) <= 0)
+ if (bid_keyword_list(p, len, 0, 0) <= 0)
break;
if (multiline == 1)
detected_bytes += len;
@@ -581,9 +641,25 @@ mtree_bid(struct archive_read *a, int best_bid)
continue;
}
if (p[0] != '/') {
- if (bid_entry(p, len) >= 0) {
+ int last_is_path, keywords;
+
+ keywords = bid_entry(p, len, nl, &last_is_path);
+ if (keywords >= 0) {
detected_bytes += len;
- if (p[len-nl-1] == '\\')
+ if (form_D == 0) {
+ if (last_is_path)
+ form_D = 1;
+ else if (keywords > 0)
+ /* This line is not `form D'. */
+ form_D = -1;
+ } else if (form_D == 1) {
+ if (!last_is_path && keywords > 0)
+ /* This this is not `form D'
+ * and We cannot accept mixed
+ * format. */
+ break;
+ }
+ if (!last_is_path && p[len-nl-1] == '\\')
/* This line continues. */
multiline = 1;
else {
@@ -596,13 +672,13 @@ mtree_bid(struct archive_read *a, int best_bid)
} else
break;
} else if (strncmp(p, "/set", 4) == 0) {
- if (bid_keyword_list(p+4, len-4, 0) <= 0)
+ if (bid_keyword_list(p+4, len-4, 0, 0) <= 0)
break;
/* This line continues. */
if (p[len-nl-1] == '\\')
multiline = 2;
} else if (strncmp(p, "/unset", 6) == 0) {
- if (bid_keyword_list(p+6, len-6, 1) <= 0)
+ if (bid_keyword_list(p+6, len-6, 1, 0) <= 0)
break;
/* This line continues. */
if (p[len-nl-1] == '\\')
@@ -614,8 +690,13 @@ mtree_bid(struct archive_read *a, int best_bid)
p += len;
avail -= len;
}
- if (entry_cnt >= MAX_BID_ENTRY || (entry_cnt > 0 && len == 0))
+ if (entry_cnt >= MAX_BID_ENTRY || (entry_cnt > 0 && len == 0)) {
+ if (is_form_d != NULL) {
+ if (form_D == 1)
+ *is_form_d = 1;
+ }
return (32);
+ }
return (0);
}
@@ -739,12 +820,12 @@ process_global_unset(struct archive_read *a,
static int
process_add_entry(struct archive_read *a, struct mtree *mtree,
- struct mtree_option **global, const char *line,
- struct mtree_entry **last_entry)
+ struct mtree_option **global, const char *line, ssize_t line_len,
+ struct mtree_entry **last_entry, int is_form_d)
{
struct mtree_entry *entry;
struct mtree_option *iter;
- const char *next, *eq;
+ const char *next, *eq, *name, *end;
size_t len;
int r;
@@ -765,17 +846,46 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
(*last_entry)->next = entry;
*last_entry = entry;
- len = strcspn(line, " \t\r\n");
+ if (is_form_d) {
+ /*
+ * This form places the file name as last parameter.
+ */
+ name = line + line_len -1;
+ while (line_len > 0) {
+ if (*name != '\r' && *name != '\n' &&
+ *name != '\t' && *name != ' ')
+ break;
+ name--;
+ line_len--;
+ }
+ len = 0;
+ while (line_len > 0) {
+ if (*name == '\r' || *name == '\n' ||
+ *name == '\t' || *name == ' ') {
+ name++;
+ break;
+ }
+ name--;
+ line_len--;
+ len++;
+ }
+ end = name;
+ } else {
+ len = strcspn(line, " \t\r\n");
+ name = line;
+ line += len;
+ end = line + line_len;
+ }
+
if ((entry->name = malloc(len + 1)) == NULL) {
archive_set_error(&a->archive, errno, "Can't allocate memory");
return (ARCHIVE_FATAL);
}
- memcpy(entry->name, line, len);
+ memcpy(entry->name, name, len);
entry->name[len] = '\0';
parse_escapes(entry->name, entry);
- line += len;
for (iter = *global; iter != NULL; iter = iter->next) {
r = add_option(a, &entry->options, iter->value,
strlen(iter->value));
@@ -787,6 +897,8 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
next = line + strspn(line, " \t\r\n");
if (*next == '\0')
return (ARCHIVE_OK);
+ if (next >= end)
+ return (ARCHIVE_OK);
line = next;
next = line + strcspn(line, " \t\r\n");
eq = strchr(line, '=');
@@ -811,7 +923,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
char *p;
struct mtree_option *global;
struct mtree_entry *last_entry;
- int r;
+ int r, is_form_d;
mtree->archive_format = ARCHIVE_FORMAT_MTREE;
mtree->archive_format_name = "mtree";
@@ -819,6 +931,8 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
global = NULL;
last_entry = NULL;
+ (void)detect_form(a, &is_form_d);
+
for (counter = 1; ; ++counter) {
len = readline(a, mtree, &p, 65536);
if (len == 0) {
@@ -828,7 +942,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
}
if (len < 0) {
free_options(global);
- return (len);
+ return ((int)len);
}
/* Leading whitespace is never significant, ignore it. */
while (*p == ' ' || *p == '\t') {
@@ -841,8 +955,8 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
if (*p == '\r' || *p == '\n' || *p == '\0')
continue;
if (*p != '/') {
- r = process_add_entry(a, mtree, &global, p,
- &last_entry);
+ r = process_add_entry(a, mtree, &global, p, len,
+ &last_entry, is_form_d);
} else if (strncmp(p, "/set", 4) == 0) {
if (p[4] != ' ' && p[4] != '\t')
break;
@@ -1008,7 +1122,8 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
if (archive_entry_filetype(entry) == AE_IFREG ||
archive_entry_filetype(entry) == AE_IFDIR) {
- mtree->fd = open(path, O_RDONLY | O_BINARY);
+ mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(mtree->fd);
if (mtree->fd == -1 &&
(errno != ENOENT ||
archive_strlen(&mtree->contents_name) > 0)) {
@@ -1091,15 +1206,19 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
* if it wasn't already parsed from the specification.
*/
if (st != NULL) {
- if ((parsed_kws & MTREE_HAS_DEVICE) == 0 &&
+ if (((parsed_kws & MTREE_HAS_DEVICE) == 0 ||
+ (parsed_kws & MTREE_HAS_NOCHANGE) != 0) &&
(archive_entry_filetype(entry) == AE_IFCHR ||
archive_entry_filetype(entry) == AE_IFBLK))
archive_entry_set_rdev(entry, st->st_rdev);
- if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME)) == 0)
+ if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME)) == 0 ||
+ (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_gid(entry, st->st_gid);
- if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME)) == 0)
+ if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME)) == 0 ||
+ (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_uid(entry, st->st_uid);
- if ((parsed_kws & MTREE_HAS_MTIME) == 0) {
+ if ((parsed_kws & MTREE_HAS_MTIME) == 0 ||
+ (parsed_kws & MTREE_HAS_NOCHANGE) != 0) {
#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtimespec.tv_nsec);
@@ -1119,11 +1238,14 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
archive_entry_set_mtime(entry, st->st_mtime, 0);
#endif
}
- if ((parsed_kws & MTREE_HAS_NLINK) == 0)
+ if ((parsed_kws & MTREE_HAS_NLINK) == 0 ||
+ (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_nlink(entry, st->st_nlink);
- if ((parsed_kws & MTREE_HAS_PERM) == 0)
+ if ((parsed_kws & MTREE_HAS_PERM) == 0 ||
+ (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_perm(entry, st->st_mode);
- if ((parsed_kws & MTREE_HAS_SIZE) == 0)
+ if ((parsed_kws & MTREE_HAS_SIZE) == 0 ||
+ (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_size(entry, st->st_size);
archive_entry_set_ino(entry, st->st_ino);
archive_entry_set_dev(entry, st->st_dev);
@@ -1213,6 +1335,10 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
if (*key == '\0')
return (ARCHIVE_OK);
+ if (strcmp(key, "nochange") == 0) {
+ *parsed_kws |= MTREE_HAS_NOCHANGE;
+ return (ARCHIVE_OK);
+ }
if (strcmp(key, "optional") == 0) {
*parsed_kws |= MTREE_HAS_OPTIONAL;
return (ARCHIVE_OK);
diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c
index 1e5c5fa72b30..99c57a0fc0eb 100644
--- a/libarchive/archive_read_support_format_rar.c
+++ b/libarchive/archive_read_support_format_rar.c
@@ -199,6 +199,13 @@ struct lzss
int64_t position;
};
+struct data_block_offsets
+{
+ int64_t header_size;
+ int64_t start_offset;
+ int64_t end_offset;
+};
+
struct rar
{
/* Entries from main RAR header */
@@ -217,6 +224,7 @@ struct rar
long mnsec;
mode_t mode;
char *filename;
+ char *filename_save;
size_t filename_allocated;
/* File header optional entries */
@@ -234,6 +242,7 @@ struct rar
int64_t bytes_uncopied;
int64_t offset;
int64_t offset_outgoing;
+ int64_t offset_seek;
char valid;
unsigned int unp_offset;
unsigned int unp_buffer_size;
@@ -243,6 +252,10 @@ struct rar
char entry_eof;
unsigned long crc_calculated;
int found_first_header;
+ char has_endarc_header;
+ struct data_block_offsets *dbo;
+ unsigned int cursor;
+ unsigned int nodes;
/* LZSS members */
struct huffman_code maincode;
@@ -301,6 +314,8 @@ static int archive_read_format_rar_read_header(struct archive_read *,
static int archive_read_format_rar_read_data(struct archive_read *,
const void **, size_t *, int64_t *);
static int archive_read_format_rar_read_data_skip(struct archive_read *a);
+static int64_t archive_read_format_rar_seek_data(struct archive_read *, int64_t,
+ int);
static int archive_read_format_rar_cleanup(struct archive_read *);
/* Support functions */
@@ -328,6 +343,7 @@ static int make_table_recurse(struct archive_read *, struct huffman_code *, int,
static int64_t expand(struct archive_read *, int64_t);
static int copy_from_lzss_window(struct archive_read *, const void **,
int64_t, int);
+static const void *rar_read_ahead(struct archive_read *, size_t, ssize_t *);
/*
* Bit stream reader.
@@ -449,11 +465,9 @@ rar_br_fillup(struct archive_read *a, struct rar_br *br)
__archive_read_consume(a, rar->bytes_unconsumed);
rar->bytes_unconsumed = 0;
}
- br->next_in = __archive_read_ahead(a, 1, &(br->avail_in));
+ br->next_in = rar_read_ahead(a, 1, &(br->avail_in));
if (br->next_in == NULL)
return (0);
- if (br->avail_in > rar->bytes_remaining)
- br->avail_in = (ssize_t)rar->bytes_remaining;
if (br->avail_in == 0)
return (0);
}
@@ -473,15 +487,13 @@ rar_br_preparation(struct archive_read *a, struct rar_br *br)
struct rar *rar = (struct rar *)(a->format->data);
if (rar->bytes_remaining > 0) {
- br->next_in = __archive_read_ahead(a, 1, &(br->avail_in));
+ br->next_in = rar_read_ahead(a, 1, &(br->avail_in));
if (br->next_in == NULL) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated RAR file data");
return (ARCHIVE_FATAL);
}
- if (br->avail_in > rar->bytes_remaining)
- br->avail_in = (ssize_t)rar->bytes_remaining;
if (br->cache_avail == 0)
(void)rar_br_fillup(a, br);
}
@@ -642,6 +654,7 @@ archive_read_support_format_rar(struct archive *_a)
archive_read_format_rar_read_header,
archive_read_format_rar_read_data,
archive_read_format_rar_read_data_skip,
+ archive_read_format_rar_seek_data,
archive_read_format_rar_cleanup);
if (r != ARCHIVE_OK)
@@ -844,13 +857,6 @@ archive_read_format_rar_read_header(struct archive_read *a,
sizeof(rar->reserved2));
}
- if (rar->main_flags & MHD_VOLUME ||
- rar->main_flags & MHD_FIRSTVOLUME)
- {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "RAR volume support unavailable.");
- return (ARCHIVE_FATAL);
- }
if (rar->main_flags & MHD_PASSWORD)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
@@ -858,7 +864,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
return (ARCHIVE_FATAL);
}
- crc32_val = crc32(0, (const unsigned char *)p + 2, skip - 2);
+ crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2);
if ((crc32_val & 0xffff) != archive_le16dec(p)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Header CRC error");
@@ -875,6 +881,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
case SUB_HEAD:
case PROTECT_HEAD:
case SIGN_HEAD:
+ case ENDARC_HEAD:
flags = archive_le16dec(p + 3);
skip = archive_le16dec(p + 5);
if (skip < 7) {
@@ -900,13 +907,15 @@ archive_read_format_rar_read_header(struct archive_read *a,
p = h;
}
- crc32_val = crc32(0, (const unsigned char *)p + 2, skip - 2);
+ crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2);
if ((crc32_val & 0xffff) != archive_le16dec(p)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Header CRC error");
return (ARCHIVE_FATAL);
}
__archive_read_consume(a, skip);
+ if (head_type == ENDARC_HEAD)
+ return (ARCHIVE_EOF);
break;
case NEWSUB_HEAD:
@@ -914,9 +923,6 @@ archive_read_format_rar_read_header(struct archive_read *a,
return ret;
break;
- case ENDARC_HEAD:
- return (ARCHIVE_EOF);
-
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Bad RAR file");
@@ -938,10 +944,12 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
rar->bytes_unconsumed = 0;
}
- if (rar->entry_eof) {
+ if (rar->entry_eof || rar->offset_seek >= rar->unp_size) {
*buff = NULL;
*size = 0;
*offset = rar->offset;
+ if (*offset < rar->unp_size)
+ *offset = rar->unp_size;
return (ARCHIVE_EOF);
}
@@ -975,6 +983,7 @@ archive_read_format_rar_read_data_skip(struct archive_read *a)
{
struct rar *rar;
int64_t bytes_skipped;
+ int ret;
rar = (struct rar *)(a->format->data);
@@ -989,9 +998,179 @@ archive_read_format_rar_read_data_skip(struct archive_read *a)
if (bytes_skipped < 0)
return (ARCHIVE_FATAL);
}
+
+ /* Compressed data to skip must be read from each header in a multivolume
+ * archive.
+ */
+ if (rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER)
+ {
+ ret = archive_read_format_rar_read_header(a, a->entry);
+ if (ret == (ARCHIVE_EOF))
+ ret = archive_read_format_rar_read_header(a, a->entry);
+ if (ret != (ARCHIVE_OK))
+ return ret;
+ return archive_read_format_rar_read_data_skip(a);
+ }
+
return (ARCHIVE_OK);
}
+static int64_t
+archive_read_format_rar_seek_data(struct archive_read *a, int64_t offset,
+ int whence)
+{
+ int64_t client_offset, ret;
+ unsigned int i;
+ struct rar *rar = (struct rar *)(a->format->data);
+
+ if (rar->compression_method == COMPRESS_METHOD_STORE)
+ {
+ /* Modify the offset for use with SEEK_SET */
+ switch (whence)
+ {
+ case SEEK_CUR:
+ client_offset = rar->offset_seek;
+ break;
+ case SEEK_END:
+ client_offset = rar->unp_size;
+ break;
+ case SEEK_SET:
+ default:
+ client_offset = 0;
+ }
+ client_offset += offset;
+ if (client_offset < 0)
+ {
+ /* Can't seek past beginning of data block */
+ return -1;
+ }
+ else if (client_offset > rar->unp_size)
+ {
+ /*
+ * Set the returned offset but only seek to the end of
+ * the data block.
+ */
+ rar->offset_seek = client_offset;
+ client_offset = rar->unp_size;
+ }
+
+ client_offset += rar->dbo[0].start_offset;
+ i = 0;
+ while (i < rar->cursor)
+ {
+ i++;
+ client_offset += rar->dbo[i].start_offset - rar->dbo[i-1].end_offset;
+ }
+ if (rar->main_flags & MHD_VOLUME)
+ {
+ /* Find the appropriate offset among the multivolume archive */
+ while (1)
+ {
+ if (client_offset < rar->dbo[rar->cursor].start_offset &&
+ rar->file_flags & FHD_SPLIT_BEFORE)
+ {
+ /* Search backwards for the correct data block */
+ if (rar->cursor == 0)
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Attempt to seek past beginning of RAR data block");
+ return (ARCHIVE_FAILED);
+ }
+ rar->cursor--;
+ client_offset -= rar->dbo[rar->cursor+1].start_offset -
+ rar->dbo[rar->cursor].end_offset;
+ if (client_offset < rar->dbo[rar->cursor].start_offset)
+ continue;
+ ret = __archive_read_seek(a, rar->dbo[rar->cursor].start_offset -
+ rar->dbo[rar->cursor].header_size, SEEK_SET);
+ if (ret < (ARCHIVE_OK))
+ return ret;
+ ret = archive_read_format_rar_read_header(a, a->entry);
+ if (ret != (ARCHIVE_OK))
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Error during seek of RAR file");
+ return (ARCHIVE_FAILED);
+ }
+ rar->cursor--;
+ break;
+ }
+ else if (client_offset > rar->dbo[rar->cursor].end_offset &&
+ rar->file_flags & FHD_SPLIT_AFTER)
+ {
+ /* Search forward for the correct data block */
+ rar->cursor++;
+ if (rar->cursor < rar->nodes &&
+ client_offset > rar->dbo[rar->cursor].end_offset)
+ {
+ client_offset += rar->dbo[rar->cursor].start_offset -
+ rar->dbo[rar->cursor-1].end_offset;
+ continue;
+ }
+ rar->cursor--;
+ ret = __archive_read_seek(a, rar->dbo[rar->cursor].end_offset,
+ SEEK_SET);
+ if (ret < (ARCHIVE_OK))
+ return ret;
+ ret = archive_read_format_rar_read_header(a, a->entry);
+ if (ret == (ARCHIVE_EOF))
+ {
+ rar->has_endarc_header = 1;
+ ret = archive_read_format_rar_read_header(a, a->entry);
+ }
+ if (ret != (ARCHIVE_OK))
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Error during seek of RAR file");
+ return (ARCHIVE_FAILED);
+ }
+ client_offset += rar->dbo[rar->cursor].start_offset -
+ rar->dbo[rar->cursor-1].end_offset;
+ continue;
+ }
+ break;
+ }
+ }
+
+ ret = __archive_read_seek(a, client_offset, SEEK_SET);
+ if (ret < (ARCHIVE_OK))
+ return ret;
+ rar->bytes_remaining = rar->dbo[rar->cursor].end_offset - ret;
+ i = rar->cursor;
+ while (i > 0)
+ {
+ i--;
+ ret -= rar->dbo[i+1].start_offset - rar->dbo[i].end_offset;
+ }
+ ret -= rar->dbo[0].start_offset;
+
+ /* Always restart reading the file after a seek */
+ a->read_data_block = NULL;
+ a->read_data_offset = 0;
+ a->read_data_output_offset = 0;
+ a->read_data_remaining = 0;
+ rar->bytes_unconsumed = 0;
+ rar->offset = 0;
+
+ /*
+ * If a seek past the end of file was requested, return the requested
+ * offset.
+ */
+ if (ret == rar->unp_size && rar->offset_seek > rar->unp_size)
+ return rar->offset_seek;
+
+ /* Return the new offset */
+ rar->offset_seek = ret;
+ return rar->offset_seek;
+ }
+ else
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Seeking of compressed RAR files is unsupported");
+ }
+ return (ARCHIVE_FAILED);
+}
+
static int
archive_read_format_rar_cleanup(struct archive_read *a)
{
@@ -1000,6 +1179,8 @@ archive_read_format_rar_cleanup(struct archive_read *a)
rar = (struct rar *)(a->format->data);
free_codes(a);
free(rar->filename);
+ free(rar->filename_save);
+ free(rar->dbo);
free(rar->unp_buffer);
free(rar->lzss.window);
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
@@ -1138,6 +1319,8 @@ read_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL);
}
+ rar->bytes_remaining = rar->packed_size;
+
/* TODO: RARv3 subblocks contain comments. For now the complete block is
* consumed at the end.
*/
@@ -1177,13 +1360,13 @@ read_header(struct archive_read *a, struct archive_entry *entry,
{
if (filename_size != strlen(filename))
{
- unsigned char highbyte, flagbits, flagbyte, offset;
- unsigned fn_end;
+ unsigned char highbyte, flagbits, flagbyte;
+ unsigned fn_end, offset;
end = filename_size;
fn_end = filename_size * 2;
filename_size = 0;
- offset = strlen(filename) + 1;
+ offset = (unsigned)strlen(filename) + 1;
highbyte = *(p + offset++);
flagbits = 0;
flagbyte = 0;
@@ -1284,6 +1467,51 @@ read_header(struct archive_read *a, struct archive_entry *entry,
p += filename_size;
}
+ /* Split file in multivolume RAR. No more need to process header. */
+ if (rar->filename_save &&
+ !memcmp(rar->filename, rar->filename_save, filename_size + 1))
+ {
+ __archive_read_consume(a, header_size - 7);
+ rar->cursor++;
+ if (rar->cursor >= rar->nodes)
+ {
+ rar->nodes++;
+ if ((rar->dbo =
+ realloc(rar->dbo, sizeof(*rar->dbo) * rar->nodes)) == NULL)
+ {
+ archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory.");
+ return (ARCHIVE_FATAL);
+ }
+ rar->dbo[rar->cursor].header_size = header_size;
+ rar->dbo[rar->cursor].start_offset = -1;
+ rar->dbo[rar->cursor].end_offset = -1;
+ }
+ if (rar->dbo[rar->cursor].start_offset < 0)
+ {
+ rar->dbo[rar->cursor].start_offset = a->filter->position;
+ rar->dbo[rar->cursor].end_offset = rar->dbo[rar->cursor].start_offset +
+ rar->packed_size;
+ }
+ return ret;
+ }
+
+ rar->filename_save = (char*)realloc(rar->filename_save,
+ filename_size + 1);
+ memcpy(rar->filename_save, rar->filename, filename_size + 1);
+
+ /* Set info for seeking */
+ free(rar->dbo);
+ if ((rar->dbo = calloc(1, sizeof(*rar->dbo))) == NULL)
+ {
+ archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory.");
+ return (ARCHIVE_FATAL);
+ }
+ rar->dbo[0].header_size = header_size;
+ rar->dbo[0].start_offset = -1;
+ rar->dbo[0].end_offset = -1;
+ rar->cursor = 0;
+ rar->nodes = 1;
+
if (rar->file_flags & FHD_SALT)
{
if (p + 8 > endp) {
@@ -1304,6 +1532,8 @@ read_header(struct archive_read *a, struct archive_entry *entry,
}
__archive_read_consume(a, header_size - 7);
+ rar->dbo[0].start_offset = a->filter->position;
+ rar->dbo[0].end_offset = rar->dbo[0].start_offset + rar->packed_size;
switch(file_header.host_os)
{
@@ -1330,9 +1560,9 @@ read_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL);
}
- rar->bytes_remaining = rar->packed_size;
rar->bytes_uncopied = rar->bytes_unconsumed = 0;
rar->lzss.position = rar->offset = 0;
+ rar->offset_seek = 0;
rar->dictionary_size = 0;
rar->offset_outgoing = 0;
rar->br.cache_avail = 0;
@@ -1488,7 +1718,7 @@ read_symlink_stored(struct archive_read *a, struct archive_entry *entry,
int ret = (ARCHIVE_OK);
rar = (struct rar *)(a->format->data);
- if ((h = __archive_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL)
+ if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL)
return (ARCHIVE_FATAL);
p = h;
@@ -1518,7 +1748,8 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size,
ssize_t bytes_avail;
rar = (struct rar *)(a->format->data);
- if (rar->bytes_remaining == 0)
+ if (rar->bytes_remaining == 0 &&
+ !(rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER))
{
*buff = NULL;
*size = 0;
@@ -1532,23 +1763,23 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size,
return (ARCHIVE_EOF);
}
- *buff = __archive_read_ahead(a, 1, &bytes_avail);
+ *buff = rar_read_ahead(a, 1, &bytes_avail);
if (bytes_avail <= 0)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated RAR file data");
return (ARCHIVE_FATAL);
}
- if (bytes_avail > rar->bytes_remaining)
- bytes_avail = (ssize_t)rar->bytes_remaining;
*size = bytes_avail;
*offset = rar->offset;
rar->offset += bytes_avail;
+ rar->offset_seek += bytes_avail;
rar->bytes_remaining -= bytes_avail;
rar->bytes_unconsumed = bytes_avail;
/* Calculate File CRC. */
- rar->crc_calculated = crc32(rar->crc_calculated, *buff, bytes_avail);
+ rar->crc_calculated = crc32(rar->crc_calculated, *buff,
+ (unsigned)bytes_avail);
return (ARCHIVE_OK);
}
@@ -1578,7 +1809,8 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
*offset = rar->offset_outgoing;
rar->offset_outgoing += *size;
/* Calculate File CRC. */
- rar->crc_calculated = crc32(rar->crc_calculated, *buff, *size);
+ rar->crc_calculated = crc32(rar->crc_calculated, *buff,
+ (unsigned)*size);
rar->unp_offset = 0;
return (ARCHIVE_OK);
}
@@ -1600,7 +1832,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
bs = rar->unp_buffer_size - rar->unp_offset;
else
bs = (size_t)rar->bytes_uncopied;
- ret = copy_from_lzss_window(a, buff, rar->offset, bs);
+ ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs);
if (ret != ARCHIVE_OK)
return (ret);
rar->offset += bs;
@@ -1611,7 +1843,8 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
*offset = rar->offset_outgoing;
rar->offset_outgoing += *size;
/* Calculate File CRC. */
- rar->crc_calculated = crc32(rar->crc_calculated, *buff, *size);
+ rar->crc_calculated = crc32(rar->crc_calculated, *buff,
+ (unsigned)*size);
return (ret);
}
continue;
@@ -1728,7 +1961,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
bs = rar->unp_buffer_size - rar->unp_offset;
else
bs = (size_t)rar->bytes_uncopied;
- ret = copy_from_lzss_window(a, buff, rar->offset, bs);
+ ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs);
if (ret != ARCHIVE_OK)
return (ret);
rar->offset += bs;
@@ -1744,7 +1977,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
*offset = rar->offset_outgoing;
rar->offset_outgoing += *size;
/* Calculate File CRC. */
- rar->crc_calculated = crc32(rar->crc_calculated, *buff, *size);
+ rar->crc_calculated = crc32(rar->crc_calculated, *buff, (unsigned)*size);
return ret;
}
@@ -1987,17 +2220,21 @@ parse_codes(struct archive_read *a)
/* Seems as though dictionary sizes are not used. Even so, minimize
* memory usage as much as possible.
*/
+ void *new_window;
+ unsigned int new_size;
+
if (rar->unp_size >= DICTIONARY_MAX_SIZE)
- rar->dictionary_size = DICTIONARY_MAX_SIZE;
+ new_size = DICTIONARY_MAX_SIZE;
else
- rar->dictionary_size = rar_fls((unsigned int)rar->unp_size) << 1;
- rar->lzss.window = (unsigned char *)realloc(rar->lzss.window,
- rar->dictionary_size);
- if (rar->lzss.window == NULL) {
+ new_size = rar_fls((unsigned int)rar->unp_size) << 1;
+ new_window = realloc(rar->lzss.window, new_size);
+ if (new_window == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Unable to allocate memory for uncompressed data.");
return (ARCHIVE_FATAL);
}
+ rar->lzss.window = (unsigned char *)new_window;
+ rar->dictionary_size = new_size;
memset(rar->lzss.window, 0, rar->dictionary_size);
rar->lzss.mask = rar->dictionary_size - 1;
}
@@ -2235,10 +2472,12 @@ add_value(struct archive_read *a, struct huffman_code *code, int value,
static int
new_node(struct huffman_code *code)
{
- code->tree = (struct huffman_tree_node *)realloc(code->tree,
- (code->numentries + 1) * sizeof(*code->tree));
- if (code->tree == NULL)
+ void *new_tree;
+
+ new_tree = realloc(code->tree, (code->numentries + 1) * sizeof(*code->tree));
+ if (new_tree == NULL)
return (-1);
+ code->tree = (struct huffman_tree_node *)new_tree;
code->tree[code->numentries].branches[0] = -1;
code->tree[code->numentries].branches[1] = -2;
return 1;
@@ -2253,8 +2492,8 @@ make_table(struct archive_read *a, struct huffman_code *code)
code->tablesize = code->maxlength;
code->table =
- (struct huffman_table_entry *)malloc(sizeof(*code->table)
- * (1 << code->tablesize));
+ (struct huffman_table_entry *)calloc(1, sizeof(*code->table)
+ * ((size_t)1 << code->tablesize));
return make_table_recurse(a, code, 0, code->table, 0, code->tablesize);
}
@@ -2586,3 +2825,34 @@ copy_from_lzss_window(struct archive_read *a, const void **buffer,
*buffer = NULL;
return (ARCHIVE_OK);
}
+
+static const void *
+rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
+{
+ struct rar *rar = (struct rar *)(a->format->data);
+ const void *h = __archive_read_ahead(a, min, avail);
+ int ret;
+ if (avail)
+ {
+ if (a->read_data_is_posix_read && *avail > (ssize_t)a->read_data_requested)
+ *avail = a->read_data_requested;
+ if (*avail > rar->bytes_remaining)
+ *avail = (ssize_t)rar->bytes_remaining;
+ if (*avail < 0)
+ return NULL;
+ else if (*avail == 0 && rar->main_flags & MHD_VOLUME &&
+ rar->file_flags & FHD_SPLIT_AFTER)
+ {
+ ret = archive_read_format_rar_read_header(a, a->entry);
+ if (ret == (ARCHIVE_EOF))
+ {
+ rar->has_endarc_header = 1;
+ ret = archive_read_format_rar_read_header(a, a->entry);
+ }
+ if (ret != (ARCHIVE_OK))
+ return NULL;
+ return rar_read_ahead(a, min, avail);
+ }
+ }
+ return h;
+}
diff --git a/libarchive/archive_read_support_format_raw.c b/libarchive/archive_read_support_format_raw.c
index df2c00c96c32..843497878a36 100644
--- a/libarchive/archive_read_support_format_raw.c
+++ b/libarchive/archive_read_support_format_raw.c
@@ -77,6 +77,7 @@ archive_read_support_format_raw(struct archive *_a)
archive_read_format_raw_read_header,
archive_read_format_raw_read_data,
archive_read_format_raw_read_data_skip,
+ NULL,
archive_read_format_raw_cleanup);
if (r != ARCHIVE_OK)
free(info);
@@ -157,7 +158,7 @@ archive_read_format_raw_read_data(struct archive_read *a,
/* Record and return an error. */
*size = 0;
*offset = info->offset;
- return (avail);
+ return ((int)avail);
}
}
diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c
index 4538331f3d05..e9523cb687c8 100644
--- a/libarchive/archive_read_support_format_tar.c
+++ b/libarchive/archive_read_support_format_tar.c
@@ -210,10 +210,10 @@ static int read_body_to_string(struct archive_read *, struct tar *,
struct archive_string *, const void *h, size_t *);
static int solaris_sparse_parse(struct archive_read *, struct tar *,
struct archive_entry *, const char *);
-static int64_t tar_atol(const char *, unsigned);
-static int64_t tar_atol10(const char *, unsigned);
-static int64_t tar_atol256(const char *, unsigned);
-static int64_t tar_atol8(const char *, unsigned);
+static int64_t tar_atol(const char *, size_t);
+static int64_t tar_atol10(const char *, size_t);
+static int64_t tar_atol256(const char *, size_t);
+static int64_t tar_atol8(const char *, size_t);
static int tar_read_header(struct archive_read *, struct tar *,
struct archive_entry *, size_t *);
static int tohex(int c);
@@ -253,6 +253,7 @@ archive_read_support_format_tar(struct archive *_a)
archive_read_format_tar_read_header,
archive_read_format_tar_read_data,
archive_read_format_tar_skip,
+ NULL,
archive_read_format_tar_cleanup);
if (r != ARCHIVE_OK)
@@ -616,13 +617,14 @@ tar_read_header(struct archive_read *a, struct tar *tar,
int err;
const char *h;
const struct archive_entry_header_ustar *header;
+ const struct archive_entry_header_gnutar *gnuheader;
tar_flush_unconsumed(a, unconsumed);
/* Read 512-byte header record */
h = __archive_read_ahead(a, 512, &bytes);
if (bytes < 0)
- return (bytes);
+ return ((int)bytes);
if (bytes == 0) { /* EOF at a block boundary. */
/* Some writers do omit the block of nulls. <sigh> */
return (ARCHIVE_EOF);
@@ -703,7 +705,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
err = header_pax_extensions(a, tar, entry, h, unconsumed);
break;
default:
- if (memcmp(header->magic, "ustar \0", 8) == 0) {
+ gnuheader = (const struct archive_entry_header_gnutar *)h;
+ if (memcmp(gnuheader->magic, "ustar \0", 8) == 0) {
a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
a->archive.archive_format_name = "GNU tar format";
err = header_gnutar(a, tar, entry, h, unconsumed);
@@ -752,7 +755,7 @@ tar_read_header(struct archive_read *a, struct tar *tar,
bytes_read = gnu_sparse_10_read(a, tar, unconsumed);
tar->entry_bytes_remaining -= bytes_read;
if (bytes_read < 0)
- return (bytes_read);
+ return ((int)bytes_read);
} else {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
@@ -2390,7 +2393,7 @@ solaris_sparse_parse(struct archive_read *a, struct tar *tar,
* On read, this implementation supports both extensions.
*/
static int64_t
-tar_atol(const char *p, unsigned char_cnt)
+tar_atol(const char *p, size_t char_cnt)
{
/*
* Technically, GNU tar considers a field to be in base-256
@@ -2407,70 +2410,55 @@ tar_atol(const char *p, unsigned char_cnt)
* it does obey locale.
*/
static int64_t
-tar_atol8(const char *p, unsigned char_cnt)
+tar_atol_base_n(const char *p, size_t char_cnt, int base)
{
int64_t l, limit, last_digit_limit;
- int digit, sign, base;
+ int digit, sign;
- base = 8;
limit = INT64_MAX / base;
last_digit_limit = INT64_MAX % base;
- while (*p == ' ' || *p == '\t')
+ /* the pointer will not be dereferenced if char_cnt is zero
+ * due to the way the && operator is evaulated.
+ */
+ while (char_cnt != 0 && (*p == ' ' || *p == '\t')) {
p++;
- if (*p == '-') {
+ char_cnt--;
+ }
+
+ sign = 1;
+ if (char_cnt != 0 && *p == '-') {
sign = -1;
p++;
- } else
- sign = 1;
+ char_cnt--;
+ }
l = 0;
- digit = *p - '0';
- while (digit >= 0 && digit < base && char_cnt-- > 0) {
- if (l>limit || (l == limit && digit > last_digit_limit)) {
- l = INT64_MAX; /* Truncate on overflow. */
- break;
+ if (char_cnt != 0) {
+ digit = *p - '0';
+ while (digit >= 0 && digit < base && char_cnt != 0) {
+ if (l>limit || (l == limit && digit > last_digit_limit)) {
+ l = INT64_MAX; /* Truncate on overflow. */
+ break;
+ }
+ l = (l * base) + digit;
+ digit = *++p - '0';
+ char_cnt--;
}
- l = (l * base) + digit;
- digit = *++p - '0';
}
return (sign < 0) ? -l : l;
}
-/*
- * Note that this implementation does not (and should not!) obey
- * locale settings; you cannot simply substitute strtol here, since
- * it does obey locale.
- */
static int64_t
-tar_atol10(const char *p, unsigned char_cnt)
+tar_atol8(const char *p, size_t char_cnt)
{
- int64_t l, limit, last_digit_limit;
- int base, digit, sign;
-
- base = 10;
- limit = INT64_MAX / base;
- last_digit_limit = INT64_MAX % base;
-
- while (*p == ' ' || *p == '\t')
- p++;
- if (*p == '-') {
- sign = -1;
- p++;
- } else
- sign = 1;
+ return tar_atol_base_n(p, char_cnt, 8);
+}
- l = 0;
- digit = *p - '0';
- while (digit >= 0 && digit < base && char_cnt-- > 0) {
- if (l > limit || (l == limit && digit > last_digit_limit)) {
- l = INT64_MAX; /* Truncate on overflow. */
- break;
- }
- l = (l * base) + digit;
- digit = *++p - '0';
- }
- return (sign < 0) ? -l : l;
+static int64_t
+tar_atol10(const char *p, size_t char_cnt)
+{
+ return tar_atol_base_n(p, char_cnt, 10);
}
/*
@@ -2479,7 +2467,7 @@ tar_atol10(const char *p, unsigned char_cnt)
* ignored.
*/
static int64_t
-tar_atol256(const char *_p, unsigned char_cnt)
+tar_atol256(const char *_p, size_t char_cnt)
{
int64_t l, upper_limit, lower_limit;
const unsigned char *p = (const unsigned char *)_p;
diff --git a/libarchive/archive_read_support_format_xar.c b/libarchive/archive_read_support_format_xar.c
index 733011c262fe..780e749d7096 100644
--- a/libarchive/archive_read_support_format_xar.c
+++ b/libarchive/archive_read_support_format_xar.c
@@ -467,6 +467,7 @@ archive_read_support_format_xar(struct archive *_a)
xar_read_header,
xar_read_data,
xar_read_data_skip,
+ NULL,
xar_cleanup);
if (r != ARCHIVE_OK)
free(xar);
diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c
index 2055313a46b7..450a6f7da519 100644
--- a/libarchive/archive_read_support_format_zip.c
+++ b/libarchive/archive_read_support_format_zip.c
@@ -57,6 +57,7 @@ struct zip_entry {
int64_t gid;
int64_t uid;
struct archive_entry *entry;
+ struct archive_string rsrcname;
time_t mtime;
time_t atime;
time_t ctime;
@@ -69,6 +70,7 @@ struct zip_entry {
struct zip {
/* Structural information about the archive. */
+ int64_t end_of_central_directory_offset;
int64_t central_directory_offset;
size_t central_directory_size;
size_t central_directory_entries;
@@ -80,6 +82,7 @@ struct zip {
struct zip_entry *zip_entries;
struct zip_entry *entry;
struct archive_rb_tree tree;
+ struct archive_rb_tree tree_rsrc;
size_t unconsumed;
@@ -120,29 +123,33 @@ struct zip {
#define ZIP_STRONG_ENCRYPTED (1<<6)
#define ZIP_UTF8_NAME (1<<11)
-static int archive_read_format_zip_streamable_bid(struct archive_read *, int);
-static int archive_read_format_zip_seekable_bid(struct archive_read *, int);
+static int archive_read_format_zip_streamable_bid(struct archive_read *,
+ int);
+static int archive_read_format_zip_seekable_bid(struct archive_read *,
+ int);
static int archive_read_format_zip_options(struct archive_read *,
const char *, const char *);
static int archive_read_format_zip_cleanup(struct archive_read *);
static int archive_read_format_zip_read_data(struct archive_read *,
const void **, size_t *, int64_t *);
static int archive_read_format_zip_read_data_skip(struct archive_read *a);
-static int archive_read_format_zip_seekable_read_header(struct archive_read *,
- struct archive_entry *);
-static int archive_read_format_zip_streamable_read_header(struct archive_read *,
- struct archive_entry *);
+static int archive_read_format_zip_seekable_read_header(
+ struct archive_read *, struct archive_entry *);
+static int archive_read_format_zip_streamable_read_header(
+ struct archive_read *, struct archive_entry *);
+static ssize_t zip_get_local_file_header_size(struct archive_read *, size_t);
#ifdef HAVE_ZLIB_H
+static int zip_deflate_init(struct archive_read *, struct zip *);
static int zip_read_data_deflate(struct archive_read *a, const void **buff,
size_t *size, int64_t *offset);
#endif
static int zip_read_data_none(struct archive_read *a, const void **buff,
size_t *size, int64_t *offset);
static int zip_read_local_file_header(struct archive_read *a,
- struct archive_entry *entry, struct zip *);
+ struct archive_entry *entry, struct zip *);
static time_t zip_time(const char *);
static const char *compression_name(int compression);
-static void process_extra(const char *, size_t, struct zip_entry *);
+static void process_extra(const char *, size_t, struct zip_entry *);
int archive_read_support_format_zip_streamable(struct archive *);
int archive_read_support_format_zip_seekable(struct archive *);
@@ -173,6 +180,7 @@ archive_read_support_format_zip_streamable(struct archive *_a)
archive_read_format_zip_streamable_read_header,
archive_read_format_zip_read_data,
archive_read_format_zip_read_data_skip,
+ NULL,
archive_read_format_zip_cleanup);
if (r != ARCHIVE_OK)
@@ -206,6 +214,7 @@ archive_read_support_format_zip_seekable(struct archive *_a)
archive_read_format_zip_seekable_read_header,
archive_read_format_zip_read_data,
archive_read_format_zip_read_data_skip,
+ NULL,
archive_read_format_zip_cleanup);
if (r != ARCHIVE_OK)
@@ -255,8 +264,48 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
/* First four bytes are signature for end of central directory
record. Four zero bytes ensure this isn't a multi-volume
Zip file (which we don't yet support). */
- if (memcmp(p, "PK\005\006\000\000\000\000", 8) != 0)
- return 0;
+ if (memcmp(p, "PK\005\006\000\000\000\000", 8) != 0) {
+ int64_t i, tail;
+ int found;
+
+ /*
+ * If there is a comment in end of central directory
+ * record, 22 bytes are too short. we have to read more
+ * to properly detect the record. Hopefully, a length
+ * of the comment is not longer than 16362 bytes(16K-22).
+ */
+ if (filesize + 22 > 1024 * 16) {
+ tail = 1024 * 16;
+ filesize = __archive_read_seek(a, tail * -1, SEEK_END);
+ } else {
+ tail = filesize + 22;
+ filesize = __archive_read_seek(a, 0, SEEK_SET);
+ }
+ if (filesize < 0)
+ return 0;
+ if ((p = __archive_read_ahead(a, (size_t)tail, NULL)) == NULL)
+ return 0;
+ for (found = 0, i = 0;!found && i < tail - 22;) {
+ switch (p[i]) {
+ case 'P':
+ if (memcmp(p+i,
+ "PK\005\006\000\000\000\000", 8) == 0) {
+ p += i;
+ filesize += tail -
+ (22 + archive_le16dec(p+20));
+ found = 1;
+ } else
+ i += 8;
+ break;
+ case 'K': i += 7; break;
+ case 005: i += 6; break;
+ case 006: i += 5; break;
+ default: i += 1; break;
+ }
+ }
+ if (!found)
+ return 0;
+ }
/* Since we've already done the hard work of finding the
end of central directory record, let's save the important
@@ -264,12 +313,14 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
zip->central_directory_entries = archive_le16dec(p + 10);
zip->central_directory_size = archive_le32dec(p + 12);
zip->central_directory_offset = archive_le32dec(p + 16);
+ zip->end_of_central_directory_offset = filesize;
/* Just one volume, so central dir must all be on this volume. */
if (zip->central_directory_entries != archive_le16dec(p + 8))
return 0;
/* Central directory can't extend beyond end of this file. */
- if (zip->central_directory_offset + (int64_t)zip->central_directory_size > filesize)
+ if (zip->central_directory_offset +
+ (int64_t)zip->central_directory_size > filesize)
return 0;
/* This is just a tiny bit higher than the maximum returned by
@@ -297,16 +348,91 @@ cmp_key(const struct archive_rb_node *n, const void *key)
}
static int
+rsrc_cmp_node(const struct archive_rb_node *n1,
+ const struct archive_rb_node *n2)
+{
+ const struct zip_entry *e1 = (const struct zip_entry *)n1;
+ const struct zip_entry *e2 = (const struct zip_entry *)n2;
+
+ return (strcmp(e2->rsrcname.s, e1->rsrcname.s));
+}
+
+static int
+rsrc_cmp_key(const struct archive_rb_node *n, const void *key)
+{
+ const struct zip_entry *e = (const struct zip_entry *)n;
+ return (strcmp((const char *)key, e->rsrcname.s));
+}
+
+static const char *
+rsrc_basename(const char *name, size_t name_length)
+{
+ const char *s, *r;
+
+ r = s = name;
+ for (;;) {
+ s = memchr(s, '/', name_length - (s - name));
+ if (s == NULL)
+ break;
+ r = ++s;
+ }
+ return (r);
+}
+
+static void
+expose_parent_dirs(struct zip *zip, const char *name, size_t name_length)
+{
+ struct archive_string str;
+ struct zip_entry *dir;
+ char *s;
+
+ archive_string_init(&str);
+ archive_strncpy(&str, name, name_length);
+ for (;;) {
+ s = strrchr(str.s, '/');
+ if (s == NULL)
+ break;
+ *s = '\0';
+ /* Transfer the parent directory from zip->tree_rsrc RB
+ * tree to zip->tree RB tree to expose. */
+ dir = (struct zip_entry *)
+ __archive_rb_tree_find_node(&zip->tree_rsrc, str.s);
+ if (dir == NULL)
+ break;
+ __archive_rb_tree_remove_node(&zip->tree_rsrc, &dir->node);
+ archive_string_free(&dir->rsrcname);
+ __archive_rb_tree_insert_node(&zip->tree, &dir->node);
+ }
+ archive_string_free(&str);
+}
+
+static int
slurp_central_directory(struct archive_read *a, struct zip *zip)
{
unsigned i;
+ int64_t correction;
static const struct archive_rb_tree_ops rb_ops = {
&cmp_node, &cmp_key
};
+ static const struct archive_rb_tree_ops rb_rsrc_ops = {
+ &rsrc_cmp_node, &rsrc_cmp_key
+ };
+
+ /*
+ * Consider the archive file we are reading may be SFX.
+ * So we have to calculate a SFX header size to revise
+ * ZIP header offsets.
+ */
+ correction = zip->end_of_central_directory_offset -
+ (zip->central_directory_offset + zip->central_directory_size);
+ /* The central directory offset is relative value, and so
+ * we revise this offset for SFX. */
+ zip->central_directory_offset += correction;
__archive_read_seek(a, zip->central_directory_offset, SEEK_SET);
zip->offset = zip->central_directory_offset;
__archive_rb_tree_init(&zip->tree, &rb_ops);
+ __archive_rb_tree_init(&zip->tree_rsrc, &rb_rsrc_ops);
zip->zip_entries = calloc(zip->central_directory_entries,
sizeof(struct zip_entry));
@@ -314,7 +440,7 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
struct zip_entry *zip_entry = &zip->zip_entries[i];
size_t filename_length, extra_length, comment_length;
uint32_t external_attributes;
- const char *p;
+ const char *name, *p, *r;
if ((p = __archive_read_ahead(a, 46, NULL)) == NULL)
return ARCHIVE_FATAL;
@@ -339,7 +465,8 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
/* disk_start = archive_le16dec(p + 34); */ /* Better be zero. */
/* internal_attributes = archive_le16dec(p + 36); */ /* text bit */
external_attributes = archive_le32dec(p + 38);
- zip_entry->local_header_offset = archive_le32dec(p + 42);
+ zip_entry->local_header_offset =
+ archive_le32dec(p + 42) + correction;
/* If we can't guess the mode, leave it zero here;
when we read the local file header we might get
@@ -348,8 +475,50 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
if (zip_entry->system == 3) {
zip_entry->mode = external_attributes >> 16;
}
- /* Register an entry to RB tree to sort it by file offset. */
- __archive_rb_tree_insert_node(&zip->tree, &zip_entry->node);
+
+ /*
+ * Mac resource fork files are stored under the
+ * "__MACOSX/" directory, so we should check if
+ * it is.
+ */
+ /* Make sure we have the file name. */
+ if ((p = __archive_read_ahead(a, 46 + filename_length, NULL))
+ == NULL)
+ return ARCHIVE_FATAL;
+ name = p + 46;
+ r = rsrc_basename(name, filename_length);
+ if (filename_length >= 9 &&
+ strncmp("__MACOSX/", name, 9) == 0) {
+ /* If this file is not a resource fork nor
+ * a directory. We should treat it as a non
+ * resource fork file to expose it. */
+ if (name[filename_length-1] != '/' &&
+ (r - name < 3 || r[0] != '.' || r[1] != '_')) {
+ __archive_rb_tree_insert_node(&zip->tree,
+ &zip_entry->node);
+ /* Expose its parent directories. */
+ expose_parent_dirs(zip, name, filename_length);
+ } else {
+ /* This file is a resource fork file or
+ * a directory. */
+ archive_strncpy(&(zip_entry->rsrcname), name,
+ filename_length);
+ __archive_rb_tree_insert_node(&zip->tree_rsrc,
+ &zip_entry->node);
+ }
+ } else {
+ /* Generate resource fork name to find its resource
+ * file at zip->tree_rsrc. */
+ archive_strcpy(&(zip_entry->rsrcname), "__MACOSX/");
+ archive_strncat(&(zip_entry->rsrcname), name, r - name);
+ archive_strcat(&(zip_entry->rsrcname), "._");
+ archive_strncat(&(zip_entry->rsrcname),
+ name + (r - name), filename_length - (r - name));
+ /* Register an entry to RB tree to sort it by
+ * file offset. */
+ __archive_rb_tree_insert_node(&zip->tree,
+ &zip_entry->node);
+ }
/* We don't read the filename until we get to the
local file header. Reading it here would speed up
@@ -379,10 +548,149 @@ zip_read_consume(struct archive_read *a, int64_t bytes)
}
static int
+zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry,
+ struct zip_entry *rsrc)
+{
+ struct zip *zip = (struct zip *)a->format->data;
+ unsigned char *metadata, *mp;
+ int64_t offset = zip->offset;
+ size_t remaining_bytes, metadata_bytes;
+ ssize_t hsize;
+ int ret = ARCHIVE_OK, eof;
+
+ switch(rsrc->compression) {
+ case 0: /* No compression. */
+#ifdef HAVE_ZLIB_H
+ case 8: /* Deflate compression. */
+#endif
+ break;
+ default: /* Unsupported compression. */
+ /* Return a warning. */
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Unsupported ZIP compression method (%s)",
+ compression_name(rsrc->compression));
+ /* We can't decompress this entry, but we will
+ * be able to skip() it and try the next entry. */
+ return (ARCHIVE_WARN);
+ }
+
+ if (rsrc->uncompressed_size > (128 * 1024)) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Mac metadata is too large: %jd > 128K bytes",
+ (intmax_t)rsrc->uncompressed_size);
+ return (ARCHIVE_WARN);
+ }
+
+ metadata = malloc((size_t)rsrc->uncompressed_size);
+ if (metadata == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for Mac metadata");
+ return (ARCHIVE_FATAL);
+ }
+
+ if (zip->offset < rsrc->local_header_offset)
+ zip_read_consume(a, rsrc->local_header_offset - zip->offset);
+ else if (zip->offset != rsrc->local_header_offset) {
+ __archive_read_seek(a, rsrc->local_header_offset, SEEK_SET);
+ zip->offset = zip->entry->local_header_offset;
+ }
+
+ hsize = zip_get_local_file_header_size(a, 0);
+ zip_read_consume(a, hsize);
+
+ remaining_bytes = (size_t)rsrc->compressed_size;
+ metadata_bytes = (size_t)rsrc->uncompressed_size;
+ mp = metadata;
+ eof = 0;
+ while (!eof && remaining_bytes) {
+ const unsigned char *p;
+ ssize_t bytes_avail;
+ size_t bytes_used;
+
+ p = __archive_read_ahead(a, 1, &bytes_avail);
+ if (p == NULL) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Truncated ZIP file header");
+ ret = ARCHIVE_WARN;
+ goto exit_mac_metadata;
+ }
+ if ((size_t)bytes_avail > remaining_bytes)
+ bytes_avail = remaining_bytes;
+ switch(rsrc->compression) {
+ case 0: /* No compression. */
+ memcpy(mp, p, bytes_avail);
+ bytes_used = (size_t)bytes_avail;
+ metadata_bytes -= bytes_used;
+ mp += bytes_used;
+ if (metadata_bytes == 0)
+ eof = 1;
+ break;
+#ifdef HAVE_ZLIB_H
+ case 8: /* Deflate compression. */
+ {
+ int r;
+
+ ret = zip_deflate_init(a, zip);
+ if (ret != ARCHIVE_OK)
+ goto exit_mac_metadata;
+ zip->stream.next_in =
+ (Bytef *)(uintptr_t)(const void *)p;
+ zip->stream.avail_in = (uInt)bytes_avail;
+ zip->stream.total_in = 0;
+ zip->stream.next_out = mp;
+ zip->stream.avail_out = (uInt)metadata_bytes;
+ zip->stream.total_out = 0;
+
+ r = inflate(&zip->stream, 0);
+ switch (r) {
+ case Z_OK:
+ break;
+ case Z_STREAM_END:
+ eof = 1;
+ break;
+ case Z_MEM_ERROR:
+ archive_set_error(&a->archive, ENOMEM,
+ "Out of memory for ZIP decompression");
+ ret = ARCHIVE_FATAL;
+ goto exit_mac_metadata;
+ default:
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_MISC,
+ "ZIP decompression failed (%d)", r);
+ ret = ARCHIVE_FATAL;
+ goto exit_mac_metadata;
+ }
+ bytes_used = zip->stream.total_in;
+ metadata_bytes -= zip->stream.total_out;
+ mp += zip->stream.total_out;
+ break;
+ }
+#endif
+ default:
+ bytes_used = 0;
+ break;
+ }
+ zip_read_consume(a, bytes_used);
+ remaining_bytes -= bytes_used;
+ }
+ archive_entry_copy_mac_metadata(entry, metadata,
+ (size_t)rsrc->uncompressed_size - metadata_bytes);
+
+ __archive_read_seek(a, offset, SEEK_SET);
+ zip->offset = offset;
+exit_mac_metadata:
+ zip->decompress_init = 0;
+ free(metadata);
+ return (ret);
+}
+
+static int
archive_read_format_zip_seekable_read_header(struct archive_read *a,
struct archive_entry *entry)
{
struct zip *zip = (struct zip *)a->format->data;
+ struct zip_entry *rsrc;
int r, ret = ARCHIVE_OK;
a->archive.archive_format = ARCHIVE_FORMAT_ZIP;
@@ -408,7 +716,19 @@ archive_read_format_zip_seekable_read_header(struct archive_read *a,
return ARCHIVE_EOF;
--zip->entries_remaining;
- if (zip->offset != zip->entry->local_header_offset) {
+ if (zip->entry->rsrcname.s)
+ rsrc = (struct zip_entry *)__archive_rb_tree_find_node(
+ &zip->tree_rsrc, zip->entry->rsrcname.s);
+ else
+ rsrc = NULL;
+
+ /* File entries are sorted by the header offset, we should mostly
+ * use zip_read_consume to advance a read point to avoid redundant
+ * data reading. */
+ if (zip->offset < zip->entry->local_header_offset)
+ zip_read_consume(a,
+ zip->entry->local_header_offset - zip->offset);
+ else if (zip->offset != zip->entry->local_header_offset) {
__archive_read_seek(a, zip->entry->local_header_offset,
SEEK_SET);
zip->offset = zip->entry->local_header_offset;
@@ -463,6 +783,11 @@ archive_read_format_zip_seekable_read_header(struct archive_read *a,
}
}
}
+ if (rsrc) {
+ int ret2 = zip_read_mac_metadata(a, entry, rsrc);
+ if (ret2 < ret)
+ ret = ret2;
+ }
return (ret);
}
@@ -513,7 +838,8 @@ archive_read_format_zip_options(struct archive_read *a,
} else if (strcmp(key, "hdrcharset") == 0) {
if (val == NULL || val[0] == 0)
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "zip: hdrcharset option needs a character-set name");
+ "zip: hdrcharset option needs a character-set name"
+ );
else {
zip->sconv = archive_string_conversion_from_charset(
&a->archive, val, 0);
@@ -549,7 +875,8 @@ archive_read_format_zip_streamable_read_header(struct archive_read *a,
if (zip->zip_entries == NULL) {
zip->zip_entries = malloc(sizeof(struct zip_entry));
if (zip->zip_entries == NULL) {
- archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ archive_set_error(&a->archive, ENOMEM,
+ "Out of memory");
return ARCHIVE_FATAL;
}
}
@@ -578,7 +905,8 @@ archive_read_format_zip_streamable_read_header(struct archive_read *a,
if (p[2] == '\003' && p[3] == '\004') {
/* Regular file entry. */
zip_read_consume(a, skipped);
- return zip_read_local_file_header(a, entry, zip);
+ return zip_read_local_file_header(a,
+ entry, zip);
}
if (p[2] == '\005' && p[3] == '\006')
@@ -592,6 +920,29 @@ archive_read_format_zip_streamable_read_header(struct archive_read *a,
}
}
+static ssize_t
+zip_get_local_file_header_size(struct archive_read *a, size_t extra)
+{
+ const char *p;
+ ssize_t filename_length, extra_length;
+
+ if ((p = __archive_read_ahead(a, extra + 30, NULL)) == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Truncated ZIP file header");
+ return (ARCHIVE_WARN);
+ }
+ p += extra;
+
+ if (memcmp(p, "PK\003\004", 4) != 0) {
+ archive_set_error(&a->archive, -1, "Damaged Zip archive");
+ return ARCHIVE_WARN;
+ }
+ filename_length = archive_le16dec(p + 26);
+ extra_length = archive_le16dec(p + 28);
+
+ return (30 + filename_length + extra_length);
+}
+
/*
* Assumes file pointer is at beginning of local file header.
*/
@@ -648,8 +999,8 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
zip_read_consume(a, 30);
if (zip->have_central_directory) {
- /* If we read the central dir entry, we must have size information
- as well, so ignore the length-at-end flag. */
+ /* If we read the central dir entry, we must have size
+ * information as well, so ignore the length-at-end flag. */
zip_entry->flags &= ~ZIP_LENGTH_AT_END;
/* If we have values from both the local file header
and the central directory, warn about mismatches
@@ -657,19 +1008,22 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
writers always put zero in the local header; don't
bother warning about that. */
if (local_crc32 != 0 && local_crc32 != zip_entry->crc32) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
"Inconsistent CRC32 values");
ret = ARCHIVE_WARN;
}
if (compressed_size != 0
&& compressed_size != zip_entry->compressed_size) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
"Inconsistent compressed size");
ret = ARCHIVE_WARN;
}
if (uncompressed_size != 0
&& uncompressed_size != zip_entry->uncompressed_size) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
"Inconsistent uncompressed size");
ret = ARCHIVE_WARN;
}
@@ -868,13 +1222,16 @@ archive_read_format_zip_read_data(struct archive_read *a,
return (r);
/* Update checksum */
if (*size)
- zip->entry_crc32 = crc32(zip->entry_crc32, *buff, *size);
+ zip->entry_crc32 = crc32(zip->entry_crc32, *buff,
+ (unsigned)*size);
/* If we hit the end, swallow any end-of-data marker. */
if (zip->end_of_entry) {
/* Check file size, CRC against these values. */
- if (zip->entry->compressed_size != zip->entry_compressed_bytes_read) {
+ if (zip->entry->compressed_size !=
+ zip->entry_compressed_bytes_read) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "ZIP compressed data is wrong size (read %jd, expected %jd)",
+ "ZIP compressed data is wrong size "
+ "(read %jd, expected %jd)",
(intmax_t)zip->entry_compressed_bytes_read,
(intmax_t)zip->entry->compressed_size);
return (ARCHIVE_WARN);
@@ -884,7 +1241,8 @@ archive_read_format_zip_read_data(struct archive_read *a,
if ((zip->entry->uncompressed_size & UINT32_MAX)
!= (zip->entry_uncompressed_bytes_read & UINT32_MAX)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "ZIP uncompressed data is wrong size (read %jd, expected %jd)",
+ "ZIP uncompressed data is wrong size "
+ "(read %jd, expected %jd)",
(intmax_t)zip->entry_uncompressed_bytes_read,
(intmax_t)zip->entry->uncompressed_size);
return (ARCHIVE_WARN);
@@ -947,7 +1305,8 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
that are longer than this, so a failure to get at
least 16 bytes really does indicate a truncated
file. */
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file data");
return (ARCHIVE_FATAL);
}
@@ -956,8 +1315,10 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
if (p[0] == 'P' && p[1] == 'K'
&& p[2] == '\007' && p[3] == '\010'
&& archive_le32dec(p + 4) == zip->entry_crc32
- && archive_le32dec(p + 8) == zip->entry_compressed_bytes_read
- && archive_le32dec(p + 12) == zip->entry_uncompressed_bytes_read) {
+ && archive_le32dec(p + 8) ==
+ zip->entry_compressed_bytes_read
+ && archive_le32dec(p + 12) ==
+ zip->entry_uncompressed_bytes_read) {
zip->entry->crc32 = archive_le32dec(p + 4);
zip->entry->compressed_size = archive_le32dec(p + 8);
zip->entry->uncompressed_size = archive_le32dec(p + 12);
@@ -968,9 +1329,10 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
/* If not at EOF, ensure we consume at least one byte. */
++p;
- /* Scan forward until we see where a PK\007\010 signature might be. */
- /* Return bytes up until that point. On the next call, the code
- above will verify the data descriptor. */
+ /* Scan forward until we see where a PK\007\010 signature
+ * might be. */
+ /* Return bytes up until that point. On the next call,
+ * the code above will verify the data descriptor. */
while (p < buff + bytes_avail - 4) {
if (p[3] == 'P') { p += 3; }
else if (p[3] == 'K') { p += 2; }
@@ -989,7 +1351,8 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
/* Grab a bunch of bytes. */
buff = __archive_read_ahead(a, 1, &bytes_avail);
if (bytes_avail <= 0) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file data");
return (ARCHIVE_FATAL);
}
@@ -1007,6 +1370,31 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
#ifdef HAVE_ZLIB_H
static int
+zip_deflate_init(struct archive_read *a, struct zip *zip)
+{
+ int r;
+
+ /* If we haven't yet read any data, initialize the decompressor. */
+ if (!zip->decompress_init) {
+ if (zip->stream_valid)
+ r = inflateReset(&zip->stream);
+ else
+ r = inflateInit2(&zip->stream,
+ -15 /* Don't check for zlib header */);
+ if (r != Z_OK) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Can't initialize ZIP decompression.");
+ return (ARCHIVE_FATAL);
+ }
+ /* Stream structure has been set up. */
+ zip->stream_valid = 1;
+ /* We've initialized decompression for this stream. */
+ zip->decompress_init = 1;
+ }
+ return (ARCHIVE_OK);
+}
+
+static int
zip_read_data_deflate(struct archive_read *a, const void **buff,
size_t *size, int64_t *offset)
{
@@ -1031,23 +1419,9 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
}
}
- /* If we haven't yet read any data, initialize the decompressor. */
- if (!zip->decompress_init) {
- if (zip->stream_valid)
- r = inflateReset(&zip->stream);
- else
- r = inflateInit2(&zip->stream,
- -15 /* Don't check for zlib header */);
- if (r != Z_OK) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Can't initialize ZIP decompression.");
- return (ARCHIVE_FATAL);
- }
- /* Stream structure has been set up. */
- zip->stream_valid = 1;
- /* We've initialized decompression for this stream. */
- zip->decompress_init = 1;
- }
+ r = zip_deflate_init(a, zip);
+ if (r != ARCHIVE_OK)
+ return (r);
/*
* Note: '1' here is a performance optimization.
@@ -1073,10 +1447,10 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
* cast to remove 'const'.
*/
zip->stream.next_in = (Bytef *)(uintptr_t)(const void *)compressed_buff;
- zip->stream.avail_in = bytes_avail;
+ zip->stream.avail_in = (uInt)bytes_avail;
zip->stream.total_in = 0;
zip->stream.next_out = zip->uncompressed_buffer;
- zip->stream.avail_out = zip->uncompressed_buffer_size;
+ zip->stream.avail_out = (uInt)zip->uncompressed_buffer_size;
zip->stream.total_out = 0;
r = inflate(&zip->stream, 0);
@@ -1116,7 +1490,8 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
return (ARCHIVE_FATAL);
}
/* Consume the optional PK\007\010 marker. */
- if (p[0] == 'P' && p[1] == 'K' && p[2] == '\007' && p[3] == '\010') {
+ if (p[0] == 'P' && p[1] == 'K' &&
+ p[2] == '\007' && p[3] == '\010') {
zip->entry->crc32 = archive_le32dec(p + 4);
zip->entry->compressed_size = archive_le32dec(p + 8);
zip->entry->uncompressed_size = archive_le32dec(p + 12);
@@ -1176,7 +1551,8 @@ archive_read_format_zip_read_data_skip(struct archive_read *a)
ssize_t bytes_avail;
buff = __archive_read_ahead(a, 16, &bytes_avail);
if (bytes_avail < 16) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file data");
return (ARCHIVE_FATAL);
}
@@ -1206,6 +1582,11 @@ archive_read_format_zip_cleanup(struct archive_read *a)
if (zip->stream_valid)
inflateEnd(&zip->stream);
#endif
+ if (zip->zip_entries && zip->central_directory_entries) {
+ unsigned i;
+ for (i = 0; i < zip->central_directory_entries; i++)
+ archive_string_free(&(zip->zip_entries[i].rsrcname));
+ }
free(zip->zip_entries);
free(zip->uncompressed_buffer);
archive_string_free(&(zip->extra));
@@ -1288,11 +1669,14 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
/* Info-ZIP Unix Extra Field (old version) "UX". */
if (datasize >= 8) {
zip_entry->atime = archive_le32dec(p + offset);
- zip_entry->mtime = archive_le32dec(p + offset + 4);
+ zip_entry->mtime =
+ archive_le32dec(p + offset + 4);
}
if (datasize >= 12) {
- zip_entry->uid = archive_le16dec(p + offset + 8);
- zip_entry->gid = archive_le16dec(p + offset + 10);
+ zip_entry->uid =
+ archive_le16dec(p + offset + 8);
+ zip_entry->gid =
+ archive_le16dec(p + offset + 10);
}
break;
}
@@ -1306,7 +1690,8 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
if (datasize >= 2)
zip_entry->uid = archive_le16dec(p + offset);
if (datasize >= 4)
- zip_entry->gid = archive_le16dec(p + offset + 2);
+ zip_entry->gid =
+ archive_le16dec(p + offset + 2);
break;
case 0x7875:
{
@@ -1318,22 +1703,26 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
/* get a uid size. */
uidsize = p[offset+1];
if (uidsize == 2)
- zip_entry->uid = archive_le16dec(
- p + offset + 2);
+ zip_entry->uid =
+ archive_le16dec(
+ p + offset + 2);
else if (uidsize == 4 && datasize >= 6)
- zip_entry->uid = archive_le32dec(
- p + offset + 2);
+ zip_entry->uid =
+ archive_le32dec(
+ p + offset + 2);
}
if (datasize >= (2 + uidsize + 3)) {
/* get a gid size. */
gidsize = p[offset+2+uidsize];
if (gidsize == 2)
- zip_entry->gid = archive_le16dec(
- p+offset+2+uidsize+1);
+ zip_entry->gid =
+ archive_le16dec(
+ p+offset+2+uidsize+1);
else if (gidsize == 4 &&
datasize >= (2 + uidsize + 5))
- zip_entry->gid = archive_le32dec(
- p+offset+2+uidsize+1);
+ zip_entry->gid =
+ archive_le32dec(
+ p+offset+2+uidsize+1);
}
}
break;
diff --git a/libarchive/archive_string.c b/libarchive/archive_string.c
index 2728a376c669..87f9288f1966 100644
--- a/libarchive/archive_string.c
+++ b/libarchive/archive_string.c
@@ -486,13 +486,13 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
* UTF-16BE/LE NFD ===> UTF-16 NFC
* UTF-16BE/LE NFC ===> UTF-16 NFD
*/
- count = utf16nbytes(s, length);
+ count = (int)utf16nbytes(s, length);
} else {
/*
* UTF-8 NFD ===> UTF-16 NFC
* UTF-8 NFC ===> UTF-16 NFD
*/
- count = mbsnbytes(s, length);
+ count = (int)mbsnbytes(s, length);
}
u16.s = (char *)dest->s;
u16.length = dest->length << 1;;
@@ -507,7 +507,7 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
sc->flag = saved_flag;/* restore the saved flag. */
return (ret);
} else if (sc != NULL && (sc->flag & SCONV_FROM_UTF16)) {
- count = utf16nbytes(s, length);
+ count = (int)utf16nbytes(s, length);
count >>= 1; /* to be WCS length */
/* Allocate memory for WCS. */
if (NULL == archive_wstring_ensure(dest,
@@ -550,8 +550,8 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
return (-1);
/* Convert MBS to WCS. */
count = MultiByteToWideChar(from_cp,
- mbflag, s, length, dest->s + dest->length,
- (dest->buffer_length >> 1) -1);
+ mbflag, s, (int)length, dest->s + dest->length,
+ (int)(dest->buffer_length >> 1) -1);
if (count == 0 &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
/* Expand the WCS buffer. */
@@ -727,7 +727,7 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
else
dp = &defchar_used;
count = WideCharToMultiByte(to_cp, 0, ws, wslen,
- as->s + as->length, as->buffer_length-1, NULL, dp);
+ as->s + as->length, (int)as->buffer_length-1, NULL, dp);
if (count == 0 &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
/* Expand the MBS buffer and retry. */
@@ -1120,8 +1120,8 @@ create_sconv_object(const char *fc, const char *tc,
}
sc->to_charset = strdup(tc);
if (sc->to_charset == NULL) {
- free(sc);
free(sc->from_charset);
+ free(sc);
return (NULL);
}
archive_string_init(&sc->utftmp);
@@ -1997,7 +1997,7 @@ static int
iconv_strncat_in_locale(struct archive_string *as, const void *_p,
size_t length, struct archive_string_conv *sc)
{
- ICONV_CONST char *inp;
+ ICONV_CONST char *itp;
size_t remaining;
iconv_t cd;
char *outp;
@@ -2018,12 +2018,12 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
return (-1);
cd = sc->cd;
- inp = (char *)(uintptr_t)_p;
+ itp = (char *)(uintptr_t)_p;
remaining = length;
outp = as->s + as->length;
avail = as->buffer_length - as->length - to_size;
while (remaining >= (size_t)from_size) {
- size_t result = iconv(cd, &inp, &remaining, &outp, &avail);
+ size_t result = iconv(cd, &itp, &remaining, &outp, &avail);
if (result != (size_t)-1)
break; /* Conversion completed. */
@@ -2065,7 +2065,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
*outp++ = '?';
avail--;
}
- inp += from_size;
+ itp += from_size;
remaining -= from_size;
return_value = -1; /* failure */
} else {
@@ -2145,7 +2145,7 @@ invalid_mbs(const void *_p, size_t n, struct archive_string_conv *sc)
if (codepage != CP_UTF8)
mbflag |= MB_PRECOMPOSED;
- if (MultiByteToWideChar(codepage, mbflag, p, n, NULL, 0) == 0)
+ if (MultiByteToWideChar(codepage, mbflag, p, (int)n, NULL, 0) == 0)
return (-1); /* Invalid */
return (0); /* Okay */
}
@@ -2202,8 +2202,8 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p,
size_t length, struct archive_string_conv *sc)
{
size_t remaining;
- char *outp;
- const uint8_t *inp;
+ char *otp;
+ const uint8_t *itp;
size_t avail;
int return_value = 0; /* success */
@@ -2227,41 +2227,41 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p,
return (-1);
remaining = length;
- inp = (const uint8_t *)_p;
- outp = as->s + as->length;
+ itp = (const uint8_t *)_p;
+ otp = as->s + as->length;
avail = as->buffer_length - as->length -1;
- while (*inp && remaining > 0) {
- if (*inp > 127 && (sc->flag & SCONV_TO_UTF8)) {
+ while (*itp && remaining > 0) {
+ if (*itp > 127 && (sc->flag & SCONV_TO_UTF8)) {
if (avail < UTF8_R_CHAR_SIZE) {
- as->length = outp - as->s;
+ as->length = otp - as->s;
if (NULL == archive_string_ensure(as,
as->buffer_length + remaining +
UTF8_R_CHAR_SIZE))
return (-1);
- outp = as->s + as->length;
+ otp = as->s + as->length;
avail = as->buffer_length - as->length -1;
}
/*
* When coping a string in UTF-8, unknown character
* should be U+FFFD (replacement character).
*/
- UTF8_SET_R_CHAR(outp);
- outp += UTF8_R_CHAR_SIZE;
+ UTF8_SET_R_CHAR(otp);
+ otp += UTF8_R_CHAR_SIZE;
avail -= UTF8_R_CHAR_SIZE;
- inp++;
+ itp++;
remaining--;
return_value = -1;
- } else if (*inp > 127) {
- *outp++ = '?';
- inp++;
+ } else if (*itp > 127) {
+ *otp++ = '?';
+ itp++;
remaining--;
return_value = -1;
} else {
- *outp++ = (char)*inp++;
+ *otp++ = (char)*itp++;
remaining--;
}
}
- as->length = outp - as->s;
+ as->length = otp - as->s;
as->s[as->length] = '\0';
return (return_value);
}
@@ -2322,7 +2322,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
/* Invalide sequence or there are not plenty bytes. */
if ((int)n < cnt) {
- cnt = n;
+ cnt = (int)n;
for (i = 1; i < cnt; i++) {
if ((s[i] & 0xc0) != 0x80) {
cnt = i;
@@ -2391,7 +2391,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
else
cnt = 1;
if ((int)n < cnt)
- cnt = n;
+ cnt = (int)n;
for (i = 1; i < cnt; i++) {
if ((s[i] & 0xc0) != 0x80) {
cnt = i;
@@ -2447,11 +2447,12 @@ combine_surrogate_pair(uint32_t uc, uint32_t uc2)
static int
cesu8_to_unicode(uint32_t *pwc, const char *s, size_t n)
{
- uint32_t wc, wc2;
+ uint32_t wc = 0;
int cnt;
cnt = _utf8_to_unicode(&wc, s, n);
if (cnt == 3 && IS_HIGH_SURROGATE_LA(wc)) {
+ uint32_t wc2 = 0;
if (n - 3 < 3) {
/* Invalid byte sequence. */
goto invalid_sequence;
@@ -3396,7 +3397,6 @@ check_first_code:
break;
REPLACE_UC_WITH(uc2);
n = n2;
- ucptr = s;
goto check_first_code;
}
as->length = p - as->s;
@@ -3478,9 +3478,9 @@ strncat_from_utf8_libarchive2(struct archive_string *as,
* Translates the wide-character into the current locale MBS.
*/
#if HAVE_WCRTOMB
- n = wcrtomb(p, wc, &shift_state);
+ n = (int)wcrtomb(p, wc, &shift_state);
#else
- n = wctomb(p, wc);
+ n = (int)wctomb(p, wc);
#endif
if (n == -1)
return (-1);
@@ -3579,13 +3579,13 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
do {
defchar = 0;
ll = WideCharToMultiByte(sc->to_cp, 0,
- (LPCWSTR)u16, bytes>>1, mbs, mbs_size,
+ (LPCWSTR)u16, (int)bytes>>1, mbs, (int)mbs_size,
NULL, &defchar);
if (ll == 0 &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
/* Need more buffer for MBS. */
ll = WideCharToMultiByte(sc->to_cp, 0,
- (LPCWSTR)u16, bytes, NULL, 0, NULL, NULL);
+ (LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL);
if (archive_string_ensure(as, ll +1) == NULL)
return (-1);
mbs = as->s + as->length;
@@ -3662,12 +3662,12 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p,
}
do {
count = MultiByteToWideChar(sc->from_cp,
- MB_PRECOMPOSED, s, length, (LPWSTR)u16, (int)avail>>1);
+ MB_PRECOMPOSED, s, (int)length, (LPWSTR)u16, (int)avail>>1);
if (count == 0 &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
/* Need more buffer for UTF-16 string */
count = MultiByteToWideChar(sc->from_cp,
- MB_PRECOMPOSED, s, length, NULL, 0);
+ MB_PRECOMPOSED, s, (int)length, NULL, 0);
if (archive_string_ensure(as16, (count +1) * 2)
== NULL)
return (-1);
diff --git a/libarchive/archive_util.c b/libarchive/archive_util.c
index 103c009d5bc8..34d8081cbce9 100644
--- a/libarchive/archive_util.c
+++ b/libarchive/archive_util.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2009,2010 Michihiro NAKAJIMA
+ * Copyright (c) 2009-2012 Michihiro NAKAJIMA
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
@@ -50,6 +50,10 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:1
#include "archive_private.h"
#include "archive_string.h"
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
/* Generic initialization of 'struct archive' objects. */
int
__archive_clean(struct archive *a)
@@ -239,7 +243,7 @@ __archive_mktemp(const char *tmpdir)
errno = ENOMEM;
goto exit_tmpfile;
}
- GetTempPathW(l, tmp);
+ GetTempPathW((DWORD)l, tmp);
archive_wstrcpy(&temp_name, tmp);
free(tmp);
} else {
@@ -293,7 +297,8 @@ __archive_mktemp(const char *tmpdir)
/* Generate a random file name through CryptGenRandom(). */
p = xp;
- if (!CryptGenRandom(hProv, (ep - p)*sizeof(wchar_t), (BYTE*)p)) {
+ if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t),
+ (BYTE*)p)) {
la_dosmaperr(GetLastError());
goto exit_tmpfile;
}
@@ -385,6 +390,7 @@ __archive_mktemp(const char *tmpdir)
fd = mkstemp(temp_name.s);
if (fd < 0)
goto exit_tmpfile;
+ __archive_ensure_cloexec_flag(fd);
unlink(temp_name.s);
exit_tmpfile:
archive_string_free(&temp_name);
@@ -438,7 +444,8 @@ __archive_mktemp(const char *tmpdir)
archive_strcat(&temp_name, "XXXXXXXXXX");
ep = temp_name.s + archive_strlen(&temp_name);
- fd = open("/dev/random", O_RDONLY);
+ fd = open("/dev/random", O_RDONLY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(fd);
if (fd < 0)
seed = time(NULL);
else {
@@ -452,10 +459,12 @@ __archive_mktemp(const char *tmpdir)
p = tp;
while (p < ep)
*p++ = num[((unsigned)rand_r(&seed)) % sizeof(num)];
- fd = open(temp_name.s, O_CREAT | O_EXCL | O_RDWR, 0600);
+ fd = open(temp_name.s, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC,
+ 0600);
} while (fd < 0 && errno == EEXIST);
if (fd < 0)
goto exit_tmpfile;
+ __archive_ensure_cloexec_flag(fd);
unlink(temp_name.s);
exit_tmpfile:
archive_string_free(&temp_name);
@@ -464,3 +473,29 @@ exit_tmpfile:
#endif /* HAVE_MKSTEMP */
#endif /* !_WIN32 || __CYGWIN__ */
+
+/*
+ * Set FD_CLOEXEC flag to a file descriptor if it is not set.
+ * We have to set the flag if the platform does not provide O_CLOEXEC
+ * or F_DUPFD_CLOEXEC flags.
+ *
+ * Note: This function is absolutely called after creating a new file
+ * descriptor even if the platform seemingly provides O_CLOEXEC or
+ * F_DUPFD_CLOEXEC macros because it is possible that the platform
+ * merely declares those macros, especially Linux 2.6.18 - 2.6.24 do it.
+ */
+void
+__archive_ensure_cloexec_flag(int fd)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ (void)fd; /* UNSED */
+#else
+ int flags;
+
+ if (fd >= 0) {
+ flags = fcntl(fd, F_GETFD);
+ if (flags != -1 && (flags & FD_CLOEXEC) == 0)
+ fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
+ }
+#endif
+}
diff --git a/libarchive/archive_virtual.c b/libarchive/archive_virtual.c
index 83089f27f942..0c4155f21e3b 100644
--- a/libarchive/archive_virtual.c
+++ b/libarchive/archive_virtual.c
@@ -67,6 +67,13 @@ archive_read_close(struct archive *a)
}
int
+archive_write_fail(struct archive *a)
+{
+ a->state = ARCHIVE_STATE_FATAL;
+ return a->state;
+}
+
+int
archive_write_free(struct archive *a)
{
if (a == NULL)
diff --git a/libarchive/archive_windows.c b/libarchive/archive_windows.c
index 12ad07dc2a74..d3bf758bb39e 100644
--- a/libarchive/archive_windows.c
+++ b/libarchive/archive_windows.c
@@ -633,35 +633,22 @@ __la_stat(const char *path, struct stat *st)
* This waitpid is limited implementation.
*/
pid_t
-__la_waitpid(pid_t wpid, int *status, int option)
+__la_waitpid(HANDLE child, int *status, int option)
{
- HANDLE child;
- DWORD cs, ret;
+ DWORD cs;
(void)option;/* UNUSED */
- *status = 0;
- child = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, wpid);
- if (child == NULL) {
- la_dosmaperr(GetLastError());
- return (-1);
- }
- ret = WaitForSingleObject(child, INFINITE);
- if (ret == WAIT_FAILED) {
- CloseHandle(child);
- la_dosmaperr(GetLastError());
- return (-1);
- }
- if (GetExitCodeProcess(child, &cs) == 0) {
- CloseHandle(child);
- la_dosmaperr(GetLastError());
- return (-1);
- }
- if (cs == STILL_ACTIVE)
- *status = 0x100;
- else
- *status = (int)(cs & 0xff);
- CloseHandle(child);
- return (wpid);
+ do {
+ if (GetExitCodeProcess(child, &cs) == 0) {
+ CloseHandle(child);
+ la_dosmaperr(GetLastError());
+ *status = 0;
+ return (-1);
+ }
+ } while (cs == STILL_ACTIVE);
+
+ *status = (int)(cs & 0xff);
+ return (0);
}
ssize_t
diff --git a/libarchive/archive_windows.h b/libarchive/archive_windows.h
index a8e54c593d07..c6f5bc510513 100644
--- a/libarchive/archive_windows.h
+++ b/libarchive/archive_windows.h
@@ -49,6 +49,9 @@
#define LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED
/* Start of configuration for native Win32 */
+#ifndef MINGW_HAS_SECURE_API
+#define MINGW_HAS_SECURE_API 1
+#endif
#include <errno.h>
#define set_errno(val) ((errno)=val)
@@ -90,8 +93,14 @@
#ifndef fileno
#define fileno _fileno
#endif
+#ifdef fstat
+#undef fstat
+#endif
#define fstat __la_fstat
#if !defined(__BORLANDC__)
+#ifdef lseek
+#undef lseek
+#endif
#define lseek _lseeki64
#else
#define lseek __la_lseek
@@ -103,6 +112,9 @@
#if !defined(__BORLANDC__)
#define setmode _setmode
#endif
+#ifdef stat
+#undef stat
+#endif
#define stat(path,stref) __la_stat(path,stref)
#if !defined(__BORLANDC__)
#define strdup _strdup
@@ -252,7 +264,7 @@ extern __int64 __la_lseek(int fd, __int64 offset, int whence);
extern int __la_open(const char *path, int flags, ...);
extern ssize_t __la_read(int fd, void *buf, size_t nbytes);
extern int __la_stat(const char *path, struct stat *st);
-extern pid_t __la_waitpid(pid_t wpid, int *status, int option);
+extern pid_t __la_waitpid(HANDLE child, int *status, int option);
extern ssize_t __la_write(int fd, const void *buf, size_t nbytes);
#define _stat64i32(path, st) __la_stat(path, st)
diff --git a/libarchive/archive_write.c b/libarchive/archive_write.c
index 6fc3907f3631..a3d1a3380c05 100644
--- a/libarchive/archive_write.c
+++ b/libarchive/archive_write.c
@@ -232,6 +232,10 @@ __archive_write_filter(struct archive_write_filter *f,
int r;
if (length == 0)
return(ARCHIVE_OK);
+ if (f->write == NULL)
+ /* If unset, a fatal error has already ocuured, so this filter
+ * didn't open. We cannot write anything. */
+ return(ARCHIVE_FATAL);
r = (f->write)(f, buff, length);
f->bytes_written += length;
return (r);
@@ -437,6 +441,8 @@ archive_write_client_close(struct archive_write_filter *f)
(*a->client_closer)(&a->archive, a->client_data);
free(state->buffer);
free(state);
+ /* Clear the close handler myself not to be called again. */
+ f->close = NULL;
a->client_data = NULL;
return (ret);
}
diff --git a/libarchive/archive_write_add_filter.c b/libarchive/archive_write_add_filter.c
index 915290aaaf99..81dd683aacc7 100644
--- a/libarchive/archive_write_add_filter.c
+++ b/libarchive/archive_write_add_filter.c
@@ -45,9 +45,13 @@ struct { int code; int (*setter)(struct archive *); } codes[] =
{ ARCHIVE_FILTER_GZIP, archive_write_add_filter_gzip },
{ ARCHIVE_FILTER_BZIP2, archive_write_add_filter_bzip2 },
{ ARCHIVE_FILTER_COMPRESS, archive_write_add_filter_compress },
+ { ARCHIVE_FILTER_GRZIP, archive_write_add_filter_grzip },
+ { ARCHIVE_FILTER_LRZIP, archive_write_add_filter_lrzip },
+ { ARCHIVE_FILTER_LZIP, archive_write_add_filter_lzip },
{ ARCHIVE_FILTER_LZMA, archive_write_add_filter_lzma },
+ { ARCHIVE_FILTER_LZOP, archive_write_add_filter_lzip },
+ { ARCHIVE_FILTER_UU, archive_write_add_filter_uuencode },
{ ARCHIVE_FILTER_XZ, archive_write_add_filter_xz },
- { ARCHIVE_FILTER_LZIP, archive_write_add_filter_lzip },
{ -1, NULL }
};
diff --git a/libarchive/archive_write_add_filter_b64encode.c b/libarchive/archive_write_add_filter_b64encode.c
new file mode 100644
index 000000000000..85eb087b0522
--- /dev/null
+++ b/libarchive/archive_write_add_filter_b64encode.c
@@ -0,0 +1,314 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_string.h"
+#include "archive_write_private.h"
+
+#define LBYTES 57
+
+struct private_b64encode {
+ int mode;
+ struct archive_string name;
+ struct archive_string encoded_buff;
+ size_t bs;
+ size_t hold_len;
+ unsigned char hold[LBYTES];
+};
+
+static int archive_filter_b64encode_options(struct archive_write_filter *,
+ const char *, const char *);
+static int archive_filter_b64encode_open(struct archive_write_filter *);
+static int archive_filter_b64encode_write(struct archive_write_filter *,
+ const void *, size_t);
+static int archive_filter_b64encode_close(struct archive_write_filter *);
+static int archive_filter_b64encode_free(struct archive_write_filter *);
+static void b64_encode(struct archive_string *, const unsigned char *, size_t);
+static int64_t atol8(const char *, size_t);
+
+static const char base64[] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '+', '/'
+};
+
+/*
+ * Add a compress filter to this write handle.
+ */
+int
+archive_write_add_filter_b64encode(struct archive *_a)
+{
+ struct archive_write *a = (struct archive_write *)_a;
+ struct archive_write_filter *f = __archive_write_allocate_filter(_a);
+ struct private_b64encode *state;
+
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_write_add_filter_uu");
+
+ state = (struct private_b64encode *)calloc(1, sizeof(*state));
+ if (state == NULL) {
+ archive_set_error(f->archive, ENOMEM,
+ "Can't allocate data for b64encode filter");
+ return (ARCHIVE_FATAL);
+ }
+ archive_strcpy(&state->name, "-");
+ state->mode = 0644;
+
+ f->data = state;
+ f->name = "b64encode";
+ f->code = ARCHIVE_FILTER_UU;
+ f->open = archive_filter_b64encode_open;
+ f->options = archive_filter_b64encode_options;
+ f->write = archive_filter_b64encode_write;
+ f->close = archive_filter_b64encode_close;
+ f->free = archive_filter_b64encode_free;
+
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Set write options.
+ */
+static int
+archive_filter_b64encode_options(struct archive_write_filter *f, const char *key,
+ const char *value)
+{
+ struct private_b64encode *state = (struct private_b64encode *)f->data;
+
+ if (strcmp(key, "mode") == 0) {
+ if (value == NULL) {
+ archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
+ "mode option requires octal digits");
+ return (ARCHIVE_FAILED);
+ }
+ state->mode = (int)atol8(value, strlen(value)) & 0777;
+ return (ARCHIVE_OK);
+ } else if (strcmp(key, "name") == 0) {
+ if (value == NULL) {
+ archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
+ "name option requires a string");
+ return (ARCHIVE_FAILED);
+ }
+ archive_strcpy(&state->name, value);
+ return (ARCHIVE_OK);
+ }
+
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+/*
+ * Setup callback.
+ */
+static int
+archive_filter_b64encode_open(struct archive_write_filter *f)
+{
+ struct private_b64encode *state = (struct private_b64encode *)f->data;
+ size_t bs = 65536, bpb;
+ int ret;
+
+ ret = __archive_write_open_filter(f->next_filter);
+ if (ret != ARCHIVE_OK)
+ return (ret);
+
+ if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
+ /* Buffer size should be a multiple number of the of bytes
+ * per block for performance. */
+ bpb = archive_write_get_bytes_per_block(f->archive);
+ if (bpb > bs)
+ bs = bpb;
+ else if (bpb != 0)
+ bs -= bs % bpb;
+ }
+
+ state->bs = bs;
+ if (archive_string_ensure(&state->encoded_buff, bs + 512) == NULL) {
+ archive_set_error(f->archive, ENOMEM,
+ "Can't allocate data for b64encode buffer");
+ return (ARCHIVE_FATAL);
+ }
+
+ archive_string_sprintf(&state->encoded_buff, "begin-base64 %o %s\n",
+ state->mode, state->name.s);
+
+ f->data = state;
+ return (0);
+}
+
+static void
+b64_encode(struct archive_string *as, const unsigned char *p, size_t len)
+{
+ int c;
+
+ for (; len >= 3; p += 3, len -= 3) {
+ c = p[0] >> 2;
+ archive_strappend_char(as, base64[c]);
+ c = ((p[0] & 0x03) << 4) | ((p[1] & 0xf0) >> 4);
+ archive_strappend_char(as, base64[c]);
+ c = ((p[1] & 0x0f) << 2) | ((p[2] & 0xc0) >> 6);
+ archive_strappend_char(as, base64[c]);
+ c = p[2] & 0x3f;
+ archive_strappend_char(as, base64[c]);
+ }
+ if (len > 0) {
+ c = p[0] >> 2;
+ archive_strappend_char(as, base64[c]);
+ c = (p[0] & 0x03) << 4;
+ if (len == 1) {
+ archive_strappend_char(as, base64[c]);
+ archive_strappend_char(as, '=');
+ archive_strappend_char(as, '=');
+ } else {
+ c |= (p[1] & 0xf0) >> 4;
+ archive_strappend_char(as, base64[c]);
+ c = (p[1] & 0x0f) << 2;
+ archive_strappend_char(as, base64[c]);
+ archive_strappend_char(as, '=');
+ }
+ }
+ archive_strappend_char(as, '\n');
+}
+
+/*
+ * Write data to the encoded stream.
+ */
+static int
+archive_filter_b64encode_write(struct archive_write_filter *f, const void *buff,
+ size_t length)
+{
+ struct private_b64encode *state = (struct private_b64encode *)f->data;
+ const unsigned char *p = buff;
+ int ret = ARCHIVE_OK;
+
+ if (length == 0)
+ return (ret);
+
+ if (state->hold_len) {
+ while (state->hold_len < LBYTES && length > 0) {
+ state->hold[state->hold_len++] = *p++;
+ length--;
+ }
+ if (state->hold_len < LBYTES)
+ return (ret);
+ b64_encode(&state->encoded_buff, state->hold, LBYTES);
+ state->hold_len = 0;
+ }
+
+ for (; length >= LBYTES; length -= LBYTES, p += LBYTES)
+ b64_encode(&state->encoded_buff, p, LBYTES);
+
+ /* Save remaining bytes. */
+ if (length > 0) {
+ memcpy(state->hold, p, length);
+ state->hold_len = length;
+ }
+ while (archive_strlen(&state->encoded_buff) >= state->bs) {
+ ret = __archive_write_filter(f->next_filter,
+ state->encoded_buff.s, state->bs);
+ memmove(state->encoded_buff.s,
+ state->encoded_buff.s + state->bs,
+ state->encoded_buff.length - state->bs);
+ state->encoded_buff.length -= state->bs;
+ }
+
+ return (ret);
+}
+
+
+/*
+ * Finish the compression...
+ */
+static int
+archive_filter_b64encode_close(struct archive_write_filter *f)
+{
+ struct private_b64encode *state = (struct private_b64encode *)f->data;
+ int ret, ret2;
+
+ /* Flush remaining bytes. */
+ if (state->hold_len != 0)
+ b64_encode(&state->encoded_buff, state->hold, state->hold_len);
+ archive_string_sprintf(&state->encoded_buff, "====\n");
+ /* Write the last block */
+ archive_write_set_bytes_in_last_block(f->archive, 1);
+ ret = __archive_write_filter(f->next_filter,
+ state->encoded_buff.s, archive_strlen(&state->encoded_buff));
+ ret2 = __archive_write_close_filter(f->next_filter);
+ if (ret > ret2)
+ ret = ret2;
+ return (ret);
+}
+
+static int
+archive_filter_b64encode_free(struct archive_write_filter *f)
+{
+ struct private_b64encode *state = (struct private_b64encode *)f->data;
+
+ archive_string_free(&state->name);
+ archive_string_free(&state->encoded_buff);
+ free(state);
+ return (ARCHIVE_OK);
+}
+
+static int64_t
+atol8(const char *p, size_t char_cnt)
+{
+ int64_t l;
+ int digit;
+
+ l = 0;
+ while (char_cnt-- > 0) {
+ if (*p >= '0' && *p <= '7')
+ digit = *p - '0';
+ else
+ break;
+ p++;
+ l <<= 3;
+ l |= digit;
+ }
+ return (l);
+}
+
diff --git a/libarchive/archive_write_add_filter_by_name.c b/libarchive/archive_write_add_filter_by_name.c
new file mode 100644
index 000000000000..e4cba4afa01c
--- /dev/null
+++ b/libarchive/archive_write_add_filter_by_name.c
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+
+/* A table that maps names to functions. */
+static
+struct { const char *name; int (*setter)(struct archive *); } names[] =
+{
+ { "b64encode", archive_write_add_filter_b64encode },
+ { "bzip2", archive_write_add_filter_bzip2 },
+ { "compress", archive_write_add_filter_compress },
+ { "grzip", archive_write_add_filter_grzip },
+ { "gzip", archive_write_add_filter_gzip },
+ { "lrzip", archive_write_add_filter_lrzip },
+ { "lzip", archive_write_add_filter_lzip },
+ { "lzma", archive_write_add_filter_lzma },
+ { "lzop", archive_write_add_filter_lzop },
+ { "uuencode", archive_write_add_filter_uuencode },
+ { "xz", archive_write_add_filter_xz },
+ { NULL, NULL }
+};
+
+int
+archive_write_add_filter_by_name(struct archive *a, const char *name)
+{
+ int i;
+
+ for (i = 0; names[i].name != NULL; i++) {
+ if (strcmp(name, names[i].name) == 0)
+ return ((names[i].setter)(a));
+ }
+
+ archive_set_error(a, EINVAL, "No such filter '%s'", name);
+ a->state = ARCHIVE_STATE_FATAL;
+ return (ARCHIVE_FATAL);
+}
diff --git a/libarchive/archive_write_add_filter_bzip2.c b/libarchive/archive_write_add_filter_bzip2.c
index 2b48959ee093..88da803a395a 100644
--- a/libarchive/archive_write_add_filter_bzip2.c
+++ b/libarchive/archive_write_add_filter_bzip2.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -54,32 +55,18 @@ archive_write_set_compression_bzip2(struct archive *a)
}
#endif
-#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR)
-int
-archive_write_add_filter_bzip2(struct archive *a)
-{
- archive_set_error(a, ARCHIVE_ERRNO_MISC,
- "bzip2 compression not supported on this platform");
- return (ARCHIVE_FATAL);
-}
-#else
-/* Don't compile this if we don't have bzlib. */
-
struct private_data {
int compression_level;
+#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
bz_stream stream;
int64_t total_in;
char *compressed;
size_t compressed_buffer_size;
+#else
+ struct archive_write_program_data *pdata;
+#endif
};
-/*
- * Yuck. bzlib.h is not const-correct, so I need this one bit
- * of ugly hackery to convert a const * pointer to a non-const pointer.
- */
-#define SET_NEXT_IN(st,src) \
- (st)->stream.next_in = (char *)(uintptr_t)(const void *)(src)
-
static int archive_compressor_bzip2_close(struct archive_write_filter *);
static int archive_compressor_bzip2_free(struct archive_write_filter *);
static int archive_compressor_bzip2_open(struct archive_write_filter *);
@@ -87,8 +74,6 @@ static int archive_compressor_bzip2_options(struct archive_write_filter *,
const char *, const char *);
static int archive_compressor_bzip2_write(struct archive_write_filter *,
const void *, size_t);
-static int drive_compressor(struct archive_write_filter *,
- struct private_data *, int finishing);
/*
* Add a bzip2 compression filter to this write handle.
@@ -115,12 +100,65 @@ archive_write_add_filter_bzip2(struct archive *_a)
f->close = &archive_compressor_bzip2_close;
f->free = &archive_compressor_bzip2_free;
f->open = &archive_compressor_bzip2_open;
- f->code = ARCHIVE_COMPRESSION_BZIP2;
+ f->code = ARCHIVE_FILTER_BZIP2;
f->name = "bzip2";
+#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
return (ARCHIVE_OK);
+#else
+ data->pdata = __archive_write_program_allocate();
+ if (data->pdata == NULL) {
+ free(data);
+ archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ return (ARCHIVE_FATAL);
+ }
+ data->compression_level = 0;
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Using external bzip2 program");
+ return (ARCHIVE_WARN);
+#endif
}
/*
+ * Set write options.
+ */
+static int
+archive_compressor_bzip2_options(struct archive_write_filter *f,
+ const char *key, const char *value)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ if (strcmp(key, "compression-level") == 0) {
+ if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
+ value[1] != '\0')
+ return (ARCHIVE_WARN);
+ data->compression_level = value[0] - '0';
+ /* Make '0' be a synonym for '1'. */
+ /* This way, bzip2 compressor supports the same 0..9
+ * range of levels as gzip. */
+ if (data->compression_level < 1)
+ data->compression_level = 1;
+ return (ARCHIVE_OK);
+ }
+
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
+/* Don't compile this if we don't have bzlib. */
+
+/*
+ * Yuck. bzlib.h is not const-correct, so I need this one bit
+ * of ugly hackery to convert a const * pointer to a non-const pointer.
+ */
+#define SET_NEXT_IN(st,src) \
+ (st)->stream.next_in = (char *)(uintptr_t)(const void *)(src)
+static int drive_compressor(struct archive_write_filter *,
+ struct private_data *, int finishing);
+
+/*
* Setup callback.
*/
static int
@@ -195,34 +233,6 @@ archive_compressor_bzip2_open(struct archive_write_filter *f)
}
/*
- * Set write options.
- */
-static int
-archive_compressor_bzip2_options(struct archive_write_filter *f,
- const char *key, const char *value)
-{
- struct private_data *data = (struct private_data *)f->data;
-
- if (strcmp(key, "compression-level") == 0) {
- if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
- value[1] != '\0')
- return (ARCHIVE_WARN);
- data->compression_level = value[0] - '0';
- /* Make '0' be a synonym for '1'. */
- /* This way, bzip2 compressor supports the same 0..9
- * range of levels as gzip. */
- if (data->compression_level < 1)
- data->compression_level = 1;
- return (ARCHIVE_OK);
- }
-
- /* Note: The "warn" return is just to inform the options
- * supervisor that we didn't handle it. It will generate
- * a suitable error if no one used this option. */
- return (ARCHIVE_WARN);
-}
-
-/*
* Write data to the compressed stream.
*
* Returns ARCHIVE_OK if all data written, error otherwise.
@@ -343,4 +353,55 @@ drive_compressor(struct archive_write_filter *f,
}
}
+#else /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */
+
+static int
+archive_compressor_bzip2_open(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+ struct archive_string as;
+ int r;
+
+ archive_string_init(&as);
+ archive_strcpy(&as, "bzip2");
+
+ /* Specify compression level. */
+ if (data->compression_level > 0) {
+ archive_strcat(&as, " -");
+ archive_strappend_char(&as, '0' + data->compression_level);
+ }
+ f->write = archive_compressor_bzip2_write;
+
+ r = __archive_write_program_open(f, data->pdata, as.s);
+ archive_string_free(&as);
+ return (r);
+}
+
+static int
+archive_compressor_bzip2_write(struct archive_write_filter *f, const void *buff,
+ size_t length)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_write(f, data->pdata, buff, length);
+}
+
+static int
+archive_compressor_bzip2_close(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_close(f, data->pdata);
+}
+
+static int
+archive_compressor_bzip2_free(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ __archive_write_program_free(data->pdata);
+ free(data);
+ return (ARCHIVE_OK);
+}
+
#endif /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */
diff --git a/libarchive/archive_write_add_filter_compress.c b/libarchive/archive_write_add_filter_compress.c
index 4923316f5d8a..26fcef4d42bc 100644
--- a/libarchive/archive_write_add_filter_compress.c
+++ b/libarchive/archive_write_add_filter_compress.c
@@ -135,7 +135,7 @@ archive_write_add_filter_compress(struct archive *_a)
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_add_filter_compress");
f->open = &archive_compressor_compress_open;
- f->code = ARCHIVE_COMPRESSION_COMPRESS;
+ f->code = ARCHIVE_FILTER_COMPRESS;
f->name = "compress";
return (ARCHIVE_OK);
}
@@ -150,7 +150,7 @@ archive_compressor_compress_open(struct archive_write_filter *f)
struct private_data *state;
size_t bs = 65536, bpb;
- f->code = ARCHIVE_COMPRESSION_COMPRESS;
+ f->code = ARCHIVE_FILTER_COMPRESS;
f->name = "compress";
ret = __archive_write_open_filter(f->next_filter);
diff --git a/libarchive/archive_write_add_filter_grzip.c b/libarchive/archive_write_add_filter_grzip.c
new file mode 100644
index 000000000000..8dc287eae033
--- /dev/null
+++ b/libarchive/archive_write_add_filter_grzip.c
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include "archive.h"
+#include "archive_write_private.h"
+
+struct write_grzip {
+ struct archive_write_program_data *pdata;
+};
+
+static int archive_write_grzip_open(struct archive_write_filter *);
+static int archive_write_grzip_options(struct archive_write_filter *,
+ const char *, const char *);
+static int archive_write_grzip_write(struct archive_write_filter *,
+ const void *, size_t);
+static int archive_write_grzip_close(struct archive_write_filter *);
+static int archive_write_grzip_free(struct archive_write_filter *);
+
+int
+archive_write_add_filter_grzip(struct archive *_a)
+{
+ struct archive_write_filter *f = __archive_write_allocate_filter(_a);
+ struct write_grzip *data;
+
+ archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_write_add_filter_grzip");
+
+ data = calloc(1, sizeof(*data));
+ if (data == NULL) {
+ archive_set_error(_a, ENOMEM, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+ data->pdata = __archive_write_program_allocate();
+ if (data->pdata == NULL) {
+ free(data);
+ archive_set_error(_a, ENOMEM, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+
+ f->name = "grzip";
+ f->code = ARCHIVE_FILTER_GRZIP;
+ f->data = data;
+ f->open = archive_write_grzip_open;
+ f->options = archive_write_grzip_options;
+ f->write = archive_write_grzip_write;
+ f->close = archive_write_grzip_close;
+ f->free = archive_write_grzip_free;
+
+ /* Note: This filter always uses an external program, so we
+ * return "warn" to inform of the fact. */
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "Using external grzip program for grzip compression");
+ return (ARCHIVE_WARN);
+}
+
+static int
+archive_write_grzip_options(struct archive_write_filter *f, const char *key,
+ const char *value)
+{
+ (void)f; /* UNUSED */
+ (void)key; /* UNUSED */
+ (void)value; /* UNUSED */
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+static int
+archive_write_grzip_open(struct archive_write_filter *f)
+{
+ struct write_grzip *data = (struct write_grzip *)f->data;
+
+ return __archive_write_program_open(f, data->pdata, "grzip");
+}
+
+static int
+archive_write_grzip_write(struct archive_write_filter *f,
+ const void *buff, size_t length)
+{
+ struct write_grzip *data = (struct write_grzip *)f->data;
+
+ return __archive_write_program_write(f, data->pdata, buff, length);
+}
+
+static int
+archive_write_grzip_close(struct archive_write_filter *f)
+{
+ struct write_grzip *data = (struct write_grzip *)f->data;
+
+ return __archive_write_program_close(f, data->pdata);
+}
+
+static int
+archive_write_grzip_free(struct archive_write_filter *f)
+{
+ struct write_grzip *data = (struct write_grzip *)f->data;
+
+ __archive_write_program_free(data->pdata);
+ free(data);
+ return (ARCHIVE_OK);
+}
diff --git a/libarchive/archive_write_add_filter_gzip.c b/libarchive/archive_write_add_filter_gzip.c
index b1564774fd51..da4607bb934c 100644
--- a/libarchive/archive_write_add_filter_gzip.c
+++ b/libarchive/archive_write_add_filter_gzip.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_gzip.c 201
#include "archive.h"
#include "archive_private.h"
+#include "archive_string.h"
#include "archive_write_private.h"
#if ARCHIVE_VERSION_NUMBER < 4000000
@@ -54,24 +55,20 @@ archive_write_set_compression_gzip(struct archive *a)
}
#endif
-#ifndef HAVE_ZLIB_H
-int
-archive_write_add_filter_gzip(struct archive *a)
-{
- archive_set_error(a, ARCHIVE_ERRNO_MISC,
- "gzip compression not supported on this platform");
- return (ARCHIVE_FATAL);
-}
-#else
/* Don't compile this if we don't have zlib. */
struct private_data {
int compression_level;
+ int timestamp;
+#ifdef HAVE_ZLIB_H
z_stream stream;
int64_t total_in;
unsigned char *compressed;
size_t compressed_buffer_size;
unsigned long crc;
+#else
+ struct archive_write_program_data *pdata;
+#endif
};
/*
@@ -88,8 +85,10 @@ static int archive_compressor_gzip_write(struct archive_write_filter *,
const void *, size_t);
static int archive_compressor_gzip_close(struct archive_write_filter *);
static int archive_compressor_gzip_free(struct archive_write_filter *);
+#ifdef HAVE_ZLIB_H
static int drive_compressor(struct archive_write_filter *,
struct private_data *, int finishing);
+#endif
/*
@@ -110,17 +109,73 @@ archive_write_add_filter_gzip(struct archive *_a)
return (ARCHIVE_FATAL);
}
f->data = data;
- data->compression_level = Z_DEFAULT_COMPRESSION;
f->open = &archive_compressor_gzip_open;
f->options = &archive_compressor_gzip_options;
f->close = &archive_compressor_gzip_close;
f->free = &archive_compressor_gzip_free;
- f->code = ARCHIVE_COMPRESSION_GZIP;
+ f->code = ARCHIVE_FILTER_GZIP;
f->name = "gzip";
+#ifdef HAVE_ZLIB_H
+ data->compression_level = Z_DEFAULT_COMPRESSION;
+ return (ARCHIVE_OK);
+#else
+ data->pdata = __archive_write_program_allocate();
+ if (data->pdata == NULL) {
+ free(data);
+ archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ return (ARCHIVE_FATAL);
+ }
+ data->compression_level = 0;
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Using external gzip program");
+ return (ARCHIVE_WARN);
+#endif
+}
+
+static int
+archive_compressor_gzip_free(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+#ifdef HAVE_ZLIB_H
+ free(data->compressed);
+#else
+ __archive_write_program_free(data->pdata);
+#endif
+ free(data);
+ f->data = NULL;
return (ARCHIVE_OK);
}
/*
+ * Set write options.
+ */
+static int
+archive_compressor_gzip_options(struct archive_write_filter *f, const char *key,
+ const char *value)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ if (strcmp(key, "compression-level") == 0) {
+ if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
+ value[1] != '\0')
+ return (ARCHIVE_WARN);
+ data->compression_level = value[0] - '0';
+ return (ARCHIVE_OK);
+ }
+ if (strcmp(key, "timestamp") == 0) {
+ data->timestamp = (value == NULL)?-1:1;
+ return (ARCHIVE_OK);
+ }
+
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+#ifdef HAVE_ZLIB_H
+/*
* Setup callback.
*/
static int
@@ -128,7 +183,6 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
{
struct private_data *data = (struct private_data *)f->data;
int ret;
- time_t t;
ret = __archive_write_open_filter(f->next_filter);
if (ret != ARCHIVE_OK)
@@ -137,8 +191,8 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
if (data->compressed == NULL) {
size_t bs = 65536, bpb;
if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
- /* Buffer size should be a multiple number of the of bytes
- * per block for performance. */
+ /* Buffer size should be a multiple number of
+ * the of bytes per block for performance. */
bpb = archive_write_get_bytes_per_block(f->archive);
if (bpb > bs)
bs = bpb;
@@ -157,18 +211,21 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
data->crc = crc32(0L, NULL, 0);
data->stream.next_out = data->compressed;
- data->stream.avail_out = data->compressed_buffer_size;
+ data->stream.avail_out = (uInt)data->compressed_buffer_size;
/* Prime output buffer with a gzip header. */
- t = time(NULL);
data->compressed[0] = 0x1f; /* GZip signature bytes */
data->compressed[1] = 0x8b;
data->compressed[2] = 0x08; /* "Deflate" compression */
data->compressed[3] = 0; /* No options */
- data->compressed[4] = (uint8_t)(t)&0xff; /* Timestamp */
- data->compressed[5] = (uint8_t)(t>>8)&0xff;
- data->compressed[6] = (uint8_t)(t>>16)&0xff;
- data->compressed[7] = (uint8_t)(t>>24)&0xff;
+ if (data->timestamp >= 0) {
+ time_t t = time(NULL);
+ data->compressed[4] = (uint8_t)(t)&0xff; /* Timestamp */
+ data->compressed[5] = (uint8_t)(t>>8)&0xff;
+ data->compressed[6] = (uint8_t)(t>>16)&0xff;
+ data->compressed[7] = (uint8_t)(t>>24)&0xff;
+ } else
+ memset(&data->compressed[4], 0, 4);
data->compressed[8] = 0; /* No deflate options */
data->compressed[9] = 3; /* OS=Unix */
data->stream.next_out += 10;
@@ -201,8 +258,8 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
"compression library: invalid setup parameter");
break;
case Z_MEM_ERROR:
- archive_set_error(f->archive, ENOMEM, "Internal error initializing "
- "compression library");
+ archive_set_error(f->archive, ENOMEM,
+ "Internal error initializing compression library");
break;
case Z_VERSION_ERROR:
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
@@ -215,29 +272,6 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
}
/*
- * Set write options.
- */
-static int
-archive_compressor_gzip_options(struct archive_write_filter *f, const char *key,
- const char *value)
-{
- struct private_data *data = (struct private_data *)f->data;
-
- if (strcmp(key, "compression-level") == 0) {
- if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
- value[1] != '\0')
- return (ARCHIVE_WARN);
- data->compression_level = value[0] - '0';
- return (ARCHIVE_OK);
- }
-
- /* Note: The "warn" return is just to inform the options
- * supervisor that we didn't handle it. It will generate
- * a suitable error if no one used this option. */
- return (ARCHIVE_WARN);
-}
-
-/*
* Write data to the compressed stream.
*/
static int
@@ -248,12 +282,12 @@ archive_compressor_gzip_write(struct archive_write_filter *f, const void *buff,
int ret;
/* Update statistics */
- data->crc = crc32(data->crc, (const Bytef *)buff, length);
+ data->crc = crc32(data->crc, (const Bytef *)buff, (uInt)length);
data->total_in += length;
/* Compress input data to output buffer */
SET_NEXT_IN(data, buff);
- data->stream.avail_in = length;
+ data->stream.avail_in = (uInt)length;
if ((ret = drive_compressor(f, data, 0)) != ARCHIVE_OK)
return (ret);
@@ -303,16 +337,6 @@ archive_compressor_gzip_close(struct archive_write_filter *f)
return (r1 < ret ? r1 : ret);
}
-static int
-archive_compressor_gzip_free(struct archive_write_filter *f)
-{
- struct private_data *data = (struct private_data *)f->data;
- free(data->compressed);
- free(data);
- f->data = NULL;
- return (ARCHIVE_OK);
-}
-
/*
* Utility function to push input data through compressor,
* writing full output blocks as necessary.
@@ -334,7 +358,8 @@ drive_compressor(struct archive_write_filter *f,
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
data->stream.next_out = data->compressed;
- data->stream.avail_out = data->compressed_buffer_size;
+ data->stream.avail_out =
+ (uInt)data->compressed_buffer_size;
}
/* If there's nothing to do, we're done. */
@@ -367,4 +392,51 @@ drive_compressor(struct archive_write_filter *f,
}
}
+#else /* HAVE_ZLIB_H */
+
+static int
+archive_compressor_gzip_open(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+ struct archive_string as;
+ int r;
+
+ archive_string_init(&as);
+ archive_strcpy(&as, "gzip");
+
+ /* Specify compression level. */
+ if (data->compression_level > 0) {
+ archive_strcat(&as, " -");
+ archive_strappend_char(&as, '0' + data->compression_level);
+ }
+ if (data->timestamp < 0)
+ /* Do not save timestamp. */
+ archive_strcat(&as, " -n");
+ else if (data->timestamp > 0)
+ /* Save timestamp. */
+ archive_strcat(&as, " -N");
+
+ f->write = archive_compressor_gzip_write;
+ r = __archive_write_program_open(f, data->pdata, as.s);
+ archive_string_free(&as);
+ return (r);
+}
+
+static int
+archive_compressor_gzip_write(struct archive_write_filter *f, const void *buff,
+ size_t length)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_write(f, data->pdata, buff, length);
+}
+
+static int
+archive_compressor_gzip_close(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_close(f, data->pdata);
+}
+
#endif /* HAVE_ZLIB_H */
diff --git a/libarchive/archive_write_add_filter_lrzip.c b/libarchive/archive_write_add_filter_lrzip.c
new file mode 100644
index 000000000000..85fdf6af57f5
--- /dev/null
+++ b/libarchive/archive_write_add_filter_lrzip.c
@@ -0,0 +1,192 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "archive.h"
+#include "archive_string.h"
+#include "archive_write_private.h"
+
+struct write_lrzip {
+ struct archive_write_program_data *pdata;
+ int compression_level;
+ enum { lzma = 0, bzip2, gzip, lzo, zpaq } compression;
+};
+
+static int archive_write_lrzip_open(struct archive_write_filter *);
+static int archive_write_lrzip_options(struct archive_write_filter *,
+ const char *, const char *);
+static int archive_write_lrzip_write(struct archive_write_filter *,
+ const void *, size_t);
+static int archive_write_lrzip_close(struct archive_write_filter *);
+static int archive_write_lrzip_free(struct archive_write_filter *);
+
+int
+archive_write_add_filter_lrzip(struct archive *_a)
+{
+ struct archive_write_filter *f = __archive_write_allocate_filter(_a);
+ struct write_lrzip *data;
+
+ archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_write_add_filter_lrzip");
+
+ data = calloc(1, sizeof(*data));
+ if (data == NULL) {
+ archive_set_error(_a, ENOMEM, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+ data->pdata = __archive_write_program_allocate();
+ if (data->pdata == NULL) {
+ free(data);
+ archive_set_error(_a, ENOMEM, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+
+ f->name = "lrzip";
+ f->code = ARCHIVE_FILTER_LRZIP;
+ f->data = data;
+ f->open = archive_write_lrzip_open;
+ f->options = archive_write_lrzip_options;
+ f->write = archive_write_lrzip_write;
+ f->close = archive_write_lrzip_close;
+ f->free = archive_write_lrzip_free;
+
+ /* Note: This filter always uses an external program, so we
+ * return "warn" to inform of the fact. */
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "Using external lrzip program for lrzip compression");
+ return (ARCHIVE_WARN);
+}
+
+static int
+archive_write_lrzip_options(struct archive_write_filter *f, const char *key,
+ const char *value)
+{
+ struct write_lrzip *data = (struct write_lrzip *)f->data;
+
+ if (strcmp(key, "compression") == 0) {
+ if (value == NULL)
+ return (ARCHIVE_WARN);
+ else if (strcmp(value, "bzip2") == 0)
+ data->compression = bzip2;
+ else if (strcmp(value, "gzip") == 0)
+ data->compression = gzip;
+ else if (strcmp(value, "lzo") == 0)
+ data->compression = lzo;
+ else if (strcmp(value, "zpaq") == 0)
+ data->compression = zpaq;
+ else
+ return (ARCHIVE_WARN);
+ return (ARCHIVE_OK);
+ } else if (strcmp(key, "compression-level") == 0) {
+ if (value == NULL || !(value[0] >= '1' && value[0] <= '9') ||
+ value[1] != '\0')
+ return (ARCHIVE_WARN);
+ data->compression_level = value[0] - '0';
+ return (ARCHIVE_OK);
+ }
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+static int
+archive_write_lrzip_open(struct archive_write_filter *f)
+{
+ struct write_lrzip *data = (struct write_lrzip *)f->data;
+ struct archive_string as;
+ int r;
+
+ archive_string_init(&as);
+ archive_strcpy(&as, "lrzip -q");
+
+ /* Specify compression type. */
+ switch (data->compression) {
+ case lzma:/* default compression */
+ break;
+ case bzip2:
+ archive_strcat(&as, " -b");
+ break;
+ case gzip:
+ archive_strcat(&as, " -g");
+ break;
+ case lzo:
+ archive_strcat(&as, " -l");
+ break;
+ case zpaq:
+ archive_strcat(&as, " -z");
+ break;
+ }
+
+ /* Specify compression level. */
+ if (data->compression_level > 0) {
+ archive_strcat(&as, " -L ");
+ archive_strappend_char(&as, '0' + data->compression_level);
+ }
+
+ r = __archive_write_program_open(f, data->pdata, as.s);
+ archive_string_free(&as);
+ return (r);
+}
+
+static int
+archive_write_lrzip_write(struct archive_write_filter *f,
+ const void *buff, size_t length)
+{
+ struct write_lrzip *data = (struct write_lrzip *)f->data;
+
+ return __archive_write_program_write(f, data->pdata, buff, length);
+}
+
+static int
+archive_write_lrzip_close(struct archive_write_filter *f)
+{
+ struct write_lrzip *data = (struct write_lrzip *)f->data;
+
+ return __archive_write_program_close(f, data->pdata);
+}
+
+static int
+archive_write_lrzip_free(struct archive_write_filter *f)
+{
+ struct write_lrzip *data = (struct write_lrzip *)f->data;
+
+ __archive_write_program_free(data->pdata);
+ free(data);
+ return (ARCHIVE_OK);
+}
diff --git a/libarchive/archive_write_add_filter_lzop.c b/libarchive/archive_write_add_filter_lzop.c
new file mode 100644
index 000000000000..088ecea5167a
--- /dev/null
+++ b/libarchive/archive_write_add_filter_lzop.c
@@ -0,0 +1,486 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+//#undef HAVE_LZO_LZOCONF_H
+//#undef HAVE_LZO_LZO1X_H
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include <time.h>
+#ifdef HAVE_LZO_LZOCONF_H
+#include <lzo/lzoconf.h>
+#endif
+#ifdef HAVE_LZO_LZO1X_H
+#include <lzo/lzo1x.h>
+#endif
+
+#include "archive.h"
+#include "archive_string.h"
+#include "archive_endian.h"
+#include "archive_write_private.h"
+
+enum lzo_method {
+ METHOD_LZO1X_1 = 1,
+ METHOD_LZO1X_1_15 = 2,
+ METHOD_LZO1X_999 = 3
+};
+struct write_lzop {
+ int compression_level;
+#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
+ unsigned char *uncompressed;
+ size_t uncompressed_buffer_size;
+ size_t uncompressed_avail_bytes;
+ unsigned char *compressed;
+ size_t compressed_buffer_size;
+ enum lzo_method method;
+ unsigned char level;
+ lzo_voidp work_buffer;
+ lzo_uint32 work_buffer_size;
+ char header_written;
+#else
+ struct archive_write_program_data *pdata;
+#endif
+};
+
+static int archive_write_lzop_open(struct archive_write_filter *);
+static int archive_write_lzop_options(struct archive_write_filter *,
+ const char *, const char *);
+static int archive_write_lzop_write(struct archive_write_filter *,
+ const void *, size_t);
+static int archive_write_lzop_close(struct archive_write_filter *);
+static int archive_write_lzop_free(struct archive_write_filter *);
+
+#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
+/* Maximum block size. */
+#define BLOCK_SIZE (256 * 1024)
+/* Block infomation is composed of uncompressed size(4 bytes),
+ * compressed size(4 bytes) and the checksum of uncompressed data(4 bytes)
+ * in this lzop writer. */
+#define BLOCK_INfO_SIZE 12
+
+#define HEADER_VERSION 9
+#define HEADER_LIBVERSION 11
+#define HEADER_METHOD 15
+#define HEADER_LEVEL 16
+#define HEADER_MTIME_LOW 25
+#define HEADER_MTIME_HIGH 29
+#define HEADER_H_CHECKSUM 34
+
+/*
+ * Header template.
+ */
+static const unsigned char header[] = {
+ /* LZOP Magic code 9 bytes */
+ 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a,
+ /* LZOP utility version(fake data) 2 bytes */
+ 0x10, 0x30,
+ /* LZO library version 2 bytes */
+ 0x09, 0x40,
+ /* Minimum required LZO library version 2 bytes */
+ 0x09, 0x40,
+ /* Method */
+ 1,
+ /* Level */
+ 5,
+ /* Flags 4 bytes
+ * -OS Unix
+ * -Stdout
+ * -Stdin
+ * -Adler32 used for uncompressed data 4 bytes */
+ 0x03, 0x00, 0x00, 0x0d,
+ /* Mode (AE_IFREG | 0644) 4 bytes */
+ 0x00, 0x00, 0x81, 0xa4,
+ /* Mtime low 4 bytes */
+ 0x00, 0x00, 0x00, 0x00,
+ /* Mtime high 4 bytes */
+ 0x00, 0x00, 0x00, 0x00,
+ /* Filename length */
+ 0x00,
+ /* Header checksum 4 bytes */
+ 0x00, 0x00, 0x00, 0x00,
+};
+#endif
+
+int
+archive_write_add_filter_lzop(struct archive *_a)
+{
+ struct archive_write_filter *f = __archive_write_allocate_filter(_a);
+ struct write_lzop *data;
+
+ archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_write_add_filter_lzop");
+
+ data = calloc(1, sizeof(*data));
+ if (data == NULL) {
+ archive_set_error(_a, ENOMEM, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+
+ f->name = "lzop";
+ f->code = ARCHIVE_FILTER_LZOP;
+ f->data = data;
+ f->open = archive_write_lzop_open;
+ f->options = archive_write_lzop_options;
+ f->write = archive_write_lzop_write;
+ f->close = archive_write_lzop_close;
+ f->free = archive_write_lzop_free;
+#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
+ if (lzo_init() != LZO_E_OK) {
+ free(data);
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "lzo_init(type check) failed");
+ return (ARCHIVE_FATAL);
+ }
+ if (lzo_version() < 0x940) {
+ free(data);
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "liblzo library is too old(%s < 0.940)",
+ lzo_version_string());
+ return (ARCHIVE_FATAL);
+ }
+ data->compression_level = 5;
+ return (ARCHIVE_OK);
+#else
+ data->pdata = __archive_write_program_allocate();
+ if (data->pdata == NULL) {
+ free(data);
+ archive_set_error(_a, ENOMEM, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+ data->compression_level = 0;
+ /* Note: We return "warn" to inform of using an external lzop
+ * program. */
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "Using external lzop program for lzop compression");
+ return (ARCHIVE_WARN);
+#endif
+}
+
+static int
+archive_write_lzop_free(struct archive_write_filter *f)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+
+#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
+ free(data->uncompressed);
+ free(data->compressed);
+ free(data->work_buffer);
+#else
+ __archive_write_program_free(data->pdata);
+#endif
+ free(data);
+ return (ARCHIVE_OK);
+}
+
+static int
+archive_write_lzop_options(struct archive_write_filter *f, const char *key,
+ const char *value)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+
+ if (strcmp(key, "compression-level") == 0) {
+ if (value == NULL || !(value[0] >= '1' && value[0] <= '9') ||
+ value[1] != '\0')
+ return (ARCHIVE_WARN);
+ data->compression_level = value[0] - '0';
+ return (ARCHIVE_OK);
+ }
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
+static int
+archive_write_lzop_open(struct archive_write_filter *f)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+ int ret;
+
+ ret = __archive_write_open_filter(f->next_filter);
+ if (ret != ARCHIVE_OK)
+ return (ret);
+
+ switch (data->compression_level) {
+ case 1:
+ data->method = METHOD_LZO1X_1_15; data->level = 1; break;
+ default:
+ case 2: case 3: case 4: case 5: case 6:
+ data->method = METHOD_LZO1X_1; data->level = 5; break;
+ case 7:
+ data->method = METHOD_LZO1X_999; data->level = 7; break;
+ case 8:
+ data->method = METHOD_LZO1X_999; data->level = 8; break;
+ case 9:
+ data->method = METHOD_LZO1X_999; data->level = 9; break;
+ }
+ switch (data->method) {
+ case METHOD_LZO1X_1:
+ data->work_buffer_size = LZO1X_1_MEM_COMPRESS; break;
+ case METHOD_LZO1X_1_15:
+ data->work_buffer_size = LZO1X_1_15_MEM_COMPRESS; break;
+ case METHOD_LZO1X_999:
+ data->work_buffer_size = LZO1X_999_MEM_COMPRESS; break;
+ }
+ if (data->work_buffer == NULL) {
+ data->work_buffer = (lzo_voidp)malloc(data->work_buffer_size);
+ if (data->work_buffer == NULL) {
+ archive_set_error(f->archive, ENOMEM,
+ "Can't allocate data for compression buffer");
+ return (ARCHIVE_FATAL);
+ }
+ }
+ if (data->compressed == NULL) {
+ data->compressed_buffer_size = sizeof(header) +
+ BLOCK_SIZE + (BLOCK_SIZE >> 4) + 64 + 3;
+ data->compressed = (unsigned char *)
+ malloc(data->compressed_buffer_size);
+ if (data->compressed == NULL) {
+ archive_set_error(f->archive, ENOMEM,
+ "Can't allocate data for compression buffer");
+ return (ARCHIVE_FATAL);
+ }
+ }
+ if (data->uncompressed == NULL) {
+ data->uncompressed_buffer_size = BLOCK_SIZE;
+ data->uncompressed = (unsigned char *)
+ malloc(data->uncompressed_buffer_size);
+ if (data->uncompressed == NULL) {
+ archive_set_error(f->archive, ENOMEM,
+ "Can't allocate data for compression buffer");
+ return (ARCHIVE_FATAL);
+ }
+ data->uncompressed_avail_bytes = BLOCK_SIZE;
+ }
+ return (ARCHIVE_OK);
+}
+
+static int
+make_header(struct archive_write_filter *f)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+ int64_t t;
+ uint32_t checksum;
+
+ memcpy(data->compressed, header, sizeof(header));
+ /* Overwrite library version. */
+ data->compressed[HEADER_LIBVERSION] = (unsigned char )
+ (lzo_version() >> 8) & 0xff;
+ data->compressed[HEADER_LIBVERSION + 1] = (unsigned char )
+ lzo_version() & 0xff;
+ /* Overwrite method and level. */
+ data->compressed[HEADER_METHOD] = (unsigned char)data->method;
+ data->compressed[HEADER_LEVEL] = data->level;
+ /* Overwrite mtime with current time. */
+ t = (int64_t)time(NULL);
+ archive_be32enc(&data->compressed[HEADER_MTIME_LOW],
+ (uint32_t)(t & 0xffffffff));
+ archive_be32enc(&data->compressed[HEADER_MTIME_HIGH],
+ (uint32_t)((t >> 32) & 0xffffffff));
+ /* Overwrite header checksum with calculated value. */
+ checksum = lzo_adler32(1, data->compressed + HEADER_VERSION,
+ (lzo_uint)(HEADER_H_CHECKSUM - HEADER_VERSION));
+ archive_be32enc(&data->compressed[HEADER_H_CHECKSUM], checksum);
+ return (sizeof(header));
+}
+
+static int
+drive_compressor(struct archive_write_filter *f)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+ unsigned char *p;
+ const int block_info_bytes = 12;
+ int header_bytes, r;
+ lzo_uint usize, csize;
+ uint32_t checksum;
+
+ if (!data->header_written) {
+ header_bytes = make_header(f);
+ data->header_written = 1;
+ } else
+ header_bytes = 0;
+ p = data->compressed;
+
+ usize = (lzo_uint)
+ (data->uncompressed_buffer_size - data->uncompressed_avail_bytes);
+ csize = 0;
+ switch (data->method) {
+ default:
+ case METHOD_LZO1X_1:
+ r = lzo1x_1_compress(data->uncompressed, usize,
+ p + header_bytes + block_info_bytes, &csize,
+ data->work_buffer);
+ break;
+ case METHOD_LZO1X_1_15:
+ r = lzo1x_1_15_compress(data->uncompressed, usize,
+ p + header_bytes + block_info_bytes, &csize,
+ data->work_buffer);
+ break;
+ case METHOD_LZO1X_999:
+ r = lzo1x_999_compress_level(data->uncompressed, usize,
+ p + header_bytes + block_info_bytes, &csize,
+ data->work_buffer, NULL, 0, 0, data->level);
+ break;
+ }
+ if (r != LZO_E_OK) {
+ archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
+ "Lzop compression failed: returned status %d", r);
+ return (ARCHIVE_FATAL);
+ }
+
+ /* Store uncompressed size. */
+ archive_be32enc(p + header_bytes, (uint32_t)usize);
+ /* Store the checksum of the uncompressed data. */
+ checksum = lzo_adler32(1, data->uncompressed, usize);
+ archive_be32enc(p + header_bytes + 8, checksum);
+
+ if (csize < usize) {
+ /* Store compressed size. */
+ archive_be32enc(p + header_bytes + 4, (uint32_t)csize);
+ r = __archive_write_filter(f->next_filter, data->compressed,
+ header_bytes + block_info_bytes + csize);
+ } else {
+ /*
+ * This case, we output uncompressed data instead.
+ */
+ /* Store uncompressed size as compressed size. */
+ archive_be32enc(p + header_bytes + 4, (uint32_t)usize);
+ r = __archive_write_filter(f->next_filter, data->compressed,
+ header_bytes + block_info_bytes);
+ if (r != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+ r = __archive_write_filter(f->next_filter, data->uncompressed,
+ usize);
+ }
+
+ if (r != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+ return (ARCHIVE_OK);
+}
+
+static int
+archive_write_lzop_write(struct archive_write_filter *f,
+ const void *buff, size_t length)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+ const char *p = buff;
+ int r;
+
+ do {
+ if (data->uncompressed_avail_bytes > length) {
+ memcpy(data->uncompressed
+ + data->uncompressed_buffer_size
+ - data->uncompressed_avail_bytes,
+ p, length);
+ data->uncompressed_avail_bytes -= length;
+ return (ARCHIVE_OK);
+ }
+
+ memcpy(data->uncompressed + data->uncompressed_buffer_size
+ - data->uncompressed_avail_bytes,
+ p, data->uncompressed_avail_bytes);
+ length -= data->uncompressed_avail_bytes;
+ p += data->uncompressed_avail_bytes;
+ data->uncompressed_avail_bytes = 0;
+
+ r = drive_compressor(f);
+ if (r != ARCHIVE_OK) return (r);
+ data->uncompressed_avail_bytes = BLOCK_SIZE;
+ } while (length);
+
+ return (ARCHIVE_OK);
+}
+
+static int
+archive_write_lzop_close(struct archive_write_filter *f)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+ const uint32_t endmark = 0;
+ int r;
+
+ if (data->uncompressed_avail_bytes < BLOCK_SIZE) {
+ /* Compress and output remaining data. */
+ r = drive_compressor(f);
+ if (r != ARCHIVE_OK)
+ return (r);
+ }
+ /* Write a zero uncompressed size as the end mark of the series of
+ * compressed block. */
+ r = __archive_write_filter(f->next_filter, &endmark, sizeof(endmark));
+ if (r != ARCHIVE_OK)
+ return (r);
+ return (__archive_write_close_filter(f->next_filter));
+}
+
+#else
+static int
+archive_write_lzop_open(struct archive_write_filter *f)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+ struct archive_string as;
+ int r;
+
+ archive_string_init(&as);
+ archive_strcpy(&as, "lzop");
+ /* Specify compression level. */
+ if (data->compression_level > 0) {
+ archive_strappend_char(&as, ' ');
+ archive_strappend_char(&as, '-');
+ archive_strappend_char(&as, '0' + data->compression_level);
+ }
+
+ r = __archive_write_program_open(f, data->pdata, as.s);
+ archive_string_free(&as);
+ return (r);
+}
+
+static int
+archive_write_lzop_write(struct archive_write_filter *f,
+ const void *buff, size_t length)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+
+ return __archive_write_program_write(f, data->pdata, buff, length);
+}
+
+static int
+archive_write_lzop_close(struct archive_write_filter *f)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+
+ return __archive_write_program_close(f, data->pdata);
+}
+#endif
diff --git a/libarchive/archive_write_add_filter_program.c b/libarchive/archive_write_add_filter_program.c
index d7d38f7072da..fc232da0cb5e 100644
--- a/libarchive/archive_write_add_filter_program.c
+++ b/libarchive/archive_write_add_filter_program.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2007 Joerg Sonnenberger
+ * Copyright (c) 2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,7 +45,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_program.c
#include "archive.h"