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