source: freewrt/tools/paxmirabilis/src/options.c@ fdd4f59

freewrt_1_0 freewrt_2_0
Last change on this file since fdd4f59 was 9ec66c9, checked in by Thorsten Glaser <tg@…>, 19 years ago

sync with upstream after feeding the patches back

git-svn-id: svn://www.freewrt.org/trunk/freewrt@225 afb5a338-a214-0410-bd46-81f09a774fd1

  • Property mode set to 100644
File size: 35.2 KB
Line 
1/** $MirOS: src/bin/pax/options.c,v 1.19 2006/07/16 17:58:39 tg Exp $ */
2/* $OpenBSD: options.c,v 1.64 2006/04/09 03:35:34 jaredy Exp $ */
3/* $NetBSD: options.c,v 1.6 1996/03/26 23:54:18 mrg Exp $ */
4
5/*-
6 * Copyright (c) 2005, 2006 Thorsten Glaser <tg@66h.42h.de>
7 * Copyright (c) 1992 Keith Muller.
8 * Copyright (c) 1992, 1993
9 * The Regents of the University of California. All rights reserved.
10 *
11 * This code is derived from software contributed to Berkeley by
12 * Keith Muller of the University of California, San Diego.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39#include <sys/param.h>
40#include <sys/time.h>
41#include <sys/stat.h>
42#ifndef __INTERIX
43#include <sys/mtio.h>
44#endif
45#include <stdio.h>
46#include <string.h>
47#include <err.h>
48#include <errno.h>
49#include <unistd.h>
50#include <stdlib.h>
51#include <limits.h>
52#include <paths.h>
53#include "pax.h"
54#include "options.h"
55#include "cpio.h"
56#include "tar.h"
57#include "extern.h"
58
59__SCCSID("@(#)options.c 8.2 (Berkeley) 4/18/94");
60__RCSID("$MirOS: src/bin/pax/options.c,v 1.19 2006/07/16 17:58:39 tg Exp $");
61
62#ifdef __GLIBC__
63char *fgetln(FILE *, size_t *);
64#endif
65
66/*
67 * Routines which handle command line options
68 */
69
70static char flgch[] = FLGCH; /* list of all possible flags */
71static OPLIST *ophead = NULL; /* head for format specific options -x */
72static OPLIST *optail = NULL; /* option tail */
73
74static int no_op(void);
75static void printflg(unsigned int);
76static int c_frmt(const void *, const void *);
77static off_t str_offt(char *);
78static char *getline(FILE *fp);
79static void pax_options(int, char **);
80static void pax_usage(void);
81static void tar_options(int, char **);
82static void tar_usage(void);
83static void cpio_options(int, char **);
84static void cpio_usage(void);
85int mkpath(char *);
86
87static void process_M(const char *, void (*)(void));
88
89/* errors from getline */
90#define GETLINE_FILE_CORRUPT 1
91#define GETLINE_OUT_OF_MEM 2
92static int getline_error;
93
94
95#define GZIP_CMD "gzip" /* command to run as gzip */
96#define COMPRESS_CMD "compress" /* command to run as compress */
97
98/*
99 * Format specific routine table - MUST BE IN SORTED ORDER BY NAME
100 * (see pax.h for description of each function)
101 *
102 * name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
103 * read, end_read, st_write, write, end_write, trail,
104 * rd_data, wr_data, options
105 */
106
107FSUB fsub[] = {
108/* 0: OLD BINARY CPIO */
109 {"bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
110 bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, cpio_trail,
111 rd_wrfile, wr_rdfile, bad_opt},
112
113/* 1: OLD OCTAL CHARACTER CPIO */
114 {"cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
115 cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, cpio_trail,
116 rd_wrfile, wr_rdfile, bad_opt},
117
118/* 2: OLD OCTAL CHARACTER CPIO, UID/GID CLEARED (ANONYMISED) */
119 {"dist", 512, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
120 cpio_rd, cpio_endrd, dist_stwr, cpio_wr, cpio_endwr, cpio_trail,
121 rd_wrfile, wr_rdfile, bad_opt},
122
123/* 3: SVR4 HEX CPIO */
124 {"sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd,
125 vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, cpio_trail,
126 rd_wrfile, wr_rdfile, bad_opt},
127
128/* 4: SVR4 HEX CPIO WITH CRC */
129 {"sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
130 vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, cpio_trail,
131 rd_wrfile, wr_rdfile, bad_opt},
132
133/* 5: OLD TAR */
134 {"tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
135 tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail,
136 rd_wrfile, wr_rdfile, tar_opt},
137
138/* 6: POSIX USTAR */
139 {"ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd,
140 ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail,
141 rd_wrfile, wr_rdfile, bad_opt},
142
143/* 7: SVR4 HEX CPIO WITH CRC, UID/GID/MTIME CLEARED (NORMALISED) */
144 {"v4norm", 512, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
145 vcpio_rd, vcpio_endrd, v4norm_stwr, vcpio_wr, cpio_endwr, cpio_trail,
146 rd_wrfile, wr_rdfile, bad_opt},
147
148/* 8: SVR4 HEX CPIO WITH CRC, UID/GID CLEARED (ANONYMISED) */
149 {"v4root", 512, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
150 vcpio_rd, vcpio_endrd, v4root_stwr, vcpio_wr, cpio_endwr, cpio_trail,
151 rd_wrfile, wr_rdfile, bad_opt},
152};
153#define F_OCPIO 0 /* format when called as cpio -6 */
154#define F_ACPIO 1 /* format when called as cpio -c */
155#define F_NCPIO 3 /* format when called as tar -R */
156#define F_CPIO 4 /* format when called as cpio or tar -S */
157#define F_OTAR 5 /* format when called as tar -o */
158#define F_TAR 6 /* format when called as tar */
159#define DEFLT 6 /* default write format from list above */
160
161/*
162 * ford is the archive search order used by get_arc() to determine what kind
163 * of archive we are dealing with. This helps to properly id archive formats
164 * some formats may be subsets of others....
165 */
166int ford[] = {6, 5, 4, 3, 1, 0, -1 };
167
168/* normalise archives */
169int anonarch = 0;
170
171/* extract to standard output */
172int to_stdout = 0;
173
174/*
175 * options()
176 * figure out if we are pax, tar or cpio. Call the appropriate options
177 * parser
178 */
179
180void
181options(int argc, char **argv)
182{
183
184 /*
185 * Are we acting like pax, tar or cpio (based on argv[0])
186 */
187 if ((argv0 = strrchr(argv[0], '/')) != NULL)
188 argv0++;
189 else
190 argv0 = argv[0];
191
192 if (strcmp(NM_TAR, argv0) == 0) {
193 tar_options(argc, argv);
194 return;
195 } else if (strcmp(NM_CPIO, argv0) == 0) {
196 cpio_options(argc, argv);
197 return;
198 }
199 /*
200 * assume pax as the default
201 */
202 argv0 = NM_PAX;
203 pax_options(argc, argv);
204}
205
206/*
207 * pax_options()
208 * look at the user specified flags. set globals as required and check if
209 * the user specified a legal set of flags. If not, complain and exit
210 */
211
212static void
213pax_options(int argc, char **argv)
214{
215 int c;
216 int i;
217 unsigned int flg = 0;
218 unsigned int bflg = 0;
219 char *pt;
220 FSUB tmp;
221
222 /*
223 * process option flags
224 */
225 while ((c=getopt(argc,argv,"ab:cdf:iklno:p:rs:tuvwx:zB:DE:G:HLOPT:U:XYZ0"))
226 != -1) {
227 switch (c) {
228 case 'a':
229 /*
230 * append
231 */
232 flg |= AF;
233 break;
234 case 'b':
235 /*
236 * specify blocksize
237 */
238 flg |= BF;
239 if ((wrblksz = (int)str_offt(optarg)) <= 0) {
240 paxwarn(1, "Invalid block size %s", optarg);
241 pax_usage();
242 }
243 break;
244 case 'c':
245 /*
246 * inverse match on patterns
247 */
248 cflag = 1;
249 flg |= CF;
250 break;
251 case 'd':
252 /*
253 * match only dir on extract, not the subtree at dir
254 */
255 dflag = 1;
256 flg |= DF;
257 break;
258 case 'f':
259 /*
260 * filename where the archive is stored
261 */
262 arcname = optarg;
263 flg |= FF;
264 break;
265 case 'i':
266 /*
267 * interactive file rename
268 */
269 iflag = 1;
270 flg |= IF;
271 break;
272 case 'k':
273 /*
274 * do not clobber files that exist
275 */
276 kflag = 1;
277 flg |= KF;
278 break;
279 case 'l':
280 /*
281 * try to link src to dest with copy (-rw)
282 */
283 lflag = 1;
284 flg |= LF;
285 break;
286 case 'n':
287 /*
288 * select first match for a pattern only
289 */
290 nflag = 1;
291 flg |= NF;
292 break;
293 case 'o':
294 /*
295 * pass format specific options
296 */
297 flg |= OF;
298 if (opt_add(optarg) < 0)
299 pax_usage();
300 break;
301 case 'p':
302 /*
303 * specify file characteristic options
304 */
305 for (pt = optarg; *pt != '\0'; ++pt) {
306 switch (*pt) {
307 case 'a':
308 /*
309 * do not preserve access time
310 */
311 patime = 0;
312 break;
313 case 'e':
314 /*
315 * preserve user id, group id, file
316 * mode, access/modification times
317 */
318 pids = 1;
319 pmode = 1;
320 patime = 1;
321 pmtime = 1;
322 break;
323 case 'm':
324 /*
325 * do not preserve modification time
326 */
327 pmtime = 0;
328 break;
329 case 'o':
330 /*
331 * preserve uid/gid
332 */
333 pids = 1;
334 break;
335 case 'p':
336 /*
337 * preserve file mode bits
338 */
339 pmode = 1;
340 break;
341 default:
342 paxwarn(1, "Invalid -p string: %c", *pt);
343 pax_usage();
344 break;
345 }
346 }
347 flg |= PF;
348 break;
349 case 'r':
350 /*
351 * read the archive
352 */
353 flg |= RF;
354 break;
355 case 's':
356 /*
357 * file name substitution name pattern
358 */
359 if (rep_add(optarg) < 0) {
360 pax_usage();
361 break;
362 }
363 flg |= SF;
364 break;
365 case 't':
366 /*
367 * preserve access time on filesystem nodes we read
368 */
369 tflag = 1;
370 flg |= TF;
371 break;
372 case 'u':
373 /*
374 * ignore those older files
375 */
376 uflag = 1;
377 flg |= UF;
378 break;
379 case 'v':
380 /*
381 * verbose operation mode
382 */
383 vflag = 1;
384 flg |= VF;
385 break;
386 case 'w':
387 /*
388 * write an archive
389 */
390 flg |= WF;
391 break;
392 case 'x':
393 /*
394 * specify an archive format on write
395 */
396 tmp.name = optarg;
397 if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
398 sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) != NULL) {
399 flg |= XF;
400 break;
401 }
402 paxwarn(1, "Unknown -x format: %s", optarg);
403 (void)fputs("pax: Known -x formats are:", stderr);
404 for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
405 (void)fprintf(stderr, " %s", fsub[i].name);
406 (void)fputs("\n\n", stderr);
407 pax_usage();
408 break;
409 case 'z':
410 /*
411 * use gzip. Non standard option.
412 */
413 gzip_program = GZIP_CMD;
414 break;
415 case 'B':
416 /*
417 * non-standard option on number of bytes written on a
418 * single archive volume.
419 */
420 if ((wrlimit = str_offt(optarg)) <= 0) {
421 paxwarn(1, "Invalid write limit %s", optarg);
422 pax_usage();
423 }
424 if (wrlimit % BLKMULT) {
425 paxwarn(1, "Write limit is not a %d byte multiple",
426 BLKMULT);
427 pax_usage();
428 }
429 flg |= CBF;
430 break;
431 case 'D':
432 /*
433 * On extraction check file inode change time before the
434 * modification of the file name. Non standard option.
435 */
436 Dflag = 1;
437 flg |= CDF;
438 break;
439 case 'E':
440 /*
441 * non-standard limit on read faults
442 * 0 indicates stop after first error, values
443 * indicate a limit, "NONE" try forever
444 */
445 flg |= CEF;
446 if (strcmp(NONE, optarg) == 0)
447 maxflt = -1;
448 else if ((maxflt = atoi(optarg)) < 0) {
449 paxwarn(1, "Error count value must be positive");
450 pax_usage();
451 }
452 break;
453 case 'G':
454 /*
455 * non-standard option for selecting files within an
456 * archive by group (gid or name)
457 */
458 if (grp_add(optarg) < 0) {
459 pax_usage();
460 break;
461 }
462 flg |= CGF;
463 break;
464 case 'H':
465 /*
466 * follow command line symlinks only
467 */
468 Hflag = 1;
469 flg |= CHF;
470 break;
471 case 'L':
472 /*
473 * follow symlinks
474 */
475 Lflag = 1;
476 flg |= CLF;
477 break;
478 case 'O':
479 /*
480 * Force one volume. Non standard option.
481 */
482 force_one_volume = 1;
483 break;
484 case 'P':
485 /*
486 * do NOT follow symlinks (default)
487 */
488 Lflag = 0;
489 flg |= CPF;
490 break;
491 case 'T':
492 /*
493 * non-standard option for selecting files within an
494 * archive by modification time range (lower,upper)
495 */
496 if (trng_add(optarg) < 0) {
497 pax_usage();
498 break;
499 }
500 flg |= CTF;
501 break;
502 case 'U':
503 /*
504 * non-standard option for selecting files within an
505 * archive by user (uid or name)
506 */
507 if (usr_add(optarg) < 0) {
508 pax_usage();
509 break;
510 }
511 flg |= CUF;
512 break;
513 case 'X':
514 /*
515 * do not pass over mount points in the file system
516 */
517 Xflag = 1;
518 flg |= CXF;
519 break;
520 case 'Y':
521 /*
522 * On extraction check file inode change time after the
523 * modification of the file name. Non standard option.
524 */
525 Yflag = 1;
526 flg |= CYF;
527 break;
528 case 'Z':
529 /*
530 * On extraction check modification time after the
531 * modification of the file name. Non standard option.
532 */
533 Zflag = 1;
534 flg |= CZF;
535 break;
536 case '0':
537 /*
538 * Use \0 as pathname terminator.
539 * (For use with the -print0 option of find(1).)
540 */
541 zeroflag = 1;
542 flg |= C0F;
543 break;
544 default:
545 pax_usage();
546 break;
547 }
548 }
549
550 /*
551 * figure out the operation mode of pax read,write,extract,copy,append
552 * or list. check that we have not been given a bogus set of flags
553 * for the operation mode.
554 */
555 if (ISLIST(flg)) {
556 act = LIST;
557 listf = stdout;
558 bflg = flg & BDLIST;
559 } else if (ISEXTRACT(flg)) {
560 act = EXTRACT;
561 bflg = flg & BDEXTR;
562 } else if (ISARCHIVE(flg)) {
563 act = ARCHIVE;
564 bflg = flg & BDARCH;
565 } else if (ISAPPND(flg)) {
566 act = APPND;
567 bflg = flg & BDARCH;
568 } else if (ISCOPY(flg)) {
569 act = COPY;
570 bflg = flg & BDCOPY;
571 } else
572 pax_usage();
573 if (bflg) {
574 printflg(flg);
575 pax_usage();
576 }
577
578 /*
579 * if we are writing (ARCHIVE) we use the default format if the user
580 * did not specify a format. when we write during an APPEND, we will
581 * adopt the format of the existing archive if none was supplied.
582 */
583 if (!(flg & XF) && (act == ARCHIVE))
584 frmt = &(fsub[DEFLT]);
585
586 /*
587 * process the args as they are interpreted by the operation mode
588 */
589 switch (act) {
590 case LIST:
591 case EXTRACT:
592 for (; optind < argc; optind++)
593 if (pat_add(argv[optind], NULL) < 0)
594 pax_usage();
595 break;
596 case COPY:
597 if (optind >= argc) {
598 paxwarn(0, "Destination directory was not supplied");
599 pax_usage();
600 }
601 --argc;
602 dirptr = argv[argc];
603 /* FALL THROUGH */
604 case ARCHIVE:
605 case APPND:
606 for (; optind < argc; optind++)
607 if (ftree_add(argv[optind], 0) < 0)
608 pax_usage();
609 /*
610 * no read errors allowed on updates/append operation!
611 */
612 maxflt = 0;
613 break;
614 }
615}
616
617
618/*
619 * tar_options()
620 * look at the user specified flags. set globals as required and check if
621 * the user specified a legal set of flags. If not, complain and exit
622 */
623
624static void
625tar_options(int argc, char **argv)
626{
627 int c;
628 int fstdin = 0;
629 int Oflag = 0;
630 int nincfiles = 0;
631 int incfiles_max = 0;
632 struct incfile {
633 char *file;
634 char *dir;
635 };
636 struct incfile *incfiles = NULL;
637
638 /*
639 * Set default values.
640 */
641 rmleadslash = 1;
642
643 /*
644 * process option flags
645 */
646 while ((c = getoldopt(argc, argv,
647 "b:cef:hmopqruts:vwxzBC:HI:LM:OPRSXZ014578")) != -1) {
648 switch (c) {
649 case 'b':
650 /*
651 * specify blocksize in 512-byte blocks
652 */
653 if ((wrblksz = (int)str_offt(optarg)) <= 0) {
654 paxwarn(1, "Invalid block size %s", optarg);
655 tar_usage();
656 }
657 wrblksz *= 512; /* XXX - check for int oflow */
658 break;
659 case 'c':
660 /*
661 * create an archive
662 */
663 act = ARCHIVE;
664 break;
665 case 'e':
666 /*
667 * stop after first error
668 */
669 maxflt = 0;
670 break;
671 case 'f':
672 /*
673 * filename where the archive is stored
674 */
675 if ((optarg[0] == '-') && (optarg[1]== '\0')) {
676 /*
677 * treat a - as stdin
678 */
679 fstdin = 1;
680 arcname = NULL;
681 break;
682 }
683 fstdin = 0;
684 arcname = optarg;
685 break;
686 case 'h':
687 /*
688 * follow symlinks
689 */
690 Lflag = 1;
691 break;
692 case 'm':
693 /*
694 * do not preserve modification time
695 */
696 pmtime = 0;
697 break;
698 case 'O':
699 Oflag = 1;
700 to_stdout = 2;
701 break;
702 case 'o':
703 Oflag = 2;
704 break;
705 case 'p':
706 /*
707 * preserve uid/gid and file mode, regardless of umask
708 */
709 pmode = 1;
710 pids = 1;
711 break;
712 case 'q':
713 /*
714 * select first match for a pattern only
715 */
716 nflag = 1;
717 break;
718 case 'r':
719 case 'u':
720 /*
721 * append to the archive
722 */
723 act = APPND;
724 break;
725 case 'R':
726 Oflag = 3;
727 anonarch = ANON_INODES | ANON_HARDLINKS;
728 break;
729 case 'S':
730 Oflag = 4;
731 anonarch = ANON_INODES | ANON_HARDLINKS;
732 break;
733 case 's':
734 /*
735 * file name substitution name pattern
736 */
737 if (rep_add(optarg) < 0) {
738 tar_usage();
739 break;
740 }
741 break;
742 case 't':
743 /*
744 * list contents of the tape
745 */
746 act = LIST;
747 break;
748 case 'v':
749 /*
750 * verbose operation mode
751 */
752 vflag++;
753 break;
754 case 'w':
755 /*
756 * interactive file rename
757 */
758 iflag = 1;
759 break;
760 case 'x':
761 /*
762 * extract an archive, preserving mode,
763 * and mtime if possible.
764 */
765 act = EXTRACT;
766 pmtime = 1;
767 break;
768 case 'z':
769 /*
770 * use gzip. Non standard option.
771 */
772 gzip_program = GZIP_CMD;
773 break;
774 case 'B':
775 /*
776 * Nothing to do here, this is pax default
777 */
778 break;
779 case 'C':
780 chdname = optarg;
781 break;
782 case 'H':
783 /*
784 * follow command line symlinks only
785 */
786 Hflag = 1;
787 break;
788 case 'I':
789 if (++nincfiles > incfiles_max) {
790 incfiles_max = nincfiles + 3;
791 incfiles = realloc(incfiles,
792 sizeof(*incfiles) * incfiles_max);
793 if (incfiles == NULL) {
794 paxwarn(0, "Unable to allocate space "
795 "for option list");
796 exit(1);
797 }
798 }
799 incfiles[nincfiles - 1].file = optarg;
800 incfiles[nincfiles - 1].dir = chdname;
801 break;
802 case 'L':
803 /*
804 * follow symlinks
805 */
806 Lflag = 1;
807 break;
808 case 'M':
809 process_M(optarg, tar_usage);
810 break;
811 case 'P':
812 /*
813 * do not remove leading '/' from pathnames
814 */
815 rmleadslash = 0;
816 break;
817 case 'X':
818 /*
819 * do not pass over mount points in the file system
820 */
821 Xflag = 1;
822 break;
823 case 'Z':
824 /*
825 * use compress.
826 */
827 gzip_program = COMPRESS_CMD;
828 break;
829 case '0':
830 arcname = DEV_0;
831 break;
832 case '1':
833 arcname = DEV_1;
834 break;
835 case '4':
836 arcname = DEV_4;
837 break;
838 case '5':
839 arcname = DEV_5;
840 break;
841 case '7':
842 arcname = DEV_7;
843 break;
844 case '8':
845 arcname = DEV_8;
846 break;
847 default:
848 tar_usage();
849 break;
850 }
851 }
852 argc -= optind;
853 argv += optind;
854
855 /* Traditional tar behaviour (pax uses stderr unless in list mode) */
856 if (fstdin == 1 && act == ARCHIVE)
857 listf = stderr;
858 else
859 listf = stdout;
860
861 /* Traditional tar behaviour (pax wants to read file list from stdin) */
862 if ((act == ARCHIVE || act == APPND) && argc == 0 && nincfiles == 0)
863 exit(0);
864
865 /*
866 * process the args as they are interpreted by the operation mode
867 */
868 switch (act) {
869 case EXTRACT:
870 if (to_stdout == 2)
871 to_stdout = 1;
872 case LIST:
873 default:
874 {
875 int sawpat = 0;
876 char *file, *dir = NULL;
877
878 while (nincfiles || *argv != NULL) {
879 /*
880 * If we queued up any include files,
881 * pull them in now. Otherwise, check
882 * for -I and -C positional flags.
883 * Anything else must be a file to
884 * extract.
885 */
886 if (nincfiles) {
887 file = incfiles->file;
888 dir = incfiles->dir;
889 incfiles++;
890 nincfiles--;
891 } else if (strcmp(*argv, "-I") == 0) {
892 if (*++argv == NULL)
893 break;
894 file = *argv++;
895 dir = chdname;
896 } else
897 file = NULL;
898 if (file != NULL) {
899 FILE *fp;
900 char *str;
901
902 if (strcmp(file, "-") == 0)
903 fp = stdin;
904 else if ((fp = fopen(file, "r")) == NULL) {
905 paxwarn(1, "Unable to open file '%s' for read", file);
906 tar_usage();
907 }
908 while ((str = getline(fp)) != NULL) {
909 if (pat_add(str, dir) < 0)
910 tar_usage();
911 sawpat = 1;
912 }
913 if (strcmp(file, "-") != 0)
914 fclose(fp);
915 if (getline_error) {
916 paxwarn(1, "Problem with file '%s'", file);
917 tar_usage();
918 }
919 } else if (strcmp(*argv, "-C") == 0) {
920 if (*++argv == NULL)
921 break;
922 chdname = *argv++;
923 } else if (pat_add(*argv++, chdname) < 0)
924 tar_usage();
925 else
926 sawpat = 1;
927 }
928 /*
929 * if patterns were added, we are doing chdir()
930 * on a file-by-file basis, else, just one
931 * global chdir (if any) after opening input.
932 */
933 if (sawpat > 0)
934 chdname = NULL;
935 }
936 break;
937 case ARCHIVE:
938 case APPND:
939 switch(Oflag) {
940 case 0:
941 frmt = &(fsub[F_TAR]);
942 break;
943 case 1:
944 frmt = &(fsub[F_OTAR]);
945 break;
946 case 2:
947 frmt = &(fsub[F_OTAR]);
948 if (opt_add("write_opt=nodir") < 0)
949 tar_usage();
950 break;
951 case 3:
952 frmt = &(fsub[F_NCPIO]);
953 break;
954 case 4:
955 frmt = &(fsub[F_CPIO]);
956 break;
957 default:
958 tar_usage();
959 break;
960 }
961
962 if (chdname != NULL) { /* initial chdir() */
963 if (ftree_add(chdname, 1) < 0)
964 tar_usage();
965 }
966
967 while (nincfiles || *argv != NULL) {
968 char *file, *dir = NULL;
969
970 /*
971 * If we queued up any include files, pull them in
972 * now. Otherwise, check for -I and -C positional
973 * flags. Anything else must be a file to include
974 * in the archive.
975 */
976 if (nincfiles) {
977 file = incfiles->file;
978 dir = incfiles->dir;
979 incfiles++;
980 nincfiles--;
981 } else if (strcmp(*argv, "-I") == 0) {
982 if (*++argv == NULL)
983 break;
984 file = *argv++;
985 dir = NULL;
986 } else
987 file = NULL;
988 if (file != NULL) {
989 FILE *fp;
990 char *str;
991
992 /* Set directory if needed */
993 if (dir) {
994 if (ftree_add(dir, 1) < 0)
995 tar_usage();
996 }
997
998 if (strcmp(file, "-") == 0)
999 fp = stdin;
1000 else if ((fp = fopen(file, "r")) == NULL) {
1001 paxwarn(1, "Unable to open file '%s' for read", file);
1002 tar_usage();
1003 }
1004 while ((str = getline(fp)) != NULL) {
1005 if (ftree_add(str, 0) < 0)
1006 tar_usage();
1007 }
1008 if (strcmp(file, "-") != 0)
1009 fclose(fp);
1010 if (getline_error) {
1011 paxwarn(1, "Problem with file '%s'",
1012 file);
1013 tar_usage();
1014 }
1015 } else if (strcmp(*argv, "-C") == 0) {
1016 if (*++argv == NULL)
1017 break;
1018 if (ftree_add(*argv++, 1) < 0)
1019 tar_usage();
1020 } else if (ftree_add(*argv++, 0) < 0)
1021 tar_usage();
1022 }
1023 /*
1024 * no read errors allowed on updates/append operation!
1025 */
1026 maxflt = 0;
1027 break;
1028 }
1029 if (to_stdout != 1)
1030 to_stdout = 0;
1031 if (!fstdin && ((arcname == NULL) || (*arcname == '\0'))) {
1032 arcname = getenv("TAPE");
1033#ifdef _PATH_DEFTAPE
1034 if ((arcname == NULL) || (*arcname == '\0'))
1035 arcname = _PATH_DEFTAPE;
1036#endif
1037 }
1038}
1039
1040int
1041mkpath(char *path)
1042{
1043 struct stat sb;
1044 char *slash;
1045 int done = 0;
1046
1047 slash = path;
1048
1049 while (!done) {
1050 slash += strspn(slash, "/");
1051 slash += strcspn(slash, "/");
1052
1053 done = (*slash == '\0');
1054 *slash = '\0';
1055
1056 if (stat(path, &sb)) {
1057 if (errno != ENOENT || mkdir(path, 0777)) {
1058 paxwarn(1, "%s", path);
1059 return (-1);
1060 }
1061 } else if (!S_ISDIR(sb.st_mode)) {
1062 syswarn(1, ENOTDIR, "%s", path);
1063 return (-1);
1064 }
1065
1066 if (!done)
1067 *slash = '/';
1068 }
1069
1070 return (0);
1071}
1072/*
1073 * cpio_options()
1074 * look at the user specified flags. set globals as required and check if
1075 * the user specified a legal set of flags. If not, complain and exit
1076 */
1077
1078static void
1079cpio_options(int argc, char **argv)
1080{
1081 int c, i;
1082 char *str;
1083 FSUB tmp;
1084 FILE *fp;
1085
1086 kflag = 1;
1087 pids = 1;
1088 pmode = 1;
1089 pmtime = 0;
1090 arcname = NULL;
1091 dflag = 1;
1092 act = -1;
1093 nodirs = 1;
1094 while ((c=getopt(argc,argv,"abcdfiklmoprstuvzABC:E:F:H:I:LM:O:SZ6")) != -1)
1095 switch (c) {
1096 case 'a':
1097 /*
1098 * preserve access time on files read
1099 */
1100 tflag = 1;
1101 break;
1102 case 'b':
1103 /*
1104 * swap bytes and half-words when reading data
1105 */
1106 break;
1107 case 'c':
1108 /*
1109 * ASCII cpio header
1110 */
1111 frmt = &(fsub[F_ACPIO]);
1112 break;
1113 case 'd':
1114 /*
1115 * create directories as needed
1116 */
1117 nodirs = 0;
1118 break;
1119 case 'f':
1120 /*
1121 * invert meaning of pattern list
1122 */
1123 cflag = 1;
1124 break;
1125 case 'i':
1126 /*
1127 * restore an archive
1128 */
1129 act = EXTRACT;
1130 break;
1131 case 'k':
1132 break;
1133 case 'l':
1134 /*
1135 * use links instead of copies when possible
1136 */
1137 lflag = 1;
1138 break;
1139 case 'm':
1140 /*
1141 * preserve modification time
1142 */
1143 pmtime = 1;
1144 break;
1145 case 'o':
1146 /*
1147 * create an archive
1148 */
1149 act = ARCHIVE;
1150 frmt = &(fsub[F_CPIO]);
1151 break;
1152 case 'p':
1153 /*
1154 * copy-pass mode
1155 */
1156 act = COPY;
1157 break;
1158 case 'r':
1159 /*
1160 * interactively rename files
1161 */
1162 iflag = 1;
1163 break;
1164 case 's':
1165 /*
1166 * swap bytes after reading data
1167 */
1168 break;
1169 case 't':
1170 /*
1171 * list contents of archive
1172 */
1173 act = LIST;
1174 listf = stdout;
1175 break;
1176 case 'u':
1177 /*
1178 * replace newer files
1179 */
1180 kflag = 0;
1181 break;
1182 case 'v':
1183 /*
1184 * verbose operation mode
1185 */
1186 vflag = 1;
1187 break;
1188 case 'z':
1189 /*
1190 * use gzip. Non standard option.
1191 */
1192 gzip_program = GZIP_CMD;
1193 break;
1194 case 'A':
1195 /*
1196 * append mode
1197 */
1198 act = APPND;
1199 break;
1200 case 'B':
1201 /*
1202 * Use 5120 byte block size
1203 */
1204 wrblksz = 5120;
1205 break;
1206 case 'C':
1207 /*
1208 * set block size in bytes
1209 */
1210 wrblksz = atoi(optarg);
1211 break;
1212 case 'E':
1213 /*
1214 * file with patterns to extract or list
1215 */
1216 if ((fp = fopen(optarg, "r")) == NULL) {
1217 paxwarn(1, "Unable to open file '%s' for read", optarg);
1218 cpio_usage();
1219 }
1220 while ((str = getline(fp)) != NULL) {
1221 pat_add(str, NULL);
1222 }
1223 fclose(fp);
1224 if (getline_error) {
1225 paxwarn(1, "Problem with file '%s'", optarg);
1226 cpio_usage();
1227 }
1228 break;
1229 case 'F':
1230 case 'I':
1231 case 'O':
1232 /*
1233 * filename where the archive is stored
1234 */
1235 if ((optarg[0] == '-') && (optarg[1]== '\0')) {
1236 /*
1237 * treat a - as stdin
1238 */
1239 arcname = NULL;
1240 break;
1241 }
1242 arcname = optarg;
1243 break;
1244 case 'H':
1245 /*
1246 * specify an archive format on write
1247 */
1248 if (!strcmp(optarg, "bin")) {
1249 tmp.name = "bcpio";
1250 } else if (!strcmp(optarg, "crc")) {
1251 tmp.name = "sv4crc";
1252 } else if (!strcmp(optarg, "newc")) {
1253 tmp.name = "sv4cpio";
1254 } else if (!strcmp(optarg, "odc")) {
1255 tmp.name = "cpio";
1256 } else {
1257 tmp.name = optarg;
1258 }
1259 if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
1260 sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) != NULL)
1261 break;
1262 paxwarn(1, "Unknown -H format: %s", optarg);
1263 (void)fputs("cpio: Known -H formats are:", stderr);
1264 for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
1265 (void)fprintf(stderr, " %s", fsub[i].name);
1266 (void)fputs("\n\n", stderr);
1267 cpio_usage();
1268 break;
1269 case 'L':
1270 /*
1271 * follow symbolic links
1272 */
1273 Lflag = 1;
1274 break;
1275 case 'M':
1276 process_M(optarg, cpio_usage);
1277 break;
1278 case 'S':
1279 /*
1280 * swap halfwords after reading data
1281 */
1282 break;
1283 case 'Z':
1284 /*
1285 * use compress. Non standard option.
1286 */
1287 gzip_program = COMPRESS_CMD;
1288 break;
1289 case '6':
1290 /*
1291 * process Version 6 cpio format
1292 */
1293 frmt = &(fsub[F_OCPIO]);
1294 break;
1295 case '?':
1296 default:
1297 cpio_usage();
1298 break;
1299 }
1300 argc -= optind;
1301 argv += optind;
1302
1303 /*
1304 * process the args as they are interpreted by the operation mode
1305 */
1306 switch (act) {
1307 case LIST:
1308 case EXTRACT:
1309 while (*argv != NULL)
1310 if (pat_add(*argv++, NULL) < 0)
1311 cpio_usage();
1312 break;
1313 case COPY:
1314 if (*argv == NULL) {
1315 paxwarn(0, "Destination directory was not supplied");
1316 cpio_usage();
1317 }
1318 dirptr = *argv;
1319 if (mkpath(dirptr) < 0)
1320 cpio_usage();
1321 --argc;
1322 ++argv;
1323 /* FALL THROUGH */
1324 case ARCHIVE:
1325 case APPND:
1326 if (*argv != NULL)
1327 cpio_usage();
1328 /*
1329 * no read errors allowed on updates/append operation!
1330 */
1331 maxflt = 0;
1332 while ((str = getline(stdin)) != NULL) {
1333 ftree_add(str, 0);
1334 }
1335 if (getline_error) {
1336 paxwarn(1, "Problem while reading stdin");
1337 cpio_usage();
1338 }
1339 break;
1340 default:
1341 cpio_usage();
1342 break;
1343 }
1344}
1345
1346/*
1347 * printflg()
1348 * print out those invalid flag sets found to the user
1349 */
1350
1351static void
1352printflg(unsigned int flg)
1353{
1354 int nxt;
1355 int pos = 0;
1356
1357 (void)fprintf(stderr,"%s: Invalid combination of options:", argv0);
1358 while ((nxt = ffs(flg)) != 0) {
1359 flg = flg >> nxt;
1360 pos += nxt;
1361 (void)fprintf(stderr, " -%c", flgch[pos-1]);
1362 }
1363 (void)putc('\n', stderr);
1364}
1365
1366/*
1367 * c_frmt()
1368 * comparison routine used by bsearch to find the format specified
1369 * by the user
1370 */
1371
1372static int
1373c_frmt(const void *a, const void *b)
1374{
1375 return(strcmp(((FSUB *)a)->name, ((FSUB *)b)->name));
1376}
1377
1378/*
1379 * opt_next()
1380 * called by format specific options routines to get each format specific
1381 * flag and value specified with -o
1382 * Return:
1383 * pointer to next OPLIST entry or NULL (end of list).
1384 */
1385
1386OPLIST *
1387opt_next(void)
1388{
1389 OPLIST *opt;
1390
1391 if ((opt = ophead) != NULL)
1392 ophead = ophead->fow;
1393 return(opt);
1394}
1395
1396/*
1397 * bad_opt()
1398 * generic routine used to complain about a format specific options
1399 * when the format does not support options.
1400 */
1401
1402int
1403bad_opt(void)
1404{
1405 OPLIST *opt;
1406
1407 if (ophead == NULL)
1408 return(0);
1409 /*
1410 * print all we were given
1411 */
1412 paxwarn(1,"These format options are not supported");
1413 while ((opt = opt_next()) != NULL)
1414 (void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
1415 pax_usage();
1416 return(0);
1417}
1418
1419/*
1420 * opt_add()
1421 * breaks the value supplied to -o into a option name and value. options
1422 * are given to -o in the form -o name-value,name=value
1423 * multiple -o may be specified.
1424 * Return:
1425 * 0 if format in name=value format, -1 if -o is passed junk
1426 */
1427
1428int
1429opt_add(const char *str)
1430{
1431 OPLIST *opt;
1432 char *frpt;
1433 char *pt;
1434 char *endpt;
1435 char *dstr;
1436
1437 if ((str == NULL) || (*str == '\0')) {
1438 paxwarn(0, "Invalid option name");
1439 return(-1);
1440 }
1441 if ((dstr = strdup(str)) == NULL) {
1442 paxwarn(0, "Unable to allocate space for option list");
1443 return(-1);
1444 }
1445 frpt = endpt = dstr;
1446
1447 /*
1448 * break into name and values pieces and stuff each one into a
1449 * OPLIST structure. When we know the format, the format specific
1450 * option function will go through this list
1451 */
1452 while ((frpt != NULL) && (*frpt != '\0')) {
1453 if ((endpt = strchr(frpt, ',')) != NULL)
1454 *endpt = '\0';
1455 if ((pt = strchr(frpt, '=')) == NULL) {
1456 paxwarn(0, "Invalid options format");
1457 free(dstr);
1458 return(-1);
1459 }
1460 if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
1461 paxwarn(0, "Unable to allocate space for option list");
1462 free(dstr);
1463 return(-1);
1464 }
1465 *pt++ = '\0';
1466 opt->name = frpt;
1467 opt->value = pt;
1468 opt->fow = NULL;
1469 if (endpt != NULL)
1470 frpt = endpt + 1;
1471 else
1472 frpt = NULL;
1473 if (ophead == NULL) {
1474 optail = ophead = opt;
1475 continue;
1476 }
1477 optail->fow = opt;
1478 optail = opt;
1479 }
1480 return(0);
1481}
1482
1483/*
1484 * str_offt()
1485 * Convert an expression of the following forms to an off_t > 0.
1486 * 1) A positive decimal number.
1487 * 2) A positive decimal number followed by a b (mult by 512).
1488 * 3) A positive decimal number followed by a k (mult by 1024).
1489 * 4) A positive decimal number followed by a m (mult by 512).
1490 * 5) A positive decimal number followed by a w (mult by sizeof int)
1491 * 6) Two or more positive decimal numbers (with/without k,b or w).
1492 * separated by x (also * for backwards compatibility), specifying
1493 * the product of the indicated values.
1494 * Return:
1495 * 0 for an error, a positive value o.w.
1496 */
1497
1498static off_t
1499str_offt(char *val)
1500{
1501 char *expr;
1502 off_t num, t;
1503
1504# ifdef LONG_OFF_T
1505 num = strtol(val, &expr, 0);
1506 if ((num == LONG_MAX) || (num <= 0) || (expr == val))
1507# else
1508 num = strtoq(val, &expr, 0);
1509 if ((num == QUAD_MAX) || (num <= 0) || (expr == val))
1510# endif
1511 return(0);
1512
1513 switch (*expr) {
1514 case 'b':
1515 t = num;
1516 num *= 512;
1517 if (t > num)
1518 return(0);
1519 ++expr;
1520 break;
1521 case 'k':
1522 t = num;
1523 num *= 1024;
1524 if (t > num)
1525 return(0);
1526 ++expr;
1527 break;
1528 case 'm':
1529 t = num;
1530 num *= 1048576;
1531 if (t > num)
1532 return(0);
1533 ++expr;
1534 break;
1535 case 'w':
1536 t = num;
1537 num *= sizeof(int);
1538 if (t > num)
1539 return(0);
1540 ++expr;
1541 break;
1542 }
1543
1544 switch (*expr) {
1545 case '\0':
1546 break;
1547 case '*':
1548 case 'x':
1549 t = num;
1550 num *= str_offt(expr + 1);
1551 if (t > num)
1552 return(0);
1553 break;
1554 default:
1555 return(0);
1556 }
1557 return(num);
1558}
1559
1560char *
1561getline(FILE *f)
1562{
1563 char *name, *temp;
1564 size_t len;
1565
1566 name = fgetln(f, &len);
1567 if (!name) {
1568 getline_error = ferror(f) ? GETLINE_FILE_CORRUPT : 0;
1569 return(0);
1570 }
1571 if (name[len-1] != '\n')
1572 len++;
1573 temp = malloc(len);
1574 if (!temp) {
1575 getline_error = GETLINE_OUT_OF_MEM;
1576 return(0);
1577 }
1578 memcpy(temp, name, len-1);
1579 temp[len-1] = 0;
1580 return(temp);
1581}
1582
1583/*
1584 * no_op()
1585 * for those option functions where the archive format has nothing to do.
1586 * Return:
1587 * 0
1588 */
1589
1590static int
1591no_op(void)
1592{
1593 return(0);
1594}
1595
1596/*
1597 * pax_usage()
1598 * print the usage summary to the user
1599 */
1600
1601void
1602pax_usage(void)
1603{
1604 (void)fputs(
1605 "usage: pax [-0cdOnRSvz] [-E limit] [-f archive] [-G group] [-s replstr]\n"
1606 "\t [-T [from_date][,to_date][/[c][m]]] [-U user] [pattern ...]\n"
1607 " pax -r [-0cDdikOnuvzYZz] [-E limit] [-f archive] [-G group]\n"
1608 "\t [-o options] [-p string] [-s replstr] [-T [from_date][,to_date]]\n"
1609 "\t [-U user] [pattern ...]\n"
1610 " pax -w [-0adHiLOPtuvXz] [-B bytes] [-b blocksize] [-f archive]\n"
1611 "\t [-G group] [-o options] [-s replstr]\n"
1612 "\t [-T [from_date][,to_date][/[c][m]]] [-U user] [-x format] [file ...]\n"
1613 " pax -r -w [-0DdHikLlnOPtuvXYZ] [-G group] [-p string] [-s replstr]\n"
1614 "\t [-T [from_date][,to_date][/[c][m]]] [-U user] [file ...] directory\n",
1615 stderr);
1616 exit(1);
1617}
1618
1619/*
1620 * tar_usage()
1621 * print the usage summary to the user
1622 */
1623
1624void
1625tar_usage(void)
1626{
1627 (void)fputs(
1628 "usage: tar {crtux}[014578befHhLmOoPpqsvwXZz]\n"
1629 "\t [blocking-factor | archive | replstr] [-C directory] [-I file]\n"
1630 "\t [file ...]\n"
1631 " tar {-crtux} [-014578eHhLmOoPpqvwXZz] [-b blocking-factor] [-M value]\n"
1632 "\t [-C directory] [-f archive] [-I file] [-s replstr] [file ...]\n",
1633 stderr);
1634 exit(1);
1635}
1636
1637/*
1638 * cpio_usage()
1639 * print the usage summary to the user
1640 */
1641
1642void
1643cpio_usage(void)
1644{
1645 (void)fputs("usage: cpio -o [-aABcLvVzZ] [-C bytes] [-H format] [-O archive]\n", stderr);
1646 (void)fputs(" [-M flag] [-F archive] <name-list [>archive]\n", stderr);
1647 (void)fputs(" cpio -i [-bBcdfmnrsStuvVzZ6] [-C bytes] [-E file] [-H format]\n", stderr);
1648 (void)fputs(" [-I archive] [-F archive] [pattern...] [<archive]\n", stderr);
1649 (void)fputs(" cpio -p [-adlLmuvV] destination-directory <name-list\n", stderr);
1650 exit(1);
1651}
1652
1653void
1654anonarch_init(void)
1655{
1656 if (anonarch & ANON_VERBOSE) {
1657 anonarch &= ~ANON_VERBOSE;
1658 paxwarn(0, "debug: -M 0x%08X", anonarch);
1659 }
1660}
1661
1662static void
1663process_M(const char *arg, void (*call_usage)(void))
1664{
1665 int j, k = 0;
1666
1667 if ((arg[0] >= '0') && (arg[0] <= '9')) {
1668#ifdef __OpenBSD__
1669 const char *s;
1670 int64_t i = strtonum(arg, 0,
1671 ANON_MAXVAL, &s);
1672 if (s)
1673 errx(1, "%s M value: %s", s,
1674 arg);
1675#else
1676 char *ep;
1677 long long i = strtoll(arg, &ep, 0);
1678 if ((ep == arg) || (*ep != '\0') ||
1679 (i < 0) || (i > ANON_MAXVAL))
1680 errx(1, "impossible M value:"
1681 " %s", arg);
1682#endif
1683 anonarch = i;
1684 return;
1685 }
1686
1687 if (!strncmp(arg, "no-", 3)) {
1688 j = 0;
1689 arg += 3;
1690 } else
1691 j = 1;
1692 if (!strncmp(arg, "uid", 3) ||
1693 !strncmp(arg, "gid", 3)) {
1694 k = ANON_UIDGID;
1695 } else if (!strncmp(arg, "ino", 3)) {
1696 k = ANON_INODES;
1697 } else if (!strncmp(arg, "mtim", 4)) {
1698 k = ANON_MTIME;
1699 } else if (!strncmp(arg, "link", 4)) {
1700 k = ANON_HARDLINKS;
1701 } else if (!strncmp(arg, "norm", 4)) {
1702 k = ANON_UIDGID | ANON_INODES
1703 | ANON_MTIME | ANON_HARDLINKS;
1704 } else if (!strncmp(arg, "root", 4)) {
1705 k = ANON_UIDGID | ANON_INODES;
1706 } else if (!strncmp(arg, "dist", 4)) {
1707 k = ANON_UIDGID | ANON_INODES
1708 | ANON_HARDLINKS;
1709 } else if (!strncmp(arg, "set", 3)) {
1710 k = ANON_INODES | ANON_HARDLINKS;
1711 } else if (!strncmp(arg, "v", 1)) {
1712 k = ANON_VERBOSE;
1713 } else if (!strncmp(arg, "debug", 5)) {
1714 k = ANON_DEBUG;
1715 } else
1716 call_usage();
1717 if (j)
1718 anonarch |= k;
1719 else
1720 anonarch &= ~k;
1721}
Note: See TracBrowser for help on using the repository browser.