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