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