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