static int
header_bin_be(struct archive_read *a, struct cpio *cpio,
    struct archive_entry *entry, size_t *namelength, size_t *name_pad)
{
	const void *h;
	const unsigned char *header;

	a->archive.archive_format = ARCHIVE_FORMAT_CPIO_BIN_BE;
	a->archive.archive_format_name = "cpio (big-endian binary)";

	/* Read fixed-size portion of header. */
	h = __archive_read_ahead(a, bin_header_size, NULL);
	if (h == NULL)
	    return (ARCHIVE_FATAL);

	/* Parse out binary fields. */
	header = (const unsigned char *)h;

	archive_entry_set_dev(entry, header[bin_dev_offset] * 256 + header[bin_dev_offset + 1]);
	archive_entry_set_ino(entry, header[bin_ino_offset] * 256 + header[bin_ino_offset + 1]);
	archive_entry_set_mode(entry, header[bin_mode_offset] * 256 + header[bin_mode_offset + 1]);
	archive_entry_set_uid(entry, header[bin_uid_offset] * 256 + header[bin_uid_offset + 1]);
	archive_entry_set_gid(entry, header[bin_gid_offset] * 256 + header[bin_gid_offset + 1]);
	archive_entry_set_nlink(entry, header[bin_nlink_offset] * 256 + header[bin_nlink_offset + 1]);
	archive_entry_set_rdev(entry, header[bin_rdev_offset] * 256 + header[bin_rdev_offset + 1]);
	archive_entry_set_mtime(entry, be4(header + bin_mtime_offset), 0);
	*namelength = header[bin_namesize_offset] * 256 + header[bin_namesize_offset + 1];
	*name_pad = *namelength & 1; /* Pad to even. */

	cpio->entry_bytes_remaining = be4(header + bin_filesize_offset);
	archive_entry_set_size(entry, cpio->entry_bytes_remaining);
	cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */
	    __archive_read_consume(a, bin_header_size);
	return (ARCHIVE_OK);
}
static int
header_bin_be(struct archive_read *a, struct cpio *cpio,
    struct archive_entry *entry, size_t *namelength, size_t *name_pad)
{
    const void *h;
    const struct cpio_bin_header *header;

    a->archive.archive_format = ARCHIVE_FORMAT_CPIO_BIN_BE;
    a->archive.archive_format_name = "cpio (big-endian binary)";

    /* Read fixed-size portion of header. */
    h = __archive_read_ahead(a, sizeof(struct cpio_bin_header), NULL);
    if (h == NULL)
        return (ARCHIVE_FATAL);
    __archive_read_consume(a, sizeof(struct cpio_bin_header));

    /* Parse out binary fields. */
    header = (const struct cpio_bin_header *)h;
    archive_entry_set_dev(entry, header->c_dev[0] * 256 + header->c_dev[1]);
    archive_entry_set_ino(entry, header->c_ino[0] * 256 + header->c_ino[1]);
    archive_entry_set_mode(entry, header->c_mode[0] * 256 + header->c_mode[1]);
    archive_entry_set_uid(entry, header->c_uid[0] * 256 + header->c_uid[1]);
    archive_entry_set_gid(entry, header->c_gid[0] * 256 + header->c_gid[1]);
    archive_entry_set_nlink(entry, header->c_nlink[0] * 256 + header->c_nlink[1]);
    archive_entry_set_rdev(entry, header->c_rdev[0] * 256 + header->c_rdev[1]);
    archive_entry_set_mtime(entry, be4(header->c_mtime), 0);
    *namelength = header->c_namesize[0] * 256 + header->c_namesize[1];
    *name_pad = *namelength & 1; /* Pad to even. */

    cpio->entry_bytes_remaining = be4(header->c_filesize);
    archive_entry_set_size(entry, cpio->entry_bytes_remaining);
    cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */
    return (ARCHIVE_OK);
}
static void
verify_zip_filesize(uint64_t size, int expected)
{
	struct archive *a;
	struct archive_entry *ae;
	char buff[256];
	size_t used;

	/* Zip format: Create a new archive in memory. */
	assert((a = archive_write_new()) != NULL);
	assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a));
	/* Disable Zip64 extensions. */
	assertEqualIntA(a, ARCHIVE_OK,
	    archive_write_set_format_option(a, "zip", "zip64", NULL));
	assertEqualIntA(a, ARCHIVE_OK,
	    archive_write_open_memory(a, buff, sizeof(buff), &used));

	assert((ae = archive_entry_new()) != NULL);
	archive_entry_set_pathname(ae, "test");
	archive_entry_set_mode(ae, AE_IFREG | 0644);
	archive_entry_set_size(ae, size);
	assertEqualInt(expected, archive_write_header(a, ae));

	archive_entry_free(ae);

	/* Don't actually write 4GB! ;-) */
	assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a));
}
static int
header_odc(struct archive_read *a, struct cpio *cpio,
    struct archive_entry *entry, size_t *namelength, size_t *name_pad)
{
	const void *h;
	int r;
	const char *header;

	a->archive.archive_format = ARCHIVE_FORMAT_CPIO_POSIX;
	a->archive.archive_format_name = "POSIX octet-oriented cpio";

	/* Find the start of the next header. */
	r = find_odc_header(a);
	if (r < ARCHIVE_WARN)
		return (r);

	if (a->archive.archive_format == ARCHIVE_FORMAT_CPIO_AFIO_LARGE) {
		int r2 = (header_afiol(a, cpio, entry, namelength, name_pad));
		if (r2 == ARCHIVE_OK)
			return (r);
		else
			return (r2);
	}

	/* Read fixed-size portion of header. */
	h = __archive_read_ahead(a, odc_header_size, NULL);
	if (h == NULL)
	    return (ARCHIVE_FATAL);

	/* Parse out octal fields. */
	header = (const char *)h;

	archive_entry_set_dev(entry, 
		(dev_t)atol8(header + odc_dev_offset, odc_dev_size));
	archive_entry_set_ino(entry, atol8(header + odc_ino_offset, odc_ino_size));
	archive_entry_set_mode(entry, 
		(mode_t)atol8(header + odc_mode_offset, odc_mode_size));
	archive_entry_set_uid(entry, atol8(header + odc_uid_offset, odc_uid_size));
	archive_entry_set_gid(entry, atol8(header + odc_gid_offset, odc_gid_size));
	archive_entry_set_nlink(entry, 
		(unsigned int)atol8(header + odc_nlink_offset, odc_nlink_size));
	archive_entry_set_rdev(entry,
		(dev_t)atol8(header + odc_rdev_offset, odc_rdev_size));
	archive_entry_set_mtime(entry, atol8(header + odc_mtime_offset, odc_mtime_size), 0);
	*namelength = (size_t)atol8(header + odc_namesize_offset, odc_namesize_size);
	*name_pad = 0; /* No padding of filename. */

