Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/libarchive/tar/write.c
104814 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2003-2007 Tim Kientzle
5
* Copyright (c) 2012 Michihiro NAKAJIMA
6
* All rights reserved.
7
*/
8
9
#include "bsdtar_platform.h"
10
11
#ifdef HAVE_SYS_TYPES_H
12
#include <sys/types.h>
13
#endif
14
#ifdef HAVE_SYS_STAT_H
15
#include <sys/stat.h>
16
#endif
17
#if HAVE_SYS_XATTR_H
18
#include <sys/xattr.h>
19
#elif HAVE_ATTR_XATTR_H
20
#include <attr/xattr.h>
21
#endif
22
#ifdef HAVE_ERRNO_H
23
#include <errno.h>
24
#endif
25
#ifdef HAVE_FCNTL_H
26
#include <fcntl.h>
27
#endif
28
#ifdef HAVE_GRP_H
29
#include <grp.h>
30
#endif
31
#ifdef HAVE_IO_H
32
#include <io.h>
33
#endif
34
#ifdef HAVE_LIBGEN_H
35
#include <libgen.h>
36
#endif
37
#ifdef HAVE_LIMITS_H
38
#include <limits.h>
39
#endif
40
#ifdef HAVE_PATHS_H
41
#include <paths.h>
42
#endif
43
#ifdef HAVE_PWD_H
44
#include <pwd.h>
45
#endif
46
#ifdef HAVE_STDINT_H
47
#include <stdint.h>
48
#endif
49
#include <stdio.h>
50
#ifdef HAVE_STDLIB_H
51
#include <stdlib.h>
52
#endif
53
#ifdef HAVE_STRING_H
54
#include <string.h>
55
#endif
56
#ifdef HAVE_UNISTD_H
57
#include <unistd.h>
58
#endif
59
60
#include "bsdtar.h"
61
#include "lafe_err.h"
62
#include "line_reader.h"
63
64
#ifndef O_BINARY
65
#define O_BINARY 0
66
#endif
67
68
struct archive_dir_entry {
69
struct archive_dir_entry *next;
70
time_t mtime_sec;
71
int mtime_nsec;
72
char *name;
73
};
74
75
struct archive_dir {
76
struct archive_dir_entry *head, *tail;
77
};
78
79
static int append_archive(struct bsdtar *, struct archive *,
80
struct archive *ina);
81
static int append_archive_filename(struct bsdtar *,
82
struct archive *, const char *fname);
83
static void archive_names_from_file(struct bsdtar *bsdtar,
84
struct archive *a);
85
static int copy_file_data_block(struct bsdtar *,
86
struct archive *a, struct archive *,
87
struct archive_entry *);
88
static void excluded_callback(struct archive *, void *,
89
struct archive_entry *);
90
static void report_write(struct bsdtar *, struct archive *,
91
struct archive_entry *, int64_t progress);
92
static void test_for_append(struct bsdtar *);
93
static int metadata_filter(struct archive *, void *,
94
struct archive_entry *);
95
static void write_archive(struct archive *, struct bsdtar *);
96
static void write_entry(struct bsdtar *, struct archive *,
97
struct archive_entry *);
98
static void write_file(struct bsdtar *, struct archive *,
99
struct archive_entry *);
100
static void write_hierarchy(struct bsdtar *, struct archive *,
101
const char *);
102
103
#if defined(_WIN32) && !defined(__CYGWIN__)
104
/* Not a full lseek() emulation, but enough for our needs here. */
105
static int
106
seek_file(int fd, int64_t offset, int whence)
107
{
108
LARGE_INTEGER distance;
109
(void)whence; /* UNUSED */
110
distance.QuadPart = offset;
111
return (SetFilePointerEx((HANDLE)_get_osfhandle(fd),
112
distance, NULL, FILE_BEGIN) ? 1 : -1);
113
}
114
115
static int
116
_open_wrap_sopen(char const *const path, int const oflag, ...)
117
{
118
va_list ap;
119
int r, pmode;
120
121
pmode = 0;
122
if (oflag & _O_CREAT)
123
{
124
va_start(ap, oflag);
125
pmode = va_arg(ap, int);
126
va_end(ap);
127
}
128
129
_sopen_s(&r, path, oflag, _SH_DENYNO, pmode & 0600);
130
if (r < 0)
131
{
132
/* _sopen_s populates errno */
133
return -1;
134
}
135
136
return r;
137
}
138
139
#define open _open_wrap_sopen
140
#define close _close
141
#define read _read
142
#ifdef lseek
143
#undef lseek
144
#endif
145
#define lseek seek_file
146
#endif
147
148
static void
149
set_writer_options(struct bsdtar *bsdtar, struct archive *a)
150
{
151
const char *writer_options;
152
int r;
153
154
writer_options = getenv(ENV_WRITER_OPTIONS);
155
if (writer_options != NULL) {
156
size_t module_len = sizeof(IGNORE_WRONG_MODULE_NAME) - 1;
157
size_t opt_len = strlen(writer_options) + 1;
158
char *p;
159
/* Set default write options. */
160
if ((p = malloc(module_len + opt_len)) == NULL)
161
lafe_errc(1, errno, "Out of memory");
162
/* Prepend magic code to ignore options for
163
* a format or filters which are not added to
164
* the archive write object. */
165
memcpy(p, IGNORE_WRONG_MODULE_NAME, module_len);
166
memcpy(p + module_len, writer_options, opt_len);
167
r = archive_write_set_options(a, p);
168
free(p);
169
if (r < ARCHIVE_WARN)
170
lafe_errc(1, 0, "%s", archive_error_string(a));
171
else
172
archive_clear_error(a);
173
}
174
if (ARCHIVE_OK != archive_write_set_options(a, bsdtar->option_options))
175
lafe_errc(1, 0, "%s", archive_error_string(a));
176
}
177
178
static void
179
set_reader_options(struct bsdtar *bsdtar, struct archive *a)
180
{
181
const char *reader_options;
182
int r;
183
184
(void)bsdtar; /* UNUSED */
185
186
reader_options = getenv(ENV_READER_OPTIONS);
187
if (reader_options != NULL) {
188
size_t module_len = sizeof(IGNORE_WRONG_MODULE_NAME) - 1;
189
size_t opt_len = strlen(reader_options) + 1;
190
char *p;
191
/* Set default write options. */
192
if ((p = malloc(module_len + opt_len)) == NULL)
193
lafe_errc(1, errno, "Out of memory");
194
/* Prepend magic code to ignore options for
195
* a format or filters which are not added to
196
* the archive write object. */
197
memcpy(p, IGNORE_WRONG_MODULE_NAME, module_len);
198
memcpy(p + module_len, reader_options, opt_len);
199
r = archive_read_set_options(a, p);
200
free(p);
201
if (r < ARCHIVE_WARN)
202
lafe_errc(1, 0, "%s", archive_error_string(a));
203
else
204
archive_clear_error(a);
205
}
206
if (bsdtar->flags & OPTFLAG_IGNORE_ZEROS)
207
if (archive_read_set_options(a,
208
"read_concatenated_archives") != ARCHIVE_OK)
209
lafe_errc(1, 0, "%s", archive_error_string(a));
210
}
211
212
void
213
tar_mode_c(struct bsdtar *bsdtar)
214
{
215
struct archive *a;
216
const void *filter_name;
217
int r;
218
219
if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL)
220
lafe_errc(1, 0, "no files or directories specified");
221
222
a = archive_write_new();
223
224
/* Support any format that the library supports. */
225
if (cset_get_format(bsdtar->cset) == NULL) {
226
r = archive_write_set_format_pax_restricted(a);
227
cset_set_format(bsdtar->cset, "pax restricted");
228
} else {
229
r = archive_write_set_format_by_name(a,
230
cset_get_format(bsdtar->cset));
231
}
232
if (r != ARCHIVE_OK) {
233
fprintf(stderr, "Can't use format %s: %s\n",
234
cset_get_format(bsdtar->cset),
235
archive_error_string(a));
236
usage();
237
}
238
239
archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block);
240
archive_write_set_bytes_in_last_block(a, bsdtar->bytes_in_last_block);
241
242
r = cset_write_add_filters(bsdtar->cset, a, &filter_name);
243
if (r < ARCHIVE_WARN) {
244
lafe_errc(1, 0, "Unsupported compression option --%s",
245
(const char *)filter_name);
246
}
247
248
set_writer_options(bsdtar, a);
249
if (bsdtar->passphrase != NULL)
250
r = archive_write_set_passphrase(a, bsdtar->passphrase);
251
else
252
r = archive_write_set_passphrase_callback(a, bsdtar,
253
&passphrase_callback);
254
if (r != ARCHIVE_OK)
255
lafe_errc(1, 0, "%s", archive_error_string(a));
256
if (ARCHIVE_OK != archive_write_open_filename(a, bsdtar->filename))
257
lafe_errc(1, 0, "%s", archive_error_string(a));
258
write_archive(a, bsdtar);
259
}
260
261
/*
262
* Same as 'c', except we only support tar or empty formats in
263
* uncompressed files on disk.
264
*/
265
void
266
tar_mode_r(struct bsdtar *bsdtar)
267
{
268
int64_t end_offset;
269
int format;
270
struct archive *a;
271
struct archive_entry *entry;
272
int r;
273
274
/* Sanity-test some arguments and the file. */
275
test_for_append(bsdtar);
276
277
format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;
278
279
#if defined(__BORLANDC__)
280
bsdtar->fd = open(bsdtar->filename, O_RDWR | O_CREAT | O_BINARY);
281
#else
282
bsdtar->fd = open(bsdtar->filename, O_RDWR | O_CREAT | O_BINARY, 0666);
283
#endif
284
if (bsdtar->fd < 0)
285
lafe_errc(1, errno,
286
"Cannot open %s", bsdtar->filename);
287
288
a = archive_read_new();
289
archive_read_support_filter_all(a);
290
archive_read_support_format_empty(a);
291
archive_read_support_format_tar(a);
292
archive_read_support_format_gnutar(a);
293
set_reader_options(bsdtar, a);
294
r = archive_read_open_fd(a, bsdtar->fd, 10240);
295
if (r != ARCHIVE_OK)
296
lafe_errc(1, archive_errno(a),
297
"Can't read archive %s: %s", bsdtar->filename,
298
archive_error_string(a));
299
while (0 == archive_read_next_header(a, &entry)) {
300
if (archive_filter_code(a, 0) != ARCHIVE_FILTER_NONE) {
301
archive_read_free(a);
302
close(bsdtar->fd);
303
lafe_errc(1, 0,
304
"Cannot append to compressed archive.");
305
}
306
/* Keep going until we hit end-of-archive */
307
format = archive_format(a);
308
}
309
310
end_offset = archive_read_header_position(a);
311
archive_read_free(a);
312
313
/* Re-open archive for writing */
314
a = archive_write_new();
315
/*
316
* Set the format to be used for writing. To allow people to
317
* extend empty files, we need to allow them to specify the format,
318
* which opens the possibility that they will specify a format that
319
* doesn't match the existing format. Hence, the following bit
320
* of arcane ugliness.
321
*/
322
323
if (cset_get_format(bsdtar->cset) != NULL) {
324
/* If the user requested a format, use that, but ... */
325
archive_write_set_format_by_name(a,
326
cset_get_format(bsdtar->cset));
327
/* ... complain if it's not compatible. */
328
format &= ARCHIVE_FORMAT_BASE_MASK;
329
if (format != (int)(archive_format(a) & ARCHIVE_FORMAT_BASE_MASK)
330
&& format != ARCHIVE_FORMAT_EMPTY) {
331
lafe_errc(1, 0,
332
"Format %s is incompatible with the archive %s.",
333
cset_get_format(bsdtar->cset), bsdtar->filename);
334
}
335
} else {
336
/*
337
* Just preserve the current format, with a little care
338
* for formats that libarchive can't write.
339
*/
340
if (format == ARCHIVE_FORMAT_EMPTY)
341
format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;
342
archive_write_set_format(a, format);
343
}
344
if (lseek(bsdtar->fd, end_offset, SEEK_SET) < 0)
345
lafe_errc(1, errno, "Could not seek to archive end");
346
set_writer_options(bsdtar, a);
347
if (ARCHIVE_OK != archive_write_open_fd(a, bsdtar->fd))
348
lafe_errc(1, 0, "%s", archive_error_string(a));
349
350
write_archive(a, bsdtar); /* XXX check return val XXX */
351
352
close(bsdtar->fd);
353
bsdtar->fd = -1;
354
}
355
356
void
357
tar_mode_u(struct bsdtar *bsdtar)
358
{
359
int64_t end_offset;
360
struct archive *a;
361
struct archive_entry *entry;
362
int format;
363
struct archive_dir_entry *p;
364
struct archive_dir archive_dir;
365
366
bsdtar->archive_dir = &archive_dir;
367
memset(&archive_dir, 0, sizeof(archive_dir));
368
369
format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;
370
371
/* Sanity-test some arguments and the file. */
372
test_for_append(bsdtar);
373
374
bsdtar->fd = open(bsdtar->filename, O_RDWR | O_BINARY);
375
if (bsdtar->fd < 0)
376
lafe_errc(1, errno,
377
"Cannot open %s", bsdtar->filename);
378
379
a = archive_read_new();
380
archive_read_support_filter_all(a);
381
archive_read_support_format_tar(a);
382
archive_read_support_format_gnutar(a);
383
set_reader_options(bsdtar, a);
384
if (archive_read_open_fd(a, bsdtar->fd, bsdtar->bytes_per_block)
385
!= ARCHIVE_OK) {
386
lafe_errc(1, 0,
387
"Can't open %s: %s", bsdtar->filename,
388
archive_error_string(a));
389
}
390
391
/* Build a list of all entries and their recorded mod times. */
392
while (0 == archive_read_next_header(a, &entry)) {
393
if (archive_filter_code(a, 0) != ARCHIVE_FILTER_NONE) {
394
archive_read_free(a);
395
close(bsdtar->fd);
396
lafe_errc(1, 0,
397
"Cannot append to compressed archive.");
398
}
399
if (archive_match_exclude_entry(bsdtar->matching,
400
ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER |
401
ARCHIVE_MATCH_EQUAL, entry) != ARCHIVE_OK)
402
lafe_errc(1, 0, "Error : %s",
403
archive_error_string(bsdtar->matching));
404
/* Record the last format determination we see */
405
format = archive_format(a);
406
/* Keep going until we hit end-of-archive */
407
}
408
409
end_offset = archive_read_header_position(a);
410
archive_read_free(a);
411
412
/* Re-open archive for writing. */
413
a = archive_write_new();
414
/*
415
* Set format to same one auto-detected above.
416
*/
417
archive_write_set_format(a, format);
418
archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block);
419
archive_write_set_bytes_in_last_block(a, bsdtar->bytes_in_last_block);
420
421
if (lseek(bsdtar->fd, end_offset, SEEK_SET) < 0)
422
lafe_errc(1, errno, "Could not seek to archive end");
423
set_writer_options(bsdtar, a);
424
if (ARCHIVE_OK != archive_write_open_fd(a, bsdtar->fd))
425
lafe_errc(1, 0, "%s", archive_error_string(a));
426
427
write_archive(a, bsdtar);
428
429
close(bsdtar->fd);
430
bsdtar->fd = -1;
431
432
while (bsdtar->archive_dir->head != NULL) {
433
p = bsdtar->archive_dir->head->next;
434
free(bsdtar->archive_dir->head->name);
435
free(bsdtar->archive_dir->head);
436
bsdtar->archive_dir->head = p;
437
}
438
bsdtar->archive_dir->tail = NULL;
439
}
440
441
442
/*
443
* Write user-specified files/dirs to opened archive.
444
*/
445
static void
446
write_archive(struct archive *a, struct bsdtar *bsdtar)
447
{
448
const char *arg;
449
struct archive_entry *entry, *sparse_entry;
450
451
/* Choose a suitable copy buffer size */
452
bsdtar->buff_size = 64 * 1024;
453
while (bsdtar->buff_size < (size_t)bsdtar->bytes_per_block)
454
bsdtar->buff_size *= 2;
455
/* Try to compensate for space we'll lose to alignment. */
456
bsdtar->buff_size += 16 * 1024;
457
458
/* Allocate a buffer for file data. */
459
if ((bsdtar->buff = malloc(bsdtar->buff_size)) == NULL)
460
lafe_errc(1, 0, "cannot allocate memory");
461
462
if ((bsdtar->resolver = archive_entry_linkresolver_new()) == NULL)
463
lafe_errc(1, 0, "cannot create link resolver");
464
archive_entry_linkresolver_set_strategy(bsdtar->resolver,
465
archive_format(a));
466
467
/* Create a read_disk object. */
468
if ((bsdtar->diskreader = archive_read_disk_new()) == NULL)
469
lafe_errc(1, 0, "Cannot create read_disk object");
470
/* Tell the read_disk how handle symlink. */
471
switch (bsdtar->symlink_mode) {
472
case 'H':
473
archive_read_disk_set_symlink_hybrid(bsdtar->diskreader);
474
break;
475
case 'L':
476
archive_read_disk_set_symlink_logical(bsdtar->diskreader);
477
break;
478
default:
479
archive_read_disk_set_symlink_physical(bsdtar->diskreader);
480
break;
481
}
482
/* Register entry filters. */
483
archive_read_disk_set_matching(bsdtar->diskreader,
484
bsdtar->matching, excluded_callback, bsdtar);
485
archive_read_disk_set_metadata_filter_callback(
486
bsdtar->diskreader, metadata_filter, bsdtar);
487
/* Set the behavior of archive_read_disk. */
488
archive_read_disk_set_behavior(bsdtar->diskreader,
489
bsdtar->readdisk_flags);
490
archive_read_disk_set_standard_lookup(bsdtar->diskreader);
491
492
if (bsdtar->names_from_file != NULL)
493
archive_names_from_file(bsdtar, a);
494
495
while (*bsdtar->argv) {
496
arg = *bsdtar->argv;
497
if (arg[0] == '-' && arg[1] == 'C') {
498
arg += 2;
499
if (*arg == '\0') {
500
bsdtar->argv++;
501
arg = *bsdtar->argv;
502
if (arg == NULL) {
503
lafe_warnc(0, "%s",
504
"Missing argument for -C");
505
bsdtar->return_value = 1;
506
goto cleanup;
507
}
508
if (*arg == '\0') {
509
lafe_warnc(0,
510
"Meaningless argument for -C: ''");
511
bsdtar->return_value = 1;
512
goto cleanup;
513
}
514
}
515
set_chdir(bsdtar, arg);
516
} else {
517
if (*arg != '/')
518
do_chdir(bsdtar); /* Handle a deferred -C */
519
if (*arg == '@') {
520
if (append_archive_filename(bsdtar, a,
521
arg + 1) != 0)
522
break;
523
} else
524
write_hierarchy(bsdtar, a, arg);
525
}
526
bsdtar->argv++;
527
}
528
529
archive_read_disk_set_matching(bsdtar->diskreader, NULL, NULL, NULL);
530
archive_read_disk_set_metadata_filter_callback(
531
bsdtar->diskreader, NULL, NULL);
532
entry = NULL;
533
archive_entry_linkify(bsdtar->resolver, &entry, &sparse_entry);
534
while (entry != NULL) {
535
int r;
536
struct archive_entry *entry2;
537
struct archive *disk = bsdtar->diskreader;
538
539
/*
540
* This tricky code here is to correctly read the contents
541
* of the entry because the disk reader bsdtar->diskreader
542
* is pointing at does not have any information about the
543
* entry by this time and using archive_read_data_block()
544
* with the disk reader consequently must fail. And we
545
* have to re-open the entry to read the contents.
546
*/
547
/* TODO: Work with -C option as well. */
548
r = archive_read_disk_open(disk,
549
archive_entry_sourcepath(entry));
550
if (r != ARCHIVE_OK) {
551
lafe_warnc(archive_errno(disk),
552
"%s", archive_error_string(disk));
553
bsdtar->return_value = 1;
554
goto next_entry;
555
}
556
557
/*
558
* Invoke archive_read_next_header2() to work
559
* archive_read_data_block(), which is called via write_file(),
560
* without failure.
561
*/
562
entry2 = archive_entry_new();
563
r = archive_read_next_header2(disk, entry2);
564
archive_entry_free(entry2);
565
if (r != ARCHIVE_OK) {
566
lafe_warnc(archive_errno(disk),
567
"%s", archive_error_string(disk));
568
if (r == ARCHIVE_FATAL)
569
bsdtar->return_value = 1;
570
archive_read_close(disk);
571
goto next_entry;
572
}
573
574
write_file(bsdtar, a, entry);
575
archive_read_close(disk);
576
next_entry:
577
archive_entry_free(entry);
578
entry = NULL;
579
archive_entry_linkify(bsdtar->resolver, &entry, &sparse_entry);
580
}
581
582
if (archive_write_close(a)) {
583
lafe_warnc(0, "%s", archive_error_string(a));
584
bsdtar->return_value = 1;
585
}
586
587
cleanup:
588
/* Free file data buffer. */
589
free(bsdtar->buff);
590
archive_entry_linkresolver_free(bsdtar->resolver);
591
bsdtar->resolver = NULL;
592
archive_read_free(bsdtar->diskreader);
593
bsdtar->diskreader = NULL;
594
595
if (bsdtar->flags & OPTFLAG_TOTALS) {
596
fprintf(stderr, "Total bytes written: %s\n",
597
tar_i64toa(archive_filter_bytes(a, -1)));
598
}
599
600
archive_write_free(a);
601
}
602
603
/*
604
* Archive names specified in file.
605
*
606
* Unless --null was specified, a line containing exactly "-C" will
607
* cause the next line to be a directory to pass to chdir(). If
608
* --null is specified, then a line "-C" is just another filename.
609
*/
610
static void
611
archive_names_from_file(struct bsdtar *bsdtar, struct archive *a)
612
{
613
struct lafe_line_reader *lr;
614
const char *line;
615
616
bsdtar->next_line_is_dir = 0;
617
618
lr = lafe_line_reader(bsdtar->names_from_file,
619
(bsdtar->flags & OPTFLAG_NULL));
620
while ((line = lafe_line_reader_next(lr)) != NULL) {
621
if (bsdtar->next_line_is_dir) {
622
if (*line != '\0')
623
set_chdir(bsdtar, line);
624
else {
625
lafe_warnc(0,
626
"Meaningless argument for -C: ''");
627
bsdtar->return_value = 1;
628
}
629
bsdtar->next_line_is_dir = 0;
630
} else if (((bsdtar->flags & OPTFLAG_NULL) == 0) &&
631
strcmp(line, "-C") == 0)
632
bsdtar->next_line_is_dir = 1;
633
else {
634
if (*line != '/')
635
do_chdir(bsdtar); /* Handle a deferred -C */
636
write_hierarchy(bsdtar, a, line);
637
}
638
}
639
lafe_line_reader_free(lr);
640
if (bsdtar->next_line_is_dir)
641
lafe_errc(1, errno,
642
"Unexpected end of filename list; "
643
"directory expected after -C");
644
}
645
646
/*
647
* Copy from specified archive to current archive. Returns non-zero
648
* for write errors (which force us to terminate the entire archiving
649
* operation). If there are errors reading the input archive, we set
650
* bsdtar->return_value but return zero, so the overall archiving
651
* operation will complete and return non-zero.
652
*/
653
static int
654
append_archive_filename(struct bsdtar *bsdtar, struct archive *a,
655
const char *raw_filename)
656
{
657
struct archive *ina;
658
const char *filename = raw_filename;
659
int rc;
660
661
if (strcmp(filename, "-") == 0)
662
filename = NULL; /* Library uses NULL for stdio. */
663
664
ina = archive_read_new();
665
archive_read_support_format_all(ina);
666
archive_read_support_filter_all(ina);
667
set_reader_options(bsdtar, ina);
668
archive_read_set_options(ina, "mtree:checkfs");
669
if (bsdtar->passphrase != NULL)
670
rc = archive_read_add_passphrase(a, bsdtar->passphrase);
671
else
672
rc = archive_read_set_passphrase_callback(ina, bsdtar,
673
&passphrase_callback);
674
if (rc != ARCHIVE_OK)
675
lafe_errc(1, 0, "%s", archive_error_string(a));
676
if (archive_read_open_filename(ina, filename,
677
bsdtar->bytes_per_block)) {
678
lafe_warnc(0, "%s", archive_error_string(ina));
679
bsdtar->return_value = 1;
680
return (0);
681
}
682
683
rc = append_archive(bsdtar, a, ina);
684
685
if (rc != ARCHIVE_OK) {
686
lafe_warnc(0, "Error reading archive %s: %s",
687
raw_filename, archive_error_string(ina));
688
bsdtar->return_value = 1;
689
}
690
archive_read_free(ina);
691
692
return (rc);
693
}
694
695
static int
696
append_archive(struct bsdtar *bsdtar, struct archive *a, struct archive *ina)
697
{
698
struct archive_entry *in_entry;
699
int e;
700
701
while (ARCHIVE_OK == (e = archive_read_next_header(ina, &in_entry))) {
702
if (archive_match_excluded(bsdtar->matching, in_entry))
703
continue;
704
if(edit_pathname(bsdtar, in_entry))
705
continue;
706
if ((bsdtar->flags & OPTFLAG_INTERACTIVE) &&
707
!yes("copy '%s'", archive_entry_pathname(in_entry)))
708
continue;
709
edit_mtime(bsdtar, in_entry);
710
if (bsdtar->verbose > 1) {
711
safe_fprintf(stderr, "a ");
712
list_item_verbose(bsdtar, stderr, in_entry);
713
} else if (bsdtar->verbose > 0)
714
safe_fprintf(stderr, "a %s",
715
archive_entry_pathname(in_entry));
716
if (need_report())
717
report_write(bsdtar, a, in_entry, 0);
718
719
e = archive_write_header(a, in_entry);
720
if (e != ARCHIVE_OK) {
721
if (!bsdtar->verbose)
722
lafe_warnc(0, "%s: %s",
723
archive_entry_pathname(in_entry),
724
archive_error_string(a));
725
else
726
fprintf(stderr, ": %s", archive_error_string(a));
727
}
728
if (e == ARCHIVE_FATAL)
729
exit(1);
730
731
if (e >= ARCHIVE_WARN) {
732
if (archive_entry_size(in_entry) == 0)
733
archive_read_data_skip(ina);
734
else if (copy_file_data_block(bsdtar, a, ina, in_entry))
735
exit(1);
736
}
737
738
if (bsdtar->verbose)
739
fprintf(stderr, "\n");
740
}
741
742
return (e == ARCHIVE_EOF ? ARCHIVE_OK : e);
743
}
744
745
/* Helper function to copy file to archive. */
746
static int
747
copy_file_data_block(struct bsdtar *bsdtar, struct archive *a,
748
struct archive *in_a, struct archive_entry *entry)
749
{
750
size_t bytes_read;
751
ssize_t bytes_written;
752
int64_t offset, progress = 0;
753
char *null_buff = NULL;
754
const void *buff;
755
int r;
756
757
while ((r = archive_read_data_block(in_a, &buff,
758
&bytes_read, &offset)) == ARCHIVE_OK) {
759
if (need_report())
760
report_write(bsdtar, a, entry, progress);
761
762
if (offset > progress) {
763
int64_t sparse = offset - progress;
764
size_t ns;
765
766
if (null_buff == NULL) {
767
null_buff = bsdtar->buff;
768
memset(null_buff, 0, bsdtar->buff_size);
769
}
770
771
while (sparse > 0) {
772
if (sparse > (int64_t)bsdtar->buff_size)
773
ns = bsdtar->buff_size;
774
else
775
ns = (size_t)sparse;
776
bytes_written =
777
archive_write_data(a, null_buff, ns);
778
if (bytes_written < 0) {
779
/* Write failed; this is bad */
780
lafe_warnc(0, "%s",
781
archive_error_string(a));
782
return (-1);
783
}
784
if ((size_t)bytes_written < ns) {
785
/* Write was truncated; warn but
786
* continue. */
787
lafe_warnc(0,
788
"%s: Truncated write; file may "
789
"have grown while being archived.",
790
archive_entry_pathname(entry));
791
return (0);
792
}
793
progress += bytes_written;
794
sparse -= bytes_written;
795
}
796
}
797
798
bytes_written = archive_write_data(a, buff, bytes_read);
799
if (bytes_written < 0) {
800
/* Write failed; this is bad */
801
lafe_warnc(0, "%s", archive_error_string(a));
802
return (-1);
803
}
804
if ((size_t)bytes_written < bytes_read) {
805
/* Write was truncated; warn but continue. */
806
lafe_warnc(0,
807
"%s: Truncated write; file may have grown "
808
"while being archived.",
809
archive_entry_pathname(entry));
810
return (0);
811
}
812
progress += bytes_written;
813
}
814
if (r < ARCHIVE_WARN) {
815
lafe_warnc(archive_errno(a), "%s", archive_error_string(a));
816
return (-1);
817
}
818
return (0);
819
}
820
821
static void
822
excluded_callback(struct archive *a, void *_data, struct archive_entry *entry)
823
{
824
struct bsdtar *bsdtar = (struct bsdtar *)_data;
825
826
if (bsdtar->flags & OPTFLAG_NO_SUBDIRS)
827
return;
828
if (!archive_read_disk_can_descend(a))
829
return;
830
if ((bsdtar->flags & OPTFLAG_INTERACTIVE) &&
831
!yes("add '%s'", archive_entry_pathname(entry)))
832
return;
833
archive_read_disk_descend(a);
834
}
835
836
static int
837
metadata_filter(struct archive *a, void *_data, struct archive_entry *entry)
838
{
839
struct bsdtar *bsdtar = (struct bsdtar *)_data;
840
841
/* XXX TODO: check whether this filesystem is
842
* synthetic and/or local. Add a new
843
* --local-only option to skip non-local
844
* filesystems. Skip synthetic filesystems
845
* regardless.
846
*
847
* The results should be cached, since
848
* tree.c doesn't usually visit a directory
849
* and the directory contents together. A simple
850
* move-to-front list should perform quite well.
851
*
852
* Use archive_read_disk_current_filesystem_is_remote().
853
*/
854
855
/*
856
* If the user vetoes this file/directory, skip it.
857
* We want this to be fairly late; if some other
858
* check would veto this file, we shouldn't bother
859
* the user with it.
860
*/
861
if ((bsdtar->flags & OPTFLAG_INTERACTIVE) &&
862
!yes("add '%s'", archive_entry_pathname(entry)))
863
return (0);
864
865
/* Note: if user vetoes, we won't descend. */
866
if (((bsdtar->flags & OPTFLAG_NO_SUBDIRS) == 0) &&
867
archive_read_disk_can_descend(a))
868
archive_read_disk_descend(a);
869
870
return (1);
871
}
872
873
/*
874
* Add the file or dir hierarchy named by 'path' to the archive
875
*/
876
static void
877
write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
878
{
879
struct archive *disk = bsdtar->diskreader;
880
struct archive_entry *entry = NULL, *spare_entry = NULL;
881
int r;
882
883
r = archive_read_disk_open(disk, path);
884
if (r != ARCHIVE_OK) {
885
lafe_warnc(archive_errno(disk),
886
"%s", archive_error_string(disk));
887
bsdtar->return_value = 1;
888
return;
889
}
890
bsdtar->first_fs = -1;
891
892
for (;;) {
893
archive_entry_free(entry);
894
entry = archive_entry_new();
895
r = archive_read_next_header2(disk, entry);
896
if (r == ARCHIVE_EOF)
897
break;
898
else if (r != ARCHIVE_OK) {
899
lafe_warnc(archive_errno(disk),
900
"%s", archive_error_string(disk));
901
if (r == ARCHIVE_FATAL || r == ARCHIVE_FAILED) {
902
bsdtar->return_value = 1;
903
archive_entry_free(entry);
904
archive_read_close(disk);
905
return;
906
} else if (r < ARCHIVE_WARN)
907
continue;
908
}
909
910
if (bsdtar->uid >= 0) {
911
archive_entry_set_uid(entry, bsdtar->uid);
912
if (!bsdtar->uname)
913
archive_entry_set_uname(entry,
914
archive_read_disk_uname(bsdtar->diskreader,
915
bsdtar->uid));
916
}
917
if (bsdtar->gid >= 0) {
918
archive_entry_set_gid(entry, bsdtar->gid);
919
if (!bsdtar->gname)
920
archive_entry_set_gname(entry,
921
archive_read_disk_gname(bsdtar->diskreader,
922
bsdtar->gid));
923
}
924
if (bsdtar->uname)
925
archive_entry_set_uname(entry, bsdtar->uname);
926
if (bsdtar->gname)
927
archive_entry_set_gname(entry, bsdtar->gname);
928
929
/*
930
* Rewrite the pathname to be archived. If rewrite
931
* fails, skip the entry.
932
*/
933
if (edit_pathname(bsdtar, entry))
934
continue;
935
936
/* Rewrite the mtime. */
937
edit_mtime(bsdtar, entry);
938
939
/* Display entry as we process it. */
940
if (bsdtar->verbose > 1) {
941
safe_fprintf(stderr, "a ");
942
list_item_verbose(bsdtar, stderr, entry);
943
} else if (bsdtar->verbose > 0) {
944
/* This format is required by SUSv2. */
945
safe_fprintf(stderr, "a %s",
946
archive_entry_pathname(entry));
947
}
948
949
/* Non-regular files get archived with zero size. */
950
if (archive_entry_filetype(entry) != AE_IFREG)
951
archive_entry_set_size(entry, 0);
952
953
archive_entry_linkify(bsdtar->resolver, &entry, &spare_entry);
954
955
while (entry != NULL) {
956
write_file(bsdtar, a, entry);
957
if (entry != spare_entry) {
958
archive_entry_free(entry);
959
}
960
entry = spare_entry;
961
spare_entry = NULL;
962
}
963
964
if (bsdtar->verbose)
965
fprintf(stderr, "\n");
966
}
967
archive_entry_free(entry);
968
archive_read_close(disk);
969
}
970
971
/*
972
* Write a single file (or directory or other filesystem object) to
973
* the archive.
974
*/
975
static void
976
write_file(struct bsdtar *bsdtar, struct archive *a,
977
struct archive_entry *entry)
978
{
979
write_entry(bsdtar, a, entry);
980
}
981
982
/*
983
* Write a single entry to the archive.
984
*/
985
static void
986
write_entry(struct bsdtar *bsdtar, struct archive *a,
987
struct archive_entry *entry)
988
{
989
int e;
990
991
e = archive_write_header(a, entry);
992
if (e != ARCHIVE_OK) {
993
if (bsdtar->verbose > 1) {
994
safe_fprintf(stderr, "a ");
995
list_item_verbose(bsdtar, stderr, entry);
996
lafe_warnc(0, ": %s", archive_error_string(a));
997
} else {
998
lafe_warnc(0, "%s: %s",
999
archive_entry_pathname(entry),
1000
archive_error_string(a));
1001
}
1002
}
1003
1004
if (e == ARCHIVE_FATAL)
1005
exit(1);
1006
1007
/*
1008
* If we opened a file earlier, write it out now. Note that
1009
* the format handler might have reset the size field to zero
1010
* to inform us that the archive body won't get stored. In
1011
* that case, just skip the write.
1012
*/
1013
if (e >= ARCHIVE_WARN && archive_entry_size(entry) > 0) {
1014
if (copy_file_data_block(bsdtar, a, bsdtar->diskreader, entry))
1015
exit(1);
1016
}
1017
}
1018
1019
static void
1020
report_write(struct bsdtar *bsdtar, struct archive *a,
1021
struct archive_entry *entry, int64_t progress)
1022
{
1023
uint64_t comp, uncomp;
1024
int compression;
1025
1026
if (bsdtar->verbose)
1027
fprintf(stderr, "\n");
1028
comp = archive_filter_bytes(a, -1);
1029
uncomp = archive_filter_bytes(a, 0);
1030
fprintf(stderr, "In: %d files, %s bytes;",
1031
archive_file_count(a), tar_i64toa(uncomp));
1032
if (comp >= uncomp)
1033
compression = 0;
1034
else
1035
compression = (int)((uncomp - comp) * 100 / uncomp);
1036
fprintf(stderr,
1037
" Out: %s bytes, compression %d%%\n",
1038
tar_i64toa(comp), compression);
1039
/* Can't have two calls to tar_i64toa() pending, so split the output. */
1040
safe_fprintf(stderr, "Current: %s (%s",
1041
archive_entry_pathname(entry),
1042
tar_i64toa(progress));
1043
fprintf(stderr, "/%s bytes)\n",
1044
tar_i64toa(archive_entry_size(entry)));
1045
}
1046
1047
static void
1048
test_for_append(struct bsdtar *bsdtar)
1049
{
1050
struct stat s;
1051
1052
if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL)
1053
lafe_errc(1, 0, "no files or directories specified");
1054
if (bsdtar->filename == NULL)
1055
lafe_errc(1, 0, "Cannot append to stdout.");
1056
1057
if (stat(bsdtar->filename, &s) != 0)
1058
return;
1059
1060
if (!S_ISREG(s.st_mode) && !S_ISBLK(s.st_mode))
1061
lafe_errc(1, 0,
1062
"Cannot append to %s: not a regular file.",
1063
bsdtar->filename);
1064
1065
/* Is this an appropriate check here on Windows? */
1066
/*
1067
if (GetFileType(handle) != FILE_TYPE_DISK)
1068
lafe_errc(1, 0, "Cannot append");
1069
*/
1070
1071
}
1072
1073