xref: /original-bsd/bin/pax/options.c (revision 4918a0cd)
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  * %sccs.include.redist.c%
10  */
11 
12 #ifndef lint
13 static char sccsid[] = "@(#)options.c	8.1 (Berkeley) 05/31/93";
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:DE:G:HLT:U:XYZ"))
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 'D':
323 			/*
324 			 * On extraction check file inode change time before the
325 			 * modification of the file name. Non standard option.
326 			 */
327 			Dflag = 1;
328 			flg |= CDF;
329 			break;
330 		case 'E':
331 			/*
332 			 * non-standard limit on read faults
333 			 * 0 indicates stop after first error, values
334 			 * indicate a limit, "NONE" try forever
335 			 */
336 			flg |= CEF;
337 			if (strcmp(NONE, optarg) == 0)
338 				maxflt = -1;
339 			else if ((maxflt = atoi(optarg)) < 0) {
340 				warn(1, "Error count value must be positive");
341 				usage();
342 			}
343 			break;
344 		case 'G':
345 			/*
346 			 * non-standard option for selecting files within an
347 			 * archive by group (gid or name)
348 			 */
349 			if (grp_add(optarg) < 0) {
350 				usage();
351 				break;
352 			}
353 			flg |= CGF;
354 			break;
355 		case 'H':
356 			/*
357 			 * follow command line symlinks only
358 			 */
359 			Hflag = 1;
360 			flg |= CHF;
361 			break;
362 		case 'L':
363 			/*
364 			 * follow symlinks
365 			 */
366 			Lflag = 1;
367 			flg |= CLF;
368 			break;
369 		case 'T':
370 			/*
371 			 * non-standard option for selecting files within an
372 			 * archive by modification time range (lower,upper)
373 			 */
374 			if (trng_add(optarg) < 0) {
375 				usage();
376 				break;
377 			}
378 			flg |= CTF;
379 			break;
380 		case 'U':
381 			/*
382 			 * non-standard option for selecting files within an
383 			 * archive by user (uid or name)
384 			 */
385 			if (usr_add(optarg) < 0) {
386 				usage();
387 				break;
388 			}
389 			flg |= CUF;
390 			break;
391 		case 'X':
392 			/*
393 			 * do not pass over mount points in the file system
394 			 */
395 			Xflag = 1;
396 			flg |= CXF;
397 			break;
398 		case 'Y':
399 			/*
400 			 * On extraction check file inode change time after the
401 			 * modification of the file name. Non standard option.
402 			 */
403 			Yflag = 1;
404 			flg |= CYF;
405 			break;
406 		case 'Z':
407 			/*
408 			 * On extraction check modification time after the
409 			 * modification of the file name. Non standard option.
410 			 */
411 			Zflag = 1;
412 			flg |= CZF;
413 			break;
414 		case '?':
415 		default:
416 			usage();
417 			break;
418 		}
419 	}
420 
421 	/*
422 	 * figure out the operation mode of pax read,write,extract,copy,append
423 	 * or list. check that we have not been given a bogus set of flags
424 	 * for the operation mode.
425 	 */
426 	if (ISLIST(flg)) {
427 		act = LIST;
428 		bflg = flg & BDLIST;
429 	} else if (ISEXTRACT(flg)) {
430 		act = EXTRACT;
431 		bflg = flg & BDEXTR;
432 	} else if (ISARCHIVE(flg)) {
433 		act = ARCHIVE;
434 		bflg = flg & BDARCH;
435 	} else if (ISAPPND(flg)) {
436 		act = APPND;
437 		bflg = flg & BDARCH;
438 	} else if (ISCOPY(flg)) {
439 		act = COPY;
440 		bflg = flg & BDCOPY;
441 	} else
442 		usage();
443 	if (bflg) {
444 		printflg(flg);
445 		usage();
446 	}
447 
448 	/*
449 	 * if we are writing (ARCHIVE) we use the default format if the user
450 	 * did not specify a format. when we write during an APPEND, we will
451 	 * adopt the format of the existing archive if none was supplied.
452 	 */
453 	if (!(flg & XF) && (act == ARCHIVE))
454 		frmt = &(fsub[DEFLT]);
455 
456 	/*
457 	 * process the args as they are interpreted by the operation mode
458 	 */
459 	switch (act) {
460 	case LIST:
461 	case EXTRACT:
462 		for (; optind < argc; optind++)
463 			if (pat_add(argv[optind]) < 0)
464 				usage();
465 		break;
466 	case COPY:
467 		if (optind >= argc) {
468 			warn(0, "Destination directory was not supplied");
469 			usage();
470 		}
471 		--argc;
472 		dirptr = argv[argc];
473 		/* FALL THROUGH */
474 	case ARCHIVE:
475 	case APPND:
476 		for (; optind < argc; optind++)
477 			if (ftree_add(argv[optind]) < 0)
478 				usage();
479 		/*
480 		 * no read errors allowed on updates/append operation!
481 		 */
482 		maxflt = 0;
483 		break;
484 	}
485 }
486 
487 /*
488  * printflg()
489  *	print out those invalid flag sets found to the user
490  */
491 
492 #if __STDC__
493 static void
494 printflg(unsigned int flg)
495 #else
496 static void
497 printflg(flg)
498 	unsigned int flg;
499 #endif
500 {
501 	int nxt;
502 	int pos = 0;
503 
504 	(void)fputs("pax: Invalid combination of options:", stderr);
505 	while (nxt = ffs(flg)) {
506 		flg = flg >> nxt;
507 		pos += nxt;
508 		(void)fprintf(stderr, " -%c", flgch[pos-1]);
509 	}
510 	(void)putc('\n', stderr);
511 }
512 
513 /*
514  * c_frmt()
515  *	comparison routine used by bsearch to find the format specified
516  *	by the user
517  */
518 
519 #if __STDC__
520 static int
521 c_frmt(const void *a, const void *b)
522 #else
523 static int
524 c_frmt(a, b)
525         void *a;
526         void *b;
527 #endif
528 {
529         return(strcmp(((FSUB *)a)->name, ((FSUB *)b)->name));
530 }
531 
532 /*
533  * opt_next()
534  *	called by format specific options routines to get each format specific
535  *	flag and value specified with -o
536  * Return:
537  *	pointer to next OPLIST entry or NULL (end of list).
538  */
539 
540 #if __STDC__
541 OPLIST *
542 opt_next(void)
543 #else
544 OPLIST *
545 opt_next()
546 #endif
547 {
548 	OPLIST *opt;
549 
550 	if ((opt = ophead) != NULL)
551 		ophead = ophead->fow;
552 	return(opt);
553 }
554 
555 /*
556  * bad_opt()
557  *	generic routine used to complain about a format specific options
558  *	when the format does not support options.
559  */
560 
561 #if __STDC__
562 int
563 bad_opt(void)
564 #else
565 int
566 bad_opt()
567 #endif
568 {
569 	register OPLIST *opt;
570 
571 	if (ophead == NULL)
572 		return(0);
573 	/*
574 	 * print all we were given
575 	 */
576 	warn(1,"These format options are not supported");
577 	while ((opt = opt_next()) != NULL)
578 		(void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
579 	usage();
580 	return(0);
581 }
582 
583 /*
584  * opt_add()
585  *	breaks the value supplied to -o into a option name and value. options
586  *	are given to -o in the form -o name-value,name=value
587  *	mulltiple -o may be specified.
588  * Return:
589  *	0 if format in name=value format, -1 if -o is passed junk
590  */
591 
592 #if __STDC__
593 int
594 opt_add(register char *str)
595 #else
596 int
597 opt_add(str)
598 	register char *str;
599 #endif
600 {
601 	register OPLIST *opt;
602 	register char *frpt;
603 	register char *pt;
604 	register char *endpt;
605 
606 	if ((str == NULL) || (*str == '\0')) {
607 		warn(0, "Invalid option name");
608 		return(-1);
609 	}
610 	frpt = endpt = str;
611 
612 	/*
613 	 * break into name and values pieces and stuff each one into a
614 	 * OPLIST structure. When we know the format, the format specific
615 	 * option function will go through this list
616 	 */
617 	while ((frpt != NULL) && (*frpt != '\0')) {
618 		if ((endpt = strchr(frpt, ',')) != NULL)
619 			*endpt = '\0';
620 		if ((pt = strchr(frpt, '=')) == NULL) {
621 			warn(0, "Invalid options format");
622 			return(-1);
623 		}
624 		if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
625 			warn(0, "Unable to allocate space for option list");
626 			return(-1);
627 		}
628 		*pt++ = '\0';
629 		opt->name = frpt;
630 		opt->value = pt;
631 		opt->fow = NULL;
632 		if (endpt != NULL)
633 			frpt = endpt + 1;
634 		else
635 			frpt = NULL;
636 		if (ophead == NULL) {
637 			optail = ophead = opt;
638 			continue;
639 		}
640 		optail->fow = opt;
641 		optail = opt;
642 	}
643 	return(0);
644 }
645 
646 /*
647  * str_offt()
648  *	Convert an expression of the following forms to an off_t > 0.
649  * 	1) A positive decimal number.
650  *	2) A positive decimal number followed by a b (mult by 512).
651  *	3) A positive decimal number followed by a k (mult by 1024).
652  *	4) A positive decimal number followed by a m (mult by 512).
653  *	5) A positive decimal number followed by a w (mult by sizeof int)
654  *	6) Two or more positive decimal numbers (with/without k,b or w).
655  *	   seperated by x (also * for backwards compatibility), specifying
656  *	   the product of the indicated values.
657  * Return:
658  *	0 for an error, a positive value o.w.
659  */
660 
661 #if __STDC__
662 static off_t
663 str_offt(char *val)
664 #else
665 static off_t
666 str_offt(val)
667 	char *val;
668 #endif
669 {
670 	char *expr;
671 	off_t num, t;
672 
673 #	ifdef NET2_STAT
674 	num = strtol(val, &expr, 0);
675 	if ((num == LONG_MAX) || (num <= 0) || (expr == val))
676 #	else
677 	num = strtoq(val, &expr, 0);
678 	if ((num == QUAD_MAX) || (num <= 0) || (expr == val))
679 #	endif
680 		return(0);
681 
682 	switch(*expr) {
683 	case 'b':
684 		t = num;
685 		num *= 512;
686 		if (t > num)
687 			return(0);
688 		++expr;
689 		break;
690 	case 'k':
691 		t = num;
692 		num *= 1024;
693 		if (t > num)
694 			return(0);
695 		++expr;
696 		break;
697 	case 'm':
698 		t = num;
699 		num *= 1048576;
700 		if (t > num)
701 			return(0);
702 		++expr;
703 		break;
704 	case 'w':
705 		t = num;
706 		num *= sizeof(int);
707 		if (t > num)
708 			return(0);
709 		++expr;
710 		break;
711 	}
712 
713 	switch(*expr) {
714 		case '\0':
715 			break;
716 		case '*':
717 		case 'x':
718 			t = num;
719 			num *= str_offt(expr + 1);
720 			if (t > num)
721 				return(0);
722 			break;
723 		default:
724 			return(0);
725 	}
726 	return(num);
727 }
728 
729 /*
730  * no_op()
731  *	for those option functions where the archive format has nothing to do.
732  * Return:
733  *	0
734  */
735 
736 #if __STDC__
737 static int
738 no_op(void)
739 #else
740 static int
741 no_op()
742 #endif
743 {
744 	return(0);
745 }
746