bool CgCompressCreator::create( const QString& path, int, int, QImage& img ){ qCDebug(LOG) << "Trying to read image" << path; QFile file(path); if( !file.open( QIODevice::ReadOnly ) ) return false; archive* a = archive_read_new(); archive_read_support_format_zip(a); ReadingData data( file ); if( archive_read_open( a, &data, nullptr, stream_read, stream_close ) ) qCWarning(LOG) << "couldn't open:" << archive_error_string(a); else{ QString name; while( !(name = next_file( a )).isNull() ){ if( name.startsWith( "Thumbnails/thumbnail." ) || name.startsWith("thumb.") ){ qCDebug(LOG) << "Found thumbnail!"; QString suffix = QFileInfo(name).suffix(); img = read_image( a, suffix.toLocal8Bit().constData() ); break; } } } archive_read_close( a ); archive_read_free( a ); if( img.isNull() ) qCWarning(LOG) << "No thumbnail found!"; return !img.isNull(); }
/* * Verify that we skip junk between entries. The compat_zip_2.zip file * has several bytes of junk between 'file1' and 'file2'. Such * junk is routinely introduced by some Zip writers when they manipulate * existing zip archives. */ static void test_compat_zip_2(void) { char name[] = "test_compat_zip_2.zip"; struct archive_entry *ae; struct archive *a; assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); extract_reference_file(name); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); /* Read first entry. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("file1", archive_entry_pathname(ae)); /* Read first entry. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("file2", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); }
struct mp_archive *mp_archive_new(struct mp_log *log, struct stream *src, int flags) { struct mp_archive *mpa = talloc_zero(NULL, struct mp_archive); mpa->log = log; mpa->locale = newlocale(LC_ALL_MASK, "C.UTF-8", (locale_t)0); if (!mpa->locale) goto err; mpa->arch = archive_read_new(); mpa->primary_src = src; if (!mpa->arch) goto err; // first volume is the primary streame if (!add_volume(log ,mpa, src, src->url)) goto err; // try to open other volumes char** volumes = find_volumes(src); for (int i = 0; volumes[i]; i++) { if (!add_volume(log, mpa, NULL, volumes[i])) { talloc_free(volumes); goto err; } } talloc_free(volumes); locale_t oldlocale = uselocale(mpa->locale); archive_read_support_format_7zip(mpa->arch); archive_read_support_format_iso9660(mpa->arch); archive_read_support_format_rar(mpa->arch); archive_read_support_format_zip(mpa->arch); archive_read_support_filter_bzip2(mpa->arch); archive_read_support_filter_gzip(mpa->arch); archive_read_support_filter_xz(mpa->arch); if (flags & MP_ARCHIVE_FLAG_UNSAFE) { archive_read_support_format_gnutar(mpa->arch); archive_read_support_format_tar(mpa->arch); } archive_read_set_read_callback(mpa->arch, read_cb); archive_read_set_skip_callback(mpa->arch, skip_cb); archive_read_set_switch_callback(mpa->arch, switch_cb); archive_read_set_open_callback(mpa->arch, open_cb); archive_read_set_close_callback(mpa->arch, close_cb); if (mpa->primary_src->seekable) archive_read_set_seek_callback(mpa->arch, seek_cb); bool fail = archive_read_open1(mpa->arch) < ARCHIVE_OK; uselocale(oldlocale); if (fail) goto err; return mpa; err: mp_archive_free(mpa); return NULL; }
/* * Read a zip file that has a zip comment in the end of the central * directory record. */ static void verify(const char *refname) { char *p; size_t s; struct archive *a; struct archive_entry *ae; extract_reference_file(refname); p = slurpfile(&s, refname); /* Symlinks can only be extracted with the seeking reader. */ assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 1)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("file0", archive_entry_pathname(ae)); assertEqualInt(AE_IFREG | 0644, archive_entry_mode(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("build.sh", archive_entry_pathname(ae)); assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae)); assertEqualInt(23, archive_entry_size(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)); }
static void test_symlink(void) { const char *refname = "test_read_format_zip_symlink.zip"; char *p; size_t s; struct archive *a; struct archive_entry *ae; extract_reference_file(refname); p = slurpfile(&s, refname); /* Symlinks can only be extracted with the seeking reader. */ assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 1)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("file", archive_entry_pathname(ae)); assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); assertEqualInt(archive_entry_is_encrypted(ae), 0); assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("symlink", archive_entry_pathname(ae)); assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); assertEqualInt(0, archive_entry_size(ae)); assertEqualString("file", archive_entry_symlink(ae)); assertEqualInt(archive_entry_is_encrypted(ae), 0); assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); 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)); }
//******************************************************************************************************** void list_archive(const char* const infile) { // Adapted from: // https://github.com/libarchive/libarchive/wiki/Examples#List_contents_of_Archive_stored_in_File // Note - this function will always be "chatty"; make sure to flush the stdout before using it... // TODO: Write a function which *returns* the list of files // (by writing it into a char** supplied by the caller) fprintf(stderr, "Opening archive '%s' for listing...\n",infile); struct archive* a = archive_read_new(); archive_read_support_format_zip(a); int err = archive_read_open_filename(a, infile,10240);//Note: Blocksize isn't neccessarilly adhered to if (err != ARCHIVE_OK) { fprintf(stderr, "CRITICAL ERROR in list_archive(): When opening archive '%s', err=%i\n",infile,err); fprintf(stderr, "CRITICAL ERROR in list_archive(): %s\n",archive_error_string(a)); exit(EXIT_FAILURE); } struct archive_entry* entry; while (archive_read_next_header(a,&entry)==ARCHIVE_OK){ printf("Found file: '%s'\n",archive_entry_pathname(entry)); archive_read_data_skip(a); } archive_read_close(a); err = archive_read_free(a); if (err != ARCHIVE_OK){ fprintf(stderr, "CRITICAL ERROR in list_archive(): Error when calling archive_read_free(), '%s', err=%i\n",infile,err); fprintf(stderr, "CRITICAL ERROR in list_archive(): %s\n",archive_error_string(a)); exit(EXIT_FAILURE); } }
/* * Issue 226: Try to reproduce hang when reading archives where the * length-at-end marker ends exactly on a block boundary. */ static void test_compat_zip_7(void) { const char *refname = "test_compat_zip_7.xps"; struct archive *a; struct archive_entry *ae; void *p; size_t s; int i; extract_reference_file(refname); p = slurpfile(&s, refname); for (i = 1; i < 1000; ++i) { assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); assertEqualIntA(a, ARCHIVE_OK, read_open_memory_minimal(a, p, s, i)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); } free(p); }
static char * file_get_zipped_contents (const char *filename, GCompareFunc func, gpointer user_data, gsize *length) { struct archive *a; struct archive_entry *entry; char *ret = NULL; int r; *length = 0; a = archive_read_new (); archive_read_support_format_zip (a); r = archive_read_open_filename (a, filename, 10240); if (r != ARCHIVE_OK) { g_print ("Failed to open archive %s\n", filename); return NULL; } while (1) { const char *name; r = archive_read_next_header(a, &entry); if (r != ARCHIVE_OK) { if (r != ARCHIVE_EOF && r == ARCHIVE_FATAL) g_warning ("Fatal error handling archive: %s", archive_error_string (a)); break; } name = archive_entry_pathname (entry); if (func (name, user_data) == 0) { size_t size = archive_entry_size (entry); char *buf; ssize_t read; buf = g_malloc (size); read = archive_read_data (a, buf, size); if (read <= 0) { g_free (buf); if (read < 0) g_warning ("Fatal error reading '%s' in archive: %s", name, archive_error_string (a)); else g_warning ("Read an empty file from the archive"); } else { ret = buf; *length = size; } break; } archive_read_data_skip(a); } archive_read_free(a); return ret; }
int archive_read_support_format_all(struct archive *a) { archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_support_format_all"); /* TODO: It would be nice to compute the ordering * here automatically so that people who enable just * a few formats can still get the benefits. That * may just require the format registration to include * a "maximum read-ahead" value (anything that uses seek * would be essentially infinite read-ahead). The core * bid management can then sort the bidders before calling * them. * * If you implement the above, please return the list below * to alphabetic order. */ /* * These bidders are all pretty cheap; they just examine a * small initial part of the archive. If one of these bids * high, we can maybe avoid running any of the more expensive * bidders below. */ archive_read_support_format_ar(a); archive_read_support_format_cpio(a); archive_read_support_format_empty(a); archive_read_support_format_lha(a); archive_read_support_format_mtree(a); archive_read_support_format_tar(a); archive_read_support_format_xar(a); /* * Install expensive bidders last. By doing them last, we * increase the chance that a high bid from someone else will * make it unnecessary for these to do anything at all. */ /* These three have potentially large look-ahead. */ archive_read_support_format_7zip(a); archive_read_support_format_cab(a); archive_read_support_format_rar(a); archive_read_support_format_iso9660(a); /* Seek is really bad, since it forces the read-ahead * logic to discard buffered data. */ archive_read_support_format_zip(a); /* Note: We always return ARCHIVE_OK here, even if some of the * above return ARCHIVE_WARN. The intent here is to enable * "as much as possible." Clients who need specific * compression should enable those individually so they can * verify the level of support. */ /* Clear any warning messages set by the above functions. */ archive_clear_error(a); return (ARCHIVE_OK); }
void load_examples(const void *data, size_t len, example_list_t *examples) { example_patch_t *patch; struct archive *arch; struct archive_entry *ent; const char *path; FILE *fp; char *buf; size_t size; char block[4096]; ssize_t count; int ret; assert(data != NULL); arch = archive_read_new(); assert(arch != NULL); if (archive_read_support_format_zip(arch)) abort(); if (archive_read_open_memory(arch, (void *) data, len)) abort(); while (!(ret = archive_read_next_header(arch, &ent))) { if (!S_ISREG(archive_entry_filetype(ent))) continue; path = archive_entry_pathname(ent); if (strncmp(path, EXAMPLE_DIR "/", strlen(EXAMPLE_DIR) + 1)) continue; /* archive_entry_size() is not reliable for Zip files */ fp = open_memstream(&buf, &size); if (fp == NULL) abort(); while ((count = archive_read_data(arch, block, sizeof(block))) > 0) if (fwrite(block, 1, count, fp) != (size_t) count) abort(); if (count < 0) { fprintf(stderr, "%s\n", archive_error_string(arch)); abort(); } fclose(fp); patch = malloc(sizeof(*patch)); patch->image = read_rgb_image(buf, size); if (patch->image == NULL) { fprintf(stderr, "Couldn't decode example %s\n", path); abort(); } TAILQ_INSERT_TAIL(examples, patch, link); free(buf); } assert(ret == ARCHIVE_EOF); if (archive_read_finish(arch)) abort(); }
int archive_read_support_format_all(struct archive *a) { archive_read_support_format_ar(a); archive_read_support_format_cpio(a); archive_read_support_format_empty(a); archive_read_support_format_iso9660(a); archive_read_support_format_mtree(a); archive_read_support_format_tar(a); archive_read_support_format_xar(a); archive_read_support_format_zip(a); return (ARCHIVE_OK); }
int dbp_meta_package_open(const char *path, struct DBPMetaPackage *mp) { struct archive *a; struct archive_entry *ae; int errid, found, size; char *data; struct stat statbuf; mp->df = NULL; if (!(a = archive_read_new())) return DBP_ERROR_NO_MEMORY; archive_read_support_format_zip(a); if (archive_read_open_filename(a, path, 512) != ARCHIVE_OK) { errid = (stat(path, &statbuf) || S_ISREG(statbuf.st_mode)) ? DBP_ERROR_NO_PKG_ACCESS : DBP_ERROR_BAD_META; goto error; } for (found = 0; archive_read_next_header(a, &ae) == ARCHIVE_OK; ) if (!strcmp("meta/default.desktop", archive_entry_pathname(ae))) { found = 1; break; } if (!found) { errid = DBP_ERROR_NO_DEFAULTD; goto error; } size = archive_entry_size(ae); if (!(data = malloc(size + 1))) { errid = DBP_ERROR_NO_MEMORY; goto error; } archive_read_data(a, data, size); data[size] = 0; mp->df = dbp_desktop_parse(data); free(data); archive_read_free(a); mp->section = "Package Entry"; return 0; error: archive_read_free(a); return errid; }
void list_archive_get(const char* const infile, char** filenames, int* nfiles, const int buffsize) { //printf("In list_archive_get\n"); //fflush(stdout); struct archive* a = archive_read_new(); archive_read_support_format_zip(a); int err = archive_read_open_filename(a, infile,10240);//Note: Blocksize isn't neccessarilly adhered to if (err != ARCHIVE_OK) { fprintf(stderr, "CRITICAL ERROR in list_archive_get(): When opening archive '%s', err=%i\n",infile,err); fprintf(stderr, "CRITICAL ERROR in list_archive_get(): %s\n",archive_error_string(a)); exit(EXIT_FAILURE); } const int nfiles_max = *nfiles; *nfiles = 0; struct archive_entry* entry; while (archive_read_next_header(a,&entry)==ARCHIVE_OK){ //printf("Found file: '%s'\n",archive_entry_pathname(entry)); //fflush(stdout); int buff_used = 0; buff_used = snprintf(filenames[*nfiles],buffsize,"%s",archive_entry_pathname(entry)); if (buff_used >= buffsize) { fprintf(stderr, "CRITICAL ERROR in list_archive_get(): When reading file '%s' from archive '%s':\n",filenames[*nfiles],infile); fprintf(stderr, "CRITICAL ERROR in list_archive_get(): Buffer too small by %i characters\n",buff_used-buffsize+1); exit(EXIT_FAILURE); } else if (buff_used < 0) { fprintf(stderr, "CRITICAL ERROR in list_archive_get(): When reading file '%s' from archive '%s':\n",filenames[*nfiles],infile); fprintf(stderr, "CRITICAL ERROR in list_archive_get(): Error in snprintf.\n"); exit(EXIT_FAILURE); } archive_read_data_skip(a); if(++(*nfiles) >= nfiles_max) { fprintf(stderr, "CRITICAL ERROR in list_archive_get(): Number of files greater than nfiles_max=%i",nfiles_max); exit(EXIT_FAILURE); } } archive_read_close(a); err = archive_read_free(a); if (err != ARCHIVE_OK){ fprintf(stderr, "CRITICAL ERROR in list_archive_get(): Error when calling archive_read_free(), '%s', err=%i\n",infile,err); fprintf(stderr, "CRITICAL ERROR in list_archive_get(): %s\n",archive_error_string(a)); exit(EXIT_FAILURE); } }
static bool set_up_input(archive *in, const std::string &filename) { // Add more as needed //archive_read_support_format_all(in); //archive_read_support_filter_all(in); //archive_read_support_format_tar(in); archive_read_support_format_zip(in); //archive_read_support_filter_xz(in); if (archive_read_open_filename(in, filename.c_str(), 10240) != ARCHIVE_OK) { LOGE("%s: Failed to open archive: %s", filename.c_str(), archive_error_string(in)); return false; } return true; }
/* Copy this function for each test file and adjust it accordingly. */ static void test_compat_zip_1(void) { char name[] = "test_compat_zip_1.zip"; struct archive_entry *ae; struct archive *a; int r; assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); extract_reference_file(name); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); /* Read first entry. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("META-INF/MANIFEST.MF", archive_entry_pathname(ae)); /* Read second entry. */ r = archive_read_next_header(a, &ae); if (r != ARCHIVE_OK) { if (strcmp(archive_error_string(a), "libarchive compiled without deflate support (no libz)") == 0) { skipping("Skipping ZIP compression check: %s", archive_error_string(a)); goto finish; } } assertEqualIntA(a, ARCHIVE_OK, r); assertEqualString("tmp.class", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ZIP); assertEqualInt(ARCHIVE_OK, archive_read_close(a)); finish: #if ARCHIVE_VERSION_NUMBER < 2000000 archive_read_finish(a); #else assertEqualInt(ARCHIVE_OK, archive_read_finish(a)); #endif }
static struct archive *file_type_archive_gen_archive(GBytes *data) {/*{{{*/ struct archive *archive = archive_read_new(); archive_read_support_format_zip(archive); archive_read_support_format_rar(archive); archive_read_support_format_7zip(archive); archive_read_support_format_tar(archive); archive_read_support_filter_all(archive); gsize data_size; char *data_ptr = (char *)g_bytes_get_data(data, &data_size); if(archive_read_open_memory(archive, data_ptr, data_size) != ARCHIVE_OK) { g_printerr("Failed to load archive: %s\n", archive_error_string(archive)); archive_read_free(archive); return NULL; } return archive; }/*}}}*/
int archive_read_support_format_by_code(struct archive *a, int format_code) { archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_support_format_by_code"); switch (format_code & ARCHIVE_FORMAT_BASE_MASK) { case ARCHIVE_FORMAT_7ZIP: return archive_read_support_format_7zip(a); break; case ARCHIVE_FORMAT_AR: return archive_read_support_format_ar(a); break; case ARCHIVE_FORMAT_CAB: return archive_read_support_format_cab(a); break; case ARCHIVE_FORMAT_CPIO: return archive_read_support_format_cpio(a); break; case ARCHIVE_FORMAT_ISO9660: return archive_read_support_format_iso9660(a); break; case ARCHIVE_FORMAT_LHA: return archive_read_support_format_lha(a); break; case ARCHIVE_FORMAT_MTREE: return archive_read_support_format_mtree(a); break; case ARCHIVE_FORMAT_RAR: return archive_read_support_format_rar(a); break; case ARCHIVE_FORMAT_TAR: return archive_read_support_format_tar(a); break; case ARCHIVE_FORMAT_XAR: return archive_read_support_format_xar(a); break; case ARCHIVE_FORMAT_ZIP: return archive_read_support_format_zip(a); break; } return (ARCHIVE_FATAL); }
/* Copy this function for each test file and adjust it accordingly. */ static void test_compat_zip_1(void) { char name[] = "test_compat_zip_1.zip"; 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_zip(a)); extract_reference_file(name); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); /* Read first entry. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("META-INF/MANIFEST.MF", archive_entry_pathname(ae)); /* Read second entry. */ r = archive_read_next_header(a, &ae); if (r == ARCHIVE_FATAL && !libz_enabled) { skipping("Skipping ZIP compression check: %s", archive_error_string(a)); goto finish; } assertEqualIntA(a, ARCHIVE_OK, r); assertEqualString("tmp.class", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ZIP); finish: assertEqualInt(ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); }
/** * @brief Verify that the firmware archive is ok * @param input_filename the firmware update filename * @param public_keys the public keys if authentication check * @return 0 if successful */ int fwup_verify(const char *input_filename, unsigned char * const *public_keys) { unsigned char *meta_conf_signature = NULL; struct resource_list *all_resources = NULL; cfg_t *cfg = NULL; int rc = 0; struct archive *a = archive_read_new(); archive_read_support_format_zip(a); if (!input_filename) ERR_CLEANUP_MSG("Specify an input firmware file"); rc = fwup_archive_open_filename(a, input_filename); if (rc != ARCHIVE_OK) ERR_CLEANUP_MSG("%s", archive_error_string(a)); struct archive_entry *ae; rc = archive_read_next_header(a, &ae); if (rc != ARCHIVE_OK) ERR_CLEANUP_MSG("%s", archive_error_string(a)); if (strcmp(archive_entry_pathname(ae), "meta.conf.ed25519") == 0) { off_t total_size; if (archive_read_all_data(a, ae, (char **) &meta_conf_signature, crypto_sign_BYTES, &total_size) < 0) ERR_CLEANUP_MSG("Error reading meta.conf.ed25519 from archive.\n" "Check for file corruption or libarchive built without zlib support"); if (total_size != crypto_sign_BYTES) ERR_CLEANUP_MSG("Unexpected meta.conf.ed25519 size: %d", total_size); rc = archive_read_next_header(a, &ae); if (rc != ARCHIVE_OK) ERR_CLEANUP_MSG("Expecting more than meta.conf.ed25519 in archive"); } if (strcmp(archive_entry_pathname(ae), "meta.conf") != 0) ERR_CLEANUP_MSG("Expecting meta.conf to be at the beginning of %s", input_filename); OK_OR_CLEANUP(cfgfile_parse_fw_ae(a, ae, &cfg, meta_conf_signature, public_keys)); OK_OR_CLEANUP(rlist_get_all(cfg, &all_resources)); while (archive_read_next_header(a, &ae) == ARCHIVE_OK) { const char *filename = archive_entry_pathname(ae); char resource_name[FWFILE_MAX_ARCHIVE_PATH]; OK_OR_CLEANUP(archive_filename_to_resource(filename, resource_name, sizeof(resource_name))); OK_OR_CLEANUP(check_resource(all_resources, resource_name, a, ae)); } // Check that all resources have been validated for (struct resource_list *r = all_resources; r != NULL; r = r->next) { if (!r->processed) ERR_CLEANUP_MSG("Resource %s not found in archive", cfg_title(r->resource)); } const char *success_message; if (*public_keys && meta_conf_signature) success_message = "Valid archive with a good signature\n"; else if (!*public_keys && meta_conf_signature) success_message = "Valid archive with an unverified signature. Specify a public key to authenticate.\n"; else success_message = "Valid archive without a signature\n"; fwup_output(FRAMING_TYPE_SUCCESS, 0, success_message); cleanup: rlist_free(all_resources); archive_read_close(a); archive_read_free(a); if (meta_conf_signature) free(meta_conf_signature); if (cfg) cfgfile_free(cfg); return rc; }
//******************************************************************************************************** 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); } }
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; }
/* * 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 ret; uintmax_t total_size, file_count, error_count; if ((a = archive_read_new()) == NULL) error("archive_read_new failed"); ac(archive_read_support_format_zip(a)); ac(archive_read_open_filename(a, fn, 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_free(a); 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); } } }
bool extract_archive(const char *filename, const char *target) { struct archive *in = NULL; struct archive *out = NULL; struct archive_entry *entry; int ret; char *cwd = NULL; if (!(in = archive_read_new())) { LOGE("Out of memory"); goto error; } // Add more as needed //archive_read_support_format_all(in); //archive_read_support_filter_all(in); archive_read_support_format_tar(in); archive_read_support_format_zip(in); archive_read_support_filter_xz(in); if (archive_read_open_filename(in, filename, 10240) != ARCHIVE_OK) { LOGE("%s: Failed to open archive: %s", filename, archive_error_string(in)); goto error; } if (!(out = archive_write_disk_new())) { LOGE("Out of memory"); goto error; } archive_write_disk_set_options(out, ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_SECURE_NODOTDOT | ARCHIVE_EXTRACT_SECURE_SYMLINKS | ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_UNLINK | ARCHIVE_EXTRACT_XATTR); if (!(cwd = getcwd(NULL, 0))) { LOGE("Failed to get cwd: %s", strerror(errno)); goto error; } if (chdir(target) < 0) { LOGE("%s: Failed to change to target directory: %s", target, strerror(errno)); goto error; } while ((ret = archive_read_next_header(in, &entry)) == ARCHIVE_OK) { if ((ret = archive_write_header(out, entry)) != ARCHIVE_OK) { LOGE("Failed to write header: %s", archive_error_string(out)); goto error; } const void *buff; size_t size; int64_t offset; int ret; while ((ret = archive_read_data_block( in, &buff, &size, &offset)) == ARCHIVE_OK) { if (archive_write_data_block(out, buff, size, offset) != ARCHIVE_OK) { LOGE("Failed to write data: %s", archive_error_string(out)); goto error; } } if (ret != ARCHIVE_EOF) { LOGE("Data copy ended without reaching EOF: %s", archive_error_string(in)); goto error; } } if (ret != ARCHIVE_EOF) { LOGE("Archive extraction ended without reaching EOF: %s", archive_error_string(in)); goto error; } chdir(cwd); archive_read_free(in); archive_write_free(out); return true; error: if (cwd) { chdir(cwd); } archive_read_free(in); archive_write_free(out); return false; }
static Eina_Bool _etui_epub_file_unzip(Etui_Provider_Data *pd) { struct archive *a; struct archive_entry *entry; int r; if (!eina_file_mkdtemp("etui-epub-tmp-XXXXXX", &pd->doc.path)) return EINA_FALSE; a = archive_read_new(); if (!a) goto free_path; if (archive_read_support_filter_all(a) != ARCHIVE_OK) goto free_path; if (archive_read_support_format_zip(a) != ARCHIVE_OK) goto free_path; r = archive_read_open_filename(a, pd->doc.filename, 16384); if (r != ARCHIVE_OK) goto free_path; while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { if (archive_entry_filetype(entry) == AE_IFREG) { char buf[PATH_MAX]; const char *name; char *dir; char *base; size_t size; void *data; name = archive_entry_pathname(entry); dir = strdup(name); base = strdup(name); if (dir && base && (strcmp(dir, ".") != 0)) { snprintf(buf, sizeof(buf), "%s/%s", pd->doc.path, dirname(dir)); buf[sizeof(buf) - 1] = '\0'; ecore_file_mkdir(buf); printf(" * %s %s %s\n", name, dirname(dir), basename(base)); } if (base) free(base); if (dir) free(dir); size = archive_entry_size(entry); data = malloc(size); if (data) { size_t res; res = archive_read_data(a, data, size); if (res > 0) { FILE *f; snprintf(buf, sizeof(buf), "%s/%s", pd->doc.path, name); buf[sizeof(buf) - 1] = '\0'; printf(" $ %s\n", buf); f = fopen(buf, "wb"); if (f) { fwrite(data, 1, size, f); fclose(f); } } free(data); } } archive_read_data_skip(a); } archive_read_free(a); return EINA_TRUE; free_path: eina_tmpstr_del(pd->doc.path); return EINA_FALSE; }