1/*-
2 * Copyright (c) 2003-2007 Tim Kientzle
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
13 *
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.
24 */
25
26#include "bsdtar_platform.h"
27
28#ifdef HAVE_SYS_TYPES_H
29#include <sys/types.h>
30#endif
31#ifdef HAVE_SYS_PARAM_H
32#include <sys/param.h>
33#endif
34#ifdef HAVE_SYS_STAT_H
35#include <sys/stat.h>
36#endif
37
38#ifdef HAVE_ERRNO_H
39#include <errno.h>
40#endif
41
42#ifdef HAVE_FCNTL_H
43#include <fcntl.h>
44#endif
45
46#ifdef HAVE_GRP_H
47#include <grp.h>
48#endif
49
50#ifdef HAVE_IO_H
51#include <io.h>
52#endif
53
54#ifdef HAVE_LIMITS_H
55#include <limits.h>
56#endif
57#ifdef HAVE_PWD_H
58#include <pwd.h>
59#endif
60#ifdef HAVE_STDINT_H
61#include <stdint.h>
62#endif
63#include <stdio.h>
64#ifdef HAVE_STDLIB_H
65#include <stdlib.h>
66#endif
67#ifdef HAVE_STRING_H
68#include <string.h>
69#endif
70#ifdef HAVE_TIME_H
71#include <time.h>
72#endif
73#ifdef HAVE_UNISTD_H
74#include <unistd.h>
75#endif
76
77#include "bsdtar.h"
78#include "err.h"
79
80struct progress_data {
81	struct bsdtar *bsdtar;
82	struct archive *archive;
83	struct archive_entry *entry;
84};
85
86static void	read_archive(struct bsdtar *bsdtar, char mode, struct archive *);
87static int unmatched_inclusions_warn(struct archive *matching, const char *);
88
89
90void
91tar_mode_t(struct bsdtar *bsdtar)
92{
93	read_archive(bsdtar, 't', NULL);
94	if (unmatched_inclusions_warn(bsdtar->matching,
95	    "Not found in archive") != 0)
96		bsdtar->return_value = 1;
97}
98
99void
100tar_mode_x(struct bsdtar *bsdtar)
101{
102	struct archive *writer;
103
104	writer = archive_write_disk_new();
105	if (writer == NULL)
106		lafe_errc(1, ENOMEM, "Cannot allocate disk writer object");
107	if ((bsdtar->flags & OPTFLAG_NUMERIC_OWNER) == 0)
108		archive_write_disk_set_standard_lookup(writer);
109	archive_write_disk_set_options(writer, bsdtar->extract_flags);
110
111	read_archive(bsdtar, 'x', writer);
112
113	if (unmatched_inclusions_warn(bsdtar->matching,
114	    "Not found in archive") != 0)
115		bsdtar->return_value = 1;
116	archive_write_free(writer);
117}
118
119static void
120progress_func(void *cookie)
121{
122	struct progress_data *progress_data = (struct progress_data *)cookie;
123	struct bsdtar *bsdtar = progress_data->bsdtar;
124	struct archive *a = progress_data->archive;
125	struct archive_entry *entry = progress_data->entry;
126	uint64_t comp, uncomp;
127	int compression;
128
129	if (!need_report())
130		return;
131
132	if (bsdtar->verbose)
133		fprintf(stderr, "\n");
134	if (a != NULL) {
135		comp = archive_filter_bytes(a, -1);
136		uncomp = archive_filter_bytes(a, 0);
137		if (comp > uncomp)
138			compression = 0;
139		else
140			compression = (int)((uncomp - comp) * 100 / uncomp);
141		fprintf(stderr,
142		    "In: %s bytes, compression %d%%;",
143		    tar_i64toa(comp), compression);
144		fprintf(stderr, "  Out: %d files, %s bytes\n",
145		    archive_file_count(a), tar_i64toa(uncomp));
146	}
147	if (entry != NULL) {
148		safe_fprintf(stderr, "Current: %s",
149		    archive_entry_pathname(entry));
150		fprintf(stderr, " (%s bytes)\n",
151		    tar_i64toa(archive_entry_size(entry)));
152	}
153}
154
155/*
156 * Handle 'x' and 't' modes.
157 */
158static void
159read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
160{
161	struct progress_data	progress_data;
162	FILE			 *out;
163	struct archive		 *a;
164	struct archive_entry	 *entry;
165	const char		 *reader_options;
166	int			  r;
167
168	while (*bsdtar->argv) {
169		if (archive_match_include_pattern(bsdtar->matching,
170		    *bsdtar->argv) != ARCHIVE_OK)
171			lafe_errc(1, 0, "Error inclusion pattern: %s",
172			    archive_error_string(bsdtar->matching));
173		bsdtar->argv++;
174	}
175
176	if (bsdtar->names_from_file != NULL)
177		if (archive_match_include_pattern_from_file(
178		    bsdtar->matching, bsdtar->names_from_file,
179		    (bsdtar->flags & OPTFLAG_NULL)) != ARCHIVE_OK)
180			lafe_errc(1, 0, "Error inclusion pattern: %s",
181			    archive_error_string(bsdtar->matching));
182
183	a = archive_read_new();
184	if (cset_read_support_filter_program(bsdtar->cset, a) == 0)
185		archive_read_support_filter_all(a);
186	archive_read_support_format_all(a);
187
188	reader_options = getenv(ENV_READER_OPTIONS);
189	if (reader_options != NULL) {
190		size_t module_len = sizeof(IGNORE_WRONG_MODULE_NAME) - 1;
191		size_t opt_len = strlen(reader_options) + 1;
192		char *p;
193		/* Set default read options. */
194		if ((p = malloc(module_len + opt_len)) == NULL)
195			lafe_errc(1, errno, "Out of memory");
196		/* Prepend magic code to ignore options for
197		 * a format or  modules which are not added to
198		 *  the archive read object. */
199		memcpy(p, IGNORE_WRONG_MODULE_NAME, module_len);
200		memcpy(p + module_len, reader_options, opt_len);
201		r = archive_read_set_options(a, p);
202		free(p);
203		if (r == ARCHIVE_FATAL)
204			lafe_errc(1, 0, "%s", archive_error_string(a));
205		else
206			archive_clear_error(a);
207	}
208	if (ARCHIVE_OK != archive_read_set_options(a, bsdtar->option_options))
209		lafe_errc(1, 0, "%s", archive_error_string(a));
210	if (bsdtar->flags & OPTFLAG_IGNORE_ZEROS)
211		if (archive_read_set_options(a,
212		    "read_concatenated_archives") != ARCHIVE_OK)
213			lafe_errc(1, 0, "%s", archive_error_string(a));
214	if (bsdtar->passphrase != NULL)
215		r = archive_read_add_passphrase(a, bsdtar->passphrase);
216	else
217		r = archive_read_set_passphrase_callback(a, bsdtar,
218			&passphrase_callback);
219	if (r != ARCHIVE_OK)
220		lafe_errc(1, 0, "%s", archive_error_string(a));
221	if (archive_read_open_filename(a, bsdtar->filename,
222					bsdtar->bytes_per_block))
223		lafe_errc(1, 0, "Error opening archive: %s",
224		    archive_error_string(a));
225
226	do_chdir(bsdtar);
227
228	if (mode == 'x') {
229		/* Set an extract callback so that we can handle SIGINFO. */
230		progress_data.bsdtar = bsdtar;
231		progress_data.archive = a;
232		archive_read_extract_set_progress_callback(a, progress_func,
233		    &progress_data);
234	}
235
236	if (mode == 'x' && (bsdtar->flags & OPTFLAG_CHROOT)) {
237#if HAVE_CHROOT
238		if (chroot(".") != 0)
239			lafe_errc(1, errno, "Can't chroot to \".\"");
240#else
241		lafe_errc(1, 0,
242		    "chroot isn't supported on this platform");
243#endif
244	}
245
246#if defined(_WIN32) && !defined(__CYGWIN__)
247	if (mode == 'x' && (bsdtar->flags & OPTFLAG_STDOUT)) {
248		_setmode(1, _O_BINARY);
249	}
250#endif
251
252	for (;;) {
253		/* Support --fast-read option */
254		const char *p;
255		if ((bsdtar->flags & OPTFLAG_FAST_READ) &&
256		    archive_match_path_unmatched_inclusions(bsdtar->matching) == 0)
257			break;
258
259		r = archive_read_next_header(a, &entry);
260		progress_data.entry = entry;
261		if (r == ARCHIVE_EOF)
262			break;
263		if (r < ARCHIVE_OK)
264			lafe_warnc(0, "%s", archive_error_string(a));
265		if (r <= ARCHIVE_WARN)
266			bsdtar->return_value = 1;
267		if (r == ARCHIVE_RETRY) {
268			/* Retryable error: try again */
269			lafe_warnc(0, "Retrying...");
270			continue;
271		}
272		if (r == ARCHIVE_FATAL)
273			break;
274		p = archive_entry_pathname(entry);
275		if (p == NULL || p[0] == '\0') {
276			lafe_warnc(0, "Archive entry has empty or unreadable filename ... skipping.");
277			bsdtar->return_value = 1;
278			continue;
279		}
280
281		if (bsdtar->uid >= 0) {
282			archive_entry_set_uid(entry, bsdtar->uid);
283			archive_entry_set_uname(entry, NULL);
284		}
285		if (bsdtar->gid >= 0) {
286			archive_entry_set_gid(entry, bsdtar->gid);
287			archive_entry_set_gname(entry, NULL);
288		}
289		if (bsdtar->uname)
290			archive_entry_set_uname(entry, bsdtar->uname);
291		if (bsdtar->gname)
292			archive_entry_set_gname(entry, bsdtar->gname);
293
294		/*
295		 * Note that pattern exclusions are checked before
296		 * pathname rewrites are handled.  This gives more
297		 * control over exclusions, since rewrites always lose
298		 * information.  (For example, consider a rewrite
299		 * s/foo[0-9]/foo/.  If we check exclusions after the
300		 * rewrite, there would be no way to exclude foo1/bar
301		 * while allowing foo2/bar.)
302		 */
303		if (archive_match_excluded(bsdtar->matching, entry))
304			continue; /* Excluded by a pattern test. */
305
306		if (mode == 't') {
307			/* Perversely, gtar uses -O to mean "send to stderr"
308			 * when used with -t. */
309			out = (bsdtar->flags & OPTFLAG_STDOUT) ?
310			    stderr : stdout;
311
312			/*
313			 * TODO: Provide some reasonable way to
314			 * preview rewrites.  gtar always displays
315			 * the unedited path in -t output, which means
316			 * you cannot easily preview rewrites.
317			 */
318			if (bsdtar->verbose < 2)
319				safe_fprintf(out, "%s",
320				    archive_entry_pathname(entry));
321			else
322				list_item_verbose(bsdtar, out, entry);
323			fflush(out);
324			r = archive_read_data_skip(a);
325			if (r == ARCHIVE_WARN) {
326				fprintf(out, "\n");
327				lafe_warnc(0, "%s",
328				    archive_error_string(a));
329			}
330			if (r == ARCHIVE_RETRY) {
331				fprintf(out, "\n");
332				lafe_warnc(0, "%s",
333				    archive_error_string(a));
334			}
335			if (r == ARCHIVE_FATAL) {
336				fprintf(out, "\n");
337				lafe_warnc(0, "%s",
338				    archive_error_string(a));
339				bsdtar->return_value = 1;
340				break;
341			}
342			fprintf(out, "\n");
343		} else {
344			/* Note: some rewrite failures prevent extraction. */
345			if (edit_pathname(bsdtar, entry))
346				continue; /* Excluded by a rewrite failure. */
347
348			if ((bsdtar->flags & OPTFLAG_INTERACTIVE) &&
349			    !yes("extract '%s'", archive_entry_pathname(entry)))
350				continue;
351
352			if (bsdtar->verbose > 1) {
353				/* GNU tar uses -tv format with -xvv */
354				safe_fprintf(stderr, "x ");
355				list_item_verbose(bsdtar, stderr, entry);
356				fflush(stderr);
357			} else if (bsdtar->verbose > 0) {
358				/* Format follows SUSv2, including the
359				 * deferred '\n'. */
360				safe_fprintf(stderr, "x %s",
361				    archive_entry_pathname(entry));
362				fflush(stderr);
363			}
364
365			/* TODO siginfo_printinfo(bsdtar, 0); */
366
367			if (bsdtar->flags & OPTFLAG_STDOUT)
368				r = archive_read_data_into_fd(a, 1);
369			else
370				r = archive_read_extract2(a, entry, writer);
371			if (r != ARCHIVE_OK) {
372				if (!bsdtar->verbose)
373					safe_fprintf(stderr, "%s", archive_entry_pathname(entry));
374				safe_fprintf(stderr, ": %s: %s",
375				    archive_error_string(a),
376				    strerror(archive_errno(a)));
377				if (!bsdtar->verbose)
378					fprintf(stderr, "\n");
379				bsdtar->return_value = 1;
380			}
381			if (bsdtar->verbose)
382				fprintf(stderr, "\n");
383			if (r == ARCHIVE_FATAL)
384				break;
385		}
386	}
387
388
389	r = archive_read_close(a);
390	if (r != ARCHIVE_OK)
391		lafe_warnc(0, "%s", archive_error_string(a));
392	if (r <= ARCHIVE_WARN)
393		bsdtar->return_value = 1;
394
395	if (bsdtar->verbose > 2)
396		fprintf(stdout, "Archive Format: %s,  Compression: %s\n",
397		    archive_format_name(a), archive_filter_name(a, 0));
398
399	archive_read_free(a);
400}
401
402
403static int
404unmatched_inclusions_warn(struct archive *matching, const char *msg)
405{
406	const char *p;
407	int r;
408
409	if (matching == NULL)
410		return (0);
411
412	while ((r = archive_match_path_unmatched_inclusions_next(
413	    matching, &p)) == ARCHIVE_OK)
414		lafe_warnc(0, "%s: %s", p, msg);
415	if (r == ARCHIVE_FATAL)
416		lafe_errc(1, errno, "Out of memory");
417
418	return (archive_match_path_unmatched_inclusions(matching));
419}
420