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); }
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); }
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); }
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); }
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 }
/* * 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); }
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); }
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); }
void Entry::set_mode(int mode) { archive_entry_set_mode(_entry, mode); }
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); }