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