1 /* $NetBSD: options.c,v 1.83 2005/02/10 17:48:33 jmc 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.83 2005/02/10 17:48:33 jmc 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 { 0, 0, 0, 0 }, 1382 }; 1383 1384 /* 1385 * cpio_options() 1386 * look at the user specified flags. set globals as required and check if 1387 * the user specified a legal set of flags. If not, complain and exit 1388 */ 1389 1390 static void 1391 cpio_options(int argc, char **argv) 1392 { 1393 FSUB tmp; 1394 unsigned int flg = 0; 1395 unsigned int bflg = 0; 1396 int c, i; 1397 FILE *fp; 1398 char *str; 1399 1400 uflag = 1; 1401 kflag = 1; 1402 pids = 1; 1403 pmode = 1; 1404 pmtime = 0; 1405 arcname = NULL; 1406 dflag = 1; 1407 nodirs = 1; 1408 /* 1409 * process option flags 1410 */ 1411 while ((c = getoldopt(argc, argv, 1412 "+abcdfiklmoprstuvzABC:E:F:H:I:LM:O:R:SVZ6", 1413 cpio_longopts, NULL)) != -1) { 1414 switch(c) { 1415 case 'a': 1416 /* 1417 * preserve access time on filesystem nodes we read 1418 */ 1419 tflag = 1; 1420 flg |= TF; 1421 break; 1422 #ifdef notyet 1423 case 'b': 1424 /* 1425 * swap bytes and half-words when reading data 1426 */ 1427 break; 1428 #endif 1429 case 'c': 1430 /* 1431 * ASCII cpio header 1432 */ 1433 frmt = &fsub[F_SV4CPIO]; 1434 break; 1435 case 'd': 1436 /* 1437 * create directories as needed 1438 * pax does this by default .. 1439 */ 1440 nodirs = 0; 1441 break; 1442 case 'f': 1443 /* 1444 * inverse match on patterns 1445 */ 1446 cflag = 1; 1447 flg |= CF; 1448 break; 1449 case 'i': 1450 /* 1451 * read the archive 1452 */ 1453 act = EXTRACT; 1454 flg |= RF; 1455 break; 1456 #ifdef notyet 1457 case 'k': 1458 break; 1459 #endif 1460 case 'l': 1461 /* 1462 * try to link src to dest with copy (-rw) 1463 */ 1464 lflag = 1; 1465 flg |= LF; 1466 break; 1467 case 'm': 1468 /* 1469 * preserve mtime 1470 */ 1471 flg |= PF; 1472 pmtime = 1; 1473 break; 1474 case 'o': 1475 /* 1476 * write an archive 1477 */ 1478 act = ARCHIVE; 1479 frmt = &(fsub[F_SV4CRC]); 1480 flg |= WF; 1481 break; 1482 case 'p': 1483 /* 1484 * cpio -p is like pax -rw 1485 */ 1486 act = COPY; 1487 flg |= RF | WF; 1488 break; 1489 case 'r': 1490 /* 1491 * interactive file rename 1492 */ 1493 iflag = 1; 1494 flg |= IF; 1495 break; 1496 #ifdef notyet 1497 case 's': 1498 /* 1499 * swap bytes after reading data 1500 */ 1501 break; 1502 #endif 1503 case 't': 1504 /* 1505 * list contents of archive 1506 */ 1507 act = LIST; 1508 listf = stdout; 1509 flg &= ~RF; 1510 break; 1511 case 'u': 1512 /* 1513 * don't ignore those older files 1514 */ 1515 uflag = 0; 1516 kflag = 0; 1517 flg |= UF; 1518 break; 1519 case 'v': 1520 /* 1521 * verbose operation mode 1522 */ 1523 vflag = 1; 1524 flg |= VF; 1525 break; 1526 case 'z': 1527 /* 1528 * use gzip. Non standard option. 1529 */ 1530 gzip_program = GZIP_CMD; 1531 break; 1532 case 'A': 1533 /* 1534 * append to an archive 1535 */ 1536 act = APPND; 1537 flg |= AF; 1538 break; 1539 case 'B': 1540 /* 1541 * set blocksize to 5120 1542 */ 1543 blksz = 5120; 1544 break; 1545 case 'C': 1546 /* 1547 * specify blocksize 1548 */ 1549 if ((blksz = (int)str_offt(optarg)) <= 0) { 1550 tty_warn(1, "Invalid block size %s", optarg); 1551 cpio_usage(); 1552 } 1553 break; 1554 case 'E': 1555 /* 1556 * file with patterns to extract or list 1557 */ 1558 if ((fp = fopen(optarg, "r")) == NULL) { 1559 tty_warn(1, "Unable to open file '%s' for read", 1560 optarg); 1561 cpio_usage(); 1562 } 1563 while ((str = getline(fp)) != NULL) { 1564 pat_add(str, NULL); 1565 } 1566 fclose(fp); 1567 if (getline_error) { 1568 tty_warn(1, "Problem with file '%s'", optarg); 1569 cpio_usage(); 1570 } 1571 break; 1572 case 'H': 1573 /* 1574 * specify an archive format on write 1575 */ 1576 tmp.name = optarg; 1577 frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub, 1578 sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt); 1579 if (frmt != NULL) { 1580 flg |= XF; 1581 break; 1582 } 1583 tty_warn(1, "Unknown -H format: %s", optarg); 1584 (void)fputs("cpio: Known -H formats are:", stderr); 1585 for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i) 1586 (void)fprintf(stderr, " %s", fsub[i].name); 1587 (void)fputs("\n\n", stderr); 1588 cpio_usage(); 1589 break; 1590 case 'I': 1591 case 'O': 1592 /* 1593 * filename where the archive is stored 1594 */ 1595 if ((optarg[0] == '-') && (optarg[1]== '\0')) { 1596 /* 1597 * treat a - as stdin 1598 */ 1599 arcname = NULL; 1600 break; 1601 } 1602 arcname = optarg; 1603 break; 1604 case 'L': 1605 /* 1606 * follow symlinks 1607 */ 1608 Lflag = 1; 1609 flg |= CLF; 1610 break; 1611 #ifdef notyet 1612 case 'M': 1613 arg = optarg; 1614 break; 1615 case 'R': 1616 arg = optarg; 1617 break; 1618 #endif 1619 case 'S': 1620 /* 1621 * swap halfwords after reading data 1622 */ 1623 cpio_swp_head = 1; 1624 break; 1625 #ifdef notyet 1626 case 'V': 1627 break; 1628 #endif 1629 case 'Z': 1630 /* 1631 * use compress. Non standard option. 1632 */ 1633 gzip_program = COMPRESS_CMD; 1634 break; 1635 case '6': 1636 /* 1637 * process Version 6 cpio format 1638 */ 1639 frmt = &(fsub[F_BCPIO]); 1640 case OPT_FORCE_LOCAL: 1641 forcelocal = 1; 1642 break; 1643 case OPT_INSECURE: 1644 secure = 0; 1645 break; 1646 1647 case OPT_SPARSE: 1648 /* do nothing; we already generate sparse files */ 1649 break; 1650 default: 1651 cpio_usage(); 1652 break; 1653 } 1654 } 1655 1656 /* 1657 * figure out the operation mode of cpio. check that we have not been 1658 * given a bogus set of flags for the operation mode. 1659 */ 1660 if (ISLIST(flg)) { 1661 act = LIST; 1662 bflg = flg & BDLIST; 1663 } else if (ISEXTRACT(flg)) { 1664 act = EXTRACT; 1665 bflg = flg & BDEXTR; 1666 } else if (ISARCHIVE(flg)) { 1667 act = ARCHIVE; 1668 bflg = flg & BDARCH; 1669 } else if (ISAPPND(flg)) { 1670 act = APPND; 1671 bflg = flg & BDARCH; 1672 } else if (ISCOPY(flg)) { 1673 act = COPY; 1674 bflg = flg & BDCOPY; 1675 } else 1676 cpio_usage(); 1677 if (bflg) { 1678 cpio_usage(); 1679 } 1680 1681 /* 1682 * if we are writing (ARCHIVE) we use the default format if the user 1683 * did not specify a format. when we write during an APPEND, we will 1684 * adopt the format of the existing archive if none was supplied. 1685 */ 1686 if (!(flg & XF) && (act == ARCHIVE)) 1687 frmt = &(fsub[F_BCPIO]); 1688 1689 /* 1690 * process the args as they are interpreted by the operation mode 1691 */ 1692 switch (act) { 1693 case LIST: 1694 case EXTRACT: 1695 for (; optind < argc; optind++) 1696 if (pat_add(argv[optind], 0) < 0) 1697 cpio_usage(); 1698 break; 1699 case COPY: 1700 if (optind >= argc) { 1701 tty_warn(0, "Destination directory was not supplied"); 1702 cpio_usage(); 1703 } 1704 --argc; 1705 dirptr = argv[argc]; 1706 /* FALLTHROUGH */ 1707 case ARCHIVE: 1708 case APPND: 1709 if (argc != optind) { 1710 for (; optind < argc; optind++) 1711 if (ftree_add(argv[optind], 0) < 0) 1712 cpio_usage(); 1713 break; 1714 } 1715 /* 1716 * no read errors allowed on updates/append operation! 1717 */ 1718 maxflt = 0; 1719 while ((str = getline(stdin)) != NULL) { 1720 ftree_add(str, 0); 1721 } 1722 if (getline_error) { 1723 tty_warn(1, "Problem while reading stdin"); 1724 cpio_usage(); 1725 } 1726 break; 1727 default: 1728 cpio_usage(); 1729 break; 1730 } 1731 } 1732 1733 /* 1734 * printflg() 1735 * print out those invalid flag sets found to the user 1736 */ 1737 1738 static void 1739 printflg(unsigned int flg) 1740 { 1741 int nxt; 1742 1743 (void)fprintf(stderr,"%s: Invalid combination of options:", argv0); 1744 while ((nxt = ffs(flg)) != 0) { 1745 flg &= ~(1 << (nxt - 1)); 1746 (void)fprintf(stderr, " -%c", flgch[nxt - 1]); 1747 } 1748 (void)putc('\n', stderr); 1749 } 1750 1751 /* 1752 * c_frmt() 1753 * comparison routine used by bsearch to find the format specified 1754 * by the user 1755 */ 1756 1757 static int 1758 c_frmt(const void *a, const void *b) 1759 { 1760 return(strcmp(((const FSUB *)a)->name, ((const FSUB *)b)->name)); 1761 } 1762 1763 /* 1764 * opt_next() 1765 * called by format specific options routines to get each format specific 1766 * flag and value specified with -o 1767 * Return: 1768 * pointer to next OPLIST entry or NULL (end of list). 1769 */ 1770 1771 OPLIST * 1772 opt_next(void) 1773 { 1774 OPLIST *opt; 1775 1776 if ((opt = ophead) != NULL) 1777 ophead = ophead->fow; 1778 return(opt); 1779 } 1780 1781 /* 1782 * bad_opt() 1783 * generic routine used to complain about a format specific options 1784 * when the format does not support options. 1785 */ 1786 1787 int 1788 bad_opt(void) 1789 { 1790 OPLIST *opt; 1791 1792 if (ophead == NULL) 1793 return(0); 1794 /* 1795 * print all we were given 1796 */ 1797 tty_warn(1," These format options are not supported for %s", 1798 frmt->name); 1799 while ((opt = opt_next()) != NULL) 1800 (void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value); 1801 if (strcmp(NM_TAR, argv0) == 0) 1802 tar_usage(); 1803 else if (strcmp(NM_CPIO, argv0) == 0) 1804 cpio_usage(); 1805 else 1806 pax_usage(); 1807 return(0); 1808 } 1809 1810 /* 1811 * opt_add() 1812 * breaks the value supplied to -o into a option name and value. options 1813 * are given to -o in the form -o name-value,name=value 1814 * multiple -o may be specified. 1815 * Return: 1816 * 0 if format in name=value format, -1 if -o is passed junk 1817 */ 1818 1819 int 1820 opt_add(const char *str) 1821 { 1822 OPLIST *opt; 1823 char *frpt; 1824 char *pt; 1825 char *endpt; 1826 char *dstr; 1827 1828 if ((str == NULL) || (*str == '\0')) { 1829 tty_warn(0, "Invalid option name"); 1830 return(-1); 1831 } 1832 if ((dstr = strdup(str)) == NULL) { 1833 tty_warn(0, "Unable to allocate space for option list"); 1834 return(-1); 1835 } 1836 frpt = endpt = dstr; 1837 1838 /* 1839 * break into name and values pieces and stuff each one into a 1840 * OPLIST structure. When we know the format, the format specific 1841 * option function will go through this list 1842 */ 1843 while ((frpt != NULL) && (*frpt != '\0')) { 1844 if ((endpt = strchr(frpt, ',')) != NULL) 1845 *endpt = '\0'; 1846 if ((pt = strchr(frpt, '=')) == NULL) { 1847 tty_warn(0, "Invalid options format"); 1848 free(dstr); 1849 return(-1); 1850 } 1851 if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) { 1852 tty_warn(0, "Unable to allocate space for option list"); 1853 free(dstr); 1854 return(-1); 1855 } 1856 *pt++ = '\0'; 1857 opt->name = frpt; 1858 opt->value = pt; 1859 opt->fow = NULL; 1860 if (endpt != NULL) 1861 frpt = endpt + 1; 1862 else 1863 frpt = NULL; 1864 if (ophead == NULL) { 1865 optail = ophead = opt; 1866 continue; 1867 } 1868 optail->fow = opt; 1869 optail = opt; 1870 } 1871 return(0); 1872 } 1873 1874 /* 1875 * str_offt() 1876 * Convert an expression of the following forms to an off_t > 0. 1877 * 1) A positive decimal number. 1878 * 2) A positive decimal number followed by a b (mult by 512). 1879 * 3) A positive decimal number followed by a k (mult by 1024). 1880 * 4) A positive decimal number followed by a m (mult by 512). 1881 * 5) A positive decimal number followed by a w (mult by sizeof int) 1882 * 6) Two or more positive decimal numbers (with/without k,b or w). 1883 * separated by x (also * for backwards compatibility), specifying 1884 * the product of the indicated values. 1885 * Return: 1886 * 0 for an error, a positive value o.w. 1887 */ 1888 1889 static off_t 1890 str_offt(char *val) 1891 { 1892 char *expr; 1893 off_t num, t; 1894 1895 num = STRTOOFFT(val, &expr, 0); 1896 if ((num == OFFT_MAX) || (num <= 0) || (expr == val)) 1897 return(0); 1898 1899 switch(*expr) { 1900 case 'b': 1901 t = num; 1902 num *= 512; 1903 if (t > num) 1904 return(0); 1905 ++expr; 1906 break; 1907 case 'k': 1908 t = num; 1909 num *= 1024; 1910 if (t > num) 1911 return(0); 1912 ++expr; 1913 break; 1914 case 'm': 1915 t = num; 1916 num *= 1048576; 1917 if (t > num) 1918 return(0); 1919 ++expr; 1920 break; 1921 case 'w': 1922 t = num; 1923 num *= sizeof(int); 1924 if (t > num) 1925 return(0); 1926 ++expr; 1927 break; 1928 } 1929 1930 switch(*expr) { 1931 case '\0': 1932 break; 1933 case '*': 1934 case 'x': 1935 t = num; 1936 num *= str_offt(expr + 1); 1937 if (t > num) 1938 return(0); 1939 break; 1940 default: 1941 return(0); 1942 } 1943 return(num); 1944 } 1945 1946 char * 1947 getline(FILE *f) 1948 { 1949 char *name, *temp; 1950 size_t len; 1951 1952 name = fgetln(f, &len); 1953 if (!name) { 1954 getline_error = ferror(f) ? GETLINE_FILE_CORRUPT : 0; 1955 return(0); 1956 } 1957 if (name[len-1] != '\n') 1958 len++; 1959 temp = malloc(len); 1960 if (!temp) { 1961 getline_error = GETLINE_OUT_OF_MEM; 1962 return(0); 1963 } 1964 memcpy(temp, name, len-1); 1965 temp[len-1] = 0; 1966 return(temp); 1967 } 1968 1969 /* 1970 * no_op() 1971 * for those option functions where the archive format has nothing to do. 1972 * Return: 1973 * 0 1974 */ 1975 1976 static int 1977 no_op(void) 1978 { 1979 return(0); 1980 } 1981 1982 /* 1983 * pax_usage() 1984 * print the usage summary to the user 1985 */ 1986 1987 void 1988 pax_usage(void) 1989 { 1990 fprintf(stderr, 1991 "usage: pax [-cdjnvzO] [-E limit] [-f archive] [-N dbdir] [-s replstr] ...\n" 1992 " [-U user] ... [-G group] ... [-T [from_date][,to_date]] ...\n" 1993 " [pattern ...]\n"); 1994 fprintf(stderr, 1995 " pax -r [-cdijknuvzADOYZ] [-E limit] [-f archive] [-N dbdir]\n" 1996 " [-o options] ... [-p string] ... [-s replstr] ... [-U user] ...\n" 1997 " [-G group] ... [-T [from_date][,to_date]] ... [pattern ...]\n"); 1998 fprintf(stderr, 1999 " pax -w [-dijtuvzAHLMOPX] [-b blocksize] [[-a] [-f archive]] [-x format]\n" 2000 " [-B bytes] [-N dbdir] [-o options] ... [-s replstr] ...\n" 2001 " [-U user] ... [-G group] ...\n" 2002 " [-T [from_date][,to_date][/[c][m]]] ... [file ...]\n"); 2003 fprintf(stderr, 2004 " pax -r -w [-dijklntuvzADHLMOPXYZ] [-N dbdir] [-p string] ...\n" 2005 " [-s replstr] ... [-U user] ... [-G group] ...\n" 2006 " [-T [from_date][,to_date][/[c][m]]] ... [file ...] directory\n"); 2007 exit(1); 2008 /* NOTREACHED */ 2009 } 2010 2011 /* 2012 * tar_usage() 2013 * print the usage summary to the user 2014 */ 2015 2016 void 2017 tar_usage(void) 2018 { 2019 (void)fputs("usage: tar [-]{crtux}[-befhjlmopqvwzHOPSXZ014578] [archive] " 2020 "[blocksize]\n" 2021 " [-C directory] [-T file] [-s replstr] " 2022 "[file ...]\n", stderr); 2023 exit(1); 2024 /* NOTREACHED */ 2025 } 2026 2027 /* 2028 * cpio_usage() 2029 * print the usage summary to the user 2030 */ 2031 2032 void 2033 cpio_usage(void) 2034 { 2035 2036 (void)fputs("usage: cpio -o [-aABcLvzZ] [-C bytes] [-F archive] " 2037 "[-H format] [-O archive]\n" 2038 " < name-list [> archive]\n" 2039 " cpio -i [-bBcdfmrsStuvzZ6] [-C bytes] [-E file] " 2040 "[-F archive] [-H format] \n" 2041 " [-I archive] " 2042 "[pattern ...] [< archive]\n" 2043 " cpio -p [-adlLmuv] destination-directory " 2044 "< name-list\n", stderr); 2045 exit(1); 2046 /* NOTREACHED */ 2047 } 2048