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