options.c revision 72089
11556Srgrimes/*-
21556Srgrimes * Copyright (c) 1992 Keith Muller.
31556Srgrimes * Copyright (c) 1992, 1993
41556Srgrimes *	The Regents of the University of California.  All rights reserved.
51556Srgrimes *
61556Srgrimes * This code is derived from software contributed to Berkeley by
71556Srgrimes * Keith Muller of the University of California, San Diego.
81556Srgrimes *
91556Srgrimes * Redistribution and use in source and binary forms, with or without
101556Srgrimes * modification, are permitted provided that the following conditions
111556Srgrimes * are met:
121556Srgrimes * 1. Redistributions of source code must retain the above copyright
131556Srgrimes *    notice, this list of conditions and the following disclaimer.
141556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
151556Srgrimes *    notice, this list of conditions and the following disclaimer in the
161556Srgrimes *    documentation and/or other materials provided with the distribution.
171556Srgrimes * 3. All advertising materials mentioning features or use of this software
181556Srgrimes *    must display the following acknowledgement:
191556Srgrimes *	This product includes software developed by the University of
201556Srgrimes *	California, Berkeley and its contributors.
211556Srgrimes * 4. Neither the name of the University nor the names of its contributors
221556Srgrimes *    may be used to endorse or promote products derived from this software
231556Srgrimes *    without specific prior written permission.
241556Srgrimes *
251556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
261556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
271556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
281556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
291556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
301556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
311556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
321556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
331556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
341556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
351556Srgrimes * SUCH DAMAGE.
361556Srgrimes */
371556Srgrimes
381556Srgrimes#ifndef lint
3936049Scharnier#if 0
4036049Scharnierstatic char sccsid[] = "@(#)options.c	8.2 (Berkeley) 4/18/94";
4136049Scharnier#endif
4236049Scharnierstatic const char rcsid[] =
4350471Speter  "$FreeBSD: head/bin/pax/options.c 72089 2001-02-06 10:39:38Z asmodai $";
441556Srgrimes#endif /* not lint */
451556Srgrimes
461556Srgrimes#include <sys/types.h>
471556Srgrimes#include <sys/stat.h>
481556Srgrimes#include <sys/mtio.h>
491556Srgrimes#include <stdio.h>
501556Srgrimes#include <string.h>
511556Srgrimes#include <unistd.h>
521556Srgrimes#include <stdlib.h>
531556Srgrimes#include <limits.h>
541556Srgrimes#include "pax.h"
551556Srgrimes#include "options.h"
561556Srgrimes#include "cpio.h"
571556Srgrimes#include "tar.h"
581556Srgrimes#include "extern.h"
591556Srgrimes
601556Srgrimes/*
611556Srgrimes * Routines which handle command line options
621556Srgrimes */
631556Srgrimes
641556Srgrimesstatic char flgch[] = FLGCH;	/* list of all possible flags */
651556Srgrimesstatic OPLIST *ophead = NULL;	/* head for format specific options -x */
661556Srgrimesstatic OPLIST *optail = NULL;	/* option tail */
671556Srgrimes
681556Srgrimesstatic int no_op __P((void));
691556Srgrimesstatic void printflg __P((unsigned int));
701556Srgrimesstatic int c_frmt __P((const void *, const void *));
711556Srgrimesstatic off_t str_offt __P((char *));
721556Srgrimesstatic void pax_options __P((register int, register char **));
731556Srgrimesstatic void pax_usage __P((void));
741556Srgrimesstatic void tar_options __P((register int, register char **));
751556Srgrimesstatic void tar_usage __P((void));
761556Srgrimes#ifdef notdef
771556Srgrimesstatic void cpio_options __P((register int, register char **));
781556Srgrimesstatic void cpio_usage __P((void));
791556Srgrimes#endif
801556Srgrimes
811556Srgrimes/*
821556Srgrimes *	Format specific routine table - MUST BE IN SORTED ORDER BY NAME
831556Srgrimes *	(see pax.h for description of each function)
841556Srgrimes *
851556Srgrimes * 	name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
861556Srgrimes *	read, end_read, st_write, write, end_write, trail,
871556Srgrimes *	rd_data, wr_data, options
881556Srgrimes */
891556Srgrimes
901556SrgrimesFSUB fsub[] = {
911556Srgrimes/* 0: OLD BINARY CPIO */
927165Sjoerg	{"bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
931556Srgrimes	bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, cpio_trail,
947165Sjoerg	rd_wrfile, wr_rdfile, bad_opt},
951556Srgrimes
961556Srgrimes/* 1: OLD OCTAL CHARACTER CPIO */
977165Sjoerg	{"cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
981556Srgrimes	cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, cpio_trail,
997165Sjoerg	rd_wrfile, wr_rdfile, bad_opt},
1001556Srgrimes
1011556Srgrimes/* 2: SVR4 HEX CPIO */
1027165Sjoerg	{"sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd,
1031556Srgrimes	vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, cpio_trail,
1047165Sjoerg	rd_wrfile, wr_rdfile, bad_opt},
1051556Srgrimes
1061556Srgrimes/* 3: SVR4 HEX CPIO WITH CRC */
1077165Sjoerg	{"sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
1081556Srgrimes	vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, cpio_trail,
1097165Sjoerg	rd_wrfile, wr_rdfile, bad_opt},
1101556Srgrimes
1111556Srgrimes/* 4: OLD TAR */
1127165Sjoerg	{"tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
1131556Srgrimes	tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail,
1147165Sjoerg	rd_wrfile, wr_rdfile, tar_opt},
1151556Srgrimes
1161556Srgrimes/* 5: POSIX USTAR */
1177165Sjoerg	{"ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd,
1181556Srgrimes	ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail,
1197165Sjoerg	rd_wrfile, wr_rdfile, bad_opt},
1201556Srgrimes};
1211556Srgrimes#define F_TAR	4	/* format when called as tar */
1221556Srgrimes#define DEFLT	5	/* default write format from list above */
1231556Srgrimes
1241556Srgrimes/*
1251556Srgrimes * ford is the archive search order used by get_arc() to determine what kind
1261556Srgrimes * of archive we are dealing with. This helps to properly id  archive formats
1271556Srgrimes * some formats may be subsets of others....
1281556Srgrimes */
1291556Srgrimesint ford[] = {5, 4, 3, 2, 1, 0, -1 };
1301556Srgrimes
1311556Srgrimes/*
1321556Srgrimes * options()
1331556Srgrimes *	figure out if we are pax, tar or cpio. Call the appropriate options
1341556Srgrimes *	parser
1351556Srgrimes */
1361556Srgrimes
1371556Srgrimes#if __STDC__
1381556Srgrimesvoid
1391556Srgrimesoptions(register int argc, register char **argv)
1401556Srgrimes#else
1411556Srgrimesvoid
1421556Srgrimesoptions(argc, argv)
1431556Srgrimes	register int argc;
1441556Srgrimes	register char **argv;
1451556Srgrimes#endif
1461556Srgrimes{
1471556Srgrimes
1481556Srgrimes	/*
1491556Srgrimes	 * Are we acting like pax, tar or cpio (based on argv[0])
1501556Srgrimes	 */
1511556Srgrimes	if ((argv0 = strrchr(argv[0], '/')) != NULL)
1521556Srgrimes		argv0++;
1531556Srgrimes	else
1541556Srgrimes		argv0 = argv[0];
1551556Srgrimes
1561556Srgrimes	if (strcmp(NM_TAR, argv0) == 0)
1571556Srgrimes		return(tar_options(argc, argv));
1581556Srgrimes#	ifdef notdef
1591556Srgrimes	else if (strcmp(NM_CPIO, argv0) == 0)
1601556Srgrimes		return(cpio_options(argc, argv));
1611556Srgrimes#	endif
1621556Srgrimes	/*
1631556Srgrimes	 * assume pax as the default
1641556Srgrimes	 */
1651556Srgrimes	argv0 = NM_PAX;
1661556Srgrimes	return(pax_options(argc, argv));
1671556Srgrimes}
1681556Srgrimes
1691556Srgrimes/*
1701556Srgrimes * pax_options()
1711556Srgrimes *	look at the user specified flags. set globals as required and check if
1721556Srgrimes *	the user specified a legal set of flags. If not, complain and exit
1731556Srgrimes */
1741556Srgrimes
1751556Srgrimes#if __STDC__
1761556Srgrimesstatic void
1771556Srgrimespax_options(register int argc, register char **argv)
1781556Srgrimes#else
1791556Srgrimesstatic void
1801556Srgrimespax_options(argc, argv)
1811556Srgrimes	register int argc;
1821556Srgrimes	register char **argv;
1831556Srgrimes#endif
1841556Srgrimes{
1851556Srgrimes	register int c;
1861556Srgrimes	register int i;
1871556Srgrimes	unsigned int flg = 0;
1881556Srgrimes	unsigned int bflg = 0;
1891556Srgrimes	register char *pt;
1901556Srgrimes        FSUB tmp;
1911556Srgrimes
1921556Srgrimes	/*
1931556Srgrimes	 * process option flags
1941556Srgrimes	 */
1951556Srgrimes	while ((c=getopt(argc,argv,"ab:cdf:iklno:p:rs:tuvwx:B:DE:G:HLPT:U:XYZ"))
19624348Simp	    != -1) {
1971556Srgrimes		switch (c) {
1981556Srgrimes		case 'a':
1991556Srgrimes			/*
2001556Srgrimes			 * append
2011556Srgrimes			 */
2021556Srgrimes			flg |= AF;
2031556Srgrimes			break;
2041556Srgrimes		case 'b':
2051556Srgrimes			/*
2061556Srgrimes			 * specify blocksize
2071556Srgrimes			 */
2081556Srgrimes			flg |= BF;
2091556Srgrimes			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
21028904Ssos				pax_warn(1, "Invalid block size %s", optarg);
2111556Srgrimes				pax_usage();
2121556Srgrimes			}
2131556Srgrimes			break;
2141556Srgrimes		case 'c':
2151556Srgrimes			/*
2161556Srgrimes			 * inverse match on patterns
2171556Srgrimes			 */
2181556Srgrimes			cflag = 1;
2191556Srgrimes			flg |= CF;
2201556Srgrimes			break;
2211556Srgrimes		case 'd':
2221556Srgrimes			/*
2231556Srgrimes			 * match only dir on extract, not the subtree at dir
2241556Srgrimes			 */
2251556Srgrimes			dflag = 1;
2261556Srgrimes			flg |= DF;
2271556Srgrimes			break;
2281556Srgrimes		case 'f':
2291556Srgrimes			/*
2301556Srgrimes			 * filename where the archive is stored
2311556Srgrimes			 */
2321556Srgrimes			arcname = optarg;
2331556Srgrimes			flg |= FF;
2341556Srgrimes			break;
2351556Srgrimes		case 'i':
2361556Srgrimes			/*
2371556Srgrimes			 * interactive file rename
2381556Srgrimes			 */
2391556Srgrimes			iflag = 1;
2401556Srgrimes			flg |= IF;
2411556Srgrimes			break;
2421556Srgrimes		case 'k':
2431556Srgrimes			/*
2441556Srgrimes			 * do not clobber files that exist
2451556Srgrimes			 */
2461556Srgrimes			kflag = 1;
2471556Srgrimes			flg |= KF;
2481556Srgrimes			break;
2491556Srgrimes		case 'l':
2501556Srgrimes			/*
2511556Srgrimes			 * try to link src to dest with copy (-rw)
2521556Srgrimes			 */
2531556Srgrimes			lflag = 1;
2541556Srgrimes			flg |= LF;
2551556Srgrimes			break;
2561556Srgrimes		case 'n':
2571556Srgrimes			/*
2581556Srgrimes			 * select first match for a pattern only
2591556Srgrimes			 */
2601556Srgrimes			nflag = 1;
2611556Srgrimes			flg |= NF;
2621556Srgrimes			break;
2631556Srgrimes		case 'o':
2641556Srgrimes			/*
2651556Srgrimes			 * pass format specific options
2661556Srgrimes			 */
2671556Srgrimes			flg |= OF;
2681556Srgrimes			if (opt_add(optarg) < 0)
2691556Srgrimes				pax_usage();
2701556Srgrimes			break;
2711556Srgrimes		case 'p':
2721556Srgrimes			/*
2731556Srgrimes			 * specify file characteristic options
2741556Srgrimes			 */
2751556Srgrimes			for (pt = optarg; *pt != '\0'; ++pt) {
2761556Srgrimes				switch(*pt) {
2771556Srgrimes				case 'a':
2781556Srgrimes					/*
2791556Srgrimes					 * do not preserve access time
2801556Srgrimes					 */
2811556Srgrimes					patime = 0;
2821556Srgrimes					break;
2831556Srgrimes				case 'e':
2841556Srgrimes					/*
2851556Srgrimes					 * preserve user id, group id, file
2861556Srgrimes					 * mode, access/modification times
2871556Srgrimes					 */
2881556Srgrimes					pids = 1;
2891556Srgrimes					pmode = 1;
2901556Srgrimes					patime = 1;
2911556Srgrimes					pmtime = 1;
2921556Srgrimes					break;
2931556Srgrimes				case 'm':
2941556Srgrimes					/*
2951556Srgrimes					 * do not preserve modification time
2961556Srgrimes					 */
2971556Srgrimes					pmtime = 0;
2981556Srgrimes					break;
2991556Srgrimes				case 'o':
3001556Srgrimes					/*
3011556Srgrimes					 * preserve uid/gid
3021556Srgrimes					 */
3031556Srgrimes					pids = 1;
3041556Srgrimes					break;
3051556Srgrimes				case 'p':
3061556Srgrimes					/*
3071556Srgrimes					 * preserver file mode bits
3081556Srgrimes					 */
3091556Srgrimes					pmode = 1;
3101556Srgrimes					break;
3111556Srgrimes				default:
31228904Ssos					pax_warn(1, "Invalid -p string: %c", *pt);
3131556Srgrimes					pax_usage();
3141556Srgrimes					break;
3151556Srgrimes				}
3161556Srgrimes			}
3171556Srgrimes			flg |= PF;
3181556Srgrimes			break;
3191556Srgrimes		case 'r':
3201556Srgrimes			/*
3211556Srgrimes			 * read the archive
3221556Srgrimes			 */
3231556Srgrimes			flg |= RF;
3241556Srgrimes			break;
3251556Srgrimes		case 's':
3261556Srgrimes			/*
3271556Srgrimes			 * file name substitution name pattern
3281556Srgrimes			 */
3291556Srgrimes			if (rep_add(optarg) < 0) {
3301556Srgrimes				pax_usage();
3311556Srgrimes				break;
3321556Srgrimes			}
3331556Srgrimes			flg |= SF;
3341556Srgrimes			break;
3351556Srgrimes		case 't':
3361556Srgrimes			/*
3371556Srgrimes			 * preserve access time on filesystem nodes we read
3381556Srgrimes			 */
3391556Srgrimes			tflag = 1;
3401556Srgrimes			flg |= TF;
3411556Srgrimes			break;
3421556Srgrimes		case 'u':
3431556Srgrimes			/*
3441556Srgrimes			 * ignore those older files
3451556Srgrimes			 */
3461556Srgrimes			uflag = 1;
3471556Srgrimes			flg |= UF;
3481556Srgrimes			break;
3491556Srgrimes		case 'v':
3501556Srgrimes			/*
3511556Srgrimes			 * verbose operation mode
3521556Srgrimes			 */
3531556Srgrimes			vflag = 1;
3541556Srgrimes			flg |= VF;
3551556Srgrimes			break;
3561556Srgrimes		case 'w':
3571556Srgrimes			/*
3581556Srgrimes			 * write an archive
3591556Srgrimes			 */
3601556Srgrimes			flg |= WF;
3611556Srgrimes			break;
3621556Srgrimes		case 'x':
3631556Srgrimes			/*
3641556Srgrimes			 * specify an archive format on write
3651556Srgrimes			 */
3661556Srgrimes			tmp.name = optarg;
3677165Sjoerg			if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
3687165Sjoerg			   sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt))) {
3691556Srgrimes				flg |= XF;
3701556Srgrimes				break;
3711556Srgrimes			}
37228904Ssos			pax_warn(1, "Unknown -x format: %s", optarg);
3731556Srgrimes			(void)fputs("pax: Known -x formats are:", stderr);
3741556Srgrimes			for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
3751556Srgrimes				(void)fprintf(stderr, " %s", fsub[i].name);
3761556Srgrimes			(void)fputs("\n\n", stderr);
3771556Srgrimes			pax_usage();
3781556Srgrimes			break;
3791556Srgrimes		case 'B':
3801556Srgrimes			/*
3811556Srgrimes			 * non-standard option on number of bytes written on a
3821556Srgrimes			 * single archive volume.
3831556Srgrimes			 */
3841556Srgrimes			if ((wrlimit = str_offt(optarg)) <= 0) {
38528904Ssos				pax_warn(1, "Invalid write limit %s", optarg);
3861556Srgrimes				pax_usage();
3871556Srgrimes			}
3881556Srgrimes			if (wrlimit % BLKMULT) {
38928904Ssos				pax_warn(1, "Write limit is not a %d byte multiple",
3901556Srgrimes				    BLKMULT);
3911556Srgrimes				pax_usage();
3921556Srgrimes			}
3931556Srgrimes			flg |= CBF;
3941556Srgrimes			break;
3951556Srgrimes		case 'D':
3961556Srgrimes			/*
3971556Srgrimes			 * On extraction check file inode change time before the
3981556Srgrimes			 * modification of the file name. Non standard option.
3991556Srgrimes			 */
4001556Srgrimes			Dflag = 1;
4011556Srgrimes			flg |= CDF;
4021556Srgrimes			break;
4031556Srgrimes		case 'E':
4041556Srgrimes			/*
4051556Srgrimes			 * non-standard limit on read faults
4061556Srgrimes			 * 0 indicates stop after first error, values
4071556Srgrimes			 * indicate a limit, "NONE" try forever
4081556Srgrimes			 */
4091556Srgrimes			flg |= CEF;
4101556Srgrimes			if (strcmp(NONE, optarg) == 0)
4111556Srgrimes				maxflt = -1;
4121556Srgrimes			else if ((maxflt = atoi(optarg)) < 0) {
41328904Ssos				pax_warn(1, "Error count value must be positive");
4141556Srgrimes				pax_usage();
4151556Srgrimes			}
4161556Srgrimes			break;
4171556Srgrimes		case 'G':
4181556Srgrimes			/*
4191556Srgrimes			 * non-standard option for selecting files within an
4201556Srgrimes			 * archive by group (gid or name)
4211556Srgrimes			 */
4221556Srgrimes			if (grp_add(optarg) < 0) {
4231556Srgrimes				pax_usage();
4241556Srgrimes				break;
4251556Srgrimes			}
4261556Srgrimes			flg |= CGF;
4271556Srgrimes			break;
4281556Srgrimes		case 'H':
4291556Srgrimes			/*
4301556Srgrimes			 * follow command line symlinks only
4311556Srgrimes			 */
4321556Srgrimes			Hflag = 1;
4331556Srgrimes			flg |= CHF;
4341556Srgrimes			break;
4351556Srgrimes		case 'L':
4361556Srgrimes			/*
4371556Srgrimes			 * follow symlinks
4381556Srgrimes			 */
4391556Srgrimes			Lflag = 1;
4401556Srgrimes			flg |= CLF;
4411556Srgrimes			break;
4421556Srgrimes		case 'P':
4431556Srgrimes			/*
4441556Srgrimes			 * do NOT follow symlinks (default)
4451556Srgrimes			 */
4461556Srgrimes			Lflag = 0;
4471556Srgrimes			flg |= CPF;
4481556Srgrimes			break;
4491556Srgrimes		case 'T':
4501556Srgrimes			/*
4511556Srgrimes			 * non-standard option for selecting files within an
4521556Srgrimes			 * archive by modification time range (lower,upper)
4531556Srgrimes			 */
4541556Srgrimes			if (trng_add(optarg) < 0) {
4551556Srgrimes				pax_usage();
4561556Srgrimes				break;
4571556Srgrimes			}
4581556Srgrimes			flg |= CTF;
4591556Srgrimes			break;
4601556Srgrimes		case 'U':
4611556Srgrimes			/*
4621556Srgrimes			 * non-standard option for selecting files within an
4631556Srgrimes			 * archive by user (uid or name)
4641556Srgrimes			 */
4651556Srgrimes			if (usr_add(optarg) < 0) {
4661556Srgrimes				pax_usage();
4671556Srgrimes				break;
4681556Srgrimes			}
4691556Srgrimes			flg |= CUF;
4701556Srgrimes			break;
4711556Srgrimes		case 'X':
4721556Srgrimes			/*
4731556Srgrimes			 * do not pass over mount points in the file system
4741556Srgrimes			 */
4751556Srgrimes			Xflag = 1;
4761556Srgrimes			flg |= CXF;
4771556Srgrimes			break;
4781556Srgrimes		case 'Y':
4791556Srgrimes			/*
4801556Srgrimes			 * On extraction check file inode change time after the
4811556Srgrimes			 * modification of the file name. Non standard option.
4821556Srgrimes			 */
4831556Srgrimes			Yflag = 1;
4841556Srgrimes			flg |= CYF;
4851556Srgrimes			break;
4861556Srgrimes		case 'Z':
4871556Srgrimes			/*
4881556Srgrimes			 * On extraction check modification time after the
4891556Srgrimes			 * modification of the file name. Non standard option.
4901556Srgrimes			 */
4911556Srgrimes			Zflag = 1;
4921556Srgrimes			flg |= CZF;
4931556Srgrimes			break;
4941556Srgrimes		case '?':
4951556Srgrimes		default:
4961556Srgrimes			pax_usage();
4971556Srgrimes			break;
4981556Srgrimes		}
4991556Srgrimes	}
5001556Srgrimes
5011556Srgrimes	/*
5021556Srgrimes	 * figure out the operation mode of pax read,write,extract,copy,append
5031556Srgrimes	 * or list. check that we have not been given a bogus set of flags
5041556Srgrimes	 * for the operation mode.
5051556Srgrimes	 */
5061556Srgrimes	if (ISLIST(flg)) {
5071556Srgrimes		act = LIST;
5081556Srgrimes		bflg = flg & BDLIST;
5091556Srgrimes	} else if (ISEXTRACT(flg)) {
5101556Srgrimes		act = EXTRACT;
5111556Srgrimes		bflg = flg & BDEXTR;
5121556Srgrimes	} else if (ISARCHIVE(flg)) {
5131556Srgrimes		act = ARCHIVE;
5141556Srgrimes		bflg = flg & BDARCH;
5151556Srgrimes	} else if (ISAPPND(flg)) {
5161556Srgrimes		act = APPND;
5171556Srgrimes		bflg = flg & BDARCH;
5181556Srgrimes	} else if (ISCOPY(flg)) {
5191556Srgrimes		act = COPY;
5201556Srgrimes		bflg = flg & BDCOPY;
5211556Srgrimes	} else
5221556Srgrimes		pax_usage();
5231556Srgrimes	if (bflg) {
5241556Srgrimes		printflg(flg);
5251556Srgrimes		pax_usage();
5261556Srgrimes	}
5271556Srgrimes
5281556Srgrimes	/*
5291556Srgrimes	 * if we are writing (ARCHIVE) we use the default format if the user
5301556Srgrimes	 * did not specify a format. when we write during an APPEND, we will
5311556Srgrimes	 * adopt the format of the existing archive if none was supplied.
5321556Srgrimes	 */
5331556Srgrimes	if (!(flg & XF) && (act == ARCHIVE))
5341556Srgrimes		frmt = &(fsub[DEFLT]);
5351556Srgrimes
5361556Srgrimes	/*
5371556Srgrimes	 * process the args as they are interpreted by the operation mode
5381556Srgrimes	 */
5391556Srgrimes	switch (act) {
5401556Srgrimes	case LIST:
5411556Srgrimes	case EXTRACT:
5421556Srgrimes		for (; optind < argc; optind++)
5431556Srgrimes			if (pat_add(argv[optind]) < 0)
5441556Srgrimes				pax_usage();
5451556Srgrimes		break;
5461556Srgrimes	case COPY:
5471556Srgrimes		if (optind >= argc) {
54828904Ssos			pax_warn(0, "Destination directory was not supplied");
5491556Srgrimes			pax_usage();
5501556Srgrimes		}
5511556Srgrimes		--argc;
5521556Srgrimes		dirptr = argv[argc];
5531556Srgrimes		/* FALL THROUGH */
5541556Srgrimes	case ARCHIVE:
5551556Srgrimes	case APPND:
5561556Srgrimes		for (; optind < argc; optind++)
5571556Srgrimes			if (ftree_add(argv[optind]) < 0)
5581556Srgrimes				pax_usage();
5591556Srgrimes		/*
5601556Srgrimes		 * no read errors allowed on updates/append operation!
5611556Srgrimes		 */
5621556Srgrimes		maxflt = 0;
5631556Srgrimes		break;
5641556Srgrimes	}
5651556Srgrimes}
5661556Srgrimes
5671556Srgrimes
5681556Srgrimes/*
5691556Srgrimes * tar_options()
5701556Srgrimes *	look at the user specified flags. set globals as required and check if
5711556Srgrimes *	the user specified a legal set of flags. If not, complain and exit
5721556Srgrimes */
5731556Srgrimes
5741556Srgrimes#if __STDC__
5751556Srgrimesstatic void
5761556Srgrimestar_options(register int argc, register char **argv)
5771556Srgrimes#else
5781556Srgrimesstatic void
5791556Srgrimestar_options(argc, argv)
5801556Srgrimes	register int argc;
5811556Srgrimes	register char **argv;
5821556Srgrimes#endif
5831556Srgrimes{
5841556Srgrimes	register char *cp;
5851556Srgrimes	int fstdin = 0;
5861556Srgrimes
5871556Srgrimes	if (argc < 2)
5881556Srgrimes		tar_usage();
5891556Srgrimes	/*
5901556Srgrimes	 * process option flags
5911556Srgrimes	 */
5921556Srgrimes	++argv;
5931556Srgrimes	for (cp = *argv++; *cp != '\0'; ++cp) {
5941556Srgrimes		switch (*cp) {
5951556Srgrimes		case '-':
5961556Srgrimes			/*
5971556Srgrimes			 * skip over -
5981556Srgrimes			 */
5991556Srgrimes			break;
6001556Srgrimes		case 'b':
6011556Srgrimes			/*
6021556Srgrimes			 * specify blocksize
6031556Srgrimes			 */
6041556Srgrimes			if (*argv == (char *)NULL) {
60528904Ssos				pax_warn(1,"blocksize must be specified with 'b'");
6061556Srgrimes				tar_usage();
6071556Srgrimes			}
6081556Srgrimes			if ((wrblksz = (int)str_offt(*argv)) <= 0) {
60928904Ssos				pax_warn(1, "Invalid block size %s", *argv);
6101556Srgrimes				tar_usage();
6111556Srgrimes			}
6121556Srgrimes			++argv;
6131556Srgrimes			break;
6141556Srgrimes		case 'c':
6151556Srgrimes			/*
6161556Srgrimes			 * create an archive
6171556Srgrimes			 */
6181556Srgrimes			act = ARCHIVE;
6191556Srgrimes			break;
6201556Srgrimes		case 'e':
6211556Srgrimes			/*
6221556Srgrimes			 * stop after first error
6231556Srgrimes			 */
6241556Srgrimes			maxflt = 0;
6251556Srgrimes			break;
6261556Srgrimes		case 'f':
6271556Srgrimes			/*
6281556Srgrimes			 * filename where the archive is stored
6291556Srgrimes			 */
6301556Srgrimes			if (*argv == (char *)NULL) {
63128904Ssos				pax_warn(1, "filename must be specified with 'f'");
6321556Srgrimes				tar_usage();
6331556Srgrimes			}
6341556Srgrimes			if ((argv[0][0] == '-') && (argv[0][1]== '\0')) {
6351556Srgrimes				/*
6361556Srgrimes				 * treat a - as stdin
6371556Srgrimes				 */
6381556Srgrimes				++argv;
6391556Srgrimes				++fstdin;
6401556Srgrimes				arcname = (char *)0;
6411556Srgrimes				break;
6421556Srgrimes			}
6431556Srgrimes			fstdin = 0;
6441556Srgrimes			arcname = *argv++;
6451556Srgrimes			break;
6461556Srgrimes		case 'm':
6471556Srgrimes			/*
6481556Srgrimes			 * do not preserve modification time
6491556Srgrimes			 */
6501556Srgrimes			pmtime = 0;
6511556Srgrimes			break;
6521556Srgrimes		case 'o':
6531556Srgrimes			if (opt_add("write_opt=nodir") < 0)
6541556Srgrimes				tar_usage();
6551556Srgrimes			break;
6561556Srgrimes		case 'p':
6571556Srgrimes			/*
6581556Srgrimes			 * preserve user id, group id, file
6591556Srgrimes			 * mode, access/modification times
6601556Srgrimes			 */
6611556Srgrimes			pids = 1;
6621556Srgrimes			pmode = 1;
6631556Srgrimes			patime = 1;
6641556Srgrimes			pmtime = 1;
6651556Srgrimes			break;
6661556Srgrimes		case 'r':
6671556Srgrimes		case 'u':
6681556Srgrimes			/*
6691556Srgrimes			 * append to the archive
6701556Srgrimes			 */
6711556Srgrimes			act = APPND;
6721556Srgrimes			break;
6731556Srgrimes		case 't':
6741556Srgrimes			/*
6751556Srgrimes			 * list contents of the tape
6761556Srgrimes			 */
6771556Srgrimes			act = LIST;
6781556Srgrimes			break;
6791556Srgrimes		case 'v':
6801556Srgrimes			/*
6811556Srgrimes			 * verbose operation mode
6821556Srgrimes			 */
6831556Srgrimes			vflag = 1;
6841556Srgrimes			break;
6851556Srgrimes		case 'w':
6861556Srgrimes			/*
6871556Srgrimes			 * interactive file rename
6881556Srgrimes			 */
6891556Srgrimes			iflag = 1;
6901556Srgrimes			break;
6911556Srgrimes		case 'x':
6921556Srgrimes			/*
6931556Srgrimes			 * write an archive
6941556Srgrimes			 */
6951556Srgrimes			act = EXTRACT;
6961556Srgrimes			break;
6971556Srgrimes		case 'B':
6981556Srgrimes			/*
6991556Srgrimes			 * Nothing to do here, this is pax default
7001556Srgrimes			 */
7011556Srgrimes			break;
7021556Srgrimes		case 'H':
7031556Srgrimes			/*
7041556Srgrimes			 * follow command line symlinks only
7051556Srgrimes			 */
7061556Srgrimes			Hflag = 1;
7071556Srgrimes			break;
7081556Srgrimes		case 'L':
7091556Srgrimes			/*
7101556Srgrimes			 * follow symlinks
7111556Srgrimes			 */
7121556Srgrimes			Lflag = 1;
7131556Srgrimes			break;
7141556Srgrimes		case 'P':
7151556Srgrimes			/*
7161556Srgrimes			 * do not follow symlinks
7171556Srgrimes			 */
7181556Srgrimes			Lflag = 0;
7191556Srgrimes			break;
7201556Srgrimes		case 'X':
7211556Srgrimes			/*
7221556Srgrimes			 * do not pass over mount points in the file system
7231556Srgrimes			 */
7241556Srgrimes			Xflag = 1;
7251556Srgrimes			break;
7261556Srgrimes		case '0':
7271556Srgrimes			arcname = DEV_0;
7281556Srgrimes			break;
7291556Srgrimes		case '1':
7301556Srgrimes			arcname = DEV_1;
7311556Srgrimes			break;
7321556Srgrimes		case '4':
7331556Srgrimes			arcname = DEV_4;
7341556Srgrimes			break;
7351556Srgrimes		case '5':
7361556Srgrimes			arcname = DEV_5;
7371556Srgrimes			break;
7381556Srgrimes		case '7':
7391556Srgrimes			arcname = DEV_7;
7401556Srgrimes			break;
7411556Srgrimes		case '8':
7421556Srgrimes			arcname = DEV_8;
7431556Srgrimes			break;
7441556Srgrimes		default:
7451556Srgrimes			tar_usage();
7461556Srgrimes			break;
7471556Srgrimes		}
7481556Srgrimes	}
7491556Srgrimes
7501556Srgrimes	/*
7511556Srgrimes	 * if we are writing (ARCHIVE) specify tar, otherwise run like pax
7521556Srgrimes	 */
7531556Srgrimes	if (act == ARCHIVE)
7541556Srgrimes		frmt = &(fsub[F_TAR]);
7551556Srgrimes
7561556Srgrimes	/*
7571556Srgrimes	 * process the args as they are interpreted by the operation mode
7581556Srgrimes	 */
7591556Srgrimes	switch (act) {
7601556Srgrimes	case LIST:
7611556Srgrimes	case EXTRACT:
7621556Srgrimes	default:
7631556Srgrimes		while (*argv != (char *)NULL)
7641556Srgrimes			if (pat_add(*argv++) < 0)
7651556Srgrimes				tar_usage();
7661556Srgrimes		break;
7671556Srgrimes	case ARCHIVE:
7681556Srgrimes	case APPND:
7691556Srgrimes		while (*argv != (char *)NULL)
7701556Srgrimes			if (ftree_add(*argv++) < 0)
7711556Srgrimes				tar_usage();
7721556Srgrimes		/*
7731556Srgrimes		 * no read errors allowed on updates/append operation!
7741556Srgrimes		 */
7751556Srgrimes		maxflt = 0;
7761556Srgrimes		break;
7771556Srgrimes	}
7781556Srgrimes	if (!fstdin && ((arcname == (char *)NULL) || (*arcname == '\0'))) {
7791556Srgrimes		arcname = getenv("TAPE");
7801556Srgrimes		if ((arcname == (char *)NULL) || (*arcname == '\0'))
7811556Srgrimes			arcname = DEV_8;
7821556Srgrimes	}
7831556Srgrimes}
7841556Srgrimes
7851556Srgrimes#ifdef notdef
7861556Srgrimes/*
7871556Srgrimes * cpio_options()
7881556Srgrimes *	look at the user specified flags. set globals as required and check if
7891556Srgrimes *	the user specified a legal set of flags. If not, complain and exit
7901556Srgrimes */
7911556Srgrimes
7921556Srgrimes#if __STDC__
7931556Srgrimesstatic void
7941556Srgrimescpio_options(register int argc, register char **argv)
7951556Srgrimes#else
7961556Srgrimesstatic void
7971556Srgrimescpio_options(argc, argv)
7981556Srgrimes	register int argc;
7991556Srgrimes	register char **argv;
8001556Srgrimes#endif
8011556Srgrimes{
8021556Srgrimes}
8031556Srgrimes#endif
8041556Srgrimes
8051556Srgrimes/*
8061556Srgrimes * printflg()
8071556Srgrimes *	print out those invalid flag sets found to the user
8081556Srgrimes */
8091556Srgrimes
8101556Srgrimes#if __STDC__
8111556Srgrimesstatic void
8121556Srgrimesprintflg(unsigned int flg)
8131556Srgrimes#else
8141556Srgrimesstatic void
8151556Srgrimesprintflg(flg)
8161556Srgrimes	unsigned int flg;
8171556Srgrimes#endif
8181556Srgrimes{
8191556Srgrimes	int nxt;
8201556Srgrimes	int pos = 0;
8211556Srgrimes
8221556Srgrimes	(void)fprintf(stderr,"%s: Invalid combination of options:", argv0);
8237165Sjoerg	while ((nxt = ffs(flg))) {
8241556Srgrimes		flg = flg >> nxt;
8251556Srgrimes		pos += nxt;
8261556Srgrimes		(void)fprintf(stderr, " -%c", flgch[pos-1]);
8271556Srgrimes	}
8281556Srgrimes	(void)putc('\n', stderr);
8291556Srgrimes}
8301556Srgrimes
8311556Srgrimes/*
8321556Srgrimes * c_frmt()
8331556Srgrimes *	comparison routine used by bsearch to find the format specified
8341556Srgrimes *	by the user
8351556Srgrimes */
8361556Srgrimes
8371556Srgrimes#if __STDC__
8381556Srgrimesstatic int
8391556Srgrimesc_frmt(const void *a, const void *b)
8401556Srgrimes#else
8411556Srgrimesstatic int
8421556Srgrimesc_frmt(a, b)
8431556Srgrimes        void *a;
8441556Srgrimes        void *b;
8451556Srgrimes#endif
8461556Srgrimes{
8471556Srgrimes        return(strcmp(((FSUB *)a)->name, ((FSUB *)b)->name));
8481556Srgrimes}
8491556Srgrimes
8501556Srgrimes/*
8511556Srgrimes * opt_next()
8521556Srgrimes *	called by format specific options routines to get each format specific
8531556Srgrimes *	flag and value specified with -o
8541556Srgrimes * Return:
8551556Srgrimes *	pointer to next OPLIST entry or NULL (end of list).
8561556Srgrimes */
8571556Srgrimes
8581556Srgrimes#if __STDC__
8591556SrgrimesOPLIST *
8601556Srgrimesopt_next(void)
8611556Srgrimes#else
8621556SrgrimesOPLIST *
8631556Srgrimesopt_next()
8641556Srgrimes#endif
8651556Srgrimes{
8661556Srgrimes	OPLIST *opt;
8671556Srgrimes
8681556Srgrimes	if ((opt = ophead) != NULL)
8691556Srgrimes		ophead = ophead->fow;
8701556Srgrimes	return(opt);
8711556Srgrimes}
8721556Srgrimes
8731556Srgrimes/*
8741556Srgrimes * bad_opt()
8751556Srgrimes *	generic routine used to complain about a format specific options
8761556Srgrimes *	when the format does not support options.
8771556Srgrimes */
8781556Srgrimes
8791556Srgrimes#if __STDC__
8801556Srgrimesint
8811556Srgrimesbad_opt(void)
8821556Srgrimes#else
8831556Srgrimesint
8841556Srgrimesbad_opt()
8851556Srgrimes#endif
8861556Srgrimes{
8871556Srgrimes	register OPLIST *opt;
8881556Srgrimes
8891556Srgrimes	if (ophead == NULL)
8901556Srgrimes		return(0);
8911556Srgrimes	/*
8921556Srgrimes	 * print all we were given
8931556Srgrimes	 */
89428904Ssos	pax_warn(1,"These format options are not supported");
8951556Srgrimes	while ((opt = opt_next()) != NULL)
8961556Srgrimes		(void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
8971556Srgrimes	pax_usage();
8981556Srgrimes	return(0);
8991556Srgrimes}
9001556Srgrimes
9011556Srgrimes/*
9021556Srgrimes * opt_add()
9031556Srgrimes *	breaks the value supplied to -o into a option name and value. options
9041556Srgrimes *	are given to -o in the form -o name-value,name=value
90546684Skris *	multiple -o may be specified.
9061556Srgrimes * Return:
9071556Srgrimes *	0 if format in name=value format, -1 if -o is passed junk
9081556Srgrimes */
9091556Srgrimes
9101556Srgrimes#if __STDC__
9111556Srgrimesint
9121556Srgrimesopt_add(register char *str)
9131556Srgrimes#else
9141556Srgrimesint
9151556Srgrimesopt_add(str)
9161556Srgrimes	register char *str;
9171556Srgrimes#endif
9181556Srgrimes{
9191556Srgrimes	register OPLIST *opt;
9201556Srgrimes	register char *frpt;
9211556Srgrimes	register char *pt;
9221556Srgrimes	register char *endpt;
9231556Srgrimes
9241556Srgrimes	if ((str == NULL) || (*str == '\0')) {
92528904Ssos		pax_warn(0, "Invalid option name");
9261556Srgrimes		return(-1);
9271556Srgrimes	}
9281556Srgrimes	frpt = endpt = str;
9291556Srgrimes
9301556Srgrimes	/*
9311556Srgrimes	 * break into name and values pieces and stuff each one into a
9321556Srgrimes	 * OPLIST structure. When we know the format, the format specific
9331556Srgrimes	 * option function will go through this list
9341556Srgrimes	 */
9351556Srgrimes	while ((frpt != NULL) && (*frpt != '\0')) {
9361556Srgrimes		if ((endpt = strchr(frpt, ',')) != NULL)
9371556Srgrimes			*endpt = '\0';
9381556Srgrimes		if ((pt = strchr(frpt, '=')) == NULL) {
93928904Ssos			pax_warn(0, "Invalid options format");
9401556Srgrimes			return(-1);
9411556Srgrimes		}
9421556Srgrimes		if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
94328904Ssos			pax_warn(0, "Unable to allocate space for option list");
9441556Srgrimes			return(-1);
9451556Srgrimes		}
9461556Srgrimes		*pt++ = '\0';
9471556Srgrimes		opt->name = frpt;
9481556Srgrimes		opt->value = pt;
9491556Srgrimes		opt->fow = NULL;
9501556Srgrimes		if (endpt != NULL)
9511556Srgrimes			frpt = endpt + 1;
9521556Srgrimes		else
9531556Srgrimes			frpt = NULL;
9541556Srgrimes		if (ophead == NULL) {
9551556Srgrimes			optail = ophead = opt;
9561556Srgrimes			continue;
9571556Srgrimes		}
9581556Srgrimes		optail->fow = opt;
9591556Srgrimes		optail = opt;
9601556Srgrimes	}
9611556Srgrimes	return(0);
9621556Srgrimes}
9631556Srgrimes
9641556Srgrimes/*
9651556Srgrimes * str_offt()
9661556Srgrimes *	Convert an expression of the following forms to an off_t > 0.
9671556Srgrimes * 	1) A positive decimal number.
9681556Srgrimes *	2) A positive decimal number followed by a b (mult by 512).
9691556Srgrimes *	3) A positive decimal number followed by a k (mult by 1024).
9701556Srgrimes *	4) A positive decimal number followed by a m (mult by 512).
9711556Srgrimes *	5) A positive decimal number followed by a w (mult by sizeof int)
9721556Srgrimes *	6) Two or more positive decimal numbers (with/without k,b or w).
97372089Sasmodai *	   separated by x (also * for backwards compatibility), specifying
9741556Srgrimes *	   the product of the indicated values.
9751556Srgrimes * Return:
9761556Srgrimes *	0 for an error, a positive value o.w.
9771556Srgrimes */
9781556Srgrimes
9791556Srgrimes#if __STDC__
9801556Srgrimesstatic off_t
9811556Srgrimesstr_offt(char *val)
9821556Srgrimes#else
9831556Srgrimesstatic off_t
9841556Srgrimesstr_offt(val)
9851556Srgrimes	char *val;
9861556Srgrimes#endif
9871556Srgrimes{
9881556Srgrimes	char *expr;
9891556Srgrimes	off_t num, t;
9901556Srgrimes
9911556Srgrimes#	ifdef NET2_STAT
9921556Srgrimes	num = strtol(val, &expr, 0);
9931556Srgrimes	if ((num == LONG_MAX) || (num <= 0) || (expr == val))
9941556Srgrimes#	else
9951556Srgrimes	num = strtoq(val, &expr, 0);
9961556Srgrimes	if ((num == QUAD_MAX) || (num <= 0) || (expr == val))
9971556Srgrimes#	endif
9981556Srgrimes		return(0);
9991556Srgrimes
10001556Srgrimes	switch(*expr) {
10011556Srgrimes	case 'b':
10021556Srgrimes		t = num;
10031556Srgrimes		num *= 512;
10041556Srgrimes		if (t > num)
10051556Srgrimes			return(0);
10061556Srgrimes		++expr;
10071556Srgrimes		break;
10081556Srgrimes	case 'k':
10091556Srgrimes		t = num;
10101556Srgrimes		num *= 1024;
10111556Srgrimes		if (t > num)
10121556Srgrimes			return(0);
10131556Srgrimes		++expr;
10141556Srgrimes		break;
10151556Srgrimes	case 'm':
10161556Srgrimes		t = num;
10171556Srgrimes		num *= 1048576;
10181556Srgrimes		if (t > num)
10191556Srgrimes			return(0);
10201556Srgrimes		++expr;
10211556Srgrimes		break;
10221556Srgrimes	case 'w':
10231556Srgrimes		t = num;
10241556Srgrimes		num *= sizeof(int);
10251556Srgrimes		if (t > num)
10261556Srgrimes			return(0);
10271556Srgrimes		++expr;
10281556Srgrimes		break;
10291556Srgrimes	}
10301556Srgrimes
10311556Srgrimes	switch(*expr) {
10321556Srgrimes		case '\0':
10331556Srgrimes			break;
10341556Srgrimes		case '*':
10351556Srgrimes		case 'x':
10361556Srgrimes			t = num;
10371556Srgrimes			num *= str_offt(expr + 1);
10381556Srgrimes			if (t > num)
10391556Srgrimes				return(0);
10401556Srgrimes			break;
10411556Srgrimes		default:
10421556Srgrimes			return(0);
10431556Srgrimes	}
10441556Srgrimes	return(num);
10451556Srgrimes}
10461556Srgrimes
10471556Srgrimes/*
10481556Srgrimes * no_op()
10491556Srgrimes *	for those option functions where the archive format has nothing to do.
10501556Srgrimes * Return:
10511556Srgrimes *	0
10521556Srgrimes */
10531556Srgrimes
10541556Srgrimes#if __STDC__
10551556Srgrimesstatic int
10561556Srgrimesno_op(void)
10571556Srgrimes#else
10581556Srgrimesstatic int
10591556Srgrimesno_op()
10601556Srgrimes#endif
10611556Srgrimes{
10621556Srgrimes	return(0);
10631556Srgrimes}
10641556Srgrimes
10651556Srgrimes/*
10661556Srgrimes * pax_usage()
10671556Srgrimes *	print the usage summary to the user
10681556Srgrimes */
10691556Srgrimes
10701556Srgrimes#if __STDC__
10711556Srgrimesvoid
10721556Srgrimespax_usage(void)
10731556Srgrimes#else
10741556Srgrimesvoid
10751556Srgrimespax_usage()
10761556Srgrimes#endif
10771556Srgrimes{
10781556Srgrimes	(void)fputs("usage: pax [-cdnv] [-E limit] [-f archive] ", stderr);
10791556Srgrimes	(void)fputs("[-s replstr] ... [-U user] ...", stderr);
10801556Srgrimes	(void)fputs("\n           [-G group] ... ", stderr);
10811556Srgrimes	(void)fputs("[-T [from_date][,to_date]] ... ", stderr);
10821556Srgrimes	(void)fputs("[pattern ...]\n", stderr);
10831556Srgrimes	(void)fputs("       pax -r [-cdiknuvDYZ] [-E limit] ", stderr);
10841556Srgrimes	(void)fputs("[-f archive] [-o options] ... \n", stderr);
10851556Srgrimes	(void)fputs("           [-p string] ... [-s replstr] ... ", stderr);
10861556Srgrimes	(void)fputs("[-U user] ... [-G group] ...\n           ", stderr);
10871556Srgrimes	(void)fputs("[-T [from_date][,to_date]] ... ", stderr);
10881556Srgrimes	(void)fputs(" [pattern ...]\n", stderr);
10891556Srgrimes	(void)fputs("       pax -w [-dituvHLPX] [-b blocksize] ", stderr);
10901556Srgrimes	(void)fputs("[ [-a] [-f archive] ] [-x format] \n", stderr);
10911556Srgrimes	(void)fputs("           [-B bytes] [-s replstr] ... ", stderr);
10921556Srgrimes	(void)fputs("[-o options] ... [-U user] ...", stderr);
10931556Srgrimes	(void)fputs("\n           [-G group] ... ", stderr);
10941556Srgrimes	(void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
10951556Srgrimes	(void)fputs("[file ...]\n", stderr);
10961556Srgrimes	(void)fputs("       pax -r -w [-diklntuvDHLPXYZ] ", stderr);
10971556Srgrimes	(void)fputs("[-p string] ... [-s replstr] ...", stderr);
10981556Srgrimes	(void)fputs("\n           [-U user] ... [-G group] ... ", stderr);
10991556Srgrimes	(void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
11001556Srgrimes	(void)fputs("\n           [file ...] directory\n", stderr);
11011556Srgrimes	exit(1);
11021556Srgrimes}
11031556Srgrimes
11041556Srgrimes/*
11051556Srgrimes * tar_usage()
11061556Srgrimes *	print the usage summary to the user
11071556Srgrimes */
11081556Srgrimes
11091556Srgrimes#if __STDC__
11101556Srgrimesvoid
11111556Srgrimestar_usage(void)
11121556Srgrimes#else
11131556Srgrimesvoid
11141556Srgrimestar_usage()
11151556Srgrimes#endif
11161556Srgrimes{
11171556Srgrimes	(void)fputs("usage: tar -{txru}[cevfbmopwBHLPX014578] [tapefile] ",
11181556Srgrimes		 stderr);
11191556Srgrimes	(void)fputs("[blocksize] file1 file2...\n", stderr);
11201556Srgrimes	exit(1);
11211556Srgrimes}
11221556Srgrimes
11231556Srgrimes#ifdef notdef
11241556Srgrimes/*
11251556Srgrimes * cpio_usage()
11261556Srgrimes *	print the usage summary to the user
11271556Srgrimes */
11281556Srgrimes
11291556Srgrimes#if __STDC__
11301556Srgrimesvoid
11311556Srgrimescpio_usage(void)
11321556Srgrimes#else
11331556Srgrimesvoid
11341556Srgrimescpio_usage()
11351556Srgrimes#endif
11361556Srgrimes{
11371556Srgrimes	exit(1);
11381556Srgrimes}
11391556Srgrimes#endif
1140