	/*
	 * Note: entry_bytes_remaining is at least 64 bits and
	 * therefore guaranteed to be big enough for a 33-bit file
	 * size.
	 */
	cpio->entry_bytes_remaining =
	    atol8(header + odc_filesize_offset, odc_filesize_size);
	archive_entry_set_size(entry, cpio->entry_bytes_remaining);
	cpio->entry_padding = 0;
	__archive_read_consume(a, odc_header_size);
	return (r);
}
static int
header_newc(struct archive_read *a, struct cpio *cpio,
    struct archive_entry *entry, size_t *namelength, size_t *name_pad)
{
	const void *h;
	const struct cpio_newc_header *header;
	size_t bytes;
	int r;

	r = find_newc_header(a);
	if (r < ARCHIVE_WARN)
		return (r);

	/* Read fixed-size portion of header. */
	bytes = (a->decompressor->read_ahead)(a, &h, sizeof(struct cpio_newc_header));
	if (bytes < sizeof(struct cpio_newc_header))
	    return (ARCHIVE_FATAL);
	(a->decompressor->consume)(a, sizeof(struct cpio_newc_header));

	/* Parse out hex fields. */
	header = (const struct cpio_newc_header *)h;

	if (memcmp(header->c_magic, "070701", 6) == 0) {
		a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_NOCRC;
		a->archive.archive_format_name = "ASCII cpio (SVR4 with no CRC)";
	} else if (memcmp(header->c_magic, "070702", 6) == 0) {
		a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_CRC;
		a->archive.archive_format_name = "ASCII cpio (SVR4 with CRC)";
	} else {
		/* TODO: Abort here? */
	}

	archive_entry_set_devmajor(entry, atol16(header->c_devmajor, sizeof(header->c_devmajor)));
	archive_entry_set_devminor(entry, atol16(header->c_devminor, sizeof(header->c_devminor)));
	archive_entry_set_ino(entry, atol16(header->c_ino, sizeof(header->c_ino)));
	archive_entry_set_mode(entry, atol16(header->c_mode, sizeof(header->c_mode)));
	archive_entry_set_uid(entry, atol16(header->c_uid, sizeof(header->c_uid)));
	archive_entry_set_gid(entry, atol16(header->c_gid, sizeof(header->c_gid)));
	archive_entry_set_nlink(entry, atol16(header->c_nlink, sizeof(header->c_nlink)));
	archive_entry_set_rdevmajor(entry, atol16(header->c_rdevmajor, sizeof(header->c_rdevmajor)));
	archive_entry_set_rdevminor(entry, atol16(header->c_rdevminor, sizeof(header->c_rdevminor)));
	archive_entry_set_mtime(entry, atol16(header->c_mtime, sizeof(header->c_mtime)), 0);
	*namelength = atol16(header->c_namesize, sizeof(header->c_namesize));
	/* Pad name to 2 more than a multiple of 4. */
	*name_pad = (2 - *namelength) & 3;

	/*
	 * Note: entry_bytes_remaining is at least 64 bits and
	 * therefore guaranteed to be big enough for a 33-bit file
	 * size.
	 */
	cpio->entry_bytes_remaining =
	    atol16(header->c_filesize, sizeof(header->c_filesize));
	archive_entry_set_size(entry, cpio->entry_bytes_remaining);
	/* Pad file contents to a multiple of 4. */
	cpio->entry_padding = 3 & -cpio->entry_bytes_remaining;
	return (r);
}
Beispiel #6
0
static int ar_entry_mode(lua_State *L) {
    struct archive_entry* self = *ar_entry_check(L, 1);
    int is_set;
    if ( NULL == self ) return 0;

    is_set = ( lua_gettop(L) == 2 );
    lua_pushnumber(L, archive_entry_mode(self));
    if ( is_set ) {
        __LA_MODE_T mode = lua_tonumber(L, 2);
        archive_entry_set_mode(self, mode);
    }
    return 1;
}
static int
header_odc(struct archive_read *a, struct cpio *cpio,
    struct archive_entry *entry, size_t *namelength, size_t *name_pad)
{
	const void *h;
	int r;
	const struct cpio_odc_header *header;
	size_t bytes;

	a->archive.archive_format = ARCHIVE_FORMAT_CPIO_POSIX;
	a->archive.archive_format_name = "POSIX octet-oriented cpio";

	/* Find the start of the next header. */
	r = find_odc_header(a);
	if (r < ARCHIVE_WARN)
		return (r);

	/* Read fixed-size portion of header. */
	bytes = (a->decompressor->read_ahead)(a, &h, sizeof(struct cpio_odc_header));
	if (bytes < sizeof(struct cpio_odc_header))
	    return (ARCHIVE_FATAL);
	(a->decompressor->consume)(a, sizeof(struct cpio_odc_header));

	/* Parse out octal fields. */
	header = (const struct cpio_odc_header *)h;

	archive_entry_set_dev(entry, atol8(header->c_dev, sizeof(header->c_dev)));
	archive_entry_set_ino(entry, atol8(header->c_ino, sizeof(header->c_ino)));
	archive_entry_set_mode(entry, atol8(header->c_mode, sizeof(header->c_mode)));
	archive_entry_set_uid(entry, atol8(header->c_uid, sizeof(header->c_uid)));
	archive_entry_set_gid(entry, atol8(header->c_gid, sizeof(header->c_gid)));
	archive_entry_set_nlink(entry, atol8(header->c_nlink, sizeof(header->c_nlink)));
	archive_entry_set_rdev(entry, atol8(header->c_rdev, sizeof(header->c_rdev)));
	archive_entry_set_mtime(entry, atol8(header->c_mtime, sizeof(header->c_mtime)), 0);
	*namelength = atol8(header->c_namesize, sizeof(header->c_namesize));
	*name_pad = 0; /* No padding of filename. */

	/*
	 * Note: entry_bytes_remaining is at least 64 bits and
	 * therefore guaranteed to be big enough for a 33-bit file
	 * size.
	 */
	cpio->entry_bytes_remaining =
	    atol8(header->c_filesize, sizeof(header->c_filesize));
	archive_entry_set_size(entry, cpio->entry_bytes_remaining);
	cpio->entry_padding = 0;
	return (r);
}
Beispiel #8
0
int ar_entry(lua_State *L) {
    struct archive_entry** self_ref = (struct archive_entry**)
        lua_newuserdata(L, sizeof(struct archive_entry*)); // ..., {ud}
    *self_ref = NULL;
    luaL_getmetatable(L, AR_ENTRY); // ..., {ud}, {meta}
    lua_setmetatable(L, -2); // ..., {ud}
    __ref_count++;
    *self_ref = archive_entry_new();

    if ( lua_istable(L, 1) ) {
        int mt;
        // If given a sourcepath, copy stat buffer from there:
        lua_pushliteral(L, "sourcepath"); // ..., {ud}, "sourcepath"
        lua_rawget(L, 1); // ..., {ud}, src
        if ( lua_isstring(L, -1) ) {
            struct stat sb;
#ifdef _MSC_VER
            stat(lua_tostring(L, -1), &sb);
#else
            lstat(lua_tostring(L, -1), &sb);
#endif
            archive_entry_copy_stat(*self_ref, &sb);
        } else {
            // Give a reasonable default mode:
            archive_entry_set_mode(*self_ref, S_IFREG);
        }
        lua_pop(L, 1); // ... {ud}
        /* XXX: optimized away by assert */
        mt = lua_getmetatable(L, -1); // ..., {ud}, {meta}
        assert(mt != 0);

        // Iterate over the table and call the method with that name
        lua_pushnil(L); // ..., {ud}, {meta}, nil
        while (lua_next(L, 1) != 0) { // ..., {ud}, {meta}, key, value
            lua_pushvalue(L, -2); // ..., {ud}, {meta}, key, value, key
            lua_gettable(L, -4); // ..., {ud}, {meta}, key, value, func
            if ( lua_isnil(L, -1) ) {
                err("InvalidArgument: '%s' is not a valid field", lua_tostring(L, -3));
            }
            lua_pushvalue(L, -5); // ..., {ud}, {meta}, key, value, func, {ud}
            lua_pushvalue(L, -3); // ..., {ud}, {meta}, key, value, func, {ud}, value
            lua_call(L, 2, 0); // ..., {ud}, {meta}, key, value
            lua_pop(L, 1);     // ..., {ud}, {meta}, key
        } // ..., {ud}, {meta}
        lua_pop(L, 1);
    }
    return 1;
}
/*
 * Check that an ISO 9660 image is correctly created.
 */
