source: freewrt/tools/paxmirabilis/options.c@ c6ac237

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

Import paxmirabilis (MirCpio) from CVS as of today:
cvs -d anoncvs@…:/cvs co src/bin/pax

This will be used to replace the dependency on
GNU tar, reduce bugs and add flexibility.

ok wbx@

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

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