1caf54c4fSMartin Matuska /*- 2*bd66c1b4SMartin Matuska * SPDX-License-Identifier: BSD-2-Clause 3*bd66c1b4SMartin Matuska * 4caf54c4fSMartin Matuska * Copyright (c) 2003-2008 Tim Kientzle 5caf54c4fSMartin Matuska * All rights reserved. 6caf54c4fSMartin Matuska */ 7caf54c4fSMartin Matuska 8caf54c4fSMartin Matuska #include "bsdtar_platform.h" 9caf54c4fSMartin Matuska 10caf54c4fSMartin Matuska #ifdef HAVE_SYS_PARAM_H 11caf54c4fSMartin Matuska #include <sys/param.h> 12caf54c4fSMartin Matuska #endif 13caf54c4fSMartin Matuska #ifdef HAVE_SYS_STAT_H 14caf54c4fSMartin Matuska #include <sys/stat.h> 15caf54c4fSMartin Matuska #endif 166c95142eSMartin Matuska #ifdef HAVE_COPYFILE_H 176c95142eSMartin Matuska #include <copyfile.h> 186c95142eSMartin Matuska #endif 19caf54c4fSMartin Matuska #ifdef HAVE_ERRNO_H 20caf54c4fSMartin Matuska #include <errno.h> 21caf54c4fSMartin Matuska #endif 22caf54c4fSMartin Matuska #ifdef HAVE_FCNTL_H 23caf54c4fSMartin Matuska #include <fcntl.h> 24caf54c4fSMartin Matuska #endif 25caf54c4fSMartin Matuska #ifdef HAVE_LANGINFO_H 26caf54c4fSMartin Matuska #include <langinfo.h> 27caf54c4fSMartin Matuska #endif 28*bd66c1b4SMartin Matuska #ifdef HAVE_LIMITS_H 29*bd66c1b4SMartin Matuska #include <limits.h> 30*bd66c1b4SMartin Matuska #endif 31caf54c4fSMartin Matuska #ifdef HAVE_LOCALE_H 32caf54c4fSMartin Matuska #include <locale.h> 33caf54c4fSMartin Matuska #endif 34caf54c4fSMartin Matuska #ifdef HAVE_PATHS_H 35caf54c4fSMartin Matuska #include <paths.h> 36caf54c4fSMartin Matuska #endif 37caf54c4fSMartin Matuska #ifdef HAVE_SIGNAL_H 38caf54c4fSMartin Matuska #include <signal.h> 39caf54c4fSMartin Matuska #endif 40caf54c4fSMartin Matuska #include <stdio.h> 41caf54c4fSMartin Matuska #ifdef HAVE_STDLIB_H 42caf54c4fSMartin Matuska #include <stdlib.h> 43caf54c4fSMartin Matuska #endif 44caf54c4fSMartin Matuska #ifdef HAVE_STRING_H 45caf54c4fSMartin Matuska #include <string.h> 46caf54c4fSMartin Matuska #endif 47caf54c4fSMartin Matuska #ifdef HAVE_TIME_H 48caf54c4fSMartin Matuska #include <time.h> 49caf54c4fSMartin Matuska #endif 50caf54c4fSMartin Matuska #ifdef HAVE_UNISTD_H 51caf54c4fSMartin Matuska #include <unistd.h> 52caf54c4fSMartin Matuska #endif 53caf54c4fSMartin Matuska 54caf54c4fSMartin Matuska #include "bsdtar.h" 55caf54c4fSMartin Matuska #include "err.h" 56caf54c4fSMartin Matuska 57833a452eSMartin Matuska #if ARCHIVE_VERSION_NUMBER < 4000000 && !defined(_PATH_DEFTAPE) 58833a452eSMartin Matuska // Libarchive 4.0 and later will NOT define _PATH_DEFTAPE 59833a452eSMartin Matuska // but will honor it if it's set in the build. 60833a452eSMartin Matuska // Until then, we'll continue to set it by default on certain platforms: 61833a452eSMartin Matuska #if defined(__linux) 62caf54c4fSMartin Matuska #define _PATH_DEFTAPE "/dev/st0" 63833a452eSMartin Matuska #elif defined(_WIN32) && !defined(__CYGWIN__) 64caf54c4fSMartin Matuska #define _PATH_DEFTAPE "\\\\.\\tape0" 65833a452eSMartin Matuska #elif !defined(__APPLE__) 66caf54c4fSMartin Matuska #define _PATH_DEFTAPE "/dev/tape" 67caf54c4fSMartin Matuska #endif 68833a452eSMartin Matuska #endif 69833a452eSMartin Matuska 70833a452eSMartin Matuska #define _PATH_STDIO "-" 71caf54c4fSMartin Matuska 72caf54c4fSMartin Matuska #ifdef __MINGW32__ 73caf54c4fSMartin Matuska int _CRT_glob = 0; /* Disable broken CRT globbing. */ 74caf54c4fSMartin Matuska #endif 75caf54c4fSMartin Matuska 76caf54c4fSMartin Matuska #if defined(HAVE_SIGACTION) && (defined(SIGINFO) || defined(SIGUSR1)) 77caf54c4fSMartin Matuska static volatile int siginfo_occurred; 78caf54c4fSMartin Matuska 79caf54c4fSMartin Matuska static void 80caf54c4fSMartin Matuska siginfo_handler(int sig) 81caf54c4fSMartin Matuska { 82caf54c4fSMartin Matuska (void)sig; /* UNUSED */ 83caf54c4fSMartin Matuska siginfo_occurred = 1; 84caf54c4fSMartin Matuska } 85caf54c4fSMartin Matuska 86caf54c4fSMartin Matuska int 87caf54c4fSMartin Matuska need_report(void) 88caf54c4fSMartin Matuska { 89caf54c4fSMartin Matuska int r = siginfo_occurred; 90caf54c4fSMartin Matuska siginfo_occurred = 0; 91caf54c4fSMartin Matuska return (r); 92caf54c4fSMartin Matuska } 93caf54c4fSMartin Matuska #else 94caf54c4fSMartin Matuska int 95caf54c4fSMartin Matuska need_report(void) 96caf54c4fSMartin Matuska { 97caf54c4fSMartin Matuska return (0); 98caf54c4fSMartin Matuska } 99caf54c4fSMartin Matuska #endif 100caf54c4fSMartin Matuska 101b9128a37SMartin Matuska static __LA_NORETURN void long_help(void); 102caf54c4fSMartin Matuska static void only_mode(struct bsdtar *, const char *opt, 103caf54c4fSMartin Matuska const char *valid); 104caf54c4fSMartin Matuska static void set_mode(struct bsdtar *, char opt); 105b9128a37SMartin Matuska static __LA_NORETURN void version(void); 106caf54c4fSMartin Matuska 107caf54c4fSMartin Matuska /* A basic set of security flags to request from libarchive. */ 108caf54c4fSMartin Matuska #define SECURITY \ 109caf54c4fSMartin Matuska (ARCHIVE_EXTRACT_SECURE_SYMLINKS \ 110caf54c4fSMartin Matuska | ARCHIVE_EXTRACT_SECURE_NODOTDOT) 111caf54c4fSMartin Matuska 11252c2bb75SMartin Matuska static char const * const vcs_files[] = { 11352c2bb75SMartin Matuska /* CVS */ 11452c2bb75SMartin Matuska "CVS", ".cvsignore", 11552c2bb75SMartin Matuska /* RCS */ 11652c2bb75SMartin Matuska "RCS", 11752c2bb75SMartin Matuska /* SCCS */ 11852c2bb75SMartin Matuska "SCCS", 11952c2bb75SMartin Matuska /* SVN */ 12052c2bb75SMartin Matuska ".svn", 12152c2bb75SMartin Matuska /* git */ 12252c2bb75SMartin Matuska ".git", ".gitignore", ".gitattributes", ".gitmodules", 12352c2bb75SMartin Matuska /* Arch */ 12452c2bb75SMartin Matuska ".arch-ids", "{arch}", "=RELEASE-ID", "=meta-update", "=update", 12552c2bb75SMartin Matuska /* Bazaar */ 12652c2bb75SMartin Matuska ".bzr", ".bzrignore", ".bzrtags", 12752c2bb75SMartin Matuska /* Mercurial */ 12852c2bb75SMartin Matuska ".hg", ".hgignore", ".hgtags", 12952c2bb75SMartin Matuska /* darcs */ 13052c2bb75SMartin Matuska "_darcs", 13152c2bb75SMartin Matuska NULL 13252c2bb75SMartin Matuska }; 13352c2bb75SMartin Matuska 134caf54c4fSMartin Matuska int 135caf54c4fSMartin Matuska main(int argc, char **argv) 136caf54c4fSMartin Matuska { 137caf54c4fSMartin Matuska struct bsdtar *bsdtar, bsdtar_storage; 138caf54c4fSMartin Matuska int opt, t; 139acc60b03SMartin Matuska char compression, compression2; 140acc60b03SMartin Matuska const char *compression_name, *compression2_name; 141acc60b03SMartin Matuska const char *compress_program; 142b9128a37SMartin Matuska char *tptr, *uptr; 143caf54c4fSMartin Matuska char possible_help_request; 144caf54c4fSMartin Matuska char buff[16]; 14513d826ffSMartin Matuska long l; 146caf54c4fSMartin Matuska 147caf54c4fSMartin Matuska /* 148caf54c4fSMartin Matuska * Use a pointer for consistency, but stack-allocated storage 149caf54c4fSMartin Matuska * for ease of cleanup. 150caf54c4fSMartin Matuska */ 1516c95142eSMartin Matuska bsdtar = &bsdtar_storage; 152caf54c4fSMartin Matuska memset(bsdtar, 0, sizeof(*bsdtar)); 153caf54c4fSMartin Matuska bsdtar->fd = -1; /* Mark as "unused" */ 154caf54c4fSMartin Matuska bsdtar->gid = -1; 155caf54c4fSMartin Matuska bsdtar->uid = -1; 15664287048SMartin Matuska bsdtar->flags = 0; 157acc60b03SMartin Matuska compression = compression2 = '\0'; 158acc60b03SMartin Matuska compression_name = compression2_name = NULL; 159acc60b03SMartin Matuska compress_program = NULL; 160caf54c4fSMartin Matuska 1616c95142eSMartin Matuska #if defined(HAVE_SIGACTION) 1626c95142eSMartin Matuska { /* Set up signal handling. */ 163caf54c4fSMartin Matuska struct sigaction sa; 164caf54c4fSMartin Matuska sa.sa_handler = siginfo_handler; 165caf54c4fSMartin Matuska sigemptyset(&sa.sa_mask); 166caf54c4fSMartin Matuska sa.sa_flags = 0; 167caf54c4fSMartin Matuska #ifdef SIGINFO 168caf54c4fSMartin Matuska if (sigaction(SIGINFO, &sa, NULL)) 169caf54c4fSMartin Matuska lafe_errc(1, errno, "sigaction(SIGINFO) failed"); 170caf54c4fSMartin Matuska #endif 171caf54c4fSMartin Matuska #ifdef SIGUSR1 172caf54c4fSMartin Matuska /* ... and treat SIGUSR1 the same way as SIGINFO. */ 173caf54c4fSMartin Matuska if (sigaction(SIGUSR1, &sa, NULL)) 174caf54c4fSMartin Matuska lafe_errc(1, errno, "sigaction(SIGUSR1) failed"); 175caf54c4fSMartin Matuska #endif 1766c95142eSMartin Matuska #ifdef SIGPIPE 1776c95142eSMartin Matuska /* Ignore SIGPIPE signals. */ 1786c95142eSMartin Matuska sa.sa_handler = SIG_IGN; 1796c95142eSMartin Matuska sigaction(SIGPIPE, &sa, NULL); 1806c95142eSMartin Matuska #endif 181caf54c4fSMartin Matuska } 182caf54c4fSMartin Matuska #endif 183caf54c4fSMartin Matuska 184cdf63a70SMartin Matuska /* Set lafe_progname before calling lafe_warnc. */ 185cdf63a70SMartin Matuska lafe_setprogname(*argv, "bsdtar"); 186caf54c4fSMartin Matuska 187caf54c4fSMartin Matuska #if HAVE_SETLOCALE 188caf54c4fSMartin Matuska if (setlocale(LC_ALL, "") == NULL) 189caf54c4fSMartin Matuska lafe_warnc(0, "Failed to set default locale"); 190caf54c4fSMartin Matuska #endif 191caf54c4fSMartin Matuska #if defined(HAVE_NL_LANGINFO) && defined(HAVE_D_MD_ORDER) 192caf54c4fSMartin Matuska bsdtar->day_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 193caf54c4fSMartin Matuska #endif 194caf54c4fSMartin Matuska possible_help_request = 0; 195caf54c4fSMartin Matuska 196caf54c4fSMartin Matuska /* Look up uid of current user for future reference */ 197caf54c4fSMartin Matuska bsdtar->user_uid = geteuid(); 198caf54c4fSMartin Matuska 199caf54c4fSMartin Matuska /* Default: open tape drive. */ 200caf54c4fSMartin Matuska bsdtar->filename = getenv("TAPE"); 201833a452eSMartin Matuska #if defined(_PATH_DEFTAPE) 202833a452eSMartin Matuska if (bsdtar->filename == NULL) { 203833a452eSMartin Matuska #if defined(_WIN32) && !defined(__CYGWIN__) 204833a452eSMartin Matuska int tapeExists = !_access(_PATH_DEFTAPE, 0); 205833a452eSMartin Matuska #else 206833a452eSMartin Matuska int tapeExists = !access(_PATH_DEFTAPE, F_OK); 207833a452eSMartin Matuska #endif 208833a452eSMartin Matuska if (tapeExists) { 209caf54c4fSMartin Matuska bsdtar->filename = _PATH_DEFTAPE; 210833a452eSMartin Matuska } 211833a452eSMartin Matuska } 212833a452eSMartin Matuska #endif 213833a452eSMartin Matuska if (bsdtar->filename == NULL) { 214833a452eSMartin Matuska bsdtar->filename = _PATH_STDIO; 215833a452eSMartin Matuska } 216caf54c4fSMartin Matuska 2176c95142eSMartin Matuska /* Default block size settings. */ 2186c95142eSMartin Matuska bsdtar->bytes_per_block = DEFAULT_BYTES_PER_BLOCK; 2196c95142eSMartin Matuska /* Allow library to default this unless user specifies -b. */ 2206c95142eSMartin Matuska bsdtar->bytes_in_last_block = -1; 2216c95142eSMartin Matuska 222caf54c4fSMartin Matuska /* Default: preserve mod time on extract */ 223caf54c4fSMartin Matuska bsdtar->extract_flags = ARCHIVE_EXTRACT_TIME; 224caf54c4fSMartin Matuska 225caf54c4fSMartin Matuska /* Default: Perform basic security checks. */ 226caf54c4fSMartin Matuska bsdtar->extract_flags |= SECURITY; 227caf54c4fSMartin Matuska 228caf54c4fSMartin Matuska #ifndef _WIN32 229caf54c4fSMartin Matuska /* On POSIX systems, assume --same-owner and -p when run by 230caf54c4fSMartin Matuska * the root user. This doesn't make any sense on Windows. */ 231caf54c4fSMartin Matuska if (bsdtar->user_uid == 0) { 232caf54c4fSMartin Matuska /* --same-owner */ 233caf54c4fSMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER; 234caf54c4fSMartin Matuska /* -p */ 235caf54c4fSMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM; 236caf54c4fSMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL; 237caf54c4fSMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR; 238caf54c4fSMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; 2396c95142eSMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_MAC_METADATA; 240caf54c4fSMartin Matuska } 241caf54c4fSMartin Matuska #endif 242caf54c4fSMartin Matuska 2436c95142eSMartin Matuska /* 2446c95142eSMartin Matuska * Enable Mac OS "copyfile()" extension by default. 2456c95142eSMartin Matuska * This has no effect on other platforms. 2466c95142eSMartin Matuska */ 247fd082e96SMartin Matuska bsdtar->readdisk_flags |= ARCHIVE_READDISK_MAC_COPYFILE; 2486c95142eSMartin Matuska #ifdef COPYFILE_DISABLE_VAR 2496c95142eSMartin Matuska if (getenv(COPYFILE_DISABLE_VAR)) 250fd082e96SMartin Matuska bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_MAC_COPYFILE; 2516c95142eSMartin Matuska #endif 25264287048SMartin Matuska #if defined(__APPLE__) 25364287048SMartin Matuska /* 25464287048SMartin Matuska * On Mac OS ACLs are archived with copyfile() (--mac-metadata) 25564287048SMartin Matuska * Translation to NFSv4 ACLs has to be requested explicitly with --acls 25664287048SMartin Matuska */ 25764287048SMartin Matuska bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_ACL; 25864287048SMartin Matuska #endif 25964287048SMartin Matuska 260fd082e96SMartin Matuska bsdtar->matching = archive_match_new(); 261fd082e96SMartin Matuska if (bsdtar->matching == NULL) 262fd082e96SMartin Matuska lafe_errc(1, errno, "Out of memory"); 263acc60b03SMartin Matuska bsdtar->cset = cset_new(); 264acc60b03SMartin Matuska if (bsdtar->cset == NULL) 265acc60b03SMartin Matuska lafe_errc(1, errno, "Out of memory"); 2666c95142eSMartin Matuska 267caf54c4fSMartin Matuska bsdtar->argv = argv; 268caf54c4fSMartin Matuska bsdtar->argc = argc; 269caf54c4fSMartin Matuska 270caf54c4fSMartin Matuska /* 271caf54c4fSMartin Matuska * Comments following each option indicate where that option 272caf54c4fSMartin Matuska * originated: SUSv2, POSIX, GNU tar, star, etc. If there's 273caf54c4fSMartin Matuska * no such comment, then I don't know of anyone else who 274caf54c4fSMartin Matuska * implements that option. 275caf54c4fSMartin Matuska */ 276caf54c4fSMartin Matuska while ((opt = bsdtar_getopt(bsdtar)) != -1) { 277caf54c4fSMartin Matuska switch (opt) { 278acc60b03SMartin Matuska case 'a': /* GNU tar */ 27964287048SMartin Matuska bsdtar->flags |= OPTFLAG_AUTO_COMPRESS; 28064287048SMartin Matuska break; 28164287048SMartin Matuska case OPTION_ACLS: /* GNU tar */ 28264287048SMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL; 28364287048SMartin Matuska bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_ACL; 28464287048SMartin Matuska bsdtar->flags |= OPTFLAG_ACLS; 285acc60b03SMartin Matuska break; 286caf54c4fSMartin Matuska case 'B': /* GNU tar */ 287caf54c4fSMartin Matuska /* libarchive doesn't need this; just ignore it. */ 288caf54c4fSMartin Matuska break; 289caf54c4fSMartin Matuska case 'b': /* SUSv2 */ 290b1c91e4bSMartin Matuska tptr = NULL; 29113d826ffSMartin Matuska l = strtol(bsdtar->argument, &tptr, 10); 29213d826ffSMartin Matuska if (l <= 0 || l > 8192L || 293b1c91e4bSMartin Matuska *(bsdtar->argument) == '\0' || tptr == NULL || 294b1c91e4bSMartin Matuska *tptr != '\0') { 295b1c91e4bSMartin Matuska lafe_errc(1, 0, "Invalid or out of range " 296b1c91e4bSMartin Matuska "(1..8192) argument to -b"); 297b1c91e4bSMartin Matuska } 29813d826ffSMartin Matuska bsdtar->bytes_per_block = 512 * (int)l; 2996c95142eSMartin Matuska /* Explicit -b forces last block size. */ 3006c95142eSMartin Matuska bsdtar->bytes_in_last_block = bsdtar->bytes_per_block; 301caf54c4fSMartin Matuska break; 302acc60b03SMartin Matuska case OPTION_B64ENCODE: 303acc60b03SMartin Matuska if (compression2 != '\0') 304acc60b03SMartin Matuska lafe_errc(1, 0, 305acc60b03SMartin Matuska "Can't specify both --uuencode and " 306acc60b03SMartin Matuska "--b64encode"); 307acc60b03SMartin Matuska compression2 = opt; 308acc60b03SMartin Matuska compression2_name = "b64encode"; 309acc60b03SMartin Matuska break; 310caf54c4fSMartin Matuska case 'C': /* GNU tar */ 3116c95142eSMartin Matuska if (strlen(bsdtar->argument) == 0) 3126c95142eSMartin Matuska lafe_errc(1, 0, 3136c95142eSMartin Matuska "Meaningless option: -C ''"); 3146c95142eSMartin Matuska 3156c95142eSMartin Matuska set_chdir(bsdtar, bsdtar->argument); 316caf54c4fSMartin Matuska break; 317caf54c4fSMartin Matuska case 'c': /* SUSv2 */ 318caf54c4fSMartin Matuska set_mode(bsdtar, opt); 319caf54c4fSMartin Matuska break; 320caf54c4fSMartin Matuska case OPTION_CHECK_LINKS: /* GNU tar */ 32164287048SMartin Matuska bsdtar->flags |= OPTFLAG_WARN_LINKS; 322caf54c4fSMartin Matuska break; 323caf54c4fSMartin Matuska case OPTION_CHROOT: /* NetBSD */ 32464287048SMartin Matuska bsdtar->flags |= OPTFLAG_CHROOT; 325caf54c4fSMartin Matuska break; 326cdf63a70SMartin Matuska case OPTION_CLEAR_NOCHANGE_FFLAGS: 327cdf63a70SMartin Matuska bsdtar->extract_flags |= 328cdf63a70SMartin Matuska ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS; 329cdf63a70SMartin Matuska break; 330caf54c4fSMartin Matuska case OPTION_EXCLUDE: /* GNU tar */ 331fd082e96SMartin Matuska if (archive_match_exclude_pattern( 332fd082e96SMartin Matuska bsdtar->matching, bsdtar->argument) != ARCHIVE_OK) 333caf54c4fSMartin Matuska lafe_errc(1, 0, 3346c95142eSMartin Matuska "Couldn't exclude %s\n", bsdtar->argument); 335caf54c4fSMartin Matuska break; 33652c2bb75SMartin Matuska case OPTION_EXCLUDE_VCS: /* GNU tar */ 33752c2bb75SMartin Matuska for(t=0; vcs_files[t]; t++) { 33852c2bb75SMartin Matuska if (archive_match_exclude_pattern( 33952c2bb75SMartin Matuska bsdtar->matching, 34052c2bb75SMartin Matuska vcs_files[t]) != ARCHIVE_OK) 34152c2bb75SMartin Matuska lafe_errc(1, 0, "Couldn't " 34252c2bb75SMartin Matuska "exclude %s\n", vcs_files[t]); 34352c2bb75SMartin Matuska } 34452c2bb75SMartin Matuska break; 34564287048SMartin Matuska case OPTION_FFLAGS: 34664287048SMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; 34764287048SMartin Matuska bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_FFLAGS; 34864287048SMartin Matuska bsdtar->flags |= OPTFLAG_FFLAGS; 34964287048SMartin Matuska break; 350caf54c4fSMartin Matuska case OPTION_FORMAT: /* GNU tar, others */ 351acc60b03SMartin Matuska cset_set_format(bsdtar->cset, bsdtar->argument); 352caf54c4fSMartin Matuska break; 353caf54c4fSMartin Matuska case 'f': /* SUSv2 */ 3546c95142eSMartin Matuska bsdtar->filename = bsdtar->argument; 355caf54c4fSMartin Matuska break; 356caf54c4fSMartin Matuska case OPTION_GID: /* cpio */ 357b1c91e4bSMartin Matuska tptr = NULL; 35813d826ffSMartin Matuska l = strtol(bsdtar->argument, &tptr, 10); 35913d826ffSMartin Matuska if (l < 0 || l >= INT_MAX || *(bsdtar->argument) == '\0' || 360b1c91e4bSMartin Matuska tptr == NULL || *tptr != '\0') { 361b1c91e4bSMartin Matuska lafe_errc(1, 0, "Invalid argument to --gid"); 362b1c91e4bSMartin Matuska } 36313d826ffSMartin Matuska bsdtar->gid = (int)l; 364caf54c4fSMartin Matuska break; 365caf54c4fSMartin Matuska case OPTION_GNAME: /* cpio */ 3666c95142eSMartin Matuska bsdtar->gname = bsdtar->argument; 367caf54c4fSMartin Matuska break; 368b9128a37SMartin Matuska case OPTION_GROUP: /* GNU tar */ 369b9128a37SMartin Matuska tptr = NULL; 370b9128a37SMartin Matuska 371b9128a37SMartin Matuska uptr = strchr(bsdtar->argument, ':'); 372b9128a37SMartin Matuska if (uptr != NULL) { 37313d826ffSMartin Matuska if (uptr[1] == '\0') { 374b9128a37SMartin Matuska lafe_errc(1, 0, "Invalid argument to --group (missing id after :)"); 375b9128a37SMartin Matuska } 376b9128a37SMartin Matuska uptr[0] = 0; 377b9128a37SMartin Matuska uptr++; 37813d826ffSMartin Matuska l = strtol(uptr, &tptr, 10); 37913d826ffSMartin Matuska if (l < 0 || l >= INT_MAX || *uptr == '\0' || 380b9128a37SMartin Matuska tptr == NULL || *tptr != '\0') { 381b9128a37SMartin Matuska lafe_errc(1, 0, "Invalid argument to --group (%s is not a number)", uptr); 382b9128a37SMartin Matuska } else { 38313d826ffSMartin Matuska bsdtar->gid = (int)l; 384b9128a37SMartin Matuska } 385b9128a37SMartin Matuska bsdtar->gname = bsdtar->argument; 386b9128a37SMartin Matuska } else { 38713d826ffSMartin Matuska l = strtol(bsdtar->argument, &tptr, 10); 38813d826ffSMartin Matuska if (l < 0 || l >= INT_MAX || *(bsdtar->argument) == '\0' || 389b9128a37SMartin Matuska tptr == NULL || *tptr != '\0') { 390b9128a37SMartin Matuska bsdtar->gname = bsdtar->argument; 391b9128a37SMartin Matuska } else { 39213d826ffSMartin Matuska bsdtar->gid = (int)l; 393b9128a37SMartin Matuska bsdtar->gname = ""; 394b9128a37SMartin Matuska } 395b9128a37SMartin Matuska } 396b9128a37SMartin Matuska break; 397acc60b03SMartin Matuska case OPTION_GRZIP: 398acc60b03SMartin Matuska if (compression != '\0') 399acc60b03SMartin Matuska lafe_errc(1, 0, 400acc60b03SMartin Matuska "Can't specify both -%c and -%c", opt, 401acc60b03SMartin Matuska compression); 402acc60b03SMartin Matuska compression = opt; 403acc60b03SMartin Matuska compression_name = "grzip"; 404acc60b03SMartin Matuska break; 405caf54c4fSMartin Matuska case 'H': /* BSD convention */ 406caf54c4fSMartin Matuska bsdtar->symlink_mode = 'H'; 407caf54c4fSMartin Matuska break; 408caf54c4fSMartin Matuska case 'h': /* Linux Standards Base, gtar; synonym for -L */ 409caf54c4fSMartin Matuska bsdtar->symlink_mode = 'L'; 410caf54c4fSMartin Matuska /* Hack: -h by itself is the "help" command. */ 411caf54c4fSMartin Matuska possible_help_request = 1; 412caf54c4fSMartin Matuska break; 413caf54c4fSMartin Matuska case OPTION_HELP: /* GNU tar, others */ 414caf54c4fSMartin Matuska long_help(); 415b9128a37SMartin Matuska /* NOTREACHED*/ 416acc60b03SMartin Matuska case OPTION_HFS_COMPRESSION: /* Mac OS X v10.6 or later */ 417acc60b03SMartin Matuska bsdtar->extract_flags |= 418acc60b03SMartin Matuska ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED; 419acc60b03SMartin Matuska break; 420cdf63a70SMartin Matuska case OPTION_IGNORE_ZEROS: 42164287048SMartin Matuska bsdtar->flags |= OPTFLAG_IGNORE_ZEROS; 422cdf63a70SMartin Matuska break; 423caf54c4fSMartin Matuska case 'I': /* GNU tar */ 424caf54c4fSMartin Matuska /* 425caf54c4fSMartin Matuska * TODO: Allow 'names' to come from an archive, 426caf54c4fSMartin Matuska * not just a text file. Design a good UI for 427caf54c4fSMartin Matuska * allowing names and mode/owner to be read 428caf54c4fSMartin Matuska * from an archive, with contents coming from 429caf54c4fSMartin Matuska * disk. This can be used to "refresh" an 430caf54c4fSMartin Matuska * archive or to design archives with special 431caf54c4fSMartin Matuska * permissions without having to create those 432caf54c4fSMartin Matuska * permissions on disk. 433caf54c4fSMartin Matuska */ 4346c95142eSMartin Matuska bsdtar->names_from_file = bsdtar->argument; 435caf54c4fSMartin Matuska break; 436caf54c4fSMartin Matuska case OPTION_INCLUDE: 437caf54c4fSMartin Matuska /* 438caf54c4fSMartin Matuska * No one else has the @archive extension, so 439caf54c4fSMartin Matuska * no one else needs this to filter entries 440caf54c4fSMartin Matuska * when transforming archives. 441caf54c4fSMartin Matuska */ 442fd082e96SMartin Matuska if (archive_match_include_pattern(bsdtar->matching, 443fd082e96SMartin Matuska bsdtar->argument) != ARCHIVE_OK) 444caf54c4fSMartin Matuska lafe_errc(1, 0, 445caf54c4fSMartin Matuska "Failed to add %s to inclusion list", 4466c95142eSMartin Matuska bsdtar->argument); 447caf54c4fSMartin Matuska break; 448caf54c4fSMartin Matuska case 'j': /* GNU tar */ 449acc60b03SMartin Matuska if (compression != '\0') 450caf54c4fSMartin Matuska lafe_errc(1, 0, 451caf54c4fSMartin Matuska "Can't specify both -%c and -%c", opt, 452acc60b03SMartin Matuska compression); 453acc60b03SMartin Matuska compression = opt; 454acc60b03SMartin Matuska compression_name = "bzip2"; 455caf54c4fSMartin Matuska break; 456caf54c4fSMartin Matuska case 'J': /* GNU tar 1.21 and later */ 457acc60b03SMartin Matuska if (compression != '\0') 458caf54c4fSMartin Matuska lafe_errc(1, 0, 459caf54c4fSMartin Matuska "Can't specify both -%c and -%c", opt, 460acc60b03SMartin Matuska compression); 461acc60b03SMartin Matuska compression = opt; 462acc60b03SMartin Matuska compression_name = "xz"; 463caf54c4fSMartin Matuska break; 464caf54c4fSMartin Matuska case 'k': /* GNU tar */ 465caf54c4fSMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE; 466caf54c4fSMartin Matuska break; 467caf54c4fSMartin Matuska case OPTION_KEEP_NEWER_FILES: /* GNU tar */ 468caf54c4fSMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER; 469caf54c4fSMartin Matuska break; 470caf54c4fSMartin Matuska case 'L': /* BSD convention */ 471caf54c4fSMartin Matuska bsdtar->symlink_mode = 'L'; 472caf54c4fSMartin Matuska break; 473caf54c4fSMartin Matuska case 'l': /* SUSv2 and GNU tar beginning with 1.16 */ 474caf54c4fSMartin Matuska /* GNU tar 1.13 used -l for --one-file-system */ 47564287048SMartin Matuska bsdtar->flags |= OPTFLAG_WARN_LINKS; 476caf54c4fSMartin Matuska break; 477acc60b03SMartin Matuska case OPTION_LRZIP: 478cdf63a70SMartin Matuska case OPTION_LZ4: 4796c95142eSMartin Matuska case OPTION_LZIP: /* GNU tar beginning with 1.23 */ 4806c95142eSMartin Matuska case OPTION_LZMA: /* GNU tar beginning with 1.20 */ 481acc60b03SMartin Matuska case OPTION_LZOP: /* GNU tar beginning with 1.21 */ 4825c831a5bSMartin Matuska case OPTION_ZSTD: 483acc60b03SMartin Matuska if (compression != '\0') 484caf54c4fSMartin Matuska lafe_errc(1, 0, 485caf54c4fSMartin Matuska "Can't specify both -%c and -%c", opt, 486acc60b03SMartin Matuska compression); 487acc60b03SMartin Matuska compression = opt; 488acc60b03SMartin Matuska switch (opt) { 489acc60b03SMartin Matuska case OPTION_LRZIP: compression_name = "lrzip"; break; 490cdf63a70SMartin Matuska case OPTION_LZ4: compression_name = "lz4"; break; 491acc60b03SMartin Matuska case OPTION_LZIP: compression_name = "lzip"; break; 492acc60b03SMartin Matuska case OPTION_LZMA: compression_name = "lzma"; break; 493acc60b03SMartin Matuska case OPTION_LZOP: compression_name = "lzop"; break; 4945c831a5bSMartin Matuska case OPTION_ZSTD: compression_name = "zstd"; break; 495acc60b03SMartin Matuska } 496caf54c4fSMartin Matuska break; 497caf54c4fSMartin Matuska case 'm': /* SUSv2 */ 498caf54c4fSMartin Matuska bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_TIME; 499caf54c4fSMartin Matuska break; 50064287048SMartin Matuska case OPTION_MAC_METADATA: /* Mac OS X */ 50164287048SMartin Matuska bsdtar->readdisk_flags |= ARCHIVE_READDISK_MAC_COPYFILE; 50264287048SMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_MAC_METADATA; 50364287048SMartin Matuska bsdtar->flags |= OPTFLAG_MAC_METADATA; 50464287048SMartin Matuska break; 505caf54c4fSMartin Matuska case 'n': /* GNU tar */ 50664287048SMartin Matuska bsdtar->flags |= OPTFLAG_NO_SUBDIRS; 507caf54c4fSMartin Matuska break; 508caf54c4fSMartin Matuska /* 509caf54c4fSMartin Matuska * Selecting files by time: 510caf54c4fSMartin Matuska * --newer-?time='date' Only files newer than 'date' 511caf54c4fSMartin Matuska * --newer-?time-than='file' Only files newer than time 512caf54c4fSMartin Matuska * on specified file (useful for incremental backups) 513caf54c4fSMartin Matuska */ 514caf54c4fSMartin Matuska case OPTION_NEWER_CTIME: /* GNU tar */ 515fd082e96SMartin Matuska if (archive_match_include_date(bsdtar->matching, 516fd082e96SMartin Matuska ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER, 517fd082e96SMartin Matuska bsdtar->argument) != ARCHIVE_OK) 518fd082e96SMartin Matuska lafe_errc(1, 0, "Error : %s", 519fd082e96SMartin Matuska archive_error_string(bsdtar->matching)); 520caf54c4fSMartin Matuska break; 521caf54c4fSMartin Matuska case OPTION_NEWER_CTIME_THAN: 522fd082e96SMartin Matuska if (archive_match_include_file_time(bsdtar->matching, 523fd082e96SMartin Matuska ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER, 524fd082e96SMartin Matuska bsdtar->argument) != ARCHIVE_OK) 525fd082e96SMartin Matuska lafe_errc(1, 0, "Error : %s", 526fd082e96SMartin Matuska archive_error_string(bsdtar->matching)); 527caf54c4fSMartin Matuska break; 528caf54c4fSMartin Matuska case OPTION_NEWER_MTIME: /* GNU tar */ 529fd082e96SMartin Matuska if (archive_match_include_date(bsdtar->matching, 530fd082e96SMartin Matuska ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER, 531fd082e96SMartin Matuska bsdtar->argument) != ARCHIVE_OK) 532fd082e96SMartin Matuska lafe_errc(1, 0, "Error : %s", 533fd082e96SMartin Matuska archive_error_string(bsdtar->matching)); 534caf54c4fSMartin Matuska break; 535caf54c4fSMartin Matuska case OPTION_NEWER_MTIME_THAN: 536fd082e96SMartin Matuska if (archive_match_include_file_time(bsdtar->matching, 537fd082e96SMartin Matuska ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER, 538fd082e96SMartin Matuska bsdtar->argument) != ARCHIVE_OK) 539fd082e96SMartin Matuska lafe_errc(1, 0, "Error : %s", 540fd082e96SMartin Matuska archive_error_string(bsdtar->matching)); 541caf54c4fSMartin Matuska break; 542caf54c4fSMartin Matuska case OPTION_NODUMP: /* star */ 543fd082e96SMartin Matuska bsdtar->readdisk_flags |= ARCHIVE_READDISK_HONOR_NODUMP; 544caf54c4fSMartin Matuska break; 545acc60b03SMartin Matuska case OPTION_NOPRESERVE_HFS_COMPRESSION: 546acc60b03SMartin Matuska /* Mac OS X v10.6 or later */ 547acc60b03SMartin Matuska bsdtar->extract_flags |= 548acc60b03SMartin Matuska ARCHIVE_EXTRACT_NO_HFS_COMPRESSION; 549acc60b03SMartin Matuska break; 55064287048SMartin Matuska case OPTION_NO_ACLS: /* GNU tar */ 55164287048SMartin Matuska bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_ACL; 55264287048SMartin Matuska bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_ACL; 55364287048SMartin Matuska bsdtar->flags |= OPTFLAG_NO_ACLS; 55464287048SMartin Matuska break; 55564287048SMartin Matuska case OPTION_NO_FFLAGS: 55664287048SMartin Matuska bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_FFLAGS; 55764287048SMartin Matuska bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_FFLAGS; 55864287048SMartin Matuska bsdtar->flags |= OPTFLAG_NO_FFLAGS; 55964287048SMartin Matuska break; 56064287048SMartin Matuska case OPTION_NO_MAC_METADATA: /* Mac OS X */ 56164287048SMartin Matuska bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_MAC_COPYFILE; 56264287048SMartin Matuska bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_MAC_METADATA; 56364287048SMartin Matuska bsdtar->flags |= OPTFLAG_NO_MAC_METADATA; 56464287048SMartin Matuska break; 565833a452eSMartin Matuska case OPTION_NO_READ_SPARSE: 566833a452eSMartin Matuska bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_SPARSE; 567833a452eSMartin Matuska bsdtar->flags |= OPTFLAG_NO_READ_SPARSE; 568833a452eSMartin Matuska break; 569f9762417SMartin Matuska case OPTION_NO_SAFE_WRITES: 570f9762417SMartin Matuska bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_SAFE_WRITES; 571f9762417SMartin Matuska break; 572caf54c4fSMartin Matuska case OPTION_NO_SAME_OWNER: /* GNU tar */ 573caf54c4fSMartin Matuska bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER; 574caf54c4fSMartin Matuska break; 575caf54c4fSMartin Matuska case OPTION_NO_SAME_PERMISSIONS: /* GNU tar */ 576caf54c4fSMartin Matuska bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_PERM; 577caf54c4fSMartin Matuska bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_ACL; 578caf54c4fSMartin Matuska bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_XATTR; 579caf54c4fSMartin Matuska bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_FFLAGS; 5806c95142eSMartin Matuska bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_MAC_METADATA; 581caf54c4fSMartin Matuska break; 58264287048SMartin Matuska case OPTION_NO_XATTRS: /* GNU tar */ 583cdf63a70SMartin Matuska bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_XATTR; 584cdf63a70SMartin Matuska bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_XATTR; 58564287048SMartin Matuska bsdtar->flags |= OPTFLAG_NO_XATTRS; 586cdf63a70SMartin Matuska break; 587caf54c4fSMartin Matuska case OPTION_NULL: /* GNU tar */ 58864287048SMartin Matuska bsdtar->flags |= OPTFLAG_NULL; 589caf54c4fSMartin Matuska break; 590caf54c4fSMartin Matuska case OPTION_NUMERIC_OWNER: /* GNU tar */ 591caf54c4fSMartin Matuska bsdtar->uname = ""; 592caf54c4fSMartin Matuska bsdtar->gname = ""; 59364287048SMartin Matuska bsdtar->flags |= OPTFLAG_NUMERIC_OWNER; 594caf54c4fSMartin Matuska break; 595caf54c4fSMartin Matuska case 'O': /* GNU tar */ 59664287048SMartin Matuska bsdtar->flags |= OPTFLAG_STDOUT; 597caf54c4fSMartin Matuska break; 598caf54c4fSMartin Matuska case 'o': /* SUSv2 and GNU conflict here, but not fatally */ 59964287048SMartin Matuska bsdtar->flags |= OPTFLAG_O; 600caf54c4fSMartin Matuska break; 601acc60b03SMartin Matuska /* 602acc60b03SMartin Matuska * Selecting files by time: 603acc60b03SMartin Matuska * --older-?time='date' Only files older than 'date' 604acc60b03SMartin Matuska * --older-?time-than='file' Only files older than time 605acc60b03SMartin Matuska * on specified file 606acc60b03SMartin Matuska */ 607acc60b03SMartin Matuska case OPTION_OLDER_CTIME: 608acc60b03SMartin Matuska if (archive_match_include_date(bsdtar->matching, 609acc60b03SMartin Matuska ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER, 610acc60b03SMartin Matuska bsdtar->argument) != ARCHIVE_OK) 611acc60b03SMartin Matuska lafe_errc(1, 0, "Error : %s", 612acc60b03SMartin Matuska archive_error_string(bsdtar->matching)); 613acc60b03SMartin Matuska break; 614acc60b03SMartin Matuska case OPTION_OLDER_CTIME_THAN: 615acc60b03SMartin Matuska if (archive_match_include_file_time(bsdtar->matching, 616acc60b03SMartin Matuska ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER, 617acc60b03SMartin Matuska bsdtar->argument) != ARCHIVE_OK) 618acc60b03SMartin Matuska lafe_errc(1, 0, "Error : %s", 619acc60b03SMartin Matuska archive_error_string(bsdtar->matching)); 620acc60b03SMartin Matuska break; 621acc60b03SMartin Matuska case OPTION_OLDER_MTIME: 622acc60b03SMartin Matuska if (archive_match_include_date(bsdtar->matching, 623acc60b03SMartin Matuska ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER, 624acc60b03SMartin Matuska bsdtar->argument) != ARCHIVE_OK) 625acc60b03SMartin Matuska lafe_errc(1, 0, "Error : %s", 626acc60b03SMartin Matuska archive_error_string(bsdtar->matching)); 627acc60b03SMartin Matuska break; 628acc60b03SMartin Matuska case OPTION_OLDER_MTIME_THAN: 629acc60b03SMartin Matuska if (archive_match_include_file_time(bsdtar->matching, 630acc60b03SMartin Matuska ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER, 631acc60b03SMartin Matuska bsdtar->argument) != ARCHIVE_OK) 632acc60b03SMartin Matuska lafe_errc(1, 0, "Error : %s", 633acc60b03SMartin Matuska archive_error_string(bsdtar->matching)); 634acc60b03SMartin Matuska break; 635caf54c4fSMartin Matuska case OPTION_ONE_FILE_SYSTEM: /* GNU tar */ 636fd082e96SMartin Matuska bsdtar->readdisk_flags |= 637fd082e96SMartin Matuska ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS; 638caf54c4fSMartin Matuska break; 639caf54c4fSMartin Matuska case OPTION_OPTIONS: 640b9128a37SMartin Matuska if (bsdtar->option_options != NULL) { 641b9128a37SMartin Matuska lafe_warnc(0, 642b9128a37SMartin Matuska "Ignoring previous option '%s', separate multiple options with commas", 643b9128a37SMartin Matuska bsdtar->option_options); 644b9128a37SMartin Matuska } 6456c95142eSMartin Matuska bsdtar->option_options = bsdtar->argument; 646caf54c4fSMartin Matuska break; 647b9128a37SMartin Matuska case OPTION_OWNER: /* GNU tar */ 648b9128a37SMartin Matuska tptr = NULL; 649b9128a37SMartin Matuska 650b9128a37SMartin Matuska uptr = strchr(bsdtar->argument, ':'); 651b9128a37SMartin Matuska if (uptr != NULL) { 652b9128a37SMartin Matuska if (uptr[1] == 0) { 653b9128a37SMartin Matuska lafe_errc(1, 0, "Invalid argument to --owner (missing id after :)"); 654b9128a37SMartin Matuska } 655b9128a37SMartin Matuska uptr[0] = 0; 656b9128a37SMartin Matuska uptr++; 65713d826ffSMartin Matuska l = strtol(uptr, &tptr, 10); 65813d826ffSMartin Matuska if (l < 0 || l >= INT_MAX || *uptr == '\0' || 659b9128a37SMartin Matuska tptr == NULL || *tptr != '\0') { 660b9128a37SMartin Matuska lafe_errc(1, 0, "Invalid argument to --owner (%s is not a number)", uptr); 661b9128a37SMartin Matuska } else { 66213d826ffSMartin Matuska bsdtar->uid = (int)l; 663b9128a37SMartin Matuska } 664b9128a37SMartin Matuska bsdtar->uname = bsdtar->argument; 665b9128a37SMartin Matuska } else { 66613d826ffSMartin Matuska l = strtol(bsdtar->argument, &tptr, 10); 66713d826ffSMartin Matuska if (l < 0 || l >= INT_MAX || *(bsdtar->argument) == '\0' || 668b9128a37SMartin Matuska tptr == NULL || *tptr != '\0') { 669b9128a37SMartin Matuska bsdtar->uname = bsdtar->argument; 670b9128a37SMartin Matuska } else { 67113d826ffSMartin Matuska bsdtar->uid = (int)l; 672b9128a37SMartin Matuska bsdtar->uname = ""; 673b9128a37SMartin Matuska } 674b9128a37SMartin Matuska } 675b9128a37SMartin Matuska break; 676caf54c4fSMartin Matuska #if 0 677caf54c4fSMartin Matuska /* 678caf54c4fSMartin Matuska * The common BSD -P option is not necessary, since 679caf54c4fSMartin Matuska * our default is to archive symlinks, not follow 680caf54c4fSMartin Matuska * them. This is convenient, as -P conflicts with GNU 681caf54c4fSMartin Matuska * tar anyway. 682caf54c4fSMartin Matuska */ 683caf54c4fSMartin Matuska case 'P': /* BSD convention */ 684caf54c4fSMartin Matuska /* Default behavior, no option necessary. */ 685caf54c4fSMartin Matuska break; 686caf54c4fSMartin Matuska #endif 687caf54c4fSMartin Matuska case 'P': /* GNU tar */ 688caf54c4fSMartin Matuska bsdtar->extract_flags &= ~SECURITY; 68964287048SMartin Matuska bsdtar->flags |= OPTFLAG_ABSOLUTE_PATHS; 690caf54c4fSMartin Matuska break; 691caf54c4fSMartin Matuska case 'p': /* GNU tar, star */ 692caf54c4fSMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM; 693caf54c4fSMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL; 694caf54c4fSMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR; 695caf54c4fSMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; 6966c95142eSMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_MAC_METADATA; 697caf54c4fSMartin Matuska break; 698cdf63a70SMartin Matuska case OPTION_PASSPHRASE: 699cdf63a70SMartin Matuska bsdtar->passphrase = bsdtar->argument; 700cdf63a70SMartin Matuska break; 701caf54c4fSMartin Matuska case OPTION_POSIX: /* GNU tar */ 702acc60b03SMartin Matuska cset_set_format(bsdtar->cset, "pax"); 703caf54c4fSMartin Matuska break; 704caf54c4fSMartin Matuska case 'q': /* FreeBSD GNU tar --fast-read, NetBSD -q */ 70564287048SMartin Matuska bsdtar->flags |= OPTFLAG_FAST_READ; 706caf54c4fSMartin Matuska break; 707caf54c4fSMartin Matuska case 'r': /* SUSv2 */ 708caf54c4fSMartin Matuska set_mode(bsdtar, opt); 709caf54c4fSMartin Matuska break; 710833a452eSMartin Matuska case OPTION_READ_SPARSE: 711833a452eSMartin Matuska bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_SPARSE; 712833a452eSMartin Matuska bsdtar->flags |= OPTFLAG_READ_SPARSE; 713833a452eSMartin Matuska break; 714caf54c4fSMartin Matuska case 'S': /* NetBSD pax-as-tar */ 715caf54c4fSMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_SPARSE; 716caf54c4fSMartin Matuska break; 717caf54c4fSMartin Matuska case 's': /* NetBSD pax-as-tar */ 718b9128a37SMartin Matuska #if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) || defined(HAVE_PCRE2POSIX_H) 7196c95142eSMartin Matuska add_substitution(bsdtar, bsdtar->argument); 720caf54c4fSMartin Matuska #else 721caf54c4fSMartin Matuska lafe_warnc(0, 722caf54c4fSMartin Matuska "-s is not supported by this version of bsdtar"); 723caf54c4fSMartin Matuska usage(); 724caf54c4fSMartin Matuska #endif 725caf54c4fSMartin Matuska break; 726f9762417SMartin Matuska case OPTION_SAFE_WRITES: 727f9762417SMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_SAFE_WRITES; 728f9762417SMartin Matuska break; 729caf54c4fSMartin Matuska case OPTION_SAME_OWNER: /* GNU tar */ 730caf54c4fSMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER; 731caf54c4fSMartin Matuska break; 732caf54c4fSMartin Matuska case OPTION_STRIP_COMPONENTS: /* GNU tar 1.15 */ 733b1c91e4bSMartin Matuska tptr = NULL; 73413d826ffSMartin Matuska l = strtol(bsdtar->argument, &tptr, 10); 73513d826ffSMartin Matuska if (l < 0 || l > 100000L || *(bsdtar->argument) == '\0' || 736b1c91e4bSMartin Matuska tptr == NULL || *tptr != '\0') { 737b1c91e4bSMartin Matuska lafe_errc(1, 0, "Invalid argument to " 738b1c91e4bSMartin Matuska "--strip-components"); 739b1c91e4bSMartin Matuska } 74013d826ffSMartin Matuska bsdtar->strip_components = (int)l; 741caf54c4fSMartin Matuska break; 742caf54c4fSMartin Matuska case 'T': /* GNU tar */ 7436c95142eSMartin Matuska bsdtar->names_from_file = bsdtar->argument; 744caf54c4fSMartin Matuska break; 745caf54c4fSMartin Matuska case 't': /* SUSv2 */ 746caf54c4fSMartin Matuska set_mode(bsdtar, opt); 747caf54c4fSMartin Matuska bsdtar->verbose++; 748caf54c4fSMartin Matuska break; 749caf54c4fSMartin Matuska case OPTION_TOTALS: /* GNU tar */ 75064287048SMartin Matuska bsdtar->flags |= OPTFLAG_TOTALS; 751caf54c4fSMartin Matuska break; 752caf54c4fSMartin Matuska case 'U': /* GNU tar */ 753caf54c4fSMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_UNLINK; 75464287048SMartin Matuska bsdtar->flags |= OPTFLAG_UNLINK_FIRST; 755caf54c4fSMartin Matuska break; 756caf54c4fSMartin Matuska case 'u': /* SUSv2 */ 757caf54c4fSMartin Matuska set_mode(bsdtar, opt); 758caf54c4fSMartin Matuska break; 759caf54c4fSMartin Matuska case OPTION_UID: /* cpio */ 760b1c91e4bSMartin Matuska tptr = NULL; 76113d826ffSMartin Matuska l = strtol(bsdtar->argument, &tptr, 10); 76213d826ffSMartin Matuska if (l < 0 || l >= INT_MAX || *(bsdtar->argument) == '\0' || 763b1c91e4bSMartin Matuska tptr == NULL || *tptr != '\0') { 764b1c91e4bSMartin Matuska lafe_errc(1, 0, "Invalid argument to --uid"); 765b1c91e4bSMartin Matuska } 76613d826ffSMartin Matuska bsdtar->uid = (int)l; 767caf54c4fSMartin Matuska break; 768caf54c4fSMartin Matuska case OPTION_UNAME: /* cpio */ 7696c95142eSMartin Matuska bsdtar->uname = bsdtar->argument; 770caf54c4fSMartin Matuska break; 771acc60b03SMartin Matuska case OPTION_UUENCODE: 772acc60b03SMartin Matuska if (compression2 != '\0') 773acc60b03SMartin Matuska lafe_errc(1, 0, 774acc60b03SMartin Matuska "Can't specify both --uuencode and " 775acc60b03SMartin Matuska "--b64encode"); 776acc60b03SMartin Matuska compression2 = opt; 777acc60b03SMartin Matuska compression2_name = "uuencode"; 778acc60b03SMartin Matuska break; 779caf54c4fSMartin Matuska case 'v': /* SUSv2 */ 780caf54c4fSMartin Matuska bsdtar->verbose++; 781caf54c4fSMartin Matuska break; 782caf54c4fSMartin Matuska case OPTION_VERSION: /* GNU convention */ 783caf54c4fSMartin Matuska version(); 784b9128a37SMartin Matuska /* NOTREACHED */ 785caf54c4fSMartin Matuska #if 0 786caf54c4fSMartin Matuska /* 787caf54c4fSMartin Matuska * The -W longopt feature is handled inside of 788caf54c4fSMartin Matuska * bsdtar_getopt(), so -W is not available here. 789caf54c4fSMartin Matuska */ 790caf54c4fSMartin Matuska case 'W': /* Obscure GNU convention. */ 791caf54c4fSMartin Matuska break; 792caf54c4fSMartin Matuska #endif 793caf54c4fSMartin Matuska case 'w': /* SUSv2 */ 79464287048SMartin Matuska bsdtar->flags |= OPTFLAG_INTERACTIVE; 795caf54c4fSMartin Matuska break; 796caf54c4fSMartin Matuska case 'X': /* GNU tar */ 797fd082e96SMartin Matuska if (archive_match_exclude_pattern_from_file( 798fd082e96SMartin Matuska bsdtar->matching, bsdtar->argument, 0) 799fd082e96SMartin Matuska != ARCHIVE_OK) 800fd082e96SMartin Matuska lafe_errc(1, 0, "Error : %s", 801fd082e96SMartin Matuska archive_error_string(bsdtar->matching)); 802caf54c4fSMartin Matuska break; 803caf54c4fSMartin Matuska case 'x': /* SUSv2 */ 804caf54c4fSMartin Matuska set_mode(bsdtar, opt); 805caf54c4fSMartin Matuska break; 80664287048SMartin Matuska case OPTION_XATTRS: /* GNU tar */ 80764287048SMartin Matuska bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR; 80864287048SMartin Matuska bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_XATTR; 80964287048SMartin Matuska bsdtar->flags |= OPTFLAG_XATTRS; 81064287048SMartin Matuska break; 811caf54c4fSMartin Matuska case 'y': /* FreeBSD version of GNU tar */ 812acc60b03SMartin Matuska if (compression != '\0') 813caf54c4fSMartin Matuska lafe_errc(1, 0, 814caf54c4fSMartin Matuska "Can't specify both -%c and -%c", opt, 815acc60b03SMartin Matuska compression); 816acc60b03SMartin Matuska compression = opt; 817acc60b03SMartin Matuska compression_name = "bzip2"; 818caf54c4fSMartin Matuska break; 819caf54c4fSMartin Matuska case 'Z': /* GNU tar */ 820acc60b03SMartin Matuska if (compression != '\0') 821caf54c4fSMartin Matuska lafe_errc(1, 0, 822caf54c4fSMartin Matuska "Can't specify both -%c and -%c", opt, 823acc60b03SMartin Matuska compression); 824acc60b03SMartin Matuska compression = opt; 825acc60b03SMartin Matuska compression_name = "compress"; 826caf54c4fSMartin Matuska break; 827caf54c4fSMartin Matuska case 'z': /* GNU tar, star, many others */ 828acc60b03SMartin Matuska if (compression != '\0') 829caf54c4fSMartin Matuska lafe_errc(1, 0, 830caf54c4fSMartin Matuska "Can't specify both -%c and -%c", opt, 831acc60b03SMartin Matuska compression); 832acc60b03SMartin Matuska compression = opt; 833acc60b03SMartin Matuska compression_name = "gzip"; 834caf54c4fSMartin Matuska break; 835caf54c4fSMartin Matuska case OPTION_USE_COMPRESS_PROGRAM: 836acc60b03SMartin Matuska compress_program = bsdtar->argument; 837caf54c4fSMartin Matuska break; 838caf54c4fSMartin Matuska default: 839caf54c4fSMartin Matuska usage(); 840caf54c4fSMartin Matuska } 841caf54c4fSMartin Matuska } 842caf54c4fSMartin Matuska 843caf54c4fSMartin Matuska /* 844caf54c4fSMartin Matuska * Sanity-check options. 845caf54c4fSMartin Matuska */ 846caf54c4fSMartin Matuska 847caf54c4fSMartin Matuska /* If no "real" mode was specified, treat -h as --help. */ 848caf54c4fSMartin Matuska if ((bsdtar->mode == '\0') && possible_help_request) { 849caf54c4fSMartin Matuska long_help(); 850caf54c4fSMartin Matuska } 851caf54c4fSMartin Matuska 852caf54c4fSMartin Matuska /* Otherwise, a mode is required. */ 853caf54c4fSMartin Matuska if (bsdtar->mode == '\0') 854caf54c4fSMartin Matuska lafe_errc(1, 0, 855caf54c4fSMartin Matuska "Must specify one of -c, -r, -t, -u, -x"); 856caf54c4fSMartin Matuska 857caf54c4fSMartin Matuska /* Check boolean options only permitted in certain modes. */ 858833a452eSMartin Matuska if (bsdtar->flags & OPTFLAG_AUTO_COMPRESS) { 859833a452eSMartin Matuska only_mode(bsdtar, "-a", "cx"); 860833a452eSMartin Matuska if (bsdtar->mode == 'x') { 861833a452eSMartin Matuska bsdtar->flags &= ~OPTFLAG_AUTO_COMPRESS; 862833a452eSMartin Matuska lafe_warnc(0, 863833a452eSMartin Matuska "Ignoring option -a in mode -x"); 864833a452eSMartin Matuska } 865833a452eSMartin Matuska } 866fd082e96SMartin Matuska if (bsdtar->readdisk_flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) 867caf54c4fSMartin Matuska only_mode(bsdtar, "--one-file-system", "cru"); 86864287048SMartin Matuska if (bsdtar->flags & OPTFLAG_FAST_READ) 869caf54c4fSMartin Matuska only_mode(bsdtar, "--fast-read", "xt"); 870acc60b03SMartin Matuska if (bsdtar->extract_flags & ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED) 871acc60b03SMartin Matuska only_mode(bsdtar, "--hfsCompression", "x"); 872acc60b03SMartin Matuska if (bsdtar->extract_flags & ARCHIVE_EXTRACT_NO_HFS_COMPRESSION) 873acc60b03SMartin Matuska only_mode(bsdtar, "--nopreserveHFSCompression", "x"); 874fd082e96SMartin Matuska if (bsdtar->readdisk_flags & ARCHIVE_READDISK_HONOR_NODUMP) 875caf54c4fSMartin Matuska only_mode(bsdtar, "--nodump", "cru"); 87664287048SMartin Matuska if (bsdtar->flags & OPTFLAG_ACLS) 87764287048SMartin Matuska only_mode(bsdtar, "--acls", "crux"); 87864287048SMartin Matuska if (bsdtar->flags & OPTFLAG_NO_ACLS) 87964287048SMartin Matuska only_mode(bsdtar, "--no-acls", "crux"); 88064287048SMartin Matuska if (bsdtar->flags & OPTFLAG_XATTRS) 88164287048SMartin Matuska only_mode(bsdtar, "--xattrs", "crux"); 88264287048SMartin Matuska if (bsdtar->flags & OPTFLAG_NO_XATTRS) 88364287048SMartin Matuska only_mode(bsdtar, "--no-xattrs", "crux"); 88464287048SMartin Matuska if (bsdtar->flags & OPTFLAG_FFLAGS) 88564287048SMartin Matuska only_mode(bsdtar, "--fflags", "crux"); 88664287048SMartin Matuska if (bsdtar->flags & OPTFLAG_NO_FFLAGS) 88764287048SMartin Matuska only_mode(bsdtar, "--no-fflags", "crux"); 88864287048SMartin Matuska if (bsdtar->flags & OPTFLAG_MAC_METADATA) 88964287048SMartin Matuska only_mode(bsdtar, "--mac-metadata", "crux"); 89064287048SMartin Matuska if (bsdtar->flags & OPTFLAG_NO_MAC_METADATA) 89164287048SMartin Matuska only_mode(bsdtar, "--no-mac-metadata", "crux"); 89264287048SMartin Matuska if (bsdtar->flags & OPTFLAG_O) { 893caf54c4fSMartin Matuska switch (bsdtar->mode) { 894caf54c4fSMartin Matuska case 'c': 895caf54c4fSMartin Matuska /* 896caf54c4fSMartin Matuska * In GNU tar, -o means "old format." The 897caf54c4fSMartin Matuska * "ustar" format is the closest thing 898caf54c4fSMartin Matuska * supported by libarchive. 899caf54c4fSMartin Matuska */ 900acc60b03SMartin Matuska cset_set_format(bsdtar->cset, "ustar"); 901caf54c4fSMartin Matuska /* TODO: bsdtar->create_format = "v7"; */ 902caf54c4fSMartin Matuska break; 903caf54c4fSMartin Matuska case 'x': 904caf54c4fSMartin Matuska /* POSIX-compatible behavior. */ 90564287048SMartin Matuska bsdtar->flags |= OPTFLAG_NO_OWNER; 906caf54c4fSMartin Matuska bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER; 907caf54c4fSMartin Matuska break; 908caf54c4fSMartin Matuska default: 909caf54c4fSMartin Matuska only_mode(bsdtar, "-o", "xc"); 910caf54c4fSMartin Matuska break; 911caf54c4fSMartin Matuska } 912caf54c4fSMartin Matuska } 91364287048SMartin Matuska if (bsdtar->flags & OPTFLAG_STDOUT) 914caf54c4fSMartin Matuska only_mode(bsdtar, "-O", "xt"); 91564287048SMartin Matuska if (bsdtar->flags & OPTFLAG_UNLINK_FIRST) 916caf54c4fSMartin Matuska only_mode(bsdtar, "-U", "x"); 91764287048SMartin Matuska if (bsdtar->flags & OPTFLAG_WARN_LINKS) 918caf54c4fSMartin Matuska only_mode(bsdtar, "--check-links", "cr"); 919caf54c4fSMartin Matuska 92064287048SMartin Matuska if ((bsdtar->flags & OPTFLAG_AUTO_COMPRESS) && 92164287048SMartin Matuska cset_auto_compress(bsdtar->cset, bsdtar->filename)) { 922acc60b03SMartin Matuska /* Ignore specified compressions if auto-compress works. */ 923acc60b03SMartin Matuska compression = '\0'; 924acc60b03SMartin Matuska compression2 = '\0'; 925caf54c4fSMartin Matuska } 926acc60b03SMartin Matuska /* Check other parameters only permitted in certain modes. */ 927acc60b03SMartin Matuska if (compress_program != NULL) { 928acc60b03SMartin Matuska only_mode(bsdtar, "--use-compress-program", "cxt"); 929acc60b03SMartin Matuska cset_add_filter_program(bsdtar->cset, compress_program); 930acc60b03SMartin Matuska /* Ignore specified compressions. */ 931acc60b03SMartin Matuska compression = '\0'; 932acc60b03SMartin Matuska compression2 = '\0'; 933acc60b03SMartin Matuska } 934acc60b03SMartin Matuska if (compression != '\0') { 935acc60b03SMartin Matuska switch (compression) { 936acc60b03SMartin Matuska case 'J': case 'j': case 'y': case 'Z': case 'z': 937acc60b03SMartin Matuska strcpy(buff, "-?"); 938acc60b03SMartin Matuska buff[1] = compression; 939acc60b03SMartin Matuska break; 940acc60b03SMartin Matuska default: 941acc60b03SMartin Matuska strcpy(buff, "--"); 942acc60b03SMartin Matuska strcat(buff, compression_name); 943acc60b03SMartin Matuska break; 944acc60b03SMartin Matuska } 945acc60b03SMartin Matuska only_mode(bsdtar, buff, "cxt"); 946acc60b03SMartin Matuska cset_add_filter(bsdtar->cset, compression_name); 947acc60b03SMartin Matuska } 948acc60b03SMartin Matuska if (compression2 != '\0') { 949acc60b03SMartin Matuska strcpy(buff, "--"); 950acc60b03SMartin Matuska strcat(buff, compression2_name); 951acc60b03SMartin Matuska only_mode(bsdtar, buff, "cxt"); 952acc60b03SMartin Matuska cset_add_filter(bsdtar->cset, compression2_name); 953acc60b03SMartin Matuska } 954acc60b03SMartin Matuska if (cset_get_format(bsdtar->cset) != NULL) 955caf54c4fSMartin Matuska only_mode(bsdtar, "--format", "cru"); 956caf54c4fSMartin Matuska if (bsdtar->symlink_mode != '\0') { 957caf54c4fSMartin Matuska strcpy(buff, "-?"); 958caf54c4fSMartin Matuska buff[1] = bsdtar->symlink_mode; 959caf54c4fSMartin Matuska only_mode(bsdtar, buff, "cru"); 960caf54c4fSMartin Matuska } 9616c95142eSMartin Matuska 96252c2bb75SMartin Matuska /* 96352c2bb75SMartin Matuska * When creating an archive from a directory tree, the directory 96452c2bb75SMartin Matuska * walking code will already avoid entering directories when 96552c2bb75SMartin Matuska * recursive inclusion of directory content is disabled, therefore 96652c2bb75SMartin Matuska * changing the matching behavior has no effect for creation modes. 96752c2bb75SMartin Matuska * It is relevant for extraction or listing. 96852c2bb75SMartin Matuska */ 96952c2bb75SMartin Matuska archive_match_set_inclusion_recursion(bsdtar->matching, 97052c2bb75SMartin Matuska !(bsdtar->flags & OPTFLAG_NO_SUBDIRS)); 97152c2bb75SMartin Matuska 9726c95142eSMartin Matuska /* Filename "-" implies stdio. */ 9736c95142eSMartin Matuska if (strcmp(bsdtar->filename, "-") == 0) 9746c95142eSMartin Matuska bsdtar->filename = NULL; 975caf54c4fSMartin Matuska 976caf54c4fSMartin Matuska switch(bsdtar->mode) { 977caf54c4fSMartin Matuska case 'c': 978caf54c4fSMartin Matuska tar_mode_c(bsdtar); 979caf54c4fSMartin Matuska break; 980caf54c4fSMartin Matuska case 'r': 981caf54c4fSMartin Matuska tar_mode_r(bsdtar); 982caf54c4fSMartin Matuska break; 983caf54c4fSMartin Matuska case 't': 984caf54c4fSMartin Matuska tar_mode_t(bsdtar); 985caf54c4fSMartin Matuska break; 986caf54c4fSMartin Matuska case 'u': 987caf54c4fSMartin Matuska tar_mode_u(bsdtar); 988caf54c4fSMartin Matuska break; 989caf54c4fSMartin Matuska case 'x': 990caf54c4fSMartin Matuska tar_mode_x(bsdtar); 991caf54c4fSMartin Matuska break; 992caf54c4fSMartin Matuska } 993caf54c4fSMartin Matuska 994fd082e96SMartin Matuska archive_match_free(bsdtar->matching); 995b9128a37SMartin Matuska #if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) || defined(HAVE_PCRE2POSIX_H) 996caf54c4fSMartin Matuska cleanup_substitution(bsdtar); 997caf54c4fSMartin Matuska #endif 998acc60b03SMartin Matuska cset_free(bsdtar->cset); 999cdf63a70SMartin Matuska passphrase_free(bsdtar->ppbuff); 1000caf54c4fSMartin Matuska 1001caf54c4fSMartin Matuska if (bsdtar->return_value != 0) 1002caf54c4fSMartin Matuska lafe_warnc(0, 1003caf54c4fSMartin Matuska "Error exit delayed from previous errors."); 1004caf54c4fSMartin Matuska return (bsdtar->return_value); 1005caf54c4fSMartin Matuska } 1006caf54c4fSMartin Matuska 1007caf54c4fSMartin Matuska static void 1008caf54c4fSMartin Matuska set_mode(struct bsdtar *bsdtar, char opt) 1009caf54c4fSMartin Matuska { 1010caf54c4fSMartin Matuska if (bsdtar->mode != '\0' && bsdtar->mode != opt) 1011caf54c4fSMartin Matuska lafe_errc(1, 0, 1012caf54c4fSMartin Matuska "Can't specify both -%c and -%c", opt, bsdtar->mode); 1013caf54c4fSMartin Matuska bsdtar->mode = opt; 1014caf54c4fSMartin Matuska } 1015caf54c4fSMartin Matuska 1016caf54c4fSMartin Matuska /* 1017caf54c4fSMartin Matuska * Verify that the mode is correct. 1018caf54c4fSMartin Matuska */ 1019caf54c4fSMartin Matuska static void 1020caf54c4fSMartin Matuska only_mode(struct bsdtar *bsdtar, const char *opt, const char *valid_modes) 1021caf54c4fSMartin Matuska { 1022caf54c4fSMartin Matuska if (strchr(valid_modes, bsdtar->mode) == NULL) 1023caf54c4fSMartin Matuska lafe_errc(1, 0, 1024caf54c4fSMartin Matuska "Option %s is not permitted in mode -%c", 1025caf54c4fSMartin Matuska opt, bsdtar->mode); 1026caf54c4fSMartin Matuska } 1027caf54c4fSMartin Matuska 1028caf54c4fSMartin Matuska 1029caf54c4fSMartin Matuska void 1030caf54c4fSMartin Matuska usage(void) 1031caf54c4fSMartin Matuska { 1032caf54c4fSMartin Matuska const char *p; 1033caf54c4fSMartin Matuska 1034cdf63a70SMartin Matuska p = lafe_getprogname(); 1035caf54c4fSMartin Matuska 1036caf54c4fSMartin Matuska fprintf(stderr, "Usage:\n"); 1037caf54c4fSMartin Matuska fprintf(stderr, " List: %s -tf <archive-filename>\n", p); 1038caf54c4fSMartin Matuska fprintf(stderr, " Extract: %s -xf <archive-filename>\n", p); 1039caf54c4fSMartin Matuska fprintf(stderr, " Create: %s -cf <archive-filename> [filenames...]\n", p); 1040caf54c4fSMartin Matuska fprintf(stderr, " Help: %s --help\n", p); 1041caf54c4fSMartin Matuska exit(1); 1042caf54c4fSMartin Matuska } 1043caf54c4fSMartin Matuska 1044caf54c4fSMartin Matuska static void 1045caf54c4fSMartin Matuska version(void) 1046caf54c4fSMartin Matuska { 1047caf54c4fSMartin Matuska printf("bsdtar %s - %s \n", 1048caf54c4fSMartin Matuska BSDTAR_VERSION_STRING, 1049cdf63a70SMartin Matuska archive_version_details()); 1050caf54c4fSMartin Matuska exit(0); 1051caf54c4fSMartin Matuska } 1052caf54c4fSMartin Matuska 1053caf54c4fSMartin Matuska static const char *long_help_msg = 1054caf54c4fSMartin Matuska "First option must be a mode specifier:\n" 1055caf54c4fSMartin Matuska " -c Create -r Add/Replace -t List -u Update -x Extract\n" 1056caf54c4fSMartin Matuska "Common Options:\n" 1057caf54c4fSMartin Matuska " -b # Use # 512-byte records per I/O block\n" 1058caf54c4fSMartin Matuska " -f <filename> Location of archive (default " _PATH_DEFTAPE ")\n" 1059caf54c4fSMartin Matuska " -v Verbose\n" 1060caf54c4fSMartin Matuska " -w Interactive\n" 1061caf54c4fSMartin Matuska "Create: %p -c [options] [<file> | <dir> | @<archive> | -C <dir> ]\n" 1062caf54c4fSMartin Matuska " <file>, <dir> add these items to archive\n" 1063caf54c4fSMartin Matuska " -z, -j, -J, --lzma Compress archive with gzip/bzip2/xz/lzma\n" 1064caf54c4fSMartin Matuska " --format {ustar|pax|cpio|shar} Select archive format\n" 1065caf54c4fSMartin Matuska " --exclude <pattern> Skip files that match pattern\n" 1066caf54c4fSMartin Matuska " -C <dir> Change to <dir> before processing remaining files\n" 1067caf54c4fSMartin Matuska " @<archive> Add entries from <archive> to output\n" 1068caf54c4fSMartin Matuska "List: %p -t [options] [<patterns>]\n" 1069caf54c4fSMartin Matuska " <patterns> If specified, list only entries that match\n" 1070caf54c4fSMartin Matuska "Extract: %p -x [options] [<patterns>]\n" 1071caf54c4fSMartin Matuska " <patterns> If specified, extract only entries that match\n" 1072caf54c4fSMartin Matuska " -k Keep (don't overwrite) existing files\n" 1073caf54c4fSMartin Matuska " -m Don't restore modification times\n" 1074caf54c4fSMartin Matuska " -O Write entries to stdout, don't restore to disk\n" 1075caf54c4fSMartin Matuska " -p Restore permissions (including ACLs, owner, file flags)\n"; 1076caf54c4fSMartin Matuska 1077caf54c4fSMartin Matuska 1078caf54c4fSMartin Matuska /* 1079caf54c4fSMartin Matuska * Note that the word 'bsdtar' will always appear in the first line 1080caf54c4fSMartin Matuska * of output. 1081caf54c4fSMartin Matuska * 1082caf54c4fSMartin Matuska * In particular, /bin/sh scripts that need to test for the presence 1083caf54c4fSMartin Matuska * of bsdtar can use the following template: 1084caf54c4fSMartin Matuska * 1085caf54c4fSMartin Matuska * if (tar --help 2>&1 | grep bsdtar >/dev/null 2>&1 ) then \ 1086caf54c4fSMartin Matuska * echo bsdtar; else echo not bsdtar; fi 1087caf54c4fSMartin Matuska */ 1088caf54c4fSMartin Matuska static void 1089caf54c4fSMartin Matuska long_help(void) 1090caf54c4fSMartin Matuska { 1091caf54c4fSMartin Matuska const char *prog; 1092caf54c4fSMartin Matuska const char *p; 1093caf54c4fSMartin Matuska 1094cdf63a70SMartin Matuska prog = lafe_getprogname(); 1095caf54c4fSMartin Matuska 1096caf54c4fSMartin Matuska fflush(stderr); 1097caf54c4fSMartin Matuska 1098caf54c4fSMartin Matuska p = (strcmp(prog,"bsdtar") != 0) ? "(bsdtar)" : ""; 1099caf54c4fSMartin Matuska printf("%s%s: manipulate archive files\n", prog, p); 1100caf54c4fSMartin Matuska 1101caf54c4fSMartin Matuska for (p = long_help_msg; *p != '\0'; p++) { 1102caf54c4fSMartin Matuska if (*p == '%') { 1103caf54c4fSMartin Matuska if (p[1] == 'p') { 1104caf54c4fSMartin Matuska fputs(prog, stdout); 1105caf54c4fSMartin Matuska p++; 1106caf54c4fSMartin Matuska } else 1107caf54c4fSMartin Matuska putchar('%'); 1108caf54c4fSMartin Matuska } else 1109caf54c4fSMartin Matuska putchar(*p); 1110caf54c4fSMartin Matuska } 1111caf54c4fSMartin Matuska version(); 1112caf54c4fSMartin Matuska } 1113