static void
add_entry(struct archive *a, const char *fname, const char *sym)
{
	struct archive_entry *ae;

	assert((ae = archive_entry_new()) != NULL);
	archive_entry_set_birthtime(ae, 2, 20);
	archive_entry_set_atime(ae, 3, 30);
	archive_entry_set_ctime(ae, 4, 40);
	archive_entry_set_mtime(ae, 5, 50);
	archive_entry_copy_pathname(ae, fname);
	if (sym != NULL)
		archive_entry_set_symlink(ae, sym);
	archive_entry_set_mode(ae, S_IFREG | 0555);
	archive_entry_set_size(ae, 0);
	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
	archive_entry_free(ae);
}
Beispiel #10
0
void
archive_entry_copy_stat(struct archive_entry *entry, const struct stat *st)
{
#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
	archive_entry_set_atime(entry, st->st_atime, st->st_atimespec.tv_nsec);
	archive_entry_set_ctime(entry, st->st_ctime, st->st_ctimespec.tv_nsec);
	archive_entry_set_mtime(entry, st->st_mtime, st->st_mtimespec.tv_nsec);
#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
	archive_entry_set_atime(entry, st->st_atime, st->st_atim.tv_nsec);
	archive_entry_set_ctime(entry, st->st_ctime, st->st_ctim.tv_nsec);
	archive_entry_set_mtime(entry, st->st_mtime, st->st_mtim.tv_nsec);
#elif HAVE_STRUCT_STAT_ST_MTIME_N
	archive_entry_set_atime(entry, st->st_atime, st->st_atime_n);
	archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_n);
	archive_entry_set_mtime(entry, st->st_mtime, st->st_mtime_n);
#elif HAVE_STRUCT_STAT_ST_UMTIME
	archive_entry_set_atime(entry, st->st_atime, st->st_uatime * 1000);
	archive_entry_set_ctime(entry, st->st_ctime, st->st_uctime * 1000);
	archive_entry_set_mtime(entry, st->st_mtime, st->st_umtime * 1000);
#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
	archive_entry_set_atime(entry, st->st_atime, st->st_atime_usec * 1000);
	archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_usec * 1000);
	archive_entry_set_mtime(entry, st->st_mtime, st->st_mtime_usec * 1000);
#else
	archive_entry_set_atime(entry, st->st_atime, 0);
	archive_entry_set_ctime(entry, st->st_ctime, 0);
	archive_entry_set_mtime(entry, st->st_mtime, 0);
#endif
#if HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC
	archive_entry_set_birthtime(entry, st->st_birthtime, st->st_birthtimespec.tv_nsec);
#elif HAVE_STRUCT_STAT_ST_BIRTHTIME
	archive_entry_set_birthtime(entry, st->st_birthtime, 0);
#else
	archive_entry_unset_birthtime(entry);
#endif
	archive_entry_set_dev(entry, st->st_dev);
	archive_entry_set_gid(entry, st->st_gid);
	archive_entry_set_uid(entry, st->st_uid);
	archive_entry_set_ino(entry, st->st_ino);
	archive_entry_set_nlink(entry, st->st_nlink);
	archive_entry_set_rdev(entry, st->st_rdev);
	archive_entry_set_size(entry, st->st_size);
	archive_entry_set_mode(entry, st->st_mode);
}
/*
 * NOTE: if a filename suffix is ".z", it is the file gziped by afio.
 * it would be nice that we can show uncompressed file size and we can
 * uncompressed file contents automatically, unfortunately we have nothing
 * to get a uncompressed file size while reading each header. It means
 * we also cannot uncompress file contents under our framework.
 */
static int
header_afiol(struct archive_read *a, struct cpio *cpio,
    struct archive_entry *entry, size_t *namelength, size_t *name_pad)
{
	const void *h;
	const char *header;

	a->archive.archive_format = ARCHIVE_FORMAT_CPIO_AFIO_LARGE;
	a->archive.archive_format_name = "afio large ASCII";

	/* Read fixed-size portion of header. */
	h = __archive_read_ahead(a, afiol_header_size, NULL);
	if (h == NULL)
	    return (ARCHIVE_FATAL);

	/* Parse out octal fields. */
	header = (const char *)h;

	archive_entry_set_dev(entry, 
		(dev_t)atol16(header + afiol_dev_offset, afiol_dev_size));
	archive_entry_set_ino(entry, atol16(header + afiol_ino_offset, afiol_ino_size));
	archive_entry_set_mode(entry,
		(mode_t)atol8(header + afiol_mode_offset, afiol_mode_size));
	archive_entry_set_uid(entry, atol16(header + afiol_uid_offset, afiol_uid_size));
	archive_entry_set_gid(entry, atol16(header + afiol_gid_offset, afiol_gid_size));
	archive_entry_set_nlink(entry,
		(unsigned int)atol16(header + afiol_nlink_offset, afiol_nlink_size));
	archive_entry_set_rdev(entry,
		(dev_t)atol16(header + afiol_rdev_offset, afiol_rdev_size));
	archive_entry_set_mtime(entry, atol16(header + afiol_mtime_offset, afiol_mtime_size), 0);
	*namelength = (size_t)atol16(header + afiol_namesize_offset, afiol_namesize_size);
	*name_pad = 0; /* No padding of filename. */

