1/*	$NetBSD: options.c,v 1.112 2011/08/31 16:24:54 plunky Exp $	*/
2
3/*-
4 * Copyright (c) 1992 Keith Muller.
5 * Copyright (c) 1992, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Keith Muller of the University of California, San Diego.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#if HAVE_NBTOOL_CONFIG_H
37#include "nbtool_config.h"
38#endif
39
40#include <sys/cdefs.h>
41#if !defined(lint)
42#if 0
43static char sccsid[] = "@(#)options.c	8.2 (Berkeley) 4/18/94";
44#else
45__RCSID("$NetBSD: options.c,v 1.112 2011/08/31 16:24:54 plunky Exp $");
46#endif
47#endif /* not lint */
48
49#include <sys/types.h>
50#include <sys/time.h>
51#include <sys/stat.h>
52#include <sys/param.h>
53#include <ctype.h>
54#include <errno.h>
55#if HAVE_NBTOOL_CONFIG_H
56#include "compat_getopt.h"
57#else
58#include <getopt.h>
59#endif
60#include <limits.h>
61#include <stdio.h>
62#include <stdlib.h>
63#include <string.h>
64#include <unistd.h>
65#include <paths.h>
66#include "pax.h"
67#include "options.h"
68#include "cpio.h"
69#include "tar.h"
70#include "extern.h"
71#ifndef SMALL
72#include "mtree.h"
73#endif	/* SMALL */
74
75/*
76 * Routines which handle command line options
77 */
78
79static int nopids;		/* tar mode: suppress "pids" for -p option */
80static char flgch[] = FLGCH;	/* list of all possible flags (pax) */
81static OPLIST *ophead = NULL;	/* head for format specific options -x */
82static OPLIST *optail = NULL;	/* option tail */
83
84static int opt_add(const char *);
85static int no_op(void);
86static void printflg(unsigned int);
87static int c_frmt(const void *, const void *);
88static off_t str_offt(char *);
89static char *get_line(FILE *fp);
90static void pax_options(int, char **);
91__dead static void pax_usage(void);
92static void tar_options(int, char **);
93__dead static void tar_usage(void);
94#ifndef NO_CPIO
95static void cpio_options(int, char **);
96__dead static void cpio_usage(void);
97#endif
98
99/* errors from get_line */
100#define GETLINE_FILE_CORRUPT 1
101#define GETLINE_OUT_OF_MEM 2
102static int get_line_error;
103
104#define BZIP2_CMD	"bzip2"		/* command to run as bzip2 */
105#define GZIP_CMD	"gzip"		/* command to run as gzip */
106#define XZ_CMD		"xz"		/* command to run as xz */
107#define COMPRESS_CMD	"compress"	/* command to run as compress */
108
109/*
110 * Long options.
111 */
112#define	OPT_USE_COMPRESS_PROGRAM	0
113#define	OPT_CHECKPOINT			1
114#define	OPT_UNLINK			2
115#define	OPT_HELP			3
116#define	OPT_ATIME_PRESERVE		4
117#define	OPT_IGNORE_FAILED_READ		5
118#define	OPT_REMOVE_FILES		6
119#define	OPT_NULL			7
120#define	OPT_TOTALS			8
121#define	OPT_VERSION			9
122#define	OPT_EXCLUDE			10
123#define	OPT_BLOCK_COMPRESS		11
124#define	OPT_NORECURSE			12
125#define	OPT_FORCE_LOCAL			13
126#define	OPT_INSECURE			14
127#define	OPT_STRICT			15
128#define	OPT_SPARSE			16
129#define OPT_XZ				17
130#if !HAVE_NBTOOL_CONFIG_H
131#define	OPT_CHROOT			18
132#endif
133
134/*
135 *	Format specific routine table - MUST BE IN SORTED ORDER BY NAME
136 *	(see pax.h for description of each function)
137 *
138 *	name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
139 *	read, end_read, st_write, write, end_write, trail,
140 *	subtrail, rd_data, wr_data, options
141 */
142
143FSUB fsub[] = {
144#ifndef NO_CPIO
145/* 0: OLD BINARY CPIO */
146	{ "bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
147	bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, NULL,
148	cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
149
150/* 1: OLD OCTAL CHARACTER CPIO */
151	{ "cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
152	cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, NULL,
153	cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
154
155/* 2: SVR4 HEX CPIO */
156	{ "sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd,
157	vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, NULL,
158	cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
159
160/* 3: SVR4 HEX CPIO WITH CRC */
161	{ "sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
162	vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, NULL,
163	cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
164#endif
165/* 4: OLD TAR */
166	{ "tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
167	tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail,
168	NULL, rd_wrfile, wr_rdfile, tar_opt },
169
170/* 5: POSIX USTAR */
171	{ "ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd,
172	ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail,
173	NULL, rd_wrfile, wr_rdfile, bad_opt }
174};
175#ifndef NO_CPIO
176#define F_BCPIO		0	/* old binary cpio format */
177#define F_CPIO		1	/* old octal character cpio format */
178#define F_SV4CPIO	2	/* SVR4 hex cpio format */
179#define F_SV4CRC	3	/* SVR4 hex with crc cpio format */
180#define F_TAR		4	/* old V7 UNIX tar format */
181#define F_USTAR		5	/* ustar format */
182#else
183#define F_TAR		0	/* old V7 UNIX tar format */
184#define F_USTAR		1	/* ustar format */
185#endif
186#define DEFLT		F_USTAR	/* default write format from list above */
187
188/*
189 * ford is the archive search order used by get_arc() to determine what kind
190 * of archive we are dealing with. This helps to properly id archive formats
191 * some formats may be subsets of others....
192 */
193int ford[] = {F_USTAR, F_TAR,
194#ifndef NO_CPIO
195    F_SV4CRC, F_SV4CPIO, F_CPIO, F_BCPIO,
196#endif
197    -1};
198
199/*
200 * filename record separator
201 */
202int sep = '\n';
203
204/*
205 * Do we have -C anywhere?
206 */
207int havechd = 0;
208
209/*
210 * options()
211 *	figure out if we are pax, tar or cpio. Call the appropriate options
212 *	parser
213 */
214
215void
216options(int argc, char **argv)
217{
218
219	/*
220	 * Are we acting like pax, tar or cpio (based on argv[0])
221	 */
222	if ((argv0 = strrchr(argv[0], '/')) != NULL)
223		argv0++;
224	else
225		argv0 = argv[0];
226
227	if (strstr(argv0, NM_TAR)) {
228		argv0 = NM_TAR;
229		tar_options(argc, argv);
230#ifndef NO_CPIO
231	} else if (strstr(argv0, NM_CPIO)) {
232		argv0 = NM_CPIO;
233		cpio_options(argc, argv);
234#endif
235	} else {
236		argv0 = NM_PAX;
237		pax_options(argc, argv);
238	}
239}
240
241struct option pax_longopts[] = {
242	{ "insecure",		no_argument,		0,
243						OPT_INSECURE },
244	{ "force-local",	no_argument,		0,
245						OPT_FORCE_LOCAL },
246	{ "use-compress-program", required_argument,	0,
247						OPT_USE_COMPRESS_PROGRAM },
248	{ "xz",			no_argument,		0,
249						OPT_XZ },
250	{ 0,			0,			0,
251						0 },
252};
253
254/*
255 * pax_options()
256 *	look at the user specified flags. set globals as required and check if
257 *	the user specified a legal set of flags. If not, complain and exit
258 */
259
260static void
261pax_options(int argc, char **argv)
262{
263	int c;
264	size_t i;
265	u_int64_t flg = 0;
266	u_int64_t bflg = 0;
267	char *pt;
268	FSUB tmp;
269
270	/*
271	 * process option flags
272	 */
273	while ((c = getopt_long(argc, argv,
274	    "0ab:cdf:ijklno:p:rs:tuvwx:zAB:DE:G:HLMN:OPT:U:VXYZ",
275	    pax_longopts, NULL)) != -1) {
276		switch (c) {
277		case '0':
278			sep = '\0';
279			break;
280		case 'a':
281			/*
282			 * append
283			 */
284			flg |= AF;
285			break;
286		case 'b':
287			/*
288			 * specify blocksize
289			 */
290			flg |= BF;
291			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
292				tty_warn(1, "Invalid block size %s", optarg);
293				pax_usage();
294			}
295			break;
296		case 'c':
297			/*
298			 * inverse match on patterns
299			 */
300			cflag = 1;
301			flg |= CF;
302			break;
303		case 'd':
304			/*
305			 * match only dir on extract, not the subtree at dir
306			 */
307			dflag = 1;
308			flg |= DF;
309			break;
310		case 'f':
311			/*
312			 * filename where the archive is stored
313			 */
314			arcname = optarg;
315			flg |= FF;
316			break;
317		case 'i':
318			/*
319			 * interactive file rename
320			 */
321			iflag = 1;
322			flg |= IF;
323			break;
324		case 'j':
325			/*
326			 * pass through bzip2
327			 */
328			gzip_program = BZIP2_CMD;
329			break;
330		case 'k':
331			/*
332			 * do not clobber files that exist
333			 */
334			kflag = 1;
335			flg |= KF;
336			break;
337		case 'l':
338			/*
339			 * try to link src to dest with copy (-rw)
340			 */
341			lflag = 1;
342			flg |= LF;
343			break;
344		case 'n':
345			/*
346			 * select first match for a pattern only
347			 */
348			nflag = 1;
349			flg |= NF;
350			break;
351		case 'o':
352			/*
353			 * pass format specific options
354			 */
355			flg |= OF;
356			if (opt_add(optarg) < 0)
357				pax_usage();
358			break;
359		case 'p':
360			/*
361			 * specify file characteristic options
362			 */
363			for (pt = optarg; *pt != '\0'; ++pt) {
364				switch(*pt) {
365				case 'a':
366					/*
367					 * do not preserve access time
368					 */
369					patime = 0;
370					break;
371				case 'e':
372					/*
373					 * preserve user id, group id, file
374					 * mode, access/modification times
375					 * and file flags.
376					 */
377					pids = 1;
378					pmode = 1;
379					patime = 1;
380					pmtime = 1;
381					pfflags = 1;
382					break;
383#if 0
384				case 'f':
385					/*
386					 * do not preserve file flags
387					 */
388					pfflags = 0;
389					break;
390#endif
391				case 'm':
392					/*
393					 * do not preserve modification time
394					 */
395					pmtime = 0;
396					break;
397				case 'o':
398					/*
399					 * preserve uid/gid
400					 */
401					pids = 1;
402					break;
403				case 'p':
404					/*
405					 * preserve file mode bits
406					 */
407					pmode = 1;
408					break;
409				default:
410					tty_warn(1, "Invalid -p string: %c",
411					    *pt);
412					pax_usage();
413					break;
414				}
415			}
416			flg |= PF;
417			break;
418		case 'r':
419			/*
420			 * read the archive
421			 */
422			flg |= RF;
423			break;
424		case 's':
425			/*
426			 * file name substitution name pattern
427			 */
428			if (rep_add(optarg) < 0) {
429				pax_usage();
430				break;
431			}
432			flg |= SF;
433			break;
434		case 't':
435			/*
436			 * preserve access time on filesystem nodes we read
437			 */
438			tflag = 1;
439			flg |= TF;
440			break;
441		case 'u':
442			/*
443			 * ignore those older files
444			 */
445			uflag = 1;
446			flg |= UF;
447			break;
448		case 'v':
449			/*
450			 * verbose operation mode
451			 */
452			vflag = 1;
453			flg |= VF;
454			break;
455		case 'w':
456			/*
457			 * write an archive
458			 */
459			flg |= WF;
460			break;
461		case 'x':
462			/*
463			 * specify an archive format on write
464			 */
465			tmp.name = optarg;
466			frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
467			    sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt);
468			if (frmt != NULL) {
469				flg |= XF;
470				break;
471			}
472			tty_warn(1, "Unknown -x format: %s", optarg);
473			(void)fputs("pax: Known -x formats are:", stderr);
474			for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
475				(void)fprintf(stderr, " %s", fsub[i].name);
476			(void)fputs("\n\n", stderr);
477			pax_usage();
478			break;
479		case 'z':
480			/*
481			 * use gzip.  Non standard option.
482			 */
483			gzip_program = GZIP_CMD;
484			break;
485		case 'A':
486			Aflag = 1;
487			flg |= CAF;
488			break;
489		case 'B':
490			/*
491			 * non-standard option on number of bytes written on a
492			 * single archive volume.
493			 */
494			if ((wrlimit = str_offt(optarg)) <= 0) {
495				tty_warn(1, "Invalid write limit %s", optarg);
496				pax_usage();
497			}
498			if (wrlimit % BLKMULT) {
499				tty_warn(1,
500				    "Write limit is not a %d byte multiple",
501				    BLKMULT);
502				pax_usage();
503			}
504			flg |= CBF;
505			break;
506		case 'D':
507			/*
508			 * On extraction check file inode change time before the
509			 * modification of the file name. Non standard option.
510			 */
511			Dflag = 1;
512			flg |= CDF;
513			break;
514		case 'E':
515			/*
516			 * non-standard limit on read faults
517			 * 0 indicates stop after first error, values
518			 * indicate a limit, "none" try forever
519			 */
520			flg |= CEF;
521			if (strcmp(none, optarg) == 0)
522				maxflt = -1;
523			else if ((maxflt = atoi(optarg)) < 0) {
524				tty_warn(1,
525				    "Error count value must be positive");
526				pax_usage();
527			}
528			break;
529		case 'G':
530			/*
531			 * non-standard option for selecting files within an
532			 * archive by group (gid or name)
533			 */
534			if (grp_add(optarg) < 0) {
535				pax_usage();
536				break;
537			}
538			flg |= CGF;
539			break;
540		case 'H':
541			/*
542			 * follow command line symlinks only
543			 */
544			Hflag = 1;
545			flg |= CHF;
546			break;
547		case 'L':
548			/*
549			 * follow symlinks
550			 */
551			Lflag = 1;
552			flg |= CLF;
553			break;
554#ifdef SMALL
555		case 'M':
556		case 'N':
557			tty_warn(1, "Support for -%c is not compiled in", c);
558			exit(1);
559#else	/* !SMALL */
560		case 'M':
561			/*
562			 * Treat list of filenames on stdin as an
563			 * mtree(8) specfile.  Non standard option.
564			 */
565			Mflag = 1;
566			flg |= CMF;
567			break;
568		case 'N':
569			/*
570			 * Use alternative directory for user db lookups.
571			 */
572			if (!setup_getid(optarg)) {
573				tty_warn(1,
574			    "Unable to use user and group databases in `%s'",
575				    optarg);
576				pax_usage();
577			}
578			break;
579#endif	/* !SMALL */
580		case 'O':
581			/*
582			 * Force one volume.  Non standard option.
583			 */
584			force_one_volume = 1;
585			break;
586		case 'P':
587			/*
588			 * do NOT follow symlinks (default)
589			 */
590			Lflag = 0;
591			flg |= CPF;
592			break;
593		case 'T':
594			/*
595			 * non-standard option for selecting files within an
596			 * archive by modification time range (lower,upper)
597			 */
598			if (trng_add(optarg) < 0) {
599				pax_usage();
600				break;
601			}
602			flg |= CTF;
603			break;
604		case 'U':
605			/*
606			 * non-standard option for selecting files within an
607			 * archive by user (uid or name)
608			 */
609			if (usr_add(optarg) < 0) {
610				pax_usage();
611				break;
612			}
613			flg |= CUF;
614			break;
615		case 'V':
616			/*
617			 * somewhat verbose operation mode (no listing)
618			 */
619			Vflag = 1;
620			flg |= VSF;
621			break;
622		case 'X':
623			/*
624			 * do not pass over mount points in the file system
625			 */
626			Xflag = 1;
627			flg |= CXF;
628			break;
629		case 'Y':
630			/*
631			 * On extraction check file inode change time after the
632			 * modification of the file name. Non standard option.
633			 */
634			Yflag = 1;
635			flg |= CYF;
636			break;
637		case 'Z':
638			/*
639			 * On extraction check modification time after the
640			 * modification of the file name. Non standard option.
641			 */
642			Zflag = 1;
643			flg |= CZF;
644			break;
645		case OPT_INSECURE:
646			secure = 0;
647			break;
648		case OPT_FORCE_LOCAL:
649			forcelocal = 1;
650			break;
651		case OPT_USE_COMPRESS_PROGRAM:
652			gzip_program = optarg;
653			break;
654		case OPT_XZ:
655			gzip_program = XZ_CMD;
656			break;
657		case '?':
658		default:
659			pax_usage();
660			break;
661		}
662	}
663
664	/*
665	 * figure out the operation mode of pax read,write,extract,copy,append
666	 * or list. check that we have not been given a bogus set of flags
667	 * for the operation mode.
668	 */
669	if (ISLIST(flg)) {
670		act = LIST;
671		listf = stdout;
672		bflg = flg & BDLIST;
673	} else if (ISEXTRACT(flg)) {
674		act = EXTRACT;
675		bflg = flg & BDEXTR;
676	} else if (ISARCHIVE(flg)) {
677		act = ARCHIVE;
678		bflg = flg & BDARCH;
679	} else if (ISAPPND(flg)) {
680		act = APPND;
681		bflg = flg & BDARCH;
682	} else if (ISCOPY(flg)) {
683		act = COPY;
684		bflg = flg & BDCOPY;
685	} else
686		pax_usage();
687	if (bflg) {
688		printflg(flg);
689		pax_usage();
690	}
691
692	/*
693	 * if we are writing (ARCHIVE) we use the default format if the user
694	 * did not specify a format. when we write during an APPEND, we will
695	 * adopt the format of the existing archive if none was supplied.
696	 */
697	if (!(flg & XF) && (act == ARCHIVE))
698		frmt = &(fsub[DEFLT]);
699
700	/*
701	 * process the args as they are interpreted by the operation mode
702	 */
703	switch (act) {
704	case LIST:
705	case EXTRACT:
706		for (; optind < argc; optind++)
707			if (pat_add(argv[optind], NULL, 0) < 0)
708				pax_usage();
709		break;
710	case COPY:
711		if (optind >= argc) {
712			tty_warn(0, "Destination directory was not supplied");
713			pax_usage();
714		}
715		--argc;
716		dirptr = argv[argc];
717		if (mkpath(dirptr) < 0)
718			exit(1);
719		/* FALLTHROUGH */
720	case ARCHIVE:
721	case APPND:
722		for (; optind < argc; optind++)
723			if (ftree_add(argv[optind], 0) < 0)
724				pax_usage();
725		/*
726		 * no read errors allowed on updates/append operation!
727		 */
728		maxflt = 0;
729		break;
730	}
731}
732
733
734/*
735 * tar_options()
736 *	look at the user specified flags. set globals as required and check if
737 *	the user specified a legal set of flags. If not, complain and exit
738 */
739
740struct option tar_longopts[] = {
741	{ "block-size",		required_argument,	0,	'b' },
742	{ "bunzip2",		no_argument,		0,	'j' },
743	{ "bzip2",		no_argument,		0,	'j' },
744	{ "create",		no_argument,		0,	'c' },	/* F */
745	/* -e -- no corresponding long option */
746	{ "file",		required_argument,	0,	'f' },
747	{ "dereference",	no_argument,		0,	'h' },
748	{ "keep-old-files",	no_argument,		0,	'k' },
749	{ "one-file-system",	no_argument,		0,	'l' },
750	{ "modification-time",	no_argument,		0,	'm' },
751	{ "old-archive",	no_argument,		0,	'o' },
752	{ "portability",	no_argument,		0,	'o' },
753	{ "same-permissions",	no_argument,		0,	'p' },
754	{ "preserve-permissions", no_argument,		0,	'p' },
755	{ "preserve",		no_argument,		0,	'p' },
756	{ "fast-read",		no_argument,		0,	'q' },
757	{ "append",		no_argument,		0,	'r' },	/* F */
758	{ "update",		no_argument,		0,	'u' },	/* F */
759	{ "list",		no_argument,		0,	't' },	/* F */
760	{ "verbose",		no_argument,		0,	'v' },
761	{ "interactive",	no_argument,		0,	'w' },
762	{ "confirmation",	no_argument,		0,	'w' },
763	{ "extract",		no_argument,		0,	'x' },	/* F */
764	{ "get",		no_argument,		0,	'x' },	/* F */
765	{ "gzip",		no_argument,		0,	'z' },
766	{ "gunzip",		no_argument,		0,	'z' },
767	{ "read-full-blocks",	no_argument,		0,	'B' },
768	{ "directory",		required_argument,	0,	'C' },
769	{ "to-stdout",		no_argument,		0,	'O' },
770	{ "absolute-paths",	no_argument,		0,	'P' },
771	{ "sparse",		no_argument,		0,	'S' },
772	{ "files-from",		required_argument,	0,	'T' },
773	{ "summary",		no_argument,		0,	'V' },
774	{ "stats",		no_argument,		0,	'V' },
775	{ "exclude-from",	required_argument,	0,	'X' },
776	{ "compress",		no_argument,		0,	'Z' },
777	{ "uncompress",		no_argument,		0,	'Z' },
778	{ "strict",		no_argument,		0,
779						OPT_STRICT },
780	{ "atime-preserve",	no_argument,		0,
781						OPT_ATIME_PRESERVE },
782	{ "unlink",		no_argument,		0,
783						OPT_UNLINK },
784	{ "use-compress-program", required_argument,	0,
785						OPT_USE_COMPRESS_PROGRAM },
786	{ "force-local",	no_argument,		0,
787						OPT_FORCE_LOCAL },
788	{ "insecure",		no_argument,		0,
789						OPT_INSECURE },
790	{ "exclude",		required_argument,	0,
791						OPT_EXCLUDE },
792	{ "no-recursion",	no_argument,		0,
793						OPT_NORECURSE },
794	{ "xz",			no_argument,		0,
795						OPT_XZ },
796#if !HAVE_NBTOOL_CONFIG_H
797	{ "chroot",		no_argument,		0,
798						OPT_CHROOT },
799#endif
800#if 0 /* Not implemented */
801	{ "catenate",		no_argument,		0,	'A' },	/* F */
802	{ "concatenate",	no_argument,		0,	'A' },	/* F */
803	{ "diff",		no_argument,		0,	'd' },	/* F */
804	{ "compare",		no_argument,		0,	'd' },	/* F */
805	{ "checkpoint",		no_argument,		0,
806						OPT_CHECKPOINT },
807	{ "help",		no_argument,		0,
808						OPT_HELP },
809	{ "info-script",	required_argument,	0,	'F' },
810	{ "new-volume-script",	required_argument,	0,	'F' },
811	{ "incremental",	no_argument,		0,	'G' },
812	{ "listed-incremental",	required_argument,	0,	'g' },
813	{ "ignore-zeros",	no_argument,		0,	'i' },
814	{ "ignore-failed-read",	no_argument,		0,
815						OPT_IGNORE_FAILED_READ },
816	{ "starting-file",	no_argument,		0,	'K' },
817	{ "tape-length",	required_argument,	0,	'L' },
818	{ "multi-volume",	no_argument,		0,	'M' },
819	{ "after-date",		required_argument,	0,	'N' },
820	{ "newer",		required_argument,	0,	'N' },
821	{ "record-number",	no_argument,		0,	'R' },
822	{ "remove-files",	no_argument,		0,
823						OPT_REMOVE_FILES },
824	{ "same-order",		no_argument,		0,	's' },
825	{ "preserve-order",	no_argument,		0,	's' },
826	{ "null",		no_argument,		0,
827						OPT_NULL },
828	{ "totals",		no_argument,		0,
829						OPT_TOTALS },
830	{ "volume-name",	required_argument,	0,	'V' }, /* XXX */
831	{ "label",		required_argument,	0,	'V' }, /* XXX */
832	{ "version",		no_argument,		0,
833						OPT_VERSION },
834	{ "verify",		no_argument,		0,	'W' },
835	{ "block-compress",	no_argument,		0,
836						OPT_BLOCK_COMPRESS },
837#endif
838	{ 0,			0,			0,	0 },
839};
840
841static void
842tar_set_action(int op)
843{
844	if (act != ERROR && act != op)
845		tar_usage();
846	act = op;
847}
848
849static void
850tar_options(int argc, char **argv)
851{
852	int c;
853	int fstdin = 0;
854	int Oflag = 0;
855	int nincfiles = 0;
856	int incfiles_max = 0;
857	struct incfile {
858		char *file;
859		char *dir;
860	};
861	struct incfile *incfiles = NULL;
862
863	/*
864	 * Set default values.
865	 */
866	rmleadslash = 1;
867	is_gnutar = 1;
868
869	/*
870	 * process option flags
871	 */
872	while ((c = getoldopt(argc, argv,
873	    "+b:cef:hjklmopqrs:tuvwxzBC:HI:OPST:X:Z014578",
874	    tar_longopts, NULL))
875	    != -1)  {
876		switch(c) {
877		case 'b':
878			/*
879			 * specify blocksize in 512-byte blocks
880			 */
881			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
882				tty_warn(1, "Invalid block size %s", optarg);
883				tar_usage();
884			}
885			wrblksz *= 512;		/* XXX - check for int oflow */
886			break;
887		case 'c':
888			/*
889			 * create an archive
890			 */
891			tar_set_action(ARCHIVE);
892			break;
893		case 'e':
894			/*
895			 * stop after first error
896			 */
897			maxflt = 0;
898			break;
899		case 'f':
900			/*
901			 * filename where the archive is stored
902			 */
903			if ((optarg[0] == '-') && (optarg[1]== '\0')) {
904				/*
905				 * treat a - as stdin
906				 */
907				fstdin = 1;
908				arcname = NULL;
909				break;
910			}
911			fstdin = 0;
912			arcname = optarg;
913			break;
914		case 'h':
915			/*
916			 * follow symlinks
917			 */
918			Lflag = 1;
919			break;
920		case 'j':
921			/*
922			 * pass through bzip2. not a standard option
923			 */
924			gzip_program = BZIP2_CMD;
925			break;
926		case 'k':
927			/*
928			 * do not clobber files that exist
929			 */
930			kflag = 1;
931			break;
932		case 'l':
933			/*
934			 * do not pass over mount points in the file system
935			 */
936			Xflag = 1;
937			break;
938		case 'm':
939			/*
940			 * do not preserve modification time
941			 */
942			pmtime = 0;
943			break;
944		case 'o':
945			/*
946			 * This option does several things based on whether
947			 * this is a create or extract operation.
948			 */
949			if (act == ARCHIVE) {
950				/* GNU tar: write V7 format archives. */
951				Oflag = 1;
952				/* 4.2BSD: don't add directory entries. */
953				if (opt_add("write_opt=nodir") < 0)
954					tar_usage();
955
956			} else {
957				/* SUS: don't preserve owner/group. */
958				pids = 0;
959				nopids = 1;
960			}
961			break;
962		case 'O':
963			Oflag = 1;
964			break;
965		case 'p':
966			/*
967			 * preserve user id, group id, file
968			 * mode, access/modification times
969			 */
970			if (!nopids)
971				pids = 1;
972			pmode = 1;
973			patime = 1;
974			pmtime = 1;
975			break;
976		case 'q':
977			/*
978			 * select first match for a pattern only
979			 */
980			nflag = 1;
981			break;
982		case 'r':
983		case 'u':
984			/*
985			 * append to the archive
986			 */
987			tar_set_action(APPND);
988			break;
989		case 's':
990			/*
991			 * file name substitution name pattern
992			 */
993			if (rep_add(optarg) < 0) {
994				tar_usage();
995				break;
996			}
997			break;
998		case 't':
999			/*
1000			 * list contents of the tape
1001			 */
1002			tar_set_action(LIST);
1003			break;
1004		case 'v':
1005			/*
1006			 * verbose operation mode
1007			 */
1008			vflag = 1;
1009			break;
1010		case 'w':
1011			/*
1012			 * interactive file rename
1013			 */
1014			iflag = 1;
1015			break;
1016		case 'x':
1017			/*
1018			 * extract an archive, preserving mode,
1019			 * and mtime if possible.
1020			 */
1021			tar_set_action(EXTRACT);
1022			pmtime = 1;
1023			break;
1024		case 'z':
1025			/*
1026			 * use gzip.  Non standard option.
1027			 */
1028			gzip_program = GZIP_CMD;
1029			break;
1030		case 'B':
1031			/*
1032			 * Nothing to do here, this is pax default
1033			 */
1034			break;
1035		case 'C':
1036			havechd++;
1037			chdname = optarg;
1038			break;
1039		case 'H':
1040			/*
1041			 * follow command line symlinks only
1042			 */
1043			Hflag = 1;
1044			break;
1045		case 'I':
1046		case 'T':
1047			if (++nincfiles > incfiles_max) {
1048				incfiles_max = nincfiles + 3;
1049				incfiles = realloc(incfiles,
1050				    sizeof(*incfiles) * incfiles_max);
1051				if (incfiles == NULL) {
1052					tty_warn(0, "Unable to allocate space "
1053					    "for option list");
1054					exit(1);
1055				}
1056			}
1057			incfiles[nincfiles - 1].file = optarg;
1058			incfiles[nincfiles - 1].dir = chdname;
1059			break;
1060		case 'P':
1061			/*
1062			 * do not remove leading '/' from pathnames
1063			 */
1064			rmleadslash = 0;
1065			Aflag = 1;
1066			break;
1067		case 'S':
1068			/* do nothing; we already generate sparse files */
1069			break;
1070		case 'V':
1071			/*
1072			 * semi-verbose operation mode (no listing)
1073			 */
1074			Vflag = 1;
1075			break;
1076		case 'X':
1077			/*
1078			 * GNU tar compat: exclude the files listed in optarg
1079			 */
1080			if (tar_gnutar_X_compat(optarg) != 0)
1081				tar_usage();
1082			break;
1083		case 'Z':
1084			/*
1085			 * use compress.
1086			 */
1087			gzip_program = COMPRESS_CMD;
1088			break;
1089		case '0':
1090			arcname = DEV_0;
1091			break;
1092		case '1':
1093			arcname = DEV_1;
1094			break;
1095		case '4':
1096			arcname = DEV_4;
1097			break;
1098		case '5':
1099			arcname = DEV_5;
1100			break;
1101		case '7':
1102			arcname = DEV_7;
1103			break;
1104		case '8':
1105			arcname = DEV_8;
1106			break;
1107		case OPT_ATIME_PRESERVE:
1108			patime = 1;
1109			break;
1110		case OPT_UNLINK:
1111			/* Just ignore -- we always unlink first. */
1112			break;
1113		case OPT_USE_COMPRESS_PROGRAM:
1114			gzip_program = optarg;
1115			break;
1116		case OPT_FORCE_LOCAL:
1117			forcelocal = 1;
1118			break;
1119		case OPT_INSECURE:
1120			secure = 0;
1121			break;
1122		case OPT_STRICT:
1123			/* disable gnu extensions */
1124			is_gnutar = 0;
1125			break;
1126		case OPT_EXCLUDE:
1127			if (tar_gnutar_minus_minus_exclude(optarg) != 0)
1128				tar_usage();
1129			break;
1130		case OPT_NORECURSE:
1131			dflag = 1;
1132			break;
1133#if !HAVE_NBTOOL_CONFIG_H
1134		case OPT_CHROOT:
1135			do_chroot = 1;
1136			break;
1137#endif
1138		case OPT_XZ:
1139			gzip_program = XZ_CMD;
1140			break;
1141		default:
1142			tar_usage();
1143			break;
1144		}
1145	}
1146	argc -= optind;
1147	argv += optind;
1148
1149	/* Tar requires an action. */
1150	if (act == ERROR)
1151		tar_usage();
1152
1153	/* Traditional tar behaviour (pax uses stderr unless in list mode) */
1154	if (fstdin == 1 && act == ARCHIVE)
1155		listf = stderr;
1156	else
1157		listf = stdout;
1158
1159	/* Traditional tar behaviour (pax wants to read file list from stdin) */
1160	if ((act == ARCHIVE || act == APPND) && argc == 0 && nincfiles == 0)
1161		exit(0);
1162	/*
1163	 * if we are writing (ARCHIVE) specify tar, otherwise run like pax
1164	 * (unless -o specified)
1165	 */
1166	if (act == ARCHIVE || act == APPND)
1167		frmt = &(fsub[Oflag ? F_TAR : F_USTAR]);
1168	else if (Oflag) {
1169		if (act == EXTRACT)
1170			to_stdout = 1;
1171		else {
1172			tty_warn(1, "The -O/-o options are only valid when "
1173			    "writing or extracting an archive");
1174			tar_usage();
1175		}
1176	}
1177
1178	/*
1179	 * process the args as they are interpreted by the operation mode
1180	 */
1181	switch (act) {
1182	case LIST:
1183	case EXTRACT:
1184	default:
1185		{
1186			int sawpat = 0;
1187			int dirisnext = 0;
1188			char *file, *dir = NULL;
1189			int mustfreedir = 0;
1190
1191			while (nincfiles || *argv != NULL) {
1192				/*
1193				 * If we queued up any include files,
1194				 * pull them in now.  Otherwise, check
1195				 * for -I and -C positional flags.
1196				 * Anything else must be a file to
1197				 * extract.
1198				 */
1199				if (nincfiles) {
1200					file = incfiles->file;
1201					dir = incfiles->dir;
1202					mustfreedir = 0;
1203					incfiles++;
1204					nincfiles--;
1205				} else if (strcmp(*argv, "-I") == 0) {
1206					if (*++argv == NULL)
1207						break;
1208					file = *argv++;
1209					dir = chdname;
1210					mustfreedir = 0;
1211				} else {
1212					file = NULL;
1213					dir = NULL;
1214					mustfreedir = 0;
1215				}
1216				if (file != NULL) {
1217					FILE *fp;
1218					char *str;
1219
1220					if (strcmp(file, "-") == 0)
1221						fp = stdin;
1222					else if ((fp = fopen(file, "r")) == NULL) {
1223						tty_warn(1, "Unable to open file '%s' for read", file);
1224						tar_usage();
1225					}
1226					while ((str = get_line(fp)) != NULL) {
1227						if (dirisnext) {
1228							if (dir && mustfreedir)
1229								free(dir);
1230							dir = str;
1231							mustfreedir = 1;
1232							dirisnext = 0;
1233							continue;
1234						}
1235						if (strcmp(str, "-C") == 0) {
1236							havechd++;
1237							dirisnext = 1;
1238							free(str);
1239							continue;
1240						}
1241						if (strncmp(str, "-C ", 3) == 0) {
1242							havechd++;
1243							if (dir && mustfreedir)
1244								free(dir);
1245							dir = strdup(str + 3);
1246							mustfreedir = 1;
1247							free(str);
1248							continue;
1249						}
1250						if (pat_add(str, dir, NOGLOB_MTCH) < 0)
1251							tar_usage();
1252						sawpat = 1;
1253					}
1254					/* Bomb if given -C w/out a dir. */
1255					if (dirisnext)
1256						tar_usage();
1257					if (dir && mustfreedir)
1258						free(dir);
1259					if (strcmp(file, "-") != 0)
1260						fclose(fp);
1261					if (get_line_error) {
1262						tty_warn(1, "Problem with file '%s'", file);
1263						tar_usage();
1264					}
1265				} else if (strcmp(*argv, "-C") == 0) {
1266					if (*++argv == NULL)
1267 						break;
1268					chdname = *argv++;
1269					havechd++;
1270				} else if (pat_add(*argv++, chdname, 0) < 0)
1271					tar_usage();
1272				else
1273					sawpat = 1;
1274			}
1275			/*
1276			 * if patterns were added, we are doing	chdir()
1277			 * on a file-by-file basis, else, just one
1278			 * global chdir (if any) after opening input.
1279			 */
1280			if (sawpat > 0)
1281				chdname = NULL;
1282		}
1283		break;
1284	case ARCHIVE:
1285	case APPND:
1286		if (chdname != NULL) {	/* initial chdir() */
1287			if (ftree_add(chdname, 1) < 0)
1288				tar_usage();
1289		}
1290
1291		while (nincfiles || *argv != NULL) {
1292			char *file, *dir;
1293
1294			/*
1295			 * If we queued up any include files, pull them in
1296			 * now.  Otherwise, check for -I and -C positional
1297			 * flags.  Anything else must be a file to include
1298			 * in the archive.
1299			 */
1300			if (nincfiles) {
1301				file = incfiles->file;
1302				dir = incfiles->dir;
1303				incfiles++;
1304				nincfiles--;
1305			} else if (strcmp(*argv, "-I") == 0) {
1306				if (*++argv == NULL)
1307					break;
1308				file = *argv++;
1309				dir = NULL;
1310			} else {
1311				file = NULL;
1312				dir = NULL;
1313			}
1314			if (file != NULL) {
1315				FILE *fp;
1316				char *str;
1317				int dirisnext = 0;
1318
1319				/* Set directory if needed */
1320				if (dir) {
1321					if (ftree_add(dir, 1) < 0)
1322						tar_usage();
1323				}
1324
1325				if (strcmp(file, "-") == 0)
1326					fp = stdin;
1327				else if ((fp = fopen(file, "r")) == NULL) {
1328					tty_warn(1, "Unable to open file '%s' for read", file);
1329					tar_usage();
1330				}
1331				while ((str = get_line(fp)) != NULL) {
1332					if (dirisnext) {
1333						if (ftree_add(str, 1) < 0)
1334							tar_usage();
1335						dirisnext = 0;
1336						continue;
1337					}
1338					if (strcmp(str, "-C") == 0) {
1339						dirisnext = 1;
1340						continue;
1341					}
1342					if (strncmp(str, "-C ", 3) == 0) {
1343						if (ftree_add(str + 3, 1) < 0)
1344							tar_usage();
1345						continue;
1346					}
1347					if (ftree_add(str, 0) < 0)
1348						tar_usage();
1349				}
1350				/* Bomb if given -C w/out a dir. */
1351				if (dirisnext)
1352					tar_usage();
1353				if (strcmp(file, "-") != 0)
1354					fclose(fp);
1355				if (get_line_error) {
1356					tty_warn(1, "Problem with file '%s'",
1357					    file);
1358					tar_usage();
1359				}
1360			} else if (strcmp(*argv, "-C") == 0) {
1361				if (*++argv == NULL)
1362					break;
1363				if (ftree_add(*argv++, 1) < 0)
1364					tar_usage();
1365			} else if (ftree_add(*argv++, 0) < 0)
1366				tar_usage();
1367		}
1368		/*
1369		 * no read errors allowed on updates/append operation!
1370		 */
1371		maxflt = 0;
1372		break;
1373	}
1374	if (!fstdin && ((arcname == NULL) || (*arcname == '\0'))) {
1375		arcname = getenv("TAPE");
1376		if ((arcname == NULL) || (*arcname == '\0'))
1377			arcname = _PATH_DEFTAPE;
1378	}
1379}
1380
1381int
1382mkpath(path)
1383	char *path;
1384{
1385	char *slash;
1386	int done = 0;
1387
1388	slash = path;
1389
1390	while (!done) {
1391		slash += strspn(slash, "/");
1392		slash += strcspn(slash, "/");
1393
1394		done = (*slash == '\0');
1395		*slash = '\0';
1396
1397		if (domkdir(path, 0777) == -1)
1398			goto out;
1399
1400		if (!done)
1401			*slash = '/';
1402	}
1403
1404	return 0;
1405out:
1406	/* Can't create or or not a directory */
1407	syswarn(1, errno, "Cannot create directory `%s'", path);
1408	return -1;
1409}
1410
1411
1412#ifndef NO_CPIO
1413struct option cpio_longopts[] = {
1414	{ "reset-access-time",	no_argument,		0,	'a' },
1415	{ "make-directories",	no_argument,		0, 	'd' },
1416	{ "nonmatching",	no_argument,		0,	'f' },
1417	{ "extract",		no_argument,		0,	'i' },
1418	{ "link",		no_argument,		0,	'l' },
1419	{ "preserve-modification-time", no_argument,	0,	'm' },
1420	{ "create",		no_argument,		0,	'o' },
1421	{ "pass-through",	no_argument,		0,	'p' },
1422	{ "rename",		no_argument,		0,	'r' },
1423	{ "list",		no_argument,		0,	't' },
1424	{ "unconditional",	no_argument,		0,	'u' },
1425	{ "verbose",		no_argument,		0,	'v' },
1426	{ "append",		no_argument,		0,	'A' },
1427	{ "pattern-file",	required_argument,	0,	'E' },
1428	{ "file",		required_argument,	0,	'F' },
1429	{ "force-local",	no_argument,		0,
1430						OPT_FORCE_LOCAL },
1431	{ "format",		required_argument,	0,	'H' },
1432	{ "dereference",	no_argument,		0,	'L' },
1433	{ "swap-halfwords",	no_argument,		0,	'S' },
1434	{ "summary",		no_argument,		0,	'V' },
1435	{ "stats",		no_argument,		0,	'V' },
1436	{ "insecure",		no_argument,		0,
1437						OPT_INSECURE },
1438	{ "sparse",		no_argument,		0,
1439						OPT_SPARSE },
1440	{ "xz",			no_argument,		0,
1441						OPT_XZ },
1442
1443#ifdef notyet
1444/* Not implemented */
1445	{ "null",		no_argument,		0,	'0' },
1446	{ "swap",		no_argument,		0,	'b' },
1447	{ "numeric-uid-gid",	no_argument,		0,	'n' },
1448	{ "swap-bytes",		no_argument,		0,	's' },
1449	{ "message",		required_argument,	0,	'M' },
1450	{ "owner",		required_argument,	0	'R' },
1451	{ "dot",		no_argument,		0,	'V' }, /* xxx */
1452	{ "block-size",		required_argument,	0,
1453						OPT_BLOCK_SIZE },
1454	{ "no-absolute-pathnames", no_argument,		0,
1455						OPT_NO_ABSOLUTE_PATHNAMES },
1456	{ "no-preserve-owner",	no_argument,		0,
1457						OPT_NO_PRESERVE_OWNER },
1458	{ "only-verify-crc",	no_argument,		0,
1459						OPT_ONLY_VERIFY_CRC },
1460	{ "rsh-command",	required_argument,	0,
1461						OPT_RSH_COMMAND },
1462	{ "version",		no_argument,		0,
1463						OPT_VERSION },
1464#endif
1465	{ 0,			0,			0,	0 },
1466};
1467
1468static void
1469cpio_set_action(int op)
1470{
1471	if ((act == APPND && op == ARCHIVE) || (act == ARCHIVE && op == APPND))
1472		act = APPND;
1473	else if (act == EXTRACT && op == LIST)
1474		act = op;
1475	else if (act != ERROR && act != op)
1476		cpio_usage();
1477	else
1478		act = op;
1479}
1480
1481/*
1482 * cpio_options()
1483 *	look at the user specified flags. set globals as required and check if
1484 *	the user specified a legal set of flags. If not, complain and exit
1485 */
1486
1487static void
1488cpio_options(int argc, char **argv)
1489{
1490	FSUB tmp;
1491	u_int64_t flg = 0;
1492	u_int64_t bflg = 0;
1493	int c;
1494	size_t i;
1495	FILE *fp;
1496	char *str;
1497
1498	uflag = 1;
1499	kflag = 1;
1500	pids = 1;
1501	pmode = 1;
1502	pmtime = 0;
1503	arcname = NULL;
1504	dflag = 1;
1505	nodirs = 1;
1506	/*
1507	 * process option flags
1508	 */
1509	while ((c = getoldopt(argc, argv,
1510	    "+abcdfiklmoprstuvzABC:E:F:H:I:LM:O:R:SVZ6",
1511	    cpio_longopts, NULL)) != -1) {
1512		switch(c) {
1513		case 'a':
1514			/*
1515			 * preserve access time on filesystem nodes we read
1516			 */
1517			tflag = 1;
1518			flg |= TF;
1519			break;
1520#ifdef notyet
1521		case 'b':
1522			/*
1523			 * swap bytes and half-words when reading data
1524			 */
1525			break;
1526#endif
1527		case 'c':
1528			/*
1529			 * ASCII cpio header
1530			 */
1531			frmt = &fsub[F_SV4CPIO];
1532			break;
1533		case 'd':
1534			/*
1535			 * create directories as needed
1536			 * pax does this by default ..
1537			 */
1538			nodirs = 0;
1539			break;
1540		case 'f':
1541			/*
1542			 * inverse match on patterns
1543			 */
1544			cflag = 1;
1545			flg |= CF;
1546			break;
1547		case 'i':
1548			/*
1549			 * read the archive
1550			 */
1551			cpio_set_action(EXTRACT);
1552			flg |= RF;
1553			break;
1554#ifdef notyet
1555		case 'k':
1556			break;
1557#endif
1558		case 'l':
1559			/*
1560			 * try to link src to dest with copy (-rw)
1561			 */
1562			lflag = 1;
1563			flg |= LF;
1564			break;
1565		case 'm':
1566			/*
1567			 * preserve mtime
1568			 */
1569			flg |= PF;
1570			pmtime = 1;
1571			break;
1572		case 'o':
1573			/*
1574			 * write an archive
1575			 */
1576			cpio_set_action(ARCHIVE);
1577			frmt = &(fsub[F_SV4CRC]);
1578			flg |= WF;
1579			break;
1580		case 'p':
1581			/*
1582			 * cpio -p is like pax -rw
1583			 */
1584			cpio_set_action(COPY);
1585			flg |= RF | WF;
1586			break;
1587		case 'r':
1588			/*
1589			 * interactive file rename
1590			 */
1591			iflag = 1;
1592			flg |= IF;
1593			break;
1594#ifdef notyet
1595		case 's':
1596			/*
1597			 * swap bytes after reading data
1598			 */
1599			break;
1600#endif
1601		case 't':
1602			/*
1603			 * list contents of archive
1604			 */
1605			cpio_set_action(LIST);
1606			listf = stdout;
1607			flg &= ~RF;
1608			break;
1609		case 'u':
1610			/*
1611			 * don't ignore those older files
1612			 */
1613			uflag = 0;
1614			kflag = 0;
1615			flg |= UF;
1616			break;
1617		case 'v':
1618			/*
1619			 * verbose operation mode
1620			 */
1621			vflag = 1;
1622			flg |= VF;
1623			break;
1624		case 'z':
1625			/*
1626			 * use gzip.  Non standard option.
1627			 */
1628			gzip_program = GZIP_CMD;
1629			break;
1630		case 'A':
1631			/*
1632			 * append to an archive
1633			 */
1634			cpio_set_action(APPND);
1635			flg |= AF;
1636			break;
1637		case 'B':
1638			/*
1639			 * set blocksize to 5120
1640			 */
1641			blksz = 5120;
1642			break;
1643		case 'C':
1644			/*
1645			 * specify blocksize
1646			 */
1647			if ((blksz = (int)str_offt(optarg)) <= 0) {
1648				tty_warn(1, "Invalid block size %s", optarg);
1649				cpio_usage();
1650			}
1651			break;
1652		case 'E':
1653			/*
1654			 * file with patterns to extract or list
1655			 */
1656			if ((fp = fopen(optarg, "r")) == NULL) {
1657				tty_warn(1, "Unable to open file '%s' for read",
1658				    optarg);
1659				cpio_usage();
1660			}
1661			while ((str = get_line(fp)) != NULL) {
1662				pat_add(str, NULL, 0);
1663			}
1664			fclose(fp);
1665			if (get_line_error) {
1666				tty_warn(1, "Problem with file '%s'", optarg);
1667				cpio_usage();
1668			}
1669			break;
1670		case 'H':
1671			/*
1672			 * specify an archive format on write
1673			 */
1674			tmp.name = optarg;
1675			frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
1676			    sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt);
1677			if (frmt != NULL) {
1678				flg |= XF;
1679				break;
1680			}
1681			tty_warn(1, "Unknown -H format: %s", optarg);
1682			(void)fputs("cpio: Known -H formats are:", stderr);
1683			for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
1684				(void)fprintf(stderr, " %s", fsub[i].name);
1685			(void)fputs("\n\n", stderr);
1686			cpio_usage();
1687			break;
1688		case 'F':
1689		case 'I':
1690		case 'O':
1691			/*
1692			 * filename where the archive is stored
1693			 */
1694			if ((optarg[0] == '-') && (optarg[1]== '\0')) {
1695				/*
1696				 * treat a - as stdin
1697				 */
1698				arcname = NULL;
1699				break;
1700			}
1701			arcname = optarg;
1702			break;
1703		case 'L':
1704			/*
1705			 * follow symlinks
1706			 */
1707			Lflag = 1;
1708			flg |= CLF;
1709			break;
1710#ifdef notyet
1711		case 'M':
1712			arg = optarg;
1713			break;
1714		case 'R':
1715			arg = optarg;
1716			break;
1717#endif
1718		case 'S':
1719			/*
1720			 * swap halfwords after reading data
1721			 */
1722			cpio_swp_head = 1;
1723			break;
1724#ifdef notyet
1725		case 'V':		/* print a '.' for each file processed */
1726			break;
1727#endif
1728		case 'V':
1729			/*
1730			 * semi-verbose operation mode (no listing)
1731			 */
1732			Vflag = 1;
1733			flg |= VF;
1734			break;
1735		case 'Z':
1736			/*
1737			 * use compress.  Non standard option.
1738			 */
1739			gzip_program = COMPRESS_CMD;
1740			break;
1741		case '6':
1742			/*
1743			 * process Version 6 cpio format
1744			 */
1745			frmt = &(fsub[F_BCPIO]);
1746			break;
1747		case OPT_FORCE_LOCAL:
1748			forcelocal = 1;
1749			break;
1750		case OPT_INSECURE:
1751			secure = 0;
1752			break;
1753		case OPT_SPARSE:
1754			/* do nothing; we already generate sparse files */
1755			break;
1756		case OPT_XZ:
1757			gzip_program = XZ_CMD;
1758			break;
1759		default:
1760			cpio_usage();
1761			break;
1762		}
1763	}
1764
1765	/*
1766	 * figure out the operation mode of cpio. check that we have not been
1767	 * given a bogus set of flags for the operation mode.
1768	 */
1769	if (ISLIST(flg)) {
1770		act = LIST;
1771		bflg = flg & BDLIST;
1772	} else if (ISEXTRACT(flg)) {
1773		act = EXTRACT;
1774		bflg = flg & BDEXTR;
1775	} else if (ISARCHIVE(flg)) {
1776		act = ARCHIVE;
1777		bflg = flg & BDARCH;
1778	} else if (ISAPPND(flg)) {
1779		act = APPND;
1780		bflg = flg & BDARCH;
1781	} else if (ISCOPY(flg)) {
1782		act = COPY;
1783		bflg = flg & BDCOPY;
1784	} else
1785		cpio_usage();
1786	if (bflg) {
1787		cpio_usage();
1788	}
1789
1790	/*
1791	 * if we are writing (ARCHIVE) we use the default format if the user
1792	 * did not specify a format. when we write during an APPEND, we will
1793	 * adopt the format of the existing archive if none was supplied.
1794	 */
1795	if (!(flg & XF) && (act == ARCHIVE))
1796		frmt = &(fsub[F_BCPIO]);
1797
1798	/*
1799	 * process the args as they are interpreted by the operation mode
1800	 */
1801	switch (act) {
1802	case LIST:
1803	case EXTRACT:
1804		for (; optind < argc; optind++)
1805			if (pat_add(argv[optind], NULL, 0) < 0)
1806				cpio_usage();
1807		break;
1808	case COPY:
1809		if (optind >= argc) {
1810			tty_warn(0, "Destination directory was not supplied");
1811			cpio_usage();
1812		}
1813		--argc;
1814		dirptr = argv[argc];
1815		/* FALLTHROUGH */
1816	case ARCHIVE:
1817	case APPND:
1818		if (argc != optind) {
1819			for (; optind < argc; optind++)
1820				if (ftree_add(argv[optind], 0) < 0)
1821					cpio_usage();
1822			break;
1823		}
1824		/*
1825		 * no read errors allowed on updates/append operation!
1826		 */
1827		maxflt = 0;
1828		while ((str = get_line(stdin)) != NULL) {
1829			ftree_add(str, 0);
1830		}
1831		if (get_line_error) {
1832			tty_warn(1, "Problem while reading stdin");
1833			cpio_usage();
1834		}
1835		break;
1836	default:
1837		cpio_usage();
1838		break;
1839	}
1840}
1841#endif
1842
1843/*
1844 * printflg()
1845 *	print out those invalid flag sets found to the user
1846 */
1847
1848static void
1849printflg(unsigned int flg)
1850{
1851	int nxt;
1852
1853	(void)fprintf(stderr,"%s: Invalid combination of options:", argv0);
1854	while ((nxt = ffs(flg)) != 0) {
1855		flg &= ~(1 << (nxt - 1));
1856		(void)fprintf(stderr, " -%c", flgch[nxt - 1]);
1857	}
1858	(void)putc('\n', stderr);
1859}
1860
1861/*
1862 * c_frmt()
1863 *	comparison routine used by bsearch to find the format specified
1864 *	by the user
1865 */
1866
1867static int
1868c_frmt(const void *a, const void *b)
1869{
1870	return strcmp(((const FSUB *)a)->name, ((const FSUB *)b)->name);
1871}
1872
1873/*
1874 * opt_next()
1875 *	called by format specific options routines to get each format specific
1876 *	flag and value specified with -o
1877 * Return:
1878 *	pointer to next OPLIST entry or NULL (end of list).
1879 */
1880
1881OPLIST *
1882opt_next(void)
1883{
1884	OPLIST *opt;
1885
1886	if ((opt = ophead) != NULL)
1887		ophead = ophead->fow;
1888	return opt;
1889}
1890
1891/*
1892 * bad_opt()
1893 *	generic routine used to complain about a format specific options
1894 *	when the format does not support options.
1895 */
1896
1897int
1898bad_opt(void)
1899{
1900	OPLIST *opt;
1901
1902	if (ophead == NULL)
1903		return 0;
1904	/*
1905	 * print all we were given
1906	 */
1907	tty_warn(1," These format options are not supported for %s",
1908	    frmt->name);
1909	while ((opt = opt_next()) != NULL)
1910		(void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
1911	if (strcmp(NM_TAR, argv0) == 0)
1912		tar_usage();
1913#ifndef NO_CPIO
1914	else if (strcmp(NM_CPIO, argv0) == 0)
1915		cpio_usage();
1916#endif
1917	else
1918		pax_usage();
1919	return 0;
1920}
1921
1922/*
1923 * opt_add()
1924 *	breaks the value supplied to -o into a option name and value. options
1925 *	are given to -o in the form -o name-value,name=value
1926 *	multiple -o may be specified.
1927 * Return:
1928 *	0 if format in name=value format, -1 if -o is passed junk
1929 */
1930
1931int
1932opt_add(const char *str)
1933{
1934	OPLIST *opt;
1935	char *frpt;
1936	char *pt;
1937	char *endpt;
1938	char *dstr;
1939
1940	if ((str == NULL) || (*str == '\0')) {
1941		tty_warn(0, "Invalid option name");
1942		return -1;
1943	}
1944	if ((dstr = strdup(str)) == NULL) {
1945		tty_warn(0, "Unable to allocate space for option list");
1946		return -1;
1947	}
1948	frpt = endpt = dstr;
1949
1950	/*
1951	 * break into name and values pieces and stuff each one into a
1952	 * OPLIST structure. When we know the format, the format specific
1953	 * option function will go through this list
1954	 */
1955	while ((frpt != NULL) && (*frpt != '\0')) {
1956		if ((endpt = strchr(frpt, ',')) != NULL)
1957			*endpt = '\0';
1958		if ((pt = strchr(frpt, '=')) == NULL) {
1959			tty_warn(0, "Invalid options format");
1960			free(dstr);
1961			return -1;
1962		}
1963		if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
1964			tty_warn(0, "Unable to allocate space for option list");
1965			free(dstr);
1966			return -1;
1967		}
1968		*pt++ = '\0';
1969		opt->name = frpt;
1970		opt->value = pt;
1971		opt->fow = NULL;
1972		if (endpt != NULL)
1973			frpt = endpt + 1;
1974		else
1975			frpt = NULL;
1976		if (ophead == NULL) {
1977			optail = ophead = opt;
1978			continue;
1979		}
1980		optail->fow = opt;
1981		optail = opt;
1982	}
1983	return 0;
1984}
1985
1986/*
1987 * str_offt()
1988 *	Convert an expression of the following forms to an off_t > 0.
1989 *	1) A positive decimal number.
1990 *	2) A positive decimal number followed by a b (mult by 512).
1991 *	3) A positive decimal number followed by a k (mult by 1024).
1992 *	4) A positive decimal number followed by a m (mult by 512).
1993 *	5) A positive decimal number followed by a w (mult by sizeof int)
1994 *	6) Two or more positive decimal numbers (with/without k,b or w).
1995 *	   separated by x (also * for backwards compatibility), specifying
1996 *	   the product of the indicated values.
1997 * Return:
1998 *	0 for an error, a positive value o.w.
1999 */
2000
2001static off_t
2002str_offt(char *val)
2003{
2004	char *expr;
2005	off_t num, t;
2006
2007	num = STRTOOFFT(val, &expr, 0);
2008	if ((num == OFFT_MAX) || (num <= 0) || (expr == val))
2009		return 0;
2010
2011	switch(*expr) {
2012	case 'b':
2013		t = num;
2014		num *= 512;
2015		if (t > num)
2016			return 0;
2017		++expr;
2018		break;
2019	case 'k':
2020		t = num;
2021		num *= 1024;
2022		if (t > num)
2023			return 0;
2024		++expr;
2025		break;
2026	case 'm':
2027		t = num;
2028		num *= 1048576;
2029		if (t > num)
2030			return 0;
2031		++expr;
2032		break;
2033	case 'w':
2034		t = num;
2035		num *= sizeof(int);
2036		if (t > num)
2037			return 0;
2038		++expr;
2039		break;
2040	}
2041
2042	switch(*expr) {
2043		case '\0':
2044			break;
2045		case '*':
2046		case 'x':
2047			t = num;
2048			num *= str_offt(expr + 1);
2049			if (t > num)
2050				return 0;
2051			break;
2052		default:
2053			return 0;
2054	}
2055	return num;
2056}
2057
2058static char *
2059get_line(FILE *f)
2060{
2061	char *name, *temp;
2062	size_t len;
2063
2064	name = fgetln(f, &len);
2065	if (!name) {
2066		get_line_error = ferror(f) ? GETLINE_FILE_CORRUPT : 0;
2067		return 0;
2068	}
2069	if (name[len-1] != '\n')
2070		len++;
2071	temp = malloc(len);
2072	if (!temp) {
2073		get_line_error = GETLINE_OUT_OF_MEM;
2074		return 0;
2075	}
2076	memcpy(temp, name, len-1);
2077	temp[len-1] = 0;
2078	return temp;
2079}
2080
2081/*
2082 * no_op()
2083 *	for those option functions where the archive format has nothing to do.
2084 * Return:
2085 *	0
2086 */
2087
2088static int
2089no_op(void)
2090{
2091	return 0;
2092}
2093
2094/*
2095 * pax_usage()
2096 *	print the usage summary to the user
2097 */
2098
2099static void
2100pax_usage(void)
2101{
2102	fprintf(stderr,
2103"usage: pax [-0cdjnvzVO] [-E limit] [-f archive] [-N dbdir] [-s replstr] ...\n"
2104"           [-U user] ... [-G group] ... [-T [from_date][,to_date]] ...\n"
2105"           [pattern ...]\n");
2106	fprintf(stderr,
2107"       pax -r [-cdijknuvzADOVYZ] [-E limit] [-f archive] [-N dbdir]\n"
2108"           [-o options] ... [-p string] ... [-s replstr] ... [-U user] ...\n"
2109"           [-G group] ... [-T [from_date][,to_date]] ... [pattern ...]\n");
2110	fprintf(stderr,
2111"       pax -w [-dijtuvzAHLMOPVX] [-b blocksize] [[-a] [-f archive]] [-x format]\n"
2112"           [-B bytes] [-N dbdir] [-o options] ... [-s replstr] ...\n"
2113"           [-U user] ... [-G group] ...\n"
2114"           [-T [from_date][,to_date][/[c][m]]] ... [file ...]\n");
2115	fprintf(stderr,
2116"       pax -r -w [-dijklntuvzADHLMOPVXYZ] [-N dbdir] [-p string] ...\n"
2117"           [-s replstr] ... [-U user] ... [-G group] ...\n"
2118"           [-T [from_date][,to_date][/[c][m]]] ... [file ...] directory\n");
2119	exit(1);
2120	/* NOTREACHED */
2121}
2122
2123/*
2124 * tar_usage()
2125 *	print the usage summary to the user
2126 */
2127
2128static void
2129tar_usage(void)
2130{
2131	(void)fputs("usage: tar [-]{crtux}[-befhjklmopqvwzHOPSXZ014578] [archive] "
2132		    "[blocksize]\n"
2133		    "           [-C directory] [-T file] [-s replstr] "
2134		    "[file ...]\n", stderr);
2135	exit(1);
2136	/* NOTREACHED */
2137}
2138
2139#ifndef NO_CPIO
2140/*
2141 * cpio_usage()
2142 *	print the usage summary to the user
2143 */
2144
2145static void
2146cpio_usage(void)
2147{
2148
2149	(void)fputs("usage: cpio -o [-aABcLvzZ] [-C bytes] [-F archive] "
2150		    "[-H format] [-O archive]\n"
2151		    "               < name-list [> archive]\n"
2152		    "       cpio -i [-bBcdfmrsStuvzZ6] [-C bytes] [-E file] "
2153		    "[-F archive] [-H format] \n"
2154		    "               [-I archive] "
2155		    "[pattern ...] [< archive]\n"
2156		    "       cpio -p [-adlLmuv] destination-directory "
2157		    "< name-list\n", stderr);
2158	exit(1);
2159	/* NOTREACHED */
2160}
2161#endif
2162