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