[Cmake-commits] [cmake-commits] hoffman committed .cvsignore NONE 1.1 CMakeLists.txt NONE 1.1 Makefile NONE 1.1 README NONE 1.1 main.c NONE 1.1 read_open_memory.c NONE 1.1 test.h NONE 1.1 test_acl_basic.c NONE 1.1 test_acl_freebsd.c NONE 1.1 test_acl_pax.c NONE 1.1 test_archive_api_feature.c NONE 1.1 test_bad_fd.c NONE 1.1 test_compat_bzip2.c NONE 1.1 test_compat_bzip2_1.tbz.uu NONE 1.1 test_compat_bzip2_2.tbz.uu NONE 1.1 test_compat_gtar.c NONE 1.1 test_compat_gtar_1.tar.uu NONE 1.1 test_compat_gzip.c NONE 1.1 test_compat_gzip_1.tgz.uu NONE 1.1 test_compat_gzip_2.tgz.uu NONE 1.1 test_compat_solaris_tar_acl.c NONE 1.1 test_compat_solaris_tar_acl.tar.uu NONE 1.1 test_compat_tar_hardlink.c NONE 1.1 test_compat_tar_hardlink_1.tar.uu NONE 1.1 test_compat_xz.c NONE 1.1 test_compat_xz_1.txz.uu NONE 1.1 test_compat_zip.c NONE 1.1 test_compat_zip_1.zip.uu NONE 1.1 test_empty_write.c NONE 1.1 test_entry.c NONE 1.1 test_entry_strmode.c NONE 1.1 test_extattr_freebsd.c NONE 1.1 test_fuzz.c NONE 1.1 test_fuzz_1.iso.uu NONE 1.1 test_link_resolver.c NONE 1.1 test_open_fd.c NONE 1.1 test_open_file.c NONE 1.1 test_open_filename.c NONE 1.1 test_pax_filename_encoding.c NONE 1.1 test_pax_filename_encoding.tar.uu NONE 1.1 test_read_compress_program.c NONE 1.1 test_read_data_large.c NONE 1.1 test_read_disk.c NONE 1.1 test_read_disk_entry_from_file.c NONE 1.1 test_read_extract.c NONE 1.1 test_read_file_nonexistent.c NONE 1.1 test_read_format_ar.c NONE 1.1 test_read_format_cpio_bin.c NONE 1.1 test_read_format_cpio_bin_Z.c NONE 1.1 test_read_format_cpio_bin_be.c NONE 1.1 test_read_format_cpio_bin_be.cpio.uu NONE 1.1 test_read_format_cpio_bin_bz2.c NONE 1.1 test_read_format_cpio_bin_gz.c NONE 1.1 test_read_format_cpio_bin_xz.c NONE 1.1 test_read_format_cpio_odc.c NONE 1.1 test_read_format_cpio_svr4_gzip.c NONE 1.1 test_read_format_cpio_svr4c_Z.c NONE 1.1 test_read_format_empty.c NONE 1.1 test_read_format_gtar_gz.c NONE 1.1 test_read_format_gtar_lzma.c NONE 1.1 test_read_format_gtar_sparse.c NONE 1.1 test_read_format_gtar_sparse_1_13.tar.uu NONE 1.1 test_read_format_gtar_sparse_1_17.tar.uu NONE 1.1 test_read_format_gtar_sparse_1_17_posix00.tar.uu NONE 1.1 test_read_format_gtar_sparse_1_17_posix01.tar.uu NONE 1.1 test_read_format_gtar_sparse_1_17_posix10.tar.uu NONE 1.1 test_read_format_gtar_sparse_1_17_posix10_modified.tar.uu NONE 1.1 test_read_format_iso_gz.c NONE 1.1 test_read_format_iso_gz.iso.gz.uu NONE 1.1 test_read_format_isojoliet_bz2.c NONE 1.1 test_read_format_isojoliet_bz2.iso.bz2.uu NONE 1.1 test_read_format_isojoliet_long.c NONE 1.1 test_read_format_isojoliet_long.iso.bz2.uu NONE 1.1 test_read_format_isojoliet_rr.c NONE 1.1 test_read_format_isojoliet_rr.iso.bz2.uu NONE 1.1 test_read_format_isorr_bz2.c NONE 1.1 test_read_format_isorr_bz2.iso.bz2.uu NONE 1.1 test_read_format_isorr_new_bz2.c NONE 1.1 test_read_format_isorr_new_bz2.iso.bz2.uu NONE 1.1 test_read_format_isozisofs_bz2.c NONE 1.1 test_read_format_isozisofs_bz2.iso.bz2.uu NONE 1.1 test_read_format_mtree.c NONE 1.1 test_read_format_pax_bz2.c NONE 1.1 test_read_format_raw.c NONE 1.1 test_read_format_raw.data.Z.uu NONE 1.1 test_read_format_raw.data.uu NONE 1.1 test_read_format_tar.c NONE 1.1 test_read_format_tar_empty_filename.c NONE 1.1 test_read_format_tar_empty_filename.tar.uu NONE 1.1 test_read_format_tbz.c NONE 1.1 test_read_format_tgz.c NONE 1.1 test_read_format_txz.c NONE 1.1 test_read_format_tz.c NONE 1.1 test_read_format_zip.c NONE 1.1 test_read_format_zip.zip.uu NONE 1.1 test_read_large.c NONE 1.1 test_read_pax_truncated.c NONE 1.1 test_read_position.c NONE 1.1 test_read_truncated.c NONE 1.1 test_tar_filenames.c NONE 1.1 test_tar_large.c NONE 1.1 test_ustar_filenames.c NONE 1.1 test_write_compress.c NONE 1.1 test_write_compress_bzip2.c NONE 1.1 test_write_compress_gzip.c NONE 1.1 test_write_compress_lzma.c NONE 1.1 test_write_compress_program.c NONE 1.1 test_write_compress_xz.c NONE 1.1 test_write_disk.c NONE 1.1 test_write_disk_failures.c NONE 1.1 test_write_disk_hardlink.c NONE 1.1 test_write_disk_perms.c NONE 1.1 test_write_disk_secure.c NONE 1.1 test_write_disk_sparse.c NONE 1.1 test_write_disk_symlink.c NONE 1.1 test_write_disk_times.c NONE 1.1 test_write_format_ar.c NONE 1.1 test_write_format_cpio.c NONE 1.1 test_write_format_cpio_empty.c NONE 1.1 test_write_format_cpio_newc.c NONE 1.1 test_write_format_cpio_odc.c NONE 1.1 test_write_format_mtree.c NONE 1.1 test_write_format_pax.c NONE 1.1 test_write_format_shar_empty.c NONE 1.1 test_write_format_tar.c NONE 1.1 test_write_format_tar_empty.c NONE 1.1 test_write_format_tar_ustar.c NONE 1.1 test_write_format_zip.c NONE 1.1 test_write_format_zip_empty.c NONE 1.1 test_write_format_zip_no_compression.c NONE 1.1 test_write_open_memory.c NONE 1.1

cmake-commits at cmake.org cmake-commits at cmake.org
Fri Oct 30 13:10:49 EDT 2009


Update of /cvsroot/CMake/CMake/Utilities/cmlibarchive/libarchive/test
In directory public:/mounts/ram/cvs-serv26614/Utilities/cmlibarchive/libarchive/test

Added Files:
	.cvsignore CMakeLists.txt Makefile README main.c 
	read_open_memory.c test.h test_acl_basic.c test_acl_freebsd.c 
	test_acl_pax.c test_archive_api_feature.c test_bad_fd.c 
	test_compat_bzip2.c test_compat_bzip2_1.tbz.uu 
	test_compat_bzip2_2.tbz.uu test_compat_gtar.c 
	test_compat_gtar_1.tar.uu test_compat_gzip.c 
	test_compat_gzip_1.tgz.uu test_compat_gzip_2.tgz.uu 
	test_compat_solaris_tar_acl.c 
	test_compat_solaris_tar_acl.tar.uu test_compat_tar_hardlink.c 
	test_compat_tar_hardlink_1.tar.uu test_compat_xz.c 
	test_compat_xz_1.txz.uu test_compat_zip.c 
	test_compat_zip_1.zip.uu test_empty_write.c test_entry.c 
	test_entry_strmode.c test_extattr_freebsd.c test_fuzz.c 
	test_fuzz_1.iso.uu test_link_resolver.c test_open_fd.c 
	test_open_file.c test_open_filename.c 
	test_pax_filename_encoding.c test_pax_filename_encoding.tar.uu 
	test_read_compress_program.c test_read_data_large.c 
	test_read_disk.c test_read_disk_entry_from_file.c 
	test_read_extract.c test_read_file_nonexistent.c 
	test_read_format_ar.c test_read_format_cpio_bin.c 
	test_read_format_cpio_bin_Z.c test_read_format_cpio_bin_be.c 
	test_read_format_cpio_bin_be.cpio.uu 
	test_read_format_cpio_bin_bz2.c test_read_format_cpio_bin_gz.c 
	test_read_format_cpio_bin_xz.c test_read_format_cpio_odc.c 
	test_read_format_cpio_svr4_gzip.c 
	test_read_format_cpio_svr4c_Z.c test_read_format_empty.c 
	test_read_format_gtar_gz.c test_read_format_gtar_lzma.c 
	test_read_format_gtar_sparse.c 
	test_read_format_gtar_sparse_1_13.tar.uu 
	test_read_format_gtar_sparse_1_17.tar.uu 
	test_read_format_gtar_sparse_1_17_posix00.tar.uu 
	test_read_format_gtar_sparse_1_17_posix01.tar.uu 
	test_read_format_gtar_sparse_1_17_posix10.tar.uu 
	test_read_format_gtar_sparse_1_17_posix10_modified.tar.uu 
	test_read_format_iso_gz.c test_read_format_iso_gz.iso.gz.uu 
	test_read_format_isojoliet_bz2.c 
	test_read_format_isojoliet_bz2.iso.bz2.uu 
	test_read_format_isojoliet_long.c 
	test_read_format_isojoliet_long.iso.bz2.uu 
	test_read_format_isojoliet_rr.c 
	test_read_format_isojoliet_rr.iso.bz2.uu 
	test_read_format_isorr_bz2.c 
	test_read_format_isorr_bz2.iso.bz2.uu 
	test_read_format_isorr_new_bz2.c 
	test_read_format_isorr_new_bz2.iso.bz2.uu 
	test_read_format_isozisofs_bz2.c 
	test_read_format_isozisofs_bz2.iso.bz2.uu 
	test_read_format_mtree.c test_read_format_pax_bz2.c 
	test_read_format_raw.c test_read_format_raw.data.Z.uu 
	test_read_format_raw.data.uu test_read_format_tar.c 
	test_read_format_tar_empty_filename.c 
	test_read_format_tar_empty_filename.tar.uu 
	test_read_format_tbz.c test_read_format_tgz.c 
	test_read_format_txz.c test_read_format_tz.c 
	test_read_format_zip.c test_read_format_zip.zip.uu 
	test_read_large.c test_read_pax_truncated.c 
	test_read_position.c test_read_truncated.c 
	test_tar_filenames.c test_tar_large.c test_ustar_filenames.c 
	test_write_compress.c test_write_compress_bzip2.c 
	test_write_compress_gzip.c test_write_compress_lzma.c 
	test_write_compress_program.c test_write_compress_xz.c 
	test_write_disk.c test_write_disk_failures.c 
	test_write_disk_hardlink.c test_write_disk_perms.c 
	test_write_disk_secure.c test_write_disk_sparse.c 
	test_write_disk_symlink.c test_write_disk_times.c 
	test_write_format_ar.c test_write_format_cpio.c 
	test_write_format_cpio_empty.c test_write_format_cpio_newc.c 
	test_write_format_cpio_odc.c test_write_format_mtree.c 
	test_write_format_pax.c test_write_format_shar_empty.c 
	test_write_format_tar.c test_write_format_tar_empty.c 
	test_write_format_tar_ustar.c test_write_format_zip.c 
	test_write_format_zip_empty.c 
	test_write_format_zip_no_compression.c 
	test_write_open_memory.c 
Log Message:
Switch to using libarchive from libtar for cpack and cmake -E tar

This allows for a built in bzip and zip capability, so external tools 
will not be needed for these packagers.  The cmake -E tar xf should be
able to handle all compression types now as well.



--- NEW FILE: test_read_format_isorr_bz2.iso.bz2.uu ---
begin 644 test_read_format_isorr_bz2.iso.bz2
M0EIH.3%!629361^[8GT``-I_W?__Z_Q5X__Z/__?8*?OWB8A_R2```4@`(`"
M at 0C0`[X.@;"X4N!H13U3:3U,TTF30-`T:9!IH:`:`!H&@`T-, at T&AD`TU`@:
MFFDT](]$T3"&1@`",0`#3`$8`@TPFFF!HU%,IFHTV4TTT:`!HT`#0```#0`#
MU#0``!QH:`-``T````&@````&0``#$`12(F2:1Z:GHU&$,$#1IHTR:#0```T
M```-&F1B5C+"&F]A9Z?`U1J4+Y`J<.R%DQ,4_M&L-&]P!VH0THE"001`PKEQ
ME0`&9.7LA`.V0`"_Z$%$0`=]@R7<U`7+0 at TP@@H@#@C`$HA6!!B,-Q),IR03
M8(41$0!KA`WX)758H0&@(6N=<U*JH8H:*:1FPW/EQB(U$,-:P=O>7`LU0AC!
M%@7\Q3`%DJ%=(0D"('\[&MK[J*15!$`=K+&R-YNQ!N+%&C)7.T-#E1>IVJ[L
M[Z9N]_H#7;&H;!)'O@,VY`YJ-R0)C14:^@C;.7"EG9(L(S&HOPA4)@D"R1 at H
M8DS22Y,"9B-XEZJ9"4Q at P/HBL$Q0GJHO'K.]Z9#V)6%C-*$=%1F\SI*/1TK=
MN.<,!."80/-@)&42M3D9",BA1GJ5.?`:ESRT%@I33,AKD0*,&I02?X[HH)67
M?]KD&>W9J3OH4Z3%F1O%/UTEWU%*2RH[CL6)ZPT:1!,462+PJ20)T"!&A"&%
M+,$`D@@*B at D()X4/A92B1'-B)DEJF7R\W/V!V6_2O$!Q8R+C1PP!@B*!@)"4
MD,2&P3N:C7$0P+4%#64U!CJ>BNO5*-8JS@"8'&/E4>D`.HTHL96`+%?`$^AF
M()HE49JS"KT92H!#R%5R33$E7](2I&CAZW+#`AJ:J!&58)9S)AO3=?["VH1^
M3#)/();9KC%[E1J,5<&N(1,S],$*[)-H$^"6Q`(((8 at 2$4OD0,1]$2P\U-F.
M85F>3TM?8G8YMVM*;8!.`"X+$H#`R-ZGR2HE<-"5*MDB at R.>4'[#((D`-A%T
MZM;_9X1L"$-E4B=@[24#0MD=22LJK0R`,8&T$A1G#I6(<HPN*X9/C$B77]P$
MF3=#+R7Q0"!0[;X,(1A("E18EZ["7$YC6BSA`NQ at HH%THXC)7!90J[;2#1!H
M!%!['FG<!7-@('K1L!OA=`](>B>`/]A,S at 1,:WV$RA5P'4C0:D\"`G6`HAA7
ML/K"'V(4B'7)&-/-%:31TQU=%BQ6)LBX\S(XB*C"82F+M5LTR"!.@$(9&R/<
M#`M+J68NWY?P4YF=3=H)+D]8-YC6AN6+'O,\)E&/^)4,4$2&,<9CSR at V!F-P
>@G!B;(\/.2E,^!VZA%!$`<!V_^+N2*<*$@/W;$^@
`
end

--- NEW FILE: test_empty_write.c ---
/*-
 * 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/lib/libarchive/test/test_empty_write.c,v 1.3 2008/09/01 05:38:33 kientzle Exp $");

DEFINE_TEST(test_empty_write)
{
    char buff[32768];
    struct archive_entry *ae;
    struct archive *a;
    size_t used;
    int r;

    /*
     * Exercise a zero-byte write to a gzip-compressed archive.
     */

    /* Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    r = archive_write_set_compression_gzip(a);
    if (r == ARCHIVE_FATAL) {
        skipping("Empty write to gzip-compressed archive");
    } else {
        assertEqualIntA(a, ARCHIVE_OK, r);
        assertEqualIntA(a, ARCHIVE_OK,
            archive_write_open_memory(a, buff, sizeof(buff), &used));
        /* Write a file to it. */
        assert((ae = archive_entry_new()) != NULL);
        archive_entry_copy_pathname(ae, "file");
        archive_entry_set_mode(ae, S_IFREG | 0755);
        archive_entry_set_size(ae, 0);
        assertA(0 == archive_write_header(a, ae));
        archive_entry_free(ae);

        /* THE TEST: write zero bytes to this entry. */
        /* This used to crash. */
        assertEqualIntA(a, 0, archive_write_data(a, "", 0));

        /* Close out the archive. */
        assertA(0 == archive_write_close(a));
        assertA(0 == archive_write_finish(a));
    }

    /*
     * Again, with bzip2 compression.
     */

    /* Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    r = archive_write_set_compression_bzip2(a);
    if (r == ARCHIVE_FATAL) {
        skipping("Empty write to bzip2-compressed archive");
    } else {
        assertEqualIntA(a, ARCHIVE_OK, r);
        assertEqualIntA(a, ARCHIVE_OK,
            archive_write_open_memory(a, buff, sizeof(buff), &used));
        /* Write a file to it. */
        assert((ae = archive_entry_new()) != NULL);
        archive_entry_copy_pathname(ae, "file");
        archive_entry_set_mode(ae, S_IFREG | 0755);
        archive_entry_set_size(ae, 0);
        assertA(0 == archive_write_header(a, ae));
        archive_entry_free(ae);

        /* THE TEST: write zero bytes to this entry. */
        assertEqualIntA(a, 0, archive_write_data(a, "", 0));

        /* Close out the archive. */
        assertA(0 == archive_write_close(a));
        assertA(0 == archive_write_finish(a));
    }

    /*
     * For good measure, one more time with no compression.
     */

    /* Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    assertA(0 == archive_write_set_compression_none(a));
    assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));
    /* Write a file to it. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    archive_entry_set_size(ae, 0);
    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);

    /* THE TEST: write zero bytes to this entry. */
    assertEqualIntA(a, 0, archive_write_data(a, "", 0));

    /* Close out the archive. */
    assertA(0 == archive_write_close(a));
    assertA(0 == archive_write_finish(a));
}

--- NEW FILE: test_read_format_raw.data.Z.uu ---
begin 644 test_read_format_raw.data.Z
('YV09MZ\40``
`
end

--- NEW FILE: test_write_format_cpio_empty.c ---
/*-
 * 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/lib/libarchive/test/test_write_format_cpio_empty.c,v 1.3 2008/09/01 05:38:33 kientzle Exp $");

/*
 * Check that an "empty" cpio archive is correctly created.
 */

/* Here's what an empty cpio archive should look like. */
static char ref[] =
"070707"  /* Magic number */
"000000"  /* Dev = 0 */
"000000"  /* ino = 0 */
"000000"  /* mode = 0 */
"000000"  /* uid = 0 */
"000000"  /* gid = 0 */
"000001"  /* nlink = 1 */
"000000"  /* rdev = 0 */
"00000000000" /* mtime = 0 */
"000013"  /* Namesize = 11 */
"00000000000" /* filesize = 0 */
"TRAILER!!!\0"; /* Name */

DEFINE_TEST(test_write_format_cpio_empty)
{
    struct archive *a;
    char buff[2048];
    size_t used;

    /* Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_cpio(a));
    assertA(0 == archive_write_set_compression_none(a));
    /* 1-byte block size ensures we see only the required bytes. */
    /* We're not testing the padding here. */
    assertA(0 == archive_write_set_bytes_per_block(a, 1));
    assertA(0 == archive_write_set_bytes_in_last_block(a, 1));
    assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));

    /* Close out the archive. */
    assertA(0 == archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assertA(0 == archive_write_finish(a));
#endif

    failure("Empty cpio archive should be exactly 87 bytes, was %d.", used);
    assert(used == 87);
    failure("Empty cpio archive is incorrectly formatted.");
    assert(memcmp(buff, ref, 87) == 0);
}

--- NEW FILE: test_compat_solaris_tar_acl.c ---
/*-
 * 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$");

/*
 * Exercise support for reading Solaris-style ACL data
 * from tar archives.
 *
 * This should work on all systems, regardless of whether local
 * filesystems support ACLs or not.
 */

DEFINE_TEST(test_compat_solaris_tar_acl)
{
    struct archive *a;
    struct archive_entry *ae;
    const char *reference1 = "test_compat_solaris_tar_acl.tar";
    int type, permset, tag, qual;
    const char *name;

    /* Sample file generated on Solaris 10 */
    extract_reference_file(reference1);
    assert(NULL != (a = archive_read_new()));
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_filename(a, reference1, 512));

    /* Archive has 1 entry with some ACLs set on it. */
    assertA(0 == archive_read_next_header(a, &ae));
    failure("Basic ACLs should set mode to 0640, not %04o",
        archive_entry_mode(ae)&0777);
    assertEqualInt((archive_entry_mode(ae) & 0777), 0640);
    assertEqualInt(7, archive_entry_acl_reset(ae,
        ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
    assertEqualInt(ARCHIVE_OK, archive_entry_acl_next(ae,
        ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
        &type, &permset, &tag, &qual, &name));
    assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ACCESS, type);
    assertEqualInt(006, permset);
    assertEqualInt(ARCHIVE_ENTRY_ACL_USER_OBJ, tag);
    assertEqualInt(-1, qual);
    assert(name == NULL);

    assertEqualInt(ARCHIVE_OK, archive_entry_acl_next(ae,
        ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
        &type, &permset, &tag, &qual, &name));
    assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ACCESS, type);
    assertEqualInt(004, permset);
    assertEqualInt(ARCHIVE_ENTRY_ACL_GROUP_OBJ, tag);
    assertEqualInt(-1, qual);
    assert(name == NULL);

    assertEqualInt(ARCHIVE_OK, archive_entry_acl_next(ae,
        ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
        &type, &permset, &tag, &qual, &name));
    assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ACCESS, type);
    assertEqualInt(000, permset);
    assertEqualInt(ARCHIVE_ENTRY_ACL_OTHER, tag);
    assertEqualInt(-1, qual);
    assert(name == NULL);

    assertEqualInt(ARCHIVE_OK, archive_entry_acl_next(ae,
        ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
        &type, &permset, &tag, &qual, &name));
    assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ACCESS, type);
    assertEqualInt(001, permset);
    assertEqualInt(ARCHIVE_ENTRY_ACL_USER, tag);
    assertEqualInt(71, qual);
    assertEqualString(name, "lp");

    assertEqualInt(ARCHIVE_OK, archive_entry_acl_next(ae,
        ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
        &type, &permset, &tag, &qual, &name));
    assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ACCESS, type);
    assertEqualInt(004, permset);
    assertEqualInt(ARCHIVE_ENTRY_ACL_USER, tag);
    assertEqualInt(666, qual);
    assertEqualString(name, "666");

    assertEqualInt(ARCHIVE_OK, archive_entry_acl_next(ae,
        ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
        &type, &permset, &tag, &qual, &name));
    assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ACCESS, type);
    assertEqualInt(007, permset);
    assertEqualInt(ARCHIVE_ENTRY_ACL_USER, tag);
    assertEqualInt(1000, qual);
    assertEqualString(name, "trasz");

    assertEqualInt(ARCHIVE_OK, archive_entry_acl_next(ae,
        ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
        &type, &permset, &tag, &qual, &name));
    assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ACCESS, type);
    assertEqualInt(004, permset);
    assertEqualInt(ARCHIVE_ENTRY_ACL_MASK, tag);
    assertEqualInt(-1, qual);
    assertEqualString(name, NULL);

    assertEqualInt(ARCHIVE_EOF, archive_entry_acl_next(ae,
        ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
        &type, &permset, &tag, &qual, &name));

    /* Close the archive. */
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}

--- NEW FILE: test_compat_tar_hardlink.c ---
/*-
 * 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/lib/libarchive/test/test_compat_tar_hardlink.c,v 1.3 2008/08/11 01:19:36 kientzle Exp $");

/*
 * Background:  There are two written standards for the tar file format.
 * The first is the POSIX 1988 "ustar" format, the second is the 2001
 * "pax extended" format that builds on the "ustar" format by adding
 * support for generic additional attributes.  Buried in the details
 * is one frustrating incompatibility:  The 1988 standard says that
 * tar readers MUST ignore the size field on hardlink entries; the
 * 2001 standard says that tar readers MUST obey the size field on
 * hardlink entries.  libarchive tries to navigate this particular
 * minefield by using auto-detect logic to guess whether it should
 * or should not obey the size field.
 *
 * This test tries to probe the boundaries of such handling; the test
 * archives here were adapted from real archives created by real
 * tar implementations that are (as of early 2008) apparently still
 * in use.
 */

static void
test_compat_tar_hardlink_1(void)
{
    char name[] = "test_compat_tar_hardlink_1.tar";
    struct archive_entry *ae;
    struct archive *a;

    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    extract_reference_file(name);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240));

    /* Read first entry, which is a regular file. */
    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString("xmcd-3.3.2/docs_d/READMf",
        archive_entry_pathname(ae));
    assertEqualString(NULL, archive_entry_hardlink(ae));
    assertEqualInt(321, archive_entry_size(ae));
    assertEqualInt(1082575645, archive_entry_mtime(ae));
    assertEqualInt(1851, archive_entry_uid(ae));
    assertEqualInt(3, archive_entry_gid(ae));
    assertEqualInt(0100444, archive_entry_mode(ae));

    /* Read second entry, which is a hard link at the end of archive. */
    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString("xmcd-3.3.2/README",
        archive_entry_pathname(ae));
    assertEqualString(
        "xmcd-3.3.2/docs_d/READMf",
        archive_entry_hardlink(ae));
    assertEqualInt(0, archive_entry_size(ae));
    assertEqualInt(1082575645, archive_entry_mtime(ae));
    assertEqualInt(1851, archive_entry_uid(ae));
    assertEqualInt(3, archive_entry_gid(ae));
    assertEqualInt(0100444, archive_entry_mode(ae));

    /* Verify the end-of-archive. */
    /*
     * This failed in libarchive 2.4.12 because the tar reader
     * tried to obey the size field for the hard link and ended
     * up running past the end of the file.
     */
    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));

    /* Verify that the format detection worked. */
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_NONE);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR);

    assertEqualInt(ARCHIVE_OK, archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
#endif
}

DEFINE_TEST(test_compat_tar_hardlink)
{
    test_compat_tar_hardlink_1();
}



--- NEW FILE: test_read_format_gtar_sparse.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_gtar_sparse.c,v 1.11 2008/12/06 05:58:24 kientzle Exp $");


struct contents {
    off_t   o;
    size_t  s;
    const char *d;
};

struct contents archive_contents_sparse[] = {
    { 1000000, 1, "a" },
    { 2000000, 1, "a" },
    { 3145728, 0, NULL }
};

struct contents archive_contents_sparse2[] = {
    { 1000000, 1, "a" },
    { 2000000, 1, "a" },
    { 3000000, 1, "a" },
    { 4000000, 1, "a" },
    { 5000000, 1, "a" },
    { 6000000, 1, "a" },
    { 7000000, 1, "a" },
    { 8000000, 1, "a" },
    { 9000000, 1, "a" },
    { 10000000, 1, "a" },
    { 11000000, 1, "a" },
    { 12000000, 1, "a" },
    { 13000000, 1, "a" },
    { 14000000, 1, "a" },
    { 15000000, 1, "a" },
    { 16000000, 1, "a" },
    { 17000000, 1, "a" },
    { 18000000, 1, "a" },
    { 19000000, 1, "a" },
    { 20000000, 1, "a" },
    { 21000000, 1, "a" },
    { 22000000, 1, "a" },
    { 23000000, 1, "a" },
    { 24000000, 1, "a" },
    { 25000000, 1, "a" },
    { 26000000, 1, "a" },
    { 27000000, 1, "a" },
    { 28000000, 1, "a" },
    { 29000000, 1, "a" },
    { 30000000, 1, "a" },
    { 31000000, 1, "a" },
    { 32000000, 1, "a" },
    { 33000000, 1, "a" },
    { 34000000, 1, "a" },
    { 35000000, 1, "a" },
    { 36000000, 1, "a" },
    { 37000000, 1, "a" },
    { 38000000, 1, "a" },
    { 39000000, 1, "a" },
    { 40000000, 1, "a" },
    { 41000000, 1, "a" },
    { 42000000, 1, "a" },
    { 43000000, 1, "a" },
    { 44000000, 1, "a" },
    { 45000000, 1, "a" },
    { 46000000, 1, "a" },
    { 47000000, 1, "a" },
    { 48000000, 1, "a" },
    { 49000000, 1, "a" },
    { 50000000, 1, "a" },
    { 51000000, 1, "a" },
    { 52000000, 1, "a" },
    { 53000000, 1, "a" },
    { 54000000, 1, "a" },
    { 55000000, 1, "a" },
    { 56000000, 1, "a" },
    { 57000000, 1, "a" },
    { 58000000, 1, "a" },
    { 59000000, 1, "a" },
    { 60000000, 1, "a" },
    { 61000000, 1, "a" },
    { 62000000, 1, "a" },
    { 63000000, 1, "a" },
    { 64000000, 1, "a" },
    { 65000000, 1, "a" },
    { 66000000, 1, "a" },
    { 67000000, 1, "a" },
    { 68000000, 1, "a" },
    { 69000000, 1, "a" },
    { 70000000, 1, "a" },
    { 71000000, 1, "a" },
    { 72000000, 1, "a" },
    { 73000000, 1, "a" },
    { 74000000, 1, "a" },
    { 75000000, 1, "a" },
    { 76000000, 1, "a" },
    { 77000000, 1, "a" },
    { 78000000, 1, "a" },
    { 79000000, 1, "a" },
    { 80000000, 1, "a" },
    { 81000000, 1, "a" },
    { 82000000, 1, "a" },
    { 83000000, 1, "a" },
    { 84000000, 1, "a" },
    { 85000000, 1, "a" },
    { 86000000, 1, "a" },
    { 87000000, 1, "a" },
    { 88000000, 1, "a" },
    { 89000000, 1, "a" },
    { 90000000, 1, "a" },
    { 91000000, 1, "a" },
    { 92000000, 1, "a" },
    { 93000000, 1, "a" },
    { 94000000, 1, "a" },
    { 95000000, 1, "a" },
    { 96000000, 1, "a" },
    { 97000000, 1, "a" },
    { 98000000, 1, "a" },
    { 99000000, 1, "a" },
    { 99000001, 0, NULL }
};

struct contents archive_contents_nonsparse[] = {
    { 0, 1, "a" },
    { 1, 0, NULL }
};

/*
 * Describe an archive with three entries:
 *
 * File 1: named "sparse"
 *   * a length of 3145728 bytes (3MiB)
 *   * a single 'a' byte at offset 1000000
 *   * a single 'a' byte at offset 2000000
 * File 2: named "sparse2"
 *   * a single 'a' byte at offset 1,000,000, 2,000,000, ..., 99,000,000
 *   * length of 99,000,001
 * File 3: named 'non-sparse'
 *   * length of 1 byte
 *   * contains a single byte 'a'
 */

struct archive_contents {
    const char *filename;
    struct contents *contents;
} files[] = {
    { "sparse", archive_contents_sparse },
    { "sparse2", archive_contents_sparse2 },
    { "non-sparse", archive_contents_nonsparse },
    { NULL, NULL }
};

static void
verify_archive_file(const char *name, struct archive_contents *ac)
{
    struct archive_entry *ae;
    int err;
    /* data, size, offset of next expected block. */
    struct contents expect;
    /* data, size, offset of block read from archive. */
    struct contents actual;
    const void *p;
    struct archive *a;

    extract_reference_file(name);

    assert((a = archive_read_new()) != NULL);
    assert(0 == archive_read_support_compression_all(a));
    assert(0 == archive_read_support_format_tar(a));
    failure("Can't open %s", name);
    assert(0 == archive_read_open_filename(a, name, 3));

    while (ac->filename != NULL) {
        struct contents *cts = ac->contents;

        if (!assertEqualIntA(a, 0, archive_read_next_header(a, &ae))) {
            assert(0 == archive_read_finish(a));
            return;
        }
        failure("Name mismatch in archive %s", name);
        assertEqualString(ac->filename, archive_entry_pathname(ae));

        expect = *cts++;
        while (0 == (err = archive_read_data_block(a,
                 &p, &actual.s, &actual.o))) {
            actual.d = p;
            while (actual.s > 0) {
                char c = *actual.d;
                if(actual.o < expect.o) {
                    /*
                     * Any byte before the expected
                     * data must be NULL.
                     */
                    failure("%s: pad at offset %d "
                        "should be zero", name, actual.o);
                    assertEqualInt(c, 0);
                } else if (actual.o == expect.o) {
                    /*
                     * Data at matching offsets must match.
                     */
                    assertEqualInt(c, *expect.d);
                    expect.d++;
                    expect.o++;
                    expect.s--;
                    /* End of expected? step to next expected. */
                    if (expect.s <= 0)
                        expect = *cts++;
                } else {
                    /*
                     * We found data beyond that expected.
                     */
                    failure("%s: Unexpected trailing data",
                        name);
                    assert(actual.o <= expect.o);
                    archive_read_finish(a);
                    return;
                }
                actual.d++;
                actual.o++;
                actual.s--;
            }
        }
        failure("%s: should be end of entry", name);
        assertEqualIntA(a, err, ARCHIVE_EOF);
        failure("%s: Size returned at EOF must be zero", name);
        assertEqualInt((int)actual.s, 0);
#if ARCHIVE_VERSION_NUMBER < 1009000
        /* libarchive < 1.9 doesn't get this right */
        skipping("offset of final sparse chunk");
#else
        failure("%s: Offset of final empty chunk must be same as file size", name);
        assertEqualInt(actual.o, expect.o);
#endif
        /* Step to next file description. */
        ++ac;
    }

    err = archive_read_next_header(a, &ae);
    assertEqualIntA(a, ARCHIVE_EOF, err);

    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif
}


DEFINE_TEST(test_read_format_gtar_sparse)
{
    /* Two archives that use the "GNU tar sparse format". */
    verify_archive_file("test_read_format_gtar_sparse_1_13.tar", files);
    verify_archive_file("test_read_format_gtar_sparse_1_17.tar", files);

    /*
     * libarchive < 1.9 doesn't support the newer --posix sparse formats
     * from GNU tar 1.15 and later.
     */
#if ARCHIVE_VERSION_NUMBER < 1009000
    skipping("read support for GNUtar --posix sparse formats");
#else
    /*
     * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1
     */
    verify_archive_file(
        "test_read_format_gtar_sparse_1_17_posix00.tar",
        files);
    /*
     * An archive created by GNU tar 1.17 using --posix --sparse-format=0.1
     */
    verify_archive_file(
        "test_read_format_gtar_sparse_1_17_posix01.tar",
        files);
    /*
     * An archive created by GNU tar 1.17 using --posix --sparse-format=1.0
     */
    verify_archive_file(
        "test_read_format_gtar_sparse_1_17_posix10.tar",
        files);
    /*
     * The last test archive here is a little odd.  First, it's
     * uncompressed, because that exercises some of the block
     * reassembly code a little harder.  Second, it includes some
     * leading comments prior to the sparse block description.
     * GNU tar doesn't do this, but I think it should, so I want
     * to ensure that libarchive correctly ignores such comments.
     * Dump the file, looking for "#!gnu-sparse-format" starting
     * at byte 0x600.
     */
    verify_archive_file(
        "test_read_format_gtar_sparse_1_17_posix10_modified.tar",
        files);
#endif
}



--- NEW FILE: test_archive_api_feature.c ---
/*-
 * 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/lib/libarchive/test/test_archive_api_feature.c,v 1.5 2008/05/26 17:00:24 kientzle Exp $");

DEFINE_TEST(test_archive_api_feature)
{
    char buff[128];
    const char *p;

    /* This is the (hopefully) final versioning API. */
    assertEqualInt(ARCHIVE_VERSION_NUMBER, archive_version_number());
    sprintf(buff, "libarchive %d.%d.%d",
        archive_version_number() / 1000000,
        (archive_version_number() / 1000) % 1000,
        archive_version_number() % 1000);
    failure("Version string is: %s, computed is: %s",
        archive_version_string(), buff);
    assert(memcmp(buff, archive_version_string(), strlen(buff)) == 0);
    if (strlen(buff) < strlen(archive_version_string())) {
        p = archive_version_string() + strlen(buff);
        failure("Version string is: %s", archive_version_string());
        assert(*p == 'a' || *p == 'b' || *p == 'c' || *p == 'd');
        ++p;
        failure("Version string is: %s", archive_version_string());
        assert(*p == '\0');
    }

/* This is all scheduled to disappear in libarchive 3.0 */
#if ARCHIVE_VERSION_NUMBER < 3000000
    assertEqualInt(ARCHIVE_VERSION_STAMP, ARCHIVE_VERSION_NUMBER);
    assertEqualInt(ARCHIVE_API_FEATURE, archive_api_feature());
    assertEqualInt(ARCHIVE_API_VERSION, archive_api_version());
    /*
     * Even though ARCHIVE_VERSION_STAMP only appears in
     * archive.h after 1.9.0 and 2.2.3, the macro is synthesized
     * in test.h, so this test is always valid.
     */
    assertEqualInt(ARCHIVE_VERSION_STAMP / 1000, ARCHIVE_API_VERSION * 1000 + ARCHIVE_API_FEATURE);
    /*
     * The function, however, isn't always available.  It appeared
     * sometime in the middle of 2.2.3, but the synthesized value
     * never has a release version, so the following conditional
     * exactly determines whether the current library has the
     * function.
     */
#if ARCHIVE_VERSION_STAMP / 1000 == 1009 || ARCHIVE_VERSION_STAMP > 2002000
    assertEqualInt(ARCHIVE_VERSION_STAMP, archive_version_stamp());
#else
    skipping("archive_version_stamp()");
#endif
    assertEqualString(ARCHIVE_LIBRARY_VERSION, archive_version());
#endif
}

--- NEW FILE: test_entry.c ---
/*-
 * 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/lib/libarchive/test/test_entry.c,v 1.10 2008/09/30 04:13:21 kientzle Exp $");

#include <locale.h>

/*
 * Most of these tests are system-independent, though a few depend on
 * features of the local system.  Such tests are conditionalized on
 * the platform name.  On unsupported platforms, only the
 * system-independent features will be tested.
 *
 * No, I don't want to use config.h in the test files because I want
 * the tests to also serve as a check on the correctness of config.h.
 * A mis-configured library build should cause tests to fail.
 */

DEFINE_TEST(test_entry)
{
    char buff[128];
    wchar_t wbuff[128];
    struct stat st;
    struct archive_entry *e, *e2;
    const struct stat *pst;
    unsigned long set, clear; /* For fflag testing. */
    int type, permset, tag, qual; /* For ACL testing. */
    const char *name; /* For ACL testing. */
    const char *xname; /* For xattr tests. */
    const void *xval; /* For xattr tests. */
    size_t xsize; /* For xattr tests. */
    int c;
    wchar_t wc;
    long l;

    assert((e = archive_entry_new()) != NULL);

    /*
     * Verify that the AE_IF* defines match S_IF* defines
     * on this platform. See comments in archive_entry.h.
     */
#ifdef S_IFREG
    assertEqualInt(S_IFREG, AE_IFREG);
#endif
#ifdef S_IFLNK
    assertEqualInt(S_IFLNK, AE_IFLNK);
#endif
#ifdef S_IFSOCK
    assertEqualInt(S_IFSOCK, AE_IFSOCK);
#endif
#ifdef S_IFCHR
    assertEqualInt(S_IFCHR, AE_IFCHR);
#endif
#ifdef S_IFBLK
    assertEqualInt(S_IFBLK, AE_IFBLK);
#endif
#ifdef S_IFDIR
    assertEqualInt(S_IFDIR, AE_IFDIR);
#endif
#ifdef S_IFIFO
    assertEqualInt(S_IFIFO, AE_IFIFO);
#endif

    /*
     * Basic set/read tests for all fields.
     * We should be able to set any field and read
     * back the same value.
     *
     * For methods that "copy" a string, we should be able
     * to overwrite the original passed-in string without
     * changing the value in the entry.
     *
     * The following tests are ordered alphabetically by the
     * name of the field.
     */

    /* atime */
    archive_entry_set_atime(e, 13579, 24680);
    assertEqualInt(archive_entry_atime(e), 13579);
    assertEqualInt(archive_entry_atime_nsec(e), 24680);
    archive_entry_unset_atime(e);
    assertEqualInt(archive_entry_atime(e), 0);
    assertEqualInt(archive_entry_atime_nsec(e), 0);
    assert(!archive_entry_atime_is_set(e));

    /* birthtime */
    archive_entry_set_birthtime(e, 17579, 24990);
    assertEqualInt(archive_entry_birthtime(e), 17579);
    assertEqualInt(archive_entry_birthtime_nsec(e), 24990);
    archive_entry_unset_birthtime(e);
    assertEqualInt(archive_entry_birthtime(e), 0);
    assertEqualInt(archive_entry_birthtime_nsec(e), 0);
    assert(!archive_entry_birthtime_is_set(e));

    /* ctime */
    archive_entry_set_ctime(e, 13580, 24681);
    assertEqualInt(archive_entry_ctime(e), 13580);
    assertEqualInt(archive_entry_ctime_nsec(e), 24681);
    archive_entry_unset_ctime(e);
    assertEqualInt(archive_entry_ctime(e), 0);
    assertEqualInt(archive_entry_ctime_nsec(e), 0);
    assert(!archive_entry_ctime_is_set(e));

#if ARCHIVE_VERSION_NUMBER >= 1009000
    /* dev */
    archive_entry_set_dev(e, 235);
    assertEqualInt(archive_entry_dev(e), 235);
#else
    skipping("archive_entry_dev()");
#endif
    /* devmajor/devminor are tested specially below. */

#if ARCHIVE_VERSION_NUMBER >= 1009000
    /* filetype */
    archive_entry_set_filetype(e, AE_IFREG);
    assertEqualInt(archive_entry_filetype(e), AE_IFREG);
#else
    skipping("archive_entry_filetype()");
#endif

    /* fflags are tested specially below */

    /* gid */
    archive_entry_set_gid(e, 204);
    assertEqualInt(archive_entry_gid(e), 204);

    /* gname */
    archive_entry_set_gname(e, "group");
    assertEqualString(archive_entry_gname(e), "group");
    wcscpy(wbuff, L"wgroup");
    archive_entry_copy_gname_w(e, wbuff);
    assertEqualWString(archive_entry_gname_w(e), L"wgroup");
    memset(wbuff, 0, sizeof(wbuff));
    assertEqualWString(archive_entry_gname_w(e), L"wgroup");

    /* hardlink */
    archive_entry_set_hardlink(e, "hardlinkname");
    assertEqualString(archive_entry_hardlink(e), "hardlinkname");
    strcpy(buff, "hardlinkname2");
    archive_entry_copy_hardlink(e, buff);
    assertEqualString(archive_entry_hardlink(e), "hardlinkname2");
    memset(buff, 0, sizeof(buff));
    assertEqualString(archive_entry_hardlink(e), "hardlinkname2");
    archive_entry_copy_hardlink(e, NULL);
    assertEqualString(archive_entry_hardlink(e), NULL);
    assertEqualWString(archive_entry_hardlink_w(e), NULL);
    wcscpy(wbuff, L"whardlink");
    archive_entry_copy_hardlink_w(e, wbuff);
    assertEqualWString(archive_entry_hardlink_w(e), L"whardlink");
    memset(wbuff, 0, sizeof(wbuff));
    assertEqualWString(archive_entry_hardlink_w(e), L"whardlink");
    archive_entry_copy_hardlink_w(e, NULL);
    assertEqualString(archive_entry_hardlink(e), NULL);
    assertEqualWString(archive_entry_hardlink_w(e), NULL);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    /* ino */
    archive_entry_set_ino(e, 8593);
    assertEqualInt(archive_entry_ino(e), 8593);
#else
    skipping("archive_entry_ino()");
#endif

    /* link */
    archive_entry_set_hardlink(e, "hardlinkname");
    archive_entry_set_symlink(e, NULL);
    archive_entry_set_link(e, "link");
    assertEqualString(archive_entry_hardlink(e), "link");
    assertEqualString(archive_entry_symlink(e), NULL);
    archive_entry_copy_link(e, "link2");
    assertEqualString(archive_entry_hardlink(e), "link2");
    assertEqualString(archive_entry_symlink(e), NULL);
    archive_entry_copy_link_w(e, L"link3");
    assertEqualString(archive_entry_hardlink(e), "link3");
    assertEqualString(archive_entry_symlink(e), NULL);
    archive_entry_set_hardlink(e, NULL);
    archive_entry_set_symlink(e, "symlink");
    archive_entry_set_link(e, "link");
    assertEqualString(archive_entry_hardlink(e), NULL);
    assertEqualString(archive_entry_symlink(e), "link");
    archive_entry_copy_link(e, "link2");
    assertEqualString(archive_entry_hardlink(e), NULL);
    assertEqualString(archive_entry_symlink(e), "link2");
    archive_entry_copy_link_w(e, L"link3");
    assertEqualString(archive_entry_hardlink(e), NULL);
    assertEqualString(archive_entry_symlink(e), "link3");
    /* Arbitrarily override symlink if both hardlink and symlink set. */
    archive_entry_set_hardlink(e, "hardlink");
    archive_entry_set_symlink(e, "symlink");
    archive_entry_set_link(e, "link");
    assertEqualString(archive_entry_hardlink(e), "hardlink");
    assertEqualString(archive_entry_symlink(e), "link");

    /* mode */
    archive_entry_set_mode(e, 0123456);
    assertEqualInt(archive_entry_mode(e), 0123456);

    /* mtime */
    archive_entry_set_mtime(e, 13581, 24682);
    assertEqualInt(archive_entry_mtime(e), 13581);
    assertEqualInt(archive_entry_mtime_nsec(e), 24682);
    archive_entry_unset_mtime(e);
    assertEqualInt(archive_entry_mtime(e), 0);
    assertEqualInt(archive_entry_mtime_nsec(e), 0);
    assert(!archive_entry_mtime_is_set(e));

#if ARCHIVE_VERSION_NUMBER >= 1009000
    /* nlink */
    archive_entry_set_nlink(e, 736);
    assertEqualInt(archive_entry_nlink(e), 736);
#else
    skipping("archive_entry_nlink()");
#endif

    /* pathname */
    archive_entry_set_pathname(e, "path");
    assertEqualString(archive_entry_pathname(e), "path");
    archive_entry_set_pathname(e, "path");
    assertEqualString(archive_entry_pathname(e), "path");
    strcpy(buff, "path2");
    archive_entry_copy_pathname(e, buff);
    assertEqualString(archive_entry_pathname(e), "path2");
    memset(buff, 0, sizeof(buff));
    assertEqualString(archive_entry_pathname(e), "path2");
    wcscpy(wbuff, L"wpath");
    archive_entry_copy_pathname_w(e, wbuff);
    assertEqualWString(archive_entry_pathname_w(e), L"wpath");
    memset(wbuff, 0, sizeof(wbuff));
    assertEqualWString(archive_entry_pathname_w(e), L"wpath");

#if ARCHIVE_VERSION_NUMBER >= 1009000
    /* rdev */
    archive_entry_set_rdev(e, 532);
    assertEqualInt(archive_entry_rdev(e), 532);
#else
    skipping("archive_entry_rdev()");
#endif
    /* rdevmajor/rdevminor are tested specially below. */

    /* size */
    archive_entry_set_size(e, 987654321);
    assertEqualInt(archive_entry_size(e), 987654321);
    archive_entry_unset_size(e);
    assertEqualInt(archive_entry_size(e), 0);
    assert(!archive_entry_size_is_set(e));

    /* sourcepath */
    archive_entry_copy_sourcepath(e, "path1");
    assertEqualString(archive_entry_sourcepath(e), "path1");

    /* symlink */
    archive_entry_set_symlink(e, "symlinkname");
    assertEqualString(archive_entry_symlink(e), "symlinkname");
#if ARCHIVE_VERSION_NUMBER >= 1009000
    strcpy(buff, "symlinkname2");
    archive_entry_copy_symlink(e, buff);
    assertEqualString(archive_entry_symlink(e), "symlinkname2");
    memset(buff, 0, sizeof(buff));
    assertEqualString(archive_entry_symlink(e), "symlinkname2");
#endif
    archive_entry_copy_symlink_w(e, NULL);
    assertEqualWString(archive_entry_symlink_w(e), NULL);
    assertEqualString(archive_entry_symlink(e), NULL);
    archive_entry_copy_symlink_w(e, L"wsymlink");
    assertEqualWString(archive_entry_symlink_w(e), L"wsymlink");
    archive_entry_copy_symlink(e, NULL);
    assertEqualWString(archive_entry_symlink_w(e), NULL);
    assertEqualString(archive_entry_symlink(e), NULL);

    /* uid */
    archive_entry_set_uid(e, 83);
    assertEqualInt(archive_entry_uid(e), 83);

    /* uname */
    archive_entry_set_uname(e, "user");
    assertEqualString(archive_entry_uname(e), "user");
    wcscpy(wbuff, L"wuser");
    archive_entry_copy_gname_w(e, wbuff);
    assertEqualWString(archive_entry_gname_w(e), L"wuser");
    memset(wbuff, 0, sizeof(wbuff));
    assertEqualWString(archive_entry_gname_w(e), L"wuser");

    /* Test fflags interface. */
    archive_entry_set_fflags(e, 0x55, 0xAA);
    archive_entry_fflags(e, &set, &clear);
    failure("Testing set/get of fflags data.");
    assertEqualInt(set, 0x55);
    failure("Testing set/get of fflags data.");
    assertEqualInt(clear, 0xAA);
#ifdef __FreeBSD__
    /* Converting fflags bitmap to string is currently system-dependent. */
    /* TODO: Make this system-independent. */
    assertEqualString(archive_entry_fflags_text(e),
        "uappnd,nouchg,nodump,noopaque,uunlnk");
    /* Test archive_entry_copy_fflags_text_w() */
    archive_entry_copy_fflags_text_w(e, L" ,nouappnd, nouchg, dump,uunlnk");
    archive_entry_fflags(e, &set, &clear);
    assertEqualInt(16, set);
    assertEqualInt(7, clear);
    /* Test archive_entry_copy_fflags_text() */
    archive_entry_copy_fflags_text(e, " ,nouappnd, nouchg, dump,uunlnk");
    archive_entry_fflags(e, &set, &clear);
    assertEqualInt(16, set);
    assertEqualInt(7, clear);
#endif

    /* See test_acl_basic.c for tests of ACL set/get consistency. */

    /* Test xattrs set/get consistency. */
    archive_entry_xattr_add_entry(e, "xattr1", "xattrvalue1", 12);
    assertEqualInt(1, archive_entry_xattr_reset(e));
    assertEqualInt(0, archive_entry_xattr_next(e, &xname, &xval, &xsize));
    assertEqualString(xname, "xattr1");
    assertEqualString(xval, "xattrvalue1");
    assertEqualInt((int)xsize, 12);
    assertEqualInt(1, archive_entry_xattr_count(e));
    assertEqualInt(ARCHIVE_WARN,
        archive_entry_xattr_next(e, &xname, &xval, &xsize));
    assertEqualString(xname, NULL);
    assertEqualString(xval, NULL);
    assertEqualInt((int)xsize, 0);
    archive_entry_xattr_clear(e);
    assertEqualInt(0, archive_entry_xattr_reset(e));
    assertEqualInt(ARCHIVE_WARN,
        archive_entry_xattr_next(e, &xname, &xval, &xsize));
    assertEqualString(xname, NULL);
    assertEqualString(xval, NULL);
    assertEqualInt((int)xsize, 0);
    archive_entry_xattr_add_entry(e, "xattr1", "xattrvalue1", 12);
    assertEqualInt(1, archive_entry_xattr_reset(e));
    archive_entry_xattr_add_entry(e, "xattr2", "xattrvalue2", 12);
    assertEqualInt(2, archive_entry_xattr_reset(e));
    assertEqualInt(0, archive_entry_xattr_next(e, &xname, &xval, &xsize));
    assertEqualInt(0, archive_entry_xattr_next(e, &xname, &xval, &xsize));
    assertEqualInt(ARCHIVE_WARN,
        archive_entry_xattr_next(e, &xname, &xval, &xsize));
    assertEqualString(xname, NULL);
    assertEqualString(xval, NULL);
    assertEqualInt((int)xsize, 0);


    /*
     * Test clone() implementation.
     */

    /* Set values in 'e' */
    archive_entry_clear(e);
    archive_entry_set_atime(e, 13579, 24680);
    archive_entry_set_birthtime(e, 13779, 24990);
    archive_entry_set_ctime(e, 13580, 24681);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    archive_entry_set_dev(e, 235);
#endif
    archive_entry_set_fflags(e, 0x55, 0xAA);
    archive_entry_set_gid(e, 204);
    archive_entry_set_gname(e, "group");
    archive_entry_set_hardlink(e, "hardlinkname");
#if ARCHIVE_VERSION_NUMBER >= 1009000
    archive_entry_set_ino(e, 8593);
#endif
    archive_entry_set_mode(e, 0123456);
    archive_entry_set_mtime(e, 13581, 24682);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    archive_entry_set_nlink(e, 736);
#endif
    archive_entry_set_pathname(e, "path");
#if ARCHIVE_VERSION_NUMBER >= 1009000
    archive_entry_set_rdev(e, 532);
#endif
    archive_entry_set_size(e, 987654321);
    archive_entry_copy_sourcepath(e, "source");
    archive_entry_set_symlink(e, "symlinkname");
    archive_entry_set_uid(e, 83);
    archive_entry_set_uname(e, "user");
    /* Add an ACL entry. */
    archive_entry_acl_add_entry(e, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
        ARCHIVE_ENTRY_ACL_READ, ARCHIVE_ENTRY_ACL_USER, 77, "user77");
    /* Add an extended attribute. */
    archive_entry_xattr_add_entry(e, "xattr1", "xattrvalue", 11);

    /* Make a clone. */
    e2 = archive_entry_clone(e);

    /* Clone should have same contents. */
    assertEqualInt(archive_entry_atime(e2), 13579);
    assertEqualInt(archive_entry_atime_nsec(e2), 24680);
    assertEqualInt(archive_entry_birthtime(e2), 13779);
    assertEqualInt(archive_entry_birthtime_nsec(e2), 24990);
    assertEqualInt(archive_entry_ctime(e2), 13580);
    assertEqualInt(archive_entry_ctime_nsec(e2), 24681);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    assertEqualInt(archive_entry_dev(e2), 235);
#endif
    archive_entry_fflags(e, &set, &clear);
    assertEqualInt(clear, 0xAA);
    assertEqualInt(set, 0x55);
    assertEqualInt(archive_entry_gid(e2), 204);
    assertEqualString(archive_entry_gname(e2), "group");
    assertEqualString(archive_entry_hardlink(e2), "hardlinkname");
#if ARCHIVE_VERSION_NUMBER >= 1009000
    assertEqualInt(archive_entry_ino(e2), 8593);
#endif
    assertEqualInt(archive_entry_mode(e2), 0123456);
    assertEqualInt(archive_entry_mtime(e2), 13581);
    assertEqualInt(archive_entry_mtime_nsec(e2), 24682);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    assertEqualInt(archive_entry_nlink(e2), 736);
#endif
    assertEqualString(archive_entry_pathname(e2), "path");
#if ARCHIVE_VERSION_NUMBER >= 1009000
    assertEqualInt(archive_entry_rdev(e2), 532);
#endif
    assertEqualInt(archive_entry_size(e2), 987654321);
    assertEqualString(archive_entry_sourcepath(e2), "source");
    assertEqualString(archive_entry_symlink(e2), "symlinkname");
    assertEqualInt(archive_entry_uid(e2), 83);
    assertEqualString(archive_entry_uname(e2), "user");
#if ARCHIVE_VERSION_NUMBER < 1009000
    skipping("ACL preserved by archive_entry_clone()");
#else
    /* Verify ACL was copied. */
    assertEqualInt(4, c = archive_entry_acl_reset(e2,
               ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
    /* First three are standard permission bits. */
    assertEqualInt(0, archive_entry_acl_next(e2,
               ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
               &type, &permset, &tag, &qual, &name));
    assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
    assertEqualInt(permset, 4);
    assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER_OBJ);
    assertEqualInt(qual, -1);
    assertEqualString(name, NULL);
    assertEqualInt(0, archive_entry_acl_next(e2,
               ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
               &type, &permset, &tag, &qual, &name));
    assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
    assertEqualInt(permset, 5);
    assertEqualInt(tag, ARCHIVE_ENTRY_ACL_GROUP_OBJ);
    assertEqualInt(qual, -1);
    assertEqualString(name, NULL);
    assertEqualInt(0, archive_entry_acl_next(e2,
               ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
               &type, &permset, &tag, &qual, &name));
    assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
    assertEqualInt(permset, 6);
    assertEqualInt(tag, ARCHIVE_ENTRY_ACL_OTHER);
    assertEqualInt(qual, -1);
    assertEqualString(name, NULL);
    /* Fourth is custom one. */
    assertEqualInt(0, archive_entry_acl_next(e2,
               ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
               &type, &permset, &tag, &qual, &name));
    assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
    assertEqualInt(permset, ARCHIVE_ENTRY_ACL_READ);
    assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER);
    assertEqualInt(qual, 77);
    assertEqualString(name, "user77");
#endif
#if ARCHIVE_VERSION_NUMBER < 1009000
    skipping("xattr data preserved by archive_entry_clone");
#else
    /* Verify xattr was copied. */
    assertEqualInt(1, c = archive_entry_xattr_reset(e2));
    assertEqualInt(0, archive_entry_xattr_next(e2, &xname, &xval, &xsize));
    assertEqualString(xname, "xattr1");
    assertEqualString(xval, "xattrvalue");
    assertEqualInt((int)xsize, 11);
    assertEqualInt(ARCHIVE_WARN,
        archive_entry_xattr_next(e2, &xname, &xval, &xsize));
    assertEqualString(xname, NULL);
    assertEqualString(xval, NULL);
    assertEqualInt((int)xsize, 0);
#endif

    /* Change the original */
    archive_entry_set_atime(e, 13580, 24690);
    archive_entry_set_birthtime(e, 13980, 24999);
    archive_entry_set_ctime(e, 13590, 24691);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    archive_entry_set_dev(e, 245);
#endif
    archive_entry_set_fflags(e, 0x85, 0xDA);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    archive_entry_set_filetype(e, AE_IFLNK);
#endif
    archive_entry_set_gid(e, 214);
    archive_entry_set_gname(e, "grouper");
    archive_entry_set_hardlink(e, "hardlinkpath");
#if ARCHIVE_VERSION_NUMBER >= 1009000
    archive_entry_set_ino(e, 8763);
#endif
    archive_entry_set_mode(e, 0123654);
    archive_entry_set_mtime(e, 18351, 28642);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    archive_entry_set_nlink(e, 73);
#endif
    archive_entry_set_pathname(e, "pathest");
#if ARCHIVE_VERSION_NUMBER >= 1009000
    archive_entry_set_rdev(e, 132);
#endif
    archive_entry_set_size(e, 987456321);
    archive_entry_copy_sourcepath(e, "source2");
    archive_entry_set_symlink(e, "symlinkpath");
    archive_entry_set_uid(e, 93);
    archive_entry_set_uname(e, "username");
    archive_entry_acl_clear(e);
    archive_entry_xattr_clear(e);

    /* Clone should still have same contents. */
    assertEqualInt(archive_entry_atime(e2), 13579);
    assertEqualInt(archive_entry_atime_nsec(e2), 24680);
    assertEqualInt(archive_entry_birthtime(e2), 13779);
    assertEqualInt(archive_entry_birthtime_nsec(e2), 24990);
    assertEqualInt(archive_entry_ctime(e2), 13580);
    assertEqualInt(archive_entry_ctime_nsec(e2), 24681);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    assertEqualInt(archive_entry_dev(e2), 235);
#endif
    archive_entry_fflags(e2, &set, &clear);
    assertEqualInt(clear, 0xAA);
    assertEqualInt(set, 0x55);
    assertEqualInt(archive_entry_gid(e2), 204);
    assertEqualString(archive_entry_gname(e2), "group");
    assertEqualString(archive_entry_hardlink(e2), "hardlinkname");
#if ARCHIVE_VERSION_NUMBER >= 1009000
    assertEqualInt(archive_entry_ino(e2), 8593);
#endif
    assertEqualInt(archive_entry_mode(e2), 0123456);
    assertEqualInt(archive_entry_mtime(e2), 13581);
    assertEqualInt(archive_entry_mtime_nsec(e2), 24682);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    assertEqualInt(archive_entry_nlink(e2), 736);
#endif
    assertEqualString(archive_entry_pathname(e2), "path");
#if ARCHIVE_VERSION_NUMBER >= 1009000
    assertEqualInt(archive_entry_rdev(e2), 532);
#endif
    assertEqualInt(archive_entry_size(e2), 987654321);
    assertEqualString(archive_entry_sourcepath(e2), "source");
    assertEqualString(archive_entry_symlink(e2), "symlinkname");
    assertEqualInt(archive_entry_uid(e2), 83);
    assertEqualString(archive_entry_uname(e2), "user");
#if ARCHIVE_VERSION_NUMBER < 1009000
    skipping("ACL held by clone of archive_entry");
#else
    /* Verify ACL was unchanged. */
    assertEqualInt(4, c = archive_entry_acl_reset(e2,
               ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
    /* First three are standard permission bits. */
    assertEqualInt(0, archive_entry_acl_next(e2,
               ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
               &type, &permset, &tag, &qual, &name));
    assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
    assertEqualInt(permset, 4);
    assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER_OBJ);
    assertEqualInt(qual, -1);
    assertEqualString(name, NULL);
    assertEqualInt(0, archive_entry_acl_next(e2,
               ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
               &type, &permset, &tag, &qual, &name));
    assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
    assertEqualInt(permset, 5);
    assertEqualInt(tag, ARCHIVE_ENTRY_ACL_GROUP_OBJ);
    assertEqualInt(qual, -1);
    assertEqualString(name, NULL);
    assertEqualInt(0, archive_entry_acl_next(e2,
               ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
               &type, &permset, &tag, &qual, &name));
    assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
    assertEqualInt(permset, 6);
    assertEqualInt(tag, ARCHIVE_ENTRY_ACL_OTHER);
    assertEqualInt(qual, -1);
    assertEqualString(name, NULL);
    /* Fourth is custom one. */
    assertEqualInt(0, archive_entry_acl_next(e2,
               ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
               &type, &permset, &tag, &qual, &name));
    assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
    assertEqualInt(permset, ARCHIVE_ENTRY_ACL_READ);
    assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER);
    assertEqualInt(qual, 77);
    assertEqualString(name, "user77");
    assertEqualInt(1, archive_entry_acl_next(e2,
               ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
               &type, &permset, &tag, &qual, &name));
    assertEqualInt(type, 0);
    assertEqualInt(permset, 0);
    assertEqualInt(tag, 0);
    assertEqualInt(qual, -1);
    assertEqualString(name, NULL);
#endif
#if ARCHIVE_VERSION_NUMBER < 1009000
    skipping("xattr preserved in archive_entry copy");
#else
    /* Verify xattr was unchanged. */
    assertEqualInt(1, archive_entry_xattr_reset(e2));
#endif

    /* Release clone. */
    archive_entry_free(e2);

    /*
     * Test clear() implementation.
     */
    archive_entry_clear(e);
    assertEqualInt(archive_entry_atime(e), 0);
    assertEqualInt(archive_entry_atime_nsec(e), 0);
    assertEqualInt(archive_entry_birthtime(e), 0);
    assertEqualInt(archive_entry_birthtime_nsec(e), 0);
    assertEqualInt(archive_entry_ctime(e), 0);
    assertEqualInt(archive_entry_ctime_nsec(e), 0);
    assertEqualInt(archive_entry_dev(e), 0);
    archive_entry_fflags(e, &set, &clear);
    assertEqualInt(clear, 0);
    assertEqualInt(set, 0);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    assertEqualInt(archive_entry_filetype(e), 0);
#endif
    assertEqualInt(archive_entry_gid(e), 0);
    assertEqualString(archive_entry_gname(e), NULL);
    assertEqualString(archive_entry_hardlink(e), NULL);
    assertEqualInt(archive_entry_ino(e), 0);
    assertEqualInt(archive_entry_mode(e), 0);
    assertEqualInt(archive_entry_mtime(e), 0);
    assertEqualInt(archive_entry_mtime_nsec(e), 0);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    assertEqualInt(archive_entry_nlink(e), 0);
#endif
    assertEqualString(archive_entry_pathname(e), NULL);
    assertEqualInt(archive_entry_rdev(e), 0);
    assertEqualInt(archive_entry_size(e), 0);
    assertEqualString(archive_entry_symlink(e), NULL);
    assertEqualInt(archive_entry_uid(e), 0);
    assertEqualString(archive_entry_uname(e), NULL);
    /* ACLs should be cleared. */
    assertEqualInt(archive_entry_acl_count(e, ARCHIVE_ENTRY_ACL_TYPE_ACCESS), 0);
    assertEqualInt(archive_entry_acl_count(e, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT), 0);
    /* Extended attributes should be cleared. */
    assertEqualInt(archive_entry_xattr_count(e), 0);

    /*
     * Test archive_entry_copy_stat().
     */
    memset(&st, 0, sizeof(st));
    /* Set all of the standard 'struct stat' fields. */
    st.st_atime = 456789;
    st.st_ctime = 345678;
    st.st_dev = 123;
    st.st_gid = 34;
    st.st_ino = 234;
    st.st_mode = 077777;
    st.st_mtime = 234567;
    st.st_nlink = 345;
    st.st_size = 123456789;
    st.st_uid = 23;
#ifdef __FreeBSD__
    /* On FreeBSD, high-res timestamp data should come through. */
    st.st_atimespec.tv_nsec = 6543210;
    st.st_ctimespec.tv_nsec = 5432109;
    st.st_mtimespec.tv_nsec = 3210987;
    st.st_birthtimespec.tv_nsec = 7459386;
#endif
    /* Copy them into the entry. */
    archive_entry_copy_stat(e, &st);
    /* Read each one back separately and compare. */
    assertEqualInt(archive_entry_atime(e), 456789);
    assertEqualInt(archive_entry_ctime(e), 345678);
    assertEqualInt(archive_entry_dev(e), 123);
    assertEqualInt(archive_entry_gid(e), 34);
    assertEqualInt(archive_entry_ino(e), 234);
    assertEqualInt(archive_entry_mode(e), 077777);
    assertEqualInt(archive_entry_mtime(e), 234567);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    assertEqualInt(archive_entry_nlink(e), 345);
#endif
    assertEqualInt(archive_entry_size(e), 123456789);
    assertEqualInt(archive_entry_uid(e), 23);
#if __FreeBSD__
    /* On FreeBSD, high-res timestamp data should come through. */
    assertEqualInt(archive_entry_atime_nsec(e), 6543210);
    assertEqualInt(archive_entry_ctime_nsec(e), 5432109);
    assertEqualInt(archive_entry_mtime_nsec(e), 3210987);
    assertEqualInt(archive_entry_birthtime_nsec(e), 7459386);
#endif

    /*
     * Test archive_entry_stat().
     */
    /* First, clear out any existing stat data. */
    memset(&st, 0, sizeof(st));
    archive_entry_copy_stat(e, &st);
    /* Set a bunch of fields individually. */
    archive_entry_set_atime(e, 456789, 321);
    archive_entry_set_ctime(e, 345678, 432);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    archive_entry_set_dev(e, 123);
#endif
    archive_entry_set_gid(e, 34);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    archive_entry_set_ino(e, 234);
#endif
    archive_entry_set_mode(e, 012345);
    archive_entry_set_mode(e, 012345);
    archive_entry_set_mtime(e, 234567, 543);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    archive_entry_set_nlink(e, 345);
#endif
    archive_entry_set_size(e, 123456789);
    archive_entry_set_uid(e, 23);
    /* Retrieve a stat structure. */
    assert((pst = archive_entry_stat(e)) != NULL);
    /* Check that the values match. */
    assertEqualInt(pst->st_atime, 456789);
    assertEqualInt(pst->st_ctime, 345678);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    assertEqualInt(pst->st_dev, 123);
#endif
    assertEqualInt(pst->st_gid, 34);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    assertEqualInt(pst->st_ino, 234);
#endif
    assertEqualInt(pst->st_mode, 012345);
    assertEqualInt(pst->st_mtime, 234567);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    assertEqualInt(pst->st_nlink, 345);
#endif
    assertEqualInt(pst->st_size, 123456789);
    assertEqualInt(pst->st_uid, 23);
#ifdef __FreeBSD__
    /* On FreeBSD, high-res timestamp data should come through. */
    assertEqualInt(pst->st_atimespec.tv_nsec, 321);
    assertEqualInt(pst->st_ctimespec.tv_nsec, 432);
    assertEqualInt(pst->st_mtimespec.tv_nsec, 543);
#endif

    /* Changing any one value should update struct stat. */
    archive_entry_set_atime(e, 456788, 0);
    assert((pst = archive_entry_stat(e)) != NULL);
    assertEqualInt(pst->st_atime, 456788);
    archive_entry_set_ctime(e, 345677, 431);
    assert((pst = archive_entry_stat(e)) != NULL);
    assertEqualInt(pst->st_ctime, 345677);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    archive_entry_set_dev(e, 122);
    assert((pst = archive_entry_stat(e)) != NULL);
    assertEqualInt(pst->st_dev, 122);
#endif
    archive_entry_set_gid(e, 33);
    assert((pst = archive_entry_stat(e)) != NULL);
    assertEqualInt(pst->st_gid, 33);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    archive_entry_set_ino(e, 233);
    assert((pst = archive_entry_stat(e)) != NULL);
    assertEqualInt(pst->st_ino, 233);
#endif
    archive_entry_set_mode(e, 012344);
    assert((pst = archive_entry_stat(e)) != NULL);
    assertEqualInt(pst->st_mode, 012344);
    archive_entry_set_mtime(e, 234566, 542);
    assert((pst = archive_entry_stat(e)) != NULL);
    assertEqualInt(pst->st_mtime, 234566);
#if ARCHIVE_VERSION_NUMBER >= 1009000
    archive_entry_set_nlink(e, 344);
    assert((pst = archive_entry_stat(e)) != NULL);
    assertEqualInt(pst->st_nlink, 344);
#endif
    archive_entry_set_size(e, 123456788);
    assert((pst = archive_entry_stat(e)) != NULL);
    assertEqualInt(pst->st_size, 123456788);
    archive_entry_set_uid(e, 22);
    assert((pst = archive_entry_stat(e)) != NULL);
    assertEqualInt(pst->st_uid, 22);
    /* We don't need to check high-res fields here. */

    /*
     * Test dev/major/minor interfaces.  Setting 'dev' or 'rdev'
     * should change the corresponding major/minor values, and
     * vice versa.
     *
     * The test here is system-specific because it assumes that
     * makedev(), major(), and minor() are defined in sys/stat.h.
     * I'm not too worried about it, though, because the code is
     * simple.  If it works on FreeBSD, it's unlikely to be broken
     * anywhere else.  Note: The functionality is present on every
     * platform even if these tests only run some places;
     * libarchive's more extensive configuration logic should find
     * the necessary definitions on every platform.
     */
#if __FreeBSD__
#if ARCHIVE_VERSION_NUMBER >= 1009000
    archive_entry_set_dev(e, 0x12345678);
    assertEqualInt(archive_entry_devmajor(e), major(0x12345678));
    assertEqualInt(archive_entry_devminor(e), minor(0x12345678));
    assertEqualInt(archive_entry_dev(e), 0x12345678);
    archive_entry_set_devmajor(e, 0xfe);
    archive_entry_set_devminor(e, 0xdcba98);
    assertEqualInt(archive_entry_devmajor(e), 0xfe);
    assertEqualInt(archive_entry_devminor(e), 0xdcba98);
    assertEqualInt(archive_entry_dev(e), makedev(0xfe, 0xdcba98));
    archive_entry_set_rdev(e, 0x12345678);
    assertEqualInt(archive_entry_rdevmajor(e), major(0x12345678));
    assertEqualInt(archive_entry_rdevminor(e), minor(0x12345678));
    assertEqualInt(archive_entry_rdev(e), 0x12345678);
    archive_entry_set_rdevmajor(e, 0xfe);
    archive_entry_set_rdevminor(e, 0xdcba98);
    assertEqualInt(archive_entry_rdevmajor(e), 0xfe);
    assertEqualInt(archive_entry_rdevminor(e), 0xdcba98);
    assertEqualInt(archive_entry_rdev(e), makedev(0xfe, 0xdcba98));
#endif
#endif

    /*
     * Exercise the character-conversion logic, if we can.
     */
    if (NULL == setlocale(LC_ALL, LOCALE_DE)) {
        skipping("Can't exercise charset-conversion logic without"
            " a suitable locale.");
    } else {
        /* A filename that cannot be converted to wide characters. */
        archive_entry_copy_pathname(e, "abc\314\214mno\374xyz");
        failure("Converting invalid chars to Unicode should fail.");
        assert(NULL == archive_entry_pathname_w(e));
        //failure("Converting invalid chars to UTF-8 should fail.");
        //assert(NULL == archive_entry_pathname_utf8(e));

        /* A group name that cannot be converted. */
        archive_entry_copy_gname(e, "abc\314\214mno\374xyz");
        failure("Converting invalid chars to Unicode should fail.");
        assert(NULL == archive_entry_gname_w(e));

        /* A user name that cannot be converted. */
        archive_entry_copy_uname(e, "abc\314\214mno\374xyz");
        failure("Converting invalid chars to Unicode should fail.");
        assert(NULL == archive_entry_uname_w(e));

        /* A hardlink target that cannot be converted. */
        archive_entry_copy_hardlink(e, "abc\314\214mno\374xyz");
        failure("Converting invalid chars to Unicode should fail.");
        assert(NULL == archive_entry_hardlink_w(e));

        /* A symlink target that cannot be converted. */
        archive_entry_copy_symlink(e, "abc\314\214mno\374xyz");
        failure("Converting invalid chars to Unicode should fail.");
        assert(NULL == archive_entry_symlink_w(e));
    }

    l = 0x12345678L;
    wc = (wchar_t)l; /* Wide character too big for UTF-8. */
    if (NULL == setlocale(LC_ALL, "C") || (long)wc != l) {
        skipping("Testing charset conversion failure requires 32-bit wchar_t and support for \"C\" locale.");
    } else {
        /*
         * Build the string L"xxx\U12345678yyy\u5678zzz" without
         * using C99 \u#### syntax, which isn't uniformly
         * supported.  (GCC 3.4.6, for instance, defaults to
         * "c89 plus GNU extensions.")
         */
        wcscpy(wbuff, L"xxxAyyyBzzz");
        wbuff[3] = (wchar_t)0x12345678;
        wbuff[7] = (wchar_t)0x5678;
        /* A wide filename that cannot be converted to narrow. */
        archive_entry_copy_pathname_w(e, wbuff);
        failure("Converting wide characters from Unicode should fail.");
        assertEqualString(NULL, archive_entry_pathname(e));
    }

    /* Release the experimental entry. */
    archive_entry_free(e);
}

--- NEW FILE: test_read_format_gtar_sparse_1_17.tar.uu ---
begin 644 test_read_format_gtar_sparse_1_17.tar
M<W!A<G-E````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#`P,#`V-#0`,#`P,3<U,``P,#`Q-S4P`#`P,#`P,#`R,#`P
M`#$P-S,S,3`Q,30P`#`Q-S<Q,P`@4P``````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<B`@`'1I;0``
M````````````````````````````````````=&EM````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````````````````P,#`P,S8T,3`P,``P,#`P,#`P
M,3`P,``P,#`P-S4P,C`P,``P,#`P,#`P,3`P,``P,#`Q-#`P,#`P,``P,#`P
M,#`P,#`P,```````````````````````````````````,#`P,30P,#`P,#``
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````80``````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
[...1330 lines suppressed...]
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
/````````````````````
`
end

--- NEW FILE: test_read_format_tz.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_tz.c,v 1.2 2008/09/01 05:38:33 kientzle Exp $");

static unsigned char archive[] = {
31,157,144,'.',0,8,28,'H',176,160,193,131,8,19,'*','\\',200,176,'!','B',24,
16,'o',212,168,1,2,0,196,24,18,'a','T',188,152,'q','#',196,143,' ','5',198,
128,'1','c',6,13,24,'4','0',206,176,1,2,198,200,26,'6','b',0,0,'Q',195,161,
205,155,'8','s',234,4,'P','g',14,157,'0','r',',',194,160,147,166,205,206,
132,'D',141,30,'=',24,'R',163,'P',144,21,151,'J',157,'J',181,170,213,171,
'X',179,'j',221,202,181,171,215,175,'`',195,138,29,'K',182,172,217,179,'h',
211,170,']',203,182,173,219,183,'g',1};

DEFINE_TEST(test_read_format_tz)
{
    struct archive_entry *ae;
    struct archive *a;
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_open_memory(a, archive, sizeof(archive)));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    failure("archive_compression_name(a)=\"%s\"",
        archive_compression_name(a));
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_COMPRESS);
    failure("archive_format_name(a)=\"%s\"", archive_format_name(a));
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
#endif
}



--- NEW FILE: test_read_format_raw.data.uu ---
begin 644 test_read_format_raw.data
$9F]O"@``
`
end

--- NEW FILE: test_write_disk_symlink.c ---
/*-
 * 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$");

/*
 * Exercise symlink recreation.
 */
DEFINE_TEST(test_write_disk_symlink)
{
    static const char data[]="abcdefghijklmnopqrstuvwxyz";
    struct archive *ad;
    struct archive_entry *ae;
    int r;

    if (!canSymlink()) {
        skipping("Symlinks not supported");
        return;
    }

    /* Write entries to disk. */
    assert((ad = archive_write_disk_new()) != NULL);

    /*
     * First, create a regular file then a symlink to that file.
     */

    /* Regular file: link1a */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "link1a");
    archive_entry_set_mode(ae, AE_IFREG | 0755);
    archive_entry_set_size(ae, sizeof(data));
    assertEqualIntA(ad, 0, archive_write_header(ad, ae));
    assertEqualInt(sizeof(data),
        archive_write_data(ad, data, sizeof(data)));
    assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
    archive_entry_free(ae);

    /* Symbolic Link: link1b -> link1a */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "link1b");
    archive_entry_set_mode(ae, AE_IFLNK | 0642);
    archive_entry_set_size(ae, 0);
    archive_entry_copy_symlink(ae, "link1a");
    assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
    if (r >= ARCHIVE_WARN)
        assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
    archive_entry_free(ae);

    /*
     * We should be able to do this in the other order as well,
     * of course.
     */

    /* Symbolic link: link2b -> link2a */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "link2b");
    archive_entry_set_mode(ae, AE_IFLNK | 0642);
    archive_entry_unset_size(ae);
    archive_entry_copy_symlink(ae, "link2a");
    assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
    if (r >= ARCHIVE_WARN) {
        assertEqualInt(ARCHIVE_WARN,
            archive_write_data(ad, data, sizeof(data)));
        assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
    }
    archive_entry_free(ae);

    /* File: link2a */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "link2a");
    archive_entry_set_mode(ae, AE_IFREG | 0755);
    archive_entry_set_size(ae, sizeof(data));
    assertEqualIntA(ad, 0, archive_write_header(ad, ae));
    assertEqualInt(sizeof(data),
        archive_write_data(ad, data, sizeof(data)));
    assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
    archive_entry_free(ae);

    assertEqualInt(ARCHIVE_OK, archive_write_finish(ad));

    /* Test the entries on disk. */

    /* Test #1 */
    assertIsReg("link1a", -1);
    assertFileSize("link1a", sizeof(data));
    assertFileNLinks("link1a", 1);
    assertIsSymlink("link1b", "link1a");

    /* Test #2: Should produce identical results to test #1 */
    assertIsReg("link2a", -1);
    assertFileSize("link2a", sizeof(data));
    assertFileNLinks("link2a", 1);
    assertIsSymlink("link2b", "link2a");
}

--- NEW FILE: test_compat_zip_1.zip.uu ---
$FreeBSD: src/lib/libarchive/test/test_compat_zip_1.zip.uu,v 1.2 2008/06/30 15:49:12 des Exp $
begin 644 test_compat_zip_1.zip
M4$L#!!0`"``(``B$@S<````````````````4````345402U)3D8O34%.249%
M4U0N34;S3<S+3$LM+M$-2RTJSLS/LU(PU#/@Y7+,0Q)Q+$A,SDA5`(H!)<U!
MTLY%J8DEJ2FZ3I56"BF9B4DY^;J&>J9Z!O$&YKI)!H8*&L&E>0J^F<E%^<65
MQ26IN<4*GGG)>IJ\7+Q<`%!+!PAHTY\490```'$```!02P,$%``(``@`"(2#
M-P````````````````D```!T;7`N8VQA<W,[]6_7/@8&!D,&+G8&#G8&3BX&
M1 at 86'@8V!E9&!F8-S3!&!C:;S+S,$CN at L'-^2BHC at T!68EFB?DYB7KJ^?U)6
M:G()4&%);@&#(@,34"\(,`(AT``@R0[D"8+Y#`RL6ML9F#>"%3```%!+!P at +
M(*8V:````'8```!02P$"%``4``@`"``(A(,W:-.?%&4```!Q````%```````
M````````````````345402U)3D8O34%.249%4U0N34902P$"%``4``@`"``(
MA(,W"R"F-F@```!V````"0````````````````"G````=&UP+F-L87-S4$L%
J!@`````"``(`>0```$8!```7`%!R;T=U87)D+"!V97)S:6]N(#0N,"XQ
`
end

--- NEW FILE: test_read_format_isorr_bz2.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_isorr_bz2.c,v 1.5 2008/09/01 05:38:33 kientzle Exp $");

/*
PLEASE use old cdrtools; mkisofs verion is 2.01.
This version mkisofs made wrong "SL" System Use Entry of RRIP.

Execute the following command to rebuild the data for this program:
   tail -n +32 test_read_format_isorr_bz2.c | /bin/sh

rm -rf /tmp/iso
mkdir /tmp/iso
mkdir /tmp/iso/dir
echo "hello" >/tmp/iso/file
dd if=/dev/zero count=1 bs=12345678 >>/tmp/iso/file
ln /tmp/iso/file /tmp/iso/hardlink
(cd /tmp/iso; ln -s file symlink)
(cd /tmp/iso; ln -s /tmp/ symlink2)
(cd /tmp/iso; ln -s /tmp/../ symlink3)
(cd /tmp/iso; ln -s .././../tmp/ symlink4)
(cd /tmp/iso; ln -s .///file symlink5)
(cd /tmp/iso; ln -s /tmp//../ symlink6)
TZ=utc touch -afhm -t 197001020000.01 /tmp/iso /tmp/iso/file /tmp/iso/dir
TZ=utc touch -afhm -t 197001030000.02 /tmp/iso/symlink /tmp/iso/symlink5
F=test_read_format_isorr_bz2.iso.bz2
mkhybrid -R -uid 1 -gid 2 /tmp/iso | bzip2 > $F
uuencode $F $F > $F.uu
exit 1
 */

DEFINE_TEST(test_read_format_isorr_bz2)
{
    const char *refname = "test_read_format_isorr_bz2.iso.bz2";
    struct archive_entry *ae;
    struct archive *a;
    const void *p;
    size_t size;
    off_t offset;
    int i;
    int r;

    extract_reference_file(refname);
    assert((a = archive_read_new()) != NULL);
    r = archive_read_support_compression_bzip2(a);
    if (r == ARCHIVE_WARN) {
        skipping("bzip2 reading not fully supported on this platform");
        assertEqualInt(0, archive_read_finish(a));
        return;
    }
    assertEqualInt(0, r);
    assertEqualInt(0, archive_read_support_format_all(a));
    assertEqualInt(ARCHIVE_OK,
        archive_read_open_filename(a, refname, 10240));

    /* Retrieve each of the 8 files on the ISO image and
     * verify that each one is what we expect. */
    for (i = 0; i < 10; ++i) {
        assertEqualInt(0, archive_read_next_header(a, &ae));

        if (strcmp(".", archive_entry_pathname(ae)) == 0) {
            /* '.' root directory. */
            assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
            assertEqualInt(2048, archive_entry_size(ae));
            /* Now, we read timestamp recorded by RRIP "TF". */ 
            assertEqualInt(86401, archive_entry_mtime(ae));
            assertEqualInt(0, archive_entry_mtime_nsec(ae));
            /* Now, we read links recorded by RRIP "PX". */ 
            assertEqualInt(3, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualIntA(a, ARCHIVE_EOF,
                archive_read_data_block(a, &p, &size, &offset));
            assertEqualInt((int)size, 0);
        } else if (strcmp("dir", archive_entry_pathname(ae)) == 0) {
            /* A directory. */
            assertEqualString("dir", archive_entry_pathname(ae));
            assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
            assertEqualInt(2048, archive_entry_size(ae));
            assertEqualInt(86401, archive_entry_mtime(ae));
            assertEqualInt(86401, archive_entry_atime(ae));
            assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("file", archive_entry_pathname(ae)) == 0) {
            /* A regular file. */
            assertEqualString("file", archive_entry_pathname(ae));
            assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
            assertEqualInt(12345684, archive_entry_size(ae));
            assertEqualInt(0,
                archive_read_data_block(a, &p, &size, &offset));
            assertEqualInt(0, offset);
            assertEqualMem(p, "hello\n", 6);
            assertEqualInt(86401, archive_entry_mtime(ae));
            assertEqualInt(86401, archive_entry_atime(ae));
            assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("hardlink", archive_entry_pathname(ae)) == 0) {
            /* A hardlink to the regular file. */
            /* Note: If "hardlink" gets returned before "file",
             * then "hardlink" will get returned as a regular file
             * and "file" will get returned as the hardlink.
             * This test should tolerate that, since it's a
             * perfectly permissible thing for libarchive to do. */
            assertEqualString("hardlink", archive_entry_pathname(ae));
            assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
            assertEqualString("file", archive_entry_hardlink(ae));
            assertEqualInt(0, archive_entry_size_is_set(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(86401, archive_entry_mtime(ae));
            assertEqualInt(86401, archive_entry_atime(ae));
            assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("symlink", archive_entry_pathname(ae)) == 0) {
            /* A symlink to the regular file. */
            assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
            assertEqualString("file", archive_entry_symlink(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(172802, archive_entry_mtime(ae));
            assertEqualInt(172802, archive_entry_atime(ae));
            assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("symlink2", archive_entry_pathname(ae)) == 0) {
            /* A symlink to /tmp (an absolute path) */
            assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
            assertEqualString("/tmp", archive_entry_symlink(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("symlink3", archive_entry_pathname(ae)) == 0) {
            /* A symlink to /tmp/.. (with a ".." component) */
            assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
            assertEqualString("/tmp/..", archive_entry_symlink(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("symlink4", archive_entry_pathname(ae)) == 0) {
            /* A symlink to a path with ".." and "." components */
            assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
            assertEqualString(".././../tmp",
                archive_entry_symlink(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("symlink5", archive_entry_pathname(ae)) == 0) {
            /* A symlink to the regular file with "/" components. */
            assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
            assertEqualString(".///file", archive_entry_symlink(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(172802, archive_entry_mtime(ae));
            assertEqualInt(172802, archive_entry_atime(ae));
            assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("symlink6", archive_entry_pathname(ae)) == 0) {
            /* A symlink to /tmp//..
             * (with "/" and ".." components) */
            assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
            assertEqualString("/tmp//..", archive_entry_symlink(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else {
            failure("Saw a file that shouldn't have been there");
            assertEqualString(archive_entry_pathname(ae), "");
        }
    }

    /* End of archive. */
    assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae));

    /* Verify archive format. */
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_BZIP2);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ISO9660_ROCKRIDGE);

    /* Close the archive. */
    assertEqualInt(0, archive_read_close(a));
    assertEqualInt(0, archive_read_finish(a));
}



--- NEW FILE: test_open_fd.c ---
/*-
 * 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$");

#if defined(_WIN32) && !defined(__CYGWIN__)
#define open _open
#define lseek _lseek
#define close _close
#endif

DEFINE_TEST(test_open_fd)
{
    char buff[64];
    struct archive_entry *ae;
    struct archive *a;
    int fd;

    fd = open("test.tar", O_RDWR | O_CREAT | O_BINARY, 0777);
    assert(fd >= 0);
    if (fd < 0)
        return;

    /* Write an archive through this fd. */
    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_none(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_write_open_fd(a, fd));

    /*
     * Write a file to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_mtime(ae, 1, 0);
    archive_entry_copy_pathname(ae, "file");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    archive_entry_set_size(ae, 8);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
    archive_entry_free(ae);
    assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9));

    /*
     * Write a second file to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file2");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    archive_entry_set_size(ae, 819200);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
    archive_entry_free(ae);

    /* Close out the archive. */
    assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    /*
     * Now, read the data back.
     */
    assert(lseek(fd, 0, SEEK_SET) == 0);
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_open_fd(a, fd, 512));

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualInt(1, archive_entry_mtime(ae));
    assertEqualInt(0, archive_entry_mtime_nsec(ae));
    assertEqualInt(0, archive_entry_atime(ae));
    assertEqualInt(0, archive_entry_ctime(ae));
    assertEqualString("file", archive_entry_pathname(ae));
    assert((S_IFREG | 0755) == archive_entry_mode(ae));
    assertEqualInt(8, archive_entry_size(ae));
    assertEqualIntA(a, 8, archive_read_data(a, buff, 10));
    assertEqualMem(buff, "12345678", 8);

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString("file2", archive_entry_pathname(ae));
    assert((S_IFREG | 0755) == archive_entry_mode(ae));
    assertEqualInt(819200, archive_entry_size(ae));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a));

    /* Verify the end of the archive. */
    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
    close(fd);


    /*
     * Verify some of the error handling.
     */
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    /* FD 100 shouldn't be open. */
    assertEqualIntA(a, ARCHIVE_FATAL,
        archive_read_open_fd(a, 100, 512));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}

--- NEW FILE: test_compat_gtar_1.tar.uu ---
begin 644 test_compat_gtar_1.tar
M+B\N+T!,;VYG3&EN:P``````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````"`@("`@,"``("`@("`P(``@("`@(#`@`"`@("`@("`@,S$Q
M("`@("`@("`@("`P("`Q,#<P,0`@3```````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<B`@`')O;W0`
M````````````````````````````````````=VAE96P`````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````Q,C,T-38W.#DP,3(S-#4V-S at Y,#$R,S0U-C<X
M.3`Q,C,T-38W.#DP,3(S-#4V-S at Y,#$R,S0U-C<X.3`Q,C,T-38W.#DP,3(S
M-#4V-S at Y,#$R,S0U-C<X.3`Q,C,T-38W.#DP,3(S-#4V-S at Y,#$R,S0U-C<X
M.3`Q,C,T-38W.#DP,3(S-#4V-S at Y,#$R,S0U-C<X.3`Q,C,T-38W.#DP,3(S
M-#4V-S at Y,#$R,S0U-C<X.3`Q,C,T-38W.#DP,3(S-#4V-S at Y,```````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````#$R,S0U-C<X.3`Q
M,C,T-38W.#DP,3(S-#4V-S at Y,#$R,S0U-C<X.3`Q,C,T-38W.#DP,3(S-#4V
M-S at Y,#$R,S0U-C<X.3`Q,C,T-38W.#DP,3(S-#4V-S at Y,#$R,S0U-C<X.0`Q
M,#`V-#0@`"`@,3<U,"``("`Q-S4P(``@("`@("`@("`@,"`Q,#<R-C<P,#$W
M,R`@,C$P,C``(#``````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````=7-T87(@(`!T:6T`````````````````
M`````````````````````'1I;0``````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````+B\N+T!,;VYG3&EN:P``````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````"`@("`@,"``("`@("`P(``@("`@(#`@`"`@("`@
M("`@,S$Q("`@("`@("`@("`P("`Q,#<P,``@2P``````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````````````!U<W1A<B`@
M`')O;W0`````````````````````````````````````=VAE96P`````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````````````Q,C,T-38W.#DP,3(S-#4V-S at Y,#$R
M,S0U-C<X.3`Q,C,T-38W.#DP,3(S-#4V-S at Y,#$R,S0U-C<X.3`Q,C,T-38W
M.#DP,3(S-#4V-S at Y,#$R,S0U-C<X.3`Q,C,T-38W.#DP,3(S-#4V-S at Y,#$R
M,S0U-C<X.3`Q,C,T-38W.#DP,3(S-#4V-S at Y,#$R,S0U-C<X.3`Q,C,T-38W
M.#DP,3(S-#4V-S at Y,#$R,S0U-C<X.3`Q,C,T-38W.#DP,3(S-#4V-S at Y,```
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````"XO+B]`
M3&]N9TQI;FL`````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````@("`@(#`@`"`@("`@,"``("`@("`P(``@("`@("`@(#,Q,2`@("`@
M("`@("`@,"`@,3`W,#$`($P`````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````=7-T87(@(`!R;V]T````````
M`````````````````````````````'=H965L````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````86)C9&5F9VAI:F%B8V1E9F=H:6IA8F-D969G:&EJ86)C
M9&5F9VAI:F%B8V1E9F=H:6IA8F-D969G:&EJ86)C9&5F9VAI:F%B8V1E9F=H
M:6IA8F-D969G:&EJ86)C9&5F9VAI:F%B8V1E9F=H:6IA8F-D969G:&EJ86)C
M9&5F9VAI:F%B8V1E9F=H:6IA8F-D969G:&EJ86)C9&5F9VAI:F%B8V1E9F=H
M:6IA8F-D969G:&EJ86)C9&5F9VAI:F%B8V1E9F=H:6H`````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````!A8F-D969G:&EJ86)C9&5F
M9VAI:F%B8V1E9F=H:6IA8F-D969G:&EJ86)C9&5F9VAI:F%B8V1E9F=H:6IA
M8F-D969G:&EJ86)C9&5F9VAI:F%B8V1E9F=H:6IA8F-D969G:&D`,3(P-S4U
M(``@(#$W-3`@`"`@,3<U,"``("`@("`@("`@(#`@,3`W,C8W,#`R-#,@(#0T
M-3(Q`"`R,3(S-#4V-S at Y,#$R,S0U-C<X.3`Q,C,T-38W.#DP,3(S-#4V-S at Y
M,#$R,S0U-C<X.3`Q,C,T-38W.#DP,3(S-#4V-S at Y,#$R,S0U-C<X.3`Q,C,T
M-38W.#DP,3(S-#4V-S at Y`'5S=&%R("``=&EM````````````````````````
M``````````````!T:6T`````````````````````````````````````````
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````````````````````````````````````````````````````````````
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````````````````````````````````````````````````````````````
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````````````````````````````````````````````````````````````
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````````````````````````````````````````````````````````````
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````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
9````````````````````````````````````
`
end

--- NEW FILE: test_write_open_memory.c ---
/*-
 * 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/lib/libarchive/test/test_write_open_memory.c,v 1.4 2008/09/01 05:38:33 kientzle Exp $");

/* Try to force archive_write_open_memory.c to write past the end of an array. */
static unsigned char buff[16384];

DEFINE_TEST(test_write_open_memory)
{
    unsigned int i;
    struct archive *a;
    struct archive_entry *ae;
    const char *name="/tmp/test";

    /* Create a simple archive_entry. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_pathname(ae, name);
    archive_entry_set_mode(ae, S_IFREG);
    assertEqualString(archive_entry_pathname(ae), name);

    /* Try writing with different buffer sizes. */
    /* Make sure that we get failure on too-small buffers, success on
     * large enough ones. */
    for (i = 100; i < 1600; i++) {
        size_t s;
        size_t blocksize = 94;
        assert((a = archive_write_new()) != NULL);
        assertA(0 == archive_write_set_format_ustar(a));
        assertA(0 == archive_write_set_bytes_in_last_block(a, 1));
        assertA(0 == archive_write_set_bytes_per_block(a, (int)blocksize));
        buff[i] = 0xAE;
        assertA(0 == archive_write_open_memory(a, buff, i, &s));
        /* If buffer is smaller than a tar header, this should fail. */
        if (i < (511/blocksize)*blocksize)
            assertA(ARCHIVE_FATAL == archive_write_header(a,ae));
        else
            assertA(0 == archive_write_header(a, ae));
        /* If buffer is smaller than a tar header plus 1024 byte
         * end-of-archive marker, then this should fail. */
        if (i < 1536)
            assertA(ARCHIVE_FATAL == archive_write_close(a));
        else
            assertA(0 == archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
        archive_write_finish(a);
#else
        assert(0 == archive_write_finish(a));
#endif
        assert(buff[i] == 0xAE);
        assert(s <= i);
    }
    archive_entry_free(ae);
}

--- NEW FILE: test_read_format_txz.c ---
/*-
 * Copyright (c) 2009 Michihiro NAKAJIMA
 * 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 unsigned char archive[] = {
253, 55,122, 88, 90,  0,  0,  4,230,214,180, 70,  2,  0, 33,  1,
 22,  0,  0,  0,116, 47,229,163,224,  5,255,  0, 73, 93,  0, 23,
  0, 51, 80, 24,164,204,238, 45, 77, 28,191, 13,144,  8, 10, 70,
  5,173,215, 47,132,237,145,162, 96,  6,131,168,152,  8,135,161,
189, 73,110,132, 27,195, 52,109,203, 22, 17,168,211, 18,181, 76,
 93,120, 88,154,155,244,141,193,206,170,224, 80,137,134, 67,  1,
  9,123,121,188,247, 28,139,  0,  0,  0,  0,  0,112,184, 17,  5,
103, 16,  8, 73,  0,  1,101,128, 12,  0,  0,  0, 30, 69, 92, 96,
177,196,103,251,  2,  0,  0,  0,  0,  4, 89, 90
};

DEFINE_TEST(test_read_format_txz)
{
    struct archive_entry *ae;
    struct archive *a;
    int r;

    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    r = archive_read_support_compression_xz(a);
    if (r == ARCHIVE_WARN) {
        skipping("xz reading not fully supported on this platform");
        assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
        return;
    }
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_open_memory(a, archive, sizeof(archive)));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_XZ);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}

--- NEW FILE: test_read_format_isojoliet_rr.iso.bz2.uu ---
begin 644 test_read_format_isojoliet_rr.iso.bz2
M0EIH.3%!62936>6EH6P``/1_____Q_?_9__\/__?8:__GF8DJD`!)$`00>``
M`(```LD(T`1^`B!(VM*0#1$T&HQ3R2:'J-I-/0&TDT`9-&-)DQ&:`]1DTTC3
MU&C]$&@C"&&B:$,J>TI at 1J>GJGI`R#0R:!B:,F"!B:&C3)@)D:&)@3)D'```
M``````````````````#@`````````````````````D2$($&5/9%/34;*>GJA
MIDVIFH](-&TGI#T@:`TT;:2-/4/4V4/2;1-'I+`43=>#%["-XX:D%L%8K`LT
M-%+E!I!YQY_+%Q'C\AJ4-.YA!<G5BTT2:&QC8A5#$+TFDC(PUI08?R@`7>/G
M(`!+PL$D@#5JA+%AM"PXLM`E6T-@)"2-$$TH&P0T"38FT(;S(<`0-"0)(LL@
M*VD&J"3L8D*!B4Z4BDH&1*8*HTX;Y_%O%)D;^G*H*01KZDLL2798ECD0A(0V
M(-MB1GOZ:I[$X^LBZN'P;/<NE"I#=G[V!HG?8P;8TD1+(-)`2=Q<U]>J8^L"
MA7A9<J37IX!.+WJC>[.K!<Q6+<B&8IE$(IO]FN'Q6>&_*:=4M&.]L^3@[[D4
M]$ED_&Q)A=TY6LXW(#$A-,AL9<M7V<_7%26VX+4M!-3MI<SX^^6GA[Q),#CT
M8$D(2.3D[/66V%X].L@^'<D"-V=)+M7)Y0R=((V.YN]6]54":@#/$E)9C+H#
M,M at E4^)P?WN`=XW6*T>,J`O at KP6@2D"3(328TAC`\37E4HK3A44(Z(#R`Y,F
M'@@%A&"V6=L%0$M(YO0!=BVM0M$"+8)]W:Z=Z[O`HF\DXIDY8$@FF,'LPH&,
M8,3!H9;B+"$`@!C/!@4GK;!*)1%D^=!%-$JS%RQY/):".-=."&LZ\E$;_/I,
ML&1J3;_:NA56-&T=P^RTM4<;1%X0+P`&-\Q_Y5,3P1E$(!,(A5D*&Q,S<=EN
MD07S"!(.:"GH:I&0VR,5>=+&:N/1,9?KMG*Z^*]<O$@,C.8)GM&!98LQ*:L&
MA<8U??1%Z at I;C)4I>GL."Z9\90N.\EF7)2%QI69%$&YD0?*"89$@0VDZ2>B+
M&"0=="KJ7!SJ.RZB)$1:@O($D*-`46,N*!/1.OPX[Z`R$&E?`'0`EJQ"!CM4
M#<-MZDN2,<0:05&^J\0M6-=B(]1R5P=<1BS7S+$:0`XL(S)0%VUGL&-T`M&4
MC6NZ%DBZR,WQ6LPPSH&OUJKNCG3KITT$S(A4(VA!,`L+=+?)"]FA0%L$%*0Z
M=@ZYPBFV0NM&XGDJ<*-E*T;R8+(R,,F1!R_TP at 1;I`*+ZRJ>!.R0,J-*])LA
MXBO-KCS8Y[*2P-7&;_._;R!*BOBN`8,Y-,MWHE6C/"9)&K8P.[(-O=4$E=(;
MV$50*9358;*&"/D4+);CFM`KR/4QC3MQ6!PX,P?-1BVH-!B@=66:""ET8H&R
MU5'YE@&"K!9?9)4Z$&AOG!=F'Z#TVE^I]AB at G74;16:A!%LE!MXX`^3L7#O@
MSZ.E5:&6QBNAVBK-S;57A9[(+XCORVN2`RBZ7C]YES@&0B=O6E)A_V6<S4.$
MTLJLJ'>=?=-<)+2A0/@PYT^F4)RZYM^5TF$^3G=)%$5/RPJQL20A(RT?*OS8
-NHO_%W)%.%"0Y:6A;```
`
end

--- NEW FILE: test_write_disk.c ---
/*-
 * 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/lib/libarchive/test/test_write_disk.c,v 1.15 2008/09/30 04:02:36 kientzle Exp $");

#if ARCHIVE_VERSION_NUMBER >= 1009000

#define UMASK 022

static void create(struct archive_entry *ae, const char *msg)
{
    struct archive *ad;
    struct stat st;

    /* Write the entry to disk. */
    assert((ad = archive_write_disk_new()) != NULL);
    failure("%s", msg);
    assertEqualIntA(ad, 0, archive_write_header(ad, ae));
    assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(ad);
#else
    assertEqualInt(0, archive_write_finish(ad));
#endif
    /* Test the entries on disk. */
    assert(0 == stat(archive_entry_pathname(ae), &st));
    failure("st.st_mode=%o archive_entry_mode(ae)=%o",
        st.st_mode, archive_entry_mode(ae));
    /* When verifying a dir, ignore the S_ISGID bit, as some systems set
     * that automatically. */
#if !defined(_WIN32) || defined(__CYGWIN__)
    if (archive_entry_filetype(ae) == AE_IFDIR)
        st.st_mode &= ~S_ISGID;
    assertEqualInt(st.st_mode, archive_entry_mode(ae) & ~UMASK);
#endif
}

static void create_reg_file(struct archive_entry *ae, const char *msg)
{
    static const char data[]="abcdefghijklmnopqrstuvwxyz";
    struct archive *ad;

    /* Write the entry to disk. */
    assert((ad = archive_write_disk_new()) != NULL);
        archive_write_disk_set_options(ad, ARCHIVE_EXTRACT_TIME);
    failure("%s", msg);
    /*
     * A touchy API design issue: archive_write_data() does (as of
     * 2.4.12) enforce the entry size as a limit on the data
     * written to the file.  This was not enforced prior to
     * 2.4.12.  The change was prompted by the refined
     * hardlink-restore semantics introduced at that time.  In
     * short, libarchive needs to know whether a "hardlink entry"
     * is going to overwrite the contents so that it can know
     * whether or not to open the file for writing.  This implies
     * that there is a fundamental semantic difference between an
     * entry with a zero size and one with a non-zero size in the
     * case of hardlinks and treating the hardlink case
     * differently from the regular file case is just asking for
     * trouble.  So, a zero size must always mean that no data
     * will be accepted, which is consistent with the file size in
     * the entry being a maximum size.
     */
    archive_entry_set_size(ae, sizeof(data));
    archive_entry_set_mtime(ae, 123456789, 0);
    assertEqualIntA(ad, 0, archive_write_header(ad, ae));
    assertEqualInt(sizeof(data), archive_write_data(ad, data, sizeof(data)));
    assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(ad);
#else
    assertEqualInt(0, archive_write_finish(ad));
#endif
    /* Test the entries on disk. */
    assertIsReg(archive_entry_pathname(ae), archive_entry_mode(ae) & 0777);
    assertFileSize(archive_entry_pathname(ae), sizeof(data));
    /* test_write_disk_times has more detailed tests of this area. */
    assertFileMtime(archive_entry_pathname(ae), 123456789, 0);
        failure("No atime given, so atime should get set to current time");
    assertFileAtimeRecent(archive_entry_pathname(ae));
}

static void create_reg_file2(struct archive_entry *ae, const char *msg)
{
    const int datasize = 100000;
    char *data;
    struct archive *ad;
    int i;

    data = malloc(datasize);
    for (i = 0; i < datasize; i++)
        data[i] = (char)(i % 256);

    /* Write the entry to disk. */
    assert((ad = archive_write_disk_new()) != NULL);
    failure("%s", msg);
    /*
     * See above for an explanation why this next call
     * is necessary.
     */
    archive_entry_set_size(ae, datasize);
    assertEqualIntA(ad, 0, archive_write_header(ad, ae));
    for (i = 0; i < datasize - 999; i += 1000) {
        assertEqualIntA(ad, ARCHIVE_OK,
            archive_write_data_block(ad, data + i, 1000, i));
    }
    assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
    assertEqualInt(0, archive_write_finish(ad));

    /* Test the entries on disk. */
    assertIsReg(archive_entry_pathname(ae), archive_entry_mode(ae) & 0777);
    assertFileSize(archive_entry_pathname(ae), i);
    assertFileContents(data, datasize, archive_entry_pathname(ae));
    free(data);
}

static void create_reg_file3(struct archive_entry *ae, const char *msg)
{
    static const char data[]="abcdefghijklmnopqrstuvwxyz";
    struct archive *ad;
    struct stat st;

    /* Write the entry to disk. */
    assert((ad = archive_write_disk_new()) != NULL);
    failure("%s", msg);
    /* Set the size smaller than the data and verify the truncation. */
    archive_entry_set_size(ae, 5);
    assertEqualIntA(ad, 0, archive_write_header(ad, ae));
    assertEqualInt(5, archive_write_data(ad, data, sizeof(data)));
    assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(ad);
#else
    assertEqualInt(0, archive_write_finish(ad));
#endif
    /* Test the entry on disk. */
    assert(0 == stat(archive_entry_pathname(ae), &st));
    failure("st.st_mode=%o archive_entry_mode(ae)=%o",
        st.st_mode, archive_entry_mode(ae));
#if !defined(_WIN32) || defined(__CYGWIN__)
    assertEqualInt(st.st_mode, (archive_entry_mode(ae) & ~UMASK));
#endif
    assertEqualInt(st.st_size, 5);
}


static void create_reg_file4(struct archive_entry *ae, const char *msg)
{
    static const char data[]="abcdefghijklmnopqrstuvwxyz";
    struct archive *ad;
    struct stat st;

    /* Write the entry to disk. */
    assert((ad = archive_write_disk_new()) != NULL);
    /* Leave the size unset.  The data should not be truncated. */
    assertEqualIntA(ad, 0, archive_write_header(ad, ae));
    assertEqualInt(ARCHIVE_OK,
        archive_write_data_block(ad, data, sizeof(data), 0));
    assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(ad);
#else
    assertEqualInt(0, archive_write_finish(ad));
#endif
    /* Test the entry on disk. */
    assert(0 == stat(archive_entry_pathname(ae), &st));
    failure("st.st_mode=%o archive_entry_mode(ae)=%o",
        st.st_mode, archive_entry_mode(ae));
#if !defined(_WIN32) || defined(__CYGWIN__)
    assertEqualInt(st.st_mode, (archive_entry_mode(ae) & ~UMASK));
#endif
    failure(msg);
    assertEqualInt(st.st_size, sizeof(data));
}

#if defined(_WIN32) && !defined(__CYGWIN__)
static void create_reg_file_win(struct archive_entry *ae, const char *msg)
{
    static const char data[]="abcdefghijklmnopqrstuvwxyz";
    struct archive *ad;
    struct stat st;
    char *p, *fname;
    size_t l;

    /* Write the entry to disk. */
    assert((ad = archive_write_disk_new()) != NULL);
        archive_write_disk_set_options(ad, ARCHIVE_EXTRACT_TIME);
    failure("%s", msg);
    archive_entry_set_size(ae, sizeof(data));
    archive_entry_set_mtime(ae, 123456789, 0);
    assertEqualIntA(ad, 0, archive_write_header(ad, ae));
    assertEqualInt(sizeof(data), archive_write_data(ad, data, sizeof(data)));
    assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(ad);
#else
    assertEqualInt(0, archive_write_finish(ad));
#endif
    /* Test the entries on disk. */
    l = strlen(archive_entry_pathname(ae));
    fname = malloc(l + 1);
    assert(NULL != fname);
    strcpy(fname, archive_entry_pathname(ae));
    /* Replace unusable characters in Windows to '_' */
    for (p = fname; *p != '\0'; p++)
        if (*p == ':' || *p == '*' || *p == '?' ||
            *p == '"' || *p == '<' || *p == '>' || *p == '|')
            *p = '_';
    assert(0 == stat(fname, &st));
    failure("st.st_mode=%o archive_entry_mode(ae)=%o",
        st.st_mode, archive_entry_mode(ae));
    assertEqualInt(st.st_size, sizeof(data));
}
#endif /* _WIN32 && !__CYGWIN__ */
#endif

DEFINE_TEST(test_write_disk)
{
#if ARCHIVE_VERSION_NUMBER < 1009000
    skipping("archive_write_disk interface");
#else
    struct archive_entry *ae;

    /* Force the umask to something predictable. */
    assertUmask(UMASK);

    /* A regular file. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    create_reg_file(ae, "Test creating a regular file");
    archive_entry_free(ae);

    /* Another regular file. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file2");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    create_reg_file2(ae, "Test creating another regular file");
    archive_entry_free(ae);

    /* A regular file with a size restriction */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file3");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    create_reg_file3(ae, "Regular file with size restriction");
    archive_entry_free(ae);

    /* A regular file with an unspecified size */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file3");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    create_reg_file4(ae, "Regular file with unspecified size");
    archive_entry_free(ae);

    /* A regular file over an existing file */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file");
    archive_entry_set_mode(ae, S_IFREG | 0724);
    create(ae, "Test creating a file over an existing file.");
    archive_entry_free(ae);

    /* A directory. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "dir");
    archive_entry_set_mode(ae, S_IFDIR | 0555);
    create(ae, "Test creating a regular dir.");
    archive_entry_free(ae);

    /* A directory over an existing file. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file");
    archive_entry_set_mode(ae, S_IFDIR | 0742);
    create(ae, "Test creating a dir over an existing file.");
    archive_entry_free(ae);

    /* A file over an existing dir. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file");
    archive_entry_set_mode(ae, S_IFREG | 0744);
    create(ae, "Test creating a file over an existing dir.");
    archive_entry_free(ae);

#if defined(_WIN32) && !defined(__CYGWIN__)
    /* A file with unusable characters in its file name. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "f:i*l?e\"f<i>l|e");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    create_reg_file_win(ae, "Test creating a regular file"
        " with unusable characters in its file name");
    archive_entry_free(ae);

    /* A file with unusable characters in its directory name. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "d:i*r?e\"c<t>o|ry/file1");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    create_reg_file_win(ae, "Test creating a regular file"
        " with unusable characters in its file name");
    archive_entry_free(ae);
#endif /* _WIN32 && !__CYGWIN__ */
#endif
}

--- NEW FILE: test_read_disk_entry_from_file.c ---
/*-
 * 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$");

static const char *
gname_lookup(void *d, gid_t g)
{
    (void)d; /* UNUSED */
    (void)g; /* UNUSED */
    return ("FOOGROUP");
}

static const char *
uname_lookup(void *d, uid_t u)
{
    (void)d; /* UNUSED */
    (void)u; /* UNUSED */
    return ("FOO");
}

DEFINE_TEST(test_read_disk_entry_from_file)
{
    struct archive *a;
    struct archive_entry *entry;
    FILE *f;

    assert((a = archive_read_disk_new()) != NULL);

    assertEqualInt(ARCHIVE_OK, archive_read_disk_set_uname_lookup(a,
               NULL, &uname_lookup, NULL));
    assertEqualInt(ARCHIVE_OK, archive_read_disk_set_gname_lookup(a,
               NULL, &gname_lookup, NULL));
    assertEqualString(archive_read_disk_uname(a, 0), "FOO");
    assertEqualString(archive_read_disk_gname(a, 0), "FOOGROUP");

    /* Create a file on disk. */
    f = fopen("foo", "wb");
    assert(f != NULL);
    assertEqualInt(4, fwrite("1234", 1, 4, f));
    fclose(f);

    /* Use archive_read_disk_entry_from_file to get information about it. */
    entry = archive_entry_new();
    assert(entry != NULL);
    archive_entry_copy_pathname(entry, "foo");
    assertEqualInt(ARCHIVE_OK,
        archive_read_disk_entry_from_file(a, entry, -1, NULL));

    /* Verify the information we got back. */
    assertEqualString(archive_entry_uname(entry), "FOO");
    assertEqualString(archive_entry_gname(entry), "FOOGROUP");
    assertEqualInt(archive_entry_size(entry), 4);

    /* Destroy the archive. */
    archive_entry_free(entry);
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}

--- NEW FILE: test_write_disk_sparse.c ---
/*-
 * 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$");

/*
 * Write a file using archive_write_data call, read the file
 * back and verify the contents.  The data written includes large
 * blocks of nulls, so it should exercise the sparsification logic
 * if ARCHIVE_EXTRACT_SPARSE is enabled.
 */
static void
verify_write_data(struct archive *a, int sparse)
{
    static const char data[]="abcdefghijklmnopqrstuvwxyz";
    struct stat st;
    struct archive_entry *ae;
    size_t buff_size = 64 * 1024;
    char *buff, *p;
    const char *msg = sparse ? "sparse" : "non-sparse";
    FILE *f;

    buff = malloc(buff_size);
    assert(buff != NULL);

    ae = archive_entry_new();
    assert(ae != NULL);
    archive_entry_set_size(ae, 8 * buff_size);
    archive_entry_set_pathname(ae, "test_write_data");
    archive_entry_set_mode(ae, AE_IFREG | 0755);
    assertEqualIntA(a, 0, archive_write_header(a, ae));

    /* Use archive_write_data() to write three relatively sparse blocks. */

    /* First has non-null data at beginning. */
    memset(buff, 0, buff_size);
    memcpy(buff, data, sizeof(data));
    failure("%s", msg);
    assertEqualInt(buff_size, archive_write_data(a, buff, buff_size));

    /* Second has non-null data in the middle. */
    memset(buff, 0, buff_size);
    memcpy(buff + buff_size / 2 - 3, data, sizeof(data));
    failure("%s", msg);
    assertEqualInt(buff_size, archive_write_data(a, buff, buff_size));

    /* Third has non-null data at the end. */
    memset(buff, 0, buff_size);
    memcpy(buff + buff_size - sizeof(data), data, sizeof(data));
    failure("%s", msg);
    assertEqualInt(buff_size, archive_write_data(a, buff, buff_size));

    failure("%s", msg);
    assertEqualIntA(a, 0, archive_write_finish_entry(a));

    /* Test the entry on disk. */
    assert(0 == stat(archive_entry_pathname(ae), &st));
        assertEqualInt(st.st_size, 8 * buff_size);
    f = fopen(archive_entry_pathname(ae), "rb");
    if (!assert(f != NULL))
        return;

    /* Check first block. */
    assertEqualInt(buff_size, fread(buff, 1, buff_size, f));
    failure("%s", msg);
    assertEqualMem(buff, data, sizeof(data));
    for (p = buff + sizeof(data); p < buff + buff_size; ++p) {
        failure("offset: %d, %s", (int)(p - buff), msg);
        if (!assertEqualInt(0, *p))
            break;
    }

    /* Check second block. */
    assertEqualInt(buff_size, fread(buff, 1, buff_size, f));
    for (p = buff; p < buff + buff_size; ++p) {
        failure("offset: %d, %s", (int)(p - buff), msg);
        if (p == buff + buff_size / 2 - 3) {
            assertEqualMem(p, data, sizeof(data));
            p += sizeof(data);
        } else if (!assertEqualInt(0, *p))
            break;
    }

    /* Check third block. */
    assertEqualInt(buff_size, fread(buff, 1, buff_size, f));
    for (p = buff; p < buff + buff_size - sizeof(data); ++p) {
        failure("offset: %d, %s", (int)(p - buff), msg);
        if (!assertEqualInt(0, *p))
            break;
    }
    failure("%s", msg);
    assertEqualMem(buff + buff_size - sizeof(data), data, sizeof(data));

    /* XXX more XXX */

    assertEqualInt(0, fclose(f));
    archive_entry_free(ae);
    free(buff);
}

/*
 * As above, but using the archive_write_data_block() call.
 */
static void
verify_write_data_block(struct archive *a, int sparse)
{
    static const char data[]="abcdefghijklmnopqrstuvwxyz";
    struct stat st;
    struct archive_entry *ae;
    size_t buff_size = 64 * 1024;
    char *buff, *p;
    const char *msg = sparse ? "sparse" : "non-sparse";
    FILE *f;

    buff = malloc(buff_size);
    assert(buff != NULL);

    ae = archive_entry_new();
    assert(ae != NULL);
    archive_entry_set_size(ae, 8 * buff_size);
    archive_entry_set_pathname(ae, "test_write_data_block");
    archive_entry_set_mode(ae, AE_IFREG | 0755);
    assertEqualIntA(a, 0, archive_write_header(a, ae));

    /* Use archive_write_data_block() to write three
       relatively sparse blocks. */

    /* First has non-null data at beginning. */
    memset(buff, 0, buff_size);
    memcpy(buff, data, sizeof(data));
    failure("%s", msg);
    assertEqualInt(ARCHIVE_OK,
        archive_write_data_block(a, buff, buff_size, 100));

    /* Second has non-null data in the middle. */
    memset(buff, 0, buff_size);
    memcpy(buff + buff_size / 2 - 3, data, sizeof(data));
    failure("%s", msg);
    assertEqualInt(ARCHIVE_OK,
        archive_write_data_block(a, buff, buff_size, buff_size + 200));

    /* Third has non-null data at the end. */
    memset(buff, 0, buff_size);
    memcpy(buff + buff_size - sizeof(data), data, sizeof(data));
    failure("%s", msg);
    assertEqualInt(ARCHIVE_OK,
        archive_write_data_block(a, buff, buff_size, buff_size * 2 + 300));

    failure("%s", msg);
    assertEqualIntA(a, 0, archive_write_finish_entry(a));

    /* Test the entry on disk. */
    assert(0 == stat(archive_entry_pathname(ae), &st));
        assertEqualInt(st.st_size, 8 * buff_size);
    f = fopen(archive_entry_pathname(ae), "rb");
    if (!assert(f != NULL))
        return;

    /* Check 100-byte gap at beginning */
    assertEqualInt(100, fread(buff, 1, 100, f));
    failure("%s", msg);
    for (p = buff; p < buff + 100; ++p) {
        failure("offset: %d, %s", (int)(p - buff), msg);
        if (!assertEqualInt(0, *p))
            break;
    }

    /* Check first block. */
    assertEqualInt(buff_size, fread(buff, 1, buff_size, f));
    failure("%s", msg);
    assertEqualMem(buff, data, sizeof(data));
    for (p = buff + sizeof(data); p < buff + buff_size; ++p) {
        failure("offset: %d, %s", (int)(p - buff), msg);
        if (!assertEqualInt(0, *p))
            break;
    }

    /* Check 100-byte gap */
    assertEqualInt(100, fread(buff, 1, 100, f));
    failure("%s", msg);
    for (p = buff; p < buff + 100; ++p) {
        failure("offset: %d, %s", (int)(p - buff), msg);
        if (!assertEqualInt(0, *p))
            break;
    }

    /* Check second block. */
    assertEqualInt(buff_size, fread(buff, 1, buff_size, f));
    for (p = buff; p < buff + buff_size; ++p) {
        failure("offset: %d, %s", (int)(p - buff), msg);
        if (p == buff + buff_size / 2 - 3) {
            assertEqualMem(p, data, sizeof(data));
            p += sizeof(data);
        } else if (!assertEqualInt(0, *p))
            break;
    }

    /* Check 100-byte gap */
    assertEqualInt(100, fread(buff, 1, 100, f));
    failure("%s", msg);
    for (p = buff; p < buff + 100; ++p) {
        failure("offset: %d, %s", (int)(p - buff), msg);
        if (!assertEqualInt(0, *p))
            break;
    }

    /* Check third block. */
    assertEqualInt(buff_size, fread(buff, 1, buff_size, f));
    for (p = buff; p < buff + buff_size - sizeof(data); ++p) {
        failure("offset: %d, %s", (int)(p - buff), msg);
        if (!assertEqualInt(0, *p))
            break;
    }
    failure("%s", msg);
    assertEqualMem(buff + buff_size - sizeof(data), data, sizeof(data));

    /* Check another block size beyond last we wrote. */
    assertEqualInt(buff_size, fread(buff, 1, buff_size, f));
    failure("%s", msg);
    for (p = buff; p < buff + buff_size; ++p) {
        failure("offset: %d, %s", (int)(p - buff), msg);
        if (!assertEqualInt(0, *p))
            break;
    }


    /* XXX more XXX */

    assertEqualInt(0, fclose(f));
    free(buff);
    archive_entry_free(ae);
}

DEFINE_TEST(test_write_disk_sparse)
{
    struct archive *ad;


    /*
     * The return values, etc, of the write data functions
     * shouldn't change regardless of whether we've requested
     * sparsification.  (The performance and pattern of actual
     * write calls to the disk should vary, of course, but the
     * client program shouldn't see any difference.)
     */
    assert((ad = archive_write_disk_new()) != NULL);
        archive_write_disk_set_options(ad, 0);
    verify_write_data(ad, 0);
    verify_write_data_block(ad, 0);
    assertEqualInt(0, archive_write_finish(ad));

    assert((ad = archive_write_disk_new()) != NULL);
        archive_write_disk_set_options(ad, ARCHIVE_EXTRACT_SPARSE);
    verify_write_data(ad, 1);
    verify_write_data_block(ad, 1);
    assertEqualInt(0, archive_write_finish(ad));

}

--- NEW FILE: test_extattr_freebsd.c ---
/*-
 * 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$");

#if defined(__FreeBSD__) && __FreeBSD__ > 4
#include <sys/extattr.h>
#endif

/*
 * Verify extended attribute restore-to-disk.  This test is FreeBSD-specific.
 */

DEFINE_TEST(test_extattr_freebsd)
{
#if !defined(__FreeBSD__)
    skipping("FreeBSD-specific extattr restore test");
#elif __FreeBSD__ < 5
    skipping("extattr restore supported only on FreeBSD 5.0 and later");
#else
    char buff[64];
    const char *xname;
    const void *xval;
    size_t xsize;
    struct stat st;
    struct archive *a;
    struct archive_entry *ae;
    int n, fd;
    int extattr_privilege_bug = 0;

    /*
     * First, do a quick manual set/read of an extended attribute
     * to verify that the local filesystem does support it.  If it
     * doesn't, we'll simply skip the remaining tests.
     */
    /* Create a test file and try to set an ACL on it. */
    fd = open("pretest", O_RDWR | O_CREAT, 0777);
    failure("Could not create test file?!");
    if (!assert(fd >= 0))
        return;

    errno = 0;
    n = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, "testattr", "1234", 4);
    if (n != 4 && errno == EOPNOTSUPP) {
        close(fd);
        skipping("extattr tests require that extattr support be enabled on the filesystem");
        return;
    }
    failure("extattr_set_fd(): errno=%d (%s)", errno, strerror(errno));
    assertEqualInt(4, n);
    close(fd);

    /*
     * Repeat the above, but with file permissions set to 0000.
     * This should work (extattr_set_fd() should follow fd
     * permissions, not file permissions), but is known broken on
     * some versions of FreeBSD.
     */
    fd = open("pretest2", O_RDWR | O_CREAT, 00000);
    failure("Could not create test file?!");
    if (!assert(fd >= 0))
        return;

    n = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, "testattr", "1234", 4);
    if (n != 4) {
        skipping("Restoring xattr to an unwritable file seems to be broken on this platform");
        extattr_privilege_bug = 1;
    }
    close(fd);

    /* Create a write-to-disk object. */
    assert(NULL != (a = archive_write_disk_new()));
    archive_write_disk_set_options(a,
        ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_XATTR);

    /* Populate an archive entry with an extended attribute. */
    ae = archive_entry_new();
    assert(ae != NULL);
    archive_entry_set_pathname(ae, "test0");
    archive_entry_set_mtime(ae, 123456, 7890);
    archive_entry_set_size(ae, 0);
    archive_entry_set_mode(ae, 0755);
    archive_entry_xattr_add_entry(ae, "user.foo", "12345", 5);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
    archive_entry_free(ae);

    /* Another entry; similar but with mode = 0. */
    ae = archive_entry_new();
    assert(ae != NULL);
    archive_entry_set_pathname(ae, "test1");
    archive_entry_set_mtime(ae, 12345678, 7890);
    archive_entry_set_size(ae, 0);
    archive_entry_set_mode(ae, 0);
    archive_entry_xattr_add_entry(ae, "user.bar", "123456", 6);
    if (extattr_privilege_bug)
        /* If the bug is here, write_header will return warning. */
        assertEqualIntA(a, ARCHIVE_WARN,
            archive_write_header(a, ae));
    else
        assertEqualIntA(a, ARCHIVE_OK,
            archive_write_header(a, ae));
    archive_entry_free(ae);

    /* Close the archive. */
    assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    /* Verify the data on disk. */
    assertEqualInt(0, stat("test0", &st));
    assertEqualInt(st.st_mtime, 123456);
    /* Verify extattr */
    n = extattr_get_file("test0", EXTATTR_NAMESPACE_USER,
        "foo", buff, sizeof(buff));
    if (assertEqualInt(n, 5)) {
        buff[n] = '\0';
        assertEqualString(buff, "12345");
    }

    /* Verify the data on disk. */
    assertEqualInt(0, stat("test1", &st));
    assertEqualInt(st.st_mtime, 12345678);
    /* Verify extattr */
    n = extattr_get_file("test1", EXTATTR_NAMESPACE_USER,
        "bar", buff, sizeof(buff));
    if (extattr_privilege_bug) {
        /* If we have the bug, the extattr won't have been written. */
        assertEqualInt(n, -1);
    } else {
        if (assertEqualInt(n, 6)) {
            buff[n] = '\0';
            assertEqualString(buff, "123456");
        }
    }

    /* Use libarchive APIs to read the file back into an entry and
     * verify that the extattr was read correctly. */
    assert((a = archive_read_disk_new()) != NULL);
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_pathname(ae, "test0");
    assertEqualInt(ARCHIVE_OK,
        archive_read_disk_entry_from_file(a, ae, -1, NULL));
    assertEqualInt(1, archive_entry_xattr_reset(ae));
    assertEqualInt(ARCHIVE_OK,
        archive_entry_xattr_next(ae, &xname, &xval, &xsize));
    assertEqualString(xname, "user.foo");
    assertEqualInt(xsize, 5);
    assertEqualMem(xval, "12345", xsize);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
    archive_entry_free(ae);
#endif
}

--- NEW FILE: test_write_format_cpio_newc.c ---
/*-
 * 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/lib/libarchive/test/test_write_format_cpio_newc.c,v 1.3 2008/09/01 05:38:33 kientzle Exp $");


static int
is_hex(const char *p, size_t l)
{
    while (l > 0) {
        if (*p >= 0 && *p <= '9') {
            /* Ascii digit */
        } else if (*p >= 'a' && *p <= 'f') {
            /* lowercase letter a-f */
        } else {
            /* Not hex. */
            return (0);
        }
        --l;
        ++p;
    }
    return (1);
}

/*
 * Detailed verification that cpio 'newc' archives are written with
 * the correct format.
 */
DEFINE_TEST(test_write_format_cpio_newc)
{
    struct archive *a;
    struct archive_entry *entry;
    char *buff, *e;
    size_t buffsize = 100000;
    size_t used;

    buff = malloc(buffsize);

    /* Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, 0, archive_write_set_format_cpio_newc(a));
    assertEqualIntA(a, 0, archive_write_set_compression_none(a));
    assertEqualIntA(a, 0, archive_write_open_memory(a, buff, buffsize, &used));

    /*
     * Add various files to it.
     * TODO: Extend this to cover more filetypes.
     */

    /* Regular file */
    assert((entry = archive_entry_new()) != NULL);
    archive_entry_set_mtime(entry, 1, 10);
    archive_entry_set_pathname(entry, "file");
    archive_entry_set_mode(entry, S_IFREG | 0664);
    archive_entry_set_size(entry, 10);
    archive_entry_set_uid(entry, 80);
    archive_entry_set_gid(entry, 90);
    archive_entry_set_dev(entry, 12);
    archive_entry_set_ino(entry, 89);
    archive_entry_set_nlink(entry, 1);
    assertEqualIntA(a, 0, archive_write_header(a, entry));
    archive_entry_free(entry);
    assertEqualIntA(a, 10, archive_write_data(a, "1234567890", 10));

    /* Directory */
    assert((entry = archive_entry_new()) != NULL);
    archive_entry_set_mtime(entry, 2, 20);
    archive_entry_set_pathname(entry, "dir");
    archive_entry_set_mode(entry, S_IFDIR | 0775);
    archive_entry_set_size(entry, 10);
    archive_entry_set_nlink(entry, 2);
    assertEqualIntA(a, 0, archive_write_header(a, entry));
    archive_entry_free(entry);
    assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10));

    /* Symlink */
    assert((entry = archive_entry_new()) != NULL);
    archive_entry_set_mtime(entry, 3, 30);
    archive_entry_set_pathname(entry, "lnk");
    archive_entry_set_mode(entry, 0664);
    archive_entry_set_filetype(entry, AE_IFLNK);
    archive_entry_set_size(entry, 0);
    archive_entry_set_uid(entry, 83);
    archive_entry_set_gid(entry, 93);
    archive_entry_set_dev(entry, 13);
    archive_entry_set_ino(entry, 88);
    archive_entry_set_nlink(entry, 1);
    archive_entry_set_symlink(entry,"a");
    assertEqualIntA(a, 0, archive_write_header(a, entry));
    archive_entry_free(entry);


#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assert(0 == archive_write_finish(a));
#endif

    /*
     * Verify the archive format.
     */
    e = buff;

    /* First entry is "file" */
    assert(is_hex(e, 110)); /* Entire header is hex digits. */
    assertEqualMem(e + 0, "070701", 6); /* Magic */
    assertEqualMem(e + 6, "00000059", 8); /* ino */
    assertEqualMem(e + 14, "000081b4", 8); /* Mode */
    assertEqualMem(e + 22, "00000050", 8); /* uid */
    assertEqualMem(e + 30, "0000005a", 8); /* gid */
    assertEqualMem(e + 38, "00000001", 8); /* nlink */
    assertEqualMem(e + 46, "00000001", 8); /* mtime */
    assertEqualMem(e + 54, "0000000a", 8); /* File size */
    assertEqualMem(e + 62, "00000000", 8); /* devmajor */
    assertEqualMem(e + 70, "0000000c", 8); /* devminor */
    assertEqualMem(e + 78, "00000000", 8); /* rdevmajor */
    assertEqualMem(e + 86, "00000000", 8); /* rdevminor */
    assertEqualMem(e + 94, "00000005", 8); /* Name size */
    assertEqualMem(e + 102, "00000000", 8); /* CRC */
    assertEqualMem(e + 110, "file\0\0", 6); /* Name contents */
    assertEqualMem(e + 116, "1234567890", 10); /* File body */
    assertEqualMem(e + 126, "\0\0", 2); /* Pad to multiple of 4 */
    e += 128; /* Must be multiple of four here! */

    /* Second entry is "dir" */
    assert(is_hex(e, 110));
    assertEqualMem(e + 0, "070701", 6); /* Magic */
    assertEqualMem(e + 6, "00000000", 8); /* ino */
    assertEqualMem(e + 14, "000041fd", 8); /* Mode */
    assertEqualMem(e + 22, "00000000", 8); /* uid */
    assertEqualMem(e + 30, "00000000", 8); /* gid */
    assertEqualMem(e + 38, "00000002", 8); /* nlink */
    assertEqualMem(e + 46, "00000002", 8); /* mtime */
    assertEqualMem(e + 54, "00000000", 8); /* File 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 */
    assertEqualMem(e + 94, "00000004", 8); /* Name size */
    assertEqualMem(e + 102, "00000000", 8); /* CRC */
    assertEqualMem(e + 110, "dir\0", 4); /* name */
    assertEqualMem(e + 114, "\0\0", 2); /* Pad to multiple of 4 */
    e += 116; /* Must be multiple of four here! */

    /* Third entry is "lnk" */
    assert(is_hex(e, 110)); /* Entire header is hex digits. */
    assertEqualMem(e + 0, "070701", 6); /* Magic */
    assertEqualMem(e + 6, "00000058", 8); /* ino */
    assertEqualMem(e + 14, "0000a1b4", 8); /* Mode */
    assertEqualMem(e + 22, "00000053", 8); /* uid */
    assertEqualMem(e + 30, "0000005d", 8); /* gid */
    assertEqualMem(e + 38, "00000001", 8); /* nlink */
    assertEqualMem(e + 46, "00000003", 8); /* mtime */
    assertEqualMem(e + 54, "00000001", 8); /* File size */
    assertEqualMem(e + 62, "00000000", 8); /* devmajor */
    assertEqualMem(e + 70, "0000000d", 8); /* devminor */
    assertEqualMem(e + 78, "00000000", 8); /* rdevmajor */
    assertEqualMem(e + 86, "00000000", 8); /* rdevminor */
    assertEqualMem(e + 94, "00000004", 8); /* Name size */
    assertEqualMem(e + 102, "00000000", 8); /* CRC */
    assertEqualMem(e + 110, "lnk\0\0\0", 6); /* Name contents */
    assertEqualMem(e + 116, "a\0\0\0", 4); /* File body + pad */
    e += 120; /* Must be multiple of four here! */

    /* TODO: Verify other types of entries. */

    /* Last entry is end-of-archive marker. */
    assert(is_hex(e, 76));
    assertEqualMem(e + 0, "070701", 6); /* Magic */
    assertEqualMem(e + 6, "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); /* File 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 */
    assertEqualMem(e + 94, "0000000b", 8); /* Name size */
    assertEqualMem(e + 102, "00000000", 8); /* CRC */
    assertEqualMem(e + 110, "TRAILER!!!\0", 11); /* Name */
    assertEqualMem(e + 121, "\0\0\0", 3); /* Pad to multiple of 4 bytes */
    e += 124; /* Must be multiple of four here! */

    assertEqualInt((int)used, e - buff);

    free(buff);
}

--- NEW FILE: test_compat_xz.c ---
/*-
 * Copyright (c) 2009 Michihiro NAKAJIMA
 * 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"
__FBSDID("$FreeBSD$");

/*
 * Verify our ability to read sample files compatibly with unxz.
 *
 * In particular:
 *  * unxz will read multiple xz streams, concatenating the output
 */

/*
 * All of the sample files have the same contents; they're just
 * compressed in different ways.
 */
static void
compat_xz(const char *name)
{
    const char *n[7] = { "f1", "f2", "f3", "d1/f1", "d1/f2", "d1/f3", NULL };
    struct archive_entry *ae;
    struct archive *a;
    int i, r;

    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    r = archive_read_support_compression_xz(a);
    if (r == ARCHIVE_WARN) {
        skipping("xz reading not fully supported on this platform");
        assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
        return;
    }
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    extract_reference_file(name);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 2));

    /* Read entries, match up names with list above. */
    for (i = 0; i < 6; ++i) {
        failure("Could not read file %d (%s) from %s", i, n[i], name);
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_next_header(a, &ae));
        assertEqualString(n[i], archive_entry_pathname(ae));
    }

    /* Verify the end-of-archive. */
    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));

    /* Verify that the format detection worked. */
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_XZ);
    assertEqualString(archive_compression_name(a), "xz");
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR);

    assertEqualInt(ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}


DEFINE_TEST(test_compat_xz)
{
    compat_xz("test_compat_xz_1.txz");
}

--- NEW FILE: test_pax_filename_encoding.tar.uu ---
begin 644 test_pax_filename_encoding.tar
M4&%X2&5A9&5R+V%B8\R,;6YO6'AY>@``````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#`P,#8T-"``,#`Q-S4P(``P,#$W-3`@`#`P,#`P,#`P,38V
M(#$P-S8V-C`W,#,V(#`Q-3,P-@`@>```````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<@`P,'1I;0``
M````````````````````````````````````=&EM````````````````````
M```````````````````P,#`P,#`@`#`P,#`P,"``````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````R,2!P871H/6%B8\R,;6YO_'AY>@HR,"!C=&EM
M93TQ,C`U-3,X-C at U"C(P(&%T:6UE/3$R,#4U,S at V,C8*,3<@4T-(24Q9+F1E
M=CTX.`HR,B!30TA)3%DN:6YO/30S,34T-#D*,3@@4T-(24Q9+FYL:6YK/3$*
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````&%B8\R,;6YO6'AY
M>@``````````````````````````````````````````````````````````
M```````````````````````````````````````````````````````````P
M,#`V-#0@`#`P,3<U,"``,#`Q-S4P(``P,#`P,#`P,#`P-2`Q,#<V-C8P-S`S
M-B`P,3,S,C4`(#``````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````=7-T87(`,#!T:6T`````````````````
M`````````````````````'1I;0``````````````````````````````````
M````,#`P,#`P(``P,#`P,#`@````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````2&5L;&\`````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````!087A(96%D97(O86)CS(QM;F_\>'EZ
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````,#`P-C0T(``P,#$W
M-3`@`#`P,3<U,"``,#`P,#`P,#`R,3,@,3`W-C8V,#<P,S8@,#$U-30S`"!X
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````'5S=&%R`#`P=&EM````````````````````````````````
M``````!T:6T``````````````````````````````````````#`P,#`P,"``
M,#`P,#`P(```````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````#(Q(&AD
M<F-H87)S970]0DE.05)9"C(Q('!A=&@]86)CS(QM;F_\>'EZ"C(P(&-T:6UE
M/3$R,#4U-#$W,S4*,C`@871I;64],3(P-34S.#8R- at HQ-R!30TA)3%DN9&5V
M/3 at X"C(R(%-#2$E,62YI;F\]-#,Q-3$R- at HQ."!30TA)3%DN;FQI;FL],0H`
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````86)CS(QM;F_\>'EZ````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````#`P,#8T-"``,#`Q-S4P(``P,#$W-3`@
M`#`P,#`P,#`P,#`U(#$P-S8V-C`W,#,V(#`Q,S4W,0`@,```````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````````````````````!U
M<W1A<@`P,'1I;0``````````````````````````````````````=&EM````
M```````````````````````````````````P,#`P,#`@`#`P,#`P,"``````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````!(96QL;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````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
C````````````````````````````````````````````````
`
end

--- NEW FILE: test_read_format_cpio_bin_be.cpio.uu ---
$FreeBSD$
begin 644 test_read_format_cpio_bin_be.cpio
M<<<`"#P\@:0#Z`````$``$GS"&\`%0````5F:6QE,3$Q,3(R,C(S,S,S-#0T
M-```86)C9&4`<<<```````````````$`````````"P````!44D%)3$52(2$A
M````````````````````````````````````````````````````````````
3````````````````````````````
`
end

--- NEW FILE: test_read_format_ar.c ---
/*-
 * Copyright (c) 2007 Kai Wang
 * Copyright (c) 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 "test.h"
__FBSDID("$FreeBSD: src/lib/libarchive/test/test_read_format_ar.c,v 1.6 2008/09/01 05:38:33 kientzle Exp $");

#if ARCHIVE_VERSION_NUMBER >= 1009000
/*
 * This "archive" is created by "GNU ar". Here we try to verify
 * our GNU format handling functionality.
 */
static unsigned char archive[] = {
'!','<','a','r','c','h','>',10,'/','/',' ',' ',' ',' ',' ',' ',' ',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
' ',' ',' ',' ',' ','4','0',' ',' ',' ',' ',' ',' ',' ',' ','`',10,
'y','y','y','t','t','t','s','s','s','a','a','a','f','f','f','.','o',
'/',10,'h','h','h','h','j','j','j','j','k','k','k','k','l','l','l',
'l','.','o','/',10,10,'/','0',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
' ',' ',' ',' ','1','1','7','5','4','6','5','6','5','2',' ',' ','1',
'0','0','1',' ',' ','0',' ',' ',' ',' ',' ','1','0','0','6','4','4',
' ',' ','8',' ',' ',' ',' ',' ',' ',' ',' ',' ','`',10,'5','5','6',
'6','7','7','8','8','g','g','h','h','.','o','/',' ',' ',' ',' ',' ',
' ',' ',' ',' ','1','1','7','5','4','6','5','6','6','8',' ',' ','1',
'0','0','1',' ',' ','0',' ',' ',' ',' ',' ','1','0','0','6','4','4',
' ',' ','4',' ',' ',' ',' ',' ',' ',' ',' ',' ','`',10,'3','3','3',
'3','/','1','9',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
'1','1','7','5','4','6','5','7','1','3',' ',' ','1','0','0','1',' ',
' ','0',' ',' ',' ',' ',' ','1','0','0','6','4','4',' ',' ','9',' ',
' ',' ',' ',' ',' ',' ',' ',' ','`',10,'9','8','7','6','5','4','3',
'2','1',10};

char buff[64];
#endif

DEFINE_TEST(test_read_format_ar)
{
#if ARCHIVE_VERSION_NUMBER < 1009000
    skipping("test_read_support_format_ar()");
#else
    struct archive_entry *ae;
    struct archive *a;
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_open_memory(a, archive, sizeof(archive)));

    /* Filename table.  */
    assertA(0 == archive_read_next_header(a, &ae));
    assertEqualString("//", archive_entry_pathname(ae));
    assertEqualInt(0, archive_entry_mtime(ae));
    assertEqualInt(0, archive_entry_uid(ae));
    assertEqualInt(0, archive_entry_gid(ae));
    assertEqualInt(0, archive_entry_size(ae));

    /* First Entry */
    assertA(0 == archive_read_next_header(a, &ae));
    assertEqualString("yyytttsssaaafff.o", archive_entry_pathname(ae));
    assertEqualInt(1175465652, archive_entry_mtime(ae));
    assertEqualInt(1001, archive_entry_uid(ae));
    assertEqualInt(0, archive_entry_gid(ae));
    assert(8 == archive_entry_size(ae));
    assertA(8 == archive_read_data(a, buff, 10));
    assert(0 == memcmp(buff, "55667788", 8));

    /* Second Entry */
    assertA(0 == archive_read_next_header(a, &ae));
    assertEqualString("gghh.o", archive_entry_pathname(ae));
    assertEqualInt(1175465668, archive_entry_mtime(ae));
    assertEqualInt(1001, archive_entry_uid(ae));
    assertEqualInt(0, archive_entry_gid(ae));
    assert(4 == archive_entry_size(ae));
    assertA(4 == archive_read_data(a, buff, 10));
    assert(0 == memcmp(buff, "3333", 4));

    /* Third Entry */
    assertA(0 == archive_read_next_header(a, &ae));
    assertEqualString("hhhhjjjjkkkkllll.o", archive_entry_pathname(ae));
    assertEqualInt(1175465713, archive_entry_mtime(ae));
    assertEqualInt(1001, archive_entry_uid(ae));
    assertEqualInt(0, archive_entry_gid(ae));
    assert(9 == archive_entry_size(ae));
    assertA(9 == archive_read_data(a, buff, 9));
    assert(0 == memcmp(buff, "987654321", 9));

    /* Test EOF */
    assertA(1 == archive_read_next_header(a, &ae));
    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif
#endif
}

--- NEW FILE: test_compat_bzip2.c ---
/*-
 * 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"
__FBSDID("$FreeBSD$");

/*
 * Verify our ability to read sample files compatibly with bunzip2.
 *
 * In particular:
 *  * bunzip2 will read multiple bzip2 streams, concatenating the output
 *  * bunzip2 will stop at the end of a stream if the following data
 *    doesn't start with a bzip2 signature.
 */

/*
 * All of the sample files have the same contents; they're just
 * compressed in different ways.
 */
static void
compat_bzip2(const char *name)
{
    const char *n[7] = { "f1", "f2", "f3", "d1/f1", "d1/f2", "d1/f3", NULL };
    struct archive_entry *ae;
    struct archive *a;
    int i;

    assert((a = archive_read_new()) != NULL);
    if (ARCHIVE_OK != archive_read_support_compression_bzip2(a)) {
        skipping("Unsupported bzip2");
        return;
    }
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    extract_reference_file(name);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 2));

    /* Read entries, match up names with list above. */
    for (i = 0; i < 6; ++i) {
        failure("Could not read file %d (%s) from %s", i, n[i], name);
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_next_header(a, &ae));
        assertEqualString(n[i], archive_entry_pathname(ae));
    }

    /* Verify the end-of-archive. */
    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));

    /* Verify that the format detection worked. */
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_BZIP2);
    assertEqualString(archive_compression_name(a), "bzip2");
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR);

    assertEqualInt(ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}


DEFINE_TEST(test_compat_bzip2)
{
    compat_bzip2("test_compat_bzip2_1.tbz");
    compat_bzip2("test_compat_bzip2_2.tbz");
}



--- NEW FILE: test_read_format_isorr_new_bz2.c ---
/*-
 * 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"

/*
PLEASE use latest cdrtools at least mkisofs version is 2.01.01a63 or later.
Old version mkisofs made wrong "SL" System Use Entry of RRIP.

Execute the following command to rebuild the data for this program:
   tail -n +32 test_read_format_isorr_new_bz2.c | /bin/sh

rm -rf /tmp/iso
mkdir /tmp/iso
mkdir /tmp/iso/dir
echo "hello" >/tmp/iso/file
dd if=/dev/zero count=1 bs=12345678 >>/tmp/iso/file
ln /tmp/iso/file /tmp/iso/hardlink
(cd /tmp/iso; ln -s file symlink)
(cd /tmp/iso; ln -s /tmp/ symlink2)
(cd /tmp/iso; ln -s /tmp/../ symlink3)
(cd /tmp/iso; ln -s .././../tmp/ symlink4)
(cd /tmp/iso; ln -s .///file symlink5)
(cd /tmp/iso; ln -s /tmp//../ symlink6)
TZ=utc touch -afhm -t 197001020000.01 /tmp/iso /tmp/iso/file /tmp/iso/dir
TZ=utc touch -afhm -t 197001030000.02 /tmp/iso/symlink
F=test_read_format_isorr_new_bz2.iso.bz2
mkhybrid -R -uid 1 -gid 2 /tmp/iso | bzip2 > $F
uuencode $F $F > $F.uu
exit 1
 */

DEFINE_TEST(test_read_format_isorr_new_bz2)
{
    const char *refname = "test_read_format_isorr_new_bz2.iso.bz2";
    struct archive_entry *ae;
    struct archive *a;
    const void *p;
    size_t size;
    off_t offset;
    int i;
    int r;

    extract_reference_file(refname);
    assert((a = archive_read_new()) != NULL);
    r = archive_read_support_compression_bzip2(a);
    if (r == ARCHIVE_WARN) {
        skipping("bzip2 reading not fully supported on this platform");
        assertEqualInt(0, archive_read_finish(a));
        return;
    }
    assertEqualInt(0, r);
    assertEqualInt(0, archive_read_support_format_all(a));
    assertEqualInt(ARCHIVE_OK,
        archive_read_open_filename(a, refname, 10240));

    /* Retrieve each of the 8 files on the ISO image and
     * verify that each one is what we expect. */
    for (i = 0; i < 10; ++i) {
        assertEqualInt(0, archive_read_next_header(a, &ae));

        if (strcmp(".", archive_entry_pathname(ae)) == 0) {
            /* '.' root directory. */
            assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
            assertEqualInt(2048, archive_entry_size(ae));
            /* Now, we read timestamp recorded by RRIP "TF". */
            assertEqualInt(86401, archive_entry_mtime(ae));
            assertEqualInt(0, archive_entry_mtime_nsec(ae));
            /* Now, we read links recorded by RRIP "PX". */
            assertEqualInt(3, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualIntA(a, ARCHIVE_EOF,
                archive_read_data_block(a, &p, &size, &offset));
            assertEqualInt((int)size, 0);
        } else if (strcmp("dir", archive_entry_pathname(ae)) == 0) {
            /* A directory. */
            assertEqualString("dir", archive_entry_pathname(ae));
            assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
            assertEqualInt(2048, archive_entry_size(ae));
            assertEqualInt(86401, archive_entry_mtime(ae));
            assertEqualInt(86401, archive_entry_atime(ae));
            assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("file", archive_entry_pathname(ae)) == 0) {
            /* A regular file. */
            assertEqualString("file", archive_entry_pathname(ae));
            assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
            assertEqualInt(12345684, archive_entry_size(ae));
            assertEqualInt(0,
                archive_read_data_block(a, &p, &size, &offset));
            assertEqualInt(0, offset);
            assertEqualMem(p, "hello\n", 6);
            assertEqualInt(86401, archive_entry_mtime(ae));
            assertEqualInt(86401, archive_entry_atime(ae));
            assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("hardlink", archive_entry_pathname(ae)) == 0) {
            /* A hardlink to the regular file. */
            /* Note: If "hardlink" gets returned before "file",
             * then "hardlink" will get returned as a regular file
             * and "file" will get returned as the hardlink.
             * This test should tolerate that, since it's a
             * perfectly permissible thing for libarchive to do. */
            assertEqualString("hardlink", archive_entry_pathname(ae));
            assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
            assertEqualString("file", archive_entry_hardlink(ae));
            assertEqualInt(0, archive_entry_size_is_set(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(86401, archive_entry_mtime(ae));
            assertEqualInt(86401, archive_entry_atime(ae));
            assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("symlink", archive_entry_pathname(ae)) == 0) {
            /* A symlink to the regular file. */
            assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
            assertEqualString("file", archive_entry_symlink(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(172802, archive_entry_mtime(ae));
            assertEqualInt(172802, archive_entry_atime(ae));
            assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("symlink2", archive_entry_pathname(ae)) == 0) {
            /* A symlink to /tmp/ (an absolute path) */
            assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
            assertEqualString("/tmp/", archive_entry_symlink(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("symlink3", archive_entry_pathname(ae)) == 0) {
            /* A symlink to /tmp/../ (with a ".." component) */
            assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
            assertEqualString("/tmp/../", archive_entry_symlink(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("symlink4", archive_entry_pathname(ae)) == 0) {
            /* A symlink to a path with ".." and "." components */
            assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
            assertEqualString(".././../tmp/",
                archive_entry_symlink(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("symlink5", archive_entry_pathname(ae)) == 0) {
            /* A symlink to the regular file with "/" components. */
            assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
            assertEqualString(".///file", archive_entry_symlink(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(172802, archive_entry_mtime(ae));
            assertEqualInt(172802, archive_entry_atime(ae));
            assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("symlink6", archive_entry_pathname(ae)) == 0) {
            /* A symlink to /tmp//../
             * (with "/" and ".." components) */
            assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
            assertEqualString("/tmp//../", archive_entry_symlink(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else {
            failure("Saw a file that shouldn't have been there");
            assertEqualString(archive_entry_pathname(ae), "");
        }
    }

    /* End of archive. */
    assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae));

    /* Verify archive format. */
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_BZIP2);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ISO9660_ROCKRIDGE);

    /* Close the archive. */
    assertEqualInt(0, archive_read_close(a));
    assertEqualInt(0, archive_read_finish(a));
}



--- NEW FILE: test_write_format_zip_empty.c ---
/*-
 * Copyright (c) 2008 Anselm Strauss
 * 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.
 */

/*
 * Development supported by Google Summer of Code 2008.
 */

#include "test.h"
__FBSDID("$FreeBSD$");

DEFINE_TEST(test_write_format_zip_empty)
{
    struct archive *a;
    char buff[256];
    size_t used;

    /* Zip format: Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_zip(a));
    assertA(0 == archive_write_set_compression_none(a));
    assertA(0 == archive_write_set_bytes_per_block(a, 1));
    assertA(0 == archive_write_set_bytes_in_last_block(a, 1));
    assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));

    /* Close out the archive without writing anything. */
    assertA(0 == archive_write_close(a));
    assertA(0 == archive_write_finish(a));

    /* Verify the correct format for an empy Zip archive. */
    assertEqualInt(used, 22);
    assertEqualMem(buff,
        "PK\005\006\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
        22);
}

--- NEW FILE: test_read_pax_truncated.c ---
/*-
 * 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/lib/libarchive/test/test_read_pax_truncated.c,v 1.4 2008/12/06 05:59:46 kientzle Exp $");

DEFINE_TEST(test_read_pax_truncated)
{
    struct archive_entry *ae;
    struct archive *a;
    size_t used, i, buff_size = 1000000;
    size_t filedata_size = 100000;
    char *buff = malloc(buff_size);
    char *buff2 = malloc(buff_size);
    char *filedata = malloc(filedata_size);

    /* Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_pax(a));
    assertA(0 == archive_write_set_compression_none(a));
    assertEqualIntA(a, ARCHIVE_OK,
            archive_write_open_memory(a, buff, buff_size, &used));

    /*
     * Write a file to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    for (i = 0; i < filedata_size; i++)
        filedata[i] = (unsigned char)rand();
    archive_entry_set_atime(ae, 1, 2);
    archive_entry_set_ctime(ae, 3, 4);
    archive_entry_set_mtime(ae, 5, 6);
    archive_entry_set_size(ae, filedata_size);
    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);
    assertA((ssize_t)filedata_size
        == archive_write_data(a, filedata, filedata_size));

    /* Close out the archive. */
    assertA(0 == archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assertA(0 == archive_write_finish(a));
#endif

    /* Now, read back a truncated version of the archive and
     * verify that we get an appropriate error. */
    for (i = 1; i < used + 100; i += 100) {
        assert((a = archive_read_new()) != NULL);
        assertA(0 == archive_read_support_format_all(a));
        assertA(0 == archive_read_support_compression_all(a));
        assertA(0 == read_open_memory2(a, buff, i, 13));

        if (i < 1536) {
            assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae));
            goto wrap_up;
        } else {
            failure("Archive truncated to %d bytes", i);
            assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
        }

        if (i < 1536 + filedata_size) {
            assertA(ARCHIVE_FATAL == archive_read_data(a, filedata, filedata_size));
            goto wrap_up;
        } else {
            failure("Archive truncated to %d bytes", i);
            assertEqualIntA(a, filedata_size,
                archive_read_data(a, filedata, filedata_size));
        }

        /* Verify the end of the archive. */
        /* Archive must be long enough to capture a 512-byte
         * block of zeroes after the entry.  (POSIX requires a
         * second block of zeros to be written but libarchive
         * does not return an error if it can't consume
         * it.) */
        if (i < 1536 + 512*((filedata_size + 511)/512) + 512) {
            failure("i=%d minsize=%d", i,
                1536 + 512*((filedata_size + 511)/512) + 512);
            assertEqualIntA(a, ARCHIVE_FATAL,
                archive_read_next_header(a, &ae));
        } else {
            assertEqualIntA(a, ARCHIVE_EOF,
                archive_read_next_header(a, &ae));
        }
    wrap_up:
        assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
        archive_read_finish(a);
#else
        assert(0 == archive_read_finish(a));
#endif
    }



    /* Same as above, except skip the body instead of reading it. */
    for (i = 1; i < used + 100; i += 100) {
        assert((a = archive_read_new()) != NULL);
        assertA(0 == archive_read_support_format_all(a));
        assertA(0 == archive_read_support_compression_all(a));
        assertA(0 == read_open_memory(a, buff, i, 7));

        if (i < 1536) {
            assertA(ARCHIVE_FATAL == archive_read_next_header(a, &ae));
            goto wrap_up2;
        } else {
            assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
        }

        if (i < 1536 + 512*((filedata_size+511)/512)) {
            assertA(ARCHIVE_FATAL == archive_read_data_skip(a));
            goto wrap_up2;
        } else {
            assertA(ARCHIVE_OK == archive_read_data_skip(a));
        }

        /* Verify the end of the archive. */
        /* Archive must be long enough to capture a 512-byte
         * block of zeroes after the entry.  (POSIX requires a
         * second block of zeros to be written but libarchive
         * does not return an error if it can't consume
         * it.) */
        if (i < 1536 + 512*((filedata_size + 511)/512) + 512) {
            assertEqualIntA(a, ARCHIVE_FATAL,
                archive_read_next_header(a, &ae));
        } else {
            assertEqualIntA(a, ARCHIVE_EOF,
                archive_read_next_header(a, &ae));
        }
    wrap_up2:
        assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
        archive_read_finish(a);
#else
        assert(0 == archive_read_finish(a));
#endif
    }

    /* Now, damage the archive in various ways and test the responses. */

    /* Damage the first size field in the pax attributes. */
    memcpy(buff2, buff, buff_size);
    buff2[512] = '9';
    buff2[513] = '9';
    buff2[514] = 'A'; /* Non-digit in size. */
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff2, used));
    assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae));
    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif

    /* Damage the size field in the pax attributes. */
    memcpy(buff2, buff, buff_size);
    buff2[512] = 'A'; /* First character not a digit. */
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff2, used));
    assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae));
    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif

    /* Damage the size field in the pax attributes. */
    memcpy(buff2, buff, buff_size);
    for (i = 512; i < 520; i++) /* Size over 999999. */
        buff2[i] = '9';
    buff2[i] = ' ';
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff2, used));
    assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae));
    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif

    /* Damage the size field in the pax attributes. */
    memcpy(buff2, buff, buff_size);
    buff2[512] = '9'; /* Valid format, but larger than attribute area. */
    buff2[513] = '9';
    buff2[514] = '9';
    buff2[515] = ' ';
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff2, used));
    assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae));
    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif

    /* Damage the size field in the pax attributes. */
    memcpy(buff2, buff, buff_size);
    buff2[512] = '1'; /* Too small. */
    buff2[513] = ' ';
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff2, used));
    assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae));
    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif

    /* Damage the size field in the pax attributes. */
    memcpy(buff2, buff, buff_size);
    buff2[512] = ' '; /* No size given. */
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff2, used));
    assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae));
    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif

    /* Damage the ustar header. */
    memcpy(buff2, buff, buff_size);
    buff2[1024]++; /* Break the checksum. */
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff2, used));
    assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae));
    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif

    /*
     * TODO: Damage the ustar header in various ways and fixup the
     * checksum in order to test boundary cases in the innermost
     * ustar header parsing.
     */

    free(buff);
    free(buff2);
    free(filedata);
}

--- NEW FILE: test_compat_gzip_1.tgz.uu ---
$FreeBSD: src/lib/libarchive/test/test_compat_gzip_1.tgz.uu,v 1.1 2008/12/06 07:08:08 kientzle Exp $

begin 644 test_compat_gzip_1.tgz
M'XL(")B^(DD``W1E<W0M<W!L:70N=&%R86$`2S-DH#DP,#`P,S%1`-*&YJ:&
MR#0,&"L8`H&!J;&9F:&A at H&AH9&),8."`>V=QL!06ER26`1T2G9F:EY)54XJ
MN>9`/*(`IX<(2#/D&F at GC`(Z``#S<P4"Z`,``!^+"`B8OB))``-T97-T+7-P
M;&ET+G1A<F%B`&- at P`[2C'!(4!$8&!B8F9 at H`&E#<U-#9!H&C!4,@<#`U-C,
MS-!8P<#0T,C$C$'!@/9.8V`H+2Y)+`(Z)3LS-:^D*B>57',@'E&`TT,$I!EQ
M#;031@$5`0`Q!<\4Z`,``!^+"`B8OB))``-T97-T+7-P;&ET+G1A<F%C`&-@
M(`VD&9.H at 0Q@8&!@9F*B`*0-S4T-D6D8,%8P!`(#4V,S,T,S!0-#0R-3(P8%
M`]H[C8&AM+ at DL0CHE.S,U+R2JIQ4<LV!>$0!3@\1D&;,-=!.&`5D``#7L]HO
MZ`,``!^+"`B8OB))``-T97-T+7-P;&ET+G1A<F%D`&- at H`Y(,=1/,Z226;B`
M at 8&!F8F)`I`V-#<U1*9AP%C!$`@,3(W-S(S,%0P,#4U-S1 at 4#&CL+C`H+2Y)
M+`(Z)3LS-:^D*B>57',@'E&`TT,$I!ER#;031@$>``"Y*#OBZ`,``!^+"`B8
MOB))``-T97-T+7-P;&ET+G1A<F%E`&- at H"U(,=1/,Z*Q'08&!F8F)@I`VM#<
MU!"9A@%C!4,@,#`U-C,S-E`P,#0T-35D4#"@L;O`H+2X)+$(Z)3LS-2\DJJ<
M5'+- at 7A$`4X/$9!FQ#703A@%0```]%Z(F^@#```?BP@(F+XB20`#=&5S="US
M<&QI="YT87)A9@!C8!@8D&*HGV9,8SL,#`S,3$P4 at +2AN:DA, at T#Q at J&0&!@
M:FQF9FRH8&!H:&IJS*!@0&-W at 4%I<4EB$=`IV9FI>255.:GDF@/QB`*<'B(@
MS9AKH)TPH@``)4=8$>@#```?BP@(F+XB20`#=&5S="US<&QI="YT87)A9P!C
M8!@%HV`4#'<``(`7"P;H`P``'XL(")B^(DD``W1E<W0M<W!L:70N=&%R86@`
.8V`8&@``E#SI#J@`````
`
end

--- NEW FILE: test_write_compress_lzma.c ---
/*-
 * Copyright (c) 2007-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
 *    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 "test.h"
__FBSDID("$FreeBSD$");

/*
 * A basic exercise of lzma reading and writing.
 *
 */

DEFINE_TEST(test_write_compress_lzma)
{
    struct archive_entry *ae;
    struct archive* a;
    char *buff, *data;
    size_t buffsize, datasize;
    char path[16];
    size_t used1, used2;
    int i, r;

    buffsize = 2000000;
    assert(NULL != (buff = (char *)malloc(buffsize)));

    datasize = 10000;
    assert(NULL != (data = (char *)malloc(datasize)));
    memset(data, 0, datasize);

    /*
     * Write a 100 files and read them all back.
     */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    r = archive_write_set_compression_lzma(a);
    if (r == ARCHIVE_FATAL) {
        skipping("lzma writing not supported on this platform");
        assertEqualInt(ARCHIVE_OK, archive_write_finish(a));
        return;
    }
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_bytes_per_block(a, 10));
    assertEqualInt(ARCHIVE_COMPRESSION_LZMA, archive_compression(a));
    assertEqualString("lzma", archive_compression_name(a));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used1));
    assertEqualInt(ARCHIVE_COMPRESSION_LZMA, archive_compression(a));
    assertEqualString("lzma", archive_compression_name(a));
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_filetype(ae, AE_IFREG);
    archive_entry_set_size(ae, datasize);
    for (i = 0; i < 100; i++) {
        sprintf(path, "file%03d", i);
        archive_entry_copy_pathname(ae, path);
        assertA(0 == archive_write_header(a, ae));
        assertA(datasize
            == (size_t)archive_write_data(a, data, datasize));
    }
    archive_entry_free(ae);
    archive_write_close(a);
    assert(0 == archive_write_finish(a));

    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    r = archive_read_support_compression_lzma(a);
    if (r == ARCHIVE_WARN) {
        skipping("Can't verify lzma writing by reading back;"
            " lzma reading not fully supported on this platform");
    } else {
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_support_compression_all(a));
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_open_memory(a, buff, used1));
        for (i = 0; i < 100; i++) {
            sprintf(path, "file%03d", i);
            if (!assertEqualInt(ARCHIVE_OK,
                archive_read_next_header(a, &ae)))
                break;
            assertEqualString(path, archive_entry_pathname(ae));
            assertEqualInt((int)datasize, archive_entry_size(ae));
        }
        assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    }
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));

    /*
     * Repeat the cycle again, this time setting some compression
     * options.
     */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_bytes_per_block(a, 10));
    assertA(0 == archive_write_set_compression_lzma(a));
    assertEqualIntA(a, ARCHIVE_WARN,
        archive_write_set_compressor_options(a, "nonexistent-option=0"));
    assertEqualIntA(a, ARCHIVE_WARN,
        archive_write_set_compressor_options(a, "compression-level=abc"));
    assertEqualIntA(a, ARCHIVE_WARN,
        archive_write_set_compressor_options(a, "compression-level=99"));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_compressor_options(a, "compression-level=9"));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used2));
    for (i = 0; i < 100; i++) {
        sprintf(path, "file%03d", i);
        assert((ae = archive_entry_new()) != NULL);
        archive_entry_copy_pathname(ae, path);
        archive_entry_set_size(ae, datasize);
        archive_entry_set_filetype(ae, AE_IFREG);
        assertA(0 == archive_write_header(a, ae));
        assertA(datasize == (size_t)archive_write_data(a, data, datasize));
        archive_entry_free(ae);
    }
    archive_write_close(a);
    assert(0 == archive_write_finish(a));


    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    r = archive_read_support_compression_lzma(a);
    if (r == ARCHIVE_WARN) {
        skipping("lzma reading not fully supported on this platform");
    } else {
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_support_compression_all(a));
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_open_memory(a, buff, used2));
        for (i = 0; i < 100; i++) {
            sprintf(path, "file%03d", i);
            failure("Trying to read %s", path);
            if (!assertEqualIntA(a, ARCHIVE_OK,
                archive_read_next_header(a, &ae)))
                break;
            assertEqualString(path, archive_entry_pathname(ae));
            assertEqualInt((int)datasize, archive_entry_size(ae));
        }
        assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    }
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));

    /*
     * Repeat again, with much lower compression.
     */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_bytes_per_block(a, 10));
    assertA(0 == archive_write_set_compression_lzma(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_compressor_options(a, "compression-level=0"));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used2));
    for (i = 0; i < 100; i++) {
        sprintf(path, "file%03d", i);
        assert((ae = archive_entry_new()) != NULL);
        archive_entry_copy_pathname(ae, path);
        archive_entry_set_size(ae, datasize);
        archive_entry_set_filetype(ae, AE_IFREG);
        assertA(0 == archive_write_header(a, ae));
        failure("Writing file %s", path);
        assertEqualIntA(a, datasize,
            (size_t)archive_write_data(a, data, datasize));
        archive_entry_free(ae);
    }
    archive_write_close(a);
    assert(0 == archive_write_finish(a));

    /* Level 0 really does result in larger data. */
    failure("Compression-level=0 wrote %d bytes; default wrote %d bytes",
        (int)used2, (int)used1);
    assert(used2 > used1);

    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    r = archive_read_support_compression_lzma(a);
    if (r == ARCHIVE_WARN) {
        skipping("lzma reading not fully supported on this platform");
    } else {
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_open_memory(a, buff, used2));
        for (i = 0; i < 100; i++) {
            sprintf(path, "file%03d", i);
            if (!assertEqualInt(ARCHIVE_OK,
                archive_read_next_header(a, &ae)))
                break;
            assertEqualString(path, archive_entry_pathname(ae));
            assertEqualInt((int)datasize, archive_entry_size(ae));
        }
        assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    }
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));

    /*
     * Test various premature shutdown scenarios to make sure we
     * don't crash or leak memory.
     */
    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_lzma(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_lzma(a));
    assertEqualInt(ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_lzma(a));
    assertEqualInt(ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_lzma(a));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used2));
    assertEqualInt(ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    /*
     * Clean up.
     */
    free(data);
    free(buff);
}

--- NEW FILE: test_write_disk_perms.c ---
/*-
 * 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/lib/libarchive/test/test_write_disk_perms.c,v 1.11 2008/12/06 06:01:50 kientzle Exp $");

#if ARCHIVE_VERSION_NUMBER >= 1009000 && (!defined(_WIN32) || defined(__CYGWIN__))

#define UMASK 022

static long _default_gid = -1;
static long _invalid_gid = -1;
static long _alt_gid = -1;

/*
 * To fully test SGID restores, we need three distinct GIDs to work
 * with:
 *    * the GID that files are created with by default (for the
 *      current user in the current directory)
 *    * An "alt gid" that this user can create files with
 *    * An "invalid gid" that this user is not permitted to create
 *      files with.
 * The second fails if this user doesn't belong to at least two groups;
 * the third fails if the current user is root.
 */
static void
searchgid(void)
{
    static int   _searched = 0;
    uid_t uid = getuid();
    gid_t gid = 0;
    unsigned int n;
    struct stat st;
    int fd;

    /* If we've already looked this up, we're done. */
    if (_searched)
        return;
    _searched = 1;

    /* Create a file on disk in the current default dir. */
    fd = open("test_gid", O_CREAT | O_BINARY, 0664);
    failure("Couldn't create a file for gid testing.");
    assert(fd > 0);

    /* See what GID it ended up with.  This is our "valid" GID. */
    assert(fstat(fd, &st) == 0);
    _default_gid = st.st_gid;

    /* Find a GID for which fchown() fails.  This is our "invalid" GID. */
    _invalid_gid = -1;
    /* This loop stops when we wrap the gid or examine 10,000 gids. */
    for (gid = 1, n = 1; gid == n && n < 10000 ; n++, gid++) {
        if (fchown(fd, uid, gid) != 0) {
            _invalid_gid = gid;
            break;
        }
    }

    /*
     * Find a GID for which fchown() succeeds, but which isn't the
     * default.  This is the "alternate" gid.
     */
    _alt_gid = -1;
    for (gid = 0, n = 0; gid == n && n < 10000 ; n++, gid++) {
        /* _alt_gid must be different than _default_gid */
        if (gid == (gid_t)_default_gid)
            continue;
        if (fchown(fd, uid, gid) == 0) {
            _alt_gid = gid;
            break;
        }
    }
    close(fd);
}

static int
altgid(void)
{
    searchgid();
    return (_alt_gid);
}

static int
invalidgid(void)
{
    searchgid();
    return (_invalid_gid);
}

static int
defaultgid(void)
{
    searchgid();
    return (_default_gid);
}
#endif

/*
 * Exercise permission and ownership restores.
 * In particular, try to exercise a bunch of border cases related
 * to files/dirs that already exist, SUID/SGID bits, etc.
 */

DEFINE_TEST(test_write_disk_perms)
{
#if ARCHIVE_VERSION_NUMBER < 1009000 || (defined(_WIN32) && !defined(__CYGWIN__))
    skipping("archive_write_disk interface");
#else
    struct archive *a;
    struct archive_entry *ae;
    struct stat st;

    assertUmask(UMASK);

    /*
     * Set ownership of the current directory to the group of this
     * process.  Otherwise, the SGID tests below fail if the
     * /tmp directory is owned by a group to which we don't belong
     * and we're on a system where group ownership is inherited.
     * (Because we're not allowed to SGID files with defaultgid().)
     */
    assertEqualInt(0, chown(".", getuid(), getgid()));

    /* Create an archive_write_disk object. */
    assert((a = archive_write_disk_new()) != NULL);

    /* Write a regular file to it. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file_0755");
    archive_entry_set_mode(ae, S_IFREG | 0777);
    assert(0 == archive_write_header(a, ae));
    assert(0 == archive_write_finish_entry(a));
    archive_entry_free(ae);

    /* Write a regular file, then write over it. */
    /* For files, the perms should get updated. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file_overwrite_0144");
    archive_entry_set_mode(ae, S_IFREG | 0777);
    assert(0 == archive_write_header(a, ae));
    archive_entry_free(ae);
    assert(0 == archive_write_finish_entry(a));
    /* Check that file was created with different perms. */
    assert(0 == stat("file_overwrite_0144", &st));
    failure("file_overwrite_0144: st.st_mode=%o", st.st_mode);
    assert((st.st_mode & 07777) != 0144);
    /* Overwrite, this should change the perms. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file_overwrite_0144");
    archive_entry_set_mode(ae, S_IFREG | 0144);
    assert(0 == archive_write_header(a, ae));
    archive_entry_free(ae);
    assert(0 == archive_write_finish_entry(a));

    /* Write a regular dir. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "dir_0514");
    archive_entry_set_mode(ae, S_IFDIR | 0514);
    assert(0 == archive_write_header(a, ae));
    archive_entry_free(ae);
    assert(0 == archive_write_finish_entry(a));

    /* Overwrite an existing dir. */
    /* For dir, the first perms should get left. */
    assertMakeDir("dir_overwrite_0744", 0744);
    /* Check original perms. */
    assert(0 == stat("dir_overwrite_0744", &st));
    failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
    assert((st.st_mode & 0777) == 0744);
    /* Overwrite shouldn't edit perms. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "dir_overwrite_0744");
    archive_entry_set_mode(ae, S_IFDIR | 0777);
    assert(0 == archive_write_header(a, ae));
    archive_entry_free(ae);
    assert(0 == archive_write_finish_entry(a));
    /* Make sure they're unchanged. */
    assert(0 == stat("dir_overwrite_0744", &st));
    failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
    assert((st.st_mode & 0777) == 0744);

    /* Write a regular file with SUID bit, but don't use _EXTRACT_PERM. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file_no_suid");
    archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0777);
    archive_write_disk_set_options(a, 0);
    assert(0 == archive_write_header(a, ae));
    assert(0 == archive_write_finish_entry(a));

    /* Write a regular file with ARCHIVE_EXTRACT_PERM. */
    assert(archive_entry_clear(ae) != NULL);
    archive_entry_copy_pathname(ae, "file_0777");
    archive_entry_set_mode(ae, S_IFREG | 0777);
    archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
    assert(0 == archive_write_header(a, ae));
    assert(0 == archive_write_finish_entry(a));

    /* Write a regular file with ARCHIVE_EXTRACT_PERM & SUID bit */
    assert(archive_entry_clear(ae) != NULL);
    archive_entry_copy_pathname(ae, "file_4742");
    archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
    archive_entry_set_uid(ae, getuid());
    archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
    assert(0 == archive_write_header(a, ae));
    assert(0 == archive_write_finish_entry(a));

    /*
     * Write a regular file with ARCHIVE_EXTRACT_PERM & SUID bit,
     * but wrong uid.  POSIX says you shouldn't restore SUID bit
     * unless the UID could be restored.
     */
    assert(archive_entry_clear(ae) != NULL);
    archive_entry_copy_pathname(ae, "file_bad_suid");
    archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
    archive_entry_set_uid(ae, getuid() + 1);
    archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
    assertA(0 == archive_write_header(a, ae));
    /*
     * Because we didn't ask for owner, the failure to
     * restore SUID shouldn't return a failure.
     * We check below to make sure SUID really wasn't set.
     * See more detailed comments below.
     */
    failure("Opportunistic SUID failure shouldn't return error.");
    assertEqualInt(0, archive_write_finish_entry(a));

        if (getuid() != 0) {
        assert(archive_entry_clear(ae) != NULL);
        archive_entry_copy_pathname(ae, "file_bad_suid2");
        archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
        archive_entry_set_uid(ae, getuid() + 1);
        archive_write_disk_set_options(a,
            ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
        assertA(0 == archive_write_header(a, ae));
        /* Owner change should fail here. */
        failure("Non-opportunistic SUID failure should return error.");
        assertEqualInt(ARCHIVE_WARN, archive_write_finish_entry(a));
    }

    /* Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit */
    assert(archive_entry_clear(ae) != NULL);
    archive_entry_copy_pathname(ae, "file_perm_sgid");
    archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
    archive_entry_set_gid(ae, defaultgid());
    archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
    assert(0 == archive_write_header(a, ae));
    failure("Setting SGID bit should succeed here.");
    assertEqualIntA(a, 0, archive_write_finish_entry(a));

    if (altgid() == -1) {
        /*
         * Current user must belong to at least two groups or
         * else we can't test setting the GID to another group.
         */
        skipping("Current user can't test gid restore: must belong to more than one group.");
    } else {
        /*
         * Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit
         * but without ARCHIVE_EXTRACT_OWNER.
         */
        /*
         * This is a weird case: The user has asked for permissions to
         * be restored but not asked for ownership to be restored.  As
         * a result, the default file creation will create a file with
         * the wrong group.  There are several possible behaviors for
         * libarchive in this scenario:
         *  = Set the SGID bit.  It is wrong and a security hole to
         *    set SGID with the wrong group.  Even POSIX thinks so.
         *  = Implicitly set the group.  I don't like this.
         *  = drop the SGID bit and warn (the old libarchive behavior)
         *  = drop the SGID bit and don't warn (the current libarchive
         *    behavior).
         * The current behavior sees SGID/SUID restore when you
         * don't ask for owner restore as an "opportunistic"
         * action.  That is, libarchive should do it if it can,
         * but if it can't, it's not an error.
         */
        assert(archive_entry_clear(ae) != NULL);
        archive_entry_copy_pathname(ae, "file_alt_sgid");
        archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
        archive_entry_set_uid(ae, getuid());
        archive_entry_set_gid(ae, altgid());
        archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
        assert(0 == archive_write_header(a, ae));
        failure("Setting SGID bit should fail because of group mismatch but the failure should be silent because we didn't ask for the group to be set.");
        assertEqualIntA(a, 0, archive_write_finish_entry(a));

        /*
         * As above, but add _EXTRACT_OWNER to verify that it
         * does succeed.
         */
        assert(archive_entry_clear(ae) != NULL);
        archive_entry_copy_pathname(ae, "file_alt_sgid_owner");
        archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
        archive_entry_set_uid(ae, getuid());
        archive_entry_set_gid(ae, altgid());
        archive_write_disk_set_options(a,
            ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
        assert(0 == archive_write_header(a, ae));
        failure("Setting SGID bit should succeed here.");
        assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a));
    }

    /*
     * Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit,
     * but wrong GID.  POSIX says you shouldn't restore SGID bit
     * unless the GID could be restored.
     */
    if (invalidgid() == -1) {
        /* This test always fails for root. */
        printf("Running as root: Can't test SGID failures.\n");
    } else {
        assert(archive_entry_clear(ae) != NULL);
        archive_entry_copy_pathname(ae, "file_bad_sgid");
        archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
        archive_entry_set_gid(ae, invalidgid());
        archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
        assertA(0 == archive_write_header(a, ae));
        failure("This SGID restore should fail without an error.");
        assertEqualIntA(a, 0, archive_write_finish_entry(a));

        assert(archive_entry_clear(ae) != NULL);
        archive_entry_copy_pathname(ae, "file_bad_sgid2");
        archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
        archive_entry_set_gid(ae, invalidgid());
        archive_write_disk_set_options(a,
            ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
        assertA(0 == archive_write_header(a, ae));
        failure("This SGID restore should fail with an error.");
        assertEqualIntA(a, ARCHIVE_WARN, archive_write_finish_entry(a));
    }

    /* Set ownership should fail if we're not root. */
    if (getuid() == 0) {
        printf("Running as root: Can't test setuid failures.\n");
    } else {
        assert(archive_entry_clear(ae) != NULL);
        archive_entry_copy_pathname(ae, "file_bad_owner");
        archive_entry_set_mode(ae, S_IFREG | 0744);
        archive_entry_set_uid(ae, getuid() + 1);
        archive_write_disk_set_options(a, ARCHIVE_EXTRACT_OWNER);
        assertA(0 == archive_write_header(a, ae));
        assertEqualIntA(a,ARCHIVE_WARN,archive_write_finish_entry(a));
    }

#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assert(0 == archive_write_finish(a));
#endif
    archive_entry_free(ae);

    /* Test the entries on disk. */
    assert(0 == stat("file_0755", &st));
    failure("file_0755: st.st_mode=%o", st.st_mode);
    assert((st.st_mode & 07777) == 0755);

    assert(0 == stat("file_overwrite_0144", &st));
    failure("file_overwrite_0144: st.st_mode=%o", st.st_mode);
    assert((st.st_mode & 07777) == 0144);

    assert(0 == stat("dir_0514", &st));
    failure("dir_0514: st.st_mode=%o", st.st_mode);
    assert((st.st_mode & 07777) == 0514);

    assert(0 == stat("dir_overwrite_0744", &st));
    failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
    assert((st.st_mode & 0777) == 0744);

    assert(0 == stat("file_no_suid", &st));
    failure("file_0755: st.st_mode=%o", st.st_mode);
    assert((st.st_mode & 07777) == 0755);

    assert(0 == stat("file_0777", &st));
    failure("file_0777: st.st_mode=%o", st.st_mode);
    assert((st.st_mode & 07777) == 0777);

    /* SUID bit should get set here. */
    assert(0 == stat("file_4742", &st));
    failure("file_4742: st.st_mode=%o", st.st_mode);
    assert((st.st_mode & 07777) == (S_ISUID | 0742));

    /* SUID bit should NOT have been set here. */
    assert(0 == stat("file_bad_suid", &st));
    failure("file_bad_suid: st.st_mode=%o", st.st_mode);
    assert((st.st_mode & 07777) == (0742));

    /* Some things don't fail if you're root, so suppress this. */
    if (getuid() != 0) {
        /* SUID bit should NOT have been set here. */
        assert(0 == stat("file_bad_suid2", &st));
        failure("file_bad_suid2: st.st_mode=%o", st.st_mode);
        assert((st.st_mode & 07777) == (0742));
    }

    /* SGID should be set here. */
    assert(0 == stat("file_perm_sgid", &st));
    failure("file_perm_sgid: st.st_mode=%o", st.st_mode);
    assert((st.st_mode & 07777) == (S_ISGID | 0742));

    if (altgid() != -1) {
        /* SGID should not be set here. */
        assert(0 == stat("file_alt_sgid", &st));
        failure("file_alt_sgid: st.st_mode=%o", st.st_mode);
        assert((st.st_mode & 07777) == (0742));

        /* SGID should be set here. */
        assert(0 == stat("file_alt_sgid_owner", &st));
        failure("file_alt_sgid: st.st_mode=%o", st.st_mode);
        assert((st.st_mode & 07777) == (S_ISGID | 0742));
    }

    if (invalidgid() != -1) {
        /* SGID should NOT be set here. */
        assert(0 == stat("file_bad_sgid", &st));
        failure("file_bad_sgid: st.st_mode=%o", st.st_mode);
        assert((st.st_mode & 07777) == (0742));
        /* SGID should NOT be set here. */
        assert(0 == stat("file_bad_sgid2", &st));
        failure("file_bad_sgid2: st.st_mode=%o", st.st_mode);
        assert((st.st_mode & 07777) == (0742));
    }

    if (getuid() != 0) {
        assert(0 == stat("file_bad_owner", &st));
        failure("file_bad_owner: st.st_mode=%o", st.st_mode);
        assert((st.st_mode & 07777) == (0744));
        failure("file_bad_owner: st.st_uid=%d getuid()=%d",
            st.st_uid, getuid());
        /* The entry had getuid()+1, but because we're
         * not root, we should not have been able to set that. */
        assert(st.st_uid == getuid());
    }
#endif
}

--- NEW FILE: test_write_format_tar_empty.c ---
/*-
 * 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/lib/libarchive/test/test_write_format_tar_empty.c,v 1.4 2008/09/01 05:38:33 kientzle Exp $");

/*
 * Check that an "empty" tar archive is correctly created.
 */

DEFINE_TEST(test_write_format_tar_empty)
{
    struct archive *a;
    char buff[2048];
    size_t used;
    unsigned int i;

    /* USTAR format: Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    assertA(0 == archive_write_set_compression_none(a));
    assertA(0 == archive_write_set_bytes_per_block(a, 512));
    assertA(0 == archive_write_set_bytes_in_last_block(a, 512));
    assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));

    /* Close out the archive. */
    assertA(0 == archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assertA(0 == archive_write_finish(a));
#endif

#if ARCHIVE_VERSION_NUMBER < 1009000
    /* Earlier versions wrote 0-length files for empty tar archives. */
    skipping("empty tar archive size");
#else
    assert(used == 1024);
#endif
    for (i = 0; i < used; i++) {
        failure("Empty tar archive should be all nulls.");
        assert(buff[i] == 0);
    }

    /* PAX format: Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_pax(a));
    assertA(0 == archive_write_set_compression_none(a));
    assertA(0 == archive_write_set_bytes_per_block(a, 512));
    assertA(0 == archive_write_set_bytes_in_last_block(a, 512));
    assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));

    /* Close out the archive. */
    assertA(0 == archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assertA(0 == archive_write_finish(a));
#endif

#if ARCHIVE_VERSION_NUMBER < 1009000
    /* Earlier versions wrote 0-length files for empty tar archives. */
    skipping("empty tar archive size");
#else
    assertEqualInt((int)used, 1024);
#endif
    for (i = 0; i < used; i++) {
        failure("Empty tar archive should be all nulls.");
        assert(buff[i] == 0);
    }
}

--- NEW FILE: test_read_format_isozisofs_bz2.c ---
/*-
 * 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$");

/*
Execute the following command to rebuild the data for this program:
   tail -n +32 test_read_format_isozisofs_bz2.c | /bin/sh

rm -rf /tmp/iso /tmp/ziso
mkdir /tmp/iso
mkdir /tmp/iso/dir
echo "hello" >/tmp/iso/file
dd if=/dev/zero count=1 bs=12345678 >>/tmp/iso/file
ln /tmp/iso/file /tmp/iso/hardlink
(cd /tmp/iso; ln -s file symlink)
(cd /tmp/iso; ln -s /tmp/ symlink2)
(cd /tmp/iso; ln -s /tmp/../ symlink3)
(cd /tmp/iso; ln -s .././../tmp/ symlink4)
TZ=utc touch -afhm -t 197001020000.01 /tmp/iso /tmp/iso/file /tmp/iso/dir
TZ=utc touch -afhm -t 197001030000.02 /tmp/iso/symlink
mkzftree /tmp/iso /tmp/ziso
TZ=utc touch -afhm -t 197001020000.01 /tmp/ziso /tmp/ziso/file /tmp/ziso/dir
TZ=utc touch -afhm -t 197001030000.02 /tmp/ziso/symlink
mkhybrid -R -uid 1 -gid 2 -z /tmp/ziso | bzip2 > test_read_format_isozisofs_bz2.iso.bz2
F=test_read_format_isozisofs_bz2.iso.bz2
uuencode $F $F > $F.uu
exit 1

 */

DEFINE_TEST(test_read_format_isozisofs_bz2)
{
    const char *refname = "test_read_format_isozisofs_bz2.iso.bz2";
    struct archive_entry *ae;
    struct archive *a;
    const void *p;
    size_t size;
    off_t offset;
    int i;
    int r;

    extract_reference_file(refname);
    assert((a = archive_read_new()) != NULL);
    r = archive_read_support_compression_bzip2(a);
    if (r == ARCHIVE_WARN) {
        skipping("bzip2 reading not fully supported on this platform");
        assertEqualInt(0, archive_read_finish(a));
        return;
    }
    assertEqualInt(0, r);
    assertEqualInt(0, archive_read_support_format_all(a));
    assertEqualInt(ARCHIVE_OK,
        archive_read_open_filename(a, refname, 10240));

    /* Retrieve each of the 8 files on the ISO image and
     * verify that each one is what we expect. */
    for (i = 0; i < 8; ++i) {
        assertEqualInt(0, archive_read_next_header(a, &ae));

        if (strcmp(".", archive_entry_pathname(ae)) == 0) {
            /* '.' root directory. */
            assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
            assertEqualInt(2048, archive_entry_size(ae));
            /* Now, we read timestamp recorded by RRIP "TF". */
            assertEqualInt(86401, archive_entry_mtime(ae));
            assertEqualInt(0, archive_entry_mtime_nsec(ae));
            /* Now, we read links recorded by RRIP "PX". */
            assertEqualInt(3, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualIntA(a, ARCHIVE_EOF,
                archive_read_data_block(a, &p, &size, &offset));
            assertEqualInt((int)size, 0);
        } else if (strcmp("dir", archive_entry_pathname(ae)) == 0) {
            /* A directory. */
            assertEqualString("dir", archive_entry_pathname(ae));
            assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
            assertEqualInt(2048, archive_entry_size(ae));
            assertEqualInt(86401, archive_entry_mtime(ae));
            assertEqualInt(86401, archive_entry_atime(ae));
            assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("file", archive_entry_pathname(ae)) == 0) {
            /* A regular file. */
            assertEqualString("file", archive_entry_pathname(ae));
            assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
            assertEqualInt(12345684, archive_entry_size(ae));
            assertEqualInt(0,
                archive_read_data_block(a, &p, &size, &offset));
            assertEqualInt(0, offset);
            assertEqualMem(p, "hello\n", 6);
            assertEqualInt(86401, archive_entry_mtime(ae));
            assertEqualInt(86401, archive_entry_atime(ae));
            assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("hardlink", archive_entry_pathname(ae)) == 0) {
            /* A hardlink to the regular file. */
            /* Note: If "hardlink" gets returned before "file",
             * then "hardlink" will get returned as a regular file
             * and "file" will get returned as the hardlink.
             * This test should tolerate that, since it's a
             * perfectly permissible thing for libarchive to do. */
            assertEqualString("hardlink", archive_entry_pathname(ae));
            assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
            assertEqualString("file", archive_entry_hardlink(ae));
            assertEqualInt(0, archive_entry_size_is_set(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(86401, archive_entry_mtime(ae));
            assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("symlink", archive_entry_pathname(ae)) == 0) {
            /* A symlink to the regular file. */
            assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
            assertEqualString("file", archive_entry_symlink(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(172802, archive_entry_mtime(ae));
            assertEqualInt(172802, archive_entry_atime(ae));
            assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("symlink2", archive_entry_pathname(ae)) == 0) {
            /* A symlink to /tmp (an absolute path) */
            assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
            assertEqualString("/tmp", archive_entry_symlink(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("symlink3", archive_entry_pathname(ae)) == 0) {
            /* A symlink to /tmp/.. (with a ".." component) */
            assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
            assertEqualString("/tmp/..", archive_entry_symlink(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else if (strcmp("symlink4", archive_entry_pathname(ae)) == 0) {
            /* A symlink to a path with ".." and "." components */
            assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
            assertEqualString(".././../tmp",
                archive_entry_symlink(ae));
            assertEqualInt(0, archive_entry_size(ae));
            assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
            assertEqualInt(1, archive_entry_uid(ae));
            assertEqualInt(2, archive_entry_gid(ae));
        } else {
            failure("Saw a file that shouldn't have been there");
            assertEqualString(archive_entry_pathname(ae), "");
        }
    }

    /* End of archive. */
    assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae));

    /* Verify archive format. */
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_BZIP2);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ISO9660_ROCKRIDGE);

    /* Close the archive. */
    assertEqualInt(0, archive_read_close(a));
    assertEqualInt(0, archive_read_finish(a));
}



--- NEW FILE: Makefile ---
# $FreeBSD: src/lib/libarchive/test/Makefile,v 1.29 2008/12/06 07:08:08 kientzle Exp $

# Where to find the libarchive sources
LA_SRCDIR=${.CURDIR}/..
.PATH: ${LA_SRCDIR}

# Get a list of all libarchive source files
LA_SRCS!=make -f ${LA_SRCDIR}/Makefile -V SRCS

TESTS= \
    test_acl_basic.c            \
    test_acl_freebsd.c          \
    test_acl_pax.c              \
    test_archive_api_feature.c      \
    test_bad_fd.c               \
    test_compat_bzip2.c         \
    test_compat_gtar.c          \
    test_compat_gzip.c          \
    test_compat_solaris_tar_acl.c       \
    test_compat_tar_hardlink.c      \
    test_compat_xz.c            \
    test_compat_zip.c           \
    test_empty_write.c          \
    test_entry.c                \
    test_entry_strmode.c            \
    test_extattr_freebsd.c          \
    test_fuzz.c             \
    test_link_resolver.c            \
    test_open_fd.c              \
    test_open_file.c            \
    test_open_filename.c            \
    test_pax_filename_encoding.c        \
    test_read_compress_program.c        \
    test_read_data_large.c          \
    test_read_disk.c            \
    test_read_disk_entry_from_file.c    \
    test_read_extract.c         \
    test_read_file_nonexistent.c        \
    test_read_format_ar.c           \
    test_read_format_cpio_bin.c     \
    test_read_format_cpio_bin_Z.c       \
    test_read_format_cpio_bin_be.c      \
    test_read_format_cpio_bin_bz2.c     \
    test_read_format_cpio_bin_gz.c      \
    test_read_format_cpio_bin_xz.c      \
    test_read_format_cpio_odc.c     \
    test_read_format_cpio_svr4_gzip.c   \
    test_read_format_cpio_svr4c_Z.c     \
    test_read_format_empty.c        \
    test_read_format_gtar_gz.c      \
    test_read_format_gtar_lzma.c        \
    test_read_format_gtar_sparse.c      \
    test_read_format_iso_gz.c       \
    test_read_format_isojoliet_bz2.c    \
    test_read_format_isojoliet_long.c   \
    test_read_format_isojoliet_rr.c     \
    test_read_format_isorr_bz2.c        \
    test_read_format_isorr_new_bz2.c    \
    test_read_format_isozisofs_bz2.c    \
    test_read_format_mtree.c        \
    test_read_format_pax_bz2.c      \
    test_read_format_raw.c          \
    test_read_format_tar.c          \
    test_read_format_tar_empty_filename.c   \
    test_read_format_tbz.c          \
    test_read_format_tgz.c          \
    test_read_format_txz.c          \
    test_read_format_tz.c           \
    test_read_format_zip.c          \
    test_read_large.c           \
    test_read_pax_truncated.c       \
    test_read_position.c            \
    test_read_truncated.c           \
    test_tar_filenames.c            \
    test_tar_large.c            \
    test_ustar_filenames.c          \
    test_write_compress.c           \
    test_write_compress_bzip2.c     \
    test_write_compress_gzip.c      \
    test_write_compress_lzma.c      \
    test_write_compress_program.c       \
    test_write_compress_xz.c        \
    test_write_disk.c           \
    test_write_disk_failures.c      \
    test_write_disk_hardlink.c      \
    test_write_disk_perms.c         \
    test_write_disk_secure.c        \
    test_write_disk_sparse.c        \
    test_write_disk_symlink.c       \
    test_write_disk_times.c         \
    test_write_format_ar.c          \
    test_write_format_cpio.c        \
    test_write_format_cpio_empty.c      \
    test_write_format_cpio_newc.c       \
    test_write_format_cpio_odc.c        \
    test_write_format_mtree.c       \
    test_write_format_pax.c         \
    test_write_format_shar_empty.c      \
    test_write_format_tar.c         \
    test_write_format_tar_empty.c       \
    test_write_format_tar_ustar.c       \
    test_write_format_zip.c         \
    test_write_format_zip_empty.c       \
    test_write_format_zip_no_compression.c  \
    test_write_open_memory.c


# Build the test program using all libarchive sources + the test sources.
SRCS= ${LA_SRCS}                \
    ${TESTS}                \
    list.h                  \
    main.c                  \
    read_open_memory.c

NO_MAN=yes

PROG=libarchive_test
INTERNALPROG=yes  # Don't install this; it's just for testing
DPADD=${LIBBZ2} ${LIBZ}
CFLAGS+= -DPLATFORM_CONFIG_H=\"config_freebsd.h\"
LDADD= -lz -lbz2 -lmd -lcrypto
CFLAGS+= -g
CFLAGS+= -I${LA_SRCDIR} -I.

# Uncomment to build and test lzma support via liblzmadec
#CFLAGS+= -I/usr/local/include -DHAVE_LIBLZMADEC=1 -DHAVE_LZMADEC_H=1
#LDADD+= -L/usr/local/lib -llzmadec

# Uncomment to build and test lzma and xz support via liblzma
CFLAGS+= -I/usr/local/include -DHAVE_LIBLZMA=1 -DHAVE_LZMA_H=1
LDADD+= -L/usr/local/lib -llzma

# Uncomment to link against dmalloc
#LDADD+= -L/usr/local/lib -ldmalloc
#CFLAGS+= -I/usr/local/include -DUSE_DMALLOC
WARNS=6

# Build libarchive_test and run it.
check test: libarchive_test
    ./libarchive_test -r ${.CURDIR}

# list.h is just a list of all tests, as indicated by DEFINE_TEST macro lines
list.h: ${TESTS} Makefile
    (cd ${.CURDIR}; cat test_*.c) | grep DEFINE_TEST > list.h

CLEANFILES += *.out *.o *.core *~ list.h .dirstamp .depend
CLEANDIRS += .deps .libs

cleantest:
    -chmod -R +w /tmp/libarchive_test.*
    rm -rf /tmp/libarchive_test.*

.include <bsd.prog.mk>

--- NEW FILE: test_read_format_raw.c ---
/*-
 * Copyright (c) 2007 Kai Wang
 * Copyright (c) 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 "test.h"
__FBSDID("$FreeBSD$");

DEFINE_TEST(test_read_format_raw)
{
    char buff[512];
    struct archive_entry *ae;
    struct archive *a;
    const char *reffile1 = "test_read_format_raw.data";
    const char *reffile2 = "test_read_format_raw.data.Z";

    /* First, try pulling data out of an uninterpretable file. */
    extract_reference_file(reffile1);
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_raw(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_open_filename(a, reffile1, 512));

    /* First (and only!) Entry */
    assertA(0 == archive_read_next_header(a, &ae));
    assertEqualString("data", archive_entry_pathname(ae));
    /* Most fields should be unset (unknown) */
    assert(!archive_entry_size_is_set(ae));
    assert(!archive_entry_atime_is_set(ae));
    assert(!archive_entry_ctime_is_set(ae));
    assert(!archive_entry_mtime_is_set(ae));
    assertEqualInt(4, archive_read_data(a, buff, 32));
    assertEqualMem(buff, "foo\n", 4);

    /* Test EOF */
    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));


    /* Second, try the same with a compressed file. */
    extract_reference_file(reffile2);
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_raw(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_open_filename(a, reffile2, 1));

    /* First (and only!) Entry */
    assertA(0 == archive_read_next_header(a, &ae));
    assertEqualString("data", archive_entry_pathname(ae));
    /* Most fields should be unset (unknown) */
    assert(!archive_entry_size_is_set(ae));
    assert(!archive_entry_atime_is_set(ae));
    assert(!archive_entry_ctime_is_set(ae));
    assert(!archive_entry_mtime_is_set(ae));
    assertEqualInt(4, archive_read_data(a, buff, 32));
    assertEqualMem(buff, "foo\n", 4);

    /* Test EOF */
    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}

--- NEW FILE: test_write_format_tar.c ---
/*-
 * 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/lib/libarchive/test/test_write_format_tar.c,v 1.4 2008/09/01 05:38:33 kientzle Exp $");

char buff[1000000];
char buff2[64];

DEFINE_TEST(test_write_format_tar)
{
    struct archive_entry *ae;
    struct archive *a;
    char *p;
    size_t used;
    size_t blocksize;

    /* Repeat the following for a variety of odd blocksizes. */
    for (blocksize = 1; blocksize < 100000; blocksize += blocksize + 3) {
        /* Create a new archive in memory. */
        assert((a = archive_write_new()) != NULL);
        assertA(0 == archive_write_set_format_ustar(a));
        assertA(0 == archive_write_set_compression_none(a));
        assertA(0 == archive_write_set_bytes_per_block(a, (int)blocksize));
        assertA(0 == archive_write_set_bytes_in_last_block(a, (int)blocksize));
        assertA(blocksize == (size_t)archive_write_get_bytes_in_last_block(a));
        assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));
        assertA(blocksize == (size_t)archive_write_get_bytes_in_last_block(a));

        /*
         * Write a file to it.
         */
        assert((ae = archive_entry_new()) != NULL);
        archive_entry_set_mtime(ae, 1, 10);
        assert(1 == archive_entry_mtime(ae));
#if !defined(__INTERIX)
        assert(10 == archive_entry_mtime_nsec(ae));
#endif
        p = strdup("file");
        archive_entry_copy_pathname(ae, p);
        strcpy(p, "XXXX");
        free(p);
        assertEqualString("file", archive_entry_pathname(ae));
        archive_entry_set_mode(ae, S_IFREG | 0755);
        assert((S_IFREG | 0755) == archive_entry_mode(ae));
        archive_entry_set_size(ae, 8);

        assertA(0 == archive_write_header(a, ae));
        archive_entry_free(ae);
        assertA(8 == archive_write_data(a, "12345678", 9));

        /* Close out the archive. */
        assertA(0 == archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
        archive_write_finish(a);
#else
        assertA(0 == archive_write_finish(a));
#endif
        /* This calculation gives "the smallest multiple of
         * the block size that is at least 2048 bytes". */
        assert(((2048 - 1)/blocksize+1)*blocksize == used);

        /*
         * Now, read the data back.
         */
        assert((a = archive_read_new()) != NULL);
        assertA(0 == archive_read_support_format_all(a));
        assertA(0 == archive_read_support_compression_all(a));
        assertA(0 == archive_read_open_memory(a, buff, used));

        assertA(0 == archive_read_next_header(a, &ae));

        assert(1 == archive_entry_mtime(ae));
        /* Not the same as above: ustar doesn't store hi-res times. */
        assert(0 == archive_entry_mtime_nsec(ae));
        assert(0 == archive_entry_atime(ae));
        assert(0 == archive_entry_ctime(ae));
        assertEqualString("file", archive_entry_pathname(ae));
        assert((S_IFREG | 0755) == archive_entry_mode(ae));
        assert(8 == archive_entry_size(ae));
        assertA(8 == archive_read_data(a, buff2, 10));
        assert(0 == memcmp(buff2, "12345678", 8));

        /* Verify the end of the archive. */
        assert(1 == archive_read_next_header(a, &ae));
        assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
        archive_read_finish(a);
#else
        assert(0 == archive_read_finish(a));
#endif
    }
}

--- NEW FILE: test_read_format_tbz.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_tbz.c,v 1.2 2008/09/01 05:38:33 kientzle Exp $");

static unsigned char archive[] = {
'B','Z','h','9','1','A','Y','&','S','Y',237,7,140,'W',0,0,27,251,144,208,
128,0,' ','@',1,'o',128,0,0,224,'"',30,0,0,'@',0,8,' ',0,'T','2',26,163,'&',
129,160,211,212,18,'I',169,234,13,168,26,6,150,'1',155,134,'p',8,173,3,183,
'J','S',26,20,'2',222,'b',240,160,'a','>',205,'f',29,170,227,'[',179,139,
'\'','L','o',211,':',178,'0',162,134,'*','>','8',24,153,230,147,'R','?',23,
'r','E','8','P',144,237,7,140,'W'};

DEFINE_TEST(test_read_format_tbz)
{
    struct archive_entry *ae;
    struct archive *a;
    int r;

    assert((a = archive_read_new()) != NULL);
    r = archive_read_support_compression_bzip2(a);
    if (r != ARCHIVE_OK) {
        skipping("Bzip2 support");
        archive_read_finish(a);
        return;
    }
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_open_memory(a, archive, sizeof(archive)));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_BZIP2);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}



--- NEW FILE: test_read_data_large.c ---
/*-
 * 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/lib/libarchive/test/test_read_data_large.c,v 1.4 2008/09/01 05:38:33 kientzle Exp $");

/*
 * Test read/write of a 10M block of data in a single operation.
 * Uses an in-memory archive with a single 10M entry.  Exercises
 * archive_read_data() to ensure it can handle large blocks like
 * this and also exercises archive_read_data_into_fd() (which
 * had a bug relating to this, fixed in Nov 2006).
 */

#if defined(_WIN32) && !defined(__CYGWIN__)
#define open _open
#define close _close
#endif

char buff1[11000000];
char buff2[10000000];
char buff3[10000000];

DEFINE_TEST(test_read_data_large)
{
    struct archive_entry *ae;
    struct archive *a;
    char tmpfilename[] = "largefile";
    int tmpfilefd;
    FILE *f;
    unsigned int i;
    size_t used;

    /* Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    assertA(0 == archive_write_set_compression_none(a));
    assertA(0 == archive_write_open_memory(a, buff1, sizeof(buff1), &used));

    /*
     * Write a file (with random contents) to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    for (i = 0; i < sizeof(buff2); i++)
        buff2[i] = (unsigned char)rand();
    archive_entry_set_size(ae, sizeof(buff2));
    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);
    assertA(sizeof(buff2) == archive_write_data(a, buff2, sizeof(buff2)));

    /* Close out the archive. */
    assertA(0 == archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assertA(0 == archive_write_finish(a));
#endif

    /* Check that archive_read_data can handle 10*10^6 at a pop. */
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff1, sizeof(buff1)));
    assertA(0 == archive_read_next_header(a, &ae));
    failure("Wrote 10MB, but didn't read the same amount");
    assertEqualIntA(a, sizeof(buff2),archive_read_data(a, buff3, sizeof(buff3)));
    failure("Read expected 10MB, but data read didn't match what was written");
    assert(0 == memcmp(buff2, buff3, sizeof(buff3)));
    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif

    /* Check archive_read_data_into_fd */
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff1, sizeof(buff1)));
    assertA(0 == archive_read_next_header(a, &ae));
    tmpfilefd = open(tmpfilename, O_WRONLY | O_CREAT | O_BINARY, 0777);
    assert(tmpfilefd != 0);
    assertEqualIntA(a, 0, archive_read_data_into_fd(a, tmpfilefd));
    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif
    close(tmpfilefd);

    f = fopen(tmpfilename, "rb");
    assert(f != NULL);
    assertEqualInt(sizeof(buff3), fread(buff3, 1, sizeof(buff3), f));
    fclose(f);
    assert(0 == memcmp(buff2, buff3, sizeof(buff3)));
}

--- NEW FILE: test.h ---
/*
 * 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/lib/libarchive/test/test.h,v 1.10 2008/06/15 10:35:22 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>
#else
#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__)
#define strdup _strdup
#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

/* FreeBSD */
#ifdef __FreeBSD__
#include <sys/cdefs.h>  /* For __FBSDID */
#else
/* Surprisingly, some non-FreeBSD platforms define __FBSDID. */
#ifndef __FBSDID
#define __FBSDID(a)     struct _undefined_hack
#endif
#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 libarchive test harness.
 */

#include "archive.h"
#include "archive_entry.h"

/* Special customized read-from-memory interface. */
int read_open_memory(struct archive *, void *, size_t, size_t);
/* "2" version exercises a slightly different set of libarchive APIs. */
int read_open_memory2(struct archive *, void *, size_t, size_t);

/* Versions of above that accept an archive argument for additional info. */
#define assertA(e)   assertion_assert(__FILE__, __LINE__, (e), #e, (a))
#define assertEqualIntA(a,v1,v2)   \
  assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a))
#define assertEqualStringA(a,v1,v2)   \
  assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a))

--- NEW FILE: test_read_format_cpio_bin_gz.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_cpio_bin_gz.c,v 1.2 2008/09/01 05:38:33 kientzle Exp $");

static unsigned char archive[] = {
31,139,8,0,244,'M','p','C',0,3,';','^','(',202,178,177,242,173,227,11,230,
23,204,'L',12,12,12,5,206,'_','|','A','4',3,131,30,195,241,'B',6,'8','`',
132,210,220,'`','2','$',200,209,211,199,'5','H','Q','Q',145,'a',20,12,'i',
0,0,170,199,228,195,0,2,0,0};

DEFINE_TEST(test_read_format_cpio_bin_gz)
{
    struct archive_entry *ae;
    struct archive *a;
    int r;

    assert((a = archive_read_new()) != NULL);
    assertEqualInt(ARCHIVE_OK, archive_read_support_compression_all(a));
    r = archive_read_support_compression_gzip(a);
    if (r == ARCHIVE_WARN) {
        skipping("gzip reading not fully supported on this platform");
        assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
        return;
    }
    failure("archive_read_support_compression_gzip");
    assertEqualInt(ARCHIVE_OK, r);
    assertEqualInt(ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualInt(ARCHIVE_OK,
        archive_read_open_memory(a, archive, sizeof(archive)));
    assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualInt(archive_compression(a),
        ARCHIVE_COMPRESSION_GZIP);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_BIN_LE);
    assertEqualInt(ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}



--- NEW FILE: test_write_compress_xz.c ---
/*-
 * Copyright (c) 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 "test.h"
__FBSDID("$FreeBSD$");

/*
 * A basic exercise of xz reading and writing.
 *
 * TODO: Add a reference file and make sure we can decompress that.
 */

DEFINE_TEST(test_write_compress_xz)
{
    struct archive_entry *ae;
    struct archive* a;
    char *buff, *data;
    size_t buffsize, datasize;
    char path[16];
    size_t used1, used2;
    int i, r;

    buffsize = 2000000;
    assert(NULL != (buff = (char *)malloc(buffsize)));

    datasize = 10000;
    assert(NULL != (data = (char *)malloc(datasize)));
    memset(data, 0, datasize);

    /*
     * Write a 100 files and read them all back.
     */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    r = archive_write_set_compression_xz(a);
    if (r == ARCHIVE_FATAL) {
        skipping("xz writing not supported on this platform");
        assertEqualInt(ARCHIVE_OK, archive_write_finish(a));
        return;
    }
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_bytes_per_block(a, 10));
    assertEqualInt(ARCHIVE_COMPRESSION_XZ, archive_compression(a));
    assertEqualString("xz", archive_compression_name(a));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used1));
    assertEqualInt(ARCHIVE_COMPRESSION_XZ, archive_compression(a));
    assertEqualString("xz", archive_compression_name(a));
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_filetype(ae, AE_IFREG);
    archive_entry_set_size(ae, datasize);
    for (i = 0; i < 100; i++) {
        sprintf(path, "file%03d", i);
        archive_entry_copy_pathname(ae, path);
        assertA(0 == archive_write_header(a, ae));
        assertA(datasize
            == (size_t)archive_write_data(a, data, datasize));
    }
    archive_entry_free(ae);
    archive_write_close(a);
    assert(0 == archive_write_finish(a));

    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    r = archive_read_support_compression_xz(a);
    if (r == ARCHIVE_WARN) {
        skipping("Can't verify xz writing by reading back;"
            " xz reading not fully supported on this platform");
    } else {
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_support_compression_all(a));
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_open_memory(a, buff, used1));
        for (i = 0; i < 100; i++) {
            sprintf(path, "file%03d", i);
            if (!assertEqualInt(ARCHIVE_OK,
                archive_read_next_header(a, &ae)))
                break;
            assertEqualString(path, archive_entry_pathname(ae));
            assertEqualInt((int)datasize, archive_entry_size(ae));
        }
        assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    }
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));

    /*
     * Repeat the cycle again, this time setting some compression
     * options.
     */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_bytes_per_block(a, 10));
    assertA(0 == archive_write_set_compression_xz(a));
    assertEqualIntA(a, ARCHIVE_WARN,
        archive_write_set_compressor_options(a, "nonexistent-option=0"));
    assertEqualIntA(a, ARCHIVE_WARN,
        archive_write_set_compressor_options(a, "compression-level=abc"));
    assertEqualIntA(a, ARCHIVE_WARN,
        archive_write_set_compressor_options(a, "compression-level=99"));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_compressor_options(a, "compression-level=9"));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used2));
    for (i = 0; i < 100; i++) {
        sprintf(path, "file%03d", i);
        assert((ae = archive_entry_new()) != NULL);
        archive_entry_copy_pathname(ae, path);
        archive_entry_set_size(ae, datasize);
        archive_entry_set_filetype(ae, AE_IFREG);
        assertA(0 == archive_write_header(a, ae));
        assertA(datasize == (size_t)archive_write_data(a, data, datasize));
        archive_entry_free(ae);
    }
    archive_write_close(a);
    assert(0 == archive_write_finish(a));

    /* Curiously, this test fails; the test data above compresses
     * better at default compression than at level 9. */
    /*
    failure("compression-level=9 wrote %d bytes, default wrote %d bytes",
        (int)used2, (int)used1);
    assert(used2 < used1);
    */

    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    r = archive_read_support_compression_xz(a);
    if (r == ARCHIVE_WARN) {
        skipping("xz reading not fully supported on this platform");
    } else {
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_support_compression_all(a));
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_open_memory(a, buff, used2));
        for (i = 0; i < 100; i++) {
            sprintf(path, "file%03d", i);
            failure("Trying to read %s", path);
            if (!assertEqualIntA(a, ARCHIVE_OK,
                archive_read_next_header(a, &ae)))
                break;
            assertEqualString(path, archive_entry_pathname(ae));
            assertEqualInt((int)datasize, archive_entry_size(ae));
        }
        assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    }
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));

    /*
     * Repeat again, with much lower compression.
     */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_bytes_per_block(a, 10));
    assertA(0 == archive_write_set_compression_xz(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_compressor_options(a, "compression-level=0"));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used2));
    for (i = 0; i < 100; i++) {
        sprintf(path, "file%03d", i);
        assert((ae = archive_entry_new()) != NULL);
        archive_entry_copy_pathname(ae, path);
        archive_entry_set_size(ae, datasize);
        archive_entry_set_filetype(ae, AE_IFREG);
        assertA(0 == archive_write_header(a, ae));
        failure("Writing file %s", path);
        assertEqualIntA(a, datasize,
            (size_t)archive_write_data(a, data, datasize));
        archive_entry_free(ae);
    }
    archive_write_close(a);
    assert(0 == archive_write_finish(a));

    /* Level 0 really does result in larger data. */
    failure("Compression-level=0 wrote %d bytes; default wrote %d bytes",
        (int)used2, (int)used1);
    assert(used2 > used1);

    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    r = archive_read_support_compression_xz(a);
    if (r == ARCHIVE_WARN) {
        skipping("xz reading not fully supported on this platform");
    } else {
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_open_memory(a, buff, used2));
        for (i = 0; i < 100; i++) {
            sprintf(path, "file%03d", i);
            if (!assertEqualInt(ARCHIVE_OK,
                archive_read_next_header(a, &ae)))
                break;
            assertEqualString(path, archive_entry_pathname(ae));
            assertEqualInt((int)datasize, archive_entry_size(ae));
        }
        assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    }
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));

    /*
     * Test various premature shutdown scenarios to make sure we
     * don't crash or leak memory.
     */
    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_xz(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_xz(a));
    assertEqualInt(ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_xz(a));
    assertEqualInt(ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_xz(a));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used2));
    assertEqualInt(ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    /*
     * Clean up.
     */
    free(data);
    free(buff);
}

--- NEW FILE: test_link_resolver.c ---
/*-
 * 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/lib/libarchive/test/test_link_resolver.c,v 1.2 2008/06/15 04:31:43 kientzle Exp $");

static void test_linkify_tar(void)
{
    struct archive_entry *entry, *e2;
    struct archive_entry_linkresolver *resolver;

    /* Initialize the resolver. */
    assert(NULL != (resolver = archive_entry_linkresolver_new()));
    archive_entry_linkresolver_set_strategy(resolver,
        ARCHIVE_FORMAT_TAR_USTAR);

    /* Create an entry with only 1 link and try to linkify it. */
    assert(NULL != (entry = archive_entry_new()));
    archive_entry_set_pathname(entry, "test1");
    archive_entry_set_ino(entry, 1);
    archive_entry_set_dev(entry, 2);
    archive_entry_set_nlink(entry, 1);
    archive_entry_set_size(entry, 10);
    archive_entry_linkify(resolver, &entry, &e2);

    /* Shouldn't have been changed. */
    assert(e2 == NULL);
    assertEqualInt(10, archive_entry_size(entry));
    assertEqualString("test1", archive_entry_pathname(entry));

    /* Now, try again with an entry that has 2 links. */
    archive_entry_set_pathname(entry, "test2");
    archive_entry_set_nlink(entry, 2);
    archive_entry_set_ino(entry, 2);
    archive_entry_linkify(resolver, &entry, &e2);
    /* Shouldn't be altered, since it wasn't seen before. */
    assert(e2 == NULL);
    assertEqualString("test2", archive_entry_pathname(entry));
    assertEqualString(NULL, archive_entry_hardlink(entry));
    assertEqualInt(10, archive_entry_size(entry));

    /* Match again and make sure it does get altered. */
    archive_entry_linkify(resolver, &entry, &e2);
    assert(e2 == NULL);
    assertEqualString("test2", archive_entry_pathname(entry));
    assertEqualString("test2", archive_entry_hardlink(entry));
    assertEqualInt(0, archive_entry_size(entry));


    /* Dirs should never be matched as hardlinks, regardless. */
    archive_entry_set_pathname(entry, "test3");
    archive_entry_set_nlink(entry, 2);
    archive_entry_set_filetype(entry, AE_IFDIR);
    archive_entry_set_ino(entry, 3);
    archive_entry_set_hardlink(entry, NULL);
    archive_entry_linkify(resolver, &entry, &e2);
    /* Shouldn't be altered, since it wasn't seen before. */
    assert(e2 == NULL);
    assertEqualString("test3", archive_entry_pathname(entry));
    assertEqualString(NULL, archive_entry_hardlink(entry));

    /* Dir, so it shouldn't get matched. */
    archive_entry_linkify(resolver, &entry, &e2);
    assert(e2 == NULL);
    assertEqualString("test3", archive_entry_pathname(entry));
    assertEqualString(NULL, archive_entry_hardlink(entry));

    archive_entry_free(entry);
    archive_entry_linkresolver_free(resolver);
}

static void test_linkify_old_cpio(void)
{
    struct archive_entry *entry, *e2;
    struct archive_entry_linkresolver *resolver;

    /* Initialize the resolver. */
    assert(NULL != (resolver = archive_entry_linkresolver_new()));
    archive_entry_linkresolver_set_strategy(resolver,
        ARCHIVE_FORMAT_CPIO_POSIX);

    /* Create an entry with 2 link and try to linkify it. */
    assert(NULL != (entry = archive_entry_new()));
    archive_entry_set_pathname(entry, "test1");
    archive_entry_set_ino(entry, 1);
    archive_entry_set_dev(entry, 2);
    archive_entry_set_nlink(entry, 2);
    archive_entry_set_size(entry, 10);
    archive_entry_linkify(resolver, &entry, &e2);

    /* Shouldn't have been changed. */
    assert(e2 == NULL);
    assertEqualInt(10, archive_entry_size(entry));
    assertEqualString("test1", archive_entry_pathname(entry));

    /* Still shouldn't be matched. */
    archive_entry_linkify(resolver, &entry, &e2);
    assert(e2 == NULL);
    assertEqualString("test1", archive_entry_pathname(entry));
    assertEqualString(NULL, archive_entry_hardlink(entry));
    assertEqualInt(10, archive_entry_size(entry));

    archive_entry_free(entry);
    archive_entry_linkresolver_free(resolver);
}

static void test_linkify_new_cpio(void)
{
    struct archive_entry *entry, *e2;
    struct archive_entry_linkresolver *resolver;

    /* Initialize the resolver. */
    assert(NULL != (resolver = archive_entry_linkresolver_new()));
    archive_entry_linkresolver_set_strategy(resolver,
        ARCHIVE_FORMAT_CPIO_SVR4_NOCRC);

    /* Create an entry with only 1 link and try to linkify it. */
    assert(NULL != (entry = archive_entry_new()));
    archive_entry_set_pathname(entry, "test1");
    archive_entry_set_ino(entry, 1);
    archive_entry_set_dev(entry, 2);
    archive_entry_set_nlink(entry, 1);
    archive_entry_set_size(entry, 10);
    archive_entry_linkify(resolver, &entry, &e2);

    /* Shouldn't have been changed. */
    assert(e2 == NULL);
    assertEqualInt(10, archive_entry_size(entry));
    assertEqualString("test1", archive_entry_pathname(entry));

    /* Now, try again with an entry that has 3 links. */
    archive_entry_set_pathname(entry, "test2");
    archive_entry_set_nlink(entry, 3);
    archive_entry_set_ino(entry, 2);
    archive_entry_linkify(resolver, &entry, &e2);

    /* First time, it just gets swallowed. */
    assert(entry == NULL);
    assert(e2 == NULL);

    /* Match again. */
    assert(NULL != (entry = archive_entry_new()));
    archive_entry_set_pathname(entry, "test3");
    archive_entry_set_ino(entry, 2);
    archive_entry_set_dev(entry, 2);
    archive_entry_set_nlink(entry, 2);
    archive_entry_set_size(entry, 10);
    archive_entry_linkify(resolver, &entry, &e2);

    /* Should get back "test2" and nothing else. */
    assertEqualString("test2", archive_entry_pathname(entry));
    assertEqualInt(0, archive_entry_size(entry));
    archive_entry_free(entry);
    assert(NULL == e2);
    archive_entry_free(e2); /* This should be a no-op. */

    /* Match a third time. */
    assert(NULL != (entry = archive_entry_new()));
    archive_entry_set_pathname(entry, "test4");
    archive_entry_set_ino(entry, 2);
    archive_entry_set_dev(entry, 2);
    archive_entry_set_nlink(entry, 3);
    archive_entry_set_size(entry, 10);
    archive_entry_linkify(resolver, &entry, &e2);

    /* Should get back "test3". */
    assertEqualString("test3", archive_entry_pathname(entry));
    assertEqualInt(0, archive_entry_size(entry));

    /* Since "test4" was the last link, should get it back also. */
    assertEqualString("test4", archive_entry_pathname(e2));
    assertEqualInt(10, archive_entry_size(e2));

    archive_entry_free(entry);
    archive_entry_free(e2);
    archive_entry_linkresolver_free(resolver);
}

DEFINE_TEST(test_link_resolver)
{
    test_linkify_tar();
    test_linkify_old_cpio();
    test_linkify_new_cpio();
}

--- NEW FILE: test_read_format_gtar_sparse_1_17_posix00.tar.uu ---
begin 644 test_read_format_gtar_sparse_1_17_posix00.tar
M+B]087A(96%D97)S+C,X-C4Y+W-P87)S90``````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#`P,#`V-#0`,#`P,3<U,``P,#`Q-S4P`#`P,#`P,#`P-#`R
M`#$P-S,S,3`Q,30R`#`Q,S0W,``@>```````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<@`P,```````
M````````````````````````````````````````````````````````````
M```````````````````P,#`P,#`P`#`P,#`P,#``````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````R-R!'3E4N<W!A<G-E+G-I>F4],S$T-3<R.`HR
M-B!'3E4N<W!A<G-E+FYU;6)L;V-K<STS"C(X($=.52YS<&%R<V4N;V9F<V5T
M/3DY.3DS- at HR-R!'3E4N<W!A<G-E+FYU;6)Y=&5S/34Q, at HR.2!'3E4N<W!A
M<G-E+F]F9G-E=#TQ.3DY.#<R"C(W($=.52YS<&%R<V4N;G5M8GET97,]-3$R
M"C(Y($=.52YS<&%R<V4N;V9F<V5T/3,Q-#4W,C@*,C4 at 1TY5+G-P87)S92YN
M=6UB>71E<STP"C(P(&%T:6UE/3$Q.3 at R.3,V,#$*,C`@8W1I;64],3$Y.#(Y
M,S8P,`H`````````````````````````````````````````````````````
[...1557 lines suppressed...]
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
H````````````````````````````````````````````````````````
`
end

--- NEW FILE: test_read_format_iso_gz.iso.gz.uu ---
begin 755 test_read_format_iso_gz.iso.gz
M'XL(",E2<$,``W1E<W0M<F5A9%]F;W)M870N:7-O`.W;WVO30!P`\-072WT4
MJ8^'#Z+ at VK1=5[JWK4FWSOZ09!/V)`4[&#(+Z_#OW7^BZ681'=L8#"?S\R&Y
MN]Q=DCL("=^#1!$`````````````````````````````````````````4.HE
M<=PH1?W3V6P[3\)U>DDV&5W;&L+J>O%OV0WW+;;E'I7+4>6RJO+\5_.+9?(J
MJEX>5:/R,BM'Q\^>5E^^.W^R.O^&`?$7C-X/\DD_#T4:NAL;<7VW..@/AFE^
MF.^GH[!],!@F:19>+Y^?M#?)DJ*PEM63CT4A2[?V)UEXTWL;&MUN*Z2UP\G!
M>"?9&J:KRD[8JWU(M[)\,J[OU?+>[F`X'(QW'FJZS3AN-QIQI]EJKK<[<7Q^
MI2+^0W2E1REZJ-'S;[B/US;<B^\_O_\`P/^CB.#":/XUC.??0NB$9FNSN;[9
M[ER$.I63+\>+^=$B-&MQK176YN%LMCA;.YU-/W\ZFI^>3,]J17N8/O0<`("[
M*5VLL8O_`0``X#&[B/RK%@````#@,;O]'[M;>U@[````````````````````
M`````````````````````````````````````````````.#.?@")(\.V`(`!
!````
`
end

--- NEW FILE: test_write_format_pax.c ---
/*-
 * 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"
__FBSDID("$FreeBSD$");

char buff2[64];

DEFINE_TEST(test_write_format_pax)
{
    size_t buffsize = 1000000;
    char *buff;
    struct archive_entry *ae;
    struct archive *a;
    size_t used;

    buff = malloc(buffsize); /* million bytes of work area */
    assert(buff != NULL);

    /* Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_pax(a));
    assertA(0 == archive_write_set_compression_none(a));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used));

    /*
     * "file" has a bunch of attributes and 8 bytes of data.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_atime(ae, 2, 20);
    archive_entry_set_birthtime(ae, 3, 30);
    archive_entry_set_ctime(ae, 4, 40);
    archive_entry_set_mtime(ae, 5, 50);
    archive_entry_copy_pathname(ae, "file");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    archive_entry_set_size(ae, 8);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
    archive_entry_free(ae);
    assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9));

    /*
     * "file2" is similar but has birthtime later than mtime.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_atime(ae, 2, 20);
    archive_entry_set_birthtime(ae, 8, 80);
    archive_entry_set_ctime(ae, 4, 40);
    archive_entry_set_mtime(ae, 5, 50);
    archive_entry_copy_pathname(ae, "file2");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    archive_entry_set_size(ae, 8);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
    archive_entry_free(ae);
    assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9));

    /*
     * XXX TODO XXX Archive directory, other file types.
     * Archive extended attributes, ACLs, other metadata.
     * Verify they get read back correctly.
     */

    /* Close out the archive. */
    assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_write_finish(a));

    /*
     *
     * Now, read the data back.
     *
     */
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, 0, archive_read_support_format_all(a));
    assertEqualIntA(a, 0, archive_read_support_compression_all(a));
    assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used));

    /*
     * Read "file"
     */
    assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
    assertEqualInt(2, archive_entry_atime(ae));
    assertEqualInt(20, archive_entry_atime_nsec(ae));
    assertEqualInt(3, archive_entry_birthtime(ae));
    assertEqualInt(30, archive_entry_birthtime_nsec(ae));
    assertEqualInt(4, archive_entry_ctime(ae));
    assertEqualInt(40, archive_entry_ctime_nsec(ae));
    assertEqualInt(5, archive_entry_mtime(ae));
    assertEqualInt(50, archive_entry_mtime_nsec(ae));
    assertEqualString("file", archive_entry_pathname(ae));
    assert((S_IFREG | 0755) == archive_entry_mode(ae));
    assertEqualInt(8, archive_entry_size(ae));
    assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
    assertEqualMem(buff2, "12345678", 8);

    /*
     * Read "file2"
     */
    assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
    assert(archive_entry_atime_is_set(ae));
    assertEqualInt(2, archive_entry_atime(ae));
    assertEqualInt(20, archive_entry_atime_nsec(ae));
    /* Birthtime > mtime above, so it doesn't get stored at all. */
    assert(!archive_entry_birthtime_is_set(ae));
    assertEqualInt(0, archive_entry_birthtime(ae));
    assertEqualInt(0, archive_entry_birthtime_nsec(ae));
    assert(archive_entry_ctime_is_set(ae));
    assertEqualInt(4, archive_entry_ctime(ae));
    assertEqualInt(40, archive_entry_ctime_nsec(ae));
    assert(archive_entry_mtime_is_set(ae));
    assertEqualInt(5, archive_entry_mtime(ae));
    assertEqualInt(50, archive_entry_mtime_nsec(ae));
    assertEqualString("file2", archive_entry_pathname(ae));
    assert((S_IFREG | 0755) == archive_entry_mode(ae));
    assertEqualInt(8, archive_entry_size(ae));
    assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
    assertEqualMem(buff2, "12345678", 8);

    /*
     * Verify the end of the archive.
     */
    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_finish(a));

    free(buff);
}

--- NEW FILE: test_pax_filename_encoding.c ---
/*-
 * 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/lib/libarchive/test/test_pax_filename_encoding.c,v 1.3 2008/08/11 01:19:36 kientzle Exp $");

#include <locale.h>

/*
 * Pax interchange is supposed to encode filenames into
 * UTF-8.  Of course, that's not always possible.  This
 * test is intended to verify that filenames always get
 * stored and restored correctly, regardless of the encodings.
 */

/*
 * Read a manually-created archive that has filenames that are
 * stored in binary instead of UTF-8 and verify that we get
 * the right filename returned and that we get a warning only
 * if the header isn't marked as binary.
 */
static void
test_pax_filename_encoding_1(void)
{
    static const char testname[] = "test_pax_filename_encoding.tar";
    /*
     * \314\214 is a valid 2-byte UTF-8 sequence.
     * \374 is invalid in UTF-8.
     */
    char filename[] = "abc\314\214mno\374xyz";
    struct archive *a;
    struct archive_entry *entry;

    /*
     * Read an archive that has non-UTF8 pax filenames in it.
     */
    extract_reference_file(testname);
    a = archive_read_new();
    assertEqualInt(ARCHIVE_OK, archive_read_support_format_tar(a));
    assertEqualInt(ARCHIVE_OK, archive_read_support_compression_all(a));
    assertEqualInt(ARCHIVE_OK,
        archive_read_open_filename(a, testname, 10240));
    /*
     * First entry in this test archive has an invalid UTF-8 sequence
     * in it, but the header is not marked as hdrcharset=BINARY, so that
     * requires a warning.
     */
    failure("Invalid UTF8 in a pax archive pathname should cause a warning");
    assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry));
    assertEqualString(filename, archive_entry_pathname(entry));
    /*
     * Second entry is identical except that it does have
     * hdrcharset=BINARY, so no warning should be generated.
     */
    failure("A pathname with hdrcharset=BINARY can have invalid UTF8\n"
        " characters in it without generating a warning");
    assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &entry));
    assertEqualString(filename, archive_entry_pathname(entry));
    archive_read_finish(a);
}

/*
 * Set the locale and write a pathname containing invalid characters.
 * This should work; the underlying implementation should automatically
 * fall back to storing the pathname in binary.
 */
static void
test_pax_filename_encoding_2(void)
{
    char filename[] = "abc\314\214mno\374xyz";
    struct archive *a;
    struct archive_entry *entry;
    char buff[65536];
    char longname[] = "abc\314\214mno\374xyz"
        "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
        "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
        "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
        "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
        "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
        "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
        ;
    size_t used;

    /*
     * We need a starting locale which has invalid sequences.
     * de_DE.UTF-8 seems to be commonly supported.
     */
    /* If it doesn't exist, just warn and return. */
    if (NULL == setlocale(LC_ALL, LOCALE_DE)) {
        skipping("invalid encoding tests require a suitable locale;"
            " %s not available on this system", LOCALE_DE);
        return;
    }

    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, 0, archive_write_set_format_pax(a));
    assertEqualIntA(a, 0, archive_write_set_compression_none(a));
    assertEqualIntA(a, 0, archive_write_set_bytes_per_block(a, 0));
    assertEqualInt(0,
        archive_write_open_memory(a, buff, sizeof(buff), &used));

    assert((entry = archive_entry_new()) != NULL);
    /* Set pathname, gname, uname, hardlink to nonconvertible values. */
    archive_entry_copy_pathname(entry, filename);
    archive_entry_copy_gname(entry, filename);
    archive_entry_copy_uname(entry, filename);
    archive_entry_copy_hardlink(entry, filename);
    archive_entry_set_filetype(entry, AE_IFREG);
    failure("This should generate a warning for nonconvertible names.");
    assertEqualInt(ARCHIVE_WARN, archive_write_header(a, entry));
    archive_entry_free(entry);

    assert((entry = archive_entry_new()) != NULL);
    /* Set path, gname, uname, and symlink to nonconvertible values. */
    archive_entry_copy_pathname(entry, filename);
    archive_entry_copy_gname(entry, filename);
    archive_entry_copy_uname(entry, filename);
    archive_entry_copy_symlink(entry, filename);
    archive_entry_set_filetype(entry, AE_IFLNK);
    failure("This should generate a warning for nonconvertible names.");
    assertEqualInt(ARCHIVE_WARN, archive_write_header(a, entry));
    archive_entry_free(entry);

    assert((entry = archive_entry_new()) != NULL);
    /* Set pathname to a very long nonconvertible value. */
    archive_entry_copy_pathname(entry, longname);
    archive_entry_set_filetype(entry, AE_IFREG);
    failure("This should generate a warning for nonconvertible names.");
    assertEqualInt(ARCHIVE_WARN, archive_write_header(a, entry));
    archive_entry_free(entry);

    assertEqualInt(0, archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assertEqualInt(0, archive_write_finish(a));
#endif

    /*
     * Now read the entries back.
     */

    assert((a = archive_read_new()) != NULL);
    assertEqualInt(0, archive_read_support_format_tar(a));
    assertEqualInt(0, archive_read_open_memory(a, buff, used));

    assertEqualInt(0, archive_read_next_header(a, &entry));
    assertEqualString(filename, archive_entry_pathname(entry));
    assertEqualString(filename, archive_entry_gname(entry));
    assertEqualString(filename, archive_entry_uname(entry));
    assertEqualString(filename, archive_entry_hardlink(entry));

    assertEqualInt(0, archive_read_next_header(a, &entry));
    assertEqualString(filename, archive_entry_pathname(entry));
    assertEqualString(filename, archive_entry_gname(entry));
    assertEqualString(filename, archive_entry_uname(entry));
    assertEqualString(filename, archive_entry_symlink(entry));

    assertEqualInt(0, archive_read_next_header(a, &entry));
    assertEqualString(longname, archive_entry_pathname(entry));

    assertEqualInt(0, archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertEqualInt(0, archive_read_finish(a));
#endif
}

/*
 * Create an entry starting from a wide-character Unicode pathname,
 * read it back into "C" locale, which doesn't support the name.
 * TODO: Figure out the "right" behavior here.
 */
static void
test_pax_filename_encoding_3(void)
{
    wchar_t badname[] = L"xxxAyyyBzzz";
    const char badname_utf8[] = "xxx\xE1\x88\xB4yyy\xE5\x99\xB8zzz";
    struct archive *a;
    struct archive_entry *entry;
    char buff[65536];
    size_t used;

    badname[3] = 0x1234;
    badname[7] = 0x5678;

    /* If it doesn't exist, just warn and return. */
    if (NULL == setlocale(LC_ALL, "C")) {
        skipping("Can't set \"C\" locale, so can't exercise "
            "certain character-conversion failures");
        return;
    }

    /* If wctomb is broken, warn and return. */
    if (wctomb(buff, 0x1234) > 0) {
        skipping("Cannot test conversion failures because \"C\" "
            "locale on this system has no invalid characters.");
        return;
    }

    /* If wctomb is broken, warn and return. */
    if (wctomb(buff, 0x1234) > 0) {
        skipping("Cannot test conversion failures because \"C\" "
            "locale on this system has no invalid characters.");
        return;
    }

    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, 0, archive_write_set_format_pax(a));
    assertEqualIntA(a, 0, archive_write_set_compression_none(a));
    assertEqualIntA(a, 0, archive_write_set_bytes_per_block(a, 0));
    assertEqualInt(0,
        archive_write_open_memory(a, buff, sizeof(buff), &used));

    assert((entry = archive_entry_new()) != NULL);
    /* Set pathname to non-convertible wide value. */
    archive_entry_copy_pathname_w(entry, badname);
    archive_entry_set_filetype(entry, AE_IFREG);
    assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
    archive_entry_free(entry);

    assert((entry = archive_entry_new()) != NULL);
    archive_entry_copy_pathname_w(entry, L"abc");
    /* Set gname to non-convertible wide value. */
    archive_entry_copy_gname_w(entry, badname);
    archive_entry_set_filetype(entry, AE_IFREG);
    assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
    archive_entry_free(entry);

    assert((entry = archive_entry_new()) != NULL);
    archive_entry_copy_pathname_w(entry, L"abc");
    /* Set uname to non-convertible wide value. */
    archive_entry_copy_uname_w(entry, badname);
    archive_entry_set_filetype(entry, AE_IFREG);
    assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
    archive_entry_free(entry);

    assert((entry = archive_entry_new()) != NULL);
    archive_entry_copy_pathname_w(entry, L"abc");
    /* Set hardlink to non-convertible wide value. */
    archive_entry_copy_hardlink_w(entry, badname);
    archive_entry_set_filetype(entry, AE_IFREG);
    assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
    archive_entry_free(entry);

    assert((entry = archive_entry_new()) != NULL);
    archive_entry_copy_pathname_w(entry, L"abc");
    /* Set symlink to non-convertible wide value. */
    archive_entry_copy_symlink_w(entry, badname);
    archive_entry_set_filetype(entry, AE_IFLNK);
    assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
    archive_entry_free(entry);

    assertEqualInt(0, archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assertEqualInt(0, archive_write_finish(a));
#endif

    /*
     * Now read the entries back.
     */

    assert((a = archive_read_new()) != NULL);
    assertEqualInt(0, archive_read_support_format_tar(a));
    assertEqualInt(0, archive_read_open_memory(a, buff, used));

    failure("A non-convertible pathname should cause a warning.");
    assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry));
    assertEqualWString(badname, archive_entry_pathname_w(entry));
    failure("If native locale can't convert, we should get UTF-8 back.");
    assertEqualString(badname_utf8, archive_entry_pathname(entry));

    failure("A non-convertible gname should cause a warning.");
    assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry));
    assertEqualWString(badname, archive_entry_gname_w(entry));
    failure("If native locale can't convert, we should get UTF-8 back.");
    assertEqualString(badname_utf8, archive_entry_gname(entry));

    failure("A non-convertible uname should cause a warning.");
    assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry));
    assertEqualWString(badname, archive_entry_uname_w(entry));
    failure("If native locale can't convert, we should get UTF-8 back.");
    assertEqualString(badname_utf8, archive_entry_uname(entry));

    failure("A non-convertible hardlink should cause a warning.");
    assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry));
    assertEqualWString(badname, archive_entry_hardlink_w(entry));
    failure("If native locale can't convert, we should get UTF-8 back.");
    assertEqualString(badname_utf8, archive_entry_hardlink(entry));

    failure("A non-convertible symlink should cause a warning.");
    assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry));
    assertEqualWString(badname, archive_entry_symlink_w(entry));
    assertEqualWString(NULL, archive_entry_hardlink_w(entry));
    failure("If native locale can't convert, we should get UTF-8 back.");
    assertEqualString(badname_utf8, archive_entry_symlink(entry));

    assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &entry));

    assertEqualInt(0, archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertEqualInt(0, archive_read_finish(a));
#endif
}

DEFINE_TEST(test_pax_filename_encoding)
{
    test_pax_filename_encoding_1();
    test_pax_filename_encoding_2();
    test_pax_filename_encoding_3();
}

--- NEW FILE: test_read_format_cpio_svr4c_Z.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_cpio_svr4c_Z.c,v 1.2 2008/09/01 05:38:33 kientzle Exp $");

static unsigned char archive[] = {
31,157,144,'0','n',4,132,'!',3,6,140,26,'8','n',228,16,19,195,160,'A',26,
'1',202,144,'q','h','p','F',25,28,20,'a','X',196,152,145,' ',141,25,2,'k',
192,160,'A',163,163,201,135,29,'c',136,'<',201,'2','c','A',147,'.',0,12,20,
248,178,165,205,155,20,27,226,220,201,243,166,152,147,'T',164,4,'I',194,164,
136,148,16,'H',1,'(',']',202,180,169,211,167,'P',163,'J',157,'J',181,170,
213,171,'X',179,'j',221,202,181,171,215,175,'L',1};

DEFINE_TEST(test_read_format_cpio_svr4c_Z)
{
    struct archive_entry *ae;
    struct archive *a;
/*  printf("Archive address: start=%X, end=%X\n", archive, archive+sizeof(archive)); */
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_open_memory(a, archive, sizeof(archive)));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    failure("archive_compression_name(a)=\"%s\"",
        archive_compression_name(a));
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_COMPRESS);
    failure("archive_format_name(a)=\"%s\"", archive_format_name(a));
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_SVR4_CRC);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
#endif
}



--- NEW FILE: test_read_extract.c ---
/*-
 * 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/lib/libarchive/test/test_read_extract.c,v 1.5 2008/09/01 05:38:33 kientzle Exp $");

#define BUFF_SIZE 1000000
#define FILE_BUFF_SIZE 100000

DEFINE_TEST(test_read_extract)
{
    struct archive_entry *ae;
    struct archive *a;
    size_t used;
    int i, numEntries = 0;
    char *buff, *file_buff;

    buff = malloc(BUFF_SIZE);
    file_buff = malloc(FILE_BUFF_SIZE);

    /* Force the umask to something predictable. */
    assertUmask(022);

    /* Create a new archive in memory containing various types of entries. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    assertA(0 == archive_write_set_compression_none(a));
    assertA(0 == archive_write_open_memory(a, buff, BUFF_SIZE, &used));
    /* A directory to be restored with EXTRACT_PERM. */
    ++numEntries;
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "dir_0775");
    archive_entry_set_mode(ae, S_IFDIR | 0775);
    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);
    /* A regular file. */
    ++numEntries;
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    for (i = 0; i < FILE_BUFF_SIZE; i++)
        file_buff[i] = (unsigned char)rand();
    archive_entry_set_size(ae, FILE_BUFF_SIZE);
    assertA(0 == archive_write_header(a, ae));
    assertA(FILE_BUFF_SIZE == archive_write_data(a, file_buff, FILE_BUFF_SIZE));
    archive_entry_free(ae);
    /* A directory that should obey umask when restored. */
    ++numEntries;
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "dir");
    archive_entry_set_mode(ae, S_IFDIR | 0777);
    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);
    /* A file in the directory. */
    ++numEntries;
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "dir/file");
    archive_entry_set_mode(ae, S_IFREG | 0700);
    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);
    /* A file in a dir that is not already in the archive. */
    ++numEntries;
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "dir2/file");
    archive_entry_set_mode(ae, S_IFREG | 0000);
    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);
    /* A dir with a trailing /. */
    ++numEntries;
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "dir3/.");
    archive_entry_set_mode(ae, S_IFDIR | 0710);
    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);
    /* Multiple dirs with a single entry. */
    ++numEntries;
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "dir4/a/../b/../c/");
    archive_entry_set_mode(ae, S_IFDIR | 0711);
    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);
    /* A symlink. */
    if (canSymlink()) {
        ++numEntries;
        assert((ae = archive_entry_new()) != NULL);
        archive_entry_copy_pathname(ae, "symlink");
        archive_entry_set_mode(ae, AE_IFLNK | 0755);
        archive_entry_set_symlink(ae, "file");
        assertA(0 == archive_write_header(a, ae));
        archive_entry_free(ae);
    }
    /* Close out the archive. */
    assertA(0 == archive_write_close(a));
    assertA(0 == archive_write_finish(a));

    /* Extract the entries to disk. */
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff, BUFF_SIZE));
    /* Restore first entry with _EXTRACT_PERM. */
    failure("Error reading first entry", i);
    assertA(0 == archive_read_next_header(a, &ae));
    assertA(0 == archive_read_extract(a, ae, ARCHIVE_EXTRACT_PERM));
    /* Rest of entries get restored with no flags. */
    for (i = 1; i < numEntries; i++) {
        failure("Error reading entry %d", i);
        assertA(0 == archive_read_next_header(a, &ae));
        failure("Failed to extract entry %d: %s", i,
            archive_entry_pathname(ae));
        assertA(0 == archive_read_extract(a, ae, 0));
    }
    assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae));
    assert(0 == archive_read_close(a));
    assert(0 == archive_read_finish(a));

    /* Test the entries on disk. */
    /* This first entry was extracted with ARCHIVE_EXTRACT_PERM,
     * so the permissions should have been restored exactly,
     * including resetting the gid bit on those platforms
     * where gid is inherited by subdirs. */
    failure("This was 0775 in archive, and should be 0775 on disk");
    assertIsDir("dir_0775", 0775);
    /* Everything else was extracted without ARCHIVE_EXTRACT_PERM,
     * so there may be some sloppiness about gid bits on directories. */
    assertIsReg("file", 0755);
    assertFileSize("file", FILE_BUFF_SIZE);
    assertFileContents(file_buff, FILE_BUFF_SIZE, "file");
    /* If EXTRACT_PERM wasn't used, be careful to ignore sgid bit
     * when checking dir modes, as some systems inherit sgid bit
     * from the parent dir. */
    failure("This was 0777 in archive, but umask should make it 0755");
    assertIsDir("dir", 0755);
    assertIsReg("dir/file", 0700);
    assertIsDir("dir2", 0755);
    assertIsReg("dir2/file", 0000);
    assertIsDir("dir3", 0710);
    assertIsDir("dir4", 0755);
    assertIsDir("dir4/a", 0755);
    assertIsDir("dir4/b", 0755);
    assertIsDir("dir4/c", 0711);
    if (canSymlink())
        assertIsSymlink("symlink", "file");

    free(buff);
    free(file_buff);
}

--- NEW FILE: test_compat_bzip2_1.tbz.uu ---
$FreeBSD: src/lib/libarchive/test/test_compat_bzip2_1.tbz.uu,v 1.1 2008/12/06 07:08:08 kientzle Exp $

begin 644 test_compat_bzip2_1.tbz
M0EIH.3%!62936;12^)(``#-;D=$00`!_@``!8RT>$`0`$```""``5#5/*'J>
MD#(&30_5!H4_5-ZH`T``327U4@&L('"(9-%8<7&$I,`:7FXH<P(<:8)$*)(U
MZH$>+*\GV#JF<`PK29-8'OPDG36S\7<D4X4)"T4OB2!"6F at Y,4%9)E-92FB6
M4````'N4T1`$`$``?X```6,M'A`$```0``@@`'0:H]$R>HR&C(T:/U0:$U'I
MJ!ZC0`#VECO\[$10H'-Z at F*:6A1$H$V("2G0Q(U0(8=(7AK$S04#!)RXOAP%
MP:D%#Q;NO)\4UL23'2[\7<D4X4)!*:)90$)::#DQ05DF4UD;;[2>````6YC1
M$$`$?X```6,M'A`$`!````@@`'4-4S*,U!HT!HT?J at T)E-I--!H`![6<G^E$
M$5QJ!S2`*)/,*+VQ9'B0",=3$#5`CA"8<%1\7A4X$T:,-A)F5^*"X5[IR?&-
M*DDY2+\7<D4X4)`;;[2>0EIH.3%!629364RNM^,```#?L-$00`#_@`0```AG
M+1X0`!`$```((`!U#5-,:1IH`TT,1^J#)&H]3U`T``!CX[_.[`F40.64EC"D
M()+?<M#$":=,4$46`@@DBMQ)81MJACLC[V0".0,7#AH=97F?G1I at 9U))RD?Q
M=R13A0D$RNM^,$)::#DQ05DF4UDS!PL0```!6]#1$$``_X``#&<M'A`0``0`
M``@@`'4-4\2-&@`:#31^J#)3TU&U!H``!B_C_.]`)J4#F929S&D0$F:4(J50
M&#)@@5&F"H,GH(J*7*@X&>KX6,VP?6Y;F%5$XR[Y/D#*9),K3^+N2*<*$@9@
MX6(`0EIH.3%!62936>ZM4*4```);D-$00`#O@``(9ST>$`0```@@`'0:IFC2
M&F@!B:/U0:$R&H:&@`"KS^U=Y`BC`#FY2*9-8%%&13E$@%8ZF(&J!##]!#E`
MKVL'2LUW2.*<!T+W-B at 46%:=GQ<#6Q*DYH/Q=R13A0D.ZM4*4$)::#DQ05DF
M4UD!Z-!@```!P`'```"```@@`""J;4&8NH/%W)%.%"0`>C08`$)::#DQ05DF
?4UDI/)=P````0!!```0`(``A`(*#%W)%.%"0*3R7<```
`
end

--- NEW FILE: test_read_format_cpio_bin_Z.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_cpio_bin_Z.c,v 1.2 2008/09/01 05:38:33 kientzle Exp $");

static unsigned char archive[] = {
31,157,144,199,226,'T',' ',16,'+','O',187,' ',232,6,'$',20,0,160,'!',156,
'!',244,154,'0','l',216,208,5,128,128,20,'3','R',12,160,177,225,2,141,'T',
164,4,'I',194,164,136,148,16,'(',';',170,'\\',201,178,165,203,151,'0','c',
202,156,'I',179,166,205,155,'8','s',234,220,201,179,167,207,159,'@',127,2};

DEFINE_TEST(test_read_format_cpio_bin_Z)
{
    struct archive_entry *ae;
    struct archive *a;
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_open_memory(a, archive, sizeof(archive)));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    failure("archive_compression_name(a)=\"%s\"",
        archive_compression_name(a));
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_COMPRESS);
    assertEqualString(archive_compression_name(a), "compress (.Z)");
    failure("archive_format_name(a)=\"%s\"",
        archive_format_name(a));
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_BIN_LE);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
#endif
}



--- NEW FILE: test_read_large.c ---
/*-
 * 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/lib/libarchive/test/test_read_large.c,v 1.4 2008/09/01 05:38:33 kientzle Exp $");

static unsigned char testdata[10 * 1024 * 1024];
static unsigned char testdatacopy[10 * 1024 * 1024];
static unsigned char buff[11 * 1024 * 1024];

#if defined(_WIN32) && !defined(__CYGWIN__)
#define open _open
#define close _close
#endif

/* Check correct behavior on large reads. */
DEFINE_TEST(test_read_large)
{
    unsigned int i;
    int tmpfilefd;
    char tmpfilename[] = "test-read_large.XXXXXX";
    size_t used;
    struct archive *a;
    struct archive_entry *entry;
    FILE *f;

    for (i = 0; i < sizeof(testdata); i++)
        testdata[i] = (unsigned char)(rand());

    assert(NULL != (a = archive_write_new()));
    assertA(0 == archive_write_set_format_ustar(a));
    assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));
    assert(NULL != (entry = archive_entry_new()));
    archive_entry_set_size(entry, sizeof(testdata));
    archive_entry_set_mode(entry, S_IFREG | 0777);
    archive_entry_set_pathname(entry, "test");
    assertA(0 == archive_write_header(a, entry));
    archive_entry_free(entry);
    assertA(sizeof(testdata) == archive_write_data(a, testdata, sizeof(testdata)));
    assertA(0 == archive_write_finish(a));

    assert(NULL != (a = archive_read_new()));
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff, sizeof(buff)));
    assertA(0 == archive_read_next_header(a, &entry));
    assertA(0 == archive_read_data_into_buffer(a, testdatacopy, sizeof(testdatacopy)));
    assertA(0 == archive_read_finish(a));
    assert(0 == memcmp(testdata, testdatacopy, sizeof(testdata)));


    assert(NULL != (a = archive_read_new()));
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff, sizeof(buff)));
    assertA(0 == archive_read_next_header(a, &entry));
    // TODO: Provide a Windows-friendly version of this?
    assert(0 < (tmpfilefd = open(tmpfilename,
            O_WRONLY | O_CREAT | O_BINARY, 0755)));
    assertA(0 == archive_read_data_into_fd(a, tmpfilefd));
    close(tmpfilefd);
    assertA(0 == archive_read_finish(a));

    f = fopen(tmpfilename, "rb");
    fread(testdatacopy, 1, sizeof(testdatacopy), f);
    fclose(f);
    assert(0 == memcmp(testdata, testdatacopy, sizeof(testdata)));
}

--- NEW FILE: test_read_file_nonexistent.c ---
/*-
 * 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_read_file_nonexistent)
{
    struct archive* a = archive_read_new();
    assertEqualInt(ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualInt(ARCHIVE_FATAL,
        archive_read_open_filename(a, "notexistent.tar", 512));
    archive_read_finish(a);
}



--- NEW FILE: test_acl_freebsd.c ---
/*-
 * 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"
__FBSDID("$FreeBSD: src/lib/libarchive/test/test_acl_freebsd.c,v 1.2 2008/11/17 21:06:17 kientzle Exp $");

#if defined(__FreeBSD__) && __FreeBSD__ > 4
#include <sys/acl.h>

struct myacl_t {
    int type;  /* Type of ACL: "access" or "default" */
    int permset; /* Permissions for this class of users. */
    int tag; /* Owner, User, Owning group, group, other, etc. */
    int qual; /* GID or UID of user/group, depending on tag. */
    const char *name; /* Name of user/group, depending on tag. */
};

static struct myacl_t acls2[] = {
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ,
      ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
      ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0,
      ARCHIVE_ENTRY_ACL_USER, 78, "user78" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
      ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0007,
      ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
      ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_EXECUTE,
      ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
      ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_EXECUTE,
      ARCHIVE_ENTRY_ACL_MASK, -1, "" },
    { 0, 0, 0, 0, NULL }
};

static void
set_acls(struct archive_entry *ae, struct myacl_t *acls)
{
    int i;

    archive_entry_acl_clear(ae);
    for (i = 0; acls[i].name != NULL; i++) {
        archive_entry_acl_add_entry(ae,
            acls[i].type, acls[i].permset, acls[i].tag, acls[i].qual,
            acls[i].name);
    }
}

static int
acl_match(acl_entry_t aclent, struct myacl_t *myacl)
{
    gid_t g, *gp;
    uid_t u, *up;
    acl_tag_t tag_type;
    acl_permset_t opaque_ps;
    int permset = 0;

    acl_get_tag_type(aclent, &tag_type);

    /* translate the silly opaque permset to a bitmap */
    acl_get_permset(aclent, &opaque_ps);
    if (acl_get_perm_np(opaque_ps, ACL_EXECUTE))
        permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
    if (acl_get_perm_np(opaque_ps, ACL_WRITE))
        permset |= ARCHIVE_ENTRY_ACL_WRITE;
    if (acl_get_perm_np(opaque_ps, ACL_READ))
        permset |= ARCHIVE_ENTRY_ACL_READ;

    if (permset != myacl->permset)
        return (0);

    switch (tag_type) {
    case ACL_USER_OBJ:
        if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
        break;
    case ACL_USER:
        if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
            return (0);
        up = acl_get_qualifier(aclent);
        u = *up;
        acl_free(up);
        if ((uid_t)myacl->qual != u)
            return (0);
        break;
    case ACL_GROUP_OBJ:
        if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
        break;
    case ACL_GROUP:
        if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
            return (0);
        gp = acl_get_qualifier(aclent);
        g = *gp;
        acl_free(gp);
        if ((gid_t)myacl->qual != g)
            return (0);
        break;
    case ACL_MASK:
        if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
        break;
    case ACL_OTHER:
        if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0);
        break;
    }
    return (1);
}

static void
compare_acls(acl_t acl, struct myacl_t *myacls)
{
    int *marker;
    int entry_id = ACL_FIRST_ENTRY;
    int matched;
    int i, n;
    acl_entry_t acl_entry;

    /* Count ACL entries in myacls array and allocate an indirect array. */
    for (n = 0; myacls[n].name != NULL; ++n)
        continue;
    marker = malloc(sizeof(marker[0]) * n);
    for (i = 0; i < n; i++)
        marker[i] = i;

    /*
     * Iterate over acls in system acl object, try to match each
     * one with an item in the myacls array.
     */
    while (1 == acl_get_entry(acl, entry_id, &acl_entry)) {
        /* After the first time... */
        entry_id = ACL_NEXT_ENTRY;

        /* Search for a matching entry (tag and qualifier) */
        for (i = 0, matched = 0; i < n && !matched; i++) {
            if (acl_match(acl_entry, &myacls[marker[i]])) {
                /* We found a match; remove it. */
                marker[i] = marker[n - 1];
                n--;
                matched = 1;
            }
        }

        /* TODO: Print out more details in this case. */
        failure("ACL entry on file that shouldn't be there");
        assert(matched == 1);
    }

    /* Dump entries in the myacls array that weren't in the system acl. */
    for (i = 0; i < n; ++i) {
        failure(" ACL entry missing from file: "
            "type=%d,permset=%d,tag=%d,qual=%d,name=``%s''\n",
            myacls[marker[i]].type, myacls[marker[i]].permset,
            myacls[marker[i]].tag, myacls[marker[i]].qual,
            myacls[marker[i]].name);
        assert(0); /* Record this as a failure. */
    }
    free(marker);
}

#endif


/*
 * Verify ACL restore-to-disk.  This test is FreeBSD-specific.
 */

DEFINE_TEST(test_acl_freebsd)
{
#if !defined(__FreeBSD__)
    skipping("FreeBSD-specific ACL restore test");
#elif __FreeBSD__ < 5
    skipping("ACL restore supported only on FreeBSD 5.0 and later");
#else
    struct stat st;
    struct archive *a;
    struct archive_entry *ae;
    int n, fd;
    acl_t acl;

    /*
     * First, do a quick manual set/read of ACL data to
     * verify that the local filesystem does support ACLs.
     * If it doesn't, we'll simply skip the remaining tests.
     */
    acl = acl_from_text("u::rwx,u:1:rw,g::rwx,g:15:rx,o::rwx,m::rwx");
    assert((void *)acl != NULL);
    /* Create a test file and try to set an ACL on it. */
    fd = open("pretest", O_WRONLY | O_CREAT | O_EXCL, 0777);
    failure("Could not create test file?!");
    if (!assert(fd >= 0)) {
        acl_free(acl);
        return;
    }

    n = acl_set_fd(fd, acl);
    acl_free(acl);
    if (n != 0 && errno == EOPNOTSUPP) {
        close(fd);
        skipping("ACL tests require that ACL support be enabled on the filesystem");
        return;
    }
    failure("acl_set_fd(): errno = %d (%s)",
        errno, strerror(errno));
    assertEqualInt(0, n);
    close(fd);

    /* Create a write-to-disk object. */
    assert(NULL != (a = archive_write_disk_new()));
    archive_write_disk_set_options(a,
        ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL);

    /* Populate an archive entry with some metadata, including ACL info */
    ae = archive_entry_new();
    assert(ae != NULL);
    archive_entry_set_pathname(ae, "test0");
    archive_entry_set_mtime(ae, 123456, 7890);
    archive_entry_set_size(ae, 0);
    set_acls(ae, acls2);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
    archive_entry_free(ae);

    /* Close the archive. */
    assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    /* Verify the data on disk. */
    assertEqualInt(0, stat("test0", &st));
    assertEqualInt(st.st_mtime, 123456);
    acl = acl_get_file("test0", ACL_TYPE_ACCESS);
    assert(acl != (acl_t)NULL);
    compare_acls(acl, acls2);
    acl_free(acl);
#endif
}

--- NEW FILE: test_write_disk_failures.c ---
/*-
 * 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/lib/libarchive/test/test_write_disk.c,v 1.15 2008/09/30 04:02:36 kientzle Exp $");

#if ARCHIVE_VERSION_NUMBER >= 1009000

#define UMASK 022


#endif

DEFINE_TEST(test_write_disk_failures)
{
#if ARCHIVE_VERSION_NUMBER < 1009000 || (defined(_WIN32) && !defined(__CYGWIN__))
    skipping("archive_write_disk interface");
#else
    struct archive_entry *ae;
    struct archive *a;
    int fd;

    /* Force the umask to something predictable. */
    assertUmask(UMASK);

    /* A directory that we can't write to. */
    assertMakeDir("dir", 0555);

    /* Can we? */
    fd = open("dir/testfile", O_WRONLY | O_CREAT | O_BINARY, 0777);
    if (fd >= 0) {
      /* Apparently, we can, so the test below won't work. */
      close(fd);
      skipping("Can't test writing to non-writable directory");
      return;
    }

    /* Try to extract a regular file into the directory above. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "dir/file");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    archive_entry_set_size(ae, 8);
    assert((a = archive_write_disk_new()) != NULL);
        archive_write_disk_set_options(a, ARCHIVE_EXTRACT_TIME);
    archive_entry_set_mtime(ae, 123456789, 0);
    assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae));
    assertEqualIntA(a, 0, archive_write_finish_entry(a));
    assertEqualInt(0, archive_write_finish(a));
    archive_entry_free(ae);
#endif
}

--- NEW FILE: test_read_format_cpio_bin.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_cpio_bin.c,v 1.2 2008/09/01 05:38:33 kientzle Exp $");

static unsigned char archive[] = {
199,'q',21,4,177,'y',237,'A',232,3,232,3,2,0,0,0,'p','C',244,'M',2,0,0,0,
0,0,'.',0,199,'q',0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,11,0,0,0,0,0,'T','R',
'A','I','L','E','R','!','!','!',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

DEFINE_TEST(test_read_format_cpio_bin)
{
    struct archive_entry *ae;
    struct archive *a;
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_open_memory(a, archive, sizeof(archive)));
    assertA(0 == archive_read_next_header(a, &ae));
    assertA(archive_compression(a) == ARCHIVE_COMPRESSION_NONE);
    assertA(archive_format(a) == ARCHIVE_FORMAT_CPIO_BIN_LE);
    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif
}



--- NEW FILE: test_read_format_gtar_gz.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_gtar_gz.c,v 1.2 2008/09/01 05:38:33 kientzle Exp $");

static unsigned char archive[] = {
31,139,8,0,'+','e',217,'D',0,3,211,211,'g',160,'9','0',0,2,'s','S','S',16,
'm','h','n','j',128,'L',195,0,131,161,129,177,177,137,129,137,185,185,161,
'!',131,129,161,129,153,161,'9',131,130,')',237,157,198,192,'P','Z','\\',
146,'X',164,160,192,'P',146,153,139,'W',29,'!','y',152,'G','`',244,'(',24,
5,163,'`',20,12,'r',0,0,226,234,'6',162,0,6,0,0};

DEFINE_TEST(test_read_format_gtar_gz)
{
    struct archive_entry *ae;
    struct archive *a;
    int r;

    assert((a = archive_read_new()) != NULL);
    assertEqualInt(ARCHIVE_OK, archive_read_support_compression_all(a));
    r = archive_read_support_compression_gzip(a);
    if (r == ARCHIVE_WARN) {
        skipping("gzip reading not fully supported on this platform");
        assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
        return;
    }
    assertEqualInt(ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualInt(ARCHIVE_OK,
        archive_read_open_memory(a, archive, sizeof(archive)));
    assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualInt(archive_compression(a),
        ARCHIVE_COMPRESSION_GZIP);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR);
    assertEqualInt(ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}



--- NEW FILE: test_open_file.c ---
/*-
 * 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_open_file)
{
    char buff[64];
    struct archive_entry *ae;
    struct archive *a;
    FILE *f;

    f = fopen("test.tar", "wb");
    assert(f != NULL);
    if (f == NULL)
        return;

    /* Write an archive through this FILE *. */
    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_none(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_write_open_FILE(a, f));

    /*
     * Write a file to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_mtime(ae, 1, 0);
    archive_entry_copy_pathname(ae, "file");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    archive_entry_set_size(ae, 8);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
    archive_entry_free(ae);
    assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9));

    /*
     * Write a second file to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file2");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    archive_entry_set_size(ae, 819200);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
    archive_entry_free(ae);

    /* Close out the archive. */
    assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));
    fclose(f);

    /*
     * Now, read the data back.
     */
    f = fopen("test.tar", "rb");
    assert(f != NULL);
    if (f == NULL)
        return;
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_open_FILE(a, f));

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualInt(1, archive_entry_mtime(ae));
    assertEqualInt(0, archive_entry_mtime_nsec(ae));
    assertEqualInt(0, archive_entry_atime(ae));
    assertEqualInt(0, archive_entry_ctime(ae));
    assertEqualString("file", archive_entry_pathname(ae));
    assert((S_IFREG | 0755) == archive_entry_mode(ae));
    assertEqualInt(8, archive_entry_size(ae));
    assertEqualIntA(a, 8, archive_read_data(a, buff, 10));
    assertEqualMem(buff, "12345678", 8);

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString("file2", archive_entry_pathname(ae));
    assert((S_IFREG | 0755) == archive_entry_mode(ae));
    assertEqualInt(819200, archive_entry_size(ae));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a));

    /* Verify the end of the archive. */
    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));

    fclose(f);
}

--- NEW FILE: test_write_format_mtree.c ---
/*-
 * 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
 *    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 "test.h"

static char buff[4096];
static struct {
    const char  *path;
    mode_t       mode;
    time_t       mtime;
    uid_t        uid;
    gid_t        gid;
} entries[] = {
    { "./Makefile",     S_IFREG | 0644, 1233041050, 1001, 1001 },
    { "./NEWS",         S_IFREG | 0644, 1231975636, 1001, 1001 },
    { "./PROJECTS",     S_IFREG | 0644, 1231975636, 1001, 1001 },
    { "./README",       S_IFREG | 0644, 1231975636, 1001, 1001 },
    { "./COPYING",      S_IFREG | 0644, 1231975636, 1001, 1001 },
    { "./subdir",       S_IFDIR | 0755, 1233504586, 1001, 1001 },
    { "./subdir/README",    S_IFREG | 0664, 1231975636, 1002, 1001 },
    { "./subdir/config",    S_IFREG | 0664, 1232266273, 1003, 1003 },
    { "./subdir2",      S_IFDIR | 0755, 1233504586, 1001, 1001 },
    { "./subdir3",      S_IFDIR | 0755, 1233504586, 1001, 1001 },
    { "./subdir3/mtree",    S_IFREG | 0664, 1232266273, 1003, 1003 },
    { NULL, 0, 0, 0, 0 }
};

static void
test_write_format_mtree_sub(int use_set, int dironly)
{
    struct archive_entry *ae;
    struct archive* a;
    size_t used;
    int i;

    /* Create a mtree format archive. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_mtree(a));
    if (use_set)
        assertA(0 == archive_write_set_options(a, "use-set"));
    if (dironly)
        assertA(0 == archive_write_set_options(a, "dironly"));
    assertA(0 == archive_write_open_memory(a, buff, sizeof(buff)-1, &used));

    /* Write entries */
    for (i = 0; entries[i].path != NULL; i++) {
        assert((ae = archive_entry_new()) != NULL);
        archive_entry_set_mtime(ae, entries[i].mtime, 0);
        assert(entries[i].mtime == archive_entry_mtime(ae));
        archive_entry_set_mode(ae, entries[i].mode);
        assert(entries[i].mode == archive_entry_mode(ae));
        archive_entry_set_uid(ae, entries[i].uid);
        assert(entries[i].uid == archive_entry_uid(ae));
        archive_entry_set_gid(ae, entries[i].gid);
        assert(entries[i].gid == archive_entry_gid(ae));
        archive_entry_copy_pathname(ae, entries[i].path);
        if ((entries[i].mode & AE_IFMT) != S_IFDIR)
            archive_entry_set_size(ae, 8);
        assertA(0 == archive_write_header(a, ae));
        if ((entries[i].mode & AE_IFMT) != S_IFDIR)
            assertA(8 == archive_write_data(a, "Hello012", 15));
        archive_entry_free(ae);
    }
    archive_write_close(a);
#if ARCHIVE_VERSION_NUMBER < 2000000
        archive_write_finish(a);
#else
        assertEqualInt(0, archive_write_finish(a));
#endif
    if (use_set) {
        const char *p;

        buff[used] = '\0';
        assert(NULL != (p = strstr(buff, "\n/set ")));
        if (p != NULL) {
            char *r;
            const char *o;
            p++;
            r = strchr(p, '\n');
            if (r != NULL)
                *r = '\0';
            if (dironly)
                o = "/set type=dir uid=1001 gid=1001 mode=755";
            else
                o = "/set type=file uid=1001 gid=1001 mode=644";
            assertEqualString(o, p);
            if (r != NULL)
                *r = '\n';
        }
    }

    /*
     * Read the data and check it.
     */
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used));

    /* Read entries */
    for (i = 0; entries[i].path != NULL; i++) {
        if (dironly && (entries[i].mode & AE_IFMT) != S_IFDIR)
            continue;
        assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
        assertEqualInt(entries[i].mtime, archive_entry_mtime(ae));
        assertEqualInt(entries[i].mode, archive_entry_mode(ae));
        assertEqualInt(entries[i].uid, archive_entry_uid(ae));
        assertEqualInt(entries[i].gid, archive_entry_gid(ae));
        assertEqualString(entries[i].path, archive_entry_pathname(ae));
        if ((entries[i].mode & AE_IFMT) != S_IFDIR)
            assertEqualInt(8, archive_entry_size(ae));
    }
    assertEqualIntA(a, 0, archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertEqualInt(0, archive_read_finish(a));
#endif
}

DEFINE_TEST(test_write_format_mtree)
{
    /* Default setting */
    test_write_format_mtree_sub(0, 0);
    /* Directory only */
    test_write_format_mtree_sub(0, 1);
    /* Use /set keyword */
    test_write_format_mtree_sub(1, 0);
    /* Use /set keyword with directory only */
    test_write_format_mtree_sub(1, 1);
}

--- NEW FILE: test_read_format_gtar_lzma.c ---
/*-
 * Copyright (c) 2008 Miklos Vajna
 * 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 unsigned char archive[] = {
0x5d, 0x0, 0x0, 0x80, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x17, 0xb, 0xbc, 0x1c, 0x7d, 0x1, 0x95, 0xc0, 0x1d, 0x4a, 0x46, 0x9c,
0x1c, 0xc5, 0x8, 0x82, 0x10, 0xed, 0x84, 0xf6, 0xea, 0x7a, 0xfe, 0x63,
0x5a, 0x34, 0x5e, 0xf7, 0xc, 0x60, 0xd6, 0x8b, 0xc1, 0x47, 0xaf, 0x11,
0x6f, 0x18, 0x94, 0x81, 0x74, 0x8a, 0xf8, 0x47, 0xcc, 0xdd, 0xc0, 0xd9,
0x40, 0xa, 0xc3, 0xac, 0x43, 0x47, 0xb5, 0xac, 0x2b, 0x31, 0xd3, 0x6,
0xa4, 0x2c, 0x44, 0x80, 0x24, 0x4b, 0xfe, 0x43, 0x22, 0x4e, 0x14, 0x30,
0x7a, 0xef, 0x99, 0x6e, 0xf, 0x8b, 0xc1, 0x79, 0x93, 0x88, 0x54, 0x73,
0x59, 0x3f, 0xc, 0xfb, 0xee, 0x9c, 0x83, 0x49, 0x93, 0x33, 0xad, 0x44,
0xbe, 0x0};

DEFINE_TEST(test_read_format_gtar_lzma)
{
    int r;

    struct archive_entry *ae;
    struct archive *a;
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_support_compression_all(a));
    r = archive_read_support_compression_lzma(a);
    if (r == ARCHIVE_WARN) {
        skipping("lzma reading not fully supported on this platform");
        assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
        return;
    }

    assertEqualIntA(a, ARCHIVE_OK, r);
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_support_format_all(a));
    r = archive_read_open_memory2(a, archive, sizeof(archive), 3);
    if (r != ARCHIVE_OK) {
        skipping("Skipping LZMA compression check: %s",
            archive_error_string(a));
        goto finish;
    }
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_next_header(a, &ae));
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_LZMA);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
finish:
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
#endif
}



--- NEW FILE: test_write_format_zip.c ---
/*-
 * Copyright (c) 2003-2008 Tim Kientzle
 * Copyright (c) 2008 Anselm Strauss
 * 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.
 */

/*
 * Development supported by Google Summer of Code 2008.
 */

/* TODO: reader does not yet restore permissions. */

#include "test.h"
__FBSDID("$FreeBSD$");

DEFINE_TEST(test_write_format_zip)
{
    char filedata[64];
    struct archive_entry *ae;
    struct archive *a;
    size_t used;
    size_t buffsize = 1000000;
    char *buff;
    const char *compression_type;

    buff = malloc(buffsize);

    /* Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a));
#ifdef HAVE_ZLIB_H
    compression_type = "zip:compression=deflate";
#else
    compression_type = "zip:compression=store";
#endif
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_format_options(a, compression_type));
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_none(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_open_memory(a, buff, buffsize, &used));

    /*
     * Write a file to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_mtime(ae, 1, 10);
    assertEqualInt(1, archive_entry_mtime(ae));
    assertEqualInt(10, archive_entry_mtime_nsec(ae));
    archive_entry_copy_pathname(ae, "file");
    assertEqualString("file", archive_entry_pathname(ae));
    archive_entry_set_mode(ae, S_IFREG | 0755);
    assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));
    archive_entry_set_size(ae, 8);

    assertEqualInt(0, archive_write_header(a, ae));
    archive_entry_free(ae);
    assertEqualInt(8, archive_write_data(a, "12345678", 9));
    assertEqualInt(0, archive_write_data(a, "1", 1));

    /*
     * Write another file to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_mtime(ae, 1, 10);
    assertEqualInt(1, archive_entry_mtime(ae));
    assertEqualInt(10, archive_entry_mtime_nsec(ae));
    archive_entry_copy_pathname(ae, "file2");
    assertEqualString("file2", archive_entry_pathname(ae));
    archive_entry_set_mode(ae, S_IFREG | 0755);
    assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));
    archive_entry_set_size(ae, 4);

    assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae));
    archive_entry_free(ae);
    assertEqualInt(4, archive_write_data(a, "1234", 5));

    /*
     * Write a directory to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_mtime(ae, 11, 110);
    archive_entry_copy_pathname(ae, "dir");
    archive_entry_set_mode(ae, S_IFDIR | 0755);
    archive_entry_set_size(ae, 512);

    assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
    failure("size should be zero so that applications know not to write");
    assertEqualInt(0, archive_entry_size(ae));
    archive_entry_free(ae);
    assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9));

    /* Close out the archive. */
    assertEqualInt(ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    /*
     * Now, read the data back.
     */
    ae = NULL;
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_open_memory(a, buff, used));

    /*
     * Read and verify first file.
     */
    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualInt(1, archive_entry_mtime(ae));
    /* Zip doesn't store high-resolution mtime. */
    assertEqualInt(0, archive_entry_mtime_nsec(ae));
    assertEqualInt(0, archive_entry_atime(ae));
    assertEqualInt(0, archive_entry_ctime(ae));
    assertEqualString("file", archive_entry_pathname(ae));
    //assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));
    assertEqualInt(0, archive_entry_size(ae));
    assertEqualIntA(a, 8,
        archive_read_data(a, filedata, sizeof(filedata)));
    assertEqualMem(filedata, "12345678", 8);


    /*
     * Read the second file back.
     */
    if (!assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae))){
        free(buff);
        return;
    }
    assertEqualInt(1, archive_entry_mtime(ae));
    assertEqualInt(0, archive_entry_mtime_nsec(ae));
    assertEqualInt(0, archive_entry_atime(ae));
    assertEqualInt(0, archive_entry_ctime(ae));
    assertEqualString("file2", archive_entry_pathname(ae));
    //assert((S_IFREG | 0755) == archive_entry_mode(ae));
    assertEqualInt(0, archive_entry_size(ae));
    assertEqualIntA(a, 4,
        archive_read_data(a, filedata, sizeof(filedata)));
    assertEqualMem(filedata, "1234", 4);

    /*
     * Read the dir entry back.
     */
    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualInt(11, archive_entry_mtime(ae));
    assertEqualInt(0, archive_entry_mtime_nsec(ae));
    assertEqualInt(0, archive_entry_atime(ae));
    assertEqualInt(0, archive_entry_ctime(ae));
    assertEqualString("dir/", archive_entry_pathname(ae));
    //assertEqualInt((S_IFDIR | 0755), archive_entry_mode(ae));
    assertEqualInt(0, archive_entry_size(ae));
    assertEqualIntA(a, 0, archive_read_data(a, filedata, 10));

    /* Verify the end of the archive. */
    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
    assertEqualInt(ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
    free(buff);
}

--- NEW FILE: test_compat_gzip.c ---
/*-
 * 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"
__FBSDID("$FreeBSD$");

/*
 * Verify our ability to read sample files compatibly with gunzip.
 *
 * In particular:
 *  * gunzip will read multiple gzip streams, concatenating the output
 *  * gunzip will stop at the end of a stream if the following data
 *    doesn't start with a gzip signature.
 */

/*
 * All of the sample files have the same contents; they're just
 * compressed in different ways.
 */
static void
verify(const char *name)
{
    const char *n[7] = { "f1", "f2", "f3", "d1/f1", "d1/f2", "d1/f3", NULL };
    struct archive_entry *ae;
    struct archive *a;
    int i,r;

    assert((a = archive_read_new()) != NULL);
    r = archive_read_support_compression_gzip(a);
    if (r == ARCHIVE_WARN) {
        skipping("gzip reading not fully supported on this platform");
        assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
        return;
    }
    assertEqualIntA(a, ARCHIVE_OK, r);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    extract_reference_file(name);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 200));

    /* Read entries, match up names with list above. */
    for (i = 0; i < 6; ++i) {
        failure("Could not read file %d (%s) from %s", i, n[i], name);
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_next_header(a, &ae));
        if (r != ARCHIVE_OK) {
            archive_read_finish(a);
            return;
        }
        assertEqualString(n[i], archive_entry_pathname(ae));
    }

    /* Verify the end-of-archive. */
    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));

    /* Verify that the format detection worked. */
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_GZIP);
    assertEqualString(archive_compression_name(a), "gzip");
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR);

    assertEqualInt(ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}


DEFINE_TEST(test_compat_gzip)
{
    /* This sample has been 'split', each piece compressed separately,
     * then concatenated.  Gunzip will emit the concatenated result. */
    /* Not supported in libarchive 2.6 and earlier */
    verify("test_compat_gzip_1.tgz");
    /* This sample has been compressed as a single stream, but then
     * some unrelated garbage text has been appended to the end. */
    verify("test_compat_gzip_2.tgz");
}



--- NEW FILE: test_write_format_tar_ustar.c ---
/*-
 * 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/lib/libarchive/test/test_write_format_tar_ustar.c,v 1.2 2008/08/11 01:19:36 kientzle Exp $");

static int
is_null(const char *p, size_t l)
{
    while (l > 0) {
        if (*p != '\0')
            return (0);
        --l;
        ++p;
    }
    return (1);
}

/* Verify the contents, then erase them to NUL bytes. */
/* Tar requires all "unused" bytes be set to NUL; this allows us
 * to easily verify that by invoking is_null() over the entire header
 * after verifying each field. */
#define myAssertEqualMem(a,b,s) assertEqualMem(a, b, s); memset(a, 0, s)

/*
 * Detailed verification that 'ustar' archives are written with
 * the correct format.
 */
DEFINE_TEST(test_write_format_tar_ustar)
{
    struct archive *a;
    struct archive_entry *entry;
    char *buff, *e;
    size_t buffsize = 100000;
    size_t used;
    int i;
    char f99[100];
    char f100[101];
    char f256[257];

    for (i = 0; i < 99; ++i)
        f99[i] = 'a' + i % 26;
    f99[99] = '\0';

    for (i = 0; i < 100; ++i)
        f100[i] = 'A' + i % 26;
    f100[100] = '\0';

    for (i = 0; i < 256; ++i)
        f256[i] = 'A' + i % 26;
    f256[155] = '/';
    f256[256] = '\0';

    buff = malloc(buffsize);

    /* Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, 0, archive_write_set_format_ustar(a));
    assertEqualIntA(a, 0, archive_write_set_compression_none(a));
    assertEqualIntA(a, 0, archive_write_open_memory(a, buff, buffsize, &used));

    /*
     * Add various files to it.
     * TODO: Extend this to cover more filetypes.
     */

    /* "file" with 10 bytes of content */
    assert((entry = archive_entry_new()) != NULL);
    archive_entry_set_mtime(entry, 1, 10);
    archive_entry_set_pathname(entry, "file");
    archive_entry_set_mode(entry, S_IFREG | 0664);
    archive_entry_set_size(entry, 10);
    archive_entry_set_uid(entry, 80);
    archive_entry_set_gid(entry, 90);
    archive_entry_set_dev(entry, 12);
    archive_entry_set_ino(entry, 89);
    archive_entry_set_nlink(entry, 2);
    assertEqualIntA(a, 0, archive_write_header(a, entry));
    archive_entry_free(entry);
    assertEqualIntA(a, 10, archive_write_data(a, "1234567890", 10));

    /* Hardlink to "file" with 10 bytes of content */
    assert((entry = archive_entry_new()) != NULL);
    archive_entry_set_mtime(entry, 1, 10);
    archive_entry_set_pathname(entry, "linkfile");
    archive_entry_set_mode(entry, S_IFREG | 0664);
    /* TODO: Put this back and fix the bug. */
    /* archive_entry_set_size(entry, 10); */
    archive_entry_set_uid(entry, 80);
    archive_entry_set_gid(entry, 90);
    archive_entry_set_dev(entry, 12);
    archive_entry_set_ino(entry, 89);
    archive_entry_set_nlink(entry, 2);
    assertEqualIntA(a, 0, archive_write_header(a, entry));
    archive_entry_free(entry);
    /* Write of data to dir should fail == zero bytes get written. */
    assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10));

    /* "dir" */
    assert((entry = archive_entry_new()) != NULL);
    archive_entry_set_mtime(entry, 2, 20);
    archive_entry_set_pathname(entry, "dir");
    archive_entry_set_mode(entry, S_IFDIR | 0775);
    archive_entry_set_size(entry, 10);
    archive_entry_set_nlink(entry, 2);
    assertEqualIntA(a, 0, archive_write_header(a, entry));
    archive_entry_free(entry);
    /* Write of data to dir should fail == zero bytes get written. */
    assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10));

    /* "symlink" pointing to "file" */
    assert((entry = archive_entry_new()) != NULL);
    archive_entry_set_mtime(entry, 3, 30);
    archive_entry_set_pathname(entry, "symlink");
    archive_entry_set_mode(entry, 0664);
    archive_entry_set_filetype(entry, AE_IFLNK);
    archive_entry_set_symlink(entry,"file");
    archive_entry_set_size(entry, 0);
    archive_entry_set_uid(entry, 88);
    archive_entry_set_gid(entry, 98);
    archive_entry_set_dev(entry, 12);
    archive_entry_set_ino(entry, 90);
    archive_entry_set_nlink(entry, 1);
    assertEqualIntA(a, 0, archive_write_header(a, entry));
    archive_entry_free(entry);
    /* Write of data to symlink should fail == zero bytes get written. */
    assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10));

    /* file with 99-char filename. */
    assert((entry = archive_entry_new()) != NULL);
    archive_entry_set_mtime(entry, 1, 10);
    archive_entry_set_pathname(entry, f99);
    archive_entry_set_mode(entry, S_IFREG | 0664);
    archive_entry_set_size(entry, 0);
    archive_entry_set_uid(entry, 82);
    archive_entry_set_gid(entry, 93);
    archive_entry_set_dev(entry, 102);
    archive_entry_set_ino(entry, 7);
    archive_entry_set_nlink(entry, 1);
    assertEqualIntA(a, 0, archive_write_header(a, entry));
    archive_entry_free(entry);

    /* file with 100-char filename. */
    assert((entry = archive_entry_new()) != NULL);
    archive_entry_set_mtime(entry, 1, 10);
    archive_entry_set_pathname(entry, f100);
    archive_entry_set_mode(entry, S_IFREG | 0664);
    archive_entry_set_size(entry, 0);
    archive_entry_set_uid(entry, 82);
    archive_entry_set_gid(entry, 93);
    archive_entry_set_dev(entry, 102);
    archive_entry_set_ino(entry, 7);
    archive_entry_set_nlink(entry, 1);
    assertEqualIntA(a, 0, archive_write_header(a, entry));
    archive_entry_free(entry);

    /* file with 256-char filename. */
    assert((entry = archive_entry_new()) != NULL);
    archive_entry_set_mtime(entry, 1, 10);
    archive_entry_set_pathname(entry, f256);
    archive_entry_set_mode(entry, S_IFREG | 0664);
    archive_entry_set_size(entry, 0);
    archive_entry_set_uid(entry, 82);
    archive_entry_set_gid(entry, 93);
    archive_entry_set_dev(entry, 102);
    archive_entry_set_ino(entry, 7);
    archive_entry_set_nlink(entry, 1);
    assertEqualIntA(a, 0, archive_write_header(a, entry));
    archive_entry_free(entry);

#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assert(0 == archive_write_finish(a));
#endif

    /*
     * Verify the archive format.
     */
    e = buff;

    /* "file" */
    myAssertEqualMem(e + 0, "file", 5); /* Filename */
    myAssertEqualMem(e + 100, "000664 ", 8); /* mode */
    myAssertEqualMem(e + 108, "000120 ", 8); /* uid */
    myAssertEqualMem(e + 116, "000132 ", 8); /* gid */
    myAssertEqualMem(e + 124, "00000000012 ", 12); /* size */
    myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */
    myAssertEqualMem(e + 148, "010034\0 ", 8); /* checksum */
    myAssertEqualMem(e + 156, "0", 1); /* linkflag */
    myAssertEqualMem(e + 157, "", 1); /* linkname */
    myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */
    myAssertEqualMem(e + 265, "", 1); /* uname */
    myAssertEqualMem(e + 297, "", 1); /* gname */
    myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */
    myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */
    myAssertEqualMem(e + 345, "", 1); /* prefix */
    assert(is_null(e + 0, 512));
    myAssertEqualMem(e + 512, "1234567890", 10);
    assert(is_null(e + 512, 512));
    e += 1024;

    /* hardlink to "file" */
    myAssertEqualMem(e + 0, "linkfile", 9); /* Filename */
    myAssertEqualMem(e + 100, "000664 ", 8); /* mode */
    myAssertEqualMem(e + 108, "000120 ", 8); /* uid */
    myAssertEqualMem(e + 116, "000132 ", 8); /* gid */
    myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */
    myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */
    myAssertEqualMem(e + 148, "010707\0 ", 8); /* checksum */
    myAssertEqualMem(e + 156, "0", 1); /* linkflag */
    myAssertEqualMem(e + 157, "", 1); /* linkname */
    myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */
    myAssertEqualMem(e + 265, "", 1); /* uname */
    myAssertEqualMem(e + 297, "", 1); /* gname */
    myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */
    myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */
    myAssertEqualMem(e + 345, "", 1); /* prefix */
    assert(is_null(e + 0, 512));
    e += 512;

    /* "dir" */
    myAssertEqualMem(e + 0, "dir/", 4); /* Filename */
    myAssertEqualMem(e + 100, "000775 ", 8); /* mode */
    myAssertEqualMem(e + 108, "000000 ", 8); /* uid */
    myAssertEqualMem(e + 116, "000000 ", 8); /* gid */
    myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */
    myAssertEqualMem(e + 136, "00000000002 ", 12); /* mtime */
    myAssertEqualMem(e + 148, "007747\0 ", 8); /* checksum */
    myAssertEqualMem(e + 156, "5", 1); /* typeflag */
    myAssertEqualMem(e + 157, "", 1); /* linkname */
    myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */
    myAssertEqualMem(e + 265, "", 1); /* uname */
    myAssertEqualMem(e + 297, "", 1); /* gname */
    myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */
    myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */
    myAssertEqualMem(e + 345, "", 1); /* prefix */
    assert(is_null(e + 0, 512));
    e += 512;

    /* "symlink" pointing to "file" */
    myAssertEqualMem(e + 0, "symlink", 8); /* Filename */
    myAssertEqualMem(e + 100, "000664 ", 8); /* mode */
    myAssertEqualMem(e + 108, "000130 ", 8); /* uid */
    myAssertEqualMem(e + 116, "000142 ", 8); /* gid */
    myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */
    myAssertEqualMem(e + 136, "00000000003 ", 12); /* mtime */
    myAssertEqualMem(e + 148, "011446\0 ", 8); /* checksum */
    myAssertEqualMem(e + 156, "2", 1); /* linkflag */
    myAssertEqualMem(e + 157, "file", 5); /* linkname */
    myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */
    myAssertEqualMem(e + 265, "", 1); /* uname */
    myAssertEqualMem(e + 297, "", 1); /* gname */
    myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */
    myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */
    myAssertEqualMem(e + 345, "", 1); /* prefix */
    assert(is_null(e + 0, 512));
    e += 512;

    /* File with 99-char filename */
    myAssertEqualMem(e + 0, f99, 100); /* Filename */
    myAssertEqualMem(e + 100, "000664 ", 8); /* mode */
    myAssertEqualMem(e + 108, "000122 ", 8); /* uid */
    myAssertEqualMem(e + 116, "000135 ", 8); /* gid */
    myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */
    myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */
    myAssertEqualMem(e + 148, "034242\0 ", 8); /* checksum */
    myAssertEqualMem(e + 156, "0", 1); /* linkflag */
    myAssertEqualMem(e + 157, "", 1); /* linkname */
    myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */
    myAssertEqualMem(e + 265, "", 1); /* uname */
    myAssertEqualMem(e + 297, "", 1); /* gname */
    myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */
    myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */
    myAssertEqualMem(e + 345, "", 1); /* prefix */
    assert(is_null(e + 0, 512));
    e += 512;

    /* File with 100-char filename */
    myAssertEqualMem(e + 0, f100, 100); /* Filename */
    myAssertEqualMem(e + 100, "000664 ", 8); /* mode */
    myAssertEqualMem(e + 108, "000122 ", 8); /* uid */
    myAssertEqualMem(e + 116, "000135 ", 8); /* gid */
    myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */
    myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */
    myAssertEqualMem(e + 148, "026230\0 ", 8); /* checksum */
    myAssertEqualMem(e + 156, "0", 1); /* linkflag */
    myAssertEqualMem(e + 157, "", 1); /* linkname */
    myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */
    myAssertEqualMem(e + 265, "", 1); /* uname */
    myAssertEqualMem(e + 297, "", 1); /* gname */
    myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */
    myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */
    myAssertEqualMem(e + 345, "", 1); /* prefix */
    assert(is_null(e + 0, 512));
    e += 512;

    /* File with 256-char filename */
    myAssertEqualMem(e + 0, f256 + 156, 100); /* Filename */
    myAssertEqualMem(e + 100, "000664 ", 8); /* mode */
    myAssertEqualMem(e + 108, "000122 ", 8); /* uid */
    myAssertEqualMem(e + 116, "000135 ", 8); /* gid */
    myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */
    myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */
    myAssertEqualMem(e + 148, "055570\0 ", 8); /* checksum */
    myAssertEqualMem(e + 156, "0", 1); /* linkflag */
    myAssertEqualMem(e + 157, "", 1); /* linkname */
    myAssertEqualMem(e + 257, "ustar\000000", 8); /* signature/version */
    myAssertEqualMem(e + 265, "", 1); /* uname */
    myAssertEqualMem(e + 297, "", 1); /* gname */
    myAssertEqualMem(e + 329, "000000 ", 8); /* devmajor */
    myAssertEqualMem(e + 337, "000000 ", 8); /* devminor */
    myAssertEqualMem(e + 345, f256, 155); /* prefix */
    assert(is_null(e + 0, 512));
    e += 512;

    /* TODO: Verify other types of entries. */

    /* Last entry is end-of-archive marker. */
    assert(is_null(e, 1024));
    e += 1024;

    assertEqualInt((int)used, e - buff);

    free(buff);
}

--- NEW FILE: test_read_format_isojoliet_bz2.c ---
/*-
 * Copyright (c) 2003-2007 Tim Kientzle
 * All rights reserved.
 *
 * Based on libarchive/test/test_read_format_isorr_bz2.c with
 * bugs introduced by Andreas Henriksson <andreas at fatal.se> for
 * testing ISO9660 image with Joliet extension.
 *
 * 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"

/*
Execute the following to rebuild the data for this program:
   tail -n +35 test_read_format_isojoliet_bz2.c | /bin/sh

rm -rf /tmp/iso
mkdir /tmp/iso
mkdir /tmp/iso/dir
echo "hello" >/tmp/iso/long-joliet-file-name.textfile
ln /tmp/iso/long-joliet-file-name.textfile /tmp/iso/hardlink
(cd /tmp/iso; ln -s long-joliet-file-name.textfile symlink)
if [ "$(uname -s)" = "Linux" ]; then # gnu coreutils touch doesn't have -h
TZ=utc touch -afm -t 197001020000.01 /tmp/iso /tmp/iso/long-joliet-file-name.textfile /tmp/iso/dir
TZ=utc touch -afm -t 197001030000.02 /tmp/iso/symlink
else
TZ=utc touch -afhm -t 197001020000.01 /tmp/iso /tmp/iso/long-joliet-file-name.textfile /tmp/iso/dir
TZ=utc touch -afhm -t 197001030000.02 /tmp/iso/symlink
fi
mkhybrid -J -uid 1 -gid 2 /tmp/iso | bzip2 > test_read_format_isojoliet_bz2.iso.bz2
F=test_read_format_isojoliet_bz2.iso.bz2
uuencode $F $F > $F.uu
exit 1
 */

DEFINE_TEST(test_read_format_isojoliet_bz2)
{
    const char *refname = "test_read_format_isojoliet_bz2.iso.bz2";
    struct archive_entry *ae;
    struct archive *a;
    const void *p;
    size_t size;
    off_t offset;
    int r;

    extract_reference_file(refname);
    assert((a = archive_read_new()) != NULL);
    r = archive_read_support_compression_bzip2(a);
    if (r == ARCHIVE_WARN) {
        skipping("bzip2 reading not fully supported on this platform");
        assertEqualInt(0, archive_read_finish(a));
        return;
    }
    assertEqualInt(0, r);
    assertEqualInt(0, archive_read_support_format_all(a));
    assertEqualInt(ARCHIVE_OK,
        archive_read_set_options(a, "iso9660:!rock-ridge"));
    assertEqualInt(ARCHIVE_OK,
        archive_read_open_filename(a, refname, 10240));

    /* First entry is '.' root directory. */
    assertEqualInt(0, archive_read_next_header(a, &ae));
    assertEqualString(".", archive_entry_pathname(ae));
    assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
    assertEqualInt(2048, archive_entry_size(ae));
    assertEqualInt(86401, archive_entry_mtime(ae));
    assertEqualInt(0, archive_entry_mtime_nsec(ae));
    assertEqualInt(86401, archive_entry_ctime(ae));
    assertEqualInt(0, archive_entry_stat(ae)->st_nlink);
    assertEqualInt(0, archive_entry_uid(ae));
    assertEqualIntA(a, ARCHIVE_EOF,
        archive_read_data_block(a, &p, &size, &offset));
    assertEqualInt((int)size, 0);

    /* A directory. */
    assertEqualInt(0, archive_read_next_header(a, &ae));
    assertEqualString("dir", archive_entry_pathname(ae));
    assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
    assertEqualInt(2048, archive_entry_size(ae));
    assertEqualInt(86401, archive_entry_mtime(ae));
    assertEqualInt(86401, archive_entry_atime(ae));

    /* A regular file with two names ("hardlink" gets returned
     * first, so it's not marked as a hardlink). */
    assertEqualInt(0, archive_read_next_header(a, &ae));
    assertEqualString("hardlink", archive_entry_pathname(ae));
    assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
    assert(archive_entry_hardlink(ae) == NULL);
    assertEqualInt(6, archive_entry_size(ae));
    assertEqualInt(0, archive_read_data_block(a, &p, &size, &offset));
    assertEqualInt(6, (int)size);
    assertEqualInt(0, offset);
    assertEqualInt(0, memcmp(p, "hello\n", 6));

    /* Second name for the same regular file (this happens to be
     * returned second, so does get marked as a hardlink). */
    assertEqualInt(0, archive_read_next_header(a, &ae));
    assertEqualString("long-joliet-file-name.textfile",
        archive_entry_pathname(ae));
    assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
    assertEqualString("hardlink", archive_entry_hardlink(ae));
    assert(!archive_entry_size_is_set(ae));

    /* A symlink to the regular file. */
    assertEqualInt(0, archive_read_next_header(a, &ae));
    assertEqualString("symlink", archive_entry_pathname(ae));
    assertEqualInt(0, archive_entry_size(ae));
    assertEqualInt(172802, archive_entry_mtime(ae));
    assertEqualInt(172802, archive_entry_atime(ae));

    /* End of archive. */
    assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae));

    /* Verify archive format. */
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_BZIP2);

    /* Close the archive. */
    assertEqualInt(0, archive_read_close(a));
    assertEqualInt(0, archive_read_finish(a));
}


--- NEW FILE: test_acl_basic.c ---
/*-
 * 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/lib/libarchive/test/test_acl_basic.c,v 1.6 2008/10/19 00:13:57 kientzle Exp $");

/*
 * Exercise the system-independent portion of the ACL support.
 * Check that archive_entry objects can save and restore ACL data.
 *
 * This should work on all systems, regardless of whether local
 * filesystems support ACLs or not.
 */

struct acl_t {
    int type;  /* Type of ACL: "access" or "default" */
    int permset; /* Permissions for this class of users. */
    int tag; /* Owner, User, Owning group, group, other, etc. */
    int qual; /* GID or UID of user/group, depending on tag. */
    const char *name; /* Name of user/group, depending on tag. */
};

static struct acl_t acls0[] = {
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE,
      ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
      ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE,
      ARCHIVE_ENTRY_ACL_OTHER, 0, "" },
};

static struct acl_t acls1[] = {
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE,
      ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
      ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
      ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE,
      ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
};

static struct acl_t acls2[] = {
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ,
      ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
      ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0,
      ARCHIVE_ENTRY_ACL_USER, 78, "user78" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
      ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0007,
      ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_EXECUTE,
      ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
};

static void
set_acls(struct archive_entry *ae, struct acl_t *acls, int n)
{
    int i;

    archive_entry_acl_clear(ae);
    for (i = 0; i < n; i++) {
        archive_entry_acl_add_entry(ae,
            acls[i].type, acls[i].permset, acls[i].tag, acls[i].qual,
            acls[i].name);
    }
}

static int
acl_match(struct acl_t *acl, int type, int permset, int tag, int qual, const char *name)
{
    if (type != acl->type)
        return (0);
    if (permset != acl->permset)
        return (0);
    if (tag != acl->tag)
        return (0);
    if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
        return (1);
    if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ)
        return (1);
    if (tag == ARCHIVE_ENTRY_ACL_OTHER)
        return (1);
    if (qual != acl->qual)
        return (0);
    if (name == NULL) {
        if (acl->name == NULL || acl->name[0] == '\0')
            return (1);
    }
    if (acl->name == NULL) {
        if (name[0] == '\0')
            return (1);
    }
    return (0 == strcmp(name, acl->name));
}

static void
compare_acls(struct archive_entry *ae, struct acl_t *acls, int n, int mode)
{
    int *marker = malloc(sizeof(marker[0]) * n);
    int i;
    int r;
    int type, permset, tag, qual;
    int matched;
    const char *name;

    for (i = 0; i < n; i++)
        marker[i] = i;

    while (0 == (r = archive_entry_acl_next(ae,
             ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
             &type, &permset, &tag, &qual, &name))) {
        for (i = 0, matched = 0; i < n && !matched; i++) {
            if (acl_match(&acls[marker[i]], type, permset,
                tag, qual, name)) {
                /* We found a match; remove it. */
                marker[i] = marker[n - 1];
                n--;
                matched = 1;
            }
        }
        if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ) {
            if (!matched) printf("No match for user_obj perm\n");
            failure("USER_OBJ permset (%02o) != user mode (%02o)",
                permset, 07 & (mode >> 6));
            assert((permset << 6) == (mode & 0700));
        } else if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ) {
            if (!matched) printf("No match for group_obj perm\n");
            failure("GROUP_OBJ permset %02o != group mode %02o",
                permset, 07 & (mode >> 3));
            assert((permset << 3) == (mode & 0070));
        } else if (tag == ARCHIVE_ENTRY_ACL_OTHER) {
            if (!matched) printf("No match for other perm\n");
            failure("OTHER permset (%02o) != other mode (%02o)",
                permset, mode & 07);
            assert((permset << 0) == (mode & 0007));
        } else {
            failure("Could not find match for ACL "
                "(type=%d,permset=%d,tag=%d,qual=%d,name=``%s'')",
                type, permset, tag, qual, name);
            assert(matched == 1);
        }
    }
#if ARCHIVE_VERSION_NUMBER < 1009000
    /* Known broken before 1.9.0. */
    skipping("archive_entry_acl_next() exits with ARCHIVE_EOF");
#else
    assertEqualInt(ARCHIVE_EOF, r);
#endif
    assert((mode & 0777) == (archive_entry_mode(ae) & 0777));
    failure("Could not find match for ACL "
        "(type=%d,permset=%d,tag=%d,qual=%d,name=``%s'')",
        acls[marker[0]].type, acls[marker[0]].permset,
        acls[marker[0]].tag, acls[marker[0]].qual, acls[marker[0]].name);
    assert(n == 0); /* Number of ACLs not matched should == 0 */
    free(marker);
}

DEFINE_TEST(test_acl_basic)
{
    struct archive_entry *ae;

    /* Create a simple archive_entry. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_pathname(ae, "file");
        archive_entry_set_mode(ae, S_IFREG | 0777);

    /* Basic owner/owning group should just update mode bits. */
    set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
    failure("Basic ACLs shouldn't be stored as extended ACLs");
    assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
    failure("Basic ACLs should set mode to 0142, not %04o",
        archive_entry_mode(ae)&0777);
    assert((archive_entry_mode(ae) & 0777) == 0142);


    /* With any extended ACL entry, we should read back a full set. */
    set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
    failure("One extended ACL should flag all ACLs to be returned.");
    assert(4 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
    compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]), 0142);
    failure("Basic ACLs should set mode to 0142, not %04o",
        archive_entry_mode(ae)&0777);
    assert((archive_entry_mode(ae) & 0777) == 0142);


    /* A more extensive set of ACLs. */
    set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
    assertEqualInt(6, archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
    compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]), 0543);
    failure("Basic ACLs should set mode to 0543, not %04o",
        archive_entry_mode(ae)&0777);
    assert((archive_entry_mode(ae) & 0777) == 0543);

    /*
     * Check that clearing ACLs gets rid of them all by repeating
     * the first test.
     */
    set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
    failure("Basic ACLs shouldn't be stored as extended ACLs");
    assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
    failure("Basic ACLs should set mode to 0142, not %04o",
        archive_entry_mode(ae)&0777);
    assert((archive_entry_mode(ae) & 0777) == 0142);
    archive_entry_free(ae);
}

--- NEW FILE: read_open_memory.c ---
/*-
 * 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/lib/libarchive/test/read_open_memory.c,v 1.3 2008/09/01 05:38:33 kientzle Exp $");

#include <errno.h>
#include <stdlib.h>
#include <string.h>

/*
 * Read an archive from a block of memory.
 *
 * This is identical to archive_read_open_memory(), except
 * that it goes out of its way to be a little bit unpleasant,
 * in order to better test the libarchive internals.
 */

struct read_memory_data {
    unsigned char   *buffer;
    unsigned char   *end;
    size_t   read_size;
    size_t copy_buff_size;
    char *copy_buff;
};

static int  memory_read_close(struct archive *, void *);
static int  memory_read_open(struct archive *, void *);
#if ARCHIVE_VERSION_NUMBER < 2000000
static ssize_t  memory_read_skip(struct archive *, void *, size_t request);
#else
static off_t    memory_read_skip(struct archive *, void *, off_t request);
#endif
static ssize_t  memory_read(struct archive *, void *, const void **buff);
static int  read_open_memory_internal(struct archive *a, void *buff,
    size_t size, size_t read_size, int fullapi);


int
read_open_memory(struct archive *a, void *buff, size_t size, size_t read_size)
{
    return read_open_memory_internal(a, buff, size, read_size, 1);
}

/*
 * As above, but don't register any optional part of the API, to verify
 * that internals work correctly with just the minimal entry points.
 */
int
read_open_memory2(struct archive *a, void *buff, size_t size, size_t read_size)
{
    return read_open_memory_internal(a, buff, size, read_size, 0);
}

static int
read_open_memory_internal(struct archive *a, void *buff,
    size_t size, size_t read_size, int fullapi)
{
    struct read_memory_data *mine;

    mine = (struct read_memory_data *)malloc(sizeof(*mine));
    if (mine == NULL) {
        archive_set_error(a, ENOMEM, "No memory");
        return (ARCHIVE_FATAL);
    }
    memset(mine, 0, sizeof(*mine));
    mine->buffer = (unsigned char *)buff;
    mine->end = mine->buffer + size;
    mine->read_size = read_size;
    mine->copy_buff_size = read_size + 64;
    mine->copy_buff = malloc(mine->copy_buff_size);
    if (fullapi)
        return (archive_read_open2(a, mine, memory_read_open,
                memory_read, memory_read_skip, memory_read_close));
    else
        return (archive_read_open2(a, mine, NULL,
                memory_read, NULL, memory_read_close));
}

/*
 * There's nothing to open.
 */
static int
memory_read_open(struct archive *a, void *client_data)
{
    (void)a; /* UNUSED */
    (void)client_data; /* UNUSED */
    return (ARCHIVE_OK);
}

/*
 * In order to exercise libarchive's internal read-combining logic,
 * we deliberately copy data for each read to a separate buffer.
 * That way, code that runs off the end of the provided data
 * will screw up.
 */
static ssize_t
memory_read(struct archive *a, void *client_data, const void **buff)
{
    struct read_memory_data *mine = (struct read_memory_data *)client_data;
    size_t size;

    (void)a; /* UNUSED */
    size = mine->end - mine->buffer;
    if (size > mine->read_size)
        size = mine->read_size;
    memset(mine->copy_buff, 0xA5, mine->copy_buff_size);
    memcpy(mine->copy_buff, mine->buffer, size);
    *buff = mine->copy_buff;

        mine->buffer += size;
    return ((ssize_t)size);
}

/*
 * How mean can a skip() routine be?  Let's try to find out.
 */
#if ARCHIVE_VERSION_NUMBER < 2000000
static ssize_t
memory_read_skip(struct archive *a, void *client_data, size_t skip)
#else
static off_t
memory_read_skip(struct archive *a, void *client_data, off_t skip)
#endif
{
    struct read_memory_data *mine = (struct read_memory_data *)client_data;

    (void)a; /* UNUSED */
    /* We can't skip by more than is available. */
    if ((off_t)skip > (off_t)(mine->end - mine->buffer))
        skip = mine->end - mine->buffer;
    /* Always do small skips by prime amounts. */
    if (skip > 71)
        skip = 71;
    mine->buffer += skip;
    return (skip);
}

/*
 * Close is just cleaning up our one small bit of data.
 */
static int
memory_read_close(struct archive *a, void *client_data)
{
    struct read_memory_data *mine = (struct read_memory_data *)client_data;
    (void)a; /* UNUSED */
    free(mine->copy_buff);
    free(mine);
    return (ARCHIVE_OK);
}

--- NEW FILE: test_read_format_zip.zip.uu ---
$FreeBSD: src/lib/libarchive/test/test_read_format_zip.zip.uu,v 1.3 2008/10/21 05:08:35 kientzle Exp $
begin 644 test_read_format_zip.zip
M4$L#!`H`"````%EFLS8````````````````$`!4`9&ER+U54"0`#&55/1M19
M_4A5>`0`Z`/H`U!+!P@```````````````!02P,$%`````@`;V:S-CHW9CT*
M````$@````4`%0!F:6QE,554"0`#055/1L!9_4A5>`0`Z`/H`\M(S<G)Y\I`
M(@%02P,$%``(``@`6FJS-@``````````$@````4`%0!F:6QE,E54"0`#K%M/
M1L!9_4A5>`0`Z`/H`\M(S<G)Y\I`(@%02P<(.C=F$@H````2````4$L!`A<#
M"@`(````66:S-@````````````````0`#0`````````0`.U!`````&1I<B]5
M5`4``QE53T95>```4$L!`A<#%``(``@`;V:S-CHW9CT*````$@````4`#0``
M`````0```.V!1P```&9I;&4Q550%``-!54]&57@``%!+`0(7`Q0`"``(`%IJ
MLS8Z-V8]"@```!(````%``T```````$```#M at 8D```!F:6QE,E54!0`#K%M/
;1E5X``!02P4&``````,``P"_````VP``````
`
end

--- NEW FILE: test_read_format_mtree.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_mtree.c,v 1.4 2008/09/18 04:13:36 kientzle Exp $");

/* Single entry with a hardlink. */
static unsigned char archive[] = {
    "#mtree\n"
    "file type=file uid=18 mode=0123 size=3\n"
    "dir type=dir\n"
    " file\\040with\\040space type=file uid=18\n"
    " ..\n"
    "file\\040with\\040space type=file\n"
    "dir2 type=dir\n"
    " dir3a type=dir\n"
    "  indir3a type=file\n"
    "dir2/fullindir2 type=file mode=0777\n"
    "  ..\n"
    " indir2 type=file\n"
    " dir3b type=dir\n"
    "  indir3b type=file\n"
    "  ..\n"
    " ..\n"
    "notindir type=file\n"
    "dir2/fullindir2 mode=0644\n"
};

DEFINE_TEST(test_read_format_mtree)
{
    char buff[16];
    struct archive_entry *ae;
    struct archive *a;
    FILE *f;

    /*
     * An access error occurred on some platform when mtree
     * format handling open a directory. It is for through
     * the routine which open a directory that we create
     * "dir" and "dir2" directories.
     */
    assertMakeDir("dir", 0775);
    assertMakeDir("dir2", 0775);

    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_open_memory(a, archive, sizeof(archive)));

    /*
     * Read "file", whose data is available on disk.
     */
    f = fopen("file", "wb");
    assert(f != NULL);
    assertEqualInt(3, fwrite("hi\n", 1, 3, f));
    fclose(f);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE);
    assertEqualString(archive_entry_pathname(ae), "file");
    assertEqualInt(archive_entry_uid(ae), 18);
    assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
    assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0123);
    assertEqualInt(archive_entry_size(ae), 3);
    assertEqualInt(3, archive_read_data(a, buff, 3));
    assertEqualMem(buff, "hi\n", 3);

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString(archive_entry_pathname(ae), "dir");
    assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString(archive_entry_pathname(ae), "dir/file with space");

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString(archive_entry_pathname(ae), "file with space");

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString(archive_entry_pathname(ae), "dir2");

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString(archive_entry_pathname(ae), "dir2/dir3a");

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString(archive_entry_pathname(ae), "dir2/dir3a/indir3a");

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString(archive_entry_pathname(ae), "dir2/fullindir2");
    assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString(archive_entry_pathname(ae), "dir2/indir2");

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString(archive_entry_pathname(ae), "dir2/dir3b");

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString(archive_entry_pathname(ae), "dir2/dir3b/indir3b");

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString(archive_entry_pathname(ae), "notindir");

    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
    assertEqualInt(ARCHIVE_OK, archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
#endif
}



--- NEW FILE: test_write_format_zip_no_compression.c ---
/*-
 * Copyright (c) 2008 Anselm Strauss
 * 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.
 */

/*
 * Development supported by Google Summer of Code 2008.
 */

#include "test.h"
__FBSDID("$FreeBSD$");

static unsigned long
bitcrc32(unsigned long c, void *_p, size_t s)
{
    /* This is a drop-in replacement for crc32() from zlib.
     * Libarchive should be able to correctly generate
     * uncompressed zip archives (including correct CRCs) even
     * when zlib is unavailable, and this function helps us verify
     * that.  Yes, this is very, very slow and unsuitable for
     * production use, but it's correct, compact, and works well
     * enough for this particular usage.  Libarchive internally
     * uses a much more efficient implementation.  */
    const unsigned char *p = _p;
    int bitctr;

    if (p == NULL)
        return (0);

    for (; s > 0; --s) {
        c ^= *p++;
        for (bitctr = 8; bitctr > 0; --bitctr) {
            if (c & 1) c = (c >> 1);
            else       c = (c >> 1) ^ 0xedb88320;
            c ^= 0x80000000;
        }
    }
    return (c);
}

/* Quick and dirty: Read 2-byte and 4-byte integers from Zip file. */
static int i2(const char *p) { return ((p[0] & 0xff) | ((p[1] & 0xff) << 8)); }
static int i4(const char *p) { return (i2(p) | (i2(p + 2) << 16)); }

DEFINE_TEST(test_write_format_zip_no_compression)
{
    /* Buffer data */
    struct archive *a;
    struct archive_entry *entry;
    char buff[100000];
    const char *buffend;
    /* p is the pointer to walk over the central directory,
     * q walks over the local headers, the data and the data descriptors. */
    const char *p, *q;
    size_t used;

    /* File data */
    char file_name[] = "file";
    char file_data1[] = {'1', '2', '3', '4', '5'};
    char file_data2[] = {'6', '7', '8', '9', '0'};
    int file_perm = 00644;
    short file_uid = 10;
    short file_gid = 20;

    /* Folder data */
    char folder_name[] = "folder/";
    int folder_perm = 00755;
    short folder_uid = 30;
    short folder_gid = 40;

    /* Time data */
    time_t t = time(NULL);
    struct tm *tm = localtime(&t);

    /* Misc variables */
    unsigned long crc;

    /* Create new ZIP archive in memory without padding. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_zip(a));
    assertA(0 == archive_write_set_format_options(a, "zip:compression=store"));
    assertA(0 == archive_write_set_compression_none(a));
    assertA(0 == archive_write_set_bytes_per_block(a, 1));
    assertA(0 == archive_write_set_bytes_in_last_block(a, 1));
    assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));

    /* Write entries. */

    /* Regular file */
    assert((entry = archive_entry_new()) != NULL);
    archive_entry_set_pathname(entry, file_name);
    archive_entry_set_mode(entry, S_IFREG | 0644);
    archive_entry_set_size(entry, sizeof(file_data1) + sizeof(file_data2));
    archive_entry_set_uid(entry, file_uid);
    archive_entry_set_gid(entry, file_gid);
    archive_entry_set_mtime(entry, t, 0);
    archive_entry_set_atime(entry, t, 0);
    archive_entry_set_ctime(entry, t, 0);
    assertEqualIntA(a, 0, archive_write_header(a, entry));
    assertEqualIntA(a, sizeof(file_data1), archive_write_data(a, file_data1, sizeof(file_data1)));
    assertEqualIntA(a, sizeof(file_data2), archive_write_data(a, file_data2, sizeof(file_data2)));
    archive_entry_free(entry);

    /* Folder */
    assert((entry = archive_entry_new()) != NULL);
    archive_entry_set_pathname(entry, folder_name);
    archive_entry_set_mode(entry, S_IFDIR | folder_perm);
    archive_entry_set_size(entry, 0);
    archive_entry_set_uid(entry, folder_uid);
    archive_entry_set_gid(entry, folder_gid);
    archive_entry_set_mtime(entry, t, 0);
    archive_entry_set_atime(entry, t, 0);
    archive_entry_set_ctime(entry, t, 0);
    assertEqualIntA(a, 0, archive_write_header(a, entry));
    archive_entry_free(entry);

    /* Close the archive . */
    assertA(0 == archive_write_close(a));
    assertA(0 == archive_write_finish(a));

    /* Remember the end of the archive in memory. */
    buffend = buff + used;

    /* Verify "End of Central Directory" record. */
    /* Get address of end-of-central-directory record. */
    p = buffend - 22; /* Assumes there is no zip comment field. */
    failure("End-of-central-directory begins with PK\\005\\006 signature");
    assertEqualMem(p, "PK\005\006", 4);
    failure("This must be disk 0");
    assertEqualInt(i2(p + 4), 0);
    failure("Central dir must start on disk 0");
    assertEqualInt(i2(p + 6), 0);
    failure("All central dir entries are on this disk");
    assertEqualInt(i2(p + 8), i2(p + 10));
    failure("CD start (%d) + CD length (%d) should == archive size - 22",
        i4(p + 12), i4(p + 16));
    assertEqualInt(i4(p + 12) + i4(p + 16), used - 22);
    failure("no zip comment");
    assertEqualInt(i2(p + 20), 0);

    /* Get address of first entry in central directory. */
    p = buff + i4(buffend - 6);
    failure("Central file record at offset %d should begin with"
        " PK\\001\\002 signature",
        i4(buffend - 10));

    /* Verify file entry in central directory. */
    assertEqualMem(p, "PK\001\002", 4); /* Signature */
    assertEqualInt(i2(p + 4), 3 * 256 + 20); /* Version made by */
    assertEqualInt(i2(p + 6), 20); /* Version needed to extract */
    assertEqualInt(i2(p + 8), 8); /* Flags */
    assertEqualInt(i2(p + 10), 0); /* Compression method */
    assertEqualInt(i2(p + 12), (tm->tm_hour * 2048) + (tm->tm_min * 32) + (tm->tm_sec / 2)); /* File time */
    assertEqualInt(i2(p + 14), ((tm->tm_year - 80) * 512) + ((tm->tm_mon + 1) * 32) + tm->tm_mday); /* File date */
    crc = bitcrc32(0, file_data1, sizeof(file_data1));
    crc = bitcrc32(crc, file_data2, sizeof(file_data2));
    assertEqualInt(i4(p + 16), crc); /* CRC-32 */
    assertEqualInt(i4(p + 20), sizeof(file_data1) + sizeof(file_data2)); /* Compressed size */
    assertEqualInt(i4(p + 24), sizeof(file_data1) + sizeof(file_data2)); /* Uncompressed size */
    assertEqualInt(i2(p + 28), strlen(file_name)); /* Pathname length */
    assertEqualInt(i2(p + 30), 13); /* Extra field length */
    assertEqualInt(i2(p + 32), 0); /* File comment length */
    assertEqualInt(i2(p + 34), 0); /* Disk number start */
    assertEqualInt(i2(p + 36), 0); /* Internal file attrs */
    assertEqualInt(i4(p + 38) >> 16 & 01777, file_perm); /* External file attrs */
    assertEqualInt(i4(p + 42), 0); /* Offset of local header */
    assertEqualMem(p + 46, file_name, strlen(file_name)); /* Pathname */
    p = p + 46 + strlen(file_name);
    assertEqualInt(i2(p), 0x5455); /* 'UT' extension header */
    assertEqualInt(i2(p + 2), 5); /* 'UT' size */
    assertEqualInt(p[4], 7); /* 'UT' flags */
    assertEqualInt(i4(p + 5), t); /* 'UT' mtime */
    p = p + 9;
    assertEqualInt(i2(p), 0x7855); /* 'Ux' extension header */
    assertEqualInt(i2(p + 2), 0); /* 'Ux' size */
    p = p + 4;

    /* Verify local header of file entry. */
    q = buff;
    assertEqualMem(q, "PK\003\004", 4); /* Signature */
    assertEqualInt(i2(q + 4), 20); /* Version needed to extract */
    assertEqualInt(i2(q + 6), 8); /* Flags */
    assertEqualInt(i2(q + 8), 0); /* Compression method */
    assertEqualInt(i2(q + 10), (tm->tm_hour * 2048) + (tm->tm_min * 32) + (tm->tm_sec / 2)); /* File time */
    assertEqualInt(i2(q + 12), ((tm->tm_year - 80) * 512) + ((tm->tm_mon + 1) * 32) + tm->tm_mday); /* File date */
    assertEqualInt(i4(q + 14), 0); /* CRC-32 */
    assertEqualInt(i4(q + 18), sizeof(file_data1) + sizeof(file_data2)); /* Compressed size */
    assertEqualInt(i4(q + 22), sizeof(file_data1) + sizeof(file_data2)); /* Uncompressed size */
    assertEqualInt(i2(q + 26), strlen(file_name)); /* Pathname length */
    assertEqualInt(i2(q + 28), 25); /* Extra field length */
    assertEqualMem(q + 30, file_name, strlen(file_name)); /* Pathname */
    q = q + 30 + strlen(file_name);
    assertEqualInt(i2(q), 0x5455); /* 'UT' extension header */
    assertEqualInt(i2(q + 2), 13); /* 'UT' size */
    assertEqualInt(q[4], 7); /* 'UT' flags */
    assertEqualInt(i4(q + 5), t); /* 'UT' mtime */
    assertEqualInt(i4(q + 9), t); /* 'UT' atime */
    assertEqualInt(i4(q + 13), t); /* 'UT' ctime */
    q = q + 17;
    assertEqualInt(i2(q), 0x7855); /* 'Ux' extension header */
    assertEqualInt(i2(q + 2), 4); /* 'Ux' size */
    assertEqualInt(i2(q + 4), file_uid); /* 'Ux' UID */
    assertEqualInt(i2(q + 6), file_gid); /* 'Ux' GID */
    q = q + 8;

    /* Verify data of file entry. */
    assertEqualMem(q, file_data1, sizeof(file_data1));
    assertEqualMem(q + sizeof(file_data1), file_data2, sizeof(file_data2));
    q = q + sizeof(file_data1) + sizeof(file_data2);

    /* Verify data descriptor of file entry. */
    assertEqualMem(q, "PK\007\010", 4); /* Signature */
    assertEqualInt(i4(q + 4), crc); /* CRC-32 */
    assertEqualInt(i4(q + 8), sizeof(file_data1) + sizeof(file_data2)); /* Compressed size */
    assertEqualInt(i4(q + 12), sizeof(file_data1) + sizeof(file_data2)); /* Uncompressed size */
    q = q + 16;

    /* Verify folder entry in central directory. */
    assertEqualMem(p, "PK\001\002", 4); /* Signature */
    assertEqualInt(i2(p + 4), 3 * 256 + 20); /* Version made by */
    assertEqualInt(i2(p + 6), 20); /* Version needed to extract */
    assertEqualInt(i2(p + 8), 8); /* Flags */
    assertEqualInt(i2(p + 10), 0); /* Compression method */
    assertEqualInt(i2(p + 12), (tm->tm_hour * 2048) + (tm->tm_min * 32) + (tm->tm_sec / 2)); /* File time */
    assertEqualInt(i2(p + 14), ((tm->tm_year - 80) * 512) + ((tm->tm_mon + 1) * 32) + tm->tm_mday); /* File date */
    crc = 0;
    assertEqualInt(i4(p + 16), crc); /* CRC-32 */
    assertEqualInt(i4(p + 20), 0); /* Compressed size */
    assertEqualInt(i4(p + 24), 0); /* Uncompressed size */
    assertEqualInt(i2(p + 28), strlen(folder_name)); /* Pathname length */
    assertEqualInt(i2(p + 30), 13); /* Extra field length */
    assertEqualInt(i2(p + 32), 0); /* File comment length */
    assertEqualInt(i2(p + 34), 0); /* Disk number start */
    assertEqualInt(i2(p + 36), 0); /* Internal file attrs */
    assertEqualInt(i4(p + 38) >> 16 & 01777, folder_perm); /* External file attrs */
    assertEqualInt(i4(p + 42), q - buff); /* Offset of local header */
    assertEqualMem(p + 46, folder_name, strlen(folder_name)); /* Pathname */
    p = p + 46 + strlen(folder_name);
    assertEqualInt(i2(p), 0x5455); /* 'UT' extension header */
    assertEqualInt(i2(p + 2), 5); /* 'UT' size */
    assertEqualInt(p[4], 7); /* 'UT' flags */
    assertEqualInt(i4(p + 5), t); /* 'UT' mtime */
    p = p + 9;
    assertEqualInt(i2(p), 0x7855); /* 'Ux' extension header */
    assertEqualInt(i2(p + 2), 0); /* 'Ux' size */
    p = p + 4;

    /* Verify local header of folder entry. */
    assertEqualMem(q, "PK\003\004", 4); /* Signature */
    assertEqualInt(i2(q + 4), 20); /* Version needed to extract */
    assertEqualInt(i2(q + 6), 8); /* Flags */
    assertEqualInt(i2(q + 8), 0); /* Compression method */
    assertEqualInt(i2(q + 10), (tm->tm_hour * 2048) + (tm->tm_min * 32) + (tm->tm_sec / 2)); /* File time */
    assertEqualInt(i2(q + 12), ((tm->tm_year - 80) * 512) + ((tm->tm_mon + 1) * 32) + tm->tm_mday); /* File date */
    assertEqualInt(i4(q + 14), 0); /* CRC-32 */
    assertEqualInt(i4(q + 18), 0); /* Compressed size */
    assertEqualInt(i4(q + 22), 0); /* Uncompressed size */
    assertEqualInt(i2(q + 26), strlen(folder_name)); /* Pathname length */
    assertEqualInt(i2(q + 28), 25); /* Extra field length */
    assertEqualMem(q + 30, folder_name, strlen(folder_name)); /* Pathname */
    q = q + 30 + strlen(folder_name);
    assertEqualInt(i2(q), 0x5455); /* 'UT' extension header */
    assertEqualInt(i2(q + 2), 13); /* 'UT' size */
    assertEqualInt(q[4], 7); /* 'UT' flags */
    assertEqualInt(i4(q + 5), t); /* 'UT' mtime */
    assertEqualInt(i4(q + 9), t); /* 'UT' atime */
    assertEqualInt(i4(q + 13), t); /* 'UT' ctime */
    q = q + 17;
    assertEqualInt(i2(q), 0x7855); /* 'Ux' extension header */
    assertEqualInt(i2(q + 2), 4); /* 'Ux' size */
    assertEqualInt(i2(q + 4), folder_uid); /* 'Ux' UID */
    assertEqualInt(i2(q + 6), folder_gid); /* 'Ux' GID */
    q = q + 8;

    /* There should not be any data in the folder entry,
     * meaning next is the data descriptor header. */

    /* Verify data descriptor of folder entry. */
    assertEqualMem(q, "PK\007\010", 4); /* Signature */
    assertEqualInt(i4(q + 4), crc); /* CRC-32 */
    assertEqualInt(i4(q + 8), 0); /* Compressed size */
    assertEqualInt(i4(q + 12), 0); /* Uncompressed size */
    q = q + 16;
}

--- NEW FILE: test_read_format_cpio_svr4_gzip.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_cpio_svr4_gzip.c,v 1.2 2008/09/01 05:38:33 kientzle Exp $");

static unsigned char archive[] = {
31,139,8,0,236,'c',217,'D',0,3,'3','0','7','0','7','0','4','0','0',181,'0',
183,'L',2,210,6,6,'&',134,169,')',' ',218,192,'8',213,2,133,'6','0','0','2',
'1','6','7','0','5','0','N','6','@',5,'&',16,202,208,212,0,';','0',130,'1',
244,24,12,160,246,17,5,136,'U',135,14,146,'`',140,144,' ','G','O',31,215,
' ','E','E','E',134,'Q',128,21,0,0,'%',215,202,221,0,2,0,0};

DEFINE_TEST(test_read_format_cpio_svr4_gzip)
{
    struct archive_entry *ae;
    struct archive *a;
    int r;

    assert((a = archive_read_new()) != NULL);
    assertEqualInt(ARCHIVE_OK, archive_read_support_compression_all(a));
    r = archive_read_support_compression_gzip(a);
    if (r == ARCHIVE_WARN) {
        skipping("gzip reading not fully supported on this platform");
        assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
        return;
    }
    assertEqualInt(ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualInt(ARCHIVE_OK,
        archive_read_open_memory(a, archive, sizeof(archive)));
    assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualInt(archive_compression(a),
        ARCHIVE_COMPRESSION_GZIP);
    assertEqualInt(archive_format(a),
        ARCHIVE_FORMAT_CPIO_SVR4_NOCRC);
    assertEqualInt(ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}



--- NEW FILE: test_read_format_tar_empty_filename.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_tar_empty_filename.c,v 1.2 2008/09/01 05:38:33 kientzle Exp $");

/*
 * Tar entries with empty filenames are unusual, but shouldn't crash us.
 */
DEFINE_TEST(test_read_format_tar_empty_filename)
{
    char name[] = "test_read_format_tar_empty_filename.tar";
    struct archive_entry *ae;
    struct archive *a;

    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    extract_reference_file(name);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240));

    /* Read first entry. */
    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString("", archive_entry_pathname(ae));
    assertEqualInt(1208628157, archive_entry_mtime(ae));
    assertEqualInt(1000, archive_entry_uid(ae));
    assertEqualString("tim", archive_entry_uname(ae));
    assertEqualInt(0, archive_entry_gid(ae));
    assertEqualString("wheel", archive_entry_gname(ae));
    assertEqualInt(040775, archive_entry_mode(ae));

    /* Verify the end-of-archive. */
    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));

    /* Verify that the format detection worked. */
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_NONE);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR);

    assertEqualInt(ARCHIVE_OK, archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
#endif
}

--- NEW FILE: README ---
$FreeBSD: src/lib/libarchive/test/README,v 1.3 2008/01/01 22:28:04 kientzle Exp $

This is the test harness for libarchive.

It compiles into a single program "libarchive_test" that is intended
to exercise as much of the library as possible.  It is, of course,
very much a work in progress.

Each test is a function named test_foo in a file named test_foo.c.
Note that the file name is the same as the function name.
Each file must start with this line:

  #include "test.h"

The test function must be declared with a line of this form

  DEFINE_TEST(test_foo)

Nothing else should appear on that line.

When you add a test, please update the Makefile to add your
file to the list of tests.  The Makefile and main.c use various
macro trickery to automatically collect a list of test functions
to be invoked.

Each test function can rely on the following:

  * The current directory will be a freshly-created empty directory
    suitable for that test.  (The top-level main() creates a
    directory for each separate test and chdir()s to that directory
    before running the test.)

  * The test function should use assert(), assertA() and similar macros
    defined in test.h.  If you need to add new macros of this form, feel
    free to do so.  The current macro set includes assertEqualInt() and
    assertEqualString() that print out additional detail about their
    arguments if the assertion does fail.  'A' versions also accept
    a struct archive * and display any error message from there on
    failure.

  * You are encouraged to document each assertion with a failure() call
    just before the assert.  The failure() function is a printf-like
    function whose text is displayed only if the assertion fails.  It
    can be used to display additional information relevant to the failure:

       failure("The data read from file %s did not match the data written to that file.", filename);
       assert(strcmp(buff1, buff2) == 0);

  * Tests are encouraged to be economical with their memory and disk usage,
    though this is not essential.  The test is occasionally run under
    a memory debugger to try to locate memory leaks in the library;
    as a result, tests should be careful to release any memory they
    allocate.

  * Disable tests on specific platforms as necessary.  Please don't
    use config.h to adjust feature requirements, as I want the tests
    to also serve as a check on the configure process.  The following
    form is appropriate:

#if !defined(__PLATFORM) && !defined(__Platform2__)
    assert(xxxx)
#endif


--- NEW FILE: test_write_compress_bzip2.c ---
/*-
 * Copyright (c) 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 "test.h"
__FBSDID("$FreeBSD$");

/*
 * A basic exercise of bzip2 reading and writing.
 *
 * TODO: Add a reference file and make sure we can decompress that.
 */

DEFINE_TEST(test_write_compress_bzip2)
{
    struct archive_entry *ae;
    struct archive* a;
    char *buff, *data;
    size_t buffsize, datasize;
    char path[16];
    size_t used1, used2;
    int i, r;

    buffsize = 2000000;
    assert(NULL != (buff = (char *)malloc(buffsize)));

    datasize = 10000;
    assert(NULL != (data = (char *)malloc(datasize)));
    memset(data, 0, datasize);

    /*
     * Write a 100 files and read them all back.
     */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    r = archive_write_set_compression_bzip2(a);
    if (r == ARCHIVE_FATAL) {
        skipping("bzip2 writing not supported on this platform");
        assertEqualInt(ARCHIVE_OK, archive_write_finish(a));
        return;
    }
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_bytes_per_block(a, 10));
    assertEqualInt(ARCHIVE_COMPRESSION_BZIP2, archive_compression(a));
    assertEqualString("bzip2", archive_compression_name(a));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used1));
    assertEqualInt(ARCHIVE_COMPRESSION_BZIP2, archive_compression(a));
    assertEqualString("bzip2", archive_compression_name(a));
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_filetype(ae, AE_IFREG);
    archive_entry_set_size(ae, datasize);
    for (i = 0; i < 999; i++) {
        sprintf(path, "file%03d", i);
        archive_entry_copy_pathname(ae, path);
        assertA(0 == archive_write_header(a, ae));
        assertA(datasize
            == (size_t)archive_write_data(a, data, datasize));
    }
    archive_entry_free(ae);
    archive_write_close(a);
    assert(0 == archive_write_finish(a));

    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff, used1));
    for (i = 0; i < 999; i++) {
        sprintf(path, "file%03d", i);
        if (!assertEqualInt(0, archive_read_next_header(a, &ae)))
            break;
        assertEqualString(path, archive_entry_pathname(ae));
        assertEqualInt((int)datasize, archive_entry_size(ae));
    }
    assert(0 == archive_read_close(a));
    assert(0 == archive_read_finish(a));

    /*
     * Repeat the cycle again, this time setting some compression
     * options.
     */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_bytes_per_block(a, 10));
    assertA(0 == archive_write_set_compression_bzip2(a));
    assertEqualIntA(a, ARCHIVE_WARN,
        archive_write_set_compressor_options(a, "nonexistent-option=0"));
    assertEqualIntA(a, ARCHIVE_WARN,
        archive_write_set_compressor_options(a, "compression-level=abc"));
    assertEqualIntA(a, ARCHIVE_WARN,
        archive_write_set_compressor_options(a, "compression-level=99"));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_compressor_options(a, "compression-level=9"));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used2));
    for (i = 0; i < 999; i++) {
        sprintf(path, "file%03d", i);
        assert((ae = archive_entry_new()) != NULL);
        archive_entry_copy_pathname(ae, path);
        archive_entry_set_size(ae, datasize);
        archive_entry_set_filetype(ae, AE_IFREG);
        assertA(0 == archive_write_header(a, ae));
        assertA(datasize == (size_t)archive_write_data(a, data, datasize));
        archive_entry_free(ae);
    }
    archive_write_close(a);
    assert(0 == archive_write_finish(a));

    /* Curiously, this test fails; the test data above compresses
     * better at default compression than at level 9. */
    /*
    failure("compression-level=9 wrote %d bytes, default wrote %d bytes",
        (int)used2, (int)used1);
    assert(used2 < used1);
    */

    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff, used2));
    for (i = 0; i < 999; i++) {
        sprintf(path, "file%03d", i);
        if (!assertEqualInt(0, archive_read_next_header(a, &ae)))
            break;
        assertEqualString(path, archive_entry_pathname(ae));
        assertEqualInt((int)datasize, archive_entry_size(ae));
    }
    assert(0 == archive_read_close(a));
    assert(0 == archive_read_finish(a));

    /*
     * Repeat again, with much lower compression.
     */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_bytes_per_block(a, 10));
    assertA(0 == archive_write_set_compression_bzip2(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_compressor_options(a, "compression-level=1"));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used2));
    for (i = 0; i < 999; i++) {
        sprintf(path, "file%03d", i);
        assert((ae = archive_entry_new()) != NULL);
        archive_entry_copy_pathname(ae, path);
        archive_entry_set_size(ae, datasize);
        archive_entry_set_filetype(ae, AE_IFREG);
        assertA(0 == archive_write_header(a, ae));
        failure("Writing file %s", path);
        assertEqualIntA(a, datasize,
            (size_t)archive_write_data(a, data, datasize));
        archive_entry_free(ae);
    }
    archive_write_close(a);
    assert(0 == archive_write_finish(a));

    /* Level 0 really does result in larger data. */
    failure("Compression-level=0 wrote %d bytes; default wrote %d bytes",
        (int)used2, (int)used1);
    assert(used2 > used1);

    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff, used2));
    for (i = 0; i < 999; i++) {
        sprintf(path, "file%03d", i);
        if (!assertEqualInt(0, archive_read_next_header(a, &ae)))
            break;
        assertEqualString(path, archive_entry_pathname(ae));
        assertEqualInt((int)datasize, archive_entry_size(ae));
    }
    assert(0 == archive_read_close(a));
    assert(0 == archive_read_finish(a));

    /*
     * Test various premature shutdown scenarios to make sure we
     * don't crash or leak memory.
     */
    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_bzip2(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_bzip2(a));
    assertEqualInt(ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_bzip2(a));
    assertEqualInt(ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_bzip2(a));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used2));
    assertEqualInt(ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    /*
     * Clean up.
     */
    free(data);
    free(buff);
}

--- NEW FILE: test_write_compress_gzip.c ---
/*-
 * Copyright (c) 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 "test.h"
__FBSDID("$FreeBSD$");

/*
 * A basic exercise of gzip reading and writing.
 *
 * TODO: Add a reference file and make sure we can decompress that.
 */

DEFINE_TEST(test_write_compress_gzip)
{
    struct archive_entry *ae;
    struct archive* a;
    char *buff, *data;
    size_t buffsize, datasize;
    char path[16];
    size_t used1, used2;
    int i, r;

    buffsize = 2000000;
    assert(NULL != (buff = (char *)malloc(buffsize)));

    datasize = 10000;
    assert(NULL != (data = (char *)malloc(datasize)));
    memset(data, 0, datasize);

    /*
     * Write a 100 files and read them all back.
     */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    r = archive_write_set_compression_gzip(a);
    if (r == ARCHIVE_FATAL) {
        skipping("gzip writing not supported on this platform");
        assertEqualInt(ARCHIVE_OK, archive_write_finish(a));
        return;
    }
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_bytes_per_block(a, 10));
    assertEqualInt(ARCHIVE_COMPRESSION_GZIP, archive_compression(a));
    assertEqualString("gzip", archive_compression_name(a));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used1));
    assertEqualInt(ARCHIVE_COMPRESSION_GZIP, archive_compression(a));
    assertEqualString("gzip", archive_compression_name(a));
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_filetype(ae, AE_IFREG);
    archive_entry_set_size(ae, datasize);
    for (i = 0; i < 100; i++) {
        sprintf(path, "file%03d", i);
        archive_entry_copy_pathname(ae, path);
        assertA(0 == archive_write_header(a, ae));
        assertA(datasize
            == (size_t)archive_write_data(a, data, datasize));
    }
    archive_entry_free(ae);
    archive_write_close(a);
    assert(0 == archive_write_finish(a));

    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    r = archive_read_support_compression_gzip(a);
    if (r == ARCHIVE_WARN) {
        skipping("Can't verify gzip writing by reading back;"
            " gzip reading not fully supported on this platform");
    } else {
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_support_compression_all(a));
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_open_memory(a, buff, used1));
        for (i = 0; i < 100; i++) {
            sprintf(path, "file%03d", i);
            if (!assertEqualInt(ARCHIVE_OK,
                archive_read_next_header(a, &ae)))
                break;
            assertEqualString(path, archive_entry_pathname(ae));
            assertEqualInt((int)datasize, archive_entry_size(ae));
        }
        assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    }
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));

    /*
     * Repeat the cycle again, this time setting some compression
     * options.
     */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_bytes_per_block(a, 10));
    assertA(0 == archive_write_set_compression_gzip(a));
    assertEqualIntA(a, ARCHIVE_WARN,
        archive_write_set_compressor_options(a, "nonexistent-option=0"));
    assertEqualIntA(a, ARCHIVE_WARN,
        archive_write_set_compressor_options(a, "compression-level=abc"));
    assertEqualIntA(a, ARCHIVE_WARN,
        archive_write_set_compressor_options(a, "compression-level=99"));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_compressor_options(a, "compression-level=9"));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used2));
    for (i = 0; i < 100; i++) {
        sprintf(path, "file%03d", i);
        assert((ae = archive_entry_new()) != NULL);
        archive_entry_copy_pathname(ae, path);
        archive_entry_set_size(ae, datasize);
        archive_entry_set_filetype(ae, AE_IFREG);
        assertA(0 == archive_write_header(a, ae));
        assertA(datasize == (size_t)archive_write_data(a, data, datasize));
        archive_entry_free(ae);
    }
    archive_write_close(a);
    assert(0 == archive_write_finish(a));

    /* Curiously, this test fails; the test data above compresses
     * better at default compression than at level 9. */
    /*
    failure("compression-level=9 wrote %d bytes, default wrote %d bytes",
        (int)used2, (int)used1);
    assert(used2 < used1);
    */

    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    r = archive_read_support_compression_gzip(a);
    if (r == ARCHIVE_WARN) {
        skipping("gzip reading not fully supported on this platform");
    } else {
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_support_compression_all(a));
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_open_memory(a, buff, used2));
        for (i = 0; i < 100; i++) {
            sprintf(path, "file%03d", i);
            if (!assertEqualInt(ARCHIVE_OK,
                archive_read_next_header(a, &ae)))
                break;
            assertEqualString(path, archive_entry_pathname(ae));
            assertEqualInt((int)datasize, archive_entry_size(ae));
        }
        assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    }
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));

    /*
     * Repeat again, with much lower compression.
     */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_bytes_per_block(a, 10));
    assertA(0 == archive_write_set_compression_gzip(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_set_compressor_options(a, "compression-level=0"));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used2));
    for (i = 0; i < 100; i++) {
        sprintf(path, "file%03d", i);
        assert((ae = archive_entry_new()) != NULL);
        archive_entry_copy_pathname(ae, path);
        archive_entry_set_size(ae, datasize);
        archive_entry_set_filetype(ae, AE_IFREG);
        assertA(0 == archive_write_header(a, ae));
        failure("Writing file %s", path);
        assertEqualIntA(a, datasize,
            (size_t)archive_write_data(a, data, datasize));
        archive_entry_free(ae);
    }
    archive_write_close(a);
    assert(0 == archive_write_finish(a));

    /* Level 0 really does result in larger data. */
    failure("Compression-level=0 wrote %d bytes; default wrote %d bytes",
        (int)used2, (int)used1);
    assert(used2 > used1);

    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    r = archive_read_support_compression_gzip(a);
    if (r == ARCHIVE_WARN) {
        skipping("gzip reading not fully supported on this platform");
    } else {
        assertEqualIntA(a, ARCHIVE_OK,
            archive_read_open_memory(a, buff, used2));
        for (i = 0; i < 100; i++) {
            sprintf(path, "file%03d", i);
            if (!assertEqualInt(ARCHIVE_OK,
                archive_read_next_header(a, &ae)))
                break;
            assertEqualString(path, archive_entry_pathname(ae));
            assertEqualInt((int)datasize, archive_entry_size(ae));
        }
        assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    }
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));

    /*
     * Test various premature shutdown scenarios to make sure we
     * don't crash or leak memory.
     */
    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_gzip(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_gzip(a));
    assertEqualInt(ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_gzip(a));
    assertEqualInt(ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_gzip(a));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used2));
    assertEqualInt(ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    /*
     * Clean up.
     */
    free(data);
    free(buff);
}

--- NEW FILE: .cvsignore ---
*.tar
*.tar.gz
*.tgz
*.zip
.depend
.deps
.dirstamp
archive.h
libarchive_test
list.h

--- NEW FILE: test_write_format_cpio_odc.c ---
/*-
 * 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/lib/libarchive/test/test_write_format_cpio_odc.c,v 1.2 2008/09/01 05:38:33 kientzle Exp $");


static int
is_octal(const char *p, size_t l)
{
    while (l > 0) {
        if (*p < '0' || *p > '7')
            return (0);
        --l;
        ++p;
    }
    return (1);
}

/*
 * Detailed verification that cpio 'odc' archives are written with
 * the correct format.
 */
DEFINE_TEST(test_write_format_cpio_odc)
{
    struct archive *a;
    struct archive_entry *entry;
    char *buff, *e;
    size_t buffsize = 100000;
    size_t used;

    buff = malloc(buffsize);

    /* Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, 0, archive_write_set_format_cpio(a));
    assertEqualIntA(a, 0, archive_write_set_compression_none(a));
    assertEqualIntA(a, 0, archive_write_open_memory(a, buff, buffsize, &used));

    /*
     * Add various files to it.
     * TODO: Extend this to cover more filetypes.
     */

    /* "file" with 10 bytes of content */
    assert((entry = archive_entry_new()) != NULL);
    archive_entry_set_mtime(entry, 1, 10);
    archive_entry_set_pathname(entry, "file");
    archive_entry_set_mode(entry, S_IFREG | 0664);
    archive_entry_set_size(entry, 10);
    archive_entry_set_uid(entry, 80);
    archive_entry_set_gid(entry, 90);
    archive_entry_set_dev(entry, 12);
    archive_entry_set_ino(entry, 89);
    archive_entry_set_nlink(entry, 2);
    assertEqualIntA(a, 0, archive_write_header(a, entry));
    archive_entry_free(entry);
    assertEqualIntA(a, 10, archive_write_data(a, "1234567890", 10));

    /* Hardlink to "file" with 10 bytes of content */
    assert((entry = archive_entry_new()) != NULL);
    archive_entry_set_mtime(entry, 1, 10);
    archive_entry_set_pathname(entry, "linkfile");
    archive_entry_set_mode(entry, S_IFREG | 0664);
    archive_entry_set_size(entry, 10);
    archive_entry_set_uid(entry, 80);
    archive_entry_set_gid(entry, 90);
    archive_entry_set_dev(entry, 12);
    archive_entry_set_ino(entry, 89);
    archive_entry_set_nlink(entry, 2);
    assertEqualIntA(a, 0, archive_write_header(a, entry));
    archive_entry_free(entry);
    assertEqualIntA(a, 10, archive_write_data(a, "1234567890", 10));

    /* "dir" */
    assert((entry = archive_entry_new()) != NULL);
    archive_entry_set_mtime(entry, 2, 20);
    archive_entry_set_pathname(entry, "dir");
    archive_entry_set_mode(entry, S_IFDIR | 0775);
    archive_entry_set_size(entry, 10);
    archive_entry_set_nlink(entry, 2);
    assertEqualIntA(a, 0, archive_write_header(a, entry));
    archive_entry_free(entry);
    /* Write of data to dir should fail == zero bytes get written. */
    assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10));

    /* "symlink" pointing to "file" */
    assert((entry = archive_entry_new()) != NULL);
    archive_entry_set_mtime(entry, 3, 30);
    archive_entry_set_pathname(entry, "symlink");
    archive_entry_set_mode(entry, 0664);
    archive_entry_set_filetype(entry, AE_IFLNK);
    archive_entry_set_symlink(entry,"file");
    archive_entry_set_size(entry, 0);
    archive_entry_set_uid(entry, 88);
    archive_entry_set_gid(entry, 98);
    archive_entry_set_dev(entry, 12);
    archive_entry_set_ino(entry, 90);
    archive_entry_set_nlink(entry, 1);
    assertEqualIntA(a, 0, archive_write_header(a, entry));
    archive_entry_free(entry);
    /* Write of data to symlink should fail == zero bytes get written. */
    assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10));

#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assert(0 == archive_write_finish(a));
#endif

    /*
     * Verify the archive format.
     */
    e = buff;

    /* "file" */
    assert(is_octal(e, 76)); /* Entire header is octal digits. */
    assertEqualMem(e + 0, "070707", 6); /* Magic */
    assertEqualMem(e + 6, "000014", 6); /* dev */
    assertEqualMem(e + 12, "000131", 6); /* ino */
    assertEqualMem(e + 18, "100664", 6); /* Mode */
    assertEqualMem(e + 24, "000120", 6); /* uid */
    assertEqualMem(e + 30, "000132", 6); /* gid */
    assertEqualMem(e + 36, "000002", 6); /* nlink */
    assertEqualMem(e + 42, "000000", 6); /* rdev */
    assertEqualMem(e + 48, "00000000001", 11); /* mtime */
    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;

    /* hardlink to "file" */
    assert(is_octal(e, 76)); /* Entire header is octal digits. */
    assertEqualMem(e + 0, "070707", 6); /* Magic */
    assertEqualMem(e + 6, "000014", 6); /* dev */
    assertEqualMem(e + 12, "000131", 6); /* ino */
    assertEqualMem(e + 18, "100664", 6); /* Mode */
    assertEqualMem(e + 24, "000120", 6); /* uid */
    assertEqualMem(e + 30, "000132", 6); /* gid */
    assertEqualMem(e + 36, "000002", 6); /* nlink */
    assertEqualMem(e + 42, "000000", 6); /* rdev */
    assertEqualMem(e + 48, "00000000001", 11); /* mtime */
    assertEqualMem(e + 59, "000011", 6); /* Name size */
    assertEqualMem(e + 65, "00000000012", 11); /* File size */
    assertEqualMem(e + 76, "linkfile\0", 9); /* Name contents */
    assertEqualMem(e + 85, "1234567890", 10); /* File contents */
    e += 95;

    /* "dir" */
    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, "040775", 6); /* Mode */
    assertEqualMem(e + 24, "000000", 6); /* uid */
    assertEqualMem(e + 30, "000000", 6); /* gid */
    assertEqualMem(e + 36, "000002", 6); /* Nlink */
    assertEqualMem(e + 42, "000000", 6); /* rdev */
    assertEqualMem(e + 48, "00000000002", 11); /* mtime */
    assertEqualMem(e + 59, "000004", 6); /* Name size */
    assertEqualMem(e + 65, "00000000000", 11); /* File size */
    assertEqualMem(e + 76, "dir\0", 4); /* name */
    e += 80;

    /* "symlink" pointing to "file" */
    assert(is_octal(e, 76)); /* Entire header is octal digits. */
    assertEqualMem(e + 0, "070707", 6); /* Magic */
    assertEqualMem(e + 6, "000014", 6); /* dev */
    assertEqualMem(e + 12, "000132", 6); /* ino */
    assertEqualMem(e + 18, "120664", 6); /* Mode */
    assertEqualMem(e + 24, "000130", 6); /* uid */
    assertEqualMem(e + 30, "000142", 6); /* gid */
    assertEqualMem(e + 36, "000001", 6); /* nlink */
    assertEqualMem(e + 42, "000000", 6); /* rdev */
    assertEqualMem(e + 48, "00000000003", 11); /* mtime */
    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); /* File contents == link target */
    e += 88;

    /* 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 */
    e += 87;

    assertEqualInt((int)used, e - buff);

    free(buff);
}

--- NEW FILE: test_read_position.c ---
/*-
 * 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/lib/libarchive/test/test_read_position.c,v 1.4 2008/09/01 05:38:33 kientzle Exp $");

static unsigned char nulls[10000];
static unsigned char  buff[10000000];

/* Check that header_position tracks correctly on read. */
DEFINE_TEST(test_read_position)
{
    struct archive *a;
    struct archive_entry *ae;
    size_t write_pos;
    intmax_t read_position;
    size_t i, j;
    size_t data_sizes[] = {0, 5, 511, 512, 513};

    /* Sanity test */
    assert(sizeof(nulls) + 512 + 1024 <= sizeof(buff));

    /* Create an archive. */
    assert(NULL != (a = archive_write_new()));
    assertA(0 == archive_write_set_format_pax_restricted(a));
    assertA(0 == archive_write_set_bytes_per_block(a, 512));
    assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &write_pos));

    for (i = 0; i < sizeof(data_sizes)/sizeof(data_sizes[0]); ++i) {
        /* Create a simple archive_entry. */
        assert((ae = archive_entry_new()) != NULL);
        archive_entry_set_pathname(ae, "testfile");
        archive_entry_set_mode(ae, S_IFREG);
        archive_entry_set_size(ae, data_sizes[i]);
        assertA(0 == archive_write_header(a, ae));
        archive_entry_free(ae);
        assertA(data_sizes[i]
            == (size_t)archive_write_data(a, nulls, sizeof(nulls)));
    }
    assertA(0 == archive_write_close(a));
    assertA(0 == archive_write_finish(a));

    /* Read the archive back. */
    assert(NULL != (a = archive_read_new()));
    assertA(0 == archive_read_support_format_tar(a));
    assertA(0 == archive_read_open_memory2(a, buff, sizeof(buff), 512));

    read_position = 0;
    /* Initial header position is zero. */
    assert(read_position == (intmax_t)archive_read_header_position(a));
    for (j = 0; j < i; ++j) {
        assertA(0 == archive_read_next_header(a, &ae));
        assert(read_position
            == (intmax_t)archive_read_header_position(a));
        /* Every other entry: read, then skip */
        if (j & 1)
            assertEqualInt(ARCHIVE_OK,
                archive_read_data_into_buffer(a, buff, 1));
        assertA(0 == archive_read_data_skip(a));
        /* read_data_skip() doesn't change header_position */
        assert(read_position
            == (intmax_t)archive_read_header_position(a));

        read_position += 512; /* Size of header. */
        read_position += (data_sizes[j] + 511) & ~511;
    }

    assertA(1 == archive_read_next_header(a, &ae));
    assert(read_position == (intmax_t)archive_read_header_position(a));
    assertA(0 == archive_read_close(a));
    assert(read_position == (intmax_t)archive_read_header_position(a));
    archive_read_finish(a);
}

--- NEW FILE: test_read_format_tgz.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_tgz.c,v 1.2 2008/09/01 05:38:33 kientzle Exp $");

static unsigned char archive[] = {
31,139,8,0,222,'C','p','C',0,3,211,'c',160,'=','0','0','0','0','7','5','U',
0,210,134,230,166,6,200,'4',28,'(',24,26,24,27,155,24,152,24,154,27,155,')',
24,24,26,152,154,25,'2','(',152,210,193,'m',12,165,197,'%',137,'E','@',167,
148,'d',230,226,'U','G','H',30,234,15,'8','=',10,'F',193,'(',24,5,131,28,
0,0,29,172,5,240,0,6,0,0};

DEFINE_TEST(test_read_format_tgz)
{
    struct archive_entry *ae;
    struct archive *a;
    int r;

    assert((a = archive_read_new()) != NULL);
    assertEqualInt(ARCHIVE_OK, archive_read_support_compression_all(a));
    r = archive_read_support_compression_gzip(a);
    if (r == ARCHIVE_WARN) {
        skipping("gzip reading not fully supported on this platform");
        assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
        return;
    }
    assertEqualInt(ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualInt(ARCHIVE_OK,
        archive_read_open_memory(a, archive, sizeof(archive)));
    assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualInt(archive_compression(a),
        ARCHIVE_COMPRESSION_GZIP);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR);
    assertEqualInt(ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK,archive_read_finish(a));
}



--- NEW FILE: test_read_format_cpio_bin_be.c ---
/*-
 * 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_read_format_cpio_bin_be)
{
    struct archive_entry *ae;
    struct archive *a;
    const char *reference = "test_read_format_cpio_bin_be.cpio";

    extract_reference_file(reference);
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_open_filename(a, reference, 10));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString(archive_entry_pathname(ae), "file1111222233334444");
    assertEqualInt(archive_entry_size(ae), 5);
    assertEqualInt(archive_entry_mtime(ae), 1240664175);
    assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
    assertEqualInt(archive_entry_uid(ae), 1000);
    assertEqualInt(archive_entry_gid(ae), 0);

    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_NONE);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_BIN_BE);
    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}



--- NEW FILE: test_read_format_iso_gz.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_iso_gz.c,v 1.2 2008/09/01 05:38:33 kientzle Exp $");

DEFINE_TEST(test_read_format_iso_gz)
{
    struct archive_entry *ae;
    struct archive *a;
    int r;
    const char *name = "test_read_format_iso_gz.iso.gz";

    extract_reference_file(name);

    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_support_compression_all(a));
    r = archive_read_support_compression_gzip(a);
    if (r == ARCHIVE_WARN) {
        skipping("gzip reading not fully supported on this platform");
        assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
        return;
    }
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_open_filename(a, name, 512));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_next_header(a, &ae));
    assertEqualInt(archive_compression(a),
        ARCHIVE_COMPRESSION_GZIP);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ISO9660);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}



--- NEW FILE: test_write_disk_secure.c ---
/*-
 * 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/lib/libarchive/test/test_write_disk_secure.c,v 1.8 2008/09/07 23:59:27 kientzle Exp $");

#define UMASK 022

/*
 * Exercise security checks that should prevent certain
 * writes.
 */

DEFINE_TEST(test_write_disk_secure)
{
#if ARCHIVE_VERSION_NUMBER < 1009000
    skipping("archive_write_disk interface");
#elif !defined(_WIN32) || defined(__CYGWIN__)
    struct archive *a;
    struct archive_entry *ae;
    struct stat st;

    /* Start with a known umask. */
    assertUmask(UMASK);

    /* Create an archive_write_disk object. */
    assert((a = archive_write_disk_new()) != NULL);

    /* Write a regular dir to it. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "dir");
    archive_entry_set_mode(ae, S_IFDIR | 0777);
    assert(0 == archive_write_header(a, ae));
    archive_entry_free(ae);
    assert(0 == archive_write_finish_entry(a));

    /* Write a symlink to the dir above. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "link_to_dir");
    archive_entry_set_mode(ae, S_IFLNK | 0777);
    archive_entry_set_symlink(ae, "dir");
    archive_write_disk_set_options(a, 0);
    assert(0 == archive_write_header(a, ae));
    assert(0 == archive_write_finish_entry(a));

    /*
     * Without security checks, we should be able to
     * extract a file through the link.
     */
    assert(archive_entry_clear(ae) != NULL);
    archive_entry_copy_pathname(ae, "link_to_dir/filea");
    archive_entry_set_mode(ae, S_IFREG | 0777);
    assert(0 == archive_write_header(a, ae));
    assert(0 == archive_write_finish_entry(a));

    /* But with security checks enabled, this should fail. */
    assert(archive_entry_clear(ae) != NULL);
    archive_entry_copy_pathname(ae, "link_to_dir/fileb");
    archive_entry_set_mode(ae, S_IFREG | 0777);
    archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS);
    failure("Extracting a file through a symlink should fail here.");
    assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
    archive_entry_free(ae);
    assert(0 == archive_write_finish_entry(a));

    /* Create another link. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "link_to_dir2");
    archive_entry_set_mode(ae, S_IFLNK | 0777);
    archive_entry_set_symlink(ae, "dir");
    archive_write_disk_set_options(a, 0);
    assert(0 == archive_write_header(a, ae));
    assert(0 == archive_write_finish_entry(a));

    /*
     * With symlink check and unlink option, it should remove
     * the link and create the dir.
     */
    assert(archive_entry_clear(ae) != NULL);
    archive_entry_copy_pathname(ae, "link_to_dir2/filec");
    archive_entry_set_mode(ae, S_IFREG | 0777);
    archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS | ARCHIVE_EXTRACT_UNLINK);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
    archive_entry_free(ae);
    assert(0 == archive_write_finish_entry(a));

    /*
     * Without security checks, extracting a dir over a link to a
     * dir should follow the link.
     */
    /* Create a symlink to a dir. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "link_to_dir3");
    archive_entry_set_mode(ae, S_IFLNK | 0777);
    archive_entry_set_symlink(ae, "dir");
    archive_write_disk_set_options(a, 0);
    assert(0 == archive_write_header(a, ae));
    assert(0 == archive_write_finish_entry(a));
    /* Extract a dir whose name matches the symlink. */
    assert(archive_entry_clear(ae) != NULL);
    archive_entry_copy_pathname(ae, "link_to_dir3");
    archive_entry_set_mode(ae, S_IFDIR | 0777);
    assert(0 == archive_write_header(a, ae));
    assert(0 == archive_write_finish_entry(a));
    /* Verify link was followed. */
    assertEqualInt(0, lstat("link_to_dir3", &st));
    assert(S_ISLNK(st.st_mode));
    archive_entry_free(ae);

    /*
     * As above, but a broken link, so the link should get replaced.
     */
    /* Create a symlink to a dir. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "link_to_dir4");
    archive_entry_set_mode(ae, S_IFLNK | 0777);
    archive_entry_set_symlink(ae, "nonexistent_dir");
    archive_write_disk_set_options(a, 0);
    assert(0 == archive_write_header(a, ae));
    assert(0 == archive_write_finish_entry(a));
    /* Extract a dir whose name matches the symlink. */
    assert(archive_entry_clear(ae) != NULL);
    archive_entry_copy_pathname(ae, "link_to_dir4");
    archive_entry_set_mode(ae, S_IFDIR | 0777);
    assert(0 == archive_write_header(a, ae));
    assert(0 == archive_write_finish_entry(a));
    /* Verify link was replaced. */
    assertEqualInt(0, lstat("link_to_dir4", &st));
    assert(S_ISDIR(st.st_mode));
    archive_entry_free(ae);

    /*
     * As above, but a link to a non-dir, so the link should get replaced.
     */
    /* Create a regular file and a symlink to it */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "non_dir");
    archive_entry_set_mode(ae, S_IFREG | 0777);
    archive_write_disk_set_options(a, 0);
    assert(0 == archive_write_header(a, ae));
    assert(0 == archive_write_finish_entry(a));
    /* Create symlink to the file. */
    archive_entry_copy_pathname(ae, "link_to_dir5");
    archive_entry_set_mode(ae, S_IFLNK | 0777);
    archive_entry_set_symlink(ae, "non_dir");
    archive_write_disk_set_options(a, 0);
    assert(0 == archive_write_header(a, ae));
    assert(0 == archive_write_finish_entry(a));
    /* Extract a dir whose name matches the symlink. */
    assert(archive_entry_clear(ae) != NULL);
    archive_entry_copy_pathname(ae, "link_to_dir5");
    archive_entry_set_mode(ae, S_IFDIR | 0777);
    assert(0 == archive_write_header(a, ae));
    assert(0 == archive_write_finish_entry(a));
    /* Verify link was replaced. */
    assertEqualInt(0, lstat("link_to_dir5", &st));
    assert(S_ISDIR(st.st_mode));
    archive_entry_free(ae);

    assert(0 == archive_write_finish(a));

    /* Test the entries on disk. */
    assert(0 == lstat("dir", &st));
    failure("dir: st.st_mode=%o", st.st_mode);
    assert((st.st_mode & 0777) == 0755);

    assert(0 == lstat("link_to_dir", &st));
    failure("link_to_dir: st.st_mode=%o", st.st_mode);
    assert(S_ISLNK(st.st_mode));
#if HAVE_LCHMOD
    /* Systems that lack lchmod() can't set symlink perms, so skip this. */
    failure("link_to_dir: st.st_mode=%o", st.st_mode);
    assert((st.st_mode & 07777) == 0755);
#endif

    assert(0 == lstat("dir/filea", &st));
    failure("dir/filea: st.st_mode=%o", st.st_mode);
    assert((st.st_mode & 07777) == 0755);

    failure("dir/fileb: This file should not have been created");
    assert(0 != lstat("dir/fileb", &st));

    assert(0 == lstat("link_to_dir2", &st));
    failure("link_to_dir2 should have been re-created as a true dir");
    assert(S_ISDIR(st.st_mode));
    failure("link_to_dir2: Implicit dir creation should obey umask, but st.st_mode=%o", st.st_mode);
    assert((st.st_mode & 0777) == 0755);

    assert(0 == lstat("link_to_dir2/filec", &st));
    assert(S_ISREG(st.st_mode));
    failure("link_to_dir2/filec: st.st_mode=%o", st.st_mode);
    assert((st.st_mode & 07777) == 0755);
#endif
}

--- NEW FILE: test_read_format_isojoliet_rr.c ---
/*-
 * Copyright (c) 2003-2007 Tim Kientzle
 * All rights reserved.
 *
 * Based on libarchive/test/test_read_format_isorr_bz2.c with
 * bugs introduced by Andreas Henriksson <andreas at fatal.se> for
 * testing ISO9660 image with Joliet extension.
 *
 * 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"

/*
Execute the following to rebuild the data for this program:
   tail -n +35 test_read_format_isojoliet_rr.c | /bin/sh

rm -rf /tmp/iso
mkdir /tmp/iso
mkdir /tmp/iso/dir
file="long-joliet-file-name.textfile"
echo "hello" >/tmp/iso/$file
ln /tmp/iso/$file /tmp/iso/hardlink
(cd /tmp/iso; ln -s $file symlink)
if [ "$(uname -s)" = "Linux" ]; then # gnu coreutils touch doesn't have -h
TZ=utc touch -afm -t 197001020000.01 /tmp/iso/hardlink /tmp/iso/$file /tmp/iso/dir
TZ=utc touch -afm -t 197001030000.02 /tmp/iso/symlink
TZ=utc touch -afm -t 197001020000.01 /tmp/iso
else
TZ=utc touch -afhm -t 197001020000.01 /tmp/iso/hardlink /tmp/iso/$file /tmp/iso/dir
TZ=utc touch -afhm -t 197001030000.02 /tmp/iso/symlink
TZ=utc touch -afhm -t 197001020000.01 /tmp/iso
fi
F=test_read_format_isojoliet_rr.iso.bz2
mkhybrid -J -uid 1 -gid 2 /tmp/iso | bzip2 > $F
uuencode $F $F > $F.uu
exit 1
 */

DEFINE_TEST(test_read_format_isojoliet_rr)
{
    const char *refname = "test_read_format_isojoliet_rr.iso.bz2";
    struct archive_entry *ae;
    struct archive *a;
    const void *p;
    size_t size;
    off_t offset;
    int r;

    extract_reference_file(refname);
    assert((a = archive_read_new()) != NULL);
    r = archive_read_support_compression_bzip2(a);
    if (r == ARCHIVE_WARN) {
        skipping("bzip2 reading not fully supported on this platform");
        assertEqualInt(0, archive_read_finish(a));
        return;
    }
    assertEqualInt(0, r);
    assertEqualInt(0, archive_read_support_format_all(a));
    assertEqualInt(ARCHIVE_OK,
        archive_read_open_filename(a, refname, 10240));

    /* First entry is '.' root directory. */
    assertEqualInt(0, archive_read_next_header(a, &ae));
    assertEqualString(".", archive_entry_pathname(ae));
    assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
    assertEqualInt(2048, archive_entry_size(ae));
    assertEqualInt(86401, archive_entry_mtime(ae));
    assertEqualInt(0, archive_entry_mtime_nsec(ae));
    assertEqualInt(3, archive_entry_stat(ae)->st_nlink);
    assertEqualInt(1, archive_entry_uid(ae));
    assertEqualIntA(a, ARCHIVE_EOF,
        archive_read_data_block(a, &p, &size, &offset));
    assertEqualInt((int)size, 0);

    /* A directory. */
    assertEqualInt(0, archive_read_next_header(a, &ae));
    assertEqualString("dir", archive_entry_pathname(ae));
    assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
    assertEqualInt(2048, archive_entry_size(ae));
    assertEqualInt(86401, archive_entry_mtime(ae));
    assertEqualInt(86401, archive_entry_atime(ae));
    assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
    assertEqualInt(1, archive_entry_uid(ae));
    assertEqualInt(2, archive_entry_gid(ae));

    /* A regular file with two names ("hardlink" gets returned
     * first, so it's not marked as a hardlink). */
    assertEqualInt(0, archive_read_next_header(a, &ae));
    assertEqualString("hardlink", archive_entry_pathname(ae));
    assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
    assert(archive_entry_hardlink(ae) == NULL);
    assertEqualInt(6, archive_entry_size(ae));
    assertEqualInt(0, archive_read_data_block(a, &p, &size, &offset));
    assertEqualInt(6, (int)size);
    assertEqualInt(0, offset);
    assertEqualInt(0, memcmp(p, "hello\n", 6));
    assertEqualInt(86401, archive_entry_mtime(ae));
    /* mkisofs records their access time. */
    /*assertEqualInt(86401, archive_entry_atime(ae));*/
    /* TODO: Actually, libarchive should be able to
     * compute nlinks correctly even without RR
     * extensions. See comments in libarchive source. */
    assertEqualInt(2, archive_entry_nlink(ae));
    assertEqualInt(1, archive_entry_uid(ae));
    assertEqualInt(2, archive_entry_gid(ae));

    /* Second name for the same regular file (this happens to be
     * returned second, so does get marked as a hardlink). */
    assertEqualInt(0, archive_read_next_header(a, &ae));
    assertEqualString("long-joliet-file-name.textfile",
        archive_entry_pathname(ae));
    assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
    assertEqualString("hardlink", archive_entry_hardlink(ae));
    assert(!archive_entry_size_is_set(ae));
    assertEqualInt(86401, archive_entry_mtime(ae));
    assertEqualInt(86401, archive_entry_atime(ae));
    /* TODO: See above. */
    assertEqualInt(2, archive_entry_nlink(ae));
    assertEqualInt(1, archive_entry_uid(ae));
    assertEqualInt(2, archive_entry_gid(ae));

    /* A symlink to the regular file. */
    assertEqualInt(0, archive_read_next_header(a, &ae));
    assertEqualString("symlink", archive_entry_pathname(ae));
    assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
    assertEqualString("long-joliet-file-name.textfile",
        archive_entry_symlink(ae));
    assertEqualInt(0, archive_entry_size(ae));
    assertEqualInt(172802, archive_entry_mtime(ae));
    assertEqualInt(172802, archive_entry_atime(ae));
    assertEqualInt(1, archive_entry_nlink(ae));
    assertEqualInt(1, archive_entry_uid(ae));
    assertEqualInt(2, archive_entry_gid(ae));

    /* End of archive. */
    assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae));

    /* Verify archive format. */
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_BZIP2);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ISO9660_ROCKRIDGE);

    /* Close the archive. */
    assertEqualInt(0, archive_read_close(a));
    assertEqualInt(0, archive_read_finish(a));
}


--- NEW FILE: test_read_truncated.c ---
/*-
 * 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/lib/libarchive/test/test_read_truncated.c,v 1.4 2008/09/01 05:38:33 kientzle Exp $");

char buff[1000000];
char buff2[100000];

DEFINE_TEST(test_read_truncated)
{
    struct archive_entry *ae;
    struct archive *a;
    unsigned int i;
    size_t used;

    /* Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    assertA(0 == archive_write_set_compression_none(a));
    assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));

    /*
     * Write a file to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    for (i = 0; i < sizeof(buff2); i++)
        buff2[i] = (unsigned char)rand();
    archive_entry_set_size(ae, sizeof(buff2));
    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);
    assertA(sizeof(buff2) == archive_write_data(a, buff2, sizeof(buff2)));

    /* Close out the archive. */
    assertA(0 == archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assertA(0 == archive_write_finish(a));
#endif

    /* Now, read back a truncated version of the archive and
     * verify that we get an appropriate error. */
    for (i = 1; i < used + 100; i += 100) {
        assert((a = archive_read_new()) != NULL);
        assertA(0 == archive_read_support_format_all(a));
        assertA(0 == archive_read_support_compression_all(a));
        assertA(0 == archive_read_open_memory(a, buff, i));

        if (i < 512) {
            assertA(ARCHIVE_FATAL == archive_read_next_header(a, &ae));
            goto wrap_up;
        } else {
            assertA(0 == archive_read_next_header(a, &ae));
        }

        if (i < 512 + sizeof(buff2)) {
            assertA(ARCHIVE_FATAL == archive_read_data(a, buff2, sizeof(buff2)));
            goto wrap_up;
        } else {
            assertA(sizeof(buff2) == archive_read_data(a, buff2, sizeof(buff2)));
        }

        /* Verify the end of the archive. */
        /* Archive must be long enough to capture a 512-byte
         * block of zeroes after the entry.  (POSIX requires a
         * second block of zeros to be written but libarchive
         * does not return an error if it can't consume
         * it.) */
        if (i < 512 + 512*((sizeof(buff2) + 511)/512) + 512) {
            assertA(ARCHIVE_FATAL == archive_read_next_header(a, &ae));
        } else {
            assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae));
        }
    wrap_up:
        assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
        archive_read_finish(a);
#else
        assert(0 == archive_read_finish(a));
#endif
    }



    /* Same as above, except skip the body instead of reading it. */
    for (i = 1; i < used + 100; i += 100) {
        assert((a = archive_read_new()) != NULL);
        assertA(0 == archive_read_support_format_all(a));
        assertA(0 == archive_read_support_compression_all(a));
        assertA(0 == archive_read_open_memory(a, buff, i));

        if (i < 512) {
            assertA(ARCHIVE_FATAL == archive_read_next_header(a, &ae));
            goto wrap_up2;
        } else {
            assertA(0 == archive_read_next_header(a, &ae));
        }

        if (i < 512 + 512*((sizeof(buff2)+511)/512)) {
            assertA(ARCHIVE_FATAL == archive_read_data_skip(a));
            goto wrap_up2;
        } else {
            assertA(ARCHIVE_OK == archive_read_data_skip(a));
        }

        /* Verify the end of the archive. */
        /* Archive must be long enough to capture a 512-byte
         * block of zeroes after the entry.  (POSIX requires a
         * second block of zeros to be written but libarchive
         * does not return an error if it can't consume
         * it.) */
        if (i < 512 + 512*((sizeof(buff2) + 511)/512) + 512) {
            assertA(ARCHIVE_FATAL == archive_read_next_header(a, &ae));
        } else {
            assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae));
        }
    wrap_up2:
        assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
        archive_read_finish(a);
#else
        assert(0 == archive_read_finish(a));
#endif
    }
}

--- NEW FILE: test_read_format_isojoliet_long.c ---
/*-
 * Copyright (c) 2003-2007 Tim Kientzle
 * 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.
 */
#include "test.h"

/*
Execute the following to rebuild the data for this program:
   tail -n +35 test_read_format_isojoliet_long.c | /bin/sh

rm -rf /tmp/iso
mkdir /tmp/iso
num=0
file="";
while [ $num -lt 100 ]
do
  num=$((num+10))
  file="${file}1234567890"
done
dir="${file}dir"
mkdir /tmp/iso/${dir}
file="${file}123"
echo "hello" > /tmp/iso/${file}
ln /tmp/iso/${file} /tmp/iso/hardlink
if [ "$(uname -s)" = "Linux" ]; then # gnu coreutils touch doesn't have -h
TZ=utc touch -afm -t 197001020000.01 /tmp/iso /tmp/iso/${file} /tmp/iso/${dir}
else
TZ=utc touch -afhm -t 197001020000.01 /tmp/iso /tmp/iso/${file} /tmp/iso/${dir}
fi
F=test_read_format_isojoliet_long.iso.bz2
mkhybrid -J -joliet-long -uid 1 -gid 2 /tmp/iso | bzip2 > $F
uuencode $F $F > $F.uu
rm -rf /tmp/iso
exit 1
 */

DEFINE_TEST(test_read_format_isojoliet_long)
{
    const char *refname = "test_read_format_isojoliet_long.iso.bz2";
    char pathname[104];
    struct archive_entry *ae;
    struct archive *a;
    const void *p;
    size_t size;
    off_t offset;
    int i, r;

    for (i = 0; i < 100; i++)
        pathname[i] = '0' + ((i+1) % 10); 
    extract_reference_file(refname);
    assert((a = archive_read_new()) != NULL);
    r = archive_read_support_compression_bzip2(a);
    if (r == ARCHIVE_WARN) {
        skipping("bzip2 reading not fully supported on this platform");
        assertEqualInt(0, archive_read_finish(a));
        return;
    }
    assertEqualInt(0, r);
    assertEqualInt(0, archive_read_support_format_all(a));
    assertEqualInt(ARCHIVE_OK,
        archive_read_set_options(a, "iso9660:!rock-ridge"));
    assertEqualInt(ARCHIVE_OK,
        archive_read_open_filename(a, refname, 10240));

    /* First entry is '.' root directory. */
    assertEqualInt(0, archive_read_next_header(a, &ae));
    assertEqualString(".", archive_entry_pathname(ae));
    assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
    assertEqualInt(2048, archive_entry_size(ae));
    assertEqualInt(86401, archive_entry_mtime(ae));
    assertEqualInt(0, archive_entry_mtime_nsec(ae));
    assertEqualInt(86401, archive_entry_ctime(ae));
    assertEqualInt(0, archive_entry_stat(ae)->st_nlink);
    assertEqualInt(0, archive_entry_uid(ae));
    assertEqualIntA(a, ARCHIVE_EOF,
        archive_read_data_block(a, &p, &size, &offset));
    assertEqualInt((int)size, 0);

    /* A directory. */
    pathname[100] = 'd';
    pathname[101] = 'i';
    pathname[102] = 'r';
    pathname[103] = '\0';
    assertEqualInt(0, archive_read_next_header(a, &ae));
    assertEqualString(pathname, archive_entry_pathname(ae));
    assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
    assertEqualInt(2048, archive_entry_size(ae));
    assertEqualInt(86401, archive_entry_mtime(ae));
    assertEqualInt(86401, archive_entry_atime(ae));

    /* A regular file with two names ("hardlink" gets returned
     * first, so it's not marked as a hardlink). */
    assertEqualInt(0, archive_read_next_header(a, &ae));
    assertEqualString("hardlink", archive_entry_pathname(ae));
    assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
    assert(archive_entry_hardlink(ae) == NULL);
    assertEqualInt(6, archive_entry_size(ae));
    assertEqualInt(0, archive_read_data_block(a, &p, &size, &offset));
    assertEqualInt(6, (int)size);
    assertEqualInt(0, offset);
    assertEqualInt(0, memcmp(p, "hello\n", 6));

    /* Second name for the same regular file (this happens to be
     * returned second, so does get marked as a hardlink). */
    pathname[100] = '1';
    pathname[101] = '2';
    pathname[102] = '3';
    pathname[103] = '\0';
    assertEqualInt(0, archive_read_next_header(a, &ae));
    assertEqualString(pathname, archive_entry_pathname(ae));
    assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
    assertEqualString("hardlink", archive_entry_hardlink(ae));
    assert(!archive_entry_size_is_set(ae));

    /* End of archive. */
    assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae));

    /* Verify archive format. */
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_BZIP2);

    /* Close the archive. */
    assertEqualInt(0, archive_read_close(a));
    assertEqualInt(0, archive_read_finish(a));
}


--- NEW FILE: test_open_filename.c ---
/*-
 * 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_open_filename)
{
    char buff[64];
    struct archive_entry *ae;
    struct archive *a;

    /* Write an archive through this FILE *. */
    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_none(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_write_open_filename(a, "test.tar"));

    /*
     * Write a file to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_mtime(ae, 1, 0);
    archive_entry_copy_pathname(ae, "file");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    archive_entry_set_size(ae, 8);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
    archive_entry_free(ae);
    assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9));

    /*
     * Write a second file to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file2");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    archive_entry_set_size(ae, 819200);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
    archive_entry_free(ae);

    /* Close out the archive. */
    assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_finish(a));

    /*
     * Now, read the data back.
     */
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_open_filename(a, "test.tar", 512));

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualInt(1, archive_entry_mtime(ae));
    assertEqualInt(0, archive_entry_mtime_nsec(ae));
    assertEqualInt(0, archive_entry_atime(ae));
    assertEqualInt(0, archive_entry_ctime(ae));
    assertEqualString("file", archive_entry_pathname(ae));
    assert((S_IFREG | 0755) == archive_entry_mode(ae));
    assertEqualInt(8, archive_entry_size(ae));
    assertEqualIntA(a, 8, archive_read_data(a, buff, 10));
    assertEqualMem(buff, "12345678", 8);

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString("file2", archive_entry_pathname(ae));
    assert((S_IFREG | 0755) == archive_entry_mode(ae));
    assertEqualInt(819200, archive_entry_size(ae));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a));

    /* Verify the end of the archive. */
    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));

    /*
     * Verify some of the error handling.
     */
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_FATAL,
        archive_read_open_filename(a, "nonexistent.tar", 512));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));

}

--- NEW FILE: test_read_disk.c ---
/*-
 * 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$");

static void
gname_cleanup(void *d)
{
    int *mp = d;
    assertEqualInt(*mp, 0x13579);
    *mp = 0x2468;
}

static const char *
gname_lookup(void *d, gid_t g)
{
    int *mp = d;
    assertEqualInt(*mp, 0x13579);
    if (g == 1)
        return ("FOOGROUP");
    return ("NOTFOOGROUP");
}

static void
uname_cleanup(void *d)
{
    int *mp = d;
    assertEqualInt(*mp, 0x1234);
    *mp = 0x2345;
}

static const char *
uname_lookup(void *d, uid_t u)
{
    int *mp = d;
    assertEqualInt(*mp, 0x1234);
    if (u == 1)
        return ("FOO");
    return ("NOTFOO");
}

/* We test GID lookup by looking up the name of group number zero and
 * checking it against the following list.  If your system uses a
 * different conventional name for group number zero, please extend
 * this array and send us a patch.  As always, please keep this list
 * sorted alphabetically.
 */
static const char *zero_groups[] = {
    "root",   /* Linux */
    "wheel"  /* BSD */
};

DEFINE_TEST(test_read_disk)
{
    struct archive *a;
    int gmagic = 0x13579, umagic = 0x1234;
    const char *p;
    size_t i;

    assert((a = archive_read_disk_new()) != NULL);

    /* Default uname/gname lookups always return NULL. */
    assert(archive_read_disk_gname(a, 0) == NULL);
    assert(archive_read_disk_uname(a, 0) == NULL);

    /* Register some weird lookup functions. */
    assertEqualInt(ARCHIVE_OK, archive_read_disk_set_gname_lookup(a,
               &gmagic, &gname_lookup, &gname_cleanup));
    /* Verify that our new function got called. */
    assertEqualString(archive_read_disk_gname(a, 0), "NOTFOOGROUP");
    assertEqualString(archive_read_disk_gname(a, 1), "FOOGROUP");

    /* De-register. */
    assertEqualInt(ARCHIVE_OK,
        archive_read_disk_set_gname_lookup(a, NULL, NULL, NULL));
    /* Ensure our cleanup function got called. */
    assertEqualInt(gmagic, 0x2468);

    /* Same thing with uname lookup.... */
    assertEqualInt(ARCHIVE_OK, archive_read_disk_set_uname_lookup(a,
               &umagic, &uname_lookup, &uname_cleanup));
    assertEqualString(archive_read_disk_uname(a, 0), "NOTFOO");
    assertEqualString(archive_read_disk_uname(a, 1), "FOO");
    assertEqualInt(ARCHIVE_OK,
        archive_read_disk_set_uname_lookup(a, NULL, NULL, NULL));
    assertEqualInt(umagic, 0x2345);

    /* Try the standard lookup functions. */
    if (archive_read_disk_set_standard_lookup(a) != ARCHIVE_OK) {
        skipping("standard uname/gname lookup");
    } else {
#if defined(__CYGWIN__)
        skipping("standard uname/gname lookup; typically no user with uid=0 on cygwin platform");
        i = 0;
        p = zero_groups[0]; /* avoid unused warnings */
#else
        /* XXX Someday, we may need to generalize this the
         * same way we generalized the group name check below.
         * That's needed only if we encounter a system where
         * uid 0 is not "root". XXX */
        assertEqualString(archive_read_disk_uname(a, 0), "root");

        /* Get the group name for group 0 and see if it makes sense. */
        p = archive_read_disk_gname(a, 0);
        if (assert(p != NULL)) {
            i = 0;
            while (i < sizeof(zero_groups)/sizeof(zero_groups[0])) {
                if (strcmp(zero_groups[i], p) == 0)
                    break;
                ++i;
            }
            if (i == sizeof(zero_groups)/sizeof(zero_groups[0])) {
                /* If you get a failure here, either
                 * archive_read_disk_gname() isn't working or
                 * your system uses a different name for group
                 * number zero.  If the latter, please add a
                 * new entry to the zero_groups[] array above.
                 */
                failure("group 0 didn't have any of the expected names");
                assertEqualString(p, zero_groups[0]);
            }
        }
#endif
    }

    /* Deregister again and verify the default lookups again. */
    assertEqualInt(ARCHIVE_OK,
        archive_read_disk_set_gname_lookup(a, NULL, NULL, NULL));
    assertEqualInt(ARCHIVE_OK,
        archive_read_disk_set_uname_lookup(a, NULL, NULL, NULL));
    assert(archive_read_disk_gname(a, 0) == NULL);
    assert(archive_read_disk_uname(a, 0) == NULL);

    /* Re-register our custom handlers. */
    gmagic = 0x13579;
    umagic = 0x1234;
    assertEqualInt(ARCHIVE_OK, archive_read_disk_set_gname_lookup(a,
               &gmagic, &gname_lookup, &gname_cleanup));
    assertEqualInt(ARCHIVE_OK, archive_read_disk_set_uname_lookup(a,
               &umagic, &uname_lookup, &uname_cleanup));

    /* Destroy the archive. */
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));

    /* Verify our cleanup functions got called. */
    assertEqualInt(gmagic, 0x2468);
    assertEqualInt(umagic, 0x2345);
}

--- NEW FILE: test_ustar_filenames.c ---
/*-
 * 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/lib/libarchive/test/test_ustar_filenames.c,v 1.2 2008/08/11 01:19:36 kientzle Exp $");

/*
 * Exercise various lengths of filenames in ustar archives.
 */

static void
test_filename(const char *prefix, int dlen, int flen)
{
    char buff[8192];
    char filename[400];
    char dirname[400];
    struct archive_entry *ae;
    struct archive *a;
    size_t used;
    int separator = 0;
    int i = 0;

    if (prefix != NULL) {
        strcpy(filename, prefix);
        i = (int)strlen(prefix);
    }
    if (dlen > 0) {
        for (; i < dlen; i++)
            filename[i] = 'a';
        filename[i++] = '/';
        separator = 1;
    }
    for (; i < dlen + flen + separator; i++)
        filename[i] = 'b';
    filename[i++] = '\0';

    strcpy(dirname, filename);

    /* Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    assertA(0 == archive_write_set_compression_none(a));
    assertA(0 == archive_write_set_bytes_per_block(a,0));
    assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));

    /*
     * Write a file to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, filename);
    archive_entry_set_mode(ae, S_IFREG | 0755);
    failure("dlen=%d, flen=%d", dlen, flen);
    if (flen > 100) {
        assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae));
    } else {
        assertEqualIntA(a, 0, archive_write_header(a, ae));
    }
    archive_entry_free(ae);

    /*
     * Write a dir to it (without trailing '/').
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, dirname);
    archive_entry_set_mode(ae, S_IFDIR | 0755);
    failure("dlen=%d, flen=%d", dlen, flen);
    if (flen >= 100) {
        assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae));
    } else {
        assertEqualIntA(a, 0, archive_write_header(a, ae));
    }
    archive_entry_free(ae);

    /* Tar adds a '/' to directory names. */
    strcat(dirname, "/");

    /*
     * Write a dir to it (with trailing '/').
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, dirname);
    archive_entry_set_mode(ae, S_IFDIR | 0755);
    failure("dlen=%d, flen=%d", dlen, flen);
    if (flen >= 100) {
        assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae));
    } else {
        assertEqualIntA(a, 0, archive_write_header(a, ae));
    }
    archive_entry_free(ae);

    /* Close out the archive. */
    assertA(0 == archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assertEqualInt(0, archive_write_finish(a));
#endif

    /*
     * Now, read the data back.
     */
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff, used));

    if (flen <= 100) {
        /* Read the file and check the filename. */
        assertA(0 == archive_read_next_header(a, &ae));
        failure("dlen=%d, flen=%d", dlen, flen);
        assertEqualString(filename, archive_entry_pathname(ae));
        assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));
    }

    /*
     * Read the two dirs and check the names.
     *
     * Both dirs should read back with the same name, since
     * tar should add a trailing '/' to any dir that doesn't
     * already have one.
     */
    if (flen <= 99) {
        assertA(0 == archive_read_next_header(a, &ae));
        assert((S_IFDIR | 0755) == archive_entry_mode(ae));
        failure("dlen=%d, flen=%d", dlen, flen);
        assertEqualString(dirname, archive_entry_pathname(ae));
    }

    if (flen <= 99) {
        assertA(0 == archive_read_next_header(a, &ae));
        assert((S_IFDIR | 0755) == archive_entry_mode(ae));
        assertEqualString(dirname, archive_entry_pathname(ae));
    }

    /* Verify the end of the archive. */
    failure("This fails if entries were written that should not have been written.  dlen=%d, flen=%d", dlen, flen);
    assertEqualInt(1, archive_read_next_header(a, &ae));
    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertEqualInt(0, archive_read_finish(a));
#endif
}

DEFINE_TEST(test_ustar_filenames)
{
    int dlen, flen;

    /* Try a bunch of different file/dir lengths that add up
     * to just a little less or a little more than 100 bytes.
     * This exercises the code that splits paths between ustar
     * filename and prefix fields.
     */
    for (dlen = 5; dlen < 70; dlen += 5) {
        for (flen = 100 - dlen - 5; flen < 100 - dlen + 5; flen++) {
            test_filename(NULL, dlen, flen);
            test_filename("/", dlen, flen);
        }
    }

    /* Probe the 100-char limit for paths with no '/'. */
    for (flen = 90; flen < 110; flen++) {
        test_filename(NULL, 0, flen);
        test_filename("/", dlen, flen);
    }

    /* XXXX TODO Probe the 100-char limit with a dir prefix. */
    /* XXXX TODO Probe the 255-char total limit. */
}

--- NEW FILE: test_write_disk_times.c ---
/*-
 * 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"
__FBSDID("$FreeBSD$");

/*
 * Exercise time restores in archive_write_disk(), including
 * correct handling of omitted time values.
 * On FreeBSD, we also test birthtime and high-res time restores.
 */

DEFINE_TEST(test_write_disk_times)
{
    struct archive *a;
    struct archive_entry *ae;

    /* Create an archive_write_disk object. */
    assert((a = archive_write_disk_new()) != NULL);
    assertEqualInt(ARCHIVE_OK,
        archive_write_disk_set_options(a, ARCHIVE_EXTRACT_TIME));

    /*
     * Easy case: mtime and atime both specified.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file1");
    archive_entry_set_mode(ae, S_IFREG | 0777);
    archive_entry_set_atime(ae, 123456, 0);
    archive_entry_set_mtime(ae, 234567, 0);
    assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae));
    assertEqualInt(ARCHIVE_OK, archive_write_finish_entry(a));
    archive_entry_free(ae);
    /* Verify */
    assertFileAtime("file1", 123456, 0);
    assertFileMtime("file1", 234567, 0);

    /*
     * mtime specified, but not atime
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file2");
    archive_entry_set_mode(ae, S_IFREG | 0777);
    archive_entry_set_mtime(ae, 234567, 0);
    assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae));
    assertEqualInt(ARCHIVE_OK, archive_write_finish_entry(a));
    archive_entry_free(ae);
    assertFileMtime("file2", 234567, 0);
    assertFileAtimeRecent("file2");

    /*
     * atime specified, but not mtime
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file3");
    archive_entry_set_mode(ae, S_IFREG | 0777);
    archive_entry_set_atime(ae, 345678, 0);
    assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae));
    assertEqualInt(ARCHIVE_OK, archive_write_finish_entry(a));
    archive_entry_free(ae);
    /* Verify: Current mtime and atime as specified. */
    assertFileAtime("file3", 345678, 0);
    assertFileMtimeRecent("file3");

    /*
     * Neither atime nor mtime specified.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file4");
    archive_entry_set_mode(ae, S_IFREG | 0777);
    assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae));
    assertEqualInt(ARCHIVE_OK, archive_write_finish_entry(a));
    archive_entry_free(ae);
    /* Verify: Current mtime and atime. */
    assertFileAtimeRecent("file4");
    assertFileMtimeRecent("file4");

#if defined(__FreeBSD__)
    /*
     * High-res mtime and atime on FreeBSD.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file10");
    archive_entry_set_mode(ae, S_IFREG | 0777);
    archive_entry_set_atime(ae, 1234567, 23456);
    archive_entry_set_mtime(ae, 2345678, 4567);
    assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae));
    assertEqualInt(ARCHIVE_OK, archive_write_finish_entry(a));
    archive_entry_free(ae);
    /* Verify */
    assertFileMtime("file10", 2345678, 4567);
    assertFileAtime("file10", 1234567, 23456);

    /*
     * Birthtime, mtime and atime on FreeBSD
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file11");
    archive_entry_set_mode(ae, S_IFREG | 0777);
    archive_entry_set_atime(ae, 1234567, 23456);
    archive_entry_set_birthtime(ae, 3456789, 12345);
    /* mtime must be later than birthtime! */
    archive_entry_set_mtime(ae, 12345678, 4567);
    assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae));
    assertEqualInt(ARCHIVE_OK, archive_write_finish_entry(a));
    archive_entry_free(ae);
    /* Verify */
    assertFileAtime("file11", 1234567, 23456);
    assertFileBirthtime("file11", 3456789, 12345);
    assertFileMtime("file11", 12345678, 4567);

    /*
     * Birthtime only on FreeBSD.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file12");
    archive_entry_set_mode(ae, S_IFREG | 0777);
    archive_entry_set_birthtime(ae, 3456789, 12345);
    assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae));
    assertEqualInt(ARCHIVE_OK, archive_write_finish_entry(a));
    archive_entry_free(ae);
    /* Verify */
    assertFileAtimeRecent("file12");
    assertFileBirthtime("file12", 3456789, 12345);
    assertFileMtimeRecent("file12");

    /*
     * mtime only on FreeBSD.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "file13");
    archive_entry_set_mode(ae, S_IFREG | 0777);
    archive_entry_set_mtime(ae, 4567890, 23456);
    assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae));
    assertEqualInt(ARCHIVE_OK, archive_write_finish_entry(a));
    archive_entry_free(ae);
    /* Verify */
    assertFileAtimeRecent("file13");
    assertFileBirthtime("file13", 4567890, 23456);
    assertFileMtime("file13", 4567890, 23456);
#else
    skipping("Platform-specific time restore tests");
#endif

    archive_write_finish(a);
}

--- NEW FILE: test_read_format_tar_empty_filename.tar.uu ---
$FreeBSD: src/lib/libarchive/test/test_read_format_tar_empty_filename.tar.uu,v 1.2 2008/07/03 03:26:30 peter Exp $
begin 644 test_compat_tar_1.tar
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#`P,#<W-2``,#`Q-S4P(``P,#`P,#`@`#`P,#`P,#`P,#`P
M(#$Q,#`R-#,Q-C<U(#`Q,3`P,0`@-0``````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<@`P,'1I;0``
M````````````````````````````````````=VAE96P`````````````````
M```````````````````P,#`P,#`@`#`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````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
&````````
`
end

--- NEW FILE: test_read_format_gtar_sparse_1_17_posix10.tar.uu ---
begin 644 test_read_format_gtar_sparse_1_17_posix10.tar
M+B]087A(96%D97)S+C,X-C8S+W-P87)S90``````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#`P,#`V-#0`,#`P,3<U,``P,#`Q-S4P`#`P,#`P,#`P,C$U
M`#$P-S,S,3`Q,30S`#`Q,S0V-@`@>```````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<@`P,```````
M````````````````````````````````````````````````````````````
M```````````````````P,#`P,#`P`#`P,#`P,#``````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````R,B!'3E4N<W!A<G-E+FUA:F]R/3$*,C(@1TY5
M+G-P87)S92YM:6YO<CTP"C(V($=.52YS<&%R<V4N;F%M93US<&%R<V4*,S$@
M1TY5+G-P87)S92YR96%L<VEZ93TS,30U-S(X"C(P(&%T:6UE/3$Q.3 at R.3,V
M,#(*,C`@8W1I;64],3$Y.#(Y,S8P,`H`````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
[...1330 lines suppressed...]
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
/````````````````````
`
end

--- NEW FILE: test_acl_pax.c ---
/*-
 * 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/lib/libarchive/test/test_acl_pax.c,v 1.6 2008/09/01 05:38:33 kientzle Exp $");

/*
 * Exercise the system-independent portion of the ACL support.
 * Check that pax archive can save and restore ACL data.
 *
 * This should work on all systems, regardless of whether local
 * filesystems support ACLs or not.
 */

static unsigned char buff[16384];

static unsigned char reference[] = {
'P','a','x','H','e','a','d','e','r','/','f','i','l','e',0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,'0','0','0','1','4','2',' ',0,'0','0','0','0','0','0',' ',0,'0','0',
'0','0','0','0',' ',0,'0','0','0','0','0','0','0','0','0','6','2',' ','0',
'0','0','0','0','0','0','0','0','0','0',' ','0','1','1','7','6','7',0,' ',
'x',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t','a','r',
0,'0','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0','0','0',
'0','0','0',' ',0,'0','0','0','0','0','0',' ',0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,'1','6',' ','S','C','H','I','L','Y','.','d','e','v','=','0',10,
'1','6',' ','S','C','H','I','L','Y','.','i','n','o','=','0',10,'1','8',' ',
'S','C','H','I','L','Y','.','n','l','i','n','k','=','0',10,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,'f','i','l','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,'0','0','0','1','4','2',' ',0,'0','0','0','0','0','0',' ',0,'0','0',
'0','0','0','0',' ',0,'0','0','0','0','0','0','0','0','0','0','0',' ','0',
'0','0','0','0','0','0','0','0','0','0',' ','0','1','0','0','0','6',0,' ',
'0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t','a','r',
0,'0','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0','0','0',
'0','0','0',' ',0,'0','0','0','0','0','0',' ',0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,'P','a','x','H','e','a','d','e','r','/','f','i','l','e',0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,'0','0','0','1','4','2',' ',0,'0','0','0','0','0','0',' ',
0,'0','0','0','0','0','0',' ',0,'0','0','0','0','0','0','0','0','1','7','2',
' ','0','0','0','0','0','0','0','0','0','0','0',' ','0','1','1','7','7','1',
0,' ','x',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t',
'a','r',0,'0','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0',
'0','0','0','0','0',' ',0,'0','0','0','0','0','0',' ',0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,'7','2',' ','S','C','H','I','L','Y','.','a','c','l','.',
'a','c','c','e','s','s','=','u','s','e','r',':',':','-','-','x',',','g','r',
'o','u','p',':',':','r','-','-',',','o','t','h','e','r',':',':','-','w','-',
',','u','s','e','r',':','u','s','e','r','7','7',':','r','-','-',':','7','7',
10,'1','6',' ','S','C','H','I','L','Y','.','d','e','v','=','0',10,'1','6',
' ','S','C','H','I','L','Y','.','i','n','o','=','0',10,'1','8',' ','S','C',
'H','I','L','Y','.','n','l','i','n','k','=','0',10,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,'f','i','l','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,'0','0','0','1','4','2',' ',0,'0','0','0','0','0','0',' ',0,'0','0','0',
'0','0','0',' ',0,'0','0','0','0','0','0','0','0','0','0','0',' ','0','0',
'0','0','0','0','0','0','0','0','0',' ','0','1','0','0','0','6',0,' ','0',
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t','a','r',0,
'0','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0','0','0',
'0','0','0',' ',0,'0','0','0','0','0','0',' ',0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,'P','a','x','H','e','a','d','e','r','/','f','i','l','e',0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,'0','0','0','5','4','3',' ',0,'0','0','0','0','0','0',' ',
0,'0','0','0','0','0','0',' ',0,'0','0','0','0','0','0','0','0','2','4','3',
' ','0','0','0','0','0','0','0','0','0','0','0',' ','0','1','1','7','7','5',
0,' ','x',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t',
'a','r',0,'0','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0',
'0','0','0','0','0',' ',0,'0','0','0','0','0','0',' ',0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,'1','1','3',' ','S','C','H','I','L','Y','.','a','c','l',
'.','a','c','c','e','s','s','=','u','s','e','r',':',':','r','-','x',',','g',
'r','o','u','p',':',':','r','-','-',',','o','t','h','e','r',':',':','-','w',
'x',',','u','s','e','r',':','u','s','e','r','7','7',':','r','-','-',':','7',
'7',',','u','s','e','r',':','u','s','e','r','7','8',':','-','-','-',':','7',
'8',',','g','r','o','u','p',':','g','r','o','u','p','7','8',':','r','w','x',
':','7','8',10,'1','6',' ','S','C','H','I','L','Y','.','d','e','v','=','0',
10,'1','6',' ','S','C','H','I','L','Y','.','i','n','o','=','0',10,'1','8',
' ','S','C','H','I','L','Y','.','n','l','i','n','k','=','0',10,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,'f','i','l','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,'0','0','0','5','4','3',' ',0,'0','0','0','0','0','0',' ',0,'0','0',
'0','0','0','0',' ',0,'0','0','0','0','0','0','0','0','0','0','0',' ','0',
'0','0','0','0','0','0','0','0','0','0',' ','0','1','0','0','1','3',0,' ',
'0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t','a','r',
0,'0','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0','0','0',
'0','0','0',' ',0,'0','0','0','0','0','0',' ',0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,'P','a','x','H','e','a','d','e','r','/','f','i','l','e',0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,'0','0','0','1','4','2',' ',0,'0','0','0','0','0','0',' ',
0,'0','0','0','0','0','0',' ',0,'0','0','0','0','0','0','0','0','0','6','2',
' ','0','0','0','0','0','0','0','0','0','0','0',' ','0','1','1','7','6','7',
0,' ','x',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t',
'a','r',0,'0','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0',
'0','0','0','0','0',' ',0,'0','0','0','0','0','0',' ',0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,'1','6',' ','S','C','H','I','L','Y','.','d','e','v','=',
'0',10,'1','6',' ','S','C','H','I','L','Y','.','i','n','o','=','0',10,'1',
'8',' ','S','C','H','I','L','Y','.','n','l','i','n','k','=','0',10,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'f','i','l','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,'0','0','0','1','4','2',' ',0,'0','0','0','0','0','0',' ',
0,'0','0','0','0','0','0',' ',0,'0','0','0','0','0','0','0','0','0','0','0',
' ','0','0','0','0','0','0','0','0','0','0','0',' ','0','1','0','0','0','6',
0,' ','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t',
'a','r',0,'0','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0',
'0','0','0','0','0',' ',0,'0','0','0','0','0','0',' ',0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};


struct acl_t {
    int type;  /* Type of ACL: "access" or "default" */
    int permset; /* Permissions for this class of users. */
    int tag; /* Owner, User, Owning group, group, other, etc. */
    int qual; /* GID or UID of user/group, depending on tag. */
    const char *name; /* Name of user/group, depending on tag. */
};

static struct acl_t acls0[] = {
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE,
      ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
      ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE,
      ARCHIVE_ENTRY_ACL_OTHER, 0, "" },
};

static struct acl_t acls1[] = {
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE,
      ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
      ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
      ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE,
      ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
};

static struct acl_t acls2[] = {
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ,
      ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
      ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0,
      ARCHIVE_ENTRY_ACL_USER, 78, "user78" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
      ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0007,
      ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" },
    { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_EXECUTE,
      ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
};

static void
set_acls(struct archive_entry *ae, struct acl_t *acls, int n)
{
    int i;

    archive_entry_acl_clear(ae);
    for (i = 0; i < n; i++) {
        archive_entry_acl_add_entry(ae,
            acls[i].type, acls[i].permset, acls[i].tag, acls[i].qual,
            acls[i].name);
    }
}

static int
acl_match(struct acl_t *acl, int type, int permset, int tag, int qual, const char *name)
{
    if (type != acl->type)
        return (0);
    if (permset != acl->permset)
        return (0);
    if (tag != acl->tag)
        return (0);
    if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
        return (1);
    if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ)
        return (1);
    if (tag == ARCHIVE_ENTRY_ACL_OTHER)
        return (1);
    if (qual != acl->qual)
        return (0);
    if (name == NULL)
        return (acl->name == NULL || acl->name[0] == '\0');
    if (acl->name == NULL)
        return (name == NULL || name[0] == '\0');
    return (0 == strcmp(name, acl->name));
}

static void
compare_acls(struct archive_entry *ae, struct acl_t *acls, int n, int mode)
{
    int *marker = malloc(sizeof(marker[0]) * n);
    int i;
    int r;
    int type, permset, tag, qual;
    int matched;
    const char *name;

    for (i = 0; i < n; i++)
        marker[i] = i;

    while (0 == (r = archive_entry_acl_next(ae,
             ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
             &type, &permset, &tag, &qual, &name))) {
        for (i = 0, matched = 0; i < n && !matched; i++) {
            if (acl_match(&acls[marker[i]], type, permset,
                tag, qual, name)) {
                /* We found a match; remove it. */
                marker[i] = marker[n - 1];
                n--;
                matched = 1;
            }
        }
        if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ) {
            if (!matched) printf("No match for user_obj perm\n");
            failure("USER_OBJ permset (%02o) != user mode (%02o)",
                permset, 07 & (mode >> 6));
            assert((permset << 6) == (mode & 0700));
        } else if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ) {
            if (!matched) printf("No match for group_obj perm\n");
            failure("GROUP_OBJ permset %02o != group mode %02o",
                permset, 07 & (mode >> 3));
            assert((permset << 3) == (mode & 0070));
        } else if (tag == ARCHIVE_ENTRY_ACL_OTHER) {
            if (!matched) printf("No match for other perm\n");
            failure("OTHER permset (%02o) != other mode (%02o)",
                permset, mode & 07);
            assert((permset << 0) == (mode & 0007));
        } else {
            failure("Could not find match for ACL "
                "(type=%d,permset=%d,tag=%d,qual=%d,name=``%s'')",
                type, permset, tag, qual, name);
            assert(matched == 1);
        }
    }
#if ARCHIVE_VERSION_NUMBER < 1009000
    /* Known broken before 1.9.0. */
    skipping("archive_entry_acl_next() exits with ARCHIVE_EOF");
#else
    assertEqualInt(ARCHIVE_EOF, r);
#endif
    assert((mode & 0777) == (archive_entry_mode(ae) & 0777));
    failure("Could not find match for ACL "
        "(type=%d,permset=%d,tag=%d,qual=%d,name=``%s'')",
        acls[marker[0]].type, acls[marker[0]].permset,
        acls[marker[0]].tag, acls[marker[0]].qual, acls[marker[0]].name);
    assert(n == 0); /* Number of ACLs not matched should == 0 */
    free(marker);
}

DEFINE_TEST(test_acl_pax)
{
    struct archive *a;
    struct archive_entry *ae;
    size_t used;
    FILE *f;

    /* Write an archive to memory. */
    assert(NULL != (a = archive_write_new()));
    assertA(0 == archive_write_set_format_pax(a));
    assertA(0 == archive_write_set_compression_none(a));
    assertA(0 == archive_write_set_bytes_per_block(a, 1));
    assertA(0 == archive_write_set_bytes_in_last_block(a, 1));
    assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));

    /* Write a series of files to the archive with different ACL info. */

    /* Create a simple archive_entry. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_pathname(ae, "file");
        archive_entry_set_mode(ae, S_IFREG | 0777);

    /* Basic owner/owning group should just update mode bits. */
    set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
    assertA(0 == archive_write_header(a, ae));

    /* With any extended ACL entry, we should read back a full set. */
    set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
    assertA(0 == archive_write_header(a, ae));


    /* A more extensive set of ACLs. */
    set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
    assertA(0 == archive_write_header(a, ae));

    /*
     * Check that clearing ACLs gets rid of them all by repeating
     * the first test.
     */
    set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);

    /* Close out the archive. */
    assertA(0 == archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assertA(0 == archive_write_finish(a));
#endif

    /* Write out the data we generated to a file for manual inspection. */
    assert(NULL != (f = fopen("testout", "wb")));
    assertEqualInt(used, (size_t)fwrite(buff, 1, (unsigned int)used, f));
    fclose(f);

    /* Write out the reference data to a file for manual inspection. */
    assert(NULL != (f = fopen("reference", "wb")));
    assert(sizeof(reference) == fwrite(reference, 1, sizeof(reference), f));
    fclose(f);

    /* Assert that the generated data matches the built-in reference data.*/
    failure("Generated pax archive does not match reference; check 'testout' and 'reference' files.");
    assertEqualMem(buff, reference, sizeof(reference));
    failure("Generated pax archive does not match reference; check 'testout' and 'reference' files.");
    assertEqualInt((int)used, sizeof(reference));

    /* Read back each entry and check that the ACL data is right. */
    assert(NULL != (a = archive_read_new()));
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff, used));

    /* First item has no ACLs */
    assertA(0 == archive_read_next_header(a, &ae));
    failure("Basic ACLs shouldn't be stored as extended ACLs");
    assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
    failure("Basic ACLs should set mode to 0142, not %04o",
        archive_entry_mode(ae)&0777);
    assert((archive_entry_mode(ae) & 0777) == 0142);

    /* Second item has a few ACLs */
    assertA(0 == archive_read_next_header(a, &ae));
    failure("One extended ACL should flag all ACLs to be returned.");
    assert(4 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
    compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]), 0142);
    failure("Basic ACLs should set mode to 0142, not %04o",
        archive_entry_mode(ae)&0777);
    assert((archive_entry_mode(ae) & 0777) == 0142);

    /* Third item has pretty extensive ACLs */
    assertA(0 == archive_read_next_header(a, &ae));
    assertEqualInt(6, archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
    compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]), 0543);
    failure("Basic ACLs should set mode to 0543, not %04o",
        archive_entry_mode(ae)&0777);
    assert((archive_entry_mode(ae) & 0777) == 0543);

    /* Fourth item has no ACLs */
    assertA(0 == archive_read_next_header(a, &ae));
    failure("Basic ACLs shouldn't be stored as extended ACLs");
    assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
    failure("Basic ACLs should set mode to 0142, not %04o",
        archive_entry_mode(ae)&0777);
    assert((archive_entry_mode(ae) & 0777) == 0142);

    /* Close the archive. */
    assertA(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertA(0 == archive_read_finish(a));
#endif
}

--- NEW FILE: test_compat_tar_hardlink_1.tar.uu ---
$FreeBSD: src/lib/libarchive/test/test_compat_tar_hardlink_1.tar.uu,v 1.1 2008/01/31 07:47:38 kientzle Exp $
begin 644 test_compat_tar_hardlink_1.tar
M>&UC9"TS+C,N,B]D;V-S7V0O4D5!1$UF````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````"`@(#0T-"``("`S-#<S(``@("`@(#,@`"`@("`@("`@-3`Q
M(#$P,#0Q-30U-#,U("`@-S8U-``@````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````!X>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX
M>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX
M>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX
M>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX
M>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX
M>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX
M>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX
M>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'@`````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````'AM8V0M,RXS+C(O
M4D5!1$U%````````````````````````````````````````````````````
M```````````````````````````````````````````````````````````@
M("`T-#0@`"`@,S0W,R``("`@("`S(``@("`@("`@(#4P,2`Q,#`T,34T-30S
M-2`@,3(R,#<`(#%X;6-D+3,N,RXR+V1O8W-?9"]214%$368`````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
&````````
`
end

--- NEW FILE: test_bad_fd.c ---
/*-
 * 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/lib/libarchive/test/test_bad_fd.c,v 1.2 2008/09/01 05:38:33 kientzle Exp $");

/* Verify that attempting to open an invalid fd returns correct error. */
DEFINE_TEST(test_bad_fd)
{
    struct archive *a;
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_compression_all(a));
    assertA(ARCHIVE_FATAL == archive_read_open_fd(a, -1, 1024));
    assertA(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertA(0 == archive_read_finish(a));
#endif
}

--- NEW FILE: test_tar_filenames.c ---
/*-
 * 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/lib/libarchive/test/test_tar_filenames.c,v 1.10 2008/09/01 05:38:33 kientzle Exp $");

/*
 * Exercise various lengths of filenames in tar archives,
 * especially around the magic sizes where ustar breaks
 * filenames into prefix/suffix.
 */

static void
test_filename(const char *prefix, int dlen, int flen)
{
    char buff[8192];
    char filename[400];
    char dirname[400];
    struct archive_entry *ae;
    struct archive *a;
    size_t used;
    char *p;
    int i;

    p = filename;
    if (prefix) {
        strcpy(filename, prefix);
        p += strlen(p);
    }
    if (dlen > 0) {
        for (i = 0; i < dlen; i++)
            *p++ = 'a';
        *p++ = '/';
    }
    for (i = 0; i < flen; i++)
        *p++ = 'b';
    *p = '\0';

    strcpy(dirname, filename);

    /* Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_pax_restricted(a));
    assertA(0 == archive_write_set_compression_none(a));
    assertA(0 == archive_write_set_bytes_per_block(a,0));
    assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));

    /*
     * Write a file to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, filename);
    archive_entry_set_mode(ae, S_IFREG | 0755);
    failure("Pathname %d/%d", dlen, flen);
    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);

    /*
     * Write a dir to it (without trailing '/').
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, dirname);
    archive_entry_set_mode(ae, S_IFDIR | 0755);
    failure("Dirname %d/%d", dlen, flen);
    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);

    /* Tar adds a '/' to directory names. */
    strcat(dirname, "/");

    /*
     * Write a dir to it (with trailing '/').
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, dirname);
    archive_entry_set_mode(ae, S_IFDIR | 0755);
    failure("Dirname %d/%d", dlen, flen);
    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);

    /* Close out the archive. */
    assertA(0 == archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assertA(0 == archive_write_finish(a));
#endif

    /*
     * Now, read the data back.
     */
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff, used));

    /* Read the file and check the filename. */
    assertA(0 == archive_read_next_header(a, &ae));
#if ARCHIVE_VERSION_NUMBER < 1009000
    skipping("Leading '/' preserved on long filenames");
#else
    assertEqualString(filename, archive_entry_pathname(ae));
#endif
    assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));

    /*
     * Read the two dirs and check the names.
     *
     * Both dirs should read back with the same name, since
     * tar should add a trailing '/' to any dir that doesn't
     * already have one.  We only report the first such failure
     * here.
     */
    assertA(0 == archive_read_next_header(a, &ae));
#if ARCHIVE_VERSION_NUMBER < 1009000
    skipping("Trailing '/' preserved on dirnames");
#else
    assertEqualString(dirname, archive_entry_pathname(ae));
#endif
    assert((S_IFDIR | 0755) == archive_entry_mode(ae));

    assertA(0 == archive_read_next_header(a, &ae));
#if ARCHIVE_VERSION_NUMBER < 1009000
    skipping("Trailing '/' added to dir names");
#else
    assertEqualString(dirname, archive_entry_pathname(ae));
#endif
    assert((S_IFDIR | 0755) == archive_entry_mode(ae));

    /* Verify the end of the archive. */
    assert(1 == archive_read_next_header(a, &ae));
    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif
}

DEFINE_TEST(test_tar_filenames)
{
    int dlen, flen;

    /* Repeat the following for a variety of dir/file lengths. */
    for (dlen = 45; dlen < 55; dlen++) {
        for (flen = 45; flen < 55; flen++) {
            test_filename(NULL, dlen, flen);
            test_filename("/", dlen, flen);
        }
    }

    for (dlen = 0; dlen < 140; dlen += 10) {
        for (flen = 98; flen < 102; flen++) {
            test_filename(NULL, dlen, flen);
            test_filename("/", dlen, flen);
        }
    }

    for (dlen = 140; dlen < 160; dlen++) {
        for (flen = 95; flen < 105; flen++) {
            test_filename(NULL, dlen, flen);
            test_filename("/", dlen, flen);
        }
    }
}

--- NEW FILE: test_read_format_cpio_bin_bz2.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_cpio_bin_bz2.c,v 1.3 2008/12/06 06:00:52 kientzle Exp $");

static unsigned char archive[] = {
'B','Z','h','9','1','A','Y','&','S','Y',134,'J',208,'4',0,0,30,246,141,253,
8,2,0,' ',1,'*','&',20,0,'`',' ',' ',2,0,128,0,'B',4,8,' ',0,'T','P',0,'4',
0,13,6,137,168,245,27,'Q',160,'a',25,169,5,'I',187,'(',10,'d','E',177,177,
142,218,232,'r',130,'4','D',247,'<','Z',190,'U',237,236,'d',227,31,' ','z',
192,'E','_',23,'r','E','8','P',144,134,'J',208,'4'};

DEFINE_TEST(test_read_format_cpio_bin_bz2)
{
    struct archive_entry *ae;
    struct archive *a;
    int r;

    assert((a = archive_read_new()) != NULL);
    r = archive_read_support_compression_bzip2(a);
    if (r != ARCHIVE_OK) {
        skipping("bzip2 support unavailable");
        archive_read_close(a);
        return;
    }
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_open_memory(a, archive, sizeof(archive)));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assert(archive_compression(a) == ARCHIVE_COMPRESSION_BZIP2);
    assert(archive_format(a) == ARCHIVE_FORMAT_CPIO_BIN_LE);
    assert(0 == archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}



--- NEW FILE: test_write_format_ar.c ---
/*-
 * Copyright (c) 2007 Kai Wang
 * Copyright (c) 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 "test.h"
__FBSDID("$FreeBSD: src/lib/libarchive/test/test_write_format_ar.c,v 1.9 2008/12/17 19:03:44 kientzle Exp $");

char buff[4096];
char buff2[64];
static char strtab[] = "abcdefghijklmn.o/\nggghhhjjjrrrttt.o/\niiijjjdddsssppp.o/\n";

DEFINE_TEST(test_write_format_ar)
{
#if ARCHIVE_VERSION_NUMBER < 1009000
    skipping("ar write support");
#else
    struct archive_entry *ae;
    struct archive* a;
    size_t used;

    /*
     * First we try to create a SVR4/GNU format archive.
     */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ar_svr4(a));
    assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));

    /* write the filename table */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "//");
    archive_entry_set_size(ae, strlen(strtab));
    assertA(0 == archive_write_header(a, ae));
    assertA(strlen(strtab) == (size_t)archive_write_data(a, strtab, strlen(strtab)));
    archive_entry_free(ae);

    /* write entries */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_mtime(ae, 1, 0);
    assert(1 == archive_entry_mtime(ae));
    archive_entry_set_mode(ae, S_IFREG | 0755);
    assert((S_IFREG | 0755) == archive_entry_mode(ae));
    archive_entry_copy_pathname(ae, "abcdefghijklmn.o");
    archive_entry_set_size(ae, 8);
    assertA(0 == archive_write_header(a, ae));
    assertA(8 == archive_write_data(a, "87654321", 15));
    archive_entry_free(ae);

    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "ggghhhjjjrrrttt.o");
    archive_entry_set_filetype(ae, AE_IFREG);
    archive_entry_set_size(ae, 7);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
    assertEqualIntA(a, 7, archive_write_data(a, "7777777", 7));
    archive_entry_free(ae);

    /* test full pathname */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "/usr/home/xx/iiijjjdddsssppp.o");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    archive_entry_set_size(ae, 8);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
    assertEqualIntA(a, 8, archive_write_data(a, "88877766", 8));
    archive_entry_free(ae);

    /* trailing "/" should be rejected */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "/usr/home/xx/iiijjj/");
    archive_entry_set_size(ae, 8);
    assertA(0 != archive_write_header(a, ae));
    archive_entry_free(ae);

    /* Non regular file should be rejected */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "gfgh.o");
    archive_entry_set_mode(ae, S_IFDIR | 0755);
    archive_entry_set_size(ae, 6);
    assertA(0 != archive_write_header(a, ae));
    archive_entry_free(ae);

    archive_write_close(a);
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assertEqualInt(0, archive_write_finish(a));
#endif

    /*
     * Now, read the data back.
     */
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used));

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualInt(0, archive_entry_mtime(ae));
    assertEqualString("//", archive_entry_pathname(ae));
    assertEqualInt(0, archive_entry_size(ae));

    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualInt(1, archive_entry_mtime(ae));
    assertEqualString("abcdefghijklmn.o", archive_entry_pathname(ae));
    assertEqualInt(8, archive_entry_size(ae));
    assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
    assertEqualMem(buff2, "87654321", 8);

    assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString("ggghhhjjjrrrttt.o", archive_entry_pathname(ae));
    assertEqualInt(7, archive_entry_size(ae));
    assertEqualIntA(a, 7, archive_read_data(a, buff2, 11));
    assertEqualMem(buff2, "7777777", 7);

    assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
    assertEqualString("iiijjjdddsssppp.o", archive_entry_pathname(ae));
    assertEqualInt(8, archive_entry_size(ae));
    assertEqualIntA(a, 8, archive_read_data(a, buff2, 17));
    assertEqualMem(buff2, "88877766", 8);

    assertEqualIntA(a, 0, archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertEqualInt(0, archive_read_finish(a));
#endif

    /*
     * Then, we try to create a BSD format archive.
     */
    memset(buff, 0, sizeof(buff));
    assert((a = archive_write_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ar_bsd(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used));

    /* write a entry need long name extension */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "ttttyyyyuuuuiiii.o");
    archive_entry_set_filetype(ae, AE_IFREG);
    archive_entry_set_size(ae, 5);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
    assertEqualInt(5, archive_entry_size(ae));
    assertEqualIntA(a, 5, archive_write_data(a, "12345", 7));
    archive_entry_free(ae);

    /* write a entry with a short name */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "ttyy.o");
    archive_entry_set_filetype(ae, AE_IFREG);
    archive_entry_set_size(ae, 6);
    assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
    assertEqualIntA(a, 6, archive_write_data(a, "555555", 7));
    archive_entry_free(ae);
    archive_write_close(a);
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assertEqualInt(0, archive_write_finish(a));
#endif

    /* Now, Read the data back */
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used));

    assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
    assertEqualString("ttttyyyyuuuuiiii.o", archive_entry_pathname(ae));
    assertEqualInt(5, archive_entry_size(ae));
    assertEqualIntA(a, 5, archive_read_data(a, buff2, 10));
    assertEqualMem(buff2, "12345", 5);

    assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
    assertEqualString("ttyy.o", archive_entry_pathname(ae));
    assertEqualInt(6, archive_entry_size(ae));
    assertEqualIntA(a, 6, archive_read_data(a, buff2, 10));
    assertEqualMem(buff2, "555555", 6);

    /* Test EOF */
    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
    assertEqualIntA(a, 0, archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertEqualInt(0, archive_read_finish(a));
#endif
#endif
}

--- NEW FILE: test_read_format_cpio_bin_xz.c ---
/*-
 * Copyright (c) 2009 Michihiro NAKAJIMA
 * 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 unsigned char archive[] = {
 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x04,
 0xe6, 0xd6, 0xb4, 0x46, 0x02, 0x00, 0x21, 0x01,
 0x16, 0x00, 0x00, 0x00, 0x74, 0x2f, 0xe5, 0xa3,
 0xe0, 0x01, 0xff, 0x00, 0x33, 0x5d, 0x00, 0x63,
 0x9c, 0x3e, 0xa0, 0x43, 0x7c, 0xe6, 0x5d, 0xdc,
 0xeb, 0x76, 0x1d, 0x4b, 0x1b, 0xe2, 0x9e, 0x43,
 0x95, 0x97, 0x60, 0x16, 0x36, 0xc6, 0xd1, 0x3f,
 0x68, 0xd1, 0x94, 0xf9, 0xee, 0x47, 0xbb, 0xc9,
 0xf3, 0xa2, 0x01, 0x2a, 0x2f, 0x2b, 0xb2, 0x23,
 0x5a, 0x06, 0x9c, 0xd0, 0x4a, 0x6b, 0x5b, 0x14,
 0xb4, 0x00, 0x00, 0x00, 0x91, 0x62, 0x1e, 0x15,
 0x04, 0x46, 0x6b, 0x4d, 0x00, 0x01, 0x4f, 0x80,
 0x04, 0x00, 0x00, 0x00, 0xa1, 0x4b, 0xdf, 0x03,
 0xb1, 0xc4, 0x67, 0xfb, 0x02, 0x00, 0x00, 0x00,
 0x00, 0x04, 0x59, 0x5a      
};

DEFINE_TEST(test_read_format_cpio_bin_xz)
{
    struct archive_entry *ae;
    struct archive *a;
    int r;

    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    r = archive_read_support_compression_xz(a);
    if (r == ARCHIVE_WARN) {
        skipping("xz reading not fully supported on this platform");
        assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
        return;
    }
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_open_memory(a, archive, sizeof(archive)));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_XZ);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_BIN_LE);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}


--- NEW FILE: test_read_format_isojoliet_bz2.iso.bz2.uu ---
begin 644 test_read_format_isojoliet_bz2.iso.bz2
M0EIH.3%!62936??^FX(``/9_^__?1_?^8__L/__?8:?_W&8 at Z@$`9``008"`
M``+)"-`$/@=NN!W8[`8#23*GY-3U$](,0:`:`&"`9``9``T-'J::>B/4``#0
MIM$9&IA-!-0'I`>HT`&1Z@``T`!H`:#0'H(,E-(-3-$-&AB-`8C0`R9#1A`#
M1A/1`&@,@!H'``#0`-`&@``-&(`!H`````&@`D1)H0B-1O)&4V2:9#"9/4/2
M`/4>H'J-#(83U/$R at WZJ#>J&CREP**.W2R[".$_:J#$"N5P7:?.#4-4/..?K
M!KG\G]P="PX^ADTP4^Y%[1+0V,;$*HTA<YH1X6CK3!F8"7`;A,@`EG8))`'G
MYLMPLN;1!"O8FP$A)&H":4#8(8(3:3:$-\J'`$#0D"2+KH"UH5!(:5K`4"&`
MBEED63`R)H"L->&\V'@+*$<.M-0L at CLZ\Z(B=]`3`4%B"00B`FF@!-]HK<2.
M)?&IAD^/KKM>TRY#@+H5W781AM)P\\-4$&88^S$WX"2$=(X7(?,=$?H.A')A
M`%2T4:GEQRL:WS4Q=4SU(F>*JM1UEK\V`5P$L[9[D*;FBNEC^GPMAH8T>K&>
MQ)_.TSB;5G`P>)20L5V6':NL^M38\&.')5)<VW?:?;C$"2$CCX^2_;^AMLCJ
M6D&YOR".&EDU$BT1!NXZY!E+8([6_XMK'6H)J`-@`)0+P,WDFWI5CYW!GY8'
M$>)BO/*5`\P%H!`D7B2](0T)?Y0"`M3A6)'=($UL$@I$0$RBA0F4.!DAM`/@
M!V,L#/`+FC!;C.K58BA"1P\H1LVXG\@^"8IJ at 0*0>TP at 8F#0R^(M($"`"#I"
M`.FD45RN3EH2^8X6C/LKMKA;@K,T&ZZ%&PIJW%:>FG[.F=KGJ_O.(K`+0#!@
MQK&-G6!">H`4_/.<\CK)K+S/I/"?`9JG,TS^C1FI[O3NN(`Q^:*`Z1WEO()6
MZ*!0 at MSD*1?AE*V5[='!>>O%XL8LXIOQB\@CIBM%\0JD'+MAR$"@T'8M;JFM
MLHN7HG1S:F]+B'BZ)SJ(=0,6*Z791QW+3RNI(7!E!)'@.B$(934!)D0=U#%#
MV21)DA=@4;RM?@RLG1[`<V&84KLL$TD01>,A:"YQF2!`P`2B)#APE)`^\F8V
M5_U]0O,4AE6?->8U4$<2N%TC-HD%($@9'E1DCQZ&B:X4\IUV83HQ7)<P7!,P
MIR1^V$C4.C/RRDR4C#)9',&OL&&"151Q"I]]+-'$K at MUH=B,RO!U3D/(89G6
M&4#&KI;&J92*590`%I72,/2VN>A'8I511-P`;=!!).^8X*0NHMB+.&!W"009
M,<;0G^>BA6F[;A;X2B!%?BP&(G7&@(,*O-QP;;1*`*6"F:X8D"Y$/T,(1JM'
M$>\,IQ&V6;/)!\)0C$,[;`O,`9A-HRHQ8@^PLT.?=7RL[2789J_J86!HF0T"
M3%@,A$VPC(:A at 3(\&9-TZP2>KA*D>D;<^L4(H=<F2>EUT419R5`$A(R(Y-^O
+_B[DBG"A(>_]-P0`
`
end

--- NEW FILE: test_read_format_tar.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_tar.c,v 1.4 2008/09/01 05:38:33 kientzle Exp $");

/*
 * Each of these archives is a short archive with a single entry.  The
 * corresponding verify function verifies the entry structure returned
 * from libarchive is what it should be.  The support functions pad with
 * lots of zeros, so we can trim trailing zero bytes from each hardcoded
 * archive to save space.
 *
 * The naming here follows the tar file type flags.  E.g. '1' is a hardlink,
 * '2' is a symlink, '5' is a dir, etc.
 */

/* Empty archive. */
static unsigned char archiveEmpty[] = {
    /* 512 zero bytes */
    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,

    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,

    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,

    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
};

static void verifyEmpty(void)
{
    struct archive_entry *ae;
    struct archive *a;

    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_open_memory(a, archiveEmpty, 512));
    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_NONE);
    assertEqualString(archive_compression_name(a), "none");
    failure("512 zero bytes should be recognized as a tar archive.");
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR);

    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif
}

/* Single entry with a hardlink. */
static unsigned char archive1[] = {
'h','a','r','d','l','i','n','k',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0','0',
'0','6','4','4',' ',0,'0','0','1','7','5','0',' ',0,'0','0','1','7','5','0',
' ',0,'0','0','0','0','0','0','0','0','0','0','0',' ','1','0','6','4','6',
'0','5','2','6','6','2',' ','0','1','3','0','5','7',0,' ','1','f','i','l',
'e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t','a','r',0,'0',
'0','t','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
't','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0',
'0','0','0','0','0',' ',0,'0','0','0','0','0','0',' '};

static void verify1(struct archive_entry *ae)
{
    /* A hardlink is not a symlink. */
    assert(archive_entry_filetype(ae) != AE_IFLNK);
    /* Nor is it a directory. */
    assert(archive_entry_filetype(ae) != AE_IFDIR);
    assertEqualInt(archive_entry_mode(ae) & 0777, 0644);
    assertEqualInt(archive_entry_uid(ae), 1000);
    assertEqualInt(archive_entry_gid(ae), 1000);
    assertEqualString(archive_entry_uname(ae), "tim");
    assertEqualString(archive_entry_gname(ae), "tim");
    assertEqualString(archive_entry_pathname(ae), "hardlink");
    assertEqualString(archive_entry_hardlink(ae), "file");
    assert(archive_entry_symlink(ae) == NULL);
    assertEqualInt(archive_entry_mtime(ae), 1184388530);
}

/* Verify that symlinks are read correctly. */
static unsigned char archive2[] = {
's','y','m','l','i','n','k',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0','0',
'0','0','7','5','5',' ','0','0','0','1','7','5','0',' ','0','0','0','1','7',
'5','0',' ','0','0','0','0','0','0','0','0','0','0','0',' ','1','0','6','4',
'6','0','5','4','1','0','1',' ','0','0','1','3','3','2','3',' ','2','f','i',
'l','e',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t','a','r',0,
'0','0','t','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,'t','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
'0','0','0','0','0','0','0',' ','0','0','0','0','0','0','0',' '};

static void verify2(struct archive_entry *ae)
{
    assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
    assertEqualInt(archive_entry_mode(ae) & 0777, 0755);
    assertEqualInt(archive_entry_uid(ae), 1000);
    assertEqualInt(archive_entry_gid(ae), 1000);
    assertEqualString(archive_entry_uname(ae), "tim");
    assertEqualString(archive_entry_gname(ae), "tim");
    assertEqualString(archive_entry_pathname(ae), "symlink");
    assertEqualString(archive_entry_symlink(ae), "file");
    assert(archive_entry_hardlink(ae) == NULL);
    assertEqualInt(archive_entry_mtime(ae), 1184389185);
}

/* Character device node. */
static unsigned char archive3[] = {
'd','e','v','c','h','a','r',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0','0',
'0','0','7','5','5',' ','0','0','0','1','7','5','0',' ','0','0','0','1','7',
'5','0',' ','0','0','0','0','0','0','0','0','0','0','0',' ','1','0','6','4',
'6','0','5','4','1','0','1',' ','0','0','1','2','4','1','2',' ','3',0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t','a','r',0,
'0','0','t','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,'t','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
'0','0','0','0','0','0','0',' ','0','0','0','0','0','0','0',' '};

static void verify3(struct archive_entry *ae)
{
    assertEqualInt(archive_entry_filetype(ae), AE_IFCHR);
    assertEqualInt(archive_entry_mode(ae) & 0777, 0755);
    assertEqualInt(archive_entry_uid(ae), 1000);
    assertEqualInt(archive_entry_gid(ae), 1000);
    assertEqualString(archive_entry_uname(ae), "tim");
    assertEqualString(archive_entry_gname(ae), "tim");
    assertEqualString(archive_entry_pathname(ae), "devchar");
    assert(archive_entry_symlink(ae) == NULL);
    assert(archive_entry_hardlink(ae) == NULL);
    assertEqualInt(archive_entry_mtime(ae), 1184389185);
}

/* Block device node. */
static unsigned char archive4[] = {
'd','e','v','b','l','o','c','k',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0','0',
'0','0','7','5','5',' ','0','0','0','1','7','5','0',' ','0','0','0','1','7',
'5','0',' ','0','0','0','0','0','0','0','0','0','0','0',' ','1','0','6','4',
'6','0','5','4','1','0','1',' ','0','0','1','2','5','7','0',' ','4',0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t','a','r',0,
'0','0','t','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,'t','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
'0','0','0','0','0','0','0',' ','0','0','0','0','0','0','0',' '};

static void verify4(struct archive_entry *ae)
{
    assertEqualInt(archive_entry_filetype(ae), AE_IFBLK);
    assertEqualInt(archive_entry_mode(ae) & 0777, 0755);
    assertEqualInt(archive_entry_uid(ae), 1000);
    assertEqualInt(archive_entry_gid(ae), 1000);
    assertEqualString(archive_entry_uname(ae), "tim");
    assertEqualString(archive_entry_gname(ae), "tim");
    assertEqualString(archive_entry_pathname(ae), "devblock");
    assert(archive_entry_symlink(ae) == NULL);
    assert(archive_entry_hardlink(ae) == NULL);
    assertEqualInt(archive_entry_mtime(ae), 1184389185);
}

/* Directory. */
static unsigned char archive5[] = {
'.',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0','0','0',
'7','5','5',' ',0,'0','0','1','7','5','0',' ',0,'0','0','1','7','5','0',
' ',0,'0','0','0','0','0','0','0','0','0','0','0',' ','1','0','3','3',
'4','0','4','1','7','3','6',' ','0','1','0','5','6','1',0,' ','5',0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t','a','r',0,
'0','0','t','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,'t','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,'0','0','0','0','0','0',' ',0,'0','0','0','0','0','0',' '};

static void verify5(struct archive_entry *ae)
{
    assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
    assertEqualInt(archive_entry_mtime(ae), 1131430878);
    assertEqualInt(archive_entry_mode(ae) & 0777, 0755);
    assertEqualInt(archive_entry_uid(ae), 1000);
    assertEqualInt(archive_entry_gid(ae), 1000);
    assertEqualString(archive_entry_uname(ae), "tim");
    assertEqualString(archive_entry_gname(ae), "tim");
}

/* fifo */
static unsigned char archive6[] = {
'f','i','f','o',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0','0',
'0','0','7','5','5',' ','0','0','0','1','7','5','0',' ','0','0','0','1','7',
'5','0',' ','0','0','0','0','0','0','0','0','0','0','0',' ','1','0','6','4',
'6','0','5','4','1','0','1',' ','0','0','1','1','7','2','4',' ','6',0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t','a','r',0,
'0','0','t','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,'t','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
'0','0','0','0','0','0','0',' ','0','0','0','0','0','0','0',' '};

static void verify6(struct archive_entry *ae)
{
    assertEqualInt(archive_entry_filetype(ae), AE_IFIFO);
    assertEqualInt(archive_entry_mode(ae) & 0777, 0755);
    assertEqualInt(archive_entry_uid(ae), 1000);
    assertEqualInt(archive_entry_gid(ae), 1000);
    assertEqualString(archive_entry_uname(ae), "tim");
    assertEqualString(archive_entry_gname(ae), "tim");
    assertEqualString(archive_entry_pathname(ae), "fifo");
    assert(archive_entry_symlink(ae) == NULL);
    assert(archive_entry_hardlink(ae) == NULL);
    assertEqualInt(archive_entry_mtime(ae), 1184389185);
}

/* GNU long link name */
static unsigned char archiveK[] = {
'.','/','.','/','@','L','o','n','g','L','i','n','k',0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,'0','0','0','0','0','0','0',0,'0','0','0','0','0','0','0',0,'0','0','0',
'0','0','0','0',0,'0','0','0','0','0','0','0','0','6','6','6',0,'0','0','0',
'0','0','0','0','0','0','0','0',0,'0','1','1','7','1','5',0,' ','K',0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u','s','t','a','r',' ',' ',
0,'r','o','o','t',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
'w','h','e','e','l',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'t',
'h','i','s','_','i','s','_','a','_','v','e','r','y','_','l','o','n','g','_',
's','y','m','l','i','n','k','_','b','o','d','y','_','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y',
'z','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
'r','s','t','u','v','w','x','y','z','_','a','b','c','d','e','f','g','h','i',
'j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','_','a',
'b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t',
'u','v','w','x','y','z','_','a','b','c','d','e','f','g','h','i','j','k','l',
'm','n','o','p','q','r','s','t','u','v','w','x','y','z','_','a','b','c','d',
'e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w',
'x','y','z','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
'p','q','r','s','t','u','v','w','x','y','z','_','a','b','c','d','e','f','g',
'h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r',
's','t','u','v','w','x','y','z','_','a','b','c','d','e','f','g','h','i','j',
'k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','_','a','b',
'c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u',
'v','w','x','y','z','_','a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z','_','a','b','c','d','e',
'f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x',
'y','z','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p',
'q','r','s','t','u','v','w','x','y','z','_','a','b','c','d','e','f','g','h',
'i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
's','y','m','l','i','n','k',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0','1',
'2','0','7','5','5',0,'0','0','0','1','7','5','0',0,'0','0','0','1','7','5',
'0',0,'0','0','0','0','0','0','0','0','0','0','0',0,'1','0','6','4','6','0',
'5','6','7','7','0',0,'0','3','5','4','4','7',0,' ','2','t','h','i','s','_',
'i','s','_','a','_','v','e','r','y','_','l','o','n','g','_','s','y','m','l',
'i','n','k','_','b','o','d','y','_','a','b','c','d','e','f','g','h','i','j',
'k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','_','a','b',
'c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u',
'v','w','x','y','z','_','a','b','c','d','e','f','g','h','i','j','k','l',0,
'u','s','t','a','r',' ',' ',0,'t','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,'t','i','m'};

static void verifyK(struct archive_entry *ae)
{
    assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
    assertEqualInt(archive_entry_mode(ae) & 0777, 0755);
    assertEqualInt(archive_entry_uid(ae), 1000);
    assertEqualInt(archive_entry_gid(ae), 1000);
    assertEqualString(archive_entry_uname(ae), "tim");
    assertEqualString(archive_entry_gname(ae), "tim");
    assertEqualString(archive_entry_pathname(ae), "symlink");
    assertEqualString(archive_entry_symlink(ae),
        "this_is_a_very_long_symlink_body_abcdefghijklmnopqrstuvwxyz_"
        "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_"
        "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_"
        "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_"
        "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_"
        "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_"
        "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_"
        "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz");
    assert(archive_entry_hardlink(ae) == NULL);
    assertEqualInt(archive_entry_mtime(ae), 1184390648);
}

/* TODO: GNU long name */

/* TODO: Solaris ACL */

/* Pax extended long link name */
static unsigned char archivexL[] = {
'.','/','P','a','x','H','e','a','d','e','r','s','.','8','6','9','7','5','/',
's','y','m','l','i','n','k',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0','0','0','0','6','4','4',0,'0','0','0','1',
'7','5','0',0,'0','0','0','1','7','5','0',0,'0','0','0','0','0','0','0','0',
'7','5','3',0,'1','0','6','4','6','0','5','7','6','1','1',0,'0','1','3','7',
'1','4',0,' ','x',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'u',
's','t','a','r',0,'0','0',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,'0','0','0','0','0','0','0',0,'0','0','0','0','0','0','0',0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'4','5','1',' ','l','i','n','k','p','a','t',
'h','=','t','h','i','s','_','i','s','_','a','_','v','e','r','y','_','l','o',
'n','g','_','s','y','m','l','i','n','k','_','b','o','d','y','_','a','b','c',
'd','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
'w','x','y','z','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n',
'o','p','q','r','s','t','u','v','w','x','y','z','_','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y',
'z','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
'r','s','t','u','v','w','x','y','z','_','a','b','c','d','e','f','g','h','i',
'j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','_','a',
'b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t',
'u','v','w','x','y','z','_','a','b','c','d','e','f','g','h','i','j','k','l',
'm','n','o','p','q','r','s','t','u','v','w','x','y','z','_','a','b','c','d',
'e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w',
'x','y','z','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
'p','q','r','s','t','u','v','w','x','y','z','_','a','b','c','d','e','f','g',
'h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r',
's','t','u','v','w','x','y','z','_','a','b','c','d','e','f','g','h','i','j',
'k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','_','a','b',
'c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u',
'v','w','x','y','z','_','a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z','_','a','b','c','d','e',
'f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x',
'y','z',10,'2','0',' ','a','t','i','m','e','=','1','1','8','4','3','9','1',
'0','2','5',10,'2','0',' ','c','t','i','m','e','=','1','1','8','4','3','9',
'0','6','4','8',10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'s','y','m',
'l','i','n','k',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'0','0','0','0','7',
'5','5',0,'0','0','0','1','7','5','0',0,'0','0','0','1','7','5','0',0,'0',
'0','0','0','0','0','0','0','0','0','0',0,'1','0','6','4','6','0','5','6',
'7','7','0',0,'0','3','7','1','2','1',0,' ','2','t','h','i','s','_','i','s',
'_','a','_','v','e','r','y','_','l','o','n','g','_','s','y','m','l','i','n',
'k','_','b','o','d','y','_','a','b','c','d','e','f','g','h','i','j','k','l',
'm','n','o','p','q','r','s','t','u','v','w','x','y','z','_','a','b','c','d',
'e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w',
'x','y','z','_','a','b','c','d','e','f','g','h','i','j','k','l','m','u','s',
't','a','r',0,'0','0','t','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,'t','i','m',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,'0','0','0','0','0','0','0',0,'0','0','0','0','0','0','0'};

static void verifyxL(struct archive_entry *ae)
{
    assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
    assertEqualInt(archive_entry_mode(ae) & 0777, 0755);
    assertEqualInt(archive_entry_uid(ae), 1000);
    assertEqualInt(archive_entry_gid(ae), 1000);
    assertEqualString(archive_entry_uname(ae), "tim");
    assertEqualString(archive_entry_gname(ae), "tim");
    assertEqualString(archive_entry_pathname(ae), "symlink");
    assertEqualString(archive_entry_symlink(ae),
        "this_is_a_very_long_symlink_body_abcdefghijklmnopqrstuvwxyz_"
        "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_"
        "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_"
        "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_"
        "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_"
        "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_"
        "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_"
        "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz");
    assert(archive_entry_hardlink(ae) == NULL);
    assertEqualInt(archive_entry_mtime(ae), 1184390648);
}


/* TODO: Any other types of headers? */

static void verify(unsigned char *d, size_t s,
    void (*f)(struct archive_entry *),
    int compression, int format)
{
    struct archive_entry *ae;
    struct archive *a;
    unsigned char *buff = malloc(100000);

    memcpy(buff, d, s);
    memset(buff + s, 0, 2048);

    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_open_memory(a, buff, s + 1024));
    assertA(0 == archive_read_next_header(a, &ae));
    assertEqualInt(archive_compression(a), compression);
    assertEqualInt(archive_format(a), format);

    /* Verify the only entry. */
    f(ae);

    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif
    free(buff);
}

DEFINE_TEST(test_read_format_tar)
{
    verifyEmpty();
    verify(archive1, sizeof(archive1), verify1,
        ARCHIVE_COMPRESSION_NONE, ARCHIVE_FORMAT_TAR_USTAR);
    verify(archive2, sizeof(archive2), verify2,
        ARCHIVE_COMPRESSION_NONE, ARCHIVE_FORMAT_TAR_USTAR);
    verify(archive3, sizeof(archive3), verify3,
        ARCHIVE_COMPRESSION_NONE, ARCHIVE_FORMAT_TAR_USTAR);
    verify(archive4, sizeof(archive4), verify4,
        ARCHIVE_COMPRESSION_NONE, ARCHIVE_FORMAT_TAR_USTAR);
    verify(archive5, sizeof(archive5), verify5,
        ARCHIVE_COMPRESSION_NONE, ARCHIVE_FORMAT_TAR_USTAR);
    verify(archive6, sizeof(archive6), verify6,
        ARCHIVE_COMPRESSION_NONE, ARCHIVE_FORMAT_TAR_USTAR);
    verify(archiveK, sizeof(archiveK), verifyK,
        ARCHIVE_COMPRESSION_NONE, ARCHIVE_FORMAT_TAR_GNUTAR);
    verify(archivexL, sizeof(archivexL), verifyxL,
        ARCHIVE_COMPRESSION_NONE, ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE);
}



--- NEW FILE: test_compat_gtar.c ---
/*-
 * 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/lib/libarchive/test/test_compat_gtar.c,v 1.4 2008/12/17 19:05:00 kientzle Exp $");

/*
 * Verify our ability to read sample files created by GNU tar.
 * It should be easy to add any new sample files sent in by users
 * to this collection of tests.
 */

/* Copy this function for each test file and adjust it accordingly. */

/*
 * test_compat_gtar_1.tgz exercises reading long filenames and
 * symlink targets stored in the GNU tar format.
 */
static void
test_compat_gtar_1(void)
{
    char name[] = "test_compat_gtar_1.tar";
    struct archive_entry *ae;
    struct archive *a;
    int r;

    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    extract_reference_file(name);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240));

    /* Read first entry. */
    assertEqualIntA(a, ARCHIVE_OK, r = archive_read_next_header(a, &ae));
    if (r != ARCHIVE_OK) {
        archive_read_finish(a);
        return;
    }
    assertEqualString(
        "12345678901234567890123456789012345678901234567890"
        "12345678901234567890123456789012345678901234567890"
        "12345678901234567890123456789012345678901234567890"
        "12345678901234567890123456789012345678901234567890",
        archive_entry_pathname(ae));
    assertEqualInt(1197179003, archive_entry_mtime(ae));
    assertEqualInt(1000, archive_entry_uid(ae));
    assertEqualString("tim", archive_entry_uname(ae));
    assertEqualInt(1000, archive_entry_gid(ae));
    assertEqualString("tim", archive_entry_gname(ae));
    assertEqualInt(0100644, archive_entry_mode(ae));

    /* Read second entry. */
    assertEqualIntA(a, ARCHIVE_OK, r = archive_read_next_header(a, &ae));
    if (r != ARCHIVE_OK) {
        archive_read_finish(a);
        return;
    }
    assertEqualString(
        "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij"
        "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij"
        "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij"
        "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij",
        archive_entry_pathname(ae));
    assertEqualString(
        "12345678901234567890123456789012345678901234567890"
        "12345678901234567890123456789012345678901234567890"
        "12345678901234567890123456789012345678901234567890"
        "12345678901234567890123456789012345678901234567890",
        archive_entry_symlink(ae));
    assertEqualInt(1197179043, archive_entry_mtime(ae));
    assertEqualInt(1000, archive_entry_uid(ae));
    assertEqualString("tim", archive_entry_uname(ae));
    assertEqualInt(1000, archive_entry_gid(ae));
    assertEqualString("tim", archive_entry_gname(ae));
    assertEqualInt(0120755, archive_entry_mode(ae));

    /* Verify the end-of-archive. */
    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));

    /* Verify that the format detection worked. */
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_NONE);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR);

    assertEqualInt(ARCHIVE_OK, archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
#endif
}


DEFINE_TEST(test_compat_gtar)
{
    test_compat_gtar_1();
}



--- NEW FILE: test_read_format_isozisofs_bz2.iso.bz2.uu ---
begin 644 test_read_format_isozisofs_bz2.iso.bz2
M0EIH.3%!62936>PH7^L``--_____R_S78__XO__?\*?OWG8E_@$`)``H!V`@
M`1@$`L%(T`/>"@4;0TV>#1$$1Z0T#$`:!ZAZ(`:#1H`!H-!Z@'J-`]30T!H`
M`::D](!/1&J>$RFTC(9'J`>ID!IH,@,`@!ID8@:#0`P0(-,3````````````
M``!&$8````(5!&3)IA&1HP$&`1IH8`$PFFA@`1II@`AID8!,:")1!$8J>R)@
M4]1M-3:CU!Z@](T&C0#0``TV4!B`/4T:#0Q&BXP#6W-XB=$X at M5PJW.GJ!JF
MMKFP'4Z]`NMV<P':A6^E8D82!$#:B;<$=VE#Y(`'J$0!?JB(H!N:5%QWCEST
M!MBJ at II#!I(C$!DUMB<BMD!-G9`52BR(?J1Y,4`%,45VA#%GU52I%Q9U,$$O
MOC+"HFPAF8V%5$.5R79LSM>I5#T&N_:21$1$04?`C at G]1D+G4&7TH%$I$`!3
M_?Y"P-0Q2$P76;]$?#W]_0LZU^.N&IEV=H,&,+QN**>N"5?`@;RFA00W)>?I
ME-Q>Q`RGC1#/ZTF!2HX<@1`,M at A`&@OXPL4C>S#5N:CMSJD7M;REW.452Q\O
MAP]FP#8@\$P"&T5_)!O/:X:!ZM+?*@4L4W6FT<WQ\0#S,E(E(4"!#!/[J7J5
M*!`ASZ7/A0.?C^-0+A4A52$$*D3T0(DUKNF#7[X2SE$_DOF$HY)7/+64,C52
MVI+L[GYZ=*9LEU^&W1^SI8$V.@<AE(&IF4L&A6AQZ#2$D2%(GTW\(##,<`#3
M5CFT*<<[?3LE-?Y>F6ZN;.PTNCOQ*/D8S/"PNWFD8ZG1HZ%S]U"EUJ5<LOSN
MK>V84V(H6'6U4N(Q9P-WM!R`(B(*([H/^PVN1%$QI(XU0E]((1!"=:.L0;R&
ME-`0ZA-H8K(:336Z&8=F'C%V%@@TO>@(6]]-. at _=,)J.QEBA'N,,E60.KM?,
M779&PQ60;(A$ZZZB'@=0T!.\+`(0_$1(@C$V40+KK4;P<:/!'4%A>3CMEO:Z
MOMP'DF;`*X0OAX.`4+'*R61R#>AH%.B^(M&1^4I\`L$2(;U'IJ*WZZ8#8$(:
MYB#]C:)1H>6.G)691>+`%4-O"2DXQ=DNI._A9JZ$<Z&[XIR^9R_<Z at 8'&IH\
M;FPHPICK6MO+<]-Z)]6M%KC`O\H,*/4HXC)8!6NR^;2#1!U0&"593-9#-C!2
M5X?U^$X`M at RHEONBE.T$3FMKBY]:A45>'"XVC0("Y$*18""8BA3K'G:%.$"G
ML4>@G)GU8^RB-X6J7/;U[@^(2F^5_28]$C;,FJ0@/-8F3;ZX>ZX4Z!;AUH;Y
MV+N\Y6E4P!R><Z]<0>"5\ZPNZ9C"KMG!Q:=K[]*775J'=<06AY@%01,]4B4A
K$N);0`$@!;IGD:NLCA.,W8 at 9$#WT00=$`$1$!!(,95L%W)%.%"0["A?ZP```
`
end

--- NEW FILE: test_compat_xz_1.txz.uu ---
begin 644 test_compat_gzip_1.txz
M_3=Z6%H```3FUK1&`@`A`18```!T+^6CX`^?`(-=`#,,/!NGC#0&C6L"2_R2
M/O9*^(7KX=WM^(=KA(RH"\09$$)!Q_+JUHQ*`]R;ITL_F3/I6:^Q0550A&)B
MHS@=K]7 at K1-9FOIP#PU!I<PUHW+W#<F(6FSL/<?5:4*>?E5&IHH&Q=N>_C&G
M-$G]+L[\,B<7%8&$NO5K31*Y>"D^*ZG,Z=H```"KU50H$1^1S``!GP&@'P``
MLZ042+'$9_L"``````196OTW>EA:```$YM:T1@(`(0$6````="_EH^`,7P!I
M70``;IBIKOMK%/A?-<U3^2)5\V,DQ(:ZUH:[B'3>TZV0266G?2,[/?\,JE6`
M__C/SA[W1?*2<Y3NQ'DCK4JEJYHQU`Q\N=H9LL3KRAH,VQQ2OD*@?1NLV]<E
MF&X."!L\R:Z]=*TJPT/BJ^``````R[PG*'(H!W,``84!X!@``/;+`G2QQ&?[
(`@`````$65H`
`
end

--- NEW FILE: test_write_format_shar_empty.c ---
/*-
 * 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/lib/libarchive/test/test_write_format_shar_empty.c,v 1.3 2008/09/01 05:38:33 kientzle Exp $");

/*
 * Check that an "empty" shar archive is correctly created as an empty file.
 */

DEFINE_TEST(test_write_format_shar_empty)
{
    struct archive *a;
    char buff[2048];
    size_t used;

    /* Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_shar(a));
    assertA(0 == archive_write_set_compression_none(a));
    /* 1-byte block size ensures we see only the required bytes. */
    /* We're not testing the padding here. */
    assertA(0 == archive_write_set_bytes_per_block(a, 1));
    assertA(0 == archive_write_set_bytes_in_last_block(a, 1));
    assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));

    /* Close out the archive. */
    assertA(0 == archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assertA(0 == archive_write_finish(a));
#endif

    failure("Empty shar archive should be exactly 0 bytes, was %d.", used);
    assert(used == 0);
}

--- NEW FILE: test_compat_gzip_2.tgz.uu ---
$FreeBSD: src/lib/libarchive/test/test_compat_gzip_2.tgz.uu,v 1.1 2008/12/06 07:08:08 kientzle Exp $

begin 644 test_compat_gzip_2.tgz
M'XL(`&76(DD``^W800["(!"%8=:>@ALXPP`]CXF=Q&A<:-UX>EN)C5M,AL;P
MO at V[0A=_.E39F2.B'*.?5QX2?Z\?XGE&27)F]L0<HCA/]D=S[G&?#K?Y*.?3
M>)V>E_'7YY07\>OZ)Y1W6Q\!-J3!?H^Z_J7TG]%_"QK0?\]4[/>HZS^_^T\!
M_;>@@OY[=N2]6E\!JOH/P])_2OC^-X'YOV]+_]97@*K^A4K_C/Y;P/S?MZ5_
MZRM`7?]<^L?_OR8P_P,`].D%,XR2*0`<``!4:&ES(&ES('5N<F5L871E9"!J
@=6YK(&1A=&$@870@=&AE(&5N9"!O9B!T:&4 at 9FEL90H`
`
end

--- NEW FILE: CMakeLists.txt ---
############################################
#
# How to build libarchive_test
#
############################################
IF(ENABLE_TEST)
  FOREACH (_src ${libarchive_SOURCES})
    LIST(APPEND parent_libarchive_SOURCES "../${_src}")
  ENDFOREACH(_src)

  SET(libarchive_test_SOURCES
    ${parent_libarchive_SOURCES}
    main.c
    read_open_memory.c
    test.h
    test_acl_basic.c
    test_acl_freebsd.c
    test_acl_pax.c
    test_archive_api_feature.c
    test_bad_fd.c
    test_compat_bzip2.c
    test_compat_gtar.c
    test_compat_gzip.c
    test_compat_solaris_tar_acl.c
    test_compat_tar_hardlink.c
    test_compat_xz.c
    test_compat_zip.c
    test_empty_write.c
    test_entry.c
    test_entry_strmode.c
    test_extattr_freebsd.c
    test_fuzz.c
    test_link_resolver.c
    test_open_fd.c
    test_open_file.c
    test_open_filename.c
    test_pax_filename_encoding.c
    test_read_compress_program.c
    test_read_data_large.c
    test_read_disk.c
    test_read_disk_entry_from_file.c
    test_read_extract.c
    test_read_file_nonexistent.c
    test_read_format_ar.c
    test_read_format_cpio_bin.c
    test_read_format_cpio_bin_Z.c
    test_read_format_cpio_bin_be.c
    test_read_format_cpio_bin_bz2.c
    test_read_format_cpio_bin_gz.c
    test_read_format_cpio_bin_xz.c
    test_read_format_cpio_odc.c
    test_read_format_cpio_svr4_gzip.c
    test_read_format_cpio_svr4c_Z.c
    test_read_format_empty.c
    test_read_format_gtar_gz.c
    test_read_format_gtar_lzma.c
    test_read_format_gtar_sparse.c
    test_read_format_iso_gz.c
    test_read_format_isojoliet_bz2.c
    test_read_format_isojoliet_long.c
    test_read_format_isojoliet_rr.c
    test_read_format_isorr_bz2.c
    test_read_format_isorr_new_bz2.c
    test_read_format_isozisofs_bz2.c
    test_read_format_mtree.c
    test_read_format_pax_bz2.c
    test_read_format_raw.c
    test_read_format_tar.c
    test_read_format_tar_empty_filename.c
    test_read_format_tbz.c
    test_read_format_tgz.c
    test_read_format_txz.c
    test_read_format_tz.c
    test_read_format_zip.c
    test_read_large.c
    test_read_pax_truncated.c
    test_read_position.c
    test_read_truncated.c
    test_tar_filenames.c
    test_tar_large.c
    test_ustar_filenames.c
    test_write_compress.c
    test_write_compress_bzip2.c
    test_write_compress_gzip.c
    test_write_compress_lzma.c
    test_write_compress_program.c
    test_write_compress_xz.c
    test_write_disk.c
    test_write_disk_failures.c
    test_write_disk_hardlink.c
    test_write_disk_perms.c
    test_write_disk_secure.c
    test_write_disk_sparse.c
    test_write_disk_symlink.c
    test_write_disk_times.c
    test_write_format_ar.c
    test_write_format_cpio.c
    test_write_format_cpio_empty.c
    test_write_format_cpio_odc.c
    test_write_format_cpio_newc.c
    test_write_format_mtree.c
    test_write_format_pax.c
    test_write_format_shar_empty.c
    test_write_format_tar.c
    test_write_format_tar_empty.c
    test_write_format_tar_ustar.c
    test_write_format_zip.c
    test_write_format_zip_empty.c
    test_write_format_zip_no_compression.c
    test_write_open_memory.c
  )

  #
  # Generate the list.h
  #
  GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h
    ${CMAKE_CURRENT_LIST_FILE} ${libarchive_test_SOURCES})
  SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES
    ${CMAKE_CURRENT_BINARY_DIR})
  #
  # Register target
  #
  ADD_EXECUTABLE(libarchive_test ${libarchive_test_SOURCES})
  TARGET_LINK_LIBRARIES(libarchive_test ${ADDITIONAL_LIBS})
  SET_PROPERTY(TARGET libarchive_test PROPERTY COMPILE_DEFINITIONS
    LIBARCHIVE_STATIC LIST_H)

  # Register ADD_TEST() for each separate test
  SET(num 0)
  FOREACH(test ${libarchive_test_SOURCES})
    IF(test MATCHES "^test_[^/]+[.]c$")
      STRING(REGEX REPLACE "^(test_[^/]+)[.]c$" "\\1" testname ${test})
      ADD_TEST("libarchive_${testname}" libarchive_test
        -q -r ${CMAKE_CURRENT_SOURCE_DIR} ${num})
      MATH(EXPR num "${num} + 1")
    ENDIF(test MATCHES "^test_[^/]+[.]c$")
  ENDFOREACH(test)


  # Experimental new test handling
  ADD_CUSTOM_TARGET(run_libarchive_test
    COMMAND libarchive_test -r ${CMAKE_CURRENT_SOURCE_DIR})
  ADD_DEPENDENCIES(run_all_tests run_libarchive_test)
ENDIF(ENABLE_TEST)


--- NEW FILE: test_read_format_gtar_sparse_1_17_posix10_modified.tar.uu ---
$FreeBSD: src/lib/libarchive/test/test_read_format_gtar_sparse_1_17_posix10_modified.tar.uu,v 1.2 2008/07/03 03:26:30 peter Exp $
begin 644 test_read_format_gtar_sparse_1_17_posix10_modified.tar
M+B]087A(96%D97)S+C,X-C8S+W-P87)S90``````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#`P,#`V-#0`,#`P,3<U,``P,#`Q-S4P`#`P,#`P,#`P,C$U
M`#$P-S,S,3`Q,30S`#`Q,S0V-@`@>```````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<@`P,```````
M````````````````````````````````````````````````````````````
M```````````````````P,#`P,#`P`#`P,#`P,#``````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````R,B!'3E4N<W!A<G-E+FUA:F]R/3$*,C(@1TY5
M+G-P87)S92YM:6YO<CTP"C(V($=.52YS<&%R<V4N;F%M93US<&%R<V4*,S$@
M1TY5+G-P87)S92YR96%L<VEZ93TS,30U-S(X"C(P(&%T:6UE/3$Q.3 at R.3,V
M,#(*,C`@8W1I;64],3$Y.#(Y,S8P,`H`````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
[...1331 lines suppressed...]
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
/````````````````````
`
end

--- NEW FILE: test_fuzz_1.iso.uu ---
$FreeBSD: src/lib/libarchive/test/test_fuzz_1.iso.uu,v 1.1 2008/12/06 07:08:08 kientzle Exp $
begin 644 test_fuzz_1.iso
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
[...26954 lines suppressed...]
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
$````````
`
end

--- NEW FILE: test_read_format_empty.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_empty.c,v 1.2 2008/09/01 05:38:33 kientzle Exp $");

static unsigned char archive[] = { 0 };

DEFINE_TEST(test_read_format_empty)
{
    struct archive_entry *ae;
    struct archive *a;
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_open_memory(a, archive, 0));
    assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae));
    assertA(archive_compression(a) == ARCHIVE_COMPRESSION_NONE);
    assertA(archive_format(a) == ARCHIVE_FORMAT_EMPTY);
    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif
}

--- NEW FILE: test_read_compress_program.c ---
/*-
 * 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/lib/libarchive/test/test_read_compress_program.c,v 1.3 2008/09/01 05:38:33 kientzle Exp $");

static unsigned char archive[] = {
31,139,8,0,222,'C','p','C',0,3,211,'c',160,'=','0','0','0','0','7','5','U',
0,210,134,230,166,6,200,'4',28,'(',24,26,24,27,155,24,152,24,154,27,155,')',
24,24,26,152,154,25,'2','(',152,210,193,'m',12,165,197,'%',137,'E','@',167,
148,'d',230,226,'U','G','H',30,234,15,'8','=',10,'F',193,'(',24,5,131,28,
0,0,29,172,5,240,0,6,0,0};

DEFINE_TEST(test_read_compress_program)
{
    int r;
    struct archive_entry *ae;
    struct archive *a;

    /*
     * First, test handling when a non-existent compression
     * program is requested.
     */
    assert((a = archive_read_new()) != NULL);
    r = archive_read_support_compression_program(a, "nonexistent");
    if (r == ARCHIVE_FATAL) {
        skipping("archive_read_support_compression_program() "
            "unsupported on this platform");
        return;
    }
    assertEqualIntA(a, ARCHIVE_OK, r);
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_FATAL,
        archive_read_open_memory(a, archive, sizeof(archive)));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));

    /*
     * If we have "gzip -d", try using that.
     */
    if (!canGunzip()) {
        skipping("Can't run gunzip program on this platform");
        return;
    }
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_support_compression_none(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_support_compression_program(a, "gunzip"));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_open_memory(a, archive, sizeof(archive)));
    assertEqualIntA(a, ARCHIVE_OK,
        archive_read_next_header(a, &ae));
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_PROGRAM);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}



--- NEW FILE: test_read_format_cpio_odc.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_cpio_odc.c,v 1.3 2008/09/01 05:38:33 kientzle Exp $");

static unsigned char archive[] = {
'0','7','0','7','0','7','0','0','2','0','2','5','0','7','4','6','6','1','0',
'4','0','7','5','5','0','0','1','7','5','0','0','0','1','7','5','0','0','0',
'0','0','0','2','0','0','0','0','0','0','1','0','3','3','4','0','5','0','0',
'5','3','0','0','0','0','0','2','0','0','0','0','0','0','0','0','0','0','0',
'.',0,'0','7','0','7','0','7','0','0','0','0','0','0','0','0','0','0','0',
'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0',
'0','0','0','0','0','1','0','0','0','0','0','0','0','0','0','0','0','0','0',
'0','0','0','0','0','0','0','0','1','3','0','0','0','0','0','0','0','0','0',
'0','0','T','R','A','I','L','E','R','!','!','!',0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0};

DEFINE_TEST(test_read_format_cpio_odc)
{
    struct archive_entry *ae;
    struct archive *a;
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_open_memory(a, archive, sizeof(archive)));
    assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
    assertA(archive_compression(a) == ARCHIVE_COMPRESSION_NONE);
    assertA(archive_format(a) == ARCHIVE_FORMAT_CPIO_POSIX);
    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif
}



--- NEW FILE: test_compat_solaris_tar_acl.tar.uu ---
$FreeBSD$
begin 644 test_acl_solaris.tar
M9FEL92UW:71H+7!O<VEX+6%C;',`````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#`P,#`V-#0`,#`P,3<U,``P,#`P,#`P`#`P,#`P,#`P,30T
M`#$Q,3<T-C`T,34W`#`P,34Q-S8`00``````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<@`P,'1R87-Z
M````````````````````````````````````<F]O=```````````````````
M```````````````````P,#`P,C$P`#`P,#`P,3``````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````Q,#`P,#`W`'5S97(Z.G)W+2QU<V5R.FQP.BTM
M>#HW,2QU<V5R.C8V-CIR+2TZ-C8V+'5S97(Z=')A<WHZ<G=X.C$P,#`L9W)O
M=7`Z.G(M+2QM87-K.G(M+2QO=&AE<CIR+2T``````````3````````/-@```
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````!%&8`````````&L`````,3`P,#`P-P!U
M<V5R.CIR=RTL=7-E<CIL<#HM+7 at Z-S$L=7-E<CHV-C8Z<BTM.C8V-BQU<V5R
M.G1R87-Z.G)W>#HQ,#`P+&=R;W5P.CIR+2TL;6%S:SIR+69I;&4M=VET:"UP
M;W-I>"UA8VQS````````````````````````````````````````````````
M```````````````````````````````````````````````````````````P
M,#`P-C0T`#`P,#$W-3``,#`P,#`P,``P,#`P,#`P,#`P,``Q,3$W-#8P-#$U
M-P`P,#$U,30T`#``````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````=7-T87(`,#!T<F%S>@``````````````
M`````````````````````')O;W0`````````````````````````````````
M````,#`P,#(Q,``P,#`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````````````````````````````````````````````````````````````
H````````````````````````````````````````````````````````
`
end

--- NEW FILE: test_write_compress.c ---
/*-
 * Copyright (c) 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 "test.h"
__FBSDID("$FreeBSD: src/lib/libarchive/test/test_write_compress.c,v 1.4 2008/12/17 19:05:25 kientzle Exp $");

/*
 * A basic exercise of compress reading and writing.
 *
 * TODO: Add a reference file and make sure we can decompress that.
 */

DEFINE_TEST(test_write_compress)
{
    struct archive_entry *ae;
    struct archive* a;
    char *buff, *data;
    size_t buffsize, datasize;
    char path[16];
    size_t used;
    int i;

    buffsize = 1000000;
    assert(NULL != (buff = (char *)malloc(buffsize)));

    datasize = 10000;
    assert(NULL != (data = (char *)malloc(datasize)));
    memset(data, 0, datasize);

    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    assertA(0 == archive_write_set_compression_compress(a));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used));

    for (i = 0; i < 100; i++) {
        sprintf(path, "file%03d", i);
        assert((ae = archive_entry_new()) != NULL);
        archive_entry_copy_pathname(ae, path);
        archive_entry_set_size(ae, datasize);
        archive_entry_set_filetype(ae, AE_IFREG);
        assertA(0 == archive_write_header(a, ae));
        assertA(datasize == (size_t)archive_write_data(a, data, datasize));
        archive_entry_free(ae);
    }


    archive_write_close(a);
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assert(0 == archive_write_finish(a));
#endif

    /*
     * Now, read the data back.
     */
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff, used));


    for (i = 0; i < 100; i++) {
        sprintf(path, "file%03d", i);
        if (!assertEqualInt(0, archive_read_next_header(a, &ae)))
            break;
        assertEqualString(path, archive_entry_pathname(ae));
        assertEqualInt((int)datasize, archive_entry_size(ae));
    }
    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif

    free(data);
    free(buff);
}

--- NEW FILE: test_read_format_zip.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_zip.c,v 1.8 2008/10/21 05:08:35 kientzle Exp $");

/*
 * The reference file for this has been manually tweaked so that:
 *   * file2 has length-at-end but file1 does not
 *   * file2 has an invalid CRC
 */

DEFINE_TEST(test_read_format_zip)
{
    const char *refname = "test_read_format_zip.zip";
    struct archive_entry *ae;
    struct archive *a;
    char *buff[128];
    const void *pv;
    size_t s;
    off_t o;
    int r;

    extract_reference_file(refname);
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_open_filename(a, refname, 10240));
    assertA(0 == archive_read_next_header(a, &ae));
    assertEqualString("dir/", archive_entry_pathname(ae));
    assertEqualInt(1179604249, archive_entry_mtime(ae));
    assertEqualInt(0, archive_entry_size(ae));
    assertEqualIntA(a, ARCHIVE_EOF,
        archive_read_data_block(a, &pv, &s, &o));
    assertEqualInt((int)s, 0);
    assertA(0 == archive_read_next_header(a, &ae));
    assertEqualString("file1", archive_entry_pathname(ae));
    assertEqualInt(1179604289, archive_entry_mtime(ae));
    assertEqualInt(18, archive_entry_size(ae));
    failure("archive_read_data() returns number of bytes read");
    r = archive_read_data(a, buff, 19);
    if (r < ARCHIVE_OK) {
        if (strcmp(archive_error_string(a),
            "libarchive compiled without deflate support (no libz)") == 0) {
            skipping("Skipping ZIP compression check: %s",
                archive_error_string(a));
            goto finish;
        }
    }
    assertEqualInt(18, r);
    assert(0 == memcmp(buff, "hello\nhello\nhello\n", 18));
    assertA(0 == archive_read_next_header(a, &ae));
    assertEqualString("file2", archive_entry_pathname(ae));
    assertEqualInt(1179605932, archive_entry_mtime(ae));
    failure("file2 has length-at-end, so we shouldn't see a valid size");
    assertEqualInt(0, archive_entry_size_is_set(ae));
    failure("file2 has a bad CRC, so reading to end should fail");
    assertEqualInt(ARCHIVE_WARN, archive_read_data(a, buff, 19));
    assert(0 == memcmp(buff, "hello\nhello\nhello\n", 18));
    assertA(archive_compression(a) == ARCHIVE_COMPRESSION_NONE);
    assertA(archive_format(a) == ARCHIVE_FORMAT_ZIP);
    assert(0 == archive_read_close(a));
finish:
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif
}



--- NEW FILE: test_read_format_isojoliet_long.iso.bz2.uu ---
begin 644 test_read_format_isojoliet_long.iso.bz2
M0EIH.3%!629364L46LD``/?__?__1_?W;__X/__?8*[_GH8DJ$``!`04<8`!
M0`+@"-`$?@"[!;`NTZ<X:@F32)GJ3:@T]08F0,:AH`:`,0!DTT::-````]0&
MIH":3$&@FF30`````````T&@````9%4]J(VIHT:``R&(,@`:::``--#(``]1
MZ@`,30X``T``,@```,AHT`````````$2A$T334])J/!-(>C4\H-&@>H#1H-#
MTADT'J9-#)H`>0GJ&3`&DG?T]7>3N%RX*8W*%^PO*-D.6'C'C^0/M/$?WQX^
M9AAM<W6!\!T::$2K$A""N(@`;L'LP`]"M"0[6O0%.V0Z!``7NP%4`W+J+KZV
M,,NOF0`Q0!)$113EJ0)*$@A$`)$2U)1*1)!)!0%3%,4+1`W!'%10"UUU+5I"
M4K86\CS=GA[A=<4[]];PNI3_L-V%HH]6"[M2B*)((;\%/IGT7V]:U/J*97CX
M?@S92XOHX=-$-^.>U].DB%':^%!/8,F5!/B`3XP$RY=\!*`)TP$W0$PYV=.W
M4*S4<KTN$HL,"O<(55C0)`!''W)GJXY-8/FT3;00VT)-#%1;T18K01UMO7['
MROXCB&+<IOU3KAQTD^(#D&$`B$-*IA8*D@$A3P=GJ/N!F]&\H>WUZH%9:./'
M;*0L:1?4X)8&.1<PC7YH=59HL4>+$=[@7\#KWE$NQG&47.#HA>@U$91B$(I"
M#QQ;VK0-I>D%"H?M1'8B,A\JE%,=PCU.%3HV+E)N&]CJ!J[W8M3L4K.4NC0(
MP at 3GM'`A4A"!!@1>A`%"$D@`*,P(!B-NM%A83\SU)LPW%OO/WVI.*Z"N/]&&
MW2 at K.:A"\YR6"D*@^Q[H]$;-`U$L):67R)\]DA(\>*`40_B'^5'B;@AY90&!
M2C))&)VK\)#2*&HLKK0VYR<]-LVMO5YFV8M;^M/0R9D$J!UH<T8;QI.8>0MG
M"]0E!S#GHMLB"4:RHV'BNU.?_-3$H:`];(4R;!=>(EWJ2AG-:F"#$$^[3R<E
M!L`GE`,`3@`>3 at -1$Q;^'``V`2E@'S"H"3-,X,!)5!)>NH"4'$7S&VGB*:I.
M(&I@<JRRQC%:DG.R0E44UG('98=8_IE\?UJ19$H/UY`4#%0]2$4`(91D at 8K+
M\FD2U#U#3`YEMF-#TU2W<U$0Y-G at MDP,UO#8PZ/=X=(.4>^%`>\Z[`T%NRFD
MGJ\C8QU.1*2;!V$34J`PX5O3IB6*KD"*I at F`EA`BI"77Z2(('XU0$"1#0*>3
M\'*$+89IZ!DQY2_M at 4PQ!3Q_PR0=#7`(791X],EP--!EHB!4KP\TWBV2QT#*
MB`A?(/:[Y/L!D`%LFN at E"@GQ$(DR)L$5#5I4H.V@*X!':PG4F-*!X))YRW at H
M.$'T-*"6#M)*5%3B8"V1X42(/I!!\H8F2\@1JICQ*EG<D.&,J,VH'#!;;J:.
M!T#,FG&29*.F\2/F28#<I\PINJ2T5T<25J9E$(&=!XRH3RGBH(&*,LST"-;K
M4#V!A@')$,0P[IH.#@?ND=`K:,)2NYSDN2WAOK%!13*G;_\7<D4X4)!+%%K)
`
end

--- NEW FILE: test_entry_strmode.c ---
/*-
 * 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/lib/libarchive/test/test_entry_strmode.c,v 1.1 2008/01/01 22:28:04 kientzle Exp $");

DEFINE_TEST(test_entry_strmode)
{
    struct archive_entry *entry;

    assert((entry = archive_entry_new()) != NULL);

    archive_entry_set_mode(entry, AE_IFREG | 0642);
    assertEqualString(archive_entry_strmode(entry), "-rw-r---w- ");

    /* Regular file + hardlink still shows as regular file. */
    archive_entry_set_mode(entry, AE_IFREG | 0644);
    archive_entry_set_hardlink(entry, "link");
    assertEqualString(archive_entry_strmode(entry), "-rw-r--r-- ");

    archive_entry_set_mode(entry, 0640);
    archive_entry_set_hardlink(entry, "link");
    assertEqualString(archive_entry_strmode(entry), "hrw-r----- ");
    archive_entry_set_hardlink(entry, NULL);

    archive_entry_set_mode(entry, AE_IFDIR | 0777);
    assertEqualString(archive_entry_strmode(entry), "drwxrwxrwx ");

    archive_entry_set_mode(entry, AE_IFBLK | 03642);
    assertEqualString(archive_entry_strmode(entry), "brw-r-S-wT ");

    archive_entry_set_mode(entry, AE_IFCHR | 05777);
    assertEqualString(archive_entry_strmode(entry), "crwsrwxrwt ");

    archive_entry_set_mode(entry, AE_IFSOCK | 0222);
    assertEqualString(archive_entry_strmode(entry), "s-w--w--w- ");

    archive_entry_set_mode(entry, AE_IFIFO | 0444);
    assertEqualString(archive_entry_strmode(entry), "pr--r--r-- ");

    archive_entry_set_mode(entry, AE_IFLNK | 04000);
    assertEqualString(archive_entry_strmode(entry), "l--S------ ");

    archive_entry_acl_add_entry(entry, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
        0007, ARCHIVE_ENTRY_ACL_GROUP, 78, "group78");
    assertEqualString(archive_entry_strmode(entry), "l--S------+");

    /* Release the experimental entry. */
    archive_entry_free(entry);
}

--- NEW FILE: test_compat_bzip2_2.tbz.uu ---
$FreeBSD: src/lib/libarchive/test/test_compat_bzip2_2.tbz.uu,v 1.1 2008/12/06 07:08:08 kientzle Exp $

begin 644 test_compat_bzip2_2.tbz
M0EIH.3%!629361HI1P<``4#;D-$00`#_@``)9RT>$`0``!@P`/@#&$Q,F`F`
M`,83$R8"8``1133"1/2-J-#$/U3@;XVF9V'`Y3882XA$*KO6\WTL`]QU&J"8
M$-=*Q$\@=`=QJ,TQ;3UH,NPT$-(!"HV&!ZO5D&@P-1D&1@'L<8&209QV9'G`
MW&PRZ0Q(-BT%&DG*DE.!U*#J.P]*#%-P9G`W9+34:#S&M`;@^1R^![C]:Y)U
MDF9/(\AR/@?P<CD<CD>@^@I_B[DBG"A(#12C at X!3;VUE(&UO<F4 at 9&%T82!T
7:&%T(&ES(&YO="!B>FEP('-T<F5A;0H`
`
end

--- NEW FILE: test_read_format_gtar_sparse_1_13.tar.uu ---
begin 644 test_read_format_gtar_sparse_1_13.tar
M<W!A<G-E````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#`Q,#`V-#0`,#`P,3<U,``P,#`Q-S4P`#`P,#`P,#`R,#`Q
M`#$P-S,S,3`Q,30P`#`Q-S<V-P`@4P``````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<B`@`'1I;0``
M````````````````````````````````````=&EM````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````````````````P,#`P,S8T,3`P,``P,#`P,#`P
M,3`P,``P,#`P-S4P,C`P,``P,#`P,#`P,3`P,``P,#`Q,S<W-S<W-P`P,#`P
M,#`P,#`P,0``````````````````````````````````,#`P,30P,#`P,#``
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````80``````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
[...1330 lines suppressed...]
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
/````````````````````
`
end

--- NEW FILE: test_write_disk_hardlink.c ---
/*-
 * 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/lib/libarchive/test/test_write_disk_hardlink.c,v 1.5 2008/09/05 06:13:11 kientzle Exp $");

#if defined(_WIN32) && !defined(__CYGWIN__)
/* Execution bits, Group members bits and others bits do not work. */
#define UMASK 0177
#define E_MASK (~0177)
#else
#define UMASK 022
#define E_MASK (~0)
#endif

/*
 * Exercise hardlink recreation.
 *
 * File permissions are chosen so that the authoritive entry
 * has the correct permission and the non-authoritive versions
 * are just writeable files.
 */
DEFINE_TEST(test_write_disk_hardlink)
{
#if ARCHIVE_VERSION_NUMBER < 1009000
    skipping("archive_write_disk_hardlink tests");
#else
    static const char data[]="abcdefghijklmnopqrstuvwxyz";
    struct archive *ad;
    struct archive_entry *ae;
    int r;

    /* Force the umask to something predictable. */
    assertUmask(UMASK);

    /* Write entries to disk. */
    assert((ad = archive_write_disk_new()) != NULL);

    /*
     * First, use a tar-like approach; a regular file, then
     * a separate "hardlink" entry.
     */

    /* Regular file. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "link1a");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    archive_entry_set_size(ae, sizeof(data));
    assertEqualIntA(ad, 0, archive_write_header(ad, ae));
    assertEqualInt(sizeof(data),
        archive_write_data(ad, data, sizeof(data)));
    assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
    archive_entry_free(ae);

    /* Link.  Size of zero means this doesn't carry data. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "link1b");
    archive_entry_set_mode(ae, S_IFREG | 0642);
    archive_entry_set_size(ae, 0);
    archive_entry_copy_hardlink(ae, "link1a");
    assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
    if (r >= ARCHIVE_WARN) {
        assertEqualInt(ARCHIVE_WARN,
            archive_write_data(ad, data, sizeof(data)));
        assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
    }
    archive_entry_free(ae);

    /*
     * Repeat tar approach test, but use unset to mark the
     * hardlink as having no data.
     */

    /* Regular file. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "link2a");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    archive_entry_set_size(ae, sizeof(data));
    assertEqualIntA(ad, 0, archive_write_header(ad, ae));
    assertEqualInt(sizeof(data),
        archive_write_data(ad, data, sizeof(data)));
    assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
    archive_entry_free(ae);

    /* Link.  Unset size means this doesn't carry data. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "link2b");
    archive_entry_set_mode(ae, S_IFREG | 0642);
    archive_entry_unset_size(ae);
    archive_entry_copy_hardlink(ae, "link2a");
    assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
    if (r >= ARCHIVE_WARN) {
        assertEqualInt(ARCHIVE_WARN,
            archive_write_data(ad, data, sizeof(data)));
        assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
    }
    archive_entry_free(ae);

    /*
     * Second, try an old-cpio-like approach; a regular file, then
     * another identical one (which has been marked hardlink).
     */

    /* Regular file. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "link3a");
    archive_entry_set_mode(ae, S_IFREG | 0600);
    archive_entry_set_size(ae, sizeof(data));
    assertEqualIntA(ad, 0, archive_write_header(ad, ae));
    assertEqualInt(sizeof(data), archive_write_data(ad, data, sizeof(data)));
    assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
    archive_entry_free(ae);

    /* Link. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "link3b");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    archive_entry_set_size(ae, sizeof(data));
    archive_entry_copy_hardlink(ae, "link3a");
    assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
    if (r > ARCHIVE_WARN) {
        assertEqualInt(sizeof(data),
            archive_write_data(ad, data, sizeof(data)));
        assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
    }
    archive_entry_free(ae);

    /*
     * Finally, try a new-cpio-like approach, where the initial
     * regular file is empty and the hardlink has the data.
     */

    /* Regular file. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "link4a");
    archive_entry_set_mode(ae, S_IFREG | 0600);
    archive_entry_set_size(ae, 0);
    assertEqualIntA(ad, 0, archive_write_header(ad, ae));
#if ARCHIVE_VERSION_NUMBER < 3000000
    assertEqualInt(ARCHIVE_WARN, archive_write_data(ad, data, 1));
#else
    assertEqualInt(-1, archive_write_data(ad, data, 1));
#endif
    assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
    archive_entry_free(ae);

    /* Link. */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "link4b");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    archive_entry_set_size(ae, sizeof(data));
    archive_entry_copy_hardlink(ae, "link4a");
    assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
    if (r > ARCHIVE_FAILED) {
        assertEqualInt(sizeof(data),
            archive_write_data(ad, data, sizeof(data)));
        assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
    }
    archive_entry_free(ae);
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(ad);
#else
    assertEqualInt(0, archive_write_finish(ad));
#endif

    /* Test the entries on disk. */

    /* Test #1 */
    /* If the hardlink was successfully created and the archive
     * doesn't carry data for it, we consider it to be
     * non-authoritive for meta data as well.  This is consistent
     * with GNU tar and BSD pax.  */
    assertIsReg("link1a", 0755 & ~UMASK);
    assertFileSize("link1a", sizeof(data));
    assertFileNLinks("link1a", 2);
    assertIsHardlink("link1a", "link1b");

    /* Test #2: Should produce identical results to test #1 */
    /* Note that marking a hardlink with size = 0 is treated the
     * same as having an unset size.  This is partly for backwards
     * compatibility (we used to not have unset tracking, so
     * relied on size == 0) and partly to match the model used by
     * common file formats that store a size of zero for
     * hardlinks. */
    assertIsReg("link2a", 0755 & ~UMASK);
    assertFileSize("link2a", sizeof(data));
    assertFileNLinks("link2a", 2);
    assertIsHardlink("link2a", "link2b");

    /* Test #3 */
    assertIsReg("link3a", 0755 & ~UMASK);
    assertFileSize("link3a", sizeof(data));
    assertFileNLinks("link3a", 2);
    assertIsHardlink("link3a", "link3b");

    /* Test #4 */
    assertIsReg("link4a", 0755 & ~UMASK);
    assertFileNLinks("link4a", 2);
    assertFileSize("link4a", sizeof(data));
    assertIsHardlink("link4a", "link4b");
#endif
}

--- NEW FILE: test_write_format_cpio.c ---
/*-
 * 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/lib/libarchive/test/test_write_format_cpio.c,v 1.6 2008/12/06 06:02:26 kientzle Exp $");

/* The version stamp macro was introduced after cpio write support. */
#if ARCHIVE_VERSION_NUMBER >= 1009000
static void
test_format(int (*set_format)(struct archive *))
{
    char filedata[64];
    struct archive_entry *ae;
    struct archive *a;
    char *p;
    size_t used;
    size_t buffsize = 1000000;
    char *buff;
    int damaged = 0;

    buff = malloc(buffsize);

    /* Create a new archive in memory. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == (*set_format)(a));
    assertA(0 == archive_write_set_compression_none(a));
    assertA(0 == archive_write_open_memory(a, buff, buffsize, &used));

    /*
     * Write a file to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_mtime(ae, 1, 10);
    assert(1 == archive_entry_mtime(ae));
    assert(10 == archive_entry_mtime_nsec(ae));
    p = strdup("file");
    archive_entry_copy_pathname(ae, p);
    strcpy(p, "XXXX");
    free(p);
    assertEqualString("file", archive_entry_pathname(ae));
    archive_entry_set_mode(ae, S_IFREG | 0755);
    assert((S_IFREG | 0755) == archive_entry_mode(ae));
    archive_entry_set_size(ae, 8);

    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);
    assertA(8 == archive_write_data(a, "12345678", 9));

    /*
     * Write another file to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_mtime(ae, 1, 10);
    assert(1 == archive_entry_mtime(ae));
    assert(10 == archive_entry_mtime_nsec(ae));
    p = strdup("file2");
    archive_entry_copy_pathname(ae, p);
    strcpy(p, "XXXX");
    free(p);
    assertEqualString("file2", archive_entry_pathname(ae));
    archive_entry_set_mode(ae, S_IFREG | 0755);
    assert((S_IFREG | 0755) == archive_entry_mode(ae));
    archive_entry_set_size(ae, 4);

    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);
    assertA(4 == archive_write_data(a, "1234", 5));

    /*
     * Write a directory to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_mtime(ae, 11, 110);
    archive_entry_copy_pathname(ae, "dir");
    archive_entry_set_mode(ae, S_IFDIR | 0755);
    archive_entry_set_size(ae, 512);

    assertA(0 == archive_write_header(a, ae));
    assertEqualInt(0, archive_entry_size(ae));
    archive_entry_free(ae);
    assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9));


    /* Close out the archive. */
    assertA(0 == archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assertA(0 == archive_write_finish(a));
#endif

    /*
     * Damage the second entry to test the search-ahead recovery.
     */
    {
        int i;
        for (i = 80; i < 150; i++) {
            if (memcmp(buff + i, "07070", 5) == 0) {
                damaged = 1;
                buff[i] = 'X';
                break;
            }
        }
    }
    failure("Unable to locate the second header for damage-recovery test.");
    assert(damaged = 1);

    /*
     * Now, read the data back.
     */
    assert((a = archive_read_new()) != NULL);
    assertA(0 == archive_read_support_format_all(a));
    assertA(0 == archive_read_support_compression_all(a));
    assertA(0 == archive_read_open_memory(a, buff, used));

    if (!assertEqualIntA(a, 0, archive_read_next_header(a, &ae))) {
        archive_read_finish(a);
        return;
    }

    assertEqualInt(1, archive_entry_mtime(ae));
    /* Not the same as above: cpio doesn't store hi-res times. */
    assert(0 == archive_entry_mtime_nsec(ae));
    assert(0 == archive_entry_atime(ae));
    assert(0 == archive_entry_ctime(ae));
    assertEqualString("file", archive_entry_pathname(ae));
    assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));
    assertEqualInt(8, archive_entry_size(ae));
    assertA(8 == archive_read_data(a, filedata, 10));
    assert(0 == memcmp(filedata, "12345678", 8));

    /*
     * Read the second file back.
     */
    if (!damaged) {
        assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
        assertEqualInt(1, archive_entry_mtime(ae));
        /* Not the same as above: cpio doesn't store hi-res times. */
        assert(0 == archive_entry_mtime_nsec(ae));
        assert(0 == archive_entry_atime(ae));
        assert(0 == archive_entry_ctime(ae));
        assertEqualString("file2", archive_entry_pathname(ae));
        assert((S_IFREG | 0755) == archive_entry_mode(ae));
        assertEqualInt(4, archive_entry_size(ae));
        assertEqualIntA(a, 4, archive_read_data(a, filedata, 10));
        assert(0 == memcmp(filedata, "1234", 4));
    }

    /*
     * Read the dir entry back.
     */
    assertEqualIntA(a,
        damaged ? ARCHIVE_WARN : ARCHIVE_OK,
        archive_read_next_header(a, &ae));
    assertEqualInt(11, archive_entry_mtime(ae));
    assert(0 == archive_entry_mtime_nsec(ae));
    assert(0 == archive_entry_atime(ae));
    assert(0 == archive_entry_ctime(ae));
    assertEqualString("dir", archive_entry_pathname(ae));
    assertEqualInt((S_IFDIR | 0755), archive_entry_mode(ae));
    assertEqualInt(0, archive_entry_size(ae));
    assertEqualIntA(a, 0, archive_read_data(a, filedata, 10));

    /* Verify the end of the archive. */
    assertEqualIntA(a, 1, archive_read_next_header(a, &ae));
    assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assert(0 == archive_read_finish(a));
#endif

    free(buff);
}
#endif

DEFINE_TEST(test_write_format_cpio)
{
#if ARCHIVE_VERSION_NUMBER >= 1009000
    test_format(archive_write_set_format_cpio);
    test_format(archive_write_set_format_cpio_newc);
#else
    skipping("cpio write support");
#endif
}

--- NEW FILE: test_compat_zip.c ---
/*-
 * 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/lib/libarchive/test/test_compat_zip.c,v 1.3 2008/09/01 05:38:33 kientzle Exp $");

/* Copy this function for each test file and adjust it accordingly. */
static void
test_compat_zip_1(void)
{
    char name[] = "test_compat_zip_1.zip";
    struct archive_entry *ae;
    struct archive *a;
    int r;

    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
    extract_reference_file(name);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240));

    /* Read first entry. */
    assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualString("META-INF/MANIFEST.MF", archive_entry_pathname(ae));

    /* Read second entry. */
    r = archive_read_next_header(a, &ae);
    if (r != ARCHIVE_OK) {
        if (strcmp(archive_error_string(a),
            "libarchive compiled without deflate support (no libz)") == 0) {
            skipping("Skipping ZIP compression check: %s",
                archive_error_string(a));
            goto finish;
        }
    }
    assertEqualIntA(a, ARCHIVE_OK, r);
    assertEqualString("tmp.class", archive_entry_pathname(ae));

    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));

    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_NONE);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ZIP);

    assertEqualInt(ARCHIVE_OK, archive_read_close(a));
finish:
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
#endif
}


DEFINE_TEST(test_compat_zip)
{
    test_compat_zip_1();
}



--- NEW FILE: test_write_compress_program.c ---
/*-
 * 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/lib/libarchive/test/test_write_compress_program.c,v 1.3 2008/09/01 05:38:33 kientzle Exp $");

char buff[1000000];
char buff2[64];

DEFINE_TEST(test_write_compress_program)
{
#if ARCHIVE_VERSION_NUMBER < 1009000
    skipping("archive_write_set_compress_program()");
#else
    struct archive_entry *ae;
    struct archive *a;
    size_t used;
    int blocksize = 1024;
    int r;

    if (!canGzip()) {
        skipping("Cannot run 'gzip'");
        return;
    }

    /* Create a new archive in memory. */
    /* Write it through an external "gzip" program. */
    assert((a = archive_write_new()) != NULL);
    assertA(0 == archive_write_set_format_ustar(a));
    r = archive_write_set_compression_program(a, "gzip");
    if (r == ARCHIVE_FATAL) {
        skipping("Write compression via external "
            "program unsupported on this platform");
        archive_write_finish(a);
        return;
    }
    assertA(0 == archive_write_set_bytes_per_block(a, blocksize));
    assertA(0 == archive_write_set_bytes_in_last_block(a, blocksize));
    assertA(blocksize == archive_write_get_bytes_in_last_block(a));
    assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));
    assertA(blocksize == archive_write_get_bytes_in_last_block(a));

    /*
     * Write a file to it.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_mtime(ae, 1, 10);
    archive_entry_copy_pathname(ae, "file");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    archive_entry_set_size(ae, 8);

    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);
    assertA(8 == archive_write_data(a, "12345678", 9));

    /* Close out the archive. */
    assertA(0 == archive_write_close(a));
    assertA(0 == archive_write_finish(a));

    /*
     * Now, read the data back through the built-in gzip support.
     */
    assert((a = archive_read_new()) != NULL);
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
    r = archive_read_support_compression_gzip(a);
    /* The compression_gzip() handler will fall back to gunzip
     * automatically, but if we know gunzip isn't available, then
     * skip the rest. */
    if (r != ARCHIVE_OK && !canGunzip()) {
        skipping("No libz and no gunzip program, "
            "unable to verify gzip compression");
        assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
        return;
    }
    assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used));

    if (!assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae))) {
        archive_read_finish(a);
        return;
    }

    assertEqualInt(1, archive_entry_mtime(ae));
    assertEqualInt(0, archive_entry_atime(ae));
    assertEqualInt(0, archive_entry_ctime(ae));
    assertEqualString("file", archive_entry_pathname(ae));
    assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));
    assertEqualInt(8, archive_entry_size(ae));
    assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
    assertEqualMem(buff2, "12345678", 8);

    /* Verify the end of the archive. */
    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
#endif
}

--- NEW FILE: test_read_format_gtar_sparse_1_17_posix01.tar.uu ---
begin 644 test_read_format_gtar_sparse_1_17_posix01.tar
M+B]087A(96%D97)S+C,X-C8Q+W-P87)S90``````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#`P,#`V-#0`,#`P,3<U,``P,#`Q-S4P`#`P,#`P,#`P,C4R
M`#$P-S,S,3`Q,30R`#`Q,S0V-``@>```````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<@`P,```````
M````````````````````````````````````````````````````````````
M```````````````````P,#`P,#`P`#`P,#`P,#``````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````R-R!'3E4N<W!A<G-E+G-I>F4],S$T-3<R.`HR
M-B!'3E4N<W!A<G-E+FYU;6)L;V-K<STS"C(V($=.52YS<&%R<V4N;F%M93US
M<&%R<V4*-3$@1TY5+G-P87)S92YM87`].3DY.3,V+#4Q,BPQ.3DY.#<R+#4Q
M,BPS,30U-S(X+#`*,C`@871I;64],3$Y.#(Y,S8P, at HR,"!C=&EM93TQ,3DX
M,CDS-C`P"@``````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
[...1330 lines suppressed...]
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
/````````````````````
`
end

--- NEW FILE: main.c ---
/*
 * 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,
[...2004 lines suppressed...]
                    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);
}

--- NEW FILE: test_fuzz.c ---
/*-
 * 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/lib/libarchive/test/test_fuzz.c,v 1.1 2008/12/06 07:08:08 kientzle Exp $");

/*
 * This was inspired by an ISO fuzz tester written by Michal Zalewski
 * and posted to the "vulnwatch" mailing list on March 17, 2005:
 *    http://seclists.org/vulnwatch/2005/q1/0088.html
 *
 * This test simply reads each archive image into memory, pokes
 * random values into it and runs it through libarchive.  It tries
 * to damage about 1% of each file and repeats the exercise 100 times
 * with each file.
 *
 * Unlike most other tests, this test does not verify libarchive's
 * responses other than to ensure that libarchive doesn't crash.
 *
 * Due to the deliberately random nature of this test, it may be hard
 * to reproduce failures.  Because this test deliberately attempts to
 * induce crashes, there's little that can be done in the way of
 * post-failure diagnostics.
 */

/* Because this works for any archive, I can just re-use the archives
 * developed for other tests.  I've not included all of the compressed
 * archives here, though; I don't want to spend all of my test time
 * testing zlib and bzlib. */
static const char *
files[] = {
    "test_fuzz_1.iso",
    "test_compat_bzip2_1.tbz",
    "test_compat_gtar_1.tar",
    "test_compat_tar_hardlink_1.tar",
    "test_compat_zip_1.zip",
    "test_read_format_gtar_sparse_1_17_posix10_modified.tar",
    "test_read_format_tar_empty_filename.tar",
    "test_read_format_zip.zip",
    NULL
};

#define UnsupportedCompress(r, a) \
        (r != ARCHIVE_OK && \
         (strcmp(archive_error_string(a), \
            "Unrecognized archive format") == 0 && \
          archive_compression(a) == ARCHIVE_COMPRESSION_NONE))

DEFINE_TEST(test_fuzz)
{
    const char **filep;
    const void *blk;
    size_t blk_size;
    off_t blk_offset;

    for (filep = files; *filep != NULL; ++filep) {
        struct archive_entry *ae;
        struct archive *a;
        char *rawimage, *image;
        size_t size;
        int i;

        extract_reference_file(*filep);
        rawimage = slurpfile(&size, *filep);
        assert(rawimage != NULL);
        image = malloc(size);
        assert(image != NULL);
        srand((unsigned)time(NULL));

        for (i = 0; i < 100; ++i) {
            FILE *f;
            int j, numbytes;

            /* Fuzz < 1% of the bytes in the archive. */
            memcpy(image, rawimage, size);
            numbytes = (int)(rand() % (size / 100));
            for (j = 0; j < numbytes; ++j)
                image[rand() % size] = (char)rand();

            /* Save the messed-up image to a file.
             * If we crash, that file will be useful. */
            f = fopen("after.test.failure.send.this.file."
                "to.libarchive.maintainers.with.system.details", "wb");
            fwrite(image, 1, (size_t)size, f);
            fclose(f);

            assert((a = archive_read_new()) != NULL);
            assertEqualIntA(a, ARCHIVE_OK,
                archive_read_support_compression_all(a));
            assertEqualIntA(a, ARCHIVE_OK,
                archive_read_support_format_all(a));

            if (0 == archive_read_open_memory(a, image, size)) {
                while(0 == archive_read_next_header(a, &ae)) {
                    while (0 == archive_read_data_block(a,
                        &blk, &blk_size, &blk_offset))
                        continue;
                }
                archive_read_close(a);
                archive_read_finish(a);
            }
        }
        free(image);
        free(rawimage);
    }
}



--- NEW FILE: test_tar_large.c ---
/*-
 * 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/lib/libarchive/test/test_tar_large.c,v 1.4 2008/09/01 05:38:33 kientzle Exp $");

#include <errno.h>
#include <stdlib.h>
#include <string.h>

/*
 * This is a somewhat tricky test that verifies the ability to
 * write and read very large entries to tar archives.  It
 * writes entries from 2GB up to 1TB to an archive in memory.
 * The memory storage here carefully avoids actually storing
 * any part of the file bodies, so it runs very quickly and requires
 * very little memory.  If you're willing to wait a few minutes,
 * you should be able to exercise petabyte entries with this code.
 */

/*
 * Each file is built up by duplicating the following block.
 */
static size_t filedatasize;
static void *filedata;

/*
 * We store the archive as blocks of data generated by libarchive,
 * each possibly followed by bytes of file data.
 */
struct memblock {
    struct memblock *next;
    size_t  size;
    void *buff;
    int64_t filebytes;
};

/*
 * The total memory store is just a list of memblocks plus
 * some accounting overhead.
 */
struct memdata {
    int64_t filebytes;
    void *buff;
    struct memblock *first;
    struct memblock *last;
};

/* The following size definitions simplify things below. */
#define KB ((int64_t)1024)
#define MB ((int64_t)1024 * KB)
#define GB ((int64_t)1024 * MB)
#define TB ((int64_t)1024 * GB)

#if ARCHIVE_VERSION_NUMBER < 2000000
static ssize_t  memory_read_skip(struct archive *, void *, size_t request);
#else
static off_t    memory_read_skip(struct archive *, void *, off_t request);
#endif
static ssize_t  memory_read(struct archive *, void *, const void **buff);
static ssize_t  memory_write(struct archive *, void *, const void *, size_t);


static ssize_t
memory_write(struct archive *a, void *_private, const void *buff, size_t size)
{
    struct memdata *private = _private;
    struct memblock *block;

    (void)a;

    /*
     * Since libarchive tries to behave in a zero-copy manner, if
     * you give a pointer to filedata to the library, a pointer
     * into that data will (usually) pop out here.  This way, we
     * can tell the difference between filedata and library header
     * and metadata.
     */
    if ((const char *)filedata <= (const char *)buff
        && (const char *)buff < (const char *)filedata + filedatasize) {
        /* We don't need to store a block of file data. */
        private->last->filebytes += (int64_t)size;
    } else {
        /* Yes, we're assuming the very first write is metadata. */
        /* It's header or metadata, copy and save it. */
        block = (struct memblock *)malloc(sizeof(*block));
        memset(block, 0, sizeof(*block));
        block->size = size;
        block->buff = malloc(size);
        memcpy(block->buff, buff, size);
        if (private->last == NULL) {
            private->first = private->last = block;
        } else {
            private->last->next = block;
            private->last = block;
        }
        block->next = NULL;
    }
    return ((long)size);
}

static ssize_t
memory_read(struct archive *a, void *_private, const void **buff)
{
    struct memdata *private = _private;
    struct memblock *block;
    ssize_t size;

    (void)a;

    free(private->buff);
    private->buff = NULL;
    if (private->first == NULL) {
        private->last = NULL;
        return (ARCHIVE_EOF);
    }
    if (private->filebytes > 0) {
        /*
         * We're returning file bytes, simulate it by
         * passing blocks from the template data.
         */
        if (private->filebytes > (int64_t)filedatasize)
            size = (ssize_t)filedatasize;
        else
            size = (ssize_t)private->filebytes;
        private->filebytes -= size;
        *buff = filedata;
    } else {
        /*
         * We need to get some real data to return.
         */
        block = private->first;
        private->first = block->next;
        size = (ssize_t)block->size;
        if (block->buff != NULL) {
            private->buff = block->buff;
            *buff = block->buff;
        } else {
            private->buff = NULL;
            *buff = filedata;
        }
        private->filebytes = block->filebytes;
        free(block);
    }
    return (size);
}


#if ARCHIVE_VERSION_NUMBER < 2000000
static ssize_t
memory_read_skip(struct archive *a, void *private, size_t skip)
{
    (void)a;  /* UNUSED */
    (void)private; /* UNUSED */
    (void)skip; /* UNUSED */
    return (0);
}
#else
static off_t
memory_read_skip(struct archive *a, void *_private, off_t skip)
{
    struct memdata *private = _private;

    (void)a;

    if (private->first == NULL) {
        private->last = NULL;
        return (0);
    }
    if (private->filebytes > 0) {
        if (private->filebytes < skip)
            skip = (off_t)private->filebytes;
        private->filebytes -= skip;
    } else {
        skip = 0;
    }
    return (skip);
}
#endif

DEFINE_TEST(test_tar_large)
{
    /* The sizes of the entries we're going to generate. */
    static int64_t tests[] = {
        /* Test for 32-bit signed overflow. */
        2 * GB - 1, 2 * GB, 2 * GB + 1,
        /* Test for 32-bit unsigned overflow. */
        4 * GB - 1, 4 * GB, 4 * GB + 1,
        /* 8GB is the "official" max for ustar. */
        8 * GB - 1, 8 * GB, 8 * GB + 1,
        /* Bend ustar a tad and you can get 64GB (12 octal digits). */
        64 * GB - 1, 64 * GB,
        /* And larger entries that require non-ustar extensions. */
        256 * GB, 1 * TB, 0 };
    int i;
    char namebuff[64];
    struct memdata memdata;
    struct archive_entry *ae;
    struct archive *a;
    int64_t  filesize;
    size_t writesize;

    filedatasize = (size_t)(1 * MB);
    filedata = malloc(filedatasize);
    memset(filedata, 0xAA, filedatasize);
    memset(&memdata, 0, sizeof(memdata));

    /*
     * Open an archive for writing.
     */
    a = archive_write_new();
    archive_write_set_format_pax_restricted(a);
    archive_write_set_bytes_per_block(a, 0); /* No buffering. */
    archive_write_open(a, &memdata, NULL, memory_write, NULL);

    /*
     * Write a series of large files to it.
     */
    for (i = 0; tests[i] != 0; i++) {
        assert((ae = archive_entry_new()) != NULL);
        sprintf(namebuff, "file_%d", i);
        archive_entry_copy_pathname(ae, namebuff);
        archive_entry_set_mode(ae, S_IFREG | 0755);
        filesize = tests[i];

        archive_entry_set_size(ae, filesize);

        assertA(0 == archive_write_header(a, ae));
        archive_entry_free(ae);

        /*
         * Write the actual data to the archive.
         */
        while (filesize > 0) {
            writesize = filedatasize;
            if ((int64_t)writesize > filesize)
                writesize = (size_t)filesize;
            assertA((int)writesize
                == archive_write_data(a, filedata, writesize));
            filesize -= writesize;
        }
    }

    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "lastfile");
    archive_entry_set_mode(ae, S_IFREG | 0755);
    assertA(0 == archive_write_header(a, ae));
    archive_entry_free(ae);


    /* Close out the archive. */
    assertA(0 == archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_write_finish(a);
#else
    assertA(0 == archive_write_finish(a));
#endif

    /*
     * Open the same archive for reading.
     */
    a = archive_read_new();
    archive_read_support_format_tar(a);
    archive_read_open2(a, &memdata, NULL,
        memory_read, memory_read_skip, NULL);

    /*
     * Read entries back.
     */
    for (i = 0; tests[i] > 0; i++) {
        assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
        sprintf(namebuff, "file_%d", i);
        assertEqualString(namebuff, archive_entry_pathname(ae));
        assert(tests[i] == archive_entry_size(ae));
    }
    assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
    assertEqualString("lastfile", archive_entry_pathname(ae));

    assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));

    /* Close out the archive. */
    assertA(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
    archive_read_finish(a);
#else
    assertA(0 == archive_read_finish(a));
#endif

    free(memdata.buff);
    free(filedata);
}

--- NEW FILE: test_read_format_isorr_new_bz2.iso.bz2.uu ---
begin 644 test_read_format_isorr_bz2.iso.bz2
M0EIH.3%!629366".K#H``-A__?__>_QUY_^Z/__?X*?OWF8DJU4`)```A2``
M@`_!"-`#[PZUHUSNPI<Z&2(T$C!,U3]4--B`FFGE!ZC!H``(QJ,0PGJ-J'J'
ME,`Q3`E$"-3)ID4\U3]%/4>D``R`-#0```-``:`!ZAH`!B43U!!H````:``!
MH`````````!H<````````````````````R!%(D":GJ/4R:/4-/4/4T&FC1D!
MIDR9`!H:`R#0```>IDPZ"IJ"51(^XL`L)`>(`<*0^$EX#Q>,#L:MV;5JVQV=
M*'5(<F)0D01`PCA0\&``X\Y>F$`SB``7_P at HB`#<M26^J`7]<1:4`MLA4$1`
M&T,`3B%8$6(ME$>N;1`C(A33(41$0!K0 at 8()6IU:$%H"`*U$@ASD4\7 at 4H:M
M/;H$!]NVG>'?XLX(6*(:("IE4D=H`(;^!@D$0)=;MV[0(H(@#JX(V7;!>#$8
MK(42:.-CC&QVZCLE;ZQ+F9`,,8%P%@40:8`*S)0.,C>R!,"*A_,='-,F%*QI
ME-&I>C%@(`28!"8HE!$((`2`R"09F"02"9Q3%\ADPX2<#B(VB6E3DAM8'S14
M!+83_"+C9]4\\#VJ:XJC1BE)&05\OI8\]C"0RD2#IJ,.1,D008)*16AD7$9!
M0HST*KC0&A9T:"F4DRH3",`/4\1=/][@1O?OOM'D;EQ$6KD>_-5C2%&UQ&JK
M4RHJJDN*QQYO3Y/U52T@[C0-ZT:,2E,,*8P2DW"02E(D$,$I(/X`I)=,""-U
M*EVEF0UF2MZMQ>/R>7TDF*_;G8$%BB\&X3 at T@*&<FDPJ65-+V.(01(-T;S*[
M>GL$<13YU4-BQ*4BL9XO*#`22@]T)]S(Q0&1410C#$P`+O;PR(PG>R,J)2/S
MEKA(_ at KQY]83UZ6(JM-P`[<40P*1;U8*97D')9[4=23%Y;HRGO66:_,45O at L
M><RTQ8X1<)*4NK<2MU2K=$YZ5J"BBCD$E+?24,V>R+2=:M&U28';7DOGQ7W0
M?D:EQ\A?`6`TH!PZU.R>:A$PCQ*KV-2Q9H3JA\!TD4!<2-N7L'XT!'R(H^AB
M)^3]JJ#QKK54V!EZQT at YP^Q5&+?#(K%)AH&H8Z%]!@T.OE`]>32]-%Q\QB#+
M\', at 44"HRUPP9+MYL8.>\Q[@6&<,5!MNU%9L(KK&9C[8\DR^CY9=]ED*HU+J
M,P9Q=RA4U'R+M#7B\,S_$=MBFS*`KD%*UQRE+"S-9<I,21_X'2#=.`^1`N;8
M'5/'6)5"#L*F/MTAAJ^EJS9+Y._D>!=DZ2419IV`S`<T(0U!S at LXGRV=A=2O
M8"Q1A\J5X-SKA:V]%<8*7L.:$R^MS9P,_K!."^&0YA2-:R'P\ANA(I4"_0:Z
HV(<0^$"YBD)"9%)`@D"(`V7/!UH`<DYY9,HRSH&N+N2*<*$@P1U8=```
`
end

--- NEW FILE: test_read_format_pax_bz2.c ---
/*-
 * 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/lib/libarchive/test/test_read_format_pax_bz2.c,v 1.2 2008/09/01 05:38:33 kientzle Exp $");

static unsigned char archive[] = {
'B','Z','h','9','1','A','Y','&','S','Y',152,180,30,185,0,0,140,127,176,212,
144,0,' ','@',1,255,226,8,'d','H',' ',238,'/',159,'@',0,16,4,'@',0,8,'0',
0,216,'A',164,167,147,'Q',147,'!',180,'#',0,'L',153,162,'i',181,'?','P',192,
26,'h','h',209,136,200,6,128,13,12,18,132,202,'5','O',209,'5','=',26,'2',
154,7,168,12,2,'d',252,13,254,29,'4',247,181,'l','T','i',130,5,195,1,'2',
'@',146,18,251,245,'c','J',130,224,172,'$','l','4',235,170,186,'c','1',255,
179,'K',188,136,18,208,152,192,149,153,10,'{','|','0','8',166,3,6,9,128,172,
'(',164,220,244,149,6,' ',243,212,'B',25,17,'6',237,13,'I',152,'L',129,209,
'G','J','<',137,'Y',16,'b',21,18,'a','Y','l','t','r',160,128,147,'l','f',
'~',219,206,'=','?','S',233,'3',251,'L','~',17,176,169,'%',23,'_',225,'M',
'C','u','k',218,8,'q',216,'(',22,235,'K',131,136,146,136,147,202,0,158,134,
'F',23,160,184,'s','0','a',246,'*','P',7,2,238,'H',167,10,18,19,22,131,215,
' '};

DEFINE_TEST(test_read_format_pax_bz2)
{
    struct archive_entry *ae;
    struct archive *a;
    int r;

    assert((a = archive_read_new()) != NULL);
    r = archive_read_support_compression_bzip2(a);
    if (r != ARCHIVE_OK) {
        archive_read_close(a);
        skipping("Bzip2 unavailable");
        return;
    }
    assertEqualIntA(a,ARCHIVE_OK, archive_read_support_format_all(a));
    assertEqualIntA(a,ARCHIVE_OK,
        archive_read_open_memory(a, archive, sizeof(archive)));
    assertEqualIntA(a,ARCHIVE_OK, archive_read_next_header(a, &ae));
    assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_BZIP2);
    assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE);
    assertEqualIntA(a,ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}





More information about the Cmake-commits mailing list