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