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