]>
git.saurik.com Git - apple/file_cmds.git/blob - pax/options.c
1 /* $OpenBSD: options.c,v 1.31 1998/01/22 06:21:29 millert Exp $ */
2 /* $NetBSD: options.c,v 1.6 1996/03/26 23:54:18 mrg Exp $ */
5 * Copyright (c) 1992 Keith Muller.
6 * Copyright (c) 1992, 1993
7 * The Regents of the University of California. All rights reserved.
9 * This code is derived from software contributed to Berkeley by
10 * Keith Muller of the University of California, San Diego.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 static char sccsid
[] = "@(#)options.c 8.2 (Berkeley) 4/18/94";
45 static char rcsid
[] __attribute__((__unused__
)) = "$OpenBSD: options.c,v 1.31 1998/01/22 06:21:29 millert Exp $";
49 #include <sys/types.h>
53 #include <sys/param.h>
68 * Routines which handle command line options
71 static char flgch
[] = FLGCH
; /* list of all possible flags */
72 static OPLIST
*ophead
= NULL
; /* head for format specific options -x */
73 static OPLIST
*optail
= NULL
; /* option tail */
75 static int no_op
__P((void));
76 static void printflg
__P((unsigned int));
77 static int c_frmt
__P((const void *, const void *));
78 static off_t str_offt
__P((char *));
79 static void pax_options
__P((register int, register char **));
80 static void pax_usage
__P((void));
81 static void tar_options
__P((register int, register char **));
82 static void tar_usage
__P((void));
83 static void cpio_options
__P((register int, register char **));
84 static void cpio_usage
__P((void));
86 #define GZIP_CMD "gzip" /* command to run as gzip */
87 #define COMPRESS_CMD "compress" /* command to run as compress */
90 * Format specific routine table - MUST BE IN SORTED ORDER BY NAME
91 * (see pax.h for description of each function)
93 * name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
94 * read, end_read, st_write, write, end_write, trail,
95 * rd_data, wr_data, options
99 /* 0: OLD BINARY CPIO */
100 {"bcpio", 5120, sizeof(HD_BCPIO
), 1, 0, 0, 1, bcpio_id
, cpio_strd
,
101 bcpio_rd
, bcpio_endrd
, cpio_stwr
, bcpio_wr
, cpio_endwr
, cpio_trail
,
102 rd_wrfile
, wr_rdfile
, bad_opt
},
104 /* 1: OLD OCTAL CHARACTER CPIO */
105 {"cpio", 5120, sizeof(HD_CPIO
), 1, 0, 0, 1, cpio_id
, cpio_strd
,
106 cpio_rd
, cpio_endrd
, cpio_stwr
, cpio_wr
, cpio_endwr
, cpio_trail
,
107 rd_wrfile
, wr_rdfile
, bad_opt
},
109 /* 2: SVR4 HEX CPIO */
110 {"sv4cpio", 5120, sizeof(HD_VCPIO
), 1, 0, 0, 1, vcpio_id
, cpio_strd
,
111 vcpio_rd
, vcpio_endrd
, cpio_stwr
, vcpio_wr
, cpio_endwr
, cpio_trail
,
112 rd_wrfile
, wr_rdfile
, bad_opt
},
114 /* 3: SVR4 HEX CPIO WITH CRC */
115 {"sv4crc", 5120, sizeof(HD_VCPIO
), 1, 0, 0, 1, crc_id
, crc_strd
,
116 vcpio_rd
, vcpio_endrd
, crc_stwr
, vcpio_wr
, cpio_endwr
, cpio_trail
,
117 rd_wrfile
, wr_rdfile
, bad_opt
},
120 {"tar", 10240, BLKMULT
, 0, 1, BLKMULT
, 0, tar_id
, no_op
,
121 tar_rd
, tar_endrd
, no_op
, tar_wr
, tar_endwr
, tar_trail
,
122 rd_wrfile
, wr_rdfile
, tar_opt
},
125 {"ustar", 10240, BLKMULT
, 0, 1, BLKMULT
, 0, ustar_id
, ustar_strd
,
126 ustar_rd
, tar_endrd
, ustar_stwr
, ustar_wr
, tar_endwr
, tar_trail
,
127 rd_wrfile
, wr_rdfile
, bad_opt
},
129 #define F_OCPIO 0 /* format when called as cpio -6 */
130 #define F_ACPIO 1 /* format when called as cpio -c */
131 #define F_CPIO 3 /* format when called as cpio */
132 #define F_OTAR 4 /* format when called as tar -o */
133 #define F_TAR 5 /* format when called as tar */
134 #define DEFLT 5 /* default write format from list above */
137 * ford is the archive search order used by get_arc() to determine what kind
138 * of archive we are dealing with. This helps to properly id archive formats
139 * some formats may be subsets of others....
141 int ford
[] = {5, 4, 3, 2, 1, 0, -1 };
145 * figure out if we are pax, tar or cpio. Call the appropriate options
151 options(register int argc
, register char **argv
)
156 register char **argv
;
161 * Are we acting like pax, tar or cpio (based on argv[0])
163 if ((argv0
= strrchr(argv
[0], '/')) != NULL
)
168 if (strcmp(NM_TAR
, argv0
) == 0)
169 return(tar_options(argc
, argv
));
170 else if (strcmp(NM_CPIO
, argv0
) == 0)
171 return(cpio_options(argc
, argv
));
173 * assume pax as the default
176 return(pax_options(argc
, argv
));
181 * look at the user specified flags. set globals as required and check if
182 * the user specified a legal set of flags. If not, complain and exit
187 pax_options(register int argc
, register char **argv
)
190 pax_options(argc
, argv
)
192 register char **argv
;
197 unsigned int flg
= 0;
198 unsigned int bflg
= 0;
205 * process option flags
207 while ((c
=getopt(argc
,argv
,"ab:cdf:iklno:p:rs:tuvwx:zB:DE:G:HLPT:U:XYZ"))
221 if ((wrblksz
= (int)str_offt(optarg
)) <= 0) {
222 paxwarn(1, "Invalid block size %s", optarg
);
228 * inverse match on patterns
235 * match only dir on extract, not the subtree at dir
242 * filename where the archive is stored
249 * interactive file rename
256 * do not clobber files that exist
263 * try to link src to dest with copy (-rw)
270 * select first match for a pattern only
277 * pass format specific options
280 if (opt_add(optarg
) < 0)
285 * specify file characteristic options
287 for (pt
= optarg
; *pt
!= '\0'; ++pt
) {
291 * do not preserve access time
297 * preserve user id, group id, file
298 * mode, access/modification times
307 * do not preserve modification time
319 * preserver file mode bits
324 paxwarn(1, "Invalid -p string: %c", *pt
);
339 * file name substitution name pattern
341 if (rep_add(optarg
) < 0) {
349 * preserve access time on filesystem nodes we read
356 * ignore those older files
363 * verbose operation mode
376 * specify an archive format on write
379 if ((frmt
= (FSUB
*)bsearch((void *)&tmp
, (void *)fsub
,
380 sizeof(fsub
)/sizeof(FSUB
), sizeof(FSUB
), c_frmt
)) != NULL
) {
384 paxwarn(1, "Unknown -x format: %s", optarg
);
385 (void)fputs("pax: Known -x formats are:", stderr
);
386 for (i
= 0; i
< (sizeof(fsub
)/sizeof(FSUB
)); ++i
)
387 (void)fprintf(stderr
, " %s", fsub
[i
].name
);
388 (void)fputs("\n\n", stderr
);
393 * use gzip. Non standard option.
396 gzip_program
= GZIP_CMD
;
400 * non-standard option on number of bytes written on a
401 * single archive volume.
403 if ((wrlimit
= str_offt(optarg
)) <= 0) {
404 paxwarn(1, "Invalid write limit %s", optarg
);
407 if (wrlimit
% BLKMULT
) {
408 paxwarn(1, "Write limit is not a %d byte multiple",
416 * On extraction check file inode change time before the
417 * modification of the file name. Non standard option.
424 * non-standard limit on read faults
425 * 0 indicates stop after first error, values
426 * indicate a limit, "NONE" try forever
429 if (strcmp(NONE
, optarg
) == 0)
431 else if ((maxflt
= atoi(optarg
)) < 0) {
432 paxwarn(1, "Error count value must be positive");
438 * non-standard option for selecting files within an
439 * archive by group (gid or name)
441 if (grp_add(optarg
) < 0) {
449 * follow command line symlinks only
463 * do NOT follow symlinks (default)
470 * non-standard option for selecting files within an
471 * archive by modification time range (lower,upper)
473 if (trng_add(optarg
) < 0) {
481 * non-standard option for selecting files within an
482 * archive by user (uid or name)
484 if (usr_add(optarg
) < 0) {
492 * do not pass over mount points in the file system
499 * On extraction check file inode change time after the
500 * modification of the file name. Non standard option.
507 * On extraction check modification time after the
508 * modification of the file name. Non standard option.
520 * figure out the operation mode of pax read,write,extract,copy,append
521 * or list. check that we have not been given a bogus set of flags
522 * for the operation mode.
527 } else if (ISEXTRACT(flg
)) {
530 } else if (ISARCHIVE(flg
)) {
533 } else if (ISAPPND(flg
)) {
536 } else if (ISCOPY(flg
)) {
547 * if we are writing (ARCHIVE) we use the default format if the user
548 * did not specify a format. when we write during an APPEND, we will
549 * adopt the format of the existing archive if none was supplied.
551 if (!(flg
& XF
) && (act
== ARCHIVE
))
552 frmt
= &(fsub
[DEFLT
]);
555 * process the args as they are interpreted by the operation mode
560 for (; optind
< argc
; optind
++)
561 if (pat_add(argv
[optind
], NULL
) < 0)
565 if (optind
>= argc
) {
566 paxwarn(0, "Destination directory was not supplied");
574 for (; optind
< argc
; optind
++)
575 if (ftree_add(argv
[optind
], 0) < 0)
578 * no read errors allowed on updates/append operation!
588 * look at the user specified flags. set globals as required and check if
589 * the user specified a legal set of flags. If not, complain and exit
594 tar_options(register int argc
, register char **argv
)
597 tar_options(argc
, argv
)
599 register char **argv
;
607 * Set default values.
612 * process option flags
614 while ((c
= getoldopt(argc
, argv
,
615 "b:cef:hmopruts:vwxzBC:HLOPXZ014578"))
620 * specify blocksize in 512-byte blocks
622 if ((wrblksz
= (int)str_offt(optarg
)) <= 0) {
623 paxwarn(1, "Invalid block size %s", optarg
);
626 wrblksz
*= 512; /* XXX - check for int oflow */
636 * stop after first error
642 * filename where the archive is stored
644 if ((optarg
[0] == '-') && (optarg
[1]== '\0')) {
663 * do not preserve modification time
668 if (opt_add("write_opt=nodir") < 0)
675 * preserve user id, group id, file
676 * mode, access/modification times
686 * append to the archive
692 * file name substitution name pattern
694 if (rep_add(optarg
) < 0) {
701 * list contents of the tape
707 * verbose operation mode
713 * interactive file rename
719 * write an archive, preserve ids if root
727 * use gzip. Non standard option.
730 gzip_program
= GZIP_CMD
;
734 * Nothing to do here, this is pax default
742 * follow command line symlinks only
754 * do not remove leading '/' from pathnames
760 * do not pass over mount points in the file system
769 gzip_program
= COMPRESS_CMD
;
797 /* Traditional tar behaviour (pax wants to read filelist from stdin) */
798 if ((act
== ARCHIVE
|| act
== APPND
) && argc
== 0)
802 * if we are writing (ARCHIVE) specify tar, otherwise run like pax
803 * (unless -o specified)
805 if (act
== ARCHIVE
|| act
== APPND
)
806 frmt
= &(fsub
[Oflag
? F_OTAR
: F_TAR
]);
808 paxwarn(1, "The -O/-o options are only valid when writing an archive");
809 tar_usage(); /* only valid when writing */
813 * process the args as they are interpreted by the operation mode
822 while (*argv
!= NULL
) {
823 if (strcmp(*argv
, "-C") == 0) {
830 if (pat_add(*argv
++, chdname
) < 0)
835 * if patterns were added, we are doing chdir()
836 * on a file-by-file basis, else, just one
837 * global chdir (if any) after opening input.
845 if (chdname
!= NULL
) { /* initial chdir() */
846 if (ftree_add(chdname
, 1) < 0)
850 while (*argv
!= NULL
) {
851 if (!strcmp(*argv
, "-C")) {
854 if (ftree_add(*argv
++, 1) < 0)
857 if (ftree_add(*argv
++, 0) < 0)
862 * no read errors allowed on updates/append operation!
867 if (!fstdin
&& ((arcname
== NULL
) || (*arcname
== '\0'))) {
868 arcname
= getenv("TAPE");
869 if ((arcname
== NULL
) || (*arcname
== '\0'))
870 arcname
= _PATH_DEFTAPE
;
879 register char *slash
;
885 slash
+= strspn(slash
, "/");
886 slash
+= strcspn(slash
, "/");
888 done
= (*slash
== '\0');
891 if (stat(path
, &sb
)) {
892 if (errno
!= ENOENT
|| mkdir(path
, 0777)) {
893 paxwarn(1, "%s", path
);
896 } else if (!S_ISDIR(sb
.st_mode
)) {
897 syswarn(1, ENOTDIR
, "%s", path
);
909 * look at the user specified flags. set globals as required and check if
910 * the user specified a legal set of flags. If not, complain and exit
915 cpio_options(register int argc
, register char **argv
)
918 cpio_options(argc
, argv
)
920 register char **argv
;
937 while ((c
=getopt(argc
,argv
,"abcdfiklmoprstuvzABC:E:F:H:I:LO:SZ6")) != EOF
)
941 * preserve access time on files read
947 * swap bytes and half-words when reading data
954 frmt
= &(fsub
[F_ACPIO
]);
958 * create directories as needed
964 * invert meaning of pattern list
978 * use links instead of copies when possible
984 * preserve modification time
993 frmt
= &(fsub
[F_CPIO
]);
1003 * interactively rename files
1009 * swap bytes after reading data
1014 * list contents of archive
1020 * replace newer files
1026 * verbose operation mode
1032 * use gzip. Non standard option.
1035 gzip_program
= GZIP_CMD
;
1045 * Use 5120 byte block size
1051 * set block size in bytes
1053 wrblksz
= atoi(optarg
);
1057 * file with patterns to extract or list
1059 if ((fp
= fopen(optarg
, "r")) == NULL
) {
1060 paxwarn(1, "Unable to open file '%s' for read", optarg
);
1063 while ((str
= fgetln(fp
, &len
)) != NULL
) {
1064 str
[len
- 1] = '\0';
1073 * filename where the archive is stored
1075 if ((optarg
[0] == '-') && (optarg
[1]== '\0')) {
1077 * treat a - as stdin
1086 * specify an archive format on write
1089 if ((frmt
= (FSUB
*)bsearch((void *)&tmp
, (void *)fsub
,
1090 sizeof(fsub
)/sizeof(FSUB
), sizeof(FSUB
), c_frmt
)) != NULL
)
1092 paxwarn(1, "Unknown -H format: %s", optarg
);
1093 (void)fputs("cpio: Known -H formats are:", stderr
);
1094 for (i
= 0; i
< (sizeof(fsub
)/sizeof(FSUB
)); ++i
)
1095 (void)fprintf(stderr
, " %s", fsub
[i
].name
);
1096 (void)fputs("\n\n", stderr
);
1101 * follow symbolic links
1107 * swap halfwords after reading data
1112 * use compress. Non standard option.
1115 gzip_program
= COMPRESS_CMD
;
1119 * process Version 6 cpio format
1121 frmt
= &(fsub
[F_OCPIO
]);
1132 * process the args as they are interpreted by the operation mode
1137 while (*argv
!= NULL
)
1138 if (pat_add(*argv
++, NULL
) < 0)
1142 if (*argv
== NULL
) {
1143 paxwarn(0, "Destination directory was not supplied");
1147 if (mkpath(dirptr
) < 0)
1157 * no read errors allowed on updates/append operation!
1160 while ((str
= fgetln(stdin
, &len
)) != NULL
) {
1161 str
[len
- 1] = '\0';
1162 ftree_add(strdup(str
), NULL
);
1173 * print out those invalid flag sets found to the user
1178 printflg(unsigned int flg
)
1188 (void)fprintf(stderr
,"%s: Invalid combination of options:", argv0
);
1189 while ((nxt
= ffs(flg
)) != 0) {
1192 (void)fprintf(stderr
, " -%c", flgch
[pos
-1]);
1194 (void)putc('\n', stderr
);
1199 * comparison routine used by bsearch to find the format specified
1205 c_frmt(const void *a
, const void *b
)
1213 return(strcmp(((FSUB
*)a
)->name
, ((FSUB
*)b
)->name
));
1218 * called by format specific options routines to get each format specific
1219 * flag and value specified with -o
1221 * pointer to next OPLIST entry or NULL (end of list).
1234 if ((opt
= ophead
) != NULL
)
1235 ophead
= ophead
->fow
;
1241 * generic routine used to complain about a format specific options
1242 * when the format does not support options.
1253 register OPLIST
*opt
;
1258 * print all we were given
1260 paxwarn(1,"These format options are not supported");
1261 while ((opt
= opt_next()) != NULL
)
1262 (void)fprintf(stderr
, "\t%s = %s\n", opt
->name
, opt
->value
);
1269 * breaks the value supplied to -o into a option name and value. options
1270 * are given to -o in the form -o name-value,name=value
1271 * mulltiple -o may be specified.
1273 * 0 if format in name=value format, -1 if -o is passed junk
1278 opt_add(register char *str
)
1285 register OPLIST
*opt
;
1286 register char *frpt
;
1288 register char *endpt
;
1290 if ((str
== NULL
) || (*str
== '\0')) {
1291 paxwarn(0, "Invalid option name");
1294 if ((str
= strdup(str
)) == NULL
) {
1295 paxwarn(0, "Unable to allocate space for option list");
1301 * break into name and values pieces and stuff each one into a
1302 * OPLIST structure. When we know the format, the format specific
1303 * option function will go through this list
1305 while ((frpt
!= NULL
) && (*frpt
!= '\0')) {
1306 if ((endpt
= strchr(frpt
, ',')) != NULL
)
1308 if ((pt
= strchr(frpt
, '=')) == NULL
) {
1309 paxwarn(0, "Invalid options format");
1313 if ((opt
= (OPLIST
*)malloc(sizeof(OPLIST
))) == NULL
) {
1314 paxwarn(0, "Unable to allocate space for option list");
1326 if (ophead
== NULL
) {
1327 optail
= ophead
= opt
;
1338 * Convert an expression of the following forms to an off_t > 0.
1339 * 1) A positive decimal number.
1340 * 2) A positive decimal number followed by a b (mult by 512).
1341 * 3) A positive decimal number followed by a k (mult by 1024).
1342 * 4) A positive decimal number followed by a m (mult by 512).
1343 * 5) A positive decimal number followed by a w (mult by sizeof int)
1344 * 6) Two or more positive decimal numbers (with/without k,b or w).
1345 * seperated by x (also * for backwards compatibility), specifying
1346 * the product of the indicated values.
1348 * 0 for an error, a positive value o.w.
1364 num
= strtol(val
, &expr
, 0);
1365 if ((num
== LONG_MAX
) || (num
<= 0) || (expr
== val
))
1367 num
= strtoq(val
, &expr
, 0);
1368 if ((num
== QUAD_MAX
) || (num
<= 0) || (expr
== val
))
1409 num
*= str_offt(expr
+ 1);
1421 * for those option functions where the archive format has nothing to do.
1439 * print the usage summary to the user
1450 (void)fputs("usage: pax [-cdnv] [-E limit] [-f archive] ", stderr
);
1451 (void)fputs("[-s replstr] ... [-U user] ...", stderr
);
1452 (void)fputs("\n [-G group] ... ", stderr
);
1453 (void)fputs("[-T [from_date][,to_date]] ... ", stderr
);
1454 (void)fputs("[pattern ...]\n", stderr
);
1455 (void)fputs(" pax -r [-cdiknuvDYZ] [-E limit] ", stderr
);
1456 (void)fputs("[-f archive] [-o options] ... \n", stderr
);
1457 (void)fputs(" [-p string] ... [-s replstr] ... ", stderr
);
1458 (void)fputs("[-U user] ... [-G group] ...\n ", stderr
);
1459 (void)fputs("[-T [from_date][,to_date]] ... ", stderr
);
1460 (void)fputs(" [pattern ...]\n", stderr
);
1461 (void)fputs(" pax -w [-dituvHLPX] [-b blocksize] ", stderr
);
1462 (void)fputs("[ [-a] [-f archive] ] [-x format] \n", stderr
);
1463 (void)fputs(" [-B bytes] [-s replstr] ... ", stderr
);
1464 (void)fputs("[-o options] ... [-U user] ...", stderr
);
1465 (void)fputs("\n [-G group] ... ", stderr
);
1466 (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr
);
1467 (void)fputs("[file ...]\n", stderr
);
1468 (void)fputs(" pax -r -w [-diklntuvDHLPXYZ] ", stderr
);
1469 (void)fputs("[-p string] ... [-s replstr] ...", stderr
);
1470 (void)fputs("\n [-U user] ... [-G group] ... ", stderr
);
1471 (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr
);
1472 (void)fputs("\n [file ...] directory\n", stderr
);
1478 * print the usage summary to the user
1489 (void)fputs("usage: tar -{txru}[cevfbmopswzBHLPXZ014578] [tapefile] ",
1491 (void)fputs("[blocksize] [replstr] [-C directory] file1 file2...\n",
1498 * print the usage summary to the user
1509 (void)fputs("usage: cpio -o [-aABcLvVzZ] [-C bytes] [-H format] [-O archive]\n", stderr
);
1510 (void)fputs(" [-F archive] < name-list [> archive]\n", stderr
);
1511 (void)fputs(" cpio -i [-bBcdfmnrsStuvVzZ6] [-C bytes] [-E file] [-H format]\n", stderr
);
1512 (void)fputs(" [-I archive] [-F archive] [pattern...] [< archive]\n", stderr
);
1513 (void)fputs(" cpio -p [-adlLmuvV] destination-directory < name-list\n", stderr
);