1 /* $NetBSD: options.c,v 1.6 1996/03/26 23:54:18 mrg 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 #ifndef lint 41 #if 0 42 static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 4/18/94"; 43 #else 44 static char rcsid[] = "$NetBSD: options.c,v 1.6 1996/03/26 23:54:18 mrg Exp $"; 45 #endif 46 #endif /* not lint */ 47 48 #include <sys/types.h> 49 #include <sys/time.h> 50 #include <sys/stat.h> 51 #include <sys/mtio.h> 52 #include <sys/param.h> 53 #include <stdio.h> 54 #include <ctype.h> 55 #include <string.h> 56 #include <unistd.h> 57 #include <stdlib.h> 58 #include <limits.h> 59 #include "pax.h" 60 #include "options.h" 61 #include "cpio.h" 62 #include "tar.h" 63 #include "extern.h" 64 65 /* 66 * Routines which handle command line options 67 */ 68 69 static char flgch[] = FLGCH; /* list of all possible flags */ 70 static OPLIST *ophead = NULL; /* head for format specific options -x */ 71 static OPLIST *optail = NULL; /* option tail */ 72 73 static int no_op __P((void)); 74 static void printflg __P((unsigned int)); 75 static int c_frmt __P((const void *, const void *)); 76 static off_t str_offt __P((char *)); 77 static void pax_options __P((register int, register char **)); 78 static void pax_usage __P((void)); 79 static void tar_options __P((register int, register char **)); 80 static void tar_usage __P((void)); 81 #ifdef notdef 82 static void cpio_options __P((register int, register char **)); 83 static void cpio_usage __P((void)); 84 #endif 85 86 #define GZIP_CMD "gzip" /* command to run as gzip */ 87 #define COMPRESS_CMD "compress" /* command to run as compress */ 88 89 /* 90 * Format specific routine table - MUST BE IN SORTED ORDER BY NAME 91 * (see pax.h for description of each function) 92 * 93 * name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read, 94 * read, end_read, st_write, write, end_write, trail, 95 * rd_data, wr_data, options 96 */ 97 98 FSUB fsub[] = { 99 /* 0: OLD BINARY CPIO */ 100 "bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd, 101 bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, cpio_trail, 102 rd_wrfile, wr_rdfile, bad_opt, 103 104 /* 1: OLD OCTAL CHARACTER CPIO */ 105 "cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd, 106 cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, cpio_trail, 107 rd_wrfile, wr_rdfile, bad_opt, 108 109 /* 2: SVR4 HEX CPIO */ 110 "sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd, 111 vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, cpio_trail, 112 rd_wrfile, wr_rdfile, bad_opt, 113 114 /* 3: SVR4 HEX CPIO WITH CRC */ 115 "sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd, 116 vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, cpio_trail, 117 rd_wrfile, wr_rdfile, bad_opt, 118 119 /* 4: OLD TAR */ 120 "tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op, 121 tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail, 122 rd_wrfile, wr_rdfile, tar_opt, 123 124 /* 5: POSIX USTAR */ 125 "ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd, 126 ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail, 127 rd_wrfile, wr_rdfile, bad_opt, 128 }; 129 #define F_TAR 4 /* format when called as tar */ 130 #define DEFLT 5 /* default write format from list above */ 131 132 /* 133 * ford is the archive search order used by get_arc() to determine what kind 134 * of archive we are dealing with. This helps to properly id archive formats 135 * some formats may be subsets of others.... 136 */ 137 int ford[] = {5, 4, 3, 2, 1, 0, -1 }; 138 139 /* 140 * options() 141 * figure out if we are pax, tar or cpio. Call the appropriate options 142 * parser 143 */ 144 145 #if __STDC__ 146 void 147 options(register int argc, register char **argv) 148 #else 149 void 150 options(argc, argv) 151 register int argc; 152 register char **argv; 153 #endif 154 { 155 156 /* 157 * Are we acting like pax, tar or cpio (based on argv[0]) 158 */ 159 if ((argv0 = strrchr(argv[0], '/')) != NULL) 160 argv0++; 161 else 162 argv0 = argv[0]; 163 164 if (strcmp(NM_TAR, argv0) == 0) 165 return(tar_options(argc, argv)); 166 # ifdef notdef 167 else if (strcmp(NM_CPIO, argv0) == 0) 168 return(cpio_options(argc, argv)); 169 # endif 170 /* 171 * assume pax as the default 172 */ 173 argv0 = NM_PAX; 174 return(pax_options(argc, argv)); 175 } 176 177 /* 178 * pax_options() 179 * look at the user specified flags. set globals as required and check if 180 * the user specified a legal set of flags. If not, complain and exit 181 */ 182 183 #if __STDC__ 184 static void 185 pax_options(register int argc, register char **argv) 186 #else 187 static void 188 pax_options(argc, argv) 189 register int argc; 190 register char **argv; 191 #endif 192 { 193 register int c; 194 register int i; 195 unsigned int flg = 0; 196 unsigned int bflg = 0; 197 register char *pt; 198 FSUB tmp; 199 extern char *optarg; 200 extern int optind; 201 202 /* 203 * process option flags 204 */ 205 while ((c=getopt(argc,argv,"ab:cdf:iklno:p:rs:tuvwx:zB:DE:G:HLPT:U:XYZ")) 206 != EOF) { 207 switch (c) { 208 case 'a': 209 /* 210 * append 211 */ 212 flg |= AF; 213 break; 214 case 'b': 215 /* 216 * specify blocksize 217 */ 218 flg |= BF; 219 if ((wrblksz = (int)str_offt(optarg)) <= 0) { 220 warn(1, "Invalid block size %s", optarg); 221 pax_usage(); 222 } 223 break; 224 case 'c': 225 /* 226 * inverse match on patterns 227 */ 228 cflag = 1; 229 flg |= CF; 230 break; 231 case 'd': 232 /* 233 * match only dir on extract, not the subtree at dir 234 */ 235 dflag = 1; 236 flg |= DF; 237 break; 238 case 'f': 239 /* 240 * filename where the archive is stored 241 */ 242 arcname = optarg; 243 flg |= FF; 244 break; 245 case 'i': 246 /* 247 * interactive file rename 248 */ 249 iflag = 1; 250 flg |= IF; 251 break; 252 case 'k': 253 /* 254 * do not clobber files that exist 255 */ 256 kflag = 1; 257 flg |= KF; 258 break; 259 case 'l': 260 /* 261 * try to link src to dest with copy (-rw) 262 */ 263 lflag = 1; 264 flg |= LF; 265 break; 266 case 'n': 267 /* 268 * select first match for a pattern only 269 */ 270 nflag = 1; 271 flg |= NF; 272 break; 273 case 'o': 274 /* 275 * pass format specific options 276 */ 277 flg |= OF; 278 if (opt_add(optarg) < 0) 279 pax_usage(); 280 break; 281 case 'p': 282 /* 283 * specify file characteristic options 284 */ 285 for (pt = optarg; *pt != '\0'; ++pt) { 286 switch(*pt) { 287 case 'a': 288 /* 289 * do not preserve access time 290 */ 291 patime = 0; 292 break; 293 case 'e': 294 /* 295 * preserve user id, group id, file 296 * mode, access/modification times 297 */ 298 pids = 1; 299 pmode = 1; 300 patime = 1; 301 pmtime = 1; 302 break; 303 case 'm': 304 /* 305 * do not preserve modification time 306 */ 307 pmtime = 0; 308 break; 309 case 'o': 310 /* 311 * preserve uid/gid 312 */ 313 pids = 1; 314 break; 315 case 'p': 316 /* 317 * preserver file mode bits 318 */ 319 pmode = 1; 320 break; 321 default: 322 warn(1, "Invalid -p string: %c", *pt); 323 pax_usage(); 324 break; 325 } 326 } 327 flg |= PF; 328 break; 329 case 'r': 330 /* 331 * read the archive 332 */ 333 flg |= RF; 334 break; 335 case 's': 336 /* 337 * file name substitution name pattern 338 */ 339 if (rep_add(optarg) < 0) { 340 pax_usage(); 341 break; 342 } 343 flg |= SF; 344 break; 345 case 't': 346 /* 347 * preserve access time on filesystem nodes we read 348 */ 349 tflag = 1; 350 flg |= TF; 351 break; 352 case 'u': 353 /* 354 * ignore those older files 355 */ 356 uflag = 1; 357 flg |= UF; 358 break; 359 case 'v': 360 /* 361 * verbose operation mode 362 */ 363 vflag = 1; 364 flg |= VF; 365 break; 366 case 'w': 367 /* 368 * write an archive 369 */ 370 flg |= WF; 371 break; 372 case 'x': 373 /* 374 * specify an archive format on write 375 */ 376 tmp.name = optarg; 377 if (frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub, 378 sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) { 379 flg |= XF; 380 break; 381 } 382 warn(1, "Unknown -x format: %s", optarg); 383 (void)fputs("pax: Known -x formats are:", stderr); 384 for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i) 385 (void)fprintf(stderr, " %s", fsub[i].name); 386 (void)fputs("\n\n", stderr); 387 pax_usage(); 388 break; 389 case 'z': 390 /* 391 * use gzip. Non standard option. 392 */ 393 zflag = 1; 394 gzip_program = GZIP_CMD; 395 break; 396 case 'B': 397 /* 398 * non-standard option on number of bytes written on a 399 * single archive volume. 400 */ 401 if ((wrlimit = str_offt(optarg)) <= 0) { 402 warn(1, "Invalid write limit %s", optarg); 403 pax_usage(); 404 } 405 if (wrlimit % BLKMULT) { 406 warn(1, "Write limit is not a %d byte multiple", 407 BLKMULT); 408 pax_usage(); 409 } 410 flg |= CBF; 411 break; 412 case 'D': 413 /* 414 * On extraction check file inode change time before the 415 * modification of the file name. Non standard option. 416 */ 417 Dflag = 1; 418 flg |= CDF; 419 break; 420 case 'E': 421 /* 422 * non-standard limit on read faults 423 * 0 indicates stop after first error, values 424 * indicate a limit, "NONE" try forever 425 */ 426 flg |= CEF; 427 if (strcmp(NONE, optarg) == 0) 428 maxflt = -1; 429 else if ((maxflt = atoi(optarg)) < 0) { 430 warn(1, "Error count value must be positive"); 431 pax_usage(); 432 } 433 break; 434 case 'G': 435 /* 436 * non-standard option for selecting files within an 437 * archive by group (gid or name) 438 */ 439 if (grp_add(optarg) < 0) { 440 pax_usage(); 441 break; 442 } 443 flg |= CGF; 444 break; 445 case 'H': 446 /* 447 * follow command line symlinks only 448 */ 449 Hflag = 1; 450 flg |= CHF; 451 break; 452 case 'L': 453 /* 454 * follow symlinks 455 */ 456 Lflag = 1; 457 flg |= CLF; 458 break; 459 case 'P': 460 /* 461 * do NOT follow symlinks (default) 462 */ 463 Lflag = 0; 464 flg |= CPF; 465 break; 466 case 'T': 467 /* 468 * non-standard option for selecting files within an 469 * archive by modification time range (lower,upper) 470 */ 471 if (trng_add(optarg) < 0) { 472 pax_usage(); 473 break; 474 } 475 flg |= CTF; 476 break; 477 case 'U': 478 /* 479 * non-standard option for selecting files within an 480 * archive by user (uid or name) 481 */ 482 if (usr_add(optarg) < 0) { 483 pax_usage(); 484 break; 485 } 486 flg |= CUF; 487 break; 488 case 'X': 489 /* 490 * do not pass over mount points in the file system 491 */ 492 Xflag = 1; 493 flg |= CXF; 494 break; 495 case 'Y': 496 /* 497 * On extraction check file inode change time after the 498 * modification of the file name. Non standard option. 499 */ 500 Yflag = 1; 501 flg |= CYF; 502 break; 503 case 'Z': 504 /* 505 * On extraction check modification time after the 506 * modification of the file name. Non standard option. 507 */ 508 Zflag = 1; 509 flg |= CZF; 510 break; 511 case '?': 512 default: 513 pax_usage(); 514 break; 515 } 516 } 517 518 /* 519 * figure out the operation mode of pax read,write,extract,copy,append 520 * or list. check that we have not been given a bogus set of flags 521 * for the operation mode. 522 */ 523 if (ISLIST(flg)) { 524 act = LIST; 525 bflg = flg & BDLIST; 526 } else if (ISEXTRACT(flg)) { 527 act = EXTRACT; 528 bflg = flg & BDEXTR; 529 } else if (ISARCHIVE(flg)) { 530 act = ARCHIVE; 531 bflg = flg & BDARCH; 532 } else if (ISAPPND(flg)) { 533 act = APPND; 534 bflg = flg & BDARCH; 535 } else if (ISCOPY(flg)) { 536 act = COPY; 537 bflg = flg & BDCOPY; 538 } else 539 pax_usage(); 540 if (bflg) { 541 printflg(flg); 542 pax_usage(); 543 } 544 545 /* 546 * if we are writing (ARCHIVE) we use the default format if the user 547 * did not specify a format. when we write during an APPEND, we will 548 * adopt the format of the existing archive if none was supplied. 549 */ 550 if (!(flg & XF) && (act == ARCHIVE)) 551 frmt = &(fsub[DEFLT]); 552 553 /* 554 * process the args as they are interpreted by the operation mode 555 */ 556 switch (act) { 557 case LIST: 558 case EXTRACT: 559 for (; optind < argc; optind++) 560 if (pat_add(argv[optind]) < 0) 561 pax_usage(); 562 break; 563 case COPY: 564 if (optind >= argc) { 565 warn(0, "Destination directory was not supplied"); 566 pax_usage(); 567 } 568 --argc; 569 dirptr = argv[argc]; 570 /* FALL THROUGH */ 571 case ARCHIVE: 572 case APPND: 573 for (; optind < argc; optind++) 574 if (ftree_add(argv[optind]) < 0) 575 pax_usage(); 576 /* 577 * no read errors allowed on updates/append operation! 578 */ 579 maxflt = 0; 580 break; 581 } 582 } 583 584 585 /* 586 * tar_options() 587 * look at the user specified flags. set globals as required and check if 588 * the user specified a legal set of flags. If not, complain and exit 589 */ 590 591 #if __STDC__ 592 static void 593 tar_options(register int argc, register char **argv) 594 #else 595 static void 596 tar_options(argc, argv) 597 register int argc; 598 register char **argv; 599 #endif 600 { 601 register int c; 602 int fstdin = 0; 603 604 /* 605 * process option flags 606 */ 607 while ((c = getoldopt(argc, argv, "b:cef:moprutvwxzBHLPXZ014578")) 608 != EOF) { 609 switch(c) { 610 case 'b': 611 /* 612 * specify blocksize 613 */ 614 if ((wrblksz = (int)str_offt(optarg)) <= 0) { 615 warn(1, "Invalid block size %s", optarg); 616 tar_usage(); 617 } 618 break; 619 case 'c': 620 /* 621 * create an archive 622 */ 623 act = ARCHIVE; 624 break; 625 case 'e': 626 /* 627 * stop after first error 628 */ 629 maxflt = 0; 630 break; 631 case 'f': 632 /* 633 * filename where the archive is stored 634 */ 635 if ((optarg[0] == '-') && (optarg[1]== '\0')) { 636 /* 637 * treat a - as stdin 638 */ 639 fstdin = 1; 640 arcname = (char *)0; 641 break; 642 } 643 fstdin = 0; 644 arcname = optarg; 645 break; 646 case 'm': 647 /* 648 * do not preserve modification time 649 */ 650 pmtime = 0; 651 break; 652 case 'o': 653 if (opt_add("write_opt=nodir") < 0) 654 tar_usage(); 655 break; 656 case 'p': 657 /* 658 * preserve user id, group id, file 659 * mode, access/modification times 660 */ 661 pids = 1; 662 pmode = 1; 663 patime = 1; 664 pmtime = 1; 665 break; 666 case 'r': 667 case 'u': 668 /* 669 * append to the archive 670 */ 671 act = APPND; 672 break; 673 case 't': 674 /* 675 * list contents of the tape 676 */ 677 act = LIST; 678 break; 679 case 'v': 680 /* 681 * verbose operation mode 682 */ 683 vflag = 1; 684 break; 685 case 'w': 686 /* 687 * interactive file rename 688 */ 689 iflag = 1; 690 break; 691 case 'x': 692 /* 693 * write an archive 694 */ 695 act = EXTRACT; 696 break; 697 case 'z': 698 /* 699 * use gzip. Non standard option. 700 */ 701 zflag = 1; 702 gzip_program = GZIP_CMD; 703 break; 704 case 'B': 705 /* 706 * Nothing to do here, this is pax default 707 */ 708 break; 709 case 'H': 710 /* 711 * follow command line symlinks only 712 */ 713 Hflag = 1; 714 break; 715 case 'L': 716 /* 717 * follow symlinks 718 */ 719 Lflag = 1; 720 break; 721 case 'P': 722 /* 723 * do not follow symlinks 724 */ 725 Lflag = 0; 726 break; 727 case 'X': 728 /* 729 * do not pass over mount points in the file system 730 */ 731 Xflag = 1; 732 break; 733 case 'Z': 734 /* 735 * use compress. 736 */ 737 zflag = 1; 738 gzip_program = COMPRESS_CMD; 739 break; 740 case '0': 741 arcname = DEV_0; 742 break; 743 case '1': 744 arcname = DEV_1; 745 break; 746 case '4': 747 arcname = DEV_4; 748 break; 749 case '5': 750 arcname = DEV_5; 751 break; 752 case '7': 753 arcname = DEV_7; 754 break; 755 case '8': 756 arcname = DEV_8; 757 break; 758 default: 759 tar_usage(); 760 break; 761 } 762 } 763 argc -= optind; 764 argv += optind; 765 766 /* 767 * if we are writing (ARCHIVE) specify tar, otherwise run like pax 768 */ 769 if (act == ARCHIVE) 770 frmt = &(fsub[F_TAR]); 771 772 /* 773 * process the args as they are interpreted by the operation mode 774 */ 775 switch (act) { 776 case LIST: 777 case EXTRACT: 778 default: 779 while (*argv != (char *)NULL) 780 if (pat_add(*argv++) < 0) 781 tar_usage(); 782 break; 783 case ARCHIVE: 784 case APPND: 785 while (*argv != (char *)NULL) 786 if (ftree_add(*argv++) < 0) 787 tar_usage(); 788 /* 789 * no read errors allowed on updates/append operation! 790 */ 791 maxflt = 0; 792 break; 793 } 794 if (!fstdin && ((arcname == (char *)NULL) || (*arcname == '\0'))) { 795 arcname = getenv("TAPE"); 796 if ((arcname == (char *)NULL) || (*arcname == '\0')) 797 arcname = DEV_8; 798 } 799 } 800 801 #ifdef notdef 802 /* 803 * cpio_options() 804 * look at the user specified flags. set globals as required and check if 805 * the user specified a legal set of flags. If not, complain and exit 806 */ 807 808 #if __STDC__ 809 static void 810 cpio_options(register int argc, register char **argv) 811 #else 812 static void 813 cpio_options(argc, argv) 814 register int argc; 815 register char **argv; 816 #endif 817 { 818 } 819 #endif 820 821 /* 822 * printflg() 823 * print out those invalid flag sets found to the user 824 */ 825 826 #if __STDC__ 827 static void 828 printflg(unsigned int flg) 829 #else 830 static void 831 printflg(flg) 832 unsigned int flg; 833 #endif 834 { 835 int nxt; 836 int pos = 0; 837 838 (void)fprintf(stderr,"%s: Invalid combination of options:", argv0); 839 while (nxt = ffs(flg)) { 840 flg = flg >> nxt; 841 pos += nxt; 842 (void)fprintf(stderr, " -%c", flgch[pos-1]); 843 } 844 (void)putc('\n', stderr); 845 } 846 847 /* 848 * c_frmt() 849 * comparison routine used by bsearch to find the format specified 850 * by the user 851 */ 852 853 #if __STDC__ 854 static int 855 c_frmt(const void *a, const void *b) 856 #else 857 static int 858 c_frmt(a, b) 859 void *a; 860 void *b; 861 #endif 862 { 863 return(strcmp(((FSUB *)a)->name, ((FSUB *)b)->name)); 864 } 865 866 /* 867 * opt_next() 868 * called by format specific options routines to get each format specific 869 * flag and value specified with -o 870 * Return: 871 * pointer to next OPLIST entry or NULL (end of list). 872 */ 873 874 #if __STDC__ 875 OPLIST * 876 opt_next(void) 877 #else 878 OPLIST * 879 opt_next() 880 #endif 881 { 882 OPLIST *opt; 883 884 if ((opt = ophead) != NULL) 885 ophead = ophead->fow; 886 return(opt); 887 } 888 889 /* 890 * bad_opt() 891 * generic routine used to complain about a format specific options 892 * when the format does not support options. 893 */ 894 895 #if __STDC__ 896 int 897 bad_opt(void) 898 #else 899 int 900 bad_opt() 901 #endif 902 { 903 register OPLIST *opt; 904 905 if (ophead == NULL) 906 return(0); 907 /* 908 * print all we were given 909 */ 910 warn(1,"These format options are not supported"); 911 while ((opt = opt_next()) != NULL) 912 (void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value); 913 pax_usage(); 914 return(0); 915 } 916 917 /* 918 * opt_add() 919 * breaks the value supplied to -o into a option name and value. options 920 * are given to -o in the form -o name-value,name=value 921 * mulltiple -o may be specified. 922 * Return: 923 * 0 if format in name=value format, -1 if -o is passed junk 924 */ 925 926 #if __STDC__ 927 int 928 opt_add(register char *str) 929 #else 930 int 931 opt_add(str) 932 register char *str; 933 #endif 934 { 935 register OPLIST *opt; 936 register char *frpt; 937 register char *pt; 938 register char *endpt; 939 940 if ((str == NULL) || (*str == '\0')) { 941 warn(0, "Invalid option name"); 942 return(-1); 943 } 944 frpt = endpt = str; 945 946 /* 947 * break into name and values pieces and stuff each one into a 948 * OPLIST structure. When we know the format, the format specific 949 * option function will go through this list 950 */ 951 while ((frpt != NULL) && (*frpt != '\0')) { 952 if ((endpt = strchr(frpt, ',')) != NULL) 953 *endpt = '\0'; 954 if ((pt = strchr(frpt, '=')) == NULL) { 955 warn(0, "Invalid options format"); 956 return(-1); 957 } 958 if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) { 959 warn(0, "Unable to allocate space for option list"); 960 return(-1); 961 } 962 *pt++ = '\0'; 963 opt->name = frpt; 964 opt->value = pt; 965 opt->fow = NULL; 966 if (endpt != NULL) 967 frpt = endpt + 1; 968 else 969 frpt = NULL; 970 if (ophead == NULL) { 971 optail = ophead = opt; 972 continue; 973 } 974 optail->fow = opt; 975 optail = opt; 976 } 977 return(0); 978 } 979 980 /* 981 * str_offt() 982 * Convert an expression of the following forms to an off_t > 0. 983 * 1) A positive decimal number. 984 * 2) A positive decimal number followed by a b (mult by 512). 985 * 3) A positive decimal number followed by a k (mult by 1024). 986 * 4) A positive decimal number followed by a m (mult by 512). 987 * 5) A positive decimal number followed by a w (mult by sizeof int) 988 * 6) Two or more positive decimal numbers (with/without k,b or w). 989 * seperated by x (also * for backwards compatibility), specifying 990 * the product of the indicated values. 991 * Return: 992 * 0 for an error, a positive value o.w. 993 */ 994 995 #if __STDC__ 996 static off_t 997 str_offt(char *val) 998 #else 999 static off_t 1000 str_offt(val) 1001 char *val; 1002 #endif 1003 { 1004 char *expr; 1005 off_t num, t; 1006 1007 # ifdef NET2_STAT 1008 num = strtol(val, &expr, 0); 1009 if ((num == LONG_MAX) || (num <= 0) || (expr == val)) 1010 # else 1011 num = strtoq(val, &expr, 0); 1012 if ((num == QUAD_MAX) || (num <= 0) || (expr == val)) 1013 # endif 1014 return(0); 1015 1016 switch(*expr) { 1017 case 'b': 1018 t = num; 1019 num *= 512; 1020 if (t > num) 1021 return(0); 1022 ++expr; 1023 break; 1024 case 'k': 1025 t = num; 1026 num *= 1024; 1027 if (t > num) 1028 return(0); 1029 ++expr; 1030 break; 1031 case 'm': 1032 t = num; 1033 num *= 1048576; 1034 if (t > num) 1035 return(0); 1036 ++expr; 1037 break; 1038 case 'w': 1039 t = num; 1040 num *= sizeof(int); 1041 if (t > num) 1042 return(0); 1043 ++expr; 1044 break; 1045 } 1046 1047 switch(*expr) { 1048 case '\0': 1049 break; 1050 case '*': 1051 case 'x': 1052 t = num; 1053 num *= str_offt(expr + 1); 1054 if (t > num) 1055 return(0); 1056 break; 1057 default: 1058 return(0); 1059 } 1060 return(num); 1061 } 1062 1063 /* 1064 * no_op() 1065 * for those option functions where the archive format has nothing to do. 1066 * Return: 1067 * 0 1068 */ 1069 1070 #if __STDC__ 1071 static int 1072 no_op(void) 1073 #else 1074 static int 1075 no_op() 1076 #endif 1077 { 1078 return(0); 1079 } 1080 1081 /* 1082 * pax_usage() 1083 * print the usage summary to the user 1084 */ 1085 1086 #if __STDC__ 1087 void 1088 pax_usage(void) 1089 #else 1090 void 1091 pax_usage() 1092 #endif 1093 { 1094 (void)fputs("usage: pax [-cdnv] [-E limit] [-f archive] ", stderr); 1095 (void)fputs("[-s replstr] ... [-U user] ...", stderr); 1096 (void)fputs("\n [-G group] ... ", stderr); 1097 (void)fputs("[-T [from_date][,to_date]] ... ", stderr); 1098 (void)fputs("[pattern ...]\n", stderr); 1099 (void)fputs(" pax -r [-cdiknuvDYZ] [-E limit] ", stderr); 1100 (void)fputs("[-f archive] [-o options] ... \n", stderr); 1101 (void)fputs(" [-p string] ... [-s replstr] ... ", stderr); 1102 (void)fputs("[-U user] ... [-G group] ...\n ", stderr); 1103 (void)fputs("[-T [from_date][,to_date]] ... ", stderr); 1104 (void)fputs(" [pattern ...]\n", stderr); 1105 (void)fputs(" pax -w [-dituvHLPX] [-b blocksize] ", stderr); 1106 (void)fputs("[ [-a] [-f archive] ] [-x format] \n", stderr); 1107 (void)fputs(" [-B bytes] [-s replstr] ... ", stderr); 1108 (void)fputs("[-o options] ... [-U user] ...", stderr); 1109 (void)fputs("\n [-G group] ... ", stderr); 1110 (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr); 1111 (void)fputs("[file ...]\n", stderr); 1112 (void)fputs(" pax -r -w [-diklntuvDHLPXYZ] ", stderr); 1113 (void)fputs("[-p string] ... [-s replstr] ...", stderr); 1114 (void)fputs("\n [-U user] ... [-G group] ... ", stderr); 1115 (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr); 1116 (void)fputs("\n [file ...] directory\n", stderr); 1117 exit(1); 1118 } 1119 1120 /* 1121 * tar_usage() 1122 * print the usage summary to the user 1123 */ 1124 1125 #if __STDC__ 1126 void 1127 tar_usage(void) 1128 #else 1129 void 1130 tar_usage() 1131 #endif 1132 { 1133 (void)fputs("usage: tar -{txru}[cevfbmopwBHLPX014578] [tapefile] ", 1134 stderr); 1135 (void)fputs("[blocksize] file1 file2...\n", stderr); 1136 exit(1); 1137 } 1138 1139 #ifdef notdef 1140 /* 1141 * cpio_usage() 1142 * print the usage summary to the user 1143 */ 1144 1145 #if __STDC__ 1146 void 1147 cpio_usage(void) 1148 #else 1149 void 1150 cpio_usage() 1151 #endif 1152 { 1153 exit(1); 1154 } 1155 #endif 1156