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 #if defined __MINGW32__
44 static const char *errnostr(int e)
55 estr = "ARCHIVE_WARN";
58 estr = "ARCHIVE_RETRY";
61 estr = "ARCHIVE_FAILED";
64 estr = "ARCHIVE_FATAL";
73 static void usage(const char *prog)
75 fprintf(stderr, "Usage: %s [-f filename] [-h] [-q] [-s]\n", prog);
78 static void printhelp()
80 fprintf(stdout, "archivetest: verify reading archives with "
83 " -f filename Filename to verify\n"
84 " -h Show this help\n"
86 " -s Verify only headers (skip data)\n\n"
87 "If no filename is specified, data is read from standard input.\n"
88 "\n%s\n", archive_version_details());
91 static int v_print(int verbose, const char *format, ...)
98 va_start(args, format);
99 r = vfprintf(stdout, format, args);
105 int main(int argc, char *argv[])
108 struct archive_entry *entry;
121 while ((c = getopt (argc, argv, "f:hqs")) != -1) {
137 fprintf(stderr, "Option -%c requires "
138 "an argument.\n", optopt);
139 else if (isprint(optopt))
140 fprintf(stderr, "Unknown option '-%c'"
143 fprintf(stderr, "Unknown option "
144 "character '\\x%x'.\n", optopt);
153 a = archive_read_new();
155 archive_read_support_filter_all(a);
156 archive_read_support_format_all(a);
158 v_print(v, "Data source: ");
160 if (filename == NULL) {
161 v_print(v, "standard input\n");
162 r = archive_read_open_fd(a, STDIN_FILENO, 4096);
164 v_print(v, "filename: %s\n", filename);
165 r = archive_read_open_filename(a, filename, 4096);
168 if (r != ARCHIVE_OK) {
169 archive_read_free(a);
170 fprintf(stderr, "Invalid or unsupported data source\n");
178 r = archive_read_next_header(a, &entry);
179 if (r == ARCHIVE_FATAL) {
180 v_print(v, "Entry %d: fatal error reading "
184 if (!format_printed) {
185 v_print(v, "Filter: %s\nFormat: %s\n",
186 archive_filter_name(a, 0), archive_format_name(a));
189 if (r == ARCHIVE_RETRY)
191 if (r == ARCHIVE_EOF)
193 p = archive_entry_pathname(entry);
194 v_print(v, "Entry %d: %s, pathname", c, errnostr(r));
195 if (p == NULL || p[0] == '\0')
196 v_print(v, " unreadable");
198 v_print(v, ": %s", p);
199 v_print(v, ", data: ");
201 v_print(v, "skipping");
203 while ((r = archive_read_data(a, buffer, 4096) > 0))
205 if (r == ARCHIVE_FATAL) {
206 v_print(v, "ERROR\nError string: %s\n",
207 archive_error_string(a));
216 v_print(v, "Last return code: %s (%d)\n", errnostr(r), r);
217 if (r == ARCHIVE_EOF || r == ARCHIVE_OK) {
218 archive_read_free(a);
221 v_print(v, "Error string: %s\n", archive_error_string(a));
222 archive_read_free(a);