	cpio->entry_bytes_remaining =
	    atol16(header + afiol_filesize_offset, afiol_filesize_size);
	archive_entry_set_size(entry, cpio->entry_bytes_remaining);
	cpio->entry_padding = 0;
	__archive_read_consume(a, afiol_header_size);
	return (ARCHIVE_OK);
}
static int
ar_parse_common_header(struct ar *ar, struct archive_entry *entry,
    const char *h)
{
	uint64_t n;

	/* Copy remaining header */
	archive_entry_set_mtime(entry,
	    (time_t)ar_atol10(h + AR_date_offset, AR_date_size), 0L);
	archive_entry_set_uid(entry,
	    (uid_t)ar_atol10(h + AR_uid_offset, AR_uid_size));
	archive_entry_set_gid(entry,
	    (gid_t)ar_atol10(h + AR_gid_offset, AR_gid_size));
	archive_entry_set_mode(entry,
	    (mode_t)ar_atol8(h + AR_mode_offset, AR_mode_size));
	n = ar_atol10(h + AR_size_offset, AR_size_size);

	ar->entry_offset = 0;
	ar->entry_padding = n % 2;
	archive_entry_set_size(entry, n);
	ar->entry_bytes_remaining = n;
	return (ARCHIVE_OK);
}
static int
header_bin_le(struct archive_read *a, struct cpio *cpio,
    struct archive_entry *entry, size_t *namelength, size_t *name_pad)
{
	const void *h;
	const struct cpio_bin_header *header;
	size_t bytes;

	a->archive.archive_format = ARCHIVE_FORMAT_CPIO_BIN_LE;
	a->archive.archive_format_name = "cpio (little-endian binary)";

	/* Read fixed-size portion of header. */
	bytes = (a->decompressor->read_ahead)(a, &h, sizeof(struct cpio_bin_header));
	if (bytes < sizeof(struct cpio_bin_header))
	    return (ARCHIVE_FATAL);
	(a->decompressor->consume)(a, sizeof(struct cpio_bin_header));

	/* Parse out binary fields. */
	header = (const struct cpio_bin_header *)h;

	archive_entry_set_dev(entry, header->c_dev[0] + header->c_dev[1] * 256);
	archive_entry_set_ino(entry, header->c_ino[0] + header->c_ino[1] * 256);
	archive_entry_set_mode(entry, header->c_mode[0] + header->c_mode[1] * 256);
	archive_entry_set_uid(entry, header->c_uid[0] + header->c_uid[1] * 256);
	archive_entry_set_gid(entry, header->c_gid[0] + header->c_gid[1] * 256);
	archive_entry_set_nlink(entry, header->c_nlink[0] + header->c_nlink[1] * 256);
	archive_entry_set_rdev(entry, header->c_rdev[0] + header->c_rdev[1] * 256);
	archive_entry_set_mtime(entry, le4(header->c_mtime), 0);
	*namelength = header->c_namesize[0] + header->c_namesize[1] * 256;
	*name_pad = *namelength & 1; /* Pad to even. */

	cpio->entry_bytes_remaining = le4(header->c_filesize);
	archive_entry_set_size(entry, cpio->entry_bytes_remaining);
	cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */
	return (ARCHIVE_OK);
}
Beispiel #14
0
static void
test_basic2(const char *compression_type)
{
	char filedata[64];
	struct archive_entry *ae;
	struct archive *a;
	size_t used;
	size_t buffsize = 1000;
	char *buff;

	buff = malloc(buffsize);

	/* Create a new archive in memory. */
	assert((a = archive_write_new()) != NULL);
	assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_7zip(a));
	if (compression_type != NULL &&
	    ARCHIVE_OK != archive_write_set_format_option(a, "7zip",
	    "compression", compression_type)) {
		skipping("%s writing not fully supported on this platform",
		   compression_type);
		assertEqualInt(ARCHIVE_OK, archive_write_free(a));
		free(buff);
		return;
	}
	assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_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, 100);
	assertEqualInt(1, archive_entry_mtime(ae));
	assertEqualInt(100, archive_entry_mtime_nsec(ae));
	archive_entry_copy_pathname(ae, "file");
	assertEqualString("file", archive_entry_pathname(ae));
	archive_entry_set_mode(ae, AE_IFREG | 0755);
	assertEqualInt((AE_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, AE_IFREG | 0755);
	assertEqualInt((AE_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, 100);
	archive_entry_copy_pathname(ae, "dir");
	archive_entry_set_mode(ae, AE_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));

	/*
	 * Write a sub directory to it.
	 */
	assert((ae = archive_entry_new()) != NULL);
	archive_entry_set_mtime(ae, 11, 200);
	archive_entry_copy_pathname(ae, "dir/subdir");
	archive_entry_set_mode(ae, AE_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));

	/*
	 * Write a sub sub-directory to it.
	 */
	assert((ae = archive_entry_new()) != NULL);
	archive_entry_set_mtime(ae, 11, 300);
	archive_entry_copy_pathname(ae, "dir/subdir/subdir");
	archive_entry_set_mode(ae, AE_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_free(a));

	/* Verify the initial header. */
	assertEqualMem(buff, "\x37\x7a\xbc\xaf\x27\x1c\x00\x03", 8);

	/*
	 * Now, read the data back.
	 */
	/* With the test memory reader -- seeking mode. */
	assert((a = archive_read_new()) != NULL);
	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
	assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7));

	/*
	 * Read and verify first file.
	 */
	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
	assertEqualInt(1, archive_entry_mtime(ae));
	assertEqualInt(100, archive_entry_mtime_nsec(ae));
	assertEqualInt(0, archive_entry_atime(ae));
	assertEqualInt(0, archive_entry_ctime(ae));
	assertEqualString("file", archive_entry_pathname(ae));
	assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae));
	assertEqualInt(8, archive_entry_size(ae));
	assertEqualIntA(a, 8,
	    archive_read_data(a, filedata, sizeof(filedata)));
	assertEqualMem(filedata, "12345678", 8);


	/*
	 * Read the second file back.
	 */
	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("file2", archive_entry_pathname(ae));
	assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae));
	assertEqualInt(4, archive_entry_size(ae));
	assertEqualIntA(a, 4,
	    archive_read_data(a, filedata, sizeof(filedata)));
	assertEqualMem(filedata, "1234", 4);

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

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

	/*
	 * Read the dir entry back.
	 */
	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
	assertEqualInt(11, archive_entry_mtime(ae));
	assertEqualInt(100, archive_entry_mtime_nsec(ae));
	assertEqualInt(0, archive_entry_atime(ae));
	assertEqualInt(0, archive_entry_ctime(ae));
	assertEqualString("dir/", archive_entry_pathname(ae));
	assertEqualInt(AE_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));

	/* Verify archive format. */
	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
	assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a));

	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
	assertEqualInt(ARCHIVE_OK, archive_read_free(a));

	free(buff);
}
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
}
Beispiel #16
0
/*
 * 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);
}
static void
test_filter_by_name(const char *filter_name, int filter_code,
    int (*can_filter_prog)(void))
{
	struct archive_entry *ae;
	struct archive *a;
	size_t used;
	size_t buffsize = 1024 * 128;
	char *buff;
	int r;

	assert((buff = malloc(buffsize)) != NULL);
	if (buff == NULL)
		return;

	/* Create a new archive in memory. */
	assert((a = archive_write_new()) != NULL);
	assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
	r = archive_write_add_filter_by_name(a, filter_name);
	if (r == ARCHIVE_WARN) {
		if (!can_filter_prog()) {
			skipping("%s filter not suported on this platform",
			    filter_name);
			assertEqualInt(ARCHIVE_OK, archive_write_free(a));
			free(buff);
			return;
		}
	} else if (r == ARCHIVE_FATAL &&
	    (strcmp(archive_error_string(a),
		   "lzma compression not supported on this platform") == 0 ||
	     strcmp(archive_error_string(a),
		   "xz compression not supported on this platform") == 0)) {
		skipping("%s filter not suported on this platform", filter_name);
		assertEqualInt(ARCHIVE_OK, archive_write_free(a));
		free(buff);
		return;
	} else {
		if (!assertEqualIntA(a, ARCHIVE_OK, r)) {
			assertEqualInt(ARCHIVE_OK, archive_write_free(a));
			free(buff);
			return;
		}
	}
	assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 10));
	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, 0);
	assertEqualInt(1, archive_entry_mtime(ae));
	archive_entry_set_ctime(ae, 1, 0);
	assertEqualInt(1, archive_entry_ctime(ae));
	archive_entry_set_atime(ae, 1, 0);
	assertEqualInt(1, archive_entry_atime(ae));
	archive_entry_copy_pathname(ae, "file");
	assertEqualString("file", archive_entry_pathname(ae));
	archive_entry_set_mode(ae, AE_IFREG | 0755);
	assertEqualInt((AE_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", 8));

	/* Close out the archive. */
	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
	assertEqualInt(ARCHIVE_OK, archive_write_free(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_filter_all(a));
	assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used));

	/*
	 * Read and verify the file.
	 */
	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
	assertEqualInt(1, archive_entry_mtime(ae));
	assertEqualString("file", archive_entry_pathname(ae));
	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
	assertEqualInt(8, archive_entry_size(ae));

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

	/* Verify archive format. */
	assertEqualIntA(a, filter_code, archive_filter_code(a, 0));
	assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a));

	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
	free(buff);
}
static int
archive_read_format_iso9660_read_header(struct archive_read *a,
    struct archive_entry *entry)
{
	struct iso9660 *iso9660;
	struct file_info *file;
	ssize_t bytes_read;
	int r;

