2 * Copyright (c) 2003-2008 Tim Kientzle
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.
26 #include "bsdtar_platform.h"
28 #ifdef HAVE_SYS_PARAM_H
29 #include <sys/param.h>
31 #ifdef HAVE_SYS_STAT_H
34 #ifdef HAVE_COPYFILE_H
43 #ifdef HAVE_LANGINFO_H
72 #if ARCHIVE_VERSION_NUMBER < 4000000 && !defined(_PATH_DEFTAPE)
73 // Libarchive 4.0 and later will NOT define _PATH_DEFTAPE
74 // but will honor it if it's set in the build.
75 // Until then, we'll continue to set it by default on certain platforms:
77 #define _PATH_DEFTAPE "/dev/st0"
78 #elif defined(_WIN32) && !defined(__CYGWIN__)
79 #define _PATH_DEFTAPE "\\\\.\\tape0"
80 #elif !defined(__APPLE__)
81 #define _PATH_DEFTAPE "/dev/tape"
85 #define _PATH_STDIO "-"
88 int _CRT_glob
= 0; /* Disable broken CRT globbing. */
91 #if defined(HAVE_SIGACTION) && (defined(SIGINFO) || defined(SIGUSR1))
92 static volatile int siginfo_occurred
;
95 siginfo_handler(int sig
)
97 (void)sig
; /* UNUSED */
104 int r
= siginfo_occurred
;
105 siginfo_occurred
= 0;
116 static __LA_NORETURN
void long_help(void);
117 static void only_mode(struct bsdtar
*, const char *opt
,
119 static void set_mode(struct bsdtar
*, char opt
);
120 static __LA_NORETURN
void version(void);
122 /* A basic set of security flags to request from libarchive. */
124 (ARCHIVE_EXTRACT_SECURE_SYMLINKS \
125 | ARCHIVE_EXTRACT_SECURE_NODOTDOT)
127 static char const * const vcs_files
[] = {
137 ".git", ".gitignore", ".gitattributes", ".gitmodules",
139 ".arch-ids", "{arch}", "=RELEASE-ID", "=meta-update", "=update",
141 ".bzr", ".bzrignore", ".bzrtags",
143 ".hg", ".hgignore", ".hgtags",
150 main(int argc
, char **argv
)
152 struct bsdtar
*bsdtar
, bsdtar_storage
;
154 char compression
, compression2
;
155 const char *compression_name
, *compression2_name
;
156 const char *compress_program
;
158 char possible_help_request
;
162 * Use a pointer for consistency, but stack-allocated storage
163 * for ease of cleanup.
165 bsdtar
= &bsdtar_storage
;
166 memset(bsdtar
, 0, sizeof(*bsdtar
));
167 bsdtar
->fd
= -1; /* Mark as "unused" */
171 compression
= compression2
= '\0';
172 compression_name
= compression2_name
= NULL
;
173 compress_program
= NULL
;
175 #if defined(HAVE_SIGACTION)
176 { /* Set up signal handling. */
178 sa
.sa_handler
= siginfo_handler
;
179 sigemptyset(&sa
.sa_mask
);
182 if (sigaction(SIGINFO
, &sa
, NULL
))
183 lafe_errc(1, errno
, "sigaction(SIGINFO) failed");
186 /* ... and treat SIGUSR1 the same way as SIGINFO. */
187 if (sigaction(SIGUSR1
, &sa
, NULL
))
188 lafe_errc(1, errno
, "sigaction(SIGUSR1) failed");
191 /* Ignore SIGPIPE signals. */
192 sa
.sa_handler
= SIG_IGN
;
193 sigaction(SIGPIPE
, &sa
, NULL
);
198 /* Set lafe_progname before calling lafe_warnc. */
199 lafe_setprogname(*argv
, "bsdtar");
202 if (setlocale(LC_ALL
, "") == NULL
)
203 lafe_warnc(0, "Failed to set default locale");
205 #if defined(HAVE_NL_LANGINFO) && defined(HAVE_D_MD_ORDER)
206 bsdtar
->day_first
= (*nl_langinfo(D_MD_ORDER
) == 'd');
208 possible_help_request
= 0;
210 /* Look up uid of current user for future reference */
211 bsdtar
->user_uid
= geteuid();
213 /* Default: open tape drive. */
214 bsdtar
->filename
= getenv("TAPE");
215 #if defined(_PATH_DEFTAPE)
216 if (bsdtar
->filename
== NULL
) {
217 #if defined(_WIN32) && !defined(__CYGWIN__)
218 int tapeExists
= !_access(_PATH_DEFTAPE
, 0);
220 int tapeExists
= !access(_PATH_DEFTAPE
, F_OK
);
223 bsdtar
->filename
= _PATH_DEFTAPE
;
227 if (bsdtar
->filename
== NULL
) {
228 bsdtar
->filename
= _PATH_STDIO
;
231 /* Default block size settings. */
232 bsdtar
->bytes_per_block
= DEFAULT_BYTES_PER_BLOCK
;
233 /* Allow library to default this unless user specifies -b. */
234 bsdtar
->bytes_in_last_block
= -1;
236 /* Default: preserve mod time on extract */
237 bsdtar
->extract_flags
= ARCHIVE_EXTRACT_TIME
;
239 /* Default: Perform basic security checks. */
240 bsdtar
->extract_flags
|= SECURITY
;
243 /* On POSIX systems, assume --same-owner and -p when run by
244 * the root user. This doesn't make any sense on Windows. */
245 if (bsdtar
->user_uid
== 0) {
247 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_OWNER
;
249 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_PERM
;
250 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_ACL
;
251 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_XATTR
;
252 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_FFLAGS
;
253 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_MAC_METADATA
;
258 * Enable Mac OS "copyfile()" extension by default.
259 * This has no effect on other platforms.
261 bsdtar
->readdisk_flags
|= ARCHIVE_READDISK_MAC_COPYFILE
;
262 #ifdef COPYFILE_DISABLE_VAR
263 if (getenv(COPYFILE_DISABLE_VAR
))
264 bsdtar
->readdisk_flags
&= ~ARCHIVE_READDISK_MAC_COPYFILE
;
266 #if defined(__APPLE__)
268 * On Mac OS ACLs are archived with copyfile() (--mac-metadata)
269 * Translation to NFSv4 ACLs has to be requested explicitly with --acls
271 bsdtar
->readdisk_flags
|= ARCHIVE_READDISK_NO_ACL
;
274 bsdtar
->matching
= archive_match_new();
275 if (bsdtar
->matching
== NULL
)
276 lafe_errc(1, errno
, "Out of memory");
277 bsdtar
->cset
= cset_new();
278 if (bsdtar
->cset
== NULL
)
279 lafe_errc(1, errno
, "Out of memory");
285 * Comments following each option indicate where that option
286 * originated: SUSv2, POSIX, GNU tar, star, etc. If there's
287 * no such comment, then I don't know of anyone else who
288 * implements that option.
290 while ((opt
= bsdtar_getopt(bsdtar
)) != -1) {
292 case 'a': /* GNU tar */
293 bsdtar
->flags
|= OPTFLAG_AUTO_COMPRESS
;
295 case OPTION_ACLS
: /* GNU tar */
296 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_ACL
;
297 bsdtar
->readdisk_flags
&= ~ARCHIVE_READDISK_NO_ACL
;
298 bsdtar
->flags
|= OPTFLAG_ACLS
;
300 case 'B': /* GNU tar */
301 /* libarchive doesn't need this; just ignore it. */
303 case 'b': /* SUSv2 */
306 t
= (int)strtol(bsdtar
->argument
, &tptr
, 10);
307 if (errno
|| t
<= 0 || t
> 8192 ||
308 *(bsdtar
->argument
) == '\0' || tptr
== NULL
||
310 lafe_errc(1, 0, "Invalid or out of range "
311 "(1..8192) argument to -b");
313 bsdtar
->bytes_per_block
= 512 * t
;
314 /* Explicit -b forces last block size. */
315 bsdtar
->bytes_in_last_block
= bsdtar
->bytes_per_block
;
317 case OPTION_B64ENCODE
:
318 if (compression2
!= '\0')
320 "Can't specify both --uuencode and "
323 compression2_name
= "b64encode";
325 case 'C': /* GNU tar */
326 if (strlen(bsdtar
->argument
) == 0)
328 "Meaningless option: -C ''");
330 set_chdir(bsdtar
, bsdtar
->argument
);
332 case 'c': /* SUSv2 */
333 set_mode(bsdtar
, opt
);
335 case OPTION_CHECK_LINKS
: /* GNU tar */
336 bsdtar
->flags
|= OPTFLAG_WARN_LINKS
;
338 case OPTION_CHROOT
: /* NetBSD */
339 bsdtar
->flags
|= OPTFLAG_CHROOT
;
341 case OPTION_CLEAR_NOCHANGE_FFLAGS
:
342 bsdtar
->extract_flags
|=
343 ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS
;
345 case OPTION_EXCLUDE
: /* GNU tar */
346 if (archive_match_exclude_pattern(
347 bsdtar
->matching
, bsdtar
->argument
) != ARCHIVE_OK
)
349 "Couldn't exclude %s\n", bsdtar
->argument
);
351 case OPTION_EXCLUDE_VCS
: /* GNU tar */
352 for(t
=0; vcs_files
[t
]; t
++) {
353 if (archive_match_exclude_pattern(
355 vcs_files
[t
]) != ARCHIVE_OK
)
356 lafe_errc(1, 0, "Couldn't "
357 "exclude %s\n", vcs_files
[t
]);
361 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_FFLAGS
;
362 bsdtar
->readdisk_flags
&= ~ARCHIVE_READDISK_NO_FFLAGS
;
363 bsdtar
->flags
|= OPTFLAG_FFLAGS
;
365 case OPTION_FORMAT
: /* GNU tar, others */
366 cset_set_format(bsdtar
->cset
, bsdtar
->argument
);
368 case 'f': /* SUSv2 */
369 bsdtar
->filename
= bsdtar
->argument
;
371 case OPTION_GID
: /* cpio */
374 t
= (int)strtol(bsdtar
->argument
, &tptr
, 10);
375 if (errno
|| t
< 0 || *(bsdtar
->argument
) == '\0' ||
376 tptr
== NULL
|| *tptr
!= '\0') {
377 lafe_errc(1, 0, "Invalid argument to --gid");
381 case OPTION_GNAME
: /* cpio */
382 bsdtar
->gname
= bsdtar
->argument
;
384 case OPTION_GROUP
: /* GNU tar */
388 uptr
= strchr(bsdtar
->argument
, ':');
391 lafe_errc(1, 0, "Invalid argument to --group (missing id after :)");
395 t
= (int)strtol(uptr
, &tptr
, 10);
396 if (errno
|| t
< 0 || *uptr
== '\0' ||
397 tptr
== NULL
|| *tptr
!= '\0') {
398 lafe_errc(1, 0, "Invalid argument to --group (%s is not a number)", uptr
);
402 bsdtar
->gname
= bsdtar
->argument
;
404 t
= (int)strtol(bsdtar
->argument
, &tptr
, 10);
405 if (errno
|| t
< 0 || *(bsdtar
->argument
) == '\0' ||
406 tptr
== NULL
|| *tptr
!= '\0') {
407 bsdtar
->gname
= bsdtar
->argument
;
415 if (compression
!= '\0')
417 "Can't specify both -%c and -%c", opt
,
420 compression_name
= "grzip";
422 case 'H': /* BSD convention */
423 bsdtar
->symlink_mode
= 'H';
425 case 'h': /* Linux Standards Base, gtar; synonym for -L */
426 bsdtar
->symlink_mode
= 'L';
427 /* Hack: -h by itself is the "help" command. */
428 possible_help_request
= 1;
430 case OPTION_HELP
: /* GNU tar, others */
433 case OPTION_HFS_COMPRESSION
: /* Mac OS X v10.6 or later */
434 bsdtar
->extract_flags
|=
435 ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED
;
437 case OPTION_IGNORE_ZEROS
:
438 bsdtar
->flags
|= OPTFLAG_IGNORE_ZEROS
;
440 case 'I': /* GNU tar */
442 * TODO: Allow 'names' to come from an archive,
443 * not just a text file. Design a good UI for
444 * allowing names and mode/owner to be read
445 * from an archive, with contents coming from
446 * disk. This can be used to "refresh" an
447 * archive or to design archives with special
448 * permissions without having to create those
449 * permissions on disk.
451 bsdtar
->names_from_file
= bsdtar
->argument
;
455 * No one else has the @archive extension, so
456 * no one else needs this to filter entries
457 * when transforming archives.
459 if (archive_match_include_pattern(bsdtar
->matching
,
460 bsdtar
->argument
) != ARCHIVE_OK
)
462 "Failed to add %s to inclusion list",
465 case 'j': /* GNU tar */
466 if (compression
!= '\0')
468 "Can't specify both -%c and -%c", opt
,
471 compression_name
= "bzip2";
473 case 'J': /* GNU tar 1.21 and later */
474 if (compression
!= '\0')
476 "Can't specify both -%c and -%c", opt
,
479 compression_name
= "xz";
481 case 'k': /* GNU tar */
482 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_NO_OVERWRITE
;
484 case OPTION_KEEP_NEWER_FILES
: /* GNU tar */
485 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER
;
487 case 'L': /* BSD convention */
488 bsdtar
->symlink_mode
= 'L';
490 case 'l': /* SUSv2 and GNU tar beginning with 1.16 */
491 /* GNU tar 1.13 used -l for --one-file-system */
492 bsdtar
->flags
|= OPTFLAG_WARN_LINKS
;
496 case OPTION_LZIP
: /* GNU tar beginning with 1.23 */
497 case OPTION_LZMA
: /* GNU tar beginning with 1.20 */
498 case OPTION_LZOP
: /* GNU tar beginning with 1.21 */
500 if (compression
!= '\0')
502 "Can't specify both -%c and -%c", opt
,
506 case OPTION_LRZIP
: compression_name
= "lrzip"; break;
507 case OPTION_LZ4
: compression_name
= "lz4"; break;
508 case OPTION_LZIP
: compression_name
= "lzip"; break;
509 case OPTION_LZMA
: compression_name
= "lzma"; break;
510 case OPTION_LZOP
: compression_name
= "lzop"; break;
511 case OPTION_ZSTD
: compression_name
= "zstd"; break;
514 case 'm': /* SUSv2 */
515 bsdtar
->extract_flags
&= ~ARCHIVE_EXTRACT_TIME
;
517 case OPTION_MAC_METADATA
: /* Mac OS X */
518 bsdtar
->readdisk_flags
|= ARCHIVE_READDISK_MAC_COPYFILE
;
519 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_MAC_METADATA
;
520 bsdtar
->flags
|= OPTFLAG_MAC_METADATA
;
522 case 'n': /* GNU tar */
523 bsdtar
->flags
|= OPTFLAG_NO_SUBDIRS
;
526 * Selecting files by time:
527 * --newer-?time='date' Only files newer than 'date'
528 * --newer-?time-than='file' Only files newer than time
529 * on specified file (useful for incremental backups)
531 case OPTION_NEWER_CTIME
: /* GNU tar */
532 if (archive_match_include_date(bsdtar
->matching
,
533 ARCHIVE_MATCH_CTIME
| ARCHIVE_MATCH_NEWER
,
534 bsdtar
->argument
) != ARCHIVE_OK
)
535 lafe_errc(1, 0, "Error : %s",
536 archive_error_string(bsdtar
->matching
));
538 case OPTION_NEWER_CTIME_THAN
:
539 if (archive_match_include_file_time(bsdtar
->matching
,
540 ARCHIVE_MATCH_CTIME
| ARCHIVE_MATCH_NEWER
,
541 bsdtar
->argument
) != ARCHIVE_OK
)
542 lafe_errc(1, 0, "Error : %s",
543 archive_error_string(bsdtar
->matching
));
545 case OPTION_NEWER_MTIME
: /* GNU tar */
546 if (archive_match_include_date(bsdtar
->matching
,
547 ARCHIVE_MATCH_MTIME
| ARCHIVE_MATCH_NEWER
,
548 bsdtar
->argument
) != ARCHIVE_OK
)
549 lafe_errc(1, 0, "Error : %s",
550 archive_error_string(bsdtar
->matching
));
552 case OPTION_NEWER_MTIME_THAN
:
553 if (archive_match_include_file_time(bsdtar
->matching
,
554 ARCHIVE_MATCH_MTIME
| ARCHIVE_MATCH_NEWER
,
555 bsdtar
->argument
) != ARCHIVE_OK
)
556 lafe_errc(1, 0, "Error : %s",
557 archive_error_string(bsdtar
->matching
));
559 case OPTION_NODUMP
: /* star */
560 bsdtar
->readdisk_flags
|= ARCHIVE_READDISK_HONOR_NODUMP
;
562 case OPTION_NOPRESERVE_HFS_COMPRESSION
:
563 /* Mac OS X v10.6 or later */
564 bsdtar
->extract_flags
|=
565 ARCHIVE_EXTRACT_NO_HFS_COMPRESSION
;
567 case OPTION_NO_ACLS
: /* GNU tar */
568 bsdtar
->extract_flags
&= ~ARCHIVE_EXTRACT_ACL
;
569 bsdtar
->readdisk_flags
|= ARCHIVE_READDISK_NO_ACL
;
570 bsdtar
->flags
|= OPTFLAG_NO_ACLS
;
572 case OPTION_NO_FFLAGS
:
573 bsdtar
->extract_flags
&= ~ARCHIVE_EXTRACT_FFLAGS
;
574 bsdtar
->readdisk_flags
|= ARCHIVE_READDISK_NO_FFLAGS
;
575 bsdtar
->flags
|= OPTFLAG_NO_FFLAGS
;
577 case OPTION_NO_MAC_METADATA
: /* Mac OS X */
578 bsdtar
->readdisk_flags
&= ~ARCHIVE_READDISK_MAC_COPYFILE
;
579 bsdtar
->extract_flags
&= ~ARCHIVE_EXTRACT_MAC_METADATA
;
580 bsdtar
->flags
|= OPTFLAG_NO_MAC_METADATA
;
582 case OPTION_NO_READ_SPARSE
:
583 bsdtar
->readdisk_flags
|= ARCHIVE_READDISK_NO_SPARSE
;
584 bsdtar
->flags
|= OPTFLAG_NO_READ_SPARSE
;
586 case OPTION_NO_SAFE_WRITES
:
587 bsdtar
->extract_flags
&= ~ARCHIVE_EXTRACT_SAFE_WRITES
;
589 case OPTION_NO_SAME_OWNER
: /* GNU tar */
590 bsdtar
->extract_flags
&= ~ARCHIVE_EXTRACT_OWNER
;
592 case OPTION_NO_SAME_PERMISSIONS
: /* GNU tar */
593 bsdtar
->extract_flags
&= ~ARCHIVE_EXTRACT_PERM
;
594 bsdtar
->extract_flags
&= ~ARCHIVE_EXTRACT_ACL
;
595 bsdtar
->extract_flags
&= ~ARCHIVE_EXTRACT_XATTR
;
596 bsdtar
->extract_flags
&= ~ARCHIVE_EXTRACT_FFLAGS
;
597 bsdtar
->extract_flags
&= ~ARCHIVE_EXTRACT_MAC_METADATA
;
599 case OPTION_NO_XATTRS
: /* GNU tar */
600 bsdtar
->extract_flags
&= ~ARCHIVE_EXTRACT_XATTR
;
601 bsdtar
->readdisk_flags
|= ARCHIVE_READDISK_NO_XATTR
;
602 bsdtar
->flags
|= OPTFLAG_NO_XATTRS
;
604 case OPTION_NULL
: /* GNU tar */
605 bsdtar
->flags
|= OPTFLAG_NULL
;
607 case OPTION_NUMERIC_OWNER
: /* GNU tar */
610 bsdtar
->flags
|= OPTFLAG_NUMERIC_OWNER
;
612 case 'O': /* GNU tar */
613 bsdtar
->flags
|= OPTFLAG_STDOUT
;
615 case 'o': /* SUSv2 and GNU conflict here, but not fatally */
616 bsdtar
->flags
|= OPTFLAG_O
;
619 * Selecting files by time:
620 * --older-?time='date' Only files older than 'date'
621 * --older-?time-than='file' Only files older than time
624 case OPTION_OLDER_CTIME
:
625 if (archive_match_include_date(bsdtar
->matching
,
626 ARCHIVE_MATCH_CTIME
| ARCHIVE_MATCH_OLDER
,
627 bsdtar
->argument
) != ARCHIVE_OK
)
628 lafe_errc(1, 0, "Error : %s",
629 archive_error_string(bsdtar
->matching
));
631 case OPTION_OLDER_CTIME_THAN
:
632 if (archive_match_include_file_time(bsdtar
->matching
,
633 ARCHIVE_MATCH_CTIME
| ARCHIVE_MATCH_OLDER
,
634 bsdtar
->argument
) != ARCHIVE_OK
)
635 lafe_errc(1, 0, "Error : %s",
636 archive_error_string(bsdtar
->matching
));
638 case OPTION_OLDER_MTIME
:
639 if (archive_match_include_date(bsdtar
->matching
,
640 ARCHIVE_MATCH_MTIME
| ARCHIVE_MATCH_OLDER
,
641 bsdtar
->argument
) != ARCHIVE_OK
)
642 lafe_errc(1, 0, "Error : %s",
643 archive_error_string(bsdtar
->matching
));
645 case OPTION_OLDER_MTIME_THAN
:
646 if (archive_match_include_file_time(bsdtar
->matching
,
647 ARCHIVE_MATCH_MTIME
| ARCHIVE_MATCH_OLDER
,
648 bsdtar
->argument
) != ARCHIVE_OK
)
649 lafe_errc(1, 0, "Error : %s",
650 archive_error_string(bsdtar
->matching
));
652 case OPTION_ONE_FILE_SYSTEM
: /* GNU tar */
653 bsdtar
->readdisk_flags
|=
654 ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS
;
657 bsdtar
->option_options
= bsdtar
->argument
;
659 case OPTION_OWNER
: /* GNU tar */
663 uptr
= strchr(bsdtar
->argument
, ':');
666 lafe_errc(1, 0, "Invalid argument to --owner (missing id after :)");
670 t
= (int)strtol(uptr
, &tptr
, 10);
671 if (errno
|| t
< 0 || *uptr
== '\0' ||
672 tptr
== NULL
|| *tptr
!= '\0') {
673 lafe_errc(1, 0, "Invalid argument to --owner (%s is not a number)", uptr
);
677 bsdtar
->uname
= bsdtar
->argument
;
679 t
= (int)strtol(bsdtar
->argument
, &tptr
, 10);
680 if (errno
|| t
< 0 || *(bsdtar
->argument
) == '\0' ||
681 tptr
== NULL
|| *tptr
!= '\0') {
682 bsdtar
->uname
= bsdtar
->argument
;
691 * The common BSD -P option is not necessary, since
692 * our default is to archive symlinks, not follow
693 * them. This is convenient, as -P conflicts with GNU
696 case 'P': /* BSD convention */
697 /* Default behavior, no option necessary. */
700 case 'P': /* GNU tar */
701 bsdtar
->extract_flags
&= ~SECURITY
;
702 bsdtar
->flags
|= OPTFLAG_ABSOLUTE_PATHS
;
704 case 'p': /* GNU tar, star */
705 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_PERM
;
706 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_ACL
;
707 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_XATTR
;
708 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_FFLAGS
;
709 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_MAC_METADATA
;
711 case OPTION_PASSPHRASE
:
712 bsdtar
->passphrase
= bsdtar
->argument
;
714 case OPTION_POSIX
: /* GNU tar */
715 cset_set_format(bsdtar
->cset
, "pax");
717 case 'q': /* FreeBSD GNU tar --fast-read, NetBSD -q */
718 bsdtar
->flags
|= OPTFLAG_FAST_READ
;
720 case 'r': /* SUSv2 */
721 set_mode(bsdtar
, opt
);
723 case OPTION_READ_SPARSE
:
724 bsdtar
->readdisk_flags
&= ~ARCHIVE_READDISK_NO_SPARSE
;
725 bsdtar
->flags
|= OPTFLAG_READ_SPARSE
;
727 case 'S': /* NetBSD pax-as-tar */
728 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_SPARSE
;
730 case 's': /* NetBSD pax-as-tar */
731 #if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) || defined(HAVE_PCRE2POSIX_H)
732 add_substitution(bsdtar
, bsdtar
->argument
);
735 "-s is not supported by this version of bsdtar");
739 case OPTION_SAFE_WRITES
:
740 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_SAFE_WRITES
;
742 case OPTION_SAME_OWNER
: /* GNU tar */
743 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_OWNER
;
745 case OPTION_STRIP_COMPONENTS
: /* GNU tar 1.15 */
748 t
= (int)strtol(bsdtar
->argument
, &tptr
, 10);
749 if (errno
|| t
< 0 || *(bsdtar
->argument
) == '\0' ||
750 tptr
== NULL
|| *tptr
!= '\0') {
751 lafe_errc(1, 0, "Invalid argument to "
752 "--strip-components");
754 bsdtar
->strip_components
= t
;
756 case 'T': /* GNU tar */
757 bsdtar
->names_from_file
= bsdtar
->argument
;
759 case 't': /* SUSv2 */
760 set_mode(bsdtar
, opt
);
763 case OPTION_TOTALS
: /* GNU tar */
764 bsdtar
->flags
|= OPTFLAG_TOTALS
;
766 case 'U': /* GNU tar */
767 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_UNLINK
;
768 bsdtar
->flags
|= OPTFLAG_UNLINK_FIRST
;
770 case 'u': /* SUSv2 */
771 set_mode(bsdtar
, opt
);
773 case OPTION_UID
: /* cpio */
776 t
= (int)strtol(bsdtar
->argument
, &tptr
, 10);
777 if (errno
|| t
< 0 || *(bsdtar
->argument
) == '\0' ||
778 tptr
== NULL
|| *tptr
!= '\0') {
779 lafe_errc(1, 0, "Invalid argument to --uid");
783 case OPTION_UNAME
: /* cpio */
784 bsdtar
->uname
= bsdtar
->argument
;
786 case OPTION_UUENCODE
:
787 if (compression2
!= '\0')
789 "Can't specify both --uuencode and "
792 compression2_name
= "uuencode";
794 case 'v': /* SUSv2 */
797 case OPTION_VERSION
: /* GNU convention */
802 * The -W longopt feature is handled inside of
803 * bsdtar_getopt(), so -W is not available here.
805 case 'W': /* Obscure GNU convention. */
808 case 'w': /* SUSv2 */
809 bsdtar
->flags
|= OPTFLAG_INTERACTIVE
;
811 case 'X': /* GNU tar */
812 if (archive_match_exclude_pattern_from_file(
813 bsdtar
->matching
, bsdtar
->argument
, 0)
815 lafe_errc(1, 0, "Error : %s",
816 archive_error_string(bsdtar
->matching
));
818 case 'x': /* SUSv2 */
819 set_mode(bsdtar
, opt
);
821 case OPTION_XATTRS
: /* GNU tar */
822 bsdtar
->extract_flags
|= ARCHIVE_EXTRACT_XATTR
;
823 bsdtar
->readdisk_flags
&= ~ARCHIVE_READDISK_NO_XATTR
;
824 bsdtar
->flags
|= OPTFLAG_XATTRS
;
826 case 'y': /* FreeBSD version of GNU tar */
827 if (compression
!= '\0')
829 "Can't specify both -%c and -%c", opt
,
832 compression_name
= "bzip2";
834 case 'Z': /* GNU tar */
835 if (compression
!= '\0')
837 "Can't specify both -%c and -%c", opt
,
840 compression_name
= "compress";
842 case 'z': /* GNU tar, star, many others */
843 if (compression
!= '\0')
845 "Can't specify both -%c and -%c", opt
,
848 compression_name
= "gzip";
850 case OPTION_USE_COMPRESS_PROGRAM
:
851 compress_program
= bsdtar
->argument
;
859 * Sanity-check options.
862 /* If no "real" mode was specified, treat -h as --help. */
863 if ((bsdtar
->mode
== '\0') && possible_help_request
) {
867 /* Otherwise, a mode is required. */
868 if (bsdtar
->mode
== '\0')
870 "Must specify one of -c, -r, -t, -u, -x");
872 /* Check boolean options only permitted in certain modes. */
873 if (bsdtar
->flags
& OPTFLAG_AUTO_COMPRESS
) {
874 only_mode(bsdtar
, "-a", "cx");
875 if (bsdtar
->mode
== 'x') {
876 bsdtar
->flags
&= ~OPTFLAG_AUTO_COMPRESS
;
878 "Ignoring option -a in mode -x");
881 if (bsdtar
->readdisk_flags
& ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS
)
882 only_mode(bsdtar
, "--one-file-system", "cru");
883 if (bsdtar
->flags
& OPTFLAG_FAST_READ
)
884 only_mode(bsdtar
, "--fast-read", "xt");
885 if (bsdtar
->extract_flags
& ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED
)
886 only_mode(bsdtar
, "--hfsCompression", "x");
887 if (bsdtar
->extract_flags
& ARCHIVE_EXTRACT_NO_HFS_COMPRESSION
)
888 only_mode(bsdtar
, "--nopreserveHFSCompression", "x");
889 if (bsdtar
->readdisk_flags
& ARCHIVE_READDISK_HONOR_NODUMP
)
890 only_mode(bsdtar
, "--nodump", "cru");
891 if (bsdtar
->flags
& OPTFLAG_ACLS
)
892 only_mode(bsdtar
, "--acls", "crux");
893 if (bsdtar
->flags
& OPTFLAG_NO_ACLS
)
894 only_mode(bsdtar
, "--no-acls", "crux");
895 if (bsdtar
->flags
& OPTFLAG_XATTRS
)
896 only_mode(bsdtar
, "--xattrs", "crux");
897 if (bsdtar
->flags
& OPTFLAG_NO_XATTRS
)
898 only_mode(bsdtar
, "--no-xattrs", "crux");
899 if (bsdtar
->flags
& OPTFLAG_FFLAGS
)
900 only_mode(bsdtar
, "--fflags", "crux");
901 if (bsdtar
->flags
& OPTFLAG_NO_FFLAGS
)
902 only_mode(bsdtar
, "--no-fflags", "crux");
903 if (bsdtar
->flags
& OPTFLAG_MAC_METADATA
)
904 only_mode(bsdtar
, "--mac-metadata", "crux");
905 if (bsdtar
->flags
& OPTFLAG_NO_MAC_METADATA
)
906 only_mode(bsdtar
, "--no-mac-metadata", "crux");
907 if (bsdtar
->flags
& OPTFLAG_O
) {
908 switch (bsdtar
->mode
) {
911 * In GNU tar, -o means "old format." The
912 * "ustar" format is the closest thing
913 * supported by libarchive.
915 cset_set_format(bsdtar
->cset
, "ustar");
916 /* TODO: bsdtar->create_format = "v7"; */
919 /* POSIX-compatible behavior. */
920 bsdtar
->flags
|= OPTFLAG_NO_OWNER
;
921 bsdtar
->extract_flags
&= ~ARCHIVE_EXTRACT_OWNER
;
924 only_mode(bsdtar
, "-o", "xc");
928 if (bsdtar
->flags
& OPTFLAG_STDOUT
)
929 only_mode(bsdtar
, "-O", "xt");
930 if (bsdtar
->flags
& OPTFLAG_UNLINK_FIRST
)
931 only_mode(bsdtar
, "-U", "x");
932 if (bsdtar
->flags
& OPTFLAG_WARN_LINKS
)
933 only_mode(bsdtar
, "--check-links", "cr");
935 if ((bsdtar
->flags
& OPTFLAG_AUTO_COMPRESS
) &&
936 cset_auto_compress(bsdtar
->cset
, bsdtar
->filename
)) {
937 /* Ignore specified compressions if auto-compress works. */
941 /* Check other parameters only permitted in certain modes. */
942 if (compress_program
!= NULL
) {
943 only_mode(bsdtar
, "--use-compress-program", "cxt");
944 cset_add_filter_program(bsdtar
->cset
, compress_program
);
945 /* Ignore specified compressions. */
949 if (compression
!= '\0') {
950 switch (compression
) {
951 case 'J': case 'j': case 'y': case 'Z': case 'z':
953 buff
[1] = compression
;
957 strcat(buff
, compression_name
);
960 only_mode(bsdtar
, buff
, "cxt");
961 cset_add_filter(bsdtar
->cset
, compression_name
);
963 if (compression2
!= '\0') {
965 strcat(buff
, compression2_name
);
966 only_mode(bsdtar
, buff
, "cxt");
967 cset_add_filter(bsdtar
->cset
, compression2_name
);
969 if (cset_get_format(bsdtar
->cset
) != NULL
)
970 only_mode(bsdtar
, "--format", "cru");
971 if (bsdtar
->symlink_mode
!= '\0') {
973 buff
[1] = bsdtar
->symlink_mode
;
974 only_mode(bsdtar
, buff
, "cru");
978 * When creating an archive from a directory tree, the directory
979 * walking code will already avoid entering directories when
980 * recursive inclusion of directory content is disabled, therefore
981 * changing the matching behavior has no effect for creation modes.
982 * It is relevant for extraction or listing.
984 archive_match_set_inclusion_recursion(bsdtar
->matching
,
985 !(bsdtar
->flags
& OPTFLAG_NO_SUBDIRS
));
987 /* Filename "-" implies stdio. */
988 if (strcmp(bsdtar
->filename
, "-") == 0)
989 bsdtar
->filename
= NULL
;
991 switch(bsdtar
->mode
) {
1009 archive_match_free(bsdtar
->matching
);
1010 #if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) || defined(HAVE_PCRE2POSIX_H)
1011 cleanup_substitution(bsdtar
);
1013 cset_free(bsdtar
->cset
);
1014 passphrase_free(bsdtar
->ppbuff
);
1016 if (bsdtar
->return_value
!= 0)
1018 "Error exit delayed from previous errors.");
1019 return (bsdtar
->return_value
);
1023 set_mode(struct bsdtar
*bsdtar
, char opt
)
1025 if (bsdtar
->mode
!= '\0' && bsdtar
->mode
!= opt
)
1027 "Can't specify both -%c and -%c", opt
, bsdtar
->mode
);
1032 * Verify that the mode is correct.
1035 only_mode(struct bsdtar
*bsdtar
, const char *opt
, const char *valid_modes
)
1037 if (strchr(valid_modes
, bsdtar
->mode
) == NULL
)
1039 "Option %s is not permitted in mode -%c",
1049 p
= lafe_getprogname();
1051 fprintf(stderr
, "Usage:\n");
1052 fprintf(stderr
, " List: %s -tf <archive-filename>\n", p
);
1053 fprintf(stderr
, " Extract: %s -xf <archive-filename>\n", p
);
1054 fprintf(stderr
, " Create: %s -cf <archive-filename> [filenames...]\n", p
);
1055 fprintf(stderr
, " Help: %s --help\n", p
);
1062 printf("bsdtar %s - %s \n",
1063 BSDTAR_VERSION_STRING
,
1064 archive_version_details());
1068 static const char *long_help_msg
=
1069 "First option must be a mode specifier:\n"
1070 " -c Create -r Add/Replace -t List -u Update -x Extract\n"
1072 " -b # Use # 512-byte records per I/O block\n"
1073 " -f <filename> Location of archive (default " _PATH_DEFTAPE
")\n"
1076 "Create: %p -c [options] [<file> | <dir> | @<archive> | -C <dir> ]\n"
1077 " <file>, <dir> add these items to archive\n"
1078 " -z, -j, -J, --lzma Compress archive with gzip/bzip2/xz/lzma\n"
1079 " --format {ustar|pax|cpio|shar} Select archive format\n"
1080 " --exclude <pattern> Skip files that match pattern\n"
1081 " -C <dir> Change to <dir> before processing remaining files\n"
1082 " @<archive> Add entries from <archive> to output\n"
1083 "List: %p -t [options] [<patterns>]\n"
1084 " <patterns> If specified, list only entries that match\n"
1085 "Extract: %p -x [options] [<patterns>]\n"
1086 " <patterns> If specified, extract only entries that match\n"
1087 " -k Keep (don't overwrite) existing files\n"
1088 " -m Don't restore modification times\n"
1089 " -O Write entries to stdout, don't restore to disk\n"
1090 " -p Restore permissions (including ACLs, owner, file flags)\n";
1094 * Note that the word 'bsdtar' will always appear in the first line
1097 * In particular, /bin/sh scripts that need to test for the presence
1098 * of bsdtar can use the following template:
1100 * if (tar --help 2>&1 | grep bsdtar >/dev/null 2>&1 ) then \
1101 * echo bsdtar; else echo not bsdtar; fi
1109 prog
= lafe_getprogname();
1113 p
= (strcmp(prog
,"bsdtar") != 0) ? "(bsdtar)" : "";
1114 printf("%s%s: manipulate archive files\n", prog
, p
);
1116 for (p
= long_help_msg
; *p
!= '\0'; p
++) {
1119 fputs(prog
, stdout
);