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