source: freewrt/tools/paxmirabilis/src/options.c@ 53c89c6

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

make this compile (on BSD)

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