1 /*- 2 * Copyright (c) 2003-2008 Tim Kientzle 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "bsdtar_platform.h" 27 __FBSDID("$FreeBSD: src/usr.bin/tar/bsdtar.c,v 1.93 2008/11/08 04:43:24 kientzle Exp $"); 28 29 #ifdef HAVE_SYS_PARAM_H 30 #include <sys/param.h> 31 #endif 32 #ifdef HAVE_SYS_STAT_H 33 #include <sys/stat.h> 34 #endif 35 #ifdef HAVE_ERRNO_H 36 #include <errno.h> 37 #endif 38 #ifdef HAVE_FCNTL_H 39 #include <fcntl.h> 40 #endif 41 #ifdef HAVE_LANGINFO_H 42 #include <langinfo.h> 43 #endif 44 #ifdef HAVE_LOCALE_H 45 #include <locale.h> 46 #endif 47 #ifdef HAVE_PATHS_H 48 #include <paths.h> 49 #endif 50 #include <stdio.h> 51 #ifdef HAVE_STDLIB_H 52 #include <stdlib.h> 53 #endif 54 #ifdef HAVE_STRING_H 55 #include <string.h> 56 #endif 57 #ifdef HAVE_TIME_H 58 #include <time.h> 59 #endif 60 #ifdef HAVE_UNISTD_H 61 #include <unistd.h> 62 #endif 63 #if HAVE_ZLIB_H 64 #include <zlib.h> 65 #endif 66 67 #include "bsdtar.h" 68 69 /* 70 * Per POSIX.1-1988, tar defaults to reading/writing archives to/from 71 * the default tape device for the system. Pick something reasonable here. 72 */ 73 #ifdef __linux 74 #define _PATH_DEFTAPE "/dev/st0" 75 #endif 76 #if defined(_WIN32) && !defined(__CYGWIN__) 77 #define _PATH_DEFTAPE "\\\\.\\tape0" 78 #endif 79 80 #ifndef _PATH_DEFTAPE 81 #define _PATH_DEFTAPE "/dev/tape" 82 #endif 83 84 /* External function to parse a date/time string (from getdate.y) */ 85 time_t get_date(time_t, const char *); 86 87 static void long_help(struct bsdtar *); 88 static void only_mode(struct bsdtar *, const char *opt, 89 const char *valid); 90 static void set_mode(struct bsdtar *, char opt); 91 static void version(void); 92 93 /* A basic set of security flags to request from libarchive. */ 94 #define SECURITY \ 95 (ARCHIVE_EXTRACT_SECURE_SYMLINKS \ 96 | ARCHIVE_EXTRACT_SECURE_NODOTDOT) 97 98 int 99 main(int argc, char **argv) 100 { 101 struct bsdtar *bsdtar, bsdtar_storage; 102 int opt, t; 103 char option_o; 104 char possible_help_request; 105 char buff[16]; 106 time_t now; 107 108 /* 109 * Use a pointer for consistency, but stack-allocated storage 110 * for ease of cleanup. 111 */ 112 bsdtar = &bsdtar_storage; 113 memset(bsdtar, 0, sizeof(*bsdtar)); 114 bsdtar->fd = -1; /* Mark as "unused" */ 115 option_o = 0; 116 #if defined(_WIN32) && !defined(__CYGWIN__) 117 /* Make sure open() function will be used with a binary mode. */ 118 /* on cygwin, we need something similar, but instead link against */ 119 /* a special startup object, binmode.o */ 120 _set_fmode(_O_BINARY); 121 #endif 122 123 /* Need bsdtar->progname before calling bsdtar_warnc. */ 124 if (*argv == NULL) 125 bsdtar->progname = "bsdtar"; 126 else { 127 #if defined(_WIN32) && !defined(__CYGWIN__) 128 bsdtar->progname = strrchr(*argv, '\\'); 129 #else 130 bsdtar->progname = strrchr(*argv, '/'); 131 #endif 132 if (bsdtar->progname != NULL) 133 bsdtar->progname++; 134 else 135 bsdtar->progname = *argv; 136 } 137 138 time(&now); 139 140 if (setlocale(LC_ALL, "") == NULL) 141 bsdtar_warnc(bsdtar, 0, "Failed to set default locale"); 142 #if defined(HAVE_NL_LANGINFO) && defined(HAVE_D_MD_ORDER) 143 bsdtar->day_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 144 #endif 145 possible_help_request = 0; 146 147 /* Look up uid of current user for future reference */ 148 bsdtar->user_uid = geteuid(); 149 150 /* Default: open tape drive. */ 151 bsdtar->filename = getenv("TAPE"); 152 if (bsdtar->filename == NULL) 153 bsdtar->filename = _PATH_DEFTAPE; 154 155 /* Default: preserve mod time on extract */ 156 bsdtar->extract_flags = ARCHIVE_EXTRACT_TIME; 157 158 /* Default: Perform basic security checks. */ 159 bsdtar->extract_flags |= SECURITY; 160 161 /* Defaults for root user: */ 162 if (bsdtar_is_privileged(bsdtar)) { 163 /* --same-owner */ 164 bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER; 165 /* -p */ 166 bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM; 167 bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL; 168 bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR; 169 bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; 170 } 171 172 bsdtar->argv = argv; 173 bsdtar->argc = argc; 174 175 /* 176 * Comments following each option indicate where that option 177 * originated: SUSv2, POSIX, GNU tar, star, etc. If there's 178 * no such comment, then I don't know of anyone else who 179 * implements that option. 180 */ 181 while ((opt = bsdtar_getopt(bsdtar)) != -1) { 182 switch (opt) { 183 case 'B': /* GNU tar */ 184 /* libarchive doesn't need this; just ignore it. */ 185 break; 186 case 'b': /* SUSv2 */ 187 t = atoi(bsdtar->optarg); 188 if (t <= 0 || t > 1024) 189 bsdtar_errc(bsdtar, 1, 0, 190 "Argument to -b is out of range (1..1024)"); 191 bsdtar->bytes_per_block = 512 * t; 192 break; 193 case 'C': /* GNU tar */ 194 set_chdir(bsdtar, bsdtar->optarg); 195 break; 196 case 'c': /* SUSv2 */ 197 set_mode(bsdtar, opt); 198 break; 199 case OPTION_CHECK_LINKS: /* GNU tar */ 200 bsdtar->option_warn_links = 1; 201 break; 202 case OPTION_CHROOT: /* NetBSD */ 203 bsdtar->option_chroot = 1; 204 break; 205 case OPTION_EXCLUDE: /* GNU tar */ 206 if (exclude(bsdtar, bsdtar->optarg)) 207 bsdtar_errc(bsdtar, 1, 0, 208 "Couldn't exclude %s\n", bsdtar->optarg); 209 break; 210 case OPTION_FORMAT: /* GNU tar, others */ 211 bsdtar->create_format = bsdtar->optarg; 212 break; 213 case OPTION_OPTIONS: 214 bsdtar->option_options = bsdtar->optarg; 215 break; 216 case 'f': /* SUSv2 */ 217 bsdtar->filename = bsdtar->optarg; 218 if (strcmp(bsdtar->filename, "-") == 0) 219 bsdtar->filename = NULL; 220 break; 221 case 'H': /* BSD convention */ 222 bsdtar->symlink_mode = 'H'; 223 break; 224 case 'h': /* Linux Standards Base, gtar; synonym for -L */ 225 bsdtar->symlink_mode = 'L'; 226 /* Hack: -h by itself is the "help" command. */ 227 possible_help_request = 1; 228 break; 229 case OPTION_HELP: /* GNU tar, others */ 230 long_help(bsdtar); 231 exit(0); 232 break; 233 case 'I': /* GNU tar */ 234 /* 235 * TODO: Allow 'names' to come from an archive, 236 * not just a text file. Design a good UI for 237 * allowing names and mode/owner to be read 238 * from an archive, with contents coming from 239 * disk. This can be used to "refresh" an 240 * archive or to design archives with special 241 * permissions without having to create those 242 * permissions on disk. 243 */ 244 bsdtar->names_from_file = bsdtar->optarg; 245 break; 246 case OPTION_INCLUDE: 247 /* 248 * Noone else has the @archive extension, so 249 * noone else needs this to filter entries 250 * when transforming archives. 251 */ 252 if (include(bsdtar, bsdtar->optarg)) 253 bsdtar_errc(bsdtar, 1, 0, 254 "Failed to add %s to inclusion list", 255 bsdtar->optarg); 256 break; 257 case 'j': /* GNU tar */ 258 #if HAVE_LIBBZ2 259 if (bsdtar->create_compression != '\0') 260 bsdtar_errc(bsdtar, 1, 0, 261 "Can't specify both -%c and -%c", opt, 262 bsdtar->create_compression); 263 bsdtar->create_compression = opt; 264 #else 265 bsdtar_warnc(bsdtar, 0, 266 "bzip2 compression not supported by this version of bsdtar"); 267 usage(bsdtar); 268 #endif 269 break; 270 case 'J': /* GNU tar 1.21 and later */ 271 #if HAVE_LIBLZMA 272 if (bsdtar->create_compression != '\0') 273 bsdtar_errc(bsdtar, 1, 0, 274 "Can't specify both -%c and -%c", opt, 275 bsdtar->create_compression); 276 bsdtar->create_compression = opt; 277 #else 278 bsdtar_warnc(bsdtar, 0, 279 "xz compression not supported by this version of bsdtar"); 280 usage(bsdtar); 281 #endif 282 break; 283 case 'k': /* GNU tar */ 284 bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE; 285 break; 286 case OPTION_KEEP_NEWER_FILES: /* GNU tar */ 287 bsdtar->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER; 288 break; 289 case 'L': /* BSD convention */ 290 bsdtar->symlink_mode = 'L'; 291 break; 292 case 'l': /* SUSv2 and GNU tar beginning with 1.16 */ 293 /* GNU tar 1.13 used -l for --one-file-system */ 294 bsdtar->option_warn_links = 1; 295 break; 296 case OPTION_LZMA: 297 #if HAVE_LIBLZMA 298 if (bsdtar->create_compression != '\0') 299 bsdtar_errc(bsdtar, 1, 0, 300 "Can't specify both -%c and -%c", opt, 301 bsdtar->create_compression); 302 bsdtar->create_compression = opt; 303 #else 304 bsdtar_warnc(bsdtar, 0, 305 "lzma compression not supported by this version of bsdtar"); 306 usage(bsdtar); 307 #endif 308 break; 309 case 'm': /* SUSv2 */ 310 bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_TIME; 311 break; 312 case 'n': /* GNU tar */ 313 bsdtar->option_no_subdirs = 1; 314 break; 315 /* 316 * Selecting files by time: 317 * --newer-?time='date' Only files newer than 'date' 318 * --newer-?time-than='file' Only files newer than time 319 * on specified file (useful for incremental backups) 320 * TODO: Add corresponding "older" options to reverse these. 321 */ 322 case OPTION_NEWER_CTIME: /* GNU tar */ 323 bsdtar->newer_ctime_sec = get_date(now, bsdtar->optarg); 324 break; 325 case OPTION_NEWER_CTIME_THAN: 326 { 327 struct stat st; 328 if (stat(bsdtar->optarg, &st) != 0) 329 bsdtar_errc(bsdtar, 1, 0, 330 "Can't open file %s", bsdtar->optarg); 331 bsdtar->newer_ctime_sec = st.st_ctime; 332 bsdtar->newer_ctime_nsec = 333 ARCHIVE_STAT_CTIME_NANOS(&st); 334 } 335 break; 336 case OPTION_NEWER_MTIME: /* GNU tar */ 337 bsdtar->newer_mtime_sec = get_date(now, bsdtar->optarg); 338 break; 339 case OPTION_NEWER_MTIME_THAN: 340 { 341 struct stat st; 342 if (stat(bsdtar->optarg, &st) != 0) 343 bsdtar_errc(bsdtar, 1, 0, 344 "Can't open file %s", bsdtar->optarg); 345 bsdtar->newer_mtime_sec = st.st_mtime; 346 bsdtar->newer_mtime_nsec = 347 ARCHIVE_STAT_MTIME_NANOS(&st); 348 } 349 break; 350 case OPTION_NODUMP: /* star */ 351 bsdtar->option_honor_nodump = 1; 352 break; 353 case OPTION_NO_SAME_OWNER: /* GNU tar */ 354 bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER; 355 break; 356 case OPTION_NO_SAME_PERMISSIONS: /* GNU tar */ 357 bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_PERM; 358 bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_ACL; 359 bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_XATTR; 360 bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_FFLAGS; 361 break; 362 case OPTION_NULL: /* GNU tar */ 363 bsdtar->option_null++; 364 break; 365 case OPTION_NUMERIC_OWNER: /* GNU tar */ 366 bsdtar->option_numeric_owner++; 367 break; 368 case 'O': /* GNU tar */ 369 bsdtar->option_stdout = 1; 370 break; 371 case 'o': /* SUSv2 and GNU conflict here, but not fatally */ 372 option_o = 1; /* Record it and resolve it later. */ 373 break; 374 case OPTION_ONE_FILE_SYSTEM: /* GNU tar */ 375 bsdtar->option_dont_traverse_mounts = 1; 376 break; 377 #if 0 378 /* 379 * The common BSD -P option is not necessary, since 380 * our default is to archive symlinks, not follow 381 * them. This is convenient, as -P conflicts with GNU 382 * tar anyway. 383 */ 384 case 'P': /* BSD convention */ 385 /* Default behavior, no option necessary. */ 386 break; 387 #endif 388 case 'P': /* GNU tar */ 389 bsdtar->extract_flags &= ~SECURITY; 390 bsdtar->option_absolute_paths = 1; 391 break; 392 case 'p': /* GNU tar, star */ 393 bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM; 394 bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL; 395 bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR; 396 bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; 397 break; 398 case OPTION_POSIX: /* GNU tar */ 399 bsdtar->create_format = "pax"; 400 break; 401 case 'q': /* FreeBSD GNU tar --fast-read, NetBSD -q */ 402 bsdtar->option_fast_read = 1; 403 break; 404 case 'r': /* SUSv2 */ 405 set_mode(bsdtar, opt); 406 break; 407 case 'S': /* NetBSD pax-as-tar */ 408 bsdtar->extract_flags |= ARCHIVE_EXTRACT_SPARSE; 409 break; 410 case 's': /* NetBSD pax-as-tar */ 411 #if HAVE_REGEX_H 412 add_substitution(bsdtar, bsdtar->optarg); 413 #else 414 bsdtar_warnc(bsdtar, 0, 415 "-s is not supported by this version of bsdtar"); 416 usage(bsdtar); 417 #endif 418 break; 419 case OPTION_SAME_OWNER: /* GNU tar */ 420 bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER; 421 break; 422 case OPTION_STRIP_COMPONENTS: /* GNU tar 1.15 */ 423 bsdtar->strip_components = atoi(bsdtar->optarg); 424 break; 425 case 'T': /* GNU tar */ 426 bsdtar->names_from_file = bsdtar->optarg; 427 break; 428 case 't': /* SUSv2 */ 429 set_mode(bsdtar, opt); 430 bsdtar->verbose++; 431 break; 432 case OPTION_TOTALS: /* GNU tar */ 433 bsdtar->option_totals++; 434 break; 435 case 'U': /* GNU tar */ 436 bsdtar->extract_flags |= ARCHIVE_EXTRACT_UNLINK; 437 bsdtar->option_unlink_first = 1; 438 break; 439 case 'u': /* SUSv2 */ 440 set_mode(bsdtar, opt); 441 break; 442 case 'v': /* SUSv2 */ 443 bsdtar->verbose++; 444 break; 445 case OPTION_VERSION: /* GNU convention */ 446 version(); 447 break; 448 #if 0 449 /* 450 * The -W longopt feature is handled inside of 451 * bsdtar_getopt(), so -W is not available here. 452 */ 453 case 'W': /* Obscure GNU convention. */ 454 break; 455 #endif 456 case 'w': /* SUSv2 */ 457 bsdtar->option_interactive = 1; 458 break; 459 case 'X': /* GNU tar */ 460 if (exclude_from_file(bsdtar, bsdtar->optarg)) 461 bsdtar_errc(bsdtar, 1, 0, 462 "failed to process exclusions from file %s", 463 bsdtar->optarg); 464 break; 465 case 'x': /* SUSv2 */ 466 set_mode(bsdtar, opt); 467 break; 468 case 'y': /* FreeBSD version of GNU tar */ 469 #if HAVE_LIBBZ2 470 if (bsdtar->create_compression != '\0') 471 bsdtar_errc(bsdtar, 1, 0, 472 "Can't specify both -%c and -%c", opt, 473 bsdtar->create_compression); 474 bsdtar->create_compression = opt; 475 #else 476 bsdtar_warnc(bsdtar, 0, 477 "bzip2 compression not supported by this version of bsdtar"); 478 usage(bsdtar); 479 #endif 480 break; 481 case 'Z': /* GNU tar */ 482 if (bsdtar->create_compression != '\0') 483 bsdtar_errc(bsdtar, 1, 0, 484 "Can't specify both -%c and -%c", opt, 485 bsdtar->create_compression); 486 bsdtar->create_compression = opt; 487 break; 488 case 'z': /* GNU tar, star, many others */ 489 #if HAVE_LIBZ 490 if (bsdtar->create_compression != '\0') 491 bsdtar_errc(bsdtar, 1, 0, 492 "Can't specify both -%c and -%c", opt, 493 bsdtar->create_compression); 494 bsdtar->create_compression = opt; 495 #else 496 bsdtar_warnc(bsdtar, 0, 497 "gzip compression not supported by this version of bsdtar"); 498 usage(bsdtar); 499 #endif 500 break; 501 case OPTION_USE_COMPRESS_PROGRAM: 502 bsdtar->compress_program = bsdtar->optarg; 503 break; 504 default: 505 usage(bsdtar); 506 } 507 } 508 509 /* 510 * Sanity-check options. 511 */ 512 513 /* If no "real" mode was specified, treat -h as --help. */ 514 if ((bsdtar->mode == '\0') && possible_help_request) { 515 long_help(bsdtar); 516 exit(0); 517 } 518 519 /* Otherwise, a mode is required. */ 520 if (bsdtar->mode == '\0') 521 bsdtar_errc(bsdtar, 1, 0, 522 "Must specify one of -c, -r, -t, -u, -x"); 523 524 /* Check boolean options only permitted in certain modes. */ 525 if (bsdtar->option_dont_traverse_mounts) 526 only_mode(bsdtar, "--one-file-system", "cru"); 527 if (bsdtar->option_fast_read) 528 only_mode(bsdtar, "--fast-read", "xt"); 529 if (bsdtar->option_honor_nodump) 530 only_mode(bsdtar, "--nodump", "cru"); 531 if (option_o > 0) { 532 switch (bsdtar->mode) { 533 case 'c': 534 /* 535 * In GNU tar, -o means "old format." The 536 * "ustar" format is the closest thing 537 * supported by libarchive. 538 */ 539 bsdtar->create_format = "ustar"; 540 /* TODO: bsdtar->create_format = "v7"; */ 541 break; 542 case 'x': 543 /* POSIX-compatible behavior. */ 544 bsdtar->option_no_owner = 1; 545 bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER; 546 break; 547 default: 548 only_mode(bsdtar, "-o", "xc"); 549 break; 550 } 551 } 552 if (bsdtar->option_no_subdirs) 553 only_mode(bsdtar, "-n", "cru"); 554 if (bsdtar->option_stdout) 555 only_mode(bsdtar, "-O", "xt"); 556 if (bsdtar->option_unlink_first) 557 only_mode(bsdtar, "-U", "x"); 558 if (bsdtar->option_warn_links) 559 only_mode(bsdtar, "--check-links", "cr"); 560 561 /* Check other parameters only permitted in certain modes. */ 562 if (bsdtar->create_compression != '\0') { 563 strcpy(buff, "-?"); 564 buff[1] = bsdtar->create_compression; 565 only_mode(bsdtar, buff, "cxt"); 566 } 567 if (bsdtar->create_format != NULL) 568 only_mode(bsdtar, "--format", "cru"); 569 if (bsdtar->symlink_mode != '\0') { 570 strcpy(buff, "-?"); 571 buff[1] = bsdtar->symlink_mode; 572 only_mode(bsdtar, buff, "cru"); 573 } 574 if (bsdtar->strip_components != 0) 575 only_mode(bsdtar, "--strip-components", "xt"); 576 577 switch(bsdtar->mode) { 578 case 'c': 579 tar_mode_c(bsdtar); 580 break; 581 case 'r': 582 tar_mode_r(bsdtar); 583 break; 584 case 't': 585 tar_mode_t(bsdtar); 586 break; 587 case 'u': 588 tar_mode_u(bsdtar); 589 break; 590 case 'x': 591 tar_mode_x(bsdtar); 592 break; 593 } 594 595 cleanup_exclusions(bsdtar); 596 #if HAVE_REGEX_H 597 cleanup_substitution(bsdtar); 598 #endif 599 600 if (bsdtar->return_value != 0) 601 bsdtar_warnc(bsdtar, 0, 602 "Error exit delayed from previous errors."); 603 return (bsdtar->return_value); 604 } 605 606 static void 607 set_mode(struct bsdtar *bsdtar, char opt) 608 { 609 if (bsdtar->mode != '\0' && bsdtar->mode != opt) 610 bsdtar_errc(bsdtar, 1, 0, 611 "Can't specify both -%c and -%c", opt, bsdtar->mode); 612 bsdtar->mode = opt; 613 } 614 615 /* 616 * Verify that the mode is correct. 617 */ 618 static void 619 only_mode(struct bsdtar *bsdtar, const char *opt, const char *valid_modes) 620 { 621 if (strchr(valid_modes, bsdtar->mode) == NULL) 622 bsdtar_errc(bsdtar, 1, 0, 623 "Option %s is not permitted in mode -%c", 624 opt, bsdtar->mode); 625 } 626 627 628 void 629 usage(struct bsdtar *bsdtar) 630 { 631 const char *p; 632 633 p = bsdtar->progname; 634 635 fprintf(stderr, "Usage:\n"); 636 fprintf(stderr, " List: %s -tf <archive-filename>\n", p); 637 fprintf(stderr, " Extract: %s -xf <archive-filename>\n", p); 638 fprintf(stderr, " Create: %s -cf <archive-filename> [filenames...]\n", p); 639 fprintf(stderr, " Help: %s --help\n", p); 640 exit(1); 641 } 642 643 static void 644 version(void) 645 { 646 printf("bsdtar %s - %s\n", 647 BSDTAR_VERSION_STRING, 648 archive_version()); 649 exit(0); 650 } 651 652 static const char *long_help_msg = 653 "First option must be a mode specifier:\n" 654 " -c Create -r Add/Replace -t List -u Update -x Extract\n" 655 "Common Options:\n" 656 " -b # Use # 512-byte records per I/O block\n" 657 " -f <filename> Location of archive (default " _PATH_DEFTAPE ")\n" 658 " -v Verbose\n" 659 " -w Interactive\n" 660 "Create: %p -c [options] [<file> | <dir> | @<archive> | -C <dir> ]\n" 661 " <file>, <dir> add these items to archive\n" 662 " -z, -j, -J, --lzma Compress archive with gzip/bzip2/xz/lzma\n" 663 " --format {ustar|pax|cpio|shar} Select archive format\n" 664 " --exclude <pattern> Skip files that match pattern\n" 665 " -C <dir> Change to <dir> before processing remaining files\n" 666 " @<archive> Add entries from <archive> to output\n" 667 "List: %p -t [options] [<patterns>]\n" 668 " <patterns> If specified, list only entries that match\n" 669 "Extract: %p -x [options] [<patterns>]\n" 670 " <patterns> If specified, extract only entries that match\n" 671 " -k Keep (don't overwrite) existing files\n" 672 " -m Don't restore modification times\n" 673 " -O Write entries to stdout, don't restore to disk\n" 674 " -p Restore permissions (including ACLs, owner, file flags)\n"; 675 676 677 /* 678 * Note that the word 'bsdtar' will always appear in the first line 679 * of output. 680 * 681 * In particular, /bin/sh scripts that need to test for the presence 682 * of bsdtar can use the following template: 683 * 684 * if (tar --help 2>&1 | grep bsdtar >/dev/null 2>&1 ) then \ 685 * echo bsdtar; else echo not bsdtar; fi 686 */ 687 static void 688 long_help(struct bsdtar *bsdtar) 689 { 690 const char *prog; 691 const char *p; 692 693 prog = bsdtar->progname; 694 695 fflush(stderr); 696 697 p = (strcmp(prog,"bsdtar") != 0) ? "(bsdtar)" : ""; 698 printf("%s%s: manipulate archive files\n", prog, p); 699 700 for (p = long_help_msg; *p != '\0'; p++) { 701 if (*p == '%') { 702 if (p[1] == 'p') { 703 fputs(prog, stdout); 704 p++; 705 } else 706 putchar('%'); 707 } else 708 putchar(*p); 709 } 710 version(); 711 } 712