xref: /netbsd-src/bin/pax/options.c (revision 1ca5c1b28139779176bd5c13ad7c5f25c0bcd5f8)
1 /*	$NetBSD: options.c,v 1.34 2001/10/25 08:51:51 lukem 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. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the University of
22  *	California, Berkeley and its contributors.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  */
39 
40 #include <sys/cdefs.h>
41 #ifndef 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.34 2001/10/25 08:51:51 lukem 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/mtio.h>
53 #include <sys/param.h>
54 #include <stdio.h>
55 #include <ctype.h>
56 #include <string.h>
57 #include <unistd.h>
58 #include <stdlib.h>
59 #include <limits.h>
60 #include <getopt.h>
61 #include "pax.h"
62 #include "options.h"
63 #include "cpio.h"
64 #include "tar.h"
65 #include "extern.h"
66 
67 /*
68  * Routines which handle command line options
69  */
70 
71 int cpio_mode;			/* set if we are in cpio mode */
72 
73 static int nopids;		/* tar mode: suppress "pids" for -p option */
74 static char *flgch = FLGCH;	/* list of all possible flags (pax) */
75 static OPLIST *ophead = NULL;	/* head for format specific options -x */
76 static OPLIST *optail = NULL;	/* option tail */
77 static char *firstminusC;	/* first -C argument encountered. */
78 
79 static int no_op(void);
80 static void printflg(unsigned int);
81 static int c_frmt(const void *, const void *);
82 static off_t str_offt(char *);
83 static void pax_options(int, char **);
84 static void pax_usage(void);
85 static void tar_options(int, char **);
86 static void tar_usage(void);
87 static void cpio_options(int, char **);
88 static void cpio_usage(void);
89 
90 static void checkpositionalminusC(char ***, int (*)(char *, int));
91 
92 #define GZIP_CMD	"gzip"		/* command to run as gzip */
93 #define COMPRESS_CMD	"compress"	/* command to run as compress */
94 
95 /*
96  *	Format specific routine table - MUST BE IN SORTED ORDER BY NAME
97  *	(see pax.h for description of each function)
98  *
99  *	name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
100  *	read, end_read, st_write, write, end_write, trail,
101  *	rd_data, wr_data, options
102  */
103 
104 FSUB fsub[] = {
105 /* 0: OLD BINARY CPIO */
106 	{ "bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
107 	bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, NULL,
108 	cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
109 
110 /* 1: OLD OCTAL CHARACTER CPIO */
111 	{ "cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
112 	cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, NULL,
113 	cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
114 
115 /* 2: SVR4 HEX CPIO */
116 	{ "sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd,
117 	vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, NULL,
118 	cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
119 
120 /* 3: SVR4 HEX CPIO WITH CRC */
121 	{ "sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
122 	vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, NULL,
123 	cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
124 
125 /* 4: OLD TAR */
126 	{ "tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
127 	tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail,
128 	NULL, rd_wrfile, wr_rdfile, tar_opt },
129 
130 /* 5: POSIX USTAR */
131 	{ "ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd,
132 	ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail,
133 	NULL, rd_wrfile, wr_rdfile, bad_opt }
134 };
135 #define F_BCPIO		0	/* old binary cpio format */
136 #define F_CPIO		1	/* old octal character cpio format */
137 #define F_SV4CPIO	2	/* SVR4 hex cpio format */
138 #define F_SV4CRC	3	/* SVR4 hex with crc cpio format */
139 #define F_TAR		4	/* old V7 UNIX tar format */
140 #define F_USTAR		5	/* ustar format */
141 #define DEFLT		F_USTAR	/* default write format from list above */
142 
143 /*
144  * ford is the archive search order used by get_arc() to determine what kind
145  * of archive we are dealing with. This helps to properly id  archive formats
146  * some formats may be subsets of others....
147  */
148 int ford[] = {F_USTAR, F_TAR, F_SV4CRC, F_SV4CPIO, F_CPIO, F_BCPIO, -1};
149 
150 /*
151  * options()
152  *	figure out if we are pax, tar or cpio. Call the appropriate options
153  *	parser
154  */
155 
156 void
157 options(int argc, char **argv)
158 {
159 
160 	/*
161 	 * Are we acting like pax, tar or cpio (based on argv[0])
162 	 */
163 	if ((argv0 = strrchr(argv[0], '/')) != NULL)
164 		argv0++;
165 	else
166 		argv0 = argv[0];
167 
168 	if (strcmp(NM_TAR, argv0) == 0)
169 		tar_options(argc, argv);
170 	else if (strcmp(NM_CPIO, argv0) == 0)
171 		cpio_options(argc, argv);
172 	else {
173 		argv0 = NM_PAX;
174 		pax_options(argc, argv);
175 	}
176 }
177 
178 /*
179  * pax_options()
180  *	look at the user specified flags. set globals as required and check if
181  *	the user specified a legal set of flags. If not, complain and exit
182  */
183 
184 static void
185 pax_options(int argc, char **argv)
186 {
187 	int c;
188 	int i;
189 	unsigned int flg = 0;
190 	unsigned int bflg = 0;
191 	char *pt;
192 	FSUB tmp;
193 
194 	/*
195 	 * process option flags
196 	 */
197 	while ((c = getopt(argc, argv,
198 	    "ab:cdf:iklno:p:rs:tuvwx:zAB:DE:G:HLMOPT:U:XYZ")) != -1) {
199 		switch (c) {
200 		case 'a':
201 			/*
202 			 * append
203 			 */
204 			flg |= AF;
205 			break;
206 		case 'b':
207 			/*
208 			 * specify blocksize
209 			 */
210 			flg |= BF;
211 			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
212 				tty_warn(1, "Invalid block size %s", optarg);
213 				pax_usage();
214 			}
215 			break;
216 		case 'c':
217 			/*
218 			 * inverse match on patterns
219 			 */
220 			cflag = 1;
221 			flg |= CF;
222 			break;
223 		case 'd':
224 			/*
225 			 * match only dir on extract, not the subtree at dir
226 			 */
227 			dflag = 1;
228 			flg |= DF;
229 			break;
230 		case 'f':
231 			/*
232 			 * filename where the archive is stored
233 			 */
234 			arcname = optarg;
235 			flg |= FF;
236 			break;
237 		case 'i':
238 			/*
239 			 * interactive file rename
240 			 */
241 			iflag = 1;
242 			flg |= IF;
243 			break;
244 		case 'k':
245 			/*
246 			 * do not clobber files that exist
247 			 */
248 			kflag = 1;
249 			flg |= KF;
250 			break;
251 		case 'l':
252 			/*
253 			 * try to link src to dest with copy (-rw)
254 			 */
255 			lflag = 1;
256 			flg |= LF;
257 			break;
258 		case 'n':
259 			/*
260 			 * select first match for a pattern only
261 			 */
262 			nflag = 1;
263 			flg |= NF;
264 			break;
265 		case 'o':
266 			/*
267 			 * pass format specific options
268 			 */
269 			flg |= OF;
270 			if (opt_add(optarg) < 0)
271 				pax_usage();
272 			break;
273 		case 'p':
274 			/*
275 			 * specify file characteristic options
276 			 */
277 			for (pt = optarg; *pt != '\0'; ++pt) {
278 				switch(*pt) {
279 				case 'a':
280 					/*
281 					 * do not preserve access time
282 					 */
283 					patime = 0;
284 					break;
285 				case 'e':
286 					/*
287 					 * preserve user id, group id, file
288 					 * mode, access/modification times
289 					 * and file flags.
290 					 */
291 					pids = 1;
292 					pmode = 1;
293 					patime = 1;
294 					pmtime = 1;
295 					pfflags = 1;
296 					break;
297 #if 0
298 				case 'f':
299 					/*
300 					 * do not preserve file flags
301 					 */
302 					pfflags = 0;
303 					break;
304 #endif
305 				case 'm':
306 					/*
307 					 * do not preserve modification time
308 					 */
309 					pmtime = 0;
310 					break;
311 				case 'o':
312 					/*
313 					 * preserve uid/gid
314 					 */
315 					pids = 1;
316 					break;
317 				case 'p':
318 					/*
319 					 * preserver file mode bits
320 					 */
321 					pmode = 1;
322 					break;
323 				default:
324 					tty_warn(1,
325 					    "Invalid -p string: %c", *pt);
326 					pax_usage();
327 					break;
328 				}
329 			}
330 			flg |= PF;
331 			break;
332 		case 'r':
333 			/*
334 			 * read the archive
335 			 */
336 			flg |= RF;
337 			break;
338 		case 's':
339 			/*
340 			 * file name substitution name pattern
341 			 */
342 			if (rep_add(optarg) < 0) {
343 				pax_usage();
344 				break;
345 			}
346 			flg |= SF;
347 			break;
348 		case 't':
349 			/*
350 			 * preserve access time on filesystem nodes we read
351 			 */
352 			tflag = 1;
353 			flg |= TF;
354 			break;
355 		case 'u':
356 			/*
357 			 * ignore those older files
358 			 */
359 			uflag = 1;
360 			flg |= UF;
361 			break;
362 		case 'v':
363 			/*
364 			 * verbose operation mode
365 			 */
366 			vflag = 1;
367 			flg |= VF;
368 			break;
369 		case 'w':
370 			/*
371 			 * write an archive
372 			 */
373 			flg |= WF;
374 			break;
375 		case 'x':
376 			/*
377 			 * specify an archive format on write
378 			 */
379 			tmp.name = optarg;
380 			frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
381 			    sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt);
382 			if (frmt != NULL) {
383 				flg |= XF;
384 				break;
385 			}
386 			tty_warn(1, "Unknown -x format: %s", optarg);
387 			(void)fputs("pax: Known -x formats are:", stderr);
388 			for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
389 				(void)fprintf(stderr, " %s", fsub[i].name);
390 			(void)fputs("\n\n", stderr);
391 			pax_usage();
392 			break;
393 		case 'z':
394 			/*
395 			 * use gzip.  Non standard option.
396 			 */
397 			zflag = 1;
398 			gzip_program = GZIP_CMD;
399 			break;
400 		case 'A':
401 			Aflag = 1;
402 			flg |= CAF;
403 			break;
404 		case 'B':
405 			/*
406 			 * non-standard option on number of bytes written on a
407 			 * single archive volume.
408 			 */
409 			if ((wrlimit = str_offt(optarg)) <= 0) {
410 				tty_warn(1, "Invalid write limit %s", optarg);
411 				pax_usage();
412 			}
413 			if (wrlimit % BLKMULT) {
414 				tty_warn(1,
415 				    "Write limit is not a %d byte multiple",
416 				    BLKMULT);
417 				pax_usage();
418 			}
419 			flg |= CBF;
420 			break;
421 		case 'D':
422 			/*
423 			 * On extraction check file inode change time before the
424 			 * modification of the file name. Non standard option.
425 			 */
426 			Dflag = 1;
427 			flg |= CDF;
428 			break;
429 		case 'E':
430 			/*
431 			 * non-standard limit on read faults
432 			 * 0 indicates stop after first error, values
433 			 * indicate a limit, "NONE" try forever
434 			 */
435 			flg |= CEF;
436 			if (strcmp(NONE, optarg) == 0)
437 				maxflt = -1;
438 			else if ((maxflt = atoi(optarg)) < 0) {
439 				tty_warn(1,
440 				    "Error count value must be positive");
441 				pax_usage();
442 			}
443 			break;
444 		case 'G':
445 			/*
446 			 * non-standard option for selecting files within an
447 			 * archive by group (gid or name)
448 			 */
449 			if (grp_add(optarg) < 0) {
450 				pax_usage();
451 				break;
452 			}
453 			flg |= CGF;
454 			break;
455 		case 'H':
456 			/*
457 			 * follow command line symlinks only
458 			 */
459 			Hflag = 1;
460 			flg |= CHF;
461 			break;
462 		case 'L':
463 			/*
464 			 * follow symlinks
465 			 */
466 			Lflag = 1;
467 			flg |= CLF;
468 			break;
469 		case 'M':
470 			/*
471 			 * Treat list of filenames on stdin as an
472 			 * mtree(8) specfile.  Non standard option.
473 			 */
474 			Mflag = 1;
475 			flg |= CMF;
476 			break;
477 		case 'O':
478 			/*
479 			 * Force one volume.  Non standard option.
480 			 */
481 			force_one_volume = 1;
482 			break;
483 		case 'P':
484 			/*
485 			 * do NOT follow symlinks (default)
486 			 */
487 			Lflag = 0;
488 			flg |= CPF;
489 			break;
490 		case 'T':
491 			/*
492 			 * non-standard option for selecting files within an
493 			 * archive by modification time range (lower,upper)
494 			 */
495 			if (trng_add(optarg) < 0) {
496 				pax_usage();
497 				break;
498 			}
499 			flg |= CTF;
500 			break;
501 		case 'U':
502 			/*
503 			 * non-standard option for selecting files within an
504 			 * archive by user (uid or name)
505 			 */
506 			if (usr_add(optarg) < 0) {
507 				pax_usage();
508 				break;
509 			}
510 			flg |= CUF;
511 			break;
512 		case 'X':
513 			/*
514 			 * do not pass over mount points in the file system
515 			 */
516 			Xflag = 1;
517 			flg |= CXF;
518 			break;
519 		case 'Y':
520 			/*
521 			 * On extraction check file inode change time after the
522 			 * modification of the file name. Non standard option.
523 			 */
524 			Yflag = 1;
525 			flg |= CYF;
526 			break;
527 		case 'Z':
528 			/*
529 			 * On extraction check modification time after the
530 			 * modification of the file name. Non standard option.
531 			 */
532 			Zflag = 1;
533 			flg |= CZF;
534 			break;
535 		case '?':
536 		default:
537 			pax_usage();
538 			break;
539 		}
540 	}
541 
542 	/*
543 	 * figure out the operation mode of pax read,write,extract,copy,append
544 	 * or list. check that we have not been given a bogus set of flags
545 	 * for the operation mode.
546 	 */
547 	if (ISLIST(flg)) {
548 		act = LIST;
549 		bflg = flg & BDLIST;
550 	} else if (ISEXTRACT(flg)) {
551 		act = EXTRACT;
552 		bflg = flg & BDEXTR;
553 	} else if (ISARCHIVE(flg)) {
554 		act = ARCHIVE;
555 		bflg = flg & BDARCH;
556 	} else if (ISAPPND(flg)) {
557 		act = APPND;
558 		bflg = flg & BDARCH;
559 	} else if (ISCOPY(flg)) {
560 		act = COPY;
561 		bflg = flg & BDCOPY;
562 	} else
563 		pax_usage();
564 	if (bflg) {
565 		printflg(flg);
566 		pax_usage();
567 	}
568 
569 	/*
570 	 * if we are writing (ARCHIVE) we use the default format if the user
571 	 * did not specify a format. when we write during an APPEND, we will
572 	 * adopt the format of the existing archive if none was supplied.
573 	 */
574 	if (!(flg & XF) && (act == ARCHIVE))
575 		frmt = &(fsub[DEFLT]);
576 
577 	/*
578 	 * process the args as they are interpreted by the operation mode
579 	 */
580 	switch (act) {
581 	case LIST:
582 	case EXTRACT:
583 		for (; optind < argc; optind++)
584 			if (pat_add(argv[optind], 0) < 0)
585 				pax_usage();
586 		break;
587 	case COPY:
588 		if (optind >= argc) {
589 			tty_warn(0, "Destination directory was not supplied");
590 			pax_usage();
591 		}
592 		--argc;
593 		dirptr = argv[argc];
594 		/* FALLTHROUGH */
595 	case ARCHIVE:
596 	case APPND:
597 		for (; optind < argc; optind++)
598 			if (ftree_add(argv[optind], 0) < 0)
599 				pax_usage();
600 		/*
601 		 * no read errors allowed on updates/append operation!
602 		 */
603 		maxflt = 0;
604 		break;
605 	}
606 }
607 
608 
609 /*
610  * tar_options()
611  *	look at the user specified flags. set globals as required and check if
612  *	the user specified a legal set of flags. If not, complain and exit
613  */
614 
615 #define	OPT_USE_COMPRESS_PROGRAM	0
616 #define	OPT_CHECKPOINT			1
617 #define	OPT_UNLINK			2
618 #define	OPT_HELP			3
619 #define	OPT_ATIME_PRESERVE		4
620 #define	OPT_FAST_READ			5
621 #define	OPT_IGNORE_FAILED_READ		6
622 #define	OPT_REMOVE_FILES		7
623 #define	OPT_NULL			8
624 #define	OPT_TOTALS			9
625 #define	OPT_VERSION			10
626 #define	OPT_EXCLUDE			11
627 #define	OPT_BLOCK_COMPRESS		12
628 #define	OPT_NORECURSE			13
629 
630 struct option tar_longopts[] = {
631 	{ "block-size",		required_argument,	0,	'b' },
632 	{ "create",		no_argument,		0,	'c' },	/* F */
633 	/* -e -- no corresponding long option */
634 	{ "file",		required_argument,	0,	'f' },
635 	{ "dereference",	no_argument,		0,	'h' },
636 	{ "one-file-system",	no_argument,		0,	'l' },
637 	{ "modification-time",	no_argument,		0,	'm' },
638 	{ "old-archive",	no_argument,		0,	'o' },
639 	{ "portability",	no_argument,		0,	'o' },
640 	{ "same-permissions",	no_argument,		0,	'p' },
641 	{ "preserve-permissions", no_argument,		0,	'p' },
642 	{ "preserve",		no_argument,		0,	'p' },
643 	{ "append",		no_argument,		0,	'r' },	/* F */
644 	{ "update",		no_argument,		0,	'u' },	/* F */
645 	{ "list",		no_argument,		0,	't' },	/* F */
646 	{ "verbose",		no_argument,		0,	'v' },
647 	{ "interactive",	no_argument,		0,	'w' },
648 	{ "confirmation",	no_argument,		0,	'w' },
649 	{ "extract",		no_argument,		0,	'x' },	/* F */
650 	{ "get",		no_argument,		0,	'x' },	/* F */
651 	{ "gzip",		no_argument,		0,	'z' },
652 	{ "gunzip",		no_argument,		0,	'z' },
653 	{ "read-full-blocks",	no_argument,		0,	'B' },
654 	{ "directory",		required_argument,	0,	'C' },
655 	{ "tape-length",	required_argument,	0,	'L' },
656 	{ "absolute-paths",	no_argument,		0,	'P' },
657 	{ "exclude-from",	required_argument,	0,	'X' },
658 	{ "compress",		no_argument,		0,	'Z' },
659 	{ "uncompress",		no_argument,		0,	'Z' },
660 	{ "atime-preserve",	no_argument,		0,
661 						OPT_ATIME_PRESERVE },
662 	{ "unlink",		no_argument,		0,
663 						OPT_UNLINK },
664 	{ "use-compress-program", required_argument,	0,
665 						OPT_USE_COMPRESS_PROGRAM },
666 #if 0 /* Not implemented */
667 	{ "catenate",		no_argument,		0,	'A' },	/* F */
668 	{ "concatenate",	no_argument,		0,	'A' },	/* F */
669 	{ "diff",		no_argument,		0,	'd' },	/* F */
670 	{ "compare",		no_argument,		0,	'd' },	/* F */
671 	{ "checkpoint",		no_argument,		0,
672 						OPT_CHECKPOINT },
673 	{ "help",		no_argument,		0,
674 						OPT_HELP },
675 	{ "info-script",	required_argument,	0,	'F' },
676 	{ "new-volume-script",	required_argument,	0,	'F' },
677 	{ "fast-read",		no_argument,		0,
678 						OPT_FAST_READ },
679 	{ "incremental",	no_argument,		0,	'G' },
680 	{ "listed-incremental",	required_argument,	0,	'g' },
681 	{ "ignore-zeros",	no_argument,		0,	'i' },
682 	{ "ignore-failed-read",	no_argument,		0,
683 						OPT_IGNORE_FAILED_READ },
684 	{ "keep-old-files",	no_argument,		0,	'k' },
685 	{ "starting-file",	no_argument,		0,	'K' },
686 	{ "multi-volume",	no_argument,		0,	'M' },
687 	{ "after-date",		required_argument,	0,	'N' },
688 	{ "newer",		required_argument,	0,	'N' },
689 	{ "to-stdout",		no_argument,		0,	'O' },
690 	{ "record-number",	no_argument,		0,	'R' },
691 	{ "remove-files",	no_argument,		0,
692 						OPT_REMOVE_FILES },
693 	{ "same-order",		no_argument,		0,	's' },
694 	{ "preserve-order",	no_argument,		0,	's' },
695 	{ "sparse",		no_argument,		0,	'S' },
696 	{ "files-from",		no_argument,		0,	'T' },
697 	{ "null",		no_argument,		0,
698 						OPT_NULL },
699 	{ "totals",		no_argument,		0,
700 						OPT_TOTALS },
701 	{ "volume-name",	required_argument,	0,	'V' },
702 	{ "label",		required_argument,	0,	'V' },
703 	{ "version",		no_argument,		0,
704 						OPT_VERSION },
705 	{ "verify",		no_argument,		0,	'W' },
706 	{ "exclude",		required_argument,	0,
707 						OPT_EXCLUDE },
708 	{ "block-compress",	no_argument,		0,
709 						OPT_BLOCK_COMPRESS },
710 	{ "norecurse",		no_argument,		0,
711 						OPT_NORECURSE },
712 #endif
713 	{ 0,			0,			0,	0 },
714 };
715 
716 static void
717 tar_options(int argc, char **argv)
718 {
719 	int c;
720 	int fstdin = 0;
721 
722 	/*
723 	 * process option flags
724 	 */
725 	while ((c = getoldopt(argc, argv, "b:cef:hlmoprutvwxzBC:LPX:Z014578",
726 	    tar_longopts, NULL))
727 	    != -1)  {
728 		switch(c) {
729 		case 'b':
730 			/*
731 			 * specify blocksize
732 			 */
733 			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
734 				tty_warn(1, "Invalid block size %s", optarg);
735 				tar_usage();
736 			}
737 			break;
738 		case 'c':
739 			/*
740 			 * create an archive
741 			 */
742 			act = ARCHIVE;
743 			break;
744 		case 'C':
745 			/*
746 			 * chdir here before extracting.
747 			 * do so lazily, in case it's a list
748 			 */
749 			firstminusC = optarg;
750 			break;
751 		case 'e':
752 			/*
753 			 * stop after first error
754 			 */
755 			maxflt = 0;
756 			break;
757 		case 'f':
758 			/*
759 			 * filename where the archive is stored
760 			 */
761 			if ((optarg[0] == '-') && (optarg[1]== '\0')) {
762 				/*
763 				 * treat a - as stdin
764 				 */
765 				fstdin = 1;
766 				arcname = (char *)0;
767 				break;
768 			}
769 			fstdin = 0;
770 			arcname = optarg;
771 			break;
772 		case 'h':
773 			/*
774 			 * follow command line symlinks only
775 			 */
776 			Hflag = 1;
777 			break;
778 		case 'l':
779 			/*
780 			 * do not pass over mount points in the file system
781 			 */
782 			Xflag = 1;
783 			break;
784 		case 'm':
785 			/*
786 			 * do not preserve modification time
787 			 */
788 			pmtime = 0;
789 			break;
790 		case 'o':
791 			/*
792 			 * This option does several things based on whether
793 			 * this is a create or extract operation.
794 			 */
795 			if (act == ARCHIVE) {
796 				/* 4.2BSD: don't add directory entries. */
797 				if (opt_add("write_opt=nodir") < 0)
798 					tar_usage();
799 
800 				/* GNU tar: write V7 format archives. */
801 				frmt = &(fsub[F_TAR]);
802 			} else {
803 				/* SUS: don't preserve owner/group. */
804 				pids = 0;
805 				nopids = 1;
806 			}
807 			break;
808 		case 'p':
809 			/*
810 			 * preserve user id, group id, file
811 			 * mode, access/modification times
812 			 */
813 			if (!nopids)
814 				pids = 1;
815 			pmode = 1;
816 			patime = 1;
817 			pmtime = 1;
818 			break;
819 		case 'r':
820 		case 'u':
821 			/*
822 			 * append to the archive
823 			 */
824 			act = APPND;
825 			break;
826 		case 't':
827 			/*
828 			 * list contents of the tape
829 			 */
830 			act = LIST;
831 			break;
832 		case 'v':
833 			/*
834 			 * verbose operation mode
835 			 */
836 			vflag = 1;
837 			break;
838 		case 'w':
839 			/*
840 			 * interactive file rename
841 			 */
842 			iflag = 1;
843 			break;
844 		case 'x':
845 			/*
846 			 * write an archive
847 			 */
848 			act = EXTRACT;
849 			break;
850 		case 'z':
851 			/*
852 			 * use gzip.  Non standard option.
853 			 */
854 			zflag = 1;
855 			gzip_program = GZIP_CMD;
856 			break;
857 		case 'B':
858 			/*
859 			 * Nothing to do here, this is pax default
860 			 */
861 			break;
862 		case 'L':
863 			/*
864 			 * follow symlinks
865 			 */
866 			Lflag = 1;
867 			break;
868 		case 'P':
869 			Aflag = 1;
870 			break;
871 		case 'X':
872 			/*
873 			 * GNU tar compat: exclude the files listed in optarg
874 			 */
875 			if (tar_gnutar_X_compat(optarg) != 0)
876 				tar_usage();
877 			break;
878 		case 'Z':
879 			/*
880 			 * use compress.
881 			 */
882 			zflag = 1;
883 			gzip_program = COMPRESS_CMD;
884 			break;
885 		case '0':
886 			arcname = DEV_0;
887 			break;
888 		case '1':
889 			arcname = DEV_1;
890 			break;
891 		case '4':
892 			arcname = DEV_4;
893 			break;
894 		case '5':
895 			arcname = DEV_5;
896 			break;
897 		case '7':
898 			arcname = DEV_7;
899 			break;
900 		case '8':
901 			arcname = DEV_8;
902 			break;
903 		case OPT_ATIME_PRESERVE:
904 			patime = 1;
905 			break;
906 		case OPT_UNLINK:
907 			/* Just ignore -- we always unlink first. */
908 			break;
909 		case OPT_USE_COMPRESS_PROGRAM:
910 			zflag = 1;
911 			gzip_program = optarg;
912 			break;
913 		default:
914 			tar_usage();
915 			break;
916 		}
917 	}
918 	argc -= optind;
919 	argv += optind;
920 
921 	if (firstminusC && (opt_chdir(firstminusC) < 0))
922 		tty_warn(1, "can't remember -C directory");
923 
924 	/*
925 	 * if we are writing (ARCHIVE) specify tar, otherwise run like pax
926 	 */
927 	if (act == ARCHIVE && frmt == NULL)
928 		frmt = &(fsub[F_USTAR]);
929 
930 	/*
931 	 * process the args as they are interpreted by the operation mode
932 	 */
933 	switch (act) {
934 	case LIST:
935 	default:
936 		while (*argv != (char *)NULL)
937 			if (pat_add(*argv++, 0) < 0)
938 				tar_usage();
939 		break;
940 	case EXTRACT:
941 		checkpositionalminusC(&argv, pat_add);
942 		break;
943 	case ARCHIVE:
944 	case APPND:
945 		checkpositionalminusC(&argv, ftree_add);
946 		/*
947 		 * no read errors allowed on updates/append operation!
948 		 */
949 		maxflt = 0;
950 		break;
951 	}
952 	if (!fstdin && ((arcname == (char *)NULL) || (*arcname == '\0'))) {
953 		arcname = getenv("TAPE");
954 		if ((arcname == (char *)NULL) || (*arcname == '\0'))
955 			arcname = DEV_8;
956 	}
957 }
958 
959 /*
960  * cpio_options()
961  *	look at the user specified flags. set globals as required and check if
962  *	the user specified a legal set of flags. If not, complain and exit
963  */
964 
965 static void
966 cpio_options(int argc, char **argv)
967 {
968 	FSUB tmp;
969 	unsigned int flg = 0;
970 	unsigned int bflg = 0;
971 	int c, i;
972 
973 	cpio_mode = uflag = 1;
974 	/*
975 	 * process option flags
976 	 */
977 	while ((c = getoldopt(argc, argv,
978 	    "ABC:E:H:I:LM:O:R:SVabcdfiklmoprstuv", NULL, NULL)) != -1)  {
979 		switch(c) {
980 		case 'A':
981 			/*
982 			 * append to an archive
983 			 */
984 			act = APPND;
985 			flg |= AF;
986 			break;
987 		case 'B':
988 			/*
989 			 * set blocksize to 5120
990 			 */
991 			blksz = 5120;
992 			break;
993 		case 'C':
994 			/*
995 			 * specify blocksize
996 			 */
997 			if ((blksz = (int)str_offt(optarg)) <= 0) {
998 				tty_warn(1, "Invalid block size %s", optarg);
999 				tar_usage();
1000 			}
1001 			break;
1002 #ifdef notyet
1003 		case 'E':
1004 			arg = optarg;
1005 			break;
1006 #endif
1007 		case 'H':
1008 			/*
1009 			 * specify an archive format on write
1010 			 */
1011 			tmp.name = optarg;
1012 			frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
1013 			    sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt);
1014 			if (frmt != NULL) {
1015 				flg |= XF;
1016 				break;
1017 			}
1018 			tty_warn(1, "Unknown -H format: %s", optarg);
1019 			(void)fputs("cpio: Known -H formats are:", stderr);
1020 			for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
1021 				(void)fprintf(stderr, " %s", fsub[i].name);
1022 			(void)fputs("\n\n", stderr);
1023 			tar_usage();
1024 			break;
1025 		case 'I':
1026 		case 'O':
1027 			/*
1028 			 * filename where the archive is stored
1029 			 */
1030 			if ((optarg[0] == '-') && (optarg[1]== '\0')) {
1031 				/*
1032 				 * treat a - as stdin
1033 				 */
1034 				arcname = (char *)0;
1035 				break;
1036 			}
1037 			arcname = optarg;
1038 			break;
1039 		case 'L':
1040 			/*
1041 			 * follow symlinks
1042 			 */
1043 			Lflag = 1;
1044 			flg |= CLF;
1045 			break;
1046 #ifdef notyet
1047 		case 'M':
1048 			arg = optarg;
1049 			break;
1050 		case 'R':
1051 			arg = optarg;
1052 			break;
1053 #endif
1054 		case 'S':
1055 			cpio_swp_head = 1;
1056 			break;
1057 #ifdef notyet
1058 		case 'V':
1059 			break;
1060 #endif
1061 		case 'a':
1062 			/*
1063 			 * preserve access time on filesystem nodes we read
1064 			 */
1065 			tflag = 1;
1066 			flg |= TF;
1067 			break;
1068 #ifdef notyet
1069 		case 'b':
1070 			break;
1071 #endif
1072 		case 'c':
1073 			frmt = &fsub[F_SV4CPIO];
1074 			break;
1075 		case 'd':
1076 			/*
1077 			 * pax does this by default ..
1078 			 */
1079 			flg |= RF;
1080 			break;
1081 		case 'f':
1082 			/*
1083 			 * inverse match on patterns
1084 			 */
1085 			cflag = 1;
1086 			flg |= CF;
1087 			break;
1088 		case 'i':
1089 			/*
1090 			 * read the archive
1091 			 */
1092 			flg |= RF;
1093 			break;
1094 #ifdef notyet
1095 		case 'k':
1096 			break;
1097 #endif
1098 		case 'l':
1099 			/*
1100 			 * try to link src to dest with copy (-rw)
1101 			 */
1102 			lflag = 1;
1103 			flg |= LF;
1104 			break;
1105 		case 'm':
1106 			/*
1107 			 * preserve mtime
1108 			 */
1109 			flg |= PF;
1110 			pmtime = 1;
1111 			break;
1112 		case 'o':
1113 			/*
1114 			 * write an archive
1115 			 */
1116 			flg |= WF;
1117 			break;
1118 		case 'p':
1119 			/*
1120 			 * cpio -p is like pax -rw
1121 			 */
1122 			flg |= RF | WF;
1123 			break;
1124 		case 'r':
1125 			/*
1126 			 * interactive file rename
1127 			 */
1128 			iflag = 1;
1129 			flg |= IF;
1130 			break;
1131 #ifdef notyet
1132 		case 's':
1133 			break;
1134 #endif
1135 		case 't':
1136 			act = LIST;
1137 			break;
1138 		case 'u':
1139 			/*
1140 			 * don't ignore those older files
1141 			 */
1142 			uflag = 0;
1143 			flg |= UF;
1144 			break;
1145 		case 'v':
1146 			/*
1147 			 * verbose operation mode
1148 			 */
1149 			vflag = 1;
1150 			flg |= VF;
1151 			break;
1152 		default:
1153 			cpio_usage();
1154 			break;
1155 		}
1156 	}
1157 
1158 	/*
1159 	 * figure out the operation mode of cpio. check that we have not been
1160 	 * given a bogus set of flags for the operation mode.
1161 	 */
1162 	if (ISLIST(flg)) {
1163 		act = LIST;
1164 		bflg = flg & BDLIST;
1165 	} else if (ISEXTRACT(flg)) {
1166 		act = EXTRACT;
1167 		bflg = flg & BDEXTR;
1168 	} else if (ISARCHIVE(flg)) {
1169 		act = ARCHIVE;
1170 		bflg = flg & BDARCH;
1171 	} else if (ISAPPND(flg)) {
1172 		act = APPND;
1173 		bflg = flg & BDARCH;
1174 	} else if (ISCOPY(flg)) {
1175 		act = COPY;
1176 		bflg = flg & BDCOPY;
1177 	} else
1178 		cpio_usage();
1179 	if (bflg) {
1180 		cpio_usage();
1181 	}
1182 
1183 	/*
1184 	 * if we are writing (ARCHIVE) we use the default format if the user
1185 	 * did not specify a format. when we write during an APPEND, we will
1186 	 * adopt the format of the existing archive if none was supplied.
1187 	 */
1188 	if (!(flg & XF) && (act == ARCHIVE))
1189 		frmt = &(fsub[F_BCPIO]);
1190 
1191 	/*
1192 	 * process the args as they are interpreted by the operation mode
1193 	 */
1194 	switch (act) {
1195 	case LIST:
1196 	case EXTRACT:
1197 		for (; optind < argc; optind++)
1198 			if (pat_add(argv[optind], 0) < 0)
1199 				cpio_usage();
1200 		break;
1201 	case COPY:
1202 		if (optind >= argc) {
1203 			tty_warn(0, "Destination directory was not supplied");
1204 			cpio_usage();
1205 		}
1206 		--argc;
1207 		dirptr = argv[argc];
1208 		/* FALLTHROUGH */
1209 	case ARCHIVE:
1210 	case APPND:
1211 		for (; optind < argc; optind++)
1212 			if (ftree_add(argv[optind], 0) < 0)
1213 				cpio_usage();
1214 		/*
1215 		 * no read errors allowed on updates/append operation!
1216 		 */
1217 		maxflt = 0;
1218 		break;
1219 	}
1220 }
1221 
1222 /*
1223  * printflg()
1224  *	print out those invalid flag sets found to the user
1225  */
1226 
1227 static void
1228 printflg(unsigned int flg)
1229 {
1230 	int nxt;
1231 	int pos = 0;
1232 
1233 	(void)fprintf(stderr,"%s: Invalid combination of options:", argv0);
1234 	while ((nxt = ffs(flg)) != 0) {
1235 		flg = flg >> nxt;
1236 		pos += nxt;
1237 		(void)fprintf(stderr, " -%c", flgch[pos-1]);
1238 	}
1239 	(void)putc('\n', stderr);
1240 }
1241 
1242 /*
1243  * c_frmt()
1244  *	comparison routine used by bsearch to find the format specified
1245  *	by the user
1246  */
1247 
1248 static int
1249 c_frmt(const void *a, const void *b)
1250 {
1251 	return(strcmp(((FSUB *)a)->name, ((FSUB *)b)->name));
1252 }
1253 
1254 /*
1255  * opt_next()
1256  *	called by format specific options routines to get each format specific
1257  *	flag and value specified with -o
1258  * Return:
1259  *	pointer to next OPLIST entry or NULL (end of list).
1260  */
1261 
1262 OPLIST *
1263 opt_next(void)
1264 {
1265 	OPLIST *opt;
1266 
1267 	if ((opt = ophead) != NULL)
1268 		ophead = ophead->fow;
1269 	return(opt);
1270 }
1271 
1272 /*
1273  * bad_opt()
1274  *	generic routine used to complain about a format specific options
1275  *	when the format does not support options.
1276  */
1277 
1278 int
1279 bad_opt(void)
1280 {
1281 	OPLIST *opt;
1282 
1283 	if (ophead == NULL)
1284 		return(0);
1285 	/*
1286 	 * print all we were given
1287 	 */
1288 	tty_warn(1,"These format options are not supported");
1289 	while ((opt = opt_next()) != NULL)
1290 		(void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
1291 	pax_usage();
1292 	return(0);
1293 }
1294 
1295 /*
1296  * opt_add()
1297  *	breaks the value supplied to -o into a option name and value. options
1298  *	are given to -o in the form -o name-value,name=value
1299  *	multiple -o may be specified.
1300  * Return:
1301  *	0 if format in name=value format, -1 if -o is passed junk
1302  */
1303 
1304 int
1305 opt_add(const char *str)
1306 {
1307 	OPLIST *opt;
1308 	char *frpt;
1309 	char *pt;
1310 	char *endpt;
1311 
1312 	if ((str == NULL) || (*str == '\0')) {
1313 		tty_warn(0, "Invalid option name");
1314 		return(-1);
1315 	}
1316 	frpt = endpt = strdup(str);
1317 
1318 	/*
1319 	 * break into name and values pieces and stuff each one into a
1320 	 * OPLIST structure. When we know the format, the format specific
1321 	 * option function will go through this list
1322 	 */
1323 	while ((frpt != NULL) && (*frpt != '\0')) {
1324 		if ((endpt = strchr(frpt, ',')) != NULL)
1325 			*endpt = '\0';
1326 		if ((pt = strchr(frpt, '=')) == NULL) {
1327 			tty_warn(0, "Invalid options format");
1328 			return(-1);
1329 		}
1330 		if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
1331 			tty_warn(0, "Unable to allocate space for option list");
1332 			return(-1);
1333 		}
1334 		*pt++ = '\0';
1335 		opt->name = frpt;
1336 		opt->value = pt;
1337 		opt->fow = NULL;
1338 		if (endpt != NULL)
1339 			frpt = endpt + 1;
1340 		else
1341 			frpt = NULL;
1342 		if (ophead == NULL) {
1343 			optail = ophead = opt;
1344 			continue;
1345 		}
1346 		optail->fow = opt;
1347 		optail = opt;
1348 	}
1349 	return(0);
1350 }
1351 
1352 /*
1353  * str_offt()
1354  *	Convert an expression of the following forms to an off_t > 0.
1355  *	1) A positive decimal number.
1356  *	2) A positive decimal number followed by a b (mult by 512).
1357  *	3) A positive decimal number followed by a k (mult by 1024).
1358  *	4) A positive decimal number followed by a m (mult by 512).
1359  *	5) A positive decimal number followed by a w (mult by sizeof int)
1360  *	6) Two or more positive decimal numbers (with/without k,b or w).
1361  *	   separated by x (also * for backwards compatibility), specifying
1362  *	   the product of the indicated values.
1363  * Return:
1364  *	0 for an error, a positive value o.w.
1365  */
1366 
1367 static off_t
1368 str_offt(char *val)
1369 {
1370 	char *expr;
1371 	off_t num, t;
1372 
1373 	num = STRTOOFFT(val, &expr, 0);
1374 	if ((num == OFFT_MAX) || (num <= 0) || (expr == val))
1375 		return(0);
1376 
1377 	switch(*expr) {
1378 	case 'b':
1379 		t = num;
1380 		num *= 512;
1381 		if (t > num)
1382 			return(0);
1383 		++expr;
1384 		break;
1385 	case 'k':
1386 		t = num;
1387 		num *= 1024;
1388 		if (t > num)
1389 			return(0);
1390 		++expr;
1391 		break;
1392 	case 'm':
1393 		t = num;
1394 		num *= 1048576;
1395 		if (t > num)
1396 			return(0);
1397 		++expr;
1398 		break;
1399 	case 'w':
1400 		t = num;
1401 		num *= sizeof(int);
1402 		if (t > num)
1403 			return(0);
1404 		++expr;
1405 		break;
1406 	}
1407 
1408 	switch(*expr) {
1409 		case '\0':
1410 			break;
1411 		case '*':
1412 		case 'x':
1413 			t = num;
1414 			num *= str_offt(expr + 1);
1415 			if (t > num)
1416 				return(0);
1417 			break;
1418 		default:
1419 			return(0);
1420 	}
1421 	return(num);
1422 }
1423 
1424 /*
1425  * no_op()
1426  *	for those option functions where the archive format has nothing to do.
1427  * Return:
1428  *	0
1429  */
1430 
1431 static int
1432 no_op(void)
1433 {
1434 	return(0);
1435 }
1436 
1437 /*
1438  * pax_usage()
1439  *	print the usage summary to the user
1440  */
1441 
1442 void
1443 pax_usage(void)
1444 {
1445 	(void)fputs("usage: pax [-cdnvz] [-E limit] [-f archive] ", stderr);
1446 	(void)fputs("[-s replstr] ... [-U user] ...", stderr);
1447 	(void)fputs("\n           [-G group] ... ", stderr);
1448 	(void)fputs("[-T [from_date][,to_date]] ... ", stderr);
1449 	(void)fputs("[pattern ...]\n", stderr);
1450 	(void)fputs("       pax -r [-cdiknuvzDYZ] [-E limit] ", stderr);
1451 	(void)fputs("[-f archive] [-o options] ... \n", stderr);
1452 	(void)fputs("           [-p string] ... [-s replstr] ... ", stderr);
1453 	(void)fputs("[-U user] ... [-G group] ...\n           ", stderr);
1454 	(void)fputs("[-T [from_date][,to_date]] ... ", stderr);
1455 	(void)fputs(" [pattern ...]\n", stderr);
1456 	(void)fputs("       pax -w [-dituvzHLMPX] [-b blocksize] ", stderr);
1457 	(void)fputs("[[-a] [-f archive]] [-x format] \n", stderr);
1458 	(void)fputs("           [-B bytes] [-o options] ... ", stderr);
1459 	(void)fputs("[-s replstr] ... [-U user] ...", stderr);
1460 	(void)fputs("\n           [-G group] ... ", stderr);
1461 	(void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
1462 	(void)fputs("[file ...]\n", stderr);
1463 	(void)fputs("       pax -r -w [-diklntuvzDHLMPXYZ] ", stderr);
1464 	(void)fputs("[-p string] ... [-s replstr] ...", stderr);
1465 	(void)fputs("\n           [-U user] ... [-G group] ... ", stderr);
1466 	(void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
1467 	(void)fputs("\n           [file ...] directory\n", stderr);
1468 	exit(1);
1469 	/* NOTREACHED */
1470 }
1471 
1472 /*
1473  * tar_usage()
1474  *	print the usage summary to the user
1475  */
1476 
1477 void
1478 tar_usage(void)
1479 {
1480 	(void)fputs("usage: tar -{txru}[cevfbhlmopwBLPX014578] [tapefile] ",
1481 		 stderr);
1482 	(void)fputs("[blocksize] [exclude-file] file1 file2...\n", stderr);
1483 	exit(1);
1484 	/* NOTREACHED */
1485 }
1486 
1487 /*
1488  * cpio_usage()
1489  *	print the usage summary to the user
1490  */
1491 
1492 void
1493 cpio_usage(void)
1494 {
1495 
1496 #if 1
1497 	(void)fputs(
1498 	    "usage: cpio -i [-BcdfmrStuv] [ -C blksize ] [ -H header ]\n",
1499 	    stderr);
1500 	(void)fputs("  [ -I file ] [ pattern ... ]\n", stderr);
1501 	(void)fputs("usage: cpio -o [-aABcLv] [ -C bufsize ] [ -H header ]\n",
1502 	    stderr);
1503 	(void)fputs("  [ -O file ]\n", stderr);
1504 	(void)fputs("usage: cpio -p [ adlLmuv ] directory\n", stderr);
1505 #else
1506 	/* no E, M, R, V, b, k or s */
1507 	(void)fputs("usage: cpio -i [-bBcdfkmrsStuvV] [ -C bufsize ]\n", stderr);
1508 	(void)fputs("  [ -E file ] [ -H header ] [ -I file [ -M message ] ]\n",
1509 	    stderr);
1510 	(void)fputs("  [ -R id ] [ pattern ... ]\n", stderr);
1511 	(void)fputs("usage: cpio -o [-aABcLvV] [ -C bufsize ] [ -H header ]\n",
1512 	    stderr);
1513 	(void)fputs("  [ -O file [ -M message ] ]\n", stderr);
1514 	(void)fputs("usage: cpio -p [ adlLmuvV ] [ -R id ] directory\n", stderr);
1515 #endif
1516 	exit(1);
1517 	/* NOTREACHED */
1518 }
1519 
1520 /*
1521  * opt_chdir
1522  *	call ftree_add or pat_add, depending on archive type.
1523  *
1524  * Returns: -1 for listing, else what ftree_add or pat_add returned.
1525  */
1526 
1527 int
1528 opt_chdir(char *name)
1529 {
1530 	switch (act) {
1531 	default:
1532 		return (-1);
1533 		break;
1534 	case ARCHIVE:
1535 	case APPND:
1536 		return (ftree_add(name, 1));
1537 		break;
1538 	case EXTRACT:
1539 		return (pat_add(name, 1));
1540 		break;
1541 	}
1542 }
1543 
1544 /*
1545  * checkpositionalminusC(argvp, addfunc)
1546  */
1547 
1548 void
1549 checkpositionalminusC(char ***argvp, int (*addfunc)(char *, int))
1550 {
1551 	while (**argvp != (char *)NULL) {
1552 		if (!strcmp(**argvp, "-C")) {
1553 			/* XXX should be allow for positional -C/dir, too? */
1554 			if ((*addfunc)(*++*argvp, 1) < 0) {
1555 				tar_usage();
1556 			}
1557 			++*argvp;
1558 			continue;
1559 		}
1560 		if ((*addfunc)(*(*argvp)++, 0) < 0)
1561 			tar_usage();
1562 	}
1563 }
1564