1228753Smm/*- 2228753Smm * Copyright (c) 2003-2008 Tim Kientzle 3228753Smm * All rights reserved. 4228753Smm * 5228753Smm * Redistribution and use in source and binary forms, with or without 6228753Smm * modification, are permitted provided that the following conditions 7228753Smm * are met: 8228753Smm * 1. Redistributions of source code must retain the above copyright 9228753Smm * notice, this list of conditions and the following disclaimer. 10228753Smm * 2. Redistributions in binary form must reproduce the above copyright 11228753Smm * notice, this list of conditions and the following disclaimer in the 12228753Smm * documentation and/or other materials provided with the distribution. 13228753Smm * 14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24228753Smm */ 25228753Smm 26228753Smm#include "bsdtar_platform.h" 27228763Smm__FBSDID("$FreeBSD: stable/10/contrib/libarchive/tar/bsdtar.c 358090 2020-02-19 01:51:44Z mm $"); 28228753Smm 29228753Smm#ifdef HAVE_SYS_PARAM_H 30228753Smm#include <sys/param.h> 31228753Smm#endif 32228753Smm#ifdef HAVE_SYS_STAT_H 33228753Smm#include <sys/stat.h> 34228753Smm#endif 35232153Smm#ifdef HAVE_COPYFILE_H 36232153Smm#include <copyfile.h> 37232153Smm#endif 38228753Smm#ifdef HAVE_ERRNO_H 39228753Smm#include <errno.h> 40228753Smm#endif 41228753Smm#ifdef HAVE_FCNTL_H 42228753Smm#include <fcntl.h> 43228753Smm#endif 44228753Smm#ifdef HAVE_LANGINFO_H 45228753Smm#include <langinfo.h> 46228753Smm#endif 47228753Smm#ifdef HAVE_LOCALE_H 48228753Smm#include <locale.h> 49228753Smm#endif 50228753Smm#ifdef HAVE_PATHS_H 51228753Smm#include <paths.h> 52228753Smm#endif 53228753Smm#ifdef HAVE_SIGNAL_H 54228753Smm#include <signal.h> 55228753Smm#endif 56228753Smm#include <stdio.h> 57228753Smm#ifdef HAVE_STDLIB_H 58228753Smm#include <stdlib.h> 59228753Smm#endif 60228753Smm#ifdef HAVE_STRING_H 61228753Smm#include <string.h> 62228753Smm#endif 63228753Smm#ifdef HAVE_TIME_H 64228753Smm#include <time.h> 65228753Smm#endif 66228753Smm#ifdef HAVE_UNISTD_H 67228753Smm#include <unistd.h> 68228753Smm#endif 69228753Smm 70228753Smm#include "bsdtar.h" 71228753Smm#include "err.h" 72228753Smm 73228753Smm/* 74228753Smm * Per POSIX.1-1988, tar defaults to reading/writing archives to/from 75228753Smm * the default tape device for the system. Pick something reasonable here. 76228753Smm */ 77228753Smm#ifdef __linux 78228753Smm#define _PATH_DEFTAPE "/dev/st0" 79228753Smm#endif 80228753Smm#if defined(_WIN32) && !defined(__CYGWIN__) 81228753Smm#define _PATH_DEFTAPE "\\\\.\\tape0" 82228753Smm#endif 83232153Smm#if defined(__APPLE__) 84232153Smm#undef _PATH_DEFTAPE 85232153Smm#define _PATH_DEFTAPE "-" /* Mac OS has no tape support, default to stdio. */ 86232153Smm#endif 87228753Smm 88228753Smm#ifndef _PATH_DEFTAPE 89228753Smm#define _PATH_DEFTAPE "/dev/tape" 90228753Smm#endif 91228753Smm 92228753Smm#ifdef __MINGW32__ 93228753Smmint _CRT_glob = 0; /* Disable broken CRT globbing. */ 94228753Smm#endif 95228753Smm 96228753Smm#if defined(HAVE_SIGACTION) && (defined(SIGINFO) || defined(SIGUSR1)) 97228753Smmstatic volatile int siginfo_occurred; 98228753Smm 99228753Smmstatic void 100228753Smmsiginfo_handler(int sig) 101228753Smm{ 102228753Smm (void)sig; /* UNUSED */ 103228753Smm siginfo_occurred = 1; 104228753Smm} 105228753Smm 106228753Smmint 107228753Smmneed_report(void) 108228753Smm{ 109228753Smm int r = siginfo_occurred; 110228753Smm siginfo_occurred = 0; 111228753Smm return (r); 112228753Smm} 113228753Smm#else 114228753Smmint 115228753Smmneed_report(void) 116228753Smm{ 117228753Smm return (0); 118228753Smm} 119228753Smm#endif 120228753Smm 121315433Smmstatic void long_help(void) __LA_DEAD; 122228753Smmstatic void only_mode(struct bsdtar *, const char *opt, 123228753Smm const char *valid); 124228753Smmstatic void set_mode(struct bsdtar *, char opt); 125315433Smmstatic void version(void) __LA_DEAD; 126228753Smm 127228753Smm/* A basic set of security flags to request from libarchive. */ 128228753Smm#define SECURITY \ 129228753Smm (ARCHIVE_EXTRACT_SECURE_SYMLINKS \ 130228753Smm | ARCHIVE_EXTRACT_SECURE_NODOTDOT) 131228753Smm 132348608Smmstatic char const * const vcs_files[] = { 133348608Smm /* CVS */ 134348608Smm "CVS", ".cvsignore", 135348608Smm /* RCS */ 136348608Smm "RCS", 137348608Smm /* SCCS */ 138348608Smm "SCCS", 139348608Smm /* SVN */ 140348608Smm ".svn", 141348608Smm /* git */ 142348608Smm ".git", ".gitignore", ".gitattributes", ".gitmodules", 143348608Smm /* Arch */ 144348608Smm ".arch-ids", "{arch}", "=RELEASE-ID", "=meta-update", "=update", 145348608Smm /* Bazaar */ 146348608Smm ".bzr", ".bzrignore", ".bzrtags", 147348608Smm /* Mercurial */ 148348608Smm ".hg", ".hgignore", ".hgtags", 149348608Smm /* darcs */ 150348608Smm "_darcs", 151348608Smm NULL 152348608Smm}; 153348608Smm 154228753Smmint 155228753Smmmain(int argc, char **argv) 156228753Smm{ 157228753Smm struct bsdtar *bsdtar, bsdtar_storage; 158228753Smm int opt, t; 159248616Smm char compression, compression2; 160248616Smm const char *compression_name, *compression2_name; 161248616Smm const char *compress_program; 162342361Smm char *tptr; 163228753Smm char possible_help_request; 164228753Smm char buff[16]; 165228753Smm 166228753Smm /* 167228753Smm * Use a pointer for consistency, but stack-allocated storage 168228753Smm * for ease of cleanup. 169228753Smm */ 170232153Smm bsdtar = &bsdtar_storage; 171228753Smm memset(bsdtar, 0, sizeof(*bsdtar)); 172228753Smm bsdtar->fd = -1; /* Mark as "unused" */ 173228753Smm bsdtar->gid = -1; 174228753Smm bsdtar->uid = -1; 175315433Smm bsdtar->flags = 0; 176248616Smm compression = compression2 = '\0'; 177248616Smm compression_name = compression2_name = NULL; 178248616Smm compress_program = NULL; 179228753Smm 180232153Smm#if defined(HAVE_SIGACTION) 181232153Smm { /* Set up signal handling. */ 182228753Smm struct sigaction sa; 183228753Smm sa.sa_handler = siginfo_handler; 184228753Smm sigemptyset(&sa.sa_mask); 185228753Smm sa.sa_flags = 0; 186228753Smm#ifdef SIGINFO 187228753Smm if (sigaction(SIGINFO, &sa, NULL)) 188228753Smm lafe_errc(1, errno, "sigaction(SIGINFO) failed"); 189228753Smm#endif 190228753Smm#ifdef SIGUSR1 191228753Smm /* ... and treat SIGUSR1 the same way as SIGINFO. */ 192228753Smm if (sigaction(SIGUSR1, &sa, NULL)) 193228753Smm lafe_errc(1, errno, "sigaction(SIGUSR1) failed"); 194228753Smm#endif 195232153Smm#ifdef SIGPIPE 196232153Smm /* Ignore SIGPIPE signals. */ 197232153Smm sa.sa_handler = SIG_IGN; 198232153Smm sigaction(SIGPIPE, &sa, NULL); 199232153Smm#endif 200228753Smm } 201228753Smm#endif 202228753Smm 203302001Smm /* Set lafe_progname before calling lafe_warnc. */ 204302001Smm lafe_setprogname(*argv, "bsdtar"); 205228753Smm 206228753Smm#if HAVE_SETLOCALE 207228753Smm if (setlocale(LC_ALL, "") == NULL) 208228753Smm lafe_warnc(0, "Failed to set default locale"); 209228753Smm#endif 210228753Smm#if defined(HAVE_NL_LANGINFO) && defined(HAVE_D_MD_ORDER) 211228753Smm bsdtar->day_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 212228753Smm#endif 213228753Smm possible_help_request = 0; 214228753Smm 215228753Smm /* Look up uid of current user for future reference */ 216228753Smm bsdtar->user_uid = geteuid(); 217228753Smm 218228753Smm /* Default: open tape drive. */ 219228753Smm bsdtar->filename = getenv("TAPE"); 220228753Smm if (bsdtar->filename == NULL) 221228753Smm bsdtar->filename = _PATH_DEFTAPE; 222228753Smm 223232153Smm /* Default block size settings. */ 224232153Smm bsdtar->bytes_per_block = DEFAULT_BYTES_PER_BLOCK; 225232153Smm /* Allow library to default this unless user specifies -b. */ 226232153Smm bsdtar->bytes_in_last_block = -1; 227232153Smm 228228753Smm /* Default: preserve mod time on extract */ 229228753Smm bsdtar->extract_flags = ARCHIVE_EXTRACT_TIME; 230228753Smm 231228753Smm /* Default: Perform basic security checks. */ 232228753Smm bsdtar->extract_flags |= SECURITY; 233228753Smm 234228753Smm#ifndef _WIN32 235228753Smm /* On POSIX systems, assume --same-owner and -p when run by 236228753Smm * the root user. This doesn't make any sense on Windows. */ 237228753Smm if (bsdtar->user_uid == 0) { 238228753Smm /* --same-owner */ 239228753Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER; 240228753Smm /* -p */ 241228753Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM; 242228753Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL; 243228753Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR; 244228753Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; 245232153Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_MAC_METADATA; 246228753Smm } 247228753Smm#endif 248228753Smm 249232153Smm /* 250232153Smm * Enable Mac OS "copyfile()" extension by default. 251232153Smm * This has no effect on other platforms. 252232153Smm */ 253238856Smm bsdtar->readdisk_flags |= ARCHIVE_READDISK_MAC_COPYFILE; 254232153Smm#ifdef COPYFILE_DISABLE_VAR 255232153Smm if (getenv(COPYFILE_DISABLE_VAR)) 256238856Smm bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_MAC_COPYFILE; 257232153Smm#endif 258315433Smm#if defined(__APPLE__) 259315433Smm /* 260315433Smm * On Mac OS ACLs are archived with copyfile() (--mac-metadata) 261315433Smm * Translation to NFSv4 ACLs has to be requested explicitly with --acls 262315433Smm */ 263315433Smm bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_ACL; 264315433Smm#endif 265315433Smm 266238856Smm bsdtar->matching = archive_match_new(); 267238856Smm if (bsdtar->matching == NULL) 268238856Smm lafe_errc(1, errno, "Out of memory"); 269248616Smm bsdtar->cset = cset_new(); 270248616Smm if (bsdtar->cset == NULL) 271248616Smm lafe_errc(1, errno, "Out of memory"); 272232153Smm 273228753Smm bsdtar->argv = argv; 274228753Smm bsdtar->argc = argc; 275228753Smm 276228753Smm /* 277228753Smm * Comments following each option indicate where that option 278228753Smm * originated: SUSv2, POSIX, GNU tar, star, etc. If there's 279228753Smm * no such comment, then I don't know of anyone else who 280228753Smm * implements that option. 281228753Smm */ 282228753Smm while ((opt = bsdtar_getopt(bsdtar)) != -1) { 283228753Smm switch (opt) { 284248616Smm case 'a': /* GNU tar */ 285315433Smm bsdtar->flags |= OPTFLAG_AUTO_COMPRESS; 286248616Smm break; 287315433Smm case OPTION_ACLS: /* GNU tar */ 288315433Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL; 289315433Smm bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_ACL; 290315433Smm bsdtar->flags |= OPTFLAG_ACLS; 291315433Smm break; 292228753Smm case 'B': /* GNU tar */ 293228753Smm /* libarchive doesn't need this; just ignore it. */ 294228753Smm break; 295228753Smm case 'b': /* SUSv2 */ 296342361Smm errno = 0; 297342361Smm tptr = NULL; 298342361Smm t = (int)strtol(bsdtar->argument, &tptr, 10); 299342361Smm if (errno || t <= 0 || t > 8192 || 300342361Smm *(bsdtar->argument) == '\0' || tptr == NULL || 301342361Smm *tptr != '\0') { 302342361Smm lafe_errc(1, 0, "Invalid or out of range " 303342361Smm "(1..8192) argument to -b"); 304342361Smm } 305228753Smm bsdtar->bytes_per_block = 512 * t; 306232153Smm /* Explicit -b forces last block size. */ 307232153Smm bsdtar->bytes_in_last_block = bsdtar->bytes_per_block; 308228753Smm break; 309248616Smm case OPTION_B64ENCODE: 310248616Smm if (compression2 != '\0') 311248616Smm lafe_errc(1, 0, 312248616Smm "Can't specify both --uuencode and " 313248616Smm "--b64encode"); 314248616Smm compression2 = opt; 315248616Smm compression2_name = "b64encode"; 316248616Smm break; 317228753Smm case 'C': /* GNU tar */ 318232153Smm if (strlen(bsdtar->argument) == 0) 319232153Smm lafe_errc(1, 0, 320232153Smm "Meaningless option: -C ''"); 321232153Smm 322232153Smm set_chdir(bsdtar, bsdtar->argument); 323228753Smm break; 324228753Smm case 'c': /* SUSv2 */ 325228753Smm set_mode(bsdtar, opt); 326228753Smm break; 327228753Smm case OPTION_CHECK_LINKS: /* GNU tar */ 328315433Smm bsdtar->flags |= OPTFLAG_WARN_LINKS; 329228753Smm break; 330228753Smm case OPTION_CHROOT: /* NetBSD */ 331315433Smm bsdtar->flags |= OPTFLAG_CHROOT; 332228753Smm break; 333302001Smm case OPTION_CLEAR_NOCHANGE_FFLAGS: 334302001Smm bsdtar->extract_flags |= 335302001Smm ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS; 336302001Smm break; 337228753Smm case OPTION_EXCLUDE: /* GNU tar */ 338238856Smm if (archive_match_exclude_pattern( 339238856Smm bsdtar->matching, bsdtar->argument) != ARCHIVE_OK) 340228753Smm lafe_errc(1, 0, 341232153Smm "Couldn't exclude %s\n", bsdtar->argument); 342228753Smm break; 343348608Smm case OPTION_EXCLUDE_VCS: /* GNU tar */ 344348608Smm for(t=0; vcs_files[t]; t++) { 345348608Smm if (archive_match_exclude_pattern( 346348608Smm bsdtar->matching, 347348608Smm vcs_files[t]) != ARCHIVE_OK) 348348608Smm lafe_errc(1, 0, "Couldn't " 349348608Smm "exclude %s\n", vcs_files[t]); 350348608Smm } 351348608Smm break; 352315433Smm case OPTION_FFLAGS: 353315433Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; 354315433Smm bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_FFLAGS; 355315433Smm bsdtar->flags |= OPTFLAG_FFLAGS; 356315433Smm break; 357228753Smm case OPTION_FORMAT: /* GNU tar, others */ 358248616Smm cset_set_format(bsdtar->cset, bsdtar->argument); 359228753Smm break; 360228753Smm case 'f': /* SUSv2 */ 361232153Smm bsdtar->filename = bsdtar->argument; 362228753Smm break; 363228753Smm case OPTION_GID: /* cpio */ 364342361Smm errno = 0; 365342361Smm tptr = NULL; 366342361Smm t = (int)strtol(bsdtar->argument, &tptr, 10); 367342361Smm if (errno || t < 0 || *(bsdtar->argument) == '\0' || 368342361Smm tptr == NULL || *tptr != '\0') { 369342361Smm lafe_errc(1, 0, "Invalid argument to --gid"); 370342361Smm } 371228753Smm bsdtar->gid = t; 372228753Smm break; 373228753Smm case OPTION_GNAME: /* cpio */ 374232153Smm bsdtar->gname = bsdtar->argument; 375228753Smm break; 376248616Smm case OPTION_GRZIP: 377248616Smm if (compression != '\0') 378248616Smm lafe_errc(1, 0, 379248616Smm "Can't specify both -%c and -%c", opt, 380248616Smm compression); 381248616Smm compression = opt; 382248616Smm compression_name = "grzip"; 383248616Smm break; 384228753Smm case 'H': /* BSD convention */ 385228753Smm bsdtar->symlink_mode = 'H'; 386228753Smm break; 387228753Smm case 'h': /* Linux Standards Base, gtar; synonym for -L */ 388228753Smm bsdtar->symlink_mode = 'L'; 389228753Smm /* Hack: -h by itself is the "help" command. */ 390228753Smm possible_help_request = 1; 391228753Smm break; 392228753Smm case OPTION_HELP: /* GNU tar, others */ 393228753Smm long_help(); 394228753Smm exit(0); 395228753Smm break; 396248616Smm case OPTION_HFS_COMPRESSION: /* Mac OS X v10.6 or later */ 397248616Smm bsdtar->extract_flags |= 398248616Smm ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED; 399248616Smm break; 400302001Smm case OPTION_IGNORE_ZEROS: 401315433Smm bsdtar->flags |= OPTFLAG_IGNORE_ZEROS; 402302001Smm break; 403228753Smm case 'I': /* GNU tar */ 404228753Smm /* 405228753Smm * TODO: Allow 'names' to come from an archive, 406228753Smm * not just a text file. Design a good UI for 407228753Smm * allowing names and mode/owner to be read 408228753Smm * from an archive, with contents coming from 409228753Smm * disk. This can be used to "refresh" an 410228753Smm * archive or to design archives with special 411228753Smm * permissions without having to create those 412228753Smm * permissions on disk. 413228753Smm */ 414232153Smm bsdtar->names_from_file = bsdtar->argument; 415228753Smm break; 416228753Smm case OPTION_INCLUDE: 417228753Smm /* 418232153Smm * No one else has the @archive extension, so 419232153Smm * no one else needs this to filter entries 420228753Smm * when transforming archives. 421228753Smm */ 422238856Smm if (archive_match_include_pattern(bsdtar->matching, 423238856Smm bsdtar->argument) != ARCHIVE_OK) 424228753Smm lafe_errc(1, 0, 425228753Smm "Failed to add %s to inclusion list", 426232153Smm bsdtar->argument); 427228753Smm break; 428228753Smm case 'j': /* GNU tar */ 429248616Smm if (compression != '\0') 430228753Smm lafe_errc(1, 0, 431228753Smm "Can't specify both -%c and -%c", opt, 432248616Smm compression); 433248616Smm compression = opt; 434248616Smm compression_name = "bzip2"; 435228753Smm break; 436228753Smm case 'J': /* GNU tar 1.21 and later */ 437248616Smm if (compression != '\0') 438228753Smm lafe_errc(1, 0, 439228753Smm "Can't specify both -%c and -%c", opt, 440248616Smm compression); 441248616Smm compression = opt; 442248616Smm compression_name = "xz"; 443228753Smm break; 444228753Smm case 'k': /* GNU tar */ 445228753Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE; 446228753Smm break; 447228753Smm case OPTION_KEEP_NEWER_FILES: /* GNU tar */ 448228753Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER; 449228753Smm break; 450228753Smm case 'L': /* BSD convention */ 451228753Smm bsdtar->symlink_mode = 'L'; 452228753Smm break; 453228753Smm case 'l': /* SUSv2 and GNU tar beginning with 1.16 */ 454228753Smm /* GNU tar 1.13 used -l for --one-file-system */ 455315433Smm bsdtar->flags |= OPTFLAG_WARN_LINKS; 456228753Smm break; 457248616Smm case OPTION_LRZIP: 458302001Smm case OPTION_LZ4: 459232153Smm case OPTION_LZIP: /* GNU tar beginning with 1.23 */ 460232153Smm case OPTION_LZMA: /* GNU tar beginning with 1.20 */ 461248616Smm case OPTION_LZOP: /* GNU tar beginning with 1.21 */ 462324418Smm case OPTION_ZSTD: 463248616Smm if (compression != '\0') 464228753Smm lafe_errc(1, 0, 465228753Smm "Can't specify both -%c and -%c", opt, 466248616Smm compression); 467248616Smm compression = opt; 468248616Smm switch (opt) { 469248616Smm case OPTION_LRZIP: compression_name = "lrzip"; break; 470302001Smm case OPTION_LZ4: compression_name = "lz4"; break; 471324418Smm case OPTION_LZIP: compression_name = "lzip"; break; 472324418Smm case OPTION_LZMA: compression_name = "lzma"; break; 473324418Smm case OPTION_LZOP: compression_name = "lzop"; break; 474324418Smm case OPTION_ZSTD: compression_name = "zstd"; break; 475248616Smm } 476228753Smm break; 477228753Smm case 'm': /* SUSv2 */ 478228753Smm bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_TIME; 479228753Smm break; 480315433Smm case OPTION_MAC_METADATA: /* Mac OS X */ 481315433Smm bsdtar->readdisk_flags |= ARCHIVE_READDISK_MAC_COPYFILE; 482315433Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_MAC_METADATA; 483315433Smm bsdtar->flags |= OPTFLAG_MAC_METADATA; 484315433Smm break; 485228753Smm case 'n': /* GNU tar */ 486315433Smm bsdtar->flags |= OPTFLAG_NO_SUBDIRS; 487228753Smm break; 488228753Smm /* 489228753Smm * Selecting files by time: 490228753Smm * --newer-?time='date' Only files newer than 'date' 491228753Smm * --newer-?time-than='file' Only files newer than time 492228753Smm * on specified file (useful for incremental backups) 493228753Smm */ 494228753Smm case OPTION_NEWER_CTIME: /* GNU tar */ 495238856Smm if (archive_match_include_date(bsdtar->matching, 496238856Smm ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER, 497238856Smm bsdtar->argument) != ARCHIVE_OK) 498238856Smm lafe_errc(1, 0, "Error : %s", 499238856Smm archive_error_string(bsdtar->matching)); 500228753Smm break; 501228753Smm case OPTION_NEWER_CTIME_THAN: 502238856Smm if (archive_match_include_file_time(bsdtar->matching, 503238856Smm ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_NEWER, 504238856Smm bsdtar->argument) != ARCHIVE_OK) 505238856Smm lafe_errc(1, 0, "Error : %s", 506238856Smm archive_error_string(bsdtar->matching)); 507228753Smm break; 508228753Smm case OPTION_NEWER_MTIME: /* GNU tar */ 509238856Smm if (archive_match_include_date(bsdtar->matching, 510238856Smm ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER, 511238856Smm bsdtar->argument) != ARCHIVE_OK) 512238856Smm lafe_errc(1, 0, "Error : %s", 513238856Smm archive_error_string(bsdtar->matching)); 514228753Smm break; 515228753Smm case OPTION_NEWER_MTIME_THAN: 516238856Smm if (archive_match_include_file_time(bsdtar->matching, 517238856Smm ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER, 518238856Smm bsdtar->argument) != ARCHIVE_OK) 519238856Smm lafe_errc(1, 0, "Error : %s", 520238856Smm archive_error_string(bsdtar->matching)); 521228753Smm break; 522228753Smm case OPTION_NODUMP: /* star */ 523238856Smm bsdtar->readdisk_flags |= ARCHIVE_READDISK_HONOR_NODUMP; 524228753Smm break; 525248616Smm case OPTION_NOPRESERVE_HFS_COMPRESSION: 526248616Smm /* Mac OS X v10.6 or later */ 527248616Smm bsdtar->extract_flags |= 528248616Smm ARCHIVE_EXTRACT_NO_HFS_COMPRESSION; 529248616Smm break; 530315433Smm case OPTION_NO_ACLS: /* GNU tar */ 531315433Smm bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_ACL; 532315433Smm bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_ACL; 533315433Smm bsdtar->flags |= OPTFLAG_NO_ACLS; 534315433Smm break; 535315433Smm case OPTION_NO_FFLAGS: 536315433Smm bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_FFLAGS; 537315433Smm bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_FFLAGS; 538315433Smm bsdtar->flags |= OPTFLAG_NO_FFLAGS; 539315433Smm break; 540315433Smm case OPTION_NO_MAC_METADATA: /* Mac OS X */ 541315433Smm bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_MAC_COPYFILE; 542315433Smm bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_MAC_METADATA; 543315433Smm bsdtar->flags |= OPTFLAG_NO_MAC_METADATA; 544315433Smm break; 545358090Smm case OPTION_NO_SAFE_WRITES: 546358090Smm bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_SAFE_WRITES; 547358090Smm break; 548228753Smm case OPTION_NO_SAME_OWNER: /* GNU tar */ 549228753Smm bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER; 550228753Smm break; 551228753Smm case OPTION_NO_SAME_PERMISSIONS: /* GNU tar */ 552228753Smm bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_PERM; 553228753Smm bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_ACL; 554228753Smm bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_XATTR; 555228753Smm bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_FFLAGS; 556232153Smm bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_MAC_METADATA; 557228753Smm break; 558315433Smm case OPTION_NO_XATTRS: /* GNU tar */ 559302001Smm bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_XATTR; 560302001Smm bsdtar->readdisk_flags |= ARCHIVE_READDISK_NO_XATTR; 561315433Smm bsdtar->flags |= OPTFLAG_NO_XATTRS; 562302001Smm break; 563228753Smm case OPTION_NULL: /* GNU tar */ 564315433Smm bsdtar->flags |= OPTFLAG_NULL; 565228753Smm break; 566228753Smm case OPTION_NUMERIC_OWNER: /* GNU tar */ 567228753Smm bsdtar->uname = ""; 568228753Smm bsdtar->gname = ""; 569315433Smm bsdtar->flags |= OPTFLAG_NUMERIC_OWNER; 570228753Smm break; 571228753Smm case 'O': /* GNU tar */ 572315433Smm bsdtar->flags |= OPTFLAG_STDOUT; 573228753Smm break; 574228753Smm case 'o': /* SUSv2 and GNU conflict here, but not fatally */ 575315433Smm bsdtar->flags |= OPTFLAG_O; 576228753Smm break; 577248616Smm /* 578248616Smm * Selecting files by time: 579248616Smm * --older-?time='date' Only files older than 'date' 580248616Smm * --older-?time-than='file' Only files older than time 581248616Smm * on specified file 582248616Smm */ 583248616Smm case OPTION_OLDER_CTIME: 584248616Smm if (archive_match_include_date(bsdtar->matching, 585248616Smm ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER, 586248616Smm bsdtar->argument) != ARCHIVE_OK) 587248616Smm lafe_errc(1, 0, "Error : %s", 588248616Smm archive_error_string(bsdtar->matching)); 589248616Smm break; 590248616Smm case OPTION_OLDER_CTIME_THAN: 591248616Smm if (archive_match_include_file_time(bsdtar->matching, 592248616Smm ARCHIVE_MATCH_CTIME | ARCHIVE_MATCH_OLDER, 593248616Smm bsdtar->argument) != ARCHIVE_OK) 594248616Smm lafe_errc(1, 0, "Error : %s", 595248616Smm archive_error_string(bsdtar->matching)); 596248616Smm break; 597248616Smm case OPTION_OLDER_MTIME: 598248616Smm if (archive_match_include_date(bsdtar->matching, 599248616Smm ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER, 600248616Smm bsdtar->argument) != ARCHIVE_OK) 601248616Smm lafe_errc(1, 0, "Error : %s", 602248616Smm archive_error_string(bsdtar->matching)); 603248616Smm break; 604248616Smm case OPTION_OLDER_MTIME_THAN: 605248616Smm if (archive_match_include_file_time(bsdtar->matching, 606248616Smm ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER, 607248616Smm bsdtar->argument) != ARCHIVE_OK) 608248616Smm lafe_errc(1, 0, "Error : %s", 609248616Smm archive_error_string(bsdtar->matching)); 610248616Smm break; 611228753Smm case OPTION_ONE_FILE_SYSTEM: /* GNU tar */ 612238856Smm bsdtar->readdisk_flags |= 613238856Smm ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS; 614228753Smm break; 615228753Smm case OPTION_OPTIONS: 616232153Smm bsdtar->option_options = bsdtar->argument; 617228753Smm break; 618228753Smm#if 0 619228753Smm /* 620228753Smm * The common BSD -P option is not necessary, since 621228753Smm * our default is to archive symlinks, not follow 622228753Smm * them. This is convenient, as -P conflicts with GNU 623228753Smm * tar anyway. 624228753Smm */ 625228753Smm case 'P': /* BSD convention */ 626228753Smm /* Default behavior, no option necessary. */ 627228753Smm break; 628228753Smm#endif 629228753Smm case 'P': /* GNU tar */ 630228753Smm bsdtar->extract_flags &= ~SECURITY; 631315433Smm bsdtar->flags |= OPTFLAG_ABSOLUTE_PATHS; 632228753Smm break; 633228753Smm case 'p': /* GNU tar, star */ 634228753Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM; 635228753Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL; 636228753Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR; 637228753Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; 638232153Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_MAC_METADATA; 639228753Smm break; 640302001Smm case OPTION_PASSPHRASE: 641302001Smm bsdtar->passphrase = bsdtar->argument; 642302001Smm break; 643228753Smm case OPTION_POSIX: /* GNU tar */ 644248616Smm cset_set_format(bsdtar->cset, "pax"); 645228753Smm break; 646228753Smm case 'q': /* FreeBSD GNU tar --fast-read, NetBSD -q */ 647315433Smm bsdtar->flags |= OPTFLAG_FAST_READ; 648228753Smm break; 649228753Smm case 'r': /* SUSv2 */ 650228753Smm set_mode(bsdtar, opt); 651228753Smm break; 652228753Smm case 'S': /* NetBSD pax-as-tar */ 653228753Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_SPARSE; 654228753Smm break; 655228753Smm case 's': /* NetBSD pax-as-tar */ 656248616Smm#if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) 657232153Smm add_substitution(bsdtar, bsdtar->argument); 658228753Smm#else 659228753Smm lafe_warnc(0, 660228753Smm "-s is not supported by this version of bsdtar"); 661228753Smm usage(); 662228753Smm#endif 663228753Smm break; 664358090Smm case OPTION_SAFE_WRITES: 665358090Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_SAFE_WRITES; 666358090Smm break; 667228753Smm case OPTION_SAME_OWNER: /* GNU tar */ 668228753Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER; 669228753Smm break; 670228753Smm case OPTION_STRIP_COMPONENTS: /* GNU tar 1.15 */ 671232153Smm errno = 0; 672342361Smm tptr = NULL; 673342361Smm t = (int)strtol(bsdtar->argument, &tptr, 10); 674342361Smm if (errno || t < 0 || *(bsdtar->argument) == '\0' || 675342361Smm tptr == NULL || *tptr != '\0') { 676342361Smm lafe_errc(1, 0, "Invalid argument to " 677342361Smm "--strip-components"); 678342361Smm } 679342361Smm bsdtar->strip_components = t; 680228753Smm break; 681228753Smm case 'T': /* GNU tar */ 682232153Smm bsdtar->names_from_file = bsdtar->argument; 683228753Smm break; 684228753Smm case 't': /* SUSv2 */ 685228753Smm set_mode(bsdtar, opt); 686228753Smm bsdtar->verbose++; 687228753Smm break; 688228753Smm case OPTION_TOTALS: /* GNU tar */ 689315433Smm bsdtar->flags |= OPTFLAG_TOTALS; 690228753Smm break; 691228753Smm case 'U': /* GNU tar */ 692228753Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_UNLINK; 693315433Smm bsdtar->flags |= OPTFLAG_UNLINK_FIRST; 694228753Smm break; 695228753Smm case 'u': /* SUSv2 */ 696228753Smm set_mode(bsdtar, opt); 697228753Smm break; 698228753Smm case OPTION_UID: /* cpio */ 699342361Smm errno = 0; 700342361Smm tptr = NULL; 701342361Smm t = (int)strtol(bsdtar->argument, &tptr, 10); 702342361Smm if (errno || t < 0 || *(bsdtar->argument) == '\0' || 703342361Smm tptr == NULL || *tptr != '\0') { 704342361Smm lafe_errc(1, 0, "Invalid argument to --uid"); 705342361Smm } 706228753Smm bsdtar->uid = t; 707228753Smm break; 708228753Smm case OPTION_UNAME: /* cpio */ 709232153Smm bsdtar->uname = bsdtar->argument; 710228753Smm break; 711248616Smm case OPTION_UUENCODE: 712248616Smm if (compression2 != '\0') 713248616Smm lafe_errc(1, 0, 714248616Smm "Can't specify both --uuencode and " 715248616Smm "--b64encode"); 716248616Smm compression2 = opt; 717248616Smm compression2_name = "uuencode"; 718248616Smm break; 719228753Smm case 'v': /* SUSv2 */ 720228753Smm bsdtar->verbose++; 721228753Smm break; 722228753Smm case OPTION_VERSION: /* GNU convention */ 723228753Smm version(); 724228753Smm break; 725228753Smm#if 0 726228753Smm /* 727228753Smm * The -W longopt feature is handled inside of 728228753Smm * bsdtar_getopt(), so -W is not available here. 729228753Smm */ 730228753Smm case 'W': /* Obscure GNU convention. */ 731228753Smm break; 732228753Smm#endif 733228753Smm case 'w': /* SUSv2 */ 734315433Smm bsdtar->flags |= OPTFLAG_INTERACTIVE; 735228753Smm break; 736228753Smm case 'X': /* GNU tar */ 737238856Smm if (archive_match_exclude_pattern_from_file( 738238856Smm bsdtar->matching, bsdtar->argument, 0) 739238856Smm != ARCHIVE_OK) 740238856Smm lafe_errc(1, 0, "Error : %s", 741238856Smm archive_error_string(bsdtar->matching)); 742228753Smm break; 743228753Smm case 'x': /* SUSv2 */ 744228753Smm set_mode(bsdtar, opt); 745228753Smm break; 746315433Smm case OPTION_XATTRS: /* GNU tar */ 747315433Smm bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR; 748315433Smm bsdtar->readdisk_flags &= ~ARCHIVE_READDISK_NO_XATTR; 749315433Smm bsdtar->flags |= OPTFLAG_XATTRS; 750315433Smm break; 751228753Smm case 'y': /* FreeBSD version of GNU tar */ 752248616Smm if (compression != '\0') 753228753Smm lafe_errc(1, 0, 754228753Smm "Can't specify both -%c and -%c", opt, 755248616Smm compression); 756248616Smm compression = opt; 757248616Smm compression_name = "bzip2"; 758228753Smm break; 759228753Smm case 'Z': /* GNU tar */ 760248616Smm if (compression != '\0') 761228753Smm lafe_errc(1, 0, 762228753Smm "Can't specify both -%c and -%c", opt, 763248616Smm compression); 764248616Smm compression = opt; 765248616Smm compression_name = "compress"; 766228753Smm break; 767228753Smm case 'z': /* GNU tar, star, many others */ 768248616Smm if (compression != '\0') 769228753Smm lafe_errc(1, 0, 770228753Smm "Can't specify both -%c and -%c", opt, 771248616Smm compression); 772248616Smm compression = opt; 773248616Smm compression_name = "gzip"; 774228753Smm break; 775228753Smm case OPTION_USE_COMPRESS_PROGRAM: 776248616Smm compress_program = bsdtar->argument; 777228753Smm break; 778228753Smm default: 779228753Smm usage(); 780228753Smm } 781228753Smm } 782228753Smm 783228753Smm /* 784228753Smm * Sanity-check options. 785228753Smm */ 786228753Smm 787228753Smm /* If no "real" mode was specified, treat -h as --help. */ 788228753Smm if ((bsdtar->mode == '\0') && possible_help_request) { 789228753Smm long_help(); 790228753Smm exit(0); 791228753Smm } 792228753Smm 793228753Smm /* Otherwise, a mode is required. */ 794228753Smm if (bsdtar->mode == '\0') 795228753Smm lafe_errc(1, 0, 796228753Smm "Must specify one of -c, -r, -t, -u, -x"); 797228753Smm 798228753Smm /* Check boolean options only permitted in certain modes. */ 799315433Smm if (bsdtar->flags & OPTFLAG_AUTO_COMPRESS) 800248616Smm only_mode(bsdtar, "-a", "c"); 801238856Smm if (bsdtar->readdisk_flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) 802228753Smm only_mode(bsdtar, "--one-file-system", "cru"); 803315433Smm if (bsdtar->flags & OPTFLAG_FAST_READ) 804228753Smm only_mode(bsdtar, "--fast-read", "xt"); 805248616Smm if (bsdtar->extract_flags & ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED) 806248616Smm only_mode(bsdtar, "--hfsCompression", "x"); 807248616Smm if (bsdtar->extract_flags & ARCHIVE_EXTRACT_NO_HFS_COMPRESSION) 808248616Smm only_mode(bsdtar, "--nopreserveHFSCompression", "x"); 809238856Smm if (bsdtar->readdisk_flags & ARCHIVE_READDISK_HONOR_NODUMP) 810228753Smm only_mode(bsdtar, "--nodump", "cru"); 811315433Smm if (bsdtar->flags & OPTFLAG_ACLS) 812315433Smm only_mode(bsdtar, "--acls", "crux"); 813315433Smm if (bsdtar->flags & OPTFLAG_NO_ACLS) 814315433Smm only_mode(bsdtar, "--no-acls", "crux"); 815315433Smm if (bsdtar->flags & OPTFLAG_XATTRS) 816315433Smm only_mode(bsdtar, "--xattrs", "crux"); 817315433Smm if (bsdtar->flags & OPTFLAG_NO_XATTRS) 818315433Smm only_mode(bsdtar, "--no-xattrs", "crux"); 819315433Smm if (bsdtar->flags & OPTFLAG_FFLAGS) 820315433Smm only_mode(bsdtar, "--fflags", "crux"); 821315433Smm if (bsdtar->flags & OPTFLAG_NO_FFLAGS) 822315433Smm only_mode(bsdtar, "--no-fflags", "crux"); 823315433Smm if (bsdtar->flags & OPTFLAG_MAC_METADATA) 824315433Smm only_mode(bsdtar, "--mac-metadata", "crux"); 825315433Smm if (bsdtar->flags & OPTFLAG_NO_MAC_METADATA) 826315433Smm only_mode(bsdtar, "--no-mac-metadata", "crux"); 827315433Smm if (bsdtar->flags & OPTFLAG_O) { 828228753Smm switch (bsdtar->mode) { 829228753Smm case 'c': 830228753Smm /* 831228753Smm * In GNU tar, -o means "old format." The 832228753Smm * "ustar" format is the closest thing 833228753Smm * supported by libarchive. 834228753Smm */ 835248616Smm cset_set_format(bsdtar->cset, "ustar"); 836228753Smm /* TODO: bsdtar->create_format = "v7"; */ 837228753Smm break; 838228753Smm case 'x': 839228753Smm /* POSIX-compatible behavior. */ 840315433Smm bsdtar->flags |= OPTFLAG_NO_OWNER; 841228753Smm bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER; 842228753Smm break; 843228753Smm default: 844228753Smm only_mode(bsdtar, "-o", "xc"); 845228753Smm break; 846228753Smm } 847228753Smm } 848315433Smm if (bsdtar->flags & OPTFLAG_STDOUT) 849228753Smm only_mode(bsdtar, "-O", "xt"); 850315433Smm if (bsdtar->flags & OPTFLAG_UNLINK_FIRST) 851228753Smm only_mode(bsdtar, "-U", "x"); 852315433Smm if (bsdtar->flags & OPTFLAG_WARN_LINKS) 853228753Smm only_mode(bsdtar, "--check-links", "cr"); 854228753Smm 855315433Smm if ((bsdtar->flags & OPTFLAG_AUTO_COMPRESS) && 856315433Smm cset_auto_compress(bsdtar->cset, bsdtar->filename)) { 857248616Smm /* Ignore specified compressions if auto-compress works. */ 858248616Smm compression = '\0'; 859248616Smm compression2 = '\0'; 860248616Smm } 861228753Smm /* Check other parameters only permitted in certain modes. */ 862248616Smm if (compress_program != NULL) { 863248616Smm only_mode(bsdtar, "--use-compress-program", "cxt"); 864248616Smm cset_add_filter_program(bsdtar->cset, compress_program); 865248616Smm /* Ignore specified compressions. */ 866248616Smm compression = '\0'; 867248616Smm compression2 = '\0'; 868248616Smm } 869248616Smm if (compression != '\0') { 870248616Smm switch (compression) { 871248616Smm case 'J': case 'j': case 'y': case 'Z': case 'z': 872248616Smm strcpy(buff, "-?"); 873248616Smm buff[1] = compression; 874248616Smm break; 875248616Smm default: 876248616Smm strcpy(buff, "--"); 877248616Smm strcat(buff, compression_name); 878248616Smm break; 879248616Smm } 880228753Smm only_mode(bsdtar, buff, "cxt"); 881248616Smm cset_add_filter(bsdtar->cset, compression_name); 882228753Smm } 883248616Smm if (compression2 != '\0') { 884248616Smm strcpy(buff, "--"); 885248616Smm strcat(buff, compression2_name); 886248616Smm only_mode(bsdtar, buff, "cxt"); 887248616Smm cset_add_filter(bsdtar->cset, compression2_name); 888248616Smm } 889248616Smm if (cset_get_format(bsdtar->cset) != NULL) 890228753Smm only_mode(bsdtar, "--format", "cru"); 891228753Smm if (bsdtar->symlink_mode != '\0') { 892228753Smm strcpy(buff, "-?"); 893228753Smm buff[1] = bsdtar->symlink_mode; 894228753Smm only_mode(bsdtar, buff, "cru"); 895228753Smm } 896228753Smm 897348608Smm /* 898348608Smm * When creating an archive from a directory tree, the directory 899348608Smm * walking code will already avoid entering directories when 900348608Smm * recursive inclusion of directory content is disabled, therefore 901348608Smm * changing the matching behavior has no effect for creation modes. 902348608Smm * It is relevant for extraction or listing. 903348608Smm */ 904348608Smm archive_match_set_inclusion_recursion(bsdtar->matching, 905348608Smm !(bsdtar->flags & OPTFLAG_NO_SUBDIRS)); 906348608Smm 907232153Smm /* Filename "-" implies stdio. */ 908232153Smm if (strcmp(bsdtar->filename, "-") == 0) 909232153Smm bsdtar->filename = NULL; 910232153Smm 911228753Smm switch(bsdtar->mode) { 912228753Smm case 'c': 913228753Smm tar_mode_c(bsdtar); 914228753Smm break; 915228753Smm case 'r': 916228753Smm tar_mode_r(bsdtar); 917228753Smm break; 918228753Smm case 't': 919228753Smm tar_mode_t(bsdtar); 920228753Smm break; 921228753Smm case 'u': 922228753Smm tar_mode_u(bsdtar); 923228753Smm break; 924228753Smm case 'x': 925228753Smm tar_mode_x(bsdtar); 926228753Smm break; 927228753Smm } 928228753Smm 929238856Smm archive_match_free(bsdtar->matching); 930248616Smm#if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) 931228753Smm cleanup_substitution(bsdtar); 932228753Smm#endif 933248616Smm cset_free(bsdtar->cset); 934302001Smm passphrase_free(bsdtar->ppbuff); 935228753Smm 936228753Smm if (bsdtar->return_value != 0) 937228753Smm lafe_warnc(0, 938228753Smm "Error exit delayed from previous errors."); 939228753Smm return (bsdtar->return_value); 940228753Smm} 941228753Smm 942228753Smmstatic void 943228753Smmset_mode(struct bsdtar *bsdtar, char opt) 944228753Smm{ 945228753Smm if (bsdtar->mode != '\0' && bsdtar->mode != opt) 946228753Smm lafe_errc(1, 0, 947228753Smm "Can't specify both -%c and -%c", opt, bsdtar->mode); 948228753Smm bsdtar->mode = opt; 949228753Smm} 950228753Smm 951228753Smm/* 952228753Smm * Verify that the mode is correct. 953228753Smm */ 954228753Smmstatic void 955228753Smmonly_mode(struct bsdtar *bsdtar, const char *opt, const char *valid_modes) 956228753Smm{ 957228753Smm if (strchr(valid_modes, bsdtar->mode) == NULL) 958228753Smm lafe_errc(1, 0, 959228753Smm "Option %s is not permitted in mode -%c", 960228753Smm opt, bsdtar->mode); 961228753Smm} 962228753Smm 963228753Smm 964228753Smmvoid 965228753Smmusage(void) 966228753Smm{ 967228753Smm const char *p; 968228753Smm 969302001Smm p = lafe_getprogname(); 970228753Smm 971228753Smm fprintf(stderr, "Usage:\n"); 972228753Smm fprintf(stderr, " List: %s -tf <archive-filename>\n", p); 973228753Smm fprintf(stderr, " Extract: %s -xf <archive-filename>\n", p); 974228753Smm fprintf(stderr, " Create: %s -cf <archive-filename> [filenames...]\n", p); 975228753Smm fprintf(stderr, " Help: %s --help\n", p); 976228753Smm exit(1); 977228753Smm} 978228753Smm 979228753Smmstatic void 980228753Smmversion(void) 981228753Smm{ 982337352Smm printf("bsdtar %s - %s \n", 983228753Smm BSDTAR_VERSION_STRING, 984302001Smm archive_version_details()); 985228753Smm exit(0); 986228753Smm} 987228753Smm 988228753Smmstatic const char *long_help_msg = 989228753Smm "First option must be a mode specifier:\n" 990228753Smm " -c Create -r Add/Replace -t List -u Update -x Extract\n" 991228753Smm "Common Options:\n" 992228753Smm " -b # Use # 512-byte records per I/O block\n" 993228753Smm " -f <filename> Location of archive (default " _PATH_DEFTAPE ")\n" 994228753Smm " -v Verbose\n" 995228753Smm " -w Interactive\n" 996228753Smm "Create: %p -c [options] [<file> | <dir> | @<archive> | -C <dir> ]\n" 997228753Smm " <file>, <dir> add these items to archive\n" 998228753Smm " -z, -j, -J, --lzma Compress archive with gzip/bzip2/xz/lzma\n" 999228753Smm " --format {ustar|pax|cpio|shar} Select archive format\n" 1000228753Smm " --exclude <pattern> Skip files that match pattern\n" 1001228753Smm " -C <dir> Change to <dir> before processing remaining files\n" 1002228753Smm " @<archive> Add entries from <archive> to output\n" 1003228753Smm "List: %p -t [options] [<patterns>]\n" 1004228753Smm " <patterns> If specified, list only entries that match\n" 1005228753Smm "Extract: %p -x [options] [<patterns>]\n" 1006228753Smm " <patterns> If specified, extract only entries that match\n" 1007228753Smm " -k Keep (don't overwrite) existing files\n" 1008228753Smm " -m Don't restore modification times\n" 1009228753Smm " -O Write entries to stdout, don't restore to disk\n" 1010228753Smm " -p Restore permissions (including ACLs, owner, file flags)\n"; 1011228753Smm 1012228753Smm 1013228753Smm/* 1014228753Smm * Note that the word 'bsdtar' will always appear in the first line 1015228753Smm * of output. 1016228753Smm * 1017228753Smm * In particular, /bin/sh scripts that need to test for the presence 1018228753Smm * of bsdtar can use the following template: 1019228753Smm * 1020228753Smm * if (tar --help 2>&1 | grep bsdtar >/dev/null 2>&1 ) then \ 1021228753Smm * echo bsdtar; else echo not bsdtar; fi 1022228753Smm */ 1023228753Smmstatic void 1024228753Smmlong_help(void) 1025228753Smm{ 1026228753Smm const char *prog; 1027228753Smm const char *p; 1028228753Smm 1029302001Smm prog = lafe_getprogname(); 1030228753Smm 1031228753Smm fflush(stderr); 1032228753Smm 1033228753Smm p = (strcmp(prog,"bsdtar") != 0) ? "(bsdtar)" : ""; 1034228753Smm printf("%s%s: manipulate archive files\n", prog, p); 1035228753Smm 1036228753Smm for (p = long_help_msg; *p != '\0'; p++) { 1037228753Smm if (*p == '%') { 1038228753Smm if (p[1] == 'p') { 1039228753Smm fputs(prog, stdout); 1040228753Smm p++; 1041228753Smm } else 1042228753Smm putchar('%'); 1043228753Smm } else 1044228753Smm putchar(*p); 1045228753Smm } 1046228753Smm version(); 1047228753Smm} 1048