xref: /dragonfly/contrib/libarchive/tar/bsdtar.c (revision 50f8aa9c)
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