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