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