xref: /openbsd/bin/pax/options.c (revision 8758bb59)
1*8758bb59Smillert /*	$OpenBSD: options.c,v 1.115 2024/05/10 20:28:31 millert Exp $	*/
28ab05b7eSderaadt /*	$NetBSD: options.c,v 1.6 1996/03/26 23:54:18 mrg Exp $	*/
3df930be7Sderaadt 
4df930be7Sderaadt /*-
5df930be7Sderaadt  * Copyright (c) 1992 Keith Muller.
6df930be7Sderaadt  * Copyright (c) 1992, 1993
7df930be7Sderaadt  *	The Regents of the University of California.  All rights reserved.
8df930be7Sderaadt  *
9df930be7Sderaadt  * This code is derived from software contributed to Berkeley by
10df930be7Sderaadt  * Keith Muller of the University of California, San Diego.
11df930be7Sderaadt  *
12df930be7Sderaadt  * Redistribution and use in source and binary forms, with or without
13df930be7Sderaadt  * modification, are permitted provided that the following conditions
14df930be7Sderaadt  * are met:
15df930be7Sderaadt  * 1. Redistributions of source code must retain the above copyright
16df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer.
17df930be7Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
18df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer in the
19df930be7Sderaadt  *    documentation and/or other materials provided with the distribution.
2029295d1cSmillert  * 3. Neither the name of the University nor the names of its contributors
21df930be7Sderaadt  *    may be used to endorse or promote products derived from this software
22df930be7Sderaadt  *    without specific prior written permission.
23df930be7Sderaadt  *
24df930be7Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25df930be7Sderaadt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26df930be7Sderaadt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27df930be7Sderaadt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28df930be7Sderaadt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29df930be7Sderaadt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30df930be7Sderaadt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31df930be7Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32df930be7Sderaadt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33df930be7Sderaadt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34df930be7Sderaadt  * SUCH DAMAGE.
35df930be7Sderaadt  */
36df930be7Sderaadt 
37df930be7Sderaadt #include <sys/types.h>
38df930be7Sderaadt #include <sys/stat.h>
393c2af966Sdownsj #include <errno.h>
40df930be7Sderaadt #include <limits.h>
41ea101a60Smillert #include <paths.h>
42bcbfc94fSguenther #include <stdio.h>
43bcbfc94fSguenther #include <stdlib.h>
44bcbfc94fSguenther #include <string.h>
45bcbfc94fSguenther #include <unistd.h>
46bcbfc94fSguenther 
47df930be7Sderaadt #include "pax.h"
48df930be7Sderaadt #include "cpio.h"
49df930be7Sderaadt #include "tar.h"
50df930be7Sderaadt #include "extern.h"
51df930be7Sderaadt 
52c01bd743Sespie static int bad_opt(void);
53c01bd743Sespie static int opt_add(const char *);
54df930be7Sderaadt /*
55bcbfc94fSguenther  * argv[0] names. Used for tar and cpio emulation
56bcbfc94fSguenther  */
57bcbfc94fSguenther 
58bcbfc94fSguenther #define NM_TAR  "tar"
59bcbfc94fSguenther #define NM_CPIO "cpio"
60bcbfc94fSguenther #define NM_PAX  "pax"
61bcbfc94fSguenther 
62bcbfc94fSguenther /*
63bcbfc94fSguenther  * Constants used to specify the legal sets of flags in pax. For each major
64bcbfc94fSguenther  * operation mode of pax, a set of illegal flags is defined. If any one of
65bcbfc94fSguenther  * those illegal flags are found set, we scream and exit
66bcbfc94fSguenther  */
67bcbfc94fSguenther 
68bcbfc94fSguenther /*
69bcbfc94fSguenther  * flags (one for each option).
70bcbfc94fSguenther  */
71bcbfc94fSguenther #define	AF	0x00000001
72bcbfc94fSguenther #define	BF	0x00000002
73bcbfc94fSguenther #define	CF	0x00000004
74bcbfc94fSguenther #define	DF	0x00000008
75bcbfc94fSguenther #define	FF	0x00000010
76bcbfc94fSguenther #define	IF	0x00000020
77bcbfc94fSguenther #define	KF	0x00000040
78bcbfc94fSguenther #define	LF	0x00000080
79bcbfc94fSguenther #define	NF	0x00000100
80bcbfc94fSguenther #define	OF	0x00000200
81bcbfc94fSguenther #define	PF	0x00000400
82bcbfc94fSguenther #define	RF	0x00000800
83bcbfc94fSguenther #define	SF	0x00001000
84bcbfc94fSguenther #define	TF	0x00002000
85bcbfc94fSguenther #define	UF	0x00004000
86bcbfc94fSguenther #define	VF	0x00008000
87bcbfc94fSguenther #define	WF	0x00010000
88bcbfc94fSguenther #define	XF	0x00020000
89bcbfc94fSguenther #define	CBF	0x00040000	/* nonstandard extension */
90bcbfc94fSguenther #define	CDF	0x00080000	/* nonstandard extension */
91bcbfc94fSguenther #define	CEF	0x00100000	/* nonstandard extension */
92bcbfc94fSguenther #define	CGF	0x00200000	/* nonstandard extension */
93bcbfc94fSguenther #define	CHF	0x00400000	/* nonstandard extension */
94bcbfc94fSguenther #define	CLF	0x00800000	/* nonstandard extension */
95bcbfc94fSguenther #define	CPF	0x01000000	/* nonstandard extension */
96bcbfc94fSguenther #define	CTF	0x02000000	/* nonstandard extension */
97bcbfc94fSguenther #define	CUF	0x04000000	/* nonstandard extension */
98bcbfc94fSguenther #define	CXF	0x08000000
99bcbfc94fSguenther #define	CYF	0x10000000	/* nonstandard extension */
100bcbfc94fSguenther #define	CZF	0x20000000	/* nonstandard extension */
101bcbfc94fSguenther #define	C0F	0x40000000	/* nonstandard extension */
102bcbfc94fSguenther 
103bcbfc94fSguenther /*
104bcbfc94fSguenther  * ascii string indexed by bit position above (alter the above and you must
105bcbfc94fSguenther  * alter this string) used to tell the user what flags caused us to complain
106bcbfc94fSguenther  */
107bcbfc94fSguenther #define FLGCH	"abcdfiklnoprstuvwxBDEGHLPTUXYZ0"
108bcbfc94fSguenther 
109bcbfc94fSguenther /*
110bcbfc94fSguenther  * legal pax operation bit patterns
111bcbfc94fSguenther  */
112bcbfc94fSguenther 
113bcbfc94fSguenther #define ISLIST(x)	(((x) & (RF|WF)) == 0)
114bcbfc94fSguenther #define	ISEXTRACT(x)	(((x) & (RF|WF)) == RF)
115bcbfc94fSguenther #define ISARCHIVE(x)	(((x) & (AF|RF|WF)) == WF)
116bcbfc94fSguenther #define ISAPPND(x)	(((x) & (AF|RF|WF)) == (AF|WF))
117bcbfc94fSguenther #define	ISCOPY(x)	(((x) & (RF|WF)) == (RF|WF))
118bcbfc94fSguenther #define	ISWRITE(x)	(((x) & (RF|WF)) == WF)
119bcbfc94fSguenther 
120bcbfc94fSguenther /*
121bcbfc94fSguenther  * Illegal option flag subsets based on pax operation
122bcbfc94fSguenther  */
123bcbfc94fSguenther 
124bcbfc94fSguenther #define	BDEXTR	(AF|BF|LF|TF|WF|XF|CBF|CHF|CLF|CPF|CXF)
125bcbfc94fSguenther #define	BDARCH	(CF|KF|LF|NF|PF|RF|CDF|CEF|CYF|CZF)
126bcbfc94fSguenther #define	BDCOPY	(AF|BF|FF|OF|XF|CBF|CEF)
127bcbfc94fSguenther #define	BDLIST (AF|BF|IF|KF|LF|OF|PF|RF|TF|UF|WF|XF|CBF|CDF|CHF|CLF|CPF|CXF|CYF|CZF)
128bcbfc94fSguenther 
129bcbfc94fSguenther 
130bcbfc94fSguenther /*
131df930be7Sderaadt  * Routines which handle command line options
132df930be7Sderaadt  */
133df930be7Sderaadt 
134df930be7Sderaadt static char flgch[] = FLGCH;	/* list of all possible flags */
135df930be7Sderaadt static OPLIST *ophead = NULL;	/* head for format specific options -x */
136df930be7Sderaadt static OPLIST *optail = NULL;	/* option tail */
137df930be7Sderaadt 
138c72b5b24Smillert static int no_op(void);
139c72b5b24Smillert static void printflg(unsigned int);
140c72b5b24Smillert static off_t str_offt(char *);
141f9bbbf45Sfgsch static char *get_line(FILE *fp);
142be87792eSmillert static void pax_options(int, char **);
143c72b5b24Smillert static void pax_usage(void);
144be87792eSmillert static void tar_options(int, char **);
145c72b5b24Smillert static void tar_usage(void);
1469a195818Skrw #ifndef NOCPIO
147be87792eSmillert static void cpio_options(int, char **);
148c72b5b24Smillert static void cpio_usage(void);
1499a195818Skrw #endif
150df930be7Sderaadt 
151a48f739dSguenther static int compress_id(char *_blk, int _size);
152a48f739dSguenther static int gzip_id(char *_blk, int _size);
153a48f739dSguenther static int bzip2_id(char *_blk, int _size);
154a48f739dSguenther static int xz_id(char *_blk, int _size);
155a48f739dSguenther 
156c7117be0Sderaadt #define GZIP_CMD	"gzip"		/* command to run as gzip */
157c7117be0Sderaadt #define COMPRESS_CMD	"compress"	/* command to run as compress */
158a914b46dSpvalchev #define BZIP2_CMD	"bzip2"		/* command to run as bzip2 */
159c7117be0Sderaadt 
160df930be7Sderaadt /*
161e1fb501dShalex  *	Format specific routine table
162df930be7Sderaadt  *	(see pax.h for description of each function)
163df930be7Sderaadt  *
164df930be7Sderaadt  *	name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
165df930be7Sderaadt  *	read, end_read, st_write, write, end_write, trail,
166df930be7Sderaadt  *	rd_data, wr_data, options
167df930be7Sderaadt  */
168df930be7Sderaadt 
169df930be7Sderaadt FSUB fsub[] = {
170f3e2c552Sderaadt #ifdef NOCPIO
171f3e2c552Sderaadt /* 0: OLD BINARY CPIO */
172f3e2c552Sderaadt 	{ },
173f3e2c552Sderaadt /* 1: OLD OCTAL CHARACTER CPIO */
174f3e2c552Sderaadt 	{ },
175f3e2c552Sderaadt /* 2: SVR4 HEX CPIO */
176f3e2c552Sderaadt 	{ },
177f3e2c552Sderaadt /* 3: SVR4 HEX CPIO WITH CRC */
178f3e2c552Sderaadt 	{ },
179f3e2c552Sderaadt #else
180df930be7Sderaadt /* 0: OLD BINARY CPIO */
18142cf9836Stholo 	{"bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
182df930be7Sderaadt 	bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, cpio_trail,
1835647df80Sespie 	bad_opt},
184df930be7Sderaadt 
185df930be7Sderaadt /* 1: OLD OCTAL CHARACTER CPIO */
18642cf9836Stholo 	{"cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
187df930be7Sderaadt 	cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, cpio_trail,
1885647df80Sespie 	bad_opt},
189df930be7Sderaadt 
190df930be7Sderaadt /* 2: SVR4 HEX CPIO */
19142cf9836Stholo 	{"sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd,
192df930be7Sderaadt 	vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, cpio_trail,
1935647df80Sespie 	bad_opt},
194df930be7Sderaadt 
195df930be7Sderaadt /* 3: SVR4 HEX CPIO WITH CRC */
19642cf9836Stholo 	{"sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
197df930be7Sderaadt 	vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, cpio_trail,
1985647df80Sespie 	bad_opt},
199f3e2c552Sderaadt #endif
200df930be7Sderaadt /* 4: OLD TAR */
20142cf9836Stholo 	{"tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
202df930be7Sderaadt 	tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail,
2035647df80Sespie 	tar_opt},
204df930be7Sderaadt 
205df930be7Sderaadt /* 5: POSIX USTAR */
206f84583feSmillert 	{"ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, no_op,
2074c043852Sguenther 	ustar_rd, tar_endrd, no_op, ustar_wr, tar_endwr, tar_trail,
2085647df80Sespie 	tar_opt},
209a48f739dSguenther 
210a48f739dSguenther #ifdef SMALL
211a48f739dSguenther /* 6: compress, to detect failure to use -Z */
212a48f739dSguenther 	{ },
213a48f739dSguenther /* 7: xz, to detect failure to decompress it */
214a48f739dSguenther 	{ },
215a48f739dSguenther /* 8: bzip2, to detect failure to use -j */
216a48f739dSguenther 	{ },
217a48f739dSguenther /* 9: gzip, to detect failure to use -z */
218a48f739dSguenther 	{ },
219013e174aSjca /* 10: POSIX PAX */
220013e174aSjca 	{ },
221a48f739dSguenther #else
222a48f739dSguenther /* 6: compress, to detect failure to use -Z */
223a48f739dSguenther 	{NULL, 0, 4, 0, 0, 0, 0, compress_id},
224a48f739dSguenther /* 7: xz, to detect failure to decompress it */
225a48f739dSguenther 	{NULL, 0, 4, 0, 0, 0, 0, xz_id},
226a48f739dSguenther /* 8: bzip2, to detect failure to use -j */
227a48f739dSguenther 	{NULL, 0, 4, 0, 0, 0, 0, bzip2_id},
228a48f739dSguenther /* 9: gzip, to detect failure to use -z */
229a48f739dSguenther 	{NULL, 0, 4, 0, 0, 0, 0, gzip_id},
230013e174aSjca /* 10: POSIX PAX */
231ce1e26fbSjca 	{"pax", 5120, BLKMULT, 0, 1, BLKMULT, 0, pax_id, no_op,
232013e174aSjca 	ustar_rd, tar_endrd, no_op, pax_wr, tar_endwr, tar_trail,
2338df76133Sjca 	pax_opt},
234a48f739dSguenther #endif
235df930be7Sderaadt };
23619e7eef2Stholo #define	F_OCPIO	0	/* format when called as cpio -6 */
23719e7eef2Stholo #define	F_ACPIO	1	/* format when called as cpio -c */
23819e7eef2Stholo #define	F_CPIO	3	/* format when called as cpio */
23998fcb8acSmillert #define F_OTAR	4	/* format when called as tar -o */
2409dcb0c6dSjca #ifdef SMALL
241e313d3ebSjca # define F_TAR	5	/* default write format when called as tar: ustar */
24285d4a8a2Scaspar # define DEFLT	5	/* default write format when called as pax: ustar */
2439dcb0c6dSjca #else
2444ce91cbeSjca # define F_TAR	10	/* default write format when called as tar: pax */
24585d4a8a2Scaspar # define DEFLT	10	/* default write format when called as pax: pax */
2469dcb0c6dSjca #endif
247df930be7Sderaadt 
248df930be7Sderaadt /*
249df930be7Sderaadt  * ford is the archive search order used by get_arc() to determine what kind
250df930be7Sderaadt  * of archive we are dealing with. This helps to properly id archive formats
251df930be7Sderaadt  * some formats may be subsets of others....
252df930be7Sderaadt  */
253ce1e26fbSjca int ford[] = {10, 5, 4, 9, 8, 7, 6, 3, 2, 1, 0, -1};
254df930be7Sderaadt 
255df930be7Sderaadt /*
256da5fb823Sguenther  * Do we have -C anywhere and what is it?
257a7a4d07aSotto  */
258a7a4d07aSotto int havechd = 0;
259da5fb823Sguenther char *chdname = NULL;
260a7a4d07aSotto 
261a7a4d07aSotto /*
262df930be7Sderaadt  * options()
263df930be7Sderaadt  *	figure out if we are pax, tar or cpio. Call the appropriate options
264df930be7Sderaadt  *	parser
265df930be7Sderaadt  */
266df930be7Sderaadt 
267df930be7Sderaadt void
options(int argc,char ** argv)268be87792eSmillert options(int argc, char **argv)
269df930be7Sderaadt {
270dab586c4Stobias 	extern char *__progname;
271df930be7Sderaadt 
272df930be7Sderaadt 	/*
273df930be7Sderaadt 	 * Are we acting like pax, tar or cpio (based on argv[0])
274df930be7Sderaadt 	 */
275dab586c4Stobias 	argv0 = __progname;
276df930be7Sderaadt 
2776118013aSderaadt 	if (strcmp(NM_TAR, argv0) == 0) {
2783228b364Sguenther 		op_mode = OP_TAR;
2796118013aSderaadt 		tar_options(argc, argv);
280f3e2c552Sderaadt #ifndef NOCPIO
281*8758bb59Smillert 	} else if (strcmp(NM_CPIO, argv0) == 0) {
2823228b364Sguenther 		op_mode = OP_CPIO;
2836118013aSderaadt 		cpio_options(argc, argv);
284f3e2c552Sderaadt #endif /* !NOCPIO */
285*8758bb59Smillert 	} else {
286df930be7Sderaadt 		argv0 = NM_PAX;
2873228b364Sguenther 		op_mode = OP_PAX;
2886118013aSderaadt 		pax_options(argc, argv);
289df930be7Sderaadt 	}
290df930be7Sderaadt 
291*8758bb59Smillert 	/* Line-buffer the file list output as needed. */
292*8758bb59Smillert 	if (listf != stderr)
293*8758bb59Smillert 		setvbuf(listf, NULL, _IOLBF, 0);
294*8758bb59Smillert }
295*8758bb59Smillert 
296df930be7Sderaadt /*
297df930be7Sderaadt  * pax_options()
298df930be7Sderaadt  *	look at the user specified flags. set globals as required and check if
299df930be7Sderaadt  *	the user specified a legal set of flags. If not, complain and exit
300df930be7Sderaadt  */
301df930be7Sderaadt 
302df930be7Sderaadt static void
pax_options(int argc,char ** argv)303be87792eSmillert pax_options(int argc, char **argv)
304df930be7Sderaadt {
305be87792eSmillert 	int c;
306e1fb501dShalex 	unsigned i;
307df930be7Sderaadt 	unsigned int flg = 0;
308df930be7Sderaadt 	unsigned int bflg = 0;
309a47b6461Sderaadt 	const char *errstr;
310be87792eSmillert 	char *pt;
311df930be7Sderaadt 
312df930be7Sderaadt 	/*
313df930be7Sderaadt 	 * process option flags
314df930be7Sderaadt 	 */
315a914b46dSpvalchev 	while ((c=getopt(argc,argv,"ab:cdf:ijklno:p:rs:tuvwx:zB:DE:G:HLOPT:U:XYZ0"))
3168781354eSaaron 	    != -1) {
317df930be7Sderaadt 		switch (c) {
318df930be7Sderaadt 		case 'a':
319df930be7Sderaadt 			/*
320df930be7Sderaadt 			 * append
321df930be7Sderaadt 			 */
322df930be7Sderaadt 			flg |= AF;
323df930be7Sderaadt 			break;
324df930be7Sderaadt 		case 'b':
325df930be7Sderaadt 			/*
326df930be7Sderaadt 			 * specify blocksize
327df930be7Sderaadt 			 */
328df930be7Sderaadt 			flg |= BF;
329df930be7Sderaadt 			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
33042cf9836Stholo 				paxwarn(1, "Invalid block size %s", optarg);
331df930be7Sderaadt 				pax_usage();
332df930be7Sderaadt 			}
333df930be7Sderaadt 			break;
334df930be7Sderaadt 		case 'c':
335df930be7Sderaadt 			/*
336df930be7Sderaadt 			 * inverse match on patterns
337df930be7Sderaadt 			 */
338df930be7Sderaadt 			cflag = 1;
339df930be7Sderaadt 			flg |= CF;
340df930be7Sderaadt 			break;
341df930be7Sderaadt 		case 'd':
342df930be7Sderaadt 			/*
343df930be7Sderaadt 			 * match only dir on extract, not the subtree at dir
344df930be7Sderaadt 			 */
345df930be7Sderaadt 			dflag = 1;
346df930be7Sderaadt 			flg |= DF;
347df930be7Sderaadt 			break;
348df930be7Sderaadt 		case 'f':
349df930be7Sderaadt 			/*
350df930be7Sderaadt 			 * filename where the archive is stored
351df930be7Sderaadt 			 */
352df930be7Sderaadt 			arcname = optarg;
353df930be7Sderaadt 			flg |= FF;
354df930be7Sderaadt 			break;
355df930be7Sderaadt 		case 'i':
356df930be7Sderaadt 			/*
357df930be7Sderaadt 			 * interactive file rename
358df930be7Sderaadt 			 */
359df930be7Sderaadt 			iflag = 1;
360df930be7Sderaadt 			flg |= IF;
361df930be7Sderaadt 			break;
362a914b46dSpvalchev 		case 'j':
363a914b46dSpvalchev 			/*
364a914b46dSpvalchev 			 * use bzip2.  Non standard option.
365a914b46dSpvalchev 			 */
366a914b46dSpvalchev 			gzip_program = BZIP2_CMD;
367a914b46dSpvalchev 			break;
368df930be7Sderaadt 		case 'k':
369df930be7Sderaadt 			/*
370df930be7Sderaadt 			 * do not clobber files that exist
371df930be7Sderaadt 			 */
372df930be7Sderaadt 			kflag = 1;
373df930be7Sderaadt 			flg |= KF;
374df930be7Sderaadt 			break;
375df930be7Sderaadt 		case 'l':
376df930be7Sderaadt 			/*
377df930be7Sderaadt 			 * try to link src to dest with copy (-rw)
378df930be7Sderaadt 			 */
379df930be7Sderaadt 			lflag = 1;
380df930be7Sderaadt 			flg |= LF;
381df930be7Sderaadt 			break;
382df930be7Sderaadt 		case 'n':
383df930be7Sderaadt 			/*
384df930be7Sderaadt 			 * select first match for a pattern only
385df930be7Sderaadt 			 */
386df930be7Sderaadt 			nflag = 1;
387df930be7Sderaadt 			flg |= NF;
388df930be7Sderaadt 			break;
389df930be7Sderaadt 		case 'o':
390df930be7Sderaadt 			/*
391df930be7Sderaadt 			 * pass format specific options
392df930be7Sderaadt 			 */
393df930be7Sderaadt 			flg |= OF;
394df930be7Sderaadt 			if (opt_add(optarg) < 0)
395df930be7Sderaadt 				pax_usage();
396df930be7Sderaadt 			break;
397df930be7Sderaadt 		case 'p':
398df930be7Sderaadt 			/*
399df930be7Sderaadt 			 * specify file characteristic options
400df930be7Sderaadt 			 */
401df930be7Sderaadt 			for (pt = optarg; *pt != '\0'; ++pt) {
402df930be7Sderaadt 				switch (*pt) {
403df930be7Sderaadt 				case 'a':
404df930be7Sderaadt 					/*
405df930be7Sderaadt 					 * do not preserve access time
406df930be7Sderaadt 					 */
407df930be7Sderaadt 					patime = 0;
408df930be7Sderaadt 					break;
409df930be7Sderaadt 				case 'e':
410df930be7Sderaadt 					/*
411df930be7Sderaadt 					 * preserve user id, group id, file
412df930be7Sderaadt 					 * mode, access/modification times
413df930be7Sderaadt 					 */
414df930be7Sderaadt 					pids = 1;
415df930be7Sderaadt 					pmode = 1;
416df930be7Sderaadt 					patime = 1;
417df930be7Sderaadt 					pmtime = 1;
418df930be7Sderaadt 					break;
419df930be7Sderaadt 				case 'm':
420df930be7Sderaadt 					/*
421df930be7Sderaadt 					 * do not preserve modification time
422df930be7Sderaadt 					 */
423df930be7Sderaadt 					pmtime = 0;
424df930be7Sderaadt 					break;
425df930be7Sderaadt 				case 'o':
426df930be7Sderaadt 					/*
427df930be7Sderaadt 					 * preserve uid/gid
428df930be7Sderaadt 					 */
429df930be7Sderaadt 					pids = 1;
430df930be7Sderaadt 					break;
431df930be7Sderaadt 				case 'p':
432df930be7Sderaadt 					/*
4334eb0b000Smillert 					 * preserve file mode bits
434df930be7Sderaadt 					 */
435df930be7Sderaadt 					pmode = 1;
436df930be7Sderaadt 					break;
437df930be7Sderaadt 				default:
43842cf9836Stholo 					paxwarn(1, "Invalid -p string: %c", *pt);
439df930be7Sderaadt 					pax_usage();
440df930be7Sderaadt 					break;
441df930be7Sderaadt 				}
442df930be7Sderaadt 			}
443df930be7Sderaadt 			flg |= PF;
444df930be7Sderaadt 			break;
445df930be7Sderaadt 		case 'r':
446df930be7Sderaadt 			/*
447df930be7Sderaadt 			 * read the archive
448df930be7Sderaadt 			 */
449df930be7Sderaadt 			flg |= RF;
450df930be7Sderaadt 			break;
451df930be7Sderaadt 		case 's':
452df930be7Sderaadt 			/*
453df930be7Sderaadt 			 * file name substitution name pattern
454df930be7Sderaadt 			 */
455df930be7Sderaadt 			if (rep_add(optarg) < 0) {
456df930be7Sderaadt 				pax_usage();
457df930be7Sderaadt 				break;
458df930be7Sderaadt 			}
459df930be7Sderaadt 			flg |= SF;
460df930be7Sderaadt 			break;
461df930be7Sderaadt 		case 't':
462df930be7Sderaadt 			/*
463df930be7Sderaadt 			 * preserve access time on filesystem nodes we read
464df930be7Sderaadt 			 */
465df930be7Sderaadt 			tflag = 1;
466df930be7Sderaadt 			flg |= TF;
467df930be7Sderaadt 			break;
468df930be7Sderaadt 		case 'u':
469df930be7Sderaadt 			/*
470df930be7Sderaadt 			 * ignore those older files
471df930be7Sderaadt 			 */
472df930be7Sderaadt 			uflag = 1;
473df930be7Sderaadt 			flg |= UF;
474df930be7Sderaadt 			break;
475df930be7Sderaadt 		case 'v':
476df930be7Sderaadt 			/*
477df930be7Sderaadt 			 * verbose operation mode
478df930be7Sderaadt 			 */
479df930be7Sderaadt 			vflag = 1;
480df930be7Sderaadt 			flg |= VF;
481df930be7Sderaadt 			break;
482df930be7Sderaadt 		case 'w':
483df930be7Sderaadt 			/*
484df930be7Sderaadt 			 * write an archive
485df930be7Sderaadt 			 */
486df930be7Sderaadt 			flg |= WF;
487df930be7Sderaadt 			break;
488df930be7Sderaadt 		case 'x':
489df930be7Sderaadt 			/*
490df930be7Sderaadt 			 * specify an archive format on write
491df930be7Sderaadt 			 */
492e1fb501dShalex 			for (i = 0; i < sizeof(fsub)/sizeof(FSUB); ++i)
493e1fb501dShalex 				if (fsub[i].name != NULL &&
494e1fb501dShalex 				    strcmp(fsub[i].name, optarg) == 0)
495e1fb501dShalex 					break;
496e1fb501dShalex 			if (i < sizeof(fsub)/sizeof(FSUB)) {
497e43eba20Sguenther 				frmt = &fsub[i];
498df930be7Sderaadt 				flg |= XF;
499df930be7Sderaadt 				break;
500df930be7Sderaadt 			}
50142cf9836Stholo 			paxwarn(1, "Unknown -x format: %s", optarg);
502df930be7Sderaadt 			(void)fputs("pax: Known -x formats are:", stderr);
503df930be7Sderaadt 			for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
504e1fb501dShalex 				if (fsub[i].name != NULL)
505e1fb501dShalex 					(void)fprintf(stderr, " %s",
506e1fb501dShalex 					    fsub[i].name);
507df930be7Sderaadt 			(void)fputs("\n\n", stderr);
508df930be7Sderaadt 			pax_usage();
509df930be7Sderaadt 			break;
5108ab05b7eSderaadt 		case 'z':
5118ab05b7eSderaadt 			/*
5128ab05b7eSderaadt 			 * use gzip.  Non standard option.
5138ab05b7eSderaadt 			 */
514c7117be0Sderaadt 			gzip_program = GZIP_CMD;
5158ab05b7eSderaadt 			break;
516df930be7Sderaadt 		case 'B':
517df930be7Sderaadt 			/*
518df930be7Sderaadt 			 * non-standard option on number of bytes written on a
519df930be7Sderaadt 			 * single archive volume.
520df930be7Sderaadt 			 */
521df930be7Sderaadt 			if ((wrlimit = str_offt(optarg)) <= 0) {
52242cf9836Stholo 				paxwarn(1, "Invalid write limit %s", optarg);
523df930be7Sderaadt 				pax_usage();
524df930be7Sderaadt 			}
525df930be7Sderaadt 			if (wrlimit % BLKMULT) {
52642cf9836Stholo 				paxwarn(1, "Write limit is not a %d byte multiple",
527df930be7Sderaadt 				    BLKMULT);
528df930be7Sderaadt 				pax_usage();
529df930be7Sderaadt 			}
530df930be7Sderaadt 			flg |= CBF;
531df930be7Sderaadt 			break;
532df930be7Sderaadt 		case 'D':
533df930be7Sderaadt 			/*
534df930be7Sderaadt 			 * On extraction check file inode change time before the
535df930be7Sderaadt 			 * modification of the file name. Non standard option.
536df930be7Sderaadt 			 */
537df930be7Sderaadt 			Dflag = 1;
538df930be7Sderaadt 			flg |= CDF;
539df930be7Sderaadt 			break;
540df930be7Sderaadt 		case 'E':
541df930be7Sderaadt 			/*
542df930be7Sderaadt 			 * non-standard limit on read faults
543df930be7Sderaadt 			 * 0 indicates stop after first error, values
54412086188Sguenther 			 * indicate a limit
545df930be7Sderaadt 			 */
546df930be7Sderaadt 			flg |= CEF;
547a47b6461Sderaadt 			maxflt = strtonum(optarg, 0, INT_MAX, &errstr);
548a47b6461Sderaadt 			if (errstr) {
549a47b6461Sderaadt 				paxwarn(1, "Error count value: %s", errstr);
550df930be7Sderaadt 				pax_usage();
551df930be7Sderaadt 			}
552df930be7Sderaadt 			break;
553df930be7Sderaadt 		case 'G':
554df930be7Sderaadt 			/*
555df930be7Sderaadt 			 * non-standard option for selecting files within an
556df930be7Sderaadt 			 * archive by group (gid or name)
557df930be7Sderaadt 			 */
558df930be7Sderaadt 			if (grp_add(optarg) < 0) {
559df930be7Sderaadt 				pax_usage();
560df930be7Sderaadt 				break;
561df930be7Sderaadt 			}
562df930be7Sderaadt 			flg |= CGF;
563df930be7Sderaadt 			break;
564df930be7Sderaadt 		case 'H':
565df930be7Sderaadt 			/*
566df930be7Sderaadt 			 * follow command line symlinks only
567df930be7Sderaadt 			 */
568df930be7Sderaadt 			Hflag = 1;
569df930be7Sderaadt 			flg |= CHF;
570df930be7Sderaadt 			break;
571df930be7Sderaadt 		case 'L':
572df930be7Sderaadt 			/*
573df930be7Sderaadt 			 * follow symlinks
574df930be7Sderaadt 			 */
575df930be7Sderaadt 			Lflag = 1;
576df930be7Sderaadt 			flg |= CLF;
577df930be7Sderaadt 			break;
578da60b202Smillert 		case 'O':
579da60b202Smillert 			/*
580da60b202Smillert 			 * Force one volume.  Non standard option.
581da60b202Smillert 			 */
582da60b202Smillert 			force_one_volume = 1;
583da60b202Smillert 			break;
584df930be7Sderaadt 		case 'P':
585df930be7Sderaadt 			/*
586df930be7Sderaadt 			 * do NOT follow symlinks (default)
587df930be7Sderaadt 			 */
588df930be7Sderaadt 			Lflag = 0;
589df930be7Sderaadt 			flg |= CPF;
590df930be7Sderaadt 			break;
591df930be7Sderaadt 		case 'T':
592df930be7Sderaadt 			/*
593df930be7Sderaadt 			 * non-standard option for selecting files within an
594df930be7Sderaadt 			 * archive by modification time range (lower,upper)
595df930be7Sderaadt 			 */
596df930be7Sderaadt 			if (trng_add(optarg) < 0) {
597df930be7Sderaadt 				pax_usage();
598df930be7Sderaadt 				break;
599df930be7Sderaadt 			}
600df930be7Sderaadt 			flg |= CTF;
601df930be7Sderaadt 			break;
602df930be7Sderaadt 		case 'U':
603df930be7Sderaadt 			/*
604df930be7Sderaadt 			 * non-standard option for selecting files within an
605df930be7Sderaadt 			 * archive by user (uid or name)
606df930be7Sderaadt 			 */
607df930be7Sderaadt 			if (usr_add(optarg) < 0) {
608df930be7Sderaadt 				pax_usage();
609df930be7Sderaadt 				break;
610df930be7Sderaadt 			}
611df930be7Sderaadt 			flg |= CUF;
612df930be7Sderaadt 			break;
613df930be7Sderaadt 		case 'X':
614df930be7Sderaadt 			/*
615df930be7Sderaadt 			 * do not pass over mount points in the file system
616df930be7Sderaadt 			 */
617df930be7Sderaadt 			Xflag = 1;
618df930be7Sderaadt 			flg |= CXF;
619df930be7Sderaadt 			break;
620df930be7Sderaadt 		case 'Y':
621df930be7Sderaadt 			/*
622df930be7Sderaadt 			 * On extraction check file inode change time after the
623df930be7Sderaadt 			 * modification of the file name. Non standard option.
624df930be7Sderaadt 			 */
625df930be7Sderaadt 			Yflag = 1;
626df930be7Sderaadt 			flg |= CYF;
627df930be7Sderaadt 			break;
628df930be7Sderaadt 		case 'Z':
629df930be7Sderaadt 			/*
630df930be7Sderaadt 			 * On extraction check modification time after the
631df930be7Sderaadt 			 * modification of the file name. Non standard option.
632df930be7Sderaadt 			 */
633df930be7Sderaadt 			Zflag = 1;
634df930be7Sderaadt 			flg |= CZF;
635df930be7Sderaadt 			break;
6369cd57097Smillert 		case '0':
6379cd57097Smillert 			/*
6389cd57097Smillert 			 * Use \0 as pathname terminator.
6399cd57097Smillert 			 * (For use with the -print0 option of find(1).)
6409cd57097Smillert 			 */
6419cd57097Smillert 			zeroflag = 1;
6429cd57097Smillert 			flg |= C0F;
6439cd57097Smillert 			break;
644df930be7Sderaadt 		default:
645df930be7Sderaadt 			pax_usage();
646df930be7Sderaadt 			break;
647df930be7Sderaadt 		}
648df930be7Sderaadt 	}
649df930be7Sderaadt 
650df930be7Sderaadt 	/*
651df930be7Sderaadt 	 * figure out the operation mode of pax read,write,extract,copy,append
652df930be7Sderaadt 	 * or list. check that we have not been given a bogus set of flags
653df930be7Sderaadt 	 * for the operation mode.
654df930be7Sderaadt 	 */
655df930be7Sderaadt 	if (ISLIST(flg)) {
656df930be7Sderaadt 		act = LIST;
65710854502Smillert 		listf = stdout;
658df930be7Sderaadt 		bflg = flg & BDLIST;
659df930be7Sderaadt 	} else if (ISEXTRACT(flg)) {
660df930be7Sderaadt 		act = EXTRACT;
661df930be7Sderaadt 		bflg = flg & BDEXTR;
662df930be7Sderaadt 	} else if (ISARCHIVE(flg)) {
663df930be7Sderaadt 		act = ARCHIVE;
664df930be7Sderaadt 		bflg = flg & BDARCH;
665df930be7Sderaadt 	} else if (ISAPPND(flg)) {
666df930be7Sderaadt 		act = APPND;
667df930be7Sderaadt 		bflg = flg & BDARCH;
668df930be7Sderaadt 	} else if (ISCOPY(flg)) {
669df930be7Sderaadt 		act = COPY;
670df930be7Sderaadt 		bflg = flg & BDCOPY;
671df930be7Sderaadt 	} else
672df930be7Sderaadt 		pax_usage();
673df930be7Sderaadt 	if (bflg) {
674df930be7Sderaadt 		printflg(flg);
675df930be7Sderaadt 		pax_usage();
676df930be7Sderaadt 	}
677df930be7Sderaadt 
678df930be7Sderaadt 	/*
679df930be7Sderaadt 	 * if we are writing (ARCHIVE) we use the default format if the user
680df930be7Sderaadt 	 * did not specify a format. when we write during an APPEND, we will
681df930be7Sderaadt 	 * adopt the format of the existing archive if none was supplied.
682df930be7Sderaadt 	 */
683df930be7Sderaadt 	if (!(flg & XF) && (act == ARCHIVE))
684df930be7Sderaadt 		frmt = &(fsub[DEFLT]);
685df930be7Sderaadt 
686df930be7Sderaadt 	/*
687df930be7Sderaadt 	 * process the args as they are interpreted by the operation mode
688df930be7Sderaadt 	 */
689df930be7Sderaadt 	switch (act) {
690df930be7Sderaadt 	case LIST:
691df930be7Sderaadt 	case EXTRACT:
692df930be7Sderaadt 		for (; optind < argc; optind++)
6933c2af966Sdownsj 			if (pat_add(argv[optind], NULL) < 0)
694df930be7Sderaadt 				pax_usage();
695df930be7Sderaadt 		break;
696df930be7Sderaadt 	case COPY:
697df930be7Sderaadt 		if (optind >= argc) {
69842cf9836Stholo 			paxwarn(0, "Destination directory was not supplied");
699df930be7Sderaadt 			pax_usage();
700df930be7Sderaadt 		}
701df930be7Sderaadt 		--argc;
702df930be7Sderaadt 		dirptr = argv[argc];
703df930be7Sderaadt 		/* FALL THROUGH */
704df930be7Sderaadt 	case ARCHIVE:
705df930be7Sderaadt 	case APPND:
706df930be7Sderaadt 		for (; optind < argc; optind++)
7073c2af966Sdownsj 			if (ftree_add(argv[optind], 0) < 0)
708df930be7Sderaadt 				pax_usage();
709df930be7Sderaadt 		/*
710df930be7Sderaadt 		 * no read errors allowed on updates/append operation!
711df930be7Sderaadt 		 */
712df930be7Sderaadt 		maxflt = 0;
713df930be7Sderaadt 		break;
714df930be7Sderaadt 	}
715df930be7Sderaadt }
716df930be7Sderaadt 
717df930be7Sderaadt 
718df930be7Sderaadt /*
719df930be7Sderaadt  * tar_options()
720df930be7Sderaadt  *	look at the user specified flags. set globals as required and check if
721df930be7Sderaadt  *	the user specified a legal set of flags. If not, complain and exit
722df930be7Sderaadt  */
723df930be7Sderaadt 
724df930be7Sderaadt static void
tar_options(int argc,char ** argv)725be87792eSmillert tar_options(int argc, char **argv)
726df930be7Sderaadt {
727be87792eSmillert 	int c;
72829e8fb76Smillert 	int nincfiles = 0;
72929e8fb76Smillert 	int incfiles_max = 0;
730f30fa552Sjca 	unsigned int i;
731f30fa552Sjca 	unsigned int format = F_TAR;
73229e8fb76Smillert 	struct incfile {
73329e8fb76Smillert 		char *file;
73429e8fb76Smillert 		char *dir;
73529e8fb76Smillert 	};
73629e8fb76Smillert 	struct incfile *incfiles = NULL;
737df930be7Sderaadt 
738df930be7Sderaadt 	/*
739c7e58f96Smillert 	 * Set default values.
740c7e58f96Smillert 	 */
741c7e58f96Smillert 	rmleadslash = 1;
742c7e58f96Smillert 
743c7e58f96Smillert 	/*
744df930be7Sderaadt 	 * process option flags
745df930be7Sderaadt 	 */
746d2b23181Sderaadt 	while ((c = getoldopt(argc, argv,
747f30fa552Sjca 	    "b:cef:hjmopqruts:vwxzBC:F:HI:LNOPXZ014578")) != -1) {
748df930be7Sderaadt 		switch (c) {
749df930be7Sderaadt 		case 'b':
750df930be7Sderaadt 			/*
75123853f2fSmillert 			 * specify blocksize in 512-byte blocks
752df930be7Sderaadt 			 */
753df930be7Sderaadt 			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
75442cf9836Stholo 				paxwarn(1, "Invalid block size %s", optarg);
755df930be7Sderaadt 				tar_usage();
756df930be7Sderaadt 			}
75723853f2fSmillert 			wrblksz *= 512;		/* XXX - check for int oflow */
758df930be7Sderaadt 			break;
759df930be7Sderaadt 		case 'c':
760df930be7Sderaadt 			/*
761df930be7Sderaadt 			 * create an archive
762df930be7Sderaadt 			 */
763df930be7Sderaadt 			act = ARCHIVE;
764df930be7Sderaadt 			break;
765df930be7Sderaadt 		case 'e':
766df930be7Sderaadt 			/*
767df930be7Sderaadt 			 * stop after first error
768df930be7Sderaadt 			 */
769df930be7Sderaadt 			maxflt = 0;
770df930be7Sderaadt 			break;
771df930be7Sderaadt 		case 'f':
772df930be7Sderaadt 			/*
773df930be7Sderaadt 			 * filename where the archive is stored
774df930be7Sderaadt 			 */
775df930be7Sderaadt 			arcname = optarg;
776df930be7Sderaadt 			break;
777c2e82e9eStholo 		case 'h':
778c2e82e9eStholo 			/*
779c2e82e9eStholo 			 * follow symlinks
780c2e82e9eStholo 			 */
781c2e82e9eStholo 			Lflag = 1;
782c2e82e9eStholo 			break;
783a914b46dSpvalchev 		case 'j':
784a914b46dSpvalchev 			/*
785a914b46dSpvalchev 			 * use bzip2.  Non standard option.
786a914b46dSpvalchev 			 */
787a914b46dSpvalchev 			gzip_program = BZIP2_CMD;
788a914b46dSpvalchev 			break;
789df930be7Sderaadt 		case 'm':
790df930be7Sderaadt 			/*
791df930be7Sderaadt 			 * do not preserve modification time
792df930be7Sderaadt 			 */
793df930be7Sderaadt 			pmtime = 0;
794df930be7Sderaadt 			break;
79598fcb8acSmillert 		case 'O':
796f30fa552Sjca 			format = F_OTAR;
797df930be7Sderaadt 			break;
7984b311c3bSmillert 		case 'o':
799f30fa552Sjca 			format = F_OTAR;
8002d53aafbSguenther 			tar_nodir = 1;
8014b311c3bSmillert 			break;
802df930be7Sderaadt 		case 'p':
803df930be7Sderaadt 			/*
8041d097e52Smillert 			 * preserve uid/gid and file mode, regardless of umask
805df930be7Sderaadt 			 */
806df930be7Sderaadt 			pmode = 1;
8071d097e52Smillert 			pids = 1;
808df930be7Sderaadt 			break;
8098f296fddSespie 		case 'q':
8108f296fddSespie 			/*
8118f296fddSespie 			 * select first match for a pattern only
8128f296fddSespie 			 */
8138f296fddSespie 			nflag = 1;
8148f296fddSespie 			break;
815df930be7Sderaadt 		case 'r':
816df930be7Sderaadt 		case 'u':
817df930be7Sderaadt 			/*
818df930be7Sderaadt 			 * append to the archive
819df930be7Sderaadt 			 */
820df930be7Sderaadt 			act = APPND;
821df930be7Sderaadt 			break;
822d2b23181Sderaadt 		case 's':
823d2b23181Sderaadt 			/*
824d2b23181Sderaadt 			 * file name substitution name pattern
825d2b23181Sderaadt 			 */
826d2b23181Sderaadt 			if (rep_add(optarg) < 0) {
827d2b23181Sderaadt 				tar_usage();
828d2b23181Sderaadt 				break;
829d2b23181Sderaadt 			}
830d2b23181Sderaadt 			break;
831df930be7Sderaadt 		case 't':
832df930be7Sderaadt 			/*
833df930be7Sderaadt 			 * list contents of the tape
834df930be7Sderaadt 			 */
835df930be7Sderaadt 			act = LIST;
836df930be7Sderaadt 			break;
837df930be7Sderaadt 		case 'v':
838df930be7Sderaadt 			/*
839df930be7Sderaadt 			 * verbose operation mode
840df930be7Sderaadt 			 */
841f2d26cdcSmillert 			vflag++;
842df930be7Sderaadt 			break;
843df930be7Sderaadt 		case 'w':
844df930be7Sderaadt 			/*
845df930be7Sderaadt 			 * interactive file rename
846df930be7Sderaadt 			 */
847df930be7Sderaadt 			iflag = 1;
848df930be7Sderaadt 			break;
849df930be7Sderaadt 		case 'x':
850df930be7Sderaadt 			/*
8513230eb4dSmillert 			 * extract an archive, preserving mode,
8521d097e52Smillert 			 * and mtime if possible.
853df930be7Sderaadt 			 */
854df930be7Sderaadt 			act = EXTRACT;
8553230eb4dSmillert 			pmtime = 1;
856df930be7Sderaadt 			break;
8578ab05b7eSderaadt 		case 'z':
8588ab05b7eSderaadt 			/*
8598ab05b7eSderaadt 			 * use gzip.  Non standard option.
8608ab05b7eSderaadt 			 */
861c7117be0Sderaadt 			gzip_program = GZIP_CMD;
8628ab05b7eSderaadt 			break;
863df930be7Sderaadt 		case 'B':
864df930be7Sderaadt 			/*
865df930be7Sderaadt 			 * Nothing to do here, this is pax default
866df930be7Sderaadt 			 */
867df930be7Sderaadt 			break;
8683c2af966Sdownsj 		case 'C':
869a7a4d07aSotto 			havechd++;
870fd899314Smichaels 			chdname = optarg;
8713c2af966Sdownsj 			break;
872f30fa552Sjca 		case 'F':
873f30fa552Sjca 			for (i = 0; i < sizeof(fsub)/sizeof(FSUB); ++i)
874f30fa552Sjca 				if (fsub[i].name != NULL &&
875f30fa552Sjca 				    strcmp(fsub[i].name, optarg) == 0)
876f30fa552Sjca 					break;
877f30fa552Sjca 			if (i < sizeof(fsub)/sizeof(FSUB)) {
878f30fa552Sjca 				format = i;
879f30fa552Sjca 				break;
880f30fa552Sjca 			}
881f30fa552Sjca 			paxwarn(1, "Unknown -F format: %s", optarg);
882f30fa552Sjca 			(void)fputs("tar: Known -F formats are:", stderr);
883f30fa552Sjca 			for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
884f30fa552Sjca 				if (fsub[i].name != NULL)
885f30fa552Sjca 					(void)fprintf(stderr, " %s",
886f30fa552Sjca 					    fsub[i].name);
887f30fa552Sjca 			(void)fputs("\n\n", stderr);
888f30fa552Sjca 			tar_usage();
889f30fa552Sjca 			break;
890df930be7Sderaadt 		case 'H':
891df930be7Sderaadt 			/*
892df930be7Sderaadt 			 * follow command line symlinks only
893df930be7Sderaadt 			 */
894df930be7Sderaadt 			Hflag = 1;
895df930be7Sderaadt 			break;
89629e8fb76Smillert 		case 'I':
89729e8fb76Smillert 			if (++nincfiles > incfiles_max) {
898968415c8Sderaadt 				size_t n = nincfiles + 3;
899968415c8Sderaadt 				struct incfile *p;
900968415c8Sderaadt 
901547153d7Stedu 				p = reallocarray(incfiles, n,
902547153d7Stedu 				    sizeof(*incfiles));
903968415c8Sderaadt 				if (p == NULL) {
90429e8fb76Smillert 					paxwarn(0, "Unable to allocate space "
90529e8fb76Smillert 					    "for option list");
90629e8fb76Smillert 					exit(1);
90729e8fb76Smillert 				}
908968415c8Sderaadt 				incfiles = p;
909968415c8Sderaadt 				incfiles_max = n;
91029e8fb76Smillert 			}
91129e8fb76Smillert 			incfiles[nincfiles - 1].file = optarg;
91229e8fb76Smillert 			incfiles[nincfiles - 1].dir = chdname;
91329e8fb76Smillert 			break;
914df930be7Sderaadt 		case 'L':
915df930be7Sderaadt 			/*
916df930be7Sderaadt 			 * follow symlinks
917df930be7Sderaadt 			 */
918df930be7Sderaadt 			Lflag = 1;
919df930be7Sderaadt 			break;
9205e460854Stedu 		case 'N':
9215e460854Stedu 			/* numeric uid and gid only */
9225e460854Stedu 			Nflag = 1;
9235e460854Stedu 			break;
924df930be7Sderaadt 		case 'P':
925df930be7Sderaadt 			/*
926c7e58f96Smillert 			 * do not remove leading '/' from pathnames
927c7e58f96Smillert 			 */
928c7e58f96Smillert 			rmleadslash = 0;
929c7e58f96Smillert 			break;
930df930be7Sderaadt 		case 'X':
931df930be7Sderaadt 			/*
932df930be7Sderaadt 			 * do not pass over mount points in the file system
933df930be7Sderaadt 			 */
934df930be7Sderaadt 			Xflag = 1;
935df930be7Sderaadt 			break;
9368ab05b7eSderaadt 		case 'Z':
9378ab05b7eSderaadt 			/*
9388ab05b7eSderaadt 			 * use compress.
9398ab05b7eSderaadt 			 */
940c7117be0Sderaadt 			gzip_program = COMPRESS_CMD;
9418ab05b7eSderaadt 			break;
942df930be7Sderaadt 		case '0':
943df930be7Sderaadt 			arcname = DEV_0;
944df930be7Sderaadt 			break;
945df930be7Sderaadt 		case '1':
946df930be7Sderaadt 			arcname = DEV_1;
947df930be7Sderaadt 			break;
948df930be7Sderaadt 		case '4':
949df930be7Sderaadt 			arcname = DEV_4;
950df930be7Sderaadt 			break;
951df930be7Sderaadt 		case '5':
952df930be7Sderaadt 			arcname = DEV_5;
953df930be7Sderaadt 			break;
954df930be7Sderaadt 		case '7':
955df930be7Sderaadt 			arcname = DEV_7;
956df930be7Sderaadt 			break;
957df930be7Sderaadt 		case '8':
958df930be7Sderaadt 			arcname = DEV_8;
959df930be7Sderaadt 			break;
960df930be7Sderaadt 		default:
961df930be7Sderaadt 			tar_usage();
962df930be7Sderaadt 			break;
963df930be7Sderaadt 		}
964df930be7Sderaadt 	}
965df930be7Sderaadt 	argc -= optind;
966df930be7Sderaadt 	argv += optind;
967df930be7Sderaadt 
968e98b7d12Sguenther 	if ((arcname == NULL) || (*arcname == '\0')) {
969f2baad8dSczarkoff 		arcname = getenv("TAPE");
970f2baad8dSczarkoff 		if ((arcname == NULL) || (*arcname == '\0'))
971f2baad8dSczarkoff 			arcname = _PATH_DEFTAPE;
972e98b7d12Sguenther 	}
973e98b7d12Sguenther 	if ((arcname[0] == '-') && (arcname[1]== '\0'))
974f2baad8dSczarkoff 		arcname = NULL;
975f2baad8dSczarkoff 
976e98b7d12Sguenther 	/*
977e98b7d12Sguenther 	 * Traditional tar behaviour: list-like output goes to stdout unless
978e98b7d12Sguenther 	 * writing the archive there.  (pax uses stderr unless in list mode)
979e98b7d12Sguenther 	 */
980e98b7d12Sguenther         if (act == LIST || act == EXTRACT || arcname != NULL)
98110854502Smillert 		listf = stdout;
98210854502Smillert 
9831e43a87cSmillert 	/* Traditional tar behaviour (pax wants to read file list from stdin) */
98429e8fb76Smillert 	if ((act == ARCHIVE || act == APPND) && argc == 0 && nincfiles == 0)
9851e43a87cSmillert 		exit(0);
9861e43a87cSmillert 
987df930be7Sderaadt 	/*
988df930be7Sderaadt 	 * process the args as they are interpreted by the operation mode
989df930be7Sderaadt 	 */
990df930be7Sderaadt 	switch (act) {
991df930be7Sderaadt 	case LIST:
992df930be7Sderaadt 	case EXTRACT:
993df930be7Sderaadt 	default:
9943c2af966Sdownsj 		{
9953c2af966Sdownsj 			int sawpat = 0;
99629e8fb76Smillert 			char *file, *dir;
9973c2af966Sdownsj 
99829e8fb76Smillert 			while (nincfiles || *argv != NULL) {
99929e8fb76Smillert 				/*
100029e8fb76Smillert 				 * If we queued up any include files,
100129e8fb76Smillert 				 * pull them in now.  Otherwise, check
100229e8fb76Smillert 				 * for -I and -C positional flags.
100329e8fb76Smillert 				 * Anything else must be a file to
100429e8fb76Smillert 				 * extract.
100529e8fb76Smillert 				 */
100629e8fb76Smillert 				if (nincfiles) {
100729e8fb76Smillert 					file = incfiles->file;
100829e8fb76Smillert 					dir = incfiles->dir;
100929e8fb76Smillert 					incfiles++;
101029e8fb76Smillert 					nincfiles--;
101129e8fb76Smillert 				} else if (strcmp(*argv, "-I") == 0) {
10124bbb0cd1Skstailey 					if (*++argv == NULL)
10133c2af966Sdownsj 						break;
101429e8fb76Smillert 					file = *argv++;
101529e8fb76Smillert 					dir = chdname;
101629e8fb76Smillert 				} else
101729e8fb76Smillert 					file = NULL;
101829e8fb76Smillert 				if (file != NULL) {
101976b0a314Sespie 					FILE *fp;
102076b0a314Sespie 					char *str;
102176b0a314Sespie 
102229e8fb76Smillert 					if (strcmp(file, "-") == 0)
102329e8fb76Smillert 						fp = stdin;
102429e8fb76Smillert 					else if ((fp = fopen(file, "r")) == NULL) {
1025fc5cb1eaSguenther 						syswarn(1, errno,
1026fc5cb1eaSguenther 						    "Unable to open %s", file);
102776b0a314Sespie 						tar_usage();
102876b0a314Sespie 					}
1029f9bbbf45Sfgsch 					while ((str = get_line(fp)) != NULL) {
103029e8fb76Smillert 						if (pat_add(str, dir) < 0)
103176b0a314Sespie 							tar_usage();
103229e8fb76Smillert 						sawpat = 1;
103376b0a314Sespie 					}
1034fc5cb1eaSguenther 					if (ferror(fp)) {
1035fc5cb1eaSguenther 						syswarn(1, errno,
1036fc5cb1eaSguenther 						    "Unable to read from %s",
1037fc5cb1eaSguenther 						    strcmp(file, "-") ? file :
1038fc5cb1eaSguenther 						    "stdin");
103976b0a314Sespie 						tar_usage();
104076b0a314Sespie 					}
1041fc5cb1eaSguenther 					if (strcmp(file, "-") != 0)
1042fc5cb1eaSguenther 						fclose(fp);
104329e8fb76Smillert 				} else if (strcmp(*argv, "-C") == 0) {
104429e8fb76Smillert 					if (*++argv == NULL)
104529e8fb76Smillert 						break;
104629e8fb76Smillert 					chdname = *argv++;
1047a7a4d07aSotto 					havechd++;
104829e8fb76Smillert 				} else if (pat_add(*argv++, chdname) < 0)
1049df930be7Sderaadt 					tar_usage();
105029e8fb76Smillert 				else
105129e8fb76Smillert 					sawpat = 1;
10523c2af966Sdownsj 			}
10533c2af966Sdownsj 			/*
1054fd899314Smichaels 			 * if patterns were added, we are doing	chdir()
1055fd899314Smichaels 			 * on a file-by-file basis, else, just one
1056fd899314Smichaels 			 * global chdir (if any) after opening input.
10573c2af966Sdownsj 			 */
1058fd899314Smichaels 			if (sawpat > 0)
1059fd899314Smichaels 				chdname = NULL;
10603c2af966Sdownsj 		}
1061df930be7Sderaadt 		break;
1062df930be7Sderaadt 	case ARCHIVE:
1063df930be7Sderaadt 	case APPND:
1064f30fa552Sjca 		frmt = &fsub[format];
10654b311c3bSmillert 
10664bbb0cd1Skstailey 		if (chdname != NULL) {	/* initial chdir() */
1067fd899314Smichaels 			if (ftree_add(chdname, 1) < 0)
1068df930be7Sderaadt 				tar_usage();
10693c2af966Sdownsj 		}
10703c2af966Sdownsj 
107129e8fb76Smillert 		while (nincfiles || *argv != NULL) {
107229e8fb76Smillert 			char *file, *dir;
107329e8fb76Smillert 
107429e8fb76Smillert 			/*
107529e8fb76Smillert 			 * If we queued up any include files, pull them in
107629e8fb76Smillert 			 * now.  Otherwise, check for -I and -C positional
107729e8fb76Smillert 			 * flags.  Anything else must be a file to include
107829e8fb76Smillert 			 * in the archive.
107929e8fb76Smillert 			 */
108029e8fb76Smillert 			if (nincfiles) {
108129e8fb76Smillert 				file = incfiles->file;
108229e8fb76Smillert 				dir = incfiles->dir;
108329e8fb76Smillert 				incfiles++;
108429e8fb76Smillert 				nincfiles--;
108529e8fb76Smillert 			} else if (strcmp(*argv, "-I") == 0) {
10864bbb0cd1Skstailey 				if (*++argv == NULL)
10873c2af966Sdownsj 					break;
108829e8fb76Smillert 				file = *argv++;
108929e8fb76Smillert 				dir = NULL;
109029e8fb76Smillert 			} else
109129e8fb76Smillert 				file = NULL;
109229e8fb76Smillert 			if (file != NULL) {
109376b0a314Sespie 				FILE *fp;
109476b0a314Sespie 				char *str;
109576b0a314Sespie 
109629e8fb76Smillert 				/* Set directory if needed */
109729e8fb76Smillert 				if (dir) {
109829e8fb76Smillert 					if (ftree_add(dir, 1) < 0)
109929e8fb76Smillert 						tar_usage();
110029e8fb76Smillert 				}
110176b0a314Sespie 
110229e8fb76Smillert 				if (strcmp(file, "-") == 0)
110329e8fb76Smillert 					fp = stdin;
110429e8fb76Smillert 				else if ((fp = fopen(file, "r")) == NULL) {
1105fc5cb1eaSguenther 					syswarn(1, errno, "Unable to open %s",
1106fc5cb1eaSguenther 					    file);
110776b0a314Sespie 					tar_usage();
110876b0a314Sespie 				}
1109f9bbbf45Sfgsch 				while ((str = get_line(fp)) != NULL) {
111076b0a314Sespie 					if (ftree_add(str, 0) < 0)
111176b0a314Sespie 						tar_usage();
111276b0a314Sespie 				}
1113fc5cb1eaSguenther 				if (ferror(fp)) {
1114fc5cb1eaSguenther 					syswarn(1, errno,
1115fc5cb1eaSguenther 					    "Unable to read from %s",
1116fc5cb1eaSguenther 					    strcmp(file, "-") ? file : "stdin");
111776b0a314Sespie 					tar_usage();
111876b0a314Sespie 				}
1119fc5cb1eaSguenther 				if (strcmp(file, "-") != 0)
1120fc5cb1eaSguenther 					fclose(fp);
112129e8fb76Smillert 			} else if (strcmp(*argv, "-C") == 0) {
112229e8fb76Smillert 				if (*++argv == NULL)
112329e8fb76Smillert 					break;
112429e8fb76Smillert 				if (ftree_add(*argv++, 1) < 0)
112529e8fb76Smillert 					tar_usage();
1126a7a4d07aSotto 				havechd++;
112729e8fb76Smillert 			} else if (ftree_add(*argv++, 0) < 0)
11283c2af966Sdownsj 				tar_usage();
11293c2af966Sdownsj 		}
1130df930be7Sderaadt 		/*
1131df930be7Sderaadt 		 * no read errors allowed on updates/append operation!
1132df930be7Sderaadt 		 */
1133df930be7Sderaadt 		maxflt = 0;
1134df930be7Sderaadt 		break;
1135df930be7Sderaadt 	}
1136df930be7Sderaadt }
1137df930be7Sderaadt 
1138c01bd743Sespie static int mkpath(char *);
1139cd90c754Sderaadt 
1140c01bd743Sespie static int
mkpath(char * path)1141366a2d32Stb mkpath(char *path)
1142849a3f9cStholo {
1143849a3f9cStholo 	struct stat sb;
1144be87792eSmillert 	char *slash;
1145849a3f9cStholo 	int done = 0;
1146849a3f9cStholo 
1147849a3f9cStholo 	slash = path;
1148849a3f9cStholo 
1149849a3f9cStholo 	while (!done) {
1150849a3f9cStholo 		slash += strspn(slash, "/");
1151849a3f9cStholo 		slash += strcspn(slash, "/");
1152849a3f9cStholo 
1153849a3f9cStholo 		done = (*slash == '\0');
1154849a3f9cStholo 		*slash = '\0';
1155849a3f9cStholo 
1156849a3f9cStholo 		if (stat(path, &sb)) {
1157849a3f9cStholo 			if (errno != ENOENT || mkdir(path, 0777)) {
1158849a3f9cStholo 				paxwarn(1, "%s", path);
1159849a3f9cStholo 				return (-1);
1160849a3f9cStholo 			}
1161849a3f9cStholo 		} else if (!S_ISDIR(sb.st_mode)) {
1162849a3f9cStholo 			syswarn(1, ENOTDIR, "%s", path);
1163849a3f9cStholo 			return (-1);
1164849a3f9cStholo 		}
1165849a3f9cStholo 
1166849a3f9cStholo 		if (!done)
1167849a3f9cStholo 			*slash = '/';
1168849a3f9cStholo 	}
1169849a3f9cStholo 
1170849a3f9cStholo 	return (0);
1171849a3f9cStholo }
1172f3e2c552Sderaadt 
1173f3e2c552Sderaadt #ifndef NOCPIO
1174df930be7Sderaadt /*
1175df930be7Sderaadt  * cpio_options()
1176df930be7Sderaadt  *	look at the user specified flags. set globals as required and check if
1177df930be7Sderaadt  *	the user specified a legal set of flags. If not, complain and exit
1178df930be7Sderaadt  */
1179df930be7Sderaadt 
1180df930be7Sderaadt static void
cpio_options(int argc,char ** argv)1181be87792eSmillert cpio_options(int argc, char **argv)
1182df930be7Sderaadt {
1183a47b6461Sderaadt 	const char *errstr;
118406edebb3Sguenther 	int c, list_only = 0;
1185e1fb501dShalex 	unsigned i;
1186537ae142Sespie 	char *str;
118719e7eef2Stholo 	FILE *fp;
118819e7eef2Stholo 
118919e7eef2Stholo 	kflag = 1;
119019e7eef2Stholo 	pids = 1;
119119e7eef2Stholo 	pmode = 1;
1192849a3f9cStholo 	pmtime = 0;
119319e7eef2Stholo 	arcname = NULL;
119419e7eef2Stholo 	dflag = 1;
119519e7eef2Stholo 	act = -1;
1196849a3f9cStholo 	nodirs = 1;
1197a914b46dSpvalchev 	while ((c=getopt(argc,argv,"abcdfijklmoprstuvzABC:E:F:H:I:LO:SZ6")) != -1)
119819e7eef2Stholo 		switch (c) {
119919e7eef2Stholo 			case 'a':
120019e7eef2Stholo 				/*
120119e7eef2Stholo 				 * preserve access time on files read
120219e7eef2Stholo 				 */
120319e7eef2Stholo 				tflag = 1;
120419e7eef2Stholo 				break;
120519e7eef2Stholo 			case 'b':
120619e7eef2Stholo 				/*
120719e7eef2Stholo 				 * swap bytes and half-words when reading data
120819e7eef2Stholo 				 */
120919e7eef2Stholo 				break;
121019e7eef2Stholo 			case 'c':
121119e7eef2Stholo 				/*
121219e7eef2Stholo 				 * ASCII cpio header
121319e7eef2Stholo 				 */
121419e7eef2Stholo 				frmt = &(fsub[F_ACPIO]);
121519e7eef2Stholo 				break;
121619e7eef2Stholo 			case 'd':
121719e7eef2Stholo 				/*
121819e7eef2Stholo 				 * create directories as needed
121919e7eef2Stholo 				 */
1220849a3f9cStholo 				nodirs = 0;
122119e7eef2Stholo 				break;
122219e7eef2Stholo 			case 'f':
122319e7eef2Stholo 				/*
122419e7eef2Stholo 				 * invert meaning of pattern list
122519e7eef2Stholo 				 */
122619e7eef2Stholo 				cflag = 1;
122719e7eef2Stholo 				break;
122819e7eef2Stholo 			case 'i':
122919e7eef2Stholo 				/*
123019e7eef2Stholo 				 * restore an archive
123119e7eef2Stholo 				 */
123219e7eef2Stholo 				act = EXTRACT;
123319e7eef2Stholo 				break;
1234a914b46dSpvalchev 			case 'j':
1235a914b46dSpvalchev 				/*
1236a914b46dSpvalchev 				 * use bzip2.  Non standard option.
1237a914b46dSpvalchev 				 */
1238a914b46dSpvalchev 				gzip_program = BZIP2_CMD;
1239a914b46dSpvalchev 				break;
124019e7eef2Stholo 			case 'k':
124119e7eef2Stholo 				break;
124219e7eef2Stholo 			case 'l':
124319e7eef2Stholo 				/*
124419e7eef2Stholo 				 * use links instead of copies when possible
124519e7eef2Stholo 				 */
124619e7eef2Stholo 				lflag = 1;
124719e7eef2Stholo 				break;
124819e7eef2Stholo 			case 'm':
124919e7eef2Stholo 				/*
125019e7eef2Stholo 				 * preserve modification time
125119e7eef2Stholo 				 */
125219e7eef2Stholo 				pmtime = 1;
125319e7eef2Stholo 				break;
125419e7eef2Stholo 			case 'o':
125519e7eef2Stholo 				/*
125619e7eef2Stholo 				 * create an archive
125719e7eef2Stholo 				 */
125819e7eef2Stholo 				act = ARCHIVE;
125955d472e4Snaddy 				if (frmt == NULL)
126019e7eef2Stholo 					frmt = &(fsub[F_CPIO]);
126119e7eef2Stholo 				break;
126219e7eef2Stholo 			case 'p':
126319e7eef2Stholo 				/*
126419e7eef2Stholo 				 * copy-pass mode
126519e7eef2Stholo 				 */
126619e7eef2Stholo 				act = COPY;
126719e7eef2Stholo 				break;
126819e7eef2Stholo 			case 'r':
126919e7eef2Stholo 				/*
127019e7eef2Stholo 				 * interactively rename files
127119e7eef2Stholo 				 */
127219e7eef2Stholo 				iflag = 1;
127319e7eef2Stholo 				break;
127419e7eef2Stholo 			case 's':
127519e7eef2Stholo 				/*
127619e7eef2Stholo 				 * swap bytes after reading data
127719e7eef2Stholo 				 */
127819e7eef2Stholo 				break;
127919e7eef2Stholo 			case 't':
128019e7eef2Stholo 				/*
128119e7eef2Stholo 				 * list contents of archive
128219e7eef2Stholo 				 */
128306edebb3Sguenther 				list_only = 1;
128419e7eef2Stholo 				break;
128519e7eef2Stholo 			case 'u':
128619e7eef2Stholo 				/*
128719e7eef2Stholo 				 * replace newer files
128819e7eef2Stholo 				 */
128919e7eef2Stholo 				kflag = 0;
129019e7eef2Stholo 				break;
129119e7eef2Stholo 			case 'v':
129219e7eef2Stholo 				/*
129319e7eef2Stholo 				 * verbose operation mode
129419e7eef2Stholo 				 */
129519e7eef2Stholo 				vflag = 1;
129619e7eef2Stholo 				break;
129719e7eef2Stholo 			case 'z':
129819e7eef2Stholo 				/*
129919e7eef2Stholo 				 * use gzip.  Non standard option.
130019e7eef2Stholo 				 */
130119e7eef2Stholo 				gzip_program = GZIP_CMD;
130219e7eef2Stholo 				break;
130319e7eef2Stholo 			case 'A':
130419e7eef2Stholo 				/*
130519e7eef2Stholo 				 * append mode
130619e7eef2Stholo 				 */
130719e7eef2Stholo 				act = APPND;
130819e7eef2Stholo 				break;
130919e7eef2Stholo 			case 'B':
131019e7eef2Stholo 				/*
131119e7eef2Stholo 				 * Use 5120 byte block size
131219e7eef2Stholo 				 */
131319e7eef2Stholo 				wrblksz = 5120;
131419e7eef2Stholo 				break;
131519e7eef2Stholo 			case 'C':
131619e7eef2Stholo 				/*
131719e7eef2Stholo 				 * set block size in bytes
131819e7eef2Stholo 				 */
1319a47b6461Sderaadt 				wrblksz = strtonum(optarg, 0, INT_MAX, &errstr);
1320a47b6461Sderaadt 				if (errstr) {
1321a47b6461Sderaadt 					paxwarn(1, "Invalid block size %s: %s",
1322a47b6461Sderaadt 					    optarg, errstr);
1323a47b6461Sderaadt 					pax_usage();
1324a47b6461Sderaadt 				}
132519e7eef2Stholo 				break;
132619e7eef2Stholo 			case 'E':
132719e7eef2Stholo 				/*
132819e7eef2Stholo 				 * file with patterns to extract or list
132919e7eef2Stholo 				 */
133019e7eef2Stholo 				if ((fp = fopen(optarg, "r")) == NULL) {
1331fc5cb1eaSguenther 					syswarn(1, errno, "Unable to open %s",
1332fc5cb1eaSguenther 					    optarg);
133319e7eef2Stholo 					cpio_usage();
1334df930be7Sderaadt 				}
1335f9bbbf45Sfgsch 				while ((str = get_line(fp)) != NULL) {
133619e7eef2Stholo 					pat_add(str, NULL);
133719e7eef2Stholo 				}
1338fc5cb1eaSguenther 				if (ferror(fp)) {
1339fc5cb1eaSguenther 					syswarn(1, errno,
1340fc5cb1eaSguenther 					    "Unable to read from %s", optarg);
1341537ae142Sespie 					cpio_usage();
1342537ae142Sespie 				}
1343fc5cb1eaSguenther 				fclose(fp);
134419e7eef2Stholo 				break;
134519e7eef2Stholo 			case 'F':
134619e7eef2Stholo 			case 'I':
134719e7eef2Stholo 			case 'O':
134819e7eef2Stholo 				/*
134919e7eef2Stholo 				 * filename where the archive is stored
135019e7eef2Stholo 				 */
135119e7eef2Stholo 				if ((optarg[0] == '-') && (optarg[1]== '\0')) {
135219e7eef2Stholo 					/*
135319e7eef2Stholo 					 * treat a - as stdin
135419e7eef2Stholo 					 */
135519e7eef2Stholo 					arcname = NULL;
135619e7eef2Stholo 					break;
135719e7eef2Stholo 				}
135819e7eef2Stholo 				arcname = optarg;
135919e7eef2Stholo 				break;
136019e7eef2Stholo 			case 'H':
136119e7eef2Stholo 				/*
136219e7eef2Stholo 				 * specify an archive format on write
136319e7eef2Stholo 				 */
1364e1fb501dShalex 				for (i = 0; i < sizeof(fsub)/sizeof(FSUB); ++i)
1365e1fb501dShalex 					if (fsub[i].name != NULL &&
1366e1fb501dShalex 					    strcmp(fsub[i].name, optarg) == 0)
136719e7eef2Stholo 						break;
1368e43eba20Sguenther 				if (i < sizeof(fsub)/sizeof(FSUB)) {
1369e43eba20Sguenther 					frmt = &fsub[i];
1370e43eba20Sguenther 					break;
1371e43eba20Sguenther 				}
137219e7eef2Stholo 				paxwarn(1, "Unknown -H format: %s", optarg);
137319e7eef2Stholo 				(void)fputs("cpio: Known -H formats are:", stderr);
137419e7eef2Stholo 				for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
1375e43eba20Sguenther 					if (fsub[i].name != NULL)
1376e43eba20Sguenther 						(void)fprintf(stderr, " %s",
1377e43eba20Sguenther 						    fsub[i].name);
137819e7eef2Stholo 				(void)fputs("\n\n", stderr);
137919e7eef2Stholo 				cpio_usage();
138019e7eef2Stholo 				break;
138119e7eef2Stholo 			case 'L':
138219e7eef2Stholo 				/*
138319e7eef2Stholo 				 * follow symbolic links
138419e7eef2Stholo 				 */
138519e7eef2Stholo 				Lflag = 1;
138619e7eef2Stholo 				break;
138719e7eef2Stholo 			case 'S':
138819e7eef2Stholo 				/*
138919e7eef2Stholo 				 * swap halfwords after reading data
139019e7eef2Stholo 				 */
139119e7eef2Stholo 				break;
139219e7eef2Stholo 			case 'Z':
139319e7eef2Stholo 				/*
139419e7eef2Stholo 				 * use compress.  Non standard option.
139519e7eef2Stholo 				 */
139619e7eef2Stholo 				gzip_program = COMPRESS_CMD;
139719e7eef2Stholo 				break;
139819e7eef2Stholo 			case '6':
139919e7eef2Stholo 				/*
140019e7eef2Stholo 				 * process Version 6 cpio format
140119e7eef2Stholo 				 */
140219e7eef2Stholo 				frmt = &(fsub[F_OCPIO]);
140319e7eef2Stholo 				break;
140419e7eef2Stholo 			default:
140519e7eef2Stholo 				cpio_usage();
140619e7eef2Stholo 				break;
140719e7eef2Stholo 		}
140819e7eef2Stholo 	argc -= optind;
140919e7eef2Stholo 	argv += optind;
141019e7eef2Stholo 
141119e7eef2Stholo 	/*
141219e7eef2Stholo 	 * process the args as they are interpreted by the operation mode
141319e7eef2Stholo 	 */
141419e7eef2Stholo 	switch (act) {
141519e7eef2Stholo 		case EXTRACT:
141606edebb3Sguenther 			if (list_only) {
141706edebb3Sguenther 				act = LIST;
141806edebb3Sguenther 
141906edebb3Sguenther 				/*
142006edebb3Sguenther 				 * cpio is like pax: list to stderr
142106edebb3Sguenther 				 * unless in list mode
142206edebb3Sguenther 				 */
142306edebb3Sguenther 				listf = stdout;
142406edebb3Sguenther 			}
14254bbb0cd1Skstailey 			while (*argv != NULL)
142619e7eef2Stholo 				if (pat_add(*argv++, NULL) < 0)
142719e7eef2Stholo 					cpio_usage();
142819e7eef2Stholo 			break;
142919e7eef2Stholo 		case COPY:
14304bbb0cd1Skstailey 			if (*argv == NULL) {
143119e7eef2Stholo 				paxwarn(0, "Destination directory was not supplied");
143219e7eef2Stholo 				cpio_usage();
143319e7eef2Stholo 			}
1434849a3f9cStholo 			dirptr = *argv;
1435849a3f9cStholo 			if (mkpath(dirptr) < 0)
1436849a3f9cStholo 				cpio_usage();
143719e7eef2Stholo 			--argc;
1438849a3f9cStholo 			++argv;
143919e7eef2Stholo 			/* FALL THROUGH */
144019e7eef2Stholo 		case ARCHIVE:
144119e7eef2Stholo 		case APPND:
14424bbb0cd1Skstailey 			if (*argv != NULL)
144319e7eef2Stholo 				cpio_usage();
144419e7eef2Stholo 			/*
144519e7eef2Stholo 			 * no read errors allowed on updates/append operation!
144619e7eef2Stholo 			 */
144719e7eef2Stholo 			maxflt = 0;
1448f9bbbf45Sfgsch 			while ((str = get_line(stdin)) != NULL) {
14491fb6e2dfSjaredy 				ftree_add(str, 0);
1450fc709564Saaron 			}
1451fc5cb1eaSguenther 			if (ferror(stdin)) {
1452fc5cb1eaSguenther 				syswarn(1, errno, "Unable to read from %s",
1453fc5cb1eaSguenther 				    "stdin");
1454537ae142Sespie 				cpio_usage();
145519e7eef2Stholo 			}
145619e7eef2Stholo 			break;
145719e7eef2Stholo 		default:
145819e7eef2Stholo 			cpio_usage();
145919e7eef2Stholo 			break;
146019e7eef2Stholo 	}
146119e7eef2Stholo }
1462f3e2c552Sderaadt #endif /* !NOCPIO */
1463df930be7Sderaadt 
1464df930be7Sderaadt /*
1465df930be7Sderaadt  * printflg()
1466df930be7Sderaadt  *	print out those invalid flag sets found to the user
1467df930be7Sderaadt  */
1468df930be7Sderaadt 
1469df930be7Sderaadt static void
printflg(unsigned int flg)1470df930be7Sderaadt printflg(unsigned int flg)
1471df930be7Sderaadt {
1472df930be7Sderaadt 	int nxt;
1473df930be7Sderaadt 	int pos = 0;
1474df930be7Sderaadt 
1475df930be7Sderaadt 	(void)fprintf(stderr,"%s: Invalid combination of options:", argv0);
147642cf9836Stholo 	while ((nxt = ffs(flg)) != 0) {
1477f37d86feSguenther 		flg >>= nxt;
1478df930be7Sderaadt 		pos += nxt;
1479df930be7Sderaadt 		(void)fprintf(stderr, " -%c", flgch[pos-1]);
1480df930be7Sderaadt 	}
1481df930be7Sderaadt 	(void)putc('\n', stderr);
1482df930be7Sderaadt }
1483df930be7Sderaadt 
1484df930be7Sderaadt /*
1485df930be7Sderaadt  * opt_next()
1486df930be7Sderaadt  *	called by format specific options routines to get each format specific
1487df930be7Sderaadt  *	flag and value specified with -o
1488df930be7Sderaadt  * Return:
1489df930be7Sderaadt  *	pointer to next OPLIST entry or NULL (end of list).
1490df930be7Sderaadt  */
1491df930be7Sderaadt 
1492df930be7Sderaadt OPLIST *
opt_next(void)1493df930be7Sderaadt opt_next(void)
1494df930be7Sderaadt {
1495df930be7Sderaadt 	OPLIST *opt;
1496df930be7Sderaadt 
1497df930be7Sderaadt 	if ((opt = ophead) != NULL)
1498df930be7Sderaadt 		ophead = ophead->fow;
1499df930be7Sderaadt 	return(opt);
1500df930be7Sderaadt }
1501df930be7Sderaadt 
1502df930be7Sderaadt /*
1503df930be7Sderaadt  * bad_opt()
1504df930be7Sderaadt  *	generic routine used to complain about a format specific options
1505df930be7Sderaadt  *	when the format does not support options.
1506df930be7Sderaadt  */
1507df930be7Sderaadt 
1508c01bd743Sespie static int
bad_opt(void)1509df930be7Sderaadt bad_opt(void)
1510df930be7Sderaadt {
1511be87792eSmillert 	OPLIST *opt;
1512df930be7Sderaadt 
1513df930be7Sderaadt 	if (ophead == NULL)
1514df930be7Sderaadt 		return(0);
1515df930be7Sderaadt 	/*
1516df930be7Sderaadt 	 * print all we were given
1517df930be7Sderaadt 	 */
151842cf9836Stholo 	paxwarn(1,"These format options are not supported");
1519df930be7Sderaadt 	while ((opt = opt_next()) != NULL)
1520df930be7Sderaadt 		(void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
1521df930be7Sderaadt 	pax_usage();
1522df930be7Sderaadt 	return(0);
1523df930be7Sderaadt }
1524df930be7Sderaadt 
1525df930be7Sderaadt /*
1526df930be7Sderaadt  * opt_add()
1527df930be7Sderaadt  *	breaks the value supplied to -o into a option name and value. options
1528df930be7Sderaadt  *	are given to -o in the form -o name-value,name=value
15294eb0b000Smillert  *	multiple -o may be specified.
1530df930be7Sderaadt  * Return:
1531df930be7Sderaadt  *	0 if format in name=value format, -1 if -o is passed junk
1532df930be7Sderaadt  */
1533df930be7Sderaadt 
1534c01bd743Sespie static int
opt_add(const char * str)15357097cf92Smillert opt_add(const char *str)
1536df930be7Sderaadt {
1537be87792eSmillert 	OPLIST *opt;
1538be87792eSmillert 	char *frpt;
1539be87792eSmillert 	char *pt;
1540be87792eSmillert 	char *endpt;
15417097cf92Smillert 	char *dstr;
1542df930be7Sderaadt 
1543df930be7Sderaadt 	if ((str == NULL) || (*str == '\0')) {
154442cf9836Stholo 		paxwarn(0, "Invalid option name");
1545df930be7Sderaadt 		return(-1);
1546df930be7Sderaadt 	}
15477097cf92Smillert 	if ((dstr = strdup(str)) == NULL) {
1548450fd277Smillert 		paxwarn(0, "Unable to allocate space for option list");
1549450fd277Smillert 		return(-1);
1550450fd277Smillert 	}
15517097cf92Smillert 	frpt = endpt = dstr;
1552df930be7Sderaadt 
1553df930be7Sderaadt 	/*
1554df930be7Sderaadt 	 * break into name and values pieces and stuff each one into a
1555df930be7Sderaadt 	 * OPLIST structure. When we know the format, the format specific
1556df930be7Sderaadt 	 * option function will go through this list
1557df930be7Sderaadt 	 */
1558df930be7Sderaadt 	while ((frpt != NULL) && (*frpt != '\0')) {
1559df930be7Sderaadt 		if ((endpt = strchr(frpt, ',')) != NULL)
1560df930be7Sderaadt 			*endpt = '\0';
1561df930be7Sderaadt 		if ((pt = strchr(frpt, '=')) == NULL) {
156242cf9836Stholo 			paxwarn(0, "Invalid options format");
15637097cf92Smillert 			free(dstr);
1564df930be7Sderaadt 			return(-1);
1565df930be7Sderaadt 		}
1566f38a3474Sguenther 		if ((opt = malloc(sizeof(OPLIST))) == NULL) {
156742cf9836Stholo 			paxwarn(0, "Unable to allocate space for option list");
15687097cf92Smillert 			free(dstr);
1569df930be7Sderaadt 			return(-1);
1570df930be7Sderaadt 		}
1571f4bfdd1aSderaadt 		dstr = NULL;	/* parts of string going onto the OPLIST */
1572df930be7Sderaadt 		*pt++ = '\0';
1573df930be7Sderaadt 		opt->name = frpt;
1574df930be7Sderaadt 		opt->value = pt;
1575df930be7Sderaadt 		opt->fow = NULL;
1576df930be7Sderaadt 		if (endpt != NULL)
1577df930be7Sderaadt 			frpt = endpt + 1;
1578df930be7Sderaadt 		else
1579df930be7Sderaadt 			frpt = NULL;
1580df930be7Sderaadt 		if (ophead == NULL) {
1581df930be7Sderaadt 			optail = ophead = opt;
1582df930be7Sderaadt 			continue;
1583df930be7Sderaadt 		}
1584df930be7Sderaadt 		optail->fow = opt;
1585df930be7Sderaadt 		optail = opt;
1586df930be7Sderaadt 	}
1587f4bfdd1aSderaadt 	free(dstr);
1588df930be7Sderaadt 	return(0);
1589df930be7Sderaadt }
1590df930be7Sderaadt 
1591df930be7Sderaadt /*
1592df930be7Sderaadt  * str_offt()
1593df930be7Sderaadt  *	Convert an expression of the following forms to an off_t > 0.
1594df930be7Sderaadt  *	1) A positive decimal number.
1595df930be7Sderaadt  *	2) A positive decimal number followed by a b (mult by 512).
1596df930be7Sderaadt  *	3) A positive decimal number followed by a k (mult by 1024).
1597df930be7Sderaadt  *	4) A positive decimal number followed by a m (mult by 512).
1598df930be7Sderaadt  *	5) A positive decimal number followed by a w (mult by sizeof int)
1599df930be7Sderaadt  *	6) Two or more positive decimal numbers (with/without k,b or w).
1600ff61e0a4Sprovos  *	   separated by x (also * for backwards compatibility), specifying
1601df930be7Sderaadt  *	   the product of the indicated values.
1602df930be7Sderaadt  * Return:
1603df930be7Sderaadt  *	0 for an error, a positive value o.w.
1604df930be7Sderaadt  */
1605df930be7Sderaadt 
1606df930be7Sderaadt static off_t
str_offt(char * val)1607df930be7Sderaadt str_offt(char *val)
1608df930be7Sderaadt {
1609df930be7Sderaadt 	char *expr;
1610df930be7Sderaadt 	off_t num, t;
1611df930be7Sderaadt 
161228071059Sguenther 	num = strtoll(val, &expr, 0);
161328071059Sguenther 	if ((num == LLONG_MAX) || (num <= 0) || (expr == val))
1614df930be7Sderaadt 		return(0);
1615df930be7Sderaadt 
1616df930be7Sderaadt 	switch (*expr) {
1617df930be7Sderaadt 	case 'b':
1618df930be7Sderaadt 		t = num;
1619df930be7Sderaadt 		num *= 512;
1620df930be7Sderaadt 		if (t > num)
1621df930be7Sderaadt 			return(0);
1622df930be7Sderaadt 		++expr;
1623df930be7Sderaadt 		break;
1624df930be7Sderaadt 	case 'k':
1625df930be7Sderaadt 		t = num;
1626df930be7Sderaadt 		num *= 1024;
1627df930be7Sderaadt 		if (t > num)
1628df930be7Sderaadt 			return(0);
1629df930be7Sderaadt 		++expr;
1630df930be7Sderaadt 		break;
1631df930be7Sderaadt 	case 'm':
1632df930be7Sderaadt 		t = num;
1633df930be7Sderaadt 		num *= 1048576;
1634df930be7Sderaadt 		if (t > num)
1635df930be7Sderaadt 			return(0);
1636df930be7Sderaadt 		++expr;
1637df930be7Sderaadt 		break;
1638df930be7Sderaadt 	case 'w':
1639df930be7Sderaadt 		t = num;
1640df930be7Sderaadt 		num *= sizeof(int);
1641df930be7Sderaadt 		if (t > num)
1642df930be7Sderaadt 			return(0);
1643df930be7Sderaadt 		++expr;
1644df930be7Sderaadt 		break;
1645df930be7Sderaadt 	}
1646df930be7Sderaadt 
1647df930be7Sderaadt 	switch (*expr) {
1648df930be7Sderaadt 		case '\0':
1649df930be7Sderaadt 			break;
1650df930be7Sderaadt 		case '*':
1651df930be7Sderaadt 		case 'x':
1652df930be7Sderaadt 			t = num;
1653df930be7Sderaadt 			num *= str_offt(expr + 1);
1654df930be7Sderaadt 			if (t > num)
1655df930be7Sderaadt 				return(0);
1656df930be7Sderaadt 			break;
1657df930be7Sderaadt 		default:
1658df930be7Sderaadt 			return(0);
1659df930be7Sderaadt 	}
1660df930be7Sderaadt 	return(num);
1661df930be7Sderaadt }
1662df930be7Sderaadt 
1663537ae142Sespie char *
get_line(FILE * f)1664f9bbbf45Sfgsch get_line(FILE *f)
1665537ae142Sespie {
1666fc5cb1eaSguenther 	char *str = NULL;
1667fc5cb1eaSguenther 	size_t size = 0;
1668fc5cb1eaSguenther 	ssize_t len;
1669537ae142Sespie 
1670fc5cb1eaSguenther 	do {
1671fc5cb1eaSguenther 		len = getline(&str, &size, f);
1672fc5cb1eaSguenther 		if (len == -1) {
1673fc5cb1eaSguenther 			free(str);
1674fc5cb1eaSguenther 			return NULL;
1675537ae142Sespie 		}
1676fc5cb1eaSguenther 		if (str[len - 1] == '\n')
1677fc5cb1eaSguenther 			str[len - 1] = '\0';
1678fc5cb1eaSguenther 	} while (str[0] == '\0');
1679fc5cb1eaSguenther 	return str;
1680537ae142Sespie }
1681537ae142Sespie 
1682df930be7Sderaadt /*
1683df930be7Sderaadt  * no_op()
1684df930be7Sderaadt  *	for those option functions where the archive format has nothing to do.
1685df930be7Sderaadt  * Return:
1686df930be7Sderaadt  *	0
1687df930be7Sderaadt  */
1688df930be7Sderaadt 
1689df930be7Sderaadt static int
no_op(void)1690df930be7Sderaadt no_op(void)
1691df930be7Sderaadt {
1692df930be7Sderaadt 	return(0);
1693df930be7Sderaadt }
1694df930be7Sderaadt 
1695df930be7Sderaadt /*
1696df930be7Sderaadt  * pax_usage()
1697df930be7Sderaadt  *	print the usage summary to the user
1698df930be7Sderaadt  */
1699df930be7Sderaadt 
1700df930be7Sderaadt void
pax_usage(void)1701df930be7Sderaadt pax_usage(void)
1702df930be7Sderaadt {
17036bf8d0c9Sjaredy 	(void)fputs(
1704a914b46dSpvalchev 	    "usage: pax [-0cdjnOvz] [-E limit] [-f archive] [-G group] [-s replstr]\n"
17053d5126eaSsobrado 	    "           [-T range] [-U user] [pattern ...]\n"
1706a914b46dSpvalchev 	    "       pax -r [-0cDdijknOuvYZz] [-E limit] [-f archive] [-G group] [-o options]\n"
1707abe48ab4Ssobrado 	    "           [-p string] [-s replstr] [-T range] [-U user] [pattern ...]\n"
1708a914b46dSpvalchev 	    "       pax -w [-0adHijLOPtuvXz] [-B bytes] [-b blocksize] [-f archive]\n"
1709abe48ab4Ssobrado 	    "           [-G group] [-o options] [-s replstr] [-T range] [-U user]\n"
1710abe48ab4Ssobrado 	    "           [-x format] [file ...]\n"
1711bb4196c7Sjmc 	    "       pax -rw [-0DdHikLlnOPtuvXYZ] [-G group] [-p string] [-s replstr]\n"
17123d5126eaSsobrado 	    "           [-T range] [-U user] [file ...] directory\n",
17136bf8d0c9Sjaredy 	    stderr);
1714df930be7Sderaadt 	exit(1);
1715df930be7Sderaadt }
1716df930be7Sderaadt 
1717df930be7Sderaadt /*
1718df930be7Sderaadt  * tar_usage()
1719df930be7Sderaadt  *	print the usage summary to the user
1720df930be7Sderaadt  */
1721df930be7Sderaadt 
1722df930be7Sderaadt void
tar_usage(void)1723df930be7Sderaadt tar_usage(void)
1724df930be7Sderaadt {
172554fea831Sjaredy 	(void)fputs(
1726f30fa552Sjca 	    "usage: tar {crtux}[014578beFfHhjLmNOoPpqsvwXZz]\n"
1727f30fa552Sjca 	    "           [blocking-factor | format | archive | replstr]\n"
1728f30fa552Sjca 	    "           [-C directory] [-I file] [file ...]\n"
17295e460854Stedu 	    "       tar {-crtux} [-014578eHhjLmNOoPpqvwXZz] [-b blocking-factor]\n"
1730f30fa552Sjca 	    "           [-C directory] [-F format] [-f archive] [-I file]\n"
1731f30fa552Sjca 	    "           [-s replstr] [file ...]\n",
1732d2b23181Sderaadt 	    stderr);
1733df930be7Sderaadt 	exit(1);
1734df930be7Sderaadt }
1735df930be7Sderaadt 
1736f3e2c552Sderaadt #ifndef NOCPIO
1737df930be7Sderaadt /*
1738df930be7Sderaadt  * cpio_usage()
1739df930be7Sderaadt  *	print the usage summary to the user
1740df930be7Sderaadt  */
1741df930be7Sderaadt 
1742df930be7Sderaadt void
cpio_usage(void)1743df930be7Sderaadt cpio_usage(void)
1744df930be7Sderaadt {
1745abe48ab4Ssobrado 	(void)fputs(
1746a914b46dSpvalchev 	    "usage: cpio -o [-AaBcjLvZz] [-C bytes] [-F archive] [-H format]\n"
1747abe48ab4Ssobrado 	    "            [-O archive] < name-list [> archive]\n"
1748a914b46dSpvalchev 	    "       cpio -i [-6BbcdfjmrSstuvZz] [-C bytes] [-E file] [-F archive] [-H format]\n"
1749abe48ab4Ssobrado 	    "            [-I archive] [pattern ...] [< archive]\n"
1750abe48ab4Ssobrado 	    "       cpio -p [-adLlmuv] destination-directory < name-list\n",
1751abe48ab4Ssobrado 	    stderr);
1752df930be7Sderaadt 	exit(1);
1753df930be7Sderaadt }
1754f3e2c552Sderaadt #endif /* !NOCPIO */
1755a48f739dSguenther 
1756a48f739dSguenther #ifndef SMALL
1757a48f739dSguenther static int
compress_id(char * blk,int size)1758a48f739dSguenther compress_id(char *blk, int size)
1759a48f739dSguenther {
1760a48f739dSguenther 	if (size >= 2 && blk[0] == '\037' && blk[1] == '\235') {
1761a48f739dSguenther 		paxwarn(0, "input compressed with %s; use the -%c option"
1762a48f739dSguenther 		    " to decompress it", "compress", 'Z');
1763a48f739dSguenther 		exit(1);
1764a48f739dSguenther 	}
1765a48f739dSguenther 	return (-1);
1766a48f739dSguenther }
1767a48f739dSguenther 
1768a48f739dSguenther static int
gzip_id(char * blk,int size)1769a48f739dSguenther gzip_id(char *blk, int size)
1770a48f739dSguenther {
1771a48f739dSguenther 	if (size >= 2 && blk[0] == '\037' && blk[1] == '\213') {
1772a48f739dSguenther 		paxwarn(0, "input compressed with %s; use the -%c option"
1773a48f739dSguenther 		    " to decompress it", "gzip", 'z');
1774a48f739dSguenther 		exit(1);
1775a48f739dSguenther 	}
1776a48f739dSguenther 	return (-1);
1777a48f739dSguenther }
1778a48f739dSguenther 
1779a48f739dSguenther static int
bzip2_id(char * blk,int size)1780a48f739dSguenther bzip2_id(char *blk, int size)
1781a48f739dSguenther {
1782a48f739dSguenther 	if (size >= 3 && blk[0] == 'B' && blk[1] == 'Z' && blk[2] == 'h') {
1783a48f739dSguenther 		paxwarn(0, "input compressed with %s; use the -%c option"
1784a48f739dSguenther 		    " to decompress it", "bzip2", 'j');
1785a48f739dSguenther 		exit(1);
1786a48f739dSguenther 	}
1787a48f739dSguenther 	return (-1);
1788a48f739dSguenther }
1789a48f739dSguenther 
1790a48f739dSguenther static int
xz_id(char * blk,int size)1791a48f739dSguenther xz_id(char *blk, int size)
1792a48f739dSguenther {
1793a48f739dSguenther 	if (size >= 6 && memcmp(blk, "\xFD\x37\x7A\x58\x5A", 6) == 0) {
1794a48f739dSguenther 		paxwarn(0, "input compressed with xz");
1795a48f739dSguenther 		exit(1);
1796a48f739dSguenther 	}
1797a48f739dSguenther 	return (-1);
1798a48f739dSguenther }
1799a48f739dSguenther #endif /* !SMALL */
1800