int extract_file(char* dumpFile, char* file) { struct archive_entry *entry; int r; struct archive *a = archive_read_new(); archive_read_support_compression_gzip(a); archive_read_support_format_cpio(a); FILE *dump = fopen(dumpFile, "r"); r = archive_read_open_FILE(a, dump); if (r != ARCHIVE_OK) { fprintf(stderr, "Fail to read cpio file"); fclose(dump); return -1; } fclose(dump); FILE *outputFile = fopen(basename(file), "w"); int notfound = 1; while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { if(strcmp(basename(archive_entry_pathname(entry)), file) == 0) { notfound = 0; printf("extract %s\n",archive_entry_pathname(entry)); archive_read_data_into_fd(a, fileno(outputFile)); } } fclose(outputFile); archive_read_free(a); if(notfound) { sprintf(stderr, "The crash log %s was not found\n", file); return -1; } return 1; }
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; }
uint8_t *load(void **context, size_t *file_size, FILE *file, size_t max_size) { size_t pos; size_t size = 0; struct chunk *chunk; struct chunk head = { 0, &head, &head }; size_t chunk_size = load_size(file); int error = 0; #ifdef WITH_LIBARCHIVE struct archive *archive = *context; struct archive_entry *archive_entry; if (archive != NULL) goto init_ok; archive = archive_read_new(); *context = archive; if (archive == NULL) { error = ENOMEM; goto error; } archive_read_support_compression_all(archive); archive_read_support_format_all(archive); archive_read_support_format_raw(archive); if (archive_read_open_FILE(archive, file) != ARCHIVE_OK) { error = EIO; goto error; } init_ok: switch (archive_read_next_header(archive, &archive_entry)) { case ARCHIVE_OK: break; case ARCHIVE_EOF: error = 0; goto error; default: error = EIO; goto error; } #else *context = (void *)0xffff; #endif if (chunk_size == 0) chunk_size = CHUNK_SIZE; else if ((max_size != 0) && (chunk_size > max_size)) chunk_size = max_size; while (1) { pos = 0; chunk = malloc(sizeof(*chunk) + chunk_size); if (chunk == NULL) { error = errno; goto error; } chunk->size = chunk_size; chunk->next = &head; chunk->prev = head.prev; chunk->prev->next = chunk; head.prev = chunk; do { size_t i; #ifdef WITH_LIBARCHIVE ssize_t j; j = archive_read_data(archive, &chunk->data[pos], (chunk->size - pos)); /* Don't bother with ARCHIVE_WARN and ARCHIVE_RETRY, consider any negative value an error. */ if (j < 0) { error = EIO; goto error; } i = (size_t)j; #else i = fread(&chunk->data[pos], 1, (chunk->size - pos), file); #endif if (i == 0) { chunk->size = pos; #ifndef WITH_LIBARCHIVE if (ferror(file)) { error = EIO; goto error; } assert(feof(file)); #endif goto process; } pos += i; size += i; if ((max_size != 0) && (size > max_size)) { error = EFBIG; goto error; } } while (pos != chunk->size); chunk_size = CHUNK_SIZE; } process: chunk = realloc(head.next, (sizeof(*chunk) + size)); if (chunk == NULL) { error = errno; goto error; } chunk->next->prev = chunk; head.next = chunk; pos = chunk->size; chunk->size = size; chunk = chunk->next; while (chunk != &head) { struct chunk *next = chunk->next; memcpy(&head.next->data[pos], chunk->data, chunk->size); pos += chunk->size; chunk->next->prev = chunk->prev; chunk->prev->next = chunk->next; free(chunk); chunk = next; } chunk = head.next; chunk->prev = chunk; chunk->next = chunk; if (file_size != NULL) *file_size = chunk->size; return chunk->data; error: #ifdef WITH_LIBARCHIVE load_finish(context); #endif chunk = head.next; while (chunk != &head) { struct chunk *next = chunk->next; free(chunk); chunk = next; } errno = error; return NULL; }
bool extractXZ(FILE *sfp, std::string dest) { struct archive *a; struct archive *ext; struct archive_entry *entry; int flags; int r; /* Select which attributes we want to restore. */ flags = ARCHIVE_EXTRACT_TIME; flags |= ARCHIVE_EXTRACT_PERM; flags |= ARCHIVE_EXTRACT_ACL; flags |= ARCHIVE_EXTRACT_FFLAGS; a = archive_read_new(); archive_read_support_format_all(a); archive_read_support_filter_all(a); ext = archive_write_disk_new(); archive_write_disk_set_options(ext, flags); archive_write_disk_set_standard_lookup(ext); if ((r = archive_read_open_FILE(a, sfp))) { std::cout<<archive_error_string(ext)<<std::endl; return false; } for (;;) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) break; if (r < ARCHIVE_OK) fprintf(stderr, "%s\n", archive_error_string(a)); if (r < ARCHIVE_WARN) { fprintf(stderr, "warn 1\n"); return false; } std::string path = archive_entry_pathname(entry); //std::cout<<"old path: "<< path<<std::endl; archive_entry_set_pathname(entry, (dest + "/" + path).c_str()); r = archive_write_header(ext, entry); if (r < ARCHIVE_OK) fprintf(stderr, "%s\n", archive_error_string(ext)); else if (archive_entry_size(entry) > 0) { r = copy_data(a, ext); if (r < ARCHIVE_OK) fprintf(stderr, "%s\n", archive_error_string(ext)); if (r < ARCHIVE_WARN) { fprintf(stderr, "warn 2\n"); return false; } } r = archive_write_finish_entry(ext); if (r < ARCHIVE_OK) fprintf(stderr, "%s\n", archive_error_string(ext)); if (r < ARCHIVE_WARN) { fprintf(stderr, "warn 3\n"); return false; } } archive_read_close(a); archive_read_free(a); archive_write_close(ext); archive_write_free(ext); return true; }
static int pkg_read_archive_v2(FILE *fs, struct pkg *pkg, struct archive **a, struct archive_entry **ae) { struct pkg_section_hdr sec; int retcode = EPKG_OK; struct pkg_archive_stdio_cookie *cookie; FILE *cookied_fs; static const int rd_chunk = 8192; if (pkg_skip_to_section(fs, PKG_FORMAT_SECTION_PAYLOAD, &sec) != EPKG_OK) { return (EPKG_END); } *a = archive_read_new(); /* We don't support anything but (zstd) + tar here */ archive_read_support_filter_none(*a); archive_read_support_format_tar(*a); cookie = xmalloc(sizeof(*cookie)); cookie->fs = fs; cookie->remain = sec.size; if (sec.flags & PKG_FORMAT_FLAGS_ZSTD) { cookie->zstream = ZSTD_createDStream(); cookie->rdbuf = xmalloc(rd_chunk); cookie->rd_len = rd_chunk; cookie->rd_offset = 0; } else { cookie->zstream = NULL; } cookied_fs = funopen(cookie, pkg_archive_cookie_read, NULL, NULL, pkg_archive_cookie_close); if (archive_read_open_FILE(*a, cookied_fs) != ARCHIVE_OK) { pkg_emit_error("archive_read_open_fd: %s", archive_error_string(*a)); retcode = EPKG_FATAL; goto cleanup; } if (archive_read_next_header(*a, ae) != ARCHIVE_OK) { pkg_emit_error("archive_read_next_header: %s", archive_error_string(*a)); retcode = EPKG_FATAL; goto cleanup; } cleanup: if (retcode != EPKG_OK) { if (*a != NULL) { archive_read_close(*a); archive_read_free(*a); } } return (retcode); }