160b4ad09SPeter Avalos /*-
28029ab02SPeter Avalos * Copyright (c) 2003-2008 Tim Kientzle
360b4ad09SPeter Avalos * All rights reserved.
460b4ad09SPeter Avalos *
560b4ad09SPeter Avalos * Redistribution and use in source and binary forms, with or without
660b4ad09SPeter Avalos * modification, are permitted provided that the following conditions
760b4ad09SPeter Avalos * are met:
860b4ad09SPeter Avalos * 1. Redistributions of source code must retain the above copyright
960b4ad09SPeter Avalos * notice, this list of conditions and the following disclaimer.
1060b4ad09SPeter Avalos * 2. Redistributions in binary form must reproduce the above copyright
1160b4ad09SPeter Avalos * notice, this list of conditions and the following disclaimer in the
1260b4ad09SPeter Avalos * documentation and/or other materials provided with the distribution.
1360b4ad09SPeter Avalos *
1460b4ad09SPeter Avalos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
1560b4ad09SPeter Avalos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1660b4ad09SPeter Avalos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1760b4ad09SPeter Avalos * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
1860b4ad09SPeter Avalos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1960b4ad09SPeter Avalos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2060b4ad09SPeter Avalos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2160b4ad09SPeter Avalos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2260b4ad09SPeter Avalos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2360b4ad09SPeter Avalos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2460b4ad09SPeter Avalos */
2560b4ad09SPeter Avalos
2660b4ad09SPeter Avalos #include "bsdtar_platform.h"
278029ab02SPeter Avalos __FBSDID("$FreeBSD: src/usr.bin/tar/bsdtar.c,v 1.93 2008/11/08 04:43:24 kientzle Exp $");
2860b4ad09SPeter Avalos
2960b4ad09SPeter Avalos #ifdef HAVE_SYS_PARAM_H
3060b4ad09SPeter Avalos #include <sys/param.h>
3160b4ad09SPeter Avalos #endif
3260b4ad09SPeter Avalos #ifdef HAVE_SYS_STAT_H
3360b4ad09SPeter Avalos #include <sys/stat.h>
3460b4ad09SPeter Avalos #endif
35c09f92d2SPeter Avalos #ifdef HAVE_COPYFILE_H
36c09f92d2SPeter Avalos #include <copyfile.h>
37c09f92d2SPeter Avalos #endif
3860b4ad09SPeter Avalos #ifdef HAVE_ERRNO_H
3960b4ad09SPeter Avalos #include <errno.h>
4060b4ad09SPeter Avalos #endif
4160b4ad09SPeter Avalos #ifdef HAVE_FCNTL_H
4260b4ad09SPeter Avalos #include <fcntl.h>
4360b4ad09SPeter Avalos #endif
4460b4ad09SPeter Avalos #ifdef HAVE_LANGINFO_H
4560b4ad09SPeter Avalos #include <langinfo.h>
4660b4ad09SPeter Avalos #endif
4760b4ad09SPeter Avalos #ifdef HAVE_LOCALE_H
4860b4ad09SPeter Avalos #include <locale.h>
4960b4ad09SPeter Avalos #endif
5060b4ad09SPeter Avalos #ifdef HAVE_PATHS_H
5160b4ad09SPeter Avalos #include <paths.h>
5260b4ad09SPeter Avalos #endif
539c82a63eSPeter Avalos #ifdef HAVE_SIGNAL_H
549c82a63eSPeter Avalos #include <signal.h>
559c82a63eSPeter Avalos #endif
5660b4ad09SPeter Avalos #include <stdio.h>
5760b4ad09SPeter Avalos #ifdef HAVE_STDLIB_H
5860b4ad09SPeter Avalos #include <stdlib.h>
5960b4ad09SPeter Avalos #endif
6060b4ad09SPeter Avalos #ifdef HAVE_STRING_H
6160b4ad09SPeter Avalos #include <string.h>
6260b4ad09SPeter Avalos #endif
6360b4ad09SPeter Avalos #ifdef HAVE_TIME_H
6460b4ad09SPeter Avalos #include <time.h>
6560b4ad09SPeter Avalos #endif
6660b4ad09SPeter Avalos #ifdef HAVE_UNISTD_H
6760b4ad09SPeter Avalos #include <unistd.h>
6860b4ad09SPeter Avalos #endif
6960b4ad09SPeter Avalos
7060b4ad09SPeter Avalos #include "bsdtar.h"
719c82a63eSPeter Avalos #include "err.h"
7260b4ad09SPeter Avalos
73*50f8aa9cSAntonio Huete Jimenez #if ARCHIVE_VERSION_NUMBER < 4000000 && !defined(_PATH_DEFTAPE)
74*50f8aa9cSAntonio Huete Jimenez // Libarchive 4.0 and later will NOT define _PATH_DEFTAPE
75*50f8aa9cSAntonio Huete Jimenez // but will honor it if it's set in the build.
76*50f8aa9cSAntonio Huete Jimenez // Until then, we'll continue to set it by default on certain platforms:
77*50f8aa9cSAntonio Huete Jimenez #if defined(__linux)
7860b4ad09SPeter Avalos #define _PATH_DEFTAPE "/dev/st0"
79*50f8aa9cSAntonio Huete Jimenez #elif defined(_WIN32) && !defined(__CYGWIN__)
808029ab02SPeter Avalos #define _PATH_DEFTAPE "\\\\.\\tape0"
81*50f8aa9cSAntonio Huete Jimenez #elif !defined(__APPLE__)
8260b4ad09SPeter Avalos #define _PATH_DEFTAPE "/dev/tape"
8360b4ad09SPeter Avalos #endif
84*50f8aa9cSAntonio Huete Jimenez #endif
85*50f8aa9cSAntonio Huete Jimenez
86*50f8aa9cSAntonio Huete Jimenez #define _PATH_STDIO "-"
8760b4ad09SPeter Avalos
889c82a63eSPeter Avalos #ifdef __MINGW32__
899c82a63eSPeter Avalos int _CRT_glob = 0; /* Disable broken CRT globbing. */
909c82a63eSPeter Avalos #endif
919c82a63eSPeter Avalos
929c82a63eSPeter Avalos #if defined(HAVE_SIGACTION) && (defined(SIGINFO) || defined(SIGUSR1))
939c82a63eSPeter Avalos static volatile int siginfo_occurred;
949c82a63eSPeter Avalos
959c82a63eSPeter Avalos static void
siginfo_handler(int sig)969c82a63eSPeter Avalos siginfo_handler(int sig)
979c82a63eSPeter Avalos {
989c82a63eSPeter Avalos (void)sig; /* UNUSED */
999c82a63eSPeter Avalos siginfo_occurred = 1;
1009c82a63eSPeter Avalos }
1019c82a63eSPeter Avalos
1029c82a63eSPeter Avalos int
need_report(void)1039c82a63eSPeter Avalos need_report(void)
1049c82a63eSPeter Avalos {
1059c82a63eSPeter Avalos int r = siginfo_occurred;
1069c82a63eSPeter Avalos siginfo_occurred = 0;
1079c82a63eSPeter Avalos return (r);
1089c82a63eSPeter Avalos }
1099c82a63eSPeter Avalos #else
1109c82a63eSPeter Avalos int
need_report(void)1119c82a63eSPeter Avalos need_report(void)
1129c82a63eSPeter Avalos {
1139c82a63eSPeter Avalos return (0);
1149c82a63eSPeter Avalos }
1159c82a63eSPeter Avalos #endif
1169c82a63eSPeter Avalos
117e95abc47Szrj static void long_help(void) __LA_DEAD;
11860b4ad09SPeter Avalos static void only_mode(struct bsdtar *, const char *opt,
11960b4ad09SPeter Avalos const char *valid);
12060b4ad09SPeter Avalos static void set_mode(struct bsdtar *, char opt);
121e95abc47Szrj static void version(void) __LA_DEAD;
12260b4ad09SPeter Avalos
12360b4ad09SPeter Avalos /* A basic set of security flags to request from libarchive. */
12460b4ad09SPeter Avalos #define SECURITY \
12560b4ad09SPeter Avalos (ARCHIVE_EXTRACT_SECURE_SYMLINKS \
12660b4ad09SPeter Avalos | ARCHIVE_EXTRACT_SECURE_NODOTDOT)
12760b4ad09SPeter Avalos
128085658deSDaniel Fojt static char const * const vcs_files[] = {
129085658deSDaniel Fojt /* CVS */
130085658deSDaniel Fojt "CVS", ".cvsignore",
131085658deSDaniel Fojt /* RCS */
132085658deSDaniel Fojt "RCS",
133085658deSDaniel Fojt /* SCCS */
134085658deSDaniel Fojt "SCCS",
135085658deSDaniel Fojt /* SVN */
136085658deSDaniel Fojt ".svn",
137085658deSDaniel Fojt /* git */
138085658deSDaniel Fojt ".git", ".gitignore", ".gitattributes", ".gitmodules",
139085658deSDaniel Fojt /* Arch */
140085658deSDaniel Fojt ".arch-ids", "{arch}", "=RELEASE-ID", "=meta-update", "=update",
141085658deSDaniel Fojt /* Bazaar */
142085658deSDaniel Fojt ".bzr", ".bzrignore", ".bzrtags",
143085658deSDaniel Fojt /* Mercurial */
144085658deSDaniel Fojt ".hg", ".hgignore", ".hgtags",
145085658deSDaniel Fojt /* darcs */
146085658deSDaniel Fojt "_darcs",
147085658deSDaniel Fojt NULL
148085658deSDaniel Fojt };
149085658deSDaniel Fojt
15060b4ad09SPeter Avalos int
main(int argc,char ** argv)15160b4ad09SPeter Avalos main(int argc, char **argv)
15260b4ad09SPeter Avalos {
15360b4ad09SPeter Avalos struct bsdtar *bsdtar, bsdtar_storage;
15460b4ad09SPeter Avalos int opt, t;
155d4d8193eSPeter Avalos char compression, compression2;
156d4d8193eSPeter Avalos const char *compression_name, *compression2_name;
157d4d8193eSPeter Avalos const char *compress_program;
158085658deSDaniel Fojt char *tptr;
15960b4ad09SPeter Avalos char possible_help_request;
16060b4ad09SPeter Avalos char buff[16];
16160b4ad09SPeter Avalos
16260b4ad09SPeter Avalos /*
16360b4ad09SPeter Avalos * Use a pointer for consistency, but stack-allocated storage
16460b4ad09SPeter Avalos * for ease of cleanup.
16560b4ad09SPeter Avalos */
166c09f92d2SPeter Avalos bsdtar = &bsdtar_storage;
16760b4ad09SPeter Avalos memset(bsdtar, 0, sizeof(*bsdtar));
16860b4ad09SPeter Avalos bsdtar->fd = -1; /* Mark as "unused" */
169c09f92d2SPeter Avalos bsdtar->gid = -1;
170c09f92d2SPeter Avalos bsdtar->uid = -1;
171e95abc47Szrj bsdtar->flags = 0;
172d4d8193eSPeter Avalos compression = compression2 = '\0';
173d4d8193eSPeter Avalos compression_name = compression2_name = NULL;
174d4d8193eSPeter Avalos compress_program = NULL;
1759c82a63eSPeter Avalos
176c09f92d2SPeter Avalos #if defined(HAVE_SIGACTION)
177c09f92d2SPeter Avalos { /* Set up signal handling. */
1789c82a63eSPeter Avalos struct sigaction sa;
1799c82a63eSPeter Avalos sa.sa_handler = siginfo_handler;
1809c82a63eSPeter Avalos sigemptyset(&sa.sa_mask);
1819c82a63eSPeter Avalos sa.sa_flags = 0;
1829c82a63eSPeter Avalos #ifdef SIGINFO
1839c82a63eSPeter Avalos if (sigaction(SIGINFO, &sa, NULL))
1849c82a63eSPeter Avalos lafe_errc(1, errno, "sigaction(SIGINFO) failed");
1859c82a63eSPeter Avalos #endif
1869c82a63eSPeter Avalos #ifdef SIGUSR1
1879c82a63eSPeter Avalos /* ... and treat SIGUSR1 the same way as SIGINFO. */
1889c82a63eSPeter Avalos if (sigaction(SIGUSR1, &sa, NULL))
1899c82a63eSPeter Avalos lafe_errc(1, errno, "sigaction(SIGUSR1) failed");
1909c82a63eSPeter Avalos #endif
191c09f92d2SPeter Avalos #ifdef SIGPIPE
192c09f92d2SPeter Avalos /* Ignore SIGPIPE signals. */
193c09f92d2SPeter Avalos sa.sa_handler = SIG_IGN;
194c09f92d2SPeter Avalos sigaction(SIGPIPE, &sa, NULL);
195c09f92d2SPeter Avalos #endif
1969c82a63eSPeter Avalos }
1978029ab02SPeter Avalos #endif
19860b4ad09SPeter Avalos
1996b384f39SPeter Avalos /* Set lafe_progname before calling lafe_warnc. */
2006b384f39SPeter Avalos lafe_setprogname(*argv, "bsdtar");
20160b4ad09SPeter Avalos
2029c82a63eSPeter Avalos #if HAVE_SETLOCALE
20360b4ad09SPeter Avalos if (setlocale(LC_ALL, "") == NULL)
2049c82a63eSPeter Avalos lafe_warnc(0, "Failed to set default locale");
2059c82a63eSPeter Avalos #endif
20660b4ad09SPeter Avalos #if defined(HAVE_NL_LANGINFO) && defined(HAVE_D_MD_ORDER)
20760b4ad09SPeter Avalos bsdtar->day_first = (*nl_langinfo(D_MD_ORDER) == 'd');
20860b4ad09SPeter Avalos #endif
20960b4ad09SPeter Avalos possible_help_request = 0;
21060b4ad09SPeter Avalos
21160b4ad09SPeter Avalos /* Look up uid of current user for future reference */
21260b4ad09SPeter Avalos bsdtar->user_uid = geteuid();
21360b4ad09SPeter Avalos
21460b4ad09SPeter Avalos /* Default: open tape drive. */
21560b4ad09SPeter Avalos bsdtar->filename = getenv("TAPE");
216*50f8aa9cSAntonio Huete Jimenez #if defined(_PATH_DEFTAPE)
217*50f8aa9cSAntonio Huete Jimenez if (bsdtar->filename == NULL) {
218*50f8aa9cSAntonio Huete Jimenez #if defined(_WIN32) && !defined(__CYGWIN__)
219*50f8aa9cSAntonio Huete Jimenez int tapeExists = !_access(_PATH_DEFTAPE, 0);
220*50f8aa9cSAntonio Huete Jimenez #else
221*50f8aa9cSAntonio Huete Jimenez int tapeExists = !access(_PATH_DEFTAPE, F_OK);
222*50f8aa9cSAntonio Huete Jimenez #endif
223*50f8aa9cSAntonio Huete Jimenez if (tapeExists) {
22460b4ad09SPeter Avalos bsdtar->filename = _PATH_DEFTAPE;
225*50f8aa9cSAntonio Huete Jimenez }
226*50f8aa9cSAntonio Huete Jimenez }
227*50f8aa9cSAntonio Huete Jimenez #endif
228*50f8aa9cSAntonio Huete Jimenez if (bsdtar->filename == NULL) {
229*50f8aa9cSAntonio Huete Jimenez bsdtar->filename = _PATH_STDIO;
230*50f8aa9cSAntonio Huete Jimenez }
23160b4ad09SPeter Avalos
232c09f92d2SPeter Avalos /* Default block size settings. */
233c09f92d2SPeter Avalos bsdtar->bytes_per_block = DEFAULT_BYTES_PER_BLOCK;
234c09f92d2SPeter Avalos /* Allow library to default this unless user specifies -b. */
235c09f92d2SPeter Avalos bsdtar->bytes_in_last_block = -1;
236c09f92d2SPeter Avalos
23760b4ad09SPeter Avalos /* Default: preserve mod time on extract */
23860b4ad09SPeter Avalos bsdtar->extract_flags = ARCHIVE_EXTRACT_TIME;
23960b4ad09SPeter Avalos
24060b4ad09SPeter Avalos /* Default: Perform basic security checks. */
24160b4ad09SPeter Avalos bsdtar->extract_flags |= SECURITY;
24260b4ad09SPeter Avalos
2439c82a63eSPeter Avalos #ifndef _WIN32
2449c82a63eSPeter Avalos /* On POSIX systems, assume --same-owner and -p when run by
2459c82a63eSPeter Avalos * the root user. This doesn't make any sense on Windows. */
2469c82a63eSPeter Avalos if (bsdtar->user_uid == 0) {
24760b4ad09SPeter Avalos /* --same-owner */
24860b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER;
24960b4ad09SPeter Avalos /* -p */
25060b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM;
25160b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL;
25260b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR;
25360b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS;
254c09f92d2SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_MAC_METADATA;
25560b4ad09SPeter Avalos }
2569c82a63eSPeter Avalos #endif
25760b4ad09SPeter Avalos
258c09f92d2SPeter Avalos /*
259c09f92d2SPeter Avalos * Enable Mac OS "copyfile()" extension by default.
260c09f92d2SPeter Avalos * This has no effect on other platforms.
261c09f92d2SPeter Avalos */
26259bf7050SPeter Avalos bsdtar->readdisk_flags |= ARCHIVE_READDISK_MAC_COPYFILE;
263c09f92d2SPeter Avalos #ifdef COPYFILE_DISABLE_VAR
264c09f92d2SPeter Avalos if (getenv(COPYFILE_DISABLE_VAR))
26559bf7050SPeter Avalos bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_MAC_COPYFILE;
266c09f92d2SPeter Avalos #endif
267e95abc47Szrj #if defined(__APPLE__)
268e95abc47Szrj /*
269e95abc47Szrj * On Mac OS ACLs are archived with copyfile() (--mac-metadata)
270e95abc47Szrj * Translation to NFSv4 ACLs has to be requested explicitly with --acls
271e95abc47Szrj */
272e95abc47Szrj bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_ACL;
273e95abc47Szrj #endif
274e95abc47Szrj
27559bf7050SPeter Avalos bsdtar->matching = archive_match_new();
27659bf7050SPeter Avalos if (bsdtar->matching == NULL)
27759bf7050SPeter Avalos lafe_errc(1, errno, "Out of memory");
278d4d8193eSPeter Avalos bsdtar->cset = cset_new();
279d4d8193eSPeter Avalos if (bsdtar->cset == NULL)
280d4d8193eSPeter Avalos lafe_errc(1, errno, "Out of memory");
281c09f92d2SPeter Avalos
28260b4ad09SPeter Avalos bsdtar->argv = argv;
28360b4ad09SPeter Avalos bsdtar->argc = argc;
28460b4ad09SPeter Avalos
28560b4ad09SPeter Avalos /*
28660b4ad09SPeter Avalos * Comments following each option indicate where that option
28760b4ad09SPeter Avalos * originated: SUSv2, POSIX, GNU tar, star, etc. If there's
28860b4ad09SPeter Avalos * no such comment, then I don't know of anyone else who
28960b4ad09SPeter Avalos * implements that option.
29060b4ad09SPeter Avalos */
2918029ab02SPeter Avalos while ((opt = bsdtar_getopt(bsdtar)) != -1) {
29260b4ad09SPeter Avalos switch (opt) {
293d4d8193eSPeter Avalos case 'a': /* GNU tar */
294e95abc47Szrj bsdtar->flags |= OPTFLAG_AUTO_COMPRESS;
295e95abc47Szrj break;
296e95abc47Szrj case OPTION_ACLS: /* GNU tar */
297e95abc47Szrj bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL;
298e95abc47Szrj bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_ACL;
299e95abc47Szrj bsdtar->flags |= OPTFLAG_ACLS;
300d4d8193eSPeter Avalos break;
30160b4ad09SPeter Avalos case 'B': /* GNU tar */
30260b4ad09SPeter Avalos /* libarchive doesn't need this; just ignore it. */
30360b4ad09SPeter Avalos break;
30460b4ad09SPeter Avalos case 'b': /* SUSv2 */
305085658deSDaniel Fojt errno = 0;
306085658deSDaniel Fojt tptr = NULL;
307085658deSDaniel Fojt t = (int)strtol(bsdtar->argument, &tptr, 10);
308085658deSDaniel Fojt if (errno || t <= 0 || t > 8192 ||
309085658deSDaniel Fojt *(bsdtar->argument) == '\0' || tptr == NULL ||
310085658deSDaniel Fojt *tptr != '\0') {
311085658deSDaniel Fojt lafe_errc(1, 0, "Invalid or out of range "
312085658deSDaniel Fojt "(1..8192) argument to -b");
313085658deSDaniel Fojt }
31460b4ad09SPeter Avalos bsdtar->bytes_per_block = 512 * t;
315c09f92d2SPeter Avalos /* Explicit -b forces last block size. */
316c09f92d2SPeter Avalos bsdtar->bytes_in_last_block = bsdtar->bytes_per_block;
31760b4ad09SPeter Avalos break;
318d4d8193eSPeter Avalos case OPTION_B64ENCODE:
319d4d8193eSPeter Avalos if (compression2 != '\0')
320d4d8193eSPeter Avalos lafe_errc(1, 0,
321d4d8193eSPeter Avalos "Can't specify both --uuencode and "
322d4d8193eSPeter Avalos "--b64encode");
323d4d8193eSPeter Avalos compression2 = opt;
324d4d8193eSPeter Avalos compression2_name = "b64encode";
325d4d8193eSPeter Avalos break;
32660b4ad09SPeter Avalos case 'C': /* GNU tar */
327c09f92d2SPeter Avalos if (strlen(bsdtar->argument) == 0)
328c09f92d2SPeter Avalos lafe_errc(1, 0,
329c09f92d2SPeter Avalos "Meaningless option: -C ''");
330c09f92d2SPeter Avalos
331c09f92d2SPeter Avalos set_chdir(bsdtar, bsdtar->argument);
33260b4ad09SPeter Avalos break;
33360b4ad09SPeter Avalos case 'c': /* SUSv2 */
33460b4ad09SPeter Avalos set_mode(bsdtar, opt);
33560b4ad09SPeter Avalos break;
33660b4ad09SPeter Avalos case OPTION_CHECK_LINKS: /* GNU tar */
337e95abc47Szrj bsdtar->flags |= OPTFLAG_WARN_LINKS;
33860b4ad09SPeter Avalos break;
33960b4ad09SPeter Avalos case OPTION_CHROOT: /* NetBSD */
340e95abc47Szrj bsdtar->flags |= OPTFLAG_CHROOT;
34160b4ad09SPeter Avalos break;
3426b384f39SPeter Avalos case OPTION_CLEAR_NOCHANGE_FFLAGS:
3436b384f39SPeter Avalos bsdtar->extract_flags |=
3446b384f39SPeter Avalos ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS;
3456b384f39SPeter Avalos break;
34660b4ad09SPeter Avalos case OPTION_EXCLUDE: /* GNU tar */
34759bf7050SPeter Avalos if (archive_match_exclude_pattern(
34859bf7050SPeter Avalos bsdtar->matching, bsdtar->argument) != ARCHIVE_OK)
3499c82a63eSPeter Avalos lafe_errc(1, 0,
350c09f92d2SPeter Avalos "Couldn't exclude %s\n", bsdtar->argument);
35160b4ad09SPeter Avalos break;
352085658deSDaniel Fojt case OPTION_EXCLUDE_VCS: /* GNU tar */
353085658deSDaniel Fojt for(t=0; vcs_files[t]; t++) {
354085658deSDaniel Fojt if (archive_match_exclude_pattern(
355085658deSDaniel Fojt bsdtar->matching,
356085658deSDaniel Fojt vcs_files[t]) != ARCHIVE_OK)
357085658deSDaniel Fojt lafe_errc(1, 0, "Couldn't "
358085658deSDaniel Fojt "exclude %s\n", vcs_files[t]);
359085658deSDaniel Fojt }
360085658deSDaniel Fojt break;
361e95abc47Szrj case OPTION_FFLAGS:
362e95abc47Szrj bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS;
363e95abc47Szrj bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_FFLAGS;
364e95abc47Szrj bsdtar->flags |= OPTFLAG_FFLAGS;
365e95abc47Szrj break;
36660b4ad09SPeter Avalos case OPTION_FORMAT: /* GNU tar, others */
367d4d8193eSPeter Avalos cset_set_format(bsdtar->cset, bsdtar->argument);
36860b4ad09SPeter Avalos break;
36960b4ad09SPeter Avalos case 'f': /* SUSv2 */
370c09f92d2SPeter Avalos bsdtar->filename = bsdtar->argument;
371c09f92d2SPeter Avalos break;
372c09f92d2SPeter Avalos case OPTION_GID: /* cpio */
373085658deSDaniel Fojt errno = 0;
374085658deSDaniel Fojt tptr = NULL;
375085658deSDaniel Fojt t = (int)strtol(bsdtar->argument, &tptr, 10);
376085658deSDaniel Fojt if (errno || t < 0 || *(bsdtar->argument) == '\0' ||
377085658deSDaniel Fojt tptr == NULL || *tptr != '\0') {
378085658deSDaniel Fojt lafe_errc(1, 0, "Invalid argument to --gid");
379085658deSDaniel Fojt }
380c09f92d2SPeter Avalos bsdtar->gid = t;
381c09f92d2SPeter Avalos break;
382c09f92d2SPeter Avalos case OPTION_GNAME: /* cpio */
383c09f92d2SPeter Avalos bsdtar->gname = bsdtar->argument;
38460b4ad09SPeter Avalos break;
385d4d8193eSPeter Avalos case OPTION_GRZIP:
386d4d8193eSPeter Avalos if (compression != '\0')
387d4d8193eSPeter Avalos lafe_errc(1, 0,
388d4d8193eSPeter Avalos "Can't specify both -%c and -%c", opt,
389d4d8193eSPeter Avalos compression);
390d4d8193eSPeter Avalos compression = opt;
391d4d8193eSPeter Avalos compression_name = "grzip";
392d4d8193eSPeter Avalos break;
39360b4ad09SPeter Avalos case 'H': /* BSD convention */
39460b4ad09SPeter Avalos bsdtar->symlink_mode = 'H';
39560b4ad09SPeter Avalos break;
39660b4ad09SPeter Avalos case 'h': /* Linux Standards Base, gtar; synonym for -L */
39760b4ad09SPeter Avalos bsdtar->symlink_mode = 'L';
39860b4ad09SPeter Avalos /* Hack: -h by itself is the "help" command. */
39960b4ad09SPeter Avalos possible_help_request = 1;
40060b4ad09SPeter Avalos break;
40160b4ad09SPeter Avalos case OPTION_HELP: /* GNU tar, others */
4029c82a63eSPeter Avalos long_help();
40360b4ad09SPeter Avalos exit(0);
40460b4ad09SPeter Avalos break;
405d4d8193eSPeter Avalos case OPTION_HFS_COMPRESSION: /* Mac OS X v10.6 or later */
406d4d8193eSPeter Avalos bsdtar->extract_flags |=
407d4d8193eSPeter Avalos ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED;
408d4d8193eSPeter Avalos break;
4096b384f39SPeter Avalos case OPTION_IGNORE_ZEROS:
410e95abc47Szrj bsdtar->flags |= OPTFLAG_IGNORE_ZEROS;
4116b384f39SPeter Avalos break;
41260b4ad09SPeter Avalos case 'I': /* GNU tar */
41360b4ad09SPeter Avalos /*
41460b4ad09SPeter Avalos * TODO: Allow 'names' to come from an archive,
41560b4ad09SPeter Avalos * not just a text file. Design a good UI for
41660b4ad09SPeter Avalos * allowing names and mode/owner to be read
41760b4ad09SPeter Avalos * from an archive, with contents coming from
41860b4ad09SPeter Avalos * disk. This can be used to "refresh" an
41960b4ad09SPeter Avalos * archive or to design archives with special
42060b4ad09SPeter Avalos * permissions without having to create those
42160b4ad09SPeter Avalos * permissions on disk.
42260b4ad09SPeter Avalos */
423c09f92d2SPeter Avalos bsdtar->names_from_file = bsdtar->argument;
42460b4ad09SPeter Avalos break;
42560b4ad09SPeter Avalos case OPTION_INCLUDE:
42660b4ad09SPeter Avalos /*
42760b4ad09SPeter Avalos * No one else has the @archive extension, so
42860b4ad09SPeter Avalos * no one else needs this to filter entries
42960b4ad09SPeter Avalos * when transforming archives.
43060b4ad09SPeter Avalos */
43159bf7050SPeter Avalos if (archive_match_include_pattern(bsdtar->matching,
43259bf7050SPeter Avalos bsdtar->argument) != ARCHIVE_OK)
4339c82a63eSPeter Avalos lafe_errc(1, 0,
43460b4ad09SPeter Avalos "Failed to add %s to inclusion list",
435c09f92d2SPeter Avalos bsdtar->argument);
43660b4ad09SPeter Avalos break;
43760b4ad09SPeter Avalos case 'j': /* GNU tar */
438d4d8193eSPeter Avalos if (compression != '\0')
4399c82a63eSPeter Avalos lafe_errc(1, 0,
44060b4ad09SPeter Avalos "Can't specify both -%c and -%c", opt,
441d4d8193eSPeter Avalos compression);
442d4d8193eSPeter Avalos compression = opt;
443d4d8193eSPeter Avalos compression_name = "bzip2";
4448029ab02SPeter Avalos break;
4458029ab02SPeter Avalos case 'J': /* GNU tar 1.21 and later */
446d4d8193eSPeter Avalos if (compression != '\0')
4479c82a63eSPeter Avalos lafe_errc(1, 0,
4488029ab02SPeter Avalos "Can't specify both -%c and -%c", opt,
449d4d8193eSPeter Avalos compression);
450d4d8193eSPeter Avalos compression = opt;
451d4d8193eSPeter Avalos compression_name = "xz";
45260b4ad09SPeter Avalos break;
45360b4ad09SPeter Avalos case 'k': /* GNU tar */
45460b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE;
45560b4ad09SPeter Avalos break;
45660b4ad09SPeter Avalos case OPTION_KEEP_NEWER_FILES: /* GNU tar */
45760b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER;
45860b4ad09SPeter Avalos break;
45960b4ad09SPeter Avalos case 'L': /* BSD convention */
46060b4ad09SPeter Avalos bsdtar->symlink_mode = 'L';
46160b4ad09SPeter Avalos break;
46260b4ad09SPeter Avalos case 'l': /* SUSv2 and GNU tar beginning with 1.16 */
46360b4ad09SPeter Avalos /* GNU tar 1.13 used -l for --one-file-system */
464e95abc47Szrj bsdtar->flags |= OPTFLAG_WARN_LINKS;
46560b4ad09SPeter Avalos break;
466d4d8193eSPeter Avalos case OPTION_LRZIP:
4676b384f39SPeter Avalos case OPTION_LZ4:
468c09f92d2SPeter Avalos case OPTION_LZIP: /* GNU tar beginning with 1.23 */
469c09f92d2SPeter Avalos case OPTION_LZMA: /* GNU tar beginning with 1.20 */
470d4d8193eSPeter Avalos case OPTION_LZOP: /* GNU tar beginning with 1.21 */
471e95abc47Szrj case OPTION_ZSTD:
472d4d8193eSPeter Avalos if (compression != '\0')
4739c82a63eSPeter Avalos lafe_errc(1, 0,
4748029ab02SPeter Avalos "Can't specify both -%c and -%c", opt,
475d4d8193eSPeter Avalos compression);
476d4d8193eSPeter Avalos compression = opt;
477d4d8193eSPeter Avalos switch (opt) {
478d4d8193eSPeter Avalos case OPTION_LRZIP: compression_name = "lrzip"; break;
4796b384f39SPeter Avalos case OPTION_LZ4: compression_name = "lz4"; break;
480d4d8193eSPeter Avalos case OPTION_LZIP: compression_name = "lzip"; break;
481d4d8193eSPeter Avalos case OPTION_LZMA: compression_name = "lzma"; break;
482d4d8193eSPeter Avalos case OPTION_LZOP: compression_name = "lzop"; break;
483e95abc47Szrj case OPTION_ZSTD: compression_name = "zstd"; break;
484d4d8193eSPeter Avalos }
4858029ab02SPeter Avalos break;
48660b4ad09SPeter Avalos case 'm': /* SUSv2 */
48760b4ad09SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_TIME;
48860b4ad09SPeter Avalos break;
489e95abc47Szrj case OPTION_MAC_METADATA: /* Mac OS X */
490e95abc47Szrj bsdtar->readdisk_flags |= ARCHIVE_READDISK_MAC_COPYFILE;
491e95abc47Szrj bsdtar->extract_flags |= ARCHIVE_EXTRACT_MAC_METADATA;
492e95abc47Szrj bsdtar->flags |= OPTFLAG_MAC_METADATA;
493e95abc47Szrj break;
49460b4ad09SPeter Avalos case 'n': /* GNU tar */
495e95abc47Szrj bsdtar->flags |= OPTFLAG_NO_SUBDIRS;
49660b4ad09SPeter Avalos break;
49760b4ad09SPeter Avalos /*
49860b4ad09SPeter Avalos * Selecting files by time:
49960b4ad09SPeter Avalos * --newer-?time='date' Only files newer than 'date'
50060b4ad09SPeter Avalos * --newer-?time-than='file' Only files newer than time
50160b4ad09SPeter Avalos * on specified file (useful for incremental backups)
50260b4ad09SPeter Avalos */
50360b4ad09SPeter Avalos case OPTION_NEWER_CTIME: /* GNU tar */
50459bf7050SPeter Avalos if (archive_match_include_date(bsdtar->matching,
50559bf7050SPeter Avalos ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER,
50659bf7050SPeter Avalos bsdtar->argument) != ARCHIVE_OK)
50759bf7050SPeter Avalos lafe_errc(1, 0, "Error : %s",
50859bf7050SPeter Avalos archive_error_string(bsdtar->matching));
50960b4ad09SPeter Avalos break;
51060b4ad09SPeter Avalos case OPTION_NEWER_CTIME_THAN:
51159bf7050SPeter Avalos if (archive_match_include_file_time(bsdtar->matching,
51259bf7050SPeter Avalos ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER,
51359bf7050SPeter Avalos bsdtar->argument) != ARCHIVE_OK)
51459bf7050SPeter Avalos lafe_errc(1, 0, "Error : %s",
51559bf7050SPeter Avalos archive_error_string(bsdtar->matching));
51660b4ad09SPeter Avalos break;
51760b4ad09SPeter Avalos case OPTION_NEWER_MTIME: /* GNU tar */
51859bf7050SPeter Avalos if (archive_match_include_date(bsdtar->matching,
51959bf7050SPeter Avalos ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER,
52059bf7050SPeter Avalos bsdtar->argument) != ARCHIVE_OK)
52159bf7050SPeter Avalos lafe_errc(1, 0, "Error : %s",
52259bf7050SPeter Avalos archive_error_string(bsdtar->matching));
52360b4ad09SPeter Avalos break;
52460b4ad09SPeter Avalos case OPTION_NEWER_MTIME_THAN:
52559bf7050SPeter Avalos if (archive_match_include_file_time(bsdtar->matching,
52659bf7050SPeter Avalos ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER,
52759bf7050SPeter Avalos bsdtar->argument) != ARCHIVE_OK)
52859bf7050SPeter Avalos lafe_errc(1, 0, "Error : %s",
52959bf7050SPeter Avalos archive_error_string(bsdtar->matching));
53060b4ad09SPeter Avalos break;
53160b4ad09SPeter Avalos case OPTION_NODUMP: /* star */
53259bf7050SPeter Avalos bsdtar->readdisk_flags |= ARCHIVE_READDISK_HONOR_NODUMP;
53360b4ad09SPeter Avalos break;
534d4d8193eSPeter Avalos case OPTION_NOPRESERVE_HFS_COMPRESSION:
535d4d8193eSPeter Avalos /* Mac OS X v10.6 or later */
536d4d8193eSPeter Avalos bsdtar->extract_flags |=
537d4d8193eSPeter Avalos ARCHIVE_EXTRACT_NO_HFS_COMPRESSION;
538d4d8193eSPeter Avalos break;
539e95abc47Szrj case OPTION_NO_ACLS: /* GNU tar */
540e95abc47Szrj bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_ACL;
541e95abc47Szrj bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_ACL;
542e95abc47Szrj bsdtar->flags |= OPTFLAG_NO_ACLS;
543e95abc47Szrj break;
544e95abc47Szrj case OPTION_NO_FFLAGS:
545e95abc47Szrj bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_FFLAGS;
546e95abc47Szrj bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_FFLAGS;
547e95abc47Szrj bsdtar->flags |= OPTFLAG_NO_FFLAGS;
548e95abc47Szrj break;
549e95abc47Szrj case OPTION_NO_MAC_METADATA: /* Mac OS X */
550e95abc47Szrj bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_MAC_COPYFILE;
551e95abc47Szrj bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_MAC_METADATA;
552e95abc47Szrj bsdtar->flags |= OPTFLAG_NO_MAC_METADATA;
553e95abc47Szrj break;
554*50f8aa9cSAntonio Huete Jimenez case OPTION_NO_READ_SPARSE:
555*50f8aa9cSAntonio Huete Jimenez bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_SPARSE;
556*50f8aa9cSAntonio Huete Jimenez bsdtar->flags |= OPTFLAG_NO_READ_SPARSE;
557*50f8aa9cSAntonio Huete Jimenez break;
558085658deSDaniel Fojt case OPTION_NO_SAFE_WRITES:
559085658deSDaniel Fojt bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_SAFE_WRITES;
560085658deSDaniel Fojt break;
56160b4ad09SPeter Avalos case OPTION_NO_SAME_OWNER: /* GNU tar */
56260b4ad09SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER;
56360b4ad09SPeter Avalos break;
56460b4ad09SPeter Avalos case OPTION_NO_SAME_PERMISSIONS: /* GNU tar */
56560b4ad09SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_PERM;
56660b4ad09SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_ACL;
56760b4ad09SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_XATTR;
56860b4ad09SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_FFLAGS;
569c09f92d2SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_MAC_METADATA;
57060b4ad09SPeter Avalos break;
571e95abc47Szrj case OPTION_NO_XATTRS: /* GNU tar */
5726b384f39SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_XATTR;
5736b384f39SPeter Avalos bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_XATTR;
574e95abc47Szrj bsdtar->flags |= OPTFLAG_NO_XATTRS;
5756b384f39SPeter Avalos break;
57660b4ad09SPeter Avalos case OPTION_NULL: /* GNU tar */
577e95abc47Szrj bsdtar->flags |= OPTFLAG_NULL;
57860b4ad09SPeter Avalos break;
57960b4ad09SPeter Avalos case OPTION_NUMERIC_OWNER: /* GNU tar */
580c09f92d2SPeter Avalos bsdtar->uname = "";
581c09f92d2SPeter Avalos bsdtar->gname = "";
582e95abc47Szrj bsdtar->flags |= OPTFLAG_NUMERIC_OWNER;
58360b4ad09SPeter Avalos break;
58460b4ad09SPeter Avalos case 'O': /* GNU tar */
585e95abc47Szrj bsdtar->flags |= OPTFLAG_STDOUT;
58660b4ad09SPeter Avalos break;
58760b4ad09SPeter Avalos case 'o': /* SUSv2 and GNU conflict here, but not fatally */
588e95abc47Szrj bsdtar->flags |= OPTFLAG_O;
58960b4ad09SPeter Avalos break;
590d4d8193eSPeter Avalos /*
591d4d8193eSPeter Avalos * Selecting files by time:
592d4d8193eSPeter Avalos * --older-?time='date' Only files older than 'date'
593d4d8193eSPeter Avalos * --older-?time-than='file' Only files older than time
594d4d8193eSPeter Avalos * on specified file
595d4d8193eSPeter Avalos */
596d4d8193eSPeter Avalos case OPTION_OLDER_CTIME:
597d4d8193eSPeter Avalos if (archive_match_include_date(bsdtar->matching,
598d4d8193eSPeter Avalos ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER,
599d4d8193eSPeter Avalos bsdtar->argument) != ARCHIVE_OK)
600d4d8193eSPeter Avalos lafe_errc(1, 0, "Error : %s",
601d4d8193eSPeter Avalos archive_error_string(bsdtar->matching));
602d4d8193eSPeter Avalos break;
603d4d8193eSPeter Avalos case OPTION_OLDER_CTIME_THAN:
604d4d8193eSPeter Avalos if (archive_match_include_file_time(bsdtar->matching,
605d4d8193eSPeter Avalos ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER,
606d4d8193eSPeter Avalos bsdtar->argument) != ARCHIVE_OK)
607d4d8193eSPeter Avalos lafe_errc(1, 0, "Error : %s",
608d4d8193eSPeter Avalos archive_error_string(bsdtar->matching));
609d4d8193eSPeter Avalos break;
610d4d8193eSPeter Avalos case OPTION_OLDER_MTIME:
611d4d8193eSPeter Avalos if (archive_match_include_date(bsdtar->matching,
612d4d8193eSPeter Avalos ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER,
613d4d8193eSPeter Avalos bsdtar->argument) != ARCHIVE_OK)
614d4d8193eSPeter Avalos lafe_errc(1, 0, "Error : %s",
615d4d8193eSPeter Avalos archive_error_string(bsdtar->matching));
616d4d8193eSPeter Avalos break;
617d4d8193eSPeter Avalos case OPTION_OLDER_MTIME_THAN:
618d4d8193eSPeter Avalos if (archive_match_include_file_time(bsdtar->matching,
619d4d8193eSPeter Avalos ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER,
620d4d8193eSPeter Avalos bsdtar->argument) != ARCHIVE_OK)
621d4d8193eSPeter Avalos lafe_errc(1, 0, "Error : %s",
622d4d8193eSPeter Avalos archive_error_string(bsdtar->matching));
623d4d8193eSPeter Avalos break;
62460b4ad09SPeter Avalos case OPTION_ONE_FILE_SYSTEM: /* GNU tar */
62559bf7050SPeter Avalos bsdtar->readdisk_flags |=
62659bf7050SPeter Avalos ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS;
62760b4ad09SPeter Avalos break;
628c09f92d2SPeter Avalos case OPTION_OPTIONS:
629c09f92d2SPeter Avalos bsdtar->option_options = bsdtar->argument;
630c09f92d2SPeter Avalos break;
63160b4ad09SPeter Avalos #if 0
63260b4ad09SPeter Avalos /*
63360b4ad09SPeter Avalos * The common BSD -P option is not necessary, since
63460b4ad09SPeter Avalos * our default is to archive symlinks, not follow
63560b4ad09SPeter Avalos * them. This is convenient, as -P conflicts with GNU
63660b4ad09SPeter Avalos * tar anyway.
63760b4ad09SPeter Avalos */
63860b4ad09SPeter Avalos case 'P': /* BSD convention */
63960b4ad09SPeter Avalos /* Default behavior, no option necessary. */
64060b4ad09SPeter Avalos break;
64160b4ad09SPeter Avalos #endif
64260b4ad09SPeter Avalos case 'P': /* GNU tar */
64360b4ad09SPeter Avalos bsdtar->extract_flags &= ~SECURITY;
644e95abc47Szrj bsdtar->flags |= OPTFLAG_ABSOLUTE_PATHS;
64560b4ad09SPeter Avalos break;
64660b4ad09SPeter Avalos case 'p': /* GNU tar, star */
64760b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM;
64860b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL;
64960b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR;
65060b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS;
651c09f92d2SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_MAC_METADATA;
65260b4ad09SPeter Avalos break;
6536b384f39SPeter Avalos case OPTION_PASSPHRASE:
6546b384f39SPeter Avalos bsdtar->passphrase = bsdtar->argument;
6556b384f39SPeter Avalos break;
65660b4ad09SPeter Avalos case OPTION_POSIX: /* GNU tar */
657d4d8193eSPeter Avalos cset_set_format(bsdtar->cset, "pax");
65860b4ad09SPeter Avalos break;
65960b4ad09SPeter Avalos case 'q': /* FreeBSD GNU tar --fast-read, NetBSD -q */
660e95abc47Szrj bsdtar->flags |= OPTFLAG_FAST_READ;
66160b4ad09SPeter Avalos break;
66260b4ad09SPeter Avalos case 'r': /* SUSv2 */
66360b4ad09SPeter Avalos set_mode(bsdtar, opt);
66460b4ad09SPeter Avalos break;
665*50f8aa9cSAntonio Huete Jimenez case OPTION_READ_SPARSE:
666*50f8aa9cSAntonio Huete Jimenez bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_SPARSE;
667*50f8aa9cSAntonio Huete Jimenez bsdtar->flags |= OPTFLAG_READ_SPARSE;
668*50f8aa9cSAntonio Huete Jimenez break;
66960b4ad09SPeter Avalos case 'S': /* NetBSD pax-as-tar */
67060b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_SPARSE;
67160b4ad09SPeter Avalos break;
67260b4ad09SPeter Avalos case 's': /* NetBSD pax-as-tar */
673d4d8193eSPeter Avalos #if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H)
674c09f92d2SPeter Avalos add_substitution(bsdtar, bsdtar->argument);
67560b4ad09SPeter Avalos #else
6769c82a63eSPeter Avalos lafe_warnc(0,
6778029ab02SPeter Avalos "-s is not supported by this version of bsdtar");
6789c82a63eSPeter Avalos usage();
67960b4ad09SPeter Avalos #endif
68060b4ad09SPeter Avalos break;
681085658deSDaniel Fojt case OPTION_SAFE_WRITES:
682085658deSDaniel Fojt bsdtar->extract_flags |= ARCHIVE_EXTRACT_SAFE_WRITES;
683085658deSDaniel Fojt break;
6848029ab02SPeter Avalos case OPTION_SAME_OWNER: /* GNU tar */
6858029ab02SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER;
6868029ab02SPeter Avalos break;
68760b4ad09SPeter Avalos case OPTION_STRIP_COMPONENTS: /* GNU tar 1.15 */
688c09f92d2SPeter Avalos errno = 0;
689085658deSDaniel Fojt tptr = NULL;
690085658deSDaniel Fojt t = (int)strtol(bsdtar->argument, &tptr, 10);
691085658deSDaniel Fojt if (errno || t < 0 || *(bsdtar->argument) == '\0' ||
692085658deSDaniel Fojt tptr == NULL || *tptr != '\0') {
693085658deSDaniel Fojt lafe_errc(1, 0, "Invalid argument to "
694085658deSDaniel Fojt "--strip-components");
695085658deSDaniel Fojt }
696085658deSDaniel Fojt bsdtar->strip_components = t;
69760b4ad09SPeter Avalos break;
69860b4ad09SPeter Avalos case 'T': /* GNU tar */
699c09f92d2SPeter Avalos bsdtar->names_from_file = bsdtar->argument;
70060b4ad09SPeter Avalos break;
70160b4ad09SPeter Avalos case 't': /* SUSv2 */
70260b4ad09SPeter Avalos set_mode(bsdtar, opt);
70360b4ad09SPeter Avalos bsdtar->verbose++;
70460b4ad09SPeter Avalos break;
70560b4ad09SPeter Avalos case OPTION_TOTALS: /* GNU tar */
706e95abc47Szrj bsdtar->flags |= OPTFLAG_TOTALS;
70760b4ad09SPeter Avalos break;
70860b4ad09SPeter Avalos case 'U': /* GNU tar */
70960b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_UNLINK;
710e95abc47Szrj bsdtar->flags |= OPTFLAG_UNLINK_FIRST;
71160b4ad09SPeter Avalos break;
71260b4ad09SPeter Avalos case 'u': /* SUSv2 */
71360b4ad09SPeter Avalos set_mode(bsdtar, opt);
71460b4ad09SPeter Avalos break;
715c09f92d2SPeter Avalos case OPTION_UID: /* cpio */
716085658deSDaniel Fojt errno = 0;
717085658deSDaniel Fojt tptr = NULL;
718085658deSDaniel Fojt t = (int)strtol(bsdtar->argument, &tptr, 10);
719085658deSDaniel Fojt if (errno || t < 0 || *(bsdtar->argument) == '\0' ||
720085658deSDaniel Fojt tptr == NULL || *tptr != '\0') {
721085658deSDaniel Fojt lafe_errc(1, 0, "Invalid argument to --uid");
722085658deSDaniel Fojt }
723c09f92d2SPeter Avalos bsdtar->uid = t;
724c09f92d2SPeter Avalos break;
725c09f92d2SPeter Avalos case OPTION_UNAME: /* cpio */
726c09f92d2SPeter Avalos bsdtar->uname = bsdtar->argument;
727c09f92d2SPeter Avalos break;
728d4d8193eSPeter Avalos case OPTION_UUENCODE:
729d4d8193eSPeter Avalos if (compression2 != '\0')
730d4d8193eSPeter Avalos lafe_errc(1, 0,
731d4d8193eSPeter Avalos "Can't specify both --uuencode and "
732d4d8193eSPeter Avalos "--b64encode");
733d4d8193eSPeter Avalos compression2 = opt;
734d4d8193eSPeter Avalos compression2_name = "uuencode";
735d4d8193eSPeter Avalos break;
73660b4ad09SPeter Avalos case 'v': /* SUSv2 */
73760b4ad09SPeter Avalos bsdtar->verbose++;
73860b4ad09SPeter Avalos break;
73960b4ad09SPeter Avalos case OPTION_VERSION: /* GNU convention */
74060b4ad09SPeter Avalos version();
74160b4ad09SPeter Avalos break;
74260b4ad09SPeter Avalos #if 0
74360b4ad09SPeter Avalos /*
74460b4ad09SPeter Avalos * The -W longopt feature is handled inside of
7458029ab02SPeter Avalos * bsdtar_getopt(), so -W is not available here.
74660b4ad09SPeter Avalos */
7478029ab02SPeter Avalos case 'W': /* Obscure GNU convention. */
74860b4ad09SPeter Avalos break;
74960b4ad09SPeter Avalos #endif
75060b4ad09SPeter Avalos case 'w': /* SUSv2 */
751e95abc47Szrj bsdtar->flags |= OPTFLAG_INTERACTIVE;
75260b4ad09SPeter Avalos break;
75360b4ad09SPeter Avalos case 'X': /* GNU tar */
75459bf7050SPeter Avalos if (archive_match_exclude_pattern_from_file(
75559bf7050SPeter Avalos bsdtar->matching, bsdtar->argument, 0)
75659bf7050SPeter Avalos != ARCHIVE_OK)
75759bf7050SPeter Avalos lafe_errc(1, 0, "Error : %s",
75859bf7050SPeter Avalos archive_error_string(bsdtar->matching));
75960b4ad09SPeter Avalos break;
76060b4ad09SPeter Avalos case 'x': /* SUSv2 */
76160b4ad09SPeter Avalos set_mode(bsdtar, opt);
76260b4ad09SPeter Avalos break;
763e95abc47Szrj case OPTION_XATTRS: /* GNU tar */
764e95abc47Szrj bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR;
765e95abc47Szrj bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_XATTR;
766e95abc47Szrj bsdtar->flags |= OPTFLAG_XATTRS;
767e95abc47Szrj break;
76860b4ad09SPeter Avalos case 'y': /* FreeBSD version of GNU tar */
769d4d8193eSPeter Avalos if (compression != '\0')
7709c82a63eSPeter Avalos lafe_errc(1, 0,
77160b4ad09SPeter Avalos "Can't specify both -%c and -%c", opt,
772d4d8193eSPeter Avalos compression);
773d4d8193eSPeter Avalos compression = opt;
774d4d8193eSPeter Avalos compression_name = "bzip2";
77560b4ad09SPeter Avalos break;
77660b4ad09SPeter Avalos case 'Z': /* GNU tar */
777d4d8193eSPeter Avalos if (compression != '\0')
7789c82a63eSPeter Avalos lafe_errc(1, 0,
77960b4ad09SPeter Avalos "Can't specify both -%c and -%c", opt,
780d4d8193eSPeter Avalos compression);
781d4d8193eSPeter Avalos compression = opt;
782d4d8193eSPeter Avalos compression_name = "compress";
78360b4ad09SPeter Avalos break;
78460b4ad09SPeter Avalos case 'z': /* GNU tar, star, many others */
785d4d8193eSPeter Avalos if (compression != '\0')
7869c82a63eSPeter Avalos lafe_errc(1, 0,
78760b4ad09SPeter Avalos "Can't specify both -%c and -%c", opt,
788d4d8193eSPeter Avalos compression);
789d4d8193eSPeter Avalos compression = opt;
790d4d8193eSPeter Avalos compression_name = "gzip";
79160b4ad09SPeter Avalos break;
79260b4ad09SPeter Avalos case OPTION_USE_COMPRESS_PROGRAM:
793d4d8193eSPeter Avalos compress_program = bsdtar->argument;
79460b4ad09SPeter Avalos break;
79560b4ad09SPeter Avalos default:
7969c82a63eSPeter Avalos usage();
79760b4ad09SPeter Avalos }
79860b4ad09SPeter Avalos }
79960b4ad09SPeter Avalos
80060b4ad09SPeter Avalos /*
80160b4ad09SPeter Avalos * Sanity-check options.
80260b4ad09SPeter Avalos */
80360b4ad09SPeter Avalos
80460b4ad09SPeter Avalos /* If no "real" mode was specified, treat -h as --help. */
80560b4ad09SPeter Avalos if ((bsdtar->mode == '\0') && possible_help_request) {
8069c82a63eSPeter Avalos long_help();
80760b4ad09SPeter Avalos exit(0);
80860b4ad09SPeter Avalos }
80960b4ad09SPeter Avalos
81060b4ad09SPeter Avalos /* Otherwise, a mode is required. */
81160b4ad09SPeter Avalos if (bsdtar->mode == '\0')
8129c82a63eSPeter Avalos lafe_errc(1, 0,
81360b4ad09SPeter Avalos "Must specify one of -c, -r, -t, -u, -x");
81460b4ad09SPeter Avalos
81560b4ad09SPeter Avalos /* Check boolean options only permitted in certain modes. */
816*50f8aa9cSAntonio Huete Jimenez if (bsdtar->flags & OPTFLAG_AUTO_COMPRESS) {
817*50f8aa9cSAntonio Huete Jimenez only_mode(bsdtar, "-a", "cx");
818*50f8aa9cSAntonio Huete Jimenez if (bsdtar->mode == 'x') {
819*50f8aa9cSAntonio Huete Jimenez bsdtar->flags &= ~OPTFLAG_AUTO_COMPRESS;
820*50f8aa9cSAntonio Huete Jimenez lafe_warnc(0,
821*50f8aa9cSAntonio Huete Jimenez "Ignoring option -a in mode -x");
822*50f8aa9cSAntonio Huete Jimenez }
823*50f8aa9cSAntonio Huete Jimenez }
82459bf7050SPeter Avalos if (bsdtar->readdisk_flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS)
82560b4ad09SPeter Avalos only_mode(bsdtar, "--one-file-system", "cru");
826e95abc47Szrj if (bsdtar->flags & OPTFLAG_FAST_READ)
82760b4ad09SPeter Avalos only_mode(bsdtar, "--fast-read", "xt");
828d4d8193eSPeter Avalos if (bsdtar->extract_flags & ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED)
829d4d8193eSPeter Avalos only_mode(bsdtar, "--hfsCompression", "x");
830d4d8193eSPeter Avalos if (bsdtar->extract_flags & ARCHIVE_EXTRACT_NO_HFS_COMPRESSION)
831d4d8193eSPeter Avalos only_mode(bsdtar, "--nopreserveHFSCompression", "x");
83259bf7050SPeter Avalos if (bsdtar->readdisk_flags & ARCHIVE_READDISK_HONOR_NODUMP)
83360b4ad09SPeter Avalos only_mode(bsdtar, "--nodump", "cru");
834e95abc47Szrj if (bsdtar->flags & OPTFLAG_ACLS)
835e95abc47Szrj only_mode(bsdtar, "--acls", "crux");
836e95abc47Szrj if (bsdtar->flags & OPTFLAG_NO_ACLS)
837e95abc47Szrj only_mode(bsdtar, "--no-acls", "crux");
838e95abc47Szrj if (bsdtar->flags & OPTFLAG_XATTRS)
839e95abc47Szrj only_mode(bsdtar, "--xattrs", "crux");
840e95abc47Szrj if (bsdtar->flags & OPTFLAG_NO_XATTRS)
841e95abc47Szrj only_mode(bsdtar, "--no-xattrs", "crux");
842e95abc47Szrj if (bsdtar->flags & OPTFLAG_FFLAGS)
843e95abc47Szrj only_mode(bsdtar, "--fflags", "crux");
844e95abc47Szrj if (bsdtar->flags & OPTFLAG_NO_FFLAGS)
845e95abc47Szrj only_mode(bsdtar, "--no-fflags", "crux");
846e95abc47Szrj if (bsdtar->flags & OPTFLAG_MAC_METADATA)
847e95abc47Szrj only_mode(bsdtar, "--mac-metadata", "crux");
848e95abc47Szrj if (bsdtar->flags & OPTFLAG_NO_MAC_METADATA)
849e95abc47Szrj only_mode(bsdtar, "--no-mac-metadata", "crux");
850e95abc47Szrj if (bsdtar->flags & OPTFLAG_O) {
85160b4ad09SPeter Avalos switch (bsdtar->mode) {
85260b4ad09SPeter Avalos case 'c':
85360b4ad09SPeter Avalos /*
85460b4ad09SPeter Avalos * In GNU tar, -o means "old format." The
85560b4ad09SPeter Avalos * "ustar" format is the closest thing
85660b4ad09SPeter Avalos * supported by libarchive.
85760b4ad09SPeter Avalos */
858d4d8193eSPeter Avalos cset_set_format(bsdtar->cset, "ustar");
85960b4ad09SPeter Avalos /* TODO: bsdtar->create_format = "v7"; */
86060b4ad09SPeter Avalos break;
86160b4ad09SPeter Avalos case 'x':
86260b4ad09SPeter Avalos /* POSIX-compatible behavior. */
863e95abc47Szrj bsdtar->flags |= OPTFLAG_NO_OWNER;
86460b4ad09SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER;
86560b4ad09SPeter Avalos break;
86660b4ad09SPeter Avalos default:
86760b4ad09SPeter Avalos only_mode(bsdtar, "-o", "xc");
86860b4ad09SPeter Avalos break;
86960b4ad09SPeter Avalos }
87060b4ad09SPeter Avalos }
871e95abc47Szrj if (bsdtar->flags & OPTFLAG_STDOUT)
87260b4ad09SPeter Avalos only_mode(bsdtar, "-O", "xt");
873e95abc47Szrj if (bsdtar->flags & OPTFLAG_UNLINK_FIRST)
87460b4ad09SPeter Avalos only_mode(bsdtar, "-U", "x");
875e95abc47Szrj if (bsdtar->flags & OPTFLAG_WARN_LINKS)
87660b4ad09SPeter Avalos only_mode(bsdtar, "--check-links", "cr");
87760b4ad09SPeter Avalos
878e95abc47Szrj if ((bsdtar->flags & OPTFLAG_AUTO_COMPRESS) &&
879e95abc47Szrj cset_auto_compress(bsdtar->cset, bsdtar->filename)) {
880d4d8193eSPeter Avalos /* Ignore specified compressions if auto-compress works. */
881d4d8193eSPeter Avalos compression = '\0';
882d4d8193eSPeter Avalos compression2 = '\0';
88360b4ad09SPeter Avalos }
884d4d8193eSPeter Avalos /* Check other parameters only permitted in certain modes. */
885d4d8193eSPeter Avalos if (compress_program != NULL) {
886d4d8193eSPeter Avalos only_mode(bsdtar, "--use-compress-program", "cxt");
887d4d8193eSPeter Avalos cset_add_filter_program(bsdtar->cset, compress_program);
888d4d8193eSPeter Avalos /* Ignore specified compressions. */
889d4d8193eSPeter Avalos compression = '\0';
890d4d8193eSPeter Avalos compression2 = '\0';
891d4d8193eSPeter Avalos }
892d4d8193eSPeter Avalos if (compression != '\0') {
893d4d8193eSPeter Avalos switch (compression) {
894d4d8193eSPeter Avalos case 'J': case 'j': case 'y': case 'Z': case 'z':
895d4d8193eSPeter Avalos strcpy(buff, "-?");
896d4d8193eSPeter Avalos buff[1] = compression;
897d4d8193eSPeter Avalos break;
898d4d8193eSPeter Avalos default:
899d4d8193eSPeter Avalos strcpy(buff, "--");
900d4d8193eSPeter Avalos strcat(buff, compression_name);
901d4d8193eSPeter Avalos break;
902d4d8193eSPeter Avalos }
903d4d8193eSPeter Avalos only_mode(bsdtar, buff, "cxt");
904d4d8193eSPeter Avalos cset_add_filter(bsdtar->cset, compression_name);
905d4d8193eSPeter Avalos }
906d4d8193eSPeter Avalos if (compression2 != '\0') {
907d4d8193eSPeter Avalos strcpy(buff, "--");
908d4d8193eSPeter Avalos strcat(buff, compression2_name);
909d4d8193eSPeter Avalos only_mode(bsdtar, buff, "cxt");
910d4d8193eSPeter Avalos cset_add_filter(bsdtar->cset, compression2_name);
911d4d8193eSPeter Avalos }
912d4d8193eSPeter Avalos if (cset_get_format(bsdtar->cset) != NULL)
91360b4ad09SPeter Avalos only_mode(bsdtar, "--format", "cru");
91460b4ad09SPeter Avalos if (bsdtar->symlink_mode != '\0') {
91560b4ad09SPeter Avalos strcpy(buff, "-?");
91660b4ad09SPeter Avalos buff[1] = bsdtar->symlink_mode;
91760b4ad09SPeter Avalos only_mode(bsdtar, buff, "cru");
91860b4ad09SPeter Avalos }
919c09f92d2SPeter Avalos
920085658deSDaniel Fojt /*
921085658deSDaniel Fojt * When creating an archive from a directory tree, the directory
922085658deSDaniel Fojt * walking code will already avoid entering directories when
923085658deSDaniel Fojt * recursive inclusion of directory content is disabled, therefore
924085658deSDaniel Fojt * changing the matching behavior has no effect for creation modes.
925085658deSDaniel Fojt * It is relevant for extraction or listing.
926085658deSDaniel Fojt */
927085658deSDaniel Fojt archive_match_set_inclusion_recursion(bsdtar->matching,
928085658deSDaniel Fojt !(bsdtar->flags & OPTFLAG_NO_SUBDIRS));
929085658deSDaniel Fojt
930c09f92d2SPeter Avalos /* Filename "-" implies stdio. */
931c09f92d2SPeter Avalos if (strcmp(bsdtar->filename, "-") == 0)
932c09f92d2SPeter Avalos bsdtar->filename = NULL;
93360b4ad09SPeter Avalos
93460b4ad09SPeter Avalos switch(bsdtar->mode) {
93560b4ad09SPeter Avalos case 'c':
93660b4ad09SPeter Avalos tar_mode_c(bsdtar);
93760b4ad09SPeter Avalos break;
93860b4ad09SPeter Avalos case 'r':
93960b4ad09SPeter Avalos tar_mode_r(bsdtar);
94060b4ad09SPeter Avalos break;
94160b4ad09SPeter Avalos case 't':
94260b4ad09SPeter Avalos tar_mode_t(bsdtar);
94360b4ad09SPeter Avalos break;
94460b4ad09SPeter Avalos case 'u':
94560b4ad09SPeter Avalos tar_mode_u(bsdtar);
94660b4ad09SPeter Avalos break;
94760b4ad09SPeter Avalos case 'x':
94860b4ad09SPeter Avalos tar_mode_x(bsdtar);
94960b4ad09SPeter Avalos break;
95060b4ad09SPeter Avalos }
95160b4ad09SPeter Avalos
95259bf7050SPeter Avalos archive_match_free(bsdtar->matching);
953d4d8193eSPeter Avalos #if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H)
95460b4ad09SPeter Avalos cleanup_substitution(bsdtar);
95560b4ad09SPeter Avalos #endif
956d4d8193eSPeter Avalos cset_free(bsdtar->cset);
9576b384f39SPeter Avalos passphrase_free(bsdtar->ppbuff);
95860b4ad09SPeter Avalos
95960b4ad09SPeter Avalos if (bsdtar->return_value != 0)
9609c82a63eSPeter Avalos lafe_warnc(0,
96160b4ad09SPeter Avalos "Error exit delayed from previous errors.");
96260b4ad09SPeter Avalos return (bsdtar->return_value);
96360b4ad09SPeter Avalos }
96460b4ad09SPeter Avalos
96560b4ad09SPeter Avalos static void
set_mode(struct bsdtar * bsdtar,char opt)96660b4ad09SPeter Avalos set_mode(struct bsdtar *bsdtar, char opt)
96760b4ad09SPeter Avalos {
96860b4ad09SPeter Avalos if (bsdtar->mode != '\0' && bsdtar->mode != opt)
9699c82a63eSPeter Avalos lafe_errc(1, 0,
97060b4ad09SPeter Avalos "Can't specify both -%c and -%c", opt, bsdtar->mode);
97160b4ad09SPeter Avalos bsdtar->mode = opt;
97260b4ad09SPeter Avalos }
97360b4ad09SPeter Avalos
97460b4ad09SPeter Avalos /*
97560b4ad09SPeter Avalos * Verify that the mode is correct.
97660b4ad09SPeter Avalos */
97760b4ad09SPeter Avalos static void
only_mode(struct bsdtar * bsdtar,const char * opt,const char * valid_modes)97860b4ad09SPeter Avalos only_mode(struct bsdtar *bsdtar, const char *opt, const char *valid_modes)
97960b4ad09SPeter Avalos {
98060b4ad09SPeter Avalos if (strchr(valid_modes, bsdtar->mode) == NULL)
9819c82a63eSPeter Avalos lafe_errc(1, 0,
98260b4ad09SPeter Avalos "Option %s is not permitted in mode -%c",
98360b4ad09SPeter Avalos opt, bsdtar->mode);
98460b4ad09SPeter Avalos }
98560b4ad09SPeter Avalos
98660b4ad09SPeter Avalos
98760b4ad09SPeter Avalos void
usage(void)9889c82a63eSPeter Avalos usage(void)
98960b4ad09SPeter Avalos {
99060b4ad09SPeter Avalos const char *p;
99160b4ad09SPeter Avalos
9926b384f39SPeter Avalos p = lafe_getprogname();
99360b4ad09SPeter Avalos
99460b4ad09SPeter Avalos fprintf(stderr, "Usage:\n");
99560b4ad09SPeter Avalos fprintf(stderr, " List: %s -tf <archive-filename>\n", p);
99660b4ad09SPeter Avalos fprintf(stderr, " Extract: %s -xf <archive-filename>\n", p);
99760b4ad09SPeter Avalos fprintf(stderr, " Create: %s -cf <archive-filename> [filenames...]\n", p);
99860b4ad09SPeter Avalos fprintf(stderr, " Help: %s --help\n", p);
99960b4ad09SPeter Avalos exit(1);
100060b4ad09SPeter Avalos }
100160b4ad09SPeter Avalos
100260b4ad09SPeter Avalos static void
version(void)100360b4ad09SPeter Avalos version(void)
100460b4ad09SPeter Avalos {
100560b4ad09SPeter Avalos printf("bsdtar %s - %s \n",
100660b4ad09SPeter Avalos BSDTAR_VERSION_STRING,
10076b384f39SPeter Avalos archive_version_details());
100860b4ad09SPeter Avalos exit(0);
100960b4ad09SPeter Avalos }
101060b4ad09SPeter Avalos
101160b4ad09SPeter Avalos static const char *long_help_msg =
101260b4ad09SPeter Avalos "First option must be a mode specifier:\n"
101360b4ad09SPeter Avalos " -c Create -r Add/Replace -t List -u Update -x Extract\n"
101460b4ad09SPeter Avalos "Common Options:\n"
101560b4ad09SPeter Avalos " -b # Use # 512-byte records per I/O block\n"
101660b4ad09SPeter Avalos " -f <filename> Location of archive (default " _PATH_DEFTAPE ")\n"
101760b4ad09SPeter Avalos " -v Verbose\n"
101860b4ad09SPeter Avalos " -w Interactive\n"
101960b4ad09SPeter Avalos "Create: %p -c [options] [<file> | <dir> | @<archive> | -C <dir> ]\n"
102060b4ad09SPeter Avalos " <file>, <dir> add these items to archive\n"
10218029ab02SPeter Avalos " -z, -j, -J, --lzma Compress archive with gzip/bzip2/xz/lzma\n"
102260b4ad09SPeter Avalos " --format {ustar|pax|cpio|shar} Select archive format\n"
102360b4ad09SPeter Avalos " --exclude <pattern> Skip files that match pattern\n"
102460b4ad09SPeter Avalos " -C <dir> Change to <dir> before processing remaining files\n"
102560b4ad09SPeter Avalos " @<archive> Add entries from <archive> to output\n"
102660b4ad09SPeter Avalos "List: %p -t [options] [<patterns>]\n"
102760b4ad09SPeter Avalos " <patterns> If specified, list only entries that match\n"
102860b4ad09SPeter Avalos "Extract: %p -x [options] [<patterns>]\n"
102960b4ad09SPeter Avalos " <patterns> If specified, extract only entries that match\n"
103060b4ad09SPeter Avalos " -k Keep (don't overwrite) existing files\n"
103160b4ad09SPeter Avalos " -m Don't restore modification times\n"
103260b4ad09SPeter Avalos " -O Write entries to stdout, don't restore to disk\n"
103360b4ad09SPeter Avalos " -p Restore permissions (including ACLs, owner, file flags)\n";
103460b4ad09SPeter Avalos
103560b4ad09SPeter Avalos
103660b4ad09SPeter Avalos /*
103760b4ad09SPeter Avalos * Note that the word 'bsdtar' will always appear in the first line
103860b4ad09SPeter Avalos * of output.
103960b4ad09SPeter Avalos *
104060b4ad09SPeter Avalos * In particular, /bin/sh scripts that need to test for the presence
104160b4ad09SPeter Avalos * of bsdtar can use the following template:
104260b4ad09SPeter Avalos *
104360b4ad09SPeter Avalos * if (tar --help 2>&1 | grep bsdtar >/dev/null 2>&1 ) then \
104460b4ad09SPeter Avalos * echo bsdtar; else echo not bsdtar; fi
104560b4ad09SPeter Avalos */
104660b4ad09SPeter Avalos static void
long_help(void)10479c82a63eSPeter Avalos long_help(void)
104860b4ad09SPeter Avalos {
104960b4ad09SPeter Avalos const char *prog;
105060b4ad09SPeter Avalos const char *p;
105160b4ad09SPeter Avalos
10526b384f39SPeter Avalos prog = lafe_getprogname();
105360b4ad09SPeter Avalos
105460b4ad09SPeter Avalos fflush(stderr);
105560b4ad09SPeter Avalos
105660b4ad09SPeter Avalos p = (strcmp(prog,"bsdtar") != 0) ? "(bsdtar)" : "";
105760b4ad09SPeter Avalos printf("%s%s: manipulate archive files\n", prog, p);
105860b4ad09SPeter Avalos
105960b4ad09SPeter Avalos for (p = long_help_msg; *p != '\0'; p++) {
106060b4ad09SPeter Avalos if (*p == '%') {
106160b4ad09SPeter Avalos if (p[1] == 'p') {
106260b4ad09SPeter Avalos fputs(prog, stdout);
106360b4ad09SPeter Avalos p++;
106460b4ad09SPeter Avalos } else
106560b4ad09SPeter Avalos putchar('%');
106660b4ad09SPeter Avalos } else
106760b4ad09SPeter Avalos putchar(*p);
106860b4ad09SPeter Avalos }
106960b4ad09SPeter Avalos version();
107060b4ad09SPeter Avalos }
1071