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