options.c revision 114469
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
40static 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: head/bin/pax/options.c 114469 2003-05-02 00:03:10Z obrien $");
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
67static char flgch[] = FLGCH;	/* list of all possible flags */
68static OPLIST *ophead = NULL;	/* head for format specific options -x */
69static OPLIST *optail = NULL;	/* option tail */
70
71static int no_op(void);
72static void printflg(unsigned int);
73static int c_frmt(const void *, const void *);
74static off_t str_offt(char *);
75static char *getline(FILE *fp);
76static void pax_options(int, char **);
77static void pax_usage(void);
78static void tar_options(int, char **);
79static void tar_usage(void);
80static void cpio_options(int, char **);
81static void cpio_usage(void);
82
83/* errors from getline */
84#define GETLINE_FILE_CORRUPT 1
85#define GETLINE_OUT_OF_MEM 2
86static 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
102FSUB 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	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	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	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	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, 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, 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 */
145int 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
153void
154options(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
187static void
188pax_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
585static void
586tar_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
978int
979mkpath(path)
980	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
1017static void
1018cpio_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 = getline(fp)) != NULL) {
1161					pat_add(str, NULL);
1162				}
1163				fclose(fp);
1164				if (getline_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 = getline(stdin)) != NULL) {
1260				ftree_add(str, NULL);
1261			}
1262			if (getline_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
1278static void
1279printflg(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
1299static int
1300c_frmt(const void *a, const void *b)
1301{
1302	return(strcmp(((FSUB *)a)->name, ((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
1313OPLIST *
1314opt_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
1329int
1330bad_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
1355int
1356opt_add(char *str)
1357{
1358	OPLIST *opt;
1359	char *frpt;
1360	char *pt;
1361	char *endpt;
1362
1363	if ((str == NULL) || (*str == '\0')) {
1364		paxwarn(0, "Invalid option name");
1365		return(-1);
1366	}
1367	if ((str = strdup(str)) == NULL) {
1368		paxwarn(0, "Unable to allocate space for option list");
1369		return(-1);
1370	}
1371	frpt = endpt = str;
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(str);
1384			return(-1);
1385		}
1386		if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
1387			paxwarn(0, "Unable to allocate space for option list");
1388			free(str);
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
1424static off_t
1425str_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
1486char *
1487getline(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
1516static int
1517no_op(void)
1518{
1519	return(0);
1520}
1521
1522/*
1523 * pax_usage()
1524 *	print the usage summary to the user
1525 */
1526
1527void
1528pax_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
1561void
1562tar_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
1576void
1577cpio_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