static int get_format(const char *archive) { struct archive *a; struct archive_entry *ae; int found_format; assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_mtree(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_raw(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_empty(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, archive, strlen(archive))); // Read one header to settle the format. // This might return EOF or OK. archive_read_next_header(a, &ae); found_format = archive_format(a); assertEqualInt(ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); return found_format; }
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); }
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); }
static void test(int formatted, archive_open_callback *o, archive_read_callback *r, archive_skip_callback *s, archive_close_callback *c, int rv, const char *msg) { struct archive* a = archive_read_new(); if (formatted) assertEqualInt(ARCHIVE_OK, archive_read_support_format_empty(a)); assertEqualInt(rv, archive_read_open2(a, NULL, o, r, s, c)); assertEqualString(msg, archive_error_string(a)); archive_read_free(a); }
static void test_empty_file2(void) { struct archive* a = archive_read_new(); struct archive_entry* e; /* Try opening an empty file with raw and empty handlers. */ assertEqualInt(ARCHIVE_OK, archive_read_support_format_raw(a)); assertEqualInt(ARCHIVE_OK, archive_read_support_format_empty(a)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); assertEqualInt(ARCHIVE_OK, archive_read_open_filename(a, "emptyfile", 0)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &e)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); archive_read_free(a); }
/* * Same as 'c', except we only support tar or empty formats in * uncompressed files on disk. */ void tar_mode_r(struct bsdtar *bsdtar) { int64_t end_offset; int format; struct archive *a; struct archive_entry *entry; int r; /* Sanity-test some arguments and the file. */ test_for_append(bsdtar); format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED; #if defined(__BORLANDC__) bsdtar->fd = open(bsdtar->filename, O_RDWR | O_CREAT | O_BINARY); #else bsdtar->fd = open(bsdtar->filename, O_RDWR | O_CREAT | O_BINARY, 0666); #endif if (bsdtar->fd < 0) lafe_errc(1, errno, "Cannot open %s", bsdtar->filename); a = archive_read_new(); archive_read_support_filter_all(a); archive_read_support_format_empty(a); archive_read_support_format_tar(a); archive_read_support_format_gnutar(a); set_reader_options(bsdtar, a); r = archive_read_open_fd(a, bsdtar->fd, 10240); if (r != ARCHIVE_OK) lafe_errc(1, archive_errno(a), "Can't read archive %s: %s", bsdtar->filename, archive_error_string(a)); while (0 == archive_read_next_header(a, &entry)) { if (archive_filter_code(a, 0) != ARCHIVE_FILTER_NONE) { archive_read_free(a); close(bsdtar->fd); lafe_errc(1, 0, "Cannot append to compressed archive."); } /* Keep going until we hit end-of-archive */ format = archive_format(a); } end_offset = archive_read_header_position(a); archive_read_free(a); /* Re-open archive for writing */ a = archive_write_new(); /* * Set the format to be used for writing. To allow people to * extend empty files, we need to allow them to specify the format, * which opens the possibility that they will specify a format that * doesn't match the existing format. Hence, the following bit * of arcane ugliness. */ if (cset_get_format(bsdtar->cset) != NULL) { /* If the user requested a format, use that, but ... */ archive_write_set_format_by_name(a, cset_get_format(bsdtar->cset)); /* ... complain if it's not compatible. */ format &= ARCHIVE_FORMAT_BASE_MASK; if (format != (int)(archive_format(a) & ARCHIVE_FORMAT_BASE_MASK) && format != ARCHIVE_FORMAT_EMPTY) { lafe_errc(1, 0, "Format %s is incompatible with the archive %s.", cset_get_format(bsdtar->cset), bsdtar->filename); } } else { /* * Just preserve the current format, with a little care * for formats that libarchive can't write. */ if (format == ARCHIVE_FORMAT_EMPTY) format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED; archive_write_set_format(a, format); } if (lseek(bsdtar->fd, end_offset, SEEK_SET) < 0) lafe_errc(1, errno, "Could not seek to archive end"); set_writer_options(bsdtar, a); if (ARCHIVE_OK != archive_write_open_fd(a, bsdtar->fd)) lafe_errc(1, 0, "%s", archive_error_string(a)); write_archive(a, bsdtar); /* XXX check return val XXX */ close(bsdtar->fd); bsdtar->fd = -1; }
static int add_pattern_from_file(struct archive_match *a, struct match_list *mlist, int mbs, const void *pathname, int nullSeparator) { struct archive *ar; struct archive_entry *ae; struct archive_string as; const void *buff; size_t size; int64_t offset; int r; ar = archive_read_new(); if (ar == NULL) { archive_set_error(&(a->archive), ENOMEM, "No memory"); return (ARCHIVE_FATAL); } r = archive_read_support_format_raw(ar); r = archive_read_support_format_empty(ar); if (r != ARCHIVE_OK) { archive_copy_error(&(a->archive), ar); archive_read_free(ar); return (r); } if (mbs) r = archive_read_open_filename(ar, pathname, 512*20); else r = archive_read_open_filename_w(ar, pathname, 512*20); if (r != ARCHIVE_OK) { archive_copy_error(&(a->archive), ar); archive_read_free(ar); return (r); } r = archive_read_next_header(ar, &ae); if (r != ARCHIVE_OK) { archive_read_free(ar); if (r == ARCHIVE_EOF) { return (ARCHIVE_OK); } else { archive_copy_error(&(a->archive), ar); return (r); } } archive_string_init(&as); while ((r = archive_read_data_block(ar, &buff, &size, &offset)) == ARCHIVE_OK) { const char *b = (const char *)buff; while (size) { const char *s = (const char *)b; size_t length = 0; int found_separator = 0; while (length < size) { if (nullSeparator) { if (*b == '\0') { found_separator = 1; break; } } else { if (*b == 0x0d || *b == 0x0a) { found_separator = 1; break; } } b++; length++; } if (!found_separator) { archive_strncat(&as, s, length); /* Read next data block. */ break; } b++; size -= length + 1; archive_strncat(&as, s, length); /* If the line is not empty, add the pattern. */ if (archive_strlen(&as) > 0) { /* Add pattern. */ r = add_pattern_mbs(a, mlist, as.s); if (r != ARCHIVE_OK) { archive_read_free(ar); archive_string_free(&as); return (r); } archive_string_empty(&as); } } } /* If an error occurred, report it immediately. */ if (r < ARCHIVE_OK) { archive_copy_error(&(a->archive), ar); archive_read_free(ar); archive_string_free(&as); return (r); } /* If the line is not empty, add the pattern. */ if (r == ARCHIVE_EOF && archive_strlen(&as) > 0) { /* Add pattern. */ r = add_pattern_mbs(a, mlist, as.s); if (r != ARCHIVE_OK) { archive_read_free(ar); archive_string_free(&as); return (r); } } archive_read_free(ar); archive_string_free(&as); return (ARCHIVE_OK); }