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