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