xref: /freebsd/contrib/libarchive/tar/read.c (revision b9128a37)
1caf54c4fSMartin Matuska /*-
2caf54c4fSMartin Matuska  * Copyright (c) 2003-2007 Tim Kientzle
3caf54c4fSMartin Matuska  * All rights reserved.
4caf54c4fSMartin Matuska  *
5caf54c4fSMartin Matuska  * Redistribution and use in source and binary forms, with or without
6caf54c4fSMartin Matuska  * modification, are permitted provided that the following conditions
7caf54c4fSMartin Matuska  * are met:
8caf54c4fSMartin Matuska  * 1. Redistributions of source code must retain the above copyright
9caf54c4fSMartin Matuska  *    notice, this list of conditions and the following disclaimer.
10caf54c4fSMartin Matuska  * 2. Redistributions in binary form must reproduce the above copyright
11caf54c4fSMartin Matuska  *    notice, this list of conditions and the following disclaimer in the
12caf54c4fSMartin Matuska  *    documentation and/or other materials provided with the distribution.
13caf54c4fSMartin Matuska  *
14caf54c4fSMartin Matuska  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15caf54c4fSMartin Matuska  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16caf54c4fSMartin Matuska  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17caf54c4fSMartin Matuska  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18caf54c4fSMartin Matuska  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19caf54c4fSMartin Matuska  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20caf54c4fSMartin Matuska  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21caf54c4fSMartin Matuska  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22caf54c4fSMartin Matuska  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23caf54c4fSMartin Matuska  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24caf54c4fSMartin Matuska  */
25caf54c4fSMartin Matuska 
26caf54c4fSMartin Matuska #include "bsdtar_platform.h"
27caf54c4fSMartin Matuska 
28caf54c4fSMartin Matuska #ifdef HAVE_SYS_TYPES_H
29caf54c4fSMartin Matuska #include <sys/types.h>
30caf54c4fSMartin Matuska #endif
31caf54c4fSMartin Matuska #ifdef HAVE_SYS_PARAM_H
32caf54c4fSMartin Matuska #include <sys/param.h>
33caf54c4fSMartin Matuska #endif
34caf54c4fSMartin Matuska #ifdef HAVE_SYS_STAT_H
35caf54c4fSMartin Matuska #include <sys/stat.h>
36caf54c4fSMartin Matuska #endif
37caf54c4fSMartin Matuska 
38caf54c4fSMartin Matuska #ifdef HAVE_ERRNO_H
39caf54c4fSMartin Matuska #include <errno.h>
40caf54c4fSMartin Matuska #endif
41cdf63a70SMartin Matuska 
42cdf63a70SMartin Matuska #ifdef HAVE_FCNTL_H
43cdf63a70SMartin Matuska #include <fcntl.h>
44cdf63a70SMartin Matuska #endif
45cdf63a70SMartin Matuska 
46caf54c4fSMartin Matuska #ifdef HAVE_GRP_H
47caf54c4fSMartin Matuska #include <grp.h>
48caf54c4fSMartin Matuska #endif
49cdf63a70SMartin Matuska 
50cdf63a70SMartin Matuska #ifdef HAVE_IO_H
51cdf63a70SMartin Matuska #include <io.h>
52cdf63a70SMartin Matuska #endif
53cdf63a70SMartin Matuska 
54caf54c4fSMartin Matuska #ifdef HAVE_LIMITS_H
55caf54c4fSMartin Matuska #include <limits.h>
56caf54c4fSMartin Matuska #endif
57caf54c4fSMartin Matuska #ifdef HAVE_PWD_H
58caf54c4fSMartin Matuska #include <pwd.h>
59caf54c4fSMartin Matuska #endif
60caf54c4fSMartin Matuska #ifdef HAVE_STDINT_H
61caf54c4fSMartin Matuska #include <stdint.h>
62caf54c4fSMartin Matuska #endif
63caf54c4fSMartin Matuska #include <stdio.h>
64caf54c4fSMartin Matuska #ifdef HAVE_STDLIB_H
65caf54c4fSMartin Matuska #include <stdlib.h>
66caf54c4fSMartin Matuska #endif
67caf54c4fSMartin Matuska #ifdef HAVE_STRING_H
68caf54c4fSMartin Matuska #include <string.h>
69caf54c4fSMartin Matuska #endif
70caf54c4fSMartin Matuska #ifdef HAVE_TIME_H
71caf54c4fSMartin Matuska #include <time.h>
72caf54c4fSMartin Matuska #endif
73caf54c4fSMartin Matuska #ifdef HAVE_UNISTD_H
74caf54c4fSMartin Matuska #include <unistd.h>
75caf54c4fSMartin Matuska #endif
76caf54c4fSMartin Matuska 
77caf54c4fSMartin Matuska #include "bsdtar.h"
78caf54c4fSMartin Matuska #include "err.h"
79caf54c4fSMartin Matuska 
80caf54c4fSMartin Matuska struct progress_data {
81caf54c4fSMartin Matuska 	struct bsdtar *bsdtar;
82caf54c4fSMartin Matuska 	struct archive *archive;
83caf54c4fSMartin Matuska 	struct archive_entry *entry;
84caf54c4fSMartin Matuska };
85caf54c4fSMartin Matuska 
866c95142eSMartin Matuska static void	read_archive(struct bsdtar *bsdtar, char mode, struct archive *);
87fd082e96SMartin Matuska static int unmatched_inclusions_warn(struct archive *matching, const char *);
88fd082e96SMartin Matuska 
89caf54c4fSMartin Matuska 
90caf54c4fSMartin Matuska void
tar_mode_t(struct bsdtar * bsdtar)91caf54c4fSMartin Matuska tar_mode_t(struct bsdtar *bsdtar)
92caf54c4fSMartin Matuska {
936c95142eSMartin Matuska 	read_archive(bsdtar, 't', NULL);
94fd082e96SMartin Matuska 	if (unmatched_inclusions_warn(bsdtar->matching,
95fd082e96SMartin Matuska 	    "Not found in archive") != 0)
96caf54c4fSMartin Matuska 		bsdtar->return_value = 1;
97caf54c4fSMartin Matuska }
98caf54c4fSMartin Matuska 
99caf54c4fSMartin Matuska void
tar_mode_x(struct bsdtar * bsdtar)100caf54c4fSMartin Matuska tar_mode_x(struct bsdtar *bsdtar)
101caf54c4fSMartin Matuska {
1026c95142eSMartin Matuska 	struct archive *writer;
1036c95142eSMartin Matuska 
1046c95142eSMartin Matuska 	writer = archive_write_disk_new();
1056c95142eSMartin Matuska 	if (writer == NULL)
1066c95142eSMartin Matuska 		lafe_errc(1, ENOMEM, "Cannot allocate disk writer object");
10764287048SMartin Matuska 	if ((bsdtar->flags & OPTFLAG_NUMERIC_OWNER) == 0)
1086c95142eSMartin Matuska 		archive_write_disk_set_standard_lookup(writer);
1096c95142eSMartin Matuska 	archive_write_disk_set_options(writer, bsdtar->extract_flags);
1106c95142eSMartin Matuska 
1116c95142eSMartin Matuska 	read_archive(bsdtar, 'x', writer);
112caf54c4fSMartin Matuska 
113fd082e96SMartin Matuska 	if (unmatched_inclusions_warn(bsdtar->matching,
114fd082e96SMartin Matuska 	    "Not found in archive") != 0)
115caf54c4fSMartin Matuska 		bsdtar->return_value = 1;
1166c95142eSMartin Matuska 	archive_write_free(writer);
117caf54c4fSMartin Matuska }
118caf54c4fSMartin Matuska 
119caf54c4fSMartin Matuska static void
progress_func(void * cookie)120caf54c4fSMartin Matuska progress_func(void *cookie)
121caf54c4fSMartin Matuska {
122cdf63a70SMartin Matuska 	struct progress_data *progress_data = (struct progress_data *)cookie;
123caf54c4fSMartin Matuska 	struct bsdtar *bsdtar = progress_data->bsdtar;
124caf54c4fSMartin Matuska 	struct archive *a = progress_data->archive;
125caf54c4fSMartin Matuska 	struct archive_entry *entry = progress_data->entry;
126caf54c4fSMartin Matuska 	uint64_t comp, uncomp;
127c5d360f8SMartin Matuska 	int compression;
128caf54c4fSMartin Matuska 
129caf54c4fSMartin Matuska 	if (!need_report())
130caf54c4fSMartin Matuska 		return;
131caf54c4fSMartin Matuska 
132caf54c4fSMartin Matuska 	if (bsdtar->verbose)
133caf54c4fSMartin Matuska 		fprintf(stderr, "\n");
134caf54c4fSMartin Matuska 	if (a != NULL) {
135acc60b03SMartin Matuska 		comp = archive_filter_bytes(a, -1);
136acc60b03SMartin Matuska 		uncomp = archive_filter_bytes(a, 0);
137c5d360f8SMartin Matuska 		if (comp > uncomp)
138c5d360f8SMartin Matuska 			compression = 0;
139c5d360f8SMartin Matuska 		else
140c5d360f8SMartin Matuska 			compression = (int)((uncomp - comp) * 100 / uncomp);
141caf54c4fSMartin Matuska 		fprintf(stderr,
142caf54c4fSMartin Matuska 		    "In: %s bytes, compression %d%%;",
143c5d360f8SMartin Matuska 		    tar_i64toa(comp), compression);
144caf54c4fSMartin Matuska 		fprintf(stderr, "  Out: %d files, %s bytes\n",
145caf54c4fSMartin Matuska 		    archive_file_count(a), tar_i64toa(uncomp));
146caf54c4fSMartin Matuska 	}
147caf54c4fSMartin Matuska 	if (entry != NULL) {
148caf54c4fSMartin Matuska 		safe_fprintf(stderr, "Current: %s",
149caf54c4fSMartin Matuska 		    archive_entry_pathname(entry));
150caf54c4fSMartin Matuska 		fprintf(stderr, " (%s bytes)\n",
151caf54c4fSMartin Matuska 		    tar_i64toa(archive_entry_size(entry)));
152caf54c4fSMartin Matuska 	}
153caf54c4fSMartin Matuska }
154caf54c4fSMartin Matuska 
155caf54c4fSMartin Matuska /*
156caf54c4fSMartin Matuska  * Handle 'x' and 't' modes.
157caf54c4fSMartin Matuska  */
158caf54c4fSMartin Matuska static void
read_archive(struct bsdtar * bsdtar,char mode,struct archive * writer)1596c95142eSMartin Matuska read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
160caf54c4fSMartin Matuska {
161caf54c4fSMartin Matuska 	struct progress_data	progress_data;
162caf54c4fSMartin Matuska 	FILE			 *out;
163caf54c4fSMartin Matuska 	struct archive		 *a;
164caf54c4fSMartin Matuska 	struct archive_entry	 *entry;
165acc60b03SMartin Matuska 	const char		 *reader_options;
166caf54c4fSMartin Matuska 	int			  r;
167caf54c4fSMartin Matuska 
168caf54c4fSMartin Matuska 	while (*bsdtar->argv) {
169fd082e96SMartin Matuska 		if (archive_match_include_pattern(bsdtar->matching,
170fd082e96SMartin Matuska 		    *bsdtar->argv) != ARCHIVE_OK)
171fd082e96SMartin Matuska 			lafe_errc(1, 0, "Error inclusion pattern: %s",
172fd082e96SMartin Matuska 			    archive_error_string(bsdtar->matching));
173caf54c4fSMartin Matuska 		bsdtar->argv++;
174caf54c4fSMartin Matuska 	}
175caf54c4fSMartin Matuska 
176caf54c4fSMartin Matuska 	if (bsdtar->names_from_file != NULL)
177fd082e96SMartin Matuska 		if (archive_match_include_pattern_from_file(
178fd082e96SMartin Matuska 		    bsdtar->matching, bsdtar->names_from_file,
17964287048SMartin Matuska 		    (bsdtar->flags & OPTFLAG_NULL)) != ARCHIVE_OK)
180fd082e96SMartin Matuska 			lafe_errc(1, 0, "Error inclusion pattern: %s",
181fd082e96SMartin Matuska 			    archive_error_string(bsdtar->matching));
182caf54c4fSMartin Matuska 
183caf54c4fSMartin Matuska 	a = archive_read_new();
184acc60b03SMartin Matuska 	if (cset_read_support_filter_program(bsdtar->cset, a) == 0)
1856c95142eSMartin Matuska 		archive_read_support_filter_all(a);
186caf54c4fSMartin Matuska 	archive_read_support_format_all(a);
187acc60b03SMartin Matuska 
188acc60b03SMartin Matuska 	reader_options = getenv(ENV_READER_OPTIONS);
189acc60b03SMartin Matuska 	if (reader_options != NULL) {
1907105995cSMartin Matuska 		size_t module_len = sizeof(IGNORE_WRONG_MODULE_NAME) - 1;
1917105995cSMartin Matuska 		size_t opt_len = strlen(reader_options) + 1;
192acc60b03SMartin Matuska 		char *p;
193acc60b03SMartin Matuska 		/* Set default read options. */
1947105995cSMartin Matuska 		if ((p = malloc(module_len + opt_len)) == NULL)
195acc60b03SMartin Matuska 			lafe_errc(1, errno, "Out of memory");
196acc60b03SMartin Matuska 		/* Prepend magic code to ignore options for
197acc60b03SMartin Matuska 		 * a format or  modules which are not added to
198acc60b03SMartin Matuska 		 *  the archive read object. */
1997105995cSMartin Matuska 		memcpy(p, IGNORE_WRONG_MODULE_NAME, module_len);
2007105995cSMartin Matuska 		memcpy(p + module_len, reader_options, opt_len);
201acc60b03SMartin Matuska 		r = archive_read_set_options(a, p);
202acc60b03SMartin Matuska 		free(p);
203acc60b03SMartin Matuska 		if (r == ARCHIVE_FATAL)
204acc60b03SMartin Matuska 			lafe_errc(1, 0, "%s", archive_error_string(a));
205acc60b03SMartin Matuska 		else
206acc60b03SMartin Matuska 			archive_clear_error(a);
207acc60b03SMartin Matuska 	}
208caf54c4fSMartin Matuska 	if (ARCHIVE_OK != archive_read_set_options(a, bsdtar->option_options))
209caf54c4fSMartin Matuska 		lafe_errc(1, 0, "%s", archive_error_string(a));
21064287048SMartin Matuska 	if (bsdtar->flags & OPTFLAG_IGNORE_ZEROS)
211cdf63a70SMartin Matuska 		if (archive_read_set_options(a,
212cdf63a70SMartin Matuska 		    "read_concatenated_archives") != ARCHIVE_OK)
213cdf63a70SMartin Matuska 			lafe_errc(1, 0, "%s", archive_error_string(a));
214cdf63a70SMartin Matuska 	if (bsdtar->passphrase != NULL)
215cdf63a70SMartin Matuska 		r = archive_read_add_passphrase(a, bsdtar->passphrase);
216cdf63a70SMartin Matuska 	else
217cdf63a70SMartin Matuska 		r = archive_read_set_passphrase_callback(a, bsdtar,
218cdf63a70SMartin Matuska 			&passphrase_callback);
219cdf63a70SMartin Matuska 	if (r != ARCHIVE_OK)
220cdf63a70SMartin Matuska 		lafe_errc(1, 0, "%s", archive_error_string(a));
221acc60b03SMartin Matuska 	if (archive_read_open_filename(a, bsdtar->filename,
222acc60b03SMartin Matuska 					bsdtar->bytes_per_block))
223caf54c4fSMartin Matuska 		lafe_errc(1, 0, "Error opening archive: %s",
224caf54c4fSMartin Matuska 		    archive_error_string(a));
225caf54c4fSMartin Matuska 
226caf54c4fSMartin Matuska 	do_chdir(bsdtar);
227caf54c4fSMartin Matuska 
228caf54c4fSMartin Matuska 	if (mode == 'x') {
229caf54c4fSMartin Matuska 		/* Set an extract callback so that we can handle SIGINFO. */
230caf54c4fSMartin Matuska 		progress_data.bsdtar = bsdtar;
231caf54c4fSMartin Matuska 		progress_data.archive = a;
232caf54c4fSMartin Matuska 		archive_read_extract_set_progress_callback(a, progress_func,
233caf54c4fSMartin Matuska 		    &progress_data);
234caf54c4fSMartin Matuska 	}
235caf54c4fSMartin Matuska 
23664287048SMartin Matuska 	if (mode == 'x' && (bsdtar->flags & OPTFLAG_CHROOT)) {
237caf54c4fSMartin Matuska #if HAVE_CHROOT
238caf54c4fSMartin Matuska 		if (chroot(".") != 0)
239caf54c4fSMartin Matuska 			lafe_errc(1, errno, "Can't chroot to \".\"");
240caf54c4fSMartin Matuska #else
241caf54c4fSMartin Matuska 		lafe_errc(1, 0,
242caf54c4fSMartin Matuska 		    "chroot isn't supported on this platform");
243caf54c4fSMartin Matuska #endif
244caf54c4fSMartin Matuska 	}
245caf54c4fSMartin Matuska 
246cdf63a70SMartin Matuska #if defined(_WIN32) && !defined(__CYGWIN__)
24764287048SMartin Matuska 	if (mode == 'x' && (bsdtar->flags & OPTFLAG_STDOUT)) {
248cdf63a70SMartin Matuska 		_setmode(1, _O_BINARY);
249cdf63a70SMartin Matuska 	}
250cdf63a70SMartin Matuska #endif
251cdf63a70SMartin Matuska 
252caf54c4fSMartin Matuska 	for (;;) {
253caf54c4fSMartin Matuska 		/* Support --fast-read option */
254cdf63a70SMartin Matuska 		const char *p;
25564287048SMartin Matuska 		if ((bsdtar->flags & OPTFLAG_FAST_READ) &&
256fd082e96SMartin Matuska 		    archive_match_path_unmatched_inclusions(bsdtar->matching) == 0)
257caf54c4fSMartin Matuska 			break;
258caf54c4fSMartin Matuska 
259caf54c4fSMartin Matuska 		r = archive_read_next_header(a, &entry);
260caf54c4fSMartin Matuska 		progress_data.entry = entry;
261caf54c4fSMartin Matuska 		if (r == ARCHIVE_EOF)
262caf54c4fSMartin Matuska 			break;
263caf54c4fSMartin Matuska 		if (r < ARCHIVE_OK)
264caf54c4fSMartin Matuska 			lafe_warnc(0, "%s", archive_error_string(a));
265caf54c4fSMartin Matuska 		if (r <= ARCHIVE_WARN)
266caf54c4fSMartin Matuska 			bsdtar->return_value = 1;
267caf54c4fSMartin Matuska 		if (r == ARCHIVE_RETRY) {
268caf54c4fSMartin Matuska 			/* Retryable error: try again */
269caf54c4fSMartin Matuska 			lafe_warnc(0, "Retrying...");
270caf54c4fSMartin Matuska 			continue;
271caf54c4fSMartin Matuska 		}
272caf54c4fSMartin Matuska 		if (r == ARCHIVE_FATAL)
273caf54c4fSMartin Matuska 			break;
274cdf63a70SMartin Matuska 		p = archive_entry_pathname(entry);
275cdf63a70SMartin Matuska 		if (p == NULL || p[0] == '\0') {
276cdf63a70SMartin Matuska 			lafe_warnc(0, "Archive entry has empty or unreadable filename ... skipping.");
277cdf63a70SMartin Matuska 			bsdtar->return_value = 1;
278cdf63a70SMartin Matuska 			continue;
279cdf63a70SMartin Matuska 		}
280caf54c4fSMartin Matuska 
281caf54c4fSMartin Matuska 		if (bsdtar->uid >= 0) {
282caf54c4fSMartin Matuska 			archive_entry_set_uid(entry, bsdtar->uid);
283caf54c4fSMartin Matuska 			archive_entry_set_uname(entry, NULL);
284caf54c4fSMartin Matuska 		}
285caf54c4fSMartin Matuska 		if (bsdtar->gid >= 0) {
286caf54c4fSMartin Matuska 			archive_entry_set_gid(entry, bsdtar->gid);
287caf54c4fSMartin Matuska 			archive_entry_set_gname(entry, NULL);
288caf54c4fSMartin Matuska 		}
289caf54c4fSMartin Matuska 		if (bsdtar->uname)
290caf54c4fSMartin Matuska 			archive_entry_set_uname(entry, bsdtar->uname);
291c5d360f8SMartin Matuska 		if (bsdtar->gname)
292caf54c4fSMartin Matuska 			archive_entry_set_gname(entry, bsdtar->gname);
293caf54c4fSMartin Matuska 
294caf54c4fSMartin Matuska 		/*
295caf54c4fSMartin Matuska 		 * Note that pattern exclusions are checked before
296caf54c4fSMartin Matuska 		 * pathname rewrites are handled.  This gives more
297caf54c4fSMartin Matuska 		 * control over exclusions, since rewrites always lose
298caf54c4fSMartin Matuska 		 * information.  (For example, consider a rewrite
299caf54c4fSMartin Matuska 		 * s/foo[0-9]/foo/.  If we check exclusions after the
300caf54c4fSMartin Matuska 		 * rewrite, there would be no way to exclude foo1/bar
301caf54c4fSMartin Matuska 		 * while allowing foo2/bar.)
302caf54c4fSMartin Matuska 		 */
303fd082e96SMartin Matuska 		if (archive_match_excluded(bsdtar->matching, entry))
304caf54c4fSMartin Matuska 			continue; /* Excluded by a pattern test. */
305caf54c4fSMartin Matuska 
306caf54c4fSMartin Matuska 		if (mode == 't') {
307caf54c4fSMartin Matuska 			/* Perversely, gtar uses -O to mean "send to stderr"
308caf54c4fSMartin Matuska 			 * when used with -t. */
30964287048SMartin Matuska 			out = (bsdtar->flags & OPTFLAG_STDOUT) ?
31064287048SMartin Matuska 			    stderr : stdout;
311caf54c4fSMartin Matuska 
312caf54c4fSMartin Matuska 			/*
313caf54c4fSMartin Matuska 			 * TODO: Provide some reasonable way to
314caf54c4fSMartin Matuska 			 * preview rewrites.  gtar always displays
315caf54c4fSMartin Matuska 			 * the unedited path in -t output, which means
316caf54c4fSMartin Matuska 			 * you cannot easily preview rewrites.
317caf54c4fSMartin Matuska 			 */
318caf54c4fSMartin Matuska 			if (bsdtar->verbose < 2)
319caf54c4fSMartin Matuska 				safe_fprintf(out, "%s",
320caf54c4fSMartin Matuska 				    archive_entry_pathname(entry));
321caf54c4fSMartin Matuska 			else
322caf54c4fSMartin Matuska 				list_item_verbose(bsdtar, out, entry);
323caf54c4fSMartin Matuska 			fflush(out);
324caf54c4fSMartin Matuska 			r = archive_read_data_skip(a);
325caf54c4fSMartin Matuska 			if (r == ARCHIVE_WARN) {
326caf54c4fSMartin Matuska 				fprintf(out, "\n");
327caf54c4fSMartin Matuska 				lafe_warnc(0, "%s",
328caf54c4fSMartin Matuska 				    archive_error_string(a));
329caf54c4fSMartin Matuska 			}
330caf54c4fSMartin Matuska 			if (r == ARCHIVE_RETRY) {
331caf54c4fSMartin Matuska 				fprintf(out, "\n");
332caf54c4fSMartin Matuska 				lafe_warnc(0, "%s",
333caf54c4fSMartin Matuska 				    archive_error_string(a));
334caf54c4fSMartin Matuska 			}
335caf54c4fSMartin Matuska 			if (r == ARCHIVE_FATAL) {
336caf54c4fSMartin Matuska 				fprintf(out, "\n");
337caf54c4fSMartin Matuska 				lafe_warnc(0, "%s",
338caf54c4fSMartin Matuska 				    archive_error_string(a));
339caf54c4fSMartin Matuska 				bsdtar->return_value = 1;
340caf54c4fSMartin Matuska 				break;
341caf54c4fSMartin Matuska 			}
342caf54c4fSMartin Matuska 			fprintf(out, "\n");
343caf54c4fSMartin Matuska 		} else {
344caf54c4fSMartin Matuska 			/* Note: some rewrite failures prevent extraction. */
345caf54c4fSMartin Matuska 			if (edit_pathname(bsdtar, entry))
346caf54c4fSMartin Matuska 				continue; /* Excluded by a rewrite failure. */
347caf54c4fSMartin Matuska 
34864287048SMartin Matuska 			if ((bsdtar->flags & OPTFLAG_INTERACTIVE) &&
349caf54c4fSMartin Matuska 			    !yes("extract '%s'", archive_entry_pathname(entry)))
350caf54c4fSMartin Matuska 				continue;
351caf54c4fSMartin Matuska 
352cdf63a70SMartin Matuska 			if (bsdtar->verbose > 1) {
353cdf63a70SMartin Matuska 				/* GNU tar uses -tv format with -xvv */
354cdf63a70SMartin Matuska 				safe_fprintf(stderr, "x ");
355cdf63a70SMartin Matuska 				list_item_verbose(bsdtar, stderr, entry);
356cdf63a70SMartin Matuska 				fflush(stderr);
357cdf63a70SMartin Matuska 			} else if (bsdtar->verbose > 0) {
358cdf63a70SMartin Matuska 				/* Format follows SUSv2, including the
359cdf63a70SMartin Matuska 				 * deferred '\n'. */
360caf54c4fSMartin Matuska 				safe_fprintf(stderr, "x %s",
361caf54c4fSMartin Matuska 				    archive_entry_pathname(entry));
362caf54c4fSMartin Matuska 				fflush(stderr);
363caf54c4fSMartin Matuska 			}
364caf54c4fSMartin Matuska 
3656c95142eSMartin Matuska 			/* TODO siginfo_printinfo(bsdtar, 0); */
366caf54c4fSMartin Matuska 
36764287048SMartin Matuska 			if (bsdtar->flags & OPTFLAG_STDOUT)
368caf54c4fSMartin Matuska 				r = archive_read_data_into_fd(a, 1);
369caf54c4fSMartin Matuska 			else
3706c95142eSMartin Matuska 				r = archive_read_extract2(a, entry, writer);
371caf54c4fSMartin Matuska 			if (r != ARCHIVE_OK) {
372caf54c4fSMartin Matuska 				if (!bsdtar->verbose)
373833a452eSMartin Matuska 					safe_fprintf(stderr, "%s", archive_entry_pathname(entry));
374d68c6869SEd Maste 				safe_fprintf(stderr, ": %s: %s",
375d68c6869SEd Maste 				    archive_error_string(a),
376d68c6869SEd Maste 				    strerror(archive_errno(a)));
377caf54c4fSMartin Matuska 				if (!bsdtar->verbose)
378caf54c4fSMartin Matuska 					fprintf(stderr, "\n");
379caf54c4fSMartin Matuska 				bsdtar->return_value = 1;
380caf54c4fSMartin Matuska 			}
381caf54c4fSMartin Matuska 			if (bsdtar->verbose)
382caf54c4fSMartin Matuska 				fprintf(stderr, "\n");
383caf54c4fSMartin Matuska 			if (r == ARCHIVE_FATAL)
384caf54c4fSMartin Matuska 				break;
385caf54c4fSMartin Matuska 		}
386caf54c4fSMartin Matuska 	}
387caf54c4fSMartin Matuska 
388caf54c4fSMartin Matuska 
389caf54c4fSMartin Matuska 	r = archive_read_close(a);
390caf54c4fSMartin Matuska 	if (r != ARCHIVE_OK)
391caf54c4fSMartin Matuska 		lafe_warnc(0, "%s", archive_error_string(a));
392caf54c4fSMartin Matuska 	if (r <= ARCHIVE_WARN)
393caf54c4fSMartin Matuska 		bsdtar->return_value = 1;
394caf54c4fSMartin Matuska 
395caf54c4fSMartin Matuska 	if (bsdtar->verbose > 2)
396caf54c4fSMartin Matuska 		fprintf(stdout, "Archive Format: %s,  Compression: %s\n",
397acc60b03SMartin Matuska 		    archive_format_name(a), archive_filter_name(a, 0));
398caf54c4fSMartin Matuska 
3996c95142eSMartin Matuska 	archive_read_free(a);
400caf54c4fSMartin Matuska }
401caf54c4fSMartin Matuska 
402caf54c4fSMartin Matuska 
403fd082e96SMartin Matuska static int
unmatched_inclusions_warn(struct archive * matching,const char * msg)404fd082e96SMartin Matuska unmatched_inclusions_warn(struct archive *matching, const char *msg)
405fd082e96SMartin Matuska {
406fd082e96SMartin Matuska 	const char *p;
407fd082e96SMartin Matuska 	int r;
408fd082e96SMartin Matuska 
409fd082e96SMartin Matuska 	if (matching == NULL)
410fd082e96SMartin Matuska 		return (0);
411fd082e96SMartin Matuska 
412fd082e96SMartin Matuska 	while ((r = archive_match_path_unmatched_inclusions_next(
413fd082e96SMartin Matuska 	    matching, &p)) == ARCHIVE_OK)
414fd082e96SMartin Matuska 		lafe_warnc(0, "%s: %s", p, msg);
415fd082e96SMartin Matuska 	if (r == ARCHIVE_FATAL)
416fd082e96SMartin Matuska 		lafe_errc(1, errno, "Out of memory");
417fd082e96SMartin Matuska 
418fd082e96SMartin Matuska 	return (archive_match_path_unmatched_inclusions(matching));
419fd082e96SMartin Matuska }
420