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