2 * Copyright (c) 2019 Martin Matuska
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * Archivetest verifies reading archives with libarchive
29 * It may be used to reproduce failures in testcases discovered by OSS-Fuzz
30 * https://github.com/google/oss-fuzz/blob/master/projects/libarchive
38 #include <archive_entry.h>
40 const char *errnostr(int errno)
51 estr = "ARCHIVE_WARN";
54 estr = "ARCHIVE_RETRY";
57 estr = "ARCHIVE_FAILED";
60 estr = "ARCHIVE_FATAL";
69 void usage(const char *prog)
71 fprintf(stderr, "Usage: %s [-f filename] [-h] [-q] [-s]\n", prog);
76 fprintf(stdout, "archivetest: verify reading archives with "
79 " -f filename Filename to verify\n"
80 " -h Show this help\n"
82 " -s Verify only headers (skip data)\n\n"
83 "If no filename is specified, data is read from standard input.\n"
84 "\n%s\n", archive_version_details());
87 int v_print(int verbose, const char *format, ...)
94 va_start(args, format);
95 r = vfprintf(stdout, format, args);
101 int main(int argc, char *argv[])
104 struct archive_entry *entry;
117 while ((c = getopt (argc, argv, "f:hqs")) != -1) {
133 fprintf(stderr, "Option -%c requires "
134 "an argument.\n", optopt);
135 else if (isprint(optopt))
136 fprintf(stderr, "Unknown option '-%c'"
139 fprintf(stderr, "Unknown option "
140 "character '\\x%x'.\n", optopt);
147 a = archive_read_new();
149 archive_read_support_filter_all(a);
150 archive_read_support_format_all(a);
152 v_print(v, "Data source: ");
154 if (filename == NULL) {
155 v_print(v, "standard input\n");
156 r = archive_read_open_fd(a, STDIN_FILENO, 4096);
158 v_print(v, "filename: %s\n", filename);
159 r = archive_read_open_filename(a, filename, 4096);
162 if (r != ARCHIVE_OK) {
163 archive_read_free(a);
164 fprintf(stderr, "Invalid or unsupported data source\n");
172 r = archive_read_next_header(a, &entry);
173 if (r == ARCHIVE_FATAL) {
174 v_print(v, "Entry %d: fatal error reading "
178 if (!format_printed) {
179 v_print(v, "Filter: %s\nFormat: %s\n",
180 archive_filter_name(a, 0), archive_format_name(a));
183 if (r == ARCHIVE_RETRY)
185 if (r == ARCHIVE_EOF)
187 p = archive_entry_pathname(entry);
188 v_print(v, "Entry %d: %s, pathname", c, errnostr(r));
189 if (p == NULL || p[0] == '\0')
190 v_print(v, " unreadable");
192 v_print(v, ": %s", p);
193 v_print(v, ", data: ");
195 v_print(v, "skipping");
197 while ((r = archive_read_data(a, buffer, 4096) > 0))
199 if (r == ARCHIVE_FATAL) {
200 v_print(v, "ERROR\nError string: %s\n",
201 archive_error_string(a));
210 v_print(v, "Last return code: %s (%d)\n", errnostr(r), r);
211 if (r == ARCHIVE_EOF || r == ARCHIVE_OK) {
212 archive_read_free(a);
215 v_print(v, "Error string: %s\n", archive_error_string(a));
216 archive_read_free(a);