English Language flag
// Log In
// CVSweb
Project: FreeWRT
// Summary // Activity // Search // Tracker // Lists // News // SCM // Wiki

SCM Repository

ViewVC logotype

Contents of /branches/freewrt_1_0/tools/paxmirabilis/src/options.c

Parent Directory Parent Directory | Revision Log Revision Log


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

root@freewrt.org:443
ViewVC Help
Powered by ViewVC 1.1.20