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