xref: /netbsd-src/bin/pax/options.c (revision ae9172d6cd9432a6a1a56760d86b32c57a66c39c)
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 #ifndef lint
39 /*static char sccsid[] = "from: @(#)options.c	8.2 (Berkeley) 4/18/94";*/
40 static char *rcsid = "$Id: options.c,v 1.4 1994/06/14 01:16:10 jtc Exp $";
41 #endif /* not lint */
42 
43 #include <sys/types.h>
44 #include <sys/time.h>
45 #include <sys/stat.h>
46 #include <sys/mtio.h>
47 #include <sys/param.h>
48 #include <stdio.h>
49 #include <ctype.h>
50 #include <string.h>
51 #include <unistd.h>
52 #include <stdlib.h>
53 #include <limits.h>
54 #include "pax.h"
55 #include "options.h"
56 #include "cpio.h"
57 #include "tar.h"
58 #include "extern.h"
59 
60 /*
61  * Routines which handle command line options
62  */
63 
64 static char flgch[] = FLGCH;	/* list of all possible flags */
65 static OPLIST *ophead = NULL;	/* head for format specific options -x */
66 static OPLIST *optail = NULL;	/* option tail */
67 
68 static int no_op __P((void));
69 static void printflg __P((unsigned int));
70 static int c_frmt __P((const void *, const void *));
71 static off_t str_offt __P((char *));
72 static void pax_options __P((register int, register char **));
73 static void pax_usage __P((void));
74 static void tar_options __P((register int, register char **));
75 static void tar_usage __P((void));
76 #ifdef notdef
77 static void cpio_options __P((register int, register char **));
78 static void cpio_usage __P((void));
79 #endif
80 
81 /*
82  *	Format specific routine table - MUST BE IN SORTED ORDER BY NAME
83  *	(see pax.h for description of each function)
84  *
85  * 	name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
86  *	read, end_read, st_write, write, end_write, trail,
87  *	rd_data, wr_data, options
88  */
89 
90 FSUB fsub[] = {
91 /* 0: OLD BINARY CPIO */
92 	"bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
93 	bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, cpio_trail,
94 	rd_wrfile, wr_rdfile, bad_opt,
95 
96 /* 1: OLD OCTAL CHARACTER CPIO */
97 	"cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
98 	cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, cpio_trail,
99 	rd_wrfile, wr_rdfile, bad_opt,
100 
101 /* 2: SVR4 HEX CPIO */
102 	"sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd,
103 	vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, cpio_trail,
104 	rd_wrfile, wr_rdfile, bad_opt,
105 
106 /* 3: SVR4 HEX CPIO WITH CRC */
107 	"sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
108 	vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, cpio_trail,
109 	rd_wrfile, wr_rdfile, bad_opt,
110 
111 /* 4: OLD TAR */
112 	"tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
113 	tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail,
114 	rd_wrfile, wr_rdfile, tar_opt,
115 
116 /* 5: POSIX USTAR */
117 	"ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd,
118 	ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail,
119 	rd_wrfile, wr_rdfile, bad_opt,
120 };
121 #define F_TAR	4	/* format when called as tar */
122 #define DEFLT	5	/* default write format from list above */
123 
124 /*
125  * ford is the archive search order used by get_arc() to determine what kind
126  * of archive we are dealing with. This helps to properly id  archive formats
127  * some formats may be subsets of others....
128  */
129 int ford[] = {5, 4, 3, 2, 1, 0, -1 };
130 
131 /*
132  * options()
133  *	figure out if we are pax, tar or cpio. Call the appropriate options
134  *	parser
135  */
136 
137 #if __STDC__
138 void
139 options(register int argc, register char **argv)
140 #else
141 void
142 options(argc, argv)
143 	register int argc;
144 	register char **argv;
145 #endif
146 {
147 
148 	/*
149 	 * Are we acting like pax, tar or cpio (based on argv[0])
150 	 */
151 	if ((argv0 = strrchr(argv[0], '/')) != NULL)
152 		argv0++;
153 	else
154 		argv0 = argv[0];
155 
156 	if (strcmp(NM_TAR, argv0) == 0)
157 		return(tar_options(argc, argv));
158 #	ifdef notdef
159 	else if (strcmp(NM_CPIO, argv0) == 0)
160 		return(cpio_options(argc, argv));
161 #	endif
162 	/*
163 	 * assume pax as the default
164 	 */
165 	argv0 = NM_PAX;
166 	return(pax_options(argc, argv));
167 }
168 
169 /*
170  * pax_options()
171  *	look at the user specified flags. set globals as required and check if
172  *	the user specified a legal set of flags. If not, complain and exit
173  */
174 
175 #if __STDC__
176 static void
177 pax_options(register int argc, register char **argv)
178 #else
179 static void
180 pax_options(argc, argv)
181 	register int argc;
182 	register char **argv;
183 #endif
184 {
185 	register int c;
186 	register int i;
187 	unsigned int flg = 0;
188 	unsigned int bflg = 0;
189 	register char *pt;
190         FSUB tmp;
191 	extern char *optarg;
192 	extern int optind;
193 
194 	/*
195 	 * process option flags
196 	 */
197 	while ((c=getopt(argc,argv,"ab:cdf:iklno:p:rs:tuvwx:B:DE:G:HLPT:U:XYZ"))
198 	    != EOF) {
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 				warn(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 					warn(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 filesystem 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)) {
371 				flg |= XF;
372 				break;
373 			}
374 			warn(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 'B':
382 			/*
383 			 * non-standard option on number of bytes written on a
384 			 * single archive volume.
385 			 */
386 			if ((wrlimit = str_offt(optarg)) <= 0) {
387 				warn(1, "Invalid write limit %s", optarg);
388 				pax_usage();
389 			}
390 			if (wrlimit % BLKMULT) {
391 				warn(1, "Write limit is not a %d byte multiple",
392 				    BLKMULT);
393 				pax_usage();
394 			}
395 			flg |= CBF;
396 			break;
397 		case 'D':
398 			/*
399 			 * On extraction check file inode change time before the
400 			 * modification of the file name. Non standard option.
401 			 */
402 			Dflag = 1;
403 			flg |= CDF;
404 			break;
405 		case 'E':
406 			/*
407 			 * non-standard limit on read faults
408 			 * 0 indicates stop after first error, values
409 			 * indicate a limit, "NONE" try forever
410 			 */
411 			flg |= CEF;
412 			if (strcmp(NONE, optarg) == 0)
413 				maxflt = -1;
414 			else if ((maxflt = atoi(optarg)) < 0) {
415 				warn(1, "Error count value must be positive");
416 				pax_usage();
417 			}
418 			break;
419 		case 'G':
420 			/*
421 			 * non-standard option for selecting files within an
422 			 * archive by group (gid or name)
423 			 */
424 			if (grp_add(optarg) < 0) {
425 				pax_usage();
426 				break;
427 			}
428 			flg |= CGF;
429 			break;
430 		case 'H':
431 			/*
432 			 * follow command line symlinks only
433 			 */
434 			Hflag = 1;
435 			flg |= CHF;
436 			break;
437 		case 'L':
438 			/*
439 			 * follow symlinks
440 			 */
441 			Lflag = 1;
442 			flg |= CLF;
443 			break;
444 		case 'P':
445 			/*
446 			 * do NOT follow symlinks (default)
447 			 */
448 			Lflag = 0;
449 			flg |= CPF;
450 			break;
451 		case 'T':
452 			/*
453 			 * non-standard option for selecting files within an
454 			 * archive by modification time range (lower,upper)
455 			 */
456 			if (trng_add(optarg) < 0) {
457 				pax_usage();
458 				break;
459 			}
460 			flg |= CTF;
461 			break;
462 		case 'U':
463 			/*
464 			 * non-standard option for selecting files within an
465 			 * archive by user (uid or name)
466 			 */
467 			if (usr_add(optarg) < 0) {
468 				pax_usage();
469 				break;
470 			}
471 			flg |= CUF;
472 			break;
473 		case 'X':
474 			/*
475 			 * do not pass over mount points in the file system
476 			 */
477 			Xflag = 1;
478 			flg |= CXF;
479 			break;
480 		case 'Y':
481 			/*
482 			 * On extraction check file inode change time after the
483 			 * modification of the file name. Non standard option.
484 			 */
485 			Yflag = 1;
486 			flg |= CYF;
487 			break;
488 		case 'Z':
489 			/*
490 			 * On extraction check modification time after the
491 			 * modification of the file name. Non standard option.
492 			 */
493 			Zflag = 1;
494 			flg |= CZF;
495 			break;
496 		case '?':
497 		default:
498 			pax_usage();
499 			break;
500 		}
501 	}
502 
503 	/*
504 	 * figure out the operation mode of pax read,write,extract,copy,append
505 	 * or list. check that we have not been given a bogus set of flags
506 	 * for the operation mode.
507 	 */
508 	if (ISLIST(flg)) {
509 		act = LIST;
510 		bflg = flg & BDLIST;
511 	} else if (ISEXTRACT(flg)) {
512 		act = EXTRACT;
513 		bflg = flg & BDEXTR;
514 	} else if (ISARCHIVE(flg)) {
515 		act = ARCHIVE;
516 		bflg = flg & BDARCH;
517 	} else if (ISAPPND(flg)) {
518 		act = APPND;
519 		bflg = flg & BDARCH;
520 	} else if (ISCOPY(flg)) {
521 		act = COPY;
522 		bflg = flg & BDCOPY;
523 	} else
524 		pax_usage();
525 	if (bflg) {
526 		printflg(flg);
527 		pax_usage();
528 	}
529 
530 	/*
531 	 * if we are writing (ARCHIVE) we use the default format if the user
532 	 * did not specify a format. when we write during an APPEND, we will
533 	 * adopt the format of the existing archive if none was supplied.
534 	 */
535 	if (!(flg & XF) && (act == ARCHIVE))
536 		frmt = &(fsub[DEFLT]);
537 
538 	/*
539 	 * process the args as they are interpreted by the operation mode
540 	 */
541 	switch (act) {
542 	case LIST:
543 	case EXTRACT:
544 		for (; optind < argc; optind++)
545 			if (pat_add(argv[optind]) < 0)
546 				pax_usage();
547 		break;
548 	case COPY:
549 		if (optind >= argc) {
550 			warn(0, "Destination directory was not supplied");
551 			pax_usage();
552 		}
553 		--argc;
554 		dirptr = argv[argc];
555 		/* FALL THROUGH */
556 	case ARCHIVE:
557 	case APPND:
558 		for (; optind < argc; optind++)
559 			if (ftree_add(argv[optind]) < 0)
560 				pax_usage();
561 		/*
562 		 * no read errors allowed on updates/append operation!
563 		 */
564 		maxflt = 0;
565 		break;
566 	}
567 }
568 
569 
570 /*
571  * tar_options()
572  *	look at the user specified flags. set globals as required and check if
573  *	the user specified a legal set of flags. If not, complain and exit
574  */
575 
576 #if __STDC__
577 static void
578 tar_options(register int argc, register char **argv)
579 #else
580 static void
581 tar_options(argc, argv)
582 	register int argc;
583 	register char **argv;
584 #endif
585 {
586 	register int c;
587 	int fstdin = 0;
588 
589 	/*
590 	 * process option flags
591 	 */
592 	while ((c = getoldopt(argc, argv, "b:cef:moprutvwxBHLPX014578"))
593 	    != EOF)  {
594 		switch(c) {
595 		case 'b':
596 			/*
597 			 * specify blocksize
598 			 */
599 			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
600 				warn(1, "Invalid block size %s", optarg);
601 				tar_usage();
602 			}
603 			break;
604 		case 'c':
605 			/*
606 			 * create an archive
607 			 */
608 			act = ARCHIVE;
609 			break;
610 		case 'e':
611 			/*
612 			 * stop after first error
613 			 */
614 			maxflt = 0;
615 			break;
616 		case 'f':
617 			/*
618 			 * filename where the archive is stored
619 			 */
620 			if ((optarg[0] == '-') && (optarg[1]== '\0')) {
621 				/*
622 				 * treat a - as stdin
623 				 */
624 				fstdin = 1;
625 				arcname = (char *)0;
626 				break;
627 			}
628 			fstdin = 0;
629 			arcname = optarg;
630 			break;
631 		case 'm':
632 			/*
633 			 * do not preserve modification time
634 			 */
635 			pmtime = 0;
636 			break;
637 		case 'o':
638 			if (opt_add("write_opt=nodir") < 0)
639 				tar_usage();
640 			break;
641 		case 'p':
642 			/*
643 			 * preserve user id, group id, file
644 			 * mode, access/modification times
645 			 */
646 			pids = 1;
647 			pmode = 1;
648 			patime = 1;
649 			pmtime = 1;
650 			break;
651 		case 'r':
652 		case 'u':
653 			/*
654 			 * append to the archive
655 			 */
656 			act = APPND;
657 			break;
658 		case 't':
659 			/*
660 			 * list contents of the tape
661 			 */
662 			act = LIST;
663 			break;
664 		case 'v':
665 			/*
666 			 * verbose operation mode
667 			 */
668 			vflag = 1;
669 			break;
670 		case 'w':
671 			/*
672 			 * interactive file rename
673 			 */
674 			iflag = 1;
675 			break;
676 		case 'x':
677 			/*
678 			 * write an archive
679 			 */
680 			act = EXTRACT;
681 			break;
682 		case 'B':
683 			/*
684 			 * Nothing to do here, this is pax default
685 			 */
686 			break;
687 		case 'H':
688 			/*
689 			 * follow command line symlinks only
690 			 */
691 			Hflag = 1;
692 			break;
693 		case 'L':
694 			/*
695 			 * follow symlinks
696 			 */
697 			Lflag = 1;
698 			break;
699 		case 'P':
700 			/*
701 			 * do not follow symlinks
702 			 */
703 			Lflag = 0;
704 			break;
705 		case 'X':
706 			/*
707 			 * do not pass over mount points in the file system
708 			 */
709 			Xflag = 1;
710 			break;
711 		case '0':
712 			arcname = DEV_0;
713 			break;
714 		case '1':
715 			arcname = DEV_1;
716 			break;
717 		case '4':
718 			arcname = DEV_4;
719 			break;
720 		case '5':
721 			arcname = DEV_5;
722 			break;
723 		case '7':
724 			arcname = DEV_7;
725 			break;
726 		case '8':
727 			arcname = DEV_8;
728 			break;
729 		default:
730 			tar_usage();
731 			break;
732 		}
733 	}
734 	argc -= optind;
735 	argv += optind;
736 
737 	/*
738 	 * if we are writing (ARCHIVE) specify tar, otherwise run like pax
739 	 */
740 	if (act == ARCHIVE)
741 		frmt = &(fsub[F_TAR]);
742 
743 	/*
744 	 * process the args as they are interpreted by the operation mode
745 	 */
746 	switch (act) {
747 	case LIST:
748 	case EXTRACT:
749 	default:
750 		while (*argv != (char *)NULL)
751 			if (pat_add(*argv++) < 0)
752 				tar_usage();
753 		break;
754 	case ARCHIVE:
755 	case APPND:
756 		while (*argv != (char *)NULL)
757 			if (ftree_add(*argv++) < 0)
758 				tar_usage();
759 		/*
760 		 * no read errors allowed on updates/append operation!
761 		 */
762 		maxflt = 0;
763 		break;
764 	}
765 	if (!fstdin && ((arcname == (char *)NULL) || (*arcname == '\0'))) {
766 		arcname = getenv("TAPE");
767 		if ((arcname == (char *)NULL) || (*arcname == '\0'))
768 			arcname = DEV_8;
769 	}
770 }
771 
772 #ifdef notdef
773 /*
774  * cpio_options()
775  *	look at the user specified flags. set globals as required and check if
776  *	the user specified a legal set of flags. If not, complain and exit
777  */
778 
779 #if __STDC__
780 static void
781 cpio_options(register int argc, register char **argv)
782 #else
783 static void
784 cpio_options(argc, argv)
785 	register int argc;
786 	register char **argv;
787 #endif
788 {
789 }
790 #endif
791 
792 /*
793  * printflg()
794  *	print out those invalid flag sets found to the user
795  */
796 
797 #if __STDC__
798 static void
799 printflg(unsigned int flg)
800 #else
801 static void
802 printflg(flg)
803 	unsigned int flg;
804 #endif
805 {
806 	int nxt;
807 	int pos = 0;
808 
809 	(void)fprintf(stderr,"%s: Invalid combination of options:", argv0);
810 	while (nxt = ffs(flg)) {
811 		flg = flg >> nxt;
812 		pos += nxt;
813 		(void)fprintf(stderr, " -%c", flgch[pos-1]);
814 	}
815 	(void)putc('\n', stderr);
816 }
817 
818 /*
819  * c_frmt()
820  *	comparison routine used by bsearch to find the format specified
821  *	by the user
822  */
823 
824 #if __STDC__
825 static int
826 c_frmt(const void *a, const void *b)
827 #else
828 static int
829 c_frmt(a, b)
830         void *a;
831         void *b;
832 #endif
833 {
834         return(strcmp(((FSUB *)a)->name, ((FSUB *)b)->name));
835 }
836 
837 /*
838  * opt_next()
839  *	called by format specific options routines to get each format specific
840  *	flag and value specified with -o
841  * Return:
842  *	pointer to next OPLIST entry or NULL (end of list).
843  */
844 
845 #if __STDC__
846 OPLIST *
847 opt_next(void)
848 #else
849 OPLIST *
850 opt_next()
851 #endif
852 {
853 	OPLIST *opt;
854 
855 	if ((opt = ophead) != NULL)
856 		ophead = ophead->fow;
857 	return(opt);
858 }
859 
860 /*
861  * bad_opt()
862  *	generic routine used to complain about a format specific options
863  *	when the format does not support options.
864  */
865 
866 #if __STDC__
867 int
868 bad_opt(void)
869 #else
870 int
871 bad_opt()
872 #endif
873 {
874 	register OPLIST *opt;
875 
876 	if (ophead == NULL)
877 		return(0);
878 	/*
879 	 * print all we were given
880 	 */
881 	warn(1,"These format options are not supported");
882 	while ((opt = opt_next()) != NULL)
883 		(void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
884 	pax_usage();
885 	return(0);
886 }
887 
888 /*
889  * opt_add()
890  *	breaks the value supplied to -o into a option name and value. options
891  *	are given to -o in the form -o name-value,name=value
892  *	mulltiple -o may be specified.
893  * Return:
894  *	0 if format in name=value format, -1 if -o is passed junk
895  */
896 
897 #if __STDC__
898 int
899 opt_add(register char *str)
900 #else
901 int
902 opt_add(str)
903 	register char *str;
904 #endif
905 {
906 	register OPLIST *opt;
907 	register char *frpt;
908 	register char *pt;
909 	register char *endpt;
910 
911 	if ((str == NULL) || (*str == '\0')) {
912 		warn(0, "Invalid option name");
913 		return(-1);
914 	}
915 	frpt = endpt = str;
916 
917 	/*
918 	 * break into name and values pieces and stuff each one into a
919 	 * OPLIST structure. When we know the format, the format specific
920 	 * option function will go through this list
921 	 */
922 	while ((frpt != NULL) && (*frpt != '\0')) {
923 		if ((endpt = strchr(frpt, ',')) != NULL)
924 			*endpt = '\0';
925 		if ((pt = strchr(frpt, '=')) == NULL) {
926 			warn(0, "Invalid options format");
927 			return(-1);
928 		}
929 		if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
930 			warn(0, "Unable to allocate space for option list");
931 			return(-1);
932 		}
933 		*pt++ = '\0';
934 		opt->name = frpt;
935 		opt->value = pt;
936 		opt->fow = NULL;
937 		if (endpt != NULL)
938 			frpt = endpt + 1;
939 		else
940 			frpt = NULL;
941 		if (ophead == NULL) {
942 			optail = ophead = opt;
943 			continue;
944 		}
945 		optail->fow = opt;
946 		optail = opt;
947 	}
948 	return(0);
949 }
950 
951 /*
952  * str_offt()
953  *	Convert an expression of the following forms to an off_t > 0.
954  * 	1) A positive decimal number.
955  *	2) A positive decimal number followed by a b (mult by 512).
956  *	3) A positive decimal number followed by a k (mult by 1024).
957  *	4) A positive decimal number followed by a m (mult by 512).
958  *	5) A positive decimal number followed by a w (mult by sizeof int)
959  *	6) Two or more positive decimal numbers (with/without k,b or w).
960  *	   seperated by x (also * for backwards compatibility), specifying
961  *	   the product of the indicated values.
962  * Return:
963  *	0 for an error, a positive value o.w.
964  */
965 
966 #if __STDC__
967 static off_t
968 str_offt(char *val)
969 #else
970 static off_t
971 str_offt(val)
972 	char *val;
973 #endif
974 {
975 	char *expr;
976 	off_t num, t;
977 
978 #	ifdef NET2_STAT
979 	num = strtol(val, &expr, 0);
980 	if ((num == LONG_MAX) || (num <= 0) || (expr == val))
981 #	else
982 	num = strtoq(val, &expr, 0);
983 	if ((num == QUAD_MAX) || (num <= 0) || (expr == val))
984 #	endif
985 		return(0);
986 
987 	switch(*expr) {
988 	case 'b':
989 		t = num;
990 		num *= 512;
991 		if (t > num)
992 			return(0);
993 		++expr;
994 		break;
995 	case 'k':
996 		t = num;
997 		num *= 1024;
998 		if (t > num)
999 			return(0);
1000 		++expr;
1001 		break;
1002 	case 'm':
1003 		t = num;
1004 		num *= 1048576;
1005 		if (t > num)
1006 			return(0);
1007 		++expr;
1008 		break;
1009 	case 'w':
1010 		t = num;
1011 		num *= sizeof(int);
1012 		if (t > num)
1013 			return(0);
1014 		++expr;
1015 		break;
1016 	}
1017 
1018 	switch(*expr) {
1019 		case '\0':
1020 			break;
1021 		case '*':
1022 		case 'x':
1023 			t = num;
1024 			num *= str_offt(expr + 1);
1025 			if (t > num)
1026 				return(0);
1027 			break;
1028 		default:
1029 			return(0);
1030 	}
1031 	return(num);
1032 }
1033 
1034 /*
1035  * no_op()
1036  *	for those option functions where the archive format has nothing to do.
1037  * Return:
1038  *	0
1039  */
1040 
1041 #if __STDC__
1042 static int
1043 no_op(void)
1044 #else
1045 static int
1046 no_op()
1047 #endif
1048 {
1049 	return(0);
1050 }
1051 
1052 /*
1053  * pax_usage()
1054  *	print the usage summary to the user
1055  */
1056 
1057 #if __STDC__
1058 void
1059 pax_usage(void)
1060 #else
1061 void
1062 pax_usage()
1063 #endif
1064 {
1065 	(void)fputs("usage: pax [-cdnv] [-E limit] [-f archive] ", stderr);
1066 	(void)fputs("[-s replstr] ... [-U user] ...", stderr);
1067 	(void)fputs("\n           [-G group] ... ", stderr);
1068 	(void)fputs("[-T [from_date][,to_date]] ... ", stderr);
1069 	(void)fputs("[pattern ...]\n", stderr);
1070 	(void)fputs("       pax -r [-cdiknuvDYZ] [-E limit] ", stderr);
1071 	(void)fputs("[-f archive] [-o options] ... \n", stderr);
1072 	(void)fputs("           [-p string] ... [-s replstr] ... ", stderr);
1073 	(void)fputs("[-U user] ... [-G group] ...\n           ", stderr);
1074 	(void)fputs("[-T [from_date][,to_date]] ... ", stderr);
1075 	(void)fputs(" [pattern ...]\n", stderr);
1076 	(void)fputs("       pax -w [-dituvHLPX] [-b blocksize] ", stderr);
1077 	(void)fputs("[ [-a] [-f archive] ] [-x format] \n", stderr);
1078 	(void)fputs("           [-B bytes] [-s replstr] ... ", stderr);
1079 	(void)fputs("[-o options] ... [-U user] ...", stderr);
1080 	(void)fputs("\n           [-G group] ... ", stderr);
1081 	(void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
1082 	(void)fputs("[file ...]\n", stderr);
1083 	(void)fputs("       pax -r -w [-diklntuvDHLPXYZ] ", stderr);
1084 	(void)fputs("[-p string] ... [-s replstr] ...", stderr);
1085 	(void)fputs("\n           [-U user] ... [-G group] ... ", stderr);
1086 	(void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
1087 	(void)fputs("\n           [file ...] directory\n", stderr);
1088 	exit(1);
1089 }
1090 
1091 /*
1092  * tar_usage()
1093  *	print the usage summary to the user
1094  */
1095 
1096 #if __STDC__
1097 void
1098 tar_usage(void)
1099 #else
1100 void
1101 tar_usage()
1102 #endif
1103 {
1104 	(void)fputs("usage: tar -{txru}[cevfbmopwBHLPX014578] [tapefile] ",
1105 		 stderr);
1106 	(void)fputs("[blocksize] file1 file2...\n", stderr);
1107 	exit(1);
1108 }
1109 
1110 #ifdef notdef
1111 /*
1112  * cpio_usage()
1113  *	print the usage summary to the user
1114  */
1115 
1116 #if __STDC__
1117 void
1118 cpio_usage(void)
1119 #else
1120 void
1121 cpio_usage()
1122 #endif
1123 {
1124 	exit(1);
1125 }
1126 #endif
1127