xref: /original-bsd/bin/pax/options.c (revision 9a45e376)
1 /*-
2  * Copyright (c) 1992 Keith Muller.
3  * Copyright (c) 1992 The Regents of the University of California.
4  * 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  * %sccs.include.redist.c%
10  */
11 
12 #ifndef lint
13 static char sccsid[] = "@(#)options.c	1.1 (Berkeley) 12/17/92";
14 #endif /* not lint */
15 
16 #include <sys/types.h>
17 #include <sys/time.h>
18 #include <sys/stat.h>
19 #include <sys/mtio.h>
20 #include <sys/param.h>
21 #include <stdio.h>
22 #include <ctype.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <limits.h>
27 #include "pax.h"
28 #include "options.h"
29 #include "cpio.h"
30 #include "extern.h"
31 
32 /*
33  * Routines which handle command line options
34  */
35 
36 static char flgch[] = FLGCH;	/* list of all possible flags */
37 static OPLIST *ophead = NULL;	/* head for format specific options -x */
38 static OPLIST *optail = NULL;	/* option tail */
39 
40 static int no_op __P((void));
41 static void printflg __P((unsigned int));
42 static int c_frmt __P((const void *, const void *));
43 static off_t str_offt __P((char *));
44 
45 /*
46  *	Format specific routine table - MUST BE IN SORTED ORDER BY NAME
47  *	(see pax.h for description of each function)
48  *
49  * 	name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
50  *	read, end_read, st_write, write, end_write, trail,
51  *	rd_data, wr_data, options
52  */
53 
54 FSUB fsub[] = {
55 /* 0: OLD BINARY CPIO */
56 	"bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
57 	bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, cpio_trail,
58 	rd_wrfile, wr_rdfile, bad_opt,
59 
60 /* 1: OLD OCTAL CHARACTER CPIO */
61 	"cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
62 	cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, cpio_trail,
63 	rd_wrfile, wr_rdfile, bad_opt,
64 
65 /* 2: SVR4 HEX CPIO */
66 	"sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd,
67 	vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, cpio_trail,
68 	rd_wrfile, wr_rdfile, bad_opt,
69 
70 /* 3: SVR4 HEX CPIO WITH CRC */
71 	"sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
72 	vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, cpio_trail,
73 	rd_wrfile, wr_rdfile, bad_opt,
74 
75 /* 4: OLD TAR */
76 	"tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
77 	tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail,
78 	rd_wrfile, wr_rdfile, tar_opt,
79 
80 /* 5: POSIX USTAR */
81 	"ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd,
82 	ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail,
83 	rd_wrfile, wr_rdfile, bad_opt,
84 };
85 #define DEFLT	5	/* default write format from list above */
86 
87 /*
88  * ford is the archive search order used by get_arc() to determine what kind
89  * of archive we are dealing with. This helps to properly id  archive formats
90  * some formats may be subsets of others....
91  */
92 int ford[] = {5, 4, 3, 2, 1, 0, -1 };
93 
94 /*
95  * options()
96  *	look at the user specified flags. set globals as required and check if
97  *	the user specified a legal set of flags. If not, complain and exit
98  */
99 
100 #if __STDC__
101 void
102 options(register int argc, register char **argv)
103 #else
104 void
105 options(argc, argv)
106 	register int argc;
107 	register char **argv;
108 #endif
109 {
110 	register int c;
111 	register int i;
112 	unsigned int flg = 0;
113 	unsigned int bflg = 0;
114 	register char *pt;
115         FSUB tmp;
116 	extern char *optarg;
117 	extern int optind;
118 
119 	/*
120 	 * process option flags
121 	 */
122 	while ((c=getopt(argc, argv,"ab:cdf:iklno:p:rs:tuvwx:B:E:G:HLT:U:XZ"))
123 	    != EOF) {
124 		switch (c) {
125 		case 'a':
126 			/*
127 			 * append
128 			 */
129 			flg |= AF;
130 			break;
131 		case 'b':
132 			/*
133 			 * specify blocksize on write
134 			 */
135 			flg |= BF;
136 			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
137 				warn(1, "Invalid block size %s", optarg);
138 				usage();
139 			}
140 			break;
141 		case 'c':
142 			/*
143 			 * inverse match on patterns
144 			 */
145 			cflag = 1;
146 			flg |= CF;
147 			break;
148 		case 'd':
149 			/*
150 			 * match only dir on extract, not the subtree at dir
151 			 */
152 			dflag = 1;
153 			flg |= DF;
154 			break;
155 		case 'f':
156 			/*
157 			 * filename where the archive is stored
158 			 */
159 			arcname = optarg;
160 			flg |= FF;
161 			break;
162 		case 'i':
163 			/*
164 			 * interactive file rename
165 			 */
166 			iflag = 1;
167 			flg |= IF;
168 			break;
169 		case 'k':
170 			/*
171 			 * do not clobber files that exist
172 			 */
173 			kflag = 1;
174 			flg |= KF;
175 			break;
176 		case 'l':
177 			/*
178 			 * try to link src to dest with copy (-rw)
179 			 */
180 			lflag = 1;
181 			flg |= LF;
182 			break;
183 		case 'n':
184 			/*
185 			 * select first match for a pattern only
186 			 */
187 			nflag = 1;
188 			flg |= NF;
189 			break;
190 		case 'o':
191 			/*
192 			 * pass format specific options
193 			 */
194 			flg |= OF;
195 			if (opt_add(optarg) < 0)
196 				usage();
197 			break;
198 		case 'p':
199 			/*
200 			 * specify file characteristic options
201 			 */
202 			for (pt = optarg; *pt != '\0'; ++pt) {
203 				switch(*pt) {
204 				case 'a':
205 					/*
206 					 * do not preserve access time
207 					 */
208 					patime = 0;
209 					break;
210 				case 'e':
211 					/*
212 					 * preserve user id, group id, file
213 					 * mode, access/modification times
214 					 */
215 					pids = 1;
216 					pmode = 1;
217 					patime = 1;
218 					pmtime = 1;
219 					break;
220 				case 'm':
221 					/*
222 					 * do not preserve modification time
223 					 */
224 					pmtime = 0;
225 					break;
226 				case 'o':
227 					/*
228 					 * preserve uid/gid
229 					 */
230 					pids = 1;
231 					break;
232 				case 'p':
233 					/*
234 					 * preserver file mode bits
235 					 */
236 					pmode = 1;
237 					break;
238 				default:
239 					warn(1, "Invalid -p string: %c", *pt);
240 					usage();
241 					break;
242 				}
243 			}
244 			flg |= PF;
245 			break;
246 		case 'r':
247 			/*
248 			 * read the archive
249 			 */
250 			flg |= RF;
251 			break;
252 		case 's':
253 			/*
254 			 * file name substitution name pattern
255 			 */
256 			if (rep_add(optarg) < 0) {
257 				usage();
258 				break;
259 			}
260 			flg |= SF;
261 			break;
262 		case 't':
263 			/*
264 			 * preserve access time on filesystem nodes we read
265 			 */
266 			tflag = 1;
267 			flg |= TF;
268 			break;
269 		case 'u':
270 			/*
271 			 * ignore those older files
272 			 */
273 			uflag = 1;
274 			flg |= UF;
275 			break;
276 		case 'v':
277 			/*
278 			 * verbose operation mode
279 			 */
280 			vflag = 1;
281 			flg |= VF;
282 			break;
283 		case 'w':
284 			/*
285 			 * write an archive
286 			 */
287 			flg |= WF;
288 			break;
289 		case 'x':
290 			/*
291 			 * specify an archive format on write
292 			 */
293 			tmp.name = optarg;
294 			if (frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
295 			    sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) {
296 				flg |= XF;
297 				break;
298 			}
299 			warn(1, "Unknown -x format: %s", optarg);
300 			(void)fputs("pax: Known -x formats are:", stderr);
301 			for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
302 				(void)fprintf(stderr, " %s", fsub[i].name);
303 			(void)fputs("\n\n", stderr);
304 			usage();
305 			break;
306 		case 'B':
307 			/*
308 			 * non-standard option on number of bytes written on a
309 			 * single archive volume.
310 			 */
311 			if ((wrlimit = str_offt(optarg)) <= 0) {
312 				warn(1, "Invalid write limit %s", optarg);
313 				usage();
314 			}
315 			if (wrlimit % BLKMULT) {
316 				warn(1, "Write limit is not a %d byte multiple",
317 				    BLKMULT);
318 				usage();
319 			}
320 			flg |= CBF;
321 			break;
322 		case 'E':
323 			/*
324 			 * non-standard limit on read faults
325 			 * 0 indicates stop after first error, values
326 			 * indicate a limit, "NONE" try forever
327 			 */
328 			flg |= CEF;
329 			if (strcmp(NONE, optarg) == 0)
330 				maxflt = -1;
331 			else if ((maxflt = atoi(optarg)) < 0) {
332 				warn(1, "Error count value must be positive");
333 				usage();
334 			}
335 			break;
336 		case 'G':
337 			/*
338 			 * non-standard option for selecting files within an
339 			 * archive by group (gid or name)
340 			 */
341 			if (grp_add(optarg) < 0) {
342 				usage();
343 				break;
344 			}
345 			flg |= CGF;
346 			break;
347 		case 'H':
348 			/*
349 			 * follow command line symlinks only
350 			 */
351 			Hflag = 1;
352 			flg |= CHF;
353 			break;
354 		case 'L':
355 			/*
356 			 * follow symlinks
357 			 */
358 			Lflag = 1;
359 			flg |= CLF;
360 			break;
361 		case 'T':
362 			/*
363 			 * non-standard option for selecting files within an
364 			 * archive by modification time range (lower,upper)
365 			 */
366 			if (trng_add(optarg) < 0) {
367 				usage();
368 				break;
369 			}
370 			flg |= CTF;
371 			break;
372 		case 'U':
373 			/*
374 			 * non-standard option for selecting files within an
375 			 * archive by user (uid or name)
376 			 */
377 			if (usr_add(optarg) < 0) {
378 				usage();
379 				break;
380 			}
381 			flg |= CUF;
382 			break;
383 		case 'X':
384 			/*
385 			 * do not pass over mount points in the file system
386 			 */
387 			Xflag = 1;
388 			flg |= CXF;
389 			break;
390 		case 'Z':
391 			/*
392 			 * On extraction check file time after the modification
393 			 * of the file name. Non standard option.
394 			 */
395 			Zflag = 1;
396 			flg |= CZF;
397 			break;
398 		case '?':
399 		default:
400 			usage();
401 			break;
402 		}
403 	}
404 
405 	/*
406 	 * figure out the operation mode of pax read,write,extract,copy,append
407 	 * or list. check that we have not been given a bogus set of flags
408 	 * for the operation mode.
409 	 */
410 	if (ISLIST(flg)) {
411 		act = LIST;
412 		bflg = flg & BDLIST;
413 	} else if (ISEXTRACT(flg)) {
414 		act = EXTRACT;
415 		bflg = flg & BDEXTR;
416 	} else if (ISARCHIVE(flg)) {
417 		act = ARCHIVE;
418 		bflg = flg & BDARCH;
419 	} else if (ISAPPND(flg)) {
420 		act = APPND;
421 		bflg = flg & BDARCH;
422 	} else if (ISCOPY(flg)) {
423 		act = COPY;
424 		bflg = flg & BDCOPY;
425 	} else
426 		usage();
427 	if (bflg) {
428 		printflg(flg);
429 		usage();
430 	}
431 
432 	/*
433 	 * if we are writing (ARCHIVE) we use the default format if the user
434 	 * did not specify a format. when we write during an APPEND, we will
435 	 * adopt the format of the existing archive if none was supplied.
436 	 */
437 	if (!(flg & XF) && (act == ARCHIVE))
438 		frmt = &(fsub[DEFLT]);
439 
440 	/*
441 	 * process the args as they are interpreted by the operation mode
442 	 */
443 	switch (act) {
444 	case LIST:
445 	case EXTRACT:
446 		for (; optind < argc; optind++)
447 			if (pat_add(argv[optind]) < 0)
448 				usage();
449 		break;
450 	case COPY:
451 		if (optind >= argc) {
452 			warn(0, "Destination directory was not supplied");
453 			usage();
454 		}
455 		--argc;
456 		dirptr = argv[argc];
457 		/* FALL THROUGH */
458 	case ARCHIVE:
459 	case APPND:
460 		for (; optind < argc; optind++)
461 			if (ftree_add(argv[optind]) < 0)
462 				usage();
463 		/*
464 		 * no read errors allowed on updates/append operation!
465 		 */
466 		maxflt = 0;
467 		break;
468 	}
469 }
470 
471 /*
472  * printflg()
473  *	print out those invalid flag sets found to the user
474  */
475 
476 #if __STDC__
477 static void
478 printflg(unsigned int flg)
479 #else
480 static void
481 printflg(flg)
482 	unsigned int flg;
483 #endif
484 {
485 	int nxt;
486 	int pos = 0;
487 
488 	(void)fputs("pax: Invalid combination of options:", stderr);
489 	while (nxt = ffs(flg)) {
490 		flg = flg >> nxt;
491 		pos += nxt;
492 		(void)fprintf(stderr, " -%c", flgch[pos-1]);
493 	}
494 	(void)putc('\n', stderr);
495 }
496 
497 /*
498  * c_frmt()
499  *	comparison routine used by bsearch to find the format specified
500  *	by the user
501  */
502 
503 #if __STDC__
504 static int
505 c_frmt(const void *a, const void *b)
506 #else
507 static int
508 c_frmt(a, b)
509         void *a;
510         void *b;
511 #endif
512 {
513         return(strcmp(((FSUB *)a)->name, ((FSUB *)b)->name));
514 }
515 
516 /*
517  * opt_next()
518  *	called by format specific options routines to get each format specific
519  *	flag and value specified with -o
520  * Return:
521  *	pointer to next OPLIST entry or NULL (end of list).
522  */
523 
524 #if __STDC__
525 OPLIST *
526 opt_next(void)
527 #else
528 OPLIST *
529 opt_next()
530 #endif
531 {
532 	OPLIST *opt;
533 
534 	if ((opt = ophead) != NULL)
535 		ophead = ophead->fow;
536 	return(opt);
537 }
538 
539 /*
540  * bad_opt()
541  *	generic routine used to complain about a format specific options
542  *	when the format does not support options.
543  */
544 
545 #if __STDC__
546 int
547 bad_opt(void)
548 #else
549 int
550 bad_opt()
551 #endif
552 {
553 	register OPLIST *opt;
554 
555 	if (ophead == NULL)
556 		return(0);
557 	/*
558 	 * print all we were given
559 	 */
560 	warn(1,"These format options are not supported");
561 	while ((opt = opt_next()) != NULL)
562 		(void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
563 	usage();
564 	return(0);
565 }
566 
567 /*
568  * opt_add()
569  *	breaks the value supplied to -o into a option name and value. options
570  *	are given to -o in the form -o name-value,name=value
571  *	mulltiple -o may be specified.
572  * Return:
573  *	0 if format in name=value format, -1 if -o is passed junk
574  */
575 
576 #if __STDC__
577 int
578 opt_add(register char *str)
579 #else
580 int
581 opt_add(str)
582 	register char *str;
583 #endif
584 {
585 	register OPLIST *opt;
586 	register char *frpt;
587 	register char *pt;
588 	register char *endpt;
589 
590 	if ((str == NULL) || (*str == '\0')) {
591 		warn(0, "Invalid option name");
592 		return(-1);
593 	}
594 	frpt = endpt = str;
595 
596 	/*
597 	 * break into name and values pieces and stuff each one into a
598 	 * OPLIST structure. When we know the format, the format specific
599 	 * option function will go through this list
600 	 */
601 	while ((frpt != NULL) && (*frpt != '\0')) {
602 		if ((endpt = strchr(frpt, ',')) != NULL)
603 			*endpt = '\0';
604 		if ((pt = strchr(frpt, '=')) == NULL) {
605 			warn(0, "Invalid options format");
606 			return(-1);
607 		}
608 		if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
609 			warn(0, "Unable to allocate space for option list");
610 			return(-1);
611 		}
612 		*pt++ = '\0';
613 		opt->name = frpt;
614 		opt->value = pt;
615 		opt->fow = NULL;
616 		if (endpt != NULL)
617 			frpt = endpt + 1;
618 		else
619 			frpt = NULL;
620 		if (ophead == NULL) {
621 			optail = ophead = opt;
622 			continue;
623 		}
624 		optail->fow = opt;
625 		optail = opt;
626 	}
627 	return(0);
628 }
629 
630 /*
631  * str_offt()
632  *	Convert an expression of the following forms to an off_t > 0.
633  * 	1) A positive decimal number.
634  *	2) A positive decimal number followed by a b (mult by 512).
635  *	3) A positive decimal number followed by a k (mult by 1024).
636  *	4) A positive decimal number followed by a m (mult by 512).
637  *	5) A positive decimal number followed by a w (mult by sizeof int)
638  *	6) Two or more positive decimal numbers (with/without k,b or w).
639  *	   seperated by x (also * for backwards compatibility), specifying
640  *	   the product of the indicated values.
641  * Return:
642  *	0 for an error, a positive value o.w.
643  */
644 
645 #if __STDC__
646 static off_t
647 str_offt(char *val)
648 #else
649 static off_t
650 str_offt(val)
651 	char *val;
652 #endif
653 {
654 	char *expr;
655 	off_t num, t;
656 
657 #	ifdef NET2_STAT
658 	num = strtol(val, &expr, 0);
659 	if ((num == LONG_MAX) || (num <= 0) || (expr == val))
660 #	else
661 	num = strtoq(val, &expr, 0);
662 	if ((num == QUAD_MAX) || (num <= 0) || (expr == val))
663 #	endif
664 		return(0);
665 
666 	switch(*expr) {
667 	case 'b':
668 		t = num;
669 		num *= 512;
670 		if (t > num)
671 			return(0);
672 		++expr;
673 		break;
674 	case 'k':
675 		t = num;
676 		num *= 1024;
677 		if (t > num)
678 			return(0);
679 		++expr;
680 		break;
681 	case 'm':
682 		t = num;
683 		num *= 1048576;
684 		if (t > num)
685 			return(0);
686 		++expr;
687 		break;
688 	case 'w':
689 		t = num;
690 		num *= sizeof(int);
691 		if (t > num)
692 			return(0);
693 		++expr;
694 		break;
695 	}
696 
697 	switch(*expr) {
698 		case '\0':
699 			break;
700 		case '*':
701 		case 'x':
702 			t = num;
703 			num *= str_offt(expr + 1);
704 			if (t > num)
705 				return(0);
706 			break;
707 		default:
708 			return(0);
709 	}
710 	return(num);
711 }
712 
713 /*
714  * no_op()
715  *	for those option functions where the archive format has nothing to do.
716  * Return:
717  *	0
718  */
719 
720 #if __STDC__
721 static int
722 no_op(void)
723 #else
724 static int
725 no_op()
726 #endif
727 {
728 	return(0);
729 }
730