Home | History | Annotate | Line # | Download | only in pax
options.c revision 1.1
      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