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