options.c revision 1.80 1 /* $NetBSD: options.c,v 1.80 2004/10/17 18:49:55 dsl 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. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #if HAVE_NBTOOL_CONFIG_H
37 #include "nbtool_config.h"
38 #endif
39
40 #include <sys/cdefs.h>
41 #if !defined(lint)
42 #if 0
43 static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 4/18/94";
44 #else
45 __RCSID("$NetBSD: options.c,v 1.80 2004/10/17 18:49:55 dsl Exp $");
46 #endif
47 #endif /* not lint */
48
49 #include <sys/types.h>
50 #include <sys/time.h>
51 #include <sys/stat.h>
52 #include <sys/mtio.h>
53 #include <sys/param.h>
54 #include <ctype.h>
55 #include <errno.h>
56 #if HAVE_NBTOOL_CONFIG_H
57 #include "compat_getopt.h"
58 #else
59 #include <getopt.h>
60 #endif
61 #include <limits.h>
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <unistd.h>
66 #include <paths.h>
67 #include "pax.h"
68 #include "options.h"
69 #include "cpio.h"
70 #include "tar.h"
71 #include "extern.h"
72 #ifndef SMALL
73 #include "mtree.h"
74 #endif /* SMALL */
75
76 /*
77 * Routines which handle command line options
78 */
79
80 static int nopids; /* tar mode: suppress "pids" for -p option */
81 static char flgch[] = FLGCH; /* list of all possible flags (pax) */
82 static OPLIST *ophead = NULL; /* head for format specific options -x */
83 static OPLIST *optail = NULL; /* option tail */
84
85 static int no_op(void);
86 static void printflg(unsigned int);
87 static int c_frmt(const void *, const void *);
88 static off_t str_offt(char *);
89 static char *getline(FILE *fp);
90 static void pax_options(int, char **);
91 static void pax_usage(void);
92 static void tar_options(int, char **);
93 static void tar_usage(void);
94 static void cpio_options(int, char **);
95 static void cpio_usage(void);
96
97 /* errors from getline */
98 #define GETLINE_FILE_CORRUPT 1
99 #define GETLINE_OUT_OF_MEM 2
100 static int getline_error;
101
102 #define BZIP2_CMD "bzip2" /* command to run as bzip2 */
103 #define GZIP_CMD "gzip" /* command to run as gzip */
104 #define COMPRESS_CMD "compress" /* command to run as compress */
105
106 /*
107 * Long options.
108 */
109 #define OPT_USE_COMPRESS_PROGRAM 0
110 #define OPT_CHECKPOINT 1
111 #define OPT_UNLINK 2
112 #define OPT_HELP 3
113 #define OPT_ATIME_PRESERVE 4
114 #define OPT_IGNORE_FAILED_READ 5
115 #define OPT_REMOVE_FILES 6
116 #define OPT_NULL 7
117 #define OPT_TOTALS 8
118 #define OPT_VERSION 9
119 #define OPT_EXCLUDE 10
120 #define OPT_BLOCK_COMPRESS 11
121 #define OPT_NORECURSE 12
122 #define OPT_FORCE_LOCAL 13
123 #define OPT_INSECURE 14
124 #define OPT_STRICT 15
125 #define OPT_SPARSE 16
126 #define OPT_CHROOT 17
127
128 /*
129 * Format specific routine table - MUST BE IN SORTED ORDER BY NAME
130 * (see pax.h for description of each function)
131 *
132 * name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
133 * read, end_read, st_write, write, end_write, trail,
134 * subtrail, rd_data, wr_data, options
135 */
136
137 FSUB fsub[] = {
138 /* 0: OLD BINARY CPIO */
139 { "bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
140 bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, NULL,
141 cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
142
143 /* 1: OLD OCTAL CHARACTER CPIO */
144 { "cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
145 cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, NULL,
146 cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
147
148 /* 2: SVR4 HEX CPIO */
149 { "sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd,
150 vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, NULL,
151 cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
152
153 /* 3: SVR4 HEX CPIO WITH CRC */
154 { "sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
155 vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, NULL,
156 cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
157
158 /* 4: OLD TAR */
159 { "tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
160 tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail,
161 NULL, rd_wrfile, wr_rdfile, tar_opt },
162
163 /* 5: POSIX USTAR */
164 { "ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd,
165 ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail,
166 NULL, rd_wrfile, wr_rdfile, bad_opt }
167 };
168 #define F_BCPIO 0 /* old binary cpio format */
169 #define F_CPIO 1 /* old octal character cpio format */
170 #define F_SV4CPIO 2 /* SVR4 hex cpio format */
171 #define F_SV4CRC 3 /* SVR4 hex with crc cpio format */
172 #define F_TAR 4 /* old V7 UNIX tar format */
173 #define F_USTAR 5 /* ustar format */
174 #define DEFLT F_USTAR /* default write format from list above */
175
176 /*
177 * ford is the archive search order used by get_arc() to determine what kind
178 * of archive we are dealing with. This helps to properly id archive formats
179 * some formats may be subsets of others....
180 */
181 int ford[] = {F_USTAR, F_TAR, F_SV4CRC, F_SV4CPIO, F_CPIO, F_BCPIO, -1};
182
183 /*
184 * filename record separator
185 */
186 int sep = '\n';
187
188 /*
189 * options()
190 * figure out if we are pax, tar or cpio. Call the appropriate options
191 * parser
192 */
193
194 void
195 options(int argc, char **argv)
196 {
197
198 /*
199 * Are we acting like pax, tar or cpio (based on argv[0])
200 */
201 if ((argv0 = strrchr(argv[0], '/')) != NULL)
202 argv0++;
203 else
204 argv0 = argv[0];
205
206 if (strcmp(NM_TAR, argv0) == 0)
207 tar_options(argc, argv);
208 else if (strcmp(NM_CPIO, argv0) == 0)
209 cpio_options(argc, argv);
210 else {
211 argv0 = NM_PAX;
212 pax_options(argc, argv);
213 }
214 }
215
216 struct option pax_longopts[] = {
217 { "insecure", no_argument, 0,
218 OPT_INSECURE },
219 { "force-local", no_argument, 0,
220 OPT_FORCE_LOCAL },
221 };
222
223 /*
224 * pax_options()
225 * look at the user specified flags. set globals as required and check if
226 * the user specified a legal set of flags. If not, complain and exit
227 */
228
229 static void
230 pax_options(int argc, char **argv)
231 {
232 int c;
233 int i;
234 unsigned int flg = 0;
235 unsigned int bflg = 0;
236 char *pt;
237 FSUB tmp;
238
239 /*
240 * process option flags
241 */
242 while ((c = getopt_long(argc, argv,
243 "0ab:cdf:ijklno:p:rs:tuvwx:zAB:DE:G:HLMN:OPT:U:XYZ",
244 pax_longopts, NULL)) != -1) {
245 switch (c) {
246 case '0':
247 sep = '\0';
248 break;
249 case 'a':
250 /*
251 * append
252 */
253 flg |= AF;
254 break;
255 case 'b':
256 /*
257 * specify blocksize
258 */
259 flg |= BF;
260 if ((wrblksz = (int)str_offt(optarg)) <= 0) {
261 tty_warn(1, "Invalid block size %s", optarg);
262 pax_usage();
263 }
264 break;
265 case 'c':
266 /*
267 * inverse match on patterns
268 */
269 cflag = 1;
270 flg |= CF;
271 break;
272 case 'd':
273 /*
274 * match only dir on extract, not the subtree at dir
275 */
276 dflag = 1;
277 flg |= DF;
278 break;
279 case 'f':
280 /*
281 * filename where the archive is stored
282 */
283 arcname = optarg;
284 flg |= FF;
285 break;
286 case 'i':
287 /*
288 * interactive file rename
289 */
290 iflag = 1;
291 flg |= IF;
292 break;
293 case 'j':
294 /*
295 * pass through bzip2
296 */
297 jflag = 1;
298 gzip_program = BZIP2_CMD;
299 break;
300 case 'k':
301 /*
302 * do not clobber files that exist
303 */
304 kflag = 1;
305 flg |= KF;
306 break;
307 case 'l':
308 /*
309 * try to link src to dest with copy (-rw)
310 */
311 lflag = 1;
312 flg |= LF;
313 break;
314 case 'n':
315 /*
316 * select first match for a pattern only
317 */
318 nflag = 1;
319 flg |= NF;
320 break;
321 case 'o':
322 /*
323 * pass format specific options
324 */
325 flg |= OF;
326 if (opt_add(optarg) < 0)
327 pax_usage();
328 break;
329 case 'p':
330 /*
331 * specify file characteristic options
332 */
333 for (pt = optarg; *pt != '\0'; ++pt) {
334 switch(*pt) {
335 case 'a':
336 /*
337 * do not preserve access time
338 */
339 patime = 0;
340 break;
341 case 'e':
342 /*
343 * preserve user id, group id, file
344 * mode, access/modification times
345 * and file flags.
346 */
347 pids = 1;
348 pmode = 1;
349 patime = 1;
350 pmtime = 1;
351 pfflags = 1;
352 break;
353 #if 0
354 case 'f':
355 /*
356 * do not preserve file flags
357 */
358 pfflags = 0;
359 break;
360 #endif
361 case 'm':
362 /*
363 * do not preserve modification time
364 */
365 pmtime = 0;
366 break;
367 case 'o':
368 /*
369 * preserve uid/gid
370 */
371 pids = 1;
372 break;
373 case 'p':
374 /*
375 * preserve file mode bits
376 */
377 pmode = 1;
378 break;
379 default:
380 tty_warn(1, "Invalid -p string: %c",
381 *pt);
382 pax_usage();
383 break;
384 }
385 }
386 flg |= PF;
387 break;
388 case 'r':
389 /*
390 * read the archive
391 */
392 flg |= RF;
393 break;
394 case 's':
395 /*
396 * file name substitution name pattern
397 */
398 if (rep_add(optarg) < 0) {
399 pax_usage();
400 break;
401 }
402 flg |= SF;
403 break;
404 case 't':
405 /*
406 * preserve access time on filesystem nodes we read
407 */
408 tflag = 1;
409 flg |= TF;
410 break;
411 case 'u':
412 /*
413 * ignore those older files
414 */
415 uflag = 1;
416 flg |= UF;
417 break;
418 case 'v':
419 /*
420 * verbose operation mode
421 */
422 vflag = 1;
423 flg |= VF;
424 break;
425 case 'w':
426 /*
427 * write an archive
428 */
429 flg |= WF;
430 break;
431 case 'x':
432 /*
433 * specify an archive format on write
434 */
435 tmp.name = optarg;
436 frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
437 sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt);
438 if (frmt != NULL) {
439 flg |= XF;
440 break;
441 }
442 tty_warn(1, "Unknown -x format: %s", optarg);
443 (void)fputs("pax: Known -x formats are:", stderr);
444 for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
445 (void)fprintf(stderr, " %s", fsub[i].name);
446 (void)fputs("\n\n", stderr);
447 pax_usage();
448 break;
449 case 'z':
450 /*
451 * use gzip. Non standard option.
452 */
453 gzip_program = GZIP_CMD;
454 break;
455 case 'A':
456 Aflag = 1;
457 flg |= CAF;
458 break;
459 case 'B':
460 /*
461 * non-standard option on number of bytes written on a
462 * single archive volume.
463 */
464 if ((wrlimit = str_offt(optarg)) <= 0) {
465 tty_warn(1, "Invalid write limit %s", optarg);
466 pax_usage();
467 }
468 if (wrlimit % BLKMULT) {
469 tty_warn(1,
470 "Write limit is not a %d byte multiple",
471 BLKMULT);
472 pax_usage();
473 }
474 flg |= CBF;
475 break;
476 case 'D':
477 /*
478 * On extraction check file inode change time before the
479 * modification of the file name. Non standard option.
480 */
481 Dflag = 1;
482 flg |= CDF;
483 break;
484 case 'E':
485 /*
486 * non-standard limit on read faults
487 * 0 indicates stop after first error, values
488 * indicate a limit, "none" try forever
489 */
490 flg |= CEF;
491 if (strcmp(none, optarg) == 0)
492 maxflt = -1;
493 else if ((maxflt = atoi(optarg)) < 0) {
494 tty_warn(1,
495 "Error count value must be positive");
496 pax_usage();
497 }
498 break;
499 case 'G':
500 /*
501 * non-standard option for selecting files within an
502 * archive by group (gid or name)
503 */
504 if (grp_add(optarg) < 0) {
505 pax_usage();
506 break;
507 }
508 flg |= CGF;
509 break;
510 case 'H':
511 /*
512 * follow command line symlinks only
513 */
514 Hflag = 1;
515 flg |= CHF;
516 break;
517 case 'L':
518 /*
519 * follow symlinks
520 */
521 Lflag = 1;
522 flg |= CLF;
523 break;
524 #ifdef SMALL
525 case 'M':
526 case 'N':
527 tty_warn(1, "Support for -%c is not compiled in", c);
528 exit(1);
529 #else /* !SMALL */
530 case 'M':
531 /*
532 * Treat list of filenames on stdin as an
533 * mtree(8) specfile. Non standard option.
534 */
535 Mflag = 1;
536 flg |= CMF;
537 break;
538 case 'N':
539 /*
540 * Use alternative directory for user db lookups.
541 */
542 if (!setup_getid(optarg)) {
543 tty_warn(1,
544 "Unable to use user and group databases in `%s'",
545 optarg);
546 pax_usage();
547 }
548 break;
549 #endif /* !SMALL */
550 case 'O':
551 /*
552 * Force one volume. Non standard option.
553 */
554 force_one_volume = 1;
555 break;
556 case 'P':
557 /*
558 * do NOT follow symlinks (default)
559 */
560 Lflag = 0;
561 flg |= CPF;
562 break;
563 case 'T':
564 /*
565 * non-standard option for selecting files within an
566 * archive by modification time range (lower,upper)
567 */
568 if (trng_add(optarg) < 0) {
569 pax_usage();
570 break;
571 }
572 flg |= CTF;
573 break;
574 case 'U':
575 /*
576 * non-standard option for selecting files within an
577 * archive by user (uid or name)
578 */
579 if (usr_add(optarg) < 0) {
580 pax_usage();
581 break;
582 }
583 flg |= CUF;
584 break;
585 case 'X':
586 /*
587 * do not pass over mount points in the file system
588 */
589 Xflag = 1;
590 flg |= CXF;
591 break;
592 case 'Y':
593 /*
594 * On extraction check file inode change time after the
595 * modification of the file name. Non standard option.
596 */
597 Yflag = 1;
598 flg |= CYF;
599 break;
600 case 'Z':
601 /*
602 * On extraction check modification time after the
603 * modification of the file name. Non standard option.
604 */
605 Zflag = 1;
606 flg |= CZF;
607 break;
608 case OPT_INSECURE:
609 secure = 0;
610 break;
611 case OPT_FORCE_LOCAL:
612 forcelocal = 0;
613 break;
614 case '?':
615 default:
616 pax_usage();
617 break;
618 }
619 }
620
621 /*
622 * figure out the operation mode of pax read,write,extract,copy,append
623 * or list. check that we have not been given a bogus set of flags
624 * for the operation mode.
625 */
626 if (ISLIST(flg)) {
627 act = LIST;
628 listf = stdout;
629 bflg = flg & BDLIST;
630 } else if (ISEXTRACT(flg)) {
631 act = EXTRACT;
632 bflg = flg & BDEXTR;
633 } else if (ISARCHIVE(flg)) {
634 act = ARCHIVE;
635 bflg = flg & BDARCH;
636 } else if (ISAPPND(flg)) {
637 act = APPND;
638 bflg = flg & BDARCH;
639 } else if (ISCOPY(flg)) {
640 act = COPY;
641 bflg = flg & BDCOPY;
642 } else
643 pax_usage();
644 if (bflg) {
645 printflg(flg);
646 pax_usage();
647 }
648
649 /*
650 * if we are writing (ARCHIVE) we use the default format if the user
651 * did not specify a format. when we write during an APPEND, we will
652 * adopt the format of the existing archive if none was supplied.
653 */
654 if (!(flg & XF) && (act == ARCHIVE))
655 frmt = &(fsub[DEFLT]);
656
657 /*
658 * process the args as they are interpreted by the operation mode
659 */
660 switch (act) {
661 case LIST:
662 case EXTRACT:
663 for (; optind < argc; optind++)
664 if (pat_add(argv[optind], NULL) < 0)
665 pax_usage();
666 break;
667 case COPY:
668 if (optind >= argc) {
669 tty_warn(0, "Destination directory was not supplied");
670 pax_usage();
671 }
672 --argc;
673 dirptr = argv[argc];
674 if (mkpath(dirptr) < 0)
675 pax_usage();
676 /* FALLTHROUGH */
677 case ARCHIVE:
678 case APPND:
679 for (; optind < argc; optind++)
680 if (ftree_add(argv[optind], 0) < 0)
681 pax_usage();
682 /*
683 * no read errors allowed on updates/append operation!
684 */
685 maxflt = 0;
686 break;
687 }
688 }
689
690
691 /*
692 * tar_options()
693 * look at the user specified flags. set globals as required and check if
694 * the user specified a legal set of flags. If not, complain and exit
695 */
696
697 struct option tar_longopts[] = {
698 { "block-size", required_argument, 0, 'b' },
699 { "bunzip2", no_argument, 0, 'j' },
700 { "bzip2", no_argument, 0, 'j' },
701 { "create", no_argument, 0, 'c' }, /* F */
702 /* -e -- no corresponding long option */
703 { "file", required_argument, 0, 'f' },
704 { "dereference", no_argument, 0, 'h' },
705 { "keep-old-files", no_argument, 0, 'k' },
706 { "one-file-system", no_argument, 0, 'l' },
707 { "modification-time", no_argument, 0, 'm' },
708 { "old-archive", no_argument, 0, 'o' },
709 { "portability", no_argument, 0, 'o' },
710 { "same-permissions", no_argument, 0, 'p' },
711 { "preserve-permissions", no_argument, 0, 'p' },
712 { "preserve", no_argument, 0, 'p' },
713 { "fast-read", no_argument, 0, 'q' },
714 { "append", no_argument, 0, 'r' }, /* F */
715 { "update", no_argument, 0, 'u' }, /* F */
716 { "list", no_argument, 0, 't' }, /* F */
717 { "verbose", no_argument, 0, 'v' },
718 { "interactive", no_argument, 0, 'w' },
719 { "confirmation", no_argument, 0, 'w' },
720 { "extract", no_argument, 0, 'x' }, /* F */
721 { "get", no_argument, 0, 'x' }, /* F */
722 { "gzip", no_argument, 0, 'z' },
723 { "gunzip", no_argument, 0, 'z' },
724 { "read-full-blocks", no_argument, 0, 'B' },
725 { "directory", required_argument, 0, 'C' },
726 { "to-stdout", no_argument, 0, 'O' },
727 { "absolute-paths", no_argument, 0, 'P' },
728 { "sparse", no_argument, 0, 'S' },
729 { "files-from", required_argument, 0, 'T' },
730 { "exclude-from", required_argument, 0, 'X' },
731 { "compress", no_argument, 0, 'Z' },
732 { "uncompress", no_argument, 0, 'Z' },
733 { "strict", no_argument, 0,
734 OPT_STRICT },
735 { "atime-preserve", no_argument, 0,
736 OPT_ATIME_PRESERVE },
737 { "unlink", no_argument, 0,
738 OPT_UNLINK },
739 { "use-compress-program", required_argument, 0,
740 OPT_USE_COMPRESS_PROGRAM },
741 { "force-local", no_argument, 0,
742 OPT_FORCE_LOCAL },
743 { "insecure", no_argument, 0,
744 OPT_INSECURE },
745 { "exclude", required_argument, 0,
746 OPT_EXCLUDE },
747 { "chroot", no_argument, 0,
748 OPT_CHROOT },
749 #if 0 /* Not implemented */
750 { "catenate", no_argument, 0, 'A' }, /* F */
751 { "concatenate", no_argument, 0, 'A' }, /* F */
752 { "diff", no_argument, 0, 'd' }, /* F */
753 { "compare", no_argument, 0, 'd' }, /* F */
754 { "checkpoint", no_argument, 0,
755 OPT_CHECKPOINT },
756 { "help", no_argument, 0,
757 OPT_HELP },
758 { "info-script", required_argument, 0, 'F' },
759 { "new-volume-script", required_argument, 0, 'F' },
760 { "incremental", no_argument, 0, 'G' },
761 { "listed-incremental", required_argument, 0, 'g' },
762 { "ignore-zeros", no_argument, 0, 'i' },
763 { "ignore-failed-read", no_argument, 0,
764 OPT_IGNORE_FAILED_READ },
765 { "starting-file", no_argument, 0, 'K' },
766 { "tape-length", required_argument, 0, 'L' },
767 { "multi-volume", no_argument, 0, 'M' },
768 { "after-date", required_argument, 0, 'N' },
769 { "newer", required_argument, 0, 'N' },
770 { "record-number", no_argument, 0, 'R' },
771 { "remove-files", no_argument, 0,
772 OPT_REMOVE_FILES },
773 { "same-order", no_argument, 0, 's' },
774 { "preserve-order", no_argument, 0, 's' },
775 { "null", no_argument, 0,
776 OPT_NULL },
777 { "totals", no_argument, 0,
778 OPT_TOTALS },
779 { "volume-name", required_argument, 0, 'V' },
780 { "label", required_argument, 0, 'V' },
781 { "version", no_argument, 0,
782 OPT_VERSION },
783 { "verify", no_argument, 0, 'W' },
784 { "block-compress", no_argument, 0,
785 OPT_BLOCK_COMPRESS },
786 { "norecurse", no_argument, 0,
787 OPT_NORECURSE },
788 #endif
789 { 0, 0, 0, 0 },
790 };
791
792 static void
793 tar_options(int argc, char **argv)
794 {
795 int c;
796 int fstdin = 0;
797 int Oflag = 0;
798 int nincfiles = 0;
799 int incfiles_max = 0;
800 struct incfile {
801 char *file;
802 char *dir;
803 };
804 struct incfile *incfiles = NULL;
805
806 /*
807 * Set default values.
808 */
809 rmleadslash = 1;
810 is_gnutar = 1;
811
812 /*
813 * process option flags
814 */
815 while ((c = getoldopt(argc, argv,
816 "+b:cef:hjklmopqrs:tuvwxzBC:HI:OPST:X:Z014578",
817 tar_longopts, NULL))
818 != -1) {
819 switch(c) {
820 case 'b':
821 /*
822 * specify blocksize in 512-byte blocks
823 */
824 if ((wrblksz = (int)str_offt(optarg)) <= 0) {
825 tty_warn(1, "Invalid block size %s", optarg);
826 tar_usage();
827 }
828 wrblksz *= 512; /* XXX - check for int oflow */
829 break;
830 case 'c':
831 /*
832 * create an archive
833 */
834 act = ARCHIVE;
835 break;
836 case 'e':
837 /*
838 * stop after first error
839 */
840 maxflt = 0;
841 break;
842 case 'f':
843 /*
844 * filename where the archive is stored
845 */
846 if ((optarg[0] == '-') && (optarg[1]== '\0')) {
847 /*
848 * treat a - as stdin
849 */
850 fstdin = 1;
851 arcname = NULL;
852 break;
853 }
854 fstdin = 0;
855 arcname = optarg;
856 break;
857 case 'h':
858 /*
859 * follow symlinks
860 */
861 Lflag = 1;
862 break;
863 case 'j':
864 /*
865 * pass through bzip2. not a standard option
866 */
867 jflag = 1;
868 gzip_program = BZIP2_CMD;
869 break;
870 case 'k':
871 /*
872 * do not clobber files that exist
873 */
874 kflag = 1;
875 break;
876 case 'l':
877 /*
878 * do not pass over mount points in the file system
879 */
880 Xflag = 1;
881 break;
882 case 'm':
883 /*
884 * do not preserve modification time
885 */
886 pmtime = 0;
887 break;
888 case 'o':
889 /*
890 * This option does several things based on whether
891 * this is a create or extract operation.
892 */
893 if (act == ARCHIVE) {
894 /* GNU tar: write V7 format archives. */
895 Oflag = 1;
896 /* 4.2BSD: don't add directory entries. */
897 if (opt_add("write_opt=nodir") < 0)
898 tar_usage();
899
900 } else {
901 /* SUS: don't preserve owner/group. */
902 pids = 0;
903 nopids = 1;
904 }
905 break;
906 case 'O':
907 Oflag = 1;
908 break;
909 case 'p':
910 /*
911 * preserve user id, group id, file
912 * mode, access/modification times
913 */
914 if (!nopids)
915 pids = 1;
916 pmode = 1;
917 patime = 1;
918 pmtime = 1;
919 break;
920 case 'q':
921 /*
922 * select first match for a pattern only
923 */
924 nflag = 1;
925 break;
926 case 'r':
927 case 'u':
928 /*
929 * append to the archive
930 */
931 act = APPND;
932 break;
933 case 's':
934 /*
935 * file name substitution name pattern
936 */
937 if (rep_add(optarg) < 0) {
938 tar_usage();
939 break;
940 }
941 break;
942 case 't':
943 /*
944 * list contents of the tape
945 */
946 act = LIST;
947 break;
948 case 'v':
949 /*
950 * verbose operation mode
951 */
952 vflag = 1;
953 break;
954 case 'w':
955 /*
956 * interactive file rename
957 */
958 iflag = 1;
959 break;
960 case 'x':
961 /*
962 * extract an archive, preserving mode,
963 * and mtime if possible.
964 */
965 act = EXTRACT;
966 pmtime = 1;
967 break;
968 case 'z':
969 /*
970 * use gzip. Non standard option.
971 */
972 zflag = 1;
973 gzip_program = GZIP_CMD;
974 break;
975 case 'B':
976 /*
977 * Nothing to do here, this is pax default
978 */
979 break;
980 case 'C':
981 chdname = optarg;
982 break;
983 case 'H':
984 /*
985 * follow command line symlinks only
986 */
987 Hflag = 1;
988 break;
989 case 'I':
990 case 'T':
991 if (++nincfiles > incfiles_max) {
992 incfiles_max = nincfiles + 3;
993 incfiles = realloc(incfiles,
994 sizeof(*incfiles) * incfiles_max);
995 if (incfiles == NULL) {
996 tty_warn(0, "Unable to allocate space "
997 "for option list");
998 exit(1);
999 }
1000 }
1001 incfiles[nincfiles - 1].file = optarg;
1002 incfiles[nincfiles - 1].dir = chdname;
1003 break;
1004 case 'P':
1005 /*
1006 * do not remove leading '/' from pathnames
1007 */
1008 rmleadslash = 0;
1009 Aflag = 1;
1010 break;
1011 case 'S':
1012 /* do nothing; we already generate sparse files */
1013 break;
1014 case 'X':
1015 /*
1016 * GNU tar compat: exclude the files listed in optarg
1017 */
1018 if (tar_gnutar_X_compat(optarg) != 0)
1019 tar_usage();
1020 break;
1021 case 'Z':
1022 /*
1023 * use compress.
1024 */
1025 zflag = 1;
1026 gzip_program = COMPRESS_CMD;
1027 break;
1028 case '0':
1029 arcname = DEV_0;
1030 break;
1031 case '1':
1032 arcname = DEV_1;
1033 break;
1034 case '4':
1035 arcname = DEV_4;
1036 break;
1037 case '5':
1038 arcname = DEV_5;
1039 break;
1040 case '7':
1041 arcname = DEV_7;
1042 break;
1043 case '8':
1044 arcname = DEV_8;
1045 break;
1046 case OPT_ATIME_PRESERVE:
1047 patime = 1;
1048 break;
1049 case OPT_UNLINK:
1050 /* Just ignore -- we always unlink first. */
1051 break;
1052 case OPT_USE_COMPRESS_PROGRAM:
1053 zflag = 1;
1054 gzip_program = optarg;
1055 break;
1056 case OPT_FORCE_LOCAL:
1057 forcelocal = 1;
1058 break;
1059 case OPT_INSECURE:
1060 secure = 0;
1061 break;
1062 case OPT_STRICT:
1063 /* disable gnu extensions */
1064 is_gnutar = 0;
1065 break;
1066 case OPT_EXCLUDE:
1067 if (tar_gnutar_minus_minus_exclude(optarg) != 0)
1068 tar_usage();
1069 break;
1070 case OPT_CHROOT:
1071 do_chroot = 1;
1072 break;
1073 default:
1074 tar_usage();
1075 break;
1076 }
1077 }
1078 argc -= optind;
1079 argv += optind;
1080
1081 /* Tar requires an action. */
1082 if (act == ERROR)
1083 tar_usage();
1084
1085 /* Traditional tar behaviour (pax uses stderr unless in list mode) */
1086 if (fstdin == 1 && act == ARCHIVE)
1087 listf = stderr;
1088 else
1089 listf = stdout;
1090
1091 /* Traditional tar behaviour (pax wants to read file list from stdin) */
1092 if ((act == ARCHIVE || act == APPND) && argc == 0 && nincfiles == 0)
1093 exit(0);
1094 /*
1095 * if we are writing (ARCHIVE) specify tar, otherwise run like pax
1096 * (unless -o specified)
1097 */
1098 if (act == ARCHIVE || act == APPND)
1099 frmt = &(fsub[Oflag ? F_TAR : F_USTAR]);
1100 else if (Oflag) {
1101 if (act == EXTRACT)
1102 to_stdout = 1;
1103 else {
1104 tty_warn(1, "The -O/-o options are only valid when "
1105 "writing or extracting an archive");
1106 tar_usage();
1107 }
1108 }
1109
1110 /*
1111 * process the args as they are interpreted by the operation mode
1112 */
1113 switch (act) {
1114 case LIST:
1115 case EXTRACT:
1116 default:
1117 {
1118 int sawpat = 0;
1119 int dirisnext = 0;
1120 char *file, *dir;
1121
1122 while (nincfiles || *argv != NULL) {
1123 /*
1124 * If we queued up any include files,
1125 * pull them in now. Otherwise, check
1126 * for -I and -C positional flags.
1127 * Anything else must be a file to
1128 * extract.
1129 */
1130 if (nincfiles) {
1131 file = incfiles->file;
1132 dir = incfiles->dir;
1133 incfiles++;
1134 nincfiles--;
1135 } else if (strcmp(*argv, "-I") == 0) {
1136 if (*++argv == NULL)
1137 break;
1138 file = *argv++;
1139 dir = chdname;
1140 } else
1141 file = NULL;
1142 if (file != NULL) {
1143 FILE *fp;
1144 char *str;
1145
1146 if (strcmp(file, "-") == 0)
1147 fp = stdin;
1148 else if ((fp = fopen(file, "r")) == NULL) {
1149 tty_warn(1, "Unable to open file '%s' for read", file);
1150 tar_usage();
1151 }
1152 while ((str = getline(fp)) != NULL) {
1153 if (dirisnext) {
1154 dir = str;
1155 dirisnext = 0;
1156 continue;
1157 }
1158 if (strcmp(str, "-C") == 0) {
1159 dirisnext = 1;
1160 continue;
1161 }
1162 if (strncmp(str, "-C ", 3) == 0) {
1163 dir = str + 3;
1164 continue;
1165 }
1166 if (pat_add(str, dir) < 0)
1167 tar_usage();
1168 sawpat = 1;
1169 }
1170 /* Bomb if given -C w/out a dir. */
1171 if (dirisnext)
1172 tar_usage();
1173 if (strcmp(file, "-") != 0)
1174 fclose(fp);
1175 if (getline_error) {
1176 tty_warn(1, "Problem with file '%s'", file);
1177 tar_usage();
1178 }
1179 } else if (strcmp(*argv, "-C") == 0) {
1180 if (*++argv == NULL)
1181 break;
1182 chdname = *argv++;
1183 } else if (pat_add(*argv++, chdname) < 0)
1184 tar_usage();
1185 else
1186 sawpat = 1;
1187 }
1188 /*
1189 * if patterns were added, we are doing chdir()
1190 * on a file-by-file basis, else, just one
1191 * global chdir (if any) after opening input.
1192 */
1193 if (sawpat > 0)
1194 chdname = NULL;
1195 }
1196 break;
1197 case ARCHIVE:
1198 case APPND:
1199 if (chdname != NULL) { /* initial chdir() */
1200 if (ftree_add(chdname, 1) < 0)
1201 tar_usage();
1202 }
1203
1204 while (nincfiles || *argv != NULL) {
1205 char *file, *dir;
1206
1207 /*
1208 * If we queued up any include files, pull them in
1209 * now. Otherwise, check for -I and -C positional
1210 * flags. Anything else must be a file to include
1211 * in the archive.
1212 */
1213 if (nincfiles) {
1214 file = incfiles->file;
1215 dir = incfiles->dir;
1216 incfiles++;
1217 nincfiles--;
1218 } else if (strcmp(*argv, "-I") == 0) {
1219 if (*++argv == NULL)
1220 break;
1221 file = *argv++;
1222 dir = NULL;
1223 } else
1224 file = NULL;
1225 if (file != NULL) {
1226 FILE *fp;
1227 char *str;
1228 int dirisnext = 0;
1229
1230 /* Set directory if needed */
1231 if (dir) {
1232 if (ftree_add(dir, 1) < 0)
1233 tar_usage();
1234 }
1235
1236 if (strcmp(file, "-") == 0)
1237 fp = stdin;
1238 else if ((fp = fopen(file, "r")) == NULL) {
1239 tty_warn(1, "Unable to open file '%s' for read", file);
1240 tar_usage();
1241 }
1242 while ((str = getline(fp)) != NULL) {
1243 if (dirisnext) {
1244 if (ftree_add(str, 1) < 0)
1245 tar_usage();
1246 dirisnext = 0;
1247 continue;
1248 }
1249 if (strcmp(str, "-C") == 0) {
1250 dirisnext = 1;
1251 continue;
1252 }
1253 if (strncmp(str, "-C ", 3) == 0) {
1254 if (ftree_add(str + 3, 1) < 0)
1255 tar_usage();
1256 continue;
1257 }
1258 if (ftree_add(str, 0) < 0)
1259 tar_usage();
1260 }
1261 /* Bomb if given -C w/out a dir. */
1262 if (dirisnext)
1263 tar_usage();
1264 if (strcmp(file, "-") != 0)
1265 fclose(fp);
1266 if (getline_error) {
1267 tty_warn(1, "Problem with file '%s'",
1268 file);
1269 tar_usage();
1270 }
1271 } else if (strcmp(*argv, "-C") == 0) {
1272 if (*++argv == NULL)
1273 break;
1274 if (ftree_add(*argv++, 1) < 0)
1275 tar_usage();
1276 } else if (ftree_add(*argv++, 0) < 0)
1277 tar_usage();
1278 }
1279 /*
1280 * no read errors allowed on updates/append operation!
1281 */
1282 maxflt = 0;
1283 break;
1284 }
1285 if (!fstdin && ((arcname == (char *)NULL) || (*arcname == '\0'))) {
1286 arcname = getenv("TAPE");
1287 if ((arcname == NULL) || (*arcname == '\0'))
1288 arcname = _PATH_DEFTAPE;
1289 }
1290 }
1291
1292 int
1293 mkpath(path)
1294 char *path;
1295 {
1296 struct stat sb;
1297 char *slash;
1298 int done = 0;
1299
1300 slash = path;
1301
1302 while (!done) {
1303 slash += strspn(slash, "/");
1304 slash += strcspn(slash, "/");
1305
1306 done = (*slash == '\0');
1307 *slash = '\0';
1308
1309 if (stat(path, &sb)) {
1310 if (errno != ENOENT || mkdir(path, 0777)) {
1311 tty_warn(1, "%s", path);
1312 return (-1);
1313 }
1314 } else if (!S_ISDIR(sb.st_mode)) {
1315 syswarn(1, ENOTDIR, "%s", path);
1316 return (-1);
1317 }
1318
1319 if (!done)
1320 *slash = '/';
1321 }
1322
1323 return (0);
1324 }
1325
1326
1327 struct option cpio_longopts[] = {
1328 { "reset-access-time", no_argument, 0, 'a' },
1329 { "make-directories", no_argument, 0, 'd' },
1330 { "nonmatching", no_argument, 0, 'f' },
1331 { "extract", no_argument, 0, 'i' },
1332 { "link", no_argument, 0, 'l' },
1333 { "preserve-modification-time", no_argument, 0, 'm' },
1334 { "create", no_argument, 0, 'o' },
1335 { "pass-through", no_argument, 0, 'p' },
1336 { "rename", no_argument, 0, 'r' },
1337 { "list", no_argument, 0, 't' },
1338 { "unconditional", no_argument, 0, 'u' },
1339 { "verbose", no_argument, 0, 'v' },
1340 { "append", no_argument, 0, 'A' },
1341 { "pattern-file", required_argument, 0, 'E' },
1342 { "file", required_argument, 0, 'F' },
1343 { "force-local", no_argument, 0,
1344 OPT_FORCE_LOCAL },
1345 { "format", required_argument, 0, 'H' },
1346 { "dereference", no_argument, 0, 'L' },
1347 { "swap-halfwords", no_argument, 0, 'S' },
1348 { "insecure", no_argument, 0,
1349 OPT_INSECURE },
1350 { "sparse", no_argument, 0,
1351 OPT_SPARSE },
1352
1353 #ifdef notyet
1354 /* Not implemented */
1355 { "null", no_argument, 0, '0' },
1356 { "swap", no_argument, 0, 'b' },
1357 { "numeric-uid-gid", no_argument, 0, 'n' },
1358 { "swap-bytes", no_argument, 0, 's' },
1359 { "message", required_argument, 0, 'M' },
1360 { "owner", required_argument, 0 'R' },
1361 { "dot", no_argument, 0, 'V' },
1362 { "block-size", required_argument, 0,
1363 OPT_BLOCK_SIZE },
1364 { "no-absolute-pathnames", no_argument, 0,
1365 OPT_NO_ABSOLUTE_PATHNAMES },
1366 { "no-preserve-owner", no_argument, 0,
1367 OPT_NO_PRESERVE_OWNER },
1368 { "only-verify-crc", no_argument, 0,
1369 OPT_ONLY_VERIFY_CRC },
1370 { "rsh-command", required_argument, 0,
1371 OPT_RSH_COMMAND },
1372 { "version", no_argument, 0,
1373 OPT_VERSION },
1374 #endif
1375 };
1376
1377 /*
1378 * cpio_options()
1379 * look at the user specified flags. set globals as required and check if
1380 * the user specified a legal set of flags. If not, complain and exit
1381 */
1382
1383 static void
1384 cpio_options(int argc, char **argv)
1385 {
1386 FSUB tmp;
1387 unsigned int flg = 0;
1388 unsigned int bflg = 0;
1389 int c, i;
1390 FILE *fp;
1391 char *str;
1392
1393 uflag = 1;
1394 kflag = 1;
1395 pids = 1;
1396 pmode = 1;
1397 pmtime = 0;
1398 arcname = NULL;
1399 dflag = 1;
1400 nodirs = 1;
1401 /*
1402 * process option flags
1403 */
1404 while ((c = getoldopt(argc, argv,
1405 "+abcdfiklmoprstuvzABC:E:F:H:I:LM:O:R:SVZ6",
1406 cpio_longopts, NULL)) != -1) {
1407 switch(c) {
1408 case 'a':
1409 /*
1410 * preserve access time on filesystem nodes we read
1411 */
1412 tflag = 1;
1413 flg |= TF;
1414 break;
1415 #ifdef notyet
1416 case 'b':
1417 /*
1418 * swap bytes and half-words when reading data
1419 */
1420 break;
1421 #endif
1422 case 'c':
1423 /*
1424 * ASCII cpio header
1425 */
1426 frmt = &fsub[F_SV4CPIO];
1427 break;
1428 case 'd':
1429 /*
1430 * create directories as needed
1431 * pax does this by default ..
1432 */
1433 nodirs = 0;
1434 flg |= RF;
1435 break;
1436 case 'f':
1437 /*
1438 * inverse match on patterns
1439 */
1440 cflag = 1;
1441 flg |= CF;
1442 break;
1443 case 'i':
1444 /*
1445 * read the archive
1446 */
1447 act = EXTRACT;
1448 flg |= RF;
1449 break;
1450 #ifdef notyet
1451 case 'k':
1452 break;
1453 #endif
1454 case 'l':
1455 /*
1456 * try to link src to dest with copy (-rw)
1457 */
1458 lflag = 1;
1459 flg |= LF;
1460 break;
1461 case 'm':
1462 /*
1463 * preserve mtime
1464 */
1465 flg |= PF;
1466 pmtime = 1;
1467 break;
1468 case 'o':
1469 /*
1470 * write an archive
1471 */
1472 act = ARCHIVE;
1473 frmt = &(fsub[F_SV4CRC]);
1474 flg |= WF;
1475 break;
1476 case 'p':
1477 /*
1478 * cpio -p is like pax -rw
1479 */
1480 act = COPY;
1481 flg |= RF | WF;
1482 break;
1483 case 'r':
1484 /*
1485 * interactive file rename
1486 */
1487 iflag = 1;
1488 flg |= IF;
1489 break;
1490 #ifdef notyet
1491 case 's':
1492 /*
1493 * swap bytes after reading data
1494 */
1495 break;
1496 #endif
1497 case 't':
1498 /*
1499 * list contents of archive
1500 */
1501 act = LIST;
1502 listf = stdout;
1503 break;
1504 case 'u':
1505 /*
1506 * don't ignore those older files
1507 */
1508 uflag = 0;
1509 kflag = 0;
1510 flg |= UF;
1511 break;
1512 case 'v':
1513 /*
1514 * verbose operation mode
1515 */
1516 vflag = 1;
1517 flg |= VF;
1518 break;
1519 case 'z':
1520 /*
1521 * use gzip. Non standard option.
1522 */
1523 gzip_program = GZIP_CMD;
1524 break;
1525 case 'A':
1526 /*
1527 * append to an archive
1528 */
1529 act = APPND;
1530 flg |= AF;
1531 break;
1532 case 'B':
1533 /*
1534 * set blocksize to 5120
1535 */
1536 blksz = 5120;
1537 break;
1538 case 'C':
1539 /*
1540 * specify blocksize
1541 */
1542 if ((blksz = (int)str_offt(optarg)) <= 0) {
1543 tty_warn(1, "Invalid block size %s", optarg);
1544 cpio_usage();
1545 }
1546 break;
1547 case 'E':
1548 /*
1549 * file with patterns to extract or list
1550 */
1551 if ((fp = fopen(optarg, "r")) == NULL) {
1552 tty_warn(1, "Unable to open file '%s' for read",
1553 optarg);
1554 cpio_usage();
1555 }
1556 while ((str = getline(fp)) != NULL) {
1557 pat_add(str, NULL);
1558 }
1559 fclose(fp);
1560 if (getline_error) {
1561 tty_warn(1, "Problem with file '%s'", optarg);
1562 cpio_usage();
1563 }
1564 break;
1565 case 'H':
1566 /*
1567 * specify an archive format on write
1568 */
1569 tmp.name = optarg;
1570 frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
1571 sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt);
1572 if (frmt != NULL) {
1573 flg |= XF;
1574 break;
1575 }
1576 tty_warn(1, "Unknown -H format: %s", optarg);
1577 (void)fputs("cpio: Known -H formats are:", stderr);
1578 for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
1579 (void)fprintf(stderr, " %s", fsub[i].name);
1580 (void)fputs("\n\n", stderr);
1581 cpio_usage();
1582 break;
1583 case 'I':
1584 case 'O':
1585 /*
1586 * filename where the archive is stored
1587 */
1588 if ((optarg[0] == '-') && (optarg[1]== '\0')) {
1589 /*
1590 * treat a - as stdin
1591 */
1592 arcname = NULL;
1593 break;
1594 }
1595 arcname = optarg;
1596 break;
1597 case 'L':
1598 /*
1599 * follow symlinks
1600 */
1601 Lflag = 1;
1602 flg |= CLF;
1603 break;
1604 #ifdef notyet
1605 case 'M':
1606 arg = optarg;
1607 break;
1608 case 'R':
1609 arg = optarg;
1610 break;
1611 #endif
1612 case 'S':
1613 /*
1614 * swap halfwords after reading data
1615 */
1616 cpio_swp_head = 1;
1617 break;
1618 #ifdef notyet
1619 case 'V':
1620 break;
1621 #endif
1622 case 'Z':
1623 /*
1624 * use compress. Non standard option.
1625 */
1626 gzip_program = COMPRESS_CMD;
1627 break;
1628 case '6':
1629 /*
1630 * process Version 6 cpio format
1631 */
1632 frmt = &(fsub[F_BCPIO]);
1633 case OPT_FORCE_LOCAL:
1634 forcelocal = 1;
1635 break;
1636 case OPT_INSECURE:
1637 secure = 0;
1638 break;
1639
1640 case OPT_SPARSE:
1641 /* do nothing; we already generate sparse files */
1642 break;
1643 default:
1644 cpio_usage();
1645 break;
1646 }
1647 }
1648
1649 /*
1650 * figure out the operation mode of cpio. check that we have not been
1651 * given a bogus set of flags for the operation mode.
1652 */
1653 if (ISLIST(flg)) {
1654 act = LIST;
1655 bflg = flg & BDLIST;
1656 } else if (ISEXTRACT(flg)) {
1657 act = EXTRACT;
1658 bflg = flg & BDEXTR;
1659 } else if (ISARCHIVE(flg)) {
1660 act = ARCHIVE;
1661 bflg = flg & BDARCH;
1662 } else if (ISAPPND(flg)) {
1663 act = APPND;
1664 bflg = flg & BDARCH;
1665 } else if (ISCOPY(flg)) {
1666 act = COPY;
1667 bflg = flg & BDCOPY;
1668 } else
1669 cpio_usage();
1670 if (bflg) {
1671 cpio_usage();
1672 }
1673
1674 /*
1675 * if we are writing (ARCHIVE) we use the default format if the user
1676 * did not specify a format. when we write during an APPEND, we will
1677 * adopt the format of the existing archive if none was supplied.
1678 */
1679 if (!(flg & XF) && (act == ARCHIVE))
1680 frmt = &(fsub[F_BCPIO]);
1681
1682 /*
1683 * process the args as they are interpreted by the operation mode
1684 */
1685 switch (act) {
1686 case LIST:
1687 case EXTRACT:
1688 for (; optind < argc; optind++)
1689 if (pat_add(argv[optind], 0) < 0)
1690 cpio_usage();
1691 break;
1692 case COPY:
1693 if (optind >= argc) {
1694 tty_warn(0, "Destination directory was not supplied");
1695 cpio_usage();
1696 }
1697 --argc;
1698 dirptr = argv[argc];
1699 /* FALLTHROUGH */
1700 case ARCHIVE:
1701 case APPND:
1702 if (argc != optind) {
1703 for (; optind < argc; optind++)
1704 if (ftree_add(argv[optind], 0) < 0)
1705 cpio_usage();
1706 break;
1707 }
1708 /*
1709 * no read errors allowed on updates/append operation!
1710 */
1711 maxflt = 0;
1712 while ((str = getline(stdin)) != NULL) {
1713 ftree_add(str, 0);
1714 }
1715 if (getline_error) {
1716 tty_warn(1, "Problem while reading stdin");
1717 cpio_usage();
1718 }
1719 break;
1720 default:
1721 cpio_usage();
1722 break;
1723 }
1724 }
1725
1726 /*
1727 * printflg()
1728 * print out those invalid flag sets found to the user
1729 */
1730
1731 static void
1732 printflg(unsigned int flg)
1733 {
1734 int nxt;
1735
1736 (void)fprintf(stderr,"%s: Invalid combination of options:", argv0);
1737 while ((nxt = ffs(flg)) != 0) {
1738 flg &= ~(1 << (nxt - 1));
1739 (void)fprintf(stderr, " -%c", flgch[nxt - 1]);
1740 }
1741 (void)putc('\n', stderr);
1742 }
1743
1744 /*
1745 * c_frmt()
1746 * comparison routine used by bsearch to find the format specified
1747 * by the user
1748 */
1749
1750 static int
1751 c_frmt(const void *a, const void *b)
1752 {
1753 return(strcmp(((const FSUB *)a)->name, ((const FSUB *)b)->name));
1754 }
1755
1756 /*
1757 * opt_next()
1758 * called by format specific options routines to get each format specific
1759 * flag and value specified with -o
1760 * Return:
1761 * pointer to next OPLIST entry or NULL (end of list).
1762 */
1763
1764 OPLIST *
1765 opt_next(void)
1766 {
1767 OPLIST *opt;
1768
1769 if ((opt = ophead) != NULL)
1770 ophead = ophead->fow;
1771 return(opt);
1772 }
1773
1774 /*
1775 * bad_opt()
1776 * generic routine used to complain about a format specific options
1777 * when the format does not support options.
1778 */
1779
1780 int
1781 bad_opt(void)
1782 {
1783 OPLIST *opt;
1784
1785 if (ophead == NULL)
1786 return(0);
1787 /*
1788 * print all we were given
1789 */
1790 tty_warn(1," These format options are not supported for %s",
1791 frmt->name);
1792 while ((opt = opt_next()) != NULL)
1793 (void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
1794 if (strcmp(NM_TAR, argv0) == 0)
1795 tar_usage();
1796 else if (strcmp(NM_CPIO, argv0) == 0)
1797 cpio_usage();
1798 else
1799 pax_usage();
1800 return(0);
1801 }
1802
1803 /*
1804 * opt_add()
1805 * breaks the value supplied to -o into a option name and value. options
1806 * are given to -o in the form -o name-value,name=value
1807 * multiple -o may be specified.
1808 * Return:
1809 * 0 if format in name=value format, -1 if -o is passed junk
1810 */
1811
1812 int
1813 opt_add(const char *str)
1814 {
1815 OPLIST *opt;
1816 char *frpt;
1817 char *pt;
1818 char *endpt;
1819 char *dstr;
1820
1821 if ((str == NULL) || (*str == '\0')) {
1822 tty_warn(0, "Invalid option name");
1823 return(-1);
1824 }
1825 if ((dstr = strdup(str)) == NULL) {
1826 tty_warn(0, "Unable to allocate space for option list");
1827 return(-1);
1828 }
1829 frpt = endpt = dstr;
1830
1831 /*
1832 * break into name and values pieces and stuff each one into a
1833 * OPLIST structure. When we know the format, the format specific
1834 * option function will go through this list
1835 */
1836 while ((frpt != NULL) && (*frpt != '\0')) {
1837 if ((endpt = strchr(frpt, ',')) != NULL)
1838 *endpt = '\0';
1839 if ((pt = strchr(frpt, '=')) == NULL) {
1840 tty_warn(0, "Invalid options format");
1841 free(dstr);
1842 return(-1);
1843 }
1844 if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
1845 tty_warn(0, "Unable to allocate space for option list");
1846 free(dstr);
1847 return(-1);
1848 }
1849 *pt++ = '\0';
1850 opt->name = frpt;
1851 opt->value = pt;
1852 opt->fow = NULL;
1853 if (endpt != NULL)
1854 frpt = endpt + 1;
1855 else
1856 frpt = NULL;
1857 if (ophead == NULL) {
1858 optail = ophead = opt;
1859 continue;
1860 }
1861 optail->fow = opt;
1862 optail = opt;
1863 }
1864 return(0);
1865 }
1866
1867 /*
1868 * str_offt()
1869 * Convert an expression of the following forms to an off_t > 0.
1870 * 1) A positive decimal number.
1871 * 2) A positive decimal number followed by a b (mult by 512).
1872 * 3) A positive decimal number followed by a k (mult by 1024).
1873 * 4) A positive decimal number followed by a m (mult by 512).
1874 * 5) A positive decimal number followed by a w (mult by sizeof int)
1875 * 6) Two or more positive decimal numbers (with/without k,b or w).
1876 * separated by x (also * for backwards compatibility), specifying
1877 * the product of the indicated values.
1878 * Return:
1879 * 0 for an error, a positive value o.w.
1880 */
1881
1882 static off_t
1883 str_offt(char *val)
1884 {
1885 char *expr;
1886 off_t num, t;
1887
1888 num = STRTOOFFT(val, &expr, 0);
1889 if ((num == OFFT_MAX) || (num <= 0) || (expr == val))
1890 return(0);
1891
1892 switch(*expr) {
1893 case 'b':
1894 t = num;
1895 num *= 512;
1896 if (t > num)
1897 return(0);
1898 ++expr;
1899 break;
1900 case 'k':
1901 t = num;
1902 num *= 1024;
1903 if (t > num)
1904 return(0);
1905 ++expr;
1906 break;
1907 case 'm':
1908 t = num;
1909 num *= 1048576;
1910 if (t > num)
1911 return(0);
1912 ++expr;
1913 break;
1914 case 'w':
1915 t = num;
1916 num *= sizeof(int);
1917 if (t > num)
1918 return(0);
1919 ++expr;
1920 break;
1921 }
1922
1923 switch(*expr) {
1924 case '\0':
1925 break;
1926 case '*':
1927 case 'x':
1928 t = num;
1929 num *= str_offt(expr + 1);
1930 if (t > num)
1931 return(0);
1932 break;
1933 default:
1934 return(0);
1935 }
1936 return(num);
1937 }
1938
1939 char *
1940 getline(FILE *f)
1941 {
1942 char *name, *temp;
1943 size_t len;
1944
1945 name = fgetln(f, &len);
1946 if (!name) {
1947 getline_error = ferror(f) ? GETLINE_FILE_CORRUPT : 0;
1948 return(0);
1949 }
1950 if (name[len-1] != '\n')
1951 len++;
1952 temp = malloc(len);
1953 if (!temp) {
1954 getline_error = GETLINE_OUT_OF_MEM;
1955 return(0);
1956 }
1957 memcpy(temp, name, len-1);
1958 temp[len-1] = 0;
1959 return(temp);
1960 }
1961
1962 /*
1963 * no_op()
1964 * for those option functions where the archive format has nothing to do.
1965 * Return:
1966 * 0
1967 */
1968
1969 static int
1970 no_op(void)
1971 {
1972 return(0);
1973 }
1974
1975 /*
1976 * pax_usage()
1977 * print the usage summary to the user
1978 */
1979
1980 void
1981 pax_usage(void)
1982 {
1983 fprintf(stderr,
1984 "usage: pax [-cdjnvzO] [-E limit] [-f archive] [-N dbdir] [-s replstr] ...\n"
1985 " [-U user] ... [-G group] ... [-T [from_date][,to_date]] ...\n"
1986 " [pattern ...]\n");
1987 fprintf(stderr,
1988 " pax -r [-cdijknuvzADOYZ] [-E limit] [-f archive] [-N dbdir]\n"
1989 " [-o options] ... [-p string] ... [-s replstr] ... [-U user] ...\n"
1990 " [-G group] ... [-T [from_date][,to_date]] ... [pattern ...]\n");
1991 fprintf(stderr,
1992 " pax -w [-dijtuvzAHLMOPX] [-b blocksize] [[-a] [-f archive]] [-x format]\n"
1993 " [-B bytes] [-N dbdir] [-o options] ... [-s replstr] ...\n"
1994 " [-U user] ... [-G group] ...\n"
1995 " [-T [from_date][,to_date][/[c][m]]] ... [file ...]\n");
1996 fprintf(stderr,
1997 " pax -r -w [-dijklntuvzADHLMOPXYZ] [-N dbdir] [-p string] ...\n"
1998 " [-s replstr] ... [-U user] ... [-G group] ...\n"
1999 " [-T [from_date][,to_date][/[c][m]]] ... [file ...] directory\n");
2000 exit(1);
2001 /* NOTREACHED */
2002 }
2003
2004 /*
2005 * tar_usage()
2006 * print the usage summary to the user
2007 */
2008
2009 void
2010 tar_usage(void)
2011 {
2012 (void)fputs("usage: tar [-]{crtux}[-befhjlmopqvwzHOPSXZ014578] [archive] "
2013 "[blocksize]\n"
2014 " [-C directory] [-T file] [-s replstr] "
2015 "[file ...]\n", stderr);
2016 exit(1);
2017 /* NOTREACHED */
2018 }
2019
2020 /*
2021 * cpio_usage()
2022 * print the usage summary to the user
2023 */
2024
2025 void
2026 cpio_usage(void)
2027 {
2028
2029 (void)fputs("usage: cpio -o [-aABcLvzZ] [-C bytes] [-F archive] "
2030 "[-H format] [-O archive]\n"
2031 " < name-list [> archive]\n"
2032 " cpio -i [-bBcdfmrsStuvzZ6] [-C bytes] [-E file] "
2033 "[-F archive] [-H format] \n"
2034 " [-I archive] "
2035 "[pattern ...] [< archive]\n"
2036 " cpio -p [-adlLmuv] destination-directory "
2037 "< name-list\n", stderr);
2038 exit(1);
2039 /* NOTREACHED */
2040 }
2041