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 7360b4ad09SPeter Avalos /* 7460b4ad09SPeter Avalos * Per POSIX.1-1988, tar defaults to reading/writing archives to/from 7560b4ad09SPeter Avalos * the default tape device for the system. Pick something reasonable here. 7660b4ad09SPeter Avalos */ 7760b4ad09SPeter Avalos #ifdef __linux 7860b4ad09SPeter Avalos #define _PATH_DEFTAPE "/dev/st0" 7960b4ad09SPeter Avalos #endif 808029ab02SPeter Avalos #if defined(_WIN32) && !defined(__CYGWIN__) 818029ab02SPeter Avalos #define _PATH_DEFTAPE "\\\\.\\tape0" 828029ab02SPeter Avalos #endif 83c09f92d2SPeter Avalos #if defined(__APPLE__) 84c09f92d2SPeter Avalos #undef _PATH_DEFTAPE 85c09f92d2SPeter Avalos #define _PATH_DEFTAPE "-" /* Mac OS has no tape support, default to stdio. */ 86c09f92d2SPeter Avalos #endif 8760b4ad09SPeter Avalos 8860b4ad09SPeter Avalos #ifndef _PATH_DEFTAPE 8960b4ad09SPeter Avalos #define _PATH_DEFTAPE "/dev/tape" 9060b4ad09SPeter Avalos #endif 9160b4ad09SPeter Avalos 929c82a63eSPeter Avalos #ifdef __MINGW32__ 939c82a63eSPeter Avalos int _CRT_glob = 0; /* Disable broken CRT globbing. */ 949c82a63eSPeter Avalos #endif 959c82a63eSPeter Avalos 969c82a63eSPeter Avalos #if defined(HAVE_SIGACTION) && (defined(SIGINFO) || defined(SIGUSR1)) 979c82a63eSPeter Avalos static volatile int siginfo_occurred; 989c82a63eSPeter Avalos 999c82a63eSPeter Avalos static void 1009c82a63eSPeter Avalos siginfo_handler(int sig) 1019c82a63eSPeter Avalos { 1029c82a63eSPeter Avalos (void)sig; /* UNUSED */ 1039c82a63eSPeter Avalos siginfo_occurred = 1; 1049c82a63eSPeter Avalos } 1059c82a63eSPeter Avalos 1069c82a63eSPeter Avalos int 1079c82a63eSPeter Avalos need_report(void) 1089c82a63eSPeter Avalos { 1099c82a63eSPeter Avalos int r = siginfo_occurred; 1109c82a63eSPeter Avalos siginfo_occurred = 0; 1119c82a63eSPeter Avalos return (r); 1129c82a63eSPeter Avalos } 1139c82a63eSPeter Avalos #else 1149c82a63eSPeter Avalos int 1159c82a63eSPeter Avalos need_report(void) 1169c82a63eSPeter Avalos { 1179c82a63eSPeter Avalos return (0); 1189c82a63eSPeter Avalos } 1199c82a63eSPeter Avalos #endif 1209c82a63eSPeter Avalos 1219c82a63eSPeter Avalos static void long_help(void); 12260b4ad09SPeter Avalos static void only_mode(struct bsdtar *, const char *opt, 12360b4ad09SPeter Avalos const char *valid); 12460b4ad09SPeter Avalos static void set_mode(struct bsdtar *, char opt); 12560b4ad09SPeter Avalos static void version(void); 12660b4ad09SPeter Avalos 12760b4ad09SPeter Avalos /* A basic set of security flags to request from libarchive. */ 12860b4ad09SPeter Avalos #define SECURITY \ 12960b4ad09SPeter Avalos (ARCHIVE_EXTRACT_SECURE_SYMLINKS \ 13060b4ad09SPeter Avalos | ARCHIVE_EXTRACT_SECURE_NODOTDOT) 13160b4ad09SPeter Avalos 13260b4ad09SPeter Avalos int 13360b4ad09SPeter Avalos main(int argc, char **argv) 13460b4ad09SPeter Avalos { 13560b4ad09SPeter Avalos struct bsdtar *bsdtar, bsdtar_storage; 13660b4ad09SPeter Avalos int opt, t; 137d4d8193eSPeter Avalos char compression, compression2; 138d4d8193eSPeter Avalos const char *compression_name, *compression2_name; 139d4d8193eSPeter Avalos const char *compress_program; 140d4d8193eSPeter Avalos char option_a, option_o; 14160b4ad09SPeter Avalos char possible_help_request; 14260b4ad09SPeter Avalos char buff[16]; 14360b4ad09SPeter Avalos 14460b4ad09SPeter Avalos /* 14560b4ad09SPeter Avalos * Use a pointer for consistency, but stack-allocated storage 14660b4ad09SPeter Avalos * for ease of cleanup. 14760b4ad09SPeter Avalos */ 148c09f92d2SPeter Avalos bsdtar = &bsdtar_storage; 14960b4ad09SPeter Avalos memset(bsdtar, 0, sizeof(*bsdtar)); 15060b4ad09SPeter Avalos bsdtar->fd = -1; /* Mark as "unused" */ 151c09f92d2SPeter Avalos bsdtar->gid = -1; 152c09f92d2SPeter Avalos bsdtar->uid = -1; 153d4d8193eSPeter Avalos option_a = option_o = 0; 154d4d8193eSPeter Avalos compression = compression2 = '\0'; 155d4d8193eSPeter Avalos compression_name = compression2_name = NULL; 156d4d8193eSPeter Avalos compress_program = NULL; 1579c82a63eSPeter Avalos 158c09f92d2SPeter Avalos #if defined(HAVE_SIGACTION) 159c09f92d2SPeter Avalos { /* Set up signal handling. */ 1609c82a63eSPeter Avalos struct sigaction sa; 1619c82a63eSPeter Avalos sa.sa_handler = siginfo_handler; 1629c82a63eSPeter Avalos sigemptyset(&sa.sa_mask); 1639c82a63eSPeter Avalos sa.sa_flags = 0; 1649c82a63eSPeter Avalos #ifdef SIGINFO 1659c82a63eSPeter Avalos if (sigaction(SIGINFO, &sa, NULL)) 1669c82a63eSPeter Avalos lafe_errc(1, errno, "sigaction(SIGINFO) failed"); 1679c82a63eSPeter Avalos #endif 1689c82a63eSPeter Avalos #ifdef SIGUSR1 1699c82a63eSPeter Avalos /* ... and treat SIGUSR1 the same way as SIGINFO. */ 1709c82a63eSPeter Avalos if (sigaction(SIGUSR1, &sa, NULL)) 1719c82a63eSPeter Avalos lafe_errc(1, errno, "sigaction(SIGUSR1) failed"); 1729c82a63eSPeter Avalos #endif 173c09f92d2SPeter Avalos #ifdef SIGPIPE 174c09f92d2SPeter Avalos /* Ignore SIGPIPE signals. */ 175c09f92d2SPeter Avalos sa.sa_handler = SIG_IGN; 176c09f92d2SPeter Avalos sigaction(SIGPIPE, &sa, NULL); 177c09f92d2SPeter Avalos #endif 1789c82a63eSPeter Avalos } 1798029ab02SPeter Avalos #endif 18060b4ad09SPeter Avalos 181*6b384f39SPeter Avalos /* Set lafe_progname before calling lafe_warnc. */ 182*6b384f39SPeter Avalos lafe_setprogname(*argv, "bsdtar"); 18360b4ad09SPeter Avalos 1849c82a63eSPeter Avalos #if HAVE_SETLOCALE 18560b4ad09SPeter Avalos if (setlocale(LC_ALL, "") == NULL) 1869c82a63eSPeter Avalos lafe_warnc(0, "Failed to set default locale"); 1879c82a63eSPeter Avalos #endif 18860b4ad09SPeter Avalos #if defined(HAVE_NL_LANGINFO) && defined(HAVE_D_MD_ORDER) 18960b4ad09SPeter Avalos bsdtar->day_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 19060b4ad09SPeter Avalos #endif 19160b4ad09SPeter Avalos possible_help_request = 0; 19260b4ad09SPeter Avalos 19360b4ad09SPeter Avalos /* Look up uid of current user for future reference */ 19460b4ad09SPeter Avalos bsdtar->user_uid = geteuid(); 19560b4ad09SPeter Avalos 19660b4ad09SPeter Avalos /* Default: open tape drive. */ 19760b4ad09SPeter Avalos bsdtar->filename = getenv("TAPE"); 19860b4ad09SPeter Avalos if (bsdtar->filename == NULL) 19960b4ad09SPeter Avalos bsdtar->filename = _PATH_DEFTAPE; 20060b4ad09SPeter Avalos 201c09f92d2SPeter Avalos /* Default block size settings. */ 202c09f92d2SPeter Avalos bsdtar->bytes_per_block = DEFAULT_BYTES_PER_BLOCK; 203c09f92d2SPeter Avalos /* Allow library to default this unless user specifies -b. */ 204c09f92d2SPeter Avalos bsdtar->bytes_in_last_block = -1; 205c09f92d2SPeter Avalos 20660b4ad09SPeter Avalos /* Default: preserve mod time on extract */ 20760b4ad09SPeter Avalos bsdtar->extract_flags = ARCHIVE_EXTRACT_TIME; 20860b4ad09SPeter Avalos 20960b4ad09SPeter Avalos /* Default: Perform basic security checks. */ 21060b4ad09SPeter Avalos bsdtar->extract_flags |= SECURITY; 21160b4ad09SPeter Avalos 2129c82a63eSPeter Avalos #ifndef _WIN32 2139c82a63eSPeter Avalos /* On POSIX systems, assume --same-owner and -p when run by 2149c82a63eSPeter Avalos * the root user. This doesn't make any sense on Windows. */ 2159c82a63eSPeter Avalos if (bsdtar->user_uid == 0) { 21660b4ad09SPeter Avalos /* --same-owner */ 21760b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER; 21860b4ad09SPeter Avalos /* -p */ 21960b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM; 22060b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL; 22160b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR; 22260b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; 223c09f92d2SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_MAC_METADATA; 22460b4ad09SPeter Avalos } 2259c82a63eSPeter Avalos #endif 22660b4ad09SPeter Avalos 227c09f92d2SPeter Avalos /* 228c09f92d2SPeter Avalos * Enable Mac OS "copyfile()" extension by default. 229c09f92d2SPeter Avalos * This has no effect on other platforms. 230c09f92d2SPeter Avalos */ 23159bf7050SPeter Avalos bsdtar->readdisk_flags |= ARCHIVE_READDISK_MAC_COPYFILE; 232c09f92d2SPeter Avalos #ifdef COPYFILE_DISABLE_VAR 233c09f92d2SPeter Avalos if (getenv(COPYFILE_DISABLE_VAR)) 23459bf7050SPeter Avalos bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_MAC_COPYFILE; 235c09f92d2SPeter Avalos #endif 23659bf7050SPeter Avalos bsdtar->matching = archive_match_new(); 23759bf7050SPeter Avalos if (bsdtar->matching == NULL) 23859bf7050SPeter Avalos lafe_errc(1, errno, "Out of memory"); 239d4d8193eSPeter Avalos bsdtar->cset = cset_new(); 240d4d8193eSPeter Avalos if (bsdtar->cset == NULL) 241d4d8193eSPeter Avalos lafe_errc(1, errno, "Out of memory"); 242c09f92d2SPeter Avalos 24360b4ad09SPeter Avalos bsdtar->argv = argv; 24460b4ad09SPeter Avalos bsdtar->argc = argc; 24560b4ad09SPeter Avalos 24660b4ad09SPeter Avalos /* 24760b4ad09SPeter Avalos * Comments following each option indicate where that option 24860b4ad09SPeter Avalos * originated: SUSv2, POSIX, GNU tar, star, etc. If there's 24960b4ad09SPeter Avalos * no such comment, then I don't know of anyone else who 25060b4ad09SPeter Avalos * implements that option. 25160b4ad09SPeter Avalos */ 2528029ab02SPeter Avalos while ((opt = bsdtar_getopt(bsdtar)) != -1) { 25360b4ad09SPeter Avalos switch (opt) { 254d4d8193eSPeter Avalos case 'a': /* GNU tar */ 255d4d8193eSPeter Avalos option_a = 1; /* Record it and resolve it later. */ 256d4d8193eSPeter Avalos break; 25760b4ad09SPeter Avalos case 'B': /* GNU tar */ 25860b4ad09SPeter Avalos /* libarchive doesn't need this; just ignore it. */ 25960b4ad09SPeter Avalos break; 26060b4ad09SPeter Avalos case 'b': /* SUSv2 */ 261c09f92d2SPeter Avalos t = atoi(bsdtar->argument); 2629c82a63eSPeter Avalos if (t <= 0 || t > 8192) 2639c82a63eSPeter Avalos lafe_errc(1, 0, 2649c82a63eSPeter Avalos "Argument to -b is out of range (1..8192)"); 26560b4ad09SPeter Avalos bsdtar->bytes_per_block = 512 * t; 266c09f92d2SPeter Avalos /* Explicit -b forces last block size. */ 267c09f92d2SPeter Avalos bsdtar->bytes_in_last_block = bsdtar->bytes_per_block; 26860b4ad09SPeter Avalos break; 269d4d8193eSPeter Avalos case OPTION_B64ENCODE: 270d4d8193eSPeter Avalos if (compression2 != '\0') 271d4d8193eSPeter Avalos lafe_errc(1, 0, 272d4d8193eSPeter Avalos "Can't specify both --uuencode and " 273d4d8193eSPeter Avalos "--b64encode"); 274d4d8193eSPeter Avalos compression2 = opt; 275d4d8193eSPeter Avalos compression2_name = "b64encode"; 276d4d8193eSPeter Avalos break; 27760b4ad09SPeter Avalos case 'C': /* GNU tar */ 278c09f92d2SPeter Avalos if (strlen(bsdtar->argument) == 0) 279c09f92d2SPeter Avalos lafe_errc(1, 0, 280c09f92d2SPeter Avalos "Meaningless option: -C ''"); 281c09f92d2SPeter Avalos 282c09f92d2SPeter Avalos set_chdir(bsdtar, bsdtar->argument); 28360b4ad09SPeter Avalos break; 28460b4ad09SPeter Avalos case 'c': /* SUSv2 */ 28560b4ad09SPeter Avalos set_mode(bsdtar, opt); 28660b4ad09SPeter Avalos break; 28760b4ad09SPeter Avalos case OPTION_CHECK_LINKS: /* GNU tar */ 28860b4ad09SPeter Avalos bsdtar->option_warn_links = 1; 28960b4ad09SPeter Avalos break; 29060b4ad09SPeter Avalos case OPTION_CHROOT: /* NetBSD */ 29160b4ad09SPeter Avalos bsdtar->option_chroot = 1; 29260b4ad09SPeter Avalos break; 293*6b384f39SPeter Avalos case OPTION_CLEAR_NOCHANGE_FFLAGS: 294*6b384f39SPeter Avalos bsdtar->extract_flags |= 295*6b384f39SPeter Avalos ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS; 296*6b384f39SPeter Avalos break; 297c09f92d2SPeter Avalos case OPTION_DISABLE_COPYFILE: /* Mac OS X */ 29859bf7050SPeter Avalos bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_MAC_COPYFILE; 299c09f92d2SPeter Avalos break; 30060b4ad09SPeter Avalos case OPTION_EXCLUDE: /* GNU tar */ 30159bf7050SPeter Avalos if (archive_match_exclude_pattern( 30259bf7050SPeter Avalos bsdtar->matching, bsdtar->argument) != ARCHIVE_OK) 3039c82a63eSPeter Avalos lafe_errc(1, 0, 304c09f92d2SPeter Avalos "Couldn't exclude %s\n", bsdtar->argument); 30560b4ad09SPeter Avalos break; 30660b4ad09SPeter Avalos case OPTION_FORMAT: /* GNU tar, others */ 307d4d8193eSPeter Avalos cset_set_format(bsdtar->cset, bsdtar->argument); 30860b4ad09SPeter Avalos break; 30960b4ad09SPeter Avalos case 'f': /* SUSv2 */ 310c09f92d2SPeter Avalos bsdtar->filename = bsdtar->argument; 311c09f92d2SPeter Avalos break; 312c09f92d2SPeter Avalos case OPTION_GID: /* cpio */ 313c09f92d2SPeter Avalos t = atoi(bsdtar->argument); 314c09f92d2SPeter Avalos if (t < 0) 315c09f92d2SPeter Avalos lafe_errc(1, 0, 316c09f92d2SPeter Avalos "Argument to --gid must be positive"); 317c09f92d2SPeter Avalos bsdtar->gid = t; 318c09f92d2SPeter Avalos break; 319c09f92d2SPeter Avalos case OPTION_GNAME: /* cpio */ 320c09f92d2SPeter Avalos bsdtar->gname = bsdtar->argument; 32160b4ad09SPeter Avalos break; 322d4d8193eSPeter Avalos case OPTION_GRZIP: 323d4d8193eSPeter Avalos if (compression != '\0') 324d4d8193eSPeter Avalos lafe_errc(1, 0, 325d4d8193eSPeter Avalos "Can't specify both -%c and -%c", opt, 326d4d8193eSPeter Avalos compression); 327d4d8193eSPeter Avalos compression = opt; 328d4d8193eSPeter Avalos compression_name = "grzip"; 329d4d8193eSPeter Avalos break; 33060b4ad09SPeter Avalos case 'H': /* BSD convention */ 33160b4ad09SPeter Avalos bsdtar->symlink_mode = 'H'; 33260b4ad09SPeter Avalos break; 33360b4ad09SPeter Avalos case 'h': /* Linux Standards Base, gtar; synonym for -L */ 33460b4ad09SPeter Avalos bsdtar->symlink_mode = 'L'; 33560b4ad09SPeter Avalos /* Hack: -h by itself is the "help" command. */ 33660b4ad09SPeter Avalos possible_help_request = 1; 33760b4ad09SPeter Avalos break; 33860b4ad09SPeter Avalos case OPTION_HELP: /* GNU tar, others */ 3399c82a63eSPeter Avalos long_help(); 34060b4ad09SPeter Avalos exit(0); 34160b4ad09SPeter Avalos break; 342d4d8193eSPeter Avalos case OPTION_HFS_COMPRESSION: /* Mac OS X v10.6 or later */ 343d4d8193eSPeter Avalos bsdtar->extract_flags |= 344d4d8193eSPeter Avalos ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED; 345d4d8193eSPeter Avalos break; 346*6b384f39SPeter Avalos case OPTION_IGNORE_ZEROS: 347*6b384f39SPeter Avalos bsdtar->option_ignore_zeros = 1; 348*6b384f39SPeter Avalos break; 34960b4ad09SPeter Avalos case 'I': /* GNU tar */ 35060b4ad09SPeter Avalos /* 35160b4ad09SPeter Avalos * TODO: Allow 'names' to come from an archive, 35260b4ad09SPeter Avalos * not just a text file. Design a good UI for 35360b4ad09SPeter Avalos * allowing names and mode/owner to be read 35460b4ad09SPeter Avalos * from an archive, with contents coming from 35560b4ad09SPeter Avalos * disk. This can be used to "refresh" an 35660b4ad09SPeter Avalos * archive or to design archives with special 35760b4ad09SPeter Avalos * permissions without having to create those 35860b4ad09SPeter Avalos * permissions on disk. 35960b4ad09SPeter Avalos */ 360c09f92d2SPeter Avalos bsdtar->names_from_file = bsdtar->argument; 36160b4ad09SPeter Avalos break; 36260b4ad09SPeter Avalos case OPTION_INCLUDE: 36360b4ad09SPeter Avalos /* 36460b4ad09SPeter Avalos * No one else has the @archive extension, so 36560b4ad09SPeter Avalos * no one else needs this to filter entries 36660b4ad09SPeter Avalos * when transforming archives. 36760b4ad09SPeter Avalos */ 36859bf7050SPeter Avalos if (archive_match_include_pattern(bsdtar->matching, 36959bf7050SPeter Avalos bsdtar->argument) != ARCHIVE_OK) 3709c82a63eSPeter Avalos lafe_errc(1, 0, 37160b4ad09SPeter Avalos "Failed to add %s to inclusion list", 372c09f92d2SPeter Avalos bsdtar->argument); 37360b4ad09SPeter Avalos break; 37460b4ad09SPeter Avalos case 'j': /* GNU tar */ 375d4d8193eSPeter Avalos if (compression != '\0') 3769c82a63eSPeter Avalos lafe_errc(1, 0, 37760b4ad09SPeter Avalos "Can't specify both -%c and -%c", opt, 378d4d8193eSPeter Avalos compression); 379d4d8193eSPeter Avalos compression = opt; 380d4d8193eSPeter Avalos compression_name = "bzip2"; 3818029ab02SPeter Avalos break; 3828029ab02SPeter Avalos case 'J': /* GNU tar 1.21 and later */ 383d4d8193eSPeter Avalos if (compression != '\0') 3849c82a63eSPeter Avalos lafe_errc(1, 0, 3858029ab02SPeter Avalos "Can't specify both -%c and -%c", opt, 386d4d8193eSPeter Avalos compression); 387d4d8193eSPeter Avalos compression = opt; 388d4d8193eSPeter Avalos compression_name = "xz"; 38960b4ad09SPeter Avalos break; 39060b4ad09SPeter Avalos case 'k': /* GNU tar */ 39160b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE; 39260b4ad09SPeter Avalos break; 39360b4ad09SPeter Avalos case OPTION_KEEP_NEWER_FILES: /* GNU tar */ 39460b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER; 39560b4ad09SPeter Avalos break; 39660b4ad09SPeter Avalos case 'L': /* BSD convention */ 39760b4ad09SPeter Avalos bsdtar->symlink_mode = 'L'; 39860b4ad09SPeter Avalos break; 39960b4ad09SPeter Avalos case 'l': /* SUSv2 and GNU tar beginning with 1.16 */ 40060b4ad09SPeter Avalos /* GNU tar 1.13 used -l for --one-file-system */ 40160b4ad09SPeter Avalos bsdtar->option_warn_links = 1; 40260b4ad09SPeter Avalos break; 403d4d8193eSPeter Avalos case OPTION_LRZIP: 404*6b384f39SPeter Avalos case OPTION_LZ4: 405c09f92d2SPeter Avalos case OPTION_LZIP: /* GNU tar beginning with 1.23 */ 406c09f92d2SPeter Avalos case OPTION_LZMA: /* GNU tar beginning with 1.20 */ 407d4d8193eSPeter Avalos case OPTION_LZOP: /* GNU tar beginning with 1.21 */ 408d4d8193eSPeter Avalos if (compression != '\0') 4099c82a63eSPeter Avalos lafe_errc(1, 0, 4108029ab02SPeter Avalos "Can't specify both -%c and -%c", opt, 411d4d8193eSPeter Avalos compression); 412d4d8193eSPeter Avalos compression = opt; 413d4d8193eSPeter Avalos switch (opt) { 414d4d8193eSPeter Avalos case OPTION_LRZIP: compression_name = "lrzip"; break; 415*6b384f39SPeter Avalos case OPTION_LZ4: compression_name = "lz4"; break; 416d4d8193eSPeter Avalos case OPTION_LZIP: compression_name = "lzip"; break; 417d4d8193eSPeter Avalos case OPTION_LZMA: compression_name = "lzma"; break; 418d4d8193eSPeter Avalos case OPTION_LZOP: compression_name = "lzop"; break; 419d4d8193eSPeter Avalos } 4208029ab02SPeter Avalos break; 42160b4ad09SPeter Avalos case 'm': /* SUSv2 */ 42260b4ad09SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_TIME; 42360b4ad09SPeter Avalos break; 42460b4ad09SPeter Avalos case 'n': /* GNU tar */ 42560b4ad09SPeter Avalos bsdtar->option_no_subdirs = 1; 42660b4ad09SPeter Avalos break; 42760b4ad09SPeter Avalos /* 42860b4ad09SPeter Avalos * Selecting files by time: 42960b4ad09SPeter Avalos * --newer-?time='date' Only files newer than 'date' 43060b4ad09SPeter Avalos * --newer-?time-than='file' Only files newer than time 43160b4ad09SPeter Avalos * on specified file (useful for incremental backups) 43260b4ad09SPeter Avalos */ 43360b4ad09SPeter Avalos case OPTION_NEWER_CTIME: /* GNU tar */ 43459bf7050SPeter Avalos if (archive_match_include_date(bsdtar->matching, 43559bf7050SPeter Avalos ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER, 43659bf7050SPeter Avalos bsdtar->argument) != ARCHIVE_OK) 43759bf7050SPeter Avalos lafe_errc(1, 0, "Error : %s", 43859bf7050SPeter Avalos archive_error_string(bsdtar->matching)); 43960b4ad09SPeter Avalos break; 44060b4ad09SPeter Avalos case OPTION_NEWER_CTIME_THAN: 44159bf7050SPeter Avalos if (archive_match_include_file_time(bsdtar->matching, 44259bf7050SPeter Avalos ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER, 44359bf7050SPeter Avalos bsdtar->argument) != ARCHIVE_OK) 44459bf7050SPeter Avalos lafe_errc(1, 0, "Error : %s", 44559bf7050SPeter Avalos archive_error_string(bsdtar->matching)); 44660b4ad09SPeter Avalos break; 44760b4ad09SPeter Avalos case OPTION_NEWER_MTIME: /* GNU tar */ 44859bf7050SPeter Avalos if (archive_match_include_date(bsdtar->matching, 44959bf7050SPeter Avalos ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER, 45059bf7050SPeter Avalos bsdtar->argument) != ARCHIVE_OK) 45159bf7050SPeter Avalos lafe_errc(1, 0, "Error : %s", 45259bf7050SPeter Avalos archive_error_string(bsdtar->matching)); 45360b4ad09SPeter Avalos break; 45460b4ad09SPeter Avalos case OPTION_NEWER_MTIME_THAN: 45559bf7050SPeter Avalos if (archive_match_include_file_time(bsdtar->matching, 45659bf7050SPeter Avalos ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER, 45759bf7050SPeter Avalos bsdtar->argument) != ARCHIVE_OK) 45859bf7050SPeter Avalos lafe_errc(1, 0, "Error : %s", 45959bf7050SPeter Avalos archive_error_string(bsdtar->matching)); 46060b4ad09SPeter Avalos break; 46160b4ad09SPeter Avalos case OPTION_NODUMP: /* star */ 46259bf7050SPeter Avalos bsdtar->readdisk_flags |= ARCHIVE_READDISK_HONOR_NODUMP; 46360b4ad09SPeter Avalos break; 464d4d8193eSPeter Avalos case OPTION_NOPRESERVE_HFS_COMPRESSION: 465d4d8193eSPeter Avalos /* Mac OS X v10.6 or later */ 466d4d8193eSPeter Avalos bsdtar->extract_flags |= 467d4d8193eSPeter Avalos ARCHIVE_EXTRACT_NO_HFS_COMPRESSION; 468d4d8193eSPeter Avalos break; 46960b4ad09SPeter Avalos case OPTION_NO_SAME_OWNER: /* GNU tar */ 47060b4ad09SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER; 47160b4ad09SPeter Avalos break; 47260b4ad09SPeter Avalos case OPTION_NO_SAME_PERMISSIONS: /* GNU tar */ 47360b4ad09SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_PERM; 47460b4ad09SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_ACL; 47560b4ad09SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_XATTR; 47660b4ad09SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_FFLAGS; 477c09f92d2SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_MAC_METADATA; 47860b4ad09SPeter Avalos break; 479*6b384f39SPeter Avalos case OPTION_NO_XATTR: /* Issue #131 */ 480*6b384f39SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_XATTR; 481*6b384f39SPeter Avalos bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_XATTR; 482*6b384f39SPeter Avalos break; 48360b4ad09SPeter Avalos case OPTION_NULL: /* GNU tar */ 48460b4ad09SPeter Avalos bsdtar->option_null++; 48560b4ad09SPeter Avalos break; 48660b4ad09SPeter Avalos case OPTION_NUMERIC_OWNER: /* GNU tar */ 487c09f92d2SPeter Avalos bsdtar->uname = ""; 488c09f92d2SPeter Avalos bsdtar->gname = ""; 48960b4ad09SPeter Avalos bsdtar->option_numeric_owner++; 49060b4ad09SPeter Avalos break; 49160b4ad09SPeter Avalos case 'O': /* GNU tar */ 49260b4ad09SPeter Avalos bsdtar->option_stdout = 1; 49360b4ad09SPeter Avalos break; 49460b4ad09SPeter Avalos case 'o': /* SUSv2 and GNU conflict here, but not fatally */ 49560b4ad09SPeter Avalos option_o = 1; /* Record it and resolve it later. */ 49660b4ad09SPeter Avalos break; 497d4d8193eSPeter Avalos /* 498d4d8193eSPeter Avalos * Selecting files by time: 499d4d8193eSPeter Avalos * --older-?time='date' Only files older than 'date' 500d4d8193eSPeter Avalos * --older-?time-than='file' Only files older than time 501d4d8193eSPeter Avalos * on specified file 502d4d8193eSPeter Avalos */ 503d4d8193eSPeter Avalos case OPTION_OLDER_CTIME: 504d4d8193eSPeter Avalos if (archive_match_include_date(bsdtar->matching, 505d4d8193eSPeter Avalos ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER, 506d4d8193eSPeter Avalos bsdtar->argument) != ARCHIVE_OK) 507d4d8193eSPeter Avalos lafe_errc(1, 0, "Error : %s", 508d4d8193eSPeter Avalos archive_error_string(bsdtar->matching)); 509d4d8193eSPeter Avalos break; 510d4d8193eSPeter Avalos case OPTION_OLDER_CTIME_THAN: 511d4d8193eSPeter Avalos if (archive_match_include_file_time(bsdtar->matching, 512d4d8193eSPeter Avalos ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER, 513d4d8193eSPeter Avalos bsdtar->argument) != ARCHIVE_OK) 514d4d8193eSPeter Avalos lafe_errc(1, 0, "Error : %s", 515d4d8193eSPeter Avalos archive_error_string(bsdtar->matching)); 516d4d8193eSPeter Avalos break; 517d4d8193eSPeter Avalos case OPTION_OLDER_MTIME: 518d4d8193eSPeter Avalos if (archive_match_include_date(bsdtar->matching, 519d4d8193eSPeter Avalos ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER, 520d4d8193eSPeter Avalos bsdtar->argument) != ARCHIVE_OK) 521d4d8193eSPeter Avalos lafe_errc(1, 0, "Error : %s", 522d4d8193eSPeter Avalos archive_error_string(bsdtar->matching)); 523d4d8193eSPeter Avalos break; 524d4d8193eSPeter Avalos case OPTION_OLDER_MTIME_THAN: 525d4d8193eSPeter Avalos if (archive_match_include_file_time(bsdtar->matching, 526d4d8193eSPeter Avalos ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER, 527d4d8193eSPeter Avalos bsdtar->argument) != ARCHIVE_OK) 528d4d8193eSPeter Avalos lafe_errc(1, 0, "Error : %s", 529d4d8193eSPeter Avalos archive_error_string(bsdtar->matching)); 530d4d8193eSPeter Avalos break; 53160b4ad09SPeter Avalos case OPTION_ONE_FILE_SYSTEM: /* GNU tar */ 53259bf7050SPeter Avalos bsdtar->readdisk_flags |= 53359bf7050SPeter Avalos ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS; 53460b4ad09SPeter Avalos break; 535c09f92d2SPeter Avalos case OPTION_OPTIONS: 536c09f92d2SPeter Avalos bsdtar->option_options = bsdtar->argument; 537c09f92d2SPeter Avalos break; 53860b4ad09SPeter Avalos #if 0 53960b4ad09SPeter Avalos /* 54060b4ad09SPeter Avalos * The common BSD -P option is not necessary, since 54160b4ad09SPeter Avalos * our default is to archive symlinks, not follow 54260b4ad09SPeter Avalos * them. This is convenient, as -P conflicts with GNU 54360b4ad09SPeter Avalos * tar anyway. 54460b4ad09SPeter Avalos */ 54560b4ad09SPeter Avalos case 'P': /* BSD convention */ 54660b4ad09SPeter Avalos /* Default behavior, no option necessary. */ 54760b4ad09SPeter Avalos break; 54860b4ad09SPeter Avalos #endif 54960b4ad09SPeter Avalos case 'P': /* GNU tar */ 55060b4ad09SPeter Avalos bsdtar->extract_flags &= ~SECURITY; 55160b4ad09SPeter Avalos bsdtar->option_absolute_paths = 1; 55260b4ad09SPeter Avalos break; 55360b4ad09SPeter Avalos case 'p': /* GNU tar, star */ 55460b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM; 55560b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL; 55660b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR; 55760b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; 558c09f92d2SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_MAC_METADATA; 55960b4ad09SPeter Avalos break; 560*6b384f39SPeter Avalos case OPTION_PASSPHRASE: 561*6b384f39SPeter Avalos bsdtar->passphrase = bsdtar->argument; 562*6b384f39SPeter Avalos break; 56360b4ad09SPeter Avalos case OPTION_POSIX: /* GNU tar */ 564d4d8193eSPeter Avalos cset_set_format(bsdtar->cset, "pax"); 56560b4ad09SPeter Avalos break; 56660b4ad09SPeter Avalos case 'q': /* FreeBSD GNU tar --fast-read, NetBSD -q */ 56760b4ad09SPeter Avalos bsdtar->option_fast_read = 1; 56860b4ad09SPeter Avalos break; 56960b4ad09SPeter Avalos case 'r': /* SUSv2 */ 57060b4ad09SPeter Avalos set_mode(bsdtar, opt); 57160b4ad09SPeter Avalos break; 57260b4ad09SPeter Avalos case 'S': /* NetBSD pax-as-tar */ 57360b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_SPARSE; 57460b4ad09SPeter Avalos break; 57560b4ad09SPeter Avalos case 's': /* NetBSD pax-as-tar */ 576d4d8193eSPeter Avalos #if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) 577c09f92d2SPeter Avalos add_substitution(bsdtar, bsdtar->argument); 57860b4ad09SPeter Avalos #else 5799c82a63eSPeter Avalos lafe_warnc(0, 5808029ab02SPeter Avalos "-s is not supported by this version of bsdtar"); 5819c82a63eSPeter Avalos usage(); 58260b4ad09SPeter Avalos #endif 58360b4ad09SPeter Avalos break; 5848029ab02SPeter Avalos case OPTION_SAME_OWNER: /* GNU tar */ 5858029ab02SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER; 5868029ab02SPeter Avalos break; 58760b4ad09SPeter Avalos case OPTION_STRIP_COMPONENTS: /* GNU tar 1.15 */ 588c09f92d2SPeter Avalos errno = 0; 589c09f92d2SPeter Avalos bsdtar->strip_components = strtol(bsdtar->argument, 590c09f92d2SPeter Avalos NULL, 0); 591c09f92d2SPeter Avalos if (errno) 592c09f92d2SPeter Avalos lafe_errc(1, 0, 593c09f92d2SPeter Avalos "Invalid --strip-components argument: %s", 594c09f92d2SPeter Avalos bsdtar->argument); 59560b4ad09SPeter Avalos break; 59660b4ad09SPeter Avalos case 'T': /* GNU tar */ 597c09f92d2SPeter Avalos bsdtar->names_from_file = bsdtar->argument; 59860b4ad09SPeter Avalos break; 59960b4ad09SPeter Avalos case 't': /* SUSv2 */ 60060b4ad09SPeter Avalos set_mode(bsdtar, opt); 60160b4ad09SPeter Avalos bsdtar->verbose++; 60260b4ad09SPeter Avalos break; 60360b4ad09SPeter Avalos case OPTION_TOTALS: /* GNU tar */ 60460b4ad09SPeter Avalos bsdtar->option_totals++; 60560b4ad09SPeter Avalos break; 60660b4ad09SPeter Avalos case 'U': /* GNU tar */ 60760b4ad09SPeter Avalos bsdtar->extract_flags |= ARCHIVE_EXTRACT_UNLINK; 60860b4ad09SPeter Avalos bsdtar->option_unlink_first = 1; 60960b4ad09SPeter Avalos break; 61060b4ad09SPeter Avalos case 'u': /* SUSv2 */ 61160b4ad09SPeter Avalos set_mode(bsdtar, opt); 61260b4ad09SPeter Avalos break; 613c09f92d2SPeter Avalos case OPTION_UID: /* cpio */ 614c09f92d2SPeter Avalos t = atoi(bsdtar->argument); 615c09f92d2SPeter Avalos if (t < 0) 616c09f92d2SPeter Avalos lafe_errc(1, 0, 617c09f92d2SPeter Avalos "Argument to --uid must be positive"); 618c09f92d2SPeter Avalos bsdtar->uid = t; 619c09f92d2SPeter Avalos break; 620c09f92d2SPeter Avalos case OPTION_UNAME: /* cpio */ 621c09f92d2SPeter Avalos bsdtar->uname = bsdtar->argument; 622c09f92d2SPeter Avalos break; 623d4d8193eSPeter Avalos case OPTION_UUENCODE: 624d4d8193eSPeter Avalos if (compression2 != '\0') 625d4d8193eSPeter Avalos lafe_errc(1, 0, 626d4d8193eSPeter Avalos "Can't specify both --uuencode and " 627d4d8193eSPeter Avalos "--b64encode"); 628d4d8193eSPeter Avalos compression2 = opt; 629d4d8193eSPeter Avalos compression2_name = "uuencode"; 630d4d8193eSPeter Avalos break; 63160b4ad09SPeter Avalos case 'v': /* SUSv2 */ 63260b4ad09SPeter Avalos bsdtar->verbose++; 63360b4ad09SPeter Avalos break; 63460b4ad09SPeter Avalos case OPTION_VERSION: /* GNU convention */ 63560b4ad09SPeter Avalos version(); 63660b4ad09SPeter Avalos break; 63760b4ad09SPeter Avalos #if 0 63860b4ad09SPeter Avalos /* 63960b4ad09SPeter Avalos * The -W longopt feature is handled inside of 6408029ab02SPeter Avalos * bsdtar_getopt(), so -W is not available here. 64160b4ad09SPeter Avalos */ 6428029ab02SPeter Avalos case 'W': /* Obscure GNU convention. */ 64360b4ad09SPeter Avalos break; 64460b4ad09SPeter Avalos #endif 64560b4ad09SPeter Avalos case 'w': /* SUSv2 */ 64660b4ad09SPeter Avalos bsdtar->option_interactive = 1; 64760b4ad09SPeter Avalos break; 64860b4ad09SPeter Avalos case 'X': /* GNU tar */ 64959bf7050SPeter Avalos if (archive_match_exclude_pattern_from_file( 65059bf7050SPeter Avalos bsdtar->matching, bsdtar->argument, 0) 65159bf7050SPeter Avalos != ARCHIVE_OK) 65259bf7050SPeter Avalos lafe_errc(1, 0, "Error : %s", 65359bf7050SPeter Avalos archive_error_string(bsdtar->matching)); 65460b4ad09SPeter Avalos break; 65560b4ad09SPeter Avalos case 'x': /* SUSv2 */ 65660b4ad09SPeter Avalos set_mode(bsdtar, opt); 65760b4ad09SPeter Avalos break; 65860b4ad09SPeter Avalos case 'y': /* FreeBSD version of GNU tar */ 659d4d8193eSPeter Avalos if (compression != '\0') 6609c82a63eSPeter Avalos lafe_errc(1, 0, 66160b4ad09SPeter Avalos "Can't specify both -%c and -%c", opt, 662d4d8193eSPeter Avalos compression); 663d4d8193eSPeter Avalos compression = opt; 664d4d8193eSPeter Avalos compression_name = "bzip2"; 66560b4ad09SPeter Avalos break; 66660b4ad09SPeter Avalos case 'Z': /* GNU tar */ 667d4d8193eSPeter Avalos if (compression != '\0') 6689c82a63eSPeter Avalos lafe_errc(1, 0, 66960b4ad09SPeter Avalos "Can't specify both -%c and -%c", opt, 670d4d8193eSPeter Avalos compression); 671d4d8193eSPeter Avalos compression = opt; 672d4d8193eSPeter Avalos compression_name = "compress"; 67360b4ad09SPeter Avalos break; 67460b4ad09SPeter Avalos case 'z': /* GNU tar, star, many others */ 675d4d8193eSPeter Avalos if (compression != '\0') 6769c82a63eSPeter Avalos lafe_errc(1, 0, 67760b4ad09SPeter Avalos "Can't specify both -%c and -%c", opt, 678d4d8193eSPeter Avalos compression); 679d4d8193eSPeter Avalos compression = opt; 680d4d8193eSPeter Avalos compression_name = "gzip"; 68160b4ad09SPeter Avalos break; 68260b4ad09SPeter Avalos case OPTION_USE_COMPRESS_PROGRAM: 683d4d8193eSPeter Avalos compress_program = bsdtar->argument; 68460b4ad09SPeter Avalos break; 68560b4ad09SPeter Avalos default: 6869c82a63eSPeter Avalos usage(); 68760b4ad09SPeter Avalos } 68860b4ad09SPeter Avalos } 68960b4ad09SPeter Avalos 69060b4ad09SPeter Avalos /* 69160b4ad09SPeter Avalos * Sanity-check options. 69260b4ad09SPeter Avalos */ 69360b4ad09SPeter Avalos 69460b4ad09SPeter Avalos /* If no "real" mode was specified, treat -h as --help. */ 69560b4ad09SPeter Avalos if ((bsdtar->mode == '\0') && possible_help_request) { 6969c82a63eSPeter Avalos long_help(); 69760b4ad09SPeter Avalos exit(0); 69860b4ad09SPeter Avalos } 69960b4ad09SPeter Avalos 70060b4ad09SPeter Avalos /* Otherwise, a mode is required. */ 70160b4ad09SPeter Avalos if (bsdtar->mode == '\0') 7029c82a63eSPeter Avalos lafe_errc(1, 0, 70360b4ad09SPeter Avalos "Must specify one of -c, -r, -t, -u, -x"); 70460b4ad09SPeter Avalos 70560b4ad09SPeter Avalos /* Check boolean options only permitted in certain modes. */ 706d4d8193eSPeter Avalos if (option_a) 707d4d8193eSPeter Avalos only_mode(bsdtar, "-a", "c"); 70859bf7050SPeter Avalos if (bsdtar->readdisk_flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) 70960b4ad09SPeter Avalos only_mode(bsdtar, "--one-file-system", "cru"); 71060b4ad09SPeter Avalos if (bsdtar->option_fast_read) 71160b4ad09SPeter Avalos only_mode(bsdtar, "--fast-read", "xt"); 712d4d8193eSPeter Avalos if (bsdtar->extract_flags & ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED) 713d4d8193eSPeter Avalos only_mode(bsdtar, "--hfsCompression", "x"); 714d4d8193eSPeter Avalos if (bsdtar->extract_flags & ARCHIVE_EXTRACT_NO_HFS_COMPRESSION) 715d4d8193eSPeter Avalos only_mode(bsdtar, "--nopreserveHFSCompression", "x"); 71659bf7050SPeter Avalos if (bsdtar->readdisk_flags & ARCHIVE_READDISK_HONOR_NODUMP) 71760b4ad09SPeter Avalos only_mode(bsdtar, "--nodump", "cru"); 718*6b384f39SPeter Avalos if (bsdtar->readdisk_flags & ARCHIVE_READDISK_NO_XATTR) 719*6b384f39SPeter Avalos only_mode(bsdtar, "--no-xattr", "crux"); 72060b4ad09SPeter Avalos if (option_o > 0) { 72160b4ad09SPeter Avalos switch (bsdtar->mode) { 72260b4ad09SPeter Avalos case 'c': 72360b4ad09SPeter Avalos /* 72460b4ad09SPeter Avalos * In GNU tar, -o means "old format." The 72560b4ad09SPeter Avalos * "ustar" format is the closest thing 72660b4ad09SPeter Avalos * supported by libarchive. 72760b4ad09SPeter Avalos */ 728d4d8193eSPeter Avalos cset_set_format(bsdtar->cset, "ustar"); 72960b4ad09SPeter Avalos /* TODO: bsdtar->create_format = "v7"; */ 73060b4ad09SPeter Avalos break; 73160b4ad09SPeter Avalos case 'x': 73260b4ad09SPeter Avalos /* POSIX-compatible behavior. */ 73360b4ad09SPeter Avalos bsdtar->option_no_owner = 1; 73460b4ad09SPeter Avalos bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER; 73560b4ad09SPeter Avalos break; 73660b4ad09SPeter Avalos default: 73760b4ad09SPeter Avalos only_mode(bsdtar, "-o", "xc"); 73860b4ad09SPeter Avalos break; 73960b4ad09SPeter Avalos } 74060b4ad09SPeter Avalos } 74160b4ad09SPeter Avalos if (bsdtar->option_no_subdirs) 74260b4ad09SPeter Avalos only_mode(bsdtar, "-n", "cru"); 74360b4ad09SPeter Avalos if (bsdtar->option_stdout) 74460b4ad09SPeter Avalos only_mode(bsdtar, "-O", "xt"); 74560b4ad09SPeter Avalos if (bsdtar->option_unlink_first) 74660b4ad09SPeter Avalos only_mode(bsdtar, "-U", "x"); 74760b4ad09SPeter Avalos if (bsdtar->option_warn_links) 74860b4ad09SPeter Avalos only_mode(bsdtar, "--check-links", "cr"); 74960b4ad09SPeter Avalos 750d4d8193eSPeter Avalos if (option_a && cset_auto_compress(bsdtar->cset, bsdtar->filename)) { 751d4d8193eSPeter Avalos /* Ignore specified compressions if auto-compress works. */ 752d4d8193eSPeter Avalos compression = '\0'; 753d4d8193eSPeter Avalos compression2 = '\0'; 75460b4ad09SPeter Avalos } 755d4d8193eSPeter Avalos /* Check other parameters only permitted in certain modes. */ 756d4d8193eSPeter Avalos if (compress_program != NULL) { 757d4d8193eSPeter Avalos only_mode(bsdtar, "--use-compress-program", "cxt"); 758d4d8193eSPeter Avalos cset_add_filter_program(bsdtar->cset, compress_program); 759d4d8193eSPeter Avalos /* Ignore specified compressions. */ 760d4d8193eSPeter Avalos compression = '\0'; 761d4d8193eSPeter Avalos compression2 = '\0'; 762d4d8193eSPeter Avalos } 763d4d8193eSPeter Avalos if (compression != '\0') { 764d4d8193eSPeter Avalos switch (compression) { 765d4d8193eSPeter Avalos case 'J': case 'j': case 'y': case 'Z': case 'z': 766d4d8193eSPeter Avalos strcpy(buff, "-?"); 767d4d8193eSPeter Avalos buff[1] = compression; 768d4d8193eSPeter Avalos break; 769d4d8193eSPeter Avalos default: 770d4d8193eSPeter Avalos strcpy(buff, "--"); 771d4d8193eSPeter Avalos strcat(buff, compression_name); 772d4d8193eSPeter Avalos break; 773d4d8193eSPeter Avalos } 774d4d8193eSPeter Avalos only_mode(bsdtar, buff, "cxt"); 775d4d8193eSPeter Avalos cset_add_filter(bsdtar->cset, compression_name); 776d4d8193eSPeter Avalos } 777d4d8193eSPeter Avalos if (compression2 != '\0') { 778d4d8193eSPeter Avalos strcpy(buff, "--"); 779d4d8193eSPeter Avalos strcat(buff, compression2_name); 780d4d8193eSPeter Avalos only_mode(bsdtar, buff, "cxt"); 781d4d8193eSPeter Avalos cset_add_filter(bsdtar->cset, compression2_name); 782d4d8193eSPeter Avalos } 783d4d8193eSPeter Avalos if (cset_get_format(bsdtar->cset) != NULL) 78460b4ad09SPeter Avalos only_mode(bsdtar, "--format", "cru"); 78560b4ad09SPeter Avalos if (bsdtar->symlink_mode != '\0') { 78660b4ad09SPeter Avalos strcpy(buff, "-?"); 78760b4ad09SPeter Avalos buff[1] = bsdtar->symlink_mode; 78860b4ad09SPeter Avalos only_mode(bsdtar, buff, "cru"); 78960b4ad09SPeter Avalos } 790c09f92d2SPeter Avalos 791c09f92d2SPeter Avalos /* Filename "-" implies stdio. */ 792c09f92d2SPeter Avalos if (strcmp(bsdtar->filename, "-") == 0) 793c09f92d2SPeter Avalos bsdtar->filename = NULL; 79460b4ad09SPeter Avalos 79560b4ad09SPeter Avalos switch(bsdtar->mode) { 79660b4ad09SPeter Avalos case 'c': 79760b4ad09SPeter Avalos tar_mode_c(bsdtar); 79860b4ad09SPeter Avalos break; 79960b4ad09SPeter Avalos case 'r': 80060b4ad09SPeter Avalos tar_mode_r(bsdtar); 80160b4ad09SPeter Avalos break; 80260b4ad09SPeter Avalos case 't': 80360b4ad09SPeter Avalos tar_mode_t(bsdtar); 80460b4ad09SPeter Avalos break; 80560b4ad09SPeter Avalos case 'u': 80660b4ad09SPeter Avalos tar_mode_u(bsdtar); 80760b4ad09SPeter Avalos break; 80860b4ad09SPeter Avalos case 'x': 80960b4ad09SPeter Avalos tar_mode_x(bsdtar); 81060b4ad09SPeter Avalos break; 81160b4ad09SPeter Avalos } 81260b4ad09SPeter Avalos 81359bf7050SPeter Avalos archive_match_free(bsdtar->matching); 814d4d8193eSPeter Avalos #if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) 81560b4ad09SPeter Avalos cleanup_substitution(bsdtar); 81660b4ad09SPeter Avalos #endif 817d4d8193eSPeter Avalos cset_free(bsdtar->cset); 818*6b384f39SPeter Avalos passphrase_free(bsdtar->ppbuff); 81960b4ad09SPeter Avalos 82060b4ad09SPeter Avalos if (bsdtar->return_value != 0) 8219c82a63eSPeter Avalos lafe_warnc(0, 82260b4ad09SPeter Avalos "Error exit delayed from previous errors."); 82360b4ad09SPeter Avalos return (bsdtar->return_value); 82460b4ad09SPeter Avalos } 82560b4ad09SPeter Avalos 82660b4ad09SPeter Avalos static void 82760b4ad09SPeter Avalos set_mode(struct bsdtar *bsdtar, char opt) 82860b4ad09SPeter Avalos { 82960b4ad09SPeter Avalos if (bsdtar->mode != '\0' && bsdtar->mode != opt) 8309c82a63eSPeter Avalos lafe_errc(1, 0, 83160b4ad09SPeter Avalos "Can't specify both -%c and -%c", opt, bsdtar->mode); 83260b4ad09SPeter Avalos bsdtar->mode = opt; 83360b4ad09SPeter Avalos } 83460b4ad09SPeter Avalos 83560b4ad09SPeter Avalos /* 83660b4ad09SPeter Avalos * Verify that the mode is correct. 83760b4ad09SPeter Avalos */ 83860b4ad09SPeter Avalos static void 83960b4ad09SPeter Avalos only_mode(struct bsdtar *bsdtar, const char *opt, const char *valid_modes) 84060b4ad09SPeter Avalos { 84160b4ad09SPeter Avalos if (strchr(valid_modes, bsdtar->mode) == NULL) 8429c82a63eSPeter Avalos lafe_errc(1, 0, 84360b4ad09SPeter Avalos "Option %s is not permitted in mode -%c", 84460b4ad09SPeter Avalos opt, bsdtar->mode); 84560b4ad09SPeter Avalos } 84660b4ad09SPeter Avalos 84760b4ad09SPeter Avalos 84860b4ad09SPeter Avalos void 8499c82a63eSPeter Avalos usage(void) 85060b4ad09SPeter Avalos { 85160b4ad09SPeter Avalos const char *p; 85260b4ad09SPeter Avalos 853*6b384f39SPeter Avalos p = lafe_getprogname(); 85460b4ad09SPeter Avalos 85560b4ad09SPeter Avalos fprintf(stderr, "Usage:\n"); 85660b4ad09SPeter Avalos fprintf(stderr, " List: %s -tf <archive-filename>\n", p); 85760b4ad09SPeter Avalos fprintf(stderr, " Extract: %s -xf <archive-filename>\n", p); 85860b4ad09SPeter Avalos fprintf(stderr, " Create: %s -cf <archive-filename> [filenames...]\n", p); 85960b4ad09SPeter Avalos fprintf(stderr, " Help: %s --help\n", p); 86060b4ad09SPeter Avalos exit(1); 86160b4ad09SPeter Avalos } 86260b4ad09SPeter Avalos 86360b4ad09SPeter Avalos static void 86460b4ad09SPeter Avalos version(void) 86560b4ad09SPeter Avalos { 86660b4ad09SPeter Avalos printf("bsdtar %s - %s\n", 86760b4ad09SPeter Avalos BSDTAR_VERSION_STRING, 868*6b384f39SPeter Avalos archive_version_details()); 86960b4ad09SPeter Avalos exit(0); 87060b4ad09SPeter Avalos } 87160b4ad09SPeter Avalos 87260b4ad09SPeter Avalos static const char *long_help_msg = 87360b4ad09SPeter Avalos "First option must be a mode specifier:\n" 87460b4ad09SPeter Avalos " -c Create -r Add/Replace -t List -u Update -x Extract\n" 87560b4ad09SPeter Avalos "Common Options:\n" 87660b4ad09SPeter Avalos " -b # Use # 512-byte records per I/O block\n" 87760b4ad09SPeter Avalos " -f <filename> Location of archive (default " _PATH_DEFTAPE ")\n" 87860b4ad09SPeter Avalos " -v Verbose\n" 87960b4ad09SPeter Avalos " -w Interactive\n" 88060b4ad09SPeter Avalos "Create: %p -c [options] [<file> | <dir> | @<archive> | -C <dir> ]\n" 88160b4ad09SPeter Avalos " <file>, <dir> add these items to archive\n" 8828029ab02SPeter Avalos " -z, -j, -J, --lzma Compress archive with gzip/bzip2/xz/lzma\n" 88360b4ad09SPeter Avalos " --format {ustar|pax|cpio|shar} Select archive format\n" 88460b4ad09SPeter Avalos " --exclude <pattern> Skip files that match pattern\n" 88560b4ad09SPeter Avalos " -C <dir> Change to <dir> before processing remaining files\n" 88660b4ad09SPeter Avalos " @<archive> Add entries from <archive> to output\n" 88760b4ad09SPeter Avalos "List: %p -t [options] [<patterns>]\n" 88860b4ad09SPeter Avalos " <patterns> If specified, list only entries that match\n" 88960b4ad09SPeter Avalos "Extract: %p -x [options] [<patterns>]\n" 89060b4ad09SPeter Avalos " <patterns> If specified, extract only entries that match\n" 89160b4ad09SPeter Avalos " -k Keep (don't overwrite) existing files\n" 89260b4ad09SPeter Avalos " -m Don't restore modification times\n" 89360b4ad09SPeter Avalos " -O Write entries to stdout, don't restore to disk\n" 89460b4ad09SPeter Avalos " -p Restore permissions (including ACLs, owner, file flags)\n"; 89560b4ad09SPeter Avalos 89660b4ad09SPeter Avalos 89760b4ad09SPeter Avalos /* 89860b4ad09SPeter Avalos * Note that the word 'bsdtar' will always appear in the first line 89960b4ad09SPeter Avalos * of output. 90060b4ad09SPeter Avalos * 90160b4ad09SPeter Avalos * In particular, /bin/sh scripts that need to test for the presence 90260b4ad09SPeter Avalos * of bsdtar can use the following template: 90360b4ad09SPeter Avalos * 90460b4ad09SPeter Avalos * if (tar --help 2>&1 | grep bsdtar >/dev/null 2>&1 ) then \ 90560b4ad09SPeter Avalos * echo bsdtar; else echo not bsdtar; fi 90660b4ad09SPeter Avalos */ 90760b4ad09SPeter Avalos static void 9089c82a63eSPeter Avalos long_help(void) 90960b4ad09SPeter Avalos { 91060b4ad09SPeter Avalos const char *prog; 91160b4ad09SPeter Avalos const char *p; 91260b4ad09SPeter Avalos 913*6b384f39SPeter Avalos prog = lafe_getprogname(); 91460b4ad09SPeter Avalos 91560b4ad09SPeter Avalos fflush(stderr); 91660b4ad09SPeter Avalos 91760b4ad09SPeter Avalos p = (strcmp(prog,"bsdtar") != 0) ? "(bsdtar)" : ""; 91860b4ad09SPeter Avalos printf("%s%s: manipulate archive files\n", prog, p); 91960b4ad09SPeter Avalos 92060b4ad09SPeter Avalos for (p = long_help_msg; *p != '\0'; p++) { 92160b4ad09SPeter Avalos if (*p == '%') { 92260b4ad09SPeter Avalos if (p[1] == 'p') { 92360b4ad09SPeter Avalos fputs(prog, stdout); 92460b4ad09SPeter Avalos p++; 92560b4ad09SPeter Avalos } else 92660b4ad09SPeter Avalos putchar('%'); 92760b4ad09SPeter Avalos } else 92860b4ad09SPeter Avalos putchar(*p); 92960b4ad09SPeter Avalos } 93060b4ad09SPeter Avalos version(); 93160b4ad09SPeter Avalos } 932