Makefiles don't get copyright notices
[unix-history] / usr / src / bin / pax / options.c
CommitLineData
2f5a0e7a
KM
1/*-
2 * Copyright (c) 1992 Keith Muller.
f547d164
KB
3 * Copyright (c) 1992, 1993
4 * The Regents of the University of California. All rights reserved.
2f5a0e7a
KM
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
f547d164 13static char sccsid[] = "@(#)options.c 8.1 (Berkeley) %G%";
2f5a0e7a
KM
14#endif /* not lint */
15
16#include <sys/types.h>
17#include <sys/time.h>
18#include <sys/stat.h>
19#include <sys/mtio.h>
20#include <sys/param.h>
21#include <stdio.h>
22#include <ctype.h>
23#include <string.h>
24#include <unistd.h>
25#include <stdlib.h>
26#include <limits.h>
27#include "pax.h"
28#include "options.h"
29#include "cpio.h"
30#include "extern.h"
31
32/*
33 * Routines which handle command line options
34 */
35
36static char flgch[] = FLGCH; /* list of all possible flags */
37static OPLIST *ophead = NULL; /* head for format specific options -x */
38static OPLIST *optail = NULL; /* option tail */
39
40static int no_op __P((void));
41static void printflg __P((unsigned int));
42static int c_frmt __P((const void *, const void *));
43static off_t str_offt __P((char *));
44
45/*
46 * Format specific routine table - MUST BE IN SORTED ORDER BY NAME
47 * (see pax.h for description of each function)
48 *
49 * name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
50 * read, end_read, st_write, write, end_write, trail,
51 * rd_data, wr_data, options
52 */
53
54FSUB fsub[] = {
55/* 0: OLD BINARY CPIO */
56 "bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
57 bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, cpio_trail,
58 rd_wrfile, wr_rdfile, bad_opt,
59
60/* 1: OLD OCTAL CHARACTER CPIO */
61 "cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
62 cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, cpio_trail,
63 rd_wrfile, wr_rdfile, bad_opt,
64
65/* 2: SVR4 HEX CPIO */
66 "sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd,
67 vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, cpio_trail,
68 rd_wrfile, wr_rdfile, bad_opt,
69
70/* 3: SVR4 HEX CPIO WITH CRC */
71 "sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
72 vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, cpio_trail,
73 rd_wrfile, wr_rdfile, bad_opt,
74
75/* 4: OLD TAR */
76 "tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
77 tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail,
78 rd_wrfile, wr_rdfile, tar_opt,
79
80/* 5: POSIX USTAR */
81 "ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd,
82 ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail,
83 rd_wrfile, wr_rdfile, bad_opt,
84};
85#define DEFLT 5 /* default write format from list above */
86
87/*
88 * ford is the archive search order used by get_arc() to determine what kind
89 * of archive we are dealing with. This helps to properly id archive formats
90 * some formats may be subsets of others....
91 */
92int ford[] = {5, 4, 3, 2, 1, 0, -1 };
93
94/*
95 * options()
96 * look at the user specified flags. set globals as required and check if
97 * the user specified a legal set of flags. If not, complain and exit
98 */
99
100#if __STDC__
101void
102options(register int argc, register char **argv)
103#else
104void
105options(argc, argv)
106 register int argc;
107 register char **argv;
108#endif
109{
110 register int c;
111 register int i;
112 unsigned int flg = 0;
113 unsigned int bflg = 0;
114 register char *pt;
115 FSUB tmp;
116 extern char *optarg;
117 extern int optind;
118
119 /*
120 * process option flags
121 */
e2e6a850 122 while ((c=getopt(argc,argv,"ab:cdf:iklno:p:rs:tuvwx:B:DE:G:HLT:U:XYZ"))
2f5a0e7a
KM
123 != EOF) {
124 switch (c) {
125 case 'a':
126 /*
127 * append
128 */
129 flg |= AF;
130 break;
131 case 'b':
132 /*
133 * specify blocksize on write
134 */
135 flg |= BF;
136 if ((wrblksz = (int)str_offt(optarg)) <= 0) {
137 warn(1, "Invalid block size %s", optarg);
138 usage();
139 }
140 break;
141 case 'c':
142 /*
143 * inverse match on patterns
144 */
145 cflag = 1;
146 flg |= CF;
147 break;
148 case 'd':
149 /*
150 * match only dir on extract, not the subtree at dir
151 */
152 dflag = 1;
153 flg |= DF;
154 break;
155 case 'f':
156 /*
157 * filename where the archive is stored
158 */
159 arcname = optarg;
160 flg |= FF;
161 break;
162 case 'i':
163 /*
164 * interactive file rename
165 */
166 iflag = 1;
167 flg |= IF;
168 break;
169 case 'k':
170 /*
171 * do not clobber files that exist
172 */
173 kflag = 1;
174 flg |= KF;
175 break;
176 case 'l':
177 /*
178 * try to link src to dest with copy (-rw)
179 */
180 lflag = 1;
181 flg |= LF;
182 break;
183 case 'n':
184 /*
185 * select first match for a pattern only
186 */
187 nflag = 1;
188 flg |= NF;
189 break;
190 case 'o':
191 /*
192 * pass format specific options
193 */
194 flg |= OF;
195 if (opt_add(optarg) < 0)
196 usage();
197 break;
198 case 'p':
199 /*
200 * specify file characteristic options
201 */
202 for (pt = optarg; *pt != '\0'; ++pt) {
203 switch(*pt) {
204 case 'a':
205 /*
206 * do not preserve access time
207 */
208 patime = 0;
209 break;
210 case 'e':
211 /*
212 * preserve user id, group id, file
213 * mode, access/modification times
214 */
215 pids = 1;
216 pmode = 1;
217 patime = 1;
218 pmtime = 1;
219 break;
220 case 'm':
221 /*
222 * do not preserve modification time
223 */
224 pmtime = 0;
225 break;
226 case 'o':
227 /*
228 * preserve uid/gid
229 */
230 pids = 1;
231 break;
232 case 'p':
233 /*
234 * preserver file mode bits
235 */
236 pmode = 1;
237 break;
238 default:
239 warn(1, "Invalid -p string: %c", *pt);
240 usage();
241 break;
242 }
243 }
244 flg |= PF;
245 break;
246 case 'r':
247 /*
248 * read the archive
249 */
250 flg |= RF;
251 break;
252 case 's':
253 /*
254 * file name substitution name pattern
255 */
256 if (rep_add(optarg) < 0) {
257 usage();
258 break;
259 }
260 flg |= SF;
261 break;
262 case 't':
263 /*
264 * preserve access time on filesystem nodes we read
265 */
266 tflag = 1;
267 flg |= TF;
268 break;
269 case 'u':
270 /*
271 * ignore those older files
272 */
273 uflag = 1;
274 flg |= UF;
275 break;
276 case 'v':
277 /*
278 * verbose operation mode
279 */
280 vflag = 1;
281 flg |= VF;
282 break;
283 case 'w':
284 /*
285 * write an archive
286 */
287 flg |= WF;
288 break;
289 case 'x':
290 /*
291 * specify an archive format on write
292 */
293 tmp.name = optarg;
294 if (frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
295 sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) {
296 flg |= XF;
297 break;
298 }
299 warn(1, "Unknown -x format: %s", optarg);
300 (void)fputs("pax: Known -x formats are:", stderr);
301 for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
302 (void)fprintf(stderr, " %s", fsub[i].name);
303 (void)fputs("\n\n", stderr);
304 usage();
305 break;
306 case 'B':
307 /*
308 * non-standard option on number of bytes written on a
309 * single archive volume.
310 */
311 if ((wrlimit = str_offt(optarg)) <= 0) {
312 warn(1, "Invalid write limit %s", optarg);
313 usage();
314 }
315 if (wrlimit % BLKMULT) {
316 warn(1, "Write limit is not a %d byte multiple",
317 BLKMULT);
318 usage();
319 }
320 flg |= CBF;
321 break;
e2e6a850
KM
322 case 'D':
323 /*
324 * On extraction check file inode change time before the
325 * modification of the file name. Non standard option.
326 */
327 Dflag = 1;
328 flg |= CDF;
329 break;
2f5a0e7a
KM
330 case 'E':
331 /*
332 * non-standard limit on read faults
333 * 0 indicates stop after first error, values
334 * indicate a limit, "NONE" try forever
335 */
336 flg |= CEF;
337 if (strcmp(NONE, optarg) == 0)
338 maxflt = -1;
339 else if ((maxflt = atoi(optarg)) < 0) {
340 warn(1, "Error count value must be positive");
341 usage();
342 }
343 break;
344 case 'G':
345 /*
346 * non-standard option for selecting files within an
347 * archive by group (gid or name)
348 */
349 if (grp_add(optarg) < 0) {
350 usage();
351 break;
352 }
353 flg |= CGF;
354 break;
355 case 'H':
356 /*
357 * follow command line symlinks only
358 */
359 Hflag = 1;
360 flg |= CHF;
361 break;
362 case 'L':
363 /*
364 * follow symlinks
365 */
366 Lflag = 1;
367 flg |= CLF;
368 break;
369 case 'T':
370 /*
371 * non-standard option for selecting files within an
372 * archive by modification time range (lower,upper)
373 */
374 if (trng_add(optarg) < 0) {
375 usage();
376 break;
377 }
378 flg |= CTF;
379 break;
380 case 'U':
381 /*
382 * non-standard option for selecting files within an
383 * archive by user (uid or name)
384 */
385 if (usr_add(optarg) < 0) {
386 usage();
387 break;
388 }
389 flg |= CUF;
390 break;
391 case 'X':
392 /*
393 * do not pass over mount points in the file system
394 */
395 Xflag = 1;
396 flg |= CXF;
397 break;
e2e6a850
KM
398 case 'Y':
399 /*
400 * On extraction check file inode change time after the
401 * modification of the file name. Non standard option.
402 */
403 Yflag = 1;
404 flg |= CYF;
405 break;
2f5a0e7a
KM
406 case 'Z':
407 /*
e2e6a850
KM
408 * On extraction check modification time after the
409 * modification of the file name. Non standard option.
2f5a0e7a
KM
410 */
411 Zflag = 1;
412 flg |= CZF;
413 break;
414 case '?':
415 default:
416 usage();
417 break;
418 }
419 }
420
421 /*
422 * figure out the operation mode of pax read,write,extract,copy,append
423 * or list. check that we have not been given a bogus set of flags
424 * for the operation mode.
425 */
426 if (ISLIST(flg)) {
427 act = LIST;
428 bflg = flg & BDLIST;
429 } else if (ISEXTRACT(flg)) {
430 act = EXTRACT;
431 bflg = flg & BDEXTR;
432 } else if (ISARCHIVE(flg)) {
433 act = ARCHIVE;
434 bflg = flg & BDARCH;
435 } else if (ISAPPND(flg)) {
436 act = APPND;
437 bflg = flg & BDARCH;
438 } else if (ISCOPY(flg)) {
439 act = COPY;
440 bflg = flg & BDCOPY;
441 } else
442 usage();
443 if (bflg) {
444 printflg(flg);
445 usage();
446 }
447
448 /*
449 * if we are writing (ARCHIVE) we use the default format if the user
450 * did not specify a format. when we write during an APPEND, we will
451 * adopt the format of the existing archive if none was supplied.
452 */
453 if (!(flg & XF) && (act == ARCHIVE))
454 frmt = &(fsub[DEFLT]);
455
456 /*
457 * process the args as they are interpreted by the operation mode
458 */
459 switch (act) {
460 case LIST:
461 case EXTRACT:
462 for (; optind < argc; optind++)
463 if (pat_add(argv[optind]) < 0)
464 usage();
465 break;
466 case COPY:
467 if (optind >= argc) {
468 warn(0, "Destination directory was not supplied");
469 usage();
470 }
471 --argc;
472 dirptr = argv[argc];
473 /* FALL THROUGH */
474 case ARCHIVE:
475 case APPND:
476 for (; optind < argc; optind++)
477 if (ftree_add(argv[optind]) < 0)
478 usage();
479 /*
480 * no read errors allowed on updates/append operation!
481 */
482 maxflt = 0;
483 break;
484 }
485}
486
487/*
488 * printflg()
489 * print out those invalid flag sets found to the user
490 */
491
492#if __STDC__
493static void
494printflg(unsigned int flg)
495#else
496static void
497printflg(flg)
498 unsigned int flg;
499#endif
500{
501 int nxt;
502 int pos = 0;
503
504 (void)fputs("pax: Invalid combination of options:", stderr);
505 while (nxt = ffs(flg)) {
506 flg = flg >> nxt;
507 pos += nxt;
508 (void)fprintf(stderr, " -%c", flgch[pos-1]);
509 }
510 (void)putc('\n', stderr);
511}
512
513/*
514 * c_frmt()
515 * comparison routine used by bsearch to find the format specified
516 * by the user
517 */
518
519#if __STDC__
520static int
521c_frmt(const void *a, const void *b)
522#else
523static int
524c_frmt(a, b)
525 void *a;
526 void *b;
527#endif
528{
529 return(strcmp(((FSUB *)a)->name, ((FSUB *)b)->name));
530}
531
532/*
533 * opt_next()
534 * called by format specific options routines to get each format specific
535 * flag and value specified with -o
536 * Return:
537 * pointer to next OPLIST entry or NULL (end of list).
538 */
539
540#if __STDC__
541OPLIST *
542opt_next(void)
543#else
544OPLIST *
545opt_next()
546#endif
547{
548 OPLIST *opt;
549
550 if ((opt = ophead) != NULL)
551 ophead = ophead->fow;
552 return(opt);
553}
554
555/*
556 * bad_opt()
557 * generic routine used to complain about a format specific options
558 * when the format does not support options.
559 */
560
561#if __STDC__
562int
563bad_opt(void)
564#else
565int
566bad_opt()
567#endif
568{
569 register OPLIST *opt;
570
571 if (ophead == NULL)
572 return(0);
573 /*
574 * print all we were given
575 */
576 warn(1,"These format options are not supported");
577 while ((opt = opt_next()) != NULL)
578 (void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
579 usage();
580 return(0);
581}
582
583/*
584 * opt_add()
585 * breaks the value supplied to -o into a option name and value. options
586 * are given to -o in the form -o name-value,name=value
587 * mulltiple -o may be specified.
588 * Return:
589 * 0 if format in name=value format, -1 if -o is passed junk
590 */
591
592#if __STDC__
593int
594opt_add(register char *str)
595#else
596int
597opt_add(str)
598 register char *str;
599#endif
600{
601 register OPLIST *opt;
602 register char *frpt;
603 register char *pt;
604 register char *endpt;
605
606 if ((str == NULL) || (*str == '\0')) {
607 warn(0, "Invalid option name");
608 return(-1);
609 }
610 frpt = endpt = str;
611
612 /*
613 * break into name and values pieces and stuff each one into a
614 * OPLIST structure. When we know the format, the format specific
615 * option function will go through this list
616 */
617 while ((frpt != NULL) && (*frpt != '\0')) {
618 if ((endpt = strchr(frpt, ',')) != NULL)
619 *endpt = '\0';
620 if ((pt = strchr(frpt, '=')) == NULL) {
621 warn(0, "Invalid options format");
622 return(-1);
623 }
624 if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
625 warn(0, "Unable to allocate space for option list");
626 return(-1);
627 }
628 *pt++ = '\0';
629 opt->name = frpt;
630 opt->value = pt;
631 opt->fow = NULL;
632 if (endpt != NULL)
633 frpt = endpt + 1;
634 else
635 frpt = NULL;
636 if (ophead == NULL) {
637 optail = ophead = opt;
638 continue;
639 }
640 optail->fow = opt;
641 optail = opt;
642 }
643 return(0);
644}
645
646/*
647 * str_offt()
648 * Convert an expression of the following forms to an off_t > 0.
649 * 1) A positive decimal number.
650 * 2) A positive decimal number followed by a b (mult by 512).
651 * 3) A positive decimal number followed by a k (mult by 1024).
652 * 4) A positive decimal number followed by a m (mult by 512).
653 * 5) A positive decimal number followed by a w (mult by sizeof int)
654 * 6) Two or more positive decimal numbers (with/without k,b or w).
655 * seperated by x (also * for backwards compatibility), specifying
656 * the product of the indicated values.
657 * Return:
658 * 0 for an error, a positive value o.w.
659 */
660
661#if __STDC__
662static off_t
663str_offt(char *val)
664#else
665static off_t
666str_offt(val)
667 char *val;
668#endif
669{
670 char *expr;
671 off_t num, t;
672
673# ifdef NET2_STAT
674 num = strtol(val, &expr, 0);
675 if ((num == LONG_MAX) || (num <= 0) || (expr == val))
676# else
677 num = strtoq(val, &expr, 0);
678 if ((num == QUAD_MAX) || (num <= 0) || (expr == val))
679# endif
680 return(0);
681
682 switch(*expr) {
683 case 'b':
684 t = num;
685 num *= 512;
686 if (t > num)
687 return(0);
688 ++expr;
689 break;
690 case 'k':
691 t = num;
692 num *= 1024;
693 if (t > num)
694 return(0);
695 ++expr;
696 break;
697 case 'm':
698 t = num;
699 num *= 1048576;
700 if (t > num)
701 return(0);
702 ++expr;
703 break;
704 case 'w':
705 t = num;
706 num *= sizeof(int);
707 if (t > num)
708 return(0);
709 ++expr;
710 break;
711 }
712
713 switch(*expr) {
714 case '\0':
715 break;
716 case '*':
717 case 'x':
718 t = num;
719 num *= str_offt(expr + 1);
720 if (t > num)
721 return(0);
722 break;
723 default:
724 return(0);
725 }
726 return(num);
727}
728
729/*
730 * no_op()
731 * for those option functions where the archive format has nothing to do.
732 * Return:
733 * 0
734 */
735
736#if __STDC__
737static int
738no_op(void)
739#else
740static int
741no_op()
742#endif
743{
744 return(0);
745}