/* Helper function to copy data between archives. */ static int copy_file_data(struct bsdtar *bsdtar, struct archive *a, struct archive *ina) { ssize_t bytes_read; ssize_t bytes_written; off_t progress = 0; bytes_read = archive_read_data(ina, bsdtar->buff, FILEDATABUFLEN); while (bytes_read > 0) { disk_pause(bsdtar); if (network_select(0)) return (-1); siginfo_printinfo(bsdtar, progress); bytes_written = archive_write_data(a, bsdtar->buff, bytes_read); if (bytes_written < bytes_read) { bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a)); return (-1); } if (truncate_archive(bsdtar)) break; if (checkpoint_archive(bsdtar, 1)) return (-1); progress += bytes_written; bytes_read = archive_read_data(ina, bsdtar->buff, FILEDATABUFLEN); } return (0); }
/* Helper function to copy data between archives. */ static int copy_file_data(struct bsdtar *bsdtar, struct archive *a, struct archive *ina, struct archive_entry *entry) { ssize_t bytes_read; ssize_t bytes_written; int64_t progress = 0; bytes_read = archive_read_data(ina, bsdtar->buff, bsdtar->buff_size); while (bytes_read > 0) { if (need_report()) report_write(bsdtar, a, entry, progress); bytes_written = archive_write_data(a, bsdtar->buff, bytes_read); if (bytes_written < bytes_read) { lafe_warnc(0, "%s", archive_error_string(a)); return (-1); } progress += bytes_written; bytes_read = archive_read_data(ina, bsdtar->buff, bsdtar->buff_size); } return (0); }
static void test_binary(void) { const char reffile[] = "test_read_format_rar_binary_data.rar"; char file1_buff[1048576]; int file1_size = sizeof(file1_buff); const char file1_test_txt[] = "\x37\xef\xb2\xbe\x33\xf6\xcc\xcb\xee\x2a\x10" "\x9d\x2e\x01\xe9\xf6\xf9\xe5\xe6\x67\x0c\x2b" "\xd8\x6b\xa0\x26\x9a\xf7\x93\x87\x42\xf1\x08" "\x42\xdc\x9b\x76\x91\x20\xa4\x01\xbe\x67\xbd" "\x08\x74\xde\xec"; char file2_buff[32618]; int file2_size = sizeof(file2_buff); const char file2_test_txt[] = "\x00\xee\x78\x00\x00\x4d\x45\x54\x41\x2d\x49" "\x4e\x46\x2f\x6d\x61\x6e\x69\x66\x65\x73\x74" "\x2e\x78\x6d\x6c\x50\x4b\x05\x06\x00\x00\x00" "\x00\x12\x00\x12\x00\xaa\x04\x00\x00\xaa\x7a" "\x00\x00\x00\x00"; struct archive_entry *ae; struct archive *a; extract_reference_file(reffile); assert((a = archive_read_new()) != NULL); assertA(0 == archive_read_support_filter_all(a)); assertA(0 == archive_read_support_format_all(a)); assertA(0 == archive_read_open_file(a, reffile, 10240)); /* First header. */ assertA(0 == archive_read_next_header(a, &ae)); assertEqualString("random_data.bin", archive_entry_pathname(ae)); assertA((int)archive_entry_mtime(ae)); assertA((int)archive_entry_ctime(ae)); assertA((int)archive_entry_atime(ae)); assertEqualInt(file1_size, archive_entry_size(ae)); assertEqualInt(33188, archive_entry_mode(ae)); assertA(file1_size == archive_read_data(a, file1_buff, file1_size)); assertEqualMem(&file1_buff[file1_size - sizeof(file1_test_txt) + 1], file1_test_txt, sizeof(file1_test_txt) - 1); /* Second header. */ assertA(0 == archive_read_next_header(a, &ae)); assertEqualString("LibarchiveAddingTest.odt", archive_entry_pathname(ae)); assertA((int)archive_entry_mtime(ae)); assertA((int)archive_entry_ctime(ae)); assertA((int)archive_entry_atime(ae)); assertEqualInt(file2_size, archive_entry_size(ae)); assertEqualInt(33188, archive_entry_mode(ae)); assertA(file2_size == archive_read_data(a, file2_buff, file2_size)); assertEqualMem(&file2_buff[file2_size + 1 - sizeof(file2_test_txt)], file2_test_txt, sizeof(file2_test_txt) - 1); /* Test EOF */ assertA(1 == archive_read_next_header(a, &ae)); assertEqualInt(2, archive_file_count(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); }
/* * Extract a file compressed with PPMd. */ static void test_ppmd() { const char *refname = "test_read_format_7zip_ppmd.7z"; struct archive_entry *ae; struct archive *a; size_t remaining; ssize_t bytes; char buff[1024]; 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 | 0666), archive_entry_mode(ae)); assertEqualString("ppmd_test.txt", archive_entry_pathname(ae)); assertEqualInt(1322464589, archive_entry_mtime(ae)); assertEqualInt(102400, archive_entry_size(ae)); assertEqualInt(archive_entry_is_encrypted(ae), 0); assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); remaining = (size_t)archive_entry_size(ae); while (remaining) { if (remaining < sizeof(buff)) assertEqualInt(remaining, bytes = archive_read_data(a, buff, sizeof(buff))); else assertEqualInt(sizeof(buff), bytes = archive_read_data(a, buff, sizeof(buff))); if (bytes > 0) remaining -= bytes; else break; } assertEqualInt(0, remaining); assertEqualInt(1, 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)); }
/* * Extract a file compressed with BCJ + LZMA2. */ static void test_bcj(const char *refname) { struct archive_entry *ae; struct archive *a; size_t remaining; ssize_t bytes; char buff[1024]; 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 x86exe. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt((AE_IFREG | 0444), archive_entry_mode(ae) & ~0111); assertEqualString("x86exe", archive_entry_pathname(ae)); assertEqualInt(172802, archive_entry_mtime(ae)); assertEqualInt(27328, archive_entry_size(ae)); remaining = (size_t)archive_entry_size(ae); while (remaining) { if (remaining < sizeof(buff)) assertEqualInt(remaining, bytes = archive_read_data(a, buff, sizeof(buff))); else assertEqualInt(sizeof(buff), bytes = archive_read_data(a, buff, sizeof(buff))); if (bytes > 0) remaining -= bytes; else break; } assertEqualInt(0, remaining); assertEqualInt(1, 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 DEB_RESULT parse_control_file(struct archive *controlarchive, struct archive_entry *entry, DEB_FILE *file) { DEB_RESULT result = DEB_RESULT_OK; int64_t size = archive_entry_size(entry); char *buf = DEB_ALLOC(char *, size + 1); /* +1 for null terminator */ if(archive_read_data(controlarchive, buf, (size_t) size) != size) { result = DEB_RESULT_CONTROL_FILE_READ_FAIL; goto cleanup; } buf[size] = '\0'; DEB_PROPERTIES *properties = deb_properties_parse(buf); if(!properties) { result = DEB_RESULT_CONTROL_FILE_PARSE_FAIL; goto cleanup; } file->properties = properties; cleanup: if(buf) { free(buf); } return result; }
void verify_read_positions(struct archive *a) { struct archive_entry *ae; intmax_t read_position = 0; size_t j; /* Initial header position is zero. */ assert(read_position == (intmax_t)archive_read_header_position(a)); for (j = 0; j < sizeof(data_sizes)/sizeof(data_sizes[0]); ++j) { assertA(0 == archive_read_next_header(a, &ae)); assertEqualInt(read_position, (intmax_t)archive_read_header_position(a)); /* Every other entry: read, then skip */ if (j & 1) assertEqualInt(1, archive_read_data(a, tmp, 1)); assertA(0 == archive_read_data_skip(a)); /* read_data_skip() doesn't change header_position */ assertEqualInt(read_position, (intmax_t)archive_read_header_position(a)); read_position += 512; /* Size of header. */ read_position += (data_sizes[j] + 511) & ~511; } assertA(1 == archive_read_next_header(a, &ae)); assertEqualInt(read_position, (intmax_t)archive_read_header_position(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(read_position, (intmax_t)archive_read_header_position(a)); }
static void verify_file0_stream(struct archive *a, int size_known) { struct archive_entry *ae; assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualString("-", archive_entry_pathname(ae)); assertEqualInt(AE_IFREG | 0664, archive_entry_mode(ae)); if (size_known) { // zip64b has the uncompressed size at the beginning, // plus CRC and compressed size using length-at-end. assert(archive_entry_size_is_set(ae)); assertEqualInt(6, archive_entry_size(ae)); } else { // zip64a does not have a size at the beginning at all. assert(!archive_entry_size_is_set(ae)); } #ifdef HAVE_ZLIB_H { char data[16]; assertEqualIntA(a, 6, archive_read_data(a, data, 16)); assertEqualMem(data, "file0\x0a", 6); } #endif 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)); }
/* * Obsolete function provided for compatibility only. Note that the API * of this function doesn't allow the caller to detect if the remaining * data from the archive entry is shorter than the buffer provided, or * even if an error occurred while reading data. */ int archive_read_data_into_buffer(struct archive *a, void *d, ssize_t len) { archive_read_data(a, d, len); return (ARCHIVE_OK); }
/* * Extract to memory to check CRC */ static int test(struct archive *a, struct archive_entry *e) { ssize_t len; int error_count; error_count = 0; if (S_ISDIR(archive_entry_filetype(e))) return 0; info(" testing: %s\t", archive_entry_pathname(e)); while ((len = archive_read_data(a, buffer, sizeof buffer)) > 0) /* nothing */; if (len < 0) { info(" %s\n", archive_error_string(a)); ++error_count; } else { info(" OK\n"); } /* shouldn't be necessary, but it doesn't hurt */ ac(archive_read_data_skip(a)); return error_count; }
static int archive_entry_seek(stream_t *s, int64_t newpos) { struct priv *p = s->priv; if (!p->mpa) return -1; if (archive_seek_data(p->mpa->arch, newpos, SEEK_SET) >= 0) return 1; // libarchive can't seek in most formats. if (newpos < s->pos) { // Hack seeking backwards into working by reopening the archive and // starting over. MP_VERBOSE(s, "trying to reopen archive for performing seek\n"); if (reopen_archive(s) < STREAM_OK) return -1; s->pos = 0; } if (newpos > s->pos) { // For seeking forwards, just keep reading data (there's no libarchive // skip function either). char buffer[4096]; while (newpos > s->pos) { if (mp_cancel_test(s->cancel)) return -1; int size = MPMIN(newpos - s->pos, sizeof(buffer)); int r = archive_read_data(p->mpa->arch, buffer, size); if (r < 0) { MP_ERR(s, "%s\n", archive_error_string(p->mpa->arch)); return -1; } s->pos += r; } } return 1; }
static void test_noeof(void) { char buff[64]; const char reffile[] = "test_read_format_rar_noeof.rar"; const char test_txt[] = "test text document\r\n"; int size = sizeof(test_txt)-1; struct archive_entry *ae; struct archive *a; extract_reference_file(reffile); assert((a = archive_read_new()) != NULL); assertA(0 == archive_read_support_filter_all(a)); assertA(0 == archive_read_support_format_all(a)); assertA(0 == archive_read_open_file(a, reffile, 10240)); /* First header. */ assertA(0 == archive_read_next_header(a, &ae)); assertEqualString("test.txt", archive_entry_pathname(ae)); assertA((int)archive_entry_mtime(ae)); assertA((int)archive_entry_ctime(ae)); assertA((int)archive_entry_atime(ae)); assertEqualInt(20, archive_entry_size(ae)); assertEqualInt(33188, archive_entry_mode(ae)); assertA(size == archive_read_data(a, buff, size)); assertEqualMem(buff, test_txt, size); /* Test EOF */ assertA(1 == archive_read_next_header(a, &ae)); assertEqualInt(1, archive_file_count(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); }
char * file_readb (int fd, int numb) { File *ptr = lookup_file(fd); if (!ptr) return malloc_strdup(empty_string); else { char * ret; char * blah; blah = (char *)new_malloc(numb+1); if (ptr->elf->fp) { clearerr(ptr->elf->fp); numb = fread(blah, 1, numb, ptr->elf->fp); #ifdef HAVE_LIBARCHIVE } else if (ptr->elf->a) { numb = archive_read_data(ptr->elf->a, blah, numb); #endif } else { /* others */ } if ((ret = transform_string_dyn("+CTCP", blah, numb, NULL))) new_free(&blah); else ret = blah; return ret; } }
xbps_dictionary_t HIDDEN xbps_archive_get_dictionary(struct archive *ar, struct archive_entry *entry) { xbps_dictionary_t d = NULL; size_t buflen; ssize_t nbytes = -1; char *buf; assert(ar != NULL); assert(entry != NULL); buflen = (size_t)archive_entry_size(entry); buf = malloc(buflen); if (buf == NULL) return NULL; nbytes = archive_read_data(ar, buf, buflen); if ((size_t)nbytes != buflen) { free(buf); return NULL; } /* If blob is already a dictionary we are done */ d = xbps_dictionary_internalize(buf); if (xbps_object_type(d) == XBPS_TYPE_DICTIONARY) { free(buf); return d; } return NULL; }
bool la_copy_data_to_fd(archive *a, int fd) { char buf[BUF_SIZE]; la_ssize_t n_read; ssize_t n_written; la_ssize_t remain; while ((n_read = archive_read_data(a, buf, sizeof(buf))) > 0) { remain = n_read; while (remain > 0) { n_written = write(fd, buf + (n_read - remain), static_cast<size_t>(remain)); if (n_written <= 0) { LOGE("Failed to write data: %s", strerror(errno)); return false; } remain -= n_written; } } if (n_read < 0) { LOGE("Failed to read archive entry data: %s", archive_error_string(a)); return false; } return true; }
static ssize_t verify_signature_read_cb(struct archive *archive, void *cookie, const void **buf) { struct signature_archive *state = cookie; char hash[SHA512_DIGEST_STRING_LENGTH]; ssize_t len, expected; if (state->sign_cur_block >= state->sign_block_number) return 0; /* The following works for sign_block_len > 1 */ if (state->sign_cur_block + 1 == state->sign_block_number) expected = state->pkg_size % state->sign_block_len; else expected = state->sign_block_len; len = archive_read_data(state->archive, state->sign_buf, expected); if (len != expected) { warnx("Short read from package"); return -1; } hash_block(state->sign_buf, len, hash); if (strcmp(hash, state->sign_blocks[state->sign_cur_block]) != 0) { warnx("Invalid signature of block %llu", (unsigned long long)state->sign_cur_block); return -1; } ++state->sign_cur_block; *buf = state->sign_buf; return len; }
static int extract_one(struct archive* a, struct archive_entry* ae, uint32_t crc) { la_ssize_t fsize, bytes_read; uint8_t* buf; int ret = 1; uint32_t computed_crc; fsize = archive_entry_size(ae); buf = malloc(fsize); if(buf == NULL) return 1; bytes_read = archive_read_data(a, buf, fsize); if(bytes_read != fsize) { assertEqualInt(bytes_read, fsize); goto fn_exit; } computed_crc = crc32(0, buf, fsize); assertEqualInt(computed_crc, crc); ret = 0; fn_exit: free(buf); return ret; }
static void test_large_splitted_file(void) { static const char *reffiles[] = { "test_read_large_splitted_rar_aa", "test_read_large_splitted_rar_ab", "test_read_large_splitted_rar_ac", "test_read_large_splitted_rar_ad", "test_read_large_splitted_rar_ae", NULL }; const char test_txt[] = "gin-bottom: 0in\"><BR>\n</P>\n</BODY>\n</HTML>"; int size = 241647978, offset = 0; char buff[64]; struct archive_entry *ae; struct archive *a; extract_reference_files(reffiles); assert((a = archive_read_new()) != NULL); assertA(0 == archive_read_support_filter_all(a)); assertA(0 == archive_read_support_format_all(a)); assertA(0 == archive_read_open_filenames(a, reffiles, 10240)); /* First header. */ assertA(0 == archive_read_next_header(a, &ae)); assertEqualString("ppmd_lzss_conversion_test.txt", archive_entry_pathname(ae)); assertA((int)archive_entry_mtime(ae)); assertA((int)archive_entry_ctime(ae)); assertA((int)archive_entry_atime(ae)); assertEqualInt(size, archive_entry_size(ae)); assertEqualInt(33188, archive_entry_mode(ae)); while (offset + (int)sizeof(buff) < size) { assertA(sizeof(buff) == archive_read_data(a, buff, sizeof(buff))); offset += sizeof(buff); } assertA(size - offset == archive_read_data(a, buff, size - offset)); assertEqualMem(buff, test_txt, size - offset); /* Test EOF */ assertA(1 == archive_read_next_header(a, &ae)); assertEqualInt(1, archive_file_count(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); }
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; }
bool Decompress(const std::string & file, const std::string & output_path, std::ostream & info_output, std::ostream & error_output) { // Ensure the output path exists. PathManager::MakeDir(output_path); struct archive * a = archive_read_new(); archive_read_support_filter_all(a); archive_read_support_format_all(a); if (archive_read_open_filename(a, file.c_str(), BUFFSIZE) != ARCHIVE_OK) { error_output << "Unable to open " << file << std::endl; return false; } char buff[BUFFSIZE]; struct archive_entry *entry; while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { std::string filename = archive_entry_pathname(entry); std::string fullpath = output_path + "/" + filename; if (archive_entry_filetype(entry) == AE_IFDIR) PathManager::MakeDir(fullpath); else { std::fstream f(fullpath.c_str(), std::ios_base::out | std::ios_base::binary | std::ios_base::trunc); if (!f) { error_output << "Unable to open file for write (permissions issue?): " << fullpath << std::endl; return false; } int size = -1; while (size != 0) { size = archive_read_data(a, buff, BUFFSIZE); if (size < 0) { error_output << "Encountered corrupt file: " << filename << std::endl; return false; } else if (size != 0) f.write(buff, size); } } archive_read_data_skip(a); } if (archive_read_free(a) != ARCHIVE_OK) { error_output << "Unable to finish read of " << file << std::endl; return false; } info_output << "Successfully decompressed " << file << std::endl; return true; }
int extract_archive(char *filename) { struct archive *a; struct archive_entry *entry; int r; size_t size; char buff[BUFFER_SIZE]; FILE *fd; a = archive_read_new(); archive_read_support_compression_gzip(a); archive_read_support_format_tar(a); r = archive_read_open_filename(a, filename, 10240); if (r != ARCHIVE_OK) { return 1; } for (;;) { if ((r = archive_read_next_header(a, &entry))) { if (r != ARCHIVE_OK) { if (r == ARCHIVE_EOF) { return 0; }else{ return 1; } } } fd = fopen(archive_entry_pathname(entry),"wb"); if (fd == NULL) { fprintf(stderr, "problem extracting archive: %s: %s\n", filename, strerror(errno)); return 1; } for (;;) { size = archive_read_data(a, buff, BUFFER_SIZE); if (size < 0) { return 1; } if (size == 0) { break; } fwrite(buff, 1, size, fd); } fclose(fd); } r = archive_read_finish(a); if (r != ARCHIVE_OK) { return 4; } return 0; }
FILE * uncompress(FILE *f, FILE* out, enum Options options) { int fdtmp = -1, i, size; struct archive *a = NULL; struct archive_entry *entry; FILE *rv = f, *ftmp; char buf[BUFSIZ], tmpfile[] = "/tmp/nile.XXXXXX", nfilter = 0; if(!(options & NILE_DECOMPRESS)) goto uncompress_cleanup; a = archive_read_new(); archive_read_support_filter_all(a); archive_read_support_format_raw(a); if(archive_read_open_FILE(a, f) != ARCHIVE_OK || archive_read_next_header(a, &entry) != ARCHIVE_OK) { fprintf(stderr, "Warning: decompression failed while open\n"); goto uncompress_cleanup; } if((nfilter = archive_filter_count(a)) == 0) { goto uncompress_cleanup; } if((fdtmp = mkstemp(tmpfile)) == -1) { perror("mkstemp"); goto uncompress_cleanup; } while((size = archive_read_data(a, buf, sizeof(buf))) > 0) { write(fdtmp, buf, size); } if (size < 0) { fprintf(stderr, "Warning: decompression failed read\n"); goto uncompress_cleanup; } if((ftmp = fdopen(fdtmp, "r")) == NULL) { perror("fdopen"); goto uncompress_cleanup; } rv = ftmp; uncompress_cleanup: rewind(f); if(out != NULL) { for(i = 0; i < nfilter; i++) { fputc(archive_filter_code(a, i), out); } for(i = i % HEADER_PADDING; i < HEADER_PADDING; i++) { fputc(0, out); } } if(fdtmp > 0) close(fdtmp); if(a != NULL) { archive_read_free(a); } return rv; }
void PictureBank::loadArchive(const std::string &filename) { std::cout << "reading image archive: " << filename << std::endl; struct archive *a; struct archive_entry *entry; int rc; a = archive_read_new(); archive_read_support_compression_all(a); archive_read_support_format_all(a); rc = archive_read_open_filename(a, filename.c_str(), 16384); // block size if (rc != ARCHIVE_OK) { THROW("Cannot open archive " << filename); } SDL_Surface *surface; SDL_RWops *rw; const Uint32 bufferSize = 10000000; // allocated buffer std::auto_ptr< Uint8 > buffer( new Uint8[ bufferSize ] ); if( buffer.get() == 0 ) THROW("Memory error, cannot allocate buffer size " << bufferSize); std::string entryname; while( archive_read_next_header(a, &entry) == ARCHIVE_OK ) { // for all entries in archive entryname = archive_entry_pathname(entry); if ((archive_entry_stat(entry)->st_mode & S_IFREG) == 0) { // not a regular file (maybe a directory). skip it. continue; } if (archive_entry_stat(entry)->st_size >= bufferSize) { THROW("Cannot load archive: file is too big " << entryname << " in archive " << filename); } int size = archive_read_data(a, buffer.get(), bufferSize); // read data into buffer rw = SDL_RWFromMem(buffer.get(), size); surface = IMG_Load_RW(rw, 0); SDL_SetAlpha( surface, 0, 0 ); setPicture(entryname, *surface); SDL_FreeRW(rw); } rc = archive_read_finish(a); if (rc != ARCHIVE_OK) { THROW("Error while reading archive " << filename); } }
/* * memory to memory */ int archive_extract_file4( void *arch_buff, size_t arch_size, const char *src, void **dest_buff, size_t *dest_len ) { const char *filename; struct archive *arch_r = NULL; struct archive_entry *entry; if( !src ) return -1; arch_r = archive_read_new(); archive_read_support_format_all( arch_r ); archive_read_support_compression_all( arch_r ); if( archive_read_open_memory( arch_r, arch_buff, arch_size ) != ARCHIVE_OK ) goto errout; while( archive_read_next_header( arch_r, &entry ) == ARCHIVE_OK ) { filename = archive_entry_pathname( entry ); if( fnmatch( src, filename, FNM_PATHNAME | FNM_PERIOD ) ) { if( archive_read_data_skip( arch_r ) != ARCHIVE_OK ) { goto errout; } } else { #ifdef DEBUG printf("extract:%s\n", filename ); #endif *dest_len = archive_entry_size( entry ); if( *dest_len > 0 ) { *dest_buff = malloc( *dest_len + 1 ); memset( *dest_buff, 0, *dest_len + 1 ); } if( archive_read_data( arch_r, *dest_buff, *dest_len) < 0 ) goto errout; } } archive_read_finish( arch_r ); return 0; errout: #ifdef DEBUG fprintf( stderr, "%s\n", archive_error_string( arch_r ) ); #endif if( arch_r ) archive_read_finish( arch_r ); return -1; }
static int archive_entry_seek(stream_t *s, int64_t newpos) { struct priv *p = s->priv; if (p->mpa && !p->broken_seek) { locale_t oldlocale = uselocale(p->mpa->locale); int r = archive_seek_data(p->mpa->arch, newpos, SEEK_SET); uselocale(oldlocale); if (r >= 0) return 1; MP_WARN(s, "possibly unsupported seeking - switching to reopening\n"); p->broken_seek = true; if (reopen_archive(s) < STREAM_OK) return -1; } // libarchive can't seek in most formats. if (newpos < s->pos) { // Hack seeking backwards into working by reopening the archive and // starting over. MP_VERBOSE(s, "trying to reopen archive for performing seek\n"); if (reopen_archive(s) < STREAM_OK) return -1; s->pos = 0; } if (newpos > s->pos) { // For seeking forwards, just keep reading data (there's no libarchive // skip function either). char buffer[4096]; while (newpos > s->pos) { if (mp_cancel_test(s->cancel)) return -1; int size = MPMIN(newpos - s->pos, sizeof(buffer)); locale_t oldlocale = uselocale(p->mpa->locale); int r = archive_read_data(p->mpa->arch, buffer, size); if (r <= 0) { if (r == 0 && newpos > p->entry_size) { MP_ERR(s, "demuxer trying to seek beyond end of archive " "entry\n"); } else if (r == 0) { MP_ERR(s, "end of archive entry reached while seeking\n"); } else { MP_ERR(s, "%s\n", archive_error_string(p->mpa->arch)); } uselocale(oldlocale); if (mp_archive_check_fatal(p->mpa, r)) { mp_archive_free(p->mpa); p->mpa = NULL; } return -1; } uselocale(oldlocale); s->pos += r; } } return 1; }
static ssize_t inner_read(struct archive *a, void *client_data, const void **buff) { (void)a; struct inner_data *data = (struct inner_data *)client_data; *buff = data->buffer; return archive_read_data(data->outer, data->buffer, EXTRACT_BUFFER_LEN); }
static int archive_entry_fill_buffer(stream_t *s, char *buffer, int max_len) { struct priv *p = s->priv; if (!p->mpa) return 0; int r = archive_read_data(p->mpa->arch, buffer, max_len); if (r < 0) MP_ERR(s, "%s\n", archive_error_string(p->mpa->arch)); return r; }
static int read_file_from_archive(const char *archive_name, struct archive *archive, struct archive_entry **entry, const char *fname, char **content, size_t *len) { int r; *content = NULL; *len = 0; retry: if (*entry == NULL && (r = archive_read_next_header(archive, entry)) != ARCHIVE_OK) { if (r == ARCHIVE_FATAL) { warnx("Cannot read from archive `%s': %s", archive_name, archive_error_string(archive)); } else { warnx("Premature end of archive `%s'", archive_name); } *entry = NULL; return -1; } if (strcmp(archive_entry_pathname(*entry), "//") == 0) { archive_read_data_skip(archive); *entry = NULL; goto retry; } if (strcmp(fname, archive_entry_pathname(*entry)) != 0) return 1; /* if (archive_entry_size(*entry) > SSIZE_MAX - 1) { warnx("Signature of archive `%s' too large to process", archive_name); return 1; } */ *len = archive_entry_size(*entry); *content = xmalloc(*len + 1); if (archive_read_data(archive, *content, *len) != (ssize_t)*len) { warnx("Cannot read complete %s from archive `%s'", fname, archive_name); free(*content); *len = 0; *content = NULL; return 1; } (*content)[*len] = '\0'; *entry = NULL; return 0; }
static int check_resource(struct resource_list *list, const char *file_resource_name, struct archive *a, struct archive_entry *ae) { struct resource_list *item = rlist_find_by_name(list, file_resource_name); if (!item) ERR_RETURN("Can't find file-resource for %s", file_resource_name); if (item->processed) ERR_RETURN("Processing %s twice. Archive is corrupt.", file_resource_name); item->processed = true; struct sparse_file_map sfm; sparse_file_init(&sfm); OK_OR_RETURN(sparse_file_get_map_from_resource(item->resource, &sfm)); size_t expected_length = sparse_file_data_size(&sfm); ssize_t archive_length = archive_entry_size(ae); if (archive_length < 0) ERR_RETURN("Missing file length in archive for %s", file_resource_name); if ((size_t) archive_length != expected_length) ERR_RETURN("Length mismatch for %s", file_resource_name); char *expected_hash = cfg_getstr(item->resource, "blake2b-256"); if (!expected_hash || strlen(expected_hash) != crypto_generichash_BYTES * 2) ERR_RETURN("invalid blake2b-256 hash for '%s'", file_resource_name); crypto_generichash_state hash_state; crypto_generichash_init(&hash_state, NULL, 0, crypto_generichash_BYTES); size_t length_left = expected_length; while (length_left != 0) { char buffer[4096]; size_t to_read = sizeof(buffer); if (to_read > length_left) to_read = length_left; ssize_t len = archive_read_data(a, buffer, to_read); if (len <= 0) ERR_RETURN("Error reading '%s' in archive", archive_entry_pathname(ae)); crypto_generichash_update(&hash_state, (const unsigned char*) buffer, len); length_left -= len; } unsigned char hash[crypto_generichash_BYTES]; crypto_generichash_final(&hash_state, hash, sizeof(hash)); char hash_str[sizeof(hash) * 2 + 1]; bytes_to_hex(hash, hash_str, sizeof(hash)); if (memcmp(hash_str, expected_hash, sizeof(hash_str)) != 0) ERR_RETURN("Detected blake2b digest mismatch for %s", file_resource_name); return 0; }
pu_mtree_reader_t *pu_mtree_reader_open_package( alpm_handle_t *h, alpm_pkg_t *p) { pu_mtree_reader_t *reader; struct archive *mtree; char path[PATH_MAX]; struct archive_entry *entry = NULL; char *buf, rbuf[256]; size_t len; FILE *fbuf; const char *dbpath = alpm_option_get_dbpath(h); const char *pkgname = alpm_pkg_get_name(p); const char *pkgver = alpm_pkg_get_version(p); if((fbuf = open_memstream(&buf, &len)) == NULL) { return NULL; } sprintf(path, "%slocal/%s-%s/mtree", dbpath, pkgname, pkgver); if((mtree = archive_read_new()) == NULL) { return NULL; } archive_read_support_filter_all(mtree); archive_read_support_format_raw(mtree); if(archive_read_open_filename(mtree, path, 64) != ARCHIVE_OK) { archive_read_free(mtree); return NULL; } if(archive_read_next_header(mtree, &entry) != ARCHIVE_OK) { archive_read_free(mtree); return NULL; } while(1) { ssize_t size; while((size = archive_read_data(mtree, rbuf, 256)) == ARCHIVE_RETRY); if(size < 0) { fclose(fbuf); free(buf); return NULL; } if(size == 0) { break; } fwrite(rbuf, size, 1, fbuf); } archive_read_free(mtree); fclose(fbuf); if((fbuf = fmemopen(buf, len, "r")) == NULL) { free(buf); return NULL; } else if((reader = pu_mtree_reader_open_stream(fbuf)) == NULL) { free(buf); fclose(fbuf); return NULL; } else { reader->_stream_buf = buf; reader->_close_stream = 1; return reader; } }