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