	iso9660 = (struct iso9660 *)(a->format->data);

	if (!a->archive.archive_format) {
		a->archive.archive_format = ARCHIVE_FORMAT_ISO9660;
		a->archive.archive_format_name = "ISO9660";
	}

	/* Get the next entry that appears after the current offset. */
	r = next_entry_seek(a, iso9660, &file);
	if (r != ARCHIVE_OK)
		return (r);

	iso9660->entry_bytes_remaining = file->size;
	iso9660->entry_sparse_offset = 0; /* Offset for sparse-file-aware clients. */

	/* Set up the entry structure with information about this entry. */
	archive_entry_set_mode(entry, file->mode);
	archive_entry_set_uid(entry, file->uid);
	archive_entry_set_gid(entry, file->gid);
	archive_entry_set_nlink(entry, file->nlinks);
	archive_entry_set_ino(entry, file->inode);
	archive_entry_set_mtime(entry, file->mtime, 0);
	archive_entry_set_ctime(entry, file->ctime, 0);
	archive_entry_set_atime(entry, file->atime, 0);
	archive_entry_set_size(entry, iso9660->entry_bytes_remaining);
	archive_string_empty(&iso9660->pathname);
	archive_entry_set_pathname(entry,
	    build_pathname(&iso9660->pathname, file));
	if (file->symlink.s != NULL)
		archive_entry_copy_symlink(entry, file->symlink.s);

	/* If this entry points to the same data as the previous
	 * entry, convert this into a hardlink to that entry.
	 * But don't bother for zero-length files. */
	if (file->offset == iso9660->previous_offset
	    && file->size == iso9660->previous_size
	    && file->size > 0) {
		archive_entry_set_hardlink(entry,
		    iso9660->previous_pathname.s);
		iso9660->entry_bytes_remaining = 0;
		iso9660->entry_sparse_offset = 0;
		release_file(iso9660, file);
		return (ARCHIVE_OK);
	}

	/* If the offset is before our current position, we can't
	 * seek backwards to extract it, so issue a warning. */
	if (file->offset < iso9660->current_position) {
		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
		    "Ignoring out-of-order file");
		iso9660->entry_bytes_remaining = 0;
		iso9660->entry_sparse_offset = 0;
		release_file(iso9660, file);
		return (ARCHIVE_WARN);
	}

	iso9660->previous_size = file->size;
	iso9660->previous_offset = file->offset;
	archive_strcpy(&iso9660->previous_pathname, iso9660->pathname.s);

	/* If this is a directory, read in all of the entries right now. */
	if (archive_entry_filetype(entry) == AE_IFDIR) {
		while (iso9660->entry_bytes_remaining > 0) {
			const void *block;
			const unsigned char *p;
			ssize_t step = iso9660->logical_block_size;
			if (step > iso9660->entry_bytes_remaining)
				step = iso9660->entry_bytes_remaining;
			bytes_read = (a->decompressor->read_ahead)(a, &block, step);
			if (bytes_read < step) {
				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
	    "Failed to read full block when scanning ISO9660 directory list");
				release_file(iso9660, file);
				return (ARCHIVE_FATAL);
			}
			if (bytes_read > step)
				bytes_read = step;
			(a->decompressor->consume)(a, bytes_read);
			iso9660->current_position += bytes_read;
			iso9660->entry_bytes_remaining -= bytes_read;
			for (p = (const unsigned char *)block;
			     *p != 0 && p < (const unsigned char *)block + bytes_read;
			     p += *p) {
				struct file_info *child;

				/* Skip '.' entry. */
				if (*(p + DR_name_len_offset) == 1
				    && *(p + DR_name_offset) == '\0')
					continue;
				/* Skip '..' entry. */
				if (*(p + DR_name_len_offset) == 1
				    && *(p + DR_name_offset) == '\001')
					continue;
				child = parse_file_info(iso9660, file, p);
				add_entry(iso9660, child);
				if (iso9660->seenRockridge) {
					a->archive.archive_format =
					    ARCHIVE_FORMAT_ISO9660_ROCKRIDGE;
					a->archive.archive_format_name =
					    "ISO9660 with Rockridge extensions";
				}
			}
		}
	}

	release_file(iso9660, file);
	return (ARCHIVE_OK);
}
static void
test_1(void)
{
	struct archive_entry *ae;
	struct archive *a;
	size_t used;
	size_t blocksize;
	int64_t offset, length;
	char *buff2;
	size_t buff2_size = 0x13000;
	char buff3[1024];
	long i;

	assert((buff2 = malloc(buff2_size)) != NULL);
	/* 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);
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_write_set_format_pax(a));
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_write_set_compression_none(a));
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_write_set_bytes_per_block(a, (int)blocksize));
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_write_set_bytes_in_last_block(a, (int)blocksize));
		assertEqualInt(blocksize,
		    archive_write_get_bytes_in_last_block(a));
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_write_open_memory(a, buff, sizeof(buff), &used));
		assertEqualInt(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);
		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, 0x81000);
		archive_entry_sparse_add_entry(ae, 0x10000, 0x1000);
		archive_entry_sparse_add_entry(ae, 0x80000, 0x1000);

		assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
		archive_entry_free(ae);
		memset(buff2, 'a', buff2_size);
		for (i = 0; i < 0x81000;) {
			size_t ws = buff2_size;
			if (i + ws > 0x81000)
				ws = 0x81000 - i;
			assertEqualInt(ws,
				archive_write_data(a, buff2, ws));
			i += ws;
		}

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

		/* This calculation gives "the smallest multiple of
		 * the block size that is at least 11264 bytes". */
		failure("blocksize=%d", blocksize);
		assertEqualInt(((11264 - 1)/blocksize+1)*blocksize, used);

		/*
		 * 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_filter_all(a));
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_read_open_memory(a, buff, used));

		assertEqualIntA(a, ARCHIVE_OK,
		    archive_read_next_header(a, &ae));

		assertEqualInt(1, archive_entry_mtime(ae));
		assertEqualInt(10, archive_entry_mtime_nsec(ae));
		assertEqualInt(0, archive_entry_atime(ae));
		assertEqualInt(0, archive_entry_ctime(ae));
		assertEqualString("file", archive_entry_pathname(ae));
		assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
		assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae));
		assertEqualInt(0x81000, archive_entry_size(ae));
		/* Verify sparse information. */
		assertEqualInt(2, archive_entry_sparse_reset(ae));
		assertEqualInt(0,
			archive_entry_sparse_next(ae, &offset, &length));
		assertEqualInt(0x10000, offset);
		assertEqualInt(0x1000, length);
		assertEqualInt(0,
			archive_entry_sparse_next(ae, &offset, &length));
		assertEqualInt(0x80000, offset);
		assertEqualInt(0x1000, length);
		/* Verify file contents. */
		memset(buff3, 0, sizeof(buff3));
		for (i = 0; i < 0x10000; i += 1024) {
			assertEqualInt(1024, archive_read_data(a, buff2, 1024));
			failure("Read data(0x%lx - 0x%lx) should be all zero",
			    i, i + 1024);
			assertEqualMem(buff2, buff3, 1024);
		}
		memset(buff3, 'a', sizeof(buff3));
		for (i = 0x10000; i < 0x11000; i += 1024) {
			assertEqualInt(1024, archive_read_data(a, buff2, 1024));
			failure("Read data(0x%lx - 0x%lx) should be all 'a'",
			    i, i + 1024);
			assertEqualMem(buff2, buff3, 1024);
		}
		memset(buff3, 0, sizeof(buff3));
		for (i = 0x11000; i < 0x80000; i += 1024) {
			assertEqualInt(1024, archive_read_data(a, buff2, 1024));
			failure("Read data(0x%lx - 0x%lx) should be all zero",
			    i, i + 1024);
			assertEqualMem(buff2, buff3, 1024);
		}
		memset(buff3, 'a', sizeof(buff3));
		for (i = 0x80000; i < 0x81000; i += 1024) {
			assertEqualInt(1024, archive_read_data(a, buff2, 1024));
			failure("Read data(0x%lx - 0x%lx) should be all 'a'",
			    i, i + 1024);
			assertEqualMem(buff2, buff3, 1024);
		}

		/* 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_free(a));
	}
	free(buff2);
}
/*
 * Test writing an empty file.
 */
static void
test_only_empty_file(void)
{
	struct archive *a;
	struct archive_entry *ae;
	size_t buffsize = 1000;
	char *buff;
	size_t used;

	buff = malloc(buffsize);

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

	/*
	 * Write an empty 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_set_atime(ae, 2, 20);
	assertEqualInt(2, archive_entry_atime(ae));
	assertEqualInt(20, archive_entry_atime_nsec(ae));
	archive_entry_set_ctime(ae, 0, 100);
	assertEqualInt(0, archive_entry_ctime(ae));
	assertEqualInt(100, archive_entry_ctime_nsec(ae));
	archive_entry_copy_pathname(ae, "empty");
	assertEqualString("empty", archive_entry_pathname(ae));
	archive_entry_set_mode(ae, AE_IFREG | 0755);
	assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));

	assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae));
	archive_entry_free(ae);

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

	/* Verify the archive file size. */
	assertEqualInt(102, used);

	/* Verify the initial header. */
	assertEqualMem(buff,
		"\x37\x7a\xbc\xaf\x27\x1c\x00\x03"
		"\x00\x5b\x58\x25\x00\x00\x00\x00"
		"\x00\x00\x00\x00\x46\x00\x00\x00"
		"\x00\x00\x00\x00\x8f\xce\x1d\xf3", 32);

	/*
	 * Now, read the data back.
	 */
	/* With the test memory reader -- seeking mode. */
	assert((a = archive_read_new()) != NULL);
	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
	assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7));

	/*
	 * Read and verify an empty file.
	 */
	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
	assertEqualInt(1, archive_entry_mtime(ae));
	assertEqualInt(0, archive_entry_mtime_nsec(ae));
	assertEqualInt(2, archive_entry_atime(ae));
	assertEqualInt(0, archive_entry_atime_nsec(ae));
	assertEqualInt(0, archive_entry_ctime(ae));
	assertEqualInt(100, archive_entry_ctime_nsec(ae));
	assertEqualString("empty", archive_entry_pathname(ae));
	assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae));
	assertEqualInt(0, archive_entry_size(ae));

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

	/* Verify archive format. */
	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
	assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a));

	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
	assertEqualInt(ARCHIVE_OK, archive_read_free(a));

	free(buff);
}
Beispiel #21
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);
	assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a));
	if (use_set)
		assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_option(a, NULL, "use-set", "1"));
	if (dironly)
		assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_option(a, NULL, "dironly", "1"));
	assertEqualIntA(a, ARCHIVE_OK, 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);
		assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
		if ((entries[i].mode & AE_IFMT) != S_IFDIR)
			assertEqualIntA(a, 8,
			    archive_write_data(a, "Hello012", 15));
		archive_entry_free(ae);
	}
	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
        assertEqualInt(ARCHIVE_OK, archive_write_free(a));

	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_filter_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, ARCHIVE_OK, archive_read_close(a));
	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
static int
header_newc(struct archive_read *a, struct cpio *cpio,
    struct archive_entry *entry, size_t *namelength, size_t *name_pad)
{
	const void *h;
	const char *header;
	int r;

	r = find_newc_header(a);
	if (r < ARCHIVE_WARN)
		return (r);

	/* Read fixed-size portion of header. */
	h = __archive_read_ahead(a, newc_header_size, NULL);
	if (h == NULL)
	    return (ARCHIVE_FATAL);

	/* Parse out hex fields. */
	header = (const char *)h;

	if (memcmp(header + newc_magic_offset, "070701", 6) == 0) {
		a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_NOCRC;
		a->archive.archive_format_name = "ASCII cpio (SVR4 with no CRC)";
	} else if (memcmp(header + newc_magic_offset, "070702", 6) == 0) {
		a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_CRC;
		a->archive.archive_format_name = "ASCII cpio (SVR4 with CRC)";
	} else {
		/* TODO: Abort here? */
	}

	archive_entry_set_devmajor(entry,
		(dev_t)atol16(header + newc_devmajor_offset, newc_devmajor_size));
	archive_entry_set_devminor(entry, 
		(dev_t)atol16(header + newc_devminor_offset, newc_devminor_size));
	archive_entry_set_ino(entry, atol16(header + newc_ino_offset, newc_ino_size));
	archive_entry_set_mode(entry, 
		(mode_t)atol16(header + newc_mode_offset, newc_mode_size));
	archive_entry_set_uid(entry, atol16(header + newc_uid_offset, newc_uid_size));
	archive_entry_set_gid(entry, atol16(header + newc_gid_offset, newc_gid_size));
	archive_entry_set_nlink(entry,
		(unsigned int)atol16(header + newc_nlink_offset, newc_nlink_size));
	archive_entry_set_rdevmajor(entry,
		(dev_t)atol16(header + newc_rdevmajor_offset, newc_rdevmajor_size));
	archive_entry_set_rdevminor(entry,
		(dev_t)atol16(header + newc_rdevminor_offset, newc_rdevminor_size));
	archive_entry_set_mtime(entry, atol16(header + newc_mtime_offset, newc_mtime_size), 0);
	*namelength = (size_t)atol16(header + newc_namesize_offset, newc_namesize_size);
	/* Pad name to 2 more than a multiple of 4. */
	*name_pad = (2 - *namelength) & 3;

	/*
	 * Note: entry_bytes_remaining is at least 64 bits and
	 * therefore guaranteed to be big enough for a 33-bit file
	 * size.
	 */
	cpio->entry_bytes_remaining =
	    atol16(header + newc_filesize_offset, newc_filesize_size);
	archive_entry_set_size(entry, cpio->entry_bytes_remaining);
	/* Pad file contents to a multiple of 4. */
	cpio->entry_padding = 3 & -cpio->entry_bytes_remaining;
	__archive_read_consume(a, newc_header_size);
	return (r);
}
static void
test_format_by_name(const char *format_name, const char *compression_type,
    int format_id, int dot_stored, const void *image, size_t image_size)
{
	struct archive_entry *ae;
	struct archive *a;
	size_t used;
	size_t buffsize = 1024 * 1024;
	char *buff;
	int r;

	assert((buff = malloc(buffsize)) != NULL);
	if (buff == NULL)
		return;

	/* Create a new archive in memory. */
	assert((a = archive_write_new()) != NULL);
	r = archive_write_set_format_by_name(a, format_name);
	if (r == ARCHIVE_WARN) {
		skipping("%s format not fully supported on this platform",
		   compression_type);
		assertEqualInt(ARCHIVE_OK, archive_write_free(a));
		free(buff);
		return;
	}
	assertEqualIntA(a, ARCHIVE_OK, r);
	if (compression_type != NULL &&
	    ARCHIVE_OK != archive_write_set_format_option(a, format_name,
	    "compression", compression_type)) {
		skipping("%s writing not fully supported on this platform",
		   compression_type);
		assertEqualInt(ARCHIVE_OK, archive_write_free(a));
		free(buff);
		return;
	}
	assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_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, 0);
	assertEqualInt(1, archive_entry_mtime(ae));
	archive_entry_set_ctime(ae, 1, 0);
	assertEqualInt(1, archive_entry_ctime(ae));
	archive_entry_set_atime(ae, 1, 0);
	assertEqualInt(1, archive_entry_atime(ae));
	archive_entry_copy_pathname(ae, "file");
	assertEqualString("file", archive_entry_pathname(ae));
	archive_entry_set_mode(ae, AE_IFREG | 0755);
	assertEqualInt((AE_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", 8));

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

	if (image && image_size > 0) {
		assertEqualMem(buff, image, image_size);
	}
	if (format_id > 0) {
		/*
		 * Now, read the data back.
		 */
		/* With the test memory reader -- seeking mode. */
		assert((a = archive_read_new()) != NULL);
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_read_support_format_all(a));
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_read_support_filter_all(a));
		assertEqualIntA(a, ARCHIVE_OK,
		    read_open_memory_seek(a, buff, used, 7));

		if (dot_stored & 1) {
			assertEqualIntA(a, ARCHIVE_OK,
			    archive_read_next_header(a, &ae));
			assertEqualString(".", archive_entry_pathname(ae));
			assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
		}
		/*
		 * Read and verify the file.
		 */
		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
		assertEqualInt(1, archive_entry_mtime(ae));
		if (dot_stored & 2) {
			assertEqualString("./file", archive_entry_pathname(ae));
		} else {
			assertEqualString("file", archive_entry_pathname(ae));
		}
		assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
		assertEqualInt(8, archive_entry_size(ae));

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

		/* Verify archive format. */
		assertEqualIntA(a, ARCHIVE_FILTER_NONE,
		    archive_filter_code(a, 0));
		assertEqualIntA(a, format_id, archive_format(a));

		assertEqualInt(ARCHIVE_OK, archive_read_close(a));
		assertEqualInt(ARCHIVE_OK, archive_read_free(a));
	}
	free(buff);
}
static void
test_open_filename_mbs(void)
{
	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_free(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_filter_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_free(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_filter_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_free(a));

}
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_API_VERSION > 1
	assertA(0 == archive_write_finish(a));
#else
	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));

	assertEqualIntA(a, 0, 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("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_API_VERSION > 1
	assert(0 == archive_read_finish(a));
#else
	archive_read_finish(a);
#endif

	free(buff);
}
Beispiel #26
0
static void
test_large(const char *compression_type)
{
	struct archive_entry *ae;
	struct archive *a;
	size_t used;
	size_t buffsize = LARGE_SIZE + 1024 * 256;
	size_t datasize = LARGE_SIZE;
	char *buff, *filedata, *filedata2;
	unsigned i;

	assert((buff = malloc(buffsize)) != NULL);
	assert((filedata = malloc(datasize)) != NULL);
	assert((filedata2 = malloc(datasize)) != NULL);

	/* Create a new archive in memory. */
	assert((a = archive_write_new()) != NULL);
	if (a == NULL || buff == NULL || filedata == NULL || filedata2 == NULL) {
		archive_write_free(a);
		free(buff);
		free(filedata);
		free(filedata2);
		return;
	}
	assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_7zip(a));
	if (compression_type != NULL &&
	    ARCHIVE_OK != archive_write_set_format_option(a, "7zip",
	    "compression", compression_type)) {
		skipping("%s writing not fully supported on this platform",
		   compression_type);
		assertEqualInt(ARCHIVE_OK, archive_write_free(a));
		free(buff);
		free(filedata);
		free(filedata2);
		return;
	}
	assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a));
	assertEqualIntA(a, ARCHIVE_OK,
	    archive_write_open_memory(a, buff, buffsize, &used));

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

	assertEqualInt(0, archive_write_header(a, ae));
	archive_entry_free(ae);
	if (strcmp(compression_type, "ppmd") == 0) {
		/* NOTE: PPMd cannot handle random data correctly.*/
		memset(filedata, 'a', datasize);
	} else {
		for (i = 0; i < datasize; i++)
			filedata[i] = (char)rand();
	}
	assertEqualInt(datasize, archive_write_data(a, filedata, datasize));

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

	/* Verify the initial header. */
	assertEqualMem(buff, "\x37\x7a\xbc\xaf\x27\x1c\x00\x03", 8);

	/*
	 * Now, read the data back.
	 */
	/* With the test memory reader -- seeking mode. */
	assert((a = archive_read_new()) != NULL);
	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
	assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7));

	/*
	 * Read and verify a large file.
	 */
	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
	assertEqualInt(1, archive_entry_mtime(ae));
	assertEqualInt(100, archive_entry_mtime_nsec(ae));
	assertEqualInt(0, archive_entry_atime(ae));
	assertEqualInt(0, archive_entry_ctime(ae));
	assertEqualString("file", archive_entry_pathname(ae));
	assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae));
	assertEqualInt(datasize, archive_entry_size(ae));
	assertEqualIntA(a, datasize, archive_read_data(a, filedata2, datasize));
	assertEqualMem(filedata, filedata2, datasize);

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

	/* Verify archive format. */
	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
	assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a));

	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
	assertEqualInt(ARCHIVE_OK, archive_read_free(a));

	free(buff);
	free(filedata);
	free(filedata2);
}
int
zip_read_file_header(struct archive_read *a, struct archive_entry *entry,
    struct zip *zip)
{
	const struct zip_file_header *p;
	const void *h;

	if ((p = __archive_read_ahead(a, sizeof *p)) == NULL) {
		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
		    "Truncated ZIP file header");
		return (ARCHIVE_FATAL);
	}

	zip->version = p->version[0];
	zip->system = p->version[1];
	zip->flags = archive_le16dec(p->flags);
	zip->compression = archive_le16dec(p->compression);
	if (zip->compression <
	    sizeof(compression_names)/sizeof(compression_names[0]))
		zip->compression_name = compression_names[zip->compression];
	else
		zip->compression_name = "??";
	zip->mtime = zip_time(p->timedate);
	zip->ctime = 0;
	zip->atime = 0;
	zip->mode = 0;
	zip->uid = 0;
	zip->gid = 0;
	zip->crc32 = archive_le32dec(p->crc32);
	zip->filename_length = archive_le16dec(p->filename_length);
	zip->extra_length = archive_le16dec(p->extra_length);
	zip->uncompressed_size = archive_le32dec(p->uncompressed_size);
	zip->compressed_size = archive_le32dec(p->compressed_size);

	(a->decompressor->consume)(a, sizeof(struct zip_file_header));


	/* Read the filename. */
	if ((h = __archive_read_ahead(a, zip->filename_length)) == NULL) {
		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
		    "Truncated ZIP file header");
		return (ARCHIVE_FATAL);
	}
	if (archive_string_ensure(&zip->pathname, zip->filename_length) == NULL)
		__archive_errx(1, "Out of memory");
	archive_strncpy(&zip->pathname, h, zip->filename_length);
	(a->decompressor->consume)(a, zip->filename_length);
	archive_entry_set_pathname(entry, zip->pathname.s);

	if (zip->pathname.s[archive_strlen(&zip->pathname) - 1] == '/')
		zip->mode = AE_IFDIR | 0777;
	else
		zip->mode = AE_IFREG | 0777;

	/* Read the extra data. */
	if ((h = __archive_read_ahead(a, zip->extra_length)) == NULL) {
		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
		    "Truncated ZIP file header");
		return (ARCHIVE_FATAL);
	}
	process_extra(h, zip);
	(a->decompressor->consume)(a, zip->extra_length);

	/* Populate some additional entry fields: */
	archive_entry_set_mode(entry, zip->mode);
	archive_entry_set_uid(entry, zip->uid);
	archive_entry_set_gid(entry, zip->gid);
	archive_entry_set_mtime(entry, zip->mtime, 0);
	archive_entry_set_ctime(entry, zip->ctime, 0);
	archive_entry_set_atime(entry, zip->atime, 0);
	archive_entry_set_size(entry, zip->uncompressed_size);

	zip->entry_bytes_remaining = zip->compressed_size;
	zip->entry_offset = 0;

	/* If there's no body, force read_data() to return EOF immediately. */
	if (0 == (zip->flags & ZIP_LENGTH_AT_END)
	    && zip->entry_bytes_remaining < 1)
		zip->end_of_entry = 1;

	/* Set up a more descriptive format name. */
	sprintf(zip->format_name, "ZIP %d.%d (%s)",
	    zip->version / 10, zip->version % 10,
	    zip->compression_name);
	a->archive.archive_format_name = zip->format_name;

	return (ARCHIVE_OK);
}
Beispiel #28
0
void Entry::set_mode(int mode)
{
    archive_entry_set_mode(_entry, mode);
}
Beispiel #29
0
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_add_filter_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. */
	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
	assertEqualInt(ARCHIVE_OK, archive_write_free(a));

	/*
	 * Now, read the data back.
	 */
	assert((a = archive_read_new()) != NULL);
	assertA(0 == archive_read_support_format_all(a));
	assertA(0 == archive_read_support_filter_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));
	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
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_add_filter_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 file with a name, filetype, and size.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "name");
    archive_entry_set_size(ae, 0);
    archive_entry_set_filetype(ae, AE_IFREG);
    assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae));
    assert(archive_error_string(a) == NULL);
    archive_entry_free(ae);

    /*
     * Write a file with a name and filetype but no size.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "name");
    archive_entry_unset_size(ae);
    archive_entry_set_filetype(ae, AE_IFREG);
    assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
    assert(archive_error_string(a) != NULL);
    archive_entry_free(ae);

    /*
     * Write a file with a name and size but no filetype.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_copy_pathname(ae, "name");
    archive_entry_set_size(ae, 0);
    assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
    assert(archive_error_string(a) != NULL);
    archive_entry_free(ae);

    /*
     * Write a file with a size and filetype but no name.
     */
    assert((ae = archive_entry_new()) != NULL);
    archive_entry_set_size(ae, 0);
    archive_entry_set_filetype(ae, AE_IFREG);
    assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
    assert(archive_error_string(a) != NULL);
    archive_entry_free(ae);

    /*
     * 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. */
    assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
    assertEqualInt(ARCHIVE_OK, archive_write_free(a));

    /*
     * Damage the second entry to test the search-ahead recovery.
     * TODO: Move the damage-recovery checking to a separate test;
     * it doesn't really belong in this write test.
     */
    {
        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_filter_all(a));
    assertA(0 == archive_read_open_memory(a, buff, used));

    if (!assertEqualIntA(a, 0, archive_read_next_header(a, &ae))) {
        archive_read_free(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));
    assertEqualMem(filedata, "12345678", 8);

    /*
     * The second file can't be read because we damaged its header.
     */

    /*
     * Read the third file back.
     * ARCHIVE_WARN here because the damaged entry was skipped.
     */
    assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae));
    assertEqualString("name", archive_entry_pathname(ae));

    /*
     * Read the dir entry back.
     */
    assertEqualIntA(a, 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));
    assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
    assertEqualInt(ARCHIVE_OK, archive_read_free(a));

    free(buff);
}