xref: /freebsd-src/bin/pax/options.c (revision e043f37205ffbde5627ff299ad25cd532f2956f0)
1b4bb70ccSBruce Evans /*-
28a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
38a16b7a1SPedro F. Giffuni  *
44b88c807SRodney W. Grimes  * Copyright (c) 1992 Keith Muller.
54b88c807SRodney W. Grimes  * Copyright (c) 1992, 1993
64b88c807SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
74b88c807SRodney W. Grimes  *
84b88c807SRodney W. Grimes  * This code is derived from software contributed to Berkeley by
94b88c807SRodney W. Grimes  * Keith Muller of the University of California, San Diego.
104b88c807SRodney W. Grimes  *
114b88c807SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
124b88c807SRodney W. Grimes  * modification, are permitted provided that the following conditions
134b88c807SRodney W. Grimes  * are met:
144b88c807SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
154b88c807SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
164b88c807SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
174b88c807SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
184b88c807SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
19fbbd9655SWarner Losh  * 3. Neither the name of the University nor the names of its contributors
204b88c807SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
214b88c807SRodney W. Grimes  *    without specific prior written permission.
224b88c807SRodney W. Grimes  *
234b88c807SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
244b88c807SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
254b88c807SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
264b88c807SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
274b88c807SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
284b88c807SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
294b88c807SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
304b88c807SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
314b88c807SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
324b88c807SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
334b88c807SRodney W. Grimes  * SUCH DAMAGE.
344b88c807SRodney W. Grimes  */
354b88c807SRodney W. Grimes 
364b88c807SRodney W. Grimes #include <sys/types.h>
374b88c807SRodney W. Grimes #include <sys/stat.h>
384b88c807SRodney W. Grimes #include <sys/mtio.h>
394b88c807SRodney W. Grimes #include <stdio.h>
404b88c807SRodney W. Grimes #include <string.h>
41b1787decSKris Kennaway #include <errno.h>
424b88c807SRodney W. Grimes #include <unistd.h>
434b88c807SRodney W. Grimes #include <stdlib.h>
444b88c807SRodney W. Grimes #include <limits.h>
45b1787decSKris Kennaway #include <paths.h>
464b88c807SRodney W. Grimes #include "pax.h"
474b88c807SRodney W. Grimes #include "options.h"
484b88c807SRodney W. Grimes #include "cpio.h"
494b88c807SRodney W. Grimes #include "tar.h"
504b88c807SRodney W. Grimes #include "extern.h"
514b88c807SRodney W. Grimes 
524b88c807SRodney W. Grimes /*
534b88c807SRodney W. Grimes  * Routines which handle command line options
544b88c807SRodney W. Grimes  */
554b88c807SRodney W. Grimes 
564b88c807SRodney W. Grimes static char flgch[] = FLGCH;	/* list of all possible flags */
574b88c807SRodney W. Grimes static OPLIST *ophead = NULL;	/* head for format specific options -x */
584b88c807SRodney W. Grimes static OPLIST *optail = NULL;	/* option tail */
594b88c807SRodney W. Grimes 
6046251ddeSWarner Losh static int no_op(void);
6146251ddeSWarner Losh static void printflg(unsigned int);
6246251ddeSWarner Losh static int c_frmt(const void *, const void *);
6346251ddeSWarner Losh static off_t str_offt(char *);
64a651f2bcSBaptiste Daroussin static char *get_line(FILE *fp);
65f789b261SWarner Losh static void pax_options(int, char **);
6646251ddeSWarner Losh static void pax_usage(void);
67f789b261SWarner Losh static void tar_options(int, char **);
6846251ddeSWarner Losh static void tar_usage(void);
69f789b261SWarner Losh static void cpio_options(int, char **);
7046251ddeSWarner Losh static void cpio_usage(void);
71b1787decSKris Kennaway 
72a651f2bcSBaptiste Daroussin /* errors from get_line */
73b1787decSKris Kennaway #define GETLINE_FILE_CORRUPT 1
74b1787decSKris Kennaway #define GETLINE_OUT_OF_MEM 2
75a651f2bcSBaptiste Daroussin static int get_line_error;
76b1787decSKris Kennaway 
77ae824d80SEd Schouten char *chdname;
784b88c807SRodney W. Grimes 
791192d531SKris Kennaway #define GZIP_CMD	"gzip"		/* command to run as gzip */
801192d531SKris Kennaway #define COMPRESS_CMD	"compress"	/* command to run as compress */
810266a5d6SDag-Erling Smørgrav #define BZIP2_CMD	"bzip2"		/* command to run as bzip2 */
821192d531SKris Kennaway 
834b88c807SRodney W. Grimes /*
844b88c807SRodney W. Grimes  *	Format specific routine table - MUST BE IN SORTED ORDER BY NAME
854b88c807SRodney W. Grimes  *	(see pax.h for description of each function)
864b88c807SRodney W. Grimes  *
874b88c807SRodney W. Grimes  * 	name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
884b88c807SRodney W. Grimes  *	read, end_read, st_write, write, end_write, trail,
894b88c807SRodney W. Grimes  *	rd_data, wr_data, options
904b88c807SRodney W. Grimes  */
914b88c807SRodney W. Grimes 
924b88c807SRodney W. Grimes FSUB fsub[] = {
934b88c807SRodney W. Grimes /* 0: OLD BINARY CPIO */
940fd510b7SJoerg Wunsch 	{"bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
954b88c807SRodney W. Grimes 	bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, cpio_trail,
9640feca3aSMark Murray 	NULL, rd_wrfile, wr_rdfile, bad_opt},
974b88c807SRodney W. Grimes 
984b88c807SRodney W. Grimes /* 1: OLD OCTAL CHARACTER CPIO */
990fd510b7SJoerg Wunsch 	{"cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
1004b88c807SRodney W. Grimes 	cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, cpio_trail,
10140feca3aSMark Murray 	NULL, rd_wrfile, wr_rdfile, bad_opt},
1024b88c807SRodney W. Grimes 
1034b88c807SRodney W. Grimes /* 2: SVR4 HEX CPIO */
1040fd510b7SJoerg Wunsch 	{"sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd,
1054b88c807SRodney W. Grimes 	vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, cpio_trail,
10640feca3aSMark Murray 	NULL, rd_wrfile, wr_rdfile, bad_opt},
1074b88c807SRodney W. Grimes 
1084b88c807SRodney W. Grimes /* 3: SVR4 HEX CPIO WITH CRC */
1090fd510b7SJoerg Wunsch 	{"sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
1104b88c807SRodney W. Grimes 	vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, cpio_trail,
11140feca3aSMark Murray 	NULL, rd_wrfile, wr_rdfile, bad_opt},
1124b88c807SRodney W. Grimes 
1134b88c807SRodney W. Grimes /* 4: OLD TAR */
1140fd510b7SJoerg Wunsch 	{"tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
11540feca3aSMark Murray 	tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, NULL, tar_trail,
1160fd510b7SJoerg Wunsch 	rd_wrfile, wr_rdfile, tar_opt},
1174b88c807SRodney W. Grimes 
1184b88c807SRodney W. Grimes /* 5: POSIX USTAR */
1190fd510b7SJoerg Wunsch 	{"ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd,
12040feca3aSMark Murray 	ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, NULL, tar_trail,
1210fd510b7SJoerg Wunsch 	rd_wrfile, wr_rdfile, bad_opt},
1224b88c807SRodney W. Grimes };
123b1787decSKris Kennaway #define F_OCPIO	0	/* format when called as cpio -6 */
124b1787decSKris Kennaway #define F_ACPIO	1	/* format when called as cpio -c */
125*a8e8a914SDag-Erling Smørgrav #define F_SCPIO	2	/* format when called with -x sv4cpio */
126b1787decSKris Kennaway #define F_CPIO	3	/* format when called as cpio */
127b1787decSKris Kennaway #define F_OTAR	4	/* format when called as tar -o */
128b1787decSKris Kennaway #define F_TAR	5	/* format when called as tar */
129*a8e8a914SDag-Erling Smørgrav #define DEFLT	F_TAR	/* default write format from list above */
1304b88c807SRodney W. Grimes 
1314b88c807SRodney W. Grimes /*
1324b88c807SRodney W. Grimes  * ford is the archive search order used by get_arc() to determine what kind
1334b88c807SRodney W. Grimes  * of archive we are dealing with. This helps to properly id  archive formats
1344b88c807SRodney W. Grimes  * some formats may be subsets of others....
1354b88c807SRodney W. Grimes  */
136*a8e8a914SDag-Erling Smørgrav int ford[] = {F_TAR, F_OTAR, F_CPIO, F_SCPIO, F_ACPIO, F_OCPIO, -1 };
1374b88c807SRodney W. Grimes 
1384b88c807SRodney W. Grimes /*
1394b88c807SRodney W. Grimes  * options()
1404b88c807SRodney W. Grimes  *	figure out if we are pax, tar or cpio. Call the appropriate options
1414b88c807SRodney W. Grimes  *	parser
1424b88c807SRodney W. Grimes  */
1434b88c807SRodney W. Grimes 
1444b88c807SRodney W. Grimes void
options(int argc,char ** argv)145f789b261SWarner Losh options(int argc, char **argv)
1464b88c807SRodney W. Grimes {
1474b88c807SRodney W. Grimes 
1484b88c807SRodney W. Grimes 	/*
1494b88c807SRodney W. Grimes 	 * Are we acting like pax, tar or cpio (based on argv[0])
1504b88c807SRodney W. Grimes 	 */
1514b88c807SRodney W. Grimes 	if ((argv0 = strrchr(argv[0], '/')) != NULL)
1524b88c807SRodney W. Grimes 		argv0++;
1534b88c807SRodney W. Grimes 	else
1544b88c807SRodney W. Grimes 		argv0 = argv[0];
1554b88c807SRodney W. Grimes 
156c113db69SPhilippe Charnier 	if (strcmp(NM_TAR, argv0) == 0) {
157c113db69SPhilippe Charnier 		tar_options(argc, argv);
158c113db69SPhilippe Charnier 		return;
159c113db69SPhilippe Charnier 	}
160c113db69SPhilippe Charnier 	else if (strcmp(NM_CPIO, argv0) == 0) {
161c113db69SPhilippe Charnier 		cpio_options(argc, argv);
162c113db69SPhilippe Charnier 		return;
163c113db69SPhilippe Charnier 	}
1644b88c807SRodney W. Grimes 	/*
1654b88c807SRodney W. Grimes 	 * assume pax as the default
1664b88c807SRodney W. Grimes 	 */
1674b88c807SRodney W. Grimes 	argv0 = NM_PAX;
168c113db69SPhilippe Charnier 	pax_options(argc, argv);
169c113db69SPhilippe Charnier 	return;
1704b88c807SRodney W. Grimes }
1714b88c807SRodney W. Grimes 
1724b88c807SRodney W. Grimes /*
1734b88c807SRodney W. Grimes  * pax_options()
1744b88c807SRodney W. Grimes  *	look at the user specified flags. set globals as required and check if
1754b88c807SRodney W. Grimes  *	the user specified a legal set of flags. If not, complain and exit
1764b88c807SRodney W. Grimes  */
1774b88c807SRodney W. Grimes 
1784b88c807SRodney W. Grimes static void
pax_options(int argc,char ** argv)179f789b261SWarner Losh pax_options(int argc, char **argv)
1804b88c807SRodney W. Grimes {
181f789b261SWarner Losh 	int c;
182cee22cbdSDavid E. O'Brien 	size_t i;
1834b88c807SRodney W. Grimes 	unsigned int flg = 0;
1844b88c807SRodney W. Grimes 	unsigned int bflg = 0;
185f789b261SWarner Losh 	char *pt;
1864b88c807SRodney W. Grimes 	FSUB tmp;
1874b88c807SRodney W. Grimes 
1884b88c807SRodney W. Grimes 	/*
1894b88c807SRodney W. Grimes 	 * process option flags
1904b88c807SRodney W. Grimes 	 */
191d6e1f8d7SEitan Adler 	while ((c=getopt(argc,argv,"ab:cdf:iklno:p:rs:tuvwx:zB:DE:G:HLOPT:U:XYZ"))
19293ef08afSWarner Losh 	    != -1) {
1934b88c807SRodney W. Grimes 		switch (c) {
1944b88c807SRodney W. Grimes 		case 'a':
1954b88c807SRodney W. Grimes 			/*
1964b88c807SRodney W. Grimes 			 * append
1974b88c807SRodney W. Grimes 			 */
1984b88c807SRodney W. Grimes 			flg |= AF;
1994b88c807SRodney W. Grimes 			break;
2004b88c807SRodney W. Grimes 		case 'b':
2014b88c807SRodney W. Grimes 			/*
2024b88c807SRodney W. Grimes 			 * specify blocksize
2034b88c807SRodney W. Grimes 			 */
2044b88c807SRodney W. Grimes 			flg |= BF;
2054b88c807SRodney W. Grimes 			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
206778766feSKris Kennaway 				paxwarn(1, "Invalid block size %s", optarg);
2074b88c807SRodney W. Grimes 				pax_usage();
2084b88c807SRodney W. Grimes 			}
2094b88c807SRodney W. Grimes 			break;
2104b88c807SRodney W. Grimes 		case 'c':
2114b88c807SRodney W. Grimes 			/*
2124b88c807SRodney W. Grimes 			 * inverse match on patterns
2134b88c807SRodney W. Grimes 			 */
2144b88c807SRodney W. Grimes 			cflag = 1;
2154b88c807SRodney W. Grimes 			flg |= CF;
2164b88c807SRodney W. Grimes 			break;
2174b88c807SRodney W. Grimes 		case 'd':
2184b88c807SRodney W. Grimes 			/*
2194b88c807SRodney W. Grimes 			 * match only dir on extract, not the subtree at dir
2204b88c807SRodney W. Grimes 			 */
2214b88c807SRodney W. Grimes 			dflag = 1;
2224b88c807SRodney W. Grimes 			flg |= DF;
2234b88c807SRodney W. Grimes 			break;
2244b88c807SRodney W. Grimes 		case 'f':
2254b88c807SRodney W. Grimes 			/*
2264b88c807SRodney W. Grimes 			 * filename where the archive is stored
2274b88c807SRodney W. Grimes 			 */
2284b88c807SRodney W. Grimes 			arcname = optarg;
2294b88c807SRodney W. Grimes 			flg |= FF;
2304b88c807SRodney W. Grimes 			break;
2314b88c807SRodney W. Grimes 		case 'i':
2324b88c807SRodney W. Grimes 			/*
2334b88c807SRodney W. Grimes 			 * interactive file rename
2344b88c807SRodney W. Grimes 			 */
2354b88c807SRodney W. Grimes 			iflag = 1;
2364b88c807SRodney W. Grimes 			flg |= IF;
2374b88c807SRodney W. Grimes 			break;
2384b88c807SRodney W. Grimes 		case 'k':
2394b88c807SRodney W. Grimes 			/*
2404b88c807SRodney W. Grimes 			 * do not clobber files that exist
2414b88c807SRodney W. Grimes 			 */
2424b88c807SRodney W. Grimes 			kflag = 1;
2434b88c807SRodney W. Grimes 			flg |= KF;
2444b88c807SRodney W. Grimes 			break;
2454b88c807SRodney W. Grimes 		case 'l':
2464b88c807SRodney W. Grimes 			/*
2474b88c807SRodney W. Grimes 			 * try to link src to dest with copy (-rw)
2484b88c807SRodney W. Grimes 			 */
2494b88c807SRodney W. Grimes 			lflag = 1;
2504b88c807SRodney W. Grimes 			flg |= LF;
2514b88c807SRodney W. Grimes 			break;
2524b88c807SRodney W. Grimes 		case 'n':
2534b88c807SRodney W. Grimes 			/*
2544b88c807SRodney W. Grimes 			 * select first match for a pattern only
2554b88c807SRodney W. Grimes 			 */
2564b88c807SRodney W. Grimes 			nflag = 1;
2574b88c807SRodney W. Grimes 			flg |= NF;
2584b88c807SRodney W. Grimes 			break;
2594b88c807SRodney W. Grimes 		case 'o':
2604b88c807SRodney W. Grimes 			/*
2614b88c807SRodney W. Grimes 			 * pass format specific options
2624b88c807SRodney W. Grimes 			 */
2634b88c807SRodney W. Grimes 			flg |= OF;
2644b88c807SRodney W. Grimes 			if (opt_add(optarg) < 0)
2654b88c807SRodney W. Grimes 				pax_usage();
2664b88c807SRodney W. Grimes 			break;
2674b88c807SRodney W. Grimes 		case 'p':
2684b88c807SRodney W. Grimes 			/*
2694b88c807SRodney W. Grimes 			 * specify file characteristic options
2704b88c807SRodney W. Grimes 			 */
2714b88c807SRodney W. Grimes 			for (pt = optarg; *pt != '\0'; ++pt) {
2724b88c807SRodney W. Grimes 				switch(*pt) {
2734b88c807SRodney W. Grimes 				case 'a':
2744b88c807SRodney W. Grimes 					/*
2754b88c807SRodney W. Grimes 					 * do not preserve access time
2764b88c807SRodney W. Grimes 					 */
2774b88c807SRodney W. Grimes 					patime = 0;
2784b88c807SRodney W. Grimes 					break;
2794b88c807SRodney W. Grimes 				case 'e':
2804b88c807SRodney W. Grimes 					/*
2814b88c807SRodney W. Grimes 					 * preserve user id, group id, file
2824b88c807SRodney W. Grimes 					 * mode, access/modification times
2834b88c807SRodney W. Grimes 					 */
2844b88c807SRodney W. Grimes 					pids = 1;
2854b88c807SRodney W. Grimes 					pmode = 1;
2864b88c807SRodney W. Grimes 					patime = 1;
2874b88c807SRodney W. Grimes 					pmtime = 1;
2884b88c807SRodney W. Grimes 					break;
2894b88c807SRodney W. Grimes 				case 'm':
2904b88c807SRodney W. Grimes 					/*
2914b88c807SRodney W. Grimes 					 * do not preserve modification time
2924b88c807SRodney W. Grimes 					 */
2934b88c807SRodney W. Grimes 					pmtime = 0;
2944b88c807SRodney W. Grimes 					break;
2954b88c807SRodney W. Grimes 				case 'o':
2964b88c807SRodney W. Grimes 					/*
2974b88c807SRodney W. Grimes 					 * preserve uid/gid
2984b88c807SRodney W. Grimes 					 */
2994b88c807SRodney W. Grimes 					pids = 1;
3004b88c807SRodney W. Grimes 					break;
3014b88c807SRodney W. Grimes 				case 'p':
3024b88c807SRodney W. Grimes 					/*
3030266a5d6SDag-Erling Smørgrav 					 * preserve file mode bits
3044b88c807SRodney W. Grimes 					 */
3054b88c807SRodney W. Grimes 					pmode = 1;
3064b88c807SRodney W. Grimes 					break;
3074b88c807SRodney W. Grimes 				default:
308778766feSKris Kennaway 					paxwarn(1, "Invalid -p string: %c", *pt);
3094b88c807SRodney W. Grimes 					pax_usage();
3104b88c807SRodney W. Grimes 					break;
3114b88c807SRodney W. Grimes 				}
3124b88c807SRodney W. Grimes 			}
3134b88c807SRodney W. Grimes 			flg |= PF;
3144b88c807SRodney W. Grimes 			break;
3154b88c807SRodney W. Grimes 		case 'r':
3164b88c807SRodney W. Grimes 			/*
3174b88c807SRodney W. Grimes 			 * read the archive
3184b88c807SRodney W. Grimes 			 */
3194b88c807SRodney W. Grimes 			flg |= RF;
3204b88c807SRodney W. Grimes 			break;
3214b88c807SRodney W. Grimes 		case 's':
3224b88c807SRodney W. Grimes 			/*
3234b88c807SRodney W. Grimes 			 * file name substitution name pattern
3244b88c807SRodney W. Grimes 			 */
3254b88c807SRodney W. Grimes 			if (rep_add(optarg) < 0) {
3264b88c807SRodney W. Grimes 				pax_usage();
3274b88c807SRodney W. Grimes 				break;
3284b88c807SRodney W. Grimes 			}
3294b88c807SRodney W. Grimes 			flg |= SF;
3304b88c807SRodney W. Grimes 			break;
3314b88c807SRodney W. Grimes 		case 't':
3324b88c807SRodney W. Grimes 			/*
3334b88c807SRodney W. Grimes 			 * preserve access time on file system nodes we read
3344b88c807SRodney W. Grimes 			 */
3354b88c807SRodney W. Grimes 			tflag = 1;
3364b88c807SRodney W. Grimes 			flg |= TF;
3374b88c807SRodney W. Grimes 			break;
3384b88c807SRodney W. Grimes 		case 'u':
3394b88c807SRodney W. Grimes 			/*
3404b88c807SRodney W. Grimes 			 * ignore those older files
3414b88c807SRodney W. Grimes 			 */
3424b88c807SRodney W. Grimes 			uflag = 1;
3434b88c807SRodney W. Grimes 			flg |= UF;
3444b88c807SRodney W. Grimes 			break;
3454b88c807SRodney W. Grimes 		case 'v':
3464b88c807SRodney W. Grimes 			/*
3474b88c807SRodney W. Grimes 			 * verbose operation mode
3484b88c807SRodney W. Grimes 			 */
3494b88c807SRodney W. Grimes 			vflag = 1;
3504b88c807SRodney W. Grimes 			flg |= VF;
3514b88c807SRodney W. Grimes 			break;
3524b88c807SRodney W. Grimes 		case 'w':
3534b88c807SRodney W. Grimes 			/*
3544b88c807SRodney W. Grimes 			 * write an archive
3554b88c807SRodney W. Grimes 			 */
3564b88c807SRodney W. Grimes 			flg |= WF;
3574b88c807SRodney W. Grimes 			break;
3584b88c807SRodney W. Grimes 		case 'x':
3594b88c807SRodney W. Grimes 			/*
3604b88c807SRodney W. Grimes 			 * specify an archive format on write
3614b88c807SRodney W. Grimes 			 */
3624b88c807SRodney W. Grimes 			tmp.name = optarg;
3630fd510b7SJoerg Wunsch 			if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
364b1787decSKris Kennaway 			    sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) != NULL) {
3654b88c807SRodney W. Grimes 				flg |= XF;
3664b88c807SRodney W. Grimes 				break;
3674b88c807SRodney W. Grimes 			}
368778766feSKris Kennaway 			paxwarn(1, "Unknown -x format: %s", optarg);
3694b88c807SRodney W. Grimes 			(void)fputs("pax: Known -x formats are:", stderr);
3704b88c807SRodney W. Grimes 			for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
3714b88c807SRodney W. Grimes 				(void)fprintf(stderr, " %s", fsub[i].name);
3724b88c807SRodney W. Grimes 			(void)fputs("\n\n", stderr);
3734b88c807SRodney W. Grimes 			pax_usage();
3744b88c807SRodney W. Grimes 			break;
3751192d531SKris Kennaway 		case 'z':
3761192d531SKris Kennaway 			/*
3771192d531SKris Kennaway 			 * use gzip.  Non standard option.
3781192d531SKris Kennaway 			 */
3791192d531SKris Kennaway 			gzip_program = GZIP_CMD;
3801192d531SKris Kennaway 			break;
3814b88c807SRodney W. Grimes 		case 'B':
3824b88c807SRodney W. Grimes 			/*
3834b88c807SRodney W. Grimes 			 * non-standard option on number of bytes written on a
3844b88c807SRodney W. Grimes 			 * single archive volume.
3854b88c807SRodney W. Grimes 			 */
3864b88c807SRodney W. Grimes 			if ((wrlimit = str_offt(optarg)) <= 0) {
387778766feSKris Kennaway 				paxwarn(1, "Invalid write limit %s", optarg);
3884b88c807SRodney W. Grimes 				pax_usage();
3894b88c807SRodney W. Grimes 			}
3904b88c807SRodney W. Grimes 			if (wrlimit % BLKMULT) {
391778766feSKris Kennaway 				paxwarn(1, "Write limit is not a %d byte multiple",
3924b88c807SRodney W. Grimes 				    BLKMULT);
3934b88c807SRodney W. Grimes 				pax_usage();
3944b88c807SRodney W. Grimes 			}
3954b88c807SRodney W. Grimes 			flg |= CBF;
3964b88c807SRodney W. Grimes 			break;
3974b88c807SRodney W. Grimes 		case 'D':
3984b88c807SRodney W. Grimes 			/*
3994b88c807SRodney W. Grimes 			 * On extraction check file inode change time before the
4004b88c807SRodney W. Grimes 			 * modification of the file name. Non standard option.
4014b88c807SRodney W. Grimes 			 */
4024b88c807SRodney W. Grimes 			Dflag = 1;
4034b88c807SRodney W. Grimes 			flg |= CDF;
4044b88c807SRodney W. Grimes 			break;
4054b88c807SRodney W. Grimes 		case 'E':
4064b88c807SRodney W. Grimes 			/*
4074b88c807SRodney W. Grimes 			 * non-standard limit on read faults
4084b88c807SRodney W. Grimes 			 * 0 indicates stop after first error, values
4094b88c807SRodney W. Grimes 			 * indicate a limit, "NONE" try forever
4104b88c807SRodney W. Grimes 			 */
4114b88c807SRodney W. Grimes 			flg |= CEF;
4124b88c807SRodney W. Grimes 			if (strcmp(NONE, optarg) == 0)
4134b88c807SRodney W. Grimes 				maxflt = -1;
4144b88c807SRodney W. Grimes 			else if ((maxflt = atoi(optarg)) < 0) {
415778766feSKris Kennaway 				paxwarn(1, "Error count value must be positive");
4164b88c807SRodney W. Grimes 				pax_usage();
4174b88c807SRodney W. Grimes 			}
4184b88c807SRodney W. Grimes 			break;
4194b88c807SRodney W. Grimes 		case 'G':
4204b88c807SRodney W. Grimes 			/*
4214b88c807SRodney W. Grimes 			 * non-standard option for selecting files within an
4224b88c807SRodney W. Grimes 			 * archive by group (gid or name)
4234b88c807SRodney W. Grimes 			 */
4244b88c807SRodney W. Grimes 			if (grp_add(optarg) < 0) {
4254b88c807SRodney W. Grimes 				pax_usage();
4264b88c807SRodney W. Grimes 				break;
4274b88c807SRodney W. Grimes 			}
4284b88c807SRodney W. Grimes 			flg |= CGF;
4294b88c807SRodney W. Grimes 			break;
4304b88c807SRodney W. Grimes 		case 'H':
4314b88c807SRodney W. Grimes 			/*
4324b88c807SRodney W. Grimes 			 * follow command line symlinks only
4334b88c807SRodney W. Grimes 			 */
4344b88c807SRodney W. Grimes 			Hflag = 1;
4354b88c807SRodney W. Grimes 			flg |= CHF;
4364b88c807SRodney W. Grimes 			break;
4374b88c807SRodney W. Grimes 		case 'L':
4384b88c807SRodney W. Grimes 			/*
4394b88c807SRodney W. Grimes 			 * follow symlinks
4404b88c807SRodney W. Grimes 			 */
4414b88c807SRodney W. Grimes 			Lflag = 1;
4424b88c807SRodney W. Grimes 			flg |= CLF;
4434b88c807SRodney W. Grimes 			break;
444d6e1f8d7SEitan Adler 		case 'O':
445d6e1f8d7SEitan Adler 			/*
446d6e1f8d7SEitan Adler 			 * Force one volume. Non standard option.
447d6e1f8d7SEitan Adler 			 */
448d6e1f8d7SEitan Adler 			Oflag = 1;
449d6e1f8d7SEitan Adler 			break;
4504b88c807SRodney W. Grimes 		case 'P':
4514b88c807SRodney W. Grimes 			/*
4524b88c807SRodney W. Grimes 			 * do NOT follow symlinks (default)
4534b88c807SRodney W. Grimes 			 */
4544b88c807SRodney W. Grimes 			Lflag = 0;
4554b88c807SRodney W. Grimes 			flg |= CPF;
4564b88c807SRodney W. Grimes 			break;
4574b88c807SRodney W. Grimes 		case 'T':
4584b88c807SRodney W. Grimes 			/*
4594b88c807SRodney W. Grimes 			 * non-standard option for selecting files within an
4604b88c807SRodney W. Grimes 			 * archive by modification time range (lower,upper)
4614b88c807SRodney W. Grimes 			 */
4624b88c807SRodney W. Grimes 			if (trng_add(optarg) < 0) {
4634b88c807SRodney W. Grimes 				pax_usage();
4644b88c807SRodney W. Grimes 				break;
4654b88c807SRodney W. Grimes 			}
4664b88c807SRodney W. Grimes 			flg |= CTF;
4674b88c807SRodney W. Grimes 			break;
4684b88c807SRodney W. Grimes 		case 'U':
4694b88c807SRodney W. Grimes 			/*
4704b88c807SRodney W. Grimes 			 * non-standard option for selecting files within an
4714b88c807SRodney W. Grimes 			 * archive by user (uid or name)
4724b88c807SRodney W. Grimes 			 */
4734b88c807SRodney W. Grimes 			if (usr_add(optarg) < 0) {
4744b88c807SRodney W. Grimes 				pax_usage();
4754b88c807SRodney W. Grimes 				break;
4764b88c807SRodney W. Grimes 			}
4774b88c807SRodney W. Grimes 			flg |= CUF;
4784b88c807SRodney W. Grimes 			break;
4794b88c807SRodney W. Grimes 		case 'X':
4804b88c807SRodney W. Grimes 			/*
4814b88c807SRodney W. Grimes 			 * do not pass over mount points in the file system
4824b88c807SRodney W. Grimes 			 */
4834b88c807SRodney W. Grimes 			Xflag = 1;
4844b88c807SRodney W. Grimes 			flg |= CXF;
4854b88c807SRodney W. Grimes 			break;
4864b88c807SRodney W. Grimes 		case 'Y':
4874b88c807SRodney W. Grimes 			/*
4884b88c807SRodney W. Grimes 			 * On extraction check file inode change time after the
4894b88c807SRodney W. Grimes 			 * modification of the file name. Non standard option.
4904b88c807SRodney W. Grimes 			 */
4914b88c807SRodney W. Grimes 			Yflag = 1;
4924b88c807SRodney W. Grimes 			flg |= CYF;
4934b88c807SRodney W. Grimes 			break;
4944b88c807SRodney W. Grimes 		case 'Z':
4954b88c807SRodney W. Grimes 			/*
4964b88c807SRodney W. Grimes 			 * On extraction check modification time after the
4974b88c807SRodney W. Grimes 			 * modification of the file name. Non standard option.
4984b88c807SRodney W. Grimes 			 */
4994b88c807SRodney W. Grimes 			Zflag = 1;
5004b88c807SRodney W. Grimes 			flg |= CZF;
5014b88c807SRodney W. Grimes 			break;
5024b88c807SRodney W. Grimes 		default:
5034b88c807SRodney W. Grimes 			pax_usage();
5044b88c807SRodney W. Grimes 			break;
5054b88c807SRodney W. Grimes 		}
5064b88c807SRodney W. Grimes 	}
5074b88c807SRodney W. Grimes 
5084b88c807SRodney W. Grimes 	/*
5094b88c807SRodney W. Grimes 	 * figure out the operation mode of pax read,write,extract,copy,append
5104b88c807SRodney W. Grimes 	 * or list. check that we have not been given a bogus set of flags
5114b88c807SRodney W. Grimes 	 * for the operation mode.
5124b88c807SRodney W. Grimes 	 */
5134b88c807SRodney W. Grimes 	if (ISLIST(flg)) {
5144b88c807SRodney W. Grimes 		act = LIST;
515b1787decSKris Kennaway 		listf = stdout;
5164b88c807SRodney W. Grimes 		bflg = flg & BDLIST;
5174b88c807SRodney W. Grimes 	} else if (ISEXTRACT(flg)) {
5184b88c807SRodney W. Grimes 		act = EXTRACT;
5194b88c807SRodney W. Grimes 		bflg = flg & BDEXTR;
5204b88c807SRodney W. Grimes 	} else if (ISARCHIVE(flg)) {
5214b88c807SRodney W. Grimes 		act = ARCHIVE;
5224b88c807SRodney W. Grimes 		bflg = flg & BDARCH;
5234b88c807SRodney W. Grimes 	} else if (ISAPPND(flg)) {
5244b88c807SRodney W. Grimes 		act = APPND;
5254b88c807SRodney W. Grimes 		bflg = flg & BDARCH;
5264b88c807SRodney W. Grimes 	} else if (ISCOPY(flg)) {
5274b88c807SRodney W. Grimes 		act = COPY;
5284b88c807SRodney W. Grimes 		bflg = flg & BDCOPY;
5294b88c807SRodney W. Grimes 	} else
5304b88c807SRodney W. Grimes 		pax_usage();
5314b88c807SRodney W. Grimes 	if (bflg) {
5324b88c807SRodney W. Grimes 		printflg(flg);
5334b88c807SRodney W. Grimes 		pax_usage();
5344b88c807SRodney W. Grimes 	}
5354b88c807SRodney W. Grimes 
5364b88c807SRodney W. Grimes 	/*
5374b88c807SRodney W. Grimes 	 * if we are writing (ARCHIVE) we use the default format if the user
5384b88c807SRodney W. Grimes 	 * did not specify a format. when we write during an APPEND, we will
5394b88c807SRodney W. Grimes 	 * adopt the format of the existing archive if none was supplied.
5404b88c807SRodney W. Grimes 	 */
5414b88c807SRodney W. Grimes 	if (!(flg & XF) && (act == ARCHIVE))
5424b88c807SRodney W. Grimes 		frmt = &(fsub[DEFLT]);
5434b88c807SRodney W. Grimes 
5444b88c807SRodney W. Grimes 	/*
5454b88c807SRodney W. Grimes 	 * process the args as they are interpreted by the operation mode
5464b88c807SRodney W. Grimes 	 */
5474b88c807SRodney W. Grimes 	switch (act) {
5484b88c807SRodney W. Grimes 	case LIST:
5494b88c807SRodney W. Grimes 	case EXTRACT:
5504b88c807SRodney W. Grimes 		for (; optind < argc; optind++)
551b1787decSKris Kennaway 			if (pat_add(argv[optind], NULL) < 0)
5524b88c807SRodney W. Grimes 				pax_usage();
5534b88c807SRodney W. Grimes 		break;
5544b88c807SRodney W. Grimes 	case COPY:
5554b88c807SRodney W. Grimes 		if (optind >= argc) {
556778766feSKris Kennaway 			paxwarn(0, "Destination directory was not supplied");
5574b88c807SRodney W. Grimes 			pax_usage();
5584b88c807SRodney W. Grimes 		}
5594b88c807SRodney W. Grimes 		--argc;
5604b88c807SRodney W. Grimes 		dirptr = argv[argc];
5614b88c807SRodney W. Grimes 		/* FALLTHROUGH */
5624b88c807SRodney W. Grimes 	case ARCHIVE:
5634b88c807SRodney W. Grimes 	case APPND:
5644b88c807SRodney W. Grimes 		for (; optind < argc; optind++)
565b1787decSKris Kennaway 			if (ftree_add(argv[optind], 0) < 0)
5664b88c807SRodney W. Grimes 				pax_usage();
5674b88c807SRodney W. Grimes 		/*
5684b88c807SRodney W. Grimes 		 * no read errors allowed on updates/append operation!
5694b88c807SRodney W. Grimes 		 */
5704b88c807SRodney W. Grimes 		maxflt = 0;
5714b88c807SRodney W. Grimes 		break;
5724b88c807SRodney W. Grimes 	}
5734b88c807SRodney W. Grimes }
5744b88c807SRodney W. Grimes 
5754b88c807SRodney W. Grimes 
5764b88c807SRodney W. Grimes /*
5774b88c807SRodney W. Grimes  * tar_options()
5784b88c807SRodney W. Grimes  *	look at the user specified flags. set globals as required and check if
5794b88c807SRodney W. Grimes  *	the user specified a legal set of flags. If not, complain and exit
5804b88c807SRodney W. Grimes  */
5814b88c807SRodney W. Grimes 
5824b88c807SRodney W. Grimes static void
tar_options(int argc,char ** argv)583f789b261SWarner Losh tar_options(int argc, char **argv)
5844b88c807SRodney W. Grimes {
585f789b261SWarner Losh 	int c;
5864b88c807SRodney W. Grimes 	int fstdin = 0;
587d6e1f8d7SEitan Adler 	int tar_Oflag = 0;
588b1787decSKris Kennaway 	int nincfiles = 0;
589b1787decSKris Kennaway 	int incfiles_max = 0;
590b1787decSKris Kennaway 	struct incfile {
591b1787decSKris Kennaway 		char *file;
592b1787decSKris Kennaway 		char *dir;
593b1787decSKris Kennaway 	};
594b1787decSKris Kennaway 	struct incfile *incfiles = NULL;
5954b88c807SRodney W. Grimes 
596b1787decSKris Kennaway 	/*
597b1787decSKris Kennaway 	 * Set default values.
598b1787decSKris Kennaway 	 */
599b1787decSKris Kennaway 	rmleadslash = 1;
600b1787decSKris Kennaway 
6014b88c807SRodney W. Grimes 	/*
6024b88c807SRodney W. Grimes 	 * process option flags
6034b88c807SRodney W. Grimes 	 */
604b1787decSKris Kennaway 	while ((c = getoldopt(argc, argv,
605b1787decSKris Kennaway 	    "b:cef:hjmopqruts:vwxyzBC:HI:LOPXZ014578")) != -1) {
606b1787decSKris Kennaway 		switch(c) {
6074b88c807SRodney W. Grimes 		case 'b':
6084b88c807SRodney W. Grimes 			/*
609b1787decSKris Kennaway 			 * specify blocksize in 512-byte blocks
6104b88c807SRodney W. Grimes 			 */
611b1787decSKris Kennaway 			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
612b1787decSKris Kennaway 				paxwarn(1, "Invalid block size %s", optarg);
6134b88c807SRodney W. Grimes 				tar_usage();
6144b88c807SRodney W. Grimes 			}
615b1787decSKris Kennaway 			wrblksz *= 512;		/* XXX - check for int oflow */
6164b88c807SRodney W. Grimes 			break;
6174b88c807SRodney W. Grimes 		case 'c':
6184b88c807SRodney W. Grimes 			/*
6194b88c807SRodney W. Grimes 			 * create an archive
6204b88c807SRodney W. Grimes 			 */
6214b88c807SRodney W. Grimes 			act = ARCHIVE;
6224b88c807SRodney W. Grimes 			break;
6234b88c807SRodney W. Grimes 		case 'e':
6244b88c807SRodney W. Grimes 			/*
6254b88c807SRodney W. Grimes 			 * stop after first error
6264b88c807SRodney W. Grimes 			 */
6274b88c807SRodney W. Grimes 			maxflt = 0;
6284b88c807SRodney W. Grimes 			break;
6294b88c807SRodney W. Grimes 		case 'f':
6304b88c807SRodney W. Grimes 			/*
6314b88c807SRodney W. Grimes 			 * filename where the archive is stored
6324b88c807SRodney W. Grimes 			 */
633b1787decSKris Kennaway 			if ((optarg[0] == '-') && (optarg[1]== '\0')) {
6344b88c807SRodney W. Grimes 				/*
6354b88c807SRodney W. Grimes 				 * treat a - as stdin
6364b88c807SRodney W. Grimes 				 */
637b1787decSKris Kennaway 				fstdin = 1;
638b1787decSKris Kennaway 				arcname = NULL;
6394b88c807SRodney W. Grimes 				break;
6404b88c807SRodney W. Grimes 			}
6414b88c807SRodney W. Grimes 			fstdin = 0;
642b1787decSKris Kennaway 			arcname = optarg;
643b1787decSKris Kennaway 			break;
644b1787decSKris Kennaway 		case 'h':
645b1787decSKris Kennaway 			/*
646b1787decSKris Kennaway 			 * follow symlinks
647b1787decSKris Kennaway 			 */
648b1787decSKris Kennaway 			Lflag = 1;
649b1787decSKris Kennaway 			break;
650b1787decSKris Kennaway 		case 'j':
651b1787decSKris Kennaway 		case 'y':
652b1787decSKris Kennaway 			/*
653b1787decSKris Kennaway 			 * use bzip2.  Non standard option.
654b1787decSKris Kennaway 			 */
655b1787decSKris Kennaway 			gzip_program = BZIP2_CMD;
6564b88c807SRodney W. Grimes 			break;
6574b88c807SRodney W. Grimes 		case 'm':
6584b88c807SRodney W. Grimes 			/*
6594b88c807SRodney W. Grimes 			 * do not preserve modification time
6604b88c807SRodney W. Grimes 			 */
6614b88c807SRodney W. Grimes 			pmtime = 0;
6624b88c807SRodney W. Grimes 			break;
6634b88c807SRodney W. Grimes 		case 'o':
6644b88c807SRodney W. Grimes 			if (opt_add("write_opt=nodir") < 0)
6654b88c807SRodney W. Grimes 				tar_usage();
666b1787decSKris Kennaway 		case 'O':
667d6e1f8d7SEitan Adler 			tar_Oflag = 1;
6684b88c807SRodney W. Grimes 			break;
6694b88c807SRodney W. Grimes 		case 'p':
6704b88c807SRodney W. Grimes 			/*
671b1787decSKris Kennaway 			 * preserve uid/gid and file mode, regardless of umask
6724b88c807SRodney W. Grimes 			 */
6734b88c807SRodney W. Grimes 			pmode = 1;
674b1787decSKris Kennaway 			pids = 1;
675b1787decSKris Kennaway 			break;
676b1787decSKris Kennaway 		case 'q':
677b1787decSKris Kennaway 			/*
678b1787decSKris Kennaway 			 * select first match for a pattern only
679b1787decSKris Kennaway 			 */
680b1787decSKris Kennaway 			nflag = 1;
6814b88c807SRodney W. Grimes 			break;
6824b88c807SRodney W. Grimes 		case 'r':
6834b88c807SRodney W. Grimes 		case 'u':
6844b88c807SRodney W. Grimes 			/*
6854b88c807SRodney W. Grimes 			 * append to the archive
6864b88c807SRodney W. Grimes 			 */
6874b88c807SRodney W. Grimes 			act = APPND;
6884b88c807SRodney W. Grimes 			break;
689b1787decSKris Kennaway 		case 's':
690b1787decSKris Kennaway 			/*
691b1787decSKris Kennaway 			 * file name substitution name pattern
692b1787decSKris Kennaway 			 */
693b1787decSKris Kennaway 			if (rep_add(optarg) < 0) {
694b1787decSKris Kennaway 				tar_usage();
695b1787decSKris Kennaway 				break;
696b1787decSKris Kennaway 			}
697b1787decSKris Kennaway 			break;
6984b88c807SRodney W. Grimes 		case 't':
6994b88c807SRodney W. Grimes 			/*
7004b88c807SRodney W. Grimes 			 * list contents of the tape
7014b88c807SRodney W. Grimes 			 */
7024b88c807SRodney W. Grimes 			act = LIST;
7034b88c807SRodney W. Grimes 			break;
7044b88c807SRodney W. Grimes 		case 'v':
7054b88c807SRodney W. Grimes 			/*
7064b88c807SRodney W. Grimes 			 * verbose operation mode
7074b88c807SRodney W. Grimes 			 */
708b1787decSKris Kennaway 			vflag++;
7094b88c807SRodney W. Grimes 			break;
7104b88c807SRodney W. Grimes 		case 'w':
7114b88c807SRodney W. Grimes 			/*
7124b88c807SRodney W. Grimes 			 * interactive file rename
7134b88c807SRodney W. Grimes 			 */
7144b88c807SRodney W. Grimes 			iflag = 1;
7154b88c807SRodney W. Grimes 			break;
7164b88c807SRodney W. Grimes 		case 'x':
7174b88c807SRodney W. Grimes 			/*
718b1787decSKris Kennaway 			 * extract an archive, preserving mode,
719b1787decSKris Kennaway 			 * and mtime if possible.
7204b88c807SRodney W. Grimes 			 */
7214b88c807SRodney W. Grimes 			act = EXTRACT;
722b1787decSKris Kennaway 			pmtime = 1;
7234b88c807SRodney W. Grimes 			break;
7241192d531SKris Kennaway 		case 'z':
7251192d531SKris Kennaway 			/*
7261192d531SKris Kennaway 			 * use gzip.  Non standard option.
7271192d531SKris Kennaway 			 */
7281192d531SKris Kennaway 			gzip_program = GZIP_CMD;
7291192d531SKris Kennaway 			break;
7304b88c807SRodney W. Grimes 		case 'B':
7314b88c807SRodney W. Grimes 			/*
7324b88c807SRodney W. Grimes 			 * Nothing to do here, this is pax default
7334b88c807SRodney W. Grimes 			 */
7344b88c807SRodney W. Grimes 			break;
735b1787decSKris Kennaway 		case 'C':
736b1787decSKris Kennaway 			chdname = optarg;
737b1787decSKris Kennaway 			break;
7384b88c807SRodney W. Grimes 		case 'H':
7394b88c807SRodney W. Grimes 			/*
7404b88c807SRodney W. Grimes 			 * follow command line symlinks only
7414b88c807SRodney W. Grimes 			 */
7424b88c807SRodney W. Grimes 			Hflag = 1;
7434b88c807SRodney W. Grimes 			break;
744b1787decSKris Kennaway 		case 'I':
745b1787decSKris Kennaway 			if (++nincfiles > incfiles_max) {
746b1787decSKris Kennaway 				incfiles_max = nincfiles + 3;
747b1787decSKris Kennaway 				incfiles = realloc(incfiles,
748b1787decSKris Kennaway 				    sizeof(*incfiles) * incfiles_max);
749b1787decSKris Kennaway 				if (incfiles == NULL) {
750b1787decSKris Kennaway 					paxwarn(0, "Unable to allocate space "
751b1787decSKris Kennaway 					    "for option list");
752b1787decSKris Kennaway 					exit(1);
753b1787decSKris Kennaway 				}
754b1787decSKris Kennaway 			}
755b1787decSKris Kennaway 			incfiles[nincfiles - 1].file = optarg;
756b1787decSKris Kennaway 			incfiles[nincfiles - 1].dir = chdname;
757b1787decSKris Kennaway 			break;
7584b88c807SRodney W. Grimes 		case 'L':
7594b88c807SRodney W. Grimes 			/*
7604b88c807SRodney W. Grimes 			 * follow symlinks
7614b88c807SRodney W. Grimes 			 */
7624b88c807SRodney W. Grimes 			Lflag = 1;
7634b88c807SRodney W. Grimes 			break;
7644b88c807SRodney W. Grimes 		case 'P':
7654b88c807SRodney W. Grimes 			/*
766b1787decSKris Kennaway 			 * do not remove leading '/' from pathnames
7674b88c807SRodney W. Grimes 			 */
768b1787decSKris Kennaway 			rmleadslash = 0;
7694b88c807SRodney W. Grimes 			break;
7704b88c807SRodney W. Grimes 		case 'X':
7714b88c807SRodney W. Grimes 			/*
7724b88c807SRodney W. Grimes 			 * do not pass over mount points in the file system
7734b88c807SRodney W. Grimes 			 */
7744b88c807SRodney W. Grimes 			Xflag = 1;
7754b88c807SRodney W. Grimes 			break;
7761192d531SKris Kennaway 		case 'Z':
7771192d531SKris Kennaway 			/*
7781192d531SKris Kennaway 			 * use compress.
7791192d531SKris Kennaway 			 */
7801192d531SKris Kennaway 			gzip_program = COMPRESS_CMD;
7811192d531SKris Kennaway 			break;
7824b88c807SRodney W. Grimes 		case '0':
7834b88c807SRodney W. Grimes 			arcname = DEV_0;
7844b88c807SRodney W. Grimes 			break;
7854b88c807SRodney W. Grimes 		case '1':
7864b88c807SRodney W. Grimes 			arcname = DEV_1;
7874b88c807SRodney W. Grimes 			break;
7884b88c807SRodney W. Grimes 		case '4':
7894b88c807SRodney W. Grimes 			arcname = DEV_4;
7904b88c807SRodney W. Grimes 			break;
7914b88c807SRodney W. Grimes 		case '5':
7924b88c807SRodney W. Grimes 			arcname = DEV_5;
7934b88c807SRodney W. Grimes 			break;
7944b88c807SRodney W. Grimes 		case '7':
7954b88c807SRodney W. Grimes 			arcname = DEV_7;
7964b88c807SRodney W. Grimes 			break;
7974b88c807SRodney W. Grimes 		case '8':
7984b88c807SRodney W. Grimes 			arcname = DEV_8;
7994b88c807SRodney W. Grimes 			break;
8004b88c807SRodney W. Grimes 		default:
8014b88c807SRodney W. Grimes 			tar_usage();
8024b88c807SRodney W. Grimes 			break;
8034b88c807SRodney W. Grimes 		}
8044b88c807SRodney W. Grimes 	}
805b1787decSKris Kennaway 	argc -= optind;
806b1787decSKris Kennaway 	argv += optind;
807b1787decSKris Kennaway 
808b1787decSKris Kennaway 	/* Traditional tar behaviour (pax uses stderr unless in list mode) */
809b1787decSKris Kennaway 	if (fstdin == 1 && act == ARCHIVE)
810b1787decSKris Kennaway 		listf = stderr;
811b1787decSKris Kennaway 	else
812b1787decSKris Kennaway 		listf = stdout;
813b1787decSKris Kennaway 
814b1787decSKris Kennaway 	/* Traditional tar behaviour (pax wants to read file list from stdin) */
815b1787decSKris Kennaway 	if ((act == ARCHIVE || act == APPND) && argc == 0 && nincfiles == 0)
816b1787decSKris Kennaway 		exit(0);
8174b88c807SRodney W. Grimes 
8184b88c807SRodney W. Grimes 	/*
8194b88c807SRodney W. Grimes 	 * if we are writing (ARCHIVE) specify tar, otherwise run like pax
820b1787decSKris Kennaway 	 * (unless -o specified)
8214b88c807SRodney W. Grimes 	 */
822b1787decSKris Kennaway 	if (act == ARCHIVE || act == APPND)
823d6e1f8d7SEitan Adler 		frmt = &(fsub[tar_Oflag ? F_OTAR : F_TAR]);
824d6e1f8d7SEitan Adler 	else if (tar_Oflag) {
825b1787decSKris Kennaway 		paxwarn(1, "The -O/-o options are only valid when writing an archive");
826b1787decSKris Kennaway 		tar_usage();		/* only valid when writing */
827b1787decSKris Kennaway 	}
8284b88c807SRodney W. Grimes 
8294b88c807SRodney W. Grimes 	/*
8304b88c807SRodney W. Grimes 	 * process the args as they are interpreted by the operation mode
8314b88c807SRodney W. Grimes 	 */
8324b88c807SRodney W. Grimes 	switch (act) {
8334b88c807SRodney W. Grimes 	case LIST:
8344b88c807SRodney W. Grimes 	case EXTRACT:
8354b88c807SRodney W. Grimes 	default:
836b1787decSKris Kennaway 		{
837b1787decSKris Kennaway 			int sawpat = 0;
838b1787decSKris Kennaway 			char *file, *dir = NULL;
839b1787decSKris Kennaway 
840b1787decSKris Kennaway 			while (nincfiles || *argv != NULL) {
841b1787decSKris Kennaway 				/*
842b1787decSKris Kennaway 				 * If we queued up any include files,
843b1787decSKris Kennaway 				 * pull them in now.  Otherwise, check
844b1787decSKris Kennaway 				 * for -I and -C positional flags.
845b1787decSKris Kennaway 				 * Anything else must be a file to
846b1787decSKris Kennaway 				 * extract.
847b1787decSKris Kennaway 				 */
848b1787decSKris Kennaway 				if (nincfiles) {
849b1787decSKris Kennaway 					file = incfiles->file;
850b1787decSKris Kennaway 					dir = incfiles->dir;
851b1787decSKris Kennaway 					incfiles++;
852b1787decSKris Kennaway 					nincfiles--;
853b1787decSKris Kennaway 				} else if (strcmp(*argv, "-I") == 0) {
854b1787decSKris Kennaway 					if (*++argv == NULL)
855b1787decSKris Kennaway 						break;
856b1787decSKris Kennaway 					file = *argv++;
857b1787decSKris Kennaway 					dir = chdname;
858b1787decSKris Kennaway 				} else
859b1787decSKris Kennaway 					file = NULL;
860b1787decSKris Kennaway 				if (file != NULL) {
861b1787decSKris Kennaway 					FILE *fp;
862b1787decSKris Kennaway 					char *str;
863b1787decSKris Kennaway 
864b1787decSKris Kennaway 					if (strcmp(file, "-") == 0)
865b1787decSKris Kennaway 						fp = stdin;
866b1787decSKris Kennaway 					else if ((fp = fopen(file, "r")) == NULL) {
867b1787decSKris Kennaway 						paxwarn(1, "Unable to open file '%s' for read", file);
8684b88c807SRodney W. Grimes 						tar_usage();
869b1787decSKris Kennaway 					}
870a651f2bcSBaptiste Daroussin 					while ((str = get_line(fp)) != NULL) {
871b1787decSKris Kennaway 						if (pat_add(str, dir) < 0)
872b1787decSKris Kennaway 							tar_usage();
873b1787decSKris Kennaway 						sawpat = 1;
874b1787decSKris Kennaway 					}
875b1787decSKris Kennaway 					if (strcmp(file, "-") != 0)
876b1787decSKris Kennaway 						fclose(fp);
877a651f2bcSBaptiste Daroussin 					if (get_line_error) {
878b1787decSKris Kennaway 						paxwarn(1, "Problem with file '%s'", file);
879b1787decSKris Kennaway 						tar_usage();
880b1787decSKris Kennaway 					}
881b1787decSKris Kennaway 				} else if (strcmp(*argv, "-C") == 0) {
882b1787decSKris Kennaway 					if (*++argv == NULL)
883b1787decSKris Kennaway 						break;
884b1787decSKris Kennaway 					chdname = *argv++;
885b1787decSKris Kennaway 				} else if (pat_add(*argv++, chdname) < 0)
886b1787decSKris Kennaway 					tar_usage();
887b1787decSKris Kennaway 				else
888b1787decSKris Kennaway 					sawpat = 1;
889b1787decSKris Kennaway 			}
890b1787decSKris Kennaway 			/*
891b1787decSKris Kennaway 			 * if patterns were added, we are doing chdir()
892b1787decSKris Kennaway 			 * on a file-by-file basis, else, just one
893b1787decSKris Kennaway 			 * global chdir (if any) after opening input.
894b1787decSKris Kennaway 			 */
895b1787decSKris Kennaway 			if (sawpat > 0)
896b1787decSKris Kennaway 				chdname = NULL;
897b1787decSKris Kennaway 		}
8984b88c807SRodney W. Grimes 		break;
8994b88c807SRodney W. Grimes 	case ARCHIVE:
9004b88c807SRodney W. Grimes 	case APPND:
901b1787decSKris Kennaway 		if (chdname != NULL) {	/* initial chdir() */
902b1787decSKris Kennaway 			if (ftree_add(chdname, 1) < 0)
9034b88c807SRodney W. Grimes 				tar_usage();
904b1787decSKris Kennaway 		}
905b1787decSKris Kennaway 
906b1787decSKris Kennaway 		while (nincfiles || *argv != NULL) {
907b1787decSKris Kennaway 			char *file, *dir = NULL;
908b1787decSKris Kennaway 
909b1787decSKris Kennaway 			/*
910b1787decSKris Kennaway 			 * If we queued up any include files, pull them in
911b1787decSKris Kennaway 			 * now.  Otherwise, check for -I and -C positional
912b1787decSKris Kennaway 			 * flags.  Anything else must be a file to include
913b1787decSKris Kennaway 			 * in the archive.
914b1787decSKris Kennaway 			 */
915b1787decSKris Kennaway 			if (nincfiles) {
916b1787decSKris Kennaway 				file = incfiles->file;
917b1787decSKris Kennaway 				dir = incfiles->dir;
918b1787decSKris Kennaway 				incfiles++;
919b1787decSKris Kennaway 				nincfiles--;
920b1787decSKris Kennaway 			} else if (strcmp(*argv, "-I") == 0) {
921b1787decSKris Kennaway 				if (*++argv == NULL)
922b1787decSKris Kennaway 					break;
923b1787decSKris Kennaway 				file = *argv++;
924b1787decSKris Kennaway 				dir = NULL;
925b1787decSKris Kennaway 			} else
926b1787decSKris Kennaway 				file = NULL;
927b1787decSKris Kennaway 			if (file != NULL) {
928b1787decSKris Kennaway 				FILE *fp;
929b1787decSKris Kennaway 				char *str;
930b1787decSKris Kennaway 
931b1787decSKris Kennaway 				/* Set directory if needed */
932b1787decSKris Kennaway 				if (dir) {
933b1787decSKris Kennaway 					if (ftree_add(dir, 1) < 0)
934b1787decSKris Kennaway 						tar_usage();
935b1787decSKris Kennaway 				}
936b1787decSKris Kennaway 
937b1787decSKris Kennaway 				if (strcmp(file, "-") == 0)
938b1787decSKris Kennaway 					fp = stdin;
939b1787decSKris Kennaway 				else if ((fp = fopen(file, "r")) == NULL) {
940b1787decSKris Kennaway 					paxwarn(1, "Unable to open file '%s' for read", file);
941b1787decSKris Kennaway 					tar_usage();
942b1787decSKris Kennaway 				}
943a651f2bcSBaptiste Daroussin 				while ((str = get_line(fp)) != NULL) {
944b1787decSKris Kennaway 					if (ftree_add(str, 0) < 0)
945b1787decSKris Kennaway 						tar_usage();
946b1787decSKris Kennaway 				}
947b1787decSKris Kennaway 				if (strcmp(file, "-") != 0)
948b1787decSKris Kennaway 					fclose(fp);
949a651f2bcSBaptiste Daroussin 				if (get_line_error) {
950b1787decSKris Kennaway 					paxwarn(1, "Problem with file '%s'",
951b1787decSKris Kennaway 					    file);
952b1787decSKris Kennaway 					tar_usage();
953b1787decSKris Kennaway 				}
954b1787decSKris Kennaway 			} else if (strcmp(*argv, "-C") == 0) {
955b1787decSKris Kennaway 				if (*++argv == NULL)
956b1787decSKris Kennaway 					break;
957b1787decSKris Kennaway 				if (ftree_add(*argv++, 1) < 0)
958b1787decSKris Kennaway 					tar_usage();
959b1787decSKris Kennaway 			} else if (ftree_add(*argv++, 0) < 0)
960b1787decSKris Kennaway 				tar_usage();
961b1787decSKris Kennaway 		}
9624b88c807SRodney W. Grimes 		/*
9634b88c807SRodney W. Grimes 		 * no read errors allowed on updates/append operation!
9644b88c807SRodney W. Grimes 		 */
9654b88c807SRodney W. Grimes 		maxflt = 0;
9664b88c807SRodney W. Grimes 		break;
9674b88c807SRodney W. Grimes 	}
968778766feSKris Kennaway 	if (!fstdin && ((arcname == NULL) || (*arcname == '\0'))) {
9694b88c807SRodney W. Grimes 		arcname = getenv("TAPE");
970778766feSKris Kennaway 		if ((arcname == NULL) || (*arcname == '\0'))
971b1787decSKris Kennaway 			arcname = _PATH_DEFTAPE;
9724b88c807SRodney W. Grimes 	}
9734b88c807SRodney W. Grimes }
9744b88c807SRodney W. Grimes 
97540feca3aSMark Murray static int
mkpath(char * path)97640feca3aSMark Murray mkpath(char *path)
977b1787decSKris Kennaway {
978b1787decSKris Kennaway 	struct stat sb;
979f789b261SWarner Losh 	char *slash;
980b1787decSKris Kennaway 	int done = 0;
981b1787decSKris Kennaway 
982b1787decSKris Kennaway 	slash = path;
983b1787decSKris Kennaway 
984b1787decSKris Kennaway 	while (!done) {
985b1787decSKris Kennaway 		slash += strspn(slash, "/");
986b1787decSKris Kennaway 		slash += strcspn(slash, "/");
987b1787decSKris Kennaway 
988b1787decSKris Kennaway 		done = (*slash == '\0');
989b1787decSKris Kennaway 		*slash = '\0';
990b1787decSKris Kennaway 
991b1787decSKris Kennaway 		if (stat(path, &sb)) {
992b1787decSKris Kennaway 			if (errno != ENOENT || mkdir(path, 0777)) {
993b1787decSKris Kennaway 				paxwarn(1, "%s", path);
994b1787decSKris Kennaway 				return (-1);
995b1787decSKris Kennaway 			}
996b1787decSKris Kennaway 		} else if (!S_ISDIR(sb.st_mode)) {
997b1787decSKris Kennaway 			syswarn(1, ENOTDIR, "%s", path);
998b1787decSKris Kennaway 			return (-1);
999b1787decSKris Kennaway 		}
1000b1787decSKris Kennaway 
1001b1787decSKris Kennaway 		if (!done)
1002b1787decSKris Kennaway 			*slash = '/';
1003b1787decSKris Kennaway 	}
1004b1787decSKris Kennaway 
1005b1787decSKris Kennaway 	return (0);
1006b1787decSKris Kennaway }
10074b88c807SRodney W. Grimes /*
10084b88c807SRodney W. Grimes  * cpio_options()
10094b88c807SRodney W. Grimes  *	look at the user specified flags. set globals as required and check if
10104b88c807SRodney W. Grimes  *	the user specified a legal set of flags. If not, complain and exit
10114b88c807SRodney W. Grimes  */
10124b88c807SRodney W. Grimes 
10134b88c807SRodney W. Grimes static void
cpio_options(int argc,char ** argv)1014f789b261SWarner Losh cpio_options(int argc, char **argv)
10154b88c807SRodney W. Grimes {
1016cee22cbdSDavid E. O'Brien 	int c;
1017cee22cbdSDavid E. O'Brien 	size_t i;
1018b1787decSKris Kennaway 	char *str;
1019b1787decSKris Kennaway 	FSUB tmp;
1020b1787decSKris Kennaway 	FILE *fp;
1021b1787decSKris Kennaway 
1022b1787decSKris Kennaway 	kflag = 1;
1023b1787decSKris Kennaway 	pids = 1;
1024b1787decSKris Kennaway 	pmode = 1;
1025b1787decSKris Kennaway 	pmtime = 0;
1026b1787decSKris Kennaway 	arcname = NULL;
1027b1787decSKris Kennaway 	dflag = 1;
1028b1787decSKris Kennaway 	act = -1;
1029b1787decSKris Kennaway 	nodirs = 1;
1030b1787decSKris Kennaway 	while ((c=getopt(argc,argv,"abcdfiklmoprstuvzABC:E:F:H:I:LO:SZ6")) != -1)
1031b1787decSKris Kennaway 		switch (c) {
1032b1787decSKris Kennaway 			case 'a':
1033b1787decSKris Kennaway 				/*
1034b1787decSKris Kennaway 				 * preserve access time on files read
1035b1787decSKris Kennaway 				 */
1036b1787decSKris Kennaway 				tflag = 1;
1037b1787decSKris Kennaway 				break;
1038b1787decSKris Kennaway 			case 'b':
1039b1787decSKris Kennaway 				/*
1040b1787decSKris Kennaway 				 * swap bytes and half-words when reading data
1041b1787decSKris Kennaway 				 */
1042b1787decSKris Kennaway 				break;
1043b1787decSKris Kennaway 			case 'c':
1044b1787decSKris Kennaway 				/*
1045b1787decSKris Kennaway 				 * ASCII cpio header
1046b1787decSKris Kennaway 				 */
1047b1787decSKris Kennaway 				frmt = &(fsub[F_ACPIO]);
1048b1787decSKris Kennaway 				break;
1049b1787decSKris Kennaway 			case 'd':
1050b1787decSKris Kennaway 				/*
1051b1787decSKris Kennaway 				 * create directories as needed
1052b1787decSKris Kennaway 				 */
1053b1787decSKris Kennaway 				nodirs = 0;
1054b1787decSKris Kennaway 				break;
1055b1787decSKris Kennaway 			case 'f':
1056b1787decSKris Kennaway 				/*
1057b1787decSKris Kennaway 				 * invert meaning of pattern list
1058b1787decSKris Kennaway 				 */
1059b1787decSKris Kennaway 				cflag = 1;
1060b1787decSKris Kennaway 				break;
1061b1787decSKris Kennaway 			case 'i':
1062b1787decSKris Kennaway 				/*
1063b1787decSKris Kennaway 				 * restore an archive
1064b1787decSKris Kennaway 				 */
1065b1787decSKris Kennaway 				act = EXTRACT;
1066b1787decSKris Kennaway 				break;
1067b1787decSKris Kennaway 			case 'k':
1068b1787decSKris Kennaway 				break;
1069b1787decSKris Kennaway 			case 'l':
1070b1787decSKris Kennaway 				/*
1071b1787decSKris Kennaway 				 * use links instead of copies when possible
1072b1787decSKris Kennaway 				 */
1073b1787decSKris Kennaway 				lflag = 1;
1074b1787decSKris Kennaway 				break;
1075b1787decSKris Kennaway 			case 'm':
1076b1787decSKris Kennaway 				/*
1077b1787decSKris Kennaway 				 * preserve modification time
1078b1787decSKris Kennaway 				 */
1079b1787decSKris Kennaway 				pmtime = 1;
1080b1787decSKris Kennaway 				break;
1081b1787decSKris Kennaway 			case 'o':
1082b1787decSKris Kennaway 				/*
1083b1787decSKris Kennaway 				 * create an archive
1084b1787decSKris Kennaway 				 */
1085b1787decSKris Kennaway 				act = ARCHIVE;
1086b1787decSKris Kennaway 				frmt = &(fsub[F_CPIO]);
1087b1787decSKris Kennaway 				break;
1088b1787decSKris Kennaway 			case 'p':
1089b1787decSKris Kennaway 				/*
1090b1787decSKris Kennaway 				 * copy-pass mode
1091b1787decSKris Kennaway 				 */
1092b1787decSKris Kennaway 				act = COPY;
1093b1787decSKris Kennaway 				break;
1094b1787decSKris Kennaway 			case 'r':
1095b1787decSKris Kennaway 				/*
1096b1787decSKris Kennaway 				 * interactively rename files
1097b1787decSKris Kennaway 				 */
1098b1787decSKris Kennaway 				iflag = 1;
1099b1787decSKris Kennaway 				break;
1100b1787decSKris Kennaway 			case 's':
1101b1787decSKris Kennaway 				/*
1102b1787decSKris Kennaway 				 * swap bytes after reading data
1103b1787decSKris Kennaway 				 */
1104b1787decSKris Kennaway 				break;
1105b1787decSKris Kennaway 			case 't':
1106b1787decSKris Kennaway 				/*
1107b1787decSKris Kennaway 				 * list contents of archive
1108b1787decSKris Kennaway 				 */
1109b1787decSKris Kennaway 				act = LIST;
1110b1787decSKris Kennaway 				listf = stdout;
1111b1787decSKris Kennaway 				break;
1112b1787decSKris Kennaway 			case 'u':
1113b1787decSKris Kennaway 				/*
1114b1787decSKris Kennaway 				 * replace newer files
1115b1787decSKris Kennaway 				 */
1116b1787decSKris Kennaway 				kflag = 0;
1117b1787decSKris Kennaway 				break;
1118b1787decSKris Kennaway 			case 'v':
1119b1787decSKris Kennaway 				/*
1120b1787decSKris Kennaway 				 * verbose operation mode
1121b1787decSKris Kennaway 				 */
1122b1787decSKris Kennaway 				vflag = 1;
1123b1787decSKris Kennaway 				break;
1124b1787decSKris Kennaway 			case 'z':
1125b1787decSKris Kennaway 				/*
1126b1787decSKris Kennaway 				 * use gzip.  Non standard option.
1127b1787decSKris Kennaway 				 */
1128b1787decSKris Kennaway 				gzip_program = GZIP_CMD;
1129b1787decSKris Kennaway 				break;
1130b1787decSKris Kennaway 			case 'A':
1131b1787decSKris Kennaway 				/*
1132b1787decSKris Kennaway 				 * append mode
1133b1787decSKris Kennaway 				 */
1134b1787decSKris Kennaway 				act = APPND;
1135b1787decSKris Kennaway 				break;
1136b1787decSKris Kennaway 			case 'B':
1137b1787decSKris Kennaway 				/*
1138b1787decSKris Kennaway 				 * Use 5120 byte block size
1139b1787decSKris Kennaway 				 */
1140b1787decSKris Kennaway 				wrblksz = 5120;
1141b1787decSKris Kennaway 				break;
1142b1787decSKris Kennaway 			case 'C':
1143b1787decSKris Kennaway 				/*
1144b1787decSKris Kennaway 				 * set block size in bytes
1145b1787decSKris Kennaway 				 */
1146b1787decSKris Kennaway 				wrblksz = atoi(optarg);
1147b1787decSKris Kennaway 				break;
1148b1787decSKris Kennaway 			case 'E':
1149b1787decSKris Kennaway 				/*
1150b1787decSKris Kennaway 				 * file with patterns to extract or list
1151b1787decSKris Kennaway 				 */
1152b1787decSKris Kennaway 				if ((fp = fopen(optarg, "r")) == NULL) {
1153b1787decSKris Kennaway 					paxwarn(1, "Unable to open file '%s' for read", optarg);
1154b1787decSKris Kennaway 					cpio_usage();
11554b88c807SRodney W. Grimes 				}
1156a651f2bcSBaptiste Daroussin 				while ((str = get_line(fp)) != NULL) {
1157b1787decSKris Kennaway 					pat_add(str, NULL);
1158b1787decSKris Kennaway 				}
1159b1787decSKris Kennaway 				fclose(fp);
1160a651f2bcSBaptiste Daroussin 				if (get_line_error) {
1161b1787decSKris Kennaway 					paxwarn(1, "Problem with file '%s'", optarg);
1162b1787decSKris Kennaway 					cpio_usage();
1163b1787decSKris Kennaway 				}
1164b1787decSKris Kennaway 				break;
1165b1787decSKris Kennaway 			case 'F':
1166b1787decSKris Kennaway 			case 'I':
1167b1787decSKris Kennaway 			case 'O':
1168b1787decSKris Kennaway 				/*
1169b1787decSKris Kennaway 				 * filename where the archive is stored
1170b1787decSKris Kennaway 				 */
1171b1787decSKris Kennaway 				if ((optarg[0] == '-') && (optarg[1]== '\0')) {
1172b1787decSKris Kennaway 					/*
1173b1787decSKris Kennaway 					 * treat a - as stdin
1174b1787decSKris Kennaway 					 */
1175b1787decSKris Kennaway 					arcname = NULL;
1176b1787decSKris Kennaway 					break;
1177b1787decSKris Kennaway 				}
1178b1787decSKris Kennaway 				arcname = optarg;
1179b1787decSKris Kennaway 				break;
1180b1787decSKris Kennaway 			case 'H':
1181b1787decSKris Kennaway 				/*
1182b1787decSKris Kennaway 				 * specify an archive format on write
1183b1787decSKris Kennaway 				 */
1184b1787decSKris Kennaway 				tmp.name = optarg;
1185b1787decSKris Kennaway 				if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
1186b1787decSKris Kennaway 				    sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) != NULL)
1187b1787decSKris Kennaway 					break;
1188b1787decSKris Kennaway 				paxwarn(1, "Unknown -H format: %s", optarg);
1189b1787decSKris Kennaway 				(void)fputs("cpio: Known -H formats are:", stderr);
1190b1787decSKris Kennaway 				for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
1191b1787decSKris Kennaway 					(void)fprintf(stderr, " %s", fsub[i].name);
1192b1787decSKris Kennaway 				(void)fputs("\n\n", stderr);
1193b1787decSKris Kennaway 				cpio_usage();
1194b1787decSKris Kennaway 				break;
1195b1787decSKris Kennaway 			case 'L':
1196b1787decSKris Kennaway 				/*
1197b1787decSKris Kennaway 				 * follow symbolic links
1198b1787decSKris Kennaway 				 */
1199b1787decSKris Kennaway 				Lflag = 1;
1200b1787decSKris Kennaway 				break;
1201b1787decSKris Kennaway 			case 'S':
1202b1787decSKris Kennaway 				/*
1203b1787decSKris Kennaway 				 * swap halfwords after reading data
1204b1787decSKris Kennaway 				 */
1205b1787decSKris Kennaway 				break;
1206b1787decSKris Kennaway 			case 'Z':
1207b1787decSKris Kennaway 				/*
1208b1787decSKris Kennaway 				 * use compress.  Non standard option.
1209b1787decSKris Kennaway 				 */
1210b1787decSKris Kennaway 				gzip_program = COMPRESS_CMD;
1211b1787decSKris Kennaway 				break;
1212b1787decSKris Kennaway 			case '6':
1213b1787decSKris Kennaway 				/*
1214b1787decSKris Kennaway 				 * process Version 6 cpio format
1215b1787decSKris Kennaway 				 */
1216b1787decSKris Kennaway 				frmt = &(fsub[F_OCPIO]);
1217b1787decSKris Kennaway 				break;
1218b1787decSKris Kennaway 			case '?':
1219b1787decSKris Kennaway 			default:
1220b1787decSKris Kennaway 				cpio_usage();
1221b1787decSKris Kennaway 				break;
1222b1787decSKris Kennaway 		}
1223b1787decSKris Kennaway 	argc -= optind;
1224b1787decSKris Kennaway 	argv += optind;
1225b1787decSKris Kennaway 
1226b1787decSKris Kennaway 	/*
1227b1787decSKris Kennaway 	 * process the args as they are interpreted by the operation mode
1228b1787decSKris Kennaway 	 */
1229b1787decSKris Kennaway 	switch (act) {
1230b1787decSKris Kennaway 		case LIST:
1231b1787decSKris Kennaway 		case EXTRACT:
1232b1787decSKris Kennaway 			while (*argv != NULL)
1233b1787decSKris Kennaway 				if (pat_add(*argv++, NULL) < 0)
1234b1787decSKris Kennaway 					cpio_usage();
1235b1787decSKris Kennaway 			break;
1236b1787decSKris Kennaway 		case COPY:
1237b1787decSKris Kennaway 			if (*argv == NULL) {
1238b1787decSKris Kennaway 				paxwarn(0, "Destination directory was not supplied");
1239b1787decSKris Kennaway 				cpio_usage();
1240b1787decSKris Kennaway 			}
1241b1787decSKris Kennaway 			dirptr = *argv;
1242b1787decSKris Kennaway 			if (mkpath(dirptr) < 0)
1243b1787decSKris Kennaway 				cpio_usage();
1244b1787decSKris Kennaway 			--argc;
1245b1787decSKris Kennaway 			++argv;
1246b1787decSKris Kennaway 			/* FALLTHROUGH */
1247b1787decSKris Kennaway 		case ARCHIVE:
1248b1787decSKris Kennaway 		case APPND:
1249b1787decSKris Kennaway 			if (*argv != NULL)
1250b1787decSKris Kennaway 				cpio_usage();
1251b1787decSKris Kennaway 			/*
1252b1787decSKris Kennaway 			 * no read errors allowed on updates/append operation!
1253b1787decSKris Kennaway 			 */
1254b1787decSKris Kennaway 			maxflt = 0;
1255a651f2bcSBaptiste Daroussin 			while ((str = get_line(stdin)) != NULL) {
125616fc3635SMark Murray 				ftree_add(str, 0);
1257b1787decSKris Kennaway 			}
1258a651f2bcSBaptiste Daroussin 			if (get_line_error) {
1259b1787decSKris Kennaway 				paxwarn(1, "Problem while reading stdin");
1260b1787decSKris Kennaway 				cpio_usage();
1261b1787decSKris Kennaway 			}
1262b1787decSKris Kennaway 			break;
1263b1787decSKris Kennaway 		default:
1264b1787decSKris Kennaway 			cpio_usage();
1265b1787decSKris Kennaway 			break;
1266b1787decSKris Kennaway 	}
1267b1787decSKris Kennaway }
12684b88c807SRodney W. Grimes 
12694b88c807SRodney W. Grimes /*
12704b88c807SRodney W. Grimes  * printflg()
12714b88c807SRodney W. Grimes  *	print out those invalid flag sets found to the user
12724b88c807SRodney W. Grimes  */
12734b88c807SRodney W. Grimes 
12744b88c807SRodney W. Grimes static void
printflg(unsigned int flg)12754b88c807SRodney W. Grimes printflg(unsigned int flg)
12764b88c807SRodney W. Grimes {
12774b88c807SRodney W. Grimes 	int nxt;
12784b88c807SRodney W. Grimes 	int pos = 0;
12794b88c807SRodney W. Grimes 
12804b88c807SRodney W. Grimes 	(void)fprintf(stderr,"%s: Invalid combination of options:", argv0);
1281b1787decSKris Kennaway 	while ((nxt = ffs(flg)) != 0) {
12824b88c807SRodney W. Grimes 		flg = flg >> nxt;
12834b88c807SRodney W. Grimes 		pos += nxt;
12844b88c807SRodney W. Grimes 		(void)fprintf(stderr, " -%c", flgch[pos-1]);
12854b88c807SRodney W. Grimes 	}
12864b88c807SRodney W. Grimes 	(void)putc('\n', stderr);
12874b88c807SRodney W. Grimes }
12884b88c807SRodney W. Grimes 
12894b88c807SRodney W. Grimes /*
12904b88c807SRodney W. Grimes  * c_frmt()
12914b88c807SRodney W. Grimes  *	comparison routine used by bsearch to find the format specified
12924b88c807SRodney W. Grimes  *	by the user
12934b88c807SRodney W. Grimes  */
12944b88c807SRodney W. Grimes 
12954b88c807SRodney W. Grimes static int
c_frmt(const void * a,const void * b)12964b88c807SRodney W. Grimes c_frmt(const void *a, const void *b)
12974b88c807SRodney W. Grimes {
129840feca3aSMark Murray 	return(strcmp(((const FSUB *)a)->name, ((const FSUB *)b)->name));
12994b88c807SRodney W. Grimes }
13004b88c807SRodney W. Grimes 
13014b88c807SRodney W. Grimes /*
13024b88c807SRodney W. Grimes  * opt_next()
13034b88c807SRodney W. Grimes  *	called by format specific options routines to get each format specific
13044b88c807SRodney W. Grimes  *	flag and value specified with -o
13054b88c807SRodney W. Grimes  * Return:
13064b88c807SRodney W. Grimes  *	pointer to next OPLIST entry or NULL (end of list).
13074b88c807SRodney W. Grimes  */
13084b88c807SRodney W. Grimes 
13094b88c807SRodney W. Grimes OPLIST *
opt_next(void)13104b88c807SRodney W. Grimes opt_next(void)
13114b88c807SRodney W. Grimes {
13124b88c807SRodney W. Grimes 	OPLIST *opt;
13134b88c807SRodney W. Grimes 
13144b88c807SRodney W. Grimes 	if ((opt = ophead) != NULL)
13154b88c807SRodney W. Grimes 		ophead = ophead->fow;
13164b88c807SRodney W. Grimes 	return(opt);
13174b88c807SRodney W. Grimes }
13184b88c807SRodney W. Grimes 
13194b88c807SRodney W. Grimes /*
13204b88c807SRodney W. Grimes  * bad_opt()
13214b88c807SRodney W. Grimes  *	generic routine used to complain about a format specific options
13224b88c807SRodney W. Grimes  *	when the format does not support options.
13234b88c807SRodney W. Grimes  */
13244b88c807SRodney W. Grimes 
13254b88c807SRodney W. Grimes int
bad_opt(void)13264b88c807SRodney W. Grimes bad_opt(void)
13274b88c807SRodney W. Grimes {
1328f789b261SWarner Losh 	OPLIST *opt;
13294b88c807SRodney W. Grimes 
13304b88c807SRodney W. Grimes 	if (ophead == NULL)
13314b88c807SRodney W. Grimes 		return(0);
13324b88c807SRodney W. Grimes 	/*
13334b88c807SRodney W. Grimes 	 * print all we were given
13344b88c807SRodney W. Grimes 	 */
1335778766feSKris Kennaway 	paxwarn(1,"These format options are not supported");
13364b88c807SRodney W. Grimes 	while ((opt = opt_next()) != NULL)
13374b88c807SRodney W. Grimes 		(void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
13384b88c807SRodney W. Grimes 	pax_usage();
13394b88c807SRodney W. Grimes 	return(0);
13404b88c807SRodney W. Grimes }
13414b88c807SRodney W. Grimes 
13424b88c807SRodney W. Grimes /*
13434b88c807SRodney W. Grimes  * opt_add()
13449d5abbddSJens Schweikhardt  *	breaks the value supplied to -o into an option name and value. Options
13454b88c807SRodney W. Grimes  *	are given to -o in the form -o name-value,name=value
134646be34b9SKris Kennaway  *	multiple -o may be specified.
13474b88c807SRodney W. Grimes  * Return:
13489d5abbddSJens Schweikhardt  *	0 if format in name=value format, -1 if -o is passed junk.
13494b88c807SRodney W. Grimes  */
13504b88c807SRodney W. Grimes 
13514b88c807SRodney W. Grimes int
opt_add(const char * str)135240feca3aSMark Murray opt_add(const char *str)
13534b88c807SRodney W. Grimes {
1354f789b261SWarner Losh 	OPLIST *opt;
1355f789b261SWarner Losh 	char *frpt;
1356f789b261SWarner Losh 	char *pt;
1357f789b261SWarner Losh 	char *endpt;
135840feca3aSMark Murray 	char *lstr;
13594b88c807SRodney W. Grimes 
13604b88c807SRodney W. Grimes 	if ((str == NULL) || (*str == '\0')) {
1361778766feSKris Kennaway 		paxwarn(0, "Invalid option name");
13624b88c807SRodney W. Grimes 		return(-1);
13634b88c807SRodney W. Grimes 	}
136440feca3aSMark Murray 	if ((lstr = strdup(str)) == NULL) {
1365b1787decSKris Kennaway 		paxwarn(0, "Unable to allocate space for option list");
1366b1787decSKris Kennaway 		return(-1);
1367b1787decSKris Kennaway 	}
136840feca3aSMark Murray 	frpt = endpt = lstr;
13694b88c807SRodney W. Grimes 
13704b88c807SRodney W. Grimes 	/*
13714b88c807SRodney W. Grimes 	 * break into name and values pieces and stuff each one into a
13724b88c807SRodney W. Grimes 	 * OPLIST structure. When we know the format, the format specific
13734b88c807SRodney W. Grimes 	 * option function will go through this list
13744b88c807SRodney W. Grimes 	 */
13754b88c807SRodney W. Grimes 	while ((frpt != NULL) && (*frpt != '\0')) {
13764b88c807SRodney W. Grimes 		if ((endpt = strchr(frpt, ',')) != NULL)
13774b88c807SRodney W. Grimes 			*endpt = '\0';
13784b88c807SRodney W. Grimes 		if ((pt = strchr(frpt, '=')) == NULL) {
1379778766feSKris Kennaway 			paxwarn(0, "Invalid options format");
138040feca3aSMark Murray 			free(lstr);
13814b88c807SRodney W. Grimes 			return(-1);
13824b88c807SRodney W. Grimes 		}
13834b88c807SRodney W. Grimes 		if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
1384778766feSKris Kennaway 			paxwarn(0, "Unable to allocate space for option list");
138540feca3aSMark Murray 			free(lstr);
13864b88c807SRodney W. Grimes 			return(-1);
13874b88c807SRodney W. Grimes 		}
1388248825e5SKevin Lo 		lstr = NULL;	/* parts of string going onto the OPLIST */
13894b88c807SRodney W. Grimes 		*pt++ = '\0';
13904b88c807SRodney W. Grimes 		opt->name = frpt;
13914b88c807SRodney W. Grimes 		opt->value = pt;
13924b88c807SRodney W. Grimes 		opt->fow = NULL;
13934b88c807SRodney W. Grimes 		if (endpt != NULL)
13944b88c807SRodney W. Grimes 			frpt = endpt + 1;
13954b88c807SRodney W. Grimes 		else
13964b88c807SRodney W. Grimes 			frpt = NULL;
13974b88c807SRodney W. Grimes 		if (ophead == NULL) {
13984b88c807SRodney W. Grimes 			optail = ophead = opt;
13994b88c807SRodney W. Grimes 			continue;
14004b88c807SRodney W. Grimes 		}
14014b88c807SRodney W. Grimes 		optail->fow = opt;
14024b88c807SRodney W. Grimes 		optail = opt;
14034b88c807SRodney W. Grimes 	}
1404248825e5SKevin Lo 	free(lstr);
14054b88c807SRodney W. Grimes 	return(0);
14064b88c807SRodney W. Grimes }
14074b88c807SRodney W. Grimes 
14084b88c807SRodney W. Grimes /*
14094b88c807SRodney W. Grimes  * str_offt()
14104b88c807SRodney W. Grimes  *	Convert an expression of the following forms to an off_t > 0.
14114b88c807SRodney W. Grimes  * 	1) A positive decimal number.
14124b88c807SRodney W. Grimes  *	2) A positive decimal number followed by a b (mult by 512).
14134b88c807SRodney W. Grimes  *	3) A positive decimal number followed by a k (mult by 1024).
14144b88c807SRodney W. Grimes  *	4) A positive decimal number followed by a m (mult by 512).
14154b88c807SRodney W. Grimes  *	5) A positive decimal number followed by a w (mult by sizeof int)
14164b88c807SRodney W. Grimes  *	6) Two or more positive decimal numbers (with/without k,b or w).
14179a01d32bSJeroen Ruigrok van der Werven  *	   separated by x (also * for backwards compatibility), specifying
14184b88c807SRodney W. Grimes  *	   the product of the indicated values.
14194b88c807SRodney W. Grimes  * Return:
14204b88c807SRodney W. Grimes  *	0 for an error, a positive value o.w.
14214b88c807SRodney W. Grimes  */
14224b88c807SRodney W. Grimes 
14234b88c807SRodney W. Grimes static off_t
str_offt(char * val)14244b88c807SRodney W. Grimes str_offt(char *val)
14254b88c807SRodney W. Grimes {
14264b88c807SRodney W. Grimes 	char *expr;
14274b88c807SRodney W. Grimes 	off_t num, t;
14284b88c807SRodney W. Grimes 
14294b88c807SRodney W. Grimes 	num = strtoq(val, &expr, 0);
14304b88c807SRodney W. Grimes 	if ((num == QUAD_MAX) || (num <= 0) || (expr == val))
14314b88c807SRodney W. Grimes 		return(0);
14324b88c807SRodney W. Grimes 
14334b88c807SRodney W. Grimes 	switch(*expr) {
14344b88c807SRodney W. Grimes 	case 'b':
14354b88c807SRodney W. Grimes 		t = num;
14364b88c807SRodney W. Grimes 		num *= 512;
14374b88c807SRodney W. Grimes 		if (t > num)
14384b88c807SRodney W. Grimes 			return(0);
14394b88c807SRodney W. Grimes 		++expr;
14404b88c807SRodney W. Grimes 		break;
14414b88c807SRodney W. Grimes 	case 'k':
14424b88c807SRodney W. Grimes 		t = num;
14434b88c807SRodney W. Grimes 		num *= 1024;
14444b88c807SRodney W. Grimes 		if (t > num)
14454b88c807SRodney W. Grimes 			return(0);
14464b88c807SRodney W. Grimes 		++expr;
14474b88c807SRodney W. Grimes 		break;
14484b88c807SRodney W. Grimes 	case 'm':
14494b88c807SRodney W. Grimes 		t = num;
14504b88c807SRodney W. Grimes 		num *= 1048576;
14514b88c807SRodney W. Grimes 		if (t > num)
14524b88c807SRodney W. Grimes 			return(0);
14534b88c807SRodney W. Grimes 		++expr;
14544b88c807SRodney W. Grimes 		break;
14554b88c807SRodney W. Grimes 	case 'w':
14564b88c807SRodney W. Grimes 		t = num;
14574b88c807SRodney W. Grimes 		num *= sizeof(int);
14584b88c807SRodney W. Grimes 		if (t > num)
14594b88c807SRodney W. Grimes 			return(0);
14604b88c807SRodney W. Grimes 		++expr;
14614b88c807SRodney W. Grimes 		break;
14624b88c807SRodney W. Grimes 	}
14634b88c807SRodney W. Grimes 
14644b88c807SRodney W. Grimes 	switch(*expr) {
14654b88c807SRodney W. Grimes 		case '\0':
14664b88c807SRodney W. Grimes 			break;
14674b88c807SRodney W. Grimes 		case '*':
14684b88c807SRodney W. Grimes 		case 'x':
14694b88c807SRodney W. Grimes 			t = num;
14704b88c807SRodney W. Grimes 			num *= str_offt(expr + 1);
14714b88c807SRodney W. Grimes 			if (t > num)
14724b88c807SRodney W. Grimes 				return(0);
14734b88c807SRodney W. Grimes 			break;
14744b88c807SRodney W. Grimes 		default:
14754b88c807SRodney W. Grimes 			return(0);
14764b88c807SRodney W. Grimes 	}
14774b88c807SRodney W. Grimes 	return(num);
14784b88c807SRodney W. Grimes }
14794b88c807SRodney W. Grimes 
1480b1787decSKris Kennaway char *
get_line(FILE * f)1481a651f2bcSBaptiste Daroussin get_line(FILE *f)
1482b1787decSKris Kennaway {
1483b1787decSKris Kennaway 	char *name, *temp;
1484b1787decSKris Kennaway 	size_t len;
1485b1787decSKris Kennaway 
1486b1787decSKris Kennaway 	name = fgetln(f, &len);
1487b1787decSKris Kennaway 	if (!name) {
1488a651f2bcSBaptiste Daroussin 		get_line_error = ferror(f) ? GETLINE_FILE_CORRUPT : 0;
1489b1787decSKris Kennaway 		return(0);
1490b1787decSKris Kennaway 	}
1491b1787decSKris Kennaway 	if (name[len-1] != '\n')
1492b1787decSKris Kennaway 		len++;
1493b1787decSKris Kennaway 	temp = malloc(len);
1494b1787decSKris Kennaway 	if (!temp) {
1495a651f2bcSBaptiste Daroussin 		get_line_error = GETLINE_OUT_OF_MEM;
1496b1787decSKris Kennaway 		return(0);
1497b1787decSKris Kennaway 	}
1498b1787decSKris Kennaway 	memcpy(temp, name, len-1);
1499b1787decSKris Kennaway 	temp[len-1] = 0;
1500b1787decSKris Kennaway 	return(temp);
1501b1787decSKris Kennaway }
1502b1787decSKris Kennaway 
15034b88c807SRodney W. Grimes /*
15044b88c807SRodney W. Grimes  * no_op()
15054b88c807SRodney W. Grimes  *	for those option functions where the archive format has nothing to do.
15064b88c807SRodney W. Grimes  * Return:
15074b88c807SRodney W. Grimes  *	0
15084b88c807SRodney W. Grimes  */
15094b88c807SRodney W. Grimes 
15104b88c807SRodney W. Grimes static int
no_op(void)15114b88c807SRodney W. Grimes no_op(void)
15124b88c807SRodney W. Grimes {
15134b88c807SRodney W. Grimes 	return(0);
15144b88c807SRodney W. Grimes }
15154b88c807SRodney W. Grimes 
15164b88c807SRodney W. Grimes /*
15174b88c807SRodney W. Grimes  * pax_usage()
15184b88c807SRodney W. Grimes  *	print the usage summary to the user
15194b88c807SRodney W. Grimes  */
15204b88c807SRodney W. Grimes 
15214b88c807SRodney W. Grimes void
pax_usage(void)15224b88c807SRodney W. Grimes pax_usage(void)
15234b88c807SRodney W. Grimes {
1524d6e1f8d7SEitan Adler 	(void)fputs("usage: pax [-cdnOvz] [-E limit] [-f archive] ", stderr);
15254b88c807SRodney W. Grimes 	(void)fputs("[-s replstr] ... [-U user] ...", stderr);
15264b88c807SRodney W. Grimes 	(void)fputs("\n	   [-G group] ... ", stderr);
15274b88c807SRodney W. Grimes 	(void)fputs("[-T [from_date][,to_date]] ... ", stderr);
15284b88c807SRodney W. Grimes 	(void)fputs("[pattern ...]\n", stderr);
1529d6e1f8d7SEitan Adler 	(void)fputs("       pax -r [-cdiknOuvzDYZ] [-E limit] ", stderr);
15304b88c807SRodney W. Grimes 	(void)fputs("[-f archive] [-o options] ... \n", stderr);
15314b88c807SRodney W. Grimes 	(void)fputs("	   [-p string] ... [-s replstr] ... ", stderr);
15324b88c807SRodney W. Grimes 	(void)fputs("[-U user] ... [-G group] ...\n	   ", stderr);
15334b88c807SRodney W. Grimes 	(void)fputs("[-T [from_date][,to_date]] ... ", stderr);
15344b88c807SRodney W. Grimes 	(void)fputs(" [pattern ...]\n", stderr);
1535d6e1f8d7SEitan Adler 	(void)fputs("       pax -w [-dituvzHLOPX] [-b blocksize] ", stderr);
15364b88c807SRodney W. Grimes 	(void)fputs("[ [-a] [-f archive] ] [-x format] \n", stderr);
15374b88c807SRodney W. Grimes 	(void)fputs("	   [-B bytes] [-s replstr] ... ", stderr);
15384b88c807SRodney W. Grimes 	(void)fputs("[-o options] ... [-U user] ...", stderr);
15394b88c807SRodney W. Grimes 	(void)fputs("\n	   [-G group] ... ", stderr);
15404b88c807SRodney W. Grimes 	(void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
15414b88c807SRodney W. Grimes 	(void)fputs("[file ...]\n", stderr);
1542d6e1f8d7SEitan Adler 	(void)fputs("       pax -r -w [-diklntuvDHLOPXYZ] ", stderr);
15434b88c807SRodney W. Grimes 	(void)fputs("[-p string] ... [-s replstr] ...", stderr);
15444b88c807SRodney W. Grimes 	(void)fputs("\n	   [-U user] ... [-G group] ... ", stderr);
15454b88c807SRodney W. Grimes 	(void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
15464b88c807SRodney W. Grimes 	(void)fputs("\n	   [file ...] directory\n", stderr);
15474b88c807SRodney W. Grimes 	exit(1);
15484b88c807SRodney W. Grimes }
15494b88c807SRodney W. Grimes 
15504b88c807SRodney W. Grimes /*
15514b88c807SRodney W. Grimes  * tar_usage()
15524b88c807SRodney W. Grimes  *	print the usage summary to the user
15534b88c807SRodney W. Grimes  */
15544b88c807SRodney W. Grimes 
15554b88c807SRodney W. Grimes void
tar_usage(void)15564b88c807SRodney W. Grimes tar_usage(void)
15574b88c807SRodney W. Grimes {
1558b1787decSKris Kennaway 	(void)fputs("usage: tar [-]{crtux}[-befhjmopqsvwyzHLOPXZ014578] [blocksize] ",
15594b88c807SRodney W. Grimes 		 stderr);
1560b1787decSKris Kennaway 	(void)fputs("[archive] [replstr] [-C directory] [-I file] [file ...]\n",
1561b1787decSKris Kennaway 	    stderr);
15624b88c807SRodney W. Grimes 	exit(1);
15634b88c807SRodney W. Grimes }
15644b88c807SRodney W. Grimes 
15654b88c807SRodney W. Grimes /*
15664b88c807SRodney W. Grimes  * cpio_usage()
15674b88c807SRodney W. Grimes  *	print the usage summary to the user
15684b88c807SRodney W. Grimes  */
15694b88c807SRodney W. Grimes 
15704b88c807SRodney W. Grimes void
cpio_usage(void)15714b88c807SRodney W. Grimes cpio_usage(void)
15724b88c807SRodney W. Grimes {
1573b1787decSKris Kennaway 	(void)fputs("usage: cpio -o [-aABcLvVzZ] [-C bytes] [-H format] [-O archive]\n", stderr);
1574b1787decSKris Kennaway 	(void)fputs("               [-F archive] < name-list [> archive]\n", stderr);
1575b1787decSKris Kennaway 	(void)fputs("       cpio -i [-bBcdfmnrsStuvVzZ6] [-C bytes] [-E file] [-H format]\n", stderr);
1576b1787decSKris Kennaway 	(void)fputs("               [-I archive] [-F archive] [pattern...] [< archive]\n", stderr);
1577b1787decSKris Kennaway 	(void)fputs("       cpio -p [-adlLmuvV] destination-directory < name-list\n", stderr);
15784b88c807SRodney W. Grimes 	exit(1);
15794b88c807SRodney W. Grimes }
1580