1 /* $NetBSD: options.c,v 1.118 2015/12/19 18:45:52 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 1992 Keith Muller. 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Keith Muller of the University of California, San Diego. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #if HAVE_NBTOOL_CONFIG_H 37 #include "nbtool_config.h" 38 #endif 39 40 #include <sys/cdefs.h> 41 #if !defined(lint) 42 #if 0 43 static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 4/18/94"; 44 #else 45 __RCSID("$NetBSD: options.c,v 1.118 2015/12/19 18:45:52 christos Exp $"); 46 #endif 47 #endif /* not lint */ 48 49 #include <sys/types.h> 50 #include <sys/time.h> 51 #include <sys/stat.h> 52 #include <sys/param.h> 53 #include <ctype.h> 54 #include <errno.h> 55 #if HAVE_NBTOOL_CONFIG_H 56 #include "compat_getopt.h" 57 #else 58 #include <getopt.h> 59 #endif 60 #include <limits.h> 61 #include <stdio.h> 62 #include <stdlib.h> 63 #include <string.h> 64 #include <unistd.h> 65 #include <inttypes.h> 66 #include <paths.h> 67 #include <util.h> 68 #include "pax.h" 69 #include "options.h" 70 #include "cpio.h" 71 #include "tar.h" 72 #include "extern.h" 73 #ifndef SMALL 74 #include "mtree.h" 75 #endif /* SMALL */ 76 77 /* 78 * Routines which handle command line options 79 */ 80 struct stat tst; /* Timestamp to set if non-0 */ 81 82 static int nopids; /* tar mode: suppress "pids" for -p option */ 83 static char flgch[] = FLGCH; /* list of all possible flags (pax) */ 84 static OPLIST *ophead = NULL; /* head for format specific options -x */ 85 static OPLIST *optail = NULL; /* option tail */ 86 87 static int opt_add(const char *); 88 static int no_op(void); 89 static void printflg(unsigned int); 90 static int c_frmt(const void *, const void *); 91 static off_t str_offt(char *); 92 static char *get_line(FILE *fp); 93 #ifndef SMALL 94 static int set_tstamp(const char *, struct stat *); 95 #endif 96 static void pax_options(int, char **); 97 __dead static void pax_usage(void); 98 static void tar_options(int, char **); 99 __dead static void tar_usage(void); 100 #ifndef NO_CPIO 101 static void cpio_options(int, char **); 102 __dead static void cpio_usage(void); 103 #endif 104 105 /* errors from get_line */ 106 #define GETLINE_FILE_CORRUPT 1 107 #define GETLINE_OUT_OF_MEM 2 108 static int get_line_error; 109 110 #define BZIP2_CMD "bzip2" /* command to run as bzip2 */ 111 #define GZIP_CMD "gzip" /* command to run as gzip */ 112 #define XZ_CMD "xz" /* command to run as xz */ 113 #define COMPRESS_CMD "compress" /* command to run as compress */ 114 115 /* 116 * Long options. 117 */ 118 #define OPT_USE_COMPRESS_PROGRAM 0 119 #define OPT_CHECKPOINT 1 120 #define OPT_UNLINK 2 121 #define OPT_HELP 3 122 #define OPT_ATIME_PRESERVE 4 123 #define OPT_IGNORE_FAILED_READ 5 124 #define OPT_REMOVE_FILES 6 125 #define OPT_NULL 7 126 #define OPT_TOTALS 8 127 #define OPT_VERSION 9 128 #define OPT_EXCLUDE 10 129 #define OPT_BLOCK_COMPRESS 11 130 #define OPT_NORECURSE 12 131 #define OPT_FORCE_LOCAL 13 132 #define OPT_INSECURE 14 133 #define OPT_STRICT 15 134 #define OPT_SPARSE 16 135 #define OPT_XZ 17 136 #define OPT_GNU 18 137 #define OPT_TIMESTAMP 19 138 #if !HAVE_NBTOOL_CONFIG_H 139 #define OPT_CHROOT 20 140 #endif 141 142 /* 143 * Format specific routine table - MUST BE IN SORTED ORDER BY NAME 144 * (see pax.h for description of each function) 145 * 146 * name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read, 147 * read, end_read, st_write, write, end_write, trail, 148 * subtrail, rd_data, wr_data, options 149 */ 150 151 FSUB fsub[] = { 152 #ifndef NO_CPIO 153 /* 0: OLD BINARY CPIO */ 154 { "bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd, 155 bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, NULL, 156 cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt }, 157 158 /* 1: OLD OCTAL CHARACTER CPIO */ 159 { "cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd, 160 cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, NULL, 161 cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt }, 162 163 /* 2: SVR4 HEX CPIO */ 164 { "sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd, 165 vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, NULL, 166 cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt }, 167 168 /* 3: SVR4 HEX CPIO WITH CRC */ 169 { "sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd, 170 vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, NULL, 171 cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt }, 172 #endif 173 /* 4: OLD TAR */ 174 { "tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op, 175 tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail, 176 NULL, rd_wrfile, wr_rdfile, tar_opt }, 177 178 /* 5: POSIX USTAR */ 179 { "ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd, 180 ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail, 181 NULL, rd_wrfile, wr_rdfile, bad_opt } 182 }; 183 #ifndef NO_CPIO 184 #define F_BCPIO 0 /* old binary cpio format */ 185 #define F_CPIO 1 /* old octal character cpio format */ 186 #define F_SV4CPIO 2 /* SVR4 hex cpio format */ 187 #define F_SV4CRC 3 /* SVR4 hex with crc cpio format */ 188 #define F_TAR 4 /* old V7 UNIX tar format */ 189 #define F_USTAR 5 /* ustar format */ 190 #else 191 #define F_TAR 0 /* old V7 UNIX tar format */ 192 #define F_USTAR 1 /* ustar format */ 193 #endif 194 #define DEFLT F_USTAR /* default write format from list above */ 195 196 /* 197 * ford is the archive search order used by get_arc() to determine what kind 198 * of archive we are dealing with. This helps to properly id archive formats 199 * some formats may be subsets of others.... 200 */ 201 int ford[] = {F_USTAR, F_TAR, 202 #ifndef NO_CPIO 203 F_SV4CRC, F_SV4CPIO, F_CPIO, F_BCPIO, 204 #endif 205 -1}; 206 207 /* 208 * filename record separator 209 */ 210 int sep = '\n'; 211 212 /* 213 * Do we have -C anywhere? 214 */ 215 int havechd = 0; 216 217 /* 218 * options() 219 * figure out if we are pax, tar or cpio. Call the appropriate options 220 * parser 221 */ 222 223 void 224 options(int argc, char **argv) 225 { 226 227 /* 228 * Are we acting like pax, tar or cpio (based on argv[0]) 229 */ 230 if ((argv0 = strrchr(argv[0], '/')) != NULL) 231 argv0++; 232 else 233 argv0 = argv[0]; 234 235 if (strstr(argv0, NM_TAR)) { 236 argv0 = NM_TAR; 237 tar_options(argc, argv); 238 #ifndef NO_CPIO 239 } else if (strstr(argv0, NM_CPIO)) { 240 argv0 = NM_CPIO; 241 cpio_options(argc, argv); 242 #endif 243 } else { 244 argv0 = NM_PAX; 245 pax_options(argc, argv); 246 } 247 } 248 249 struct option pax_longopts[] = { 250 { "insecure", no_argument, 0, 251 OPT_INSECURE }, 252 { "force-local", no_argument, 0, 253 OPT_FORCE_LOCAL }, 254 { "use-compress-program", required_argument, 0, 255 OPT_USE_COMPRESS_PROGRAM }, 256 { "xz", no_argument, 0, 257 OPT_XZ }, 258 { "gnu", no_argument, 0, 259 OPT_GNU }, 260 { "timestamp", required_argument, 0, 261 OPT_TIMESTAMP }, 262 { 0, 0, 0, 263 0 }, 264 }; 265 266 /* 267 * pax_options() 268 * look at the user specified flags. set globals as required and check if 269 * the user specified a legal set of flags. If not, complain and exit 270 */ 271 272 static void 273 pax_options(int argc, char **argv) 274 { 275 int c; 276 size_t i; 277 u_int64_t flg = 0; 278 u_int64_t bflg = 0; 279 char *pt; 280 FSUB tmp; 281 282 /* 283 * process option flags 284 */ 285 while ((c = getopt_long(argc, argv, 286 "0ab:cdf:ijklno:p:rs:tuvwx:zAB:DE:G:HLMN:OPT:U:VXYZ", 287 pax_longopts, NULL)) != -1) { 288 switch (c) { 289 case '0': 290 sep = '\0'; 291 break; 292 case 'a': 293 /* 294 * append 295 */ 296 flg |= AF; 297 break; 298 case 'b': 299 /* 300 * specify blocksize 301 */ 302 flg |= BF; 303 if ((wrblksz = (int)str_offt(optarg)) <= 0) { 304 tty_warn(1, "Invalid block size %s", optarg); 305 pax_usage(); 306 } 307 break; 308 case 'c': 309 /* 310 * inverse match on patterns 311 */ 312 cflag = 1; 313 flg |= CF; 314 break; 315 case 'd': 316 /* 317 * match only dir on extract, not the subtree at dir 318 */ 319 dflag = 1; 320 flg |= DF; 321 break; 322 case 'f': 323 /* 324 * filename where the archive is stored 325 */ 326 arcname = optarg; 327 flg |= FF; 328 break; 329 case 'i': 330 /* 331 * interactive file rename 332 */ 333 iflag = 1; 334 flg |= IF; 335 break; 336 case 'j': 337 /* 338 * pass through bzip2 339 */ 340 gzip_program = BZIP2_CMD; 341 break; 342 case 'k': 343 /* 344 * do not clobber files that exist 345 */ 346 kflag = 1; 347 flg |= KF; 348 break; 349 case 'l': 350 /* 351 * try to link src to dest with copy (-rw) 352 */ 353 lflag = 1; 354 flg |= LF; 355 break; 356 case 'n': 357 /* 358 * select first match for a pattern only 359 */ 360 nflag = 1; 361 flg |= NF; 362 break; 363 case 'o': 364 /* 365 * pass format specific options 366 */ 367 flg |= OF; 368 if (opt_add(optarg) < 0) 369 pax_usage(); 370 break; 371 case 'p': 372 /* 373 * specify file characteristic options 374 */ 375 for (pt = optarg; *pt != '\0'; ++pt) { 376 switch(*pt) { 377 case 'a': 378 /* 379 * do not preserve access time 380 */ 381 patime = 0; 382 break; 383 case 'e': 384 /* 385 * preserve user id, group id, file 386 * mode, access/modification times 387 * and file flags. 388 */ 389 pids = 1; 390 pmode = 1; 391 patime = 1; 392 pmtime = 1; 393 pfflags = 1; 394 break; 395 #if 0 396 case 'f': 397 /* 398 * do not preserve file flags 399 */ 400 pfflags = 0; 401 break; 402 #endif 403 case 'm': 404 /* 405 * do not preserve modification time 406 */ 407 pmtime = 0; 408 break; 409 case 'o': 410 /* 411 * preserve uid/gid 412 */ 413 pids = 1; 414 break; 415 case 'p': 416 /* 417 * preserve file mode bits 418 */ 419 pmode = 1; 420 break; 421 default: 422 tty_warn(1, "Invalid -p string: %c", 423 *pt); 424 pax_usage(); 425 break; 426 } 427 } 428 flg |= PF; 429 break; 430 case 'r': 431 /* 432 * read the archive 433 */ 434 flg |= RF; 435 break; 436 case 's': 437 /* 438 * file name substitution name pattern 439 */ 440 if (rep_add(optarg) < 0) { 441 pax_usage(); 442 break; 443 } 444 flg |= SF; 445 break; 446 case 't': 447 /* 448 * preserve access time on filesystem nodes we read 449 */ 450 tflag = 1; 451 flg |= TF; 452 break; 453 case 'u': 454 /* 455 * ignore those older files 456 */ 457 uflag = 1; 458 flg |= UF; 459 break; 460 case 'v': 461 /* 462 * verbose operation mode 463 */ 464 vflag = 1; 465 flg |= VF; 466 break; 467 case 'w': 468 /* 469 * write an archive 470 */ 471 flg |= WF; 472 break; 473 case 'x': 474 /* 475 * specify an archive format on write 476 */ 477 tmp.name = optarg; 478 frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub, 479 sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt); 480 if (frmt != NULL) { 481 flg |= XF; 482 break; 483 } 484 tty_warn(1, "Unknown -x format: %s", optarg); 485 (void)fputs("pax: Known -x formats are:", stderr); 486 for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i) 487 (void)fprintf(stderr, " %s", fsub[i].name); 488 (void)fputs("\n\n", stderr); 489 pax_usage(); 490 break; 491 case 'z': 492 /* 493 * use gzip. Non standard option. 494 */ 495 gzip_program = GZIP_CMD; 496 break; 497 case 'A': 498 Aflag = 1; 499 flg |= CAF; 500 break; 501 case 'B': 502 /* 503 * non-standard option on number of bytes written on a 504 * single archive volume. 505 */ 506 if ((wrlimit = str_offt(optarg)) <= 0) { 507 tty_warn(1, "Invalid write limit %s", optarg); 508 pax_usage(); 509 } 510 if (wrlimit % BLKMULT) { 511 tty_warn(1, 512 "Write limit is not a %d byte multiple", 513 BLKMULT); 514 pax_usage(); 515 } 516 flg |= CBF; 517 break; 518 case 'D': 519 /* 520 * On extraction check file inode change time before the 521 * modification of the file name. Non standard option. 522 */ 523 Dflag = 1; 524 flg |= CDF; 525 break; 526 case 'E': 527 /* 528 * non-standard limit on read faults 529 * 0 indicates stop after first error, values 530 * indicate a limit, "none" try forever 531 */ 532 flg |= CEF; 533 if (strcmp(none, optarg) == 0) 534 maxflt = -1; 535 else if ((maxflt = atoi(optarg)) < 0) { 536 tty_warn(1, 537 "Error count value must be positive"); 538 pax_usage(); 539 } 540 break; 541 case 'G': 542 /* 543 * non-standard option for selecting files within an 544 * archive by group (gid or name) 545 */ 546 if (grp_add(optarg) < 0) { 547 pax_usage(); 548 break; 549 } 550 flg |= CGF; 551 break; 552 case 'H': 553 /* 554 * follow command line symlinks only 555 */ 556 Hflag = 1; 557 flg |= CHF; 558 break; 559 case 'L': 560 /* 561 * follow symlinks 562 */ 563 Lflag = 1; 564 flg |= CLF; 565 break; 566 #ifdef SMALL 567 case 'M': 568 case 'N': 569 tty_warn(1, "Support for -%c is not compiled in", c); 570 exit(1); 571 #else /* !SMALL */ 572 case 'M': 573 /* 574 * Treat list of filenames on stdin as an 575 * mtree(8) specfile. Non standard option. 576 */ 577 Mflag = 1; 578 flg |= CMF; 579 break; 580 case 'N': 581 /* 582 * Use alternative directory for user db lookups. 583 */ 584 if (!setup_getid(optarg)) { 585 tty_warn(1, 586 "Unable to use user and group databases in `%s'", 587 optarg); 588 pax_usage(); 589 } 590 break; 591 #endif /* !SMALL */ 592 case 'O': 593 /* 594 * Force one volume. Non standard option. 595 */ 596 force_one_volume = 1; 597 break; 598 case 'P': 599 /* 600 * do NOT follow symlinks (default) 601 */ 602 Lflag = 0; 603 flg |= CPF; 604 break; 605 case 'T': 606 /* 607 * non-standard option for selecting files within an 608 * archive by modification time range (lower,upper) 609 */ 610 if (trng_add(optarg) < 0) { 611 pax_usage(); 612 break; 613 } 614 flg |= CTF; 615 break; 616 case 'U': 617 /* 618 * non-standard option for selecting files within an 619 * archive by user (uid or name) 620 */ 621 if (usr_add(optarg) < 0) { 622 pax_usage(); 623 break; 624 } 625 flg |= CUF; 626 break; 627 case 'V': 628 /* 629 * somewhat verbose operation mode (no listing) 630 */ 631 Vflag = 1; 632 flg |= VSF; 633 break; 634 case 'X': 635 /* 636 * do not pass over mount points in the file system 637 */ 638 Xflag = 1; 639 flg |= CXF; 640 break; 641 case 'Y': 642 /* 643 * On extraction check file inode change time after the 644 * modification of the file name. Non standard option. 645 */ 646 Yflag = 1; 647 flg |= CYF; 648 break; 649 case 'Z': 650 /* 651 * On extraction check modification time after the 652 * modification of the file name. Non standard option. 653 */ 654 Zflag = 1; 655 flg |= CZF; 656 break; 657 case OPT_INSECURE: 658 secure = 0; 659 break; 660 case OPT_FORCE_LOCAL: 661 forcelocal = 1; 662 break; 663 case OPT_USE_COMPRESS_PROGRAM: 664 gzip_program = optarg; 665 break; 666 case OPT_XZ: 667 gzip_program = XZ_CMD; 668 break; 669 case OPT_GNU: 670 is_gnutar = 1; 671 break; 672 #ifndef SMALL 673 case OPT_TIMESTAMP: 674 if (set_tstamp(optarg, &tst) == -1) { 675 tty_warn(1, "Invalid timestamp `%s'", optarg); 676 tar_usage(); 677 } 678 break; 679 #endif 680 case '?': 681 default: 682 pax_usage(); 683 break; 684 } 685 } 686 687 /* 688 * figure out the operation mode of pax read,write,extract,copy,append 689 * or list. check that we have not been given a bogus set of flags 690 * for the operation mode. 691 */ 692 if (ISLIST(flg)) { 693 act = LIST; 694 listf = stdout; 695 bflg = flg & BDLIST; 696 } else if (ISEXTRACT(flg)) { 697 act = EXTRACT; 698 bflg = flg & BDEXTR; 699 } else if (ISARCHIVE(flg)) { 700 act = ARCHIVE; 701 bflg = flg & BDARCH; 702 } else if (ISAPPND(flg)) { 703 act = APPND; 704 bflg = flg & BDARCH; 705 } else if (ISCOPY(flg)) { 706 act = COPY; 707 bflg = flg & BDCOPY; 708 } else 709 pax_usage(); 710 if (bflg) { 711 printflg(flg); 712 pax_usage(); 713 } 714 715 /* 716 * if we are writing (ARCHIVE) we use the default format if the user 717 * did not specify a format. when we write during an APPEND, we will 718 * adopt the format of the existing archive if none was supplied. 719 */ 720 if (!(flg & XF) && (act == ARCHIVE)) 721 frmt = &(fsub[DEFLT]); 722 723 /* 724 * process the args as they are interpreted by the operation mode 725 */ 726 switch (act) { 727 case LIST: 728 case EXTRACT: 729 for (; optind < argc; optind++) 730 if (pat_add(argv[optind], NULL, 0) < 0) 731 pax_usage(); 732 break; 733 case COPY: 734 if (optind >= argc) { 735 tty_warn(0, "Destination directory was not supplied"); 736 pax_usage(); 737 } 738 --argc; 739 dirptr = argv[argc]; 740 if (mkpath(dirptr) < 0) 741 exit(1); 742 /* FALLTHROUGH */ 743 case ARCHIVE: 744 case APPND: 745 for (; optind < argc; optind++) 746 if (ftree_add(argv[optind], 0) < 0) 747 pax_usage(); 748 /* 749 * no read errors allowed on updates/append operation! 750 */ 751 maxflt = 0; 752 break; 753 } 754 } 755 756 757 /* 758 * tar_options() 759 * look at the user specified flags. set globals as required and check if 760 * the user specified a legal set of flags. If not, complain and exit 761 */ 762 763 struct option tar_longopts[] = { 764 { "block-size", required_argument, 0, 'b' }, 765 { "bunzip2", no_argument, 0, 'j' }, 766 { "bzip2", no_argument, 0, 'j' }, 767 { "create", no_argument, 0, 'c' }, /* F */ 768 /* -e -- no corresponding long option */ 769 { "file", required_argument, 0, 'f' }, 770 { "dereference", no_argument, 0, 'h' }, 771 { "keep-old-files", no_argument, 0, 'k' }, 772 { "one-file-system", no_argument, 0, 'l' }, 773 { "modification-time", no_argument, 0, 'm' }, 774 { "old-archive", no_argument, 0, 'o' }, 775 { "portability", no_argument, 0, 'o' }, 776 { "same-permissions", no_argument, 0, 'p' }, 777 { "preserve-permissions", no_argument, 0, 'p' }, 778 { "preserve", no_argument, 0, 'p' }, 779 { "fast-read", no_argument, 0, 'q' }, 780 { "append", no_argument, 0, 'r' }, /* F */ 781 { "update", no_argument, 0, 'u' }, /* F */ 782 { "list", no_argument, 0, 't' }, /* F */ 783 { "verbose", no_argument, 0, 'v' }, 784 { "interactive", no_argument, 0, 'w' }, 785 { "confirmation", no_argument, 0, 'w' }, 786 { "extract", no_argument, 0, 'x' }, /* F */ 787 { "get", no_argument, 0, 'x' }, /* F */ 788 { "gzip", no_argument, 0, 'z' }, 789 { "gunzip", no_argument, 0, 'z' }, 790 { "read-full-blocks", no_argument, 0, 'B' }, 791 { "directory", required_argument, 0, 'C' }, 792 { "xz", no_argument, 0, 'J' }, 793 { "to-stdout", no_argument, 0, 'O' }, 794 { "absolute-paths", no_argument, 0, 'P' }, 795 { "sparse", no_argument, 0, 'S' }, 796 { "files-from", required_argument, 0, 'T' }, 797 { "summary", no_argument, 0, 'V' }, 798 { "stats", no_argument, 0, 'V' }, 799 { "exclude-from", required_argument, 0, 'X' }, 800 { "compress", no_argument, 0, 'Z' }, 801 { "uncompress", no_argument, 0, 'Z' }, 802 { "strict", no_argument, 0, 803 OPT_STRICT }, 804 { "atime-preserve", no_argument, 0, 805 OPT_ATIME_PRESERVE }, 806 { "unlink", no_argument, 0, 807 OPT_UNLINK }, 808 { "use-compress-program", required_argument, 0, 809 OPT_USE_COMPRESS_PROGRAM }, 810 { "force-local", no_argument, 0, 811 OPT_FORCE_LOCAL }, 812 { "insecure", no_argument, 0, 813 OPT_INSECURE }, 814 { "exclude", required_argument, 0, 815 OPT_EXCLUDE }, 816 { "no-recursion", no_argument, 0, 817 OPT_NORECURSE }, 818 #if !HAVE_NBTOOL_CONFIG_H 819 { "chroot", no_argument, 0, 820 OPT_CHROOT }, 821 #endif 822 { "timestamp", required_argument, 0, 823 OPT_TIMESTAMP }, 824 #if 0 /* Not implemented */ 825 { "catenate", no_argument, 0, 'A' }, /* F */ 826 { "concatenate", no_argument, 0, 'A' }, /* F */ 827 { "diff", no_argument, 0, 'd' }, /* F */ 828 { "compare", no_argument, 0, 'd' }, /* F */ 829 { "checkpoint", no_argument, 0, 830 OPT_CHECKPOINT }, 831 { "help", no_argument, 0, 832 OPT_HELP }, 833 { "info-script", required_argument, 0, 'F' }, 834 { "new-volume-script", required_argument, 0, 'F' }, 835 { "incremental", no_argument, 0, 'G' }, 836 { "listed-incremental", required_argument, 0, 'g' }, 837 { "ignore-zeros", no_argument, 0, 'i' }, 838 { "ignore-failed-read", no_argument, 0, 839 OPT_IGNORE_FAILED_READ }, 840 { "starting-file", no_argument, 0, 'K' }, 841 { "tape-length", required_argument, 0, 'L' }, 842 { "multi-volume", no_argument, 0, 'M' }, 843 { "after-date", required_argument, 0, 'N' }, 844 { "newer", required_argument, 0, 'N' }, 845 { "record-number", no_argument, 0, 'R' }, 846 { "remove-files", no_argument, 0, 847 OPT_REMOVE_FILES }, 848 { "same-order", no_argument, 0, 's' }, 849 { "preserve-order", no_argument, 0, 's' }, 850 { "null", no_argument, 0, 851 OPT_NULL }, 852 { "totals", no_argument, 0, 853 OPT_TOTALS }, 854 { "volume-name", required_argument, 0, 'V' }, /* XXX */ 855 { "label", required_argument, 0, 'V' }, /* XXX */ 856 { "version", no_argument, 0, 857 OPT_VERSION }, 858 { "verify", no_argument, 0, 'W' }, 859 { "block-compress", no_argument, 0, 860 OPT_BLOCK_COMPRESS }, 861 #endif 862 { 0, 0, 0, 0 }, 863 }; 864 865 static void 866 tar_set_action(int op) 867 { 868 if (act != ERROR && act != op) 869 tar_usage(); 870 act = op; 871 } 872 873 static void 874 tar_options(int argc, char **argv) 875 { 876 int c; 877 int fstdin = 0; 878 int Oflag = 0; 879 int nincfiles = 0; 880 int incfiles_max = 0; 881 struct incfile { 882 char *file; 883 char *dir; 884 }; 885 struct incfile *incfiles = NULL; 886 887 /* 888 * Set default values. 889 */ 890 rmleadslash = 1; 891 is_gnutar = 1; 892 893 /* 894 * process option flags 895 */ 896 while ((c = getoldopt(argc, argv, 897 "+b:cef:hjklmopqrs:tuvwxzBC:HI:JOPST:X:Z014578", 898 tar_longopts, NULL)) 899 != -1) { 900 switch(c) { 901 case 'b': 902 /* 903 * specify blocksize in 512-byte blocks 904 */ 905 if ((wrblksz = (int)str_offt(optarg)) <= 0) { 906 tty_warn(1, "Invalid block size %s", optarg); 907 tar_usage(); 908 } 909 wrblksz *= 512; /* XXX - check for int oflow */ 910 break; 911 case 'c': 912 /* 913 * create an archive 914 */ 915 tar_set_action(ARCHIVE); 916 break; 917 case 'e': 918 /* 919 * stop after first error 920 */ 921 maxflt = 0; 922 break; 923 case 'f': 924 /* 925 * filename where the archive is stored 926 */ 927 if ((optarg[0] == '-') && (optarg[1]== '\0')) { 928 /* 929 * treat a - as stdin 930 */ 931 fstdin = 1; 932 arcname = NULL; 933 break; 934 } 935 fstdin = 0; 936 arcname = optarg; 937 break; 938 case 'h': 939 /* 940 * follow symlinks 941 */ 942 Lflag = 1; 943 break; 944 case 'j': 945 /* 946 * pass through bzip2. not a standard option 947 */ 948 gzip_program = BZIP2_CMD; 949 break; 950 case 'k': 951 /* 952 * do not clobber files that exist 953 */ 954 kflag = 1; 955 break; 956 case 'l': 957 /* 958 * do not pass over mount points in the file system 959 */ 960 Xflag = 1; 961 break; 962 case 'm': 963 /* 964 * do not preserve modification time 965 */ 966 pmtime = 0; 967 break; 968 case 'o': 969 /* 970 * This option does several things based on whether 971 * this is a create or extract operation. 972 */ 973 if (act == ARCHIVE) { 974 /* GNU tar: write V7 format archives. */ 975 Oflag = 1; 976 /* 4.2BSD: don't add directory entries. */ 977 if (opt_add("write_opt=nodir") < 0) 978 tar_usage(); 979 980 } else { 981 /* SUS: don't preserve owner/group. */ 982 pids = 0; 983 nopids = 1; 984 } 985 break; 986 case 'p': 987 /* 988 * preserve user id, group id, file 989 * mode, access/modification times 990 */ 991 if (!nopids) 992 pids = 1; 993 pmode = 1; 994 patime = 1; 995 pmtime = 1; 996 break; 997 case 'q': 998 /* 999 * select first match for a pattern only 1000 */ 1001 nflag = 1; 1002 break; 1003 case 'r': 1004 case 'u': 1005 /* 1006 * append to the archive 1007 */ 1008 tar_set_action(APPND); 1009 break; 1010 case 's': 1011 /* 1012 * file name substitution name pattern 1013 */ 1014 if (rep_add(optarg) < 0) { 1015 tar_usage(); 1016 break; 1017 } 1018 break; 1019 case 't': 1020 /* 1021 * list contents of the tape 1022 */ 1023 tar_set_action(LIST); 1024 break; 1025 case 'v': 1026 /* 1027 * verbose operation mode 1028 */ 1029 vflag = 1; 1030 break; 1031 case 'w': 1032 /* 1033 * interactive file rename 1034 */ 1035 iflag = 1; 1036 break; 1037 case 'x': 1038 /* 1039 * extract an archive, preserving mode, 1040 * and mtime if possible. 1041 */ 1042 tar_set_action(EXTRACT); 1043 pmtime = 1; 1044 break; 1045 case 'z': 1046 /* 1047 * use gzip. Non standard option. 1048 */ 1049 gzip_program = GZIP_CMD; 1050 break; 1051 case 'B': 1052 /* 1053 * Nothing to do here, this is pax default 1054 */ 1055 break; 1056 case 'C': 1057 havechd++; 1058 chdname = optarg; 1059 break; 1060 case 'H': 1061 /* 1062 * follow command line symlinks only 1063 */ 1064 Hflag = 1; 1065 break; 1066 case 'I': 1067 case 'T': 1068 if (++nincfiles > incfiles_max) { 1069 incfiles_max = nincfiles + 3; 1070 incfiles = realloc(incfiles, 1071 sizeof(*incfiles) * incfiles_max); 1072 if (incfiles == NULL) { 1073 tty_warn(0, "Unable to allocate space " 1074 "for option list"); 1075 exit(1); 1076 } 1077 } 1078 incfiles[nincfiles - 1].file = optarg; 1079 incfiles[nincfiles - 1].dir = chdname; 1080 break; 1081 case 'J': 1082 gzip_program = XZ_CMD; 1083 break; 1084 case 'O': 1085 Oflag = 1; 1086 break; 1087 case 'P': 1088 /* 1089 * do not remove leading '/' from pathnames 1090 */ 1091 rmleadslash = 0; 1092 Aflag = 1; 1093 break; 1094 case 'S': 1095 /* do nothing; we already generate sparse files */ 1096 break; 1097 case 'V': 1098 /* 1099 * semi-verbose operation mode (no listing) 1100 */ 1101 Vflag = 1; 1102 break; 1103 case 'X': 1104 /* 1105 * GNU tar compat: exclude the files listed in optarg 1106 */ 1107 if (tar_gnutar_X_compat(optarg) != 0) 1108 tar_usage(); 1109 break; 1110 case 'Z': 1111 /* 1112 * use compress. 1113 */ 1114 gzip_program = COMPRESS_CMD; 1115 break; 1116 case '0': 1117 arcname = DEV_0; 1118 break; 1119 case '1': 1120 arcname = DEV_1; 1121 break; 1122 case '4': 1123 arcname = DEV_4; 1124 break; 1125 case '5': 1126 arcname = DEV_5; 1127 break; 1128 case '7': 1129 arcname = DEV_7; 1130 break; 1131 case '8': 1132 arcname = DEV_8; 1133 break; 1134 case OPT_ATIME_PRESERVE: 1135 patime = 1; 1136 break; 1137 case OPT_UNLINK: 1138 /* Just ignore -- we always unlink first. */ 1139 break; 1140 case OPT_USE_COMPRESS_PROGRAM: 1141 gzip_program = optarg; 1142 break; 1143 case OPT_FORCE_LOCAL: 1144 forcelocal = 1; 1145 break; 1146 case OPT_INSECURE: 1147 secure = 0; 1148 break; 1149 case OPT_STRICT: 1150 /* disable gnu extensions */ 1151 is_gnutar = 0; 1152 break; 1153 case OPT_EXCLUDE: 1154 if (tar_gnutar_minus_minus_exclude(optarg) != 0) 1155 tar_usage(); 1156 break; 1157 case OPT_NORECURSE: 1158 dflag = 1; 1159 break; 1160 #if !HAVE_NBTOOL_CONFIG_H 1161 case OPT_CHROOT: 1162 do_chroot = 1; 1163 break; 1164 #endif 1165 #ifndef SMALL 1166 case OPT_TIMESTAMP: 1167 if (set_tstamp(optarg, &tst) == -1) { 1168 tty_warn(1, "Invalid timestamp `%s'", optarg); 1169 tar_usage(); 1170 } 1171 break; 1172 #endif 1173 default: 1174 tar_usage(); 1175 break; 1176 } 1177 } 1178 argc -= optind; 1179 argv += optind; 1180 1181 /* Tar requires an action. */ 1182 if (act == ERROR) 1183 tar_usage(); 1184 1185 /* Traditional tar behaviour (pax uses stderr unless in list mode) */ 1186 if (fstdin == 1 && act == ARCHIVE) 1187 listf = stderr; 1188 else 1189 listf = stdout; 1190 1191 /* Traditional tar behaviour (pax wants to read file list from stdin) */ 1192 if ((act == ARCHIVE || act == APPND) && argc == 0 && nincfiles == 0) 1193 exit(0); 1194 /* 1195 * if we are writing (ARCHIVE) specify tar, otherwise run like pax 1196 * (unless -o specified) 1197 */ 1198 if (act == ARCHIVE || act == APPND) 1199 frmt = &(fsub[Oflag ? F_TAR : F_USTAR]); 1200 else if (Oflag) { 1201 if (act == EXTRACT) 1202 to_stdout = 1; 1203 else { 1204 tty_warn(1, "The -O/-o options are only valid when " 1205 "writing or extracting an archive"); 1206 tar_usage(); 1207 } 1208 } 1209 1210 /* 1211 * process the args as they are interpreted by the operation mode 1212 */ 1213 switch (act) { 1214 case LIST: 1215 case EXTRACT: 1216 default: 1217 { 1218 int sawpat = 0; 1219 int dirisnext = 0; 1220 char *file, *dir = NULL; 1221 int mustfreedir = 0; 1222 1223 while (nincfiles || *argv != NULL) { 1224 /* 1225 * If we queued up any include files, 1226 * pull them in now. Otherwise, check 1227 * for -I and -C positional flags. 1228 * Anything else must be a file to 1229 * extract. 1230 */ 1231 if (nincfiles) { 1232 file = incfiles->file; 1233 dir = incfiles->dir; 1234 mustfreedir = 0; 1235 incfiles++; 1236 nincfiles--; 1237 } else if (strcmp(*argv, "-I") == 0) { 1238 if (*++argv == NULL) 1239 break; 1240 file = *argv++; 1241 dir = chdname; 1242 mustfreedir = 0; 1243 } else { 1244 file = NULL; 1245 dir = NULL; 1246 mustfreedir = 0; 1247 } 1248 if (file != NULL) { 1249 FILE *fp; 1250 char *str; 1251 1252 if (strcmp(file, "-") == 0) 1253 fp = stdin; 1254 else if ((fp = fopen(file, "r")) == NULL) { 1255 tty_warn(1, "Unable to open file '%s' for read", file); 1256 tar_usage(); 1257 } 1258 while ((str = get_line(fp)) != NULL) { 1259 if (dirisnext) { 1260 if (dir && mustfreedir) 1261 free(dir); 1262 dir = str; 1263 mustfreedir = 1; 1264 dirisnext = 0; 1265 continue; 1266 } 1267 if (strcmp(str, "-C") == 0) { 1268 havechd++; 1269 dirisnext = 1; 1270 free(str); 1271 continue; 1272 } 1273 if (strncmp(str, "-C ", 3) == 0) { 1274 havechd++; 1275 if (dir && mustfreedir) 1276 free(dir); 1277 dir = strdup(str + 3); 1278 mustfreedir = 1; 1279 free(str); 1280 continue; 1281 } 1282 if (pat_add(str, dir, NOGLOB_MTCH) < 0) 1283 tar_usage(); 1284 sawpat = 1; 1285 } 1286 /* Bomb if given -C w/out a dir. */ 1287 if (dirisnext) 1288 tar_usage(); 1289 if (dir && mustfreedir) 1290 free(dir); 1291 if (strcmp(file, "-") != 0) 1292 fclose(fp); 1293 if (get_line_error) { 1294 tty_warn(1, "Problem with file '%s'", file); 1295 tar_usage(); 1296 } 1297 } else if (strcmp(*argv, "-C") == 0) { 1298 if (*++argv == NULL) 1299 break; 1300 chdname = *argv++; 1301 havechd++; 1302 } else if (pat_add(*argv++, chdname, 0) < 0) 1303 tar_usage(); 1304 else 1305 sawpat = 1; 1306 } 1307 /* 1308 * if patterns were added, we are doing chdir() 1309 * on a file-by-file basis, else, just one 1310 * global chdir (if any) after opening input. 1311 */ 1312 if (sawpat > 0) 1313 chdname = NULL; 1314 } 1315 break; 1316 case ARCHIVE: 1317 case APPND: 1318 if (chdname != NULL) { /* initial chdir() */ 1319 if (ftree_add(chdname, 1) < 0) 1320 tar_usage(); 1321 } 1322 1323 while (nincfiles || *argv != NULL) { 1324 char *file, *dir; 1325 1326 /* 1327 * If we queued up any include files, pull them in 1328 * now. Otherwise, check for -I and -C positional 1329 * flags. Anything else must be a file to include 1330 * in the archive. 1331 */ 1332 if (nincfiles) { 1333 file = incfiles->file; 1334 dir = incfiles->dir; 1335 incfiles++; 1336 nincfiles--; 1337 } else if (strcmp(*argv, "-I") == 0) { 1338 if (*++argv == NULL) 1339 break; 1340 file = *argv++; 1341 dir = NULL; 1342 } else { 1343 file = NULL; 1344 dir = NULL; 1345 } 1346 if (file != NULL) { 1347 FILE *fp; 1348 char *str; 1349 int dirisnext = 0; 1350 1351 /* Set directory if needed */ 1352 if (dir) { 1353 if (ftree_add(dir, 1) < 0) 1354 tar_usage(); 1355 } 1356 1357 if (strcmp(file, "-") == 0) 1358 fp = stdin; 1359 else if ((fp = fopen(file, "r")) == NULL) { 1360 tty_warn(1, "Unable to open file '%s' for read", file); 1361 tar_usage(); 1362 } 1363 while ((str = get_line(fp)) != NULL) { 1364 if (dirisnext) { 1365 if (ftree_add(str, 1) < 0) 1366 tar_usage(); 1367 dirisnext = 0; 1368 continue; 1369 } 1370 if (strcmp(str, "-C") == 0) { 1371 dirisnext = 1; 1372 continue; 1373 } 1374 if (strncmp(str, "-C ", 3) == 0) { 1375 if (ftree_add(str + 3, 1) < 0) 1376 tar_usage(); 1377 continue; 1378 } 1379 if (ftree_add(str, 0) < 0) 1380 tar_usage(); 1381 } 1382 /* Bomb if given -C w/out a dir. */ 1383 if (dirisnext) 1384 tar_usage(); 1385 if (strcmp(file, "-") != 0) 1386 fclose(fp); 1387 if (get_line_error) { 1388 tty_warn(1, "Problem with file '%s'", 1389 file); 1390 tar_usage(); 1391 } 1392 } else if (strcmp(*argv, "-C") == 0) { 1393 if (*++argv == NULL) 1394 break; 1395 if (ftree_add(*argv++, 1) < 0) 1396 tar_usage(); 1397 } else if (ftree_add(*argv++, 0) < 0) 1398 tar_usage(); 1399 } 1400 /* 1401 * no read errors allowed on updates/append operation! 1402 */ 1403 maxflt = 0; 1404 break; 1405 } 1406 if (!fstdin && ((arcname == NULL) || (*arcname == '\0'))) { 1407 arcname = getenv("TAPE"); 1408 if ((arcname == NULL) || (*arcname == '\0')) 1409 arcname = _PATH_DEFTAPE; 1410 } 1411 } 1412 1413 int 1414 mkpath(char *path) 1415 { 1416 char *slash; 1417 int done = 0; 1418 1419 slash = path; 1420 1421 while (!done) { 1422 slash += strspn(slash, "/"); 1423 slash += strcspn(slash, "/"); 1424 1425 done = (*slash == '\0'); 1426 *slash = '\0'; 1427 1428 if (domkdir(path, 0777) == -1) 1429 goto out; 1430 1431 if (!done) 1432 *slash = '/'; 1433 } 1434 1435 return 0; 1436 out: 1437 /* Can't create or or not a directory */ 1438 syswarn(1, errno, "Cannot create directory `%s'", path); 1439 return -1; 1440 } 1441 1442 1443 #ifndef NO_CPIO 1444 struct option cpio_longopts[] = { 1445 { "reset-access-time", no_argument, 0, 'a' }, 1446 { "make-directories", no_argument, 0, 'd' }, 1447 { "nonmatching", no_argument, 0, 'f' }, 1448 { "extract", no_argument, 0, 'i' }, 1449 { "link", no_argument, 0, 'l' }, 1450 { "preserve-modification-time", no_argument, 0, 'm' }, 1451 { "create", no_argument, 0, 'o' }, 1452 { "pass-through", no_argument, 0, 'p' }, 1453 { "rename", no_argument, 0, 'r' }, 1454 { "list", no_argument, 0, 't' }, 1455 { "unconditional", no_argument, 0, 'u' }, 1456 { "verbose", no_argument, 0, 'v' }, 1457 { "append", no_argument, 0, 'A' }, 1458 { "pattern-file", required_argument, 0, 'E' }, 1459 { "file", required_argument, 0, 'F' }, 1460 { "force-local", no_argument, 0, 1461 OPT_FORCE_LOCAL }, 1462 { "format", required_argument, 0, 'H' }, 1463 { "dereference", no_argument, 0, 'L' }, 1464 { "swap-halfwords", no_argument, 0, 'S' }, 1465 { "summary", no_argument, 0, 'V' }, 1466 { "stats", no_argument, 0, 'V' }, 1467 { "insecure", no_argument, 0, 1468 OPT_INSECURE }, 1469 { "sparse", no_argument, 0, 1470 OPT_SPARSE }, 1471 { "xz", no_argument, 0, 1472 OPT_XZ }, 1473 1474 #ifdef notyet 1475 /* Not implemented */ 1476 { "null", no_argument, 0, '0' }, 1477 { "swap", no_argument, 0, 'b' }, 1478 { "numeric-uid-gid", no_argument, 0, 'n' }, 1479 { "swap-bytes", no_argument, 0, 's' }, 1480 { "message", required_argument, 0, 'M' }, 1481 { "owner", required_argument, 0 'R' }, 1482 { "dot", no_argument, 0, 'V' }, /* xxx */ 1483 { "block-size", required_argument, 0, 1484 OPT_BLOCK_SIZE }, 1485 { "no-absolute-pathnames", no_argument, 0, 1486 OPT_NO_ABSOLUTE_PATHNAMES }, 1487 { "no-preserve-owner", no_argument, 0, 1488 OPT_NO_PRESERVE_OWNER }, 1489 { "only-verify-crc", no_argument, 0, 1490 OPT_ONLY_VERIFY_CRC }, 1491 { "rsh-command", required_argument, 0, 1492 OPT_RSH_COMMAND }, 1493 { "version", no_argument, 0, 1494 OPT_VERSION }, 1495 #endif 1496 { 0, 0, 0, 0 }, 1497 }; 1498 1499 static void 1500 cpio_set_action(int op) 1501 { 1502 if ((act == APPND && op == ARCHIVE) || (act == ARCHIVE && op == APPND)) 1503 act = APPND; 1504 else if (act == EXTRACT && op == LIST) 1505 act = op; 1506 else if (act != ERROR && act != op) 1507 cpio_usage(); 1508 else 1509 act = op; 1510 } 1511 1512 /* 1513 * cpio_options() 1514 * look at the user specified flags. set globals as required and check if 1515 * the user specified a legal set of flags. If not, complain and exit 1516 */ 1517 1518 static void 1519 cpio_options(int argc, char **argv) 1520 { 1521 FSUB tmp; 1522 u_int64_t flg = 0; 1523 u_int64_t bflg = 0; 1524 int c; 1525 size_t i; 1526 FILE *fp; 1527 char *str; 1528 1529 uflag = 1; 1530 kflag = 1; 1531 pids = 1; 1532 pmode = 1; 1533 pmtime = 0; 1534 arcname = NULL; 1535 dflag = 1; 1536 nodirs = 1; 1537 /* 1538 * process option flags 1539 */ 1540 while ((c = getoldopt(argc, argv, 1541 "+abcdfiklmoprstuvzABC:E:F:H:I:LM:O:R:SVZ6", 1542 cpio_longopts, NULL)) != -1) { 1543 switch(c) { 1544 case 'a': 1545 /* 1546 * preserve access time on filesystem nodes we read 1547 */ 1548 tflag = 1; 1549 flg |= TF; 1550 break; 1551 #ifdef notyet 1552 case 'b': 1553 /* 1554 * swap bytes and half-words when reading data 1555 */ 1556 break; 1557 #endif 1558 case 'c': 1559 /* 1560 * ASCII cpio header 1561 */ 1562 frmt = &fsub[F_SV4CPIO]; 1563 break; 1564 case 'd': 1565 /* 1566 * create directories as needed 1567 * pax does this by default .. 1568 */ 1569 nodirs = 0; 1570 break; 1571 case 'f': 1572 /* 1573 * inverse match on patterns 1574 */ 1575 cflag = 1; 1576 flg |= CF; 1577 break; 1578 case 'i': 1579 /* 1580 * read the archive 1581 */ 1582 cpio_set_action(EXTRACT); 1583 flg |= RF; 1584 break; 1585 #ifdef notyet 1586 case 'k': 1587 break; 1588 #endif 1589 case 'l': 1590 /* 1591 * try to link src to dest with copy (-rw) 1592 */ 1593 lflag = 1; 1594 flg |= LF; 1595 break; 1596 case 'm': 1597 /* 1598 * preserve mtime 1599 */ 1600 flg |= PF; 1601 pmtime = 1; 1602 break; 1603 case 'o': 1604 /* 1605 * write an archive 1606 */ 1607 cpio_set_action(ARCHIVE); 1608 frmt = &(fsub[F_SV4CRC]); 1609 flg |= WF; 1610 break; 1611 case 'p': 1612 /* 1613 * cpio -p is like pax -rw 1614 */ 1615 cpio_set_action(COPY); 1616 flg |= RF | WF; 1617 break; 1618 case 'r': 1619 /* 1620 * interactive file rename 1621 */ 1622 iflag = 1; 1623 flg |= IF; 1624 break; 1625 #ifdef notyet 1626 case 's': 1627 /* 1628 * swap bytes after reading data 1629 */ 1630 break; 1631 #endif 1632 case 't': 1633 /* 1634 * list contents of archive 1635 */ 1636 cpio_set_action(LIST); 1637 listf = stdout; 1638 flg &= ~RF; 1639 break; 1640 case 'u': 1641 /* 1642 * don't ignore those older files 1643 */ 1644 uflag = 0; 1645 kflag = 0; 1646 flg |= UF; 1647 break; 1648 case 'v': 1649 /* 1650 * verbose operation mode 1651 */ 1652 vflag = 1; 1653 flg |= VF; 1654 break; 1655 case 'z': 1656 /* 1657 * use gzip. Non standard option. 1658 */ 1659 gzip_program = GZIP_CMD; 1660 break; 1661 case 'A': 1662 /* 1663 * append to an archive 1664 */ 1665 cpio_set_action(APPND); 1666 flg |= AF; 1667 break; 1668 case 'B': 1669 /* 1670 * set blocksize to 5120 1671 */ 1672 blksz = 5120; 1673 break; 1674 case 'C': 1675 /* 1676 * specify blocksize 1677 */ 1678 if ((blksz = (int)str_offt(optarg)) <= 0) { 1679 tty_warn(1, "Invalid block size %s", optarg); 1680 cpio_usage(); 1681 } 1682 break; 1683 case 'E': 1684 /* 1685 * file with patterns to extract or list 1686 */ 1687 if ((fp = fopen(optarg, "r")) == NULL) { 1688 tty_warn(1, "Unable to open file '%s' for read", 1689 optarg); 1690 cpio_usage(); 1691 } 1692 while ((str = get_line(fp)) != NULL) { 1693 pat_add(str, NULL, 0); 1694 } 1695 fclose(fp); 1696 if (get_line_error) { 1697 tty_warn(1, "Problem with file '%s'", optarg); 1698 cpio_usage(); 1699 } 1700 break; 1701 case 'H': 1702 /* 1703 * specify an archive format on write 1704 */ 1705 tmp.name = optarg; 1706 frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub, 1707 sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt); 1708 if (frmt != NULL) { 1709 flg |= XF; 1710 break; 1711 } 1712 tty_warn(1, "Unknown -H format: %s", optarg); 1713 (void)fputs("cpio: Known -H formats are:", stderr); 1714 for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i) 1715 (void)fprintf(stderr, " %s", fsub[i].name); 1716 (void)fputs("\n\n", stderr); 1717 cpio_usage(); 1718 break; 1719 case 'F': 1720 case 'I': 1721 case 'O': 1722 /* 1723 * filename where the archive is stored 1724 */ 1725 if ((optarg[0] == '-') && (optarg[1]== '\0')) { 1726 /* 1727 * treat a - as stdin 1728 */ 1729 arcname = NULL; 1730 break; 1731 } 1732 arcname = optarg; 1733 break; 1734 case 'L': 1735 /* 1736 * follow symlinks 1737 */ 1738 Lflag = 1; 1739 flg |= CLF; 1740 break; 1741 #ifdef notyet 1742 case 'M': 1743 arg = optarg; 1744 break; 1745 case 'R': 1746 arg = optarg; 1747 break; 1748 #endif 1749 case 'S': 1750 /* 1751 * swap halfwords after reading data 1752 */ 1753 cpio_swp_head = 1; 1754 break; 1755 #ifdef notyet 1756 case 'V': /* print a '.' for each file processed */ 1757 break; 1758 #endif 1759 case 'V': 1760 /* 1761 * semi-verbose operation mode (no listing) 1762 */ 1763 Vflag = 1; 1764 flg |= VF; 1765 break; 1766 case 'Z': 1767 /* 1768 * use compress. Non standard option. 1769 */ 1770 gzip_program = COMPRESS_CMD; 1771 break; 1772 case '6': 1773 /* 1774 * process Version 6 cpio format 1775 */ 1776 frmt = &(fsub[F_BCPIO]); 1777 break; 1778 case OPT_FORCE_LOCAL: 1779 forcelocal = 1; 1780 break; 1781 case OPT_INSECURE: 1782 secure = 0; 1783 break; 1784 case OPT_SPARSE: 1785 /* do nothing; we already generate sparse files */ 1786 break; 1787 case OPT_XZ: 1788 gzip_program = XZ_CMD; 1789 break; 1790 default: 1791 cpio_usage(); 1792 break; 1793 } 1794 } 1795 1796 /* 1797 * figure out the operation mode of cpio. check that we have not been 1798 * given a bogus set of flags for the operation mode. 1799 */ 1800 if (ISLIST(flg)) { 1801 act = LIST; 1802 bflg = flg & BDLIST; 1803 } else if (ISEXTRACT(flg)) { 1804 act = EXTRACT; 1805 bflg = flg & BDEXTR; 1806 } else if (ISARCHIVE(flg)) { 1807 act = ARCHIVE; 1808 bflg = flg & BDARCH; 1809 } else if (ISAPPND(flg)) { 1810 act = APPND; 1811 bflg = flg & BDARCH; 1812 } else if (ISCOPY(flg)) { 1813 act = COPY; 1814 bflg = flg & BDCOPY; 1815 } else 1816 cpio_usage(); 1817 if (bflg) { 1818 cpio_usage(); 1819 } 1820 1821 /* 1822 * if we are writing (ARCHIVE) we use the default format if the user 1823 * did not specify a format. when we write during an APPEND, we will 1824 * adopt the format of the existing archive if none was supplied. 1825 */ 1826 if (!(flg & XF) && (act == ARCHIVE)) 1827 frmt = &(fsub[F_BCPIO]); 1828 1829 /* 1830 * process the args as they are interpreted by the operation mode 1831 */ 1832 switch (act) { 1833 case LIST: 1834 case EXTRACT: 1835 for (; optind < argc; optind++) 1836 if (pat_add(argv[optind], NULL, 0) < 0) 1837 cpio_usage(); 1838 break; 1839 case COPY: 1840 if (optind >= argc) { 1841 tty_warn(0, "Destination directory was not supplied"); 1842 cpio_usage(); 1843 } 1844 --argc; 1845 dirptr = argv[argc]; 1846 /* FALLTHROUGH */ 1847 case ARCHIVE: 1848 case APPND: 1849 if (argc != optind) { 1850 for (; optind < argc; optind++) 1851 if (ftree_add(argv[optind], 0) < 0) 1852 cpio_usage(); 1853 break; 1854 } 1855 /* 1856 * no read errors allowed on updates/append operation! 1857 */ 1858 maxflt = 0; 1859 while ((str = get_line(stdin)) != NULL) { 1860 ftree_add(str, 0); 1861 } 1862 if (get_line_error) { 1863 tty_warn(1, "Problem while reading stdin"); 1864 cpio_usage(); 1865 } 1866 break; 1867 default: 1868 cpio_usage(); 1869 break; 1870 } 1871 } 1872 #endif 1873 1874 /* 1875 * printflg() 1876 * print out those invalid flag sets found to the user 1877 */ 1878 1879 static void 1880 printflg(unsigned int flg) 1881 { 1882 int nxt; 1883 1884 (void)fprintf(stderr,"%s: Invalid combination of options:", argv0); 1885 while ((nxt = ffs(flg)) != 0) { 1886 flg &= ~(1 << (nxt - 1)); 1887 (void)fprintf(stderr, " -%c", flgch[nxt - 1]); 1888 } 1889 (void)putc('\n', stderr); 1890 } 1891 1892 /* 1893 * c_frmt() 1894 * comparison routine used by bsearch to find the format specified 1895 * by the user 1896 */ 1897 1898 static int 1899 c_frmt(const void *a, const void *b) 1900 { 1901 return strcmp(((const FSUB *)a)->name, ((const FSUB *)b)->name); 1902 } 1903 1904 /* 1905 * opt_next() 1906 * called by format specific options routines to get each format specific 1907 * flag and value specified with -o 1908 * Return: 1909 * pointer to next OPLIST entry or NULL (end of list). 1910 */ 1911 1912 OPLIST * 1913 opt_next(void) 1914 { 1915 OPLIST *opt; 1916 1917 if ((opt = ophead) != NULL) 1918 ophead = ophead->fow; 1919 return opt; 1920 } 1921 1922 /* 1923 * bad_opt() 1924 * generic routine used to complain about a format specific options 1925 * when the format does not support options. 1926 */ 1927 1928 int 1929 bad_opt(void) 1930 { 1931 OPLIST *opt; 1932 1933 if (ophead == NULL) 1934 return 0; 1935 /* 1936 * print all we were given 1937 */ 1938 tty_warn(1," These format options are not supported for %s", 1939 frmt->name); 1940 while ((opt = opt_next()) != NULL) 1941 (void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value); 1942 if (strcmp(NM_TAR, argv0) == 0) 1943 tar_usage(); 1944 #ifndef NO_CPIO 1945 else if (strcmp(NM_CPIO, argv0) == 0) 1946 cpio_usage(); 1947 #endif 1948 else 1949 pax_usage(); 1950 return 0; 1951 } 1952 1953 /* 1954 * opt_add() 1955 * breaks the value supplied to -o into a option name and value. options 1956 * are given to -o in the form -o name-value,name=value 1957 * multiple -o may be specified. 1958 * Return: 1959 * 0 if format in name=value format, -1 if -o is passed junk 1960 */ 1961 1962 int 1963 opt_add(const char *str) 1964 { 1965 OPLIST *opt; 1966 char *frpt; 1967 char *pt; 1968 char *endpt; 1969 char *dstr; 1970 1971 if ((str == NULL) || (*str == '\0')) { 1972 tty_warn(0, "Invalid option name"); 1973 return -1; 1974 } 1975 if ((dstr = strdup(str)) == NULL) { 1976 tty_warn(0, "Unable to allocate space for option list"); 1977 return -1; 1978 } 1979 frpt = endpt = dstr; 1980 1981 /* 1982 * break into name and values pieces and stuff each one into a 1983 * OPLIST structure. When we know the format, the format specific 1984 * option function will go through this list 1985 */ 1986 while ((frpt != NULL) && (*frpt != '\0')) { 1987 if ((endpt = strchr(frpt, ',')) != NULL) 1988 *endpt = '\0'; 1989 if ((pt = strchr(frpt, '=')) == NULL) { 1990 tty_warn(0, "Invalid options format"); 1991 free(dstr); 1992 return -1; 1993 } 1994 if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) { 1995 tty_warn(0, "Unable to allocate space for option list"); 1996 free(dstr); 1997 return -1; 1998 } 1999 *pt++ = '\0'; 2000 opt->name = frpt; 2001 opt->value = pt; 2002 opt->fow = NULL; 2003 if (endpt != NULL) 2004 frpt = endpt + 1; 2005 else 2006 frpt = NULL; 2007 if (ophead == NULL) { 2008 optail = ophead = opt; 2009 continue; 2010 } 2011 optail->fow = opt; 2012 optail = opt; 2013 } 2014 return 0; 2015 } 2016 2017 /* 2018 * str_offt() 2019 * Convert an expression of the following forms to an off_t > 0. 2020 * 1) A positive decimal number. 2021 * 2) A positive decimal number followed by a b (mult by 512). 2022 * 3) A positive decimal number followed by a k (mult by 1024). 2023 * 4) A positive decimal number followed by a m (mult by 512). 2024 * 5) A positive decimal number followed by a w (mult by sizeof int) 2025 * 6) Two or more positive decimal numbers (with/without k,b or w). 2026 * separated by x (also * for backwards compatibility), specifying 2027 * the product of the indicated values. 2028 * Return: 2029 * 0 for an error, a positive value o.w. 2030 */ 2031 2032 static off_t 2033 str_offt(char *val) 2034 { 2035 char *expr; 2036 off_t num, t; 2037 2038 num = STRTOOFFT(val, &expr, 0); 2039 if ((num == OFFT_MAX) || (num <= 0) || (expr == val)) 2040 return 0; 2041 2042 switch(*expr) { 2043 case 'b': 2044 t = num; 2045 num *= 512; 2046 if (t > num) 2047 return 0; 2048 ++expr; 2049 break; 2050 case 'k': 2051 t = num; 2052 num *= 1024; 2053 if (t > num) 2054 return 0; 2055 ++expr; 2056 break; 2057 case 'm': 2058 t = num; 2059 num *= 1048576; 2060 if (t > num) 2061 return 0; 2062 ++expr; 2063 break; 2064 case 'w': 2065 t = num; 2066 num *= sizeof(int); 2067 if (t > num) 2068 return 0; 2069 ++expr; 2070 break; 2071 } 2072 2073 switch(*expr) { 2074 case '\0': 2075 break; 2076 case '*': 2077 case 'x': 2078 t = num; 2079 num *= str_offt(expr + 1); 2080 if (t > num) 2081 return 0; 2082 break; 2083 default: 2084 return 0; 2085 } 2086 return num; 2087 } 2088 2089 static char * 2090 get_line(FILE *f) 2091 { 2092 char *name, *temp; 2093 size_t len; 2094 2095 name = fgetln(f, &len); 2096 if (!name) { 2097 get_line_error = ferror(f) ? GETLINE_FILE_CORRUPT : 0; 2098 return 0; 2099 } 2100 if (name[len-1] != '\n') 2101 len++; 2102 temp = malloc(len); 2103 if (!temp) { 2104 get_line_error = GETLINE_OUT_OF_MEM; 2105 return 0; 2106 } 2107 memcpy(temp, name, len-1); 2108 temp[len-1] = 0; 2109 return temp; 2110 } 2111 2112 #ifndef SMALL 2113 /* 2114 * set_tstamp() 2115 * Use a specific timestamp for all individual files created in the 2116 * archive 2117 */ 2118 static int 2119 set_tstamp(const char *b, struct stat *st) 2120 { 2121 time_t when; 2122 char *eb; 2123 long long l; 2124 2125 if (stat(b, st) != -1) 2126 return 0; 2127 2128 #ifndef HAVE_NBTOOL_CONFIG_H 2129 errno = 0; 2130 if ((when = parsedate(b, NULL, NULL)) == -1 && errno != 0) 2131 #endif 2132 { 2133 errno = 0; 2134 l = strtoll(b, &eb, 0); 2135 if (b == eb || *eb || errno) 2136 return -1; 2137 when = (time_t)l; 2138 } 2139 2140 st->st_ino = 1; 2141 #if HAVE_STRUCT_STAT_BIRTHTIME 2142 st->st_birthtime = 2143 #endif 2144 st->st_mtime = st->st_ctime = st->st_atime = when; 2145 return 0; 2146 } 2147 #endif 2148 2149 /* 2150 * no_op() 2151 * for those option functions where the archive format has nothing to do. 2152 * Return: 2153 * 0 2154 */ 2155 2156 static int 2157 no_op(void) 2158 { 2159 return 0; 2160 } 2161 2162 /* 2163 * pax_usage() 2164 * print the usage summary to the user 2165 */ 2166 2167 static void 2168 pax_usage(void) 2169 { 2170 fprintf(stderr, 2171 "usage: pax [-0cdjnvzVO] [-E limit] [-f archive] [-N dbdir] [-s replstr] ...\n" 2172 " [-U user] ... [-G group] ... [-T [from_date][,to_date]] ...\n" 2173 " [pattern ...]\n"); 2174 fprintf(stderr, 2175 " pax -r [-cdijknuvzADOVYZ] [-E limit] [-f archive] [-N dbdir]\n" 2176 " [-o options] ... [-p string] ... [-s replstr] ... [-U user] ...\n" 2177 " [-G group] ... [-T [from_date][,to_date]] ... [pattern ...]\n"); 2178 fprintf(stderr, 2179 " pax -w [-dijtuvzAHLMOPVX] [-b blocksize] [[-a] [-f archive]] [-x format]\n" 2180 " [-B bytes] [-N dbdir] [-o options] ... [-s replstr] ...\n" 2181 " [-U user] ... [-G group] ...\n" 2182 " [-T [from_date][,to_date][/[c][m]]] ... [file ...]\n"); 2183 fprintf(stderr, 2184 " pax -r -w [-dijklntuvzADHLMOPVXYZ] [-N dbdir] [-p string] ...\n" 2185 " [-s replstr] ... [-U user] ... [-G group] ...\n" 2186 " [-T [from_date][,to_date][/[c][m]]] ... [file ...] directory\n"); 2187 exit(1); 2188 /* NOTREACHED */ 2189 } 2190 2191 /* 2192 * tar_usage() 2193 * print the usage summary to the user 2194 */ 2195 2196 static void 2197 tar_usage(void) 2198 { 2199 (void)fputs("usage: tar [-]{crtux}[-befhjklmopqvwzHJOPSXZ014578] " 2200 "[archive] [blocksize]\n" 2201 " [-C directory] [-T file] [-s replstr] " 2202 "[file ...]\n", stderr); 2203 exit(1); 2204 /* NOTREACHED */ 2205 } 2206 2207 #ifndef NO_CPIO 2208 /* 2209 * cpio_usage() 2210 * print the usage summary to the user 2211 */ 2212 2213 static void 2214 cpio_usage(void) 2215 { 2216 2217 (void)fputs("usage: cpio -o [-aABcLvzZ] [-C bytes] [-F archive] " 2218 "[-H format] [-O archive]\n" 2219 " < name-list [> archive]\n" 2220 " cpio -i [-bBcdfmrsStuvzZ6] [-C bytes] [-E file] " 2221 "[-F archive] [-H format] \n" 2222 " [-I archive] " 2223 "[pattern ...] [< archive]\n" 2224 " cpio -p [-adlLmuv] destination-directory " 2225 "< name-list\n", stderr); 2226 exit(1); 2227 /* NOTREACHED */ 2228 } 2229 #endif 2230