inline void genSafariExtension(const std::string& uid, const std::string& path, QueryData& results) { Row r; r["uid"] = uid; r["path"] = path; // Loop through (Plist key -> table column name) in kSafariExtensionKeys. struct archive* ext = archive_read_new(); if (ext == nullptr) { return; } // Perform a dry run of the file read. if (!readFile(path).ok()) { return; } // Finally drop privileges to the user controlling the extension. auto dropper = DropPrivileges::get(); if (!dropper->dropToParent(path)) { return; } // Use open_file, instead of the preferred open_filename for OS X 10.9. archive_read_support_format_xar(ext); if (archive_read_open_filename(ext, path.c_str(), 10240) != ARCHIVE_OK) { archive_read_finish(ext); return; } struct archive_entry* entry = nullptr; while (archive_read_next_header(ext, &entry) == ARCHIVE_OK) { auto item_path = archive_entry_pathname(entry); // Documentation for libarchive mentions these APIs may return NULL. if (item_path == nullptr) { archive_read_data_skip(ext); continue; } // Assume there is no non-root Info. if (std::string(item_path).find("Info.plist") == std::string::npos) { archive_read_data_skip(ext); continue; } // Read the decompressed Info.plist content. auto content = std::string(archive_entry_size(entry), '\0'); archive_read_data_into_buffer(ext, &content[0], content.size()); // If the Plist can be parsed, extract important keys into columns. pt::ptree tree; if (parsePlistContent(content, tree).ok()) { for (const auto& it : kSafariExtensionKeys) { r[it.second] = tree.get(it.first, ""); } } break; } archive_read_close(ext); archive_read_finish(ext); results.push_back(std::move(r)); }
int archive_extract_tar_bzip2(void) { struct archive *a; struct archive *ext; int r = 0; int flags = 0; int error = 0; a = archive_read_new(); archive_read_support_format_tar(a); archive_read_support_compression_bzip2(a); ext = archive_write_disk_new(); archive_write_disk_set_options(ext, flags); if ((r = archive_read_open_file(a, NULL, 10240))) { fprintf(stderr, "archiving: %s", archive_error_string(a)); error = r; } else { for (;;) { struct archive_entry *entry; r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) { break; } if (r != ARCHIVE_OK) { fprintf(stderr, "archiving: %s", archive_error_string(a)); error = 1; break; } if (archive_write_header(ext, entry) != ARCHIVE_OK) { fprintf(stderr, "archiving: %s", archive_error_string(ext)); } else { const void *buff; size_t size; off_t offset; for (;;) { r = archive_read_data_block(a, &buff, &size, &offset); if (r == ARCHIVE_EOF) { r = ARCHIVE_OK; break; } if (r != ARCHIVE_OK) { fprintf(stderr, "archiving: %s", archive_error_string(ext)); break; } r = archive_write_data_block(ext, buff, size, offset); if (r != ARCHIVE_OK) { fprintf(stderr, "archiving: %s", archive_error_string(ext)); break; } } if (r != ARCHIVE_OK) { error = 1; break; } r = archive_write_finish_entry(ext); if (r != ARCHIVE_OK) { fprintf(stderr, "archiving: %s", archive_error_string(ext)); error = 1; break; } } } } archive_read_close(a); archive_read_finish(a); return error; }
/* * Apple shipped an extended version of GNU tar with Mac OS X 10.5 * and earlier. */ static void test_compat_mac_1(void) { char name[] = "test_compat_mac-1.tar.Z"; struct archive_entry *ae; struct archive *a; const void *attr; size_t attrSize; 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)); extract_reference_file(name); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString(TESTPATH, archive_entry_pathname(ae)); assertEqualInt(1275688109, archive_entry_mtime(ae)); assertEqualInt(95594, archive_entry_uid(ae)); assertEqualString("kientzle", archive_entry_uname(ae)); assertEqualInt(5000, archive_entry_gid(ae)); assertEqualString("", archive_entry_gname(ae)); assertEqualInt(040755, archive_entry_mode(ae)); attr = archive_entry_mac_metadata(ae, &attrSize); assert(attr == NULL); assertEqualInt(0, attrSize); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString(TESTPATH "dir/", archive_entry_pathname(ae)); assertEqualInt(1275687611, archive_entry_mtime(ae)); assertEqualInt(95594, archive_entry_uid(ae)); assertEqualString("kientzle", archive_entry_uname(ae)); assertEqualInt(5000, archive_entry_gid(ae)); assertEqualString("", archive_entry_gname(ae)); assertEqualInt(040755, archive_entry_mode(ae)); attr = archive_entry_mac_metadata(ae, &attrSize); assert(attr != NULL); assertEqualInt(225, attrSize); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString(TESTPATH "file", archive_entry_pathname(ae)); assertEqualInt(1275687588, archive_entry_mtime(ae)); assertEqualInt(95594, archive_entry_uid(ae)); assertEqualString("kientzle", archive_entry_uname(ae)); assertEqualInt(5000, archive_entry_gid(ae)); assertEqualString("", archive_entry_gname(ae)); assertEqualInt(0100644, archive_entry_mode(ae)); attr = archive_entry_mac_metadata(ae, &attrSize); assert(attr != NULL); assertEqualInt(225, attrSize); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("dir/", archive_entry_pathname(ae)); assertEqualInt(1275688064, archive_entry_mtime(ae)); assertEqualInt(95594, archive_entry_uid(ae)); assertEqualString("kientzle", archive_entry_uname(ae)); assertEqualInt(5000, archive_entry_gid(ae)); assertEqualString("", archive_entry_gname(ae)); assertEqualInt(040755, archive_entry_mode(ae)); attr = archive_entry_mac_metadata(ae, &attrSize); assert(attr != NULL); assertEqualInt(225, attrSize); assertEqualMem("\x00\x05\x16\x07\x00\x02\x00\x00Mac OS X", attr, 16); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("file", archive_entry_pathname(ae)); assertEqualInt(1275625860, archive_entry_mtime(ae)); assertEqualInt(95594, archive_entry_uid(ae)); assertEqualString("kientzle", archive_entry_uname(ae)); assertEqualInt(5000, archive_entry_gid(ae)); assertEqualString("", archive_entry_gname(ae)); assertEqualInt(0100644, archive_entry_mode(ae)); attr = archive_entry_mac_metadata(ae, &attrSize); assert(attr != NULL); assertEqualInt(225, attrSize); assertEqualMem("\x00\x05\x16\x07\x00\x02\x00\x00Mac OS X", attr, 16); /* Verify the end-of-archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); /* Verify that the format detection worked. */ assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR); assertEqualInt(ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); }
void pkg_archive_close(struct archive *a){ archive_read_close(a); archive_read_finish(a); }
off_t epic_stat(const char *filename, struct stat *buf) { #ifdef HAVE_LIBARCHIVE struct archive *a; struct archive_entry *entry = NULL; #endif int ret; char * zip; char * zipstr; char * sl; int ziploc; int scan = 0; #ifdef HAVE_LIBARCHIVE /* * should probably fill the stat structure with * as much as possible.. i don't know what might * rely on this information.. */ zipstr = LOCAL_COPY(filename); sl = LOCAL_COPY(filename); zip = zipstr; if (((ziploc=stristr(zipstr, ".zip"))!=-1) || ((ziploc=stristr(zipstr, ".tar"))!=-1)) { zip+=ziploc; while (*zip!='/') { if (*zip==0) break; zip++; ziploc++; } sl+=ziploc; *zip++ = 0; if ( strstr(sl, "/")!=NULL ) scan=1; a = archive_read_new(); archive_read_support_format_all(a); if ( !(ret=archive_read_open_filename(a, zipstr, 10240)) ) { if (scan) { if (!(find_in_archive(a, &entry, zip, 0)) ) { return -1; } else { /* this is such a hack, but libarchive consistantly */ /* crashes on me when i use it's stat routines */ buf->st_size=1; buf->st_mode=33188; archive_read_close(a); archive_read_free(a); return 0; } } } } #endif if (!stat(filename, buf)) { return 0; } else { return -1; } }
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 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); }
int pkg_add(struct pkgdb *db, const char *path, unsigned flags, struct pkg_manifest_key *keys) { const char *arch; const char *origin; const char *name; struct archive *a; struct archive_entry *ae; struct pkg *pkg = NULL; struct pkg_dep *dep = NULL; struct pkg *pkg_inst = NULL; bool extract = true; bool handle_rc = false; bool disable_mtree; char dpath[MAXPATHLEN]; const char *basedir; const char *ext; char *mtree; char *prefix; int retcode = EPKG_OK; int ret; assert(path != NULL); /* * Open the package archive file, read all the meta files and set the * current archive_entry to the first non-meta file. * If there is no non-meta files, EPKG_END is returned. */ ret = pkg_open2(&pkg, &a, &ae, path, keys, 0); if (ret == EPKG_END) extract = false; else if (ret != EPKG_OK) { retcode = ret; goto cleanup; } if ((flags & PKG_ADD_UPGRADE) == 0) pkg_emit_install_begin(pkg); if (pkg_is_valid(pkg) != EPKG_OK) { pkg_emit_error("the package is not valid"); return (EPKG_FATAL); } if (flags & PKG_ADD_AUTOMATIC) pkg_set(pkg, PKG_AUTOMATIC, (int64_t)true); /* * Check the architecture */ pkg_get(pkg, PKG_ARCH, &arch, PKG_ORIGIN, &origin, PKG_NAME, &name); if (!is_valid_abi(arch, true)) { if ((flags & PKG_ADD_FORCE) == 0) { retcode = EPKG_FATAL; goto cleanup; } } /* * Check if the package is already installed */ ret = pkg_try_installed(db, origin, &pkg_inst, PKG_LOAD_BASIC); if (ret == EPKG_OK) { if ((flags & PKG_FLAG_FORCE) == 0) { pkg_emit_already_installed(pkg_inst); retcode = EPKG_INSTALLED; pkg_free(pkg_inst); pkg_inst = NULL; goto cleanup; } else { pkg_emit_notice("package %s is already installed, forced install", name); pkg_free(pkg_inst); pkg_inst = NULL; } } else if (ret != EPKG_END) { retcode = ret; goto cleanup; } /* * Check for dependencies by searching the same directory as * the package archive we're reading. Of course, if we're * reading from a file descriptor or a unix domain socket or * somesuch, there's no valid directory to search. */ if (pkg_type(pkg) == PKG_FILE) { basedir = dirname(path); if ((ext = strrchr(path, '.')) == NULL) { pkg_emit_error("%s has no extension", path); retcode = EPKG_FATAL; goto cleanup; } } else { basedir = NULL; ext = NULL; } while (pkg_deps(pkg, &dep) == EPKG_OK) { if (pkg_is_installed(db, pkg_dep_origin(dep)) == EPKG_OK) continue; if (basedir != NULL) { const char *dep_name = pkg_dep_name(dep); const char *dep_ver = pkg_dep_version(dep); snprintf(dpath, sizeof(dpath), "%s/%s-%s%s", basedir, dep_name, dep_ver, ext); if ((flags & PKG_ADD_UPGRADE) == 0 && access(dpath, F_OK) == 0) { ret = pkg_add(db, dpath, PKG_ADD_AUTOMATIC, keys); if (ret != EPKG_OK) { retcode = EPKG_FATAL; goto cleanup; } } else { pkg_emit_error("Missing dependency matching '%s'", pkg_dep_get(dep, PKG_DEP_ORIGIN)); retcode = EPKG_FATAL; goto cleanup; } } else { retcode = EPKG_FATAL; pkg_emit_missing_dep(pkg, dep); goto cleanup; } } /* register the package before installing it in case there are * problems that could be caught here. */ retcode = pkgdb_register_pkg(db, pkg, flags & PKG_ADD_UPGRADE, flags & PKG_FLAG_FORCE); if (retcode != EPKG_OK) goto cleanup; /* MTREE replicates much of the standard functionality * inplicit in the way pkg works. It has to remain available * in the ports for compatibility with the old pkg_tools, but * ultimately, MTREE should be made redundant. Use this for * experimantal purposes and to develop MTREE-free versions of * packages. */ pkg_config_bool(PKG_CONFIG_DISABLE_MTREE, &disable_mtree); if (!disable_mtree) { pkg_get(pkg, PKG_PREFIX, &prefix, PKG_MTREE, &mtree); if ((retcode = do_extract_mtree(mtree, prefix)) != EPKG_OK) goto cleanup_reg; } /* * Execute pre-install scripts */ if ((flags & (PKG_ADD_NOSCRIPT | PKG_ADD_USE_UPGRADE_SCRIPTS)) == 0) pkg_script_run(pkg, PKG_SCRIPT_PRE_INSTALL); /* add the user and group if necessary */ /* pkg_add_user_group(pkg); */ /* * Extract the files on disk. */ if (extract && (retcode = do_extract(a, ae)) != EPKG_OK) { /* If the add failed, clean up (silently) */ pkg_delete_files(pkg, 2); pkg_delete_dirs(db, pkg, 1); goto cleanup_reg; } /* * Execute post install scripts */ if ((flags & PKG_ADD_NOSCRIPT) == 0) { if ((flags & PKG_ADD_USE_UPGRADE_SCRIPTS) == PKG_ADD_USE_UPGRADE_SCRIPTS) pkg_script_run(pkg, PKG_SCRIPT_POST_UPGRADE); else pkg_script_run(pkg, PKG_SCRIPT_POST_INSTALL); } /* * start the different related services if the users do want that * and that the service is running */ pkg_config_bool(PKG_CONFIG_HANDLE_RC_SCRIPTS, &handle_rc); if (handle_rc) pkg_start_stop_rc_scripts(pkg, PKG_RC_START); cleanup_reg: if ((flags & PKG_ADD_UPGRADE) == 0) pkgdb_register_finale(db, retcode); if (retcode == EPKG_OK && (flags & PKG_ADD_UPGRADE) == 0) pkg_emit_install_finished(pkg); cleanup: if (a != NULL) { archive_read_close(a); archive_read_free(a); } pkg_free(pkg); if (pkg_inst != NULL) pkg_free(pkg_inst); return (retcode); }
/* * Verify our ability to read sample files created by Solaris pax for * a sparse file. */ static void test_compat_solaris_pax_sparse_1(void) { char name[] = "test_compat_solaris_pax_sparse_1.pax.Z"; struct archive_entry *ae; struct archive *a; int64_t offset, length; const void *buff; size_t bytes_read; char data[1024*8]; int r; 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)); extract_reference_file(name); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); /* Read first entry. */ assertEqualIntA(a, ARCHIVE_OK, r = archive_read_next_header(a, &ae)); if (r != ARCHIVE_OK) { archive_read_free(a); return; } assertEqualString("hole", archive_entry_pathname(ae)); assertEqualInt(1310411683, archive_entry_mtime(ae)); assertEqualInt(101, archive_entry_uid(ae)); assertEqualString("cue", archive_entry_uname(ae)); assertEqualInt(10, archive_entry_gid(ae)); assertEqualString("staff", archive_entry_gname(ae)); assertEqualInt(0100644, archive_entry_mode(ae)); /* Verify the sparse information. */ failure("This sparse file should have tree data blocks"); assertEqualInt(3, archive_entry_sparse_reset(ae)); assertEqualInt(ARCHIVE_OK, archive_entry_sparse_next(ae, &offset, &length)); assertEqualInt(0, offset); assertEqualInt(131072, length); assertEqualInt(ARCHIVE_OK, archive_entry_sparse_next(ae, &offset, &length)); assertEqualInt(393216, offset); assertEqualInt(131072, length); assertEqualInt(ARCHIVE_OK, archive_entry_sparse_next(ae, &offset, &length)); assertEqualInt(786432, offset); assertEqualInt(32775, length); while (ARCHIVE_OK == archive_read_data_block(a, &buff, &bytes_read, &offset)) { failure("The data blocks should not include the hole"); assert((offset >= 0 && offset + bytes_read <= 131072) || (offset >= 393216 && offset + bytes_read <= 393216+131072) || (offset >= 786432 && offset + bytes_read <= 786432+32775)); if (offset == 0 && bytes_read >= 1024*8) { memset(data, 'a', sizeof(data)); failure("First data block should be 8K bytes of 'a'"); assertEqualMem(buff, data, sizeof(data)); } else if (offset + bytes_read == 819207 && bytes_read >= 7) { const char *last = buff; last += bytes_read - 7; memset(data, 'c', 7); failure("Last seven bytes should be all 'c'"); assertEqualMem(last, data, 7); } } /* Verify the end-of-archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); /* Verify that the format detection worked. */ assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE); assertEqualInt(ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); }
/* * Release memory and other resources. */ static int _archive_read_free(struct archive *_a) { struct archive_read *a = (struct archive_read *)_a; struct archive_read_passphrase *p; int i, n; int slots; int r = ARCHIVE_OK; if (_a == NULL) return (ARCHIVE_OK); archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_read_free"); if (a->archive.state != ARCHIVE_STATE_CLOSED && a->archive.state != ARCHIVE_STATE_FATAL) r = archive_read_close(&a->archive); /* Call cleanup functions registered by optional components. */ if (a->cleanup_archive_extract != NULL) r = (a->cleanup_archive_extract)(a); /* Cleanup format-specific data. */ slots = sizeof(a->formats) / sizeof(a->formats[0]); for (i = 0; i < slots; i++) { a->format = &(a->formats[i]); if (a->formats[i].cleanup) (a->formats[i].cleanup)(a); } /* Free the filters */ __archive_read_free_filters(a); /* Release the bidder objects. */ n = sizeof(a->bidders)/sizeof(a->bidders[0]); for (i = 0; i < n; i++) { if (a->bidders[i].free != NULL) { int r1 = (a->bidders[i].free)(&a->bidders[i]); if (r1 < r) r = r1; } } /* Release passphrase list. */ p = a->passphrases.first; while (p != NULL) { struct archive_read_passphrase *np = p->next; /* A passphrase should be cleaned. */ memset(p->passphrase, 0, strlen(p->passphrase)); free(p->passphrase); free(p); p = np; } archive_string_free(&a->archive.error_string); archive_entry_free(a->entry); a->archive.magic = 0; __archive_clean(&a->archive); free(a->client.dataset); free(a); return (r); }
static void test_filename(const char *prefix, int dlen, int flen) { char buff[8192]; char filename[400]; char dirname[400]; struct archive_entry *ae; struct archive *a; size_t used; int separator = 0; int i = 0; if (prefix != NULL) { strcpy(filename, prefix); i = (int)strlen(prefix); } if (dlen > 0) { for (; i < dlen; i++) filename[i] = 'a'; filename[i++] = '/'; separator = 1; } for (; i < dlen + flen + separator; i++) filename[i] = 'b'; filename[i] = '\0'; strcpy(dirname, filename); /* Create a new archive in memory. */ assert((a = archive_write_new()) != NULL); assertA(0 == archive_write_set_format_ustar(a)); assertA(0 == archive_write_set_compression_none(a)); assertA(0 == archive_write_set_bytes_per_block(a,0)); assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); /* * Write a file to it. */ assert((ae = archive_entry_new()) != NULL); archive_entry_copy_pathname(ae, filename); archive_entry_set_mode(ae, S_IFREG | 0755); failure("dlen=%d, flen=%d", dlen, flen); if (flen > 100) { assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); } else { assertEqualIntA(a, 0, archive_write_header(a, ae)); } archive_entry_free(ae); /* * Write a dir to it (without trailing '/'). */ assert((ae = archive_entry_new()) != NULL); archive_entry_copy_pathname(ae, dirname); archive_entry_set_mode(ae, S_IFDIR | 0755); failure("dlen=%d, flen=%d", dlen, flen); if (flen >= 100) { assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); } else { assertEqualIntA(a, 0, archive_write_header(a, ae)); } archive_entry_free(ae); /* Tar adds a '/' to directory names. */ strcat(dirname, "/"); /* * Write a dir to it (with trailing '/'). */ assert((ae = archive_entry_new()) != NULL); archive_entry_copy_pathname(ae, dirname); archive_entry_set_mode(ae, S_IFDIR | 0755); failure("dlen=%d, flen=%d", dlen, flen); if (flen >= 100) { assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); } else { assertEqualIntA(a, 0, archive_write_header(a, ae)); } archive_entry_free(ae); /* Close out the archive. */ assertA(0 == archive_write_close(a)); #if ARCHIVE_VERSION_NUMBER < 2000000 archive_write_finish(a); #else assertEqualInt(0, archive_write_finish(a)); #endif /* * Now, read the data back. */ assert((a = archive_read_new()) != NULL); assertA(0 == archive_read_support_format_all(a)); assertA(0 == archive_read_support_compression_all(a)); assertA(0 == archive_read_open_memory(a, buff, used)); if (flen <= 100) { /* Read the file and check the filename. */ assertA(0 == archive_read_next_header(a, &ae)); failure("dlen=%d, flen=%d", dlen, flen); assertEqualString(filename, archive_entry_pathname(ae)); assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae)); } /* * Read the two dirs and check the names. * * Both dirs should read back with the same name, since * tar should add a trailing '/' to any dir that doesn't * already have one. */ if (flen <= 99) { assertA(0 == archive_read_next_header(a, &ae)); assert((S_IFDIR | 0755) == archive_entry_mode(ae)); failure("dlen=%d, flen=%d", dlen, flen); assertEqualString(dirname, archive_entry_pathname(ae)); } if (flen <= 99) { assertA(0 == archive_read_next_header(a, &ae)); assert((S_IFDIR | 0755) == archive_entry_mode(ae)); assertEqualString(dirname, archive_entry_pathname(ae)); } /* Verify the end of the archive. */ failure("This fails if entries were written that should not have been written. dlen=%d, flen=%d", dlen, flen); assertEqualInt(1, archive_read_next_header(a, &ae)); assert(0 == archive_read_close(a)); #if ARCHIVE_VERSION_NUMBER < 2000000 archive_read_finish(a); #else assertEqualInt(0, archive_read_finish(a)); #endif }
static void archive_conv_close(struct archive_conv *conv) { archive_write_close(conv->out); archive_write_free(conv->out); archive_read_close(conv->in); archive_read_free(conv->in); }
/** * Extract the archive stored at the given @path. This function * returns -1 if an error occurred, otherwise 0. */ int extract_archive_from_file(const char *path) { struct archive *archive = NULL; CallbackData *data = NULL; int status2; int status; archive = archive_read_new(); if (archive == NULL) { note(NULL, ERROR, INTERNAL, "can't initialize archive structure"); status = -1; goto end; } status = archive_read_support_format_cpio(archive); if (status != ARCHIVE_OK) { note(NULL, ERROR, INTERNAL, "can't set archive format: %s", archive_error_string(archive)); status = -1; goto end; } status = archive_read_support_format_gnutar(archive); if (status != ARCHIVE_OK) { note(NULL, ERROR, INTERNAL, "can't set archive format: %s", archive_error_string(archive)); status = -1; goto end; } status = archive_read_support_filter_gzip(archive); if (status != ARCHIVE_OK) { note(NULL, ERROR, INTERNAL, "can't add archive filter: %s", archive_error_string(archive)); status = -1; goto end; } status = archive_read_support_filter_lzop(archive); if (status != ARCHIVE_OK) { note(NULL, ERROR, INTERNAL, "can't add archive filter: %s", archive_error_string(archive)); status = -1; goto end; } data = talloc_zero(NULL, CallbackData); if (data == NULL) { note(NULL, ERROR, INTERNAL, "can't allocate callback data"); status = -1; goto end; } data->path = talloc_strdup(data, path); if (data->path == NULL) { note(NULL, ERROR, INTERNAL, "can't allocate callback data path"); status = -1; goto end; } status = archive_read_open(archive, data, open_callback, read_callback, close_callback); if (status != ARCHIVE_OK) { /* Don't complain if no error message were registered, * ie. when testing for a self-extracting archive. */ if (archive_error_string(archive) != NULL) note(NULL, ERROR, INTERNAL, "can't read archive: %s", archive_error_string(archive)); status = -1; goto end; } status = extract_archive(archive); end: if (archive != NULL) { status2 = archive_read_close(archive); if (status2 != ARCHIVE_OK) { note(NULL, WARNING, INTERNAL, "can't close archive: %s", archive_error_string(archive)); } status2 = archive_read_free(archive); if (status2 != ARCHIVE_OK) { note(NULL, WARNING, INTERNAL, "can't free archive: %s", archive_error_string(archive)); } } TALLOC_FREE(data); return status; }
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); /* * Note: archive_write_disk_set_standard_lookup() is useful * here, but it requires library routines that can add 500k or * more to a static executable. */ //archive_read_support_format_tar(a); archive_read_support_format_all(a); archive_read_support_compression_all(a); /* * On my system, enabling other archive formats adds 20k-30k * each. Enabling gzip decompression adds about 20k. * Enabling bzip2 is more expensive because the libbz2 library * isn't very well factored. */ if (filename != NULL && strcmp(filename, "-") == 0) filename = NULL; if ((r = archive_read_open_file(a, filename, 10240))) fail("archive_read_open_file()", archive_error_string(a), r); for (;;) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) break; if (r != ARCHIVE_OK) fail("archive_read_next_header()", archive_error_string(a), 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) warn("archive_write_header()", archive_error_string(ext)); else { copy_data(a, ext); r = archive_write_finish_entry(ext); if (r != ARCHIVE_OK) fail("archive_write_finish_entry()", archive_error_string(ext), 1); } } if (verbose || !do_extract) msg("\n"); } archive_read_close(a); archive_read_free(a); exit(0); }
/* * test_compat_gtar_1.tgz exercises reading long filenames and * symlink targets stored in the GNU tar format. */ static void test_compat_gtar_1(void) { char name[] = "test_compat_gtar_1.tar"; struct archive_entry *ae; struct archive *a; int r; assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); extract_reference_file(name); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); /* Read first entry. */ assertEqualIntA(a, ARCHIVE_OK, r = archive_read_next_header(a, &ae)); if (r != ARCHIVE_OK) { archive_read_free(a); return; } assertEqualString( "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890", archive_entry_pathname(ae)); assertEqualInt(1197179003, archive_entry_mtime(ae)); assertEqualInt(1000, archive_entry_uid(ae)); assertEqualString("tim", archive_entry_uname(ae)); assertEqualInt(1000, archive_entry_gid(ae)); assertEqualString("tim", archive_entry_gname(ae)); assertEqualInt(0100644, archive_entry_mode(ae)); /* Read second entry. */ assertEqualIntA(a, ARCHIVE_OK, r = archive_read_next_header(a, &ae)); if (r != ARCHIVE_OK) { archive_read_free(a); return; } assertEqualString( "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij" "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij" "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij" "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij", archive_entry_pathname(ae)); assertEqualString( "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890", archive_entry_symlink(ae)); assertEqualInt(1197179043, archive_entry_mtime(ae)); assertEqualInt(1000, archive_entry_uid(ae)); assertEqualString("tim", archive_entry_uname(ae)); assertEqualInt(1000, archive_entry_gid(ae)); assertEqualString("tim", archive_entry_gname(ae)); assertEqualInt(0120755, archive_entry_mode(ae)); /* Verify the end-of-archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); /* Verify that the format detection worked. */ assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR); assertEqualInt(ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); }
/** * Issue 152: A file generated by a tool that doesn't really * believe in populating local file headers at all. This * is only readable with the seeking reader. */ static void test_compat_zip_5(void) { const char *refname = "test_compat_zip_5.zip"; struct archive_entry *ae; struct archive *a; void *p; size_t s; extract_reference_file(refname); p = slurpfile(&s, refname); /* Verify with seek support. * Everything works correctly here. */ 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, read_open_memory_seek(a, p, s, 18)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("Metadata/Job_PT.xml", archive_entry_pathname(ae)); assertEqualInt(3559, archive_entry_size(ae)); assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); assertEqualInt(0666, archive_entry_perm(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("Metadata/MXDC_Empty_PT.xml", archive_entry_pathname(ae)); assertEqualInt(456, archive_entry_size(ae)); assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); assertEqualInt(0666, archive_entry_perm(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("Documents/1/Metadata/Page1_Thumbnail.JPG", archive_entry_pathname(ae)); assertEqualInt(1495, archive_entry_size(ae)); assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); assertEqualInt(0666, archive_entry_perm(ae)); /* TODO: Read some of the file data and verify it. The code to read uncompressed Zip entries with "file at end" semantics is tricky and should be verified more carefully. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("Documents/1/Pages/_rels/1.fpage.rels", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("Documents/1/Pages/1.fpage", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("Documents/1/Resources/Fonts/3DFDBC8B-4514-41F1-A808-DEA1C79BAC2B.odttf", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("Documents/1/_rels/FixedDocument.fdoc.rels", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("Documents/1/FixedDocument.fdoc", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("_rels/FixedDocumentSequence.fdseq.rels", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("FixedDocumentSequence.fdseq", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("_rels/.rels", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("[Content_Types].xml", archive_entry_pathname(ae)); 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)); /* Try reading without seek support. */ 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, read_open_memory(a, p, s, 3)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("Metadata/Job_PT.xml", archive_entry_pathname(ae)); assertEqualInt(0, archive_entry_size(ae)); assert(!archive_entry_size_is_set(ae)); assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); assertEqualInt(0666, archive_entry_perm(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("Metadata/MXDC_Empty_PT.xml", archive_entry_pathname(ae)); assertEqualInt(0, archive_entry_size(ae)); assert(!archive_entry_size_is_set(ae)); assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); assertEqualInt(0666, archive_entry_perm(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("Documents/1/Metadata/Page1_Thumbnail.JPG", archive_entry_pathname(ae)); assertEqualInt(0, archive_entry_size(ae)); assert(!archive_entry_size_is_set(ae)); assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); assertEqualInt(0666, archive_entry_perm(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("Documents/1/Pages/_rels/1.fpage.rels", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("Documents/1/Pages/1.fpage", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("Documents/1/Resources/Fonts/3DFDBC8B-4514-41F1-A808-DEA1C79BAC2B.odttf", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("Documents/1/_rels/FixedDocument.fdoc.rels", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("Documents/1/FixedDocument.fdoc", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("_rels/FixedDocumentSequence.fdseq.rels", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("FixedDocumentSequence.fdseq", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("_rels/.rels", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("[Content_Types].xml", archive_entry_pathname(ae)); 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)); free(p); }
static void * extract(void *p) { locale_t archive_locale; locale_t old_locale; struct archive *a; struct archive *ext = NULL; struct archive_entry *entry = NULL; int r; int flags; struct extract_data *data = (struct extract_data *)p; flags = data->flags; int exitval = -EFAULT; /* * Enable system locale - change from the standard (C) to system locale. * This allows libarchive (in case it is activated) to handle filenames. * We only change LC_CTYPE since libarchive only needs the charset set. * We don't use LC_ALL because it causes problems on some systems. * We restore the original LC_CTYPE after extraction to avoid side effects. * We use uselocale instead of setlocale to avoid setting LC_CTYPE globally. * See on libarchive Website for a more complete description of the issue: * https://github.com/libarchive/libarchive/issues/587 * https://github.com/libarchive/libarchive/wiki/Filenames */ archive_locale = newlocale(LC_CTYPE_MASK, "", (locale_t)0); old_locale = uselocale(archive_locale); a = archive_read_new(); if (!a) { goto out; } ext = archive_write_disk_new(); if (!ext) { goto out; } archive_write_disk_set_options(ext, flags); /* * Note: archive_write_disk_set_standard_lookup() is useful * here, but it requires library routines that can add 500k or * more to a static executable. */ archive_read_support_format_all(a); archive_read_support_filter_all(a); /* * On my system, enabling other archive formats adds 20k-30k * each. Enabling gzip decompression adds about 20k. * Enabling bzip2 is more expensive because the libbz2 library * isn't very well factored. */ char* FIFO = alloca(strlen(get_tmpdir())+strlen(FIFO_FILE_NAME)+1); sprintf(FIFO, "%s%s", get_tmpdir(), FIFO_FILE_NAME); if ((r = archive_read_open_filename(a, FIFO, 4096))) { ERROR("archive_read_open_filename(): %s %d", archive_error_string(a), r); goto out; } for (;;) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) break; if (r != ARCHIVE_OK) { ERROR("archive_read_next_header(): %s %d", archive_error_string(a), 1); goto out; } if (debug) TRACE("Extracting %s", archive_entry_pathname(entry)); r = archive_write_header(ext, entry); if (r != ARCHIVE_OK) TRACE("archive_write_header(): %s", archive_error_string(ext)); else { copy_data(a, ext); r = archive_write_finish_entry(ext); if (r != ARCHIVE_OK) { ERROR("archive_write_finish_entry(): %s", archive_error_string(ext)); goto out; } } } exitval = 0; out: if (ext) { r = archive_write_free(ext); if (r) { ERROR("archive_write_free(): %s %d", archive_error_string(a), r); exitval = -EFAULT; } } if (a) { archive_read_close(a); archive_read_free(a); } uselocale(old_locale); data->exitval = exitval; pthread_exit(NULL); }
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; }
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]); rawimage = (char *)realloc(rawimage, oldsize + size); memcpy(rawimage + oldsize, tmp, size); oldsize += size; size = oldsize; free(tmp); if (!assert(rawimage != NULL)) continue; } } 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 verify_contents(struct archive *a, int expect_details) { char filedata[64]; struct archive_entry *ae; /* * Read and verify first file. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt(1, archive_entry_mtime(ae)); /* Zip doesn't store high-resolution mtime. */ assertEqualInt(0, archive_entry_mtime_nsec(ae)); assertEqualInt(0, archive_entry_atime(ae)); assertEqualInt(0, archive_entry_ctime(ae)); assertEqualString("file", archive_entry_pathname(ae)); if (expect_details) { assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); assertEqualInt(8, archive_entry_size(ae)); } else { assertEqualInt(0, archive_entry_size(ae)); } assertEqualIntA(a, 8, archive_read_data(a, filedata, sizeof(filedata))); assertEqualMem(filedata, "12345678", 8); /* * Read the second file back. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt(1, archive_entry_mtime(ae)); assertEqualInt(0, archive_entry_mtime_nsec(ae)); assertEqualInt(0, archive_entry_atime(ae)); assertEqualInt(0, archive_entry_ctime(ae)); assertEqualString("file2", archive_entry_pathname(ae)); if (expect_details) { assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); assertEqualInt(4, archive_entry_size(ae)); } else { assertEqualInt(0, archive_entry_size(ae)); } assertEqualIntA(a, 4, archive_read_data(a, filedata, sizeof(filedata))); assertEqualMem(filedata, "1234", 4); /* * Read the third file back. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt(1, archive_entry_mtime(ae)); assertEqualInt(0, archive_entry_mtime_nsec(ae)); assertEqualInt(0, archive_entry_atime(ae)); assertEqualInt(0, archive_entry_ctime(ae)); assertEqualString("symlink", archive_entry_pathname(ae)); if (expect_details) { assertEqualInt(AE_IFLNK | 0755, archive_entry_mode(ae)); assertEqualInt(0, archive_entry_size(ae)); assertEqualString("file1", archive_entry_symlink(ae)); } else { assertEqualInt(AE_IFREG | 0666, archive_entry_mode(ae)); assertEqualInt(0, archive_entry_size(ae)); } /* * Read the dir entry back. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt(11, archive_entry_mtime(ae)); assertEqualInt(0, archive_entry_mtime_nsec(ae)); assertEqualInt(0, archive_entry_atime(ae)); assertEqualInt(0, archive_entry_ctime(ae)); assertEqualString("dir/", archive_entry_pathname(ae)); if (expect_details) assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae)); assertEqualInt(0, archive_entry_size(ae)); assertEqualIntA(a, 0, archive_read_data(a, filedata, 10)); /* Verify the end of the archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); }
/* * Main loop: open the zipfile, iterate over its contents and decide what * to do with each entry. */ static void unzip(const char *fn) { struct archive *a; struct archive_entry *e; int fd, ret; uintmax_t total_size, file_count, error_count; if (strcmp(fn, "-") == 0) fd = STDIN_FILENO; else if ((fd = open(fn, O_RDONLY)) < 0) error("%s", fn); if ((a = archive_read_new()) == NULL) error("archive_read_new failed"); ac(archive_read_support_format_zip(a)); ac(archive_read_open_fd(a, fd, 8192)); if (!zipinfo_mode) { if (!p_opt && !q_opt) printf("Archive: %s\n", fn); if (v_opt == 1) { printf(" Length Date Time Name\n"); printf(" -------- ---- ---- ----\n"); } else if (v_opt == 2) { printf(" Length Method Size Ratio Date Time CRC-32 Name\n"); printf("-------- ------ ------- ----- ---- ---- ------ ----\n"); } } total_size = 0; file_count = 0; error_count = 0; for (;;) { ret = archive_read_next_header(a, &e); if (ret == ARCHIVE_EOF) break; ac(ret); if (!zipinfo_mode) { if (t_opt) error_count += test(a, e); else if (v_opt) list(a, e); else if (p_opt || c_opt) extract_stdout(a, e); else extract(a, e); } else { if (Z1_opt) list(a, e); } total_size += archive_entry_size(e); ++file_count; } if (zipinfo_mode) { if (v_opt == 1) { printf(" -------- -------\n"); printf(" %8ju %ju file%s\n", total_size, file_count, file_count != 1 ? "s" : ""); } else if (v_opt == 2) { printf("-------- ------- --- -------\n"); printf("%8ju %7ju 0%% %ju file%s\n", total_size, total_size, file_count, file_count != 1 ? "s" : ""); } } ac(archive_read_close(a)); (void)archive_read_finish(a); if (fd != STDIN_FILENO && close(fd) != 0) error("%s", fn); if (t_opt) { if (error_count > 0) { errorx("%d checksum error(s) found.", error_count); } else { printf("No errors detected in compressed data of %s.\n", fn); } } }
/* * Handle read modes: 'x', 't' and 'p'. */ static void read_archive(struct bsdar *bsdar, char mode) { struct archive *a; struct archive_entry *entry; struct stat sb; struct tm *tp; const char *bname; const char *name; mode_t md; size_t size; time_t mtime; uid_t uid; gid_t gid; char **av; char buf[25]; char find; int flags, r, i; if ((a = archive_read_new()) == NULL) bsdar_errc(bsdar, EX_SOFTWARE, 0, "archive_read_new failed"); archive_read_support_format_ar(a); AC(archive_read_open_filename(a, bsdar->filename, DEF_BLKSZ)); for (;;) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY || r == ARCHIVE_FATAL) bsdar_warnc(bsdar, 0, "%s", archive_error_string(a)); if (r == ARCHIVE_EOF || r == ARCHIVE_FATAL) break; if (r == ARCHIVE_RETRY) { bsdar_warnc(bsdar, 0, "Retrying..."); continue; } if ((name = archive_entry_pathname(entry)) == NULL) break; /* Skip pseudo members. */ if (strcmp(name, "/") == 0 || strcmp(name, "//") == 0) continue; if (bsdar->argc > 0) { find = 0; for(i = 0; i < bsdar->argc; i++) { av = &bsdar->argv[i]; if (*av == NULL) continue; if ((bname = basename(*av)) == NULL) bsdar_errc(bsdar, EX_SOFTWARE, errno, "basename failed"); if (strcmp(bname, name) != 0) continue; *av = NULL; find = 1; break; } if (!find) continue; } if (mode == 't') { if (bsdar->options & AR_V) { md = archive_entry_mode(entry); uid = archive_entry_uid(entry); gid = archive_entry_gid(entry); size = archive_entry_size(entry); mtime = archive_entry_mtime(entry); (void)strmode(md, buf); (void)fprintf(stdout, "%s %6d/%-6d %8ju ", buf + 1, uid, gid, (uintmax_t)size); tp = localtime(&mtime); (void)strftime(buf, sizeof(buf), "%b %e %H:%M %Y", tp); (void)fprintf(stdout, "%s %s", buf, name); } else (void)fprintf(stdout, "%s", name); r = archive_read_data_skip(a); if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY || r == ARCHIVE_FATAL) { (void)fprintf(stdout, "\n"); bsdar_warnc(bsdar, 0, "%s", archive_error_string(a)); } if (r == ARCHIVE_FATAL) break; (void)fprintf(stdout, "\n"); } else { /* mode == 'x' || mode = 'p' */ if (mode == 'p') { if (bsdar->options & AR_V) { (void)fprintf(stdout, "\n<%s>\n\n", name); fflush(stdout); } r = archive_read_data_into_fd(a, 1); } else { /* mode == 'x' */ if (stat(name, &sb) != 0) { if (errno != ENOENT) { bsdar_warnc(bsdar, 0, "stat %s failed", bsdar->filename); continue; } } else { /* stat success, file exist */ if (bsdar->options & AR_CC) continue; if (bsdar->options & AR_U && archive_entry_mtime(entry) <= sb.st_mtime) continue; } if (bsdar->options & AR_V) (void)fprintf(stdout, "x - %s\n", name); /* Disallow absolute paths. */ if (name[0] == '/') { bsdar_warnc(bsdar, 0, "Absolute path '%s'", name); continue; } /* Basic path security flags. */ flags = ARCHIVE_EXTRACT_SECURE_SYMLINKS | \ ARCHIVE_EXTRACT_SECURE_NODOTDOT; if (bsdar->options & AR_O) flags |= ARCHIVE_EXTRACT_TIME; r = archive_read_extract(a, entry, flags); } if (r) bsdar_warnc(bsdar, 0, "%s", archive_error_string(a)); } } AC(archive_read_close(a)); AC(archive_read_free(a)); }
static void test_open_filename_mbs(void) { char buff[64]; struct archive_entry *ae; struct archive *a; /* Write an archive through this FILE *. */ assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_none(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_filename(a, "test.tar")); /* * Write a file to it. */ assert((ae = archive_entry_new()) != NULL); archive_entry_set_mtime(ae, 1, 0); archive_entry_copy_pathname(ae, "file"); archive_entry_set_mode(ae, S_IFREG | 0755); archive_entry_set_size(ae, 8); assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); archive_entry_free(ae); assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); /* * Write a second file to it. */ assert((ae = archive_entry_new()) != NULL); archive_entry_copy_pathname(ae, "file2"); archive_entry_set_mode(ae, S_IFREG | 0755); archive_entry_set_size(ae, 819200); assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); archive_entry_free(ae); /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* * Now, read the data back. */ assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, "test.tar", 512)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt(1, archive_entry_mtime(ae)); assertEqualInt(0, archive_entry_mtime_nsec(ae)); assertEqualInt(0, archive_entry_atime(ae)); assertEqualInt(0, archive_entry_ctime(ae)); assertEqualString("file", archive_entry_pathname(ae)); assert((S_IFREG | 0755) == archive_entry_mode(ae)); assertEqualInt(8, archive_entry_size(ae)); assertEqualIntA(a, 8, archive_read_data(a, buff, 10)); assertEqualMem(buff, "12345678", 8); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("file2", archive_entry_pathname(ae)); assert((S_IFREG | 0755) == archive_entry_mode(ae)); assertEqualInt(819200, archive_entry_size(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); /* Verify the end of the archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* * Verify some of the error handling. */ assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_FATAL, archive_read_open_filename(a, "nonexistent.tar", 512)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); }
/* * Extract a mixed archive file which has both LZMA and LZMA2 encoded files. * LZMA: file1, file2, file3, file4 * LZMA2: zfile1, zfile2, zfile3, zfile4 */ static void test_extract_all_files2(const char *refname) { struct archive_entry *ae; struct archive *a; char buff[128]; extract_reference_file(refname); 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_filename(a, refname, 10240)); /* Verify regular file1. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); assertEqualString("dir1/file1", archive_entry_pathname(ae)); assertEqualInt(86401, archive_entry_mtime(ae)); assertEqualInt(13, archive_entry_size(ae)); assertEqualInt(13, archive_read_data(a, buff, sizeof(buff))); assertEqualMem(buff, "aaaaaaaaaaaa\n", 13); /* Verify regular file2. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); assertEqualString("file2", archive_entry_pathname(ae)); assertEqualInt(86401, archive_entry_mtime(ae)); assertEqualInt(26, archive_entry_size(ae)); assertEqualInt(26, archive_read_data(a, buff, sizeof(buff))); assertEqualMem(buff, "aaaaaaaaaaaa\nbbbbbbbbbbbb\n", 26); /* Verify regular file3. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); assertEqualString("file3", archive_entry_pathname(ae)); assertEqualInt(86401, archive_entry_mtime(ae)); assertEqualInt(39, archive_entry_size(ae)); assertEqualInt(39, archive_read_data(a, buff, sizeof(buff))); assertEqualMem(buff, "aaaaaaaaaaaa\nbbbbbbbbbbbb\ncccccccccccc\n", 39); /* Verify regular file4. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); assertEqualString("file4", archive_entry_pathname(ae)); assertEqualInt(86401, archive_entry_mtime(ae)); assertEqualInt(52, archive_entry_size(ae)); assertEqualInt(52, archive_read_data(a, buff, sizeof(buff))); assertEqualMem(buff, "aaaaaaaaaaaa\nbbbbbbbbbbbb\ncccccccccccc\ndddddddddddd\n", 52); /* Verify regular zfile1. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); assertEqualString("dir1/zfile1", archive_entry_pathname(ae)); assertEqualInt(5184001, archive_entry_mtime(ae)); assertEqualInt(13, archive_entry_size(ae)); assertEqualInt(13, archive_read_data(a, buff, sizeof(buff))); assertEqualMem(buff, "aaaaaaaaaaaa\n", 13); /* Verify regular zfile2. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); assertEqualString("zfile2", archive_entry_pathname(ae)); assertEqualInt(5184001, archive_entry_mtime(ae)); assertEqualInt(26, archive_entry_size(ae)); assertEqualInt(26, archive_read_data(a, buff, sizeof(buff))); assertEqualMem(buff, "aaaaaaaaaaaa\nbbbbbbbbbbbb\n", 26); /* Verify regular zfile3. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); assertEqualString("zfile3", archive_entry_pathname(ae)); assertEqualInt(5184001, archive_entry_mtime(ae)); assertEqualInt(39, archive_entry_size(ae)); assertEqualInt(39, archive_read_data(a, buff, sizeof(buff))); assertEqualMem(buff, "aaaaaaaaaaaa\nbbbbbbbbbbbb\ncccccccccccc\n", 39); /* Verify regular zfile4. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); assertEqualString("zfile4", archive_entry_pathname(ae)); assertEqualInt(5184001, archive_entry_mtime(ae)); assertEqualInt(52, archive_entry_size(ae)); assertEqualInt(52, archive_read_data(a, buff, sizeof(buff))); assertEqualMem(buff, "aaaaaaaaaaaa\nbbbbbbbbbbbb\ncccccccccccc\ndddddddddddd\n", 52); /* Verify directory dir1. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt((AE_IFDIR | 0755), archive_entry_mode(ae)); assertEqualString("dir1/", archive_entry_pathname(ae)); assertEqualInt(2764801, archive_entry_mtime(ae)); assertEqualInt(9, archive_file_count(a)); /* End of archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); /* Verify archive format. */ assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); /* Close the archive. */ assertEqualInt(ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); }
static void mode_in(struct cpio *cpio) { struct archive *a; struct archive_entry *entry; struct archive *ext; const char *destpath; int r; ext = archive_write_disk_new(); if (ext == NULL) lafe_errc(1, 0, "Couldn't allocate restore object"); r = archive_write_disk_set_options(ext, cpio->extract_flags); if (r != ARCHIVE_OK) lafe_errc(1, 0, "%s", archive_error_string(ext)); a = archive_read_new(); if (a == NULL) lafe_errc(1, 0, "Couldn't allocate archive object"); archive_read_support_compression_all(a); archive_read_support_format_all(a); if (archive_read_open_file(a, cpio->filename, cpio->bytes_per_block)) lafe_errc(1, archive_errno(a), "%s", archive_error_string(a)); for (;;) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) break; if (r != ARCHIVE_OK) { lafe_errc(1, archive_errno(a), "%s", archive_error_string(a)); } if (lafe_excluded(cpio->matching, archive_entry_pathname(entry))) continue; if (cpio->option_rename) { destpath = cpio_rename(archive_entry_pathname(entry)); archive_entry_set_pathname(entry, destpath); } else destpath = archive_entry_pathname(entry); if (destpath == NULL) continue; if (cpio->verbose) fprintf(stdout, "%s\n", destpath); if (cpio->uid_override >= 0) archive_entry_set_uid(entry, cpio->uid_override); if (cpio->gid_override >= 0) archive_entry_set_gid(entry, cpio->gid_override); r = archive_write_header(ext, entry); if (r != ARCHIVE_OK) { fprintf(stderr, "%s: %s\n", archive_entry_pathname(entry), archive_error_string(ext)); } else if (archive_entry_size(entry) > 0) { r = extract_data(a, ext); if (r != ARCHIVE_OK) cpio->return_value = 1; } } r = archive_read_close(a); if (r != ARCHIVE_OK) lafe_errc(1, 0, "%s", archive_error_string(a)); r = archive_write_close(ext); if (r != ARCHIVE_OK) lafe_errc(1, 0, "%s", archive_error_string(ext)); if (!cpio->quiet) { int64_t blocks = (archive_position_uncompressed(a) + 511) / 512; fprintf(stderr, "%lu %s\n", (unsigned long)blocks, blocks == 1 ? "block" : "blocks"); } archive_read_finish(a); archive_write_finish(ext); exit(cpio->return_value); }
bool LibArchiveInterface::copyFiles(const QVariantList& files, const QString& destinationDirectory, ExtractionOptions options) { kDebug() << "Changing current directory to " << destinationDirectory; QDir::setCurrent(destinationDirectory); const bool extractAll = files.isEmpty(); const bool preservePaths = options.value(QLatin1String( "PreservePaths" )).toBool(); QString rootNode = options.value(QLatin1String("RootNode"), QVariant()).toString(); if ((!rootNode.isEmpty()) && (!rootNode.endsWith(QLatin1Char('/')))) { rootNode.append(QLatin1Char('/')); } ArchiveRead arch(archive_read_new()); if (!(arch.data())) { return false; } if (archive_read_support_compression_all(arch.data()) != ARCHIVE_OK) { return false; } if (archive_read_support_format_all(arch.data()) != ARCHIVE_OK) { return false; } if (archive_read_open_filename(arch.data(), QFile::encodeName(filename()), 10240) != ARCHIVE_OK) { emit error(i18nc("@info", "Could not open the archive <filename>%1</filename>, libarchive cannot handle it.", filename())); return false; } ArchiveWrite writer(archive_write_disk_new()); if (!(writer.data())) { return false; } archive_write_disk_set_options(writer.data(), extractionFlags()); int entryNr = 0; int totalCount = 0; if (extractAll) { if (!m_cachedArchiveEntryCount) { emit progress(0); //TODO: once information progress has been implemented, send //feedback here that the archive is being read kDebug() << "For getting progress information, the archive will be listed once"; m_emitNoEntries = true; list(); m_emitNoEntries = false; } totalCount = m_cachedArchiveEntryCount; } else { totalCount = files.size(); } m_currentExtractedFilesSize = 0; bool overwriteAll = false; // Whether to overwrite all files bool skipAll = false; // Whether to skip all files struct archive_entry *entry; QString fileBeingRenamed; while (archive_read_next_header(arch.data(), &entry) == ARCHIVE_OK) { fileBeingRenamed.clear(); // retry with renamed entry, fire an overwrite query again // if the new entry also exists retry: const bool entryIsDir = S_ISDIR(archive_entry_mode(entry)); //we skip directories if not preserving paths if (!preservePaths && entryIsDir) { archive_read_data_skip(arch.data()); continue; } //entryName is the name inside the archive, full path QString entryName = QDir::fromNativeSeparators(QFile::decodeName(archive_entry_pathname(entry))); if (entryName.startsWith(QLatin1Char( '/' ))) { //for now we just can't handle absolute filenames in a tar archive. //TODO: find out what to do here!! emit error(i18n("This archive contains archive entries with absolute paths, which are not yet supported by ark.")); return false; } if (files.contains(entryName) || entryName == fileBeingRenamed || extractAll) { // entryFI is the fileinfo pointing to where the file will be // written from the archive QFileInfo entryFI(entryName); //kDebug() << "setting path to " << archive_entry_pathname( entry ); const QString fileWithoutPath(entryFI.fileName()); //if we DON'T preserve paths, we cut the path and set the entryFI //fileinfo to the one without the path if (!preservePaths) { //empty filenames (ie dirs) should have been skipped already, //so asserting Q_ASSERT(!fileWithoutPath.isEmpty()); archive_entry_copy_pathname(entry, QFile::encodeName(fileWithoutPath).constData()); entryFI = QFileInfo(fileWithoutPath); //OR, if the commonBase has been set, then we remove this //common base from the filename } else if (!rootNode.isEmpty()) { kDebug() << "Removing" << rootNode << "from" << entryName; const QString truncatedFilename(entryName.remove(0, rootNode.size())); archive_entry_copy_pathname(entry, QFile::encodeName(truncatedFilename).constData()); entryFI = QFileInfo(truncatedFilename); } //now check if the file about to be written already exists if (!entryIsDir && entryFI.exists()) { if (skipAll) { archive_read_data_skip(arch.data()); archive_entry_clear(entry); continue; } else if (!overwriteAll && !skipAll) { Kerfuffle::OverwriteQuery query(entryName); emit userQuery(&query); query.waitForResponse(); if (query.responseCancelled()) { archive_read_data_skip(arch.data()); archive_entry_clear(entry); break; } else if (query.responseSkip()) { archive_read_data_skip(arch.data()); archive_entry_clear(entry); continue; } else if (query.responseAutoSkip()) { archive_read_data_skip(arch.data()); archive_entry_clear(entry); skipAll = true; continue; } else if (query.responseRename()) { const QString newName(query.newFilename()); fileBeingRenamed = newName; archive_entry_copy_pathname(entry, QFile::encodeName(newName).constData()); goto retry; } else if (query.responseOverwriteAll()) { overwriteAll = true; } } } //if there is an already existing directory: if (entryIsDir && entryFI.exists()) { if (entryFI.isWritable()) { kDebug(1601) << "Warning, existing, but writable dir"; } else { kDebug(1601) << "Warning, existing, but non-writable dir. skipping"; archive_entry_clear(entry); archive_read_data_skip(arch.data()); continue; } } int header_response; kDebug() << "Writing " << fileWithoutPath << " to " << archive_entry_pathname(entry); if ((header_response = archive_write_header(writer.data(), entry)) == ARCHIVE_OK) { //if the whole archive is extracted and the total filesize is //available, we use partial progress copyData(arch.data(), writer.data(), (extractAll && m_extractedFilesSize)); } else if (header_response == ARCHIVE_WARN) { kDebug() << "Warning while writing " << entryName; } else { kDebug() << "Writing header failed with error code " << header_response << "While attempting to write " << entryName; } //if we only partially extract the archive and the number of //archive entries is available we use a simple progress based on //number of items extracted if (!extractAll && m_cachedArchiveEntryCount) { ++entryNr; emit progress(float(entryNr) / totalCount); } archive_entry_clear(entry); } else { archive_read_data_skip(arch.data()); } } return archive_read_close(arch.data()) == ARCHIVE_OK; }
/* * Apple shipped a customized version of bsdtar starting with MacOS 10.6. */ static void test_compat_mac_2(void) { char name[] = "test_compat_mac-2.tar.Z"; struct archive_entry *ae; struct archive *a; const void *attr; size_t attrSize; 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)); extract_reference_file(name); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("./", archive_entry_pathname(ae)); assertEqualInt(1303628303, archive_entry_mtime(ae)); assertEqualInt(501, archive_entry_uid(ae)); assertEqualString("tim", archive_entry_uname(ae)); assertEqualInt(20, archive_entry_gid(ae)); assertEqualString("staff", archive_entry_gname(ae)); assertEqualInt(040755, archive_entry_mode(ae)); attr = archive_entry_mac_metadata(ae, &attrSize); assert(attr == NULL); assertEqualInt(0, attrSize); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("./mydir/", archive_entry_pathname(ae)); assertEqualInt(1303628303, archive_entry_mtime(ae)); assertEqualInt(501, archive_entry_uid(ae)); assertEqualString("tim", archive_entry_uname(ae)); assertEqualInt(20, archive_entry_gid(ae)); assertEqualString("staff", archive_entry_gname(ae)); assertEqualInt(040755, archive_entry_mode(ae)); attr = archive_entry_mac_metadata(ae, &attrSize); assert(attr != NULL); assertEqualInt(267, attrSize); assertEqualMem("\x00\x05\x16\x07\x00\x02\x00\x00Mac OS X", attr, 16); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("./myfile", archive_entry_pathname(ae)); assertEqualInt(1303628303, archive_entry_mtime(ae)); assertEqualInt(501, archive_entry_uid(ae)); assertEqualString("tim", archive_entry_uname(ae)); assertEqualInt(20, archive_entry_gid(ae)); assertEqualString("staff", archive_entry_gname(ae)); assertEqualInt(0100644, archive_entry_mode(ae)); attr = archive_entry_mac_metadata(ae, &attrSize); assert(attr != NULL); assertEqualInt(267, attrSize); assertEqualMem("\x00\x05\x16\x07\x00\x02\x00\x00Mac OS X", attr, 16); /* Verify the end-of-archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); /* Verify that the format detection worked. */ assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); assertEqualInt(ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); }
static void * extract(void *p) { struct archive *a; struct archive *ext; struct archive_entry *entry; int r; int flags; struct extract_data *data = (struct extract_data *)p; flags = data->flags; a = archive_read_new(); ext = archive_write_disk_new(); archive_write_disk_set_options(ext, flags); /* * Note: archive_write_disk_set_standard_lookup() is useful * here, but it requires library routines that can add 500k or * more to a static executable. */ archive_read_support_format_all(a); archive_read_support_filter_all(a); /* * On my system, enabling other archive formats adds 20k-30k * each. Enabling gzip decompression adds about 20k. * Enabling bzip2 is more expensive because the libbz2 library * isn't very well factored. */ if ((r = archive_read_open_filename(a, FIFO, 4096))) { ERROR("archive_read_open_filename(): %s %d\n", archive_error_string(a), r); pthread_exit((void *)-1); } for (;;) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) break; if (r != ARCHIVE_OK) { ERROR("archive_read_next_header(): %s %d\n", archive_error_string(a), 1); pthread_exit((void *)-1); } if (debug) TRACE("Extracting %s\n", archive_entry_pathname(entry)); r = archive_write_header(ext, entry); if (r != ARCHIVE_OK) TRACE("archive_write_header(): %s\n", archive_error_string(ext)); else { copy_data(a, ext); r = archive_write_finish_entry(ext); if (r != ARCHIVE_OK) { ERROR("archive_write_finish_entry(): %s\n", archive_error_string(ext)); pthread_exit((void *)-1); } } } archive_read_close(a); archive_read_free(a); pthread_exit((void *)0); }
static void test_filename(const char *prefix, int dlen, int flen) { char buff[8192]; char filename[400]; char dirname[400]; struct archive_entry *ae; struct archive *a; size_t used; 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_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("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. */ 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)); /* Read the file and check the filename. */ assertA(0 == archive_read_next_header(a, &ae)); 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. We only report the first such failure * here. */ assertA(0 == archive_read_next_header(a, &ae)); assertEqualString(dirname, archive_entry_pathname(ae)); assert((S_IFDIR | 0755) == archive_entry_mode(ae)); assertA(0 == archive_read_next_header(a, &ae)); assertEqualString(dirname, archive_entry_pathname(ae)); assert((S_IFDIR | 0755) == archive_entry_mode(ae)); /* Verify the end of the archive. */ assert(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_read_format_mtree1(void) { const char reffile[] = "test_read_format_mtree.mtree"; char buff[16]; struct archive_entry *ae; struct archive *a; FILE *f; extract_reference_file(reffile); /* * An access error occurred on some platform when mtree * format handling open a directory. It is for through * the routine which open a directory that we create * "dir" and "dir2" directories. */ assertMakeDir("dir", 0775); assertMakeDir("dir2", 0775); assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_file(a, reffile, 11)); /* * Read "file", whose data is available on disk. */ f = fopen("file", "wb"); assert(f != NULL); assertEqualInt(3, fwrite("hi\n", 1, 3, f)); fclose(f); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE); assertEqualString(archive_entry_pathname(ae), "file"); assertEqualInt(archive_entry_uid(ae), 18); assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0123); assertEqualInt(archive_entry_size(ae), 3); assertEqualInt(3, archive_read_data(a, buff, 3)); assertEqualMem(buff, "hi\n", 3); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString(archive_entry_pathname(ae), "dir"); assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString(archive_entry_pathname(ae), "dir/file with space"); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString(archive_entry_pathname(ae), "file with space"); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString(archive_entry_pathname(ae), "dir2"); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString(archive_entry_pathname(ae), "dir2/dir3a"); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString(archive_entry_pathname(ae), "dir2/dir3a/indir3a"); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString(archive_entry_pathname(ae), "dir2/fullindir2"); assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString(archive_entry_pathname(ae), "dir2/indir2"); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString(archive_entry_pathname(ae), "dir2/dir3b"); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString(archive_entry_pathname(ae), "dir2/dir3b/indir3b"); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString(archive_entry_pathname(ae), "notindir"); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_finish(a)); }