Home | History | Annotate | Line # | Download | only in pax
options.c revision 1.4
      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[] = "from: @(#)options.c	8.2 (Berkeley) 4/18/94";*/
     40 static char *rcsid = "$Id: options.c,v 1.4 1994/06/14 01:16:10 jtc Exp $";
     41 #endif /* not lint */
     42 
     43 #include <sys/types.h>
     44 #include <sys/time.h>
     45 #include <sys/stat.h>
     46 #include <sys/mtio.h>
     47 #include <sys/param.h>
     48 #include <stdio.h>
     49 #include <ctype.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 	    != EOF) {
    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 				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 					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 			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 				warn(1, "Invalid write limit %s", optarg);
    388 				pax_usage();
    389 			}
    390 			if (wrlimit % BLKMULT) {
    391 				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 				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 			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 int c;
    587 	int fstdin = 0;
    588 
    589 	/*
    590 	 * process option flags
    591 	 */
    592 	while ((c = getoldopt(argc, argv, "b:cef:moprutvwxBHLPX014578"))
    593 	    != EOF)  {
    594 		switch(c) {
    595 		case 'b':
    596 			/*
    597 			 * specify blocksize
    598 			 */
    599 			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
    600 				warn(1, "Invalid block size %s", optarg);
    601 				tar_usage();
    602 			}
    603 			break;
    604 		case 'c':
    605 			/*
    606 			 * create an archive
    607 			 */
    608 			act = ARCHIVE;
    609 			break;
    610 		case 'e':
    611 			/*
    612 			 * stop after first error
    613 			 */
    614 			maxflt = 0;
    615 			break;
    616 		case 'f':
    617 			/*
    618 			 * filename where the archive is stored
    619 			 */
    620 			if ((optarg[0] == '-') && (optarg[1]== '\0')) {
    621 				/*
    622 				 * treat a - as stdin
    623 				 */
    624 				fstdin = 1;
    625 				arcname = (char *)0;
    626 				break;
    627 			}
    628 			fstdin = 0;
    629 			arcname = optarg;
    630 			break;
    631 		case 'm':
    632 			/*
    633 			 * do not preserve modification time
    634 			 */
    635 			pmtime = 0;
    636 			break;
    637 		case 'o':
    638 			if (opt_add("write_opt=nodir") < 0)
    639 				tar_usage();
    640 			break;
    641 		case 'p':
    642 			/*
    643 			 * preserve user id, group id, file
    644 			 * mode, access/modification times
    645 			 */
    646 			pids = 1;
    647 			pmode = 1;
    648 			patime = 1;
    649 			pmtime = 1;
    650 			break;
    651 		case 'r':
    652 		case 'u':
    653 			/*
    654 			 * append to the archive
    655 			 */
    656 			act = APPND;
    657 			break;
    658 		case 't':
    659 			/*
    660 			 * list contents of the tape
    661 			 */
    662 			act = LIST;
    663 			break;
    664 		case 'v':
    665 			/*
    666 			 * verbose operation mode
    667 			 */
    668 			vflag = 1;
    669 			break;
    670 		case 'w':
    671 			/*
    672 			 * interactive file rename
    673 			 */
    674 			iflag = 1;
    675 			break;
    676 		case 'x':
    677 			/*
    678 			 * write an archive
    679 			 */
    680 			act = EXTRACT;
    681 			break;
    682 		case 'B':
    683 			/*
    684 			 * Nothing to do here, this is pax default
    685 			 */
    686 			break;
    687 		case 'H':
    688 			/*
    689 			 * follow command line symlinks only
    690 			 */
    691 			Hflag = 1;
    692 			break;
    693 		case 'L':
    694 			/*
    695 			 * follow symlinks
    696 			 */
    697 			Lflag = 1;
    698 			break;
    699 		case 'P':
    700 			/*
    701 			 * do not follow symlinks
    702 			 */
    703 			Lflag = 0;
    704 			break;
    705 		case 'X':
    706 			/*
    707 			 * do not pass over mount points in the file system
    708 			 */
    709 			Xflag = 1;
    710 			break;
    711 		case '0':
    712 			arcname = DEV_0;
    713 			break;
    714 		case '1':
    715 			arcname = DEV_1;
    716 			break;
    717 		case '4':
    718 			arcname = DEV_4;
    719 			break;
    720 		case '5':
    721 			arcname = DEV_5;
    722 			break;
    723 		case '7':
    724 			arcname = DEV_7;
    725 			break;
    726 		case '8':
    727 			arcname = DEV_8;
    728 			break;
    729 		default:
    730 			tar_usage();
    731 			break;
    732 		}
    733 	}
    734 	argc -= optind;
    735 	argv += optind;
    736 
    737 	/*
    738 	 * if we are writing (ARCHIVE) specify tar, otherwise run like pax
    739 	 */
    740 	if (act == ARCHIVE)
    741 		frmt = &(fsub[F_TAR]);
    742 
    743 	/*
    744 	 * process the args as they are interpreted by the operation mode
    745 	 */
    746 	switch (act) {
    747 	case LIST:
    748 	case EXTRACT:
    749 	default:
    750 		while (*argv != (char *)NULL)
    751 			if (pat_add(*argv++) < 0)
    752 				tar_usage();
    753 		break;
    754 	case ARCHIVE:
    755 	case APPND:
    756 		while (*argv != (char *)NULL)
    757 			if (ftree_add(*argv++) < 0)
    758 				tar_usage();
    759 		/*
    760 		 * no read errors allowed on updates/append operation!
    761 		 */
    762 		maxflt = 0;
    763 		break;
    764 	}
    765 	if (!fstdin && ((arcname == (char *)NULL) || (*arcname == '\0'))) {
    766 		arcname = getenv("TAPE");
    767 		if ((arcname == (char *)NULL) || (*arcname == '\0'))
    768 			arcname = DEV_8;
    769 	}
    770 }
    771 
    772 #ifdef notdef
    773 /*
    774  * cpio_options()
    775  *	look at the user specified flags. set globals as required and check if
    776  *	the user specified a legal set of flags. If not, complain and exit
    777  */
    778 
    779 #if __STDC__
    780 static void
    781 cpio_options(register int argc, register char **argv)
    782 #else
    783 static void
    784 cpio_options(argc, argv)
    785 	register int argc;
    786 	register char **argv;
    787 #endif
    788 {
    789 }
    790 #endif
    791 
    792 /*
    793  * printflg()
    794  *	print out those invalid flag sets found to the user
    795  */
    796 
    797 #if __STDC__
    798 static void
    799 printflg(unsigned int flg)
    800 #else
    801 static void
    802 printflg(flg)
    803 	unsigned int flg;
    804 #endif
    805 {
    806 	int nxt;
    807 	int pos = 0;
    808 
    809 	(void)fprintf(stderr,"%s: Invalid combination of options:", argv0);
    810 	while (nxt = ffs(flg)) {
    811 		flg = flg >> nxt;
    812 		pos += nxt;
    813 		(void)fprintf(stderr, " -%c", flgch[pos-1]);
    814 	}
    815 	(void)putc('\n', stderr);
    816 }
    817 
    818 /*
    819  * c_frmt()
    820  *	comparison routine used by bsearch to find the format specified
    821  *	by the user
    822  */
    823 
    824 #if __STDC__
    825 static int
    826 c_frmt(const void *a, const void *b)
    827 #else
    828 static int
    829 c_frmt(a, b)
    830         void *a;
    831         void *b;
    832 #endif
    833 {
    834         return(strcmp(((FSUB *)a)->name, ((FSUB *)b)->name));
    835 }
    836 
    837 /*
    838  * opt_next()
    839  *	called by format specific options routines to get each format specific
    840  *	flag and value specified with -o
    841  * Return:
    842  *	pointer to next OPLIST entry or NULL (end of list).
    843  */
    844 
    845 #if __STDC__
    846 OPLIST *
    847 opt_next(void)
    848 #else
    849 OPLIST *
    850 opt_next()
    851 #endif
    852 {
    853 	OPLIST *opt;
    854 
    855 	if ((opt = ophead) != NULL)
    856 		ophead = ophead->fow;
    857 	return(opt);
    858 }
    859 
    860 /*
    861  * bad_opt()
    862  *	generic routine used to complain about a format specific options
    863  *	when the format does not support options.
    864  */
    865 
    866 #if __STDC__
    867 int
    868 bad_opt(void)
    869 #else
    870 int
    871 bad_opt()
    872 #endif
    873 {
    874 	register OPLIST *opt;
    875 
    876 	if (ophead == NULL)
    877 		return(0);
    878 	/*
    879 	 * print all we were given
    880 	 */
    881 	warn(1,"These format options are not supported");
    882 	while ((opt = opt_next()) != NULL)
    883 		(void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
    884 	pax_usage();
    885 	return(0);
    886 }
    887 
    888 /*
    889  * opt_add()
    890  *	breaks the value supplied to -o into a option name and value. options
    891  *	are given to -o in the form -o name-value,name=value
    892  *	mulltiple -o may be specified.
    893  * Return:
    894  *	0 if format in name=value format, -1 if -o is passed junk
    895  */
    896 
    897 #if __STDC__
    898 int
    899 opt_add(register char *str)
    900 #else
    901 int
    902 opt_add(str)
    903 	register char *str;
    904 #endif
    905 {
    906 	register OPLIST *opt;
    907 	register char *frpt;
    908 	register char *pt;
    909 	register char *endpt;
    910 
    911 	if ((str == NULL) || (*str == '\0')) {
    912 		warn(0, "Invalid option name");
    913 		return(-1);
    914 	}
    915 	frpt = endpt = str;
    916 
    917 	/*
    918 	 * break into name and values pieces and stuff each one into a
    919 	 * OPLIST structure. When we know the format, the format specific
    920 	 * option function will go through this list
    921 	 */
    922 	while ((frpt != NULL) && (*frpt != '\0')) {
    923 		if ((endpt = strchr(frpt, ',')) != NULL)
    924 			*endpt = '\0';
    925 		if ((pt = strchr(frpt, '=')) == NULL) {
    926 			warn(0, "Invalid options format");
    927 			return(-1);
    928 		}
    929 		if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
    930 			warn(0, "Unable to allocate space for option list");
    931 			return(-1);
    932 		}
    933 		*pt++ = '\0';
    934 		opt->name = frpt;
    935 		opt->value = pt;
    936 		opt->fow = NULL;
    937 		if (endpt != NULL)
    938 			frpt = endpt + 1;
    939 		else
    940 			frpt = NULL;
    941 		if (ophead == NULL) {
    942 			optail = ophead = opt;
    943 			continue;
    944 		}
    945 		optail->fow = opt;
    946 		optail = opt;
    947 	}
    948 	return(0);
    949 }
    950 
    951 /*
    952  * str_offt()
    953  *	Convert an expression of the following forms to an off_t > 0.
    954  * 	1) A positive decimal number.
    955  *	2) A positive decimal number followed by a b (mult by 512).
    956  *	3) A positive decimal number followed by a k (mult by 1024).
    957  *	4) A positive decimal number followed by a m (mult by 512).
    958  *	5) A positive decimal number followed by a w (mult by sizeof int)
    959  *	6) Two or more positive decimal numbers (with/without k,b or w).
    960  *	   seperated by x (also * for backwards compatibility), specifying
    961  *	   the product of the indicated values.
    962  * Return:
    963  *	0 for an error, a positive value o.w.
    964  */
    965 
    966 #if __STDC__
    967 static off_t
    968 str_offt(char *val)
    969 #else
    970 static off_t
    971 str_offt(val)
    972 	char *val;
    973 #endif
    974 {
    975 	char *expr;
    976 	off_t num, t;
    977 
    978 #	ifdef NET2_STAT
    979 	num = strtol(val, &expr, 0);
    980 	if ((num == LONG_MAX) || (num <= 0) || (expr == val))
    981 #	else
    982 	num = strtoq(val, &expr, 0);
    983 	if ((num == QUAD_MAX) || (num <= 0) || (expr == val))
    984 #	endif
    985 		return(0);
    986 
    987 	switch(*expr) {
    988 	case 'b':
    989 		t = num;
    990 		num *= 512;
    991 		if (t > num)
    992 			return(0);
    993 		++expr;
    994 		break;
    995 	case 'k':
    996 		t = num;
    997 		num *= 1024;
    998 		if (t > num)
    999 			return(0);
   1000 		++expr;
   1001 		break;
   1002 	case 'm':
   1003 		t = num;
   1004 		num *= 1048576;
   1005 		if (t > num)
   1006 			return(0);
   1007 		++expr;
   1008 		break;
   1009 	case 'w':
   1010 		t = num;
   1011 		num *= sizeof(int);
   1012 		if (t > num)
   1013 			return(0);
   1014 		++expr;
   1015 		break;
   1016 	}
   1017 
   1018 	switch(*expr) {
   1019 		case '\0':
   1020 			break;
   1021 		case '*':
   1022 		case 'x':
   1023 			t = num;
   1024 			num *= str_offt(expr + 1);
   1025 			if (t > num)
   1026 				return(0);
   1027 			break;
   1028 		default:
   1029 			return(0);
   1030 	}
   1031 	return(num);
   1032 }
   1033 
   1034 /*
   1035  * no_op()
   1036  *	for those option functions where the archive format has nothing to do.
   1037  * Return:
   1038  *	0
   1039  */
   1040 
   1041 #if __STDC__
   1042 static int
   1043 no_op(void)
   1044 #else
   1045 static int
   1046 no_op()
   1047 #endif
   1048 {
   1049 	return(0);
   1050 }
   1051 
   1052 /*
   1053  * pax_usage()
   1054  *	print the usage summary to the user
   1055  */
   1056 
   1057 #if __STDC__
   1058 void
   1059 pax_usage(void)
   1060 #else
   1061 void
   1062 pax_usage()
   1063 #endif
   1064 {
   1065 	(void)fputs("usage: pax [-cdnv] [-E limit] [-f archive] ", stderr);
   1066 	(void)fputs("[-s replstr] ... [-U user] ...", stderr);
   1067 	(void)fputs("\n           [-G group] ... ", stderr);
   1068 	(void)fputs("[-T [from_date][,to_date]] ... ", stderr);
   1069 	(void)fputs("[pattern ...]\n", stderr);
   1070 	(void)fputs("       pax -r [-cdiknuvDYZ] [-E limit] ", stderr);
   1071 	(void)fputs("[-f archive] [-o options] ... \n", stderr);
   1072 	(void)fputs("           [-p string] ... [-s replstr] ... ", stderr);
   1073 	(void)fputs("[-U user] ... [-G group] ...\n           ", stderr);
   1074 	(void)fputs("[-T [from_date][,to_date]] ... ", stderr);
   1075 	(void)fputs(" [pattern ...]\n", stderr);
   1076 	(void)fputs("       pax -w [-dituvHLPX] [-b blocksize] ", stderr);
   1077 	(void)fputs("[ [-a] [-f archive] ] [-x format] \n", stderr);
   1078 	(void)fputs("           [-B bytes] [-s replstr] ... ", stderr);
   1079 	(void)fputs("[-o options] ... [-U user] ...", stderr);
   1080 	(void)fputs("\n           [-G group] ... ", stderr);
   1081 	(void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
   1082 	(void)fputs("[file ...]\n", stderr);
   1083 	(void)fputs("       pax -r -w [-diklntuvDHLPXYZ] ", stderr);
   1084 	(void)fputs("[-p string] ... [-s replstr] ...", stderr);
   1085 	(void)fputs("\n           [-U user] ... [-G group] ... ", stderr);
   1086 	(void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
   1087 	(void)fputs("\n           [file ...] directory\n", stderr);
   1088 	exit(1);
   1089 }
   1090 
   1091 /*
   1092  * tar_usage()
   1093  *	print the usage summary to the user
   1094  */
   1095 
   1096 #if __STDC__
   1097 void
   1098 tar_usage(void)
   1099 #else
   1100 void
   1101 tar_usage()
   1102 #endif
   1103 {
   1104 	(void)fputs("usage: tar -{txru}[cevfbmopwBHLPX014578] [tapefile] ",
   1105 		 stderr);
   1106 	(void)fputs("[blocksize] file1 file2...\n", stderr);
   1107 	exit(1);
   1108 }
   1109 
   1110 #ifdef notdef
   1111 /*
   1112  * cpio_usage()
   1113  *	print the usage summary to the user
   1114  */
   1115 
   1116 #if __STDC__
   1117 void
   1118 cpio_usage(void)
   1119 #else
   1120 void
   1121 cpio_usage()
   1122 #endif
   1123 {
   1124 	exit(1);
   1125 }
   1126 #endif
   1127