int Tarball::install () { archive_entry *entry; int r; archive* a = archive_read_new(); archive_read_support_format_all(a); archive_read_support_filter_all(a); archive* ext = archive_write_disk_new(); const int flags = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS; archive_write_disk_set_options(ext, flags); archive_write_disk_set_standard_lookup(ext); const std::string subdir = "deps"; const std::string filename = subdir + "/" + basename(this->location); printf("Unpacking archive %s\n", filename.c_str()); if ((r = archive_read_open_filename(a,filename.c_str(), 10240))) { fprintf(stderr, "Error opening archive:\n%s\n", archive_error_string(a)); return -1; } for (;;) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) { break; } if (r < ARCHIVE_OK) { fprintf(stderr, "%s\n", archive_error_string(a)); } if (r < ARCHIVE_WARN) { return -1; } rewrite_subdir(entry, subdir); r = archive_write_header(ext, entry); if (r < ARCHIVE_OK) { fprintf(stderr, "%s\n", archive_error_string(ext)); } else if (archive_entry_size(entry) > 0) { r = copy_data(a, ext); if (r < ARCHIVE_OK) { fprintf(stderr, "%s\n", archive_error_string(ext)); } if (r < ARCHIVE_WARN) { return -1; } } r = archive_write_finish_entry(ext); if (r < ARCHIVE_OK) { fprintf(stderr, "%s\n", archive_error_string(ext)); } if (r < ARCHIVE_WARN) { return -1; } } archive_read_close(a); archive_read_free(a); archive_write_close(ext); archive_write_free(ext); return 0; };
static struct extract * get_extract(struct archive_read *a) { /* If we haven't initialized, do it now. */ /* This also sets up a lot of global state. */ if (a->extract == NULL) { a->extract = (struct extract *)malloc(sizeof(*a->extract)); if (a->extract == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't extract"); return (NULL); } memset(a->extract, 0, sizeof(*a->extract)); a->extract->ad = archive_write_disk_new(); if (a->extract->ad == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't extract"); return (NULL); } if (archive_write_disk_set_standard_lookup(a->extract->ad)) { archive_set_error(&a->archive, ENOMEM, "Can't extract"); return (NULL); } a->cleanup_archive_extract = archive_read_extract_cleanup; } return (a->extract); }
/* * 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; }
int extract_archive(const char* filename, const char* to_path) { struct archive* a; struct archive* ext; struct archive_entry* entry; int r; int flags = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS; a = archive_read_new(); ext = archive_write_disk_new(); archive_write_disk_set_options(ext, flags); archive_write_disk_set_standard_lookup(ext); archive_read_support_format_all(a); archive_read_support_compression_all(a); if(filename != NULL && strcmp(filename, "-") == 0) { filename = NULL; } if((r = archive_read_open_file(a, filename, 10240))) { printf("archive_read_open_file(): %s\n", archive_error_string(a)); return r; } for(;;) { r = archive_read_next_header(a, &entry); if(r == ARCHIVE_EOF) { break; } if(r != ARCHIVE_OK) { printf("archive_read_next_header(): %s\n", archive_error_string(a)); return 0; } // rewrite pathname const char* path = archive_entry_pathname(entry); char new_path[PATH_MAX + 1]; sprintf(new_path, "%s/%s", to_path, path + (strncmp(path, "rootfs/", 7) == 0 ? 7 : 0)); archive_entry_set_pathname(entry, new_path); r = archive_write_header(ext, entry); if(r != ARCHIVE_OK) { printf("archive_write_header(): %s\n", archive_error_string(ext)); } else { copy_data(a, ext); if(r != ARCHIVE_OK) { printf("archive_write_finish_entry(): %s\n", archive_error_string(ext)); return 0; } } r = archive_write_finish_entry(ext); } archive_read_close(a); archive_read_finish(a); archive_write_close(ext); archive_write_finish(ext); return 1; }
static void mode_pass(struct cpio *cpio, const char *destdir) { struct lafe_line_reader *lr; const char *p; int r; /* Ensure target dir has a trailing '/' to simplify path surgery. */ cpio->destdir = malloc(strlen(destdir) + 8); strcpy(cpio->destdir, destdir); if (destdir[strlen(destdir) - 1] != '/') strcat(cpio->destdir, "/"); cpio->archive = archive_write_disk_new(); if (cpio->archive == NULL) lafe_errc(1, 0, "Failed to allocate archive object"); r = archive_write_disk_set_options(cpio->archive, cpio->extract_flags); if (r != ARCHIVE_OK) lafe_errc(1, 0, "%s", archive_error_string(cpio->archive)); cpio->linkresolver = archive_entry_linkresolver_new(); archive_write_disk_set_standard_lookup(cpio->archive); cpio->archive_read_disk = archive_read_disk_new(); if (cpio->archive_read_disk == NULL) lafe_errc(1, 0, "Failed to allocate archive object"); if (cpio->option_follow_links) archive_read_disk_set_symlink_logical(cpio->archive_read_disk); else archive_read_disk_set_symlink_physical(cpio->archive_read_disk); archive_read_disk_set_standard_lookup(cpio->archive_read_disk); lr = lafe_line_reader("-", cpio->option_null); while ((p = lafe_line_reader_next(lr)) != NULL) file_to_archive(cpio, p); lafe_line_reader_free(lr); archive_entry_linkresolver_free(cpio->linkresolver); r = archive_write_close(cpio->archive); if (cpio->dot) fprintf(stderr, "\n"); if (r != ARCHIVE_OK) lafe_errc(1, 0, "%s", archive_error_string(cpio->archive)); if (!cpio->quiet) { int64_t blocks = (archive_filter_bytes(cpio->archive, 0) + 511) / 512; fprintf(stderr, "%lu %s\n", (unsigned long)blocks, blocks == 1 ? "block" : "blocks"); } archive_write_free(cpio->archive); }
// Based on libarchive's public example code. // https://github.com/libarchive/libarchive/wiki/Examples#wiki-Constructing_Objects_On_Disk void GuiZipper::unpackFile(const char *zipFile, const char *outputDir) throw (ZipperException*) { // TODO: use archive_write_disk_open instead (if/when it exists) char cwd[4096]; getcwd(cwd, 4096); char *absZipFile = fileManager_->getAbsFilePath(zipFile); platformstl::filesystem_traits<char> traits; traits.set_current_directory(outputDir); struct archive *a; struct archive *ext; struct archive_entry *entry; int flags; int r; flags = ARCHIVE_EXTRACT_TIME; flags |= ARCHIVE_EXTRACT_PERM; flags |= ARCHIVE_EXTRACT_ACL; flags |= ARCHIVE_EXTRACT_FFLAGS; a = archive_read_new(); archive_read_support_format_tar(a); archive_read_support_filter_gzip(a); ext = archive_write_disk_new(); archive_write_disk_set_options(ext, flags); archive_write_disk_set_standard_lookup(ext); r = archive_read_open_filename(a, absZipFile, 10240); checkForErrors("Error opening archive for reading", a, r); for (;;) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) { break; } checkForErrors("Error reading next archive header", a, r); r = archive_write_header(ext, entry); checkForErrors("Error writing next archive header", a, r); copyData(a, ext, outputDir); r = archive_write_finish_entry(ext); checkForErrors("Error writing archive finish entry", a, r); } r = archive_read_close(a); checkForErrors("Error closing read archive", a, r); r = archive_read_free(a); checkForErrors("Error freeing read archive", a, r); r = archive_write_close(ext); checkForErrors("Error closing write archive", a, r); r = archive_write_free(ext); checkForErrors("Error freeing write archive", a, r); traits.set_current_directory(cwd); delete absZipFile; }
static void extract(const char *filename) { struct archive *a; struct archive *ext; struct archive_entry *entry; int flags; int r; flags = ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM; a = archive_read_new(); archive_read_support_format_all(a); #if ARCHIVE_VERSION_NUMBER < 3000000 archive_read_support_compression_all(a); #else archive_read_support_filter_all(a); #endif ext = archive_write_disk_new(); archive_write_disk_set_options(ext, flags); archive_write_disk_set_standard_lookup(ext); #if ARCHIVE_VERSION_NUMBER < 3000000 if ((r = archive_read_open_file(a, filename, 10240))) die("archive_read_open_file"); #else if ((r = archive_read_open_filename(a, filename, 10240))) die("archive_read_open_filename"); #endif for (;;) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) break; if (r < ARCHIVE_WARN) die(archive_error_string(a)); r = archive_write_header(ext, entry); if (r == ARCHIVE_OK && archive_entry_size(entry) > 0) { r = copy_data(a, ext); if (r < ARCHIVE_WARN) die(archive_error_string(a)); } r = archive_write_finish_entry(ext); if (r < ARCHIVE_WARN) die(archive_error_string(ext)); } archive_read_close(a); archive_read_free(a); archive_write_close(ext); archive_write_free(ext); }
void tar_mode_x(struct bsdtar *bsdtar) { struct archive *writer; writer = archive_write_disk_new(); if (writer == NULL) lafe_errc(1, ENOMEM, "Cannot allocate disk writer object"); if (!bsdtar->option_numeric_owner) archive_write_disk_set_standard_lookup(writer); archive_write_disk_set_options(writer, bsdtar->extract_flags); read_archive(bsdtar, 'x', writer); if (lafe_unmatched_inclusions_warn(bsdtar->matching, "Not found in archive") != 0) bsdtar->return_value = 1; archive_write_free(writer); }
static void mode_pass(struct cpio *cpio, const char *destdir) { unsigned long blocks; struct line_reader *lr; const char *p; int r; /* Ensure target dir has a trailing '/' to simplify path surgery. */ cpio->destdir = malloc(strlen(destdir) + 8); strcpy(cpio->destdir, destdir); if (destdir[strlen(destdir) - 1] != '/') strcat(cpio->destdir, "/"); cpio->archive = archive_write_disk_new(); if (cpio->archive == NULL) cpio_errc(1, 0, "Failed to allocate archive object"); r = archive_write_disk_set_options(cpio->archive, cpio->extract_flags); if (r != ARCHIVE_OK) cpio_errc(1, 0, archive_error_string(cpio->archive)); cpio->linkresolver = archive_entry_linkresolver_new(); archive_write_disk_set_standard_lookup(cpio->archive); lr = process_lines_init("-", cpio->line_separator); while ((p = process_lines_next(lr)) != NULL) file_to_archive(cpio, p); process_lines_free(lr); archive_entry_linkresolver_free(cpio->linkresolver); r = archive_write_close(cpio->archive); if (r != ARCHIVE_OK) cpio_errc(1, 0, archive_error_string(cpio->archive)); if (!cpio->quiet) { blocks = (archive_position_uncompressed(cpio->archive) + 511) / 512; fprintf(stderr, "%lu %s\n", blocks, blocks == 1 ? "block" : "blocks"); } archive_write_finish(cpio->archive); }
static struct archive *open_disk(int flags) { struct archive *disk; int r; disk = archive_write_disk_new(); if (!disk) { opkg_msg(ERROR, "Failed to create disk archive object.\n"); return NULL; } r = archive_write_disk_set_options(disk, flags); if (r == ARCHIVE_WARN) opkg_msg(NOTICE, "Warning when setting disk options: %s\n", archive_error_string(disk)); else if (r != ARCHIVE_OK) { opkg_msg(ERROR, "Failed to set disk options: %s\n", archive_error_string(disk)); goto err_cleanup; } r = archive_write_disk_set_standard_lookup(disk); if (r == ARCHIVE_WARN) opkg_msg(NOTICE, "Warning when setting user/group lookup functions: %s\n", archive_error_string(disk)); else if (r != ARCHIVE_OK) { opkg_msg(ERROR, "Failed to set user/group lookup functions: %s\n", archive_error_string(disk)); goto err_cleanup; } return disk; err_cleanup: archive_write_free(disk); return NULL; }
RESULTCODE ArchiveProcessorImpl::Decompress() { const char* tpath = GetArchivePath(); if(tpath==NULL) { return AG_FAILURE; } struct archive *a; struct archive *ext; struct archive_entry *entry; int flags; int r; /* Select which attributes we want to restore. */ flags = ARCHIVE_EXTRACT_TIME; flags |= ARCHIVE_EXTRACT_PERM; flags |= ARCHIVE_EXTRACT_ACL; flags |= ARCHIVE_EXTRACT_FFLAGS; a = archive_read_new(); archive_read_support_format_all(a); archive_read_support_compression_all(a); ext = archive_write_disk_new(); archive_write_disk_set_options(ext, flags); archive_write_disk_set_standard_lookup(ext); if((r = archive_read_open_filename(a, tpath, 10240))) { return AG_FAILURE; } while(true) { r = archive_read_next_header(a, &entry); if( r== ARCHIVE_EOF) { break; } if( r < ARCHIVE_OK) { fprintf(stderr, "%s\n", archive_error_string(a)); } if( r< ARCHIVE_WARN) { break; } r = archive_write_header(ext, entry); if (r < ARCHIVE_OK) { fprintf(stderr, "%s\n", archive_error_string(ext)); } else if (archive_entry_size(entry) > 0) { r = copy_data(a, ext); } if (r < ARCHIVE_OK) { fprintf(stderr, "%s\n", archive_error_string(ext)); } if (r < ARCHIVE_WARN) { break; } r = archive_write_finish_entry(ext); if (r < ARCHIVE_OK) { fprintf(stderr, "%s\n", archive_error_string(ext)); } if(r < ARCHIVE_WARN) { break; } } archive_read_close(a); archive_read_free(a); archive_write_close(ext); archive_write_free(ext); //return r==ARCHIVE_OK ? AG_SUCCESS : AG_FAILURE; return AG_SUCCESS; }
static bool extract_theme(const std::string &path, const std::string &target, const std::string &theme_name) { mb::autoclose::archive in(archive_read_new(), archive_read_free); if (!in) { LOGE("%s: Out of memory when creating archive reader", __FUNCTION__); return false; } mb::autoclose::archive out(archive_write_disk_new(), archive_write_free); if (!out) { LOGE("%s: Out of memory when creating disk writer", __FUNCTION__); return false; } archive_read_support_format_zip(in.get()); // Set up disk writer parameters. We purposely don't extract any file // metadata int flags = ARCHIVE_EXTRACT_SECURE_SYMLINKS | ARCHIVE_EXTRACT_SECURE_NODOTDOT; archive_write_disk_set_standard_lookup(out.get()); archive_write_disk_set_options(out.get(), flags); if (archive_read_open_filename(in.get(), path.c_str(), 10240) != ARCHIVE_OK) { LOGE("%s: Failed to open file: %s", path.c_str(), archive_error_string(in.get())); return false; } archive_entry *entry; int ret; std::string target_path; std::string common_prefix("theme/common/"); std::string theme_prefix("theme/"); theme_prefix += theme_name; theme_prefix += '/'; while (true) { ret = archive_read_next_header(in.get(), &entry); if (ret == ARCHIVE_EOF) { break; } else if (ret == ARCHIVE_RETRY) { LOGW("%s: Retrying header read", path.c_str()); continue; } else if (ret != ARCHIVE_OK) { LOGE("%s: Failed to read header: %s", path.c_str(), archive_error_string(in.get())); return false; } const char *path = archive_entry_pathname(entry); if (!path || !*path) { LOGE("%s: Header has null or empty filename", path); return false; } const char *suffix; if (mb::util::starts_with(path, common_prefix)) { suffix = path + common_prefix.size(); } else if (mb::util::starts_with(path, theme_prefix)) { suffix = path + theme_prefix.size(); } else { LOGV("Skipping: %s", path); continue; } // Build path target_path = target; if (target_path.back() != '/' && *suffix != '/') { target_path += '/'; } target_path += suffix; LOGV("Extracting: %s -> %s", path, target_path.c_str()); archive_entry_set_pathname(entry, target_path.c_str()); // Extract file ret = archive_read_extract2(in.get(), entry, out.get()); if (ret != ARCHIVE_OK) { LOGE("%s: %s", archive_entry_pathname(entry), archive_error_string(in.get())); return false; } } if (archive_read_close(in.get()) != ARCHIVE_OK) { LOGE("%s: Failed to close file: %s", path.c_str(), archive_error_string(in.get())); return false; } return true; }
bool libarchive_tar_extract(const std::string &filename, const std::string &target, const std::vector<std::string> &patterns) { if (target.empty()) { LOGE("%s: Invalid target path for extraction", target.c_str()); return false; } autoclose::archive matcher(archive_match_new(), archive_match_free); if (!matcher) { LOGE("%s: Out of memory when creating matcher", __FUNCTION__); return false; } autoclose::archive in(archive_read_new(), archive_read_free); if (!in) { LOGE("%s: Out of memory when creating archive reader", __FUNCTION__); return false; } autoclose::archive out(archive_write_disk_new(), archive_write_free); if (!out) { LOGE("%s: Out of memory when creating disk writer", __FUNCTION__); return false; } // Set up matcher parameters for (const std::string &pattern : patterns) { if (archive_match_include_pattern( matcher.get(), pattern.c_str()) != ARCHIVE_OK) { LOGE("Invalid pattern: %s", pattern.c_str()); return false; } } // Set up archive reader parameters //archive_read_support_format_gnutar(in.get()); archive_read_support_format_tar(in.get()); //archive_read_support_filter_bzip2(in.get()); //archive_read_support_filter_gzip(in.get()); //archive_read_support_filter_xz(in.get()); // Set up disk writer parameters archive_write_disk_set_standard_lookup(out.get()); archive_write_disk_set_options(out.get(), LIBARCHIVE_DISK_WRITER_FLAGS); if (archive_read_open_filename( in.get(), filename.c_str(), 10240) != ARCHIVE_OK) { LOGE("%s: Failed to open file: %s", filename.c_str(), archive_error_string(in.get())); return false; } archive_entry *entry; int ret; std::string target_path; while (true) { ret = archive_read_next_header(in.get(), &entry); if (ret == ARCHIVE_EOF) { break; } else if (ret == ARCHIVE_RETRY) { LOGW("%s: Retrying header read", filename.c_str()); continue; } else if (ret != ARCHIVE_OK) { LOGE("%s: Failed to read header: %s", filename.c_str(), archive_error_string(in.get())); return false; } const char *path = archive_entry_pathname(entry); if (!path || !*path) { LOGE("%s: Header has null or empty filename", filename.c_str()); return false; } LOGV("%s", path); // Build path target_path = target; if (target_path.back() != '/' && *path != '/') { target_path += '/'; } target_path += path; archive_entry_set_pathname(entry, target_path.c_str()); // Check pattern matches if (archive_match_excluded(matcher.get(), entry)) { continue; } // Extract file ret = archive_read_extract2(in.get(), entry, out.get()); if (ret != ARCHIVE_OK) { LOGE("%s: %s", archive_entry_pathname(entry), archive_error_string(in.get())); return false; } } if (archive_read_close(in.get()) != ARCHIVE_OK) { LOGE("%s: %s", filename.c_str(), archive_error_string(in.get())); return false; } // Check that all patterns were matched const char *pattern; while ((ret = archive_match_path_unmatched_inclusions_next( matcher.get(), &pattern)) == ARCHIVE_OK) { LOGE("%s: Pattern not matched: %s", filename.c_str(), pattern); } if (ret != ARCHIVE_EOF) { LOGE("%s: %s", filename.c_str(), archive_error_string(matcher.get())); return false; } return archive_match_path_unmatched_inclusions(matcher.get()) == 0; }
void Package::readPackageFile(const std::string &package_path) { if (!package_path.empty()) mPackagePath = package_path; boost::filesystem::path unpacked_dir = mWorkDir; unpacked_dir /= mPackagePath.stem(); mUnpackedDir = unpacked_dir; const void *buf; int r; struct archive *a = archive_read_new(); struct archive_entry *entry; archive_read_support_compression_bzip2(a); archive_read_support_format_tar(a); struct archive *ext = archive_write_disk_new(); int flags = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS; archive_write_disk_set_options(ext, flags); archive_write_disk_set_standard_lookup(ext); r = archive_read_open_filename(a, package_path.c_str(), 16384); if (r != ARCHIVE_OK) { archive_read_free(a); archive_write_free(ext); throw Exception(std::string("archive_read_open_filename() failed for file: ") + package_path); } while (true) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) { break; } if (r < ARCHIVE_OK) { std::cerr << archive_error_string(ext) << std::endl; } if (r < ARCHIVE_WARN) { archive_read_free(a); archive_write_free(ext); throw Exception(std::string("archive_read_next_header() failed:") + archive_error_string(a)); } std::cout << std::string("extract: ") << archive_entry_pathname(entry) << std::endl; archive_entry_set_pathname(entry, (mUnpackedDir.string() + std::string("/") + archive_entry_pathname(entry)).c_str()); r = archive_write_header(ext, entry); if (r < ARCHIVE_OK) { archive_read_free(a); archive_write_free(ext); throw Exception(std::string("archive_write_header() failed:") + archive_error_string(ext)); } else if (archive_entry_size(entry) > 0) { size_t size; int64_t offset; while (true) { r = archive_read_data_block(a, &buf, &size, &offset); if (r == ARCHIVE_EOF) break; if (r < ARCHIVE_WARN) { archive_read_free(a); archive_write_free(ext); throw Exception(std::string(archive_error_string(ext))); } if (r < ARCHIVE_OK) { std::cerr << archive_error_string(ext) << std::endl; break; } r = archive_write_data_block(ext, buf, size, offset); if (r < ARCHIVE_WARN) { archive_read_free(a); archive_write_free(ext); throw Exception(std::string(archive_error_string(ext))); } if (r < ARCHIVE_OK) { std::cerr << archive_error_string(ext) << std::endl; break; } } r = archive_write_finish_entry(ext); if (r < ARCHIVE_OK) std::cerr << archive_error_string(ext) << std::endl; if (r < ARCHIVE_WARN) { archive_read_free(a); archive_write_free(ext); throw Exception(std::string(archive_error_string(ext))); } } } archive_read_close(a); archive_read_free(a); archive_write_close(ext); archive_write_free(ext); }
void mfu_flist_archive_extract(const char* filename, bool verbose, int flags) { int r; /* TODO: this needs to be parallelized */ /* initiate archive object for reading */ struct archive* a = archive_read_new(); /* initiate archive object for writing */ struct archive* ext = archive_write_disk_new(); archive_write_disk_set_options(ext, flags); /* we want all the format supports */ archive_read_support_filter_bzip2(a); archive_read_support_filter_gzip(a); archive_read_support_filter_compress(a); archive_read_support_format_tar(a); archive_write_disk_set_standard_lookup(ext); if (filename != NULL && strcmp(filename, "-") == 0) { filename = NULL; } /* blocksize set to 1024K */ if ((r = archive_read_open_filename(a, filename, 10240))) { errmsg(archive_error_string(a)); exit(r); } struct archive_entry* entry; for (;;) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) { break; } if (r != ARCHIVE_OK) { errmsg(archive_error_string(a)); exit(r); } if (verbose) { msg("x "); } if (verbose) { msg(archive_entry_pathname(entry)); } r = archive_write_header(ext, entry); if (r != ARCHIVE_OK) { errmsg(archive_error_string(a)); } else { copy_data(a, ext); } if (verbose) { msg("\n"); } } archive_read_close(a); archive_read_free(a); }
static void extract_archive(const char *filename, const char *output) { struct archive *a; struct archive *ext; struct archive_entry *entry; int flags; int r; flags = ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_SECURE_NODOTDOT; a = archive_read_new(); #if ARCHIVE_VERSION_NUMBER < 4000000 archive_read_support_compression_bzip2(a); #else archive_read_support_filter_bzip2(a); #endif archive_read_support_format_tar(a); ext = archive_write_disk_new(); archive_write_disk_set_options(ext, flags); archive_write_disk_set_standard_lookup(ext); r = archive_read_open_file(a, filename, 10240); if (r) { std::string msg = extract_archive_error(filename, output, a); archive_read_close(a); #if ARCHIVE_VERSION_NUMBER < 4000000 archive_read_finish(a); #else archive_read_free(a); #endif throw utils::InternalError(msg); } for (;;) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) { break; } if (r != ARCHIVE_OK) { std::string msg = extract_archive_error(filename, output, a); archive_read_close(a); #if ARCHIVE_VERSION_NUMBER < 4000000 archive_read_finish(a); #else archive_read_free(a); #endif archive_write_close(ext); #if ARCHIVE_VERSION_NUMBER < 4000000 archive_write_finish(ext); #else archive_write_free(ext); #endif throw utils::InternalError(msg); } if (r < ARCHIVE_WARN) { break; } r = archive_write_header(ext, entry); if (r != ARCHIVE_OK) { std::string msg = extract_archive_error(filename, output, a); archive_read_close(a); #if ARCHIVE_VERSION_NUMBER < 4000000 archive_read_finish(a); #else archive_read_free(a); #endif archive_write_close(ext); #if ARCHIVE_VERSION_NUMBER < 4000000 archive_write_finish(ext); #else archive_write_free(ext); #endif throw utils::InternalError(msg); } else { r = copy_data(a, ext); if (r != ARCHIVE_OK) { std::string msg = extract_archive_error(filename, output, a); archive_read_close(a); #if ARCHIVE_VERSION_NUMBER < 4000000 archive_read_finish(a); #else archive_read_free(a); #endif archive_write_close(ext); #if ARCHIVE_VERSION_NUMBER < 4000000 archive_write_finish(ext); #else archive_write_free(ext); #endif throw utils::InternalError(msg); } } } archive_read_close(a); #if ARCHIVE_VERSION_NUMBER < 4000000 archive_read_finish(a); #else archive_read_free(a); #endif archive_write_close(ext); #if ARCHIVE_VERSION_NUMBER < 4000000 archive_write_finish(ext); #else archive_write_free(ext); #endif }
bool vesKiwiArchiveUtils::extractArchive(const std::string& filename, const std::string& destDir) { this->mEntries.clear(); struct archive *a; struct archive *ext; struct archive_entry *entry; int flags; int r; flags = ARCHIVE_EXTRACT_TIME; flags |= ARCHIVE_EXTRACT_PERM; flags |= ARCHIVE_EXTRACT_ACL; flags |= ARCHIVE_EXTRACT_FFLAGS; a = archive_read_new(); archive_read_support_format_all(a); archive_read_support_compression_all(a); ext = archive_write_disk_new(); archive_write_disk_set_options(ext, flags); archive_write_disk_set_standard_lookup(ext); if ((r = archive_read_open_file(a, filename.c_str(), 10240))) { this->setError("Error Opening File", "Failed to open file: " + filename); return false; } for (;;) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) break; if (r != ARCHIVE_OK) fprintf(stderr, "%s\n", archive_error_string(a)); if (r < ARCHIVE_WARN) { this->setError("Error Reading Archive", archive_error_string(a)); return false; } std::string destPath = archive_entry_pathname(entry); //printf("entry: %s\n", destPath.c_str()); if (destDir.size()) { destPath = destDir + "/" + destPath; } archive_entry_set_pathname(entry, destPath.c_str()); r = archive_write_header(ext, entry); if (r != ARCHIVE_OK) fprintf(stderr, "%s\n", archive_error_string(ext)); else if (archive_entry_size(entry) > 0) { copy_data(a, ext); if (r != ARCHIVE_OK) fprintf(stderr, "%s\n", archive_error_string(ext)); if (r < ARCHIVE_WARN) { this->setError("Error Reading Archive", archive_error_string(ext)); return false; } } r = archive_write_finish_entry(ext); if (r != ARCHIVE_OK) fprintf(stderr, "%s\n", archive_error_string(ext)); if (r < ARCHIVE_WARN) { this->setError("Error Reading Archive", archive_error_string(ext)); return false; } this->mEntries.push_back(destPath); } archive_read_close(a); archive_read_free(a); archive_write_close(ext); archive_write_free(ext); return true; }
bool ExtractArchive(const char *zip_file, const char *out_dir) { struct archive *input = archive_read_new(); archive_read_support_format_all(input); archive_read_support_compression_all(input); struct archive *output = archive_write_disk_new(); archive_write_disk_set_options(output, ARCHIVE_EXTRACT_TIME); archive_write_disk_set_standard_lookup(output); const int BLOCK_SIZE = 65536; int r = archive_read_open_filename(input, zip_file, BLOCK_SIZE); if (r != ARCHIVE_OK) { debug(("Error opening archive %s: %s\n", zip_file, archive_error_string(input))); extraction_error = IDS_BADARCHIVE; return false; } // libarchive can only extract into the current directory, so we // need to set it and restore it. char original_dir[MAX_PATH]; getcwd(original_dir, sizeof(original_dir)); chdir(out_dir); bool retval = true; while (true) { struct archive_entry *entry; r = archive_read_next_header(input, &entry); if (r == ARCHIVE_EOF) break; if (r != ARCHIVE_OK) { debug(("Error reading archive header: %s\n", archive_error_string(input))); extraction_error = IDS_BADARCHIVE; retval = false; break; } r = archive_write_header(output, entry); if (r != ARCHIVE_OK) { debug(("Error writing archive header: %s\n", archive_error_string(input))); extraction_error = IDS_UNKNOWNERROR; retval = false; break; } if (archive_entry_size(entry) > 0) { r = CopyArchiveData(input, output); if (r != ARCHIVE_OK) { debug(("CopyArchiveData error: %s\n", archive_error_string(input))); extraction_error = IDS_UNKNOWNERROR; retval = false; break; } } r = archive_write_finish_entry(output); if (r != ARCHIVE_OK) { debug(("write_finish_entry error: %s\n", archive_error_string(input))); extraction_error = IDS_UNKNOWNERROR; retval = false; break; } debug(("Archive file %s extracted\n", archive_entry_pathname(entry))); // Extraction went OK; process Windows messages ClearMessageQueue(); // Check for user hitting abort button // Check for user abort if (abort_download) { retval = false; break; } } archive_read_close(input); archive_read_free(input); archive_write_close(output); archive_write_free(output); // Go back to original working directory chdir(original_dir); return retval; }
int archive_extract_all( char *arch_file, char *dest_dir, char *suffix ) { int ret, flags; char *pwd = NULL, *filename = NULL, *filename_new = NULL, *hardlink = NULL; struct archive *arch_r = NULL, *arch_w = NULL; struct archive_entry *entry = NULL; if( !arch_file ) 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_filename( arch_r, arch_file, 10240 ) != ARCHIVE_OK ) goto errout; if( dest_dir ) { if( util_mkdir( dest_dir ) == -1 ) { if( errno == EEXIST ) { if( access( dest_dir, R_OK | W_OK | X_OK ) == -1 ) { goto errout; } } else { goto errout; } } pwd = getcwd( NULL, 0 ); chdir( dest_dir ); } flags = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_OWNER; arch_w = archive_write_disk_new(); archive_write_disk_set_options( arch_w, flags ); archive_write_disk_set_standard_lookup( arch_w ); while( archive_read_next_header( arch_r, &entry ) == ARCHIVE_OK ) { if( suffix ) filename = (char *)archive_entry_pathname( entry ); #ifdef DEBUG if( !filename ) filename = (char *)archive_entry_pathname( entry ); printf("extract:%s\n", filename ); #endif if( suffix && archive_entry_filetype( entry ) != AE_IFDIR ) { filename_new = util_strcat( filename, suffix, NULL ); archive_entry_set_pathname( entry, filename_new ); free( filename_new ); if( archive_entry_nlink( entry ) > 0 ) { hardlink = (char *)archive_entry_hardlink( entry ); if( hardlink ) { filename_new = util_strcat( hardlink, suffix, NULL ); archive_entry_set_hardlink( entry, filename_new ); free( filename_new ); } } } ret = archive_read_extract2( arch_r, entry, arch_w ); if( ret != ARCHIVE_OK && ret != ARCHIVE_WARN ) { goto errout; } #ifdef DEBUG if( ret != ARCHIVE_OK) { printf("ret:%d, file:%s, link:%d, size:%d, read_err:%s, write_err:%s\n", ret, filename, archive_entry_nlink(entry), archive_entry_size(entry), archive_error_string(arch_r), archive_error_string(arch_w)); } #endif } archive_read_finish( arch_r ); archive_write_finish( arch_w ); if( pwd ) { chdir( pwd ); free( pwd ); } return 0; errout: if( arch_r ) archive_read_finish( arch_r ); if( arch_w ) archive_write_finish( arch_w ); if( pwd ) { chdir( pwd ); free( pwd ); } return -1; }
emb_ruby_error_t emb_ruby_uncompress(){ struct archive *input_archive; struct archive *output_archive; struct archive_entry* entry; int result; int output_flags; unsigned char buff[2048]; int buffsize = 2048; int size; output_flags = ARCHIVE_EXTRACT_TIME; output_flags |= ARCHIVE_EXTRACT_PERM; output_flags |= ARCHIVE_EXTRACT_ACL; output_flags |= ARCHIVE_EXTRACT_FFLAGS; input_archive = archive_read_new(); output_archive = archive_write_disk_new(); archive_read_support_filter_gzip(input_archive); archive_read_support_format_tar(input_archive); //archive_read_support_format_raw(a); archive_write_disk_set_options(output_archive, output_flags); archive_write_disk_set_standard_lookup(output_archive); result = archive_read_open_memory(input_archive, (void*)binary_data, binary_size); if (result != ARCHIVE_OK) { fprintf(stderr, "%s\n", archive_error_string(input_archive)); return E_UNCOMPRESS_ERROR; } for (;;) { /** * Read new header from memory */ result = archive_read_next_header(input_archive, &entry); // EOF if (result == ARCHIVE_EOF) { break; } // error handling if (result != ARCHIVE_OK) { fprintf(stderr, "%s\n", archive_error_string(input_archive)); emd_ruby_uncompress_cleanup(input_archive, output_archive); return E_UNCOMPRESS_ERROR; } /** * Write new header into disk */ result = archive_write_header(output_archive, entry); // error handling if (result != ARCHIVE_OK) { fprintf(stderr, "%s\n", archive_error_string(output_archive)); emd_ruby_uncompress_cleanup(input_archive, output_archive); return E_UNCOMPRESS_ERROR; } /** * copy the data */ result = emb_ruby_uncompress_copy_data(input_archive, output_archive); if (result != ARCHIVE_OK) { fprintf(stderr, "%s\n", archive_error_string(output_archive)); emd_ruby_uncompress_cleanup(input_archive, output_archive); return E_UNCOMPRESS_ERROR; } /** * Write the trailing */ result = archive_write_finish_entry(output_archive); if (result != ARCHIVE_OK) { fprintf(stderr, "%s\n", archive_error_string(output_archive)); emd_ruby_uncompress_cleanup(input_archive, output_archive); return E_UNCOMPRESS_ERROR; } } emd_ruby_uncompress_cleanup(input_archive, output_archive); return E_SUCCESS; }
//******************************************************************************************************** void read_archive(const char* const infile, const char* const extractFolder){ // Strongly inspired by // https://github.com/libarchive/libarchive/wiki/Examples#A_Complete_Extractor //printf("Opening archive '%s' for extracting to folder '%s'...\n",infile,extractFolder); //Check that the archive exists //Check that the folder exists, if not then create it struct archive* a = archive_read_new(); archive_read_support_format_zip(a); struct archive* ext = archive_write_disk_new(); archive_write_disk_set_options(ext,ARCHIVE_EXTRACT_TIME|ARCHIVE_EXTRACT_PERM|ARCHIVE_EXTRACT_ACL|ARCHIVE_EXTRACT_FFLAGS); archive_write_disk_set_standard_lookup(ext); int err; err = archive_read_open_filename(a, infile, 10240); if (err != ARCHIVE_OK) { fprintf(stderr, "CRITICAL ERROR in read_archive(): When opening archive '%s', err=%i\n",infile,err); fprintf(stderr, "CRITICAL ERROR in read_archive(): %s\n",archive_error_string(a)); exit(EXIT_FAILURE); } struct archive_entry *entry; const int fcount_max = 1000; char fcompleted=0; //C-Boolean for(int fcount=0; fcount<fcount_max;fcount++){ err = archive_read_next_header(a,&entry); if (err == ARCHIVE_EOF){ fcompleted=1; break; } else if (err != ARCHIVE_OK){ fprintf(stderr, "CRITICAL ERROR in read_archive(): When reading archive, err=%i\n",err); fprintf(stderr, "CRITICAL ERROR in read_archive(): %s\n",archive_error_string(a)); exit(EXIT_FAILURE); } //printf("Found file: '%s'\n",archive_entry_pathname(entry)); //Avoid clobbering files in current directory - solution from // http://stackoverflow.com/questions/4496001/libarchive-to-extract-to-a-specified-folder char newPath[PATH_MAX]; int buff_used = snprintf(newPath, PATH_MAX, "%s/%s",extractFolder,archive_entry_pathname(entry)); if (buff_used >= PATH_MAX || buff_used < 0){ fprintf(stderr, "CRITICAL ERROR in read_archive(): Buffer overflow or other error when creating the path.\n"); fprintf(stderr, "CRITICAL ERROR in read_archive(): buff_used=%i\n",buff_used); exit(EXIT_FAILURE); } archive_entry_set_pathname(entry,newPath); err = archive_write_header(ext, entry); if (err != ARCHIVE_OK){ fprintf(stderr, "CRITICAL ERROR in read_archive(): when extracting archive (creating new file), err=%i\n",err); fprintf(stderr, "CRITICAL ERROR in read_archive(): %s\n",archive_error_string(ext)); exit(EXIT_FAILURE); } //Write the data! const void* buff; size_t size; la_int64_t offset; const int bcount_max = 100000000; char bcompleted = 0; //C boolean for (int bcount=0; bcount<bcount_max;bcount++){ err = archive_read_data_block(a,&buff,&size, &offset); if ( err == ARCHIVE_EOF ) { bcompleted=1; break; } else if (err != ARCHIVE_OK){ fprintf(stderr, "CRITICAL ERROR in read_archive(): When extracting archive (reading data), err=%i\n",err); fprintf(stderr, "CRITICAL ERROR in read_archive(): %s\n",archive_error_string(a)); exit(EXIT_FAILURE); } err = archive_write_data_block(ext,buff,size,offset); if (err != ARCHIVE_OK){ fprintf(stderr, "CRITICAL ERROR in read_archive(): When extracting archive (writing data), err=%i\n",err); fprintf(stderr, "CRITICAL ERROR in read_archive(): %s\n",archive_error_string(a)); exit(EXIT_FAILURE); } } if (!bcompleted){ fprintf(stderr, "CRITICAL ERROR in read_archive(): The file writing block loop was aborted by the infinite loop guard\n"); exit(EXIT_FAILURE); } err=archive_write_finish_entry(ext); if (err != ARCHIVE_OK) { fprintf(stderr, "CRITICAL ERROR in read_archive(): When extracting archive (closing new file), err=%i\n",err); fprintf(stderr, "CRITICAL ERROR in read_archive(): %s\n",archive_error_string(ext)); exit(EXIT_FAILURE); } } archive_read_close(a); err=archive_read_free(a); if (err != ARCHIVE_OK){ fprintf(stderr, "CRITICAL ERROR in read_archive(): When calling archive_read_free(a), err=%i\n",err); fprintf(stderr, "CRITICAL ERROR in read_archive(): %s\n",archive_error_string(a)); exit(EXIT_FAILURE); } archive_write_close(ext); err = archive_write_free(ext); if (err != ARCHIVE_OK){ fprintf(stderr, "CRITICAL ERROR in read_archive(): When calling archive_read_free(ext), err=%i\n",err); fprintf(stderr, "CRITICAL ERROR in read_archive(): %s\n",archive_error_string(a)); exit(EXIT_FAILURE); } if (!fcompleted) { fprintf(stderr, "CRITICAL ERROR in read_archive(): The file header loop was aborted by the infinite loop guard\n"); exit(EXIT_FAILURE); } }
bool extractXZ(FILE *sfp, std::string dest) { struct archive *a; struct archive *ext; struct archive_entry *entry; int flags; int r; /* Select which attributes we want to restore. */ flags = ARCHIVE_EXTRACT_TIME; flags |= ARCHIVE_EXTRACT_PERM; flags |= ARCHIVE_EXTRACT_ACL; flags |= ARCHIVE_EXTRACT_FFLAGS; a = archive_read_new(); archive_read_support_format_all(a); archive_read_support_filter_all(a); ext = archive_write_disk_new(); archive_write_disk_set_options(ext, flags); archive_write_disk_set_standard_lookup(ext); if ((r = archive_read_open_FILE(a, sfp))) { std::cout<<archive_error_string(ext)<<std::endl; return false; } for (;;) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) break; if (r < ARCHIVE_OK) fprintf(stderr, "%s\n", archive_error_string(a)); if (r < ARCHIVE_WARN) { fprintf(stderr, "warn 1\n"); return false; } std::string path = archive_entry_pathname(entry); //std::cout<<"old path: "<< path<<std::endl; archive_entry_set_pathname(entry, (dest + "/" + path).c_str()); r = archive_write_header(ext, entry); if (r < ARCHIVE_OK) fprintf(stderr, "%s\n", archive_error_string(ext)); else if (archive_entry_size(entry) > 0) { r = copy_data(a, ext); if (r < ARCHIVE_OK) fprintf(stderr, "%s\n", archive_error_string(ext)); if (r < ARCHIVE_WARN) { fprintf(stderr, "warn 2\n"); return false; } } r = archive_write_finish_entry(ext); if (r < ARCHIVE_OK) fprintf(stderr, "%s\n", archive_error_string(ext)); if (r < ARCHIVE_WARN) { fprintf(stderr, "warn 3\n"); return false; } } archive_read_close(a); archive_read_free(a); archive_write_close(ext); archive_write_free(ext); return true; }
int main(int argc, char* argv[]){ struct archive* ar; struct archive_entry* aren; int arnum; if(argc < 3){ fprintf(stderr, "Usage: %s infile outfile\n", argv[0]); return 255; } #ifdef ENABLE_STAGE_1 puts("==> Stage 1: Listing"); ar = archive_read_new(); archive_read_support_filter_all(ar); archive_read_support_format_all(ar); arnum = archive_read_open_filename(ar, argv[1], 16384); if(arnum != ARCHIVE_OK){ fprintf(stderr, "%s: %s: %s\n", argv[0], argv[1], archive_error_string(ar)); return 1; } while(archive_read_next_header(ar, &aren) == ARCHIVE_OK){ const char *hardlink, *symlink; printf("%s format: %s, pathname: %s, size: %"PRId64", links: %d," "username: %s, uid: %d", argv[1], archive_format_name(ar), archive_entry_pathname(aren), archive_entry_size(aren), archive_entry_nlink(aren), archive_entry_uname(aren), archive_entry_uid(aren)); hardlink = archive_entry_hardlink(aren); symlink = archive_entry_symlink(aren); if(hardlink != NULL){ printf(", hardlink: %s", hardlink); } if(symlink != NULL){ printf(", symlink: %s", symlink); } putchar('\n'); } archive_read_close(ar); archive_read_free(ar); #endif #ifdef ENABLE_STAGE_2 puts("==> Stage 2: Displaying"); ar = archive_read_new(); archive_read_support_filter_all(ar); archive_read_support_format_all(ar); arnum = archive_read_open_filename(ar, argv[1], 16384); if(arnum != ARCHIVE_OK){ fprintf(stderr, "%s: %s: %s\n", argv[0], argv[1], archive_error_string(ar)); return 2; } while(archive_read_next_header(ar, &aren) == ARCHIVE_OK){ printf("<<< %s >>>\n", archive_entry_pathname(aren)); for(;;){ size_t size; off_t offset; const void* buffer; switch(archive_read_data_block(ar, &buffer, &size, &offset)){ case ARCHIVE_OK: puts(":: Block reading succeeded"); fwrite(buffer, size, 1, stdout); break; case ARCHIVE_WARN: puts(":: Block reading succeeded, warning exists"); fwrite(buffer, size, 1, stdout); break; case ARCHIVE_EOF: goto loop_outside; case ARCHIVE_RETRY: puts(":: Block reading failed, retrying"); break; case ARCHIVE_FATAL: puts(":: Fatal error! STOP!"); return 2; } } loop_outside: puts("@@ Extract OK @@"); } archive_read_close(ar); archive_read_free(ar); #endif #ifdef ENABLE_STAGE_3 puts("==> Stage 3: Extracting"); struct archive* arext; ar = archive_read_new(); archive_read_support_format_all(ar); archive_read_support_filter_all(ar); arext = archive_write_disk_new(); archive_write_disk_set_options(arext, ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR ); archive_write_disk_set_standard_lookup(arext); if(archive_read_open_filename(ar, argv[1], 16384)){ fprintf(stderr, "%s: %s: %s\n", argv[0], argv[1], archive_error_string(ar)); return 3; } while((arnum = archive_read_next_header(ar, &aren)) == ARCHIVE_OK){ int filesize, accsize; printf("<<< %s >>>\n", archive_entry_pathname(aren)); if(archive_write_header(arext, aren) != ARCHIVE_OK){ puts(":: Write header not OK ..."); }else if((filesize = archive_entry_size(aren)) > 0){ accsize = 0; for(;;){ size_t size; off_t offset; const void* buffer; arnum = archive_read_data_block(ar, &buffer, &size, &offset); if(arnum != ARCHIVE_OK){ break; } arnum = archive_write_data(arext, buffer, size); if(arnum >= 0){ accsize += arnum; printf(":: %d of %d bytes written\n", accsize, filesize); } } } if(archive_write_finish_entry(arext) != ARCHIVE_OK){ return 3; } } archive_read_close(ar); archive_read_free(ar); archive_write_close(arext); archive_write_free(arext); #endif return 0; }
static void extract(const char *filename, int do_extract, int flags) { struct archive *a; struct archive *ext; struct archive_entry *entry; int r; a = archive_read_new(); ext = archive_write_disk_new(); archive_write_disk_set_options(ext, flags); #ifndef NO_BZIP2_EXTRACT archive_read_support_filter_bzip2(a); #endif #ifndef NO_GZIP_EXTRACT archive_read_support_filter_gzip(a); #endif #ifndef NO_COMPRESS_EXTRACT archive_read_support_filter_compress(a); #endif #ifndef NO_TAR_EXTRACT archive_read_support_format_tar(a); #endif #ifndef NO_CPIO_EXTRACT archive_read_support_format_cpio(a); #endif #ifndef NO_LOOKUP archive_write_disk_set_standard_lookup(ext); #endif if (filename != NULL && strcmp(filename, "-") == 0) filename = NULL; if ((r = archive_read_open_filename(a, filename, 10240))) { errmsg(archive_error_string(a)); errmsg("\n"); exit(r); } for (;;) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) break; if (r != ARCHIVE_OK) { errmsg(archive_error_string(a)); errmsg("\n"); exit(1); } if (verbose && do_extract) msg("x "); if (verbose || !do_extract) msg(archive_entry_pathname(entry)); if (do_extract) { r = archive_write_header(ext, entry); if (r != ARCHIVE_OK) errmsg(archive_error_string(a)); else copy_data(a, ext); } if (verbose || !do_extract) msg("\n"); } archive_read_close(a); archive_read_free(a); exit(0); }
static bool ExtractArchive(const char *zip_file, const char *out_dir) { struct archive *input = archive_read_new(); archive_read_support_format_all(input); archive_read_support_compression_all(input); struct archive *output = archive_write_disk_new(); archive_write_disk_set_options(output, ARCHIVE_EXTRACT_TIME); archive_write_disk_set_standard_lookup(output); int hRes; const int BLOCK_SIZE = 65536; int r = archive_read_open_filename(input, zip_file, BLOCK_SIZE); if (r != ARCHIVE_OK) { extraction_error = IDS_BADARCHIVE; return false; } // libarchive can only extract into the current directory, so we // need to set it and restore it. char original_dir[MAX_PATH]; char *cRet = getcwd(original_dir, sizeof(original_dir)); hRes = chdir(out_dir); bool retval = true; while (true) { struct archive_entry *entry; r = archive_read_next_header(input, &entry); if (r == ARCHIVE_EOF) break; if (r != ARCHIVE_OK) { extraction_error = IDS_BADARCHIVE; retval = false; break; } r = archive_write_header(output, entry); if (r != ARCHIVE_OK) { const char *msg = archive_error_string(output); extraction_error = IDS_UNKNOWNERROR; retval = false; break; } if (archive_entry_size(entry) > 0) { r = CopyArchiveData(input, output); if (r != ARCHIVE_OK) { const char *msg = archive_error_string(output); extraction_error = IDS_UNKNOWNERROR; retval = false; break; } } r = archive_write_finish_entry(output); if (r != ARCHIVE_OK) { extraction_error = IDS_UNKNOWNERROR; retval = false; break; } // Extraction went OK; process Windows messages ClearMessageQueue(); } archive_read_close(input); archive_read_free(input); archive_write_close(output); archive_write_free(output); // Go back to original working directory hRes = chdir(original_dir); return retval; }