aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Matuska <mm@FreeBSD.org>2011-12-20 22:47:56 +0000
committerMartin Matuska <mm@FreeBSD.org>2011-12-20 22:47:56 +0000
commit35fa5e2f58abd428bff0de1238364880447ef095 (patch)
tree07565a115ca59ea7230cd38e88901b0290750cde
downloadsrc-35fa5e2f58abd428bff0de1238364880447ef095.tar.gz
src-35fa5e2f58abd428bff0de1238364880447ef095.zip
Vendor import of libarchive (release/2.8, r3824)
Notes
Notes: svn path=/vendor/libarchive/dist/; revision=228753
-rw-r--r--CMakeLists.txt873
-rw-r--r--COPYING60
-rw-r--r--CTestConfig.cmake11
-rw-r--r--INSTALL30
-rw-r--r--Makefile.am630
-rw-r--r--NEWS550
-rw-r--r--README137
-rw-r--r--build/autoconf/check_stdcall_func.m451
-rw-r--r--build/autoconf/la_uid_t.m420
-rwxr-xr-xbuild/autogen.sh68
-rw-r--r--build/bump-version.sh36
-rw-r--r--build/clean.sh81
-rw-r--r--build/cmake/AddTest28.cmake107
-rw-r--r--build/cmake/CheckFileOffsetBits.c14
-rw-r--r--build/cmake/CheckFileOffsetBits.cmake44
-rw-r--r--build/cmake/CheckFuncs.cmake49
-rw-r--r--build/cmake/CheckFuncs_stub.c.in16
-rw-r--r--build/cmake/CheckHeaderDirent.cmake32
-rw-r--r--build/cmake/CheckStructMember.cmake43
-rw-r--r--build/cmake/CheckTypeExists.cmake42
-rw-r--r--build/cmake/FindLZMA.cmake52
-rw-r--r--build/cmake/config.h.in759
-rw-r--r--build/pkgconfig/libarchive.pc.in10
-rw-r--r--build/version1
-rw-r--r--configure.ac508
-rw-r--r--contrib/README32
-rw-r--r--contrib/libarchive.1aix53.spec160
-rw-r--r--contrib/libarchive.spec147
-rw-r--r--contrib/libarchive_autodetect-st_lib_archive.m4154
-rw-r--r--contrib/psota-benchmark/results.txt122
-rw-r--r--contrib/psota-benchmark/tcp.sh104
-rw-r--r--contrib/shar/Makefile14
-rw-r--r--contrib/shar/shar.1128
-rw-r--r--contrib/shar/shar.c314
-rw-r--r--contrib/shar/tree.c542
-rw-r--r--contrib/shar/tree.h115
-rw-r--r--contrib/shar/tree_config.h78
-rw-r--r--contrib/untar.c225
-rw-r--r--cpio/CMakeLists.txt51
-rw-r--r--cpio/bsdcpio.1405
-rw-r--r--cpio/cmdline.c369
-rw-r--r--cpio/config_freebsd.h56
-rw-r--r--cpio/cpio.c1267
-rw-r--r--cpio/cpio.h109
-rw-r--r--cpio/cpio_platform.h77
-rw-r--r--cpio/cpio_windows.c338
-rw-r--r--cpio/cpio_windows.h72
-rw-r--r--cpio/test/CMakeLists.txt79
-rw-r--r--cpio/test/main.c2140
-rw-r--r--cpio/test/test.h285
-rw-r--r--cpio/test/test_0.c67
-rw-r--r--cpio/test/test_basic.c173
-rw-r--r--cpio/test/test_cmdline.c107
-rw-r--r--cpio/test/test_format_newc.c294
-rw-r--r--cpio/test/test_gcpio_compat.c108
-rw-r--r--cpio/test/test_gcpio_compat_ref.bin.uu16
-rw-r--r--cpio/test/test_gcpio_compat_ref.crc.uu27
-rw-r--r--cpio/test/test_gcpio_compat_ref.newc.uu27
-rw-r--r--cpio/test/test_gcpio_compat_ref.ustar.uu84
-rw-r--r--cpio/test/test_gcpio_compat_ref_nosym.bin.uu15
-rw-r--r--cpio/test/test_gcpio_compat_ref_nosym.crc.uu15
-rw-r--r--cpio/test/test_gcpio_compat_ref_nosym.newc.uu15
-rw-r--r--cpio/test/test_gcpio_compat_ref_nosym.ustar.uu72
-rw-r--r--cpio/test/test_option_B_upper.c52
-rw-r--r--cpio/test/test_option_C_upper.c62
-rw-r--r--cpio/test/test_option_J_upper.c56
-rw-r--r--cpio/test/test_option_L_upper.c101
-rw-r--r--cpio/test/test_option_Z_upper.c56
-rw-r--r--cpio/test/test_option_a.c154
-rw-r--r--cpio/test/test_option_c.c221
-rw-r--r--cpio/test/test_option_d.c64
-rw-r--r--cpio/test/test_option_f.c76
-rw-r--r--cpio/test/test_option_f.cpio.uu16
-rw-r--r--cpio/test/test_option_help.c84
-rw-r--r--cpio/test/test_option_l.c50
-rw-r--r--cpio/test/test_option_lzma.c56
-rw-r--r--cpio/test/test_option_m.c63
-rw-r--r--cpio/test/test_option_m.cpio.uu16
-rw-r--r--cpio/test/test_option_t.c95
-rw-r--r--cpio/test/test_option_t.cpio.uu16
-rw-r--r--cpio/test/test_option_t.stdout.uu5
-rw-r--r--cpio/test/test_option_tv.stdout.uu6
-rw-r--r--cpio/test/test_option_u.c81
-rw-r--r--cpio/test/test_option_version.c109
-rw-r--r--cpio/test/test_option_y.c57
-rw-r--r--cpio/test/test_option_z.c56
-rw-r--r--cpio/test/test_owner_parse.c122
-rw-r--r--cpio/test/test_passthrough_dotdot.c76
-rw-r--r--cpio/test/test_passthrough_reverse.c85
-rw-r--r--cpio/test/test_pathmatch.c243
-rw-r--r--doc/mdoc2man.awk391
-rw-r--r--doc/mdoc2wiki.awk448
-rw-r--r--doc/update.sh117
-rw-r--r--examples/minitar/Makefile34
-rw-r--r--examples/minitar/README12
-rw-r--r--examples/minitar/minitar.c421
-rw-r--r--examples/minitar/tree.c423
-rw-r--r--examples/minitar/tree.h78
-rw-r--r--examples/tarfilter.c113
-rw-r--r--examples/untar.c262
-rw-r--r--libarchive/CMakeLists.txt139
-rw-r--r--libarchive/archive.h748
-rw-r--r--libarchive/archive_check_magic.c134
-rw-r--r--libarchive/archive_crc32.h66
-rw-r--r--libarchive/archive_endian.h162
-rw-r--r--libarchive/archive_entry.3433
-rw-r--r--libarchive/archive_entry.c2202
-rw-r--r--libarchive/archive_entry.h524
-rw-r--r--libarchive/archive_entry_copy_bhfi.c74
-rw-r--r--libarchive/archive_entry_copy_stat.c77
-rw-r--r--libarchive/archive_entry_link_resolver.c405
-rw-r--r--libarchive/archive_entry_private.h184
-rw-r--r--libarchive/archive_entry_stat.c118
-rw-r--r--libarchive/archive_entry_strmode.c87
-rw-r--r--libarchive/archive_entry_xattr.c158
-rw-r--r--libarchive/archive_hash.h309
-rw-r--r--libarchive/archive_platform.h165
-rw-r--r--libarchive/archive_private.h124
-rw-r--r--libarchive/archive_read.3714
-rw-r--r--libarchive/archive_read.c1249
-rw-r--r--libarchive/archive_read_data_into_fd.c93
-rw-r--r--libarchive/archive_read_disk.3308
-rw-r--r--libarchive/archive_read_disk.c198
-rw-r--r--libarchive/archive_read_disk_entry_from_file.c570
-rw-r--r--libarchive/archive_read_disk_private.h62
-rw-r--r--libarchive/archive_read_disk_set_standard_lookup.c303
-rw-r--r--libarchive/archive_read_extract.c183
-rw-r--r--libarchive/archive_read_open_fd.c190
-rw-r--r--libarchive/archive_read_open_file.c165
-rw-r--r--libarchive/archive_read_open_filename.c272
-rw-r--r--libarchive/archive_read_open_memory.c156
-rw-r--r--libarchive/archive_read_private.h199
-rw-r--r--libarchive/archive_read_support_compression_all.c60
-rw-r--r--libarchive/archive_read_support_compression_bzip2.c353
-rw-r--r--libarchive/archive_read_support_compression_compress.c444
-rw-r--r--libarchive/archive_read_support_compression_gzip.c465
-rw-r--r--libarchive/archive_read_support_compression_none.c40
-rw-r--r--libarchive/archive_read_support_compression_program.c459
-rw-r--r--libarchive/archive_read_support_compression_rpm.c287
-rw-r--r--libarchive/archive_read_support_compression_uu.c637
-rw-r--r--libarchive/archive_read_support_compression_xz.c708
-rw-r--r--libarchive/archive_read_support_format_all.c51
-rw-r--r--libarchive/archive_read_support_format_ar.c584
-rw-r--r--libarchive/archive_read_support_format_cpio.c777
-rw-r--r--libarchive/archive_read_support_format_empty.c93
-rw-r--r--libarchive/archive_read_support_format_iso9660.c2961
-rw-r--r--libarchive/archive_read_support_format_mtree.c1309
-rw-r--r--libarchive/archive_read_support_format_raw.c185
-rw-r--r--libarchive/archive_read_support_format_tar.c2418
-rw-r--r--libarchive/archive_read_support_format_xar.c3151
-rw-r--r--libarchive/archive_read_support_format_zip.c903
-rw-r--r--libarchive/archive_string.c453
-rw-r--r--libarchive/archive_string.h151
-rw-r--r--libarchive/archive_string_sprintf.c164
-rw-r--r--libarchive/archive_util.3160
-rw-r--r--libarchive/archive_util.c392
-rw-r--r--libarchive/archive_virtual.c94
-rw-r--r--libarchive/archive_windows.c1236
-rw-r--r--libarchive/archive_windows.h347
-rw-r--r--libarchive/archive_write.3629
-rw-r--r--libarchive/archive_write.c466
-rw-r--r--libarchive/archive_write_disk.3375
-rw-r--r--libarchive/archive_write_disk.c2712
-rw-r--r--libarchive/archive_write_disk_private.h38
-rw-r--r--libarchive/archive_write_disk_set_standard_lookup.c262
-rw-r--r--libarchive/archive_write_open_fd.c144
-rw-r--r--libarchive/archive_write_open_file.c109
-rw-r--r--libarchive/archive_write_open_filename.c166
-rw-r--r--libarchive/archive_write_open_memory.c126
-rw-r--r--libarchive/archive_write_private.h122
-rw-r--r--libarchive/archive_write_set_compression_bzip2.c408
-rw-r--r--libarchive/archive_write_set_compression_compress.c492
-rw-r--r--libarchive/archive_write_set_compression_gzip.c477
-rw-r--r--libarchive/archive_write_set_compression_none.c257
-rw-r--r--libarchive/archive_write_set_compression_program.c347
-rw-r--r--libarchive/archive_write_set_compression_xz.c439
-rw-r--r--libarchive/archive_write_set_format.c72
-rw-r--r--libarchive/archive_write_set_format_ar.c550
-rw-r--r--libarchive/archive_write_set_format_by_name.c76
-rw-r--r--libarchive/archive_write_set_format_cpio.c344
-rw-r--r--libarchive/archive_write_set_format_cpio_newc.c295
-rw-r--r--libarchive/archive_write_set_format_mtree.c1050
-rw-r--r--libarchive/archive_write_set_format_pax.c1386
-rw-r--r--libarchive/archive_write_set_format_shar.c625
-rw-r--r--libarchive/archive_write_set_format_ustar.c587
-rw-r--r--libarchive/archive_write_set_format_zip.c670
-rw-r--r--libarchive/config_freebsd.h154
-rw-r--r--libarchive/cpio.5325
-rw-r--r--libarchive/filter_fork.c161
-rw-r--r--libarchive/filter_fork.h41
-rw-r--r--libarchive/filter_fork_windows.c113
-rw-r--r--libarchive/libarchive-formats.5355
-rw-r--r--libarchive/libarchive.3331
-rw-r--r--libarchive/libarchive_internals.3365
-rw-r--r--libarchive/mtree.5269
-rw-r--r--libarchive/tar.5831
-rw-r--r--libarchive/test/.cvsignore10
-rw-r--r--libarchive/test/CMakeLists.txt159
-rw-r--r--libarchive/test/README63
-rw-r--r--libarchive/test/main.c2130
-rw-r--r--libarchive/test/read_open_memory.c167
-rw-r--r--libarchive/test/test.h302
-rw-r--r--libarchive/test/test_acl_basic.c229
-rw-r--r--libarchive/test/test_acl_freebsd.c255
-rw-r--r--libarchive/test/test_acl_pax.c517
-rw-r--r--libarchive/test/test_archive_api_feature.c76
-rw-r--r--libarchive/test/test_bad_fd.c41
-rw-r--r--libarchive/test/test_compat_bzip2.c85
-rw-r--r--libarchive/test/test_compat_bzip2_1.tbz.uu24
-rw-r--r--libarchive/test/test_compat_bzip2_2.tbz.uu11
-rw-r--r--libarchive/test/test_compat_cpio.c106
-rw-r--r--libarchive/test/test_compat_cpio_1.cpio.uu19
-rw-r--r--libarchive/test/test_compat_gtar.c119
-rw-r--r--libarchive/test/test_compat_gtar_1.tar.uu232
-rw-r--r--libarchive/test/test_compat_gzip.c97
-rw-r--r--libarchive/test/test_compat_gzip_1.tgz.uu24
-rw-r--r--libarchive/test/test_compat_gzip_2.tgz.uu11
-rw-r--r--libarchive/test/test_compat_lzma.c155
-rw-r--r--libarchive/test/test_compat_lzma_1.tlz.uu10
-rw-r--r--libarchive/test/test_compat_lzma_2.tlz.uu9
-rw-r--r--libarchive/test/test_compat_lzma_3.tlz.uu9
-rw-r--r--libarchive/test/test_compat_solaris_tar_acl.c128
-rw-r--r--libarchive/test/test_compat_solaris_tar_acl.tar.uu61
-rw-r--r--libarchive/test/test_compat_tar_hardlink.c108
-rw-r--r--libarchive/test/test_compat_tar_hardlink_1.tar.uu39
-rw-r--r--libarchive/test/test_compat_xz.c84
-rw-r--r--libarchive/test/test_compat_xz_1.txz.uu13
-rw-r--r--libarchive/test/test_compat_zip.c80
-rw-r--r--libarchive/test/test_compat_zip_1.zip.uu15
-rw-r--r--libarchive/test/test_empty_write.c120
-rw-r--r--libarchive/test/test_entry.c903
-rw-r--r--libarchive/test/test_entry_strmode.c71
-rw-r--r--libarchive/test/test_extattr_freebsd.c172
-rw-r--r--libarchive/test/test_fuzz.c166
-rw-r--r--libarchive/test/test_fuzz_1.iso.Z.uu495
-rw-r--r--libarchive/test/test_link_resolver.c205
-rw-r--r--libarchive/test/test_open_failure.c198
-rw-r--r--libarchive/test/test_open_fd.c128
-rw-r--r--libarchive/test/test_open_file.c108
-rw-r--r--libarchive/test/test_open_filename.c109
-rw-r--r--libarchive/test/test_pax_filename_encoding.c333
-rw-r--r--libarchive/test/test_pax_filename_encoding.tar.uu118
-rw-r--r--libarchive/test/test_read_compress_program.c84
-rw-r--r--libarchive/test/test_read_data_large.c125
-rw-r--r--libarchive/test/test_read_disk.c172
-rw-r--r--libarchive/test/test_read_disk_entry_from_file.c80
-rw-r--r--libarchive/test/test_read_extract.c168
-rw-r--r--libarchive/test/test_read_file_nonexistent.c37
-rw-r--r--libarchive/test/test_read_format_ar.ar.uu12
-rw-r--r--libarchive/test/test_read_format_ar.c87
-rw-r--r--libarchive/test/test_read_format_cpio_bin.c64
-rw-r--r--libarchive/test/test_read_format_cpio_bin_Z.c61
-rw-r--r--libarchive/test/test_read_format_cpio_bin_be.c55
-rw-r--r--libarchive/test/test_read_format_cpio_bin_be.cpio.uu8
-rw-r--r--libarchive/test/test_read_format_cpio_bin_bz2.c58
-rw-r--r--libarchive/test/test_read_format_cpio_bin_gz.c61
-rw-r--r--libarchive/test/test_read_format_cpio_bin_lzma.c60
-rw-r--r--libarchive/test/test_read_format_cpio_bin_xz.c70
-rw-r--r--libarchive/test/test_read_format_cpio_odc.c68
-rw-r--r--libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c127
-rw-r--r--libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.rpm.uu47
-rw-r--r--libarchive/test/test_read_format_cpio_svr4_gzip.c61
-rw-r--r--libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c127
-rw-r--r--libarchive/test/test_read_format_cpio_svr4_gzip_rpm.rpm.uu46
-rw-r--r--libarchive/test/test_read_format_cpio_svr4c_Z.c62
-rw-r--r--libarchive/test/test_read_format_empty.c47
-rw-r--r--libarchive/test/test_read_format_gtar_gz.c60
-rw-r--r--libarchive/test/test_read_format_gtar_lzma.c78
-rw-r--r--libarchive/test/test_read_format_gtar_sparse.c318
-rw-r--r--libarchive/test/test_read_format_gtar_sparse_1_13.tar.uu1370
-rw-r--r--libarchive/test/test_read_format_gtar_sparse_1_17.tar.uu1370
-rw-r--r--libarchive/test/test_read_format_gtar_sparse_1_17_posix00.tar.uu1597
-rw-r--r--libarchive/test/test_read_format_gtar_sparse_1_17_posix01.tar.uu1370
-rw-r--r--libarchive/test/test_read_format_gtar_sparse_1_17_posix10.tar.uu1370
-rw-r--r--libarchive/test/test_read_format_gtar_sparse_1_17_posix10_modified.tar.uu1370
-rw-r--r--libarchive/test/test_read_format_iso.iso.Z.uu26
-rw-r--r--libarchive/test/test_read_format_iso_2.iso.Z.uu35
-rw-r--r--libarchive/test/test_read_format_iso_Z.c99
-rw-r--r--libarchive/test/test_read_format_iso_joliet.iso.Z.uu66
-rw-r--r--libarchive/test/test_read_format_iso_joliet_long.iso.Z.uu71
-rw-r--r--libarchive/test/test_read_format_iso_joliet_rockridge.iso.Z.uu68
-rw-r--r--libarchive/test/test_read_format_iso_multi_extent.c94
-rw-r--r--libarchive/test/test_read_format_iso_multi_extent.iso.Z.uu67
-rw-r--r--libarchive/test/test_read_format_iso_rockridge.iso.Z.uu206
-rw-r--r--libarchive/test/test_read_format_iso_rockridge_ce.iso.Z.uu63
-rw-r--r--libarchive/test/test_read_format_iso_rockridge_new.iso.Z.uu208
-rw-r--r--libarchive/test/test_read_format_iso_rockridge_rr_moved.iso.Z.uu304
-rw-r--r--libarchive/test/test_read_format_iso_zisofs.iso.Z.uu63
-rw-r--r--libarchive/test/test_read_format_isojoliet_bz2.c135
-rw-r--r--libarchive/test/test_read_format_isojoliet_long.c141
-rw-r--r--libarchive/test/test_read_format_isojoliet_rr.c160
-rw-r--r--libarchive/test/test_read_format_isorr_bz2.c203
-rw-r--r--libarchive/test/test_read_format_isorr_ce.c223
-rw-r--r--libarchive/test/test_read_format_isorr_new_bz2.c204
-rw-r--r--libarchive/test/test_read_format_isorr_rr_moved.c270
-rw-r--r--libarchive/test/test_read_format_isozisofs_bz2.c187
-rw-r--r--libarchive/test/test_read_format_mtree.c186
-rw-r--r--libarchive/test/test_read_format_mtree.mtree.uu13
-rw-r--r--libarchive/test/test_read_format_pax_bz2.c66
-rw-r--r--libarchive/test/test_read_format_raw.c89
-rw-r--r--libarchive/test/test_read_format_raw.data.Z.uu5
-rw-r--r--libarchive/test/test_read_format_raw.data.uu5
-rw-r--r--libarchive/test/test_read_format_tar.c480
-rw-r--r--libarchive/test/test_read_format_tar_empty_filename.c66
-rw-r--r--libarchive/test/test_read_format_tar_empty_filename.tar.uu39
-rw-r--r--libarchive/test/test_read_format_tbz.c59
-rw-r--r--libarchive/test/test_read_format_tgz.c60
-rw-r--r--libarchive/test/test_read_format_tlz.c60
-rw-r--r--libarchive/test/test_read_format_txz.c63
-rw-r--r--libarchive/test/test_read_format_tz.c61
-rw-r--r--libarchive/test/test_read_format_xar.c697
-rw-r--r--libarchive/test/test_read_format_zip.c92
-rw-r--r--libarchive/test/test_read_format_zip.zip.uu14
-rw-r--r--libarchive/test/test_read_large.c93
-rw-r--r--libarchive/test/test_read_pax_truncated.c288
-rw-r--r--libarchive/test/test_read_position.c94
-rw-r--r--libarchive/test/test_read_truncated.c149
-rw-r--r--libarchive/test/test_read_uu.c134
-rw-r--r--libarchive/test/test_tar_filenames.c186
-rw-r--r--libarchive/test/test_tar_large.c312
-rw-r--r--libarchive/test/test_ustar_filenames.c191
-rw-r--r--libarchive/test/test_write_compress.c102
-rw-r--r--libarchive/test/test_write_compress_bzip2.c228
-rw-r--r--libarchive/test/test_write_compress_gzip.c252
-rw-r--r--libarchive/test/test_write_compress_lzma.c250
-rw-r--r--libarchive/test/test_write_compress_program.c118
-rw-r--r--libarchive/test/test_write_compress_xz.c257
-rw-r--r--libarchive/test/test_write_disk.c332
-rw-r--r--libarchive/test/test_write_disk_failures.c72
-rw-r--r--libarchive/test/test_write_disk_hardlink.c219
-rw-r--r--libarchive/test/test_write_disk_perms.c457
-rw-r--r--libarchive/test/test_write_disk_secure.c215
-rw-r--r--libarchive/test/test_write_disk_sparse.c280
-rw-r--r--libarchive/test/test_write_disk_symlink.c117
-rw-r--r--libarchive/test/test_write_disk_times.c167
-rw-r--r--libarchive/test/test_write_format_ar.c209
-rw-r--r--libarchive/test/test_write_format_cpio.c194
-rw-r--r--libarchive/test/test_write_format_cpio_empty.c75
-rw-r--r--libarchive/test/test_write_format_cpio_newc.c214
-rw-r--r--libarchive/test/test_write_format_cpio_odc.c241
-rw-r--r--libarchive/test/test_write_format_mtree.c155
-rw-r--r--libarchive/test/test_write_format_pax.c146
-rw-r--r--libarchive/test/test_write_format_shar_empty.c58
-rw-r--r--libarchive/test/test_write_format_tar.c114
-rw-r--r--libarchive/test/test_write_format_tar_empty.c92
-rw-r--r--libarchive/test/test_write_format_tar_ustar.c347
-rw-r--r--libarchive/test/test_write_format_zip.c180
-rw-r--r--libarchive/test/test_write_format_zip_empty.c56
-rw-r--r--libarchive/test/test_write_format_zip_no_compression.c304
-rw-r--r--libarchive/test/test_write_open_memory.c76
-rw-r--r--libarchive_fe/err.c74
-rw-r--r--libarchive_fe/err.h41
-rw-r--r--libarchive_fe/lafe_platform.h55
-rw-r--r--libarchive_fe/line_reader.c171
-rw-r--r--libarchive_fe/line_reader.h35
-rw-r--r--libarchive_fe/matching.c284
-rw-r--r--libarchive_fe/matching.h46
-rw-r--r--libarchive_fe/pathmatch.c255
-rw-r--r--libarchive_fe/pathmatch.h42
-rw-r--r--tar/CMakeLists.txt55
-rw-r--r--tar/bsdtar.1988
-rw-r--r--tar/bsdtar.c757
-rw-r--r--tar/bsdtar.h165
-rw-r--r--tar/bsdtar_platform.h132
-rw-r--r--tar/bsdtar_windows.c298
-rw-r--r--tar/bsdtar_windows.h60
-rw-r--r--tar/cmdline.c385
-rw-r--r--tar/config_freebsd.h84
-rw-r--r--tar/getdate.c1037
-rw-r--r--tar/read.c445
-rw-r--r--tar/subst.c289
-rw-r--r--tar/test/CMakeLists.txt67
-rw-r--r--tar/test/main.c2242
-rw-r--r--tar/test/test.h288
-rw-r--r--tar/test/test_0.c67
-rw-r--r--tar/test/test_basic.c115
-rw-r--r--tar/test/test_copy.c372
-rw-r--r--tar/test/test_empty_mtree.c45
-rw-r--r--tar/test/test_getdate.c80
-rw-r--r--tar/test/test_help.c84
-rw-r--r--tar/test/test_option_T_upper.c188
-rw-r--r--tar/test/test_option_q.c129
-rw-r--r--tar/test/test_option_r.c117
-rw-r--r--tar/test/test_option_s.c107
-rw-r--r--tar/test/test_patterns.c184
-rw-r--r--tar/test/test_patterns_2.tar.uu231
-rw-r--r--tar/test/test_patterns_3.tar.uu231
-rw-r--r--tar/test/test_patterns_4.tar.uu641
-rw-r--r--tar/test/test_stdio.c125
-rw-r--r--tar/test/test_strip_components.c109
-rw-r--r--tar/test/test_symlink_dir.c160
-rw-r--r--tar/test/test_version.c97
-rw-r--r--tar/test/test_windows.c323
-rw-r--r--tar/tree.c821
-rw-r--r--tar/tree.h141
-rw-r--r--tar/util.c559
-rw-r--r--tar/write.c1155
397 files changed, 108328 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 000000000000..04aa9a6f40f3
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,873 @@
+#
+#
+PROJECT(libarchive C)
+#
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6.3 FATAL_ERROR)
+SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake")
+if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${libarchive_BINARY_DIR}/bin)
+endif()
+
+#
+# Version - read from 'version' file.
+#
+FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/build/version _version)
+STRING(REGEX REPLACE
+ "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]?$" "\\1" _major ${_version})
+STRING(REGEX REPLACE
+ "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]?$" "\\1" _minor ${_version})
+STRING(REGEX REPLACE
+ "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]?$" "\\1" _revision ${_version})
+STRING(REGEX REPLACE
+ "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]?)$" "\\1" _quality ${_version})
+SET(_version_number ${_major}${_minor}${_revision})
+STRING(REGEX REPLACE "[0]*([^0][0-9]*)$" "\\1" _minor ${_minor})
+STRING(REGEX REPLACE "[0]*([^0][0-9]*)$" "\\1" _revision ${_revision})
+#
+SET(VERSION "${_major}.${_minor}.${_revision}${_quality}")
+SET(BSDCPIO_VERSION_STRING "${VERSION}")
+SET(BSDTAR_VERSION_STRING "${VERSION}")
+SET(LIBARCHIVE_VERSION_NUMBER "${_version_number}")
+SET(LIBARCHIVE_VERSION_STRING "${VERSION}")
+# Shared library number
+SET(SOVERSION 8)
+
+# Enable CTest/CDash support
+include(CTest)
+
+# Provide ADD_TEST_28 macro to approximate CMake 2.8 ADD_TEST(NAME).
+# TODO: Require CMake 2.8 and drop this workaround (perhaps late 2010).
+INCLUDE(AddTest28)
+
+OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON)
+OPTION(ENABLE_TAR "Enable tar building" ON)
+OPTION(ENABLE_TAR_SHARED "Enable dynamic build of tar" OFF)
+OPTION(ENABLE_CPIO "Enable cpio building" ON)
+OPTION(ENABLE_CPIO_SHARED "Enable dynamic build of cpio" OFF)
+OPTION(ENABLE_XATTR "Enable extended attribute support" ON)
+OPTION(ENABLE_ACL "Enable ACL support" ON)
+OPTION(ENABLE_TEST "Enable unit and regression tests" ON)
+
+IF(ENABLE_TEST)
+ ENABLE_TESTING()
+ENDIF(ENABLE_TEST)
+IF(WIN32 AND NOT CYGWIN)
+ # Currently, dynamic build only.
+ SET(ENABLE_TAR_SHARED ON)
+ SET(ENABLE_CPIO_SHARED ON)
+ENDIF(WIN32 AND NOT CYGWIN)
+
+IF(WIN32)
+ SET(_WIN32_WINNT 0x0500 CACHE INTERNAL "Setting _WIN32_WINNT to 0x0500 for Windows 2000 APIs")
+ SET(WINVER 0x0500 CACHE INTERNAL "Setting WINVER to 0x0500 for Windows 2000 APIs")
+ENDIF(WIN32)
+
+#
+INCLUDE(CheckCSourceRuns)
+INCLUDE(CheckFileOffsetBits)
+INCLUDE(CheckFuncs)
+INCLUDE(CheckHeaderDirent)
+INCLUDE(CheckIncludeFile)
+INCLUDE(CheckIncludeFiles)
+INCLUDE(CheckLibraryExists)
+INCLUDE(CheckStructMember)
+INCLUDE(CheckSymbolExists)
+INCLUDE(CheckTypeExists)
+INCLUDE(CheckTypeSize)
+
+#
+# Generate list.h
+#
+MACRO (GENERATE_LIST_H _listfile _cmlist __list_sources)
+ SET(_argv ${ARGV})
+ # Remove _listfile and _cmlist from _argv
+ LIST(REMOVE_AT _argv 0 1)
+ IF (NOT EXISTS "${_listfile}" OR
+ ${_cmlist} IS_NEWER_THAN "${_listfile}")
+
+ MESSAGE(STATUS "Generating ${_listfile}")
+ FILE(WRITE ${_listfile} "")
+ FOREACH (testfile ${_argv})
+ IF (testfile MATCHES "^test_[^/]+[.]c$")
+ FILE(STRINGS ${testfile} testvar REGEX "^DEFINE_TEST")
+ FOREACH (deftest ${testvar})
+ FILE(APPEND ${_listfile} "${deftest}\n")
+ ENDFOREACH (deftest)
+ ENDIF (testfile MATCHES "^test_[^/]+[.]c$")
+ ENDFOREACH (testfile)
+
+ ENDIF (NOT EXISTS "${_listfile}" OR
+ ${_cmlist} IS_NEWER_THAN "${_listfile}")
+ENDMACRO (GENERATE_LIST_H)
+#
+# Generate installation rules for man pages.
+#
+MACRO (INSTALL_MAN __mans)
+ FOREACH (_man ${ARGV})
+ STRING(REGEX REPLACE "^.+[.]([1-9])" "\\1" _mansect ${_man})
+ INSTALL(FILES ${_man} DESTINATION "share/man/man${_mansect}")
+ ENDFOREACH (_man)
+ENDMACRO (INSTALL_MAN __mans)
+
+#
+# Check compress/decompress libraries
+#
+IF(WIN32 AND NOT CMAKE_CL_64 AND NOT CYGWIN)
+ # GnuWin32 is only for Win32, not Win64.
+ SET(__GNUWIN32PATH "C:/Program Files/GnuWin32")
+ENDIF(WIN32 AND NOT CMAKE_CL_64 AND NOT CYGWIN)
+IF(DEFINED __GNUWIN32PATH AND EXISTS "${__GNUWIN32PATH}")
+ # You have to add a path availabel DLL file into PATH environment variable.
+ # Maybe DLL path is "C:/Program Files/GnuWin32/bin".
+ # The zlib and the bzip2 Setup program have installed programs and DLLs into
+ # "C:/Program Files/GnuWin32" by default.
+ # This is convenience setting for Windows.
+ SET(CMAKE_PREFIX_PATH ${__GNUWIN32PATH} $(CMAKE_PREFIX_PATH))
+ #
+ # If you didn't use Setup program or installed into nonstandard path,
+ # cmake cannot find out your zlib or bzip2 libraries and include files,
+ # you should execute cmake with -DCMAKE_PREFIX_PATH option.
+ # e.g.
+ # cmake -DCMAKE_PREFIX_PATH=<your-GnuWin32-path> <path-to-source>
+ #
+ # If compiling error occured in zconf.h, You may need patch to zconf.h.
+ #--- zconf.h.orig 2005-07-21 00:40:26.000000000
+ #+++ zconf.h 2009-01-19 11:39:10.093750000
+ #@@ -286,7 +286,7 @@
+ #
+ # #if 1 /* HAVE_UNISTD_H -- this line is updated by ./configure */
+ # # include <sys/types.h> /* for off_t */
+ #-# include <unistd.h> /* for SEEK_* and off_t */
+ #+# include <stdio.h> /* for SEEK_* and off_t */
+ # # ifdef VMS
+ # # include <unixio.h> /* for off_t */
+ # # endif
+ENDIF(DEFINED __GNUWIN32PATH AND EXISTS "${__GNUWIN32PATH}")
+
+SET(ADDITIONAL_LIBS "")
+#
+# Find ZLIB
+#
+FIND_PACKAGE(ZLIB)
+IF(ZLIB_FOUND)
+ SET(HAVE_LIBZ 1)
+ SET(HAVE_ZLIB_H 1)
+ INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${ZLIB_LIBRARIES})
+ IF(WIN32 AND NOT CYGWIN)
+ SET(CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIR})
+ SET(CMAKE_REQUIRED_LIBRARIES ${ZLIB_LIBRARIES})
+ CHECK_C_SOURCE_Runs(
+ "#ifndef ZLIB_WINAPI\n#define ZLIB_WINAPI\n#endif\n#include <zlib.h>\nint main() {uLong f = zlibCompileFlags(); return (f&(1U<<10))?0:-1; }"
+ ZLIB_WINAPI)
+ ENDIF(WIN32 AND NOT CYGWIN)
+ENDIF(ZLIB_FOUND)
+MARK_AS_ADVANCED(CLEAR ZLIB_INCLUDE_DIR)
+MARK_AS_ADVANCED(CLEAR ZLIB_LIBRARY)
+#
+# Find BZip2
+#
+FIND_PACKAGE(BZip2)
+IF(BZIP2_FOUND)
+ SET(HAVE_LIBBZ2 1)
+ SET(HAVE_BZLIB_H 1)
+ INCLUDE_DIRECTORIES(${BZIP2_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${BZIP2_LIBRARIES})
+ENDIF(BZIP2_FOUND)
+MARK_AS_ADVANCED(CLEAR BZIP2_INCLUDE_DIR)
+MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARY)
+#
+# Find LZMA
+#
+FIND_PACKAGE(LZMA)
+IF(LZMA_FOUND)
+ SET(HAVE_LIBLZMA 1)
+ SET(HAVE_LZMA_H 1)
+ INCLUDE_DIRECTORIES(${LZMA_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${LZMA_LIBRARIES})
+ MARK_AS_ADVANCED(CLEAR LZMA_INCLUDE_DIR)
+ MARK_AS_ADVANCED(CLEAR LZMA_LIBRARY)
+ELSEIF(LZMADEC_FOUND)
+ SET(HAVE_LIBLZMADEC 1)
+ SET(HAVE_LZMADEC_H 1)
+ INCLUDE_DIRECTORIES(${LZMADEC_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${LZMADEC_LIBRARIES})
+ MARK_AS_ADVANCED(CLEAR LZMADEC_INCLUDE_DIR)
+ MARK_AS_ADVANCED(CLEAR LZMADEC_LIBRARY)
+ELSE(LZMA_FOUND)
+ MARK_AS_ADVANCED(CLEAR LZMA_INCLUDE_DIR)
+ MARK_AS_ADVANCED(CLEAR LZMA_LIBRARY)
+ENDIF(LZMA_FOUND)
+
+#
+# Check headers
+#
+CHECK_HEADER_DIRENT()
+
+SET(INCLUDES "")
+MACRO (LA_CHECK_INCLUDE_FILE header var)
+ CHECK_INCLUDE_FILES("${INCLUDES};${header}" ${var})
+ IF (${var})
+ SET(INCLUDES ${INCLUDES} ${header})
+ ENDIF (${var})
+ENDMACRO (LA_CHECK_INCLUDE_FILE)
+
+# Some FreeBSD headers assume sys/types.h was already included.
+LA_CHECK_INCLUDE_FILE("sys/types.h" HAVE_SYS_TYPES_H)
+
+# Alphabetize the rest unless there's a compelling reason
+LA_CHECK_INCLUDE_FILE("acl/libacl.h" HAVE_ACL_LIBACL_H)
+LA_CHECK_INCLUDE_FILE("ctype.h" HAVE_CTYPE_H)
+LA_CHECK_INCLUDE_FILE("direct.h" HAVE_DIRECT_H)
+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)
+LA_CHECK_INCLUDE_FILE("fcntl.h" HAVE_FCNTL_H)
+LA_CHECK_INCLUDE_FILE("grp.h" HAVE_GRP_H)
+LA_CHECK_INCLUDE_FILE("inttypes.h" HAVE_INTTYPES_H)
+LA_CHECK_INCLUDE_FILE("io.h" HAVE_IO_H)
+LA_CHECK_INCLUDE_FILE("langinfo.h" HAVE_LANGINFO_H)
+LA_CHECK_INCLUDE_FILE("limits.h" HAVE_LIMITS_H)
+LA_CHECK_INCLUDE_FILE("linux/fs.h" HAVE_LINUX_FS_H)
+LA_CHECK_INCLUDE_FILE("locale.h" HAVE_LOCALE_H)
+LA_CHECK_INCLUDE_FILE("memory.h" HAVE_MEMORY_H)
+LA_CHECK_INCLUDE_FILE("paths.h" HAVE_PATHS_H)
+LA_CHECK_INCLUDE_FILE("poll.h" HAVE_POLL_H)
+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("stdarg.h" HAVE_STDARG_H)
+LA_CHECK_INCLUDE_FILE("stdint.h" HAVE_STDINT_H)
+LA_CHECK_INCLUDE_FILE("stdlib.h" HAVE_STDLIB_H)
+LA_CHECK_INCLUDE_FILE("string.h" HAVE_STRING_H)
+LA_CHECK_INCLUDE_FILE("strings.h" HAVE_STRINGS_H)
+LA_CHECK_INCLUDE_FILE("sys/acl.h" HAVE_SYS_ACL_H)
+LA_CHECK_INCLUDE_FILE("sys/cdefs.h" HAVE_SYS_CDEFS_H)
+LA_CHECK_INCLUDE_FILE("sys/ioctl.h" HAVE_SYS_IOCTL_H)
+LA_CHECK_INCLUDE_FILE("sys/mkdev.h" HAVE_SYS_MKDEV_H)
+LA_CHECK_INCLUDE_FILE("sys/param.h" HAVE_SYS_PARAM_H)
+LA_CHECK_INCLUDE_FILE("sys/poll.h" HAVE_SYS_POLL_H)
+LA_CHECK_INCLUDE_FILE("sys/select.h" HAVE_SYS_SELECT_H)
+LA_CHECK_INCLUDE_FILE("sys/stat.h" HAVE_SYS_STAT_H)
+LA_CHECK_INCLUDE_FILE("sys/time.h" HAVE_SYS_TIME_H)
+LA_CHECK_INCLUDE_FILE("sys/utime.h" HAVE_SYS_UTIME_H)
+LA_CHECK_INCLUDE_FILE("sys/wait.h" HAVE_SYS_WAIT_H)
+LA_CHECK_INCLUDE_FILE("time.h" HAVE_TIME_H)
+LA_CHECK_INCLUDE_FILE("unistd.h" HAVE_UNISTD_H)
+LA_CHECK_INCLUDE_FILE("utime.h" HAVE_UTIME_H)
+LA_CHECK_INCLUDE_FILE("wchar.h" HAVE_WCHAR_H)
+LA_CHECK_INCLUDE_FILE("wctype.h" HAVE_WCTYPE_H)
+LA_CHECK_INCLUDE_FILE("windows.h" HAVE_WINDOWS_H)
+
+
+#
+# Some headers require extra includes when they're available.
+#
+
+#
+# Find OpenSSL
+#
+IF(ENABLE_OPENSSL)
+ FIND_PACKAGE(OpenSSL)
+ENDIF()
+
+# FreeBSD libmd
+CHECK_LIBRARY_EXISTS(md "MD5Init" "" LIBMD_FOUND)
+IF(LIBMD_FOUND)
+ SET(CMAKE_REQUIRED_LIBRARIES "md")
+ FIND_LIBRARY(LIBMD_LIBRARY NAMES md)
+ LIST(APPEND ADDITIONAL_LIBS ${LIBMD_LIBRARY})
+ENDIF(LIBMD_FOUND)
+
+#
+# How to prove that HASH functions, which have several names on various
+# platforms, can be mapped to archive_{hash name}_init,
+# archive_{hash name}_update and archive_{hash name}_final through
+# archive_hash.h
+#
+MACRO(CHECK_MD HASH IMPLEMENTATIONS)
+ IF(HAVE_SYS_TYPES_H)
+ SET(HASH_HEADER_CONFIG "#define HAVE_SYS_TYPES_H 1\n")
+ ELSE(HAVE_SYS_TYPES_H)
+ SET(HASH_HEADER_CONFIG "")
+ ENDIF(HAVE_SYS_TYPES_H)
+
+ FOREACH(IMPLEMENTATION ${IMPLEMENTATIONS})
+ IF(NOT DEFINED ARCHIVE_HASH_${HASH}_${IMPLEMENTATION})
+ STRING(TOLOWER "${HASH}" lower_hash)
+ STRING(TOUPPER "${HASH}" hash)
+
+ SET(HASH_REQUIRED_INCLUDES)
+ SET(TRY_HASH_REQUIRED_INCLUDES
+ "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_CURRENT_SOURCE_DIR}/libarchive")
+ SET(HASH_REQUIRED_LIBS)
+ SET(TRY_HASH_REQUIRED_LIBS)
+ IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND)
+ SET(HASH_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
+ SET(TRY_HASH_REQUIRED_INCLUDES
+ "${TRY_HASH_REQUIRED_INCLUDES};${OPENSSL_INCLUDE_DIR}")
+ SET(HASH_REQUIRED_LIBS ${OPENSSL_LIBRARIES})
+ SET(TRY_HASH_REQUIRED_LIBS
+ "-DLINK_LIBRARIES:STRING=${OPENSSL_LIBRARIES}")
+ ELSEIF("${IMPLEMENTATION}" MATCHES "^LIBMD$" AND LIBMD_FOUND)
+ SET(TRY_HASH_REQUIRED_LIBS
+ "-DLINK_LIBRARIES:STRING=${LIBMD_LIBRARY}")
+ ENDIF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND)
+
+ SET(SOURCE "#define ${hash}_COMPILE_TEST
+#define ARCHIVE_HASH_${hash}_${IMPLEMENTATION}
+#define __LIBARCHIVE_BUILD
+${HASH_HEADER_CONFIG}
+#include \"archive_hash.h\"
+
+int
+main(int argc, char **argv)
+{
+ archive_${lower_hash}_ctx ctx;
+
+ archive_${lower_hash}_init(&ctx);
+ archive_${lower_hash}_update(&ctx, *argv, argc);
+ archive_${lower_hash}_final(&ctx, *argv);
+ return 0;
+}
+")
+
+ FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_hash_md.c" "${SOURCE}")
+ MESSAGE(STATUS "Checking support for ARCHIVE_HASH_${HASH}_${IMPLEMENTATION}")
+
+ TRY_COMPILE(ARCHIVE_HASH_${HASH}_${IMPLEMENTATION}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_hash_md.c
+ CMAKE_FLAGS
+ "${TRY_HASH_REQUIRED_LIBS}"
+ "${TRY_HASH_REQUIRED_INCLUDES}"
+ OUTPUT_VARIABLE OUTPUT)
+
+ IF (ARCHIVE_HASH_${HASH}_${IMPLEMENTATION})
+ MESSAGE(STATUS "Checking support for ARCHIVE_HASH_${HASH}_${IMPLEMENTATION} -- found")
+ IF (HASH_REQUIRED_INCLUDES)
+ INCLUDE_DIRECTORIES(${HASH_REQUIRED_INCLUDES})
+ ENDIF (HASH_REQUIRED_INCLUDES)
+ IF (HASH_REQUIRED_LIBS)
+ LIST(APPEND ADDITIONAL_LIBS ${HASH_REQUIRED_LIBS})
+ LIST(REMOVE_DUPLICATES ADDITIONAL_LIBS)
+ ENDIF (HASH_REQUIRED_LIBS)
+ BREAK()
+ ENDIF (ARCHIVE_HASH_${HASH}_${IMPLEMENTATION})
+
+ MESSAGE(STATUS "Checking support for ARCHIVE_HASH_${HASH}_${IMPLEMENTATION} -- not found")
+ FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Checking support for ARCHIVE_HASH_${HASH}_${IMPLEMENTATION} failed with the following output:\n"
+ "${OUTPUT}\n"
+ "Source file was:\n${SOURCE}\n")
+ ELSE(NOT DEFINED ARCHIVE_HASH_${HASH}_${IMPLEMENTATION})
+ IF(ARCHIVE_HASH_${HASH}_${IMPLEMENTATION})
+ BREAK()
+ ENDIF(ARCHIVE_HASH_${HASH}_${IMPLEMENTATION})
+ ENDIF(NOT DEFINED ARCHIVE_HASH_${HASH}_${IMPLEMENTATION})
+ ENDFOREACH(IMPLEMENTATION)
+ENDMACRO(CHECK_MD HASH IMPLEMENTATIONS)
+
+#
+# HASH functions on Windows is defined at archive_windows.c, thus we do not
+# need the test what the functions can be mapped to archive_{hash name}_init,
+# archive_{hash name}_update and archive_{hash name}_final.
+# The functions on Windows use CALG_{hash name} macro to create a crypt object
+# and then we need to know what CALG_{hash name} macros is available to show
+# ARCHIVE_HASH_{hash name}_WIN macros because Windows 2000 and earlier version
+# of Windows XP do not support SHA256, SHA384 and SHA512.
+#
+MACRO(CHECK_HASH_WIN HASH_LIST)
+ IF(WIN32 AND NOT CYGWIN)
+ FOREACH(HASH ${HASH_LIST})
+ IF(NOT DEFINED ARCHIVE_HASH_${HASH}_WIN)
+ STRING(TOUPPER "${HASH}" hash)
+ SET(ALGID "")
+ IF ("${HASH}" MATCHES "^MD5$")
+ SET(ALGID "CALG_MD5")
+ ENDIF ("${HASH}" MATCHES "^MD5$")
+ IF ("${HASH}" MATCHES "^SHA1$")
+ SET(ALGID "CALG_SHA1")
+ ENDIF ("${HASH}" MATCHES "^SHA1$")
+ IF ("${HASH}" MATCHES "^SHA256$")
+ SET(ALGID "CALG_SHA_256")
+ ENDIF ("${HASH}" MATCHES "^SHA256$")
+ IF ("${HASH}" MATCHES "^SHA384$")
+ SET(ALGID "CALG_SHA_384")
+ ENDIF ("${HASH}" MATCHES "^SHA384$")
+ IF ("${HASH}" MATCHES "^SHA512$")
+ SET(ALGID "CALG_SHA_512")
+ ENDIF ("${HASH}" MATCHES "^SHA512$")
+
+ SET(SOURCE "#define ${hash}_COMPILE_TEST
+#define _WIN32_WINNT ${_WIN32_WINNT}
+#define WINVER ${WINVER}
+#include <windows.h>
+#include <wincrypt.h>
+
+int
+main(int argc, char **argv)
+{
+ return ${ALGID};
+}
+")
+ SET(SOURCE_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_hash_win.c")
+
+ FILE(WRITE "${SOURCE_FILE}" "${SOURCE}")
+ MESSAGE(STATUS "Checking support for ARCHIVE_HASH_${HASH}_WIN")
+
+ TRY_COMPILE(ARCHIVE_HASH_${HASH}_WIN
+ ${CMAKE_BINARY_DIR}
+ ${SOURCE_FILE}
+ CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_CURRENT_SOURCE_DIR}/libarchive"
+ OUTPUT_VARIABLE OUTPUT)
+
+ IF (ARCHIVE_HASH_${HASH}_WIN)
+ MESSAGE(STATUS
+ "Checking support for ARCHIVE_HASH_${HASH}_WIN -- found")
+ ELSE (ARCHIVE_HASH_${HASH}_WIN)
+ MESSAGE(STATUS
+ "Checking support for ARCHIVE_HASH_${HASH}_WIN -- not found")
+ FILE(APPEND
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Checking support for ARCHIVE_HASH_${HASH}_WIN failed with the following output:\n"
+ "${OUTPUT}\n"
+ "Source file was:\n${SOURCE}\n")
+ ENDIF (ARCHIVE_HASH_${HASH}_WIN)
+
+ ENDIF(NOT DEFINED ARCHIVE_HASH_${HASH}_WIN)
+ ENDFOREACH(HASH)
+ ENDIF(WIN32 AND NOT CYGWIN)
+ENDMACRO(CHECK_HASH_WIN HASH_LIST)
+
+#
+# Check MD5/RMD160/SHA support
+#
+CHECK_MD(MD5 "LIBC;LIBMD;LIBSYSTEM;OPENSSL")
+CHECK_MD(RMD160 "LIBC;OPENSSL")
+CHECK_MD(SHA1 "LIBC;LIBMD;LIBSYSTEM;OPENSSL")
+CHECK_MD(SHA256 "LIBC;LIBC2;LIBC3;LIBMD;LIBSYSTEM;OPENSSL")
+CHECK_MD(SHA384 "LIBC;LIBC2;LIBC3;LIBSYSTEM;OPENSSL")
+CHECK_MD(SHA512 "LIBC;LIBC2;LIBC3;LIBMD;LIBSYSTEM;OPENSSL")
+CHECK_HASH_WIN("MD5;SHA1;SHA256;SHA384;SHA512")
+
+#
+# Find Libxml2
+#
+FIND_PACKAGE(LibXml2)
+IF(LIBXML2_FOUND)
+ INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${LIBXML2_LIBRARIES})
+ SET(HAVE_LIBXML2 1)
+ # libxml2's include files use iconv.h
+ # We need a directory path of iconv.h so that it won't fail to check
+ # "libxml/xmlreader.h".
+ FIND_PATH(ICONV_INCLUDE_DIR iconv.h)
+ INCLUDE_DIRECTORIES(${ICONV_INCLUDE_DIR})
+ SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR})
+ CHECK_INCLUDE_FILES("libxml/xmlreader.h" HAVE_LIBXML_XMLREADER_H)
+ SET(CMAKE_REQUIRED_INCLUDES "")
+ELSE(LIBXML2_FOUND)
+ #
+ # Find Expat
+ #
+ FIND_PACKAGE(EXPAT)
+ IF(EXPAT_FOUND)
+ INCLUDE_DIRECTORIES(${EXPAT_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${EXPAT_LIBRARIES})
+ SET(HAVE_LIBEXPAT 1)
+ LA_CHECK_INCLUDE_FILE("expat.h" HAVE_EXPAT_H)
+ ENDIF(EXPAT_FOUND)
+ENDIF(LIBXML2_FOUND)
+
+#
+# Check functions
+#
+CHECK_SYMBOL_EXISTS(CreateHardLinkA "windows.h" HAVE_CREATEHARDLINKA)
+CHECK_SYMBOL_EXISTS(CreateHardLinkW "windows.h" HAVE_CREATEHARDLINKW)
+CHECK_SYMBOL_EXISTS(_CrtSetReportMode "crtdbg.h" HAVE__CrtSetReportMode)
+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(fchdir HAVE_FCHDIR)
+CHECK_FUNCTION_EXISTS_GLIBC(fchflags HAVE_FCHFLAGS)
+CHECK_FUNCTION_EXISTS_GLIBC(fchmod HAVE_FCHMOD)
+CHECK_FUNCTION_EXISTS_GLIBC(fchown HAVE_FCHOWN)
+CHECK_FUNCTION_EXISTS_GLIBC(fcntl HAVE_FCNTL)
+CHECK_FUNCTION_EXISTS_GLIBC(fork HAVE_FORK)
+CHECK_FUNCTION_EXISTS_GLIBC(fstat HAVE_FSTAT)
+CHECK_FUNCTION_EXISTS_GLIBC(ftruncate HAVE_FTRUNCATE)
+CHECK_FUNCTION_EXISTS_GLIBC(futimens HAVE_FUTIMENS)
+CHECK_FUNCTION_EXISTS_GLIBC(futimes HAVE_FUTIMES)
+CHECK_FUNCTION_EXISTS_GLIBC(geteuid HAVE_GETEUID)
+CHECK_FUNCTION_EXISTS_GLIBC(getgrgid_r HAVE_GETGRGID_R)
+CHECK_FUNCTION_EXISTS_GLIBC(getgrnam_r HAVE_GETGRNAM_R)
+CHECK_FUNCTION_EXISTS_GLIBC(getpwnam_r HAVE_GETPWNAM_R)
+CHECK_FUNCTION_EXISTS_GLIBC(getpwuid_r HAVE_GETPWUID_R)
+CHECK_FUNCTION_EXISTS_GLIBC(getpid HAVE_GETPID)
+CHECK_FUNCTION_EXISTS_GLIBC(lchflags HAVE_LCHFLAGS)
+CHECK_FUNCTION_EXISTS_GLIBC(lchmod HAVE_LCHMOD)
+CHECK_FUNCTION_EXISTS_GLIBC(lchown HAVE_LCHOWN)
+CHECK_FUNCTION_EXISTS_GLIBC(link HAVE_LINK)
+CHECK_FUNCTION_EXISTS_GLIBC(lstat HAVE_LSTAT)
+CHECK_FUNCTION_EXISTS_GLIBC(lutimes HAVE_LUTIMES)
+CHECK_FUNCTION_EXISTS_GLIBC(memmove HAVE_MEMMOVE)
+CHECK_FUNCTION_EXISTS_GLIBC(mkdir HAVE_MKDIR)
+CHECK_FUNCTION_EXISTS_GLIBC(mkfifo HAVE_MKFIFO)
+CHECK_FUNCTION_EXISTS_GLIBC(mknod HAVE_MKNOD)
+CHECK_FUNCTION_EXISTS_GLIBC(nl_langinfo HAVE_NL_LANGINFO)
+CHECK_FUNCTION_EXISTS_GLIBC(pipe HAVE_PIPE)
+CHECK_FUNCTION_EXISTS_GLIBC(poll HAVE_POLL)
+CHECK_FUNCTION_EXISTS_GLIBC(readlink HAVE_READLINK)
+CHECK_FUNCTION_EXISTS_GLIBC(select HAVE_SELECT)
+CHECK_FUNCTION_EXISTS_GLIBC(setenv HAVE_SETENV)
+CHECK_FUNCTION_EXISTS_GLIBC(setlocale HAVE_SETLOCALE)
+CHECK_FUNCTION_EXISTS_GLIBC(sigaction HAVE_SIGACTION)
+CHECK_FUNCTION_EXISTS_GLIBC(strchr HAVE_STRCHR)
+CHECK_FUNCTION_EXISTS_GLIBC(strdup HAVE_STRDUP)
+CHECK_FUNCTION_EXISTS_GLIBC(strerror HAVE_STRERROR)
+CHECK_FUNCTION_EXISTS_GLIBC(strncpy_s HAVE_STRNCPY_S)
+CHECK_FUNCTION_EXISTS_GLIBC(strrchr HAVE_STRRCHR)
+CHECK_FUNCTION_EXISTS_GLIBC(symlink HAVE_SYMLINK)
+CHECK_FUNCTION_EXISTS_GLIBC(timegm HAVE_TIMEGM)
+CHECK_FUNCTION_EXISTS_GLIBC(tzset HAVE_TZSET)
+CHECK_FUNCTION_EXISTS_GLIBC(unsetenv HAVE_UNSETENV)
+CHECK_FUNCTION_EXISTS_GLIBC(utime HAVE_UTIME)
+CHECK_FUNCTION_EXISTS_GLIBC(utimes HAVE_UTIMES)
+CHECK_FUNCTION_EXISTS_GLIBC(utimensat HAVE_UTIMENSAT)
+CHECK_FUNCTION_EXISTS_GLIBC(vfork HAVE_VFORK)
+CHECK_FUNCTION_EXISTS_GLIBC(wcrtomb HAVE_WCRTOMB)
+CHECK_FUNCTION_EXISTS_GLIBC(wcscmp HAVE_WCSCMP)
+CHECK_FUNCTION_EXISTS_GLIBC(wcscpy HAVE_WCSCPY)
+CHECK_FUNCTION_EXISTS_GLIBC(wcslen HAVE_WCSLEN)
+CHECK_FUNCTION_EXISTS_GLIBC(wctomb HAVE_WCTOMB)
+CHECK_SYMBOL_EXISTS(wmemcmp "wchar.h" HAVE_WMEMCMP)
+CHECK_SYMBOL_EXISTS(wmemcpy "wchar.h" HAVE_WMEMCPY)
+
+SET(CMAKE_REQUIRED_LIBRARIES "")
+CHECK_SYMBOL_EXISTS(fseeko "stdio.h" HAVE_FSEEKO)
+CHECK_SYMBOL_EXISTS(strerror_r "string.h" HAVE_STRERROR_R)
+CHECK_SYMBOL_EXISTS(strftime "time.h" HAVE_STRFTIME)
+CHECK_SYMBOL_EXISTS(vprintf "stdio.h" HAVE_VPRINTF)
+CHECK_SYMBOL_EXISTS(cygwin_conv_path "sys/cygwin.h" HAVE_CYGWIN_CONV_PATH)
+
+CHECK_SYMBOL_EXISTS(major "sys/mkdev.h" MAJOR_IN_MKDEV)
+CHECK_SYMBOL_EXISTS(major "sys/sysmacros.h" MAJOR_IN_SYSMACROS)
+
+IF(HAVE_STRERROR_R)
+ SET(HAVE_DECL_STRERROR_R 1)
+ENDIF(HAVE_STRERROR_R)
+
+#
+# Check defines
+#
+SET(headers "limits.h")
+IF(HAVE_STDINT_H)
+ LIST(APPEND headers "stdint.h")
+ENDIF(HAVE_STDINT_H)
+IF(HAVE_INTTYPES_H)
+ LIST(APPEND headers "inttypes.h")
+ENDIF(HAVE_INTTYPES_H)
+CHECK_SYMBOL_EXISTS(EFTYPE "errno.h" HAVE_EFTYPE)
+CHECK_SYMBOL_EXISTS(EILSEQ "errno.h" HAVE_EILSEQ)
+CHECK_SYMBOL_EXISTS(D_MD_ORDER "langinfo.h" HAVE_D_MD_ORDER)
+CHECK_SYMBOL_EXISTS(optarg "unistd.h" HAVE_DECL_OPTARG)
+CHECK_SYMBOL_EXISTS(optind "unistd.h" HAVE_DECL_OPTIND)
+CHECK_SYMBOL_EXISTS(INT64_MAX "${headers}" HAVE_DECL_INT64_MAX)
+CHECK_SYMBOL_EXISTS(INT64_MIN "${headers}" HAVE_DECL_INT64_MIN)
+CHECK_SYMBOL_EXISTS(UINT32_MAX "${headers}" HAVE_DECL_UINT32_MAX)
+CHECK_SYMBOL_EXISTS(UINT64_MAX "${headers}" HAVE_DECL_UINT64_MAX)
+CHECK_SYMBOL_EXISTS(SIZE_MAX "${headers}" HAVE_DECL_SIZE_MAX)
+CHECK_SYMBOL_EXISTS(SSIZE_MAX "limits.h" HAVE_DECL_SSIZE_MAX)
+
+#
+# Check struct members
+#
+# Check for birthtime in struct stat
+CHECK_STRUCT_MEMBER("struct stat" st_birthtime
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIME)
+
+# Check for high-resolution timestamps in struct stat
+CHECK_STRUCT_MEMBER("struct stat" st_birthtimespec.tv_nsec
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
+CHECK_STRUCT_MEMBER("struct stat" st_mtimespec.tv_nsec
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
+CHECK_STRUCT_MEMBER("struct stat" st_mtim.tv_nsec
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
+CHECK_STRUCT_MEMBER("struct stat" st_mtime_n
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_N)
+CHECK_STRUCT_MEMBER("struct stat" st_umtime
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_UMTIME)
+CHECK_STRUCT_MEMBER("struct stat" st_mtime_usec
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_USEC)
+# Check for block size support in struct stat
+CHECK_STRUCT_MEMBER("struct stat" st_blksize
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BLKSIZE)
+# Check for st_flags in struct stat (BSD fflags)
+CHECK_STRUCT_MEMBER("struct stat" st_flags
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_FLAGS)
+#
+#
+CHECK_STRUCT_MEMBER("struct tm" tm_sec
+ "sys/types.h;sys/time.h;time.h" TIME_WITH_SYS_TIME)
+
+#
+# Check for integer types
+#
+# XXX There must be a way to make this simpler <sigh> XXXX
+#
+CHECK_TYPE_SIZE("long long int" LONG_LONG_INT)
+CHECK_TYPE_SIZE("unsigned long long" UNSIGNED_LONG_LONG)
+CHECK_TYPE_SIZE("unsigned long long int" UNSIGNED_LONG_LONG_INT)
+
+#
+CHECK_TYPE_SIZE(dev_t DEV_T)
+IF(NOT HAVE_DEV_T)
+ IF(MSVC)
+ SET(dev_t "unsigned int")
+ ENDIF(MSVC)
+ENDIF(NOT HAVE_DEV_T)
+#
+CHECK_TYPE_SIZE(gid_t GID_T)
+IF(NOT HAVE_GID_T)
+ IF(WIN32)
+ SET(gid_t "short")
+ ELSE(WIN32)
+ SET(gid_t "unsigned int")
+ ENDIF(WIN32)
+ENDIF(NOT HAVE_GID_T)
+#
+CHECK_TYPE_SIZE(id_t ID_T)
+IF(NOT HAVE_ID_T)
+ IF(WIN32)
+ SET(id_t "short")
+ ELSE(WIN32)
+ SET(id_t "unsigned int")
+ ENDIF(WIN32)
+ENDIF(NOT HAVE_ID_T)
+#
+CHECK_TYPE_SIZE(int32_t INT32_T)
+IF(NOT HAVE_INT32_T)
+ SET(int32_t "int")
+ENDIF(NOT HAVE_INT32_T)
+#
+CHECK_TYPE_SIZE(int64_t INT64_T)
+IF(NOT HAVE_INT64_T)
+ IF(WIN32)
+ SET(int64_t __int64)
+ ENDIF(WIN32)
+ENDIF(NOT HAVE_INT64_T)
+#
+CHECK_TYPE_SIZE(intmax_t INTMAX_T)
+IF(NOT HAVE_INTMAX_T)
+ SET(intmax_t "int64_t")
+ENDIF(NOT HAVE_INTMAX_T)
+#
+CHECK_TYPE_SIZE(mode_t MODE_T)
+IF(NOT HAVE_MODE_T)
+ IF(WIN32)
+ SET(mode_t "unsigned short")
+ ELSE(WIN32)
+ SET(mode_t "int")
+ ENDIF(WIN32)
+ENDIF(NOT HAVE_MODE_T)
+#
+CHECK_TYPE_SIZE(off_t OFF_T)
+IF(NOT HAVE_OFF_T)
+ SET(off_t "__int64")
+ENDIF(NOT HAVE_OFF_T)
+#
+CHECK_TYPE_SIZE(size_t SIZE_T)
+IF(NOT HAVE_SIZE_T)
+ IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ SET(size_t "uint64_t")
+ ELSE("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ SET(size_t "uint32_t")
+ ENDIF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ENDIF(NOT HAVE_SIZE_T)
+#
+CHECK_TYPE_SIZE(ssize_t SSIZE_T)
+IF(NOT HAVE_SSIZE_T)
+ IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ SET(ssize_t "int64_t")
+ ELSE("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ SET(ssize_t "long")
+ ENDIF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ENDIF(NOT HAVE_SSIZE_T)
+#
+CHECK_TYPE_SIZE(uid_t UID_T)
+IF(NOT HAVE_UID_T)
+ IF(WIN32)
+ SET(uid_t "short")
+ ELSE(WIN32)
+ SET(uid_t "unsigned int")
+ ENDIF(WIN32)
+ENDIF(NOT HAVE_UID_T)
+#
+CHECK_TYPE_SIZE(pid_t PID_T)
+IF(NOT HAVE_PID_T)
+ IF(WIN32)
+ SET(pid_t "int")
+ ELSE(WIN32)
+ MESSAGE(FATAL_ERROR "pid_t doesn't exist on this platform?")
+ ENDIF(WIN32)
+ENDIF(NOT HAVE_PID_T)
+#
+CHECK_TYPE_SIZE(uint16_t UINT16_T)
+IF(NOT HAVE_UINT16_T)
+ SET(uint16_t "unsigned short")
+ENDIF(NOT HAVE_UINT16_T)
+#
+CHECK_TYPE_SIZE(uint32_t UINT32_T)
+IF(NOT HAVE_UINT32_T)
+ SET(uint32_t "unsigned int")
+ENDIF(NOT HAVE_UINT32_T)
+#
+CHECK_TYPE_SIZE(uint64_t UINT64_T)
+IF(NOT HAVE_UINT64_T)
+ IF(WIN32)
+ SET(uint64_t "unsigned __int64")
+ ENDIF(WIN32)
+ENDIF(NOT HAVE_UINT64_T)
+#
+CHECK_TYPE_SIZE(uintmax_t UINTMAX_T)
+IF(NOT HAVE_UINTMAX_T)
+ SET(uintmax_t "uint64_t")
+ENDIF(NOT HAVE_UINTMAX_T)
+#
+CHECK_TYPE_SIZE(intptr_t INTPTR_T)
+IF(NOT HAVE_INTPTR_T)
+ IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ SET(intptr_t "int64_t")
+ ELSE()
+ SET(intptr_t "int32_t")
+ ENDIF()
+ENDIF(NOT HAVE_INTPTR_T)
+#
+CHECK_TYPE_SIZE(uintptr_t UINTPTR_T)
+IF(NOT HAVE_UINTPTR_T)
+ IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ SET(uintptr_t "uint64_t")
+ ELSE()
+ SET(uintptr_t "uint32_t")
+ ENDIF()
+ENDIF(NOT HAVE_UINTPTR_T)
+#
+CHECK_TYPE_SIZE(wchar_t SIZEOF_WCHAR_T)
+IF(HAVE_SIZEOF_WCHAR_T)
+ SET(HAVE_WCHAR_T 1)
+ENDIF(HAVE_SIZEOF_WCHAR_T)
+#
+# Check if _FILE_OFFSET_BITS macro needed for large files
+#
+CHECK_FILE_OFFSET_BITS()
+
+
+
+#
+# Check for Extended Attribute libraries, headers, and functions
+#
+IF(ENABLE_XATTR)
+ LA_CHECK_INCLUDE_FILE(attr/xattr.h HAVE_ATTR_XATTR_H)
+ LA_CHECK_INCLUDE_FILE(sys/xattr.h HAVE_SYS_XATTR_H)
+ LA_CHECK_INCLUDE_FILE(sys/extattr.h HAVE_SYS_EXTATTR_H)
+ CHECK_LIBRARY_EXISTS(attr "setxattr" "" HAVE_ATTR_LIB)
+ IF(HAVE_ATTR_LIB)
+ SET(CMAKE_REQUIRED_LIBRARIES "attr")
+ ENDIF(HAVE_ATTR_LIB)
+ CHECK_SYMBOL_EXISTS(EXTATTR_NAMESPACE_USER "sys/types.h;sys/extattr.h" HAVE_DECL_EXTATTR_NAMESPACE_USER)
+ CHECK_FUNCTION_EXISTS_GLIBC(extattr_get_file HAVE_EXTATTR_GET_FILE)
+ CHECK_FUNCTION_EXISTS_GLIBC(extattr_list_file HAVE_EXTATTR_LIST_FILE)
+ CHECK_FUNCTION_EXISTS_GLIBC(extattr_set_fd HAVE_EXTATTR_SET_FD)
+ CHECK_FUNCTION_EXISTS_GLIBC(extattr_set_file HAVE_EXTATTR_SET_FILE)
+ CHECK_FUNCTION_EXISTS_GLIBC(fsetxattr HAVE_FSETXATTR)
+ CHECK_FUNCTION_EXISTS_GLIBC(getxattr HAVE_GETXATTR)
+ CHECK_FUNCTION_EXISTS_GLIBC(lgetxattr HAVE_LGETXATTR)
+ CHECK_FUNCTION_EXISTS_GLIBC(listxattr HAVE_LISTXATTR)
+ CHECK_FUNCTION_EXISTS_GLIBC(llistxattr HAVE_LLISTXATTR)
+ CHECK_FUNCTION_EXISTS_GLIBC(lsetxattr HAVE_LSETXATTR)
+ENDIF(ENABLE_XATTR)
+
+#
+# Check for ACL libraries, headers, and functions
+#
+# The ACL support in libarchive is written against the POSIX1e draft,
+# which was never officially approved and varies quite a bit across
+# platforms. Worse, some systems have completely non-POSIX acl functions,
+# which makes the following checks rather more complex than I would like.
+#
+IF(ENABLE_ACL)
+ CHECK_LIBRARY_EXISTS(acl "acl_get_file" "" HAVE_ACL_LIB)
+ IF(HAVE_ACL_LIB)
+ SET(CMAKE_REQUIRED_LIBRARIES "acl")
+ FIND_LIBRARY(ACL_LIBRARY NAMES acl)
+ LIST(APPEND ADDITIONAL_LIBS ${ACL_LIBRARY})
+ ENDIF(HAVE_ACL_LIB)
+ #
+ CHECK_FUNCTION_EXISTS_GLIBC(acl_create_entry HAVE_ACL_CREATE_ENTRY)
+ CHECK_FUNCTION_EXISTS_GLIBC(acl_init HAVE_ACL_INIT)
+ CHECK_FUNCTION_EXISTS_GLIBC(acl_set_fd HAVE_ACL_SET_FD)
+ CHECK_FUNCTION_EXISTS_GLIBC(acl_set_fd_np HAVE_ACL_SET_FD_NP)
+ CHECK_FUNCTION_EXISTS_GLIBC(acl_set_file HAVE_ACL_SET_FILE)
+ CHECK_TYPE_EXISTS(acl_permset_t "${INCLUDES}" HAVE_ACL_PERMSET_T)
+
+ # The "acl_get_perm()" function was omitted from the POSIX draft.
+ # (It's a pretty obvious oversight; otherwise, there's no way to
+ # test for specific permissions in a permset.) Linux uses the obvious
+ # name, FreeBSD adds _np to mark it as "non-Posix extension."
+ # Test for both as a double-check that we really have POSIX-style ACL support.
+ CHECK_SYMBOL_EXISTS(acl_get_perm "${INCLUDES}" HAVE_ACL_GET_PERM)
+ CHECK_SYMBOL_EXISTS(acl_get_perm_np "${INCLUDES}" HAVE_ACL_GET_PERM_NP)
+ CHECK_SYMBOL_EXISTS(acl_get_link "${INCLUDES}" HAVE_ACL_GET_LINK)
+ CHECK_SYMBOL_EXISTS(acl_get_link_np "${INCLUDES}" HAVE_ACL_GET_LINK_NP)
+
+ # MacOS has an acl.h that isn't POSIX. It can be detected by
+ # checking for ACL_USER
+ CHECK_SYMBOL_EXISTS(ACL_USER "${INCLUDES}" HAVE_ACL_USER)
+ENDIF(ENABLE_ACL)
+
+# Generate "config.h" from "build/cmake/config.h.in"
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in
+ ${CMAKE_CURRENT_BINARY_DIR}/config.h)
+INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
+ADD_DEFINITIONS(-DHAVE_CONFIG_H)
+
+#
+# Register installation of PDF documents.
+#
+IF(WIN32 AND NOT CYGWIN)
+ #
+ # On Windows platform, It's better that we install PDF documents
+ # on one's computer.
+ # These PDF documents are available in the release package.
+ #
+ IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doc/pdf)
+ INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/pdf
+ DESTINATION share/man
+ FILES_MATCHING PATTERN "*.pdf"
+ )
+ ENDIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doc/pdf)
+ENDIF(WIN32 AND NOT CYGWIN)
+#
+#
+#
+INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/libarchive)
+#
+IF(MSVC)
+ ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
+ENDIF(MSVC)
+# Especially for early development, we want to be a little
+# aggressive about diagnosing build problems; this can get
+# relaxed somewhat in final shipping versions.
+IF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$")
+ ADD_DEFINITIONS(-Wall -Werror)
+ENDIF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$")
+
+IF(ENABLE_TEST)
+ADD_CUSTOM_TARGET(run_all_tests)
+ENDIF(ENABLE_TEST)
+
+add_subdirectory(libarchive)
+add_subdirectory(tar)
+add_subdirectory(cpio)
diff --git a/COPYING b/COPYING
new file mode 100644
index 000000000000..9dbf49dbf21c
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,60 @@
+The libarchive distribution as a whole is Copyright by Tim Kientzle
+and is subject to the copyright notice reproduced at the bottom of
+this file.
+
+Each individual file in this distribution should have a clear
+copyright/licensing statement at the beginning of the file. If any do
+not, please let me know and I will rectify it. The following is
+intended to summarize the copyright status of the individual files;
+the actual statements in the files are controlling.
+
+* Except as listed below, all C sources (including .c and .h files)
+ and documentation files are subject to the copyright notice reproduced
+ at the bottom of this file.
+
+* The following source files are also subject in whole or in part to
+ a 3-clause UC Regents copyright; please read the individual source
+ files for details:
+ libarchive/archive_entry.c
+ libarchive/archive_read_support_compression_compress.c
+ libarchive/archive_write_set_compression_compress.c
+ libarchive/mtree.5
+ tar/matching.c
+
+* The following source files are in the public domain:
+ tar/getdate.c
+
+* The build files---including Makefiles, configure scripts,
+ and auxiliary scripts used as part of the compile process---have
+ widely varying licensing terms. Please check individual files before
+ distributing them to see if those restrictions apply to you.
+
+I intend for all new source code to use the license below and hope over
+time to replace code with other licenses with new implementations that
+do use the license below. The varying licensing of the build scripts
+seems to be an unavoidable mess.
+
+
+Copyright (c) 2003-2009 <author(s)>
+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
+ in this position and unchanged.
+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.
diff --git a/CTestConfig.cmake b/CTestConfig.cmake
new file mode 100644
index 000000000000..7a09742db098
--- /dev/null
+++ b/CTestConfig.cmake
@@ -0,0 +1,11 @@
+# TODO: This file should be moved into the build/cmake directory...
+
+# The libarchive CDash page appears at
+# http://my.cdash.org/index.php?project=libarchive
+set(CTEST_PROJECT_NAME "libarchive")
+set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
+
+set(CTEST_DROP_METHOD "http")
+set(CTEST_DROP_SITE "my.cdash.org")
+set(CTEST_DROP_LOCATION "/submit.php?project=libarchive")
+set(CTEST_DROP_SITE_CDASH TRUE)
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 000000000000..d91cc0691f43
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,30 @@
+More complete build documentation is available on the libarchive
+Wiki: http://libarchive.googlecode.com/
+
+On most Unix-like systems, you should be able to install libarchive,
+bsdtar, and bsdcpio using the following common steps:
+ ./configure
+ make
+ make install
+
+If you need to customize the target directories or otherwise adjust
+the build setting, use
+ ./configure --help
+to list the configure options.
+
+If you are developing libarchive and need to update the
+configure script and other build files:
+ /bin/sh build/autogen.sh
+
+To create a distribution, please use the 'distcheck' target:
+ /bin/sh build/autogen.sh && ./configure && make distcheck
+
+On non-Unix-like systems, use the "cmake" utility (available from
+http://cmake.org/) to generate suitable build files for your platform.
+Cmake requires the name of the directory containing CmakeLists.txt and
+the "generator" to use for your build environment. For example, to
+build with Xcode on Mac OS, you can use the following command:
+ cmake -G "Xcode" ~/libarchive-download-dir/
+The result will be appropriate makefiles, solution files, or project
+files that can be used with the corresponding development tool.
+See the libarchive Wiki or the cmake site for further documentation. \ No newline at end of file
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 000000000000..100ce9f34665
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,630 @@
+## Process this file with automake to produce Makefile.in
+
+AUTOMAKE_OPTIONS= foreign subdir-objects
+ACLOCAL_AMFLAGS = -I build/autoconf
+
+#
+# What to build and install
+#
+lib_LTLIBRARIES= libarchive.la
+noinst_LTLIBRARIES= libarchive_fe.la
+bin_PROGRAMS= $(bsdtar_programs) $(bsdcpio_programs)
+man_MANS= $(libarchive_man_MANS) $(bsdtar_man_MANS) $(bsdcpio_man_MANS)
+BUILT_SOURCES= libarchive/test/list.h tar/test/list.h cpio/test/list.h
+
+#
+# What to test: We always test libarchive, test bsdtar and bsdcpio only
+# if we built them.
+#
+check_PROGRAMS= libarchive_test $(bsdtar_test_programs) $(bsdcpio_test_programs)
+TESTS= libarchive_test $(bsdtar_test_programs) $(bsdcpio_test_programs)
+TESTS_ENVIRONMENT= $(libarchive_TESTS_ENVIRONMENT) $(bsdtar_TESTS_ENVIRONMENT) $(bsdcpio_TESTS_ENVIRONMENT)
+# Always build and test both bsdtar and bsdcpio as part of 'distcheck'
+DISTCHECK_CONFIGURE_FLAGS = --enable-bsdtar --enable-bsdcpio
+# Uncommenting this line can help diagnose some errors. This is ordinarily
+# enabled in the libarchive development branch but is disabled
+# for libarchive production releases.
+#AM_CFLAGS=-Wall -Werror
+PLATFORMCPPFLAGS = @PLATFORMCPPFLAGS@
+AM_CPPFLAGS=$(PLATFORMCPPFLAGS)
+
+#
+# What to include in the distribution
+#
+EXTRA_DIST= \
+ CMakeLists.txt \
+ build/autogen.sh \
+ build/bump-version.sh \
+ build/clean.sh \
+ build/cmake \
+ build/version \
+ contrib \
+ doc \
+ examples \
+ $(libarchive_EXTRA_DIST) \
+ $(libarchive_test_EXTRA_DIST) \
+ $(bsdtar_EXTRA_DIST) \
+ $(bsdtar_test_EXTRA_DIST) \
+ $(bsdcpio_EXTRA_DIST) \
+ $(bsdcpio_test_EXTRA_DIST)
+
+# a) Clean out some unneeded files and directories
+# b) Collect all documentation and format it for distribution.
+dist-hook:
+ rm -rf `find $(distdir) -name CVS -type d`
+ rm -rf `find $(distdir) -name .svn -type d`
+ rm -f `find $(distdir) -name '*~'`
+ rm -f `find $(distdir) -name '*.out'`
+ rm -f `find $(distdir) -name '*.core'`
+ -rm -f $(distdir)/*/Makefile $(distdir)/*/*/Makefile
+ cd $(distdir)/doc && /bin/sh update.sh
+
+# Verify cmake builds as part of the acceptance
+distcheck-hook:
+ mkdir $(distdir)/_build/cmtest
+ cd $(distdir)/_build/cmtest && cmake ../.. && make && make test
+ rm -rf $(distdir)/_build/cmtest
+
+#
+# Extra rules for cleanup
+#
+DISTCLEANFILES= \
+ libarchive/test/list.h \
+ tar/test/list.h \
+ cpio/test/list.h
+
+distclean-local:
+ -rm -rf .ref
+ -rm -rf autom4te.cache/
+ -rm -f *~
+ -[ -f libarchive/Makefile ] && cd libarchive && make clean
+ -[ -f libarchive/test/Makefile ] && cd libarchive/test && make clean
+ -[ -f tar/Makefile ] && cd tar && make clean
+ -[ -f tar/test/Makefile ] && cd tar/test && make clean
+ -[ -f cpio/Makefile ] && cd cpio && make clean
+ -[ -f cpio/test/Makefile ] && cd cpio/test && make clean
+
+#
+# Libarchive headers, source, etc.
+#
+#
+
+include_HEADERS= libarchive/archive.h libarchive/archive_entry.h
+
+libarchive_la_SOURCES= \
+ libarchive/archive_check_magic.c \
+ libarchive/archive_crc32.h \
+ libarchive/archive_endian.h \
+ libarchive/archive_entry.c \
+ libarchive/archive_entry.h \
+ libarchive/archive_entry_copy_stat.c \
+ libarchive/archive_entry_link_resolver.c \
+ libarchive/archive_entry_private.h \
+ libarchive/archive_entry_stat.c \
+ libarchive/archive_entry_strmode.c \
+ libarchive/archive_entry_xattr.c \
+ libarchive/archive_hash.h \
+ libarchive/archive_platform.h \
+ libarchive/archive_private.h \
+ libarchive/archive_read.c \
+ libarchive/archive_read_data_into_fd.c \
+ libarchive/archive_read_disk.c \
+ libarchive/archive_read_disk_entry_from_file.c \
+ libarchive/archive_read_disk_private.h \
+ libarchive/archive_read_disk_set_standard_lookup.c \
+ libarchive/archive_read_extract.c \
+ libarchive/archive_read_open_fd.c \
+ libarchive/archive_read_open_file.c \
+ libarchive/archive_read_open_filename.c \
+ libarchive/archive_read_open_memory.c \
+ libarchive/archive_read_private.h \
+ libarchive/archive_read_support_compression_all.c \
+ libarchive/archive_read_support_compression_bzip2.c \
+ libarchive/archive_read_support_compression_compress.c \
+ libarchive/archive_read_support_compression_gzip.c \
+ libarchive/archive_read_support_compression_none.c \
+ libarchive/archive_read_support_compression_program.c \
+ libarchive/archive_read_support_compression_rpm.c \
+ libarchive/archive_read_support_compression_uu.c \
+ libarchive/archive_read_support_compression_xz.c \
+ libarchive/archive_read_support_format_all.c \
+ libarchive/archive_read_support_format_ar.c \
+ libarchive/archive_read_support_format_cpio.c \
+ libarchive/archive_read_support_format_empty.c \
+ libarchive/archive_read_support_format_iso9660.c \
+ libarchive/archive_read_support_format_mtree.c \
+ libarchive/archive_read_support_format_raw.c \
+ libarchive/archive_read_support_format_tar.c \
+ libarchive/archive_read_support_format_xar.c \
+ libarchive/archive_read_support_format_zip.c \
+ libarchive/archive_string.c \
+ libarchive/archive_string.h \
+ libarchive/archive_string_sprintf.c \
+ libarchive/archive_util.c \
+ libarchive/archive_virtual.c \
+ libarchive/archive_write.c \
+ libarchive/archive_write_disk.c \
+ libarchive/archive_write_disk_private.h \
+ libarchive/archive_write_disk_set_standard_lookup.c \
+ libarchive/archive_write_open_fd.c \
+ libarchive/archive_write_open_file.c \
+ libarchive/archive_write_open_filename.c \
+ libarchive/archive_write_open_memory.c \
+ libarchive/archive_write_private.h \
+ libarchive/archive_write_set_compression_bzip2.c \
+ libarchive/archive_write_set_compression_compress.c \
+ libarchive/archive_write_set_compression_gzip.c \
+ libarchive/archive_write_set_compression_none.c \
+ libarchive/archive_write_set_compression_program.c \
+ libarchive/archive_write_set_compression_xz.c \
+ libarchive/archive_write_set_format.c \
+ libarchive/archive_write_set_format_ar.c \
+ libarchive/archive_write_set_format_by_name.c \
+ libarchive/archive_write_set_format_cpio.c \
+ libarchive/archive_write_set_format_cpio_newc.c \
+ libarchive/archive_write_set_format_mtree.c \
+ 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_zip.c \
+ libarchive/config_freebsd.h \
+ libarchive/filter_fork.c \
+ libarchive/filter_fork.h
+
+if INC_WINDOWS_FILES
+libarchive_la_SOURCES+= \
+ libarchive/archive_entry_copy_bhfi.c \
+ libarchive/archive_windows.h \
+ libarchive/archive_windows.c \
+ libarchive/filter_fork_windows.c
+endif
+
+# -no-undefined marks that libarchive doesn't rely on symbols
+# defined in the application. This is mandatory for cygwin.
+libarchive_la_LDFLAGS= -no-undefined -version-info $(ARCHIVE_LIBTOOL_VERSION)
+
+# Manpages to install
+libarchive_man_MANS= \
+ libarchive/archive_entry.3 \
+ libarchive/archive_read.3 \
+ libarchive/archive_read_disk.3 \
+ libarchive/archive_util.3 \
+ libarchive/archive_write.3 \
+ libarchive/archive_write_disk.3 \
+ libarchive/cpio.5 \
+ libarchive/libarchive.3 \
+ libarchive/libarchive_internals.3 \
+ libarchive/libarchive-formats.5 \
+ libarchive/mtree.5 \
+ libarchive/tar.5
+
+# Additional libarchive files to include in the distribution
+libarchive_EXTRA_DIST= \
+ libarchive/test/list.h \
+ libarchive/archive_windows.c \
+ libarchive/archive_windows.h \
+ libarchive/filter_fork_windows.c \
+ libarchive/CMakeLists.txt \
+ $(libarchive_man_MANS)
+
+# pkgconfig
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = build/pkgconfig/libarchive.pc
+
+#
+#
+# libarchive_test program
+#
+#
+libarchive_test_SOURCES= \
+ $(libarchive_la_SOURCES) \
+ libarchive/test/main.c \
+ libarchive/test/read_open_memory.c \
+ libarchive/test/test.h \
+ libarchive/test/test_acl_basic.c \
+ libarchive/test/test_acl_freebsd.c \
+ libarchive/test/test_acl_pax.c \
+ libarchive/test/test_archive_api_feature.c \
+ libarchive/test/test_bad_fd.c \
+ libarchive/test/test_compat_bzip2.c \
+ libarchive/test/test_compat_cpio.c \
+ libarchive/test/test_compat_gtar.c \
+ libarchive/test/test_compat_gzip.c \
+ libarchive/test/test_compat_lzma.c \
+ libarchive/test/test_compat_solaris_tar_acl.c \
+ libarchive/test/test_compat_tar_hardlink.c \
+ libarchive/test/test_compat_xz.c \
+ libarchive/test/test_compat_zip.c \
+ libarchive/test/test_empty_write.c \
+ libarchive/test/test_entry.c \
+ libarchive/test/test_extattr_freebsd.c \
+ libarchive/test/test_fuzz.c \
+ libarchive/test/test_entry_strmode.c \
+ libarchive/test/test_link_resolver.c \
+ libarchive/test/test_open_failure.c \
+ libarchive/test/test_open_fd.c \
+ 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_entry_from_file.c \
+ libarchive/test/test_read_extract.c \
+ libarchive/test/test_read_file_nonexistent.c \
+ libarchive/test/test_read_format_ar.c \
+ libarchive/test/test_read_format_cpio_bin.c \
+ libarchive/test/test_read_format_cpio_bin_Z.c \
+ libarchive/test/test_read_format_cpio_bin_be.c \
+ libarchive/test/test_read_format_cpio_bin_bz2.c \
+ libarchive/test/test_read_format_cpio_bin_gz.c \
+ libarchive/test/test_read_format_cpio_bin_lzma.c \
+ libarchive/test/test_read_format_cpio_bin_xz.c \
+ libarchive/test/test_read_format_cpio_odc.c \
+ libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c \
+ libarchive/test/test_read_format_cpio_svr4_gzip.c \
+ libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c \
+ libarchive/test/test_read_format_cpio_svr4c_Z.c \
+ libarchive/test/test_read_format_empty.c \
+ libarchive/test/test_read_format_gtar_gz.c \
+ libarchive/test/test_read_format_gtar_lzma.c \
+ libarchive/test/test_read_format_gtar_sparse.c \
+ libarchive/test/test_read_format_iso_Z.c \
+ libarchive/test/test_read_format_iso_multi_extent.c \
+ libarchive/test/test_read_format_isojoliet_bz2.c \
+ libarchive/test/test_read_format_isojoliet_long.c \
+ libarchive/test/test_read_format_isojoliet_rr.c \
+ libarchive/test/test_read_format_isorr_bz2.c \
+ libarchive/test/test_read_format_isorr_ce.c \
+ libarchive/test/test_read_format_isorr_new_bz2.c \
+ libarchive/test/test_read_format_isorr_rr_moved.c \
+ libarchive/test/test_read_format_isozisofs_bz2.c \
+ libarchive/test/test_read_format_mtree.c \
+ libarchive/test/test_read_format_pax_bz2.c \
+ libarchive/test/test_read_format_raw.c \
+ libarchive/test/test_read_format_tar.c \
+ libarchive/test/test_read_format_tar_empty_filename.c \
+ libarchive/test/test_read_format_tbz.c \
+ libarchive/test/test_read_format_tgz.c \
+ libarchive/test/test_read_format_tlz.c \
+ libarchive/test/test_read_format_txz.c \
+ libarchive/test/test_read_format_tz.c \
+ libarchive/test/test_read_format_xar.c \
+ libarchive/test/test_read_format_zip.c \
+ libarchive/test/test_read_large.c \
+ libarchive/test/test_read_pax_truncated.c \
+ libarchive/test/test_read_position.c \
+ libarchive/test/test_read_truncated.c \
+ libarchive/test/test_read_uu.c \
+ libarchive/test/test_tar_filenames.c \
+ libarchive/test/test_tar_large.c \
+ libarchive/test/test_ustar_filenames.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_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_failures.c \
+ libarchive/test/test_write_disk_hardlink.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_format_ar.c \
+ libarchive/test/test_write_format_cpio.c \
+ libarchive/test/test_write_format_cpio_empty.c \
+ libarchive/test/test_write_format_cpio_odc.c \
+ libarchive/test/test_write_format_cpio_newc.c \
+ libarchive/test/test_write_format_mtree.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_ustar.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_CPPFLAGS= -I$(top_srcdir)/libarchive -I$(top_builddir)/libarchive/test -DLIBARCHIVE_STATIC $(PLATFORMCPPFLAGS)
+
+# The "list.h" file just lists all of the tests defined in all of the sources.
+# Building it automatically provides a sanity-check on libarchive_test_SOURCES
+# above.
+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_test_EXTRA_DIST=\
+ libarchive/test/test_compat_bzip2_1.tbz.uu \
+ libarchive/test/test_compat_bzip2_2.tbz.uu \
+ libarchive/test/test_compat_cpio_1.cpio.uu \
+ libarchive/test/test_compat_gtar_1.tar.uu \
+ libarchive/test/test_compat_gzip_1.tgz.uu \
+ libarchive/test/test_compat_gzip_2.tgz.uu \
+ 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_solaris_tar_acl.tar.uu \
+ libarchive/test/test_compat_tar_hardlink_1.tar.uu \
+ libarchive/test/test_compat_xz_1.txz.uu \
+ libarchive/test/test_compat_zip_1.zip.uu \
+ libarchive/test/test_fuzz_1.iso.Z.uu \
+ libarchive/test/test_pax_filename_encoding.tar.uu \
+ libarchive/test/test_read_format_ar.ar.uu \
+ libarchive/test/test_read_format_cpio_bin_be.cpio.uu \
+ libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.rpm.uu \
+ libarchive/test/test_read_format_cpio_svr4_gzip_rpm.rpm.uu \
+ libarchive/test/test_read_format_gtar_sparse_1_13.tar.uu \
+ libarchive/test/test_read_format_gtar_sparse_1_17.tar.uu \
+ libarchive/test/test_read_format_gtar_sparse_1_17_posix00.tar.uu \
+ libarchive/test/test_read_format_gtar_sparse_1_17_posix01.tar.uu \
+ libarchive/test/test_read_format_gtar_sparse_1_17_posix10.tar.uu \
+ libarchive/test/test_read_format_gtar_sparse_1_17_posix10_modified.tar.uu \
+ libarchive/test/test_read_format_iso.iso.Z.uu \
+ libarchive/test/test_read_format_iso_2.iso.Z.uu \
+ libarchive/test/test_read_format_iso_joliet.iso.Z.uu \
+ libarchive/test/test_read_format_iso_joliet_long.iso.Z.uu \
+ libarchive/test/test_read_format_iso_joliet_rockridge.iso.Z.uu \
+ libarchive/test/test_read_format_iso_multi_extent.iso.Z.uu \
+ libarchive/test/test_read_format_iso_rockridge.iso.Z.uu \
+ libarchive/test/test_read_format_iso_rockridge_ce.iso.Z.uu \
+ libarchive/test/test_read_format_iso_rockridge_new.iso.Z.uu \
+ libarchive/test/test_read_format_iso_rockridge_rr_moved.iso.Z.uu\
+ libarchive/test/test_read_format_iso_zisofs.iso.Z.uu \
+ libarchive/test/test_read_format_mtree.mtree.uu \
+ libarchive/test/test_read_format_raw.data.Z.uu \
+ libarchive/test/test_read_format_raw.data.uu \
+ libarchive/test/test_read_format_tar_empty_filename.tar.uu \
+ libarchive/test/test_read_format_zip.zip.uu \
+ libarchive/test/CMakeLists.txt \
+ libarchive/test/README
+
+#
+# Common code for libarchive frontends (cpio, tar)
+#
+libarchive_fe_la_SOURCES= \
+ libarchive_fe/err.c \
+ libarchive_fe/err.h \
+ libarchive_fe/lafe_platform.h \
+ libarchive_fe/line_reader.c \
+ libarchive_fe/line_reader.h \
+ libarchive_fe/matching.c \
+ libarchive_fe/matching.h \
+ libarchive_fe/pathmatch.c \
+ libarchive_fe/pathmatch.h
+
+#
+#
+# bsdtar source, docs, etc.
+#
+#
+
+bsdtar_SOURCES= \
+ tar/bsdtar.c \
+ tar/bsdtar.h \
+ tar/bsdtar_platform.h \
+ tar/cmdline.c \
+ tar/getdate.c \
+ tar/read.c \
+ tar/subst.c \
+ tar/tree.c \
+ tar/tree.h \
+ tar/util.c \
+ tar/write.c
+
+if INC_WINDOWS_FILES
+bsdtar_SOURCES+= \
+ tar/bsdtar_windows.h \
+ tar/bsdtar_windows.c
+endif
+
+bsdtar_DEPENDENCIES= libarchive.la libarchive_fe.la
+
+if STATIC_BSDTAR
+bsdtar_ldstatic= -static
+bsdtar_ccstatic= -DLIBARCHIVE_STATIC
+else
+bsdtar_ldstatic=
+bsdtar_ccstatic=
+endif
+
+bsdtar_LDADD= libarchive.la libarchive_fe.la
+bsdtar_CPPFLAGS= -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe $(bsdtar_ccstatic) $(PLATFORMCPPFLAGS)
+bsdtar_LDFLAGS= $(bsdtar_ldstatic)
+
+bsdtar_EXTRA_DIST= \
+ tar/bsdtar.1 \
+ tar/bsdtar_windows.h \
+ tar/bsdtar_windows.c \
+ tar/CMakeLists.txt \
+ tar/config_freebsd.h \
+ tar/test/list.h
+
+
+if BUILD_BSDTAR
+bsdtar_man_MANS= tar/bsdtar.1
+bsdtar_programs= bsdtar
+else
+bsdtar_man_MANS=
+bsdtar_programs=
+endif
+
+#
+# bsdtar_test
+#
+
+bsdtar_test_SOURCES= \
+ tar/getdate.c \
+ 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_getdate.c \
+ tar/test/test_help.c \
+ tar/test/test_option_T_upper.c \
+ tar/test/test_option_q.c \
+ tar/test/test_option_r.c \
+ tar/test/test_option_s.c \
+ tar/test/test_patterns.c \
+ tar/test/test_stdio.c \
+ tar/test/test_strip_components.c \
+ tar/test/test_symlink_dir.c \
+ tar/test/test_version.c \
+ tar/test/test_windows.c
+
+# For now, bsdtar_test uses Windows shims from tar/bsdtar_windows.*
+if INC_WINDOWS_FILES
+bsdtar_test_SOURCES+= \
+ tar/bsdtar_windows.h \
+ tar/bsdtar_windows.c
+endif
+
+bsdtar_test_CPPFLAGS=\
+ -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe \
+ -I$(top_srcdir)/tar -I$(top_builddir)/tar/test \
+ $(PLATFORMCPPFLAGS)
+
+tar/test/list.h: Makefile
+ cat $(top_srcdir)/tar/test/test_*.c | grep DEFINE_TEST > tar/test/list.h
+
+if BUILD_BSDTAR
+bsdtar_test_programs= bsdtar_test
+bsdtar_TESTS_ENVIRONMENT= BSDTAR=`cd $(top_builddir);/bin/pwd`/bsdtar$(EXEEXT) BSDTAR_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/tar/test
+else
+bsdtar_test_programs=
+bsdtar_TESTS_ENVIRONMENT=
+endif
+
+bsdtar_test_EXTRA_DIST= \
+ tar/test/test_patterns_2.tar.uu \
+ tar/test/test_patterns_3.tar.uu \
+ tar/test/test_patterns_4.tar.uu \
+ tar/test/CMakeLists.txt
+
+
+#
+#
+# bsdcpio source, docs, etc.
+#
+#
+
+bsdcpio_SOURCES= \
+ cpio/cmdline.c \
+ cpio/cpio.c \
+ cpio/cpio.h \
+ cpio/cpio_platform.h
+
+if INC_WINDOWS_FILES
+bsdcpio_SOURCES+= \
+ cpio/cpio_windows.h \
+ cpio/cpio_windows.c
+endif
+
+bsdcpio_DEPENDENCIES = libarchive.la libarchive_fe.la
+
+
+if STATIC_BSDCPIO
+bsdcpio_ldstatic= -static
+bsdcpio_ccstatic= -DLIBARCHIVE_STATIC
+else
+bsdcpio_ldstatic=
+bsdcpio_ccstatic=
+endif
+
+bsdcpio_LDADD= libarchive_fe.la libarchive.la
+bsdcpio_CPPFLAGS= -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe $(bsdcpio_ccstatic) $(PLATFORMCPPFLAGS)
+bsdcpio_LDFLAGS= $(bsdcpio_ldstatic)
+
+bsdcpio_EXTRA_DIST= \
+ cpio/test/list.h \
+ cpio/bsdcpio.1 \
+ cpio/cpio_windows.h \
+ cpio/cpio_windows.c \
+ cpio/CMakeLists.txt \
+ cpio/config_freebsd.h
+
+
+if BUILD_BSDCPIO
+# Manpages to install
+bsdcpio_man_MANS= cpio/bsdcpio.1
+bsdcpio_programs= bsdcpio
+else
+bsdcpio_man_MANS=
+bsdcpio_programs=
+endif
+
+#
+# bsdcpio_test
+#
+
+bsdcpio_test_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_format_newc.c \
+ cpio/test/test_gcpio_compat.c \
+ cpio/test/test_option_B_upper.c \
+ cpio/test/test_option_C_upper.c \
+ cpio/test/test_option_J_upper.c \
+ cpio/test/test_option_L_upper.c \
+ cpio/test/test_option_Z_upper.c \
+ cpio/test/test_option_a.c \
+ cpio/test/test_option_c.c \
+ cpio/test/test_option_d.c \
+ cpio/test/test_option_f.c \
+ cpio/test/test_option_help.c \
+ cpio/test/test_option_l.c \
+ cpio/test/test_option_lzma.c \
+ cpio/test/test_option_m.c \
+ cpio/test/test_option_t.c \
+ cpio/test/test_option_u.c \
+ cpio/test/test_option_version.c \
+ cpio/test/test_option_y.c \
+ cpio/test/test_option_z.c \
+ cpio/test/test_owner_parse.c \
+ cpio/test/test_passthrough_dotdot.c \
+ cpio/test/test_passthrough_reverse.c \
+ cpio/test/test_pathmatch.c
+
+bsdcpio_test_CPPFLAGS= \
+ -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe \
+ -I$(top_srcdir)/cpio -I$(top_builddir)/cpio/test \
+ $(PLATFORMCPPFLAGS)
+bsdcpio_test_LDADD=libarchive_fe.la
+
+cpio/test/list.h: Makefile
+ cat $(top_srcdir)/cpio/test/test_*.c | grep DEFINE_TEST > cpio/test/list.h
+
+if BUILD_BSDCPIO
+bsdcpio_test_programs= bsdcpio_test
+bsdcpio_TESTS_ENVIRONMENT= BSDCPIO=`cd $(top_builddir);/bin/pwd`/bsdcpio$(EXEEXT) BSDCPIO_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/cpio/test
+else
+bsdcpio_test_programs=
+bsdcpio_TESTS_ENVIRONMENT=
+endif
+
+bsdcpio_test_EXTRA_DIST= \
+ cpio/test/test_gcpio_compat_ref.bin.uu \
+ cpio/test/test_gcpio_compat_ref.crc.uu \
+ cpio/test/test_gcpio_compat_ref.newc.uu \
+ cpio/test/test_gcpio_compat_ref.ustar.uu \
+ cpio/test/test_gcpio_compat_ref_nosym.bin.uu \
+ cpio/test/test_gcpio_compat_ref_nosym.crc.uu \
+ cpio/test/test_gcpio_compat_ref_nosym.newc.uu \
+ cpio/test/test_gcpio_compat_ref_nosym.ustar.uu \
+ cpio/test/test_option_f.cpio.uu \
+ cpio/test/test_option_m.cpio.uu \
+ cpio/test/test_option_t.cpio.uu \
+ cpio/test/test_option_t.stdout.uu \
+ cpio/test/test_option_tv.stdout.uu \
+ cpio/test/CMakeLists.txt
diff --git a/NEWS b/NEWS
new file mode 100644
index 000000000000..4a25fe37d99b
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,550 @@
+Feb 05, 2011: Fix issue 134: Improve handling of open failures
+Dec 06, 2010: Fix issue 119: Relax ISO verification
+Dec 06, 2010: Fix issue 121: mtree parsing
+Dec 05, 2010: Fix extraction of GNU tar 'D' directory entries
+Dec 05, 2010: Be less demanding in LZMA/XZ compression tests
+Jun 30, 2010: libarchive 2.8.4 released
+Jun 30, 2010: Improved reliability of hash function detection
+Jun 30, 2010: Fix issues on ancient FreeBSD, QNX, ancient NetBSD and Minix
+
+Mar 14, 2010: libarchive 2.8.3 released
+Mar 14, 2010: Symlink dereference fix for Linux broke the build there; corrected.
+
+Mar 14, 2010: libarchive 2.8.2 released
+Mar 12, 2010: Fix NULL deference for short self-extracting zip archives.
+Mar 12, 2010: Don't dereference symlinks on Linux when reading ACLs.
+Mar 07, 2010: Better detection of SHA2 support for old OpenSSL versions.
+Mar 07, 2010: Fix parsing of input files for bsdtar -T.
+Mar 07, 2010: Do not leak setup_xattr into the global namespace.
+
+Mar 06, 2010: libarchive 2.8.1 released
+Mar 06, 2010: Fix build when an older libarchive is already installed
+Mar 03, 2010: Use O_BINARY opening files in bsdtar
+Mar 02, 2010: Include missing archive_crc32.h
+Mar 01, 2010: Correctly include iconv.h required by libxml2.
+
+Feb 04, 2010: libarchive 2.8.0 released
+Jan 17, 2010: Fix error handling for 'echo nonexistent | cpio -o'
+Jan 17, 2010: Don't use futimes() on Cygwin
+
+Jan 02, 2010: libarchive 2.7.902a released (test release for 2.8)
+Jan 02, 2010: Fix tar/test/test_windows on MinGW
+Jan 02, 2010: Fix memory leaks in libarchive tests
+Jan 01, 2010: Fix memory leak when filter startup fails
+
+Dec 27, 2009: libarchive 2.7.901a released (test release for 2.8)
+
+Aug 04, 2009: libarchive 2.7.1 released
+Jul 20, 2009: Suppress bogus warning about unxz
+Jul 19, 2009: Support Cygwin 1.7
+Jun 11, 2009: Support lzma/xz files compressed with larger buffer sizes.
+May 24, 2009: Handle gzip files signed with OpenBSD "gzsig" program.
+May 07, 2009: Avoid false failures when reading from pipe.
+
+Apr 16, 2009: libarchive 2.7.0 released
+
+Apr 10, 2009: libarchive 2.6.992a released
+Apr 09, 2009: Fix SIGPIPE issue building with MSVC.
+Apr 09, 2009: Fix several minor memory leaks in libarchive and libarchive_test
+
+Apr 08, 2009: libarchive 2.6.991a released
+Apr 07, 2009: Additional tests added to bsdcpio_test
+
+Apr 01, 2009: libarchive 2.6.990a released
+Apr 01, 2009: Use command-line gunzip, bunzip2, unxz, unlzma for
+ decompression if the library is built without suitable
+ libraries. The setup functions return ARCHIVE_WARN
+ in this case so clients can adapt if necessary.
+Apr 01, 2009: Use getpw*_r and getgr*_r functions for thread-safety.
+Mar 24, 2009: Add archive_read_next_header2(), which is up to 25%
+ more efficient for some clients; from Brian Harring.
+Mar 22, 2009: PDF versions of manpages are now included in the distribution.
+Mar, 2009: Major work to improve Cygwin build by Charles Wilson.
+Feb/Mar, 2009: Major work on cmake build support, mostly by Michihiro NAKAJIMA.
+Feb/Mar, 2009: Major work on Visual Studio support by Michihiro NAKAJIMA.
+ All tests now pass.
+Feb 25, 2009: Fix Debian Bug #516577
+Feb 21, 2009: Yacc is no longer needed to build; date parser rewritten in C.
+Jan/Feb, 2009: Mtree work by Michihiro.
+Feb, 2009: Joliet support by Andreas Henriksson.
+Jan/Feb, 2009: New options framework by Michihiro.
+Feb, 2009: High-res timestamps on Tru64, AIX, and GNU Hurd, by Björn Jacke.
+Jan 18, 2009: Extended attributes work on FreeBSD and Linux now with pax format.
+Jan 07, 2009: New archive_read_disk_entry_from_file() knows about ACLs,
+ extended attributes, etc so that bsdtar and bsdcpio don't require
+ such system-specific knowledge.
+Jan 03, 2009: Read filter system extensively refactored. In particular,
+ read filter pipelines are now built out automatically and individual
+ filters should be much easier to implement. Documentation on the
+ Googlecode Wiki explains how to implement new filters.
+Dec 28, 2008: Many Windows/Visual Studio fixes from Michihiro NAKAJIMA.
+
+Dec 28, 2008: Main libarchive development moved from FreeBSD Perforce
+ server to Google Code. This should make it easier for more
+ people to participate in libarchive development.
+
+Dec 28, 2008: libarchive 2.6.0 released
+Dec 25, 2008: libarchive 2.5.905a released
+Dec 10, 2008: libarchive 2.5.904a released
+Dec 04, 2008: libarchive 2.5.903a released
+Nov 09, 2008: libarchive 2.5.902a released
+Nov 08, 2008: libarchive 2.5.901a released
+Nov 08, 2008: Start of pre-release testing for libarchive 2.6
+
+Nov 07, 2008: Read filter refactor: The decompression routines just
+ consume and produce arbitrarily-sized blocks. The reblocking
+ from read_support_compression_none() has been pulled into the
+ read core. Also, the decompression bid now makes multiple
+ passes and stacks read filters.
+Oct 21, 2008: bsdcpio: New command-line parser.
+Oct 19, 2008: Internal read_ahead change: short reads are now an error
+Oct 06, 2008: bsdtar: option parser no longer uses getopt_long(),
+ gives consistent option parsing on all platforms.
+Sep 19, 2008: Jaakko Heinonen: shar utility built on libarchive
+Sep 17, 2008: Pedro Giffuni: birthtime support
+Sep 17, 2008: Miklos Vajna: lzma reader and test. Note: I still have
+ some concerns about the auto-detection (LZMA file format
+ doesn't support auto-detection well), so this is not yet
+ enabled under archive_read_support_compression_all(). For
+ now, you must call archive_read_support_compression_lzma() if
+ you want LZMA read support.
+Sep 11, 2008: Ivailo Petrov: Many fixes to Windows build, new solution files
+Jul 26, 2008: archive_entry now tracks which values have not been set.
+ This helps zip extraction (file size is often "unknown") and
+ time restores (tar usually doesn't know atime).
+Jul 26, 2008: Joerg Sonnenberger: Performance improvements to shar writer
+Jul 25, 2008: Joerg Sonnenberger: mtree write support
+
+Jul 02, 2008: libarchive 2.5.5 released
+
+Jul 02, 2008: libarchive 2.5.5b released
+Jul 01, 2008: bsdcpio is being used by enough people, we can call it 1.0.0 now
+Jun 20, 2008: bsdcpio: If a -l link fails with EXDEV, copy the file instead
+Jun 19, 2008: bsdcpio: additional long options for better GNU cpio compat
+Jun 15, 2008: Many small portability and bugfixes since 2.5.4b.
+
+May 25, 2008: libarchive 2.5.4b released
+May 21, 2008: Joerg Sonnenberger: fix bsdtar hardlink handling for newc format
+
+May 21, 2008: More progress on Windows building. Thanks to "Scott"
+ for the Windows makefiles, thanks to Kees Zeelenberg for
+ code contributions.
+
+May 21, 2008: Fix a number of non-exploitable integer and buffer overflows,
+ thanks to David Remahl at Apple for pointing these out.
+
+May 21, 2008: Colin Percival: SIGINFO or SIGUSR1 to bsdtar prints progress info
+
+May 16, 2008: bsdtar's test harness no longer depends on file ordering.
+ This was causing spurious test failures on a lot of systems.
+ Thanks to Bernhard R. Link for the diagnosis.
+
+May 14, 2008: Joerg Sonnenberger: -s substitution support for bsdtar
+
+May 13, 2008: Joerg Sonnenberger: Many mtree improvements
+
+May 11, 2008: Joerg Sonnenberger: fix hardlink extraction when
+ hardlinks have different permissions from original file
+
+April 30, 2008: Primary libarchive work has been moved into the FreeBSD
+ project's Perforce repository: http://perforce.freebsd.org/
+ The libarchive project can be browsed at
+ //depot/user/kientzle/libarchive-portable
+ Direct link: http://preview.tinyurl.com/46mdgr
+
+May 04, 2008: libarchive 2.5.3b released
+ * libarchive: Several fixes to link resolver to address bsdcpio crashes
+ * bsdcpio: -p hardlink handling fixes
+ * tar/pax: Ensure ustar dirnames end in '/'; be more careful about
+ measuring filenames when deciding what pathname fields to use
+ * libarchive: Mark which entry strings are set; be accurate about
+ distinguishing empty strings ("") from unset ones (NULL)
+ * tar: Don't crash reading entries with empty filenames
+ * libarchive_test, bsdtar_test, bsdcpio_test: Better detaults:
+ run all tests, delete temp dirs, summarize repeated failures
+ * -no-undefined to libtool for Cygwin
+ * libarchive_test: Skip large file tests on systems with 32-bit off_t
+ * iso9660: Don't bother trying to find the body of an empty file;
+ this works around strange behavior from some ISO9660 writers
+ * tar: allow -r -T to be used together
+ * tar: allow --format with -r or -u
+ * libarchive: Don't build archive.h
+
+May 04, 2008: Simplified building: archive.h is no longer constructed
+ This may require additional #if conditionals on some platforms.
+
+Mar 30, 2008: libarchive 2.5.1b released
+
+Mar 15, 2008: libarchive 2.5.0b released
+Mar 15, 2008: bsdcpio now seems to correctly write hardlinks into newc,
+ ustar, and old cpio archives. Just a little more testing before
+ bsdcpio 1.0 becomes a reality.
+Mar 15, 2008: I think the new linkify() interface is finally handling
+ all known hardlink strategies.
+Mar 15, 2008: Mtree read fixes from Joerg Sonnenberger.
+Mar 15, 2008: Many new bsdtar and bsdcpio options from Joerg Sonnenberger.
+Mar 15, 2008: test harnesses no longer require uudecode; they
+ now have built-in decoding logic that decodes the reference
+ files as they are needed.
+
+Mar 14, 2008: libarchive 2.4.14 released; identical to 2.4.13 except for
+ a point fix for gname/uname mixup in pax format that was introduced
+ with the UTF-8 fixes.
+
+Feb 26, 2008: libarchive 2.4.13 released
+Feb 25, 2008: Handle path, linkname, gname, or uname that can't be converted
+ to/from UTF-8. Implement "hdrcharset" attribute from SUS-2008.
+Feb 25, 2008: Fix name clash on NetBSD.
+Feb 18, 2008: Fix writing empty 'ar' archives, per Kai Wang
+Feb 18, 2008: [bsdtar] Permit appending on block devices.
+Feb 09, 2008: New "linkify" resolver to help with newc hardlink writing;
+ bsdcpio still needs to be converted to use this.
+Feb 02, 2008: Windows compatibility fixes from Ivailo Petrov, Kees Zeelenberg
+Jan 30, 2008: Ignore hardlink size for non-POSIX tar archives.
+
+Jan 22, 2008: libarchive 2.4.12 released
+Jan 22, 2008: Fix bad padding when writing symlinks to newc cpio archives.
+Jan 22, 2008: Verify bsdcpio_test by getting it to work against GNU cpio 2.9.
+ bsdcpio_test complains about missing options (-y and -z), format
+ of informational messages (--version, --help), and a minor formatting
+ issue in odc format output. After this update, bsdcpio_test uncovered
+ several more cosmetic issues in bsdcpio, all now fixed.
+Jan 22, 2008: Experimental support for self-extracting Zip archives.
+Jan 22, 2008: Extend hardlink restore strategy to work correctly with
+ hardlinks extracted from newc cpio files. (Which store the body
+ only with the last occurrence of a link.)
+
+Dec 30, 2007: libarchive 2.4.11 released
+Dec 30, 2007: Fixed a compile error in bsdcpio on some systems.
+
+Dec 29, 2007: libarchive 2.4.10 released
+Dec 29, 2007: bsdcpio 0.9.0 is ready for wider use.
+Dec 29, 2007: Completed initial test harness for bsdcpio.
+
+Dec 22, 2007: libarchive 2.4.9 released
+Dec 22, 2007: Implement the remaining options for bsdcpio: -a, -q, -L, -f,
+ pattern selection for -i and -it.
+
+Dec 13, 2007: libarchive 2.4.8 released
+Dec 13, 2007: gzip and bzip2 compression now handle zero-byte writes correctly,
+ Thanks to Damien Golding for bringing this to my attention.
+
+Dec 12, 2007: libarchive 2.4.7 released
+
+Dec 10, 2007: libarchive 2.4.6 released
+Dec 09, 2007: tar/test/test_copy.c verifies "tar -c | tar -x" copy pipeline
+Dec 07, 2007: Fix a couple of minor memory leaks.
+
+Dec 04, 2007: libarchive 2.4.5 released
+Dec 04, 2007: Fix cpio/test/test_write_odc by setting the umask first.
+
+Dec 03, 2007: libarchive 2.4.4 released
+Dec 03, 2007: New configure options --disable-xattr and --disable-acl,
+ thanks to Samuli Suominen.
+
+Dec 03, 2007: libarchive 2.4.3 released
+Dec 03, 2007: Thanks to Lapo Luchini for sending me a ZIP file that
+ libarchive couldn't handle. Fixed a bug in handling of
+ "length at end" flags in ZIP files.
+Dec 03, 2007: Fixed bsdcpio -help, bsdtar -help tests.
+Dec 02, 2007: First cut at real bsdtar test harness.
+
+Dec 02, 2007: libarchive 2.4.2 released
+
+Dec 02, 2007: libarchive 2.4.1 released
+Dec 02, 2007: Minor fixes, rough cut of mdoc-to-man conversion for
+ man pages.
+
+Oct 30, 2007: libarchive 2.4.0 released
+Oct 30, 2007: Minor compile fix thanks to Joerg Schilling.
+Oct 30, 2007: Only run the format auction once at the beginning of the
+ archive. This is simpler and supports better error recovery.
+Oct 29, 2007: Test support for very large entries in tar archives:
+ libarchive_test now exercises entries from 2GB up to 1TB.
+
+Oct 27, 2007: libarchive 2.3.5 released
+Oct 27, 2007: Correct some unnecessary internal data copying in the
+ "compression none" reader and writer; this reduces user time
+ by up to 2/3 in some tests. (Thanks to Jan Psota for
+ publishing his performance test results to GNU tar's bug-tar
+ mailing list; those results pointed me towards this problem.)
+Oct 27, 2007: Fix for skipping archive entries that are exactly
+ a multiple of 4G on 32-bit platforms.
+Oct 25, 2007: Fix for reading very large (>8G) tar archives; this was
+ broken when I put in support for new GNU tar sparse formats.
+Oct 20, 2007: Initial work on new pattern-matching code for cpio; I
+ hope this eventually replaces the code currently in bsdtar.
+
+Oct 08, 2007: libarchive 2.3.4 released
+Oct 05, 2007: Continuing work on bsdcpio test suite.
+Oct 05, 2007: New cpio.5 manpage, updates to "History" of bsdcpio.1 and
+ bsdtar.1 manpages.
+Oct 05, 2007: Fix zip reader to immediately return EOF if you try
+ to read body of non-regular file. In particular, this fixes
+ bsdtar extraction of zip archives.
+
+Sep 30, 2007: libarchive 2.3.3 released
+Sep 26, 2007: Rework Makefile.am so that the enable/disable options
+ actually do the right things.
+Sep 26, 2007: cpio-odc and cpio-newc archives no longer write bodies
+ for non-regular files.
+Sep 26, 2007: Test harness for bsdcpio is in place, needs more tests written.
+ This is much nicer than the ragtag collection of test scripts
+ that bsdtar has.
+
+Sep 20, 2007: libarchive 2.3.2 released
+Sep 20, 2007: libarchive 2.3.1 broke bsdtar because the archive_write_data()
+ fix was implemented incorrectly.
+
+Sep 16, 2007: libarchive 2.3.1 released
+Sep 16, 2007: Many fixes to bsdcpio 0.3: handle hardlinks with -p, recognize
+ block size on writing, fix a couple of segfaults.
+Sep 16, 2007: Fixed return value from archive_write_data() when used
+ with archive_write_disk() to match the documentation and other
+ instances of this same function.
+Sep 15, 2007: Add archive_entry_link_resolver, archive_entry_strmode
+
+Sep 11, 2007: libarchive 2.2.8 released
+Sep 09, 2007: bsdcpio 0.2 supports most (not yet all) of the old POSIX spec.
+
+Sep 01, 2007: libarchive 2.2.7 released
+Aug 31, 2007: Support for reading mtree files, including an mtree.5 manpage
+ (A little experimental still.)
+Aug 18, 2007: Read gtar 1.17 --posix --sparse entries.
+Aug 13, 2007: Refined suid/sgid restore handling; it is no longer
+ an error if suid/sgid bits are dropped when you request
+ perm restore but don't request owner restore.
+Aug 06, 2007: Use --enable-bsdcpio if you want to try bsdcpio
+
+Aug 05, 2007: libarchive 2.2.6 released
+Aug 05, 2007: New configure option --disable-bsdtar, thanks to Joerg
+ Sonnenberger.
+Aug 05, 2007: Several bug fixes from FreeBSD CVS repo.
+
+Jul 13, 2007: libarchive 2.2.5 released
+
+Jul 12, 2007: libarchive 2.2.4 released
+Jul 12, 2007: Thanks to Colin Percival's help in diagnosing and
+ fixing several critical security bugs. Details available at
+ http://security.freebsd.org/advisories/FreeBSD-SA-07:05.libarchive.asc
+
+May 26, 2007: libarchive 2.2.3 released
+May 26, 2007: Fix memory leaks in ZIP reader and shar writer, add some
+ missing system headers to archive_entry.h, dead code cleanup
+ from Colin Percival, more tests for gzip/bzip2, fix an
+ EOF anomaly in bzip2 decompression.
+
+May 12, 2007: libarchive 2.2.2 released
+May 12, 2007: Fix archive_write_disk permission restore by cloning
+ entry passed into write_header so that permission info is
+ still available at finish_entry time. (archive_read_extract()
+ worked okay because it held onto the passed-in entry, but
+ direct consumers of archive_write_disk would break). This
+ required fixing archive_entry_clone(), which now works and has
+ a reasonably complete test case.
+May 10, 2007: Skeletal cpio implementation.
+
+May 06, 2007: libarchive 2.2.1 released
+May 06, 2007: Flesh out a lot more of test_entry.c so as to catch
+ problems such as the device node breakage before releasing <sigh>.
+May 05, 2007: Fix a bad bug introduced in 2.1.9 that broke device
+ node entries in tar archives.
+May 03, 2007: Move 'struct stat' out of archive_entry core as well.
+ This removes some portability headaches and fixes a bunch
+ of corner cases that arise when manipulating archives on
+ dissimilar systems.
+
+Apr 30, 2007: libarchive 2.1.10 released
+Apr 31, 2007: Minor code cleanup.
+
+Apr 24, 2007: libarchive 2.1.9 released
+Apr 24, 2007: Fix some recently-introduced problems with libraries
+ (Just let automake handle it and it all works much better.)
+ Finish isolating major()/minor()/makedev() in archive_entry.c.
+
+Apr 23, 2007: libarchive 2.1.8 released
+Apr 23, 2007: Minor fixes found from building on MacOS X
+
+Apr 22, 2007: libarchive 2.1.7 released
+Apr 22, 2007: Eliminated all uses of 'struct stat' from the
+ format readers/writers. This should improve portability;
+ 'struct stat' is now only used in archive_entry and in
+ code that actually touches the disk.
+
+Apr 17, 2007: libarchive 2.1.6 released
+ Libarchive now compiles and passes all tests on Interix.
+
+Apr 16, 2007: libarchive 2.1.5 released
+
+Apr 15, 2007: libarchive 2.1b2 released
+Apr 15, 2007: New libarchive_internals.3 documentation of internal APIs.
+ Not complete, but should prove helpful.
+Apr 15, 2007: Experimental "read_compress_program" and "write_compress_program"
+ for using libarchive with external compression. Not yet
+ well tested, and likely has portability issues. Feedback
+ appreciated.
+
+Apr 14, 2007: libarchive 2.0.31 released
+Apr 14, 2007: More fixes for Interix, more 'ar' work
+
+Apr 14, 2007: libarchive 2.0.30 released
+Apr 13, 2007: libarchive now enforces trailing '/' on dirs
+ written to tar archives
+
+Apr 11, 2007: libarchive 2.0.29 released
+Apr 11, 2007: Make it easier to statically configure for different platforms.
+Apr 11, 2007: Updated config.guess, config.sub, libtool
+
+Apr 06, 2007: libarchive 2.0.28 released
+Apr 06, 2007: 'ar' format read/write support thanks to Kai Wang.
+
+Apr 01, 2007: libarchive 2.0.27 released
+Mar 31, 2007: Several minor fixes from Colin Percival and Joerg Sonnenberger.
+
+Mar 12, 2007: libarchive 2.0.25 released
+Mar 12, 2007: Fix broken --unlink flag.
+
+Mar 11, 2007: libarchive 2.0.24 released
+Mar 10, 2007: Correct an ACL blunder that causes any ACL with an entry
+ that refers to a non-existent user or group to not be restored correctly.
+ The fix both makes the parser more tolerant (so that archives created
+ with the buggy ACLs can be read now) and corrects the ACL formatter.
+Mar 10, 2007: More work on test portability to Linux.
+
+Mar 10, 2007: libarchive 2.0.22 released
+Mar 10, 2007: Header cleanups; added linux/fs.h, removed
+ some unnecessary headers, added #include guards in bsdtar.
+ If you see any obvious compile failures from this, let me know.
+Mar 10, 2007: Work on bsdtar test scripts: not yet robust enough
+ to enable as part of "make check", but getting better.
+Mar 10, 2007: libarchive now returns ARCHIVE_FAILED when
+ a header write fails in a way that only affects this item.
+ Less bad than ARCHIVE_FATAL, but worse than ARCHIVE_WARN.
+
+Mar 07, 2007: libarchive 2.0.21 released
+Mar 07, 2007: Add some ACL tests (only for the system-independent
+ portion of the ACL support for now).
+Mar 07, 2007: tar's ability to read ACLs off disk got
+ turned off for FreeBSD; re-enable it. (ACL restores and
+ libarchive support for storing/reading ACLs from pax
+ archives was unaffected.)
+
+Mar 02, 2007: libarchive 2.0.20 released
+Mar 2, 2007: It's not perfect, but it's pretty good.
+ Libarchive 2.0 is officially out of beta.
+
+Feb 28, 2007: libarchive 2.0b17 released
+Feb 27, 2007: Make the GID restore checks more robust by checking
+ whether the current user has too few or too many privileges.
+
+Feb 26, 2007: libarchive 2.0b15 released
+Feb 26, 2007: Don't lose symlinks when extracting from ISOs.
+ Thanks to Diego "Flameeyes" Pettenò for telling me about the
+ broken testcase on Gentoo that (finally!) led me to the cause
+ of this long-standing bug.
+
+Feb 26, 2007: libarchive 2.0b14 released
+Feb 26, 2007: Fix a broken test on platforms that lack lchmod().
+
+Feb 25, 2007: libarchive 2.0b13 released
+Feb 25, 2007: Empty archives were being written as empty files,
+ without a proper end-of-archive marker. Fixed.
+
+Feb 23, 2007: libarchive 2.0b12 released
+Feb 22, 2007: Basic security checks added: _EXTRACT_SECURE_NODOTDOT
+ and _EXTRACT_SECURE_SYMLINK. These checks used to be in bsdtar,
+ but they belong down in libarchive where they can be used by
+ other tools and where they can be better optimized.
+
+Feb 11, 2007: libarchive 2.0b11 released
+Feb 10, 2007: Fixed a bunch of errors in libarchive's handling
+ of EXTRACT_PERM and EXTRACT_OWNER, especially relating
+ to SUID and SGID bits.
+
+Jan 31, 2007: libarchive 2.0b9 released
+Jan 31, 2007: Added read support for "empty" archives as a
+ distinct archive format. Bsdtar uses this to handle, e.g.,
+ "touch foo.tar; tar -rf foo.tar"
+
+Jan 22, 2007: libarchive 2.0b6 released
+Jan 22, 2007: archive_write_disk API is now in place. It provides
+ a finer-grained interface than archive_read_extract. In particular,
+ you can use it to create objects on disk without having an archive
+ around (just feed it archive_entry objects describing what you
+ want to create), you can override the uname/gname-to-uid/gid lookups
+ (minitar uses this to avoid getpwXXX() and getgrXXX() bloat).
+
+Jan 09, 2007: libarchive 2.0a3 released
+Jan 9, 2007: archive_extract is now much better; it handles the
+ most common cases with a minimal number of system calls.
+ Some features still need a lot of testing, especially corner
+ cases involving objects that already exist on disk. I expect
+ the next round of API overhaul will simplify building test cases.
+Jan 9, 2007: a number of fixes thanks to Colin Percival, especially
+ corrections to the skip() framework and handling of large files.
+Jan 9, 2007: Fixes for large ISOs. The code should correctly handle
+ very large ISOs with entries up to 4G. Thanks to Robert Sciuk
+ for pointing out these issues.
+
+Sep 05, 2006: libarchive 1.3.1 released
+Sep 5, 2006: Bump version to 1.3 for new I/O wrappers.
+Sep 4, 2006: New memory and FILE read/write wrappers.
+Sep 4, 2006: libarchive test harness is now minimally functional;
+ it's located a few minor bugs in error-handling logic
+
+Aug 17, 2006: libarchive 1.2.54 released
+Aug 17, 2006: Outline ABI changes for libarchive 2.0; these
+ are protected behind #ifdef's until I think I've found everything
+ that needs to change.
+Aug 17, 2006: Fix error-handling in archive_read/write_close()
+ They weren't returning any errors before.
+Aug 17, 2006: Fix recursive-add logic to not trigger if it's not set
+ Fixes a bug adding files when writing archive to pipe or when
+ using archive_write_open() directly.
+Jul 2006: New "skip" handling improves performance extracting
+ single files from large uncompressed archives.
+
+Mar 21, 2006: 1.2.52 released
+Mar 21, 2006: Fix -p on platforms that don't have platform-specific
+ extended attribute code.
+Mar 20, 2006: Add NEWS file; fill in some older history from other
+ files. I'll try to keep this file up-to-date from now on.
+
+OLDER NEWS SUMMARIES
+
+Mar 19, 2006: libarchive 1.2.51 released
+Mar 18, 2006: Many fixes to extended attribute support, including a redesign
+ of the storage format to simplify debugging.
+Mar 12, 2006: Remove 'tp' support; it was a fun idea, but not worth
+ spending much time on.
+Mar 11, 2006: Incorporated Jaakko Heinonen's still-experimental support
+ for extended attributes (Currently Linux-only.).
+Mar 11, 2006: Reorganized distribution package: There is now one tar.gz
+ file that builds both libarchive and bsdtar.
+Feb 13, 2006: Minor bug fixes: correctly read cpio device entries, write
+ Pax attribute entry names.
+Nov 7, 2005: Experimental 'tp' format support in libarchive. Feedback
+ appreciated; this is not enabled by archive_read_support_format_all()
+ yet as I'm not quite content with the format detection heuristics.
+Nov 7, 2005: Some more portability improvements thanks to Darin Broady,
+ minor bugfixes.
+Oct 12, 2005: Use GNU libtool to build shared libraries on many systems.
+Aug 9, 2005: Correctly detect that MacOS X does not have POSIX ACLs.
+Apr 17, 2005: Kees Zeelenberg has ported libarchive and bsdtar to Windows:
+ http://gnuwin32.sourceforge.net/
+Apr 11, 2005: Extended Zip/Zip64 support thanks to Dan Nelson. -L/-h
+ fix from Jaakko Heinonen.
+Mar 12, 2005: archive_read_extract can now handle very long
+ pathnames (I've tested with pathnames up to 1MB).
+Mar 12, 2005: Marcus Geiger has written an article about libarchive
+ http://xsnil.antbear.org/2005/02/05/archive-mit-libarchive-verarbeiten/
+ including examples of using it from Objective-C. His MoinX
+ http://moinx.antbear.org/ desktop Wiki uses
+ libarchive for archiving and restoring Wiki pages.
+Jan 22, 2005: Preliminary ZIP extraction support,
+ new directory-walking code for bsdtar.
+Jan 16, 2005: ISO9660 extraction code added; manpage corrections.
+May 22, 2004: Many gtar-compatible long options have been added; almost
+ all FreeBSD ports extract correctly with bsdtar.
+May 18, 2004: bsdtar can read Solaris, HP-UX, Unixware, star, gtar,
+ and pdtar archives.
diff --git a/README b/README
new file mode 100644
index 000000000000..03e47e85497e
--- /dev/null
+++ b/README
@@ -0,0 +1,137 @@
+README for libarchive bundle.
+
+Questions? Issues?
+ * http://libarchive.googlecode.com/ is the home for ongoing
+ libarchive development, including issue tracker, additional
+ documentation, and links to the libarchive mailing lists.
+
+This distribution bundle includes the following components:
+ * libarchive: a library for reading and writing streaming archives
+ * tar: the 'bsdtar' program is a full-featured 'tar'
+ replacement built on libarchive
+ * cpio: the 'bsdcpio' program is a different interface to
+ essentially the same functionality
+ * examples: Some small example programs that you may find useful.
+ * examples/minitar: a compact sample demonstrating use of libarchive.
+ I use this for testing link pollution; it should produce a very
+ small executable file on most systems.
+ * contrib: Various items sent to me by third parties;
+ please contact the authors with any questions.
+
+The top-level directory contains the following information files:
+ * NEWS - highlights of recent changes
+ * COPYING - what you can do with this
+ * INSTALL - installation instructions
+ * README - this file
+ * configure - configuration script, see INSTALL for details.
+ * CMakeLists.txt - input for "cmake" build tool, see INSTALL
+
+The following files in the top-level directory are used by the
+'configure' script:
+ * Makefile.am, aclocal.m4, configure.ac
+ - used to build this distribution, only needed by maintainers
+ * Makefile.in, config.h.in
+ - templates used by configure script
+
+Guide to Documentation installed by this system:
+ * bsdtar.1 explains the use of the bsdtar program
+ * bsdcpio.1 explains the use of the bsdcpio program
+ * libarchive.3 gives an overview of the library as a whole
+ * archive_read.3, archive_write.3, archive_write_disk.3, and
+ archive_read_disk.3 provide detailed calling sequences for the read
+ and write APIs
+ * archive_entry.3 details the "struct archive_entry" utility class
+ * archive_internals.3 provides some insight into libarchive's
+ internal structure and operation.
+ * libarchive-formats.5 documents the file formats supported by the library
+ * cpio.5, mtree.5, and tar.5 provide detailed information about these
+ popular archive formats, including hard-to-find details about
+ modern cpio and tar variants.
+The manual pages above are provided in the 'doc' directory in
+a number of different formats.
+
+You should also read the copious comments in "archive.h" and the
+source code for the sample programs for more details. Please let me
+know about any errors or omissions you find.
+
+Currently, the library automatically detects and reads the following:
+ * gzip compression
+ * bzip2 compression
+ * compress/LZW compression
+ * lzma and xz compression
+ * GNU tar format (including GNU long filenames, long link names, and
+ sparse files)
+ * Solaris 9 extended tar format (including ACLs)
+ * Old V7 tar archives
+ * POSIX ustar
+ * POSIX pax interchange format
+ * POSIX octet-oriented cpio
+ * SVR4 ASCII cpio
+ * POSIX octet-oriented cpio
+ * Binary cpio (big-endian or little-endian)
+ * ISO9660 CD-ROM images (with optional Rockridge or Joliet extensions)
+ * ZIP archives (with uncompressed or "deflate" compressed entries)
+ * GNU and BSD 'ar' archives
+ * 'mtree' format
+
+The library can write:
+ * gzip compression
+ * bzip2 compression
+ * compress/LZW compression
+ * lzma and xz compression
+ * POSIX ustar
+ * POSIX pax interchange format
+ * "restricted" pax format, which will create ustar archives except for
+ entries that require pax extensions (for long filenames, ACLs, etc).
+ * POSIX octet-oriented cpio
+ * SVR4 "newc" cpio
+ * shar archives
+ * ZIP archives (with uncompressed or "deflate" compressed entries)
+ * GNU and BSD 'ar' archives
+ * 'mtree' format
+
+Notes about the library architecture:
+
+ * This is a heavily stream-oriented system. There is no direct
+ support for in-place modification or random access.
+
+ * The library is designed to be extended with new compression and
+ archive formats. The only requirement is that the format be
+ readable or writable as a stream and that each archive entry be
+ independent. There are articles on the libarchive Wiki explaining
+ how to extend libarchive.
+
+ * On read, compression and format are always detected automatically.
+
+ * I've attempted to minimize static link pollution. If you don't
+ explicitly invoke a particular feature (such as support for a
+ particular compression or format), it won't get pulled in.
+ In particular, if you don't explicitly enable a particular
+ compression or decompression support, you won't need to link
+ against the corresponding compression or decompression libraries.
+ This also reduces the size of statically-linked binaries in
+ environments where that matters.
+
+ * On read, the library accepts whatever blocks you hand it.
+ Your read callback is free to pass the library a byte at a time
+ or mmap the entire archive and give it to the library at once.
+ On write, the library always produces correctly-blocked output.
+
+ * The object-style approach allows you to have multiple archive streams
+ open at once. bsdtar uses this in its "@archive" extension.
+
+ * The archive itself is read/written using callback functions.
+ You can read an archive directly from an in-memory buffer or
+ write it to a socket, if you wish. There are some utility
+ functions to provide easy-to-use "open file," etc, capabilities.
+
+ * The read/write APIs are designed to allow individual entries
+ to be read or written to any data source: You can create
+ a block of data in memory and add it to a tar archive without
+ first writing a temporary file. You can also read an entry from
+ an archive and write the data directly to a socket. If you want
+ to read/write entries to disk, there are convenience functions to
+ make this especially easy.
+
+ * Note: "pax interchange format" is really an extended tar format,
+ despite what the name says.
diff --git a/build/autoconf/check_stdcall_func.m4 b/build/autoconf/check_stdcall_func.m4
new file mode 100644
index 000000000000..926b046c5330
--- /dev/null
+++ b/build/autoconf/check_stdcall_func.m4
@@ -0,0 +1,51 @@
+# AC_LANG_STDCALL_FUNC_LINK_TRY(FUNCTION, SIGNATURE)
+# -------------------------------
+# Produce a source which links correctly iff the FUNCTION exists.
+AC_DEFUN([AC_LANG_STDCALL_FUNC_LINK_TRY],
+[_AC_LANG_DISPATCH([$0], _AC_LANG, $@)])
+
+# AC_CHECK_STDCALL_FUNC(FUNCTION, SIGNATURE, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# -----------------------------------------------------------------
+AC_DEFUN([AC_CHECK_STDCALL_FUNC],
+[AS_VAR_PUSHDEF([ac_var], [ac_cv_func_$1])dnl
+AC_CACHE_CHECK([for $1], ac_var,
+[AC_LINK_IFELSE([AC_LANG_STDCALL_FUNC_LINK_TRY([$1],[$2])],
+ [AS_VAR_SET(ac_var, yes)],
+ [AS_VAR_SET(ac_var, no)])])
+AS_IF([test AS_VAR_GET(ac_var) = yes], [$3], [$4])dnl
+AS_VAR_POPDEF([ac_var])dnl
+])# AC_CHECK_FUNC
+
+# AC_LANG_STDCALL_FUNC_LINK_TRY(C)(FUNCTION, SIGNATURE)
+# ----------------------------------
+# Don't include <ctype.h> because on OSF/1 3.0 it includes
+# <sys/types.h> which includes <sys/select.h> which contains a
+# prototype for select. Similarly for bzero.
+m4_define([AC_LANG_STDCALL_FUNC_LINK_TRY(C)],
+[AC_LANG_PROGRAM(
+[/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char __stdcall $1 ( $2 ) below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char __stdcall $1 ( $2 );
+char (*f) ( $2 );
+],
+[/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$1) || defined (__stub___$1)
+choke me
+#else
+f = $1;
+#endif
+])])
+
+# AC_LANG_STDCALL_FUNC_LINK_TRY(C++)(FUNCTION)
+# ------------------------------------
+m4_copy([AC_LANG_STDCALL_FUNC_LINK_TRY(C)], [AC_LANG_STDCALL_FUNC_LINK_TRY(C++)])
+
diff --git a/build/autoconf/la_uid_t.m4 b/build/autoconf/la_uid_t.m4
new file mode 100644
index 000000000000..31eef5e96fcb
--- /dev/null
+++ b/build/autoconf/la_uid_t.m4
@@ -0,0 +1,20 @@
+# la_TYPE_UID_T
+# -------------
+AC_DEFUN([la_TYPE_UID_T],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_CACHE_CHECK(for uid_t in sys/types.h, la_cv_type_uid_t,
+[AC_EGREP_HEADER(uid_t, sys/types.h,
+ la_cv_type_uid_t=yes, la_cv_type_uid_t=no)])
+if test $la_cv_type_uid_t = no; then
+ case $host in
+ *mingw*) def_uid_t=short ;;
+ *) def_uid_t=int ;;
+ esac
+ AC_DEFINE_UNQUOTED(uid_t, [$def_uid_t],
+ [Define to match typeof st_uid field of struct stat if <sys/types.h> doesn't define.])
+ AC_DEFINE_UNQUOTED(gid_t, [$def_uid_t],
+ [Define to match typeof st_gid field of struct stat if <sys/types.h> doesn't define.])
+fi
+])
+AU_ALIAS([AC_TYPE_UID_T], [la_TYPE_UID_T])
+
diff --git a/build/autogen.sh b/build/autogen.sh
new file mode 100755
index 000000000000..ad7d245b794a
--- /dev/null
+++ b/build/autogen.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+PATH=/usr/local/gnu-autotools/bin/:$PATH
+export PATH
+
+# Start from one level above the build directory
+if [ -f version ]; then
+ cd ..
+fi
+
+if [ \! -f build/version ]; then
+ echo "Can't find source directory"
+ exit 1
+fi
+
+# BSD make's "OBJDIR" support freaks out the automake-generated
+# Makefile. Effectively disable it.
+export MAKEOBJDIRPREFIX=/junk
+
+# Start from the build directory, where the version file is located
+if [ -f build/version ]; then
+ cd build
+fi
+
+if [ \! -f version ]; then
+ echo "Can't find version file"
+ exit 1
+fi
+
+# Update the build number in the 'version' file.
+# Separate number from additional alpha/beta/etc marker
+MARKER=`cat version | sed 's/[0-9.]//g'`
+# Bump the number
+VN=`cat version | sed 's/[^0-9.]//g'`
+# Build out the string.
+VS="$(($VN/1000000)).$(( ($VN/1000)%1000 )).$(( $VN%1000 ))$MARKER"
+
+cd ..
+
+# Clean up the source dir as much as we can.
+/bin/sh build/clean.sh
+
+# Substitute the integer version into Libarchive's archive.h
+perl -p -i -e "s/^(#define\tARCHIVE_VERSION_NUMBER).*/\$1 $VN/" libarchive/archive.h
+perl -p -i -e "s/^(#define\tARCHIVE_VERSION_STRING).*/\$1 \"libarchive $VS\"/" libarchive/archive.h
+# Substitute versions into configure.ac as well
+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
+
+set -xe
+aclocal -I build/autoconf
+
+# Note: --automake flag needed only for libtoolize from
+# libtool 1.5.x; in libtool 2.2.x it is a synonym for --quiet
+case `uname` in
+Darwin) glibtoolize --automake -c;;
+*) libtoolize --automake -c;;
+esac
+autoconf
+autoheader
+automake -a -c
+
+curl 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' > build/autoconf/config.guess
+curl 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' > build/autoconf/config.sub
+
+./configure
+make distcheck
+make dist-zip
diff --git a/build/bump-version.sh b/build/bump-version.sh
new file mode 100644
index 000000000000..0304cf3fb329
--- /dev/null
+++ b/build/bump-version.sh
@@ -0,0 +1,36 @@
+#!/bin/sh +v
+
+# Start from the build directory, where the version file is located
+if [ -f build/version ]; then
+ cd build
+fi
+
+if [ \! -f version ]; then
+ echo "Can't find version file"
+ exit 1
+fi
+
+# Update the build number in the 'version' file.
+# Separate number from additional alpha/beta/etc marker
+MARKER=`cat version | sed 's/[0-9.]//g'`
+# Bump the number
+VN=`cat version | sed 's/[^0-9.]//g'`
+# Reassemble and write back out
+VN=$(($VN + 1))
+rm -f version.old
+mv version version.old
+chmod +w version.old
+echo $VN$MARKER > version
+VS="$(($VN/1000000)).$(( ($VN/1000)%1000 )).$(( $VN%1000 ))$MARKER"
+cd ..
+
+ANNOUNCE=`date +"%b %d, %Y:"`" libarchive $VS released"
+
+echo $ANNOUNCE
+
+# Add a version notice to NEWS
+mv NEWS NEWS.bak
+chmod +w NEWS.bak
+echo > NEWS
+echo $ANNOUNCE >> NEWS
+cat NEWS.bak >> NEWS
diff --git a/build/clean.sh b/build/clean.sh
new file mode 100644
index 000000000000..5b4c5624a60d
--- /dev/null
+++ b/build/clean.sh
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+if [ \! -f build/version ]; then
+ echo 'Must run the clean script from the top-level dir of the libarchive distribution' 1>&2
+ exit 1
+fi
+
+#
+# The automake-generated 'maintainer-clean' target does clean up a
+# lot. If that fails, try plain 'clean' in case we're using the cmake
+# or other makefile. But don't worry if we can't...
+#
+make maintainer-clean || make clean || true
+
+# If we're on BSD, blow away the build dir under /usr/obj
+rm -rf /usr/obj`pwd`
+
+#
+# Try to clean up a bit more...
+#
+
+find . -name '*.So' | xargs rm
+find . -name '*.a' | xargs rm
+find . -name '*.la' | xargs rm
+find . -name '*.lo' | xargs rm
+find . -name '*.o' | xargs rm
+find . -name '*.orig' | xargs rm
+find . -name '*.po' | xargs rm
+find . -name '*.rej' | xargs rm
+find . -name '*~' | xargs rm
+find . -name '.depend' | xargs rm
+find . -name '.deps' | xargs rm -rf
+find . -name '.dirstamp' | xargs rm
+find . -name '.libs' | xargs rm -rf
+
+rm -rf autom4te.cache
+
+rm -f Makefile.in
+rm -f aclocal.m4
+rm -f bsdcpio
+rm -f bsdcpio_test
+rm -f bsdtar
+rm -f bsdtar_test
+rm -f build/autoconf/compile
+rm -f build/autoconf/config.*
+rm -f build/autoconf/depcomp
+rm -f build/autoconf/install-sh
+rm -f build/autoconf/libtool.m4
+rm -f build/autoconf/ltmain.sh
+rm -f build/autoconf/ltoptions.m4
+rm -f build/autoconf/ltsugar.m4
+rm -f build/autoconf/ltversion.m4
+rm -f build/autoconf/lt~obsolete.m4
+rm -f build/autoconf/missing
+rm -f build/pkgconfig/libarchive.pc
+rm -f build/version.old
+rm -f config.h
+rm -f config.h.in
+rm -f config.log
+rm -f config.status
+rm -f configure
+rm -f cpio/*.1.gz
+rm -f cpio/bsdcpio
+rm -f cpio/test/bsdcpio_test
+rm -f cpio/test/list.h
+rm -f doc/html/*
+rm -f doc/man/*
+rm -f doc/pdf/*
+rm -f doc/text/*
+rm -f doc/wiki/*
+rm -f libarchive/*.[35].gz
+rm -f libarchive/libarchive.so*
+rm -f libarchive/test/libarchive_test
+rm -f libarchive/test/list.h
+rm -f libarchive_test
+rm -f libtool
+rm -f stamp-h1
+rm -f tar/*.1.gz
+rm -f tar/bsdtar
+rm -f tar/test/bsdtar_test
+rm -f tar/test/list.h
diff --git a/build/cmake/AddTest28.cmake b/build/cmake/AddTest28.cmake
new file mode 100644
index 000000000000..ab26a9a9b8bf
--- /dev/null
+++ b/build/cmake/AddTest28.cmake
@@ -0,0 +1,107 @@
+# - Macro approximating the CMake 2.8 ADD_TEST(NAME) signature.
+# ADD_TEST_28(NAME <name> COMMAND <command> [arg1 [arg2 ...]])
+# <name> - The name of the test
+# <command> - The test executable
+# [argN...] - Arguments to the test executable
+# This macro approximates the ADD_TEST(NAME) signature provided in
+# CMake 2.8 but works with CMake 2.6 too. See CMake 2.8 documentation
+# of ADD_TEST()for details.
+#
+# This macro automatically replaces a <command> that names an
+# executable target with the target location. A generator expression
+# of the form "$<TARGET_FILE:tgt>" is supported in both the command
+# and arguments of the test. Howerver, this macro only works for
+# targets without per-config output name properties set.
+#
+# Example usage:
+# add_test(NAME mytest COMMAND testDriver --exe $<TARGET_FILE:myexe>)
+# This creates a test "mytest" whose command runs a testDriver tool
+# passing the full path to the executable file produced by target
+# "myexe".
+
+#=============================================================================
+# Copyright 2009 Kitware, Inc.
+# 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
+# in this position and unchanged.
+# 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.
+#=============================================================================
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6.3)
+
+# CMake 2.8 supports ADD_TEST(NAME) natively.
+IF(NOT "${CMAKE_VERSION}" VERSION_LESS "2.8")
+ MACRO(ADD_TEST_28)
+ ADD_TEST(${ARGV})
+ ENDMACRO()
+ RETURN()
+ENDIF()
+
+# Simulate ADD_TEST(NAME) signature from CMake 2.8.
+MACRO(ADD_TEST_28 NAME name COMMAND command)
+ # Enforce the signature.
+ IF(NOT "x${NAME}" STREQUAL "xNAME")
+ MESSAGE(FATAL_ERROR "First ADD_TEST_28 argument must be \"NAME\"")
+ ENDIF()
+ IF(NOT "x${COMMAND}" STREQUAL "xCOMMAND")
+ MESSAGE(FATAL_ERROR "Third ADD_TEST_28 argument must be \"COMMAND\"")
+ ENDIF()
+
+ # Perform "COMMAND myexe ..." substitution.
+ SET(cmd "${command}")
+ IF(TARGET "${cmd}")
+ _ADD_TEST_28_GET_EXE(${cmd} cmd)
+ ENDIF()
+
+ # Perform "COMMAND ... $<TARGET_FILE:myexe> ..." substitution.
+ SET(target_file "\\$<TARGET_FILE:(.+)>")
+ SET(args)
+ FOREACH(ARG ${cmd} ${ARGN})
+ SET(arg "${ARG}")
+ IF("${arg}" MATCHES "${target_file}")
+ STRING(REGEX REPLACE "${target_file}" "\\1" tgt "${arg}")
+ IF(TARGET "${tgt}")
+ _ADD_TEST_28_GET_EXE(${tgt} exe)
+ STRING(REGEX REPLACE "${target_file}" "${exe}" arg "${arg}")
+ ENDIF()
+ ENDIF()
+ LIST(APPEND args "${arg}")
+ ENDFOREACH()
+
+ # Invoke old ADD_TEST() signature with transformed arguments.
+ ADD_TEST(${name} ${args})
+ENDMACRO()
+
+# Get the test-time location of an executable target.
+MACRO(_ADD_TEST_28_GET_EXE tgt exe_var)
+ # The LOCATION property gives a build-time location.
+ GET_TARGET_PROPERTY(${exe_var} ${tgt} LOCATION)
+
+ # In single-configuration generatrs the build-time and test-time
+ # locations are the same because there is no per-config variable
+ # reference. In multi-configuration generators the following
+ # substitution converts the build-time configuration variable
+ # reference to a test-time configuration variable reference.
+ IF(CMAKE_CONFIGURATION_TYPES)
+ STRING(REPLACE "${CMAKE_CFG_INTDIR}" "\${CTEST_CONFIGURATION_TYPE}"
+ ${exe_var} "${${exe_var}}")
+ ENDIF(CMAKE_CONFIGURATION_TYPES)
+ENDMACRO()
diff --git a/build/cmake/CheckFileOffsetBits.c b/build/cmake/CheckFileOffsetBits.c
new file mode 100644
index 000000000000..d948fecf2b4e
--- /dev/null
+++ b/build/cmake/CheckFileOffsetBits.c
@@ -0,0 +1,14 @@
+#include <sys/types.h>
+
+#define KB ((off_t)1024)
+#define MB ((off_t)1024 * KB)
+#define GB ((off_t)1024 * MB)
+#define TB ((off_t)1024 * GB)
+int t2[(((64 * GB -1) % 671088649) == 268434537)
+ && (((TB - (64 * GB -1) + 255) % 1792151290) == 305159546)? 1: -1];
+
+int main()
+{
+ ;
+ return 0;
+}
diff --git a/build/cmake/CheckFileOffsetBits.cmake b/build/cmake/CheckFileOffsetBits.cmake
new file mode 100644
index 000000000000..4132b387e178
--- /dev/null
+++ b/build/cmake/CheckFileOffsetBits.cmake
@@ -0,0 +1,44 @@
+# - Check if _FILE_OFFSET_BITS macro needed for large files
+# CHECK_FILE_OFFSET_BITS ()
+#
+# 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
+# Copyright (c) 2009, Michihiro NAKAJIMA
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+#INCLUDE(CheckCXXSourceCompiles)
+
+GET_FILENAME_COMPONENT(_selfdir_CheckFileOffsetBits
+ "${CMAKE_CURRENT_LIST_FILE}" PATH)
+
+MACRO (CHECK_FILE_OFFSET_BITS)
+ IF(NOT DEFINED _FILE_OFFSET_BITS)
+ MESSAGE(STATUS "Cheking _FILE_OFFSET_BITS for large files")
+ TRY_COMPILE(__WITHOUT_FILE_OFFSET_BITS_64
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${_selfdir_CheckFileOffsetBits}/CheckFileOffsetBits.c
+ COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS})
+ IF(NOT __WITHOUT_FILE_OFFSET_BITS_64)
+ TRY_COMPILE(__WITH_FILE_OFFSET_BITS_64
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${_selfdir_CheckFileOffsetBits}/CheckFileOffsetBits.c
+ COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_FILE_OFFSET_BITS=64)
+ ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64)
+
+ IF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
+ SET(_FILE_OFFSET_BITS 64 CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files")
+ MESSAGE(STATUS "Cheking _FILE_OFFSET_BITS for large files - needed")
+ ELSE(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
+ SET(_FILE_OFFSET_BITS "" CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files")
+ MESSAGE(STATUS "Cheking _FILE_OFFSET_BITS for large files - not needed")
+ ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
+ ENDIF(NOT DEFINED _FILE_OFFSET_BITS)
+
+ENDMACRO (CHECK_FILE_OFFSET_BITS)
+
diff --git a/build/cmake/CheckFuncs.cmake b/build/cmake/CheckFuncs.cmake
new file mode 100644
index 000000000000..0670df97f869
--- /dev/null
+++ b/build/cmake/CheckFuncs.cmake
@@ -0,0 +1,49 @@
+# Check if the system has the specified function; treat glibc "stub"
+# functions as nonexistent:
+# CHECK_FUNCTION_EXISTS_GLIBC (FUNCTION FUNCVAR)
+#
+# FUNCTION - the function(s) where the prototype should be declared
+# FUNCVAR - variable to define if the function does exist
+#
+# In particular, this understands the glibc convention of
+# defining macros __stub_XXXX or __stub___XXXX if the function
+# does appear in the library but is merely a stub that does nothing.
+# By detecting this case, we can select alternate behavior on
+# platforms that don't support this functionality.
+#
+# 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
+# Copyright (c) 2009, Michihiro NAKAJIMA
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+INCLUDE(CheckFunctionExists)
+GET_FILENAME_COMPONENT(_selfdir_CheckFunctionExistsGlibc
+ "${CMAKE_CURRENT_LIST_FILE}" PATH)
+
+MACRO (CHECK_FUNCTION_EXISTS_GLIBC _FUNC _FUNCVAR)
+ IF(NOT DEFINED ${_FUNCVAR})
+ SET(CHECK_STUB_FUNC_1 "__stub_${_FUNC}")
+ SET(CHECK_STUB_FUNC_2 "__stub___${_FUNC}")
+ CONFIGURE_FILE( ${_selfdir_CheckFunctionExistsGlibc}/CheckFuncs_stub.c.in
+ ${CMAKE_CURRENT_BINARY_DIR}/cmake.tmp/CheckFuncs_stub.c IMMEDIATE)
+ TRY_COMPILE(__stub
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}/cmake.tmp/CheckFuncs_stub.c
+ COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+ CMAKE_FLAGS
+ -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_INCLUDE_FILE_FLAGS}
+ "${CHECK_INCLUDE_FILE_C_INCLUDE_DIRS}")
+ IF (__stub)
+ SET("${_FUNCVAR}" "" CACHE INTERNAL "Have function ${_FUNC}")
+ ELSE (__stub)
+ CHECK_FUNCTION_EXISTS("${_FUNC}" "${_FUNCVAR}")
+ ENDIF (__stub)
+ ENDIF(NOT DEFINED ${_FUNCVAR})
+ENDMACRO (CHECK_FUNCTION_EXISTS_GLIBC)
+
diff --git a/build/cmake/CheckFuncs_stub.c.in b/build/cmake/CheckFuncs_stub.c.in
new file mode 100644
index 000000000000..50da414b5f51
--- /dev/null
+++ b/build/cmake/CheckFuncs_stub.c.in
@@ -0,0 +1,16 @@
+#ifdef __STDC__
+#include <limits.h>
+#else
+#include <assert.h>
+#endif
+
+int
+main()
+{
+#if defined ${CHECK_STUB_FUNC_1} || defined ${CHECK_STUB_FUNC_2}
+ return 0;
+#else
+this system have stub
+ return 0;
+#endif
+}
diff --git a/build/cmake/CheckHeaderDirent.cmake b/build/cmake/CheckHeaderDirent.cmake
new file mode 100644
index 000000000000..e9a7ea855326
--- /dev/null
+++ b/build/cmake/CheckHeaderDirent.cmake
@@ -0,0 +1,32 @@
+# - Check if the system has the specified type
+# CHECK_HEADER_DIRENT (HEADER1 HEARDER2 ...)
+#
+# HEADER - the header(s) where the prototype should be declared
+#
+# 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
+# Copyright (c) 2009, Michihiro NAKAJIMA
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+
+INCLUDE(CheckTypeExists)
+
+MACRO (CHECK_HEADER_DIRENT)
+ CHECK_TYPE_EXISTS("DIR *" dirent.h HAVE_DIRENT_H)
+ IF(NOT HAVE_DIRENT_H)
+ CHECK_TYPE_EXISTS("DIR *" sys/ndir.h HAVE_SYS_NDIR_H)
+ IF(NOT HAVE_SYS_NDIR_H)
+ CHECK_TYPE_EXISTS("DIR *" ndir.h HAVE_NDIR_H)
+ IF(NOT HAVE_NDIR_H)
+ CHECK_TYPE_EXISTS("DIR *" sys/dir.h HAVE_SYS_DIR_H)
+ ENDIF(NOT HAVE_NDIR_H)
+ ENDIF(NOT HAVE_SYS_NDIR_H)
+ ENDIF(NOT HAVE_DIRENT_H)
+ENDMACRO (CHECK_HEADER_DIRENT)
+
diff --git a/build/cmake/CheckStructMember.cmake b/build/cmake/CheckStructMember.cmake
new file mode 100644
index 000000000000..05ddb3a11f20
--- /dev/null
+++ b/build/cmake/CheckStructMember.cmake
@@ -0,0 +1,43 @@
+# - Check if the given struct or class has the specified member variable
+# CHECK_STRUCT_MEMBER (STRUCT MEMBER HEADER VARIABLE)
+#
+# STRUCT - the name of the struct or class you are interested in
+# MEMBER - the member which existence you want to check
+# HEADER - the header(s) where the prototype should be declared
+# VARIABLE - variable to store the result
+#
+# 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
+
+# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+
+INCLUDE(CheckCSourceCompiles)
+
+MACRO (CHECK_STRUCT_MEMBER _STRUCT _MEMBER _HEADER _RESULT)
+ SET(_INCLUDE_FILES)
+ FOREACH (it ${_HEADER})
+ SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n")
+ ENDFOREACH (it)
+
+ SET(_CHECK_STRUCT_MEMBER_SOURCE_CODE "
+${_INCLUDE_FILES}
+int main()
+{
+ static ${_STRUCT} tmp;
+ if (sizeof(tmp.${_MEMBER}))
+ return 0;
+ return 0;
+}
+")
+ CHECK_C_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT})
+
+ENDMACRO (CHECK_STRUCT_MEMBER)
+
diff --git a/build/cmake/CheckTypeExists.cmake b/build/cmake/CheckTypeExists.cmake
new file mode 100644
index 000000000000..b05234fd8753
--- /dev/null
+++ b/build/cmake/CheckTypeExists.cmake
@@ -0,0 +1,42 @@
+# - Check if the system has the specified type
+# CHECK_TYPE_EXISTS (TYPE HEADER VARIABLE)
+#
+# TYPE - the name of the type or struct or class you are interested in
+# HEADER - the header(s) where the prototype should be declared
+# VARIABLE - variable to store the result
+#
+# 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
+# Copyright (c) 2009, Michihiro NAKAJIMA
+# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+
+INCLUDE(CheckCSourceCompiles)
+
+MACRO (CHECK_TYPE_EXISTS _TYPE _HEADER _RESULT)
+ SET(_INCLUDE_FILES)
+ FOREACH (it ${_HEADER})
+ SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n")
+ ENDFOREACH (it)
+
+ SET(_CHECK_TYPE_EXISTS_SOURCE_CODE "
+${_INCLUDE_FILES}
+int main()
+{
+ static ${_TYPE} tmp;
+ if (sizeof(tmp))
+ return 0;
+ return 0;
+}
+")
+ CHECK_C_SOURCE_COMPILES("${_CHECK_TYPE_EXISTS_SOURCE_CODE}" ${_RESULT})
+
+ENDMACRO (CHECK_TYPE_EXISTS)
+
diff --git a/build/cmake/FindLZMA.cmake b/build/cmake/FindLZMA.cmake
new file mode 100644
index 000000000000..1d065c4abcc7
--- /dev/null
+++ b/build/cmake/FindLZMA.cmake
@@ -0,0 +1,52 @@
+# - Find lzma and lzmadec
+# Find the native LZMA includes and library
+#
+# LZMA_INCLUDE_DIR - where to find lzma.h, etc.
+# LZMA_LIBRARIES - List of libraries when using liblzma.
+# LZMA_FOUND - True if liblzma found.
+# LZMADEC_INCLUDE_DIR - where to find lzmadec.h, etc.
+# LZMADEC_LIBRARIES - List of libraries when using liblzmadec.
+# LZMADEC_FOUND - True if liblzmadec found.
+
+IF (LZMA_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(LZMA_FIND_QUIETLY TRUE)
+ENDIF (LZMA_INCLUDE_DIR)
+
+FIND_PATH(LZMA_INCLUDE_DIR lzma.h)
+FIND_LIBRARY(LZMA_LIBRARY NAMES lzma )
+
+# handle the QUIETLY and REQUIRED arguments and set LZMA_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZMA DEFAULT_MSG LZMA_LIBRARY LZMA_INCLUDE_DIR)
+
+IF(LZMA_FOUND)
+ SET( LZMA_LIBRARIES ${LZMA_LIBRARY} )
+ELSE(LZMA_FOUND)
+ SET( LZMA_LIBRARIES )
+
+ IF (LZMADEC_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(LZMADEC_FIND_QUIETLY TRUE)
+ ENDIF (LZMADEC_INCLUDE_DIR)
+
+ FIND_PATH(LZMADEC_INCLUDE_DIR lzmadec.h)
+ FIND_LIBRARY(LZMADEC_LIBRARY NAMES lzmadec )
+
+ # handle the QUIETLY and REQUIRED arguments and set LZMADEC_FOUND to TRUE if
+ # all listed variables are TRUE
+ INCLUDE(FindPackageHandleStandardArgs)
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZMADEC DEFAULT_MSG LZMADEC_LIBRARY
+ LZMADEC_INCLUDE_DIR)
+
+ IF(LZMADEC_FOUND)
+ SET( LZMADEC_LIBRARIES ${LZMADEC_LIBRARY} )
+ ELSE(LZMADEC_FOUND)
+ SET( LZMADEC_LIBRARIES )
+ ENDIF(LZMADEC_FOUND)
+ENDIF(LZMA_FOUND)
+
+
+MARK_AS_ADVANCED( LZMA_LIBRARY LZMA_INCLUDE_DIR
+ LZMADEC_LIBRARY LZMADEC_INCLUDE_DIR )
diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in
new file mode 100644
index 000000000000..d2f14b4e464e
--- /dev/null
+++ b/build/cmake/config.h.in
@@ -0,0 +1,759 @@
+/* config.h. Generated from config.h.cmake by cmake configure */
+
+/* Define ZLIB_WINAPI if zlib was built on Visual Studio. */
+#cmakedefine ZLIB_WINAPI 1
+
+/* MD5 via ARCHIVE_HASH_MD5_LIBC supported. */
+#cmakedefine ARCHIVE_HASH_MD5_LIBC
+
+/* MD5 via ARCHIVE_HASH_MD5_LIBSYSTEM supported. */
+#cmakedefine ARCHIVE_HASH_MD5_LIBSYSTEM
+
+/* MD5 via ARCHIVE_HASH_MD5_OPENSSL supported. */
+#cmakedefine ARCHIVE_HASH_MD5_OPENSSL
+
+/* MD5 via ARCHIVE_HASH_MD5_WIN supported. */
+#cmakedefine ARCHIVE_HASH_MD5_WIN
+
+/* RMD160 via ARCHIVE_HASH_RMD160_LIBC supported. */
+#cmakedefine ARCHIVE_HASH_RMD160_LIBC
+
+/* RMD160 via ARCHIVE_HASH_RMD160_OPENSSL supported. */
+#cmakedefine ARCHIVE_HASH_RMD160_OPENSSL
+
+/* SHA1 via ARCHIVE_HASH_SHA1_LIBC supported. */
+#cmakedefine ARCHIVE_HASH_SHA1_LIBC
+
+/* SHA1 via ARCHIVE_HASH_SHA1_LIBSYSTEM supported. */
+#cmakedefine ARCHIVE_HASH_SHA1_LIBSYSTEM
+
+/* SHA1 via ARCHIVE_HASH_SHA1_OPENSSL supported. */
+#cmakedefine ARCHIVE_HASH_SHA1_OPENSSL
+
+/* SHA1 via ARCHIVE_HASH_SHA1_WIN supported. */
+#cmakedefine ARCHIVE_HASH_SHA1_WIN
+
+/* SHA256 via ARCHIVE_HASH_SHA256_LIBC supported. */
+#cmakedefine ARCHIVE_HASH_SHA256_LIBC
+
+/* SHA256 via ARCHIVE_HASH_SHA256_LIBC2 supported. */
+#cmakedefine ARCHIVE_HASH_SHA256_LIBC2
+
+/* SHA256 via ARCHIVE_HASH_SHA256_LIBC3 supported. */
+#cmakedefine ARCHIVE_HASH_SHA256_LIBC3
+
+/* SHA256 via ARCHIVE_HASH_SHA256_LIBSYSTEM supported. */
+#cmakedefine ARCHIVE_HASH_SHA256_LIBSYSTEM
+
+/* SHA256 via ARCHIVE_HASH_SHA256_OPENSSL supported. */
+#cmakedefine ARCHIVE_HASH_SHA256_OPENSSL
+
+/* SHA256 via ARCHIVE_HASH_SHA256_WIN supported. */
+#cmakedefine ARCHIVE_HASH_SHA256_WIN
+
+/* SHA384 via ARCHIVE_HASH_SHA384_LIBC supported. */
+#cmakedefine ARCHIVE_HASH_SHA384_LIBC
+
+/* SHA384 via ARCHIVE_HASH_SHA384_LIBC2 supported. */
+#cmakedefine ARCHIVE_HASH_SHA384_LIBC2
+
+/* SHA384 via ARCHIVE_HASH_SHA384_LIBC3 supported. */
+#cmakedefine ARCHIVE_HASH_SHA384_LIBC3
+
+/* SHA384 via ARCHIVE_HASH_SHA384_LIBSYSTEM supported. */
+#cmakedefine ARCHIVE_HASH_SHA384_LIBSYSTEM
+
+/* SHA384 via ARCHIVE_HASH_SHA384_OPENSSL supported. */
+#cmakedefine ARCHIVE_HASH_SHA384_OPENSSL
+
+/* SHA384 via ARCHIVE_HASH_SHA384_WIN supported. */
+#cmakedefine ARCHIVE_HASH_SHA384_WIN
+
+/* SHA512 via ARCHIVE_HASH_SHA512_LIBC supported. */
+#cmakedefine ARCHIVE_HASH_SHA512_LIBC
+
+/* SHA512 via ARCHIVE_HASH_SHA512_LIBC2 supported. */
+#cmakedefine ARCHIVE_HASH_SHA512_LIBC2
+
+/* SHA512 via ARCHIVE_HASH_SHA512_LIBC3 supported. */
+#cmakedefine ARCHIVE_HASH_SHA512_LIBC3
+
+/* SHA512 via ARCHIVE_HASH_SHA512_LIBSYSTEM supported. */
+#cmakedefine ARCHIVE_HASH_SHA512_LIBSYSTEM
+
+/* SHA512 via ARCHIVE_HASH_SHA512_OPENSSL supported. */
+#cmakedefine ARCHIVE_HASH_SHA512_OPENSSL
+
+/* SHA512 via ARCHIVE_HASH_SHA512_WIN supported. */
+#cmakedefine ARCHIVE_HASH_SHA512_WIN
+
+/* Version number of bsdcpio */
+#cmakedefine BSDCPIO_VERSION_STRING "${BSDCPIO_VERSION_STRING}"
+
+/* Version number of bsdtar */
+#cmakedefine BSDTAR_VERSION_STRING "${BSDTAR_VERSION_STRING}"
+
+/* Define to 1 if you have the `acl_create_entry' function. */
+#cmakedefine HAVE_ACL_CREATE_ENTRY 1
+
+/* Define to 1 if you have the `acl_get_link' function. */
+#cmakedefine HAVE_ACL_GET_LINK 1
+
+/* Define to 1 if you have the `acl_get_link_np' function. */
+#cmakedefine HAVE_ACL_GET_LINK_NP 1
+
+/* Define to 1 if you have the `acl_get_perm' function. */
+#cmakedefine HAVE_ACL_GET_PERM 1
+
+/* Define to 1 if you have the `acl_get_perm_np' function. */
+#cmakedefine HAVE_ACL_GET_PERM_NP 1
+
+/* Define to 1 if you have the `acl_init' function. */
+#cmakedefine HAVE_ACL_INIT 1
+
+/* Define to 1 if you have the <acl/libacl.h> header file. */
+#cmakedefine HAVE_ACL_LIBACL_H 1
+
+/* Define to 1 if the system has the type `acl_permset_t'. */
+#cmakedefine HAVE_ACL_PERMSET_T 1
+
+/* Define to 1 if you have the `acl_set_fd' function. */
+#cmakedefine HAVE_ACL_SET_FD 1
+
+/* Define to 1 if you have the `acl_set_fd_np' function. */
+#cmakedefine HAVE_ACL_SET_FD_NP 1
+
+/* Define to 1 if you have the `acl_set_file' function. */
+#cmakedefine HAVE_ACL_SET_FILE 1
+
+/* True for systems with POSIX ACL support */
+#cmakedefine HAVE_ACL_USER 1
+
+/* Define to 1 if you have the <attr/xattr.h> header file. */
+#cmakedefine HAVE_ATTR_XATTR_H 1
+
+/* Define to 1 if you have the <bsdxml.h> header file. */
+#cmakedefine HAVE_BSDXML_H 1
+
+/* Define to 1 if you have the <bzlib.h> header file. */
+#cmakedefine HAVE_BZLIB_H 1
+
+/* Define to 1 if you have the `chflags' function. */
+#cmakedefine HAVE_CHFLAGS 1
+
+/* Define to 1 if you have the `chown' function. */
+#cmakedefine HAVE_CHOWN 1
+
+/* Define to 1 if you have the `chroot' function. */
+#cmakedefine HAVE_CHROOT 1
+
+/* Define to 1 if you have the `CreateHardLinkA' function. */
+#cmakedefine HAVE_CREATEHARDLINKA 1
+
+/* Define to 1 if you have the `CreateHardLinkW' function. */
+#cmakedefine HAVE_CREATEHARDLINKW 1
+
+/* Define to 1 if you have the <ctype.h> header file. */
+#cmakedefine HAVE_CTYPE_H 1
+
+/* Define to 1 if you have the `cygwin_conv_path' function. */
+#cmakedefine HAVE_CYGWIN_CONV_PATH 1
+
+/* Define to 1 if you have the declaration of `INT64_MAX', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_INT64_MAX 1
+
+/* Define to 1 if you have the declaration of `INT64_MIN', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_INT64_MIN 1
+
+/* Define to 1 if you have the declaration of `optarg', and to 0 if you don't.
+ */
+#cmakedefine HAVE_DECL_OPTARG 1
+
+/* Define to 1 if you have the declaration of `optind', and to 0 if you don't.
+ */
+#cmakedefine HAVE_DECL_OPTIND 1
+
+/* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_SIZE_MAX 1
+
+/* Define to 1 if you have the declaration of `SSIZE_MAX', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_SSIZE_MAX 1
+
+/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_STRERROR_R 1
+
+/* Define to 1 if you have the declaration of `UINT32_MAX', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_UINT32_MAX 1
+
+/* Define to 1 if you have the declaration of `UINT64_MAX', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_UINT64_MAX 1
+
+/* Define to 1 if you have the <direct.h> header file. */
+#cmakedefine HAVE_DIRECT_H 1
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#cmakedefine HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#cmakedefine HAVE_DLFCN_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#cmakedefine HAVE_DOPRNT 1
+
+/* Define to 1 if nl_langinfo supports D_MD_ORDER */
+#cmakedefine HAVE_D_MD_ORDER 1
+
+/* A possible errno value for invalid file format errors */
+#cmakedefine HAVE_EFTYPE 1
+
+/* A possible errno value for invalid file format errors */
+#cmakedefine HAVE_EILSEQ 1
+
+/* Define to 1 if you have the <errno.h> header file. */
+#cmakedefine HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <expat.h> header file. */
+#cmakedefine HAVE_EXPAT_H 1
+
+/* Define to 1 if you have the <ext2fs/ext2_fs.h> header file. */
+#cmakedefine HAVE_EXT2FS_EXT2_FS_H 1
+
+/* Define to 1 if you have the `extattr_get_file' function. */
+#cmakedefine HAVE_EXTATTR_GET_FILE 1
+
+/* Define to 1 if you have the `extattr_list_file' function. */
+#cmakedefine HAVE_EXTATTR_LIST_FILE 1
+
+/* Define to 1 if you have the `extattr_set_fd' function. */
+#cmakedefine HAVE_EXTATTR_SET_FD 1
+
+/* Define to 1 if you have the `extattr_set_file' function. */
+#cmakedefine HAVE_EXTATTR_SET_FILE 1
+
+/* Define to 1 if you have the `fchdir' function. */
+#cmakedefine HAVE_FCHDIR 1
+
+/* Define to 1 if you have the `fchflags' function. */
+#cmakedefine HAVE_FCHFLAGS 1
+
+/* Define to 1 if you have the `fchmod' function. */
+#cmakedefine HAVE_FCHMOD 1
+
+/* Define to 1 if you have the `fchown' function. */
+#cmakedefine HAVE_FCHOWN 1
+
+/* Define to 1 if you have the `fcntl' function. */
+#cmakedefine HAVE_FCNTL 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#cmakedefine HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fork' function. */
+#cmakedefine HAVE_FORK 1
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#cmakedefine HAVE_FSEEKO 1
+
+/* Define to 1 if you have the `fsetxattr' function. */
+#cmakedefine HAVE_FSETXATTR 1
+
+/* Define to 1 if you have the `fstat' function. */
+#cmakedefine HAVE_FSTAT 1
+
+/* Define to 1 if you have the `ftruncate' function. */
+#cmakedefine HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have the `futimens' function. */
+#cmakedefine HAVE_FUTIMENS 1
+
+/* Define to 1 if you have the `futimes' function. */
+#cmakedefine HAVE_FUTIMES 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#cmakedefine HAVE_GETEUID 1
+
+/* Define to 1 if you have the `getgrgid_r' function. */
+#cmakedefine HAVE_GETGRGID_R 1
+
+/* Define to 1 if you have the `getgrnam_r' function. */
+#cmakedefine HAVE_GETGRNAM_R 1
+
+/* Define to 1 if you have the `getpwnam_r' function. */
+#cmakedefine HAVE_GETPWNAM_R 1
+
+/* Define to 1 if you have the `getpwuid_r' function. */
+#cmakedefine HAVE_GETPWUID_R 1
+
+/* Define to 1 if you have the `getpid' function. */
+#cmakedefine HAVE_GETPID 1
+
+/* Define to 1 if you have the `getxattr' function. */
+#cmakedefine HAVE_GETXATTR 1
+
+/* Define to 1 if you have the <grp.h> header file. */
+#cmakedefine HAVE_GRP_H 1
+
+/* Define to 1 if the system has the type `intmax_t'. */
+#cmakedefine HAVE_INTMAX_T 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#cmakedefine HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <io.h> header file. */
+#cmakedefine HAVE_IO_H 1
+
+/* Define to 1 if you have the <langinfo.h> header file. */
+#cmakedefine HAVE_LANGINFO_H 1
+
+/* Define to 1 if you have the `lchflags' function. */
+#cmakedefine HAVE_LCHFLAGS 1
+
+/* Define to 1 if you have the `lchmod' function. */
+#cmakedefine HAVE_LCHMOD 1
+
+/* Define to 1 if you have the `lchown' function. */
+#cmakedefine HAVE_LCHOWN 1
+
+/* Define to 1 if you have the `lgetxattr' function. */
+#cmakedefine HAVE_LGETXATTR 1
+
+/* Define to 1 if you have the `acl' library (-lacl). */
+#cmakedefine HAVE_LIBACL 1
+
+/* Define to 1 if you have the `attr' library (-lattr). */
+#cmakedefine HAVE_LIBATTR 1
+
+/* Define to 1 if you have the `bsdxml' library (-lbsdxml). */
+#cmakedefine HAVE_LIBBSDXML 1
+
+/* Define to 1 if you have the `bz2' library (-lbz2). */
+#cmakedefine HAVE_LIBBZ2 1
+
+/* Define to 1 if you have the `expat' library (-lexpat). */
+#cmakedefine HAVE_LIBEXPAT 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 `xml2' library (-lxml2). */
+#cmakedefine HAVE_LIBXML2 1
+
+/* Define to 1 if you have the <libxml/xmlreader.h> header file. */
+#cmakedefine HAVE_LIBXML_XMLREADER_H 1
+
+/* Define to 1 if you have the `z' library (-lz). */
+#cmakedefine HAVE_LIBZ 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#cmakedefine HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the link() function. */
+#cmakedefine HAVE_LINK 1
+
+/* Define to 1 if you have the <linux/fs.h> header file. */
+#cmakedefine HAVE_LINUX_FS_H 1
+
+/* Define to 1 if you have the `listxattr' function. */
+#cmakedefine HAVE_LISTXATTR 1
+
+/* Define to 1 if you have the `llistxattr' function. */
+#cmakedefine HAVE_LLISTXATTR 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#cmakedefine HAVE_LOCALE_H 1
+
+/* Define to 1 if the system has the type `long long int'. */
+#cmakedefine HAVE_LONG_LONG_INT 1
+
+/* Define to 1 if you have the `lsetxattr' function. */
+#cmakedefine HAVE_LSETXATTR 1
+
+/* Define to 1 if you have the `lstat' function. */
+#cmakedefine HAVE_LSTAT 1
+
+/* Define to 1 if `lstat' has the bug that it succeeds when given the
+ zero-length file name argument. */
+#cmakedefine HAVE_LSTAT_EMPTY_STRING_BUG 1
+
+/* Define to 1 if you have the `lutimes' function. */
+#cmakedefine HAVE_LUTIMES 1
+
+/* Define to 1 if you have the <lzmadec.h> header file. */
+#cmakedefine HAVE_LZMADEC_H 1
+
+/* Define to 1 if you have the <lzma.h> header file. */
+#cmakedefine HAVE_LZMA_H 1
+
+/* Define to 1 if you have the `memmove' function. */
+#cmakedefine HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#cmakedefine HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mkdir' function. */
+#cmakedefine HAVE_MKDIR 1
+
+/* Define to 1 if you have the `mkfifo' function. */
+#cmakedefine HAVE_MKFIFO 1
+
+/* Define to 1 if you have the `mknod' function. */
+#cmakedefine HAVE_MKNOD 1
+
+/* 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 `nl_langinfo' function. */
+#cmakedefine HAVE_NL_LANGINFO 1
+
+/* Define to 1 if you have the <paths.h> header file. */
+#cmakedefine HAVE_PATHS_H 1
+
+/* Define to 1 if you have the `pipe' function. */
+#cmakedefine HAVE_PIPE 1
+
+/* Define to 1 if you have the `poll' function. */
+#cmakedefine HAVE_POLL 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#cmakedefine HAVE_POLL_H 1
+
+/* Define to 1 if you have the <process.h> header file. */
+#cmakedefine HAVE_PROCESS_H 1
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#cmakedefine HAVE_PWD_H 1
+
+/* Define to 1 if you have the `readlink' function. */
+#cmakedefine HAVE_READLINK 1
+
+/* Define to 1 if you have the <regex.h> header file. */
+#cmakedefine HAVE_REGEX_H 1
+
+/* Define to 1 if you have the `select' function. */
+#cmakedefine HAVE_SELECT 1
+
+/* Define to 1 if you have the `setenv' function. */
+#cmakedefine HAVE_SETENV 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#cmakedefine HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `sigaction' function. */
+#cmakedefine HAVE_SIGACTION 1
+
+/* Define to 1 if you have the <signal.h> header file. */
+#cmakedefine HAVE_SIGNAL_H 1
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+ zero-length file name argument. */
+#cmakedefine HAVE_STAT_EMPTY_STRING_BUG 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#cmakedefine HAVE_STDARG_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#cmakedefine HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#cmakedefine HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strchr' function. */
+#cmakedefine HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strdup' function. */
+#cmakedefine HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#cmakedefine HAVE_STRERROR 1
+
+/* Define to 1 if you have the `strerror_r' function. */
+#cmakedefine HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the `strftime' function. */
+#cmakedefine HAVE_STRFTIME 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#cmakedefine HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#cmakedefine HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strrchr' function. */
+#cmakedefine HAVE_STRRCHR 1
+
+/* Define to 1 if `st_birthtime' is member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_BIRTHTIME 1
+
+/* Define to 1 if `st_birthtimespec.tv_nsec' is member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1
+
+/* Define to 1 if `st_blksize' is member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_BLKSIZE 1
+
+/* Define to 1 if `st_flags' is member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_FLAGS 1
+
+/* Define to 1 if `st_mtimespec.tv_nsec' is member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1
+
+/* Define to 1 if `st_mtime_n' is member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_MTIME_N 1
+
+/* Define to 1 if `st_mtime_usec' is member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_MTIME_USEC 1
+
+/* Define to 1 if `st_mtim.tv_nsec' is member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1
+
+/* Define to 1 if `st_umtime' is member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_UMTIME 1
+
+/* Define to 1 if you have the symlink() function. */
+#cmakedefine HAVE_SYMLINK 1
+
+/* Define to 1 if you have the <sys/acl.h> header file. */
+#cmakedefine HAVE_SYS_ACL_H 1
+
+/* Define to 1 if you have the <sys/cdefs.h> header file. */
+#cmakedefine HAVE_SYS_CDEFS_H 1
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+#cmakedefine HAVE_SYS_DIR_H 1
+
+/* Define to 1 if you have the <sys/extattr.h> header file. */
+#cmakedefine HAVE_SYS_EXTATTR_H 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#cmakedefine HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/mkdev.h> header file. */
+#cmakedefine HAVE_SYS_MKDEV_H 1
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+#cmakedefine HAVE_SYS_NDIR_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#cmakedefine HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+#cmakedefine HAVE_SYS_POLL_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#cmakedefine HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#cmakedefine HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#cmakedefine HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#cmakedefine HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+#cmakedefine HAVE_SYS_UTIME_H 1
+
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+#cmakedefine HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <sys/xattr.h> header file. */
+#cmakedefine HAVE_SYS_XATTR_H 1
+
+/* Define to 1 if you have the `timegm' function. */
+#cmakedefine HAVE_TIMEGM 1
+
+/* Define to 1 if you have the <time.h> header file. */
+#cmakedefine HAVE_TIME_H 1
+
+/* Define to 1 if you have the `tzset' function. */
+#cmakedefine HAVE_TZSET 1
+
+/* Define to 1 if the system has the type `uintmax_t'. */
+#cmakedefine HAVE_UINTMAX_T 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#cmakedefine HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `unsetenv' function. */
+#cmakedefine HAVE_UNSETENV 1
+
+/* Define to 1 if the system has the type `unsigned long long'. */
+#cmakedefine HAVE_UNSIGNED_LONG_LONG 1
+
+/* Define to 1 if the system has the type `unsigned long long int'. */
+#cmakedefine HAVE_UNSIGNED_LONG_LONG_INT 1
+
+/* Define to 1 if you have the `utime' function. */
+#cmakedefine HAVE_UTIME 1
+
+/* Define to 1 if you have the `utimensat' function. */
+#cmakedefine HAVE_UTIMENSAT 1
+
+/* Define to 1 if you have the `utimes' function. */
+#cmakedefine HAVE_UTIMES 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#cmakedefine HAVE_UTIME_H 1
+
+/* Define to 1 if you have the `vfork' function. */
+#cmakedefine HAVE_VFORK 1
+
+/* Define to 1 if you have the `vprintf' function. */
+#cmakedefine HAVE_VPRINTF 1
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#cmakedefine HAVE_WCHAR_H 1
+
+/* Define to 1 if the system has the type `wchar_t'. */
+#cmakedefine HAVE_WCHAR_T 1
+
+/* Define to 1 if you have the `wcrtomb' function. */
+#cmakedefine HAVE_WCRTOMB 1
+
+/* Define to 1 if you have the `wcscmp' function. */
+#cmakedefine HAVE_WCSCMP 1
+
+/* Define to 1 if you have the `wcscpy' function. */
+#cmakedefine HAVE_WCSCPY 1
+
+/* Define to 1 if you have the `wcslen' function. */
+#cmakedefine HAVE_WCSLEN 1
+
+/* Define to 1 if you have the `wctomb' function. */
+#cmakedefine HAVE_WCTOMB 1
+
+/* Define to 1 if you have the <wctype.h> header file. */
+#cmakedefine HAVE_WCTYPE_H 1
+
+/* Define to 1 if you have the <windows.h> header file. */
+#cmakedefine HAVE_WINDOWS_H 1
+
+/* Define to 1 if you have _CrtSetReportMode in <crtdbg.h> */
+#cmakedefine HAVE__CrtSetReportMode 1
+
+/* Define to 1 if you have the `wmemcmp' function. */
+#cmakedefine HAVE_WMEMCMP 1
+
+/* Define to 1 if you have the `wmemcpy' function. */
+#cmakedefine HAVE_WMEMCPY 1
+
+/* Define to 1 if you have the <zlib.h> header file. */
+#cmakedefine HAVE_ZLIB_H 1
+
+/* Version number of libarchive as a single integer */
+#cmakedefine LIBARCHIVE_VERSION_NUMBER "${LIBARCHIVE_VERSION_NUMBER}"
+
+/* Version number of libarchive */
+#cmakedefine LIBARCHIVE_VERSION_STRING "${LIBARCHIVE_VERSION_STRING}"
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+ slash. */
+#cmakedefine LSTAT_FOLLOWS_SLASHED_SYMLINK 1
+
+/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
+ */
+#cmakedefine MAJOR_IN_MKDEV 1
+
+/* Define to 1 if `major', `minor', and `makedev' are declared in
+ <sysmacros.h>. */
+#cmakedefine MAJOR_IN_SYSMACROS 1
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#cmakedefine NO_MINUS_C_MINUS_O 1
+
+/* The size of `wchar_t', as computed by sizeof. */
+#cmakedefine SIZEOF_WCHAR_T ${SIZEOF_WCHAR_T}
+
+/* Define to 1 if strerror_r returns char *. */
+#cmakedefine STRERROR_R_CHAR_P 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#cmakedefine TIME_WITH_SYS_TIME 1
+
+/* Version number of package */
+#cmakedefine VERSION "${VERSION}"
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS}
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+#cmakedefine _LARGEFILE_SOURCE 1
+
+/* Define for large files, on AIX-style hosts. */
+#cmakedefine _LARGE_FILES ${_LARGE_FILES}
+
+/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+#cmakedefine _UINT64_T
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#cmakedefine const ${const}
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#cmakedefine gid_t ${gid_t}
+
+/* Define to `unsigned long' if <sys/types.h> does not define. */
+#cmakedefine id_t ${id_t}
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#cmakedefine int32_t ${int32_t}
+
+/* Define to the type of a signed integer type of width exactly 64 bits if
+ such a type exists and the standard includes do not define it. */
+#cmakedefine int64_t ${int64_t}
+
+/* Define to the widest signed integer type if <stdint.h> and <inttypes.h> do
+ not define. */
+#cmakedefine intmax_t ${intmax_t}
+
+/* Define to `int' if <sys/types.h> does not define. */
+#cmakedefine mode_t ${mode_t}
+
+/* Define to `long long' if <sys/types.h> does not define. */
+#cmakedefine off_t ${off_t}
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#cmakedefine pid_t ${pid_t}
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#cmakedefine size_t ${size_t}
+
+/* Define to `int' if <sys/types.h> does not define. */
+#cmakedefine ssize_t ${ssize_t}
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#cmakedefine uid_t ${uid_t}
+
+/* Define to `unsigned short' if <sys/types.h> doesn't define. */
+#cmakedefine uint16_t ${uint16_t}
+
+/* Define to `unsigned int' if <sys/types.h> doesn't define. */
+#cmakedefine uint32_t ${uint32_t}
+
+/* Define to the type of an unsigned integer type of width exactly 64 bits if
+ such a type exists and the standard includes do not define it. */
+#cmakedefine uint64_t ${uint64_t}
+
+/* Define to the widest unsigned integer type if <stdint.h> and <inttypes.h>
+ do not define. */
+#cmakedefine uintmax_t ${uintmax_t}
+
+/* Define to `int' if <sys/types.h> does not define. */
+#cmakedefine intptr_t ${intptr_t}
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#cmakedefine uintptr_t ${uintptr_t}
diff --git a/build/pkgconfig/libarchive.pc.in b/build/pkgconfig/libarchive.pc.in
new file mode 100644
index 000000000000..5f1d6a63d03c
--- /dev/null
+++ b/build/pkgconfig/libarchive.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libarchive
+Description: library that can create and read several streaming archive formats
+Version: @VERSION@
+Libs: -larchive
+Libs.private: @LIBS@
diff --git a/build/version b/build/version
new file mode 100644
index 000000000000..4f810f734517
--- /dev/null
+++ b/build/version
@@ -0,0 +1 @@
+2008005
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 000000000000..5a93cd674e6f
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,508 @@
+dnl Process this file with autoconf to produce a configure script.
+
+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],[2.8.5])
+m4_define([LIBARCHIVE_VERSION_N],[2008005])
+
+dnl bsdtar and bsdcpio versioning tracks libarchive
+m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S())
+m4_define([BSDCPIO_VERSION_S],LIBARCHIVE_VERSION_S())
+
+#
+# Now starts the "real" configure script.
+#
+
+AC_INIT([libarchive],LIBARCHIVE_VERSION_S(),[kientzle@freebsd.org])
+# Make sure the srcdir contains "libarchive" directory
+AC_CONFIG_SRCDIR([libarchive])
+# Use auxiliary subscripts from this subdirectory (cleans up root)
+AC_CONFIG_AUX_DIR([build/autoconf])
+# M4 scripts
+AC_CONFIG_MACRO_DIR([build/autoconf])
+# Must follow AC_CONFIG macros above...
+AM_INIT_AUTOMAKE()
+
+# Libtool versioning uses different conventions on different
+# platforms. At least on FreeBSD, libtool uses an overly complex
+# convention that attempts to solve problems that most people just
+# don't have and which just causes confusion for most end users.
+ARCHIVE_MAJOR=$(( LIBARCHIVE_VERSION_N() / 1000000 ))
+ARCHIVE_MINOR=$(( (LIBARCHIVE_VERSION_N() / 1000) % 1000 ))
+ARCHIVE_REVISION=$(( LIBARCHIVE_VERSION_N() % 1000 ))
+ARCHIVE_LIBTOOL_MAJOR=`echo $((${ARCHIVE_MAJOR} + ${ARCHIVE_MINOR}))`
+ARCHIVE_LIBTOOL_VERSION=$ARCHIVE_LIBTOOL_MAJOR:$ARCHIVE_REVISION:$ARCHIVE_MINOR
+
+# Stick the version numbers into config.h
+AC_DEFINE([LIBARCHIVE_VERSION_STRING],"LIBARCHIVE_VERSION_S()",
+ [Version number of libarchive])
+AC_DEFINE_UNQUOTED([LIBARCHIVE_VERSION_NUMBER],"LIBARCHIVE_VERSION_N()",
+ [Version number of libarchive as a single integer])
+AC_DEFINE([BSDCPIO_VERSION_STRING],"BSDCPIO_VERSION_S()",
+ [Version number of bsdcpio])
+AC_DEFINE([BSDTAR_VERSION_STRING],"BSDTAR_VERSION_S()",
+ [Version number of bsdtar])
+
+# The shell variables here must be the same as the AC_SUBST() variables
+# below, but the shell variable names apparently cannot be the same as
+# the m4 macro names above. Why? Ask autoconf.
+BSDCPIO_VERSION_STRING=BSDCPIO_VERSION_S()
+BSDTAR_VERSION_STRING=BSDTAR_VERSION_S()
+LIBARCHIVE_VERSION_STRING=LIBARCHIVE_VERSION_S()
+LIBARCHIVE_VERSION_NUMBER=LIBARCHIVE_VERSION_N()
+
+# Substitute the above version numbers into the various files below.
+# Yes, I believe this is the fourth time we define what are essentially
+# the same symbols. Why? Ask autoconf.
+AC_SUBST(ARCHIVE_LIBTOOL_VERSION)
+AC_SUBST(BSDCPIO_VERSION_STRING)
+AC_SUBST(BSDTAR_VERSION_STRING)
+AC_SUBST(LIBARCHIVE_VERSION_STRING)
+AC_SUBST(LIBARCHIVE_VERSION_NUMBER)
+
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([build/pkgconfig/libarchive.pc])
+
+# Check for host type
+AC_CANONICAL_HOST
+
+dnl Compilation on mingw and Cygwin needs special Makefile rules
+inc_windows_files=no
+inc_cygwin_files=no
+case "$host_os" in
+ *mingw* ) inc_windows_files=yes ;;
+ *cygwin*) inc_cygwin_files=yes ;;
+esac
+AM_CONDITIONAL([INC_WINDOWS_FILES], [test $inc_windows_files = yes])
+AM_CONDITIONAL([INC_CYGWIN_FILES], [test $inc_cygwin_files = yes])
+
+dnl Defines that are required for specific platforms (e.g. -D_POSIX_SOURCE, etc)
+PLATFORMCPPFLAGS=
+case "$host_os" in
+ *mingw* ) PLATFORMCPPFLAGS=-D__USE_MINGW_ANSI_STDIO ;;
+esac
+AC_SUBST(PLATFORMCPPFLAGS)
+
+# Checks for programs.
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_USE_SYSTEM_EXTENSIONS
+AC_LIBTOOL_WIN32_DLL
+AC_PROG_LIBTOOL
+AC_CHECK_TOOL([STRIP],[strip])
+
+#
+# Options for building bsdtar.
+#
+# Default is to build bsdtar, but allow people to override that.
+#
+AC_ARG_ENABLE([bsdtar],
+ [AS_HELP_STRING([--enable-bsdtar], [enable build of bsdtar (default)])
+ AS_HELP_STRING([--enable-bsdtar=static], [force static build of bsdtar])
+ AS_HELP_STRING([--enable-bsdtar=shared], [force dynamic build of bsdtar])
+AS_HELP_STRING([--disable-bsdtar], [disable build of bsdtar])],
+ [], [enable_bsdtar=yes])
+
+case "$enable_bsdtar" in
+yes)
+ if test "$enable_static" = "no"; then
+ static_bsdtar=no
+ else
+ static_bsdtar=yes
+ fi
+ build_bsdtar=yes
+ ;;
+dynamic|shared)
+ if test "$enable_shared" = "no"; then
+ AC_MSG_FAILURE([Shared linking of bsdtar requires shared libarchive])
+ fi
+ build_bsdtar=yes
+ static_bsdtar=no
+ ;;
+static)
+ build_bsdtar=yes
+ static_bsdtar=yes
+ ;;
+no)
+ build_bsdtar=no
+ static_bsdtar=no
+ ;;
+*)
+ AC_MSG_FAILURE([Unsupported value for --enable-bsdtar])
+ ;;
+esac
+
+AM_CONDITIONAL([BUILD_BSDTAR], [ test "$build_bsdtar" = yes ])
+AM_CONDITIONAL([STATIC_BSDTAR], [ test "$static_bsdtar" = yes ])
+
+#
+# Options for building bsdcpio.
+#
+# Default is not to build bsdcpio, but that can be overridden.
+#
+AC_ARG_ENABLE([bsdcpio],
+ [AS_HELP_STRING([--enable-bsdcpio], [enable build of bsdcpio (default)])
+ AS_HELP_STRING([--enable-bsdcpio=static], [static build of bsdcpio])
+ AS_HELP_STRING([--enable-bsdcpio=shared], [dynamic build of bsdcpio])
+AS_HELP_STRING([--disable-bsdcpio], [disable build of bsdcpio])],
+ [], [enable_bsdcpio=yes])
+
+case "$enable_bsdcpio" in
+yes)
+ if test "$enable_static" = "no"; then
+ static_bsdcpio=no
+ else
+ static_bsdcpio=yes
+ fi
+ build_bsdcpio=yes
+ ;;
+dynamic|shared)
+ if test "$enabled_shared" = "no"; then
+ AC_MSG_FAILURE([Shared linking of bsdcpio requires shared libarchive])
+ fi
+ build_bsdcpio=yes
+ ;;
+static)
+ build_bsdcpio=yes
+ static_bsdcpio=yes
+ ;;
+no)
+ build_bsdcpio=no
+ static_bsdcpio=no
+ ;;
+*)
+ AC_MSG_FAILURE([Unsupported value for --enable-bsdcpio])
+ ;;
+esac
+
+AM_CONDITIONAL([BUILD_BSDCPIO], [ test "$build_bsdcpio" = yes ])
+AM_CONDITIONAL([STATIC_BSDCPIO], [ test "$static_bsdcpio" = yes ])
+
+# Set up defines needed before including any headers
+case $host in
+ *mingw* | *cygwin* )
+ AC_DEFINE([_WIN32_WINNT], 0x0500, [Define to '0x0500' for Windows 2000 APIs.])
+ AC_DEFINE([WINVER], 0x0500, [Define to '0x0500' for Windows 2000 APIs.])
+ ;;
+esac
+
+# Checks for header files.
+AC_HEADER_DIRENT
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS([acl/libacl.h attr/xattr.h ctype.h errno.h])
+AC_CHECK_HEADERS([ext2fs/ext2_fs.h fcntl.h grp.h])
+AC_CHECK_HEADERS([inttypes.h io.h langinfo.h limits.h linux/fs.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 sys/mkdev.h])
+AC_CHECK_HEADERS([sys/param.h sys/poll.h sys/select.h sys/time.h sys/utime.h])
+AC_CHECK_HEADERS([time.h unistd.h utime.h wchar.h wctype.h windows.h])
+
+# Checks for libraries.
+AC_ARG_WITH([zlib],
+ AS_HELP_STRING([--without-zlib], [Don't build support for gzip through zlib]))
+
+if test "x$with_zlib" != "xno"; then
+ AC_CHECK_HEADERS([zlib.h])
+ AC_CHECK_LIB(z,inflate)
+fi
+
+AC_ARG_WITH([bz2lib],
+ AS_HELP_STRING([--without-bz2lib], [Don't build support for bzip2 through bz2lib]))
+
+if test "x$with_bz2lib" != "xno"; then
+ AC_CHECK_HEADERS([bzlib.h])
+ AC_CHECK_LIB(bz2,BZ2_bzDecompressInit)
+fi
+
+AC_ARG_WITH([lzmadec],
+ AS_HELP_STRING([--without-lzmadec], [Don't build support for lzma through lzmadec]))
+
+if test "x$with_lzmadec" != "xno"; then
+ AC_CHECK_HEADERS([lzmadec.h])
+ AC_CHECK_LIB(lzmadec,lzmadec_decode)
+fi
+
+AC_ARG_WITH([lzma],
+ AS_HELP_STRING([--without-lzma], [Don't build support for xz through lzma]))
+
+if test "x$with_lzma" != "xno"; then
+ AC_CHECK_HEADERS([lzma.h])
+ AC_CHECK_LIB(lzma,lzma_stream_decoder)
+fi
+
+AC_ARG_WITH([openssl],
+ AS_HELP_STRING([--without-openssl], [Don't build support for mtree and xar hashes through openssl]))
+
+AC_ARG_WITH([xml2],
+ AS_HELP_STRING([--without-xml2], [Don't build support for xar through libxml2]))
+AC_ARG_WITH([expat],
+ AS_HELP_STRING([--without-expat], [Don't build support for xar through expat]))
+
+if test "x$with_xml2" != "xno"; then
+ AC_PATH_PROG([XML2_CONFIG], [xml2-config],, [${PATH}])
+ if test "x$XML2_CONFIG" != "x"; then
+ CPPFLAGS="${CPPFLAGS} `${XML2_CONFIG} --cflags`"
+ LIBS="${LIBS} `${XML2_CONFIG} --libs`"
+ fi
+ AC_CHECK_HEADERS([libxml/xmlreader.h])
+ AC_CHECK_LIB(xml2,xmlInitParser)
+fi
+if test "x$ac_cv_header_libxml_xmlreader_h" != "xyes"; then
+ if test "x$with_expat" != "xno"; then
+ AC_CHECK_HEADERS([expat.h])
+ AC_CHECK_LIB(expat,XML_ParserCreate)
+ fi
+fi
+
+AC_DEFUN([MD_CHECK], [
+ if test "$found_$1" != yes; then
+ saved_LIBS="$LIBS"
+ saved_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS -I$srcdir/libarchive"
+ if test $ac_cv_header_sys_types_h = yes; then
+ CPPFLAGS="$CPPFLAGS -DHAVE_SYS_TYPES_H=1"
+ fi
+ LIBS="$LIBS $4"
+ AC_MSG_CHECKING([support for ARCHIVE_HASH_$1_$2])
+ AC_LINK_IFELSE([
+#define $1_COMPILE_TEST
+#define ARCHIVE_HASH_$1_$2
+#define __LIBARCHIVE_BUILD
+#include "archive_hash.h"
+
+int
+main(int argc, char **argv)
+{
+ archive_$3_ctx ctx;
+
+ archive_$3_init(&ctx);
+ archive_$3_update(&ctx, *argv, argc);
+ archive_$3_final(&ctx, *argv);
+ return 0;
+}
+],
+ [ AC_MSG_RESULT([yes])
+ found_$1=yes
+ mdLIBS="$mdLIBS $4"
+ AC_DEFINE(ARCHIVE_HASH_$1_$2, 1, [ $1 via ARCHIVE_HASH_$1_$2 supported.])
+ ],
+ [ AC_MSG_RESULT([no])])
+ LIBS="$saved_LIBS"
+ CPPFLAGS="$saved_CPPFLAGS"
+ fi
+])
+
+MD_CHECK(MD5, LIBC, md5)
+MD_CHECK(MD5, LIBSYSTEM, md5)
+MD_CHECK(RMD160, LIBC, rmd160)
+MD_CHECK(SHA1, LIBC, sha1)
+MD_CHECK(SHA1, LIBSYSTEM, sha1)
+MD_CHECK(SHA256, LIBC, sha256)
+MD_CHECK(SHA256, LIBC2, sha256)
+MD_CHECK(SHA256, LIBC3, sha256)
+MD_CHECK(SHA256, LIBSYSTEM, sha256)
+MD_CHECK(SHA384, LIBC, sha384)
+MD_CHECK(SHA384, LIBC2, sha384)
+MD_CHECK(SHA384, LIBC3, sha384)
+MD_CHECK(SHA384, LIBSYSTEM, sha384)
+MD_CHECK(SHA512, LIBC, sha512)
+MD_CHECK(SHA512, LIBC2, sha512)
+MD_CHECK(SHA512, LIBC3, sha512)
+MD_CHECK(SHA512, LIBSYSTEM, sha512)
+
+if test "x$with_openssl" != "xno"; then
+ MD_CHECK(MD5, OPENSSL, md5, -lcrypto)
+ MD_CHECK(RMD160, OPENSSL, rmd160, -lcrypto)
+ MD_CHECK(SHA1, OPENSSL, sha1, -lcrypto)
+ MD_CHECK(SHA256, OPENSSL, sha256, -lcrypto)
+ MD_CHECK(SHA384, OPENSSL, sha384, -lcrypto)
+ MD_CHECK(SHA512, OPENSSL, sha512, -lcrypto)
+fi
+LIBS="$LIBS $mdLIBS"
+
+# TODO: Give the user the option of using a pre-existing system
+# libarchive. This will define HAVE_LIBARCHIVE which will cause
+# bsdtar_platform.h to use #include <...> for the libarchive headers.
+# Need to include Makefile.am magic to link against system
+# -larchive in that case.
+#AC_CHECK_LIB(archive,archive_version)
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+# AC_TYPE_UID_T defaults to "int", which is incorrect for MinGW
+# and MSVC. Use a customized version.
+la_TYPE_UID_T
+AC_TYPE_MODE_T
+# AC_TYPE_OFF_T defaults to "long", which limits us to 4GB files on
+# most systems... default to "long long" instead.
+AC_CHECK_TYPE(off_t, [long long])
+AC_TYPE_SIZE_T
+AC_CHECK_TYPE(id_t, [unsigned long])
+AC_CHECK_TYPE(uintptr_t, [unsigned int])
+
+# Check for birthtime in struct stat
+AC_CHECK_MEMBERS([struct stat.st_birthtime])
+
+# Check for high-resolution timestamps in struct stat
+AC_CHECK_MEMBERS([struct stat.st_birthtimespec.tv_nsec])
+AC_CHECK_MEMBERS([struct stat.st_mtimespec.tv_nsec])
+AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec])
+AC_CHECK_MEMBERS([struct stat.st_mtime_n]) # AIX
+AC_CHECK_MEMBERS([struct stat.st_umtime]) # Tru64
+AC_CHECK_MEMBERS([struct stat.st_mtime_usec]) # Hurd
+# Check for block size support in struct stat
+AC_CHECK_MEMBERS([struct stat.st_blksize])
+# Check for st_flags in struct stat (BSD fflags)
+AC_CHECK_MEMBERS([struct stat.st_flags])
+
+# If you have uintmax_t, we assume printf supports %ju
+# If you have unsigned long long, we assume printf supports %llu
+# TODO: Check for %ju and %llu support directly.
+AC_CHECK_TYPES([uintmax_t, unsigned long long])
+
+# We need int64_t, uint64_t, intmax_t, and uintmax_t
+AC_TYPE_INTMAX_T
+AC_TYPE_INT64_T
+AC_TYPE_UINTMAX_T
+AC_TYPE_UINT64_T
+
+# TODO: If any of these are missing, define them right here.
+AC_CHECK_DECLS([SIZE_MAX, SSIZE_MAX, INT64_MAX, INT64_MIN, UINT64_MAX, UINT32_MAX])
+
+AC_CHECK_DECL([EFTYPE],
+ [AC_DEFINE(HAVE_EFTYPE, 1, [A possible errno value for invalid file format errors])],
+ [],
+ [#include <errno.h>])
+AC_CHECK_DECL([EILSEQ],
+ [AC_DEFINE(HAVE_EILSEQ, 1, [A possible errno value for invalid file format errors])],
+ [],
+ [#include <errno.h>])
+AC_CHECK_TYPE([wchar_t],
+ [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_[]wchar_t), 1, [Define to 1 if the system has the type `wchar_t'.])dnl
+ AC_CHECK_SIZEOF([wchar_t])],
+ [])
+
+AC_HEADER_TIME
+
+# Checks for library functions.
+AC_PROG_GCC_TRADITIONAL
+AC_HEADER_MAJOR
+AC_FUNC_FSEEKO
+AC_FUNC_MEMCMP
+AC_FUNC_LSTAT
+AC_FUNC_STAT
+AC_FUNC_STRERROR_R
+AC_FUNC_STRFTIME
+AC_FUNC_VPRINTF
+# check for:
+# CreateHardLinkA(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES)
+# 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])
+AC_CHECK_FUNCS([fchdir fchflags fchmod fchown fcntl fork])
+AC_CHECK_FUNCS([fstat ftruncate futimens futimes geteuid getpid])
+AC_CHECK_FUNCS([getgrgid_r getgrnam_r getpwnam_r getpwuid_r ])
+AC_CHECK_FUNCS([lchflags lchmod lchown link lstat])
+AC_CHECK_FUNCS([lutimes memmove memset mkdir mkfifo mknod])
+AC_CHECK_FUNCS([nl_langinfo pipe poll readlink])
+AC_CHECK_FUNCS([select setenv setlocale sigaction])
+AC_CHECK_FUNCS([strchr strdup strerror strncpy_s strrchr symlink timegm])
+AC_CHECK_FUNCS([tzset unsetenv utime utimensat utimes vfork])
+AC_CHECK_FUNCS([wcrtomb wcscmp wcscpy wcslen wctomb wmemcmp wmemcpy])
+# detects cygwin-1.7, as opposed to older versions
+AC_CHECK_FUNCS([cygwin_conv_path])
+
+# FreeBSD's nl_langinfo supports an option to specify whether the
+# current locale uses month/day or day/month ordering. It makes the
+# output a little prettier...
+AC_CHECK_DECL([D_MD_ORDER],
+[AC_DEFINE(HAVE_D_MD_ORDER, 1, [Define to 1 if nl_langinfo supports D_MD_ORDER])],
+[],
+[#if HAVE_LANGINFO_H
+#include <langinfo.h>
+#endif
+])
+
+# Check for dirent.d_namlen field explicitly
+# (This is a bit more straightforward than, if not quite as portable as,
+# the recipe given by the autoconf maintainers.)
+AC_CHECK_MEMBER(struct dirent.d_namlen,,,
+[#if HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+])
+
+# Check for Extended Attributes support
+AC_ARG_ENABLE([xattr],
+ AS_HELP_STRING([--disable-xattr],
+ [Enable Extended Attributes support (default: check)]))
+
+if test "x$enable_xattr" != "xno"; then
+ AC_CHECK_HEADERS([attr/xattr.h])
+ AC_CHECK_HEADERS([sys/xattr.h])
+ AC_CHECK_LIB(attr,setxattr)
+ AC_CHECK_FUNCS([extattr_get_file extattr_list_file])
+ AC_CHECK_FUNCS([extattr_set_fd extattr_set_file])
+ AC_CHECK_FUNCS([fsetxattr getxattr])
+ AC_CHECK_FUNCS([lgetxattr listxattr llistxattr lsetxattr])
+ AC_CHECK_DECLS([EXTATTR_NAMESPACE_USER], [], [], [#include <sys/types.h>
+#include <sys/extattr.h>
+])
+fi
+
+# Check for ACL support
+#
+# The ACL support in libarchive is written against the POSIX1e draft,
+# which was never officially approved and varies quite a bit across
+# platforms. Worse, some systems have completely non-POSIX acl functions,
+# which makes the following checks rather more complex than I would like.
+#
+AC_ARG_ENABLE([acl],
+ AS_HELP_STRING([--disable-acl],
+ [Enable ACL support (default: check)]))
+
+if test "x$enable_acl" != "xno"; then
+ AC_CHECK_HEADERS([sys/acl.h])
+ AC_CHECK_LIB([acl],[acl_get_file])
+ AC_CHECK_FUNCS([acl_create_entry acl_init acl_set_fd acl_set_fd_np acl_set_file])
+
+ AC_CHECK_TYPES(acl_permset_t,,,
+ [#if HAVE_SYS_TYPES_H
+ #include <sys/types.h>
+ #endif
+ #if HAVE_SYS_ACL_H
+ #include <sys/acl.h>
+ #endif
+ ])
+
+ # The "acl_get_perm()" function was omitted from the POSIX draft.
+ # (It's a pretty obvious oversight; otherwise, there's no way to
+ # test for specific permissions in a permset.) Linux uses the obvious
+ # name, FreeBSD adds _np to mark it as "non-Posix extension."
+ # Test for both as a double-check that we really have POSIX-style ACL support.
+ AC_CHECK_FUNCS(acl_get_perm_np acl_get_perm acl_get_link acl_get_link_np,,,
+ [#if HAVE_SYS_TYPES_H
+ #include <sys/types.h>
+ #endif
+ #if HAVE_SYS_ACL_H
+ #include <sys/acl.h>
+ #endif
+ ])
+
+ # MacOS has an acl.h that isn't POSIX. It can be detected by
+ # checking for ACL_USER
+ AC_CHECK_DECL([ACL_USER],
+ [AC_DEFINE(HAVE_ACL_USER, 1, [True for systems with POSIX ACL support])],
+ [],
+ [#include <sys/acl.h>])
+fi
+
+# Additional requirements
+AC_SYS_LARGEFILE
+
+AC_OUTPUT
diff --git a/contrib/README b/contrib/README
new file mode 100644
index 000000000000..2eb0114ff569
--- /dev/null
+++ b/contrib/README
@@ -0,0 +1,32 @@
+Many people have graciously sent me configuration
+files and other useful tidbits for use with libarchive.
+
+I do not support or use any of these; but if you can use them, enjoy!
+
+======================================================================
+
+From: Andre Stechert <andre@splunk.com>
+
+libarchive_autodetect-st_lib_archive.m4
+
+M4 macros for use with autoconf to detect whether a suitable
+version of libarchive is installed on this system.
+
+
+======================================================================
+
+libarchive.spec
+
+An RPM ".spec" file for building libarchive on most systems.
+This apparently was originally developed by a group at pld-linux.org.
+Several people have sent me different versions of this file.
+
+======================================================================
+
+From: Robert Meier <rm1023@dcx.com>
+
+libarchive.1aix53.spec
+
+As above, for use on AIX5.3.
+
+======================================================================
diff --git a/contrib/libarchive.1aix53.spec b/contrib/libarchive.1aix53.spec
new file mode 100644
index 000000000000..1c3bb7d1ed61
--- /dev/null
+++ b/contrib/libarchive.1aix53.spec
@@ -0,0 +1,160 @@
+# $LastChangedRevision: 8 $, $LastChangedDate: 2008-05-01 00:11:33 +0200 (št , 01 máj 2008) $
+Summary: Library to create and read several different archive formats
+Summary(pl): Biblioteka do tworzenia i odczytu rnych formatw archiww
+Name: libarchive
+Version: 2.0a3
+Release: 1aix53
+License: BSD
+Group: Libraries
+Source0: http://people.freebsd.org/~kientzle/libarchive/src/%{name}-%{version}.tar.gz
+Patch: %{name}-0123457890.patch
+URL: http://people.freebsd.org/~kientzle/libarchive/
+Requires: glibc
+Requires: zlib
+Requires: bzip2
+BuildRequires: gcc
+BuildRequires: gcc-c++
+BuildRequires: gawk
+BuildRequires: zlib-devel
+BuildRequires: bzip2
+BuildRoot: %{_tmppath}/%{name}-%{version}-build
+
+%description
+Libarchive is a programming library that can create and read several
+different streaming archive formats, including most popular TAR
+variants and several CPIO formats. It can also write SHAR archives.
+
+%description -l pl
+Libarchive jest bibliotek suac to tworzenia i odczytu wielu
+rnych strumieniowych formatw archiww, wczajc w to popularne
+odmiany TAR oraz wiele formatw CPIO. Biblioteka ta potrafi take
+zapisywa archiwa SHAR.
+
+%package devel
+Summary: Header files for libarchive library
+Summary(pl): Pliki nagwkowe biblioteki libarchive
+Group: Development/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+Header files for libarchive library.
+
+%description devel -l pl
+Pliki nagwkowe biblioteki libarchive.
+
+%package static
+Summary: Static libarchive library
+Summary(pl): Statyczna biblioteka libarchive
+Group: Development/Libraries
+Requires: %{name}-devel = %{version}-%{release}
+
+%description static
+Static libarchive library.
+
+%description static -l pl
+Statyczna biblioteka libarchive.
+
+%package -n bsdtar
+Summary: bsdtar - tar(1) implementation based on libarchive
+Summary(pl): bsdtar - implementacja programu tar(1) oparta na libarchive
+Group: Applications/Archiving
+Requires: %{name} = %{version}-%{release}
+
+%description -n bsdtar
+bsdtar - tar(1) implementation based on libarchive.
+
+%description -n bsdtar -l pl
+bsdtar - implementacja programu tar(1), oparta na libarchive.
+
+%prep
+%setup -q
+%patch0 -p1
+
+%build
+# Specify paths to avoid use of vacpp
+# -maix64 - required to use large files with aix-5.3
+# -static - required for interoperability without copying libraries
+# -D_BSD - required to include definition of makedev
+# -X64 - required to assemble 64-bit COFF files
+mkdir -p %{buildroot}
+PATH=/opt/freeware/libexec:/opt/freeware/bin:/usr/local/bin:/usr/bin:/etc:/usr/sbin:/usr/ucb:/usr/bin/X11:/sbin:. \
+CPATH=/opt/freeware/include:/usr/local/include \
+LIBPATH=/opt/freeware/lib:/usr/local/lib:/usr/share/lib \
+LD_LIBRARY_PATH=/opt/freeware/lib:/usr/local/lib:/usr/share/lib \
+CFLAGS="$RPM_OPT_FLAGS -maix64 -static -D_BSD" \
+CXXFLAGS="$RPM_OPT_FLAGS -maix64 -static -D_BSD" \
+AR="ar -X64" \
+./configure \
+--prefix=%{_prefix} \
+--libexecdir=%{_libexecdir} \
+--mandir=%{_mandir} \
+--infodir=%{_infodir} \
+--enable-shared=yes \
+--enable-static=yes \
+| tee %{buildroot}/config.log
+make | tee %{buildroot}/make.log
+
+%install
+[ "%buildroot" != "/" ] && [ -d %buildroot ] && rm -rf %buildroot;
+make DESTDIR=%buildroot install
+# original install builds, but does install bsdtar
+cp .libs/%{name}.a %{buildroot}%{_libdir}
+cp bsdtar %{buildroot}%{_bindir}
+cp tar/bsdtar.1 %{buildroot}%{_mandir}/man1
+
+%clean
+rm -fr %buildroot
+
+%files
+%defattr(644,root,root,755)
+%{_libdir}/libarchive.a
+
+%files devel
+%defattr(644,root,root,755)
+%{_libdir}/libarchive.la
+%{_includedir}/*.h
+%doc %{_mandir}/man3/*
+%doc %{_mandir}/man5/*
+
+%files -n bsdtar
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_bindir}/bsdtar
+%doc %{_mandir}/man1/bsdtar.1*
+
+%define date %(echo `LC_ALL="C" date +"%a %b %d %Y"`)
+%changelog
+* %{date} PLD Team <feedback@pld-linux.org>
+All persons listed below can be reached at <cvs_login>@pld-linux.org
+
+$Log: libarchive.spec,v $
+Release 1aix53 2006/12/12 rm1023@dcx.com
+- tweak for aix-5.3
+- added libarchive-0123457890.patch for "0123457890" error
+- replaced libarchive-1.3.1.tar.gz with libarchive-2.0a3.tar.gz
+- removed obsolete -CVE-2006-5680.patch and -man_progname.patch
+
+Revision 1.6 2006/11/15 10:41:28 qboosh
+- BR: acl-devel,attr-devel
+- devel deps
+
+Revision 1.5 2006/11/08 22:22:25 twittner
+- up to 1.3.1
+- added BR: e2fsprogs-devel
+- added -CVE-2006-5680.patch agains entering in infinite
+loop in corrupt archives
+- added bsdtar package (bsdtar is included now in libarchive
+sources)
+- rel. 0.1 for testing
+
+Revision 1.4 2005/12/15 18:26:36 twittner
+- up to 1.2.37
+- removed -shared.patch (no longer needed)
+
+Revision 1.3 2005/10/05 17:00:12 arekm
+- up to 1.02.034
+
+Revision 1.2 2005/07/27 20:17:21 qboosh
+- typo
+
+Revision 1.1 2005/07/27 08:36:03 adamg
+- new
diff --git a/contrib/libarchive.spec b/contrib/libarchive.spec
new file mode 100644
index 000000000000..1b81f6dc964a
--- /dev/null
+++ b/contrib/libarchive.spec
@@ -0,0 +1,147 @@
+# $LastChangedRevision: 8 $, $LastChangedDate: 2008-05-01 00:11:33 +0200 (št , 01 máj 2008) $
+Summary: Library to create and read several different archive formats
+Summary(pl): Biblioteka do tworzenia i odczytu rnych formatw archiww
+Name: libarchive
+Version: 2.0a3
+Release: 1
+License: BSD
+Group: Libraries
+Source0: http://people.freebsd.org/~kientzle/libarchive/src/%{name}-%{version}.tar.gz
+Patch: %{name}-0123457890.patch
+URL: http://people.freebsd.org/~kientzle/libarchive/
+Requires: glibc
+Requires: zlib
+Requires: bzip2
+BuildRequires: gcc
+BuildRequires: gcc-c++
+BuildRequires: gawk
+BuildRequires: zlib-devel
+BuildRequires: bzip2
+BuildRoot: %{_tmppath}/%{name}-%{version}-build
+
+%description
+Libarchive is a programming library that can create and read several
+different streaming archive formats, including most popular TAR
+variants and several CPIO formats. It can also write SHAR archives.
+
+%description -l pl
+Libarchive jest bibliotek suac to tworzenia i odczytu wielu
+rnych strumieniowych formatw archiww, wczajc w to popularne
+odmiany TAR oraz wiele formatw CPIO. Biblioteka ta potrafi take
+zapisywa archiwa SHAR.
+
+%package devel
+Summary: Header files for libarchive library
+Summary(pl): Pliki nagwkowe biblioteki libarchive
+Group: Development/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+Header files for libarchive library.
+
+%description devel -l pl
+Pliki nagwkowe biblioteki libarchive.
+
+%package static
+Summary: Static libarchive library
+Summary(pl): Statyczna biblioteka libarchive
+Group: Development/Libraries
+Requires: %{name}-devel = %{version}-%{release}
+
+%description static
+Static libarchive library.
+
+%description static -l pl
+Statyczna biblioteka libarchive.
+
+%package -n bsdtar
+Summary: bsdtar - tar(1) implementation based on libarchive
+Summary(pl): bsdtar - implementacja programu tar(1) oparta na libarchive
+Group: Applications/Archiving
+Requires: %{name} = %{version}-%{release}
+
+%description -n bsdtar
+bsdtar - tar(1) implementation based on libarchive.
+
+%description -n bsdtar -l pl
+bsdtar - implementacja programu tar(1), oparta na libarchive.
+
+%prep
+%setup -q
+%patch0 -p1
+
+%build
+mkdir -p %{buildroot}
+./configure \
+--prefix=%{_prefix} \
+--libexecdir=%{_libexecdir} \
+--mandir=%{_mandir} \
+--infodir=%{_infodir} \
+--enable-shared=yes \
+--enable-static=yes \
+| tee %{buildroot}/config.log
+make | tee %{buildroot}/make.log
+
+%install
+[ "%buildroot" != "/" ] && [ -d %buildroot ] && rm -rf %buildroot;
+make DESTDIR=%buildroot install
+# original install builds, but does install bsdtar
+cp .libs/%{name}.a %{buildroot}%{_libdir}
+cp bsdtar %{buildroot}%{_bindir}
+cp tar/bsdtar.1 %{buildroot}%{_mandir}/man1
+
+%clean
+rm -fr %buildroot
+
+%files
+%defattr(644,root,root,755)
+%{_libdir}/libarchive.a
+
+%files devel
+%defattr(644,root,root,755)
+%{_libdir}/libarchive.la
+%{_includedir}/*.h
+%doc %{_mandir}/man3/*
+%doc %{_mandir}/man5/*
+
+%files -n bsdtar
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_bindir}/bsdtar
+%doc %{_mandir}/man1/bsdtar.1*
+
+%define date %(echo `LC_ALL="C" date +"%a %b %d %Y"`)
+%changelog
+* %{date} PLD Team <feedback@pld-linux.org>
+All persons listed below can be reached at <cvs_login>@pld-linux.org
+
+$Log: libarchive.spec,v $
+Release 1 2006/12/12 rm1023@dcx.com
+- added libarchive-0123457890.patch for "0123457890" error
+- replaced libarchive-1.3.1.tar.gz with libarchive-2.0a3.tar.gz
+- removed obsolete -CVE-2006-5680.patch and -man_progname.patch
+
+Revision 1.6 2006/11/15 10:41:28 qboosh
+- BR: acl-devel,attr-devel
+- devel deps
+
+Revision 1.5 2006/11/08 22:22:25 twittner
+- up to 1.3.1
+- added BR: e2fsprogs-devel
+- added -CVE-2006-5680.patch agains entering in infinite
+loop in corrupt archives
+- added bsdtar package (bsdtar is included now in libarchive
+sources)
+- rel. 0.1 for testing
+
+Revision 1.4 2005/12/15 18:26:36 twittner
+- up to 1.2.37
+- removed -shared.patch (no longer needed)
+
+Revision 1.3 2005/10/05 17:00:12 arekm
+- up to 1.02.034
+
+Revision 1.2 2005/07/27 20:17:21 qboosh
+- typo
+
+Revision 1.1 2005/07/27 08:36:03 adamg
+- new
diff --git a/contrib/libarchive_autodetect-st_lib_archive.m4 b/contrib/libarchive_autodetect-st_lib_archive.m4
new file mode 100644
index 000000000000..4419e888f240
--- /dev/null
+++ b/contrib/libarchive_autodetect-st_lib_archive.m4
@@ -0,0 +1,154 @@
+dnl
+dnl @synopsis ST_LIB_ARCHIVE([ENABLED-DEFAULT])
+dnl
+dnl This macro figures out what's necessary to link a program against an
+dnl instance of the BSD libarchive package by Tim Kientzle.
+dnl
+dnl See http://people.freebsd.org/~kientzle/libarchive/ for more info.
+dnl
+dnl It exports and substitutes the variables LIBARCHIVE_LIBS, LIBARCHIVE_LDFLAGS,
+dnl and LIBARCHIVE_CPPFLAGS to appropriate values for the identified instance of
+dnl libarchive. The values are AC_SUBST'd, so a user could, for example, simply
+dnl include @LIBARCHIVE_CPPFLAGS@ in the definition of AM_CPPFLAGS in a Makefile.am.
+dnl
+dnl ENABLED-DEFAULT is either "yes" or "no" and determines whether the default value
+dnl is --with-libarchive or --without-libarchive. It is not possible to specify a
+dnl default directory. More simply, any reasonable choice for a default should just
+dnl go into the auto-detect list.
+dnl
+dnl The macro defines the symbol HAVE_LIBARCHIVE if the library is found. You
+dnl should use autoheader to include a definition for this symbol in a config.h
+dnl file. Sample usage in a C/C++ source is as follows:
+dnl
+dnl #ifdef HAVE_LIBARCHIVE
+dnl #include <archive.h>
+dnl #endif /* HAVE_LIBARCHIVE */
+dnl
+dnl @category InstalledPackages
+dnl @author Andre Stechert <andre@splunk.com>
+dnl @version 2006-04-20
+dnl @license GPLWithACException
+
+AC_DEFUN([ST_LIB_ARCHIVE],
+[
+#
+# Handle input from the configurer and blend with the requirements from the maintainer.
+# We go through the trouble of creating a second set of variables other than the with_foo
+# variables in order to be sure that error/corner cases have been cleaned up.
+#
+# After this statement, three trusted variable are defined.
+#
+# st_lib_archive_ENABLED will be either "yes" or "no". its value determines whether
+# or not we bother with the rest of the checks and whether or not we export a
+# bunch of variables.
+#
+# st_lib_archive_LOCATION will be either "auto" or "defined". if it is "auto", then
+# we try a bunch of standard locations. if it is "defined", then we just try the value
+# provided in st_lib_archive_DIR.
+#
+# st_lib_archive_DIR will contain the string provided by the user, provided that it's
+# actually a directory.
+#
+AC_MSG_CHECKING([if libarchive is wanted])
+AC_ARG_WITH([libarchive],
+ AS_HELP_STRING([--with-libarchive=DIR], [libarchive installation directory]),
+ [if test "x$with_libarchive" = "xno" ; then
+ st_lib_archive_ENABLED=no
+ elif test "x$with_libarchive" = "xyes" ; then
+ st_lib_archive_ENABLED=yes
+ st_lib_archive_LOCATION=auto
+ else
+ st_lib_archive_ENABLED=yes
+ st_lib_archive_LOCATION=defined
+ if test -d "$with_libarchive" ; then
+ st_lib_archive_DIR="$with_libarchive"
+ else
+ AC_MSG_ERROR([$with_libarchive is not a directory])
+ fi
+ fi],
+ [if test "x$1" = "xno" ; then
+ st_lib_archive_ENABLED=no
+ elif test "x$1" = "xyes" ; then
+ st_lib_archive_ENABLED=yes
+ else
+ st_lib_archive_ENABLED=yes
+ fi])
+
+if test "$st_lib_archive_ENABLED" = "yes" ; then
+ AC_MSG_RESULT([yes])
+#
+# After this statement, one trusted variable is defined.
+#
+# st_lib_archive_LIB will be either "lib" or "lib64", depending on whether the configurer
+# specified 32, 64. The default is "lib".
+#
+ AC_MSG_CHECKING([whether to use lib or lib64])
+ AC_ARG_WITH([libarchive-bits],
+ AS_HELP_STRING([--with-libarchive-bits=32/64], [if 64, look in /lib64 on hybrid systems]),
+ [if test "x$with_libarchive_bits" = "x32" ; then
+ st_lib_archive_LIB=lib
+ elif test "x$with_libarchive_bits" = "x64" ; then
+ st_lib_archive_LIB=lib64
+ else
+ AC_MSG_ERROR([the argument must be either 32 or 64])
+ fi],
+ [st_lib_archive_LIB=lib])
+ AC_MSG_RESULT($st_lib_archive_LIB)
+#
+# Save the environment before verifying libarchive availability
+#
+ st_lib_archive_SAVECPPFLAGS="$CPPFLAGS"
+ st_lib_archive_SAVELDFLAGS="$LDFLAGS"
+ AC_LANG_SAVE
+ AC_LANG_C
+
+ if test "x$st_lib_archive_LOCATION" = "xdefined" ; then
+ CPPFLAGS="-I$st_lib_archive_DIR/include $st_lib_archive_SAVECPPFLAGS"
+ LDFLAGS="-L$st_lib_archive_DIR/$st_lib_archive_LIB $st_lib_archive_SAVELDFLAGS"
+ AC_CHECK_LIB(archive, archive_read_new, [st_lib_archive_found_lib=yes], [st_lib_archive_found_lib=no])
+ AC_CHECK_HEADER(archive.h, [st_lib_archive_found_hdr=yes], [st_lib_archive_found_hdr=no])
+ if test "x$st_lib_archive_found_lib" = "xyes" && test "x$st_lib_archive_found_hdr" = "xyes"; then
+ LIBARCHIVE_CPPFLAGS="-I$dir/include"
+ LIBARCHIVE_LDFLAGS="-L$dir/$st_lib_archive_LIB"
+ else
+ AC_MSG_ERROR([could not find libarchive in the requested location])
+ fi
+ else
+ #
+ # These are the common install directories for Linux, FreeBSD, Solaris, and Mac.
+ #
+ for dir in /usr /usr/local /usr/sfw /opt/csw /opt/local /sw
+ do
+ if test -d "$dir" ; then
+ CPPFLAGS="-I$dir/include $st_lib_archive_SAVECPPFLAGS"
+ LDFLAGS="-L$dir/$st_lib_archive_LIB $st_lib_archive_SAVELDFLAGS"
+ AC_CHECK_LIB(archive, archive_read_new, [st_lib_archive_found_lib=yes], [st_lib_archive_found_lib=no])
+ AC_CHECK_HEADER(archive.h, [st_lib_archive_found_hdr=yes], [st_lib_archive_found_hdr=no])
+ if test "x$st_lib_archive_found_lib" = "xyes" && test "x$st_lib_archive_found_hdr" = "xyes"; then
+ LIBARCHIVE_CPPFLAGS="-I$dir/include"
+ LIBARCHIVE_LDFLAGS="-L$dir/$st_lib_archive_LIB"
+ break
+ fi
+ fi
+ done
+ fi
+
+ if test "x$st_lib_archive_found_hdr" = "xyes" && test "x$st_lib_archive_found_lib" = "xyes" ; then
+ LIBARCHIVE_LIBS="-larchive"
+ AC_DEFINE([HAVE_LIBARCHIVE], [1], [Defined to 1 if libarchive is available for use.])
+ AC_SUBST(LIBARCHIVE_LIBS)
+ AC_SUBST(LIBARCHIVE_CPPFLAGS)
+ AC_SUBST(LIBARCHIVE_LDFLAGS)
+ fi
+
+#
+# Restore the environment now that we're done.
+#
+ AC_LANG_RESTORE
+ CPPFLAGS="$st_lib_archive_SAVECPPFLAGS"
+ LDFLAGS="$st_lib_archive_SAVELDFLAGS"
+else
+ AC_MSG_RESULT([no])
+fi
+AM_CONDITIONAL(LIBARCHIVE, test "x$st_lib_archive_found_lib" = "xyes" && test "x$st_lib_archive_found_hdr" = "xyes")
+])
diff --git a/contrib/psota-benchmark/results.txt b/contrib/psota-benchmark/results.txt
new file mode 100644
index 000000000000..8197b28f7eae
--- /dev/null
+++ b/contrib/psota-benchmark/results.txt
@@ -0,0 +1,122 @@
+ODP: [Bug-tar] GNU tar, star and BSD tar speed comparision +new script
+
+Jan Psota
+Thu, 25 Oct 2007 06:51:13 -0700
+
+Latest TCP script at the bottom (3180 bytes).
+4 tests: 64bit dual core Athlon tmpfs / disk (reiserfs) - 60MB/s,
+ 32bit Athlon tmpfs / disk (reiserfs) - 55MB/s
+Both machines were idle -- used for testing only.
+Tarball and extracted files were on different physical devices.
+Test data: linux 2.6.22/3 kernel sources for memory operations,
+for the other data average file size should bring enough info.
+
+2 x [...] processor means 1 processor with 2 cores (2 entries in cpuinfo).
+Archive format is set to pax (Joerg).
+Let's end with it. I only wanted to send You a new version of TCP script :-).
+
+--
+Jan Psota
+
+TCP, version 2007-10-25
+Linux 2.6.22-suspend2-r2 / Gentoo Base System release 2.0.0_rc5
+2012MB of memory, 2 x AMD Athlon(tm) 64 X2 Dual Core Processor 4200+ 2211.348
+512 KB 4426.24 bmips
+gcc (GCC) 4.2.2 (Gentoo 4.2.2 p1.0)
+CFLAGS="-O2 -march=k8 -pipe"
+
+bsdtar: bsdtar 2.3.4 - libarchive 2.3.4
+gnutar: tar (GNU tar) 1.19
+star: star: star 1.5a85 (x86_64-unknown-linux-gnu)
+
+best time of 5 repetitions,
+ src=linux-2.6.23, 291M in 23867 files, avg 13KB/file,
+ archive=/tmp/tcp.tar, extract to /tmp/tcptmp
+program operation real user system %CPU speed
+bsdtar create 0.764 0.232 0.532 99.96 370308 KB/s
+gnutar create 0.743 0.200 0.512 95.87 380775 KB/s
+star create 0.587 0.040 0.820 100.00 441247 KB/s
+
+bsdtar list 0.164 0.096 0.068 99.84 1579341 KB/s
+gnutar list 0.218 0.064 0.152 98.92 1188128 KB/s
+star list 0.359 0.044 0.240 79.09 721481 KB/s
+
+bsdtar extract 0.733 0.200 0.504 96.02 353358 KB/s
+gnutar extract 0.625 0.092 0.508 96.02 414419 KB/s
+star extract 0.875 0.096 0.980 100.00 296013 KB/s
+
+bsdtar compare 0.001 0.000 0.000 0.00 259012000 KB/s
+gnutar compare 0.719 0.288 0.400 95.66 360239 KB/s
+star compare 0.695 0.224 0.636 100.00 372679 KB/s
+
+[...]
+best time of 3 repetitions,
+ src=/home, 3.2G in 7447 files, avg 554KB/file,
+ archive=/var/tcp.tar, extract to /mnt/a/tcptmp
+program operation real user system %CPU speed
+bsdtar create 184.680 0.552 13.365 7.53 17958 KB/s
+gnutar create 159.240 0.256 12.417 7.95 20827 KB/s
+star create 181.779 0.140 14.789 8.21 18203 KB/s
+
+bsdtar list 0.053 0.032 0.016 91.41 62435471 KB/s
+gnutar list 56.535 0.136 3.764 6.89 58531 KB/s
+star list 56.652 0.080 5.236 9.38 58410 KB/s
+
+bsdtar extract 78.914 0.820 15.149 20.23 41932 KB/s
+gnutar extract 78.480 0.196 14.197 18.33 42164 KB/s
+star extract 79.439 0.132 12.973 16.49 41655 KB/s
+
+bsdtar compare 0.001 0.000 0.000 0.00 3309080000 KB/s
+gnutar compare 61.771 3.464 8.905 20.02 53570 KB/s
+star compare 57.561 1.728 9.897 20.19 57488 KB/s
+
+
+Linux 2.6.22-suspend2-smp / Gentoo Base System release 2.0.0_rc5
+504MB of memory, 1 x AMD Athlon(tm) Processor 1500.033 256 KB 3002.55 bmips
+gcc (GCC) 4.2.2 (Gentoo 4.2.2 p1.0)
+CFLAGS="-O2 -march=athlon-xp -mfpmath=sse -frename-registers -pipe"
+
+bsdtar: bsdtar 2.3.4 - libarchive 2.3.4
+gnutar: tar (GNU tar) 1.19
+star: star: star 1.5a85 (i686-pc-linux-gnu)
+
+best time of 3 repetitions,
+ src=/usr/src/linux-2.6.22-suspend2/drivers, 119M in 5900 files,
+ avg 21KB/file, archive=/tmp/tcp.tar, extract to /tmp/tcptmp
+program operation real user system %CPU speed
+bsdtar create 1.329 0.192 1.132 99.63 89784 KB/s
+gnutar create 1.223 0.124 1.092 99.46 97566 KB/s
+star create 1.848 0.036 1.708 94.36 61372 KB/s
+
+bsdtar list 0.167 0.060 0.108 100.00 679137 KB/s
+gnutar list 0.161 0.040 0.124 100.00 704447 KB/s
+star list 0.859 0.044 0.716 88.51 132032 KB/s
+
+bsdtar extract 1.186 0.172 1.012 99.87 95629 KB/s
+gnutar extract 1.064 0.056 1.004 99.63 106593 KB/s
+star extract 1.920 0.088 1.724 94.40 59070 KB/s
+
+bsdtar compare 0.002 0.000 0.000 0.00 56708000 KB/s
+gnutar compare 0.925 0.232 0.692 99.90 122611 KB/s
+star compare 1.569 0.376 1.096 93.79 72285 KB/s
+
+[...]
+best time of 3 repetitions,
+ src=/home/jasiu, 2.1G in 8416 files, avg 277KB/file,
+ archive=/home/j2/tcp.tar, extract to /mnt/a/tar/tcptmp
+program operation real user system %CPU speed
+bsdtar create 182.171 1.692 29.130 16.91 11584 KB/s
+gnutar create 174.999 0.632 27.450 16.04 12059 KB/s
+star create 180.004 0.360 41.795 23.41 11677 KB/s
+
+bsdtar list 0.214 0.076 0.136 99.04 9822294 KB/s
+gnutar list 0.210 0.076 0.136 100.00 10009385 KB/s
+star list 43.462 0.148 18.109 42.00 48363 KB/s
+
+bsdtar extract 94.912 4.476 31.574 37.98 22146 KB/s
+gnutar extract 94.657 0.396 29.462 31.54 22206 KB/s
+star extract 100.814 0.400 39.906 39.98 20849 KB/s
+
+bsdtar compare 0.003 0.000 0.004 100.00 700657000 KB/s
+gnutar compare 80.174 3.932 20.365 30.30 26217 KB/s
+star compare 73.911 8.341 27.670 48.72 28439 KB/s
diff --git a/contrib/psota-benchmark/tcp.sh b/contrib/psota-benchmark/tcp.sh
new file mode 100644
index 000000000000..6c0e4b5e92e5
--- /dev/null
+++ b/contrib/psota-benchmark/tcp.sh
@@ -0,0 +1,104 @@
+#!/bin/sh
+# tar comparision program
+# 2007-10-25 Jan Psota
+
+n=3 # number of repetitions
+TAR=(bsdtar gnutar star) # TApeArchivers to compare
+OPT=("" "--seek" "-no-fsync")
+pax="--format=pax" # comment out for defaults
+OPN=(create list extract compare) # operations
+version="2007-10-25"
+TIMEFORMAT=$'%R\t%U\t%S\t%P'
+LC_ALL=C
+
+test $# -ge 2 || {
+ echo -e "usage:\t$0 source_dir where_to_place_archive
+[where_to_extract_it]
+
+TCP, version $version
+TCP stands for Tar Comparision Program here.
+It currently compares: BSD tar (bsdtar), GNU tar (gnutar) and star in archive
+creation, listing, extraction and archive-to-extracted comparision.
+Tcp prints out best time of n=$n repetitions.
+
+Tcp creates temporary archive named tcp.tar with $pax and some native
+(--seek/-no-fsync) options and extracts it to [\$3]/tcptmp/.
+If unset, third argument defaults to [\$2].
+After normal exit tcp removes tarball and extracted files.
+Tcp does not check filesystems destination directories are on for free space,
+so make sure there is enough space (a bit more than source_dir uses) for both:
+archive and extracted files.
+Do not use white space in arguments.
+ Jan Psota, $version"
+ exit 0
+}
+src=$1
+dst=$2/tcp.tar
+dst_path=${3:-$2}/tcptmp
+test -e $dst -o -e /tmp/tcp \
+ && { echo "$dst or /tmp/tcp exists, exiting"; exit 1; }
+mkdir $dst_path || exit 2
+
+use_times ()
+{
+ awk -F"\t" -vN=$n -vL="`du -k $dst`" -vOFS="\t" -vORS="" '
+ { if (NF==4) { printf "\t%s\t%10.1d KB/s\n", $0, ($1+0>0 ?
+(L+0)/($1+0) : 0) } }' \
+ /tmp/tcp | sort | head -1
+ > /tmp/tcp
+}
+
+test -d $src || { echo "'$src' is not a directory"; exit 3; }
+
+# system information: type, release, memory, cpu(s), compiler and flags
+echo -e "TCP, version $version\n"`uname -sr`" / "`head -1 /etc/*-release`
+free -m | awk '/^Mem/ { printf "%dMB of memory, ", $2 }'
+test -e /proc/cpuinfo \
+ && awk -F: '/name|cache size|MHz|mips/ { if (!a) b=b $2 }
+ /^$/ { a++ } END { print a" x"b" bmips" }' /proc/cpuinfo
+test -e /etc/gentoo-release \
+ && gcc --version | head -1 && grep ^CFLAGS /etc/make.conf
+
+# tar versions
+echo
+for tar in [EMAIL PROTECTED]; do echo -ne "$tar:\t"; $tar --version | head -1;
+done
+
+echo -e "\nbest time of $n repetitions,\n"\
+" src=$src, "\
+`du -sh $src | awk '{print $1}'`" in "`find $src | wc -l`" files, "\
+"avg "$((`du -sk $src | awk '{print $1}'`/`find $src -type f | wc
+-l`))"KB/file,\n"\
+" archive=$dst, extract to $dst_path"
+
+echo -e "program\toperation\treal\tuser\tsystem\t%CPU\t speed"
+> /tmp/tcp
+let op_num=0
+for op in "cf $dst $pax -C $src ." "tf $dst" "xf $dst -C $dst_path" \
+ "f $dst -C $dst_path --diff"; do
+ let tar_num=0
+ for tar in [EMAIL PROTECTED]; do
+ echo -en "$tar\t${OPN[op_num]}\t"
+ for ((i=1; i<=$n; i++)); do
+ echo $op | grep -q ^cf && rm -f $dst
+ echo $op | grep -q ^xf &&
+ { chmod -R u+w $dst_path
+ rm -rf $dst_path; mkdir $dst_path; }
+ sync
+ if echo $op | grep -q ^f; then # op == compare
+ time $tar $op ${OPT[$tar_num]} > /dev/null
+ else # op in (create | list | extract)
+ time $tar $op ${OPT[$tar_num]} > /dev/null \
+ || break 3
+ fi 2>> /tmp/tcp
+ done
+ use_times
+ let tar_num++
+ done
+ let op_num++
+ echo
+done
+rm -rf $dst_path $dst
+echo
+cat /tmp/tcp
+rm -f /tmp/tcp
diff --git a/contrib/shar/Makefile b/contrib/shar/Makefile
new file mode 100644
index 000000000000..3bd94d4192cb
--- /dev/null
+++ b/contrib/shar/Makefile
@@ -0,0 +1,14 @@
+# $FreeBSD$
+
+PROG= shar
+SRCS= shar.c tree.c
+
+WARNS?= 6
+
+DPADD= ${LIBARCHIVE}
+LDADD= -larchive
+
+LINKS= ${BINDIR}/shar
+MLINKS= shar.1
+
+.include <bsd.prog.mk>
diff --git a/contrib/shar/shar.1 b/contrib/shar/shar.1
new file mode 100644
index 000000000000..e3152f299ebe
--- /dev/null
+++ b/contrib/shar/shar.1
@@ -0,0 +1,128 @@
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. 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.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)shar.1 8.1 (Berkeley) 6/6/93
+.\" $FreeBSD$
+.\"
+.Dd April 17, 2008
+.Dt SHAR 1
+.Os
+.Sh NAME
+.Nm shar
+.Nd create a shell archive of files
+.Sh SYNOPSIS
+.Nm
+.Op Fl br
+.Op Fl o Ar archive-file
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+command writes a
+.Xr sh 1
+shell script which will recreate the file hierarchy specified by the command
+line operands.
+.Pp
+The
+.Nm
+command is normally used for distributing files by
+.Xr ftp 1
+or
+.Xr mail 1 .
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl b
+Use an alternative binary format. Content of files will be uuencoded.
+This option should be used to archive binary files correctly.
+In this mode also file permissions will be stored to the archive.
+uudecode(1) is needed to extract archives created with this option.
+.It Fl o Ar archive-file
+Redirect output to
+.Ar archive-file .
+.It Fl r
+If
+.Ar file
+given on command line is a directory the entire subtree will be archived.
+Symbolic links given on command line are followed. Other symbolic links will
+be archived as such.
+.El
+.Sh EXAMPLES
+To create a shell archive of the program
+.Xr ls 1
+and mail it to Rick:
+.Bd -literal -offset indent
+cd ls
+shar -r . \&| mail -s "ls source" rick
+.Ed
+.Pp
+To recreate the program directory:
+.Bd -literal -offset indent
+mkdir ls
+cd ls
+\&...
+<delete header lines and examine mailed archive>
+\&...
+sh archive
+.Ed
+.Sh SEE ALSO
+.Xr compress 1 ,
+.Xr mail 1 ,
+.Xr tar 1 ,
+.Xr uuencode 1 ,
+.Xr uuencode 5
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.4 .
+This is a re-implementation based on the libarchive(3) library.
+.Sh BUGS
+The
+.Nm
+command makes no provisions for hard links.
+.Pp
+Files containing magic characters or files without a newline ('\\n') as the
+last character are not handled correctly with the default format. Use the -b
+option for binary files.
+.Pp
+It is easy to insert trojan horses into
+.Nm
+files.
+It is strongly recommended that all shell archive files be examined
+before running them through
+.Xr sh 1 .
+Archives produced using this implementation of
+.Nm
+may be easily examined with the command:
+.Bd -literal -offset indent
+egrep -v '^[X#]' shar.file
+.Ed
diff --git a/contrib/shar/shar.c b/contrib/shar/shar.c
new file mode 100644
index 000000000000..12c84255309f
--- /dev/null
+++ b/contrib/shar/shar.c
@@ -0,0 +1,314 @@
+/*-
+ * Copyright (c) 2008 Jaakko Heinonen
+ * 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
+ * in this position and unchanged.
+ * 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 <sys/cdefs.h>
+#ifdef __FBSDID
+__FBSDID("$FreeBSD$");
+#endif
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <archive.h>
+#include <archive_entry.h>
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "tree.h"
+
+/* command line options */
+static int b_opt; /* use alternative shar binary format */
+static int r_opt; /* recurse into subdirectories */
+static char *o_arg; /* output file name */
+
+static void
+usage(void)
+{
+ fprintf(stderr, "Usage: shar [-br] [-o filename] file ...\n");
+ exit(EX_USAGE);
+}
+
+/*
+ * Initialize archive structure and create a shar archive.
+ */
+static struct archive *
+shar_create(void)
+{
+ struct archive *a;
+
+ if ((a = archive_write_new()) == NULL)
+ errx(EXIT_FAILURE, "%s", archive_error_string(a));
+
+ if (b_opt)
+ archive_write_set_format_shar_dump(a);
+ else
+ archive_write_set_format_shar(a);
+ archive_write_set_compression_none(a);
+
+ if (archive_write_open_filename(a, o_arg) != ARCHIVE_OK)
+ errx(EX_CANTCREAT, "%s", archive_error_string(a));
+
+ return (a);
+}
+
+/* buffer for file data */
+static char buffer[32768];
+
+/*
+ * Write file data to an archive entry.
+ */
+static int
+shar_write_entry_data(struct archive *a, const int fd)
+{
+ ssize_t bytes_read, bytes_written;
+
+ assert(a != NULL);
+ assert(fd >= 0);
+
+ bytes_read = read(fd, buffer, sizeof(buffer));
+ while (bytes_read != 0) {
+ if (bytes_read < 0) {
+ archive_set_error(a, errno, "Read failed");
+ return (ARCHIVE_WARN);
+ }
+ bytes_written = archive_write_data(a, buffer, bytes_read);
+ if (bytes_written < 0)
+ return (ARCHIVE_WARN);
+ bytes_read = read(fd, buffer, sizeof(buffer));
+ }
+
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Write a file to the archive. We have special handling for symbolic links.
+ */
+static int
+shar_write_entry(struct archive *a, const char *pathname, const char *accpath,
+ const struct stat *st)
+{
+ struct archive_entry *entry;
+ int fd = -1;
+ int ret = ARCHIVE_OK;
+
+ assert(a != NULL);
+ assert(pathname != NULL);
+ assert(accpath != NULL);
+ assert(st != NULL);
+
+ entry = archive_entry_new();
+
+ if (S_ISREG(st->st_mode) && st->st_size > 0) {
+ /* regular file */
+ if ((fd = open(accpath, O_RDONLY)) == -1) {
+ warn("%s", accpath);
+ ret = ARCHIVE_WARN;
+ goto out;
+ }
+ } else if (S_ISLNK(st->st_mode)) {
+ /* symbolic link */
+ char lnkbuff[PATH_MAX + 1];
+ int lnklen;
+ if ((lnklen = readlink(accpath, lnkbuff, PATH_MAX)) == -1) {
+ warn("%s", accpath);
+ ret = ARCHIVE_WARN;
+ goto out;
+ }
+ lnkbuff[lnklen] = '\0';
+ archive_entry_set_symlink(entry, lnkbuff);
+ }
+ archive_entry_copy_stat(entry, st);
+ archive_entry_set_pathname(entry, pathname);
+ if (!S_ISREG(st->st_mode) || st->st_size == 0)
+ archive_entry_set_size(entry, 0);
+ if (archive_write_header(a, entry) != ARCHIVE_OK) {
+ warnx("%s: %s", pathname, archive_error_string(a));
+ ret = ARCHIVE_WARN;
+ goto out;
+ }
+ if (fd >= 0) {
+ if ((ret = shar_write_entry_data(a, fd)) != ARCHIVE_OK)
+ warnx("%s: %s", accpath, archive_error_string(a));
+ }
+out:
+ archive_entry_free(entry);
+ if (fd >= 0)
+ close(fd);
+
+ return (ret);
+}
+
+/*
+ * Write singe path to the archive. The path can be a regular file, directory
+ * or device. Symbolic links are followed.
+ */
+static int
+shar_write_path(struct archive *a, const char *pathname)
+{
+ struct stat st;
+
+ assert(a != NULL);
+ assert(pathname != NULL);
+
+ if ((stat(pathname, &st)) == -1) {
+ warn("%s", pathname);
+ return (ARCHIVE_WARN);
+ }
+
+ return (shar_write_entry(a, pathname, pathname, &st));
+}
+
+/*
+ * Write tree to the archive. If pathname is a symbolic link it will be
+ * followed. Other symbolic links are stored as such to the archive.
+ */
+static int
+shar_write_tree(struct archive *a, const char *pathname)
+{
+ struct tree *t;
+ const struct stat *lst, *st;
+ int error = 0;
+ int tree_ret;
+ int first;
+
+ assert(a != NULL);
+ assert(pathname != NULL);
+
+ t = tree_open(pathname);
+ for (first = 1; (tree_ret = tree_next(t)); first = 0) {
+ if (tree_ret == TREE_ERROR_DIR) {
+ warnx("%s: %s", tree_current_path(t),
+ strerror(tree_errno(t)));
+ error = 1;
+ continue;
+ } else if (tree_ret != TREE_REGULAR)
+ continue;
+ if ((lst = tree_current_lstat(t)) == NULL) {
+ warn("%s", tree_current_path(t));
+ error = 1;
+ continue;
+ }
+ /*
+ * If the symlink was given on command line then
+ * follow it rather than write it as symlink.
+ */
+ if (first && S_ISLNK(lst->st_mode)) {
+ if ((st = tree_current_stat(t)) == NULL) {
+ warn("%s", tree_current_path(t));
+ error = 1;
+ continue;
+ }
+ } else
+ st = lst;
+
+ if (shar_write_entry(a, tree_current_path(t),
+ tree_current_access_path(t), st) != ARCHIVE_OK)
+ error = 1;
+
+ tree_descend(t);
+ }
+
+ tree_close(t);
+
+ return ((error != 0) ? ARCHIVE_WARN : ARCHIVE_OK);
+}
+
+/*
+ * Create a shar archive and write files/trees into it.
+ */
+static int
+shar_write(char **fn, size_t nfn)
+{
+ struct archive *a;
+ size_t i;
+ int error = 0;
+
+ assert(fn != NULL);
+ assert(nfn > 0);
+
+ a = shar_create();
+
+ for (i = 0; i < nfn; i++) {
+ if (r_opt) {
+ if (shar_write_tree(a, fn[i]) != ARCHIVE_OK)
+ error = 1;
+ } else {
+ if (shar_write_path(a, fn[i]) != ARCHIVE_OK)
+ error = 1;
+ }
+ }
+
+ if (archive_write_finish(a) != ARCHIVE_OK)
+ errx(EXIT_FAILURE, "%s", archive_error_string(a));
+
+ if (error != 0)
+ warnx("Error exit delayed from previous errors.");
+
+ return (error);
+}
+
+int
+main(int argc, char **argv)
+{
+ int opt;
+
+ while ((opt = getopt(argc, argv, "bro:")) != -1) {
+ switch (opt) {
+ case 'b':
+ b_opt = 1;
+ break;
+ case 'o':
+ o_arg = optarg;
+ break;
+ case 'r':
+ r_opt = 1;
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if(argc < 1)
+ usage();
+
+ if (shar_write(argv, argc) != 0)
+ exit(EXIT_FAILURE);
+ else
+ exit(EXIT_SUCCESS);
+ /* NOTREACHED */
+}
+
diff --git a/contrib/shar/tree.c b/contrib/shar/tree.c
new file mode 100644
index 000000000000..d5a04abf5f4b
--- /dev/null
+++ b/contrib/shar/tree.c
@@ -0,0 +1,542 @@
+/*-
+ * 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.
+ */
+
+/*-
+ * This is a new directory-walking system that addresses a number
+ * of problems I've had with fts(3). In particular, it has no
+ * pathname-length limits (other than the size of 'int'), handles
+ * deep logical traversals, uses considerably less memory, and has
+ * an opaque interface (easier to modify in the future).
+ *
+ * Internally, it keeps a single list of "tree_entry" items that
+ * represent filesystem objects that require further attention.
+ * Non-directories are not kept in memory: they are pulled from
+ * readdir(), returned to the client, then freed as soon as possible.
+ * Any directory entry to be traversed gets pushed onto the stack.
+ *
+ * There is surprisingly little information that needs to be kept for
+ * each item on the stack. Just the name, depth (represented here as the
+ * string length of the parent directory's pathname), and some markers
+ * indicating how to get back to the parent (via chdir("..") for a
+ * regular dir or via fchdir(2) for a symlink).
+ */
+#include "tree_config.h"
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.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 "tree.h"
+
+/*
+ * TODO:
+ * 1) Loop checking.
+ * 3) Arbitrary logical traversals by closing/reopening intermediate fds.
+ */
+
+struct tree_entry {
+ struct tree_entry *next;
+ struct tree_entry *parent;
+ char *name;
+ size_t dirname_length;
+ dev_t dev;
+ ino_t ino;
+ int fd;
+ int flags;
+};
+
+/* Definitions for tree_entry.flags bitmap. */
+#define isDir 1 /* This entry is a regular directory. */
+#define isDirLink 2 /* This entry is a symbolic link to a directory. */
+#define needsPreVisit 4 /* This entry needs to be previsited. */
+#define needsPostVisit 8 /* This entry needs to be postvisited. */
+
+/*
+ * Local data for this package.
+ */
+struct tree {
+ struct tree_entry *stack;
+ struct tree_entry *current;
+ DIR *d;
+ int initialDirFd;
+ int flags;
+ int visit_type;
+ int tree_errno; /* Error code from last failed operation. */
+
+ char *buff;
+ const char *basename;
+ size_t buff_length;
+ size_t path_length;
+ size_t dirname_length;
+
+ int depth;
+ int openCount;
+ int maxOpenCount;
+
+ struct stat lst;
+ struct stat st;
+};
+
+/* Definitions for tree.flags bitmap. */
+#define needsReturn 8 /* Marks first entry as not having been returned yet. */
+#define hasStat 16 /* The st entry is set. */
+#define hasLstat 32 /* The lst entry is set. */
+
+
+#ifdef HAVE_DIRENT_D_NAMLEN
+/* BSD extension; avoids need for a strlen() call. */
+#define D_NAMELEN(dp) (dp)->d_namlen
+#else
+#define D_NAMELEN(dp) (strlen((dp)->d_name))
+#endif
+
+#if 0
+#include <stdio.h>
+void
+tree_dump(struct tree *t, FILE *out)
+{
+ struct tree_entry *te;
+
+ fprintf(out, "\tdepth: %d\n", t->depth);
+ fprintf(out, "\tbuff: %s\n", t->buff);
+ fprintf(out, "\tpwd: "); fflush(stdout); system("pwd");
+ fprintf(out, "\taccess: %s\n", t->basename);
+ fprintf(out, "\tstack:\n");
+ for (te = t->stack; te != NULL; te = te->next) {
+ fprintf(out, "\t\tte->name: %s%s%s\n", te->name,
+ te->flags & needsPreVisit ? "" : " *",
+ t->current == te ? " (current)" : "");
+ }
+}
+#endif
+
+/*
+ * Add a directory path to the current stack.
+ */
+static void
+tree_push(struct tree *t, const char *path)
+{
+ struct tree_entry *te;
+
+ te = malloc(sizeof(*te));
+ memset(te, 0, sizeof(*te));
+ te->next = t->stack;
+ t->stack = te;
+ te->fd = -1;
+ te->name = strdup(path);
+ te->flags = needsPreVisit | needsPostVisit;
+ te->dirname_length = t->dirname_length;
+}
+
+/*
+ * Append a name to the current path.
+ */
+static void
+tree_append(struct tree *t, const char *name, size_t name_length)
+{
+ char *p;
+
+ if (t->buff != NULL)
+ t->buff[t->dirname_length] = '\0';
+ /* Strip trailing '/' from name, unless entire name is "/". */
+ while (name_length > 1 && name[name_length - 1] == '/')
+ name_length--;
+
+ /* Resize pathname buffer as needed. */
+ while (name_length + 1 + t->dirname_length >= t->buff_length) {
+ t->buff_length *= 2;
+ if (t->buff_length < 1024)
+ t->buff_length = 1024;
+ t->buff = realloc(t->buff, t->buff_length);
+ }
+ p = t->buff + t->dirname_length;
+ t->path_length = t->dirname_length + name_length;
+ /* Add a separating '/' if it's needed. */
+ if (t->dirname_length > 0 && p[-1] != '/') {
+ *p++ = '/';
+ t->path_length ++;
+ }
+ strncpy(p, name, name_length);
+ p[name_length] = '\0';
+ t->basename = p;
+}
+
+/*
+ * Open a directory tree for traversal.
+ */
+struct tree *
+tree_open(const char *path)
+{
+ struct tree *t;
+
+ t = malloc(sizeof(*t));
+ memset(t, 0, sizeof(*t));
+ tree_append(t, path, strlen(path));
+ t->initialDirFd = open(".", O_RDONLY);
+ /*
+ * During most of the traversal, items are set up and then
+ * returned immediately from tree_next(). That doesn't work
+ * for the very first entry, so we set a flag for this special
+ * case.
+ */
+ t->flags = needsReturn;
+ return (t);
+}
+
+/*
+ * We've finished a directory; ascend back to the parent.
+ */
+static void
+tree_ascend(struct tree *t)
+{
+ struct tree_entry *te;
+
+ te = t->stack;
+ t->depth--;
+ if (te->flags & isDirLink) {
+ fchdir(te->fd);
+ close(te->fd);
+ t->openCount--;
+ } else {
+ chdir("..");
+ }
+}
+
+/*
+ * Pop the working stack.
+ */
+static void
+tree_pop(struct tree *t)
+{
+ struct tree_entry *te;
+
+ t->buff[t->dirname_length] = '\0';
+ if (t->stack == t->current && t->current != NULL)
+ t->current = t->current->parent;
+ te = t->stack;
+ t->stack = te->next;
+ t->dirname_length = te->dirname_length;
+ t->basename = t->buff + t->dirname_length;
+ /* Special case: starting dir doesn't skip leading '/'. */
+ if (t->dirname_length > 0)
+ t->basename++;
+ free(te->name);
+ free(te);
+}
+
+/*
+ * Get the next item in the tree traversal.
+ */
+int
+tree_next(struct tree *t)
+{
+ struct dirent *de = NULL;
+
+ /* Handle the startup case by returning the initial entry. */
+ if (t->flags & needsReturn) {
+ t->flags &= ~needsReturn;
+ return (t->visit_type = TREE_REGULAR);
+ }
+
+ while (t->stack != NULL) {
+ /* If there's an open dir, get the next entry from there. */
+ while (t->d != NULL) {
+ de = readdir(t->d);
+ if (de == NULL) {
+ closedir(t->d);
+ t->d = NULL;
+ } else if (de->d_name[0] == '.'
+ && de->d_name[1] == '\0') {
+ /* Skip '.' */
+ } else if (de->d_name[0] == '.'
+ && de->d_name[1] == '.'
+ && de->d_name[2] == '\0') {
+ /* Skip '..' */
+ } else {
+ /*
+ * Append the path to the current path
+ * and return it.
+ */
+ tree_append(t, de->d_name, D_NAMELEN(de));
+ t->flags &= ~hasLstat;
+ t->flags &= ~hasStat;
+ return (t->visit_type = TREE_REGULAR);
+ }
+ }
+
+ /* If the current dir needs to be visited, set it up. */
+ if (t->stack->flags & needsPreVisit) {
+ t->current = t->stack;
+ tree_append(t, t->stack->name, strlen(t->stack->name));
+ t->stack->flags &= ~needsPreVisit;
+ /* If it is a link, set up fd for the ascent. */
+ if (t->stack->flags & isDirLink) {
+ t->stack->fd = open(".", O_RDONLY);
+ t->openCount++;
+ if (t->openCount > t->maxOpenCount)
+ t->maxOpenCount = t->openCount;
+ }
+ t->dirname_length = t->path_length;
+ if (chdir(t->stack->name) != 0) {
+ /* chdir() failed; return error */
+ tree_pop(t);
+ t->tree_errno = errno;
+ return (t->visit_type = TREE_ERROR_DIR);
+ }
+ t->depth++;
+ t->d = opendir(".");
+ if (t->d == NULL) {
+ tree_ascend(t); /* Undo "chdir" */
+ tree_pop(t);
+ t->tree_errno = errno;
+ return (t->visit_type = TREE_ERROR_DIR);
+ }
+ t->flags &= ~hasLstat;
+ t->flags &= ~hasStat;
+ t->basename = ".";
+ return (t->visit_type = TREE_POSTDESCENT);
+ }
+
+ /* We've done everything necessary for the top stack entry. */
+ if (t->stack->flags & needsPostVisit) {
+ tree_ascend(t);
+ tree_pop(t);
+ t->flags &= ~hasLstat;
+ t->flags &= ~hasStat;
+ return (t->visit_type = TREE_POSTASCENT);
+ }
+ }
+ return (t->visit_type = 0);
+}
+
+/*
+ * Return error code.
+ */
+int
+tree_errno(struct tree *t)
+{
+ return (t->tree_errno);
+}
+
+/*
+ * Called by the client to mark the directory just returned from
+ * tree_next() as needing to be visited.
+ */
+void
+tree_descend(struct tree *t)
+{
+ if (t->visit_type != TREE_REGULAR)
+ return;
+
+ if (tree_current_is_physical_dir(t)) {
+ tree_push(t, t->basename);
+ t->stack->flags |= isDir;
+ } else if (tree_current_is_dir(t)) {
+ tree_push(t, t->basename);
+ t->stack->flags |= isDirLink;
+ }
+}
+
+/*
+ * Get the stat() data for the entry just returned from tree_next().
+ */
+const struct stat *
+tree_current_stat(struct tree *t)
+{
+ if (!(t->flags & hasStat)) {
+ if (stat(t->basename, &t->st) != 0)
+ return NULL;
+ t->flags |= hasStat;
+ }
+ return (&t->st);
+}
+
+/*
+ * Get the lstat() data for the entry just returned from tree_next().
+ */
+const struct stat *
+tree_current_lstat(struct tree *t)
+{
+ if (!(t->flags & hasLstat)) {
+ if (lstat(t->basename, &t->lst) != 0)
+ return NULL;
+ t->flags |= hasLstat;
+ }
+ return (&t->lst);
+}
+
+/*
+ * Test whether current entry is a dir or link to a dir.
+ */
+int
+tree_current_is_dir(struct tree *t)
+{
+ const struct stat *st;
+
+ /*
+ * If we already have lstat() info, then try some
+ * cheap tests to determine if this is a dir.
+ */
+ if (t->flags & hasLstat) {
+ /* If lstat() says it's a dir, it must be a dir. */
+ if (S_ISDIR(tree_current_lstat(t)->st_mode))
+ 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))
+ return 0;
+ /*
+ * It's a link, but we don't know what it's a link to,
+ * so we'll have to use stat().
+ */
+ }
+
+ st = tree_current_stat(t);
+ /* If we can't stat it, it's not a dir. */
+ if (st == NULL)
+ return 0;
+ /* Use the definitive test. Hopefully this is cached. */
+ return (S_ISDIR(st->st_mode));
+}
+
+/*
+ * Test whether current entry is a physical directory. Usually, we
+ * already have at least one of stat() or lstat() in memory, so we
+ * use tricks to try to avoid an extra trip to the disk.
+ */
+int
+tree_current_is_physical_dir(struct tree *t)
+{
+ const struct stat *st;
+
+ /*
+ * If stat() says it isn't a dir, then it's not a dir.
+ * If stat() data is cached, this check is free, so do it first.
+ */
+ if ((t->flags & hasStat)
+ && (!S_ISDIR(tree_current_stat(t)->st_mode)))
+ return 0;
+
+ /*
+ * Either stat() said it was a dir (in which case, we have
+ * to determine whether it's really a link to a dir) or
+ * stat() info wasn't available. So we use lstat(), which
+ * hopefully is already cached.
+ */
+
+ st = tree_current_lstat(t);
+ /* If we can't stat it, it's not a dir. */
+ if (st == NULL)
+ return 0;
+ /* Use the definitive test. Hopefully this is cached. */
+ return (S_ISDIR(st->st_mode));
+}
+
+/*
+ * Test whether current entry is a symbolic link.
+ */
+int
+tree_current_is_physical_link(struct tree *t)
+{
+ const struct stat *st = tree_current_lstat(t);
+ if (st == NULL)
+ return 0;
+ return (S_ISLNK(st->st_mode));
+}
+
+/*
+ * Return the access path for the entry just returned from tree_next().
+ */
+const char *
+tree_current_access_path(struct tree *t)
+{
+ return (t->basename);
+}
+
+/*
+ * Return the full path for the entry just returned from tree_next().
+ */
+const char *
+tree_current_path(struct tree *t)
+{
+ return (t->buff);
+}
+
+/*
+ * Return the length of the path for the entry just returned from tree_next().
+ */
+size_t
+tree_current_pathlen(struct tree *t)
+{
+ return (t->path_length);
+}
+
+/*
+ * Return the nesting depth of the entry just returned from tree_next().
+ */
+int
+tree_current_depth(struct tree *t)
+{
+ return (t->depth);
+}
+
+/*
+ * Terminate the traversal and release any resources.
+ */
+void
+tree_close(struct tree *t)
+{
+ /* Release anything remaining in the stack. */
+ while (t->stack != NULL)
+ tree_pop(t);
+ if (t->buff)
+ free(t->buff);
+ /* chdir() back to where we started. */
+ if (t->initialDirFd >= 0) {
+ fchdir(t->initialDirFd);
+ close(t->initialDirFd);
+ t->initialDirFd = -1;
+ }
+ free(t);
+}
diff --git a/contrib/shar/tree.h b/contrib/shar/tree.h
new file mode 100644
index 000000000000..ff38f5346c1c
--- /dev/null
+++ b/contrib/shar/tree.h
@@ -0,0 +1,115 @@
+/*-
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+/*-
+ * A set of routines for traversing directory trees.
+ * Similar in concept to the fts library, but with a few
+ * important differences:
+ * * Uses less memory. In particular, fts stores an entire directory
+ * in memory at a time. This package only keeps enough subdirectory
+ * information in memory to track the traversal. Information
+ * about non-directories is discarded as soon as possible.
+ * * Supports very deep logical traversals. The fts package
+ * uses "non-chdir" approach for logical traversals. This
+ * package does use a chdir approach for logical traversals
+ * and can therefore handle pathnames much longer than
+ * PATH_MAX.
+ * * Supports deep physical traversals "out of the box."
+ * Due to the memory optimizations above, there's no need to
+ * limit dir names to 32k.
+ */
+
+#include <sys/stat.h>
+#include <stdio.h>
+
+struct tree;
+
+/* Initiate/terminate a tree traversal. */
+struct tree *tree_open(const char * /* pathname */);
+void tree_close(struct tree *);
+
+/*
+ * tree_next() returns Zero if there is no next entry, non-zero if there is.
+ * Note that directories are potentially visited three times. The first
+ * time as "regular" file. If tree_descend() is invoked at that time,
+ * the directory is added to a work list and will be visited two more
+ * times: once just after descending into the directory and again
+ * just after ascending back to the parent.
+ *
+ * TREE_ERROR is returned if the descent failed (because the
+ * directory couldn't be opened, for instance). This is returned
+ * instead of TREE_PREVISIT/TREE_POSTVISIT.
+ */
+#define TREE_REGULAR 1
+#define TREE_POSTDESCENT 2
+#define TREE_POSTASCENT 3
+#define TREE_ERROR_DIR -1
+int tree_next(struct tree *);
+
+int tree_errno(struct tree *);
+
+/*
+ * Request that current entry be visited. If you invoke it on every
+ * directory, you'll get a physical traversal. This is ignored if the
+ * current entry isn't a directory or a link to a directory. So, if
+ * you invoke this on every returned path, you'll get a full logical
+ * traversal.
+ */
+void tree_descend(struct tree *);
+
+/*
+ * Return information about the current entry.
+ */
+
+int tree_current_depth(struct tree *);
+/*
+ * The current full pathname, length of the full pathname,
+ * and a name that can be used to access the file.
+ * Because tree does use chdir extensively, the access path is
+ * almost never the same as the full current path.
+ */
+const char *tree_current_path(struct tree *);
+size_t tree_current_pathlen(struct tree *);
+const char *tree_current_access_path(struct tree *);
+/*
+ * Request the lstat() or stat() data for the current path. Since the
+ * tree package needs to do some of this anyway, and caches the
+ * results, you should take advantage of it here if you need it rather
+ * than make a redundant stat() or lstat() call of your own.
+ */
+const struct stat *tree_current_stat(struct tree *);
+const struct stat *tree_current_lstat(struct tree *);
+/* The following tests may use mechanisms much faster than stat()/lstat(). */
+/* "is_physical_dir" is equivalent to S_ISDIR(tree_current_lstat()->st_mode) */
+int tree_current_is_physical_dir(struct tree *);
+/* "is_physical_link" is equivalent to S_ISLNK(tree_current_lstat()->st_mode) */
+int tree_current_is_physical_link(struct tree *);
+/* "is_dir" is equivalent to S_ISDIR(tree_current_stat()->st_mode) */
+int tree_current_is_dir(struct tree *);
+
+/* For testing/debugging: Dump the internal status to the given filehandle. */
+void tree_dump(struct tree *, FILE *);
diff --git a/contrib/shar/tree_config.h b/contrib/shar/tree_config.h
new file mode 100644
index 000000000000..8dfd90baf685
--- /dev/null
+++ b/contrib/shar/tree_config.h
@@ -0,0 +1,78 @@
+/*-
+ * 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.
+ *
+ * $FreeBSD$
+ */
+#ifndef TREE_CONFIG_H_INCLUDED
+#define TREE_CONFIG_H_INCLUDED
+
+#if defined(PLATFORM_CONFIG_H)
+/*
+ * Use hand-built config.h in environments that need it.
+ */
+#include PLATFORM_CONFIG_H
+#elif defined(HAVE_CONFIG_H)
+/*
+ * Most POSIX platforms use the 'configure' script to build config.h
+ */
+#include "../config.h"
+#elif defined(__FreeBSD__)
+/*
+ * Built-in definitions for FreeBSD.
+ */
+#define HAVE_DIRENT_D_NAMLEN 1
+#define HAVE_DIRENT_H 1
+#define HAVE_ERRNO_H 1
+#define HAVE_FCNTL_H 1
+#define HAVE_LIBARCHIVE 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_UNISTD_H 1
+#else
+/*
+ * Warn if there's no platform configuration.
+ */
+#error Oops: No config.h and no built-in configuration in bsdtar_platform.h.
+#endif /* !HAVE_CONFIG_H */
+
+/* No non-FreeBSD platform will have __FBSDID, so just define it here. */
+#ifdef __FreeBSD__
+#include <sys/cdefs.h> /* For __FBSDID */
+#else
+/* Just leaving this macro replacement empty leads to a dangling semicolon. */
+#define __FBSDID(a) struct _undefined_hack
+#endif
+
+#ifdef HAVE_LIBARCHIVE
+/* If we're using the platform libarchive, include system headers. */
+#include <archive.h>
+#include <archive_entry.h>
+#else
+/* Otherwise, include user headers. */
+#include "archive.h"
+#include "archive_entry.h"
+#endif
+
+#endif /* !TREE_CONFIG_H_INCLUDED */
diff --git a/contrib/untar.c b/contrib/untar.c
new file mode 100644
index 000000000000..dc092d325e02
--- /dev/null
+++ b/contrib/untar.c
@@ -0,0 +1,225 @@
+/*
+ * "untar" is an extremely simple tar extractor:
+ * * A single C source file, so it should be easy to compile
+ * and run on any system with a C compiler.
+ * * Extremely portable standard C. The only non-ANSI function
+ * used is mkdir().
+ * * Reads basic ustar tar archives.
+ * * Does not require libarchive or any other special library.
+ *
+ * To compile: cc -o untar untar.c
+ *
+ * Usage: untar <archive>
+ *
+ * In particular, this program should be sufficient to extract the
+ * distribution for libarchive, allowing people to bootstrap
+ * libarchive on systems that do not already have a tar program.
+ *
+ * To unpack libarchive-x.y.z.tar.gz:
+ * * gunzip libarchive-x.y.z.tar.gz
+ * * untar libarchive-x.y.z.tar
+ *
+ * Written by Tim Kientzle, March 2009.
+ *
+ * Released into the public domain.
+ */
+
+/* These are all highly standard and portable headers. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* This is for mkdir(); this may need to be changed for some platforms. */
+#include <sys/stat.h> /* For mkdir() */
+
+/* Parse an octal number, ignoring leading and trailing nonsense. */
+static int
+parseoct(const char *p, size_t n)
+{
+ int i = 0;
+
+ while (*p < '0' || *p > '7') {
+ ++p;
+ --n;
+ }
+ while (*p >= '0' && *p <= '7' && n > 0) {
+ i *= 8;
+ i += *p - '0';
+ ++p;
+ --n;
+ }
+ return (i);
+}
+
+/* Returns true if this is 512 zero bytes. */
+static int
+is_end_of_archive(const char *p)
+{
+ int n;
+ for (n = 511; n >= 0; --n)
+ if (p[n] != '\0')
+ return (0);
+ return (1);
+}
+
+/* Create a directory, including parent directories as necessary. */
+static void
+create_dir(char *pathname, int mode)
+{
+ char *p;
+ int r;
+
+ /* Strip trailing '/' */
+ if (pathname[strlen(pathname) - 1] == '/')
+ pathname[strlen(pathname) - 1] = '\0';
+
+ /* Try creating the directory. */
+ r = mkdir(pathname, mode);
+
+ if (r != 0) {
+ /* On failure, try creating parent directory. */
+ p = strrchr(pathname, '/');
+ if (p != NULL) {
+ *p = '\0';
+ create_dir(pathname, 0755);
+ *p = '/';
+ r = mkdir(pathname, mode);
+ }
+ }
+ if (r != 0)
+ fprintf(stderr, "Could not create directory %s\n", pathname);
+}
+
+/* Create a file, including parent directory as necessary. */
+static FILE *
+create_file(char *pathname, int mode)
+{
+ FILE *f;
+ f = fopen(pathname, "w+");
+ if (f == NULL) {
+ /* Try creating parent dir and then creating file. */
+ char *p = strrchr(pathname, '/');
+ if (p != NULL) {
+ *p = '\0';
+ create_dir(pathname, 0755);
+ *p = '/';
+ f = fopen(pathname, "w+");
+ }
+ }
+ return (f);
+}
+
+/* Verify the tar checksum. */
+static int
+verify_checksum(const char *p)
+{
+ int n, u = 0;
+ for (n = 0; n < 512; ++n) {
+ if (n < 148 || n > 155)
+ /* Standard tar checksum adds unsigned bytes. */
+ u += ((unsigned char *)p)[n];
+ else
+ u += 0x20;
+
+ }
+ return (u == parseoct(p + 148, 8));
+}
+
+/* Extract a tar archive. */
+static void
+untar(FILE *a, const char *path)
+{
+ char buff[512];
+ FILE *f = NULL;
+ size_t bytes_read;
+ int filesize;
+
+ printf("Extracting from %s\n", path);
+ for (;;) {
+ bytes_read = fread(buff, 1, 512, a);
+ if (bytes_read < 512) {
+ fprintf(stderr,
+ "Short read on %s: expected 512, got %d\n",
+ path, bytes_read);
+ return;
+ }
+ if (is_end_of_archive(buff)) {
+ printf("End of %s\n", path);
+ return;
+ }
+ if (!verify_checksum(buff)) {
+ fprintf(stderr, "Checksum failure\n");
+ return;
+ }
+ filesize = parseoct(buff + 124, 12);
+ switch (buff[156]) {
+ case '1':
+ printf(" Ignoring hardlink %s\n", buff);
+ break;
+ case '2':
+ printf(" Ignoring symlink %s\n", buff);
+ break;
+ case '3':
+ printf(" Ignoring character device %s\n", buff);
+ break;
+ case '4':
+ printf(" Ignoring block device %s\n", buff);
+ break;
+ case '5':
+ printf(" Extracting dir %s\n", buff);
+ create_dir(buff, parseoct(buff + 100, 8));
+ filesize = 0;
+ break;
+ case '6':
+ printf(" Ignoring FIFO %s\n", buff);
+ break;
+ default:
+ printf(" Extracting file %s\n", buff);
+ f = create_file(buff, parseoct(buff + 100, 8));
+ break;
+ }
+ while (filesize > 0) {
+ bytes_read = fread(buff, 1, 512, a);
+ if (bytes_read < 512) {
+ fprintf(stderr,
+ "Short read on %s: Expected 512, got %d\n",
+ path, bytes_read);
+ return;
+ }
+ if (filesize < 512)
+ bytes_read = filesize;
+ if (f != NULL) {
+ if (fwrite(buff, 1, bytes_read, f)
+ != bytes_read)
+ {
+ fprintf(stderr, "Failed write\n");
+ fclose(f);
+ f = NULL;
+ }
+ }
+ filesize -= bytes_read;
+ }
+ if (f != NULL) {
+ fclose(f);
+ f = NULL;
+ }
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ FILE *a;
+
+ ++argv; /* Skip program name */
+ for ( ;*argv != NULL; ++argv) {
+ a = fopen(*argv, "r");
+ if (a == NULL)
+ fprintf(stderr, "Unable to open %s\n", *argv);
+ else {
+ untar(a, *argv);
+ fclose(a);
+ }
+ }
+ return (0);
+}
diff --git a/cpio/CMakeLists.txt b/cpio/CMakeLists.txt
new file mode 100644
index 000000000000..ce500b1cc6b4
--- /dev/null
+++ b/cpio/CMakeLists.txt
@@ -0,0 +1,51 @@
+############################################
+#
+# How to build bsdcpio
+#
+############################################
+IF(ENABLE_CPIO)
+
+ SET(bsdcpio_SOURCES
+ cmdline.c
+ cpio.c
+ cpio.h
+ cpio_platform.h
+ ../libarchive_fe/err.c
+ ../libarchive_fe/err.h
+ ../libarchive_fe/lafe_platform.h
+ ../libarchive_fe/line_reader.c
+ ../libarchive_fe/line_reader.h
+ ../libarchive_fe/matching.c
+ ../libarchive_fe/matching.h
+ ../libarchive_fe/pathmatch.c
+ ../libarchive_fe/pathmatch.h
+ )
+ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libarchive_fe)
+ IF(WIN32 AND NOT CYGWIN)
+ LIST(APPEND bsdcpio_SOURCES cpio_windows.c)
+ LIST(APPEND bsdcpio_SOURCES cpio_windows.h)
+ ENDIF(WIN32 AND NOT CYGWIN)
+
+ # bsdcpio documentation
+ SET(bsdcpio_MANS bsdcpio.1)
+
+ # How to build bsdcpio
+ ADD_EXECUTABLE(bsdcpio ${bsdcpio_SOURCES})
+ IF(ENABLE_CPIO_SHARED)
+ TARGET_LINK_LIBRARIES(bsdcpio archive ${ADDITIONAL_LIBS})
+ ELSE(ENABLE_CPIO_SHARED)
+ TARGET_LINK_LIBRARIES(bsdcpio archive_static ${ADDITIONAL_LIBS})
+ SET_TARGET_PROPERTIES(bsdcpio PROPERTIES COMPILE_DEFINITIONS
+ LIBARCHIVE_STATIC)
+ ENDIF(ENABLE_CPIO_SHARED)
+ # Full path to the compiled executable (used by test suite)
+ GET_TARGET_PROPERTY(BSDCPIO bsdcpio LOCATION)
+
+ # Installation rules
+ INSTALL(TARGETS bsdcpio RUNTIME DESTINATION bin)
+ INSTALL_MAN(${bsdcpio_MANS})
+
+ENDIF(ENABLE_CPIO)
+
+# Test suite
+add_subdirectory(test)
diff --git a/cpio/bsdcpio.1 b/cpio/bsdcpio.1
new file mode 100644
index 000000000000..79b6997ef4a8
--- /dev/null
+++ b/cpio/bsdcpio.1
@@ -0,0 +1,405 @@
+.\" 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 AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 21, 2007
+.Dt BSDCPIO 1
+.Os
+.Sh NAME
+.Nm cpio
+.Nd copy files to and from archives
+.Sh SYNOPSIS
+.Nm
+.Brq Fl i
+.Op Ar options
+.Op Ar pattern ...
+.Op Ar < archive
+.Nm
+.Brq Fl o
+.Op Ar options
+.Ar < name-list
+.Op Ar > archive
+.Nm
+.Brq Fl p
+.Op Ar options
+.Ar dest-dir
+.Ar < name-list
+.Sh DESCRIPTION
+.Nm
+copies files between archives and directories.
+This implementation can extract from tar, pax, cpio, zip, jar, ar,
+and ISO 9660 cdrom images and can create tar, pax, cpio, ar,
+and shar archives.
+.Pp
+The first option to
+.Nm
+is a mode indicator from the following list:
+.Bl -tag -compact -width indent
+.It Fl i
+Input.
+Read an archive from standard input (unless overriden) and extract the
+contents to disk or (if the
+.Fl t
+option is specified)
+list the contents to standard output.
+If one or more file patterns are specified, only files matching
+one of the patterns will be extracted.
+.It Fl o
+Output.
+Read a list of filenames from standard input and produce a new archive
+on standard output (unless overriden) containing the specified items.
+.It Fl p
+Pass-through.
+Read a list of filenames from standard input and copy the files to the
+specified directory.
+.El
+.Pp
+.Sh OPTIONS
+Unless specifically stated otherwise, options are applicable in
+all operating modes.
+.Bl -tag -width indent
+.It Fl 0
+Read filenames separated by NUL characters instead of newlines.
+This is necessary if any of the filenames being read might contain newlines.
+.It Fl A
+(o mode only)
+Append to the specified archive.
+(Not yet implemented.)
+.It Fl a
+(o and p modes)
+Reset access times on files after they are read.
+.It Fl B
+(o mode only)
+Block output to records of 5120 bytes.
+.It Fl C Ar size
+(o mode only)
+Block output to records of
+.Ar size
+bytes.
+.It Fl c
+(o mode only)
+Use the old POSIX portable character format.
+Equivalent to
+.Fl -format Ar odc .
+.It Fl d
+(i and p modes)
+Create directories as necessary.
+.It Fl E Ar file
+(i mode only)
+Read list of file name patterns from
+.Ar file
+to list and extract.
+.It Fl F Ar file
+Read archive from or write archive to
+.Ar file .
+.It Fl f Ar pattern
+(i mode only)
+Ignore files that match
+.Ar pattern .
+.It Fl -format Ar format
+(o mode only)
+Produce the output archive in the specified format.
+Supported formats include:
+.Pp
+.Bl -tag -width "iso9660" -compact
+.It Ar cpio
+Synonym for
+.Ar odc .
+.It Ar newc
+The SVR4 portable cpio format.
+.It Ar odc
+The old POSIX.1 portable octet-oriented cpio format.
+.It Ar pax
+The POSIX.1 pax format, an extension of the ustar format.
+.It Ar ustar
+The POSIX.1 tar format.
+.El
+.Pp
+The default format is
+.Ar odc .
+See
+.Xr libarchive_formats 5
+for more complete information about the
+formats currently supported by the underlying
+.Xr libarchive 3
+library.
+.It Fl H Ar format
+Synonym for
+.Fl -format .
+.It Fl h , Fl -help
+Print usage information.
+.It Fl I Ar file
+Read archive from
+.Ar file .
+.It Fl i
+Input mode.
+See above for description.
+.It Fl -insecure
+(i and p mode only)
+Disable security checks during extraction or copying.
+This allows extraction via symbolic links and path names containing
+.Sq ..
+in the name.
+.It Fl J
+(o mode only)
+Compress the file with xz-compatible compression before writing it.
+In input mode, this option is ignored; xz compression is recognized
+automatically on input.
+.It Fl j
+Synonym for
+.Fl y .
+.It Fl L
+(o and p modes)
+All symbolic links will be followed.
+Normally, symbolic links are archived and copied as symbolic links.
+With this option, the target of the link will be archived or copied instead.
+.It Fl l
+(p mode only)
+Create links from the target directory to the original files,
+instead of copying.
+.It Fl lzma
+(o mode only)
+Compress the file with lzma-compatible compression before writing it.
+In input mode, this option is ignored; lzma compression is recognized
+automatically on input.
+.It Fl m
+(i and p modes)
+Set file modification time on created files to match
+those in the source.
+.It Fl n
+(i mode, only with
+.Fl t )
+Display numeric uid and gid.
+By default,
+.Nm
+displays the user and group names when they are provided in the
+archive, or looks up the user and group names in the system
+password database.
+.It Fl no-preserve-owner
+(i mode only)
+Do not attempt to restore file ownership.
+This is the default when run by non-root users.
+.It Fl O Ar file
+Write archive to
+.Ar file .
+.It Fl o
+Output mode.
+See above for description.
+.It Fl p
+Pass-through mode.
+See above for description.
+.It Fl preserve-owner
+(i mode only)
+Restore file ownership.
+This is the default when run by the root user.
+.It Fl -quiet
+Suppress unnecessary messages.
+.It Fl R Oo user Oc Ns Oo : Oc Ns Oo group Oc
+Set the owner and/or group on files in the output.
+If group is specified with no user
+(for example,
+.Fl R Ar :wheel )
+then the group will be set but not the user.
+If the user is specified with a trailing colon and no group
+(for example,
+.Fl R Ar root: )
+then the group will be set to the user's default group.
+If the user is specified with no trailing colon, then
+the user will be set but not the group.
+In
+.Fl i
+and
+.Fl p
+modes, this option can only be used by the super-user.
+(For compatibility, a period can be used in place of the colon.)
+.It Fl r
+(All modes.)
+Rename files interactively.
+For each file, a prompt is written to
+.Pa /dev/tty
+containing the name of the file and a line is read from
+.Pa /dev/tty .
+If the line read is blank, the file is skipped.
+If the line contains a single period, the file is processed normally.
+Otherwise, the line is taken to be the new name of the file.
+.It Fl t
+(i mode only)
+List the contents of the archive to stdout;
+do not restore the contents to disk.
+.It Fl u
+(i and p modes)
+Unconditionally overwrite existing files.
+Ordinarily, an older file will not overwrite a newer file on disk.
+.It Fl v
+Print the name of each file to stderr as it is processed.
+With
+.Fl t ,
+provide a detailed listing of each file.
+.It Fl -version
+Print the program version information and exit.
+.It Fl y
+(o mode only)
+Compress the archive with bzip2-compatible compression before writing it.
+In input mode, this option is ignored;
+bzip2 compression is recognized automatically on input.
+.It Fl Z
+(o mode only)
+Compress the archive with compress-compatible compression before writing it.
+In input mode, this option is ignored;
+compression is recognized automatically on input.
+.It Fl z
+(o mode only)
+Compress the archive with gzip-compatible compression before writing it.
+In input mode, this option is ignored;
+gzip compression is recognized automatically on input.
+.El
+.Sh ENVIRONMENT
+The following environment variables affect the execution of
+.Nm :
+.Bl -tag -width ".Ev BLOCKSIZE"
+.It Ev LANG
+The locale to use.
+See
+.Xr environ 7
+for more information.
+.It Ev TZ
+The timezone to use when displaying dates.
+See
+.Xr environ 7
+for more information.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+The
+.Nm
+command is traditionally used to copy file heirarchies in conjunction
+with the
+.Xr find 1
+command.
+The first example here simply copies all files from
+.Pa src
+to
+.Pa dest :
+.Dl Nm find Pa src | Nm Fl pmud Pa dest
+.Pp
+By carefully selecting options to the
+.Xr find 1
+command and combining it with other standard utilities,
+it is possible to exercise very fine control over which files are copied.
+This next example copies files from
+.Pa src
+to
+.Pa dest
+that are more than 2 days old and whose names match a particular pattern:
+.Dl Nm find Pa src Fl mtime Ar +2 | Nm grep foo[bar] | Nm Fl pdmu Pa dest
+.Pp
+This example copies files from
+.Pa src
+to
+.Pa dest
+that are more than 2 days old and which contain the word
+.Do foobar Dc :
+.Dl Nm find Pa src Fl mtime Ar +2 | Nm xargs Nm grep -l foobar | Nm Fl pdmu Pa dest
+.Sh COMPATIBILITY
+The mode options i, o, and p and the options
+a, B, c, d, f, l, m, r, t, u, and v comply with SUSv2.
+.Pp
+The old POSIX.1 standard specified that only
+.Fl i ,
+.Fl o ,
+and
+.Fl p
+were interpreted as command-line options.
+Each took a single argument of a list of modifier
+characters.
+For example, the standard syntax allows
+.Fl imu
+but does not support
+.Fl miu
+or
+.Fl i Fl m Fl u ,
+since
+.Ar m
+and
+.Ar u
+are only modifiers to
+.Fl i ,
+they are not command-line options in their own right.
+The syntax supported by this implementation is backwards-compatible
+with the standard.
+For best compatibility, scripts should limit themselves to the
+standard syntax.
+.Sh SEE ALSO
+.Xr bzip2 1 ,
+.Xr tar 1 ,
+.Xr gzip 1 ,
+.Xr mt 1 ,
+.Xr pax 1 ,
+.Xr libarchive 3 ,
+.Xr cpio 5 ,
+.Xr libarchive-formats 5 ,
+.Xr tar 5
+.Sh STANDARDS
+There is no current POSIX standard for the cpio command; it appeared
+in
+.St -p1003.1-96
+but was dropped from
+.St -p1003.1-2001 .
+.Pp
+The cpio, ustar, and pax interchange file formats are defined by
+.St -p1003.1-2001
+for the pax command.
+.Sh HISTORY
+The original
+.Nm cpio
+and
+.Nm find
+utilities were written by Dick Haight
+while working in AT&T's Unix Support Group.
+They first appeared in 1977 in PWB/UNIX 1.0, the
+.Dq Programmer's Work Bench
+system developed for use within AT&T.
+They were first released outside of AT&T as part of System III Unix in 1981.
+As a result,
+.Nm cpio
+actually predates
+.Nm tar ,
+even though it was not well-known outside of AT&T until some time later.
+.Pp
+This is a complete re-implementation based on the
+.Xr libarchive 3
+library.
+.Sh BUGS
+The cpio archive format has several basic limitations:
+It does not store user and group names, only numbers.
+As a result, it cannot be reliably used to transfer
+files between systems with dissimilar user and group numbering.
+Older cpio formats limit the user and group numbers to
+16 or 18 bits, which is insufficient for modern systems.
+The cpio archive formats cannot support files over 4 gigabytes,
+except for the
+.Dq odc
+variant, which can support files up to 8 gigabytes.
diff --git a/cpio/cmdline.c b/cpio/cmdline.c
new file mode 100644
index 000000000000..2223798c124d
--- /dev/null
+++ b/cpio/cmdline.c
@@ -0,0 +1,369 @@
+/*-
+ * 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
+ * in this position and unchanged.
+ * 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 "cpio_platform.h"
+__FBSDID("$FreeBSD: src/usr.bin/cpio/cmdline.c,v 1.5 2008/12/06 07:30:40 kientzle Exp $");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "cpio.h"
+#include "err.h"
+
+/*
+ * Short options for cpio. Please keep this sorted.
+ */
+static const char *short_options = "0AaBC:cdE:F:f:H:hI:iJjLlmnO:opR:rtuvW:yZz";
+
+/*
+ * Long options for cpio. Please keep this sorted.
+ */
+static const struct option {
+ const char *name;
+ int required; /* 1 if this option requires an argument */
+ int equivalent; /* Equivalent short option. */
+} cpio_longopts[] = {
+ { "create", 0, 'o' },
+ { "extract", 0, 'i' },
+ { "file", 1, 'F' },
+ { "format", 1, 'H' },
+ { "help", 0, 'h' },
+ { "insecure", 0, OPTION_INSECURE },
+ { "link", 0, 'l' },
+ { "list", 0, 't' },
+ { "lzma", 0, OPTION_LZMA },
+ { "make-directories", 0, 'd' },
+ { "no-preserve-owner", 0, OPTION_NO_PRESERVE_OWNER },
+ { "null", 0, '0' },
+ { "numeric-uid-gid", 0, 'n' },
+ { "owner", 1, 'R' },
+ { "pass-through", 0, 'p' },
+ { "preserve-modification-time", 0, 'm' },
+ { "preserve-owner", 0, OPTION_PRESERVE_OWNER },
+ { "quiet", 0, OPTION_QUIET },
+ { "unconditional", 0, 'u' },
+ { "verbose", 0, 'v' },
+ { "version", 0, OPTION_VERSION },
+ { "xz", 0, 'J' },
+ { NULL, 0, 0 }
+};
+
+/*
+ * I used to try to select platform-provided getopt() or
+ * getopt_long(), but that caused a lot of headaches. In particular,
+ * I couldn't consistently use long options in the test harness
+ * because not all platforms have getopt_long(). That in turn led to
+ * overuse of the -W hack in the test harness, which made it rough to
+ * run the test harness against GNU cpio. (I periodically run the
+ * test harness here against GNU cpio as a sanity-check. Yes,
+ * I've found a couple of bugs in GNU cpio that way.)
+ */
+int
+cpio_getopt(struct cpio *cpio)
+{
+ enum { state_start = 0, state_next_word, state_short, state_long };
+ static int state = state_start;
+ static char *opt_word;
+
+ const struct option *popt, *match = NULL, *match2 = NULL;
+ const char *p, *long_prefix = "--";
+ size_t optlength;
+ int opt = '?';
+ int required = 0;
+
+ cpio->optarg = NULL;
+
+ /* First time through, initialize everything. */
+ if (state == state_start) {
+ /* Skip program name. */
+ ++cpio->argv;
+ --cpio->argc;
+ state = state_next_word;
+ }
+
+ /*
+ * We're ready to look at the next word in argv.
+ */
+ if (state == state_next_word) {
+ /* No more arguments, so no more options. */
+ if (cpio->argv[0] == NULL)
+ return (-1);
+ /* Doesn't start with '-', so no more options. */
+ if (cpio->argv[0][0] != '-')
+ return (-1);
+ /* "--" marks end of options; consume it and return. */
+ if (strcmp(cpio->argv[0], "--") == 0) {
+ ++cpio->argv;
+ --cpio->argc;
+ return (-1);
+ }
+ /* Get next word for parsing. */
+ opt_word = *cpio->argv++;
+ --cpio->argc;
+ if (opt_word[1] == '-') {
+ /* Set up long option parser. */
+ state = state_long;
+ opt_word += 2; /* Skip leading '--' */
+ } else {
+ /* Set up short option parser. */
+ state = state_short;
+ ++opt_word; /* Skip leading '-' */
+ }
+ }
+
+ /*
+ * We're parsing a group of POSIX-style single-character options.
+ */
+ if (state == state_short) {
+ /* Peel next option off of a group of short options. */
+ opt = *opt_word++;
+ if (opt == '\0') {
+ /* End of this group; recurse to get next option. */
+ state = state_next_word;
+ return cpio_getopt(cpio);
+ }
+
+ /* Does this option take an argument? */
+ p = strchr(short_options, opt);
+ if (p == NULL)
+ return ('?');
+ if (p[1] == ':')
+ required = 1;
+
+ /* If it takes an argument, parse that. */
+ if (required) {
+ /* If arg is run-in, opt_word already points to it. */
+ if (opt_word[0] == '\0') {
+ /* Otherwise, pick up the next word. */
+ opt_word = *cpio->argv;
+ if (opt_word == NULL) {
+ lafe_warnc(0,
+ "Option -%c requires an argument",
+ opt);
+ return ('?');
+ }
+ ++cpio->argv;
+ --cpio->argc;
+ }
+ if (opt == 'W') {
+ state = state_long;
+ long_prefix = "-W "; /* For clearer errors. */
+ } else {
+ state = state_next_word;
+ cpio->optarg = opt_word;
+ }
+ }
+ }
+
+ /* We're reading a long option, including -W long=arg convention. */
+ if (state == state_long) {
+ /* After this long option, we'll be starting a new word. */
+ state = state_next_word;
+
+ /* Option name ends at '=' if there is one. */
+ p = strchr(opt_word, '=');
+ if (p != NULL) {
+ optlength = (size_t)(p - opt_word);
+ cpio->optarg = (char *)(uintptr_t)(p + 1);
+ } else {
+ optlength = strlen(opt_word);
+ }
+
+ /* Search the table for an unambiguous match. */
+ for (popt = cpio_longopts; popt->name != NULL; popt++) {
+ /* Short-circuit if first chars don't match. */
+ if (popt->name[0] != opt_word[0])
+ continue;
+ /* If option is a prefix of name in table, record it.*/
+ if (strncmp(opt_word, popt->name, optlength) == 0) {
+ match2 = match; /* Record up to two matches. */
+ match = popt;
+ /* If it's an exact match, we're done. */
+ if (strlen(popt->name) == optlength) {
+ match2 = NULL; /* Forget the others. */
+ break;
+ }
+ }
+ }
+
+ /* Fail if there wasn't a unique match. */
+ if (match == NULL) {
+ lafe_warnc(0,
+ "Option %s%s is not supported",
+ long_prefix, opt_word);
+ return ('?');
+ }
+ if (match2 != NULL) {
+ lafe_warnc(0,
+ "Ambiguous option %s%s (matches --%s and --%s)",
+ long_prefix, opt_word, match->name, match2->name);
+ return ('?');
+ }
+
+ /* We've found a unique match; does it need an argument? */
+ if (match->required) {
+ /* Argument required: get next word if necessary. */
+ if (cpio->optarg == NULL) {
+ cpio->optarg = *cpio->argv;
+ if (cpio->optarg == NULL) {
+ lafe_warnc(0,
+ "Option %s%s requires an argument",
+ long_prefix, match->name);
+ return ('?');
+ }
+ ++cpio->argv;
+ --cpio->argc;
+ }
+ } else {
+ /* Argument forbidden: fail if there is one. */
+ if (cpio->optarg != NULL) {
+ lafe_warnc(0,
+ "Option %s%s does not allow an argument",
+ long_prefix, match->name);
+ return ('?');
+ }
+ }
+ return (match->equivalent);
+ }
+
+ return (opt);
+}
+
+
+/*
+ * Parse the argument to the -R or --owner flag.
+ *
+ * The format is one of the following:
+ * <username|uid> - Override user but not group
+ * <username>: - Override both, group is user's default group
+ * <uid>: - Override user but not group
+ * <username|uid>:<groupname|gid> - Override both
+ * :<groupname|gid> - Override group but not user
+ *
+ * Where uid/gid are decimal representations and groupname/username
+ * are names to be looked up in system database. Note that we try
+ * to look up an argument as a name first, then try numeric parsing.
+ *
+ * A period can be used instead of the colon.
+ *
+ * Sets uid/gid return as appropriate, -1 indicates uid/gid not specified.
+ *
+ * Returns NULL if no error, otherwise returns error string for display.
+ *
+ */
+const char *
+owner_parse(const char *spec, int *uid, int *gid)
+{
+ static char errbuff[128];
+ const char *u, *ue, *g;
+
+ *uid = -1;
+ *gid = -1;
+
+ if (spec[0] == '\0')
+ return ("Invalid empty user/group spec");
+
+ /*
+ * Split spec into [user][:.][group]
+ * u -> first char of username, NULL if no username
+ * ue -> first char after username (colon, period, or \0)
+ * g -> first char of group name
+ */
+ if (*spec == ':' || *spec == '.') {
+ /* If spec starts with ':' or '.', then just group. */
+ ue = u = NULL;
+ g = spec + 1;
+ } else {
+ /* Otherwise, [user] or [user][:] or [user][:][group] */
+ ue = u = spec;
+ while (*ue != ':' && *ue != '.' && *ue != '\0')
+ ++ue;
+ g = ue;
+ if (*g != '\0') /* Skip : or . to find first char of group. */
+ ++g;
+ }
+
+ if (u != NULL) {
+ /* Look up user: ue is first char after end of user. */
+ char *user;
+ struct passwd *pwent;
+
+ user = (char *)malloc(ue - u + 1);
+ if (user == NULL)
+ return ("Couldn't allocate memory");
+ memcpy(user, u, ue - u);
+ user[ue - u] = '\0';
+ if ((pwent = getpwnam(user)) != NULL) {
+ *uid = pwent->pw_uid;
+ if (*ue != '\0')
+ *gid = pwent->pw_gid;
+ } else {
+ char *end;
+ errno = 0;
+ *uid = strtoul(user, &end, 10);
+ if (errno || *end != '\0') {
+ snprintf(errbuff, sizeof(errbuff),
+ "Couldn't lookup user ``%s''", user);
+ errbuff[sizeof(errbuff) - 1] = '\0';
+ return (errbuff);
+ }
+ }
+ free(user);
+ }
+
+ if (*g != '\0') {
+ struct group *grp;
+ if ((grp = getgrnam(g)) != NULL) {
+ *gid = grp->gr_gid;
+ } else {
+ char *end;
+ errno = 0;
+ *gid = strtoul(g, &end, 10);
+ if (errno || *end != '\0') {
+ snprintf(errbuff, sizeof(errbuff),
+ "Couldn't lookup group ``%s''", g);
+ errbuff[sizeof(errbuff) - 1] = '\0';
+ return (errbuff);
+ }
+ }
+ }
+ return (NULL);
+}
diff --git a/cpio/config_freebsd.h b/cpio/config_freebsd.h
new file mode 100644
index 000000000000..00c4c737f737
--- /dev/null
+++ b/cpio/config_freebsd.h
@@ -0,0 +1,56 @@
+/*-
+ * 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.
+ *
+ * $FreeBSD: src/usr.bin/cpio/config_freebsd.h,v 1.3 2008/12/06 07:30:40 kientzle Exp $
+ */
+
+/* A hand-tooled configuration for FreeBSD. */
+
+#include <sys/param.h> /* __FreeBSD_version */
+
+#define HAVE_DIRENT_H 1
+#define HAVE_ERRNO_H 1
+#define HAVE_FCNTL_H 1
+#define HAVE_FUTIMES 1
+#define HAVE_GRP_H 1
+#define HAVE_LIBARCHIVE 1
+#define HAVE_LINK 1
+#define HAVE_LSTAT 1
+#define HAVE_LUTIMES 1
+#define HAVE_PWD_H 1
+#define HAVE_READLINK 1
+#define HAVE_STDARG_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define HAVE_SYMLINK 1
+#define HAVE_SYS_CDEFS_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_SYS_TIME_H 1
+#define HAVE_TIME_H 1
+#define HAVE_UINTMAX_T 1
+#define HAVE_UNISTD_H 1
+#define HAVE_UNSIGNED_LONG_LONG 1
+#define HAVE_UTIME_H 1
+#define HAVE_UTIMES 1
+
diff --git a/cpio/cpio.c b/cpio/cpio.c
new file mode 100644
index 000000000000..7d5031bbcd8f
--- /dev/null
+++ b/cpio/cpio.c
@@ -0,0 +1,1267 @@
+/*-
+ * 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
+ * in this position and unchanged.
+ * 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 "cpio_platform.h"
+__FBSDID("$FreeBSD: src/usr.bin/cpio/cpio.c,v 1.15 2008/12/06 07:30:40 kientzle Exp $");
+
+#include <sys/types.h>
+#include <archive.h>
+#include <archive_entry.h>
+
+#ifdef HAVE_SYS_MKDEV_H
+#include <sys/mkdev.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdio.h>
+#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_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#include "cpio.h"
+#include "err.h"
+#include "line_reader.h"
+#include "matching.h"
+
+/* Fixed size of uname/gname caches. */
+#define name_cache_size 101
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+struct name_cache {
+ int probes;
+ int hits;
+ size_t size;
+ struct {
+ id_t id;
+ char *name;
+ } cache[name_cache_size];
+};
+
+static int extract_data(struct archive *, struct archive *);
+const char * cpio_i64toa(int64_t);
+static const char *cpio_rename(const char *name);
+static int entry_to_archive(struct cpio *, struct archive_entry *);
+static int file_to_archive(struct cpio *, const char *);
+static void free_cache(struct name_cache *cache);
+static void list_item_verbose(struct cpio *, struct archive_entry *);
+static void long_help(void);
+static const char *lookup_gname(struct cpio *, gid_t gid);
+static int lookup_gname_helper(struct cpio *,
+ const char **name, id_t gid);
+static const char *lookup_uname(struct cpio *, uid_t uid);
+static int lookup_uname_helper(struct cpio *,
+ const char **name, id_t uid);
+static void mode_in(struct cpio *);
+static void mode_list(struct cpio *);
+static void mode_out(struct cpio *);
+static void mode_pass(struct cpio *, const char *);
+static int restore_time(struct cpio *, struct archive_entry *,
+ const char *, int fd);
+static void usage(void);
+static void version(void);
+
+int
+main(int argc, char *argv[])
+{
+ static char buff[16384];
+ struct cpio _cpio; /* Allocated on stack. */
+ struct cpio *cpio;
+ const char *errmsg;
+ int uid, gid;
+ int opt;
+
+ cpio = &_cpio;
+ memset(cpio, 0, sizeof(*cpio));
+ cpio->buff = buff;
+ cpio->buff_size = sizeof(buff);
+
+ /* Need lafe_progname before calling lafe_warnc. */
+ if (*argv == NULL)
+ lafe_progname = "bsdcpio";
+ else {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ lafe_progname = strrchr(*argv, '\\');
+#else
+ lafe_progname = strrchr(*argv, '/');
+#endif
+ if (lafe_progname != NULL)
+ lafe_progname++;
+ else
+ lafe_progname = *argv;
+ }
+
+ cpio->uid_override = -1;
+ cpio->gid_override = -1;
+ cpio->argv = argv;
+ cpio->argc = argc;
+ cpio->mode = '\0';
+ cpio->verbose = 0;
+ cpio->compress = '\0';
+ cpio->extract_flags = ARCHIVE_EXTRACT_NO_AUTODIR;
+ cpio->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER;
+ cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_SYMLINKS;
+ cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_NODOTDOT;
+ cpio->extract_flags |= ARCHIVE_EXTRACT_PERM;
+ cpio->extract_flags |= ARCHIVE_EXTRACT_FFLAGS;
+ cpio->extract_flags |= ARCHIVE_EXTRACT_ACL;
+#if !defined(_WIN32) && !defined(__CYGWIN__)
+ if (geteuid() == 0)
+ cpio->extract_flags |= ARCHIVE_EXTRACT_OWNER;
+#endif
+ cpio->bytes_per_block = 512;
+ cpio->filename = NULL;
+
+ while ((opt = cpio_getopt(cpio)) != -1) {
+ switch (opt) {
+ case '0': /* GNU convention: --null, -0 */
+ cpio->option_null = 1;
+ break;
+ case 'A': /* NetBSD/OpenBSD */
+ cpio->option_append = 1;
+ break;
+ case 'a': /* POSIX 1997 */
+ cpio->option_atime_restore = 1;
+ break;
+ case 'B': /* POSIX 1997 */
+ cpio->bytes_per_block = 5120;
+ break;
+ case 'C': /* NetBSD/OpenBSD */
+ cpio->bytes_per_block = atoi(cpio->optarg);
+ if (cpio->bytes_per_block <= 0)
+ lafe_errc(1, 0, "Invalid blocksize %s", cpio->optarg);
+ break;
+ case 'c': /* POSIX 1997 */
+ cpio->format = "odc";
+ break;
+ case 'd': /* POSIX 1997 */
+ cpio->extract_flags &= ~ARCHIVE_EXTRACT_NO_AUTODIR;
+ break;
+ case 'E': /* NetBSD/OpenBSD */
+ lafe_include_from_file(&cpio->matching,
+ cpio->optarg, cpio->option_null);
+ break;
+ case 'F': /* NetBSD/OpenBSD/GNU cpio */
+ cpio->filename = cpio->optarg;
+ break;
+ case 'f': /* POSIX 1997 */
+ lafe_exclude(&cpio->matching, cpio->optarg);
+ break;
+ case 'H': /* GNU cpio (also --format) */
+ cpio->format = cpio->optarg;
+ break;
+ case 'h':
+ long_help();
+ break;
+ case 'I': /* NetBSD/OpenBSD */
+ cpio->filename = cpio->optarg;
+ break;
+ case 'i': /* POSIX 1997 */
+ if (cpio->mode != '\0')
+ lafe_errc(1, 0,
+ "Cannot use both -i and -%c", cpio->mode);
+ cpio->mode = opt;
+ break;
+ case 'J': /* GNU tar, others */
+ cpio->compress = opt;
+ break;
+ case 'j': /* GNU tar, others */
+ cpio->compress = opt;
+ break;
+ case OPTION_INSECURE:
+ cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_SYMLINKS;
+ cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT;
+ break;
+ case 'L': /* GNU cpio */
+ cpio->option_follow_links = 1;
+ break;
+ case 'l': /* POSIX 1997 */
+ cpio->option_link = 1;
+ break;
+ case OPTION_LZMA: /* GNU tar, others */
+ cpio->compress = opt;
+ break;
+ case 'm': /* POSIX 1997 */
+ cpio->extract_flags |= ARCHIVE_EXTRACT_TIME;
+ break;
+ case 'n': /* GNU cpio */
+ cpio->option_numeric_uid_gid = 1;
+ break;
+ case OPTION_NO_PRESERVE_OWNER: /* GNU cpio */
+ cpio->extract_flags &= ~ARCHIVE_EXTRACT_OWNER;
+ break;
+ case 'O': /* GNU cpio */
+ cpio->filename = cpio->optarg;
+ break;
+ case 'o': /* POSIX 1997 */
+ if (cpio->mode != '\0')
+ lafe_errc(1, 0,
+ "Cannot use both -o and -%c", cpio->mode);
+ cpio->mode = opt;
+ break;
+ case 'p': /* POSIX 1997 */
+ if (cpio->mode != '\0')
+ lafe_errc(1, 0,
+ "Cannot use both -p and -%c", cpio->mode);
+ cpio->mode = opt;
+ cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT;
+ break;
+ case OPTION_PRESERVE_OWNER:
+ cpio->extract_flags |= ARCHIVE_EXTRACT_OWNER;
+ break;
+ case OPTION_QUIET: /* GNU cpio */
+ cpio->quiet = 1;
+ break;
+ case 'R': /* GNU cpio, also --owner */
+ errmsg = owner_parse(cpio->optarg, &uid, &gid);
+ if (errmsg) {
+ lafe_warnc(-1, "%s", errmsg);
+ usage();
+ }
+ if (uid != -1)
+ cpio->uid_override = uid;
+ if (gid != -1)
+ cpio->gid_override = gid;
+ break;
+ case 'r': /* POSIX 1997 */
+ cpio->option_rename = 1;
+ break;
+ case 't': /* POSIX 1997 */
+ cpio->option_list = 1;
+ break;
+ case 'u': /* POSIX 1997 */
+ cpio->extract_flags
+ &= ~ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER;
+ break;
+ case 'v': /* POSIX 1997 */
+ cpio->verbose++;
+ break;
+ case OPTION_VERSION: /* GNU convention */
+ version();
+ break;
+#if 0
+ /*
+ * cpio_getopt() handles -W specially, so it's not
+ * available here.
+ */
+ case 'W': /* Obscure, but useful GNU convention. */
+ break;
+#endif
+ case 'y': /* tar convention */
+ cpio->compress = opt;
+ break;
+ case 'Z': /* tar convention */
+ cpio->compress = opt;
+ break;
+ case 'z': /* tar convention */
+ cpio->compress = opt;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ /*
+ * Sanity-check args, error out on nonsensical combinations.
+ */
+ /* -t implies -i if no mode was specified. */
+ if (cpio->option_list && cpio->mode == '\0')
+ cpio->mode = 'i';
+ /* -t requires -i */
+ if (cpio->option_list && cpio->mode != 'i')
+ lafe_errc(1, 0, "Option -t requires -i");
+ /* -n requires -it */
+ if (cpio->option_numeric_uid_gid && !cpio->option_list)
+ lafe_errc(1, 0, "Option -n requires -it");
+ /* Can only specify format when writing */
+ if (cpio->format != NULL && cpio->mode != 'o')
+ lafe_errc(1, 0, "Option --format requires -o");
+ /* -l requires -p */
+ if (cpio->option_link && cpio->mode != 'p')
+ lafe_errc(1, 0, "Option -l requires -p");
+ /* TODO: Flag other nonsensical combinations. */
+
+ switch (cpio->mode) {
+ case 'o':
+ /* TODO: Implement old binary format in libarchive,
+ use that here. */
+ if (cpio->format == NULL)
+ cpio->format = "odc"; /* Default format */
+
+ mode_out(cpio);
+ break;
+ case 'i':
+ while (*cpio->argv != NULL) {
+ lafe_include(&cpio->matching, *cpio->argv);
+ --cpio->argc;
+ ++cpio->argv;
+ }
+ if (cpio->option_list)
+ mode_list(cpio);
+ else
+ mode_in(cpio);
+ break;
+ case 'p':
+ if (*cpio->argv == NULL || **cpio->argv == '\0')
+ lafe_errc(1, 0,
+ "-p mode requires a target directory");
+ mode_pass(cpio, *cpio->argv);
+ break;
+ default:
+ lafe_errc(1, 0,
+ "Must specify at least one of -i, -o, or -p");
+ }
+
+ free_cache(cpio->gname_cache);
+ free_cache(cpio->uname_cache);
+ return (cpio->return_value);
+}
+
+static void
+usage(void)
+{
+ const char *p;
+
+ p = lafe_progname;
+
+ fprintf(stderr, "Brief Usage:\n");
+ fprintf(stderr, " List: %s -it < archive\n", p);
+ fprintf(stderr, " Extract: %s -i < archive\n", p);
+ fprintf(stderr, " Create: %s -o < filenames > archive\n", p);
+ fprintf(stderr, " Help: %s --help\n", p);
+ exit(1);
+}
+
+static const char *long_help_msg =
+ "First option must be a mode specifier:\n"
+ " -i Input -o Output -p Pass\n"
+ "Common Options:\n"
+ " -v Verbose\n"
+ "Create: %p -o [options] < [list of files] > [archive]\n"
+ " -J,-y,-z,--lzma Compress archive with xz/bzip2/gzip/lzma\n"
+ " --format {odc|newc|ustar} Select archive format\n"
+ "List: %p -it < [archive]\n"
+ "Extract: %p -i [options] < [archive]\n";
+
+
+/*
+ * Note that the word 'bsdcpio' will always appear in the first line
+ * of output.
+ *
+ * In particular, /bin/sh scripts that need to test for the presence
+ * of bsdcpio can use the following template:
+ *
+ * if (cpio --help 2>&1 | grep bsdcpio >/dev/null 2>&1 ) then \
+ * echo bsdcpio; else echo not bsdcpio; fi
+ */
+static void
+long_help(void)
+{
+ const char *prog;
+ const char *p;
+
+ prog = lafe_progname;
+
+ fflush(stderr);
+
+ p = (strcmp(prog,"bsdcpio") != 0) ? "(bsdcpio)" : "";
+ printf("%s%s: manipulate archive files\n", prog, p);
+
+ for (p = long_help_msg; *p != '\0'; p++) {
+ if (*p == '%') {
+ if (p[1] == 'p') {
+ fputs(prog, stdout);
+ p++;
+ } else
+ putchar('%');
+ } else
+ putchar(*p);
+ }
+ version();
+}
+
+static void
+version(void)
+{
+ fprintf(stdout,"bsdcpio %s -- %s\n",
+ BSDCPIO_VERSION_STRING,
+ archive_version());
+ exit(0);
+}
+
+static void
+mode_out(struct cpio *cpio)
+{
+ struct archive_entry *entry, *spare;
+ struct lafe_line_reader *lr;
+ const char *p;
+ int r;
+
+ if (cpio->option_append)
+ lafe_errc(1, 0, "Append mode not yet supported.");
+
+ cpio->archive_read_disk = archive_read_disk_new();
+ if (cpio->archive_read_disk == NULL)
+ lafe_errc(1, 0, "Failed to allocate archive object");
+ if (cpio->option_follow_links)
+ archive_read_disk_set_symlink_logical(cpio->archive_read_disk);
+ else
+ archive_read_disk_set_symlink_physical(cpio->archive_read_disk);
+ archive_read_disk_set_standard_lookup(cpio->archive_read_disk);
+
+ cpio->archive = archive_write_new();
+ if (cpio->archive == NULL)
+ lafe_errc(1, 0, "Failed to allocate archive object");
+ switch (cpio->compress) {
+ case 'J':
+ r = archive_write_set_compression_xz(cpio->archive);
+ break;
+ case OPTION_LZMA:
+ r = archive_write_set_compression_lzma(cpio->archive);
+ break;
+ case 'j': case 'y':
+ r = archive_write_set_compression_bzip2(cpio->archive);
+ break;
+ case 'z':
+ r = archive_write_set_compression_gzip(cpio->archive);
+ break;
+ case 'Z':
+ r = archive_write_set_compression_compress(cpio->archive);
+ break;
+ default:
+ r = archive_write_set_compression_none(cpio->archive);
+ break;
+ }
+ if (r < ARCHIVE_WARN)
+ lafe_errc(1, 0, "Requested compression 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));
+ archive_write_set_bytes_per_block(cpio->archive, cpio->bytes_per_block);
+ cpio->linkresolver = archive_entry_linkresolver_new();
+ archive_entry_linkresolver_set_strategy(cpio->linkresolver,
+ archive_format(cpio->archive));
+
+ /*
+ * The main loop: Copy each file into the output archive.
+ */
+ r = archive_write_open_file(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);
+ while ((p = lafe_line_reader_next(lr)) != NULL)
+ file_to_archive(cpio, p);
+ lafe_line_reader_free(lr);
+
+ /*
+ * The hardlink detection may have queued up a couple of entries
+ * that can now be flushed.
+ */
+ entry = NULL;
+ archive_entry_linkify(cpio->linkresolver, &entry, &spare);
+ while (entry != NULL) {
+ entry_to_archive(cpio, entry);
+ archive_entry_free(entry);
+ entry = NULL;
+ archive_entry_linkify(cpio->linkresolver, &entry, &spare);
+ }
+
+ r = archive_write_close(cpio->archive);
+ if (r != ARCHIVE_OK)
+ lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
+
+ if (!cpio->quiet) {
+ int64_t blocks =
+ (archive_position_uncompressed(cpio->archive) + 511)
+ / 512;
+ fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
+ blocks == 1 ? "block" : "blocks");
+ }
+ archive_write_finish(cpio->archive);
+}
+
+/*
+ * This is used by both out mode (to copy objects from disk into
+ * an archive) and pass mode (to copy objects from disk to
+ * an archive_write_disk "archive").
+ */
+static int
+file_to_archive(struct cpio *cpio, const char *srcpath)
+{
+ const char *destpath;
+ struct archive_entry *entry, *spare;
+ size_t len;
+ const char *p;
+ int r;
+
+ /*
+ * Create an archive_entry describing the source file.
+ *
+ */
+ entry = archive_entry_new();
+ if (entry == NULL)
+ lafe_errc(1, 0, "Couldn't allocate entry");
+ archive_entry_copy_sourcepath(entry, srcpath);
+ r = archive_read_disk_entry_from_file(cpio->archive_read_disk,
+ entry, -1, NULL);
+ if (r < ARCHIVE_FAILED)
+ lafe_errc(1, 0, "%s",
+ archive_error_string(cpio->archive_read_disk));
+ if (r < ARCHIVE_OK)
+ lafe_warnc(0, "%s",
+ archive_error_string(cpio->archive_read_disk));
+ if (r <= ARCHIVE_FAILED) {
+ cpio->return_value = 1;
+ return (r);
+ }
+
+ if (cpio->uid_override >= 0)
+ archive_entry_set_uid(entry, cpio->uid_override);
+ if (cpio->gid_override >= 0)
+ archive_entry_set_gid(entry, cpio->gid_override);
+
+ /*
+ * Generate a destination path for this entry.
+ * "destination path" is the name to which it will be copied in
+ * pass mode or the name that will go into the archive in
+ * output mode.
+ */
+ destpath = srcpath;
+ if (cpio->destdir) {
+ len = strlen(cpio->destdir) + strlen(srcpath) + 8;
+ if (len >= cpio->pass_destpath_alloc) {
+ while (len >= cpio->pass_destpath_alloc) {
+ cpio->pass_destpath_alloc += 512;
+ cpio->pass_destpath_alloc *= 2;
+ }
+ free(cpio->pass_destpath);
+ cpio->pass_destpath = malloc(cpio->pass_destpath_alloc);
+ if (cpio->pass_destpath == NULL)
+ lafe_errc(1, ENOMEM,
+ "Can't allocate path buffer");
+ }
+ strcpy(cpio->pass_destpath, cpio->destdir);
+ p = srcpath;
+ while (p[0] == '/')
+ ++p;
+ strcat(cpio->pass_destpath, p);
+ destpath = cpio->pass_destpath;
+ }
+ if (cpio->option_rename)
+ destpath = cpio_rename(destpath);
+ if (destpath == NULL)
+ return (0);
+ archive_entry_copy_pathname(entry, destpath);
+
+ /*
+ * If we're trying to preserve hardlinks, match them here.
+ */
+ spare = NULL;
+ if (cpio->linkresolver != NULL
+ && archive_entry_filetype(entry) != AE_IFDIR) {
+ archive_entry_linkify(cpio->linkresolver, &entry, &spare);
+ }
+
+ if (entry != NULL) {
+ r = entry_to_archive(cpio, entry);
+ archive_entry_free(entry);
+ if (spare != NULL) {
+ if (r == 0)
+ r = entry_to_archive(cpio, spare);
+ archive_entry_free(spare);
+ }
+ }
+ return (r);
+}
+
+static int
+entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
+{
+ const char *destpath = archive_entry_pathname(entry);
+ const char *srcpath = archive_entry_sourcepath(entry);
+ int fd = -1;
+ ssize_t bytes_read;
+ int r;
+
+ /* Print out the destination name to the user. */
+ if (cpio->verbose)
+ fprintf(stderr,"%s", destpath);
+
+ /*
+ * Option_link only makes sense in pass mode and for
+ * regular files. Also note: if a link operation fails
+ * because of cross-device restrictions, we'll fall back
+ * to copy mode for that entry.
+ *
+ * TODO: Test other cpio implementations to see if they
+ * hard-link anything other than regular files here.
+ */
+ if (cpio->option_link
+ && archive_entry_filetype(entry) == AE_IFREG)
+ {
+ struct archive_entry *t;
+ /* Save the original entry in case we need it later. */
+ t = archive_entry_clone(entry);
+ if (t == NULL)
+ lafe_errc(1, ENOMEM, "Can't create link");
+ /* Note: link(2) doesn't create parent directories,
+ * so we use archive_write_header() instead as a
+ * convenience. */
+ archive_entry_set_hardlink(t, srcpath);
+ /* This is a straight link that carries no data. */
+ archive_entry_set_size(t, 0);
+ r = archive_write_header(cpio->archive, t);
+ archive_entry_free(t);
+ if (r != ARCHIVE_OK)
+ lafe_warnc(archive_errno(cpio->archive),
+ "%s", archive_error_string(cpio->archive));
+ if (r == ARCHIVE_FATAL)
+ exit(1);
+#ifdef EXDEV
+ if (r != ARCHIVE_OK && archive_errno(cpio->archive) == EXDEV) {
+ /* Cross-device link: Just fall through and use
+ * the original entry to copy the file over. */
+ lafe_warnc(0, "Copying file instead");
+ } else
+#endif
+ return (0);
+ }
+
+ /*
+ * Make sure we can open the file (if necessary) before
+ * trying to write the header.
+ */
+ if (archive_entry_filetype(entry) == AE_IFREG) {
+ if (archive_entry_size(entry) > 0) {
+ fd = open(srcpath, O_RDONLY | O_BINARY);
+ if (fd < 0) {
+ lafe_warnc(errno,
+ "%s: could not open file", srcpath);
+ goto cleanup;
+ }
+ }
+ } else {
+ archive_entry_set_size(entry, 0);
+ }
+
+ r = archive_write_header(cpio->archive, entry);
+
+ if (r != ARCHIVE_OK)
+ lafe_warnc(archive_errno(cpio->archive),
+ "%s: %s",
+ srcpath,
+ archive_error_string(cpio->archive));
+
+ if (r == ARCHIVE_FATAL)
+ exit(1);
+
+ if (r >= ARCHIVE_WARN && fd >= 0) {
+ bytes_read = read(fd, cpio->buff, cpio->buff_size);
+ while (bytes_read > 0) {
+ r = archive_write_data(cpio->archive,
+ cpio->buff, bytes_read);
+ if (r < 0)
+ lafe_errc(1, archive_errno(cpio->archive),
+ "%s", archive_error_string(cpio->archive));
+ if (r < bytes_read) {
+ lafe_warnc(0,
+ "Truncated write; file may have grown while being archived.");
+ }
+ bytes_read = read(fd, cpio->buff, cpio->buff_size);
+ }
+ }
+
+ fd = restore_time(cpio, entry, srcpath, fd);
+
+cleanup:
+ if (cpio->verbose)
+ fprintf(stderr,"\n");
+ if (fd >= 0)
+ close(fd);
+ return (0);
+}
+
+static int
+restore_time(struct cpio *cpio, struct archive_entry *entry,
+ const char *name, int fd)
+{
+#ifndef HAVE_UTIMES
+ static int warned = 0;
+
+ (void)cpio; /* UNUSED */
+ (void)entry; /* UNUSED */
+ (void)name; /* UNUSED */
+
+ if (!warned)
+ lafe_warnc(0, "Can't restore access times on this platform");
+ warned = 1;
+ return (fd);
+#else
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ struct __timeval times[2];
+#else
+ struct timeval times[2];
+#endif
+
+ if (!cpio->option_atime_restore)
+ return (fd);
+
+ times[1].tv_sec = archive_entry_mtime(entry);
+ times[1].tv_usec = archive_entry_mtime_nsec(entry) / 1000;
+
+ times[0].tv_sec = archive_entry_atime(entry);
+ times[0].tv_usec = archive_entry_atime_nsec(entry) / 1000;
+
+#if defined(HAVE_FUTIMES) && !defined(__CYGWIN__)
+ if (fd >= 0 && futimes(fd, times) == 0)
+ return (fd);
+#endif
+ /*
+ * Some platform cannot restore access times if the file descriptor
+ * is still opened.
+ */
+ if (fd >= 0) {
+ close(fd);
+ fd = -1;
+ }
+
+#ifdef HAVE_LUTIMES
+ if (lutimes(name, times) != 0)
+#else
+ if ((AE_IFLNK != archive_entry_filetype(entry))
+ && utimes(name, times) != 0)
+#endif
+ lafe_warnc(errno, "Can't update time for %s", name);
+#endif
+ return (fd);
+}
+
+
+static void
+mode_in(struct cpio *cpio)
+{
+ struct archive *a;
+ struct archive_entry *entry;
+ struct archive *ext;
+ const char *destpath;
+ int r;
+
+ ext = archive_write_disk_new();
+ if (ext == NULL)
+ lafe_errc(1, 0, "Couldn't allocate restore object");
+ r = archive_write_disk_set_options(ext, cpio->extract_flags);
+ if (r != ARCHIVE_OK)
+ lafe_errc(1, 0, "%s", archive_error_string(ext));
+ a = archive_read_new();
+ if (a == NULL)
+ lafe_errc(1, 0, "Couldn't allocate archive object");
+ archive_read_support_compression_all(a);
+ archive_read_support_format_all(a);
+
+ if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block))
+ lafe_errc(1, archive_errno(a),
+ "%s", archive_error_string(a));
+ for (;;) {
+ r = archive_read_next_header(a, &entry);
+ if (r == ARCHIVE_EOF)
+ break;
+ if (r != ARCHIVE_OK) {
+ lafe_errc(1, archive_errno(a),
+ "%s", archive_error_string(a));
+ }
+ if (lafe_excluded(cpio->matching, archive_entry_pathname(entry)))
+ continue;
+ if (cpio->option_rename) {
+ destpath = cpio_rename(archive_entry_pathname(entry));
+ archive_entry_set_pathname(entry, destpath);
+ } else
+ destpath = archive_entry_pathname(entry);
+ if (destpath == NULL)
+ continue;
+ if (cpio->verbose)
+ fprintf(stdout, "%s\n", destpath);
+ if (cpio->uid_override >= 0)
+ archive_entry_set_uid(entry, cpio->uid_override);
+ if (cpio->gid_override >= 0)
+ archive_entry_set_gid(entry, cpio->gid_override);
+ r = archive_write_header(ext, entry);
+ if (r != ARCHIVE_OK) {
+ fprintf(stderr, "%s: %s\n",
+ archive_entry_pathname(entry),
+ archive_error_string(ext));
+ } else if (archive_entry_size(entry) > 0) {
+ r = extract_data(a, ext);
+ if (r != ARCHIVE_OK)
+ cpio->return_value = 1;
+ }
+ }
+ r = archive_read_close(a);
+ if (r != ARCHIVE_OK)
+ lafe_errc(1, 0, "%s", archive_error_string(a));
+ r = archive_write_close(ext);
+ if (r != ARCHIVE_OK)
+ lafe_errc(1, 0, "%s", archive_error_string(ext));
+ if (!cpio->quiet) {
+ int64_t blocks = (archive_position_uncompressed(a) + 511)
+ / 512;
+ fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
+ blocks == 1 ? "block" : "blocks");
+ }
+ archive_read_finish(a);
+ archive_write_finish(ext);
+ exit(cpio->return_value);
+}
+
+/*
+ * Exits if there's a fatal error. Returns ARCHIVE_OK
+ * if everything is kosher.
+ */
+static int
+extract_data(struct archive *ar, struct archive *aw)
+{
+ int r;
+ size_t size;
+ const void *block;
+ off_t offset;
+
+ for (;;) {
+ r = archive_read_data_block(ar, &block, &size, &offset);
+ if (r == ARCHIVE_EOF)
+ return (ARCHIVE_OK);
+ if (r != ARCHIVE_OK) {
+ lafe_warnc(archive_errno(ar),
+ "%s", archive_error_string(ar));
+ exit(1);
+ }
+ r = archive_write_data_block(aw, block, size, offset);
+ if (r != ARCHIVE_OK) {
+ lafe_warnc(archive_errno(aw),
+ "%s", archive_error_string(aw));
+ return (r);
+ }
+ }
+}
+
+static void
+mode_list(struct cpio *cpio)
+{
+ struct archive *a;
+ struct archive_entry *entry;
+ int r;
+
+ a = archive_read_new();
+ if (a == NULL)
+ lafe_errc(1, 0, "Couldn't allocate archive object");
+ archive_read_support_compression_all(a);
+ archive_read_support_format_all(a);
+
+ if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block))
+ lafe_errc(1, archive_errno(a),
+ "%s", archive_error_string(a));
+ for (;;) {
+ r = archive_read_next_header(a, &entry);
+ if (r == ARCHIVE_EOF)
+ break;
+ if (r != ARCHIVE_OK) {
+ lafe_errc(1, archive_errno(a),
+ "%s", archive_error_string(a));
+ }
+ if (lafe_excluded(cpio->matching, archive_entry_pathname(entry)))
+ continue;
+ if (cpio->verbose)
+ list_item_verbose(cpio, entry);
+ else
+ fprintf(stdout, "%s\n", archive_entry_pathname(entry));
+ }
+ r = archive_read_close(a);
+ if (r != ARCHIVE_OK)
+ lafe_errc(1, 0, "%s", archive_error_string(a));
+ if (!cpio->quiet) {
+ int64_t blocks = (archive_position_uncompressed(a) + 511)
+ / 512;
+ fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
+ blocks == 1 ? "block" : "blocks");
+ }
+ archive_read_finish(a);
+ exit(0);
+}
+
+/*
+ * Display information about the current file.
+ *
+ * The format here roughly duplicates the output of 'ls -l'.
+ * This is based on SUSv2, where 'tar tv' is documented as
+ * listing additional information in an "unspecified format,"
+ * and 'pax -l' is documented as using the same format as 'ls -l'.
+ */
+static void
+list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
+{
+ char size[32];
+ char date[32];
+ char uids[16], gids[16];
+ const char *uname, *gname;
+ FILE *out = stdout;
+ const char *fmt;
+ time_t mtime;
+ static time_t now;
+
+ if (!now)
+ time(&now);
+
+ if (cpio->option_numeric_uid_gid) {
+ /* Format numeric uid/gid for display. */
+ strcpy(uids, cpio_i64toa(archive_entry_uid(entry)));
+ uname = uids;
+ strcpy(gids, cpio_i64toa(archive_entry_gid(entry)));
+ gname = gids;
+ } else {
+ /* Use uname if it's present, else lookup name from uid. */
+ uname = archive_entry_uname(entry);
+ if (uname == NULL)
+ uname = lookup_uname(cpio, archive_entry_uid(entry));
+ /* Use gname if it's present, else lookup name from gid. */
+ gname = archive_entry_gname(entry);
+ if (gname == NULL)
+ gname = lookup_gname(cpio, archive_entry_gid(entry));
+ }
+
+ /* Print device number or file size. */
+ if (archive_entry_filetype(entry) == AE_IFCHR
+ || archive_entry_filetype(entry) == AE_IFBLK) {
+ snprintf(size, sizeof(size), "%lu,%lu",
+ (unsigned long)archive_entry_rdevmajor(entry),
+ (unsigned long)archive_entry_rdevminor(entry));
+ } else {
+ strcpy(size, cpio_i64toa(archive_entry_size(entry)));
+ }
+
+ /* Format the time using 'ls -l' conventions. */
+ mtime = archive_entry_mtime(entry);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Windows' strftime function does not support %e format. */
+ if (mtime - now > 365*86400/2
+ || mtime - now < -365*86400/2)
+ fmt = cpio->day_first ? "%d %b %Y" : "%b %d %Y";
+ else
+ fmt = cpio->day_first ? "%d %b %H:%M" : "%b %d %H:%M";
+#else
+ if (abs(mtime - now) > (365/2)*86400)
+ fmt = cpio->day_first ? "%e %b %Y" : "%b %e %Y";
+ else
+ fmt = cpio->day_first ? "%e %b %H:%M" : "%b %e %H:%M";
+#endif
+ strftime(date, sizeof(date), fmt, localtime(&mtime));
+
+ fprintf(out, "%s%3d %-8s %-8s %8s %12s %s",
+ archive_entry_strmode(entry),
+ archive_entry_nlink(entry),
+ uname, gname, size, date,
+ archive_entry_pathname(entry));
+
+ /* Extra information for links. */
+ if (archive_entry_hardlink(entry)) /* Hard link */
+ fprintf(out, " link to %s", archive_entry_hardlink(entry));
+ else if (archive_entry_symlink(entry)) /* Symbolic link */
+ fprintf(out, " -> %s", archive_entry_symlink(entry));
+ fprintf(out, "\n");
+}
+
+static void
+mode_pass(struct cpio *cpio, const char *destdir)
+{
+ struct lafe_line_reader *lr;
+ const char *p;
+ int r;
+
+ /* Ensure target dir has a trailing '/' to simplify path surgery. */
+ cpio->destdir = malloc(strlen(destdir) + 8);
+ strcpy(cpio->destdir, destdir);
+ if (destdir[strlen(destdir) - 1] != '/')
+ strcat(cpio->destdir, "/");
+
+ cpio->archive = archive_write_disk_new();
+ if (cpio->archive == NULL)
+ lafe_errc(1, 0, "Failed to allocate archive object");
+ r = archive_write_disk_set_options(cpio->archive, cpio->extract_flags);
+ if (r != ARCHIVE_OK)
+ lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
+ cpio->linkresolver = archive_entry_linkresolver_new();
+ archive_write_disk_set_standard_lookup(cpio->archive);
+
+ cpio->archive_read_disk = archive_read_disk_new();
+ if (cpio->archive_read_disk == NULL)
+ lafe_errc(1, 0, "Failed to allocate archive object");
+ if (cpio->option_follow_links)
+ archive_read_disk_set_symlink_logical(cpio->archive_read_disk);
+ else
+ archive_read_disk_set_symlink_physical(cpio->archive_read_disk);
+ archive_read_disk_set_standard_lookup(cpio->archive_read_disk);
+
+ lr = lafe_line_reader("-", cpio->option_null);
+ while ((p = lafe_line_reader_next(lr)) != NULL)
+ file_to_archive(cpio, p);
+ lafe_line_reader_free(lr);
+
+ archive_entry_linkresolver_free(cpio->linkresolver);
+ r = archive_write_close(cpio->archive);
+ if (r != ARCHIVE_OK)
+ lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
+
+ if (!cpio->quiet) {
+ int64_t blocks =
+ (archive_position_uncompressed(cpio->archive) + 511)
+ / 512;
+ fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
+ blocks == 1 ? "block" : "blocks");
+ }
+
+ archive_write_finish(cpio->archive);
+}
+
+/*
+ * Prompt for a new name for this entry. Returns a pointer to the
+ * new name or NULL if the entry should not be copied. This
+ * implements the semantics defined in POSIX.1-1996, which specifies
+ * that an input of '.' means the name should be unchanged. GNU cpio
+ * treats '.' as a literal new name.
+ */
+static const char *
+cpio_rename(const char *name)
+{
+ static char buff[1024];
+ FILE *t;
+ char *p, *ret;
+
+ t = fopen("/dev/tty", "r+");
+ if (t == NULL)
+ return (name);
+ fprintf(t, "%s (Enter/./(new name))? ", name);
+ fflush(t);
+
+ p = fgets(buff, sizeof(buff), t);
+ fclose(t);
+ if (p == NULL)
+ /* End-of-file is a blank line. */
+ return (NULL);
+
+ while (*p == ' ' || *p == '\t')
+ ++p;
+ if (*p == '\n' || *p == '\0')
+ /* Empty line. */
+ return (NULL);
+ if (*p == '.' && p[1] == '\n')
+ /* Single period preserves original name. */
+ return (name);
+ ret = p;
+ /* Trim the final newline. */
+ while (*p != '\0' && *p != '\n')
+ ++p;
+ /* Overwrite the final \n with a null character. */
+ *p = '\0';
+ return (ret);
+}
+
+static void
+free_cache(struct name_cache *cache)
+{
+ size_t i;
+
+ if (cache != NULL) {
+ for (i = 0; i < cache->size; i++)
+ free(cache->cache[i].name);
+ free(cache);
+ }
+}
+
+/*
+ * Lookup uname/gname from uid/gid, return NULL if no match.
+ */
+static const char *
+lookup_name(struct cpio *cpio, struct name_cache **name_cache_variable,
+ int (*lookup_fn)(struct cpio *, const char **, id_t), id_t id)
+{
+ char asnum[16];
+ struct name_cache *cache;
+ const char *name;
+ int slot;
+
+
+ if (*name_cache_variable == NULL) {
+ *name_cache_variable = malloc(sizeof(struct name_cache));
+ if (*name_cache_variable == NULL)
+ lafe_errc(1, ENOMEM, "No more memory");
+ memset(*name_cache_variable, 0, sizeof(struct name_cache));
+ (*name_cache_variable)->size = name_cache_size;
+ }
+
+ cache = *name_cache_variable;
+ cache->probes++;
+
+ slot = id % cache->size;
+ if (cache->cache[slot].name != NULL) {
+ if (cache->cache[slot].id == id) {
+ cache->hits++;
+ return (cache->cache[slot].name);
+ }
+ free(cache->cache[slot].name);
+ cache->cache[slot].name = NULL;
+ }
+
+ if (lookup_fn(cpio, &name, id) == 0) {
+ if (name == NULL || name[0] == '\0') {
+ /* If lookup failed, format it as a number. */
+ snprintf(asnum, sizeof(asnum), "%u", (unsigned)id);
+ name = asnum;
+ }
+ cache->cache[slot].name = strdup(name);
+ if (cache->cache[slot].name != NULL) {
+ cache->cache[slot].id = id;
+ return (cache->cache[slot].name);
+ }
+ /*
+ * Conveniently, NULL marks an empty slot, so
+ * if the strdup() fails, we've just failed to
+ * cache it. No recovery necessary.
+ */
+ }
+ return (NULL);
+}
+
+static const char *
+lookup_uname(struct cpio *cpio, uid_t uid)
+{
+ return (lookup_name(cpio, &cpio->uname_cache,
+ &lookup_uname_helper, (id_t)uid));
+}
+
+static int
+lookup_uname_helper(struct cpio *cpio, const char **name, id_t id)
+{
+ struct passwd *pwent;
+
+ (void)cpio; /* UNUSED */
+
+ errno = 0;
+ pwent = getpwuid((uid_t)id);
+ if (pwent == NULL) {
+ *name = NULL;
+ if (errno != 0 && errno != ENOENT)
+ lafe_warnc(errno, "getpwuid(%d) failed", id);
+ return (errno);
+ }
+
+ *name = pwent->pw_name;
+ return (0);
+}
+
+static const char *
+lookup_gname(struct cpio *cpio, gid_t gid)
+{
+ return (lookup_name(cpio, &cpio->gname_cache,
+ &lookup_gname_helper, (id_t)gid));
+}
+
+static int
+lookup_gname_helper(struct cpio *cpio, const char **name, id_t id)
+{
+ struct group *grent;
+
+ (void)cpio; /* UNUSED */
+
+ errno = 0;
+ grent = getgrgid((gid_t)id);
+ if (grent == NULL) {
+ *name = NULL;
+ if (errno != 0)
+ lafe_warnc(errno, "getgrgid(%d) failed", id);
+ return (errno);
+ }
+
+ *name = grent->gr_name;
+ return (0);
+}
+
+/*
+ * It would be nice to just use printf() for formatting large numbers,
+ * but the compatibility problems are a big headache. Hence the
+ * following simple utility function.
+ */
+const char *
+cpio_i64toa(int64_t n0)
+{
+ // 2^64 =~ 1.8 * 10^19, so 20 decimal digits suffice.
+ // We also need 1 byte for '-' and 1 for '\0'.
+ static char buff[22];
+ int64_t n = n0 < 0 ? -n0 : n0;
+ char *p = buff + sizeof(buff);
+
+ *--p = '\0';
+ do {
+ *--p = '0' + (int)(n % 10);
+ n /= 10;
+ } while (n > 0);
+ if (n0 < 0)
+ *--p = '-';
+ return p;
+}
diff --git a/cpio/cpio.h b/cpio/cpio.h
new file mode 100644
index 000000000000..3eed83494b8e
--- /dev/null
+++ b/cpio/cpio.h
@@ -0,0 +1,109 @@
+/*-
+ * 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.
+ *
+ * $FreeBSD: src/usr.bin/cpio/cpio.h,v 1.7 2008/12/06 07:30:40 kientzle Exp $
+ */
+
+#ifndef CPIO_H_INCLUDED
+#define CPIO_H_INCLUDED
+
+#include "cpio_platform.h"
+#include <stdio.h>
+
+#include "matching.h"
+
+/*
+ * The internal state for the "cpio" program.
+ *
+ * Keeping all of the state in a structure like this simplifies memory
+ * leak testing (at exit, anything left on the heap is suspect). A
+ * pointer to this structure is passed to most cpio internal
+ * functions.
+ */
+struct cpio {
+ /* Option parsing */
+ const char *optarg;
+
+ /* Options */
+ const char *filename;
+ char mode; /* -i -o -p */
+ char compress; /* -j, -y, or -z */
+ const char *format; /* -H format */
+ int bytes_per_block; /* -b block_size */
+ int verbose; /* -v */
+ int quiet; /* --quiet */
+ int extract_flags; /* Flags for extract operation */
+ char symlink_mode; /* H or L, per BSD conventions */
+ const char *compress_program;
+ int option_append; /* -A, only relevant for -o */
+ int option_atime_restore; /* -a */
+ int option_follow_links; /* -L */
+ int option_link; /* -l */
+ int option_list; /* -t */
+ char option_null; /* --null */
+ int option_numeric_uid_gid; /* -n */
+ int option_rename; /* -r */
+ char *destdir;
+ size_t pass_destpath_alloc;
+ char *pass_destpath;
+ int uid_override;
+ int gid_override;
+ int day_first; /* true if locale prefers day/mon */
+
+ /* If >= 0, then close this when done. */
+ int fd;
+
+ /* Miscellaneous state information */
+ struct archive *archive;
+ struct archive *archive_read_disk;
+ int argc;
+ char **argv;
+ int return_value; /* Value returned by main() */
+ struct archive_entry_linkresolver *linkresolver;
+
+ struct name_cache *uname_cache;
+ struct name_cache *gname_cache;
+
+ /* Work data. */
+ struct lafe_matching *matching;
+ char *buff;
+ size_t buff_size;
+};
+
+const char *owner_parse(const char *, int *, int *);
+
+
+/* Fake short equivalents for long options that otherwise lack them. */
+enum {
+ OPTION_INSECURE = 1,
+ OPTION_LZMA,
+ OPTION_NO_PRESERVE_OWNER,
+ OPTION_PRESERVE_OWNER,
+ OPTION_QUIET,
+ OPTION_VERSION
+};
+
+int cpio_getopt(struct cpio *cpio);
+
+#endif
diff --git a/cpio/cpio_platform.h b/cpio/cpio_platform.h
new file mode 100644
index 000000000000..31d9a738fcb0
--- /dev/null
+++ b/cpio/cpio_platform.h
@@ -0,0 +1,77 @@
+/*-
+ * 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.
+ *
+ * $FreeBSD: src/usr.bin/cpio/cpio_platform.h,v 1.2 2008/12/06 07:15:42 kientzle Exp $
+ */
+
+/*
+ * This header is the first thing included in any of the cpio
+ * source files. As far as possible, platform-specific issues should
+ * be dealt with here and not within individual source files.
+ */
+
+#ifndef CPIO_PLATFORM_H_INCLUDED
+#define CPIO_PLATFORM_H_INCLUDED
+
+#if defined(PLATFORM_CONFIG_H)
+/* Use hand-built config.h in environments that need it. */
+#include PLATFORM_CONFIG_H
+#else
+/* Read config.h or die trying. */
+#include "config.h"
+#endif
+
+/* Get a real definition for __FBSDID if we can */
+#if HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+
+/* If not, define it so as to avoid dangling semicolons. */
+#ifndef __FBSDID
+#define __FBSDID(a) struct _undefined_hack
+#endif
+
+#ifdef HAVE_LIBARCHIVE
+/* If we're using the platform libarchive, include system headers. */
+#include <archive.h>
+#include <archive_entry.h>
+#else
+/* Otherwise, include user headers. */
+#include "archive.h"
+#include "archive_entry.h"
+#endif
+
+/* How to mark functions that don't return. */
+#if defined(__GNUC__) && (__GNUC__ > 2 || \
+ (__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
+#define __LA_DEAD __attribute__((__noreturn__))
+#else
+#define __LA_DEAD
+#endif
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include "cpio_windows.h"
+#endif
+
+#endif /* !CPIO_PLATFORM_H_INCLUDED */
diff --git a/cpio/cpio_windows.c b/cpio/cpio_windows.c
new file mode 100644
index 000000000000..420e01d5e192
--- /dev/null
+++ b/cpio/cpio_windows.c
@@ -0,0 +1,338 @@
+/*-
+ * Copyright (c) 2009 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$
+ */
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+
+#include "cpio_platform.h"
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <io.h>
+#include <stddef.h>
+#ifdef HAVE_SYS_UTIME_H
+#include <sys/utime.h>
+#endif
+#include <sys/stat.h>
+#include <process.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <windows.h>
+#include <sddl.h>
+
+#include "cpio.h"
+#include "err.h"
+
+#define EPOC_TIME (116444736000000000ULL)
+
+static void cpio_dosmaperr(unsigned long);
+
+/*
+ * Prepend "\\?\" to the path name and convert it to unicode to permit
+ * an extended-length path for a maximum total path length of 32767
+ * characters.
+ * see also http://msdn.microsoft.com/en-us/library/aa365247.aspx
+ */
+static wchar_t *
+permissive_name(const char *name)
+{
+ wchar_t *wn, *wnp;
+ wchar_t *ws, *wsp;
+ DWORD l, len, slen, alloclen;
+ int unc;
+
+ len = (DWORD)strlen(name);
+ wn = malloc((len + 1) * sizeof(wchar_t));
+ if (wn == NULL)
+ return (NULL);
+ l = MultiByteToWideChar(CP_ACP, 0, name, len, wn, len);
+ if (l == 0) {
+ free(wn);
+ return (NULL);
+ }
+ wn[l] = L'\0';
+
+ /* Get a full path names */
+ l = GetFullPathNameW(wn, 0, NULL, NULL);
+ if (l == 0) {
+ free(wn);
+ return (NULL);
+ }
+ wnp = malloc(l * sizeof(wchar_t));
+ if (wnp == NULL) {
+ free(wn);
+ return (NULL);
+ }
+ len = GetFullPathNameW(wn, l, wnp, NULL);
+ free(wn);
+ wn = wnp;
+
+ if (wnp[0] == L'\\' && wnp[1] == L'\\' &&
+ wnp[2] == L'?' && wnp[3] == L'\\')
+ /* We have already permissive names. */
+ return (wn);
+
+ if (wnp[0] == L'\\' && wnp[1] == L'\\' &&
+ wnp[2] == L'.' && wnp[3] == L'\\') {
+ /* Device names */
+ if (((wnp[4] >= L'a' && wnp[4] <= L'z') ||
+ (wnp[4] >= L'A' && wnp[4] <= L'Z')) &&
+ wnp[5] == L':' && wnp[6] == L'\\')
+ wnp[2] = L'?';/* Not device names. */
+ return (wn);
+ }
+
+ unc = 0;
+ if (wnp[0] == L'\\' && wnp[1] == L'\\' && wnp[2] != L'\\') {
+ wchar_t *p = &wnp[2];
+
+ /* Skip server-name letters. */
+ while (*p != L'\\' && *p != L'\0')
+ ++p;
+ if (*p == L'\\') {
+ wchar_t *rp = ++p;
+ /* Skip share-name letters. */
+ while (*p != L'\\' && *p != L'\0')
+ ++p;
+ if (*p == L'\\' && p != rp) {
+ /* Now, match patterns such as
+ * "\\server-name\share-name\" */
+ wnp += 2;
+ len -= 2;
+ unc = 1;
+ }
+ }
+ }
+
+ alloclen = slen = 4 + (unc * 4) + len + 1;
+ ws = wsp = malloc(slen * sizeof(wchar_t));
+ if (ws == NULL) {
+ free(wn);
+ return (NULL);
+ }
+ /* prepend "\\?\" */
+ wcsncpy(wsp, L"\\\\?\\", 4);
+ wsp += 4;
+ slen -= 4;
+ if (unc) {
+ /* append "UNC\" ---> "\\?\UNC\" */
+ wcsncpy(wsp, L"UNC\\", 4);
+ wsp += 4;
+ slen -= 4;
+ }
+ wcsncpy(wsp, wnp, slen);
+ free(wn);
+ ws[alloclen - 1] = L'\0';
+ return (ws);
+}
+
+static HANDLE
+cpio_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode,
+ LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
+ DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
+{
+ wchar_t *wpath;
+ HANDLE handle;
+
+ handle = CreateFileA(path, dwDesiredAccess, dwShareMode,
+ lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes,
+ hTemplateFile);
+ if (handle != INVALID_HANDLE_VALUE)
+ return (handle);
+ if (GetLastError() != ERROR_PATH_NOT_FOUND)
+ return (handle);
+ wpath = permissive_name(path);
+ if (wpath == NULL)
+ return (handle);
+ handle = CreateFileW(wpath, dwDesiredAccess, dwShareMode,
+ lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes,
+ hTemplateFile);
+ free(wpath);
+ return (handle);
+}
+
+#define WINTIME(sec, usec) ((Int32x32To64(sec, 10000000) + EPOC_TIME) + (usec * 10))
+static int
+__hutimes(HANDLE handle, const struct __timeval *times)
+{
+ ULARGE_INTEGER wintm;
+ FILETIME fatime, fmtime;
+
+ wintm.QuadPart = WINTIME(times[0].tv_sec, times[0].tv_usec);
+ fatime.dwLowDateTime = wintm.LowPart;
+ fatime.dwHighDateTime = wintm.HighPart;
+ wintm.QuadPart = WINTIME(times[1].tv_sec, times[1].tv_usec);
+ fmtime.dwLowDateTime = wintm.LowPart;
+ fmtime.dwHighDateTime = wintm.HighPart;
+ if (SetFileTime(handle, NULL, &fatime, &fmtime) == 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+ return (0);
+}
+
+int
+futimes(int fd, const struct __timeval *times)
+{
+
+ return (__hutimes((HANDLE)_get_osfhandle(fd), times));
+}
+
+int
+utimes(const char *name, const struct __timeval *times)
+{
+ int ret;
+ HANDLE handle;
+
+ handle = cpio_CreateFile(name, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (handle == INVALID_HANDLE_VALUE) {
+ cpio_dosmaperr(GetLastError());
+ return (-1);
+ }
+ ret = __hutimes(handle, times);
+ CloseHandle(handle);
+ return (ret);
+}
+
+/*
+ * The following function was modified from PostgreSQL sources and is
+ * subject to the copyright below.
+ */
+/*-------------------------------------------------------------------------
+ *
+ * win32error.c
+ * Map win32 error codes to errno values
+ *
+ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * $PostgreSQL: pgsql/src/port/win32error.c,v 1.4 2008/01/01 19:46:00 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+/*
+PostgreSQL Database Management System
+(formerly known as Postgres, then as Postgres95)
+
+Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
+
+Portions Copyright (c) 1994, The Regents of the University of California
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose, without fee, and without a written agreement
+is hereby granted, provided that the above copyright notice and this
+paragraph and the following two paragraphs appear in all copies.
+
+IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
+LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
+DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
+PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+*/
+
+static const struct {
+ DWORD winerr;
+ int doserr;
+} doserrors[] =
+{
+ { ERROR_INVALID_FUNCTION, EINVAL },
+ { ERROR_FILE_NOT_FOUND, ENOENT },
+ { ERROR_PATH_NOT_FOUND, ENOENT },
+ { ERROR_TOO_MANY_OPEN_FILES, EMFILE },
+ { ERROR_ACCESS_DENIED, EACCES },
+ { ERROR_INVALID_HANDLE, EBADF },
+ { ERROR_ARENA_TRASHED, ENOMEM },
+ { ERROR_NOT_ENOUGH_MEMORY, ENOMEM },
+ { ERROR_INVALID_BLOCK, ENOMEM },
+ { ERROR_BAD_ENVIRONMENT, E2BIG },
+ { ERROR_BAD_FORMAT, ENOEXEC },
+ { ERROR_INVALID_ACCESS, EINVAL },
+ { ERROR_INVALID_DATA, EINVAL },
+ { ERROR_INVALID_DRIVE, ENOENT },
+ { ERROR_CURRENT_DIRECTORY, EACCES },
+ { ERROR_NOT_SAME_DEVICE, EXDEV },
+ { ERROR_NO_MORE_FILES, ENOENT },
+ { ERROR_LOCK_VIOLATION, EACCES },
+ { ERROR_SHARING_VIOLATION, EACCES },
+ { ERROR_BAD_NETPATH, ENOENT },
+ { ERROR_NETWORK_ACCESS_DENIED, EACCES },
+ { ERROR_BAD_NET_NAME, ENOENT },
+ { ERROR_FILE_EXISTS, EEXIST },
+ { ERROR_CANNOT_MAKE, EACCES },
+ { ERROR_FAIL_I24, EACCES },
+ { ERROR_INVALID_PARAMETER, EINVAL },
+ { ERROR_NO_PROC_SLOTS, EAGAIN },
+ { ERROR_DRIVE_LOCKED, EACCES },
+ { ERROR_BROKEN_PIPE, EPIPE },
+ { ERROR_DISK_FULL, ENOSPC },
+ { ERROR_INVALID_TARGET_HANDLE, EBADF },
+ { ERROR_INVALID_HANDLE, EINVAL },
+ { ERROR_WAIT_NO_CHILDREN, ECHILD },
+ { ERROR_CHILD_NOT_COMPLETE, ECHILD },
+ { ERROR_DIRECT_ACCESS_HANDLE, EBADF },
+ { ERROR_NEGATIVE_SEEK, EINVAL },
+ { ERROR_SEEK_ON_DEVICE, EACCES },
+ { ERROR_DIR_NOT_EMPTY, ENOTEMPTY },
+ { ERROR_NOT_LOCKED, EACCES },
+ { ERROR_BAD_PATHNAME, ENOENT },
+ { ERROR_MAX_THRDS_REACHED, EAGAIN },
+ { ERROR_LOCK_FAILED, EACCES },
+ { ERROR_ALREADY_EXISTS, EEXIST },
+ { ERROR_FILENAME_EXCED_RANGE, ENOENT },
+ { ERROR_NESTING_NOT_ALLOWED, EAGAIN },
+ { ERROR_NOT_ENOUGH_QUOTA, ENOMEM }
+};
+
+static void
+cpio_dosmaperr(unsigned long e)
+{
+ int i;
+
+ if (e == 0) {
+ errno = 0;
+ return;
+ }
+
+ for (i = 0; i < sizeof(doserrors); i++) {
+ if (doserrors[i].winerr == e) {
+ errno = doserrors[i].doserr;
+ return;
+ }
+ }
+
+ /* fprintf(stderr, "unrecognized win32 error code: %lu", e); */
+ errno = EINVAL;
+ return;
+}
+#endif
diff --git a/cpio/cpio_windows.h b/cpio/cpio_windows.h
new file mode 100644
index 000000000000..105bf69991de
--- /dev/null
+++ b/cpio/cpio_windows.h
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 2009 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 CPIO_WINDOWS_H
+#define CPIO_WINDOWS_H 1
+
+#include <io.h>
+#include <string.h>
+
+#define getgrgid(id) NULL
+#define getgrnam(name) NULL
+#define getpwnam(name) NULL
+#define getpwuid(id) NULL
+
+#ifdef _MSC_VER
+#define snprintf sprintf_s
+#define strdup _strdup
+#define open _open
+#define read _read
+#define close _close
+#endif
+
+struct passwd {
+ char *pw_name;
+ uid_t pw_uid;
+ gid_t pw_gid;
+};
+
+struct group {
+ char *gr_name;
+ gid_t gr_gid;
+};
+
+struct _timeval64i32 {
+ time_t tv_sec;
+ long tv_usec;
+};
+#define __timeval _timeval64i32
+
+extern int futimes(int fd, const struct __timeval *times);
+#ifndef HAVE_FUTIMES
+#define HAVE_FUTIMES 1
+#endif
+extern int utimes(const char *name, const struct __timeval *times);
+#ifndef HAVE_UTIMES
+#define HAVE_UTIMES 1
+#endif
+
+#endif /* CPIO_WINDOWS_H */
diff --git a/cpio/test/CMakeLists.txt b/cpio/test/CMakeLists.txt
new file mode 100644
index 000000000000..a822bcdfba5b
--- /dev/null
+++ b/cpio/test/CMakeLists.txt
@@ -0,0 +1,79 @@
+############################################
+#
+# How to build bsdcpio_test
+#
+############################################
+IF(ENABLE_CPIO AND ENABLE_TEST)
+ SET(bsdcpio_test_SOURCES
+ ../cmdline.c
+ ../../libarchive_fe/err.c
+ ../../libarchive_fe/pathmatch.c
+ main.c
+ test.h
+ test_0.c
+ test_basic.c
+ test_cmdline.c
+ test_format_newc.c
+ test_gcpio_compat.c
+ test_option_B_upper.c
+ test_option_C_upper.c
+ test_option_J_upper.c
+ test_option_L_upper.c
+ test_option_Z_upper.c
+ test_option_a.c
+ test_option_c.c
+ test_option_d.c
+ test_option_f.c
+ test_option_help.c
+ test_option_l.c
+ test_option_lzma.c
+ test_option_m.c
+ test_option_t.c
+ test_option_u.c
+ test_option_version.c
+ test_option_y.c
+ test_option_z.c
+ test_owner_parse.c
+ test_passthrough_dotdot.c
+ test_passthrough_reverse.c
+ test_pathmatch.c
+ )
+ IF(WIN32 AND NOT CYGWIN)
+ LIST(APPEND bsdcpio_test_SOURCES ../cpio_windows.h)
+ ENDIF(WIN32 AND NOT CYGWIN)
+
+ #
+ # Register target
+ #
+ ADD_EXECUTABLE(bsdcpio_test ${bsdcpio_test_SOURCES})
+ SET_PROPERTY(TARGET bsdcpio_test PROPERTY COMPILE_DEFINITIONS LIST_H)
+
+ #
+ # Generate list.h by grepping DEFINE_TEST() lines out of the C sources.
+ #
+ GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h
+ ${CMAKE_CURRENT_LIST_FILE} ${bsdcpio_test_SOURCES})
+ SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES
+ ${CMAKE_CURRENT_BINARY_DIR})
+
+ # list.h has a line DEFINE_TEST(testname) for every
+ # test. We can use that to define the tests for cmake by
+ # defining a DEFINE_TEST macro and reading list.h in.
+ MACRO (DEFINE_TEST _testname)
+ ADD_TEST_28(
+ NAME bsdcpio_${_testname}
+ COMMAND bsdcpio_test -vv
+ -p $<TARGET_FILE:bsdcpio>
+ -r ${CMAKE_CURRENT_SOURCE_DIR}
+ ${_testname})
+ ENDMACRO (DEFINE_TEST _testname)
+
+ INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h)
+
+ # Experimental new test handling
+ ADD_CUSTOM_TARGET(run_bsdcpio_test
+ COMMAND bsdcpio_test -p ${BSDCPIO} -r ${CMAKE_CURRENT_SOURCE_DIR})
+ ADD_DEPENDENCIES(run_bsdcpio_test bsdcpio)
+ ADD_DEPENDENCIES(run_all_tests run_bsdcpio_test)
+ENDIF(ENABLE_CPIO AND ENABLE_TEST)
+
diff --git a/cpio/test/main.c b/cpio/test/main.c
new file mode 100644
index 000000000000..90336a9e630d
--- /dev/null
+++ b/cpio/test/main.c
@@ -0,0 +1,2140 @@
+/*
+ * Copyright (c) 2003-2009 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "test.h"
+#include <errno.h>
+#include <locale.h>
+#include <stdarg.h>
+#include <time.h>
+
+/*
+ * This same file is used pretty much verbatim for all test harnesses.
+ *
+ * The next few lines are the only differences.
+ * TODO: Move this into a separate configuration header, have all test
+ * suites share one copy of this file.
+ */
+__FBSDID("$FreeBSD: src/usr.bin/cpio/test/main.c,v 1.3 2008/08/24 04:58:22 kientzle Exp $");
+#define KNOWNREF "test_option_f.cpio.uu"
+#define ENVBASE "BSDCPIO" /* Prefix for environment variables. */
+#define PROGRAM "bsdcpio" /* Name of program being tested. */
+#undef LIBRARY /* Not testing a library. */
+#undef EXTRA_DUMP /* How to dump extra data */
+/* How to generate extra version info. */
+#define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "")
+
+/*
+ *
+ * Windows support routines
+ *
+ * Note: Configuration is a tricky issue. Using HAVE_* feature macros
+ * in the test harness is dangerous because they cover up
+ * configuration errors. The classic example of this is omitting a
+ * configure check. If libarchive and libarchive_test both look for
+ * the same feature macro, such errors are hard to detect. Platform
+ * macros (e.g., _WIN32 or __GNUC__) are a little better, but can
+ * easily lead to very messy code. It's best to limit yourself
+ * to only the most generic programming techniques in the test harness
+ * and thus avoid conditionals altogether. Where that's not possible,
+ * try to minimize conditionals by grouping platform-specific tests in
+ * one place (e.g., test_acl_freebsd) or by adding new assert()
+ * functions (e.g., assertMakeHardlink()) to cover up platform
+ * differences. Platform-specific coding in libarchive_test is often
+ * a symptom that some capability is missing from libarchive itself.
+ */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include <io.h>
+#include <windows.h>
+#ifndef F_OK
+#define F_OK (0)
+#endif
+#ifndef S_ISDIR
+#define S_ISDIR(m) ((m) & _S_IFDIR)
+#endif
+#ifndef S_ISREG
+#define S_ISREG(m) ((m) & _S_IFREG)
+#endif
+#if !defined(__BORLANDC__)
+#define access _access
+#define chdir _chdir
+#endif
+#ifndef fileno
+#define fileno _fileno
+#endif
+/*#define fstat _fstat64*/
+#if !defined(__BORLANDC__)
+#define getcwd _getcwd
+#endif
+#define lstat stat
+/*#define lstat _stat64*/
+/*#define stat _stat64*/
+#define rmdir _rmdir
+#if !defined(__BORLANDC__)
+#define strdup _strdup
+#define umask _umask
+#endif
+#define int64_t __int64
+#endif
+
+#if defined(HAVE__CrtSetReportMode)
+# include <crtdbg.h>
+#endif
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+void *GetFunctionKernel32(const char *name)
+{
+ static HINSTANCE lib;
+ static int set;
+ if (!set) {
+ set = 1;
+ lib = LoadLibrary("kernel32.dll");
+ }
+ if (lib == NULL) {
+ fprintf(stderr, "Can't load kernel32.dll?!\n");
+ exit(1);
+ }
+ return (void *)GetProcAddress(lib, name);
+}
+
+static int
+my_CreateSymbolicLinkA(const char *linkname, const char *target, int flags)
+{
+ static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, DWORD);
+ static int set;
+ if (!set) {
+ set = 1;
+ f = GetFunctionKernel32("CreateSymbolicLinkA");
+ }
+ return f == NULL ? 0 : (*f)(linkname, target, flags);
+}
+
+static int
+my_CreateHardLinkA(const char *linkname, const char *target)
+{
+ static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES);
+ static int set;
+ if (!set) {
+ set = 1;
+ f = GetFunctionKernel32("CreateHardLinkA");
+ }
+ return f == NULL ? 0 : (*f)(linkname, target, NULL);
+}
+
+int
+my_GetFileInformationByName(const char *path, BY_HANDLE_FILE_INFORMATION *bhfi)
+{
+ HANDLE h;
+ int r;
+
+ memset(bhfi, 0, sizeof(*bhfi));
+ h = CreateFile(path, FILE_READ_ATTRIBUTES, 0, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ return (0);
+ r = GetFileInformationByHandle(h, bhfi);
+ CloseHandle(h);
+ return (r);
+}
+#endif
+
+#if defined(HAVE__CrtSetReportMode)
+static void
+invalid_parameter_handler(const wchar_t * expression,
+ const wchar_t * function, const wchar_t * file,
+ unsigned int line, uintptr_t pReserved)
+{
+ /* nop */
+}
+#endif
+
+/*
+ *
+ * OPTIONS FLAGS
+ *
+ */
+
+/* Enable core dump on failure. */
+static int dump_on_failure = 0;
+/* Default is to remove temp dirs and log data for successful tests. */
+static int keep_temp_files = 0;
+/* Default is to just report pass/fail for each test. */
+static int verbosity = 0;
+#define VERBOSITY_SUMMARY_ONLY -1 /* -q */
+#define VERBOSITY_PASSFAIL 0 /* Default */
+#define VERBOSITY_LIGHT_REPORT 1 /* -v */
+#define VERBOSITY_FULL 2 /* -vv */
+/* A few places generate even more output for verbosity > VERBOSITY_FULL,
+ * mostly for debugging the test harness itself. */
+/* Cumulative count of assertion failures. */
+static int failures = 0;
+/* Cumulative count of reported skips. */
+static int skips = 0;
+/* Cumulative count of assertions checked. */
+static int assertions = 0;
+
+/* Directory where uuencoded reference files can be found. */
+static const char *refdir;
+
+/*
+ * Report log information selectively to console and/or disk log.
+ */
+static int log_console = 0;
+static FILE *logfile;
+static void
+vlogprintf(const char *fmt, va_list ap)
+{
+#ifdef va_copy
+ va_list lfap;
+ va_copy(lfap, ap);
+#endif
+ if (log_console)
+ vfprintf(stdout, fmt, ap);
+ if (logfile != NULL)
+#ifdef va_copy
+ vfprintf(logfile, fmt, lfap);
+ va_end(lfap);
+#else
+ vfprintf(logfile, fmt, ap);
+#endif
+}
+
+static void
+logprintf(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vlogprintf(fmt, ap);
+ va_end(ap);
+}
+
+/* Set up a message to display only if next assertion fails. */
+static char msgbuff[4096];
+static const char *msg, *nextmsg;
+void
+failure(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vsprintf(msgbuff, fmt, ap);
+ va_end(ap);
+ nextmsg = msgbuff;
+}
+
+/*
+ * Copy arguments into file-local variables.
+ * This was added to permit vararg assert() functions without needing
+ * variadic wrapper macros. Turns out that the vararg capability is almost
+ * never used, so almost all of the vararg assertions can be simplified
+ * by removing the vararg capability and reworking the wrapper macro to
+ * pass __FILE__, __LINE__ directly into the function instead of using
+ * this hook. I suspect this machinery is used so rarely that we
+ * would be better off just removing it entirely. That would simplify
+ * the code here noticably.
+ */
+static const char *test_filename;
+static int test_line;
+static void *test_extra;
+void assertion_setup(const char *filename, int line)
+{
+ test_filename = filename;
+ test_line = line;
+}
+
+/* Called at the beginning of each assert() function. */
+static void
+assertion_count(const char *file, int line)
+{
+ (void)file; /* UNUSED */
+ (void)line; /* UNUSED */
+ ++assertions;
+ /* Proper handling of "failure()" message. */
+ msg = nextmsg;
+ nextmsg = NULL;
+ /* Uncomment to print file:line after every assertion.
+ * Verbose, but occasionally useful in tracking down crashes. */
+ /* printf("Checked %s:%d\n", file, line); */
+}
+
+/*
+ * For each test source file, we remember how many times each
+ * assertion was reported. Cleared before each new test,
+ * used by test_summarize().
+ */
+static struct line {
+ int count;
+ int skip;
+} failed_lines[10000];
+
+/* Count this failure, setup up log destination and handle initial report. */
+static void
+failure_start(const char *filename, int line, const char *fmt, ...)
+{
+ va_list ap;
+
+ /* Record another failure for this line. */
+ ++failures;
+ /* test_filename = filename; */
+ failed_lines[line].count++;
+
+ /* Determine whether to log header to console. */
+ switch (verbosity) {
+ case VERBOSITY_FULL:
+ log_console = 1;
+ break;
+ case VERBOSITY_LIGHT_REPORT:
+ log_console = (failed_lines[line].count < 2);
+ break;
+ default:
+ log_console = 0;
+ }
+
+ /* Log file:line header for this failure */
+ va_start(ap, fmt);
+#if _MSC_VER
+ logprintf("%s(%d): ", filename, line);
+#else
+ logprintf("%s:%d: ", filename, line);
+#endif
+ vlogprintf(fmt, ap);
+ va_end(ap);
+ logprintf("\n");
+
+ if (msg != NULL && msg[0] != '\0') {
+ logprintf(" Description: %s\n", msg);
+ msg = NULL;
+ }
+
+ /* Determine whether to log details to console. */
+ if (verbosity == VERBOSITY_LIGHT_REPORT)
+ log_console = 0;
+}
+
+/* Complete reporting of failed tests. */
+/*
+ * The 'extra' hook here is used by libarchive to include libarchive
+ * error messages with assertion failures. It could also be used
+ * to add strerror() output, for example. Just define the EXTRA_DUMP()
+ * macro appropriately.
+ */
+static void
+failure_finish(void *extra)
+{
+ (void)extra; /* UNUSED (maybe) */
+#ifdef EXTRA_DUMP
+ if (extra != NULL)
+ logprintf(" detail: %s\n", EXTRA_DUMP(extra));
+#endif
+
+ if (dump_on_failure) {
+ fprintf(stderr,
+ " *** forcing core dump so failure can be debugged ***\n");
+ *(char *)(NULL) = 0;
+ exit(1);
+ }
+}
+
+/* Inform user that we're skipping some checks. */
+void
+test_skipping(const char *fmt, ...)
+{
+ char buff[1024];
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsprintf(buff, fmt, ap);
+ va_end(ap);
+ /* failure_start() isn't quite right, but is awfully convenient. */
+ failure_start(test_filename, test_line, "SKIPPING: %s", buff);
+ --failures; /* Undo failures++ in failure_start() */
+ /* Don't failure_finish() here. */
+ /* Mark as skip, so doesn't count as failed test. */
+ failed_lines[test_line].skip = 1;
+ ++skips;
+}
+
+/*
+ *
+ * ASSERTIONS
+ *
+ */
+
+/* Generic assert() just displays the failed condition. */
+int
+assertion_assert(const char *file, int line, int value,
+ const char *condition, void *extra)
+{
+ assertion_count(file, line);
+ if (!value) {
+ failure_start(file, line, "Assertion failed: %s", condition);
+ failure_finish(extra);
+ }
+ return (value);
+}
+
+/* chdir() and report any errors */
+int
+assertion_chdir(const char *file, int line, const char *pathname)
+{
+ assertion_count(file, line);
+ if (chdir(pathname) == 0)
+ return (1);
+ failure_start(file, line, "chdir(\"%s\")", pathname);
+ failure_finish(NULL);
+ return (0);
+
+}
+
+/* Verify two integers are equal. */
+int
+assertion_equal_int(const char *file, int line,
+ long long v1, const char *e1, long long v2, const char *e2, void *extra)
+{
+ assertion_count(file, line);
+ if (v1 == v2)
+ return (1);
+ failure_start(file, line, "%s != %s", e1, e2);
+ logprintf(" %s=%lld (0x%llx, 0%llo)\n", e1, v1, v1, v1);
+ logprintf(" %s=%lld (0x%llx, 0%llo)\n", e2, v2, v2, v2);
+ failure_finish(extra);
+ return (0);
+}
+
+static void strdump(const char *e, const char *p)
+{
+ const char *q = p;
+
+ logprintf(" %s = ", e);
+ if (p == NULL) {
+ logprintf("NULL");
+ return;
+ }
+ logprintf("\"");
+ while (*p != '\0') {
+ unsigned int c = 0xff & *p++;
+ switch (c) {
+ case '\a': printf("\a"); break;
+ case '\b': printf("\b"); break;
+ case '\n': printf("\n"); break;
+ case '\r': printf("\r"); break;
+ default:
+ if (c >= 32 && c < 127)
+ logprintf("%c", c);
+ else
+ logprintf("\\x%02X", c);
+ }
+ }
+ logprintf("\"");
+ logprintf(" (length %d)\n", q == NULL ? -1 : (int)strlen(q));
+}
+
+/* Verify two strings are equal, dump them if not. */
+int
+assertion_equal_string(const char *file, int line,
+ const char *v1, const char *e1,
+ const char *v2, const char *e2,
+ void *extra)
+{
+ assertion_count(file, line);
+ if (v1 == v2 || (v1 != NULL && v2 != NULL && strcmp(v1, v2) == 0))
+ return (1);
+ failure_start(file, line, "%s != %s", e1, e2);
+ strdump(e1, v1);
+ strdump(e2, v2);
+ failure_finish(extra);
+ return (0);
+}
+
+static void
+wcsdump(const char *e, const wchar_t *w)
+{
+ logprintf(" %s = ", e);
+ if (w == NULL) {
+ logprintf("(null)");
+ return;
+ }
+ logprintf("\"");
+ while (*w != L'\0') {
+ unsigned int c = *w++;
+ if (c >= 32 && c < 127)
+ logprintf("%c", c);
+ else if (c < 256)
+ logprintf("\\x%02X", c);
+ else if (c < 0x10000)
+ logprintf("\\u%04X", c);
+ else
+ logprintf("\\U%08X", c);
+ }
+ logprintf("\"\n");
+}
+
+#ifndef HAVE_WCSCMP
+static int
+wcscmp(const wchar_t *s1, const wchar_t *s2)
+{
+
+ while (*s1 == *s2++) {
+ if (*s1++ == L'\0')
+ return 0;
+ }
+ if (*s1 > *--s2)
+ return 1;
+ else
+ return -1;
+}
+#endif
+
+/* Verify that two wide strings are equal, dump them if not. */
+int
+assertion_equal_wstring(const char *file, int line,
+ const wchar_t *v1, const char *e1,
+ const wchar_t *v2, const char *e2,
+ void *extra)
+{
+ assertion_count(file, line);
+ if (v1 == v2 || wcscmp(v1, v2) == 0)
+ return (1);
+ failure_start(file, line, "%s != %s", e1, e2);
+ wcsdump(e1, v1);
+ wcsdump(e2, v2);
+ failure_finish(extra);
+ return (0);
+}
+
+/*
+ * Pretty standard hexdump routine. As a bonus, if ref != NULL, then
+ * any bytes in p that differ from ref will be highlighted with '_'
+ * before and after the hex value.
+ */
+static void
+hexdump(const char *p, const char *ref, size_t l, size_t offset)
+{
+ size_t i, j;
+ char sep;
+
+ if (p == NULL) {
+ logprintf("(null)\n");
+ return;
+ }
+ for(i=0; i < l; i+=16) {
+ logprintf("%04x", (unsigned)(i + offset));
+ sep = ' ';
+ for (j = 0; j < 16 && i + j < l; j++) {
+ if (ref != NULL && p[i + j] != ref[i + j])
+ sep = '_';
+ logprintf("%c%02x", sep, 0xff & (int)p[i+j]);
+ if (ref != NULL && p[i + j] == ref[i + j])
+ sep = ' ';
+ }
+ for (; j < 16; j++) {
+ logprintf("%c ", sep);
+ sep = ' ';
+ }
+ logprintf("%c", sep);
+ for (j=0; j < 16 && i + j < l; j++) {
+ int c = p[i + j];
+ if (c >= ' ' && c <= 126)
+ logprintf("%c", c);
+ else
+ logprintf(".");
+ }
+ logprintf("\n");
+ }
+}
+
+/* Verify that two blocks of memory are the same, display the first
+ * block of differences if they're not. */
+int
+assertion_equal_mem(const char *file, int line,
+ const void *_v1, const char *e1,
+ const void *_v2, const char *e2,
+ size_t l, const char *ld, void *extra)
+{
+ const char *v1 = (const char *)_v1;
+ const char *v2 = (const char *)_v2;
+ size_t offset;
+
+ assertion_count(file, line);
+ if (v1 == v2 || (v1 != NULL && v2 != NULL && memcmp(v1, v2, l) == 0))
+ return (1);
+
+ failure_start(file, line, "%s != %s", e1, e2);
+ logprintf(" size %s = %d\n", ld, (int)l);
+ /* Dump 48 bytes (3 lines) so that the first difference is
+ * in the second line. */
+ offset = 0;
+ while (l > 64 && memcmp(v1, v2, 32) == 0) {
+ /* Two lines agree, so step forward one line. */
+ v1 += 16;
+ v2 += 16;
+ l -= 16;
+ offset += 16;
+ }
+ logprintf(" Dump of %s\n", e1);
+ hexdump(v1, v2, l < 64 ? l : 64, offset);
+ logprintf(" Dump of %s\n", e2);
+ hexdump(v2, v1, l < 64 ? l : 64, offset);
+ logprintf("\n");
+ failure_finish(extra);
+ return (0);
+}
+
+/* Verify that the named file exists and is empty. */
+int
+assertion_empty_file(const char *f1fmt, ...)
+{
+ char buff[1024];
+ char f1[1024];
+ struct stat st;
+ va_list ap;
+ ssize_t s;
+ FILE *f;
+
+ assertion_count(test_filename, test_line);
+ va_start(ap, f1fmt);
+ vsprintf(f1, f1fmt, ap);
+ va_end(ap);
+
+ if (stat(f1, &st) != 0) {
+ failure_start(test_filename, test_line, "Stat failed: %s", f1);
+ failure_finish(NULL);
+ return (0);
+ }
+ if (st.st_size == 0)
+ return (1);
+
+ failure_start(test_filename, test_line, "File should be empty: %s", f1);
+ logprintf(" File size: %d\n", (int)st.st_size);
+ logprintf(" Contents:\n");
+ f = fopen(f1, "rb");
+ if (f == NULL) {
+ logprintf(" Unable to open %s\n", f1);
+ } else {
+ s = ((off_t)sizeof(buff) < st.st_size) ?
+ (ssize_t)sizeof(buff) : (ssize_t)st.st_size;
+ s = fread(buff, 1, s, f);
+ hexdump(buff, NULL, s, 0);
+ fclose(f);
+ }
+ failure_finish(NULL);
+ return (0);
+}
+
+/* Verify that the named file exists and is not empty. */
+int
+assertion_non_empty_file(const char *f1fmt, ...)
+{
+ char f1[1024];
+ struct stat st;
+ va_list ap;
+
+ assertion_count(test_filename, test_line);
+ va_start(ap, f1fmt);
+ vsprintf(f1, f1fmt, ap);
+ va_end(ap);
+
+ if (stat(f1, &st) != 0) {
+ failure_start(test_filename, test_line, "Stat failed: %s", f1);
+ failure_finish(NULL);
+ return (0);
+ }
+ if (st.st_size == 0) {
+ failure_start(test_filename, test_line, "File empty: %s", f1);
+ failure_finish(NULL);
+ return (0);
+ }
+ return (1);
+}
+
+/* Verify that two files have the same contents. */
+/* TODO: hexdump the first bytes that actually differ. */
+int
+assertion_equal_file(const char *fn1, const char *f2pattern, ...)
+{
+ char fn2[1024];
+ va_list ap;
+ char buff1[1024];
+ char buff2[1024];
+ FILE *f1, *f2;
+ int n1, n2;
+
+ assertion_count(test_filename, test_line);
+ va_start(ap, f2pattern);
+ vsprintf(fn2, f2pattern, ap);
+ va_end(ap);
+
+ f1 = fopen(fn1, "rb");
+ f2 = fopen(fn2, "rb");
+ for (;;) {
+ n1 = fread(buff1, 1, sizeof(buff1), f1);
+ n2 = fread(buff2, 1, sizeof(buff2), f2);
+ if (n1 != n2)
+ break;
+ if (n1 == 0 && n2 == 0) {
+ fclose(f1);
+ fclose(f2);
+ return (1);
+ }
+ if (memcmp(buff1, buff2, n1) != 0)
+ break;
+ }
+ fclose(f1);
+ fclose(f2);
+ failure_start(test_filename, test_line, "Files not identical");
+ logprintf(" file1=\"%s\"\n", fn1);
+ logprintf(" file2=\"%s\"\n", fn2);
+ failure_finish(test_extra);
+ return (0);
+}
+
+/* Verify that the named file does exist. */
+int
+assertion_file_exists(const char *fpattern, ...)
+{
+ char f[1024];
+ va_list ap;
+
+ assertion_count(test_filename, test_line);
+ va_start(ap, fpattern);
+ vsprintf(f, fpattern, ap);
+ va_end(ap);
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ if (!_access(f, 0))
+ return (1);
+#else
+ if (!access(f, F_OK))
+ return (1);
+#endif
+ failure_start(test_filename, test_line, "File should exist: %s", f);
+ failure_finish(test_extra);
+ return (0);
+}
+
+/* Verify that the named file doesn't exist. */
+int
+assertion_file_not_exists(const char *fpattern, ...)
+{
+ char f[1024];
+ va_list ap;
+
+ assertion_count(test_filename, test_line);
+ va_start(ap, fpattern);
+ vsprintf(f, fpattern, ap);
+ va_end(ap);
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ if (_access(f, 0))
+ return (1);
+#else
+ if (access(f, F_OK))
+ return (1);
+#endif
+ failure_start(test_filename, test_line, "File should not exist: %s", f);
+ failure_finish(test_extra);
+ return (0);
+}
+
+/* Compare the contents of a file to a block of memory. */
+int
+assertion_file_contents(const void *buff, int s, const char *fpattern, ...)
+{
+ char fn[1024];
+ va_list ap;
+ char *contents;
+ FILE *f;
+ int n;
+
+ assertion_count(test_filename, test_line);
+ va_start(ap, fpattern);
+ vsprintf(fn, fpattern, ap);
+ va_end(ap);
+
+ f = fopen(fn, "rb");
+ if (f == NULL) {
+ failure_start(test_filename, test_line,
+ "File should exist: %s", fn);
+ failure_finish(test_extra);
+ return (0);
+ }
+ contents = malloc(s * 2);
+ n = fread(contents, 1, s * 2, f);
+ fclose(f);
+ if (n == s && memcmp(buff, contents, s) == 0) {
+ free(contents);
+ return (1);
+ }
+ failure_start(test_filename, test_line, "File contents don't match");
+ logprintf(" file=\"%s\"\n", fn);
+ if (n > 0)
+ hexdump(contents, buff, n > 512 ? 512 : n, 0);
+ else {
+ logprintf(" File empty, contents should be:\n");
+ hexdump(buff, NULL, s > 512 ? 512 : n, 0);
+ }
+ failure_finish(test_extra);
+ free(contents);
+ return (0);
+}
+
+/* Check the contents of a text file, being tolerant of line endings. */
+int
+assertion_text_file_contents(const char *buff, const char *fn)
+{
+ char *contents;
+ const char *btxt, *ftxt;
+ FILE *f;
+ int n, s;
+
+ assertion_count(test_filename, test_line);
+ f = fopen(fn, "r");
+ if (f == NULL) {
+ failure_start(test_filename, test_line,
+ "File doesn't exist: %s", fn);
+ failure_finish(test_extra);
+ return (0);
+ }
+ s = strlen(buff);
+ contents = malloc(s * 2 + 128);
+ n = fread(contents, 1, s * 2 + 128 - 1, f);
+ if (n >= 0)
+ contents[n] = '\0';
+ fclose(f);
+ /* Compare texts. */
+ btxt = buff;
+ ftxt = (const char *)contents;
+ while (*btxt != '\0' && *ftxt != '\0') {
+ if (*btxt == *ftxt) {
+ ++btxt;
+ ++ftxt;
+ continue;
+ }
+ if (btxt[0] == '\n' && ftxt[0] == '\r' && ftxt[1] == '\n') {
+ /* Pass over different new line characters. */
+ ++btxt;
+ ftxt += 2;
+ continue;
+ }
+ break;
+ }
+ if (*btxt == '\0' && *ftxt == '\0') {
+ free(contents);
+ return (1);
+ }
+ failure_start(test_filename, test_line, "Contents don't match");
+ logprintf(" file=\"%s\"\n", fn);
+ if (n > 0)
+ hexdump(contents, buff, n, 0);
+ else {
+ logprintf(" File empty, contents should be:\n");
+ hexdump(buff, NULL, s, 0);
+ }
+ failure_finish(test_extra);
+ free(contents);
+ return (0);
+}
+
+/* Test that two paths point to the same file. */
+/* As a side-effect, asserts that both files exist. */
+static int
+is_hardlink(const char *file, int line,
+ const char *path1, const char *path2)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ BY_HANDLE_FILE_INFORMATION bhfi1, bhfi2;
+ int r;
+
+ assertion_count(file, line);
+ r = my_GetFileInformationByName(path1, &bhfi1);
+ if (r == 0) {
+ failure_start(file, line, "File %s can't be inspected?", path1);
+ failure_finish(NULL);
+ return (0);
+ }
+ r = my_GetFileInformationByName(path2, &bhfi2);
+ if (r == 0) {
+ failure_start(file, line, "File %s can't be inspected?", path2);
+ failure_finish(NULL);
+ return (0);
+ }
+ return (bhfi1.dwVolumeSerialNumber == bhfi2.dwVolumeSerialNumber
+ && bhfi1.nFileIndexHigh == bhfi2.nFileIndexHigh
+ && bhfi1.nFileIndexLow == bhfi2.nFileIndexLow);
+#else
+ struct stat st1, st2;
+ int r;
+
+ assertion_count(file, line);
+ r = lstat(path1, &st1);
+ if (r != 0) {
+ failure_start(file, line, "File should exist: %s", path1);
+ failure_finish(NULL);
+ return (0);
+ }
+ r = lstat(path2, &st2);
+ if (r != 0) {
+ failure_start(file, line, "File should exist: %s", path2);
+ failure_finish(NULL);
+ return (0);
+ }
+ return (st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev);
+#endif
+}
+
+int
+assertion_is_hardlink(const char *file, int line,
+ const char *path1, const char *path2)
+{
+ if (is_hardlink(file, line, path1, path2))
+ return (1);
+ failure_start(file, line,
+ "Files %s and %s are not hardlinked", path1, path2);
+ failure_finish(NULL);
+ return (0);
+}
+
+int
+assertion_is_not_hardlink(const char *file, int line,
+ const char *path1, const char *path2)
+{
+ if (!is_hardlink(file, line, path1, path2))
+ return (1);
+ failure_start(file, line,
+ "Files %s and %s should not be hardlinked", path1, path2);
+ failure_finish(NULL);
+ return (0);
+}
+
+/* Verify a/b/mtime of 'pathname'. */
+/* If 'recent', verify that it's within last 10 seconds. */
+static int
+assertion_file_time(const char *file, int line,
+ const char *pathname, long t, long nsec, char type, int recent)
+{
+ long long filet, filet_nsec;
+ int r;
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#define EPOC_TIME (116444736000000000ULL)
+ FILETIME ftime, fbirthtime, fatime, fmtime;
+ ULARGE_INTEGER wintm;
+ HANDLE h;
+ ftime.dwLowDateTime = 0;
+ ftime.dwHighDateTime = 0;
+
+ assertion_count(file, line);
+ h = CreateFile(pathname, FILE_READ_ATTRIBUTES, 0, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE) {
+ failure_start(file, line, "Can't access %s\n", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+ r = GetFileTime(h, &fbirthtime, &fatime, &fmtime);
+ switch (type) {
+ case 'a': ftime = fatime; break;
+ case 'b': ftime = fbirthtime; break;
+ case 'm': ftime = fmtime; break;
+ }
+ CloseHandle(h);
+ if (r == 0) {
+ failure_start(file, line, "Can't GetFileTime %s\n", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+ wintm.LowPart = ftime.dwLowDateTime;
+ wintm.HighPart = ftime.dwHighDateTime;
+ filet = (wintm.QuadPart - EPOC_TIME) / 10000000;
+ filet_nsec = ((wintm.QuadPart - EPOC_TIME) % 10000000) * 100;
+ nsec = (nsec / 100) * 100; /* Round the request */
+#else
+ struct stat st;
+
+ assertion_count(file, line);
+ r = lstat(pathname, &st);
+ if (r != 0) {
+ failure_start(file, line, "Can't stat %s\n", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+ switch (type) {
+ case 'a': filet = st.st_atime; break;
+ case 'm': filet = st.st_mtime; break;
+ case 'b': filet = 0; break;
+ default: fprintf(stderr, "INTERNAL: Bad type %c for file time", type);
+ exit(1);
+ }
+#if defined(__FreeBSD__)
+ switch (type) {
+ case 'a': filet_nsec = st.st_atimespec.tv_nsec; break;
+ case 'b': filet = st.st_birthtime;
+ filet_nsec = st.st_birthtimespec.tv_nsec; break;
+ case 'm': filet_nsec = st.st_mtimespec.tv_nsec; break;
+ default: fprintf(stderr, "INTERNAL: Bad type %c for file time", type);
+ exit(1);
+ }
+ /* FreeBSD generally only stores to microsecond res, so round. */
+ filet_nsec = (filet_nsec / 1000) * 1000;
+ nsec = (nsec / 1000) * 1000;
+#else
+ filet_nsec = nsec = 0; /* Generic POSIX only has whole seconds. */
+ if (type == 'b') return (1); /* Generic POSIX doesn't have birthtime */
+#if defined(__HAIKU__)
+ if (type == 'a') return (1); /* Haiku doesn't have atime. */
+#endif
+#endif
+#endif
+ if (recent) {
+ /* Check that requested time is up-to-date. */
+ time_t now = time(NULL);
+ if (filet < now - 10 || filet > now + 1) {
+ failure_start(file, line,
+ "File %s has %ctime %ld, %ld seconds ago\n",
+ pathname, type, filet, now - filet);
+ failure_finish(NULL);
+ return (0);
+ }
+ } else if (filet != t || filet_nsec != nsec) {
+ failure_start(file, line,
+ "File %s has %ctime %ld.%09ld, expected %ld.%09ld",
+ pathname, type, filet, filet_nsec, t, nsec);
+ failure_finish(NULL);
+ return (0);
+ }
+ return (1);
+}
+
+/* Verify atime of 'pathname'. */
+int
+assertion_file_atime(const char *file, int line,
+ const char *pathname, long t, long nsec)
+{
+ return assertion_file_time(file, line, pathname, t, nsec, 'a', 0);
+}
+
+/* Verify atime of 'pathname' is up-to-date. */
+int
+assertion_file_atime_recent(const char *file, int line, const char *pathname)
+{
+ return assertion_file_time(file, line, pathname, 0, 0, 'a', 1);
+}
+
+/* Verify birthtime of 'pathname'. */
+int
+assertion_file_birthtime(const char *file, int line,
+ const char *pathname, long t, long nsec)
+{
+ return assertion_file_time(file, line, pathname, t, nsec, 'b', 0);
+}
+
+/* Verify birthtime of 'pathname' is up-to-date. */
+int
+assertion_file_birthtime_recent(const char *file, int line,
+ const char *pathname)
+{
+ return assertion_file_time(file, line, pathname, 0, 0, 'b', 1);
+}
+
+/* Verify mtime of 'pathname'. */
+int
+assertion_file_mtime(const char *file, int line,
+ const char *pathname, long t, long nsec)
+{
+ return assertion_file_time(file, line, pathname, t, nsec, 'm', 0);
+}
+
+/* Verify mtime of 'pathname' is up-to-date. */
+int
+assertion_file_mtime_recent(const char *file, int line, const char *pathname)
+{
+ return assertion_file_time(file, line, pathname, 0, 0, 'm', 1);
+}
+
+/* Verify number of links to 'pathname'. */
+int
+assertion_file_nlinks(const char *file, int line,
+ const char *pathname, int nlinks)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ BY_HANDLE_FILE_INFORMATION bhfi;
+ int r;
+
+ assertion_count(file, line);
+ r = my_GetFileInformationByName(pathname, &bhfi);
+ if (r != 0 && bhfi.nNumberOfLinks == (DWORD)nlinks)
+ return (1);
+ failure_start(file, line, "File %s has %d links, expected %d",
+ pathname, bhfi.nNumberOfLinks, nlinks);
+ failure_finish(NULL);
+ return (0);
+#else
+ struct stat st;
+ int r;
+
+ assertion_count(file, line);
+ r = lstat(pathname, &st);
+ if (r == 0 && st.st_nlink == nlinks)
+ return (1);
+ failure_start(file, line, "File %s has %d links, expected %d",
+ pathname, st.st_nlink, nlinks);
+ failure_finish(NULL);
+ return (0);
+#endif
+}
+
+/* Verify size of 'pathname'. */
+int
+assertion_file_size(const char *file, int line, const char *pathname, long size)
+{
+ int64_t filesize;
+ int r;
+
+ assertion_count(file, line);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ {
+ BY_HANDLE_FILE_INFORMATION bhfi;
+ r = !my_GetFileInformationByName(pathname, &bhfi);
+ filesize = ((int64_t)bhfi.nFileSizeHigh << 32) + bhfi.nFileSizeLow;
+ }
+#else
+ {
+ struct stat st;
+ r = lstat(pathname, &st);
+ filesize = st.st_size;
+ }
+#endif
+ if (r == 0 && filesize == size)
+ return (1);
+ failure_start(file, line, "File %s has size %ld, expected %ld",
+ pathname, (long)filesize, (long)size);
+ failure_finish(NULL);
+ return (0);
+}
+
+/* Assert that 'pathname' is a dir. If mode >= 0, verify that too. */
+int
+assertion_is_dir(const char *file, int line, const char *pathname, int mode)
+{
+ struct stat st;
+ int r;
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ (void)mode; /* UNUSED */
+#endif
+ assertion_count(file, line);
+ r = lstat(pathname, &st);
+ if (r != 0) {
+ failure_start(file, line, "Dir should exist: %s", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+ if (!S_ISDIR(st.st_mode)) {
+ failure_start(file, line, "%s is not a dir", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ /* Windows doesn't handle permissions the same way as POSIX,
+ * so just ignore the mode tests. */
+ /* TODO: Can we do better here? */
+ if (mode >= 0 && mode != (st.st_mode & 07777)) {
+ failure_start(file, line, "Dir %s has wrong mode", pathname);
+ logprintf(" Expected: 0%3o\n", mode);
+ logprintf(" Found: 0%3o\n", st.st_mode & 07777);
+ failure_finish(NULL);
+ return (0);
+ }
+#endif
+ return (1);
+}
+
+/* Verify that 'pathname' is a regular file. If 'mode' is >= 0,
+ * verify that too. */
+int
+assertion_is_reg(const char *file, int line, const char *pathname, int mode)
+{
+ struct stat st;
+ int r;
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ (void)mode; /* UNUSED */
+#endif
+ assertion_count(file, line);
+ r = lstat(pathname, &st);
+ if (r != 0 || !S_ISREG(st.st_mode)) {
+ failure_start(file, line, "File should exist: %s", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ /* Windows doesn't handle permissions the same way as POSIX,
+ * so just ignore the mode tests. */
+ /* TODO: Can we do better here? */
+ if (mode >= 0 && mode != (st.st_mode & 07777)) {
+ failure_start(file, line, "File %s has wrong mode", pathname);
+ logprintf(" Expected: 0%3o\n", mode);
+ logprintf(" Found: 0%3o\n", st.st_mode & 07777);
+ failure_finish(NULL);
+ return (0);
+ }
+#endif
+ return (1);
+}
+
+/* Check whether 'pathname' is a symbolic link. If 'contents' is
+ * non-NULL, verify that the symlink has those contents. */
+static int
+is_symlink(const char *file, int line,
+ const char *pathname, const char *contents)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ (void)pathname; /* UNUSED */
+ (void)contents; /* UNUSED */
+ assertion_count(file, line);
+ /* Windows sort-of has real symlinks, but they're only usable
+ * by privileged users and are crippled even then, so there's
+ * really not much point in bothering with this. */
+ return (0);
+#else
+ char buff[300];
+ struct stat st;
+ ssize_t linklen;
+ int r;
+
+ assertion_count(file, line);
+ r = lstat(pathname, &st);
+ if (r != 0) {
+ failure_start(file, line,
+ "Symlink should exist: %s", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+ if (!S_ISLNK(st.st_mode))
+ return (0);
+ if (contents == NULL)
+ return (1);
+ linklen = readlink(pathname, buff, sizeof(buff));
+ if (linklen < 0) {
+ failure_start(file, line, "Can't read symlink %s", pathname);
+ failure_finish(NULL);
+ return (0);
+ }
+ buff[linklen] = '\0';
+ if (strcmp(buff, contents) != 0)
+ return (0);
+ return (1);
+#endif
+}
+
+/* Assert that path is a symlink that (optionally) contains contents. */
+int
+assertion_is_symlink(const char *file, int line,
+ const char *path, const char *contents)
+{
+ if (is_symlink(file, line, path, contents))
+ return (1);
+ if (contents)
+ failure_start(file, line, "File %s is not a symlink to %s",
+ path, contents);
+ else
+ failure_start(file, line, "File %s is not a symlink", path);
+ failure_finish(NULL);
+ return (0);
+}
+
+
+/* Create a directory and report any errors. */
+int
+assertion_make_dir(const char *file, int line, const char *dirname, int mode)
+{
+ assertion_count(file, line);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ (void)mode; /* UNUSED */
+ if (0 == _mkdir(dirname))
+ return (1);
+#else
+ if (0 == mkdir(dirname, mode))
+ return (1);
+#endif
+ failure_start(file, line, "Could not create directory %s", dirname);
+ failure_finish(NULL);
+ return(0);
+}
+
+/* Create a file with the specified contents and report any failures. */
+int
+assertion_make_file(const char *file, int line,
+ const char *path, int mode, const char *contents)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* TODO: Rework this to set file mode as well. */
+ FILE *f;
+ (void)mode; /* UNUSED */
+ assertion_count(file, line);
+ f = fopen(path, "wb");
+ if (f == NULL) {
+ failure_start(file, line, "Could not create file %s", path);
+ failure_finish(NULL);
+ return (0);
+ }
+ if (contents != NULL) {
+ if (strlen(contents)
+ != fwrite(contents, 1, strlen(contents), f)) {
+ fclose(f);
+ failure_start(file, line,
+ "Could not write file %s", path);
+ failure_finish(NULL);
+ return (0);
+ }
+ }
+ fclose(f);
+ return (1);
+#else
+ int fd;
+ assertion_count(file, line);
+ fd = open(path, O_CREAT | O_WRONLY, mode >= 0 ? mode : 0644);
+ if (fd < 0) {
+ failure_start(file, line, "Could not create %s", path);
+ failure_finish(NULL);
+ return (0);
+ }
+ if (contents != NULL) {
+ if ((ssize_t)strlen(contents)
+ != write(fd, contents, strlen(contents))) {
+ close(fd);
+ failure_start(file, line, "Could not write to %s", path);
+ failure_finish(NULL);
+ return (0);
+ }
+ }
+ close(fd);
+ return (1);
+#endif
+}
+
+/* Create a hardlink and report any failures. */
+int
+assertion_make_hardlink(const char *file, int line,
+ const char *newpath, const char *linkto)
+{
+ int succeeded;
+
+ assertion_count(file, line);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ succeeded = my_CreateHardLinkA(newpath, linkto);
+#elif HAVE_LINK
+ succeeded = !link(linkto, newpath);
+#else
+ succeeded = 0;
+#endif
+ if (succeeded)
+ return (1);
+ failure_start(file, line, "Could not create hardlink");
+ logprintf(" New link: %s\n", newpath);
+ logprintf(" Old name: %s\n", linkto);
+ failure_finish(NULL);
+ return(0);
+}
+
+/* Create a symlink and report any failures. */
+int
+assertion_make_symlink(const char *file, int line,
+ const char *newpath, const char *linkto)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ int targetIsDir = 0; /* TODO: Fix this */
+ assertion_count(file, line);
+ if (my_CreateSymbolicLinkA(newpath, linkto, targetIsDir))
+ return (1);
+#elif HAVE_SYMLINK
+ assertion_count(file, line);
+ if (0 == symlink(linkto, newpath))
+ return (1);
+#endif
+ failure_start(file, line, "Could not create symlink");
+ logprintf(" New link: %s\n", newpath);
+ logprintf(" Old name: %s\n", linkto);
+ failure_finish(NULL);
+ return(0);
+}
+
+/* Set umask, report failures. */
+int
+assertion_umask(const char *file, int line, int mask)
+{
+ assertion_count(file, line);
+ (void)file; /* UNUSED */
+ (void)line; /* UNUSED */
+ umask(mask);
+ return (1);
+}
+
+/*
+ *
+ * UTILITIES for use by tests.
+ *
+ */
+
+/*
+ * Check whether platform supports symlinks. This is intended
+ * for tests to use in deciding whether to bother testing symlink
+ * support; if the platform doesn't support symlinks, there's no point
+ * in checking whether the program being tested can create them.
+ *
+ * Note that the first time this test is called, we actually go out to
+ * disk to create and verify a symlink. This is necessary because
+ * symlink support is actually a property of a particular filesystem
+ * and can thus vary between directories on a single system. After
+ * the first call, this returns the cached result from memory, so it's
+ * safe to call it as often as you wish.
+ */
+int
+canSymlink(void)
+{
+ /* Remember the test result */
+ static int value = 0, tested = 0;
+ if (tested)
+ return (value);
+
+ ++tested;
+ assertion_make_file(__FILE__, __LINE__, "canSymlink.0", 0644, "a");
+ /* Note: Cygwin has its own symlink() emulation that does not
+ * use the Win32 CreateSymbolicLink() function. */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ value = my_CreateSymbolicLinkA("canSymlink.1", "canSymlink.0", 0)
+ && is_symlink(__FILE__, __LINE__, "canSymlink.1", "canSymlink.0");
+#elif HAVE_SYMLINK
+ value = (0 == symlink("canSymlink.0", "canSymlink.1"))
+ && is_symlink(__FILE__, __LINE__, "canSymlink.1","canSymlink.0");
+#endif
+ 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
+int
+canGzip(void)
+{
+ static int tested = 0, value = 0;
+ if (!tested) {
+ tested = 1;
+ if (systemf("gzip -V %s", redirectArgs) == 0)
+ value = 1;
+ }
+ return (value);
+}
+
+/*
+ * Can this platform run the gunzip program?
+ */
+int
+canGunzip(void)
+{
+ static int tested = 0, value = 0;
+ if (!tested) {
+ tested = 1;
+ if (systemf("gunzip -V %s", redirectArgs) == 0)
+ value = 1;
+ }
+ return (value);
+}
+
+/*
+ * Sleep as needed; useful for verifying disk timestamp changes by
+ * ensuring that the wall-clock time has actually changed before we
+ * go back to re-read something from disk.
+ */
+void
+sleepUntilAfter(time_t t)
+{
+ while (t >= time(NULL))
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ Sleep(500);
+#else
+ sleep(1);
+#endif
+}
+
+/*
+ * Call standard system() call, but build up the command line using
+ * sprintf() conventions.
+ */
+int
+systemf(const char *fmt, ...)
+{
+ char buff[8192];
+ va_list ap;
+ int r;
+
+ va_start(ap, fmt);
+ vsprintf(buff, fmt, ap);
+ if (verbosity > VERBOSITY_FULL)
+ logprintf("Cmd: %s\n", buff);
+ r = system(buff);
+ va_end(ap);
+ return (r);
+}
+
+/*
+ * Slurp a file into memory for ease of comparison and testing.
+ * Returns size of file in 'sizep' if non-NULL, null-terminates
+ * data in memory for ease of use.
+ */
+char *
+slurpfile(size_t * sizep, const char *fmt, ...)
+{
+ char filename[8192];
+ struct stat st;
+ va_list ap;
+ char *p;
+ ssize_t bytes_read;
+ FILE *f;
+ int r;
+
+ va_start(ap, fmt);
+ vsprintf(filename, fmt, ap);
+ va_end(ap);
+
+ f = fopen(filename, "rb");
+ if (f == NULL) {
+ /* Note: No error; non-existent file is okay here. */
+ return (NULL);
+ }
+ r = fstat(fileno(f), &st);
+ if (r != 0) {
+ logprintf("Can't stat file %s\n", filename);
+ fclose(f);
+ return (NULL);
+ }
+ p = malloc((size_t)st.st_size + 1);
+ if (p == NULL) {
+ logprintf("Can't allocate %ld bytes of memory to read file %s\n",
+ (long int)st.st_size, filename);
+ fclose(f);
+ return (NULL);
+ }
+ bytes_read = fread(p, 1, (size_t)st.st_size, f);
+ if (bytes_read < st.st_size) {
+ logprintf("Can't read file %s\n", filename);
+ fclose(f);
+ free(p);
+ return (NULL);
+ }
+ p[st.st_size] = '\0';
+ if (sizep != NULL)
+ *sizep = (size_t)st.st_size;
+ fclose(f);
+ return (p);
+}
+
+/* Read a uuencoded file from the reference directory, decode, and
+ * write the result into the current directory. */
+#define UUDECODE(c) (((c) - 0x20) & 0x3f)
+void
+extract_reference_file(const char *name)
+{
+ char buff[1024];
+ FILE *in, *out;
+
+ sprintf(buff, "%s/%s.uu", refdir, name);
+ in = fopen(buff, "r");
+ failure("Couldn't open reference file %s", buff);
+ assert(in != NULL);
+ if (in == NULL)
+ return;
+ /* Read up to and including the 'begin' line. */
+ for (;;) {
+ if (fgets(buff, sizeof(buff), in) == NULL) {
+ /* TODO: This is a failure. */
+ return;
+ }
+ if (memcmp(buff, "begin ", 6) == 0)
+ break;
+ }
+ /* Now, decode the rest and write it. */
+ /* Not a lot of error checking here; the input better be right. */
+ out = fopen(name, "wb");
+ while (fgets(buff, sizeof(buff), in) != NULL) {
+ char *p = buff;
+ int bytes;
+
+ if (memcmp(buff, "end", 3) == 0)
+ break;
+
+ bytes = UUDECODE(*p++);
+ while (bytes > 0) {
+ int n = 0;
+ /* Write out 1-3 bytes from that. */
+ if (bytes > 0) {
+ n = UUDECODE(*p++) << 18;
+ n |= UUDECODE(*p++) << 12;
+ fputc(n >> 16, out);
+ --bytes;
+ }
+ if (bytes > 0) {
+ n |= UUDECODE(*p++) << 6;
+ fputc((n >> 8) & 0xFF, out);
+ --bytes;
+ }
+ if (bytes > 0) {
+ n |= UUDECODE(*p++);
+ fputc(n & 0xFF, out);
+ --bytes;
+ }
+ }
+ }
+ fclose(out);
+ fclose(in);
+}
+
+/*
+ *
+ * TEST management
+ *
+ */
+
+/*
+ * "list.h" is simply created by "grep DEFINE_TEST test_*.c"; it has
+ * a line like
+ * DEFINE_TEST(test_function)
+ * for each test.
+ */
+
+/* Use "list.h" to declare all of the test functions. */
+#undef DEFINE_TEST
+#define DEFINE_TEST(name) void name(void);
+#include "list.h"
+
+/* 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[] = {
+ #include "list.h"
+};
+
+/*
+ * Summarize repeated failures in the just-completed test.
+ */
+static void
+test_summarize(const char *filename, int failed)
+{
+ unsigned int i;
+
+ switch (verbosity) {
+ case VERBOSITY_SUMMARY_ONLY:
+ printf(failed ? "E" : ".");
+ fflush(stdout);
+ break;
+ case VERBOSITY_PASSFAIL:
+ printf(failed ? "FAIL\n" : "ok\n");
+ break;
+ }
+
+ log_console = (verbosity == VERBOSITY_LIGHT_REPORT);
+
+ for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) {
+ if (failed_lines[i].count > 1 && !failed_lines[i].skip)
+ logprintf("%s:%d: Summary: Failed %d times\n",
+ filename, i, failed_lines[i].count);
+ }
+ /* Clear the failure history for the next file. */
+ memset(failed_lines, 0, sizeof(failed_lines));
+}
+
+/*
+ * Actually run a single test, with appropriate setup and cleanup.
+ */
+static int
+test_run(int i, const char *tmpdir)
+{
+ char logfilename[64];
+ int failures_before = failures;
+ int oldumask;
+
+ switch (verbosity) {
+ case VERBOSITY_SUMMARY_ONLY: /* No per-test reports at all */
+ break;
+ case VERBOSITY_PASSFAIL: /* rest of line will include ok/FAIL marker */
+ printf("%3d: %-50s", i, tests[i].name);
+ fflush(stdout);
+ break;
+ default: /* Title of test, details will follow */
+ printf("%3d: %s\n", i, tests[i].name);
+ }
+
+ /* Chdir to the top-level work directory. */
+ if (!assertChdir(tmpdir)) {
+ fprintf(stderr,
+ "ERROR: Can't chdir to top work dir %s\n", tmpdir);
+ exit(1);
+ }
+ /* Create a log file for this test. */
+ sprintf(logfilename, "%s.log", tests[i].name);
+ logfile = fopen(logfilename, "w");
+ fprintf(logfile, "%s\n\n", tests[i].name);
+ /* Chdir() to a work dir for this specific test. */
+ if (!assertMakeDir(tests[i].name, 0755)
+ || !assertChdir(tests[i].name)) {
+ fprintf(stderr,
+ "ERROR: Can't chdir to work dir %s/%s\n",
+ tmpdir, tests[i].name);
+ exit(1);
+ }
+ /* Explicitly reset the locale before each test. */
+ setlocale(LC_ALL, "C");
+ /* Record the umask before we run the test. */
+ umask(oldumask = umask(0));
+ /*
+ * Run the actual test.
+ */
+ (*tests[i].func)();
+ /*
+ * Clean up and report afterwards.
+ */
+ /* Restore umask */
+ umask(oldumask);
+ /* Reset locale. */
+ setlocale(LC_ALL, "C");
+ /* Reset directory. */
+ if (!assertChdir(tmpdir)) {
+ fprintf(stderr, "ERROR: Couldn't chdir to temp dir %s\n",
+ tmpdir);
+ exit(1);
+ }
+ /* Report per-test summaries. */
+ tests[i].failures = failures - failures_before;
+ test_summarize(test_filename, tests[i].failures);
+ /* Close the per-test log file. */
+ fclose(logfile);
+ logfile = NULL;
+ /* If there were no failures, we can remove the work dir and logfile. */
+ if (tests[i].failures == 0) {
+ if (!keep_temp_files && assertChdir(tmpdir)) {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Make sure not to leave empty directories.
+ * Sometimes a processing of closing files used by tests
+ * is not done, then rmdir will be failed and it will
+ * leave a empty test directory. So we should wait a few
+ * seconds and retry rmdir. */
+ int r, t;
+ for (t = 0; t < 10; t++) {
+ if (t > 0)
+ Sleep(1000);
+ r = systemf("rmdir /S /Q %s", tests[i].name);
+ if (r == 0)
+ break;
+ }
+ systemf("del %s", logfilename);
+#else
+ systemf("rm -rf %s", tests[i].name);
+ systemf("rm %s", logfilename);
+#endif
+ }
+ }
+ /* Return appropriate status. */
+ return (tests[i].failures);
+}
+
+/*
+ *
+ *
+ * MAIN and support routines.
+ *
+ *
+ */
+
+static void
+usage(const char *program)
+{
+ static const int limit = sizeof(tests) / sizeof(tests[0]);
+ int i;
+
+ printf("Usage: %s [options] <test> <test> ...\n", program);
+ printf("Default is to run all tests.\n");
+ printf("Otherwise, specify the numbers of the tests you wish to run.\n");
+ printf("Options:\n");
+ printf(" -d Dump core after any failure, for debugging.\n");
+ printf(" -k Keep all temp files.\n");
+ printf(" Default: temp files for successful tests deleted.\n");
+#ifdef PROGRAM
+ printf(" -p <path> Path to executable to be tested.\n");
+ printf(" Default: path taken from " ENVBASE " environment variable.\n");
+#endif
+ printf(" -q Quiet.\n");
+ printf(" -r <dir> Path to dir containing reference files.\n");
+ printf(" Default: Current directory.\n");
+ printf(" -v Verbose.\n");
+ printf("Available tests:\n");
+ for (i = 0; i < limit; i++)
+ printf(" %d: %s\n", i, tests[i].name);
+ exit(1);
+}
+
+static char *
+get_refdir(const char *d)
+{
+ char tried[512] = { '\0' };
+ char buff[128];
+ char *pwd, *p;
+
+ /* If a dir was specified, try that */
+ if (d != NULL) {
+ pwd = NULL;
+ snprintf(buff, sizeof(buff), "%s", d);
+ p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
+ if (p != NULL) goto success;
+ strncat(tried, buff, sizeof(tried) - strlen(tried) - 1);
+ strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1);
+ goto failure;
+ }
+
+ /* Get the current dir. */
+ pwd = getcwd(NULL, 0);
+ while (pwd[strlen(pwd) - 1] == '\n')
+ pwd[strlen(pwd) - 1] = '\0';
+
+ /* Look for a known file. */
+ snprintf(buff, sizeof(buff), "%s", pwd);
+ p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
+ if (p != NULL) goto success;
+ strncat(tried, buff, sizeof(tried) - strlen(tried) - 1);
+ strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1);
+
+ snprintf(buff, sizeof(buff), "%s/test", pwd);
+ p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
+ if (p != NULL) goto success;
+ strncat(tried, buff, sizeof(tried) - strlen(tried) - 1);
+ strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1);
+
+#if defined(LIBRARY)
+ snprintf(buff, sizeof(buff), "%s/%s/test", pwd, LIBRARY);
+#else
+ snprintf(buff, sizeof(buff), "%s/%s/test", pwd, PROGRAM);
+#endif
+ p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
+ if (p != NULL) goto success;
+ strncat(tried, buff, sizeof(tried) - strlen(tried) - 1);
+ strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1);
+
+ if (memcmp(pwd, "/usr/obj", 8) == 0) {
+ snprintf(buff, sizeof(buff), "%s", pwd + 8);
+ p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
+ if (p != NULL) goto success;
+ strncat(tried, buff, sizeof(tried) - strlen(tried) - 1);
+ strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1);
+
+ snprintf(buff, sizeof(buff), "%s/test", pwd + 8);
+ p = slurpfile(NULL, "%s/%s", buff, KNOWNREF);
+ if (p != NULL) goto success;
+ strncat(tried, buff, sizeof(tried) - strlen(tried) - 1);
+ strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1);
+ }
+
+failure:
+ printf("Unable to locate known reference file %s\n", KNOWNREF);
+ printf(" Checked following directories:\n%s\n", tried);
+#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
+ DebugBreak();
+#endif
+ exit(1);
+
+success:
+ free(p);
+ free(pwd);
+ return strdup(buff);
+}
+
+int
+main(int argc, char **argv)
+{
+ static const int limit = sizeof(tests) / sizeof(tests[0]);
+ int i, tests_run = 0, tests_failed = 0, option;
+ time_t now;
+ char *refdir_alloc = NULL;
+ const char *progname;
+ const char *tmp, *option_arg, *p;
+ char tmpdir[256];
+ char tmpdir_timestamp[256];
+
+ (void)argc; /* UNUSED */
+
+#if defined(HAVE__CrtSetReportMode)
+ /* To stop to run the default invalid parameter handler. */
+ _set_invalid_parameter_handler(invalid_parameter_handler);
+ /* Disable annoying assertion message box. */
+ _CrtSetReportMode(_CRT_ASSERT, 0);
+#endif
+
+ /*
+ * Name of this program, used to build root of our temp directory
+ * tree.
+ */
+ progname = p = argv[0];
+ while (*p != '\0') {
+ /* Support \ or / dir separators for Windows compat. */
+ if (*p == '/' || *p == '\\')
+ progname = p + 1;
+ ++p;
+ }
+
+#ifdef PROGRAM
+ /* Get the target program from environment, if available. */
+ testprogfile = getenv(ENVBASE);
+#endif
+
+ if (getenv("TMPDIR") != NULL)
+ tmp = getenv("TMPDIR");
+ else if (getenv("TMP") != NULL)
+ tmp = getenv("TMP");
+ else if (getenv("TEMP") != NULL)
+ tmp = getenv("TEMP");
+ else if (getenv("TEMPDIR") != NULL)
+ tmp = getenv("TEMPDIR");
+ else
+ tmp = "/tmp";
+
+ /* Allow -d to be controlled through the environment. */
+ if (getenv(ENVBASE "_DEBUG") != NULL)
+ dump_on_failure = 1;
+
+ /* Get the directory holding test files from environment. */
+ refdir = getenv(ENVBASE "_TEST_FILES");
+
+ /*
+ * Parse options, without using getopt(), which isn't available
+ * on all platforms.
+ */
+ ++argv; /* Skip program name */
+ while (*argv != NULL) {
+ if (**argv != '-')
+ break;
+ p = *argv++;
+ ++p; /* Skip '-' */
+ while (*p != '\0') {
+ option = *p++;
+ option_arg = NULL;
+ /* If 'opt' takes an argument, parse that. */
+ if (option == 'p' || option == 'r') {
+ if (*p != '\0')
+ option_arg = p;
+ else if (*argv == NULL) {
+ fprintf(stderr,
+ "Option -%c requires argument.\n",
+ option);
+ usage(progname);
+ } else
+ option_arg = *argv++;
+ p = ""; /* End of this option word. */
+ }
+
+ /* Now, handle the option. */
+ switch (option) {
+ case 'd':
+ dump_on_failure = 1;
+ break;
+ case 'k':
+ keep_temp_files = 1;
+ break;
+ case 'p':
+#ifdef PROGRAM
+ testprogfile = option_arg;
+#else
+ usage(progname);
+#endif
+ break;
+ case 'q':
+ verbosity--;
+ break;
+ case 'r':
+ refdir = option_arg;
+ break;
+ case 'v':
+ verbosity++;
+ break;
+ default:
+ usage(progname);
+ }
+ }
+ }
+
+ /*
+ * Sanity-check that our options make sense.
+ */
+#ifdef PROGRAM
+ if (testprogfile == NULL)
+ usage(progname);
+ {
+ char *testprg;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Command.com sometimes rejects '/' separators. */
+ testprg = strdup(testprogfile);
+ for (i = 0; testprg[i] != '\0'; i++) {
+ if (testprg[i] == '/')
+ testprg[i] = '\\';
+ }
+ testprogfile = testprg;
+#endif
+ /* Quote the name that gets put into shell command lines. */
+ testprg = malloc(strlen(testprogfile) + 3);
+ strcpy(testprg, "\"");
+ strcat(testprg, testprogfile);
+ strcat(testprg, "\"");
+ testprog = testprg;
+ }
+#endif
+
+ /*
+ * Create a temp directory for the following tests.
+ * Include the time the tests started as part of the name,
+ * to make it easier to track the results of multiple tests.
+ */
+ now = time(NULL);
+ for (i = 0; ; i++) {
+ strftime(tmpdir_timestamp, sizeof(tmpdir_timestamp),
+ "%Y-%m-%dT%H.%M.%S",
+ localtime(&now));
+ sprintf(tmpdir, "%s/%s.%s-%03d", tmp, progname,
+ tmpdir_timestamp, i);
+ if (assertMakeDir(tmpdir,0755))
+ break;
+ if (i >= 999) {
+ fprintf(stderr,
+ "ERROR: Unable to create temp directory %s\n",
+ tmpdir);
+ exit(1);
+ }
+ }
+
+ /*
+ * If the user didn't specify a directory for locating
+ * reference files, try to find the reference files in
+ * the "usual places."
+ */
+ refdir = refdir_alloc = get_refdir(refdir);
+
+ /*
+ * Banner with basic information.
+ */
+ printf("\n");
+ printf("If tests fail or crash, details will be in:\n");
+ printf(" %s\n", tmpdir);
+ printf("\n");
+ if (verbosity > VERBOSITY_SUMMARY_ONLY) {
+ printf("Reference files will be read from: %s\n", refdir);
+#ifdef PROGRAM
+ printf("Running tests on: %s\n", testprog);
+#endif
+ printf("Exercising: ");
+ fflush(stdout);
+ printf("%s\n", EXTRA_VERSION);
+ } else {
+ printf("Running ");
+ fflush(stdout);
+ }
+
+ /*
+ * Run some or all of the individual tests.
+ */
+ if (*argv == NULL) {
+ /* Default: Run all tests. */
+ for (i = 0; i < limit; i++) {
+ if (test_run(i, tmpdir))
+ tests_failed++;
+ tests_run++;
+ }
+ } else {
+ while (*(argv) != NULL) {
+ if (**argv >= '0' && **argv <= '9') {
+ i = atoi(*argv);
+ if (i < 0 || i >= limit) {
+ printf("*** INVALID Test %s\n", *argv);
+ free(refdir_alloc);
+ usage(progname);
+ /* usage() never returns */
+ }
+ } else {
+ for (i = 0; i < limit; ++i) {
+ if (strcmp(*argv, tests[i].name) == 0)
+ break;
+ }
+ if (i >= limit) {
+ printf("*** INVALID Test ``%s''\n",
+ *argv);
+ free(refdir_alloc);
+ usage(progname);
+ /* usage() never returns */
+ }
+ }
+ if (test_run(i, tmpdir))
+ tests_failed++;
+ tests_run++;
+ argv++;
+ }
+ }
+
+ /*
+ * Report summary statistics.
+ */
+ if (verbosity > VERBOSITY_SUMMARY_ONLY) {
+ printf("\n");
+ printf("Totals:\n");
+ printf(" Tests run: %8d\n", tests_run);
+ printf(" Tests failed: %8d\n", tests_failed);
+ printf(" Assertions checked:%8d\n", assertions);
+ printf(" Assertions failed: %8d\n", failures);
+ printf(" Skips reported: %8d\n", skips);
+ }
+ if (failures) {
+ printf("\n");
+ printf("Failing tests:\n");
+ for (i = 0; i < limit; ++i) {
+ if (tests[i].failures)
+ printf(" %d: %s (%d failures)\n", i,
+ tests[i].name, tests[i].failures);
+ }
+ printf("\n");
+ printf("Details for failing tests: %s\n", tmpdir);
+ printf("\n");
+ } else {
+ if (verbosity == VERBOSITY_SUMMARY_ONLY)
+ printf("\n");
+ printf("%d tests passed, no failures\n", tests_run);
+ }
+
+ free(refdir_alloc);
+
+ /* If the final tmpdir is empty, we can remove it. */
+ /* This should be the usual case when all tests succeed. */
+ assertChdir("..");
+ rmdir(tmpdir);
+
+ return (tests_failed ? 1 : 0);
+}
diff --git a/cpio/test/test.h b/cpio/test/test.h
new file mode 100644
index 000000000000..2d68f3104d14
--- /dev/null
+++ b/cpio/test/test.h
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2003-2006 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/usr.bin/cpio/test/test.h,v 1.2 2008/06/21 02:17:18 kientzle Exp $
+ */
+
+/* Every test program should #include "test.h" as the first thing. */
+
+/*
+ * The goal of this file (and the matching test.c) is to
+ * simplify the very repetitive test-*.c test programs.
+ */
+#if defined(HAVE_CONFIG_H)
+/* Most POSIX platforms use the 'configure' script to build config.h */
+#include "config.h"
+#elif defined(__FreeBSD__)
+/* Building as part of FreeBSD system requires a pre-built config.h. */
+#include "config_freebsd.h"
+#elif defined(_WIN32) && !defined(__CYGWIN__)
+/* Win32 can't run the 'configure' script. */
+#include "config_windows.h"
+#else
+/* Warn if the library hasn't been (automatically or manually) configured. */
+#error Oops: No config.h and no pre-built configuration in test.h.
+#endif
+
+#include <sys/types.h> /* Windows requires this before sys/stat.h */
+#include <sys/stat.h>
+
+#ifdef USE_DMALLOC
+#include <dmalloc.h>
+#endif
+#if HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#ifdef HAVE_DIRECT_H
+#include <direct.h>
+#define dirent direct
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <wchar.h>
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
+/*
+ * System-specific tweaks. We really want to minimize these
+ * as much as possible, since they make it harder to understand
+ * the mainline code.
+ */
+
+/* Windows (including Visual Studio and MinGW but not Cygwin) */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include "../cpio_windows.h"
+#if !defined(__BORLANDC__)
+#define strdup _strdup
+#endif
+#define LOCALE_DE "deu"
+#else
+#define LOCALE_DE "de_DE.UTF-8"
+#endif
+
+/* Visual Studio */
+#ifdef _MSC_VER
+#define snprintf sprintf_s
+#endif
+
+/* Cygwin */
+#if defined(__CYGWIN__)
+/* Cygwin-1.7.x is lazy about populating nlinks, so don't
+ * expect it to be accurate. */
+# define NLINKS_INACCURATE_FOR_DIRS
+#endif
+
+#if defined(__HAIKU__) || defined(__QNXNTO__)
+/* Haiku and QNX have typedefs in stdint.h (needed for int64_t) */
+#include <stdint.h>
+#endif
+
+/* Get a real definition for __FBSDID if we can */
+#if HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+
+/* If not, define it so as to avoid dangling semicolons. */
+#ifndef __FBSDID
+#define __FBSDID(a) struct _undefined_hack
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/*
+ * Redefine DEFINE_TEST for use in defining the test functions.
+ */
+#undef DEFINE_TEST
+#define DEFINE_TEST(name) void name(void); void name(void)
+
+/* An implementation of the standard assert() macro */
+#define assert(e) assertion_assert(__FILE__, __LINE__, (e), #e, NULL)
+/* chdir() and error if it fails */
+#define assertChdir(path) \
+ assertion_chdir(__FILE__, __LINE__, path)
+/* Assert two integers are the same. Reports value of each one if not. */
+#define assertEqualInt(v1,v2) \
+ assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
+/* Assert two strings are the same. Reports value of each one if not. */
+#define assertEqualString(v1,v2) \
+ assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
+/* As above, but v1 and v2 are wchar_t * */
+#define assertEqualWString(v1,v2) \
+ assertion_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL)
+/* As above, but raw blocks of bytes. */
+#define assertEqualMem(v1, v2, l) \
+ assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL)
+/* Assert two files are the same; allow printf-style expansion of second name.
+ * See below for comments about variable arguments here...
+ */
+#define assertEqualFile \
+ assertion_setup(__FILE__, __LINE__);assertion_equal_file
+/* Assert that a file is empty; supports printf-style arguments. */
+#define assertEmptyFile \
+ assertion_setup(__FILE__, __LINE__);assertion_empty_file
+/* Assert that a file is not empty; supports printf-style arguments. */
+#define assertNonEmptyFile \
+ assertion_setup(__FILE__, __LINE__);assertion_non_empty_file
+#define assertFileAtime(pathname, sec, nsec) \
+ assertion_file_atime(__FILE__, __LINE__, pathname, sec, nsec)
+#define assertFileAtimeRecent(pathname) \
+ assertion_file_atime_recent(__FILE__, __LINE__, pathname)
+#define assertFileBirthtime(pathname, sec, nsec) \
+ assertion_file_birthtime(__FILE__, __LINE__, pathname, sec, nsec)
+#define assertFileBirthtimeRecent(pathname) \
+ assertion_file_birthtime_recent(__FILE__, __LINE__, pathname)
+/* Assert that a file exists; supports printf-style arguments. */
+#define assertFileExists \
+ assertion_setup(__FILE__, __LINE__);assertion_file_exists
+/* Assert that a file exists; supports printf-style arguments. */
+#define assertFileNotExists \
+ assertion_setup(__FILE__, __LINE__);assertion_file_not_exists
+/* Assert that file contents match a string; supports printf-style arguments. */
+#define assertFileContents \
+ assertion_setup(__FILE__, __LINE__);assertion_file_contents
+#define assertFileMtime(pathname, sec, nsec) \
+ assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec)
+#define assertFileMtimeRecent(pathname) \
+ assertion_file_mtime_recent(__FILE__, __LINE__, pathname)
+#define assertFileNLinks(pathname, nlinks) \
+ assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks)
+#define assertFileSize(pathname, size) \
+ assertion_file_size(__FILE__, __LINE__, pathname, size)
+#define assertTextFileContents \
+ assertion_setup(__FILE__, __LINE__);assertion_text_file_contents
+#define assertIsDir(pathname, mode) \
+ assertion_is_dir(__FILE__, __LINE__, pathname, mode)
+#define assertIsHardlink(path1, path2) \
+ assertion_is_hardlink(__FILE__, __LINE__, path1, path2)
+#define assertIsNotHardlink(path1, path2) \
+ assertion_is_not_hardlink(__FILE__, __LINE__, path1, path2)
+#define assertIsReg(pathname, mode) \
+ assertion_is_reg(__FILE__, __LINE__, pathname, mode)
+#define assertIsSymlink(pathname, contents) \
+ assertion_is_symlink(__FILE__, __LINE__, pathname, contents)
+/* Create a directory, report error if it fails. */
+#define assertMakeDir(dirname, mode) \
+ assertion_make_dir(__FILE__, __LINE__, dirname, mode)
+#define assertMakeFile(path, mode, contents) \
+ assertion_make_file(__FILE__, __LINE__, path, mode, contents)
+#define assertMakeHardlink(newfile, oldfile) \
+ assertion_make_hardlink(__FILE__, __LINE__, newfile, oldfile)
+#define assertMakeSymlink(newfile, linkto) \
+ assertion_make_symlink(__FILE__, __LINE__, newfile, linkto)
+#define assertUmask(mask) \
+ assertion_umask(__FILE__, __LINE__, mask)
+
+/*
+ * This would be simple with C99 variadic macros, but I don't want to
+ * require that. Instead, I insert a function call before each
+ * skipping() call to pass the file and line information down. Crude,
+ * but effective.
+ */
+#define skipping \
+ assertion_setup(__FILE__, __LINE__);test_skipping
+
+/* Function declarations. These are defined in test_utility.c. */
+void failure(const char *fmt, ...);
+int assertion_assert(const char *, int, int, const char *, void *);
+int assertion_chdir(const char *, int, const char *);
+int assertion_empty_file(const char *, ...);
+int assertion_equal_file(const char *, const char *, ...);
+int assertion_equal_int(const char *, int, long long, const char *, long long, const char *, void *);
+int assertion_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *);
+int assertion_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *);
+int assertion_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *);
+int assertion_file_atime(const char *, int, const char *, long, long);
+int assertion_file_atime_recent(const char *, int, const char *);
+int assertion_file_birthtime(const char *, int, const char *, long, long);
+int assertion_file_birthtime_recent(const char *, int, const char *);
+int assertion_file_contents(const void *, int, const char *, ...);
+int assertion_file_exists(const char *, ...);
+int assertion_file_mtime(const char *, int, const char *, long, long);
+int assertion_file_mtime_recent(const char *, int, const char *);
+int assertion_file_nlinks(const char *, int, const char *, int);
+int assertion_file_not_exists(const char *, ...);
+int assertion_file_size(const char *, int, const char *, long);
+int assertion_is_dir(const char *, int, const char *, int);
+int assertion_is_hardlink(const char *, int, const char *, const char *);
+int assertion_is_not_hardlink(const char *, int, const char *, const char *);
+int assertion_is_reg(const char *, int, const char *, int);
+int assertion_is_symlink(const char *, int, const char *, const char *);
+int assertion_make_dir(const char *, int, const char *, int);
+int assertion_make_file(const char *, int, const char *, int, const char *);
+int assertion_make_hardlink(const char *, int, const char *newpath, const char *);
+int assertion_make_symlink(const char *, int, const char *newpath, const char *);
+int assertion_non_empty_file(const char *, ...);
+int assertion_text_file_contents(const char *buff, const char *f);
+int assertion_umask(const char *, int, int);
+void assertion_setup(const char *, int);
+
+void test_skipping(const char *fmt, ...);
+
+/* Like sprintf, then system() */
+int systemf(const char * fmt, ...);
+
+/* Delay until time() returns a value after this. */
+void sleepUntilAfter(time_t);
+
+/* Return true if this platform can create symlinks. */
+int canSymlink(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);
+
+/* Suck file into string allocated via malloc(). Call free() when done. */
+/* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
+char *slurpfile(size_t *, const char *fmt, ...);
+
+/* Extracts named reference file to the current directory. */
+void extract_reference_file(const char *);
+
+/*
+ * Special interfaces for program test harness.
+ */
+
+/* Pathname of exe to be tested. */
+const char *testprogfile;
+/* Name of exe to use in printf-formatted command strings. */
+/* On Windows, this includes leading/trailing quotes. */
+const char *testprog;
diff --git a/cpio/test/test_0.c b/cpio/test/test_0.c
new file mode 100644
index 000000000000..75a1437fd70e
--- /dev/null
+++ b/cpio/test/test_0.c
@@ -0,0 +1,67 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+/*
+ * This first test does basic sanity checks on the environment. For
+ * most of these, we just exit on failure.
+ */
+#if !defined(_WIN32) || defined(__CYGWIN__)
+#define DEV_NULL "/dev/null"
+#else
+#define DEV_NULL "NUL"
+#endif
+
+DEFINE_TEST(test_0)
+{
+ struct stat st;
+
+ failure("File %s does not exist?!", testprogfile);
+ if (!assertEqualInt(0, stat(testprogfile, &st)))
+ exit(1);
+
+ failure("%s is not executable?!", testprogfile);
+ if (!assert((st.st_mode & 0111) != 0))
+ exit(1);
+
+ /*
+ * Try to succesfully run the program; this requires that
+ * we know some option that will succeed.
+ */
+ if (0 == systemf("%s --version >" DEV_NULL, testprog)) {
+ /* This worked. */
+ } else if (0 == systemf("%s -W version >" DEV_NULL, testprog)) {
+ /* This worked. */
+ } else {
+ failure("Unable to successfully run any of the following:\n"
+ " * %s --version\n"
+ " * %s -W version\n",
+ testprog, testprog);
+ assert(0);
+ }
+
+ /* TODO: Ensure that our reference files are available. */
+}
diff --git a/cpio/test/test_basic.c b/cpio/test/test_basic.c
new file mode 100644
index 000000000000..852b069a16e7
--- /dev/null
+++ b/cpio/test/test_basic.c
@@ -0,0 +1,173 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD: src/usr.bin/cpio/test/test_basic.c,v 1.4 2008/08/25 06:39:29 kientzle Exp $");
+
+static void
+verify_files(const char *msg)
+{
+ /*
+ * Verify unpacked files.
+ */
+
+ /* Regular file with 2 links. */
+ assertIsReg("file", 0644);
+ failure(msg);
+ assertFileSize("file", 10);
+ assertFileNLinks("file", 2);
+
+ /* Another name for the same file. */
+ assertIsHardlink("linkfile", "file");
+
+ /* Symlink */
+ if (canSymlink())
+ assertIsSymlink("symlink", "file");
+
+ /* Another file with 1 link and different permissions. */
+ assertIsReg("file2", 0777);
+ assertFileSize("file2", 10);
+ assertFileNLinks("file2", 1);
+
+ /* dir */
+ assertIsDir("dir", 0775);
+}
+
+static void
+basic_cpio(const char *target,
+ const char *pack_options,
+ const char *unpack_options,
+ const char *se)
+{
+ int r;
+
+ if (!assertMakeDir(target, 0775))
+ return;
+
+ /* Use the cpio program to create an archive. */
+ r = systemf("%s -o %s < filelist >%s/archive 2>%s/pack.err",
+ testprog, pack_options, target, target);
+ failure("Error invoking %s -o %s", testprog, pack_options);
+ assertEqualInt(r, 0);
+
+ assertChdir(target);
+
+ /* Verify stderr. */
+ failure("Expected: %s, options=%s", se, pack_options);
+ assertTextFileContents(se, "pack.err");
+
+ /*
+ * Use cpio to unpack the archive into another directory.
+ */
+ r = systemf("%s -i %s< archive >unpack.out 2>unpack.err",
+ testprog, unpack_options);
+ failure("Error invoking %s -i %s", testprog, unpack_options);
+ assertEqualInt(r, 0);
+
+ /* Verify stderr. */
+ failure("Error invoking %s -i %s in dir %s", testprog, unpack_options, target);
+ assertTextFileContents(se, "unpack.err");
+
+ verify_files(pack_options);
+
+ assertChdir("..");
+}
+
+static void
+passthrough(const char *target)
+{
+ int r;
+
+ if (!assertMakeDir(target, 0775))
+ return;
+
+ /*
+ * Use cpio passthrough mode to copy files to another directory.
+ */
+ r = systemf("%s -p %s <filelist >%s/stdout 2>%s/stderr",
+ testprog, target, target, target);
+ failure("Error invoking %s -p", testprog);
+ assertEqualInt(r, 0);
+
+ assertChdir(target);
+
+ /* Verify stderr. */
+ failure("Error invoking %s -p in dir %s",
+ testprog, target);
+ assertTextFileContents("1 block\n", "stderr");
+
+ verify_files("passthrough");
+ assertChdir("..");
+}
+
+DEFINE_TEST(test_basic)
+{
+ FILE *filelist;
+ const char *msg;
+
+ assertUmask(0);
+
+ /*
+ * Create an assortment of files on disk.
+ */
+ filelist = fopen("filelist", "w");
+
+ /* File with 10 bytes content. */
+ assertMakeFile("file", 0644, "1234567890");
+ fprintf(filelist, "file\n");
+
+ /* hardlink to above file. */
+ assertMakeHardlink("linkfile", "file");
+ fprintf(filelist, "linkfile\n");
+
+ /* Symlink to above file. */
+ if (canSymlink()) {
+ assertMakeSymlink("symlink", "file");
+ fprintf(filelist, "symlink\n");
+ }
+
+ /* Another file with different permissions. */
+ assertMakeFile("file2", 0777, "1234567890");
+ fprintf(filelist, "file2\n");
+
+ /* Directory. */
+ assertMakeDir("dir", 0775);
+ fprintf(filelist, "dir\n");
+ /* All done. */
+ fclose(filelist);
+
+ assertUmask(022);
+
+ /* Archive/dearchive with a variety of options. */
+ msg = canSymlink() ? "2 blocks\n" : "1 block\n";
+ basic_cpio("copy", "", "", msg);
+ basic_cpio("copy_odc", "--format=odc", "", msg);
+ basic_cpio("copy_newc", "-H newc", "", "2 blocks\n");
+ basic_cpio("copy_cpio", "-H odc", "", msg);
+ msg = canSymlink() ? "9 blocks\n" : "8 blocks\n";
+ basic_cpio("copy_ustar", "-H ustar", "", msg);
+
+ /* Copy in one step using -p */
+ passthrough("passthrough");
+}
diff --git a/cpio/test/test_cmdline.c b/cpio/test/test_cmdline.c
new file mode 100644
index 000000000000..2dd7d651dc57
--- /dev/null
+++ b/cpio/test/test_cmdline.c
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 2003-2009 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+/*
+ * Test the command-line parsing.
+ */
+
+DEFINE_TEST(test_cmdline)
+{
+ FILE *f;
+
+ /* Create an empty file. */
+ f = fopen("empty", "wb");
+ assert(f != NULL);
+ fclose(f);
+
+ failure("-Q is an invalid option on every cpio program I know of");
+ assert(0 != systemf("%s -i -Q <empty >1.out 2>1.err", testprog));
+ assertEmptyFile("1.out");
+
+ failure("-f requires an argument");
+ assert(0 != systemf("%s -if <empty >2.out 2>2.err", testprog));
+ assertEmptyFile("2.out");
+
+ failure("-f requires an argument");
+ assert(0 != systemf("%s -i -f <empty >3.out 2>3.err", testprog));
+ assertEmptyFile("3.out");
+
+ failure("--format requires an argument");
+ assert(0 != systemf("%s -i --format <empty >4.out 2>4.err", testprog));
+ assertEmptyFile("4.out");
+
+ failure("--badopt is an invalid option");
+ assert(0 != systemf("%s -i --badop <empty >5.out 2>5.err", testprog));
+ assertEmptyFile("5.out");
+
+ failure("--badopt is an invalid option");
+ assert(0 != systemf("%s -i --badopt <empty >6.out 2>6.err", testprog));
+ assertEmptyFile("6.out");
+
+ failure("--n is ambiguous");
+ assert(0 != systemf("%s -i --n <empty >7.out 2>7.err", testprog));
+ assertEmptyFile("7.out");
+
+ failure("--create forbids an argument");
+ assert(0 != systemf("%s --create=arg <empty >8.out 2>8.err", testprog));
+ assertEmptyFile("8.out");
+
+ failure("-i with empty input should succeed");
+ assert(0 == systemf("%s -i <empty >9.out 2>9.err", testprog));
+ assertEmptyFile("9.out");
+
+ failure("-o with empty input should succeed");
+ assert(0 == systemf("%s -o <empty >10.out 2>10.err", testprog));
+
+ failure("-i -p is nonsense");
+ assert(0 != systemf("%s -i -p <empty >11.out 2>11.err", testprog));
+ assertEmptyFile("11.out");
+
+ failure("-p -i is nonsense");
+ assert(0 != systemf("%s -p -i <empty >12.out 2>12.err", testprog));
+ assertEmptyFile("12.out");
+
+ failure("-i -o is nonsense");
+ assert(0 != systemf("%s -i -o <empty >13.out 2>13.err", testprog));
+ assertEmptyFile("13.out");
+
+ failure("-o -i is nonsense");
+ assert(0 != systemf("%s -o -i <empty >14.out 2>14.err", testprog));
+ assertEmptyFile("14.out");
+
+ failure("-o -p is nonsense");
+ assert(0 != systemf("%s -o -p <empty >15.out 2>15.err", testprog));
+ assertEmptyFile("15.out");
+
+ failure("-p -o is nonsense");
+ assert(0 != systemf("%s -p -o <empty >16.out 2>16.err", testprog));
+ assertEmptyFile("16.out");
+
+ failure("-p with empty input should fail");
+ assert(0 != systemf("%s -p <empty >17.out 2>17.err", testprog));
+ assertEmptyFile("17.out");
+}
diff --git a/cpio/test/test_format_newc.c b/cpio/test/test_format_newc.c
new file mode 100644
index 000000000000..06749a2f9caa
--- /dev/null
+++ b/cpio/test/test_format_newc.c
@@ -0,0 +1,294 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD: src/usr.bin/cpio/test/test_format_newc.c,v 1.2 2008/08/22 02:09:10 kientzle Exp $");
+
+/* Number of bytes needed to pad 'n' to multiple of 'block', assuming
+ * that 'block' is a power of two. This trick can be more easily
+ * remembered as -n & (block - 1), but many compilers quite reasonably
+ * warn about "-n" when n is an unsigned value. (~(n) + 1) is the
+ * same thing, but written in a way that won't offend anyone. */
+#define PAD(n, block) ((~(n) + 1) & ((block) - 1))
+
+static int
+is_hex(const char *p, size_t l)
+{
+ while (l > 0) {
+ if ((*p >= '0' && *p <= '9')
+ || (*p >= 'a' && *p <= 'f')
+ || (*p >= 'A' && *p <= 'F'))
+ {
+ --l;
+ ++p;
+ } else
+ return (0);
+
+ }
+ return (1);
+}
+
+static int
+from_hex(const char *p, size_t l)
+{
+ int r = 0;
+
+ while (l > 0) {
+ r *= 16;
+ if (*p >= 'a' && *p <= 'f')
+ r += *p + 10 - 'a';
+ else if (*p >= 'A' && *p <= 'F')
+ r += *p + 10 - 'A';
+ else
+ r += *p - '0';
+ --l;
+ ++p;
+ }
+ return (r);
+}
+
+DEFINE_TEST(test_format_newc)
+{
+ FILE *list;
+ int r;
+ int devmajor, devminor, ino, gid;
+ int uid = -1;
+ time_t t, t2, now;
+ char *p, *e;
+ size_t s, fs, ns;
+
+ assertUmask(0);
+
+#if !defined(_WIN32)
+ uid = getuid();
+#endif
+
+ /*
+ * Create an assortment of files.
+ * TODO: Extend this to cover more filetypes.
+ */
+ list = fopen("list", "w");
+
+ /* "file1" */
+ assertMakeFile("file1", 0644, "1234567890");
+ fprintf(list, "file1\n");
+
+ /* "hardlink" */
+ assertMakeHardlink("hardlink", "file1");
+ fprintf(list, "hardlink\n");
+
+ /* Another hardlink, but this one won't be archived. */
+ assertMakeHardlink("hardlink2", "file1");
+
+ /* "symlink" */
+ if (canSymlink()) {
+ assertMakeSymlink("symlink", "file1");
+ fprintf(list, "symlink\n");
+ }
+
+ /* "dir" */
+ assertMakeDir("dir", 0775);
+ fprintf(list, "dir\n");
+
+ /* Record some facts about what we just created: */
+ now = time(NULL); /* They were all created w/in last two seconds. */
+
+ /* Use the cpio program to create an archive. */
+ fclose(list);
+ r = systemf("%s -o --format=newc <list >newc.out 2>newc.err",
+ testprog);
+ if (!assertEqualInt(r, 0))
+ return;
+
+ /* Verify that nothing went to stderr. */
+ if (canSymlink()) {
+ assertTextFileContents("2 blocks\n", "newc.err");
+ } else {
+ assertTextFileContents("1 block\n", "newc.err");
+ }
+
+ /* Verify that stdout is a well-formed cpio file in "newc" format. */
+ p = slurpfile(&s, "newc.out");
+ assertEqualInt(s, canSymlink() ? 1024 : 512);
+ e = p;
+
+ /*
+ * Some of these assertions could be stronger, but it's
+ * a little tricky because they depend on the local environment.
+ */
+
+ /* First entry is "file1" */
+ assert(is_hex(e, 110)); /* Entire header is octal digits. */
+ assertEqualMem(e + 0, "070701", 6); /* Magic */
+ ino = from_hex(e + 6, 8); /* ino */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Group members bits and others bits do not work. */
+ assertEqualInt(0x8180, from_hex(e + 14, 8) & 0xffc0); /* Mode */
+#else
+ assertEqualInt(0x81a4, from_hex(e + 14, 8)); /* Mode */
+#endif
+ if (uid < 0)
+ uid = from_hex(e + 22, 8);
+ assertEqualInt(from_hex(e + 22, 8), uid); /* uid */
+ gid = from_hex(e + 30, 8); /* gid */
+ assertEqualMem(e + 38, "00000003", 8); /* nlink */
+ t = from_hex(e + 46, 8); /* mtime */
+ failure("t=0x%08x now=0x%08x=%d", t, now, now);
+ assert(t <= now); /* File wasn't created in future. */
+ failure("t=0x%08x now - 2=0x%08x = %d", t, now - 2, now - 2);
+ assert(t >= now - 2); /* File was created w/in last 2 secs. */
+ failure("newc format stores body only with last appearance of a link\n"
+ " first appearance should be empty, so this file size\n"
+ " field should be zero");
+ assertEqualInt(0, from_hex(e + 54, 8)); /* File size */
+ fs = from_hex(e + 54, 8);
+ fs += PAD(fs, 4);
+ devmajor = from_hex(e + 62, 8); /* devmajor */
+ devminor = from_hex(e + 70, 8); /* devminor */
+ assert(is_hex(e + 78, 8)); /* rdevmajor */
+ assert(is_hex(e + 86, 8)); /* rdevminor */
+ assertEqualMem(e + 94, "00000006", 8); /* Name size */
+ ns = from_hex(e + 94, 8);
+ ns += PAD(ns + 2, 4);
+ assertEqualInt(0, from_hex(e + 102, 8)); /* check field */
+ assertEqualMem(e + 110, "file1\0", 6); /* Name contents */
+ /* Since there's another link, no file contents here. */
+ /* But add in file size so that an error here doesn't cascade. */
+ e += 110 + fs + ns;
+
+ if (canSymlink()) {
+ /* "symlink" pointing to "file1" */
+ assert(is_hex(e, 110));
+ assertEqualMem(e + 0, "070701", 6); /* Magic */
+ assert(is_hex(e + 6, 8)); /* ino */
+ assertEqualInt(0xa1ff, from_hex(e + 14, 8)); /* Mode */
+ assertEqualInt(from_hex(e + 22, 8), uid); /* uid */
+ assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */
+ assertEqualMem(e + 38, "00000001", 8); /* nlink */
+ t2 = from_hex(e + 46, 8); /* mtime */
+ failure("First entry created at t=0x%08x this entry created at t2=0x%08x", t, t2);
+ assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
+ assertEqualMem(e + 54, "00000005", 8); /* File size */
+ fs = from_hex(e + 54, 8);
+ fs += PAD(fs, 4);
+ assertEqualInt(devmajor, from_hex(e + 62, 8)); /* devmajor */
+ assertEqualInt(devminor, from_hex(e + 70, 8)); /* devminor */
+ assert(is_hex(e + 78, 8)); /* rdevmajor */
+ assert(is_hex(e + 86, 8)); /* rdevminor */
+ assertEqualMem(e + 94, "00000008", 8); /* Name size */
+ ns = from_hex(e + 94, 8);
+ ns += PAD(ns + 2, 4);
+ assertEqualInt(0, from_hex(e + 102, 8)); /* check field */
+ assertEqualMem(e + 110, "symlink\0\0\0", 10); /* Name contents */
+ assertEqualMem(e + 110 + ns, "file1\0\0\0", 8); /* symlink target */
+ e += 110 + fs + ns;
+ }
+
+ /* "dir" */
+ assert(is_hex(e, 110));
+ assertEqualMem(e + 0, "070701", 6); /* Magic */
+ assert(is_hex(e + 6, 8)); /* ino */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Group members bits and others bits do not work. */
+ assertEqualInt(0x41c0, from_hex(e + 14, 8) & 0xffc0); /* Mode */
+#else
+ /* Mode: sgid bit sometimes propagates from parent dirs, ignore it. */
+ assertEqualInt(040775, from_hex(e + 14, 8) & ~02000);
+#endif
+ assertEqualInt(from_hex(e + 22, 8), uid); /* uid */
+ assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */
+#ifndef NLINKS_INACCURATE_FOR_DIRS
+ assertEqualMem(e + 38, "00000002", 8); /* nlink */
+#endif
+ t2 = from_hex(e + 46, 8); /* mtime */
+ failure("First entry created at t=0x%08x this entry created at t2=0x%08x", t, t2);
+ assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
+ assertEqualMem(e + 54, "00000000", 8); /* File size */
+ fs = from_hex(e + 54, 8);
+ fs += PAD(fs, 4);
+ assertEqualInt(devmajor, from_hex(e + 62, 8)); /* devmajor */
+ assertEqualInt(devminor, from_hex(e + 70, 8)); /* devminor */
+ assert(is_hex(e + 78, 8)); /* rdevmajor */
+ assert(is_hex(e + 86, 8)); /* rdevminor */
+ assertEqualMem(e + 94, "00000004", 8); /* Name size */
+ ns = from_hex(e + 94, 8);
+ ns += PAD(ns + 2, 4);
+ assertEqualInt(0, from_hex(e + 102, 8)); /* check field */
+ assertEqualMem(e + 110, "dir\0\0\0", 6); /* Name contents */
+ e += 110 + fs + ns;
+
+ /* Hardlink identical to "file1" */
+ /* Since we only wrote two of the three links to this
+ * file, this link should get deferred by the hardlink logic. */
+ assert(is_hex(e, 110));
+ assertEqualMem(e + 0, "070701", 6); /* Magic */
+ failure("If these aren't the same, then the hardlink detection failed to match them.");
+ assertEqualInt(ino, from_hex(e + 6, 8)); /* ino */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Group members bits and others bits do not work. */
+ assertEqualInt(0x8180, from_hex(e + 14, 8) & 0xffc0); /* Mode */
+#else
+ assertEqualInt(0x81a4, from_hex(e + 14, 8)); /* Mode */
+#endif
+ assertEqualInt(from_hex(e + 22, 8), uid); /* uid */
+ assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */
+ assertEqualMem(e + 38, "00000003", 8); /* nlink */
+ t2 = from_hex(e + 46, 8); /* mtime */
+ failure("First entry created at t=0x%08x this entry created at t2=0x%08x", t, t2);
+ assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
+ assertEqualInt(10, from_hex(e + 54, 8)); /* File size */
+ fs = from_hex(e + 54, 8);
+ fs += PAD(fs, 4);
+ assertEqualInt(devmajor, from_hex(e + 62, 8)); /* devmajor */
+ assertEqualInt(devminor, from_hex(e + 70, 8)); /* devminor */
+ assert(is_hex(e + 78, 8)); /* rdevmajor */
+ assert(is_hex(e + 86, 8)); /* rdevminor */
+ assertEqualMem(e + 94, "00000009", 8); /* Name size */
+ ns = from_hex(e + 94, 8);
+ ns += PAD(ns + 2, 4);
+ assertEqualInt(0, from_hex(e + 102, 8)); /* check field */
+ assertEqualMem(e + 110, "hardlink\0\0", 10); /* Name contents */
+ assertEqualMem(e + 110 + ns, "1234567890\0\0", 12); /* File contents */
+ e += 110 + ns + fs;
+
+ /* Last entry is end-of-archive marker. */
+ assert(is_hex(e, 110));
+ assertEqualMem(e + 0, "070701", 6); /* Magic */
+ assertEqualMem(e + 8, "00000000", 8); /* ino */
+ assertEqualMem(e + 14, "00000000", 8); /* mode */
+ assertEqualMem(e + 22, "00000000", 8); /* uid */
+ assertEqualMem(e + 30, "00000000", 8); /* gid */
+ assertEqualMem(e + 38, "00000001", 8); /* nlink */
+ assertEqualMem(e + 46, "00000000", 8); /* mtime */
+ assertEqualMem(e + 54, "00000000", 8); /* size */
+ assertEqualMem(e + 62, "00000000", 8); /* devmajor */
+ assertEqualMem(e + 70, "00000000", 8); /* devminor */
+ assertEqualMem(e + 78, "00000000", 8); /* rdevmajor */
+ assertEqualMem(e + 86, "00000000", 8); /* rdevminor */
+ assertEqualInt(11, from_hex(e + 94, 8)); /* name size */
+ assertEqualMem(e + 102, "00000000", 8); /* check field */
+ assertEqualMem(e + 110, "TRAILER!!!\0\0", 12); /* Name */
+
+ free(p);
+}
diff --git a/cpio/test/test_gcpio_compat.c b/cpio/test/test_gcpio_compat.c
new file mode 100644
index 000000000000..461e427c2e88
--- /dev/null
+++ b/cpio/test/test_gcpio_compat.c
@@ -0,0 +1,108 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD: src/usr.bin/cpio/test/test_gcpio_compat.c,v 1.2 2008/08/22 02:27:06 kientzle Exp $");
+
+static void
+unpack_test(const char *from, const char *options, const char *se)
+{
+ int r;
+
+ /* Create a work dir named after the file we're unpacking. */
+ assertMakeDir(from, 0775);
+ assertChdir(from);
+
+ /*
+ * Use cpio to unpack the sample archive
+ */
+ extract_reference_file(from);
+ r = systemf("%s -i %s < %s >unpack.out 2>unpack.err",
+ testprog, options, from);
+ failure("Error invoking %s -i %s < %s",
+ testprog, options, from);
+ assertEqualInt(r, 0);
+
+ /* Verify that nothing went to stderr. */
+ if (canSymlink()) {
+ failure("Error invoking %s -i %s < %s",
+ testprog, options, from);
+ assertTextFileContents(se, "unpack.err");
+ }
+
+ /*
+ * Verify unpacked files.
+ */
+
+ /* Regular file with 2 links. */
+ assertIsReg("file", 0644);
+ failure("%s", from);
+ assertFileSize("file", 10);
+ assertFileSize("linkfile", 10);
+ failure("%s", from);
+ assertFileNLinks("file", 2);
+
+ /* Another name for the same file. */
+ failure("%s", from);
+ assertIsHardlink("linkfile", "file");
+ assertFileSize("file", 10);
+ assertFileSize("linkfile", 10);
+
+ /* Symlink */
+ if (canSymlink())
+ assertIsSymlink("symlink", "file");
+
+ /* dir */
+ assertIsDir("dir", 0775);
+
+ assertChdir("..");
+}
+
+DEFINE_TEST(test_gcpio_compat)
+{
+ assertUmask(0);
+
+ /* Dearchive sample files with a variety of options. */
+ if (canSymlink()) {
+ unpack_test("test_gcpio_compat_ref.bin",
+ "--no-preserve-owner", "1 block\n");
+ unpack_test("test_gcpio_compat_ref.crc",
+ "--no-preserve-owner", "2 blocks\n");
+ unpack_test("test_gcpio_compat_ref.newc",
+ "--no-preserve-owner", "2 blocks\n");
+ /* gcpio-2.9 only reads 6 blocks here */
+ unpack_test("test_gcpio_compat_ref.ustar",
+ "--no-preserve-owner", "7 blocks\n");
+ } else {
+ unpack_test("test_gcpio_compat_ref_nosym.bin",
+ "--no-preserve-owner", "1 block\n");
+ unpack_test("test_gcpio_compat_ref_nosym.crc",
+ "--no-preserve-owner", "2 blocks\n");
+ unpack_test("test_gcpio_compat_ref_nosym.newc",
+ "--no-preserve-owner", "2 blocks\n");
+ /* gcpio-2.9 only reads 6 blocks here */
+ unpack_test("test_gcpio_compat_ref_nosym.ustar",
+ "--no-preserve-owner", "7 blocks\n");
+ }
+}
diff --git a/cpio/test/test_gcpio_compat_ref.bin.uu b/cpio/test/test_gcpio_compat_ref.bin.uu
new file mode 100644
index 000000000000..745d8ab7851a
--- /dev/null
+++ b/cpio/test/test_gcpio_compat_ref.bin.uu
@@ -0,0 +1,16 @@
+$FreeBSD$
+begin 644 test_gcpio_compat_ref.bin
+MQW%9`*IWI('H`^@#`@````U'=YD%````"@!F:6QE```Q,C,T-38W.#D*QW%9
+M`*IWI('H`^@#`@````U'=YD)````"@!L:6YK9FEL90``,3(S-#4V-S@Y"L=Q
+M60"K=^VAZ`/H`P$````-1X29"`````0`<WEM;&EN:P!F:6QEQW%9`*YW_4'H
+M`^@#`@````U'A9D$``````!D:7(`QW$``````````````0`````````+````
+M``!44D%)3$52(2$A````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+1````````````````````````
+`
+end
diff --git a/cpio/test/test_gcpio_compat_ref.crc.uu b/cpio/test/test_gcpio_compat_ref.crc.uu
new file mode 100644
index 000000000000..df8dde05bd82
--- /dev/null
+++ b/cpio/test/test_gcpio_compat_ref.crc.uu
@@ -0,0 +1,27 @@
+$FreeBSD$
+begin 644 test_gcpio_compat_ref.crc
+M,#<P-S`R,#`S,S<W86$P,#`P.#%A-#`P,#`P,V4X,#`P,#`S93@P,#`P,#`P
+M,C0W,&0Y.3<W,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#4Y,#`P,#`P,#`P,#`P
+M,#`P,#`P,#`P,#`U,#`P,#`P,#!F:6QE```P-S`W,#(P,#,S-S=A83`P,#`X
+M,6$T,#`P,#`S93@P,#`P,#-E.#`P,#`P,#`R-#<P9#DY-S<P,#`P,#`P83`P
+M,#`P,#`P,#`P,#`P-3DP,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#DP,#`P,#%E
+M-VQI;FMF:6QE```Q,C,T-38W.#D*```P-S`W,#(P,#,S-S=A8C`P,#!A,65D
+M,#`P,#`S93@P,#`P,#-E.#`P,#`P,#`Q-#<P9#DY.#0P,#`P,#`P-#`P,#`P
+M,#`P,#`P,#`P-3DP,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#@P,#`P,#`P,'-Y
+M;6QI;FL```!F:6QE,#<P-S`R,#`S,S<W864P,#`P-#%F9#`P,#`P,V4X,#`P
+M,#`S93@P,#`P,#`P,C0W,&0Y.3@U,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#4Y
+M,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`T,#`P,#`P,#!D:7(````P-S`W,#(P
+M,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`Q,#`P,#`P
+M,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P
+M,#`P,&(P,#`P,#`P,%1204E,15(A(2$`````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+B````````````````````````````````````````````````
+`
+end
diff --git a/cpio/test/test_gcpio_compat_ref.newc.uu b/cpio/test/test_gcpio_compat_ref.newc.uu
new file mode 100644
index 000000000000..1e29ba907bb4
--- /dev/null
+++ b/cpio/test/test_gcpio_compat_ref.newc.uu
@@ -0,0 +1,27 @@
+$FreeBSD$
+begin 644 test_gcpio_compat_ref.newc
+M,#<P-S`Q,#`S,S<W86$P,#`P.#%A-#`P,#`P,V4X,#`P,#`S93@P,#`P,#`P
+M,C0W,&0Y.3<W,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#4Y,#`P,#`P,#`P,#`P
+M,#`P,#`P,#`P,#`U,#`P,#`P,#!F:6QE```P-S`W,#$P,#,S-S=A83`P,#`X
+M,6$T,#`P,#`S93@P,#`P,#-E.#`P,#`P,#`R-#<P9#DY-S<P,#`P,#`P83`P
+M,#`P,#`P,#`P,#`P-3DP,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#DP,#`P,#`P
+M,&QI;FMF:6QE```Q,C,T-38W.#D*```P-S`W,#$P,#,S-S=A8C`P,#!A,65D
+M,#`P,#`S93@P,#`P,#-E.#`P,#`P,#`Q-#<P9#DY.#0P,#`P,#`P-#`P,#`P
+M,#`P,#`P,#`P-3DP,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#@P,#`P,#`P,'-Y
+M;6QI;FL```!F:6QE,#<P-S`Q,#`S,S<W864P,#`P-#%F9#`P,#`P,V4X,#`P
+M,#`S93@P,#`P,#`P,C0W,&0Y.3@U,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#4Y
+M,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`T,#`P,#`P,#!D:7(````P-S`W,#$P
+M,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`Q,#`P,#`P
+M,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P
+M,#`P,&(P,#`P,#`P,%1204E,15(A(2$`````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+B````````````````````````````````````````````````
+`
+end
diff --git a/cpio/test/test_gcpio_compat_ref.ustar.uu b/cpio/test/test_gcpio_compat_ref.ustar.uu
new file mode 100644
index 000000000000..77989f4aed06
--- /dev/null
+++ b/cpio/test/test_gcpio_compat_ref.ustar.uu
@@ -0,0 +1,84 @@
+$FreeBSD$
+begin 644 test_gcpio_compat_ref.ustar
+M9FEL90``````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````#`P,#`V-#0`,#`P,3<U,``P,#`Q-S4P`#`P,#`P,#`P,#$R
+M`#$P-S`S,S$T-38W`#`P,3$S-C,`,```````````````````````````````
+M````````````````````````````````````````````````````````````
+M``````````````````````````````````````````!U<W1A<@`P,'1I;0``
+M````````````````````````````````````=&EM````````````````````
+M```````````````````P,#`P,#`P`#`P,#`P,#``````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M```````````````````````Q,C,T-38W.#D*````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````````````````````````````````````&QI;FMF:6QE````
+M````````````````````````````````````````````````````````````
+M```````````````````````````````````````````````````````````P
+M,#`P-C0T`#`P,#$W-3``,#`P,3<U,``P,#`P,#`P,#`P,``Q,#<P,S,Q-#4V
+M-P`P,#$S,#<W`#%F:6QE````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````=7-T87(`,#!T:6T`````````````````
+M`````````````````````'1I;0``````````````````````````````````
+M````,#`P,#`P,``P,#`P,#`P````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````<WEM;&EN:P``````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````````````#`P,#`W-34`,#`P,3<U,``P,#`Q-S4P`#`P,#`P
+M,#`P,#`P`#$P-S`S,S$T-C`T`#`P,3(W-C0`,F9I;&4`````````````````
+M````````````````````````````````````````````````````````````
+M``````````````````````````````````````````````````!U<W1A<@`P
+M,'1I;0``````````````````````````````````````=&EM````````````
+M```````````````````````````P,#`P,#`P`#`P,#`P,#``````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M``````````````````````````````!D:7(O````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````,#`P,#<W-0`P,#`Q
+M-S4P`#`P,#$W-3``,#`P,#`P,#`P,#``,3`W,#,S,30V,#4`,#`Q,3,P,0`U
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````'5S=&%R`#`P=&EM````````````````````````````````
+M``````!T:6T``````````````````````````````````````#`P,#`P,#``
+M,#`P,#`P,```````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+=````````````````````````````````````````
+`
+end
diff --git a/cpio/test/test_gcpio_compat_ref_nosym.bin.uu b/cpio/test/test_gcpio_compat_ref_nosym.bin.uu
new file mode 100644
index 000000000000..a3e87a7167ed
--- /dev/null
+++ b/cpio/test/test_gcpio_compat_ref_nosym.bin.uu
@@ -0,0 +1,15 @@
+begin 644 test_gcpio_compat_ref_nosym.bin
+MQW%4`-[Z_4'H`^@#`@`VNZU*NQX$``````!D:7(`QW%4`-SZI('H`^@#`@`G
+MNZU*NQX%````"@!F:6QE```Q,C,T-38W.#D*QW%4`-SZI('H`^@#`@`GNZU*
+MNQX)````"@!L:6YK9FEL90``,3(S-#4V-S@Y"L=Q``````````````$`````
+M````"P``````5%)!24Q%4B$A(0``````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+1````````````````````````
+`
+end
diff --git a/cpio/test/test_gcpio_compat_ref_nosym.crc.uu b/cpio/test/test_gcpio_compat_ref_nosym.crc.uu
new file mode 100644
index 000000000000..38ba9fe1431d
--- /dev/null
+++ b/cpio/test/test_gcpio_compat_ref_nosym.crc.uu
@@ -0,0 +1,15 @@
+begin 644 test_gcpio_compat_ref_nosym.crc
+M,#<P-S`R,#`U-D9!1$4P,#`P-#%&1#`P,#`P,T4X,#`P,#`S13@P,#`P,#`P
+M,C1!040Q14)",#`P,#`P,#`P,#`P,#`P,#`P,#`P,#4T,#`P,#`P0D(P,35"
+M,#`S-C`P,#`P,#`T,#`P,#`P,#!D:7(````P-S`W,#(P,#4V1D%$0S`P,#`X
+M,4$T,#`P,#`S13@P,#`P,#-%.#`P,#`P,#`R-$%!1#%%0D(P,#`P,#`P,#`P
+M,#`P,#`P,#`P,#`P-30P,#`P,#!"0C`Q-4(P,#(W,#`P,#`P,#4P,#`P,#`P
+M,&9I;&4``#`W,#<P,C`P-39&041#,#`P,#@Q030P,#`P,#-%.#`P,#`P,T4X
+M,#`P,#`P,#(T04%$,45"0C`P,#`P,#!!,#`P,#`P,#`P,#`P,#`U-#`P,#`P
+M,$)",#$U0C`P,C<P,#`P,#`P.3`P,#`P,44W;&EN:V9I;&4``#$R,S0U-C<X
+M.0H``#`W,#<P,C`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P
+M,#`P,#$P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P
+M,#`P,#`P,#`P,#`P,#`P0C`P,#`P,#`P5%)!24Q%4B$A(0``````````````
+1````````````````````````
+`
+end
diff --git a/cpio/test/test_gcpio_compat_ref_nosym.newc.uu b/cpio/test/test_gcpio_compat_ref_nosym.newc.uu
new file mode 100644
index 000000000000..24049641f7f5
--- /dev/null
+++ b/cpio/test/test_gcpio_compat_ref_nosym.newc.uu
@@ -0,0 +1,15 @@
+begin 644 test_gcpio_compat_ref_nosym.newc
+M,#<P-S`Q,#`U-D9!1$4P,#`P-#%&1#`P,#`P,T4X,#`P,#`S13@P,#`P,#`P
+M,C1!040Q14)",#`P,#`P,#`P,#`P,#`P,#`P,#`P,#4T,#`P,#`P0D(P,35"
+M,#`S-C`P,#`P,#`T,#`P,#`P,#!D:7(````P-S`W,#$P,#4V1D%$0S`P,#`X
+M,4$T,#`P,#`S13@P,#`P,#-%.#`P,#`P,#`R-$%!1#%%0D(P,#`P,#`P,#`P
+M,#`P,#`P,#`P,#`P-30P,#`P,#!"0C`Q-4(P,#(W,#`P,#`P,#4P,#`P,#`P
+M,&9I;&4``#`W,#<P,3`P-39&041#,#`P,#@Q030P,#`P,#-%.#`P,#`P,T4X
+M,#`P,#`P,#(T04%$,45"0C`P,#`P,#!!,#`P,#`P,#`P,#`P,#`U-#`P,#`P
+M,$)",#$U0C`P,C<P,#`P,#`P.3`P,#`P,#`P;&EN:V9I;&4``#$R,S0U-C<X
+M.0H``#`W,#<P,3`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P
+M,#`P,#$P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P
+M,#`P,#`P,#`P,#`P,#`P0C`P,#`P,#`P5%)!24Q%4B$A(0``````````````
+1````````````````````````
+`
+end
diff --git a/cpio/test/test_gcpio_compat_ref_nosym.ustar.uu b/cpio/test/test_gcpio_compat_ref_nosym.ustar.uu
new file mode 100644
index 000000000000..5f9fcbe6950e
--- /dev/null
+++ b/cpio/test/test_gcpio_compat_ref_nosym.ustar.uu
@@ -0,0 +1,72 @@
+begin 644 test_gcpio_compat_ref_nosym.ustar
+M9&ER+P``````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````#`P,#`W-S4`,#`P,3<U,``P,#`Q-S4P`#`P,#`P,#`P,#`P
+M`#$Q,C4S,C$W,C<S`#`P,3$S-3$`-0``````````````````````````````
+M````````````````````````````````````````````````````````````
+M``````````````````````````````````````````!U<W1A<@`P,'1I;0``
+M````````````````````````````````````=&EM````````````````````
+M```````````````````P,#`P,C<S`#8V,#`P-C8`````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M``````````````````````!F:6QE````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````,#`P,#8T-``P,#`Q-S4P`#`P
+M,#$W-3``,#`P,#`P,#`P,3(`,3$R-3,R,3<R-S,`,#`Q,30R,P`P````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````'5S=&%R`#`P=&EM``````````````````````````````````````!T
+M:6T``````````````````````````````````````#`P,#`R-S,`-C8P,#`T
+M-P``````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````````````````````````````````````#$R,S0U-C<X.0H`
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````;&EN:V9I;&4`````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````````````#`P,#`V-#0`,#`P,3<U,``P,#`Q-S4P`#`P,#`P
+M,#`P,#`P`#$Q,C4S,C$W,C<S`#`P,3,Q,S<`,69I;&4`````````````````
+M````````````````````````````````````````````````````````````
+M``````````````````````````````````````````````````!U<W1A<@`P
+M,'1I;0``````````````````````````````````````=&EM````````````
+M```````````````````````````P,#`P,C<S`#8V,#`P-#<`````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+,````````````````
+`
+end
diff --git a/cpio/test/test_option_B_upper.c b/cpio/test/test_option_B_upper.c
new file mode 100644
index 000000000000..b040354b6053
--- /dev/null
+++ b/cpio/test/test_option_B_upper.c
@@ -0,0 +1,52 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+
+DEFINE_TEST(test_option_B_upper)
+{
+ struct stat st;
+ int r;
+
+ /*
+ * Create a file on disk.
+ */
+ assertMakeFile("file", 0644, NULL);
+
+ /* Create an archive without -B; this should be 512 bytes. */
+ r = systemf("echo file | %s -o > small.cpio 2>small.err", testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "small.err");
+ assertEqualInt(0, stat("small.cpio", &st));
+ assertEqualInt(512, st.st_size);
+
+ /* Create an archive with -B; this should be 5120 bytes. */
+ r = systemf("echo file | %s -oB > large.cpio 2>large.err", testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "large.err");
+ assertEqualInt(0, stat("large.cpio", &st));
+ assertEqualInt(5120, st.st_size);
+}
diff --git a/cpio/test/test_option_C_upper.c b/cpio/test/test_option_C_upper.c
new file mode 100644
index 000000000000..c8e63fd34fb5
--- /dev/null
+++ b/cpio/test/test_option_C_upper.c
@@ -0,0 +1,62 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+
+DEFINE_TEST(test_option_C_upper)
+{
+ int r;
+
+ /*
+ * Create a file on disk.
+ */
+ assertMakeFile("file", 0644, NULL);
+
+ /* Create an archive without -C; this should be 512 bytes. */
+ r = systemf("echo file | %s -o > small.cpio 2>small.err", testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "small.err");
+ assertFileSize("small.cpio", 512);
+
+ /* Create an archive with -C 513; this should be 513 bytes. */
+ r = systemf("echo file | %s -o -C 513 > 513.cpio 2>513.err",
+ testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "513.err");
+ assertFileSize("513.cpio", 513);
+
+ /* Create an archive with -C 12345; this should be 12345 bytes. */
+ r = systemf("echo file | %s -o -C12345 > 12345.cpio 2>12345.err",
+ testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "12345.err");
+ assertFileSize("12345.cpio", 12345);
+
+ /* Create an archive with invalid -C request */
+ assert(0 != systemf("echo file | %s -o -C > bad.cpio 2>bad.err",
+ testprog));
+ assertEmptyFile("bad.cpio");
+}
diff --git a/cpio/test/test_option_J_upper.c b/cpio/test/test_option_J_upper.c
new file mode 100644
index 000000000000..532aacf39cc2
--- /dev/null
+++ b/cpio/test/test_option_J_upper.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2003-2009 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_option_J_upper)
+{
+ 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 -J >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("-J 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, "\3757zXZ", 5);
+}
diff --git a/cpio/test/test_option_L_upper.c b/cpio/test/test_option_L_upper.c
new file mode 100644
index 000000000000..1774343f6732
--- /dev/null
+++ b/cpio/test/test_option_L_upper.c
@@ -0,0 +1,101 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD: src/usr.bin/cpio/test/test_option_L.c,v 1.2 2008/08/24 06:21:00 kientzle Exp $");
+
+/* This is a little pointless, as Windows doesn't support symlinks
+ * (except for the seriously crippled CreateSymbolicLink API) so these
+ * tests won't run on Windows. */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#define CAT "type"
+#else
+#define CAT "cat"
+#endif
+
+DEFINE_TEST(test_option_L_upper)
+{
+ FILE *filelist;
+ int r;
+
+ if (!canSymlink()) {
+ skipping("Symlink tests");
+ return;
+ }
+
+ filelist = fopen("filelist", "w");
+
+ /* Create a file and a symlink to the file. */
+ assertMakeFile("file", 0644, "1234567890");
+ fprintf(filelist, "file\n");
+
+ /* Symlink to above file. */
+ assertMakeSymlink("symlink", "file");
+ fprintf(filelist, "symlink\n");
+
+ fclose(filelist);
+
+ r = systemf(CAT " filelist | %s -pd copy >copy.out 2>copy.err", testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "copy.err");
+
+ failure("Regular -p without -L should preserve symlinks.");
+ assertIsSymlink("copy/symlink", NULL);
+
+ r = systemf(CAT " filelist | %s -pd -L copy-L >copy-L.out 2>copy-L.err", testprog);
+ assertEqualInt(r, 0);
+ assertEmptyFile("copy-L.out");
+ assertTextFileContents("1 block\n", "copy-L.err");
+ failure("-pdL should dereference symlinks and turn them into files.");
+ assertIsReg("copy-L/symlink", -1);
+
+ r = systemf(CAT " filelist | %s -o >archive.out 2>archive.err", testprog);
+ failure("Error invoking %s -o ", testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "archive.err");
+
+ assertMakeDir("unpack", 0755);
+ assertChdir("unpack");
+ r = systemf(CAT " ../archive.out | %s -i >unpack.out 2>unpack.err", testprog);
+ failure("Error invoking %s -i", testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "unpack.err");
+ assertChdir("..");
+
+ assertIsSymlink("unpack/symlink", NULL);
+
+ r = systemf(CAT " filelist | %s -oL >archive-L.out 2>archive-L.err", testprog);
+ failure("Error invoking %s -oL", testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "archive-L.err");
+
+ assertMakeDir("unpack-L", 0755);
+ assertChdir("unpack-L");
+ r = systemf(CAT " ../archive-L.out | %s -i >unpack-L.out 2>unpack-L.err", testprog);
+ failure("Error invoking %s -i < archive-L.out", testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "unpack-L.err");
+ assertChdir("..");
+ assertIsReg("unpack-L/symlink", -1);
+}
diff --git a/cpio/test/test_option_Z_upper.c b/cpio/test/test_option_Z_upper.c
new file mode 100644
index 000000000000..936ce0c2d3e6
--- /dev/null
+++ b/cpio/test/test_option_Z_upper.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2003-2009 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_option_Z_upper)
+{
+ char *p;
+ int r;
+ size_t s;
+
+ /* Create a file. */
+ assertMakeFile("f", 0644, "a");
+
+ /* Archive it with compress compression. */
+ r = systemf("echo f | %s -oZ >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 compress support");
+ return;
+ }
+ failure("-Z option is broken");
+ assertEqualInt(r, 0);
+ return;
+ }
+ /* Check that the archive file has a compress signature. */
+ p = slurpfile(&s, "archive.out");
+ assert(s > 2);
+ assertEqualMem(p, "\x1f\x9d", 2);
+}
diff --git a/cpio/test/test_option_a.c b/cpio/test/test_option_a.c
new file mode 100644
index 000000000000..606de606e2c5
--- /dev/null
+++ b/cpio/test/test_option_a.c
@@ -0,0 +1,154 @@
+/*-
+ * Copyright (c) 2003-2008 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+#if defined(HAVE_UTIME_H)
+#include <utime.h>
+#elif defined(HAVE_SYS_UTIME_H)
+#include <sys/utime.h>
+#endif
+__FBSDID("$FreeBSD: src/usr.bin/cpio/test/test_option_a.c,v 1.3 2008/08/24 06:21:00 kientzle Exp $");
+
+static struct {
+ const char *name;
+ time_t atime_sec;
+} files[] = {
+ { "f0", 0 },
+ { "f1", 0 },
+ { "f2", 0 },
+ { "f3", 0 },
+ { "f4", 0 },
+ { "f5", 0 }
+};
+
+/*
+ * Create a bunch of test files and record their atimes.
+ * For the atime preserve/change tests, the files must have
+ * atimes in the past. We can accomplish this by explicitly invoking
+ * utime() on platforms that support it or by simply sleeping
+ * for a second after creating the files. (Creating all of the files
+ * at once means we only need to sleep once.)
+ */
+static void
+test_create(void)
+{
+ struct stat st;
+ struct utimbuf times;
+ static const int numfiles = sizeof(files) / sizeof(files[0]);
+ int i;
+
+ for (i = 0; i < numfiles; ++i) {
+ /*
+ * Note: Have to write at least one byte to the file.
+ * cpio doesn't bother reading the file if it's zero length,
+ * so the atime never gets changed in that case, which
+ * makes the tests below rather pointless.
+ */
+ assertMakeFile(files[i].name, 0644, "a");
+
+ /* If utime() isn't supported on your platform, just
+ * #ifdef this section out. Most of the test below is
+ * still valid. */
+ memset(&times, 0, sizeof(times));
+ times.actime = 1;
+ times.modtime = 3;
+ assertEqualInt(0, utime(files[i].name, &times));
+
+ /* Record whatever atime the file ended up with. */
+ /* If utime() is available, this should be 1, but there's
+ * no harm in being careful. */
+ assertEqualInt(0, stat(files[i].name, &st));
+ files[i].atime_sec = st.st_atime;
+ }
+
+ /* Wait until the atime on the last file is actually in the past. */
+ sleepUntilAfter(files[numfiles - 1].atime_sec);
+}
+
+DEFINE_TEST(test_option_a)
+{
+ struct stat st;
+ int r;
+ char *p;
+
+ /* Create all of the test files. */
+ test_create();
+
+ /* Sanity check; verify that atimes really do get modified. */
+ assert((p = slurpfile(NULL, "f0")) != NULL);
+ free(p);
+ assertEqualInt(0, stat("f0", &st));
+ if (st.st_atime == files[0].atime_sec) {
+ skipping("Cannot verify -a option\n"
+ " Your system appears to not support atime.");
+ }
+ else
+ {
+ /*
+ * If this disk is mounted noatime, then we can't
+ * verify correct operation without -a.
+ */
+
+ /* Copy the file without -a; should change the atime. */
+ r = systemf("echo %s | %s -pd copy-no-a > copy-no-a.out 2>copy-no-a.err", files[1].name, testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "copy-no-a.err");
+ assertEmptyFile("copy-no-a.out");
+ assertEqualInt(0, stat(files[1].name, &st));
+ failure("Copying file without -a should have changed atime.");
+ assert(st.st_atime != files[1].atime_sec);
+
+ /* Archive the file without -a; should change the atime. */
+ r = systemf("echo %s | %s -o > archive-no-a.out 2>archive-no-a.err", files[2].name, testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "copy-no-a.err");
+ assertEqualInt(0, stat(files[2].name, &st));
+ failure("Archiving file without -a should have changed atime.");
+ assert(st.st_atime != files[2].atime_sec);
+ }
+
+ /*
+ * We can, of course, still verify that the atime is unchanged
+ * when using the -a option.
+ */
+
+ /* Copy the file with -a; should not change the atime. */
+ r = systemf("echo %s | %s -pad copy-a > copy-a.out 2>copy-a.err",
+ files[3].name, testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "copy-a.err");
+ assertEmptyFile("copy-a.out");
+ assertEqualInt(0, stat(files[3].name, &st));
+ failure("Copying file with -a should not have changed atime.");
+ assertEqualInt(st.st_atime, files[3].atime_sec);
+
+ /* Archive the file with -a; should not change the atime. */
+ r = systemf("echo %s | %s -oa > archive-a.out 2>archive-a.err",
+ files[4].name, testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "copy-a.err");
+ assertEqualInt(0, stat(files[4].name, &st));
+ failure("Archiving file with -a should not have changed atime.");
+ assertEqualInt(st.st_atime, files[4].atime_sec);
+}
diff --git a/cpio/test/test_option_c.c b/cpio/test/test_option_c.c
new file mode 100644
index 000000000000..63dcdbd53d46
--- /dev/null
+++ b/cpio/test/test_option_c.c
@@ -0,0 +1,221 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+static int
+is_octal(const char *p, size_t l)
+{
+ while (l > 0) {
+ if (*p < '0' || *p > '7')
+ return (0);
+ --l;
+ ++p;
+ }
+ return (1);
+}
+
+static int
+from_octal(const char *p, size_t l)
+{
+ int r = 0;
+
+ while (l > 0) {
+ r *= 8;
+ r += *p - '0';
+ --l;
+ ++p;
+ }
+ return (r);
+}
+
+DEFINE_TEST(test_option_c)
+{
+ FILE *filelist;
+ int r;
+ int uid = -1;
+ int dev, ino, gid;
+ time_t t, now;
+ char *p, *e;
+ size_t s;
+
+ assertUmask(0);
+
+#if !defined(_WIN32)
+ uid = getuid();
+#endif
+
+ /*
+ * Create an assortment of files.
+ * TODO: Extend this to cover more filetypes.
+ */
+ filelist = fopen("filelist", "w");
+
+ /* "file" */
+ assertMakeFile("file", 0644, "1234567890");
+ fprintf(filelist, "file\n");
+
+ /* "symlink" */
+ if (canSymlink()) {
+ assertMakeSymlink("symlink", "file");
+ fprintf(filelist, "symlink\n");
+ }
+
+ /* "dir" */
+ assertMakeDir("dir", 0775);
+ /* Record some facts about what we just created: */
+ now = time(NULL); /* They were all created w/in last two seconds. */
+ fprintf(filelist, "dir\n");
+
+ /* Use the cpio program to create an archive. */
+ fclose(filelist);
+ r = systemf("%s -oc <filelist >basic.out 2>basic.err", testprog);
+ /* Verify that nothing went to stderr. */
+ assertTextFileContents("1 block\n", "basic.err");
+
+ /* Assert that the program finished. */
+ failure("%s -oc crashed", testprog);
+ if (!assertEqualInt(r, 0))
+ return;
+
+ /* Verify that stdout is a well-formed cpio file in "odc" format. */
+ p = slurpfile(&s, "basic.out");
+ assertEqualInt(s, 512);
+ e = p;
+
+ /*
+ * Some of these assertions could be stronger, but it's
+ * a little tricky because they depend on the local environment.
+ */
+
+ /* First entry is "file" */
+ assert(is_octal(e, 76)); /* Entire header is octal digits. */
+ assertEqualMem(e + 0, "070707", 6); /* Magic */
+ assert(is_octal(e + 6, 6)); /* dev */
+ dev = from_octal(e + 6, 6);
+ assert(is_octal(e + 12, 6)); /* ino */
+ ino = from_octal(e + 12, 6);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Group members bits and others bits do not work. */
+ assertEqualMem(e + 18, "100666", 6); /* Mode */
+#else
+ assertEqualMem(e + 18, "100644", 6); /* Mode */
+#endif
+ if (uid < 0)
+ uid = from_octal(e + 24, 6);
+ assertEqualInt(from_octal(e + 24, 6), uid); /* uid */
+ assert(is_octal(e + 30, 6)); /* gid */
+ gid = from_octal(e + 30, 6);
+ assertEqualMem(e + 36, "000001", 6); /* nlink */
+ failure("file entries should not have rdev set (dev field was 0%o)",
+ dev);
+ assertEqualMem(e + 42, "000000", 6); /* rdev */
+ t = from_octal(e + 48, 11); /* mtime */
+ assert(t <= now); /* File wasn't created in future. */
+ assert(t >= now - 2); /* File was created w/in last 2 secs. */
+ assertEqualMem(e + 59, "000005", 6); /* Name size */
+ assertEqualMem(e + 65, "00000000012", 11); /* File size */
+ assertEqualMem(e + 76, "file\0", 5); /* Name contents */
+ assertEqualMem(e + 81, "1234567890", 10); /* File contents */
+ e += 91;
+
+ /* "symlink" pointing to "file" */
+ if (canSymlink()) {
+ assert(is_octal(e, 76)); /* Entire header is octal digits. */
+ assertEqualMem(e + 0, "070707", 6); /* Magic */
+ assertEqualInt(dev, from_octal(e + 6, 6)); /* dev */
+ assert(ino != from_octal(e + 12, 6)); /* ino */
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ /* On Windows, symbolic link and group members bits and
+ * others bits do not work. */
+ assertEqualMem(e + 18, "120777", 6); /* Mode */
+#endif
+ assertEqualInt(from_octal(e + 24, 6), uid); /* uid */
+ assertEqualInt(gid, from_octal(e + 30, 6)); /* gid */
+ assertEqualMem(e + 36, "000001", 6); /* nlink */
+ failure("file entries should have rdev == 0 (dev was 0%o)",
+ from_octal(e + 6, 6));
+ assertEqualMem(e + 42, "000000", 6); /* rdev */
+ t = from_octal(e + 48, 11); /* mtime */
+ assert(t <= now); /* File wasn't created in future. */
+ assert(t >= now - 2); /* File was created w/in last 2 secs. */
+ assertEqualMem(e + 59, "000010", 6); /* Name size */
+ assertEqualMem(e + 65, "00000000004", 11); /* File size */
+ assertEqualMem(e + 76, "symlink\0", 8); /* Name contents */
+ assertEqualMem(e + 84, "file", 4); /* Symlink target. */
+ e += 88;
+ }
+
+ /* "dir" */
+ assert(is_octal(e, 76));
+ assertEqualMem(e + 0, "070707", 6); /* Magic */
+ /* Dev should be same as first entry. */
+ assert(is_octal(e + 6, 6)); /* dev */
+ assertEqualInt(dev, from_octal(e + 6, 6));
+ /* Ino must be different from first entry. */
+ assert(is_octal(e + 12, 6)); /* ino */
+ assert(ino != from_octal(e + 12, 6));
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Group members bits and others bits do not work. */
+ assertEqualMem(e + 18, "040777", 6); /* Mode */
+#else
+ /* Accept 042775 to accomodate systems where sgid bit propagates. */
+ if (memcmp(e + 18, "042775", 6) != 0)
+ assertEqualMem(e + 18, "040775", 6); /* Mode */
+#endif
+ assertEqualInt(from_octal(e + 24, 6), uid); /* uid */
+ /* Gid should be same as first entry. */
+ assert(is_octal(e + 30, 6)); /* gid */
+ assertEqualInt(gid, from_octal(e + 30, 6));
+#ifndef NLINKS_INACCURATE_FOR_DIRS
+ assertEqualMem(e + 36, "000002", 6); /* Nlink */
+#endif
+ t = from_octal(e + 48, 11); /* mtime */
+ assert(t <= now); /* File wasn't created in future. */
+ assert(t >= now - 2); /* File was created w/in last 2 secs. */
+ assertEqualMem(e + 59, "000004", 6); /* Name size */
+ assertEqualMem(e + 65, "00000000000", 11); /* File size */
+ assertEqualMem(e + 76, "dir\0", 4); /* name */
+ e += 80;
+
+ /* TODO: Verify other types of entries. */
+
+ /* Last entry is end-of-archive marker. */
+ assert(is_octal(e, 76));
+ assertEqualMem(e + 0, "070707", 6); /* Magic */
+ assertEqualMem(e + 6, "000000", 6); /* dev */
+ assertEqualMem(e + 12, "000000", 6); /* ino */
+ assertEqualMem(e + 18, "000000", 6); /* Mode */
+ assertEqualMem(e + 24, "000000", 6); /* uid */
+ assertEqualMem(e + 30, "000000", 6); /* gid */
+ assertEqualMem(e + 36, "000001", 6); /* Nlink */
+ assertEqualMem(e + 42, "000000", 6); /* rdev */
+ assertEqualMem(e + 48, "00000000000", 11); /* mtime */
+ assertEqualMem(e + 59, "000013", 6); /* Name size */
+ assertEqualMem(e + 65, "00000000000", 11); /* File size */
+ assertEqualMem(e + 76, "TRAILER!!!\0", 11); /* Name */
+
+ free(p);
+}
diff --git a/cpio/test/test_option_d.c b/cpio/test/test_option_d.c
new file mode 100644
index 000000000000..9ff14539698f
--- /dev/null
+++ b/cpio/test/test_option_d.c
@@ -0,0 +1,64 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+
+DEFINE_TEST(test_option_d)
+{
+ int r;
+
+ /*
+ * Create a file in a directory.
+ */
+ assertMakeDir("dir", 0755);
+ assertMakeFile("dir/file", 0644, NULL);
+
+ /* Create an archive. */
+ r = systemf("echo dir/file | %s -o > archive.cpio 2>archive.err", testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "archive.err");
+ assertFileSize("archive.cpio", 512);
+
+ /* Dearchive without -d, this should fail. */
+ assertMakeDir("without-d", 0755);
+ assertChdir("without-d");
+ r = systemf("%s -i < ../archive.cpio >out 2>err", testprog);
+ assertEqualInt(r, 0);
+ assertEmptyFile("out");
+ /* And the file should not be restored. */
+ assertFileNotExists("dir/file");
+
+ /* Dearchive with -d, this should succeed. */
+ assertChdir("..");
+ assertMakeDir("with-d", 0755);
+ assertChdir("with-d");
+ r = systemf("%s -id < ../archive.cpio >out 2>err", testprog);
+ assertEqualInt(r, 0);
+ assertEmptyFile("out");
+ assertTextFileContents("1 block\n", "err");
+ /* And the file should be restored. */
+ assertFileExists("dir/file");
+}
diff --git a/cpio/test/test_option_f.c b/cpio/test/test_option_f.c
new file mode 100644
index 000000000000..784e0858431b
--- /dev/null
+++ b/cpio/test/test_option_f.c
@@ -0,0 +1,76 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+/*
+ * Unpack the archive in a new dir.
+ */
+static void
+unpack(const char *dirname, const char *option)
+{
+ int r;
+
+ assertMakeDir(dirname, 0755);
+ assertChdir(dirname);
+ extract_reference_file("test_option_f.cpio");
+ r = systemf("%s -i %s < test_option_f.cpio > copy-no-a.out 2>copy-no-a.err", testprog, option);
+ assertEqualInt(0, r);
+ assertChdir("..");
+}
+
+DEFINE_TEST(test_option_f)
+{
+ /* Calibrate: No -f option, so everything should be extracted. */
+ unpack("t0", "--no-preserve-owner");
+ assertFileExists("t0/a123");
+ assertFileExists("t0/a234");
+ assertFileExists("t0/b123");
+ assertFileExists("t0/b234");
+
+ /* Don't extract 'a*' files. */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Single quotes isn't used by command.exe. */
+ unpack("t1", "--no-preserve-owner -f a*");
+#else
+ unpack("t1", "--no-preserve-owner -f 'a*'");
+#endif
+ assertFileNotExists("t1/a123");
+ assertFileNotExists("t1/a234");
+ assertFileExists("t1/b123");
+ assertFileExists("t1/b234");
+
+ /* Don't extract 'b*' files. */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Single quotes isn't used by command.exe. */
+ unpack("t2", "--no-preserve-owner -f b*");
+#else
+ unpack("t2", "--no-preserve-owner -f 'b*'");
+#endif
+ assertFileExists("t2/a123");
+ assertFileExists("t2/a234");
+ assertFileNotExists("t2/b123");
+ assertFileNotExists("t2/b234");
+}
diff --git a/cpio/test/test_option_f.cpio.uu b/cpio/test/test_option_f.cpio.uu
new file mode 100644
index 000000000000..42c63c39685e
--- /dev/null
+++ b/cpio/test/test_option_f.cpio.uu
@@ -0,0 +1,16 @@
+$FreeBSD$
+begin 644 test_option_f.cpio
+M,#<P-S`W,#`P,3,Q-C(Q-38Q,3`P-C0T,#`Q-S4P,#`Q-S4P,#`P,#`Q,#`P
+M,#`P,3`W,S4Q,3(U,C8P,#`P,#4P,#`P,#`P,#`P,&$Q,C,`,#<P-S`W,#`P
+M,3,Q-C(Q-38S,3`P-C0T,#`Q-S4P,#`Q-S4P,#`P,#`Q,#`P,#`P,3`W,S4Q
+M,3(U-#`P,#`P,#4P,#`P,#`P,#`P,&$R,S0`,#<P-S`W,#`P,3,Q-C(Q-38R
+M,3`P-C0T,#`Q-S4P,#`Q-S4P,#`P,#`Q,#`P,#`P,3`W,S4Q,3(U,S0P,#`P
+M,#4P,#`P,#`P,#`P,&(Q,C,`,#<P-S`W,#`P,3,Q-C(Q-38T,3`P-C0T,#`Q
+M-S4P,#`Q-S4P,#`P,#`Q,#`P,#`P,3`W,S4Q,3(U-#,P,#`P,#4P,#`P,#`P
+M,#`P,&(R,S0`,#<P-S`W,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P
+M,#`P,#`Q,#`P,#`P,#`P,#`P,#`P,#`P,#`P,3,P,#`P,#`P,#`P,%1204E,
+M15(A(2$`````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+1````````````````````````
+`
+end
diff --git a/cpio/test/test_option_help.c b/cpio/test/test_option_help.c
new file mode 100644
index 000000000000..56234306f539
--- /dev/null
+++ b/cpio/test/test_option_help.c
@@ -0,0 +1,84 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+/*
+ * Test that "--help", "-h", and "-W help" options all work and
+ * generate reasonable output.
+ */
+
+static int
+in_first_line(const char *p, const char *substring)
+{
+ size_t l = strlen(substring);
+
+ while (*p != '\0' && *p != '\n') {
+ if (memcmp(p, substring, l) == 0)
+ return (1);
+ ++p;
+ }
+ return (0);
+}
+
+DEFINE_TEST(test_option_help)
+{
+ int r;
+ char *p;
+ size_t plen;
+
+ /* Exercise --help option. */
+ r = systemf("%s --help >help.stdout 2>help.stderr", testprog);
+ assertEqualInt(r, 0);
+ failure("--help should generate nothing to stderr.");
+ assertEmptyFile("help.stderr");
+ /* Help message should start with name of program. */
+ p = slurpfile(&plen, "help.stdout");
+ failure("Help output should be long enough.");
+ assert(plen >= 7);
+ failure("First line of help output should contain string 'bsdcpio'");
+ assert(in_first_line(p, "bsdcpio"));
+ /*
+ * TODO: Extend this check to further verify that --help output
+ * looks approximately right.
+ */
+ free(p);
+
+ /* -h option should generate the same output. */
+ r = systemf("%s -h >h.stdout 2>h.stderr", testprog);
+ assertEqualInt(r, 0);
+ failure("-h should generate nothing to stderr.");
+ assertEmptyFile("h.stderr");
+ failure("stdout should be same for -h and --help");
+ assertEqualFile("h.stdout", "help.stdout");
+
+ /* -W help should be another synonym. */
+ r = systemf("%s -W help >Whelp.stdout 2>Whelp.stderr", testprog);
+ assertEqualInt(r, 0);
+ failure("-W help should generate nothing to stderr.");
+ assertEmptyFile("Whelp.stderr");
+ failure("stdout should be same for -W help and --help");
+ assertEqualFile("Whelp.stdout", "help.stdout");
+}
diff --git a/cpio/test/test_option_l.c b/cpio/test/test_option_l.c
new file mode 100644
index 000000000000..5c76e688e6e9
--- /dev/null
+++ b/cpio/test/test_option_l.c
@@ -0,0 +1,50 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_option_l)
+{
+ int r;
+
+ /* Create a file. */
+ assertMakeFile("f", 0644, "a");
+
+ /* Copy the file to the "copy" dir. */
+ r = systemf("echo f | %s -pd copy >copy.out 2>copy.err",
+ testprog);
+ assertEqualInt(r, 0);
+
+ /* Check that the copy is a true copy and not a link. */
+ assertIsNotHardlink("f", "copy/f");
+
+ /* Copy the file to the "link" dir with the -l option. */
+ r = systemf("echo f | %s -pld link >link.out 2>link.err",
+ testprog);
+ assertEqualInt(r, 0);
+
+ /* Check that this is a link and not a copy. */
+ assertIsHardlink("f", "link/f");
+}
diff --git a/cpio/test/test_option_lzma.c b/cpio/test/test_option_lzma.c
new file mode 100644
index 000000000000..c6e335301505
--- /dev/null
+++ b/cpio/test/test_option_lzma.c
@@ -0,0 +1,56 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_option_lzma)
+{
+ char *p;
+ int r;
+ size_t s;
+
+ /* Create a file. */
+ assertMakeFile("f", 0644, "a");
+
+ /* Archive it with lzma compression. */
+ r = systemf("echo f | %s -o --lzma >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 lzma support");
+ return;
+ }
+ failure("--lzma 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, "\x5d\00\00", 3);
+}
diff --git a/cpio/test/test_option_m.c b/cpio/test/test_option_m.c
new file mode 100644
index 000000000000..de880b2883e1
--- /dev/null
+++ b/cpio/test/test_option_m.c
@@ -0,0 +1,63 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+
+DEFINE_TEST(test_option_m)
+{
+ int r;
+
+ /*
+ * The reference archive has one file with an mtime in 1970, 1
+ * second after the start of the epoch.
+ */
+
+ /* Restored without -m, the result should have a current mtime. */
+ assertMakeDir("without-m", 0755);
+ assertChdir("without-m");
+ extract_reference_file("test_option_m.cpio");
+ r = systemf("%s --no-preserve-owner -i < test_option_m.cpio >out 2>err", testprog);
+ assertEqualInt(r, 0);
+ assertEmptyFile("out");
+ assertTextFileContents("1 block\n", "err");
+ /* Should have been created within the last few seconds. */
+ assertFileMtimeRecent("file");
+
+ /* With -m, it should have an mtime in 1970. */
+ assertChdir("..");
+ assertMakeDir("with-m", 0755);
+ assertChdir("with-m");
+ extract_reference_file("test_option_m.cpio");
+ r = systemf("%s --no-preserve-owner -im < test_option_m.cpio >out 2>err", testprog);
+ assertEqualInt(r, 0);
+ assertEmptyFile("out");
+ assertTextFileContents("1 block\n", "err");
+ /*
+ * mtime in reference archive is '1' == 1 second after
+ * midnight Jan 1, 1970 UTC.
+ */
+ assertFileMtime("file", 1, 0);
+}
diff --git a/cpio/test/test_option_m.cpio.uu b/cpio/test/test_option_m.cpio.uu
new file mode 100644
index 000000000000..3d2002355e55
--- /dev/null
+++ b/cpio/test/test_option_m.cpio.uu
@@ -0,0 +1,16 @@
+$FreeBSD$
+begin 644 test_option_m.cpio
+M,#<P-S`W,#`P,3,Q-#4P,#8T,3`P-C0T,#`Q-S4P,#`Q-S4P,#`P,#`Q,#`P
+M,#`P,#`P,#`P,#`P,#$P,#`P,#4P,#`P,#`P,#`P,&9I;&4`,#<P-S`W,#`P
+M,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`Q,#`P,#`P,#`P,#`P
+M,#`P,#`P,#`P,3,P,#`P,#`P,#`P,%1204E,15(A(2$`````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+1````````````````````````
+`
+end
diff --git a/cpio/test/test_option_t.c b/cpio/test/test_option_t.c
new file mode 100644
index 000000000000..4427bb3a6cd7
--- /dev/null
+++ b/cpio/test/test_option_t.c
@@ -0,0 +1,95 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+
+DEFINE_TEST(test_option_t)
+{
+ char *p;
+ int r;
+
+ /* List reference archive, make sure the TOC is correct. */
+ extract_reference_file("test_option_t.cpio");
+ r = systemf("%s -it < test_option_t.cpio >it.out 2>it.err", testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "it.err");
+ extract_reference_file("test_option_t.stdout");
+ p = slurpfile(NULL, "test_option_t.stdout");
+ assertTextFileContents(p, "it.out");
+ free(p);
+
+ /* We accept plain "-t" as a synonym for "-it" */
+ r = systemf("%s -t < test_option_t.cpio >t.out 2>t.err", testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "t.err");
+ extract_reference_file("test_option_t.stdout");
+ p = slurpfile(NULL, "test_option_t.stdout");
+ assertTextFileContents(p, "t.out");
+ free(p);
+
+ /* But "-ot" is an error. */
+ assert(0 != systemf("%s -ot < test_option_t.cpio >ot.out 2>ot.err",
+ testprog));
+ assertEmptyFile("ot.out");
+
+ /* List reference archive verbosely, make sure the TOC is correct. */
+ r = systemf("%s -itv < test_option_t.cpio >tv.out 2>tv.err", testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "tv.err");
+ extract_reference_file("test_option_tv.stdout");
+
+ /* This doesn't work because the usernames on different systems
+ * are different and cpio now looks up numeric UIDs on
+ * the local system. */
+ /* assertEqualFile("tv.out", "test_option_tv.stdout"); */
+
+ /* List reference archive with numeric IDs, verify TOC is correct. */
+ r = systemf("%s -itnv < test_option_t.cpio >itnv.out 2>itnv.err",
+ testprog);
+ assertEqualInt(r, 0);
+ assertTextFileContents("1 block\n", "itnv.err");
+ p = slurpfile(NULL, "itnv.out");
+ /* Since -n uses numeric UID/GID, this part should be the
+ * same on every system. */
+ assertEqualMem(p, "-rw-r--r-- 1 1000 1000 0 ",42);
+ /* Date varies depending on local timezone. */
+ if (memcmp(p + 42, "Dec 31 1969", 12) == 0) {
+ /* East of Greenwich we get Dec 31, 1969. */
+ } else {
+ /* West of Greenwich get Jan 1, 1970 */
+ assertEqualMem(p + 42, "Jan ", 4);
+ /* Some systems format "Jan 01", some "Jan 1" */
+ assert(p[46] == ' ' || p[46] == '0');
+ assertEqualMem(p + 47, "1 1970 ", 8);
+ }
+ assertEqualMem(p + 54, " file", 5);
+ free(p);
+
+ /* But "-n" without "-t" is an error. */
+ assert(0 != systemf("%s -in < test_option_t.cpio >in.out 2>in.err",
+ testprog));
+ assertEmptyFile("in.out");
+}
diff --git a/cpio/test/test_option_t.cpio.uu b/cpio/test/test_option_t.cpio.uu
new file mode 100644
index 000000000000..055fe747d06f
--- /dev/null
+++ b/cpio/test/test_option_t.cpio.uu
@@ -0,0 +1,16 @@
+$FreeBSD$
+begin 644 test_option_t.cpio
+M,#<P-S`W,#`P,3,Q-#4P,#8T,3`P-C0T,#`Q-S4P,#`Q-S4P,#`P,#`Q,#`P
+M,#`P,#`P,#`P,#`P,#$P,#`P,#4P,#`P,#`P,#`P,&9I;&4`,#<P-S`W,#`P
+M,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`Q,#`P,#`P,#`P,#`P
+M,#`P,#`P,#`P,3,P,#`P,#`P,#`P,%1204E,15(A(2$`````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+1````````````````````````
+`
+end
diff --git a/cpio/test/test_option_t.stdout.uu b/cpio/test/test_option_t.stdout.uu
new file mode 100644
index 000000000000..2457706eceed
--- /dev/null
+++ b/cpio/test/test_option_t.stdout.uu
@@ -0,0 +1,5 @@
+$FreeBSD$
+begin 644 test_option_t.stdout
+%9FEL90H`
+`
+end
diff --git a/cpio/test/test_option_tv.stdout.uu b/cpio/test/test_option_tv.stdout.uu
new file mode 100644
index 000000000000..e28888ac4747
--- /dev/null
+++ b/cpio/test/test_option_tv.stdout.uu
@@ -0,0 +1,6 @@
+$FreeBSD: src/usr.bin/cpio/test/test_option_tv.stdout.uu,v 1.2 2008/11/29 20:22:02 kientzle Exp $
+begin 644 test_option_tv.stdout
+M+7)W+7(M+7(M+2`@(#$@=&EM("`@("`@=&EM("`@("`@("`@("`@(#`@1&5C
+/(#,Q("`Q.38Y(&9I;&4*
+`
+end
diff --git a/cpio/test/test_option_u.c b/cpio/test/test_option_u.c
new file mode 100644
index 000000000000..08058aa45396
--- /dev/null
+++ b/cpio/test/test_option_u.c
@@ -0,0 +1,81 @@
+/*-
+ * 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 "test.h"
+#if defined(HAVE_UTIME_H)
+#include <utime.h>
+#elif defined(HAVE_SYS_UTIME_H)
+#include <sys/utime.h>
+#endif
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_option_u)
+{
+ struct utimbuf times;
+ char *p;
+ size_t s;
+ int r;
+
+ /* Create a file. */
+ assertMakeFile("f", 0644, "a");
+
+ /* Copy the file to the "copy" dir. */
+ r = systemf("echo f | %s -pd copy >copy.out 2>copy.err",
+ testprog);
+ assertEqualInt(r, 0);
+
+ /* Check that the file contains only a single "a" */
+ p = slurpfile(&s, "copy/f");
+ assertEqualInt(s, 1);
+ assertEqualMem(p, "a", 1);
+
+ /* Recreate the file with a single "b" */
+ assertMakeFile("f", 0644, "b");
+
+ /* Set the mtime to the distant past. */
+ memset(&times, 0, sizeof(times));
+ times.actime = 1;
+ times.modtime = 3;
+ assertEqualInt(0, utime("f", &times));
+
+ /* Copy the file to the "copy" dir. */
+ r = systemf("echo f | %s -pd copy >copy.out 2>copy.err",
+ testprog);
+ assertEqualInt(r, 0);
+
+ /* Verify that the file hasn't changed (it wasn't overwritten) */
+ p = slurpfile(&s, "copy/f");
+ assertEqualInt(s, 1);
+ assertEqualMem(p, "a", 1);
+
+ /* Copy the file to the "copy" dir with -u (force) */
+ r = systemf("echo f | %s -pud copy >copy.out 2>copy.err",
+ testprog);
+ assertEqualInt(r, 0);
+
+ /* Verify that the file has changed (it was overwritten) */
+ p = slurpfile(&s, "copy/f");
+ assertEqualInt(s, 1);
+ assertEqualMem(p, "b", 1);
+}
diff --git a/cpio/test/test_option_version.c b/cpio/test/test_option_version.c
new file mode 100644
index 000000000000..7345da1e5157
--- /dev/null
+++ b/cpio/test/test_option_version.c
@@ -0,0 +1,109 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+/*
+ * Test that --version option works and generates reasonable output.
+ */
+
+static void
+verify(const char *p, size_t s)
+{
+ const char *q = p;
+
+ /* Version message should start with name of program, then space. */
+ failure("version message too short:", p);
+ if (!assert(s > 6))
+ return;
+ failure("Version message should begin with 'bsdcpio': %s", p);
+ if (!assertEqualMem(q, "bsdcpio ", 8))
+ /* If we're not testing bsdcpio, don't keep going. */
+ return;
+ q += 8; s -= 8;
+ /* Version number is a series of digits and periods. */
+ while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) {
+ ++q;
+ --s;
+ }
+ /* Version number terminated by space. */
+ failure("Version: %s", p);
+ assert(s > 1);
+ /* Skip a single trailing a,b,c, or d. */
+ if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd')
+ ++q;
+ failure("Version: %s", p);
+ assert(*q == ' ');
+ ++q; --s;
+ /* Separator. */
+ failure("Version: %s", p);
+ assertEqualMem(q, "-- ", 3);
+ q += 3; s -= 3;
+ /* libarchive name and version number */
+ assert(s > 11);
+ failure("Version: %s", p);
+ assertEqualMem(q, "libarchive ", 11);
+ q += 11; s -= 11;
+ /* Version number is a series of digits and periods. */
+ while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) {
+ ++q;
+ --s;
+ }
+ /* Skip a single trailing a,b,c, or d. */
+ if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd')
+ ++q;
+ /* All terminated by end-of-line: \r, \r\n, or \n */
+ assert(s >= 1);
+ failure("Version: %s", p);
+ if (*q == '\x0d') {
+ if (q[1] != '\0')
+ assertEqualMem(q, "\x0d\x0a", 2);
+ } else
+ assertEqualMem(q, "\x0a", 1);
+}
+
+
+DEFINE_TEST(test_option_version)
+{
+ int r;
+ char *p;
+ size_t s;
+
+ r = systemf("%s --version >version.stdout 2>version.stderr", testprog);
+ if (r != 0)
+ r = systemf("%s -W version >version.stdout 2>version.stderr",
+ testprog);
+ failure("Unable to run either %s --version or %s -W version",
+ testprog, testprog);
+ if (!assert(r == 0))
+ return;
+
+ /* --version should generate nothing to stderr. */
+ assertEmptyFile("version.stderr");
+ /* Verify format of version message. */
+ p = slurpfile(&s, "version.stdout");
+ verify(p, s);
+ free(p);
+}
diff --git a/cpio/test/test_option_y.c b/cpio/test/test_option_y.c
new file mode 100644
index 000000000000..58734966ce6a
--- /dev/null
+++ b/cpio/test/test_option_y.c
@@ -0,0 +1,57 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD: src/usr.bin/cpio/test/test_option_y.c,v 1.2 2008/08/24 06:21:00 kientzle Exp $");
+
+DEFINE_TEST(test_option_y)
+{
+ char *p;
+ int r;
+ size_t s;
+
+ /* Create a file. */
+ assertMakeFile("f", 0644, "a");
+
+ /* Archive it with bzip2 compression. */
+ r = systemf("echo f | %s -oy >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 bzip2 support");
+ return;
+ }
+ failure("-y option is broken");
+ assertEqualInt(r, 0);
+ return;
+ }
+ assertTextFileContents("1 block\n", "archive.err");
+ /* Check that the archive file has a bzip2 signature. */
+ p = slurpfile(&s, "archive.out");
+ assert(s > 2);
+ assertEqualMem(p, "BZh9", 4);
+}
diff --git a/cpio/test/test_option_z.c b/cpio/test/test_option_z.c
new file mode 100644
index 000000000000..91d37ac1983a
--- /dev/null
+++ b/cpio/test/test_option_z.c
@@ -0,0 +1,56 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_option_z)
+{
+ char *p;
+ int r;
+ size_t s;
+
+ /* Create a file. */
+ assertMakeFile("f", 0644, "a");
+
+ /* Archive it with gzip compression. */
+ r = systemf("echo f | %s -oz >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 gzip support");
+ return;
+ }
+ failure("-z option is broken");
+ assertEqualInt(r, 0);
+ return;
+ }
+ /* Check that the archive file has a gzip signature. */
+ p = slurpfile(&s, "archive.out");
+ assert(s > 4);
+ assertEqualMem(p, "\x1f\x8b\x08\x00", 4);
+}
diff --git a/cpio/test/test_owner_parse.c b/cpio/test/test_owner_parse.c
new file mode 100644
index 000000000000..d07724e0e776
--- /dev/null
+++ b/cpio/test/test_owner_parse.c
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 2003-2009 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+#include "../cpio.h"
+#include "err.h"
+
+#if !defined(_WIN32)
+#define ROOT "root"
+static int root_uids[] = { 0 };
+/* Solaris 9 root has gid 1 (other) */
+static int root_gids[] = { 0, 1 };
+#elif defined(__CYGWIN__)
+/* On cygwin, the Administrator user most likely exists (unless
+ * it has been renamed or is in a non-English localization), but
+ * its primary group membership depends on how the user set up
+ * their /etc/passwd. Likely values are 513 (None), 545 (Users),
+ * or 544 (Administrators). Just check for one of those...
+ * TODO: Handle non-English localizations...e.g. French 'Administrateur'
+ * Use CreateWellKnownSID() and LookupAccountName()?
+ */
+#define ROOT "Administrator"
+static int root_uids[] = { 500 };
+static int root_gids[] = { 513, 545, 544 };
+#endif
+
+#if defined(ROOT)
+static int
+int_in_list(int i, int *l, size_t n)
+{
+ while (n-- > 0)
+ if (*l++ == i)
+ return (1);
+ failure("%d", i);
+ return (0);
+}
+#endif
+
+DEFINE_TEST(test_owner_parse)
+{
+#if !defined(ROOT)
+ skipping("No uid/gid configuration for this OS");
+#else
+ int uid, gid;
+
+ assert(NULL == owner_parse(ROOT, &uid, &gid));
+ assert(int_in_list(uid, root_uids,
+ sizeof(root_uids)/sizeof(root_uids[0])));
+ assertEqualInt(-1, gid);
+
+
+ assert(NULL == owner_parse(ROOT ":", &uid, &gid));
+ assert(int_in_list(uid, root_uids,
+ sizeof(root_uids)/sizeof(root_uids[0])));
+ assert(int_in_list(gid, root_gids,
+ sizeof(root_gids)/sizeof(root_gids[0])));
+
+ assert(NULL == owner_parse(ROOT ".", &uid, &gid));
+ assert(int_in_list(uid, root_uids,
+ sizeof(root_uids)/sizeof(root_uids[0])));
+ assert(int_in_list(gid, root_gids,
+ sizeof(root_gids)/sizeof(root_gids[0])));
+
+ assert(NULL == owner_parse("111", &uid, &gid));
+ assertEqualInt(111, uid);
+ assertEqualInt(-1, gid);
+
+ assert(NULL == owner_parse("112:", &uid, &gid));
+ assertEqualInt(112, uid);
+ /* Can't assert gid, since we don't know gid for user #112. */
+
+ assert(NULL == owner_parse("113.", &uid, &gid));
+ assertEqualInt(113, uid);
+ /* Can't assert gid, since we don't know gid for user #113. */
+
+ assert(NULL == owner_parse(":114", &uid, &gid));
+ assertEqualInt(-1, uid);
+ assertEqualInt(114, gid);
+
+ assert(NULL == owner_parse(".115", &uid, &gid));
+ assertEqualInt(-1, uid);
+ assertEqualInt(115, gid);
+
+ assert(NULL == owner_parse("116:117", &uid, &gid));
+ assertEqualInt(116, uid);
+ assertEqualInt(117, gid);
+
+ /*
+ * TODO: Lookup current user/group name, build strings and
+ * use those to verify username/groupname lookups for ordinary
+ * users.
+ */
+
+ assert(NULL != owner_parse(":nonexistentgroup", &uid, &gid));
+ assert(NULL != owner_parse(ROOT ":nonexistentgroup", &uid, &gid));
+ assert(NULL !=
+ owner_parse("nonexistentuser:nonexistentgroup", &uid, &gid));
+#endif
+}
diff --git a/cpio/test/test_passthrough_dotdot.c b/cpio/test/test_passthrough_dotdot.c
new file mode 100644
index 000000000000..bb04341a4c79
--- /dev/null
+++ b/cpio/test/test_passthrough_dotdot.c
@@ -0,0 +1,76 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD: src/usr.bin/cpio/test/test_passthrough_dotdot.c,v 1.4 2008/08/24 06:21:00 kientzle Exp $");
+
+/*
+ * Verify that "cpio -p .." works.
+ */
+
+DEFINE_TEST(test_passthrough_dotdot)
+{
+ int r;
+ FILE *filelist;
+
+ assertUmask(0);
+
+ /*
+ * Create an assortment of files on disk.
+ */
+ filelist = fopen("filelist", "w");
+
+ /* Directory. */
+ assertMakeDir("dir", 0755);
+ assertChdir("dir");
+
+ fprintf(filelist, ".\n");
+
+ /* File with 10 bytes content. */
+ assertMakeFile("file", 0642, "1234567890");
+ fprintf(filelist, "file\n");
+
+ /* All done. */
+ fclose(filelist);
+
+
+ /*
+ * Use cpio passthrough mode to copy files to another directory.
+ */
+ r = systemf("%s -pdvm .. <../filelist >../stdout 2>../stderr",
+ testprog);
+ failure("Error invoking %s -pd ..", testprog);
+ assertEqualInt(r, 0);
+
+ assertChdir("..");
+
+ /* Verify stderr and stdout. */
+ assertTextFileContents("../.\n../file\n1 block\n", "stderr");
+ assertEmptyFile("stdout");
+
+ /* Regular file. */
+ assertIsReg("file", 0642);
+ assertFileSize("file", 10);
+ assertFileNLinks("file", 1);
+}
diff --git a/cpio/test/test_passthrough_reverse.c b/cpio/test/test_passthrough_reverse.c
new file mode 100644
index 000000000000..674e52bc0a18
--- /dev/null
+++ b/cpio/test/test_passthrough_reverse.c
@@ -0,0 +1,85 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD: src/usr.bin/cpio/test/test_passthrough_reverse.c,v 1.2 2008/08/24 06:21:00 kientzle Exp $");
+
+/*
+ * As reported by Bernd Walter: Some people are in the habit of
+ * using "find -d" to generate a list for cpio -p because that
+ * copies the top-level dir last, which preserves owner and mode
+ * information. That's not necessary for bsdcpio (libarchive defers
+ * restoring directory information), but bsdcpio should still generate
+ * the correct results with this usage.
+ */
+
+DEFINE_TEST(test_passthrough_reverse)
+{
+ int r;
+ FILE *filelist;
+
+ assertUmask(0);
+
+ /*
+ * Create an assortment of files on disk.
+ */
+ filelist = fopen("filelist", "w");
+
+ /* Directory. */
+ assertMakeDir("dir", 0743);
+
+ /* File with 10 bytes content. */
+ assertMakeFile("dir/file", 0644, "1234567890");
+ fprintf(filelist, "dir/file\n");
+
+ /* Write dir last. */
+ fprintf(filelist, "dir\n");
+
+ /* All done. */
+ fclose(filelist);
+
+
+ /*
+ * Use cpio passthrough mode to copy files to another directory.
+ */
+ r = systemf("%s -pdvm out <filelist >stdout 2>stderr", testprog);
+ failure("Error invoking %s -pd out", testprog);
+ assertEqualInt(r, 0);
+
+ assertChdir("out");
+
+ /* Verify stderr and stdout. */
+ assertTextFileContents("out/dir/file\nout/dir\n1 block\n",
+ "../stderr");
+ assertEmptyFile("../stdout");
+
+ /* dir */
+ assertIsDir("dir", 0743);
+
+
+ /* Regular file. */
+ assertIsReg("dir/file", 0644);
+ assertFileSize("dir/file", 10);
+ assertFileNLinks("dir/file", 1);
+}
diff --git a/cpio/test/test_pathmatch.c b/cpio/test/test_pathmatch.c
new file mode 100644
index 000000000000..177c2bcc4af4
--- /dev/null
+++ b/cpio/test/test_pathmatch.c
@@ -0,0 +1,243 @@
+/*-
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+#include "pathmatch.h"
+
+/*
+ * Verify that the pattern matcher implements the wildcard logic specified
+ * in SUSv2 for the cpio command. This is essentially the
+ * shell glob syntax:
+ * * - matches any sequence of chars, including '/'
+ * ? - matches any single char, including '/'
+ * [...] - matches any of a set of chars, '-' specifies a range,
+ * initial '!' is undefined
+ *
+ * The specification in SUSv2 is a bit incomplete, I assume the following:
+ * Trailing '-' in [...] is not special.
+ *
+ * TODO: Figure out if there's a good way to extend this to handle
+ * Windows paths that use '\' as a path separator. <sigh>
+ */
+
+DEFINE_TEST(test_pathmatch)
+{
+ assertEqualInt(1, lafe_pathmatch("a/b/c", "a/b/c", 0));
+ assertEqualInt(0, lafe_pathmatch("a/b/", "a/b/c", 0));
+ assertEqualInt(0, lafe_pathmatch("a/b", "a/b/c", 0));
+ assertEqualInt(0, lafe_pathmatch("a/b/c", "a/b/", 0));
+ assertEqualInt(0, lafe_pathmatch("a/b/c", "a/b", 0));
+
+ /* Empty pattern only matches empty string. */
+ assertEqualInt(1, lafe_pathmatch("","", 0));
+ assertEqualInt(0, lafe_pathmatch("","a", 0));
+ assertEqualInt(1, lafe_pathmatch("*","", 0));
+ assertEqualInt(1, lafe_pathmatch("*","a", 0));
+ assertEqualInt(1, lafe_pathmatch("*","abcd", 0));
+ /* SUSv2: * matches / */
+ assertEqualInt(1, lafe_pathmatch("*","abcd/efgh/ijkl", 0));
+ assertEqualInt(1, lafe_pathmatch("abcd*efgh/ijkl","abcd/efgh/ijkl", 0));
+ assertEqualInt(1, lafe_pathmatch("abcd***efgh/ijkl","abcd/efgh/ijkl", 0));
+ assertEqualInt(1, lafe_pathmatch("abcd***/efgh/ijkl","abcd/efgh/ijkl", 0));
+ assertEqualInt(0, lafe_pathmatch("?", "", 0));
+ assertEqualInt(0, lafe_pathmatch("?", "\0", 0));
+ assertEqualInt(1, lafe_pathmatch("?", "a", 0));
+ assertEqualInt(0, lafe_pathmatch("?", "ab", 0));
+ assertEqualInt(1, lafe_pathmatch("?", ".", 0));
+ assertEqualInt(1, lafe_pathmatch("?", "?", 0));
+ assertEqualInt(1, lafe_pathmatch("a", "a", 0));
+ assertEqualInt(0, lafe_pathmatch("a", "ab", 0));
+ assertEqualInt(0, lafe_pathmatch("a", "ab", 0));
+ assertEqualInt(1, lafe_pathmatch("a?c", "abc", 0));
+ /* SUSv2: ? matches / */
+ assertEqualInt(1, lafe_pathmatch("a?c", "a/c", 0));
+ assertEqualInt(1, lafe_pathmatch("a?*c*", "a/c", 0));
+ assertEqualInt(1, lafe_pathmatch("*a*", "a/c", 0));
+ assertEqualInt(1, lafe_pathmatch("*a*", "/a/c", 0));
+ assertEqualInt(1, lafe_pathmatch("*a*", "defaaaaaaa", 0));
+ assertEqualInt(0, lafe_pathmatch("a*", "defghi", 0));
+ assertEqualInt(0, lafe_pathmatch("*a*", "defghi", 0));
+
+ /* Character classes */
+ assertEqualInt(1, lafe_pathmatch("abc[def", "abc[def", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[def]", "abc[def", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[def", "abcd", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[def]", "abcd", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[def]", "abce", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[def]", "abcf", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[def]", "abcg", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d*f]", "abcd", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d*f]", "abc*", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[d*f]", "abcdefghi", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[d*", "abcdefghi", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d*", "abc[defghi", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d-f]", "abcd", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d-f]", "abce", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d-f]", "abcf", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[d-f]", "abcg", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[d-fh-k]", "abca", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abcd", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abce", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abcf", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[d-fh-k]", "abcg", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abch", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abci", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abcj", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abck", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[d-fh-k]", "abcl", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[d-fh-k]", "abc-", 0));
+
+ /* [] matches nothing, [!] is the same as ? */
+ assertEqualInt(0, lafe_pathmatch("abc[]efg", "abcdefg", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[]efg", "abcqefg", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[]efg", "abcefg", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[!]efg", "abcdefg", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[!]efg", "abcqefg", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[!]efg", "abcefg", 0));
+
+ /* I assume: Trailing '-' is non-special. */
+ assertEqualInt(0, lafe_pathmatch("abc[d-fh-]", "abcl", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d-fh-]", "abch", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d-fh-]", "abc-", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d-fh-]", "abc-", 0));
+
+ /* ']' can be backslash-quoted within a character class. */
+ assertEqualInt(1, lafe_pathmatch("abc[\\]]", "abc]", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[\\]d]", "abc]", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[\\]d]", "abcd", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d\\]]", "abc]", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d\\]]", "abcd", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d]e]", "abcde]", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d\\]e]", "abc]", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[d\\]e]", "abcd]e", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[d]e]", "abc]", 0));
+
+ /* backslash-quoted chars can appear as either end of a range. */
+ assertEqualInt(1, lafe_pathmatch("abc[\\d-f]gh", "abcegh", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[\\d-f]gh", "abcggh", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[\\d-f]gh", "abc\\gh", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d-\\f]gh", "abcegh", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[\\d-\\f]gh", "abcegh", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[\\d-\\f]gh", "abcegh", 0));
+ /* backslash-quoted '-' isn't special. */
+ assertEqualInt(0, lafe_pathmatch("abc[d\\-f]gh", "abcegh", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[d\\-f]gh", "abc-gh", 0));
+
+ /* Leading '!' negates a character class. */
+ assertEqualInt(0, lafe_pathmatch("abc[!d]", "abcd", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[!d]", "abce", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[!d]", "abcc", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[!d-z]", "abcq", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[!d-gi-z]", "abch", 0));
+ assertEqualInt(1, lafe_pathmatch("abc[!fgijkl]", "abch", 0));
+ assertEqualInt(0, lafe_pathmatch("abc[!fghijkl]", "abch", 0));
+
+ /* Backslash quotes next character. */
+ assertEqualInt(0, lafe_pathmatch("abc\\[def]", "abc\\d", 0));
+ assertEqualInt(1, lafe_pathmatch("abc\\[def]", "abc[def]", 0));
+ assertEqualInt(0, lafe_pathmatch("abc\\\\[def]", "abc[def]", 0));
+ assertEqualInt(0, lafe_pathmatch("abc\\\\[def]", "abc\\[def]", 0));
+ assertEqualInt(1, lafe_pathmatch("abc\\\\[def]", "abc\\d", 0));
+ assertEqualInt(1, lafe_pathmatch("abcd\\", "abcd\\", 0));
+ assertEqualInt(0, lafe_pathmatch("abcd\\", "abcd\\[", 0));
+ assertEqualInt(0, lafe_pathmatch("abcd\\", "abcde", 0));
+ assertEqualInt(0, lafe_pathmatch("abcd\\[", "abcd\\", 0));
+
+ /*
+ * Because '.' and '/' have special meanings, we can
+ * identify many equivalent paths even if they're expressed
+ * differently. (But quoting a character with '\\' suppresses
+ * special meanings!)
+ */
+ assertEqualInt(0, lafe_pathmatch("a/b/", "a/bc", 0));
+ assertEqualInt(1, lafe_pathmatch("a/./b", "a/b", 0));
+ assertEqualInt(0, lafe_pathmatch("a\\/./b", "a/b", 0));
+ assertEqualInt(0, lafe_pathmatch("a/\\./b", "a/b", 0));
+ assertEqualInt(0, lafe_pathmatch("a/.\\/b", "a/b", 0));
+ assertEqualInt(0, lafe_pathmatch("a\\/\\.\\/b", "a/b", 0));
+ assertEqualInt(1, lafe_pathmatch("./abc/./def/", "abc/def/", 0));
+ assertEqualInt(1, lafe_pathmatch("abc/def", "./././abc/./def", 0));
+ assertEqualInt(1, lafe_pathmatch("abc/def/././//", "./././abc/./def/", 0));
+ assertEqualInt(1, lafe_pathmatch(".////abc/.//def", "./././abc/./def", 0));
+ assertEqualInt(1, lafe_pathmatch("./abc?def/", "abc/def/", 0));
+ failure("\"?./\" is not the same as \"/./\"");
+ assertE