static void verify(unsigned char *d, size_t s, void (*f)(struct archive_entry *), int compression, int format) { struct archive_entry *ae; struct archive *a; unsigned char *buff = malloc(100000); memcpy(buff, d, s); memset(buff + s, 0, 2048); assert((a = archive_read_new()) != NULL); assertA(0 == archive_read_support_compression_all(a)); assertA(0 == archive_read_support_format_all(a)); assertA(0 == archive_read_open_memory(a, buff, s + 1024)); assertA(0 == archive_read_next_header(a, &ae)); assertEqualInt(archive_compression(a), compression); assertEqualInt(archive_format(a), format); /* Verify the only entry. */ f(ae); assert(0 == archive_read_close(a)); #if ARCHIVE_VERSION_NUMBER < 2000000 archive_read_finish(a); #else assert(0 == archive_read_finish(a)); #endif free(buff); }
static void test(int skip_explicitely) { struct archive* a = archive_read_new(); struct archive_entry* e; assertEqualInt(ARCHIVE_OK, archive_read_support_format_raw(a)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); assertEqualInt(ARCHIVE_OK, archive_read_open_memory(a, (void*) data, sizeof(data))); assertEqualString(NULL, archive_error_string(a)); assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &e)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); if (skip_explicitely) assertEqualInt(ARCHIVE_OK, archive_read_data_skip(a)); assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &e)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); archive_read_free(a); }
/* * We should get a warning if the contents file doesn't exist. */ static void test_read_format_mtree5(void) { static char archive[] = "#mtree\n" "a type=file contents=nonexistent_file\n"; struct archive_entry *ae; struct archive *a; assertMakeDir("mtree5", 0777); assertChdir("mtree5"); assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, archive, sizeof(archive))); assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae)); assert(strlen(archive_error_string(a)) > 0); assertEqualString(archive_entry_pathname(ae), "a"); assertEqualInt(archive_entry_filetype(ae), AE_IFREG); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(1, archive_file_count(a)); assertEqualInt(ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); assertChdir(".."); }
static void test_read_format_mtree2(void) { static char archive[] = "#mtree\n" "d type=dir content=.\n"; struct archive_entry *ae; struct archive *a; assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, archive, sizeof(archive))); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE); assertEqualString(archive_entry_pathname(ae), "d"); assertEqualInt(archive_entry_filetype(ae), AE_IFDIR); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(1, archive_file_count(a)); assertEqualInt(ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); }
int load_package_files(struct pkg *pkg, int fd) { struct archive *archive; struct file_t file; if (file_from_fd(&file, fd) < 0) return -1; archive = archive_read_new(); archive_read_support_filter_all(archive); archive_read_support_format_all(archive); if (archive_read_open_memory(archive, file.mmap, file.st.st_size) != ARCHIVE_OK) { archive_read_free(archive); return -1; } struct archive_entry *entry; while (archive_read_next_header(archive, &entry) == ARCHIVE_OK) { const char *entry_name = archive_entry_pathname(entry); if (!is_package_metadata(entry_name)) pkg->files = alpm_list_add(pkg->files, strdup(entry_name)); } archive_read_close(archive); archive_read_free(archive); return 0; }
static void verify(unsigned char *d, size_t s, void (*f)(struct archive_entry *), int compression, int format) { struct archive_entry *ae; struct archive *a; unsigned char *buff = malloc(100000); memcpy(buff, d, s); memset(buff + s, 0, 2048); assert((a = archive_read_new()) != NULL); assertA(0 == archive_read_support_filter_all(a)); assertA(0 == archive_read_support_format_all(a)); assertA(0 == archive_read_open_memory(a, buff, s + 1024)); assertA(0 == archive_read_next_header(a, &ae)); assertEqualInt(archive_filter_code(a, 0), compression); assertEqualInt(archive_format(a), format); /* Verify the only entry. */ f(ae); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); }
static int get_format(const char *archive) { struct archive *a; struct archive_entry *ae; int found_format; assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_mtree(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_raw(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_empty(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, archive, strlen(archive))); // Read one header to settle the format. // This might return EOF or OK. archive_read_next_header(a, &ae); found_format = archive_format(a); assertEqualInt(ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); return found_format; }
/* * memory to file */ int archive_extract_file3( void *arch_buff, size_t arch_size, const char *src, char *dest ) { int flags; const char *filename; struct archive *arch_r = NULL, *arch_w = NULL; struct archive_entry *entry; if( !src || !dest ) return -1; arch_r = archive_read_new(); archive_read_support_format_all( arch_r ); archive_read_support_compression_all( arch_r ); if( archive_read_open_memory( arch_r, arch_buff, arch_size ) != ARCHIVE_OK ) goto errout; while( archive_read_next_header( arch_r, &entry ) == ARCHIVE_OK ) { filename = archive_entry_pathname( entry ); if( fnmatch( src, filename, FNM_PATHNAME | FNM_PERIOD ) ) { if( archive_read_data_skip( arch_r ) != ARCHIVE_OK ) { goto errout; } } else { #ifdef DEBUG printf("extract:%s\n", filename ); #endif flags = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS; arch_w = archive_write_disk_new(); archive_write_disk_set_options( arch_w, flags ); archive_write_disk_set_standard_lookup( arch_w ); archive_entry_set_pathname( entry, dest ); if( archive_read_extract2( arch_r, entry, arch_w ) != ARCHIVE_OK ) goto errout; archive_write_finish( arch_w ); } } archive_read_finish( arch_r ); return 0; errout: #ifdef DEBUG fprintf( stderr, "%s\n", archive_error_string( arch_r ) ); #endif if( arch_r ) archive_read_finish( arch_r ); if( arch_w ) archive_write_finish( arch_w ); return -1; }
static void verify(unsigned char *buff, size_t used, enum vtype type, struct fns *fns) { struct archive *a; struct archive_entry *ae; size_t i; /* * Read ISO image. */ assert((a = archive_read_new()) != NULL); assertEqualIntA(a, 0, archive_read_support_format_all(a)); assertEqualIntA(a, 0, archive_read_support_filter_all(a)); if (type >= 1) assertA(0 == archive_read_set_option(a, NULL, "rockridge", NULL)); if (type >= 2) assertA(0 == archive_read_set_option(a, NULL, "joliet", NULL)); assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); /* * Read Root Directory * Root Directory entry must be in ISO image. */ assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); assertEqualInt(archive_entry_atime(ae), archive_entry_ctime(ae)); assertEqualInt(archive_entry_atime(ae), archive_entry_mtime(ae)); assertEqualString(".", archive_entry_pathname(ae)); switch (type) { case ROCKRIDGE: assert((S_IFDIR | 0555) == archive_entry_mode(ae)); break; case JOLIET: assert((S_IFDIR | 0700) == archive_entry_mode(ae)); break; case ISO9660: assert((S_IFDIR | 0700) == archive_entry_mode(ae)); break; } /* * Verify file status. */ memset(fns->names, 0, sizeof(char *) * fns->alloc); fns->cnt = 0; for (i = 0; i < fns->alloc; i++) verify_file(a, type, fns); for (i = 0; i < fns->alloc; i++) free(fns->names[i]); assertEqualInt((int)fns->longest_len, (int)fns->maxlen); /* * Verify the end of the archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); }
/* * memory to memory */ int archive_extract_file4( void *arch_buff, size_t arch_size, const char *src, void **dest_buff, size_t *dest_len ) { const char *filename; struct archive *arch_r = NULL; struct archive_entry *entry; if( !src ) return -1; arch_r = archive_read_new(); archive_read_support_format_all( arch_r ); archive_read_support_compression_all( arch_r ); if( archive_read_open_memory( arch_r, arch_buff, arch_size ) != ARCHIVE_OK ) goto errout; while( archive_read_next_header( arch_r, &entry ) == ARCHIVE_OK ) { filename = archive_entry_pathname( entry ); if( fnmatch( src, filename, FNM_PATHNAME | FNM_PERIOD ) ) { if( archive_read_data_skip( arch_r ) != ARCHIVE_OK ) { goto errout; } } else { #ifdef DEBUG printf("extract:%s\n", filename ); #endif *dest_len = archive_entry_size( entry ); if( *dest_len > 0 ) { *dest_buff = malloc( *dest_len + 1 ); memset( *dest_buff, 0, *dest_len + 1 ); } if( archive_read_data( arch_r, *dest_buff, *dest_len) < 0 ) goto errout; } } archive_read_finish( arch_r ); return 0; errout: #ifdef DEBUG fprintf( stderr, "%s\n", archive_error_string( arch_r ) ); #endif if( arch_r ) archive_read_finish( arch_r ); return -1; }
static bool taste_tar(io_block_t *ib) { struct archive *ar = archive_read_new(); archive_read_support_compression_none(ar); archive_read_support_format_tar(ar); archive_read_open_memory(ar, ib->output, ib->outsize); struct archive_entry *entry; bool ok = (archive_read_next_header(ar, &entry) == ARCHIVE_OK); archive_read_finish(ar); return ok; }
void load_examples(const void *data, size_t len, example_list_t *examples) { example_patch_t *patch; struct archive *arch; struct archive_entry *ent; const char *path; FILE *fp; char *buf; size_t size; char block[4096]; ssize_t count; int ret; assert(data != NULL); arch = archive_read_new(); assert(arch != NULL); if (archive_read_support_format_zip(arch)) abort(); if (archive_read_open_memory(arch, (void *) data, len)) abort(); while (!(ret = archive_read_next_header(arch, &ent))) { if (!S_ISREG(archive_entry_filetype(ent))) continue; path = archive_entry_pathname(ent); if (strncmp(path, EXAMPLE_DIR "/", strlen(EXAMPLE_DIR) + 1)) continue; /* archive_entry_size() is not reliable for Zip files */ fp = open_memstream(&buf, &size); if (fp == NULL) abort(); while ((count = archive_read_data(arch, block, sizeof(block))) > 0) if (fwrite(block, 1, count, fp) != (size_t) count) abort(); if (count < 0) { fprintf(stderr, "%s\n", archive_error_string(arch)); abort(); } fclose(fp); patch = malloc(sizeof(*patch)); patch->image = read_rgb_image(buf, size); if (patch->image == NULL) { fprintf(stderr, "Couldn't decode example %s\n", path); abort(); } TAILQ_INSERT_TAIL(examples, patch, link); free(buf); } assert(ret == ARCHIVE_EOF); if (archive_read_finish(arch)) abort(); }
Reader *Reader::read_open_memory(const char *string, size_t length, const char *cmd, bool raw) { struct archive *ar = archive_read_new(); if (!ar) { throw Error("Unable to allocate libarchive handle!"); } char *content = (char*) malloc(length); if (!content) { archive_read_free(ar); throw Error("Unable to allocate memory when duplicating buffer"); } memcpy((void*) content, (void*) string, length); try { if(cmd) { if(archive_read_support_filter_program(ar, cmd) != ARCHIVE_OK) throw 0; } else { if(archive_read_support_filter_all(ar) != ARCHIVE_OK) throw 0; } if(raw) { if(archive_read_support_format_raw(ar) != ARCHIVE_OK) throw 0; } else { if(archive_read_support_format_all(ar) != ARCHIVE_OK) throw 0; } if(archive_read_open_memory(ar, (void*) content, length) != ARCHIVE_OK) throw 0; } catch(...) { std::string error_msg = archive_error_string(ar); archive_read_free(ar); free(content); throw Error(error_msg); } Reader *reader_obj = new Reader(ar); reader_obj->_archive_content = content; return reader_obj; }
void archive_read() { struct archive *a; a = archive_read_new(); archive_read_support_format_all(a); archive_read_support_filter_all(a); archive_read_open_memory(a, buffer_, read_size_); struct archive_entry *ae; if (archive_read_next_header(a, &ae) == ARCHIVE_OK) { int size = archive_entry_size(ae); archive_buffer_ = new char[size]; archive_buffer_size_ = size; archive_read_data(a, archive_buffer_, size); } archive_read_free(a); }
int do_extract_mtree(char *mtree, const char *prefix) { struct archive *a = NULL; struct archive_entry *ae; char path[MAXPATHLEN]; const char *fpath; int retcode = EPKG_OK; int ret; if (mtree == NULL || *mtree == '\0') return EPKG_OK; a = archive_read_new(); archive_read_support_filter_none(a); archive_read_support_format_mtree(a); if (archive_read_open_memory(a, mtree, strlen(mtree)) != ARCHIVE_OK) { pkg_emit_error("Fail to extract the mtree: %s", archive_error_string(a)); retcode = EPKG_FATAL; goto cleanup; } while ((ret = archive_read_next_header(a, &ae)) != ARCHIVE_EOF) { if (ret != ARCHIVE_OK) { pkg_emit_error("Skipping unsupported mtree line: %s", archive_error_string(a)); continue; } fpath = archive_entry_pathname(ae); if (*fpath != '/') { snprintf(path, sizeof(path), "%s/%s", prefix, fpath); archive_entry_set_pathname(ae, path); } /* Ignored failed extraction on purpose */ archive_read_extract(a, ae, EXTRACT_ARCHIVE_FLAGS); } cleanup: if (a != NULL) archive_read_free(a); return (retcode); }
static void verifyEmpty(void) { struct archive_entry *ae; struct archive *a; assert((a = archive_read_new()) != NULL); assertA(0 == archive_read_support_filter_all(a)); assertA(0 == archive_read_support_format_all(a)); assertA(0 == archive_read_open_memory(a, archiveEmpty, 512)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualString(archive_filter_name(a, 0), "none"); failure("512 zero bytes should be recognized as a tar archive."); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); }
static struct archive *file_type_archive_gen_archive(GBytes *data) {/*{{{*/ struct archive *archive = archive_read_new(); archive_read_support_format_zip(archive); archive_read_support_format_rar(archive); archive_read_support_format_7zip(archive); archive_read_support_format_tar(archive); archive_read_support_filter_all(archive); gsize data_size; char *data_ptr = (char *)g_bytes_get_data(data, &data_size); if(archive_read_open_memory(archive, data_ptr, data_size) != ARCHIVE_OK) { g_printerr("Failed to load archive: %s\n", archive_error_string(archive)); archive_read_free(archive); return NULL; } return archive; }/*}}}*/
int load_package(pkg_t *pkg, int fd) { struct archive *archive; struct file_t file; if (file_from_fd(&file, fd) < 0) { return -1; } archive = archive_read_new(); archive_read_support_filter_all(archive); archive_read_support_format_all(archive); if (archive_read_open_memory(archive, file.mmap, file.st.st_size) != ARCHIVE_OK) { archive_read_free(archive); return -1; } bool found_pkginfo = false; struct archive_entry *entry; while (archive_read_next_header(archive, &entry) == ARCHIVE_OK && !found_pkginfo) { const char *entry_name = archive_entry_pathname(entry); const mode_t mode = archive_entry_mode(entry); if (S_ISREG(mode) && streq(entry_name, ".PKGINFO")) { read_pkginfo(archive, pkg); found_pkginfo = true; } } archive_read_close(archive); archive_read_free(archive); if (found_pkginfo) { pkg->size = file.st.st_size; pkg->mtime = file.st.st_mtime; pkg->name_hash = _alpm_hash_sdbm(pkg->name); return 0; } return -1; }
static void verifyEmpty(void) { struct archive_entry *ae; struct archive *a; assert((a = archive_read_new()) != NULL); assertA(0 == archive_read_support_compression_all(a)); assertA(0 == archive_read_support_format_all(a)); assertA(0 == archive_read_open_memory(a, archiveEmpty, 512)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_NONE); failure("512 zero bytes should be recognized as a tar archive."); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR); assert(0 == archive_read_close(a)); #if ARCHIVE_API_VERSION > 1 assert(0 == archive_read_finish(a)); #else archive_read_finish(a); #endif }
/* * Reported to libarchive.googlecode.com as Issue 121. */ static void test_read_format_mtree3(void) { static char archive[] = "#mtree\n" "a type=file contents=file\n" "b type=link link=a\n" "c type=file contents=file\n"; struct archive_entry *ae; struct archive *a; assertMakeDir("mtree3", 0777); assertChdir("mtree3"); assertMakeFile("file", 0644, "file contents"); assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, archive, sizeof(archive))); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString(archive_entry_pathname(ae), "a"); assertEqualInt(archive_entry_filetype(ae), AE_IFREG); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString(archive_entry_pathname(ae), "b"); assertEqualInt(archive_entry_filetype(ae), AE_IFLNK); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString(archive_entry_pathname(ae), "c"); assertEqualInt(archive_entry_filetype(ae), AE_IFREG); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(3, archive_file_count(a)); assertEqualInt(ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); assertChdir(".."); }
struct pkg_vulnerabilities * read_pkg_vulnerabilities_memory(void *buf, size_t len, int check_sum) { #ifdef BOOTSTRAP errx(EXIT_FAILURE, "Audit functions are unsupported during bootstrap"); #else struct archive *a; struct pkg_vulnerabilities *pv; if ((a = archive_read_new()) == NULL) errx(EXIT_FAILURE, "memory allocation failed"); if (archive_read_support_compression_all(a) != ARCHIVE_OK || archive_read_support_format_raw(a) != ARCHIVE_OK || archive_read_open_memory(a, buf, len) != ARCHIVE_OK) errx(EXIT_FAILURE, "Cannot open pkg_vulnerabilies buffer: %s", archive_error_string(a)); pv = read_pkg_vulnerabilities_archive(a, check_sum); return pv; #endif }
Installer::ProceedState RomInstaller::on_checked_device() { // /sbin is not going to be populated with anything useful in a normal boot // image. We can almost guarantee that a recovery image is going to be // installed though, so we'll open the recovery partition with libmbp and // extract its /sbin with libarchive into the chroot's /sbin. std::string block_dev(_recovery_block_dev); mbp::BootImage bi; mbp::CpioFile innerCpio; const unsigned char *ramdisk_data; std::size_t ramdisk_size; bool using_boot = false; // Check if the device has a combined boot/recovery partition. If the // FOTAKernel partition is listed, it will be used instead of the combined // ramdisk from the boot image bool combined = mb_device_flags(_device) & FLAG_HAS_COMBINED_BOOT_AND_RECOVERY; if (combined && block_dev.empty()) { block_dev = _boot_block_dev; using_boot = true; } if (block_dev.empty()) { display_msg("Could not determine the recovery block device"); return ProceedState::Fail; } if (!bi.loadFile(block_dev)) { display_msg("Failed to load recovery partition image"); return ProceedState::Fail; } // Load ramdisk bi.ramdiskImageC(&ramdisk_data, &ramdisk_size); if (using_boot) { if (!innerCpio.load(ramdisk_data, ramdisk_size)) { display_msg("Failed to load ramdisk from combined boot image"); return ProceedState::Fail; } if (!innerCpio.contentsC("sbin/ramdisk-recovery.cpio", &ramdisk_data, &ramdisk_size)) { display_msg("Could not find recovery ramdisk in combined boot image"); return ProceedState::Fail; } } autoclose::archive in(archive_read_new(), archive_read_free); autoclose::archive out(archive_write_disk_new(), archive_write_free); if (!in || !out) { LOGE("Out of memory"); return ProceedState::Fail; } archive_entry *entry; // Set up input archive_read_support_filter_gzip(in.get()); archive_read_support_filter_lzop(in.get()); archive_read_support_filter_lz4(in.get()); archive_read_support_filter_lzma(in.get()); archive_read_support_filter_xz(in.get()); archive_read_support_format_cpio(in.get()); int ret = archive_read_open_memory(in.get(), const_cast<unsigned char *>(ramdisk_data), ramdisk_size); if (ret != ARCHIVE_OK) { LOGW("Failed to open recovery ramdisk: %s", archive_error_string(in.get())); return ProceedState::Fail; } // Set up output archive_write_disk_set_options(out.get(), ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_SECURE_NODOTDOT | ARCHIVE_EXTRACT_SECURE_SYMLINKS | ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_UNLINK | ARCHIVE_EXTRACT_XATTR); while ((ret = archive_read_next_header(in.get(), &entry)) == ARCHIVE_OK) { std::string path = archive_entry_pathname(entry); if (path == "default.prop") { path = "default.recovery.prop"; } else if (!util::starts_with(path, "sbin/")) { continue; } LOGE("Copying from recovery: %s", path.c_str()); archive_entry_set_pathname(entry, in_chroot(path).c_str()); if (util::libarchive_copy_header_and_data( in.get(), out.get(), entry) != ARCHIVE_OK) { return ProceedState::Fail; } archive_entry_set_pathname(entry, path.c_str()); } if (ret != ARCHIVE_EOF) { LOGE("Archive extraction ended without reaching EOF: %s", archive_error_string(in.get())); return ProceedState::Fail; } // Create fake /etc/fstab file to please installers that read the file std::string etc_fstab(in_chroot("/etc/fstab")); if (access(etc_fstab.c_str(), R_OK) < 0 && errno == ENOENT) { autoclose::file fp(autoclose::fopen(etc_fstab.c_str(), "w")); if (fp) { auto system_devs = mb_device_system_block_devs(_device); auto cache_devs = mb_device_cache_block_devs(_device); auto data_devs = mb_device_data_block_devs(_device); // Set block device if it's provided and non-empty const char *system_dev = system_devs && system_devs[0] && system_devs[0][0] ? system_devs[0] : "dummy"; const char *cache_dev = cache_devs && cache_devs[0] && cache_devs[0][0] ? cache_devs[0] : "dummy"; const char *data_dev = data_devs && data_devs[0] && data_devs[0][0] ? data_devs[0] : "dummy"; fprintf(fp.get(), "%s /system ext4 rw 0 0\n", system_dev); fprintf(fp.get(), "%s /cache ext4 rw 0 0\n", cache_dev); fprintf(fp.get(), "%s /data ext4 rw 0 0\n", data_dev); } } // Load recovery properties util::file_get_all_properties( in_chroot("/default.recovery.prop"), &_recovery_props); return ProceedState::Continue; }
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_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 }
Installer::ProceedState RomInstaller::on_checked_device() { // /sbin is not going to be populated with anything useful in a normal boot // image. We can almost guarantee that a recovery image is going to be // installed though, so we'll open the recovery partition with libmbp and // extract its /sbin with libarchive into the chroot's /sbin. mbp::BootImage bi; if (!bi.loadFile(_recovery_block_dev)) { display_msg("Failed to load recovery partition image"); return ProceedState::Fail; } const unsigned char *ramdisk_data; std::size_t ramdisk_size; bi.ramdiskImageC(&ramdisk_data, &ramdisk_size); autoclose::archive in(archive_read_new(), archive_read_free); autoclose::archive out(archive_write_disk_new(), archive_write_free); if (!in | !out) { LOGE("Out of memory"); return ProceedState::Fail; } archive_entry *entry; // Set up input archive_read_support_filter_gzip(in.get()); archive_read_support_filter_lzop(in.get()); archive_read_support_filter_lz4(in.get()); archive_read_support_filter_lzma(in.get()); archive_read_support_format_cpio(in.get()); int ret = archive_read_open_memory(in.get(), const_cast<unsigned char *>(ramdisk_data), ramdisk_size); if (ret != ARCHIVE_OK) { LOGW("Failed to open recovery ramdisk: %s", archive_error_string(in.get())); return ProceedState::Fail; } // Set up output archive_write_disk_set_options(out.get(), ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_SECURE_NODOTDOT | ARCHIVE_EXTRACT_SECURE_SYMLINKS | ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_UNLINK | ARCHIVE_EXTRACT_XATTR); while ((ret = archive_read_next_header(in.get(), &entry)) == ARCHIVE_OK) { std::string path = archive_entry_pathname(entry); if (!util::starts_with(path, "sbin/")) { continue; } LOGE("Copying from recovery: %s", path.c_str()); archive_entry_set_pathname(entry, (_chroot + "/" + path).c_str()); if (util::archive_copy_header_and_data(in.get(), out.get(), entry) != ARCHIVE_OK) { return ProceedState::Fail; } archive_entry_set_pathname(entry, path.c_str()); } if (ret != ARCHIVE_EOF) { LOGE("Archive extraction ended without reaching EOF: %s", archive_error_string(in.get())); return ProceedState::Fail; } return ProceedState::Continue; }
static void test_fuzz(const struct files *filesets) { const void *blk; size_t blk_size; int64_t blk_offset; int n; for (n = 0; filesets[n].names != NULL; ++n) { const size_t buffsize = 30000000; struct archive_entry *ae; struct archive *a; char *rawimage = NULL, *image = NULL, *tmp = NULL; size_t size = 0, oldsize = 0; int i, q; extract_reference_files(filesets[n].names); if (filesets[n].uncompress) { int r; /* Use format_raw to decompress the data. */ assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_raw(a)); r = archive_read_open_filenames(a, filesets[n].names, 16384); if (r != ARCHIVE_OK) { archive_read_free(a); if (filesets[n].names[0] == NULL || filesets[n].names[1] == NULL) { skipping("Cannot uncompress fileset"); } else { skipping("Cannot uncompress %s", filesets[n].names[0]); } continue; } assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); rawimage = malloc(buffsize); size = archive_read_data(a, rawimage, buffsize); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); assert(size > 0); if (filesets[n].names[0] == NULL || filesets[n].names[1] == NULL) { failure("Internal buffer is not big enough for " "uncompressed test files"); } else { failure("Internal buffer is not big enough for " "uncompressed test file: %s", filesets[n].names[0]); } if (!assert(size < buffsize)) { free(rawimage); continue; } } else { for (i = 0; filesets[n].names[i] != NULL; ++i) { tmp = slurpfile(&size, filesets[n].names[i]); char *newraw = (char *)realloc(rawimage, oldsize + size); if (!assert(newraw != NULL)) { free(rawimage); continue; } rawimage = newraw; memcpy(rawimage + oldsize, tmp, size); oldsize += size; size = oldsize; free(tmp); } } if (size == 0) continue; image = malloc(size); assert(image != NULL); if (image == NULL) { free(rawimage); return; } srand((unsigned)time(NULL)); for (i = 0; i < 1000; ++i) { FILE *f; int j, numbytes, trycnt; /* Fuzz < 1% of the bytes in the archive. */ memcpy(image, rawimage, size); q = (int)size / 100; if (q < 4) q = 4; numbytes = (int)(rand() % q); for (j = 0; j < numbytes; ++j) image[rand() % size] = (char)rand(); /* Save the messed-up image to a file. * If we crash, that file will be useful. */ for (trycnt = 0; trycnt < 3; trycnt++) { f = fopen("after.test.failure.send.this.file." "to.libarchive.maintainers.with.system.details", "wb"); if (f != NULL) break; #if defined(_WIN32) && !defined(__CYGWIN__) /* * Sometimes previous close operation does not completely * end at this time. So we should take a wait while * the operation running. */ Sleep(100); #endif } assertEqualInt((size_t)size, fwrite(image, 1, (size_t)size, f)); fclose(f); // Try to read all headers and bodies. assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); if (0 == archive_read_open_memory(a, image, size)) { while(0 == archive_read_next_header(a, &ae)) { while (0 == archive_read_data_block(a, &blk, &blk_size, &blk_offset)) continue; } archive_read_close(a); } archive_read_free(a); // Just list headers, skip bodies. assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); if (0 == archive_read_open_memory(a, image, size)) { while(0 == archive_read_next_header(a, &ae)) { } archive_read_close(a); } archive_read_free(a); } free(image); free(rawimage); } }
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 void *load_repo(void *repo_obj) { char repofile[FILENAME_MAX]; _cleanup_free_ char *line = NULL; struct archive *a; struct archive_entry *e; struct pkg_t pkg; struct repo_t *repo; struct result_t *result; struct stat st; void *repodata = MAP_FAILED; struct archive_line_reader read_buffer = {}; repo = repo_obj; snprintf(repofile, sizeof(repofile), CACHEPATH "/%s.files", repo->name); result = result_new(repo->name, 50); a = archive_read_new(); archive_read_support_format_all(a); archive_read_support_filter_all(a); MALLOC(line, MAX_LINE_SIZE, return NULL); repo->fd = open(repofile, O_RDONLY); if (repo->fd < 0) { /* fail silently if the file doesn't exist */ if (errno != ENOENT) { fprintf(stderr, "error: failed to open repo: %s: %s\n", repofile, strerror(errno)); } goto cleanup; } fstat(repo->fd, &st); repodata = mmap(0, st.st_size, PROT_READ, MAP_SHARED | MAP_POPULATE, repo->fd, 0); if (repodata == MAP_FAILED) { fprintf(stderr, "error: failed to map pages for %s: %s\n", repofile, strerror(errno)); goto cleanup; } if (archive_read_open_memory(a, repodata, st.st_size) != ARCHIVE_OK) { fprintf(stderr, "error: failed to load repo: %s: %s\n", repofile, archive_error_string(a)); goto cleanup; } while (archive_read_next_header(a, &e) == ARCHIVE_OK) { const char *entryname = archive_entry_pathname(e); size_t len; int r; if (entryname == NULL) { /* libarchive error */ continue; } len = strlen(entryname); r = parse_pkgname(&pkg, entryname, len); if (r < 0) { fprintf(stderr, "error parsing pkgname from: %s: %s\n", entryname, strerror(-r)); continue; } memset(&read_buffer, 0, sizeof(struct archive_line_reader)); read_buffer.line.base = line; r = config.filefunc(repo->name, &pkg, a, result, &read_buffer); if (r < 0) { break; } } archive_read_close(a); cleanup: archive_read_free(a); if (repo->fd >= 0) { close(repo->fd); } if (repodata != MAP_FAILED) { munmap(repodata, st.st_size); } return result; }
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); }
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); }