]>
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 (0 == strcmp("pax", optarg
)) { /* alias for ustar */
382 if ((frmt
= (FSUB
*)bsearch((void *)&tmp
, (void *)fsub
,
383 sizeof(fsub
)/sizeof(FSUB
), sizeof(FSUB
), c_frmt
)) != NULL
) {
387 paxwarn(1, "Unknown -x format: %s", optarg
);
388 (void)fputs("pax: Known -x formats are:", stderr
);
389 for (i
= 0; i
< (sizeof(fsub
)/sizeof(FSUB
)); ++i
)
390 (void)fprintf(stderr
, " %s", fsub
[i
].name
);
391 (void)fputs("\n\n", stderr
);
396 * use gzip. Non standard option.
399 gzip_program
= GZIP_CMD
;
403 * non-standard option on number of bytes written on a
404 * single archive volume.
406 if ((wrlimit
= str_offt(optarg
)) <= 0) {
407 paxwarn(1, "Invalid write limit %s", optarg
);
410 if (wrlimit
% BLKMULT
) {
411 paxwarn(1, "Write limit is not a %d byte multiple",
419 * On extraction check file inode change time before the
420 * modification of the file name. Non standard option.
427 * non-standard limit on read faults
428 * 0 indicates stop after first error, values
429 * indicate a limit, "NONE" try forever
432 if (strcmp(NONE
, optarg
) == 0)
434 else if ((maxflt
= atoi(optarg
)) < 0) {
435 paxwarn(1, "Error count value must be positive");
441 * non-standard option for selecting files within an
442 * archive by group (gid or name)
444 if (grp_add(optarg
) < 0) {
452 * follow command line symlinks only
466 * do NOT follow symlinks (default)
473 * non-standard option for selecting files within an
474 * archive by modification time range (lower,upper)
476 if (trng_add(optarg
) < 0) {
484 * non-standard option for selecting files within an
485 * archive by user (uid or name)
487 if (usr_add(optarg
) < 0) {
495 * do not pass over mount points in the file system
502 * On extraction check file inode change time after the
503 * modification of the file name. Non standard option.
510 * On extraction check modification time after the
511 * modification of the file name. Non standard option.
523 * figure out the operation mode of pax read,write,extract,copy,append
524 * or list. check that we have not been given a bogus set of flags
525 * for the operation mode.
530 } else if (ISEXTRACT(flg
)) {
533 } else if (ISARCHIVE(flg
)) {
536 } else if (ISAPPND(flg
)) {
539 } else if (ISCOPY(flg
)) {
550 * if we are writing (ARCHIVE) we use the default format if the user
551 * did not specify a format. when we write during an APPEND, we will
552 * adopt the format of the existing archive if none was supplied.
554 if (!(flg
& XF
) && (act
== ARCHIVE
))
555 frmt
= &(fsub
[DEFLT
]);
558 * process the args as they are interpreted by the operation mode
563 for (; optind
< argc
; optind
++)
564 if (pat_add(argv
[optind
], NULL
) < 0)
568 if (optind
>= argc
) {
569 paxwarn(0, "Destination directory was not supplied");
577 for (; optind
< argc
; optind
++)
578 if (ftree_add(argv
[optind
], 0) < 0)
581 * no read errors allowed on updates/append operation!
591 * look at the user specified flags. set globals as required and check if
592 * the user specified a legal set of flags. If not, complain and exit
597 tar_options(register int argc
, register char **argv
)
600 tar_options(argc
, argv
)
602 register char **argv
;
610 * Set default values.
615 * process option flags
617 while ((c
= getoldopt(argc
, argv
,
618 "b:cef:hmopruts:vwxzBC:HLOPXZ014578"))
623 * specify blocksize in 512-byte blocks
625 if ((wrblksz
= (int)str_offt(optarg
)) <= 0) {
626 paxwarn(1, "Invalid block size %s", optarg
);
629 wrblksz
*= 512; /* XXX - check for int oflow */
639 * stop after first error
645 * filename where the archive is stored
647 if ((optarg
[0] == '-') && (optarg
[1]== '\0')) {
666 * do not preserve modification time
671 if (opt_add("write_opt=nodir") < 0)
678 * preserve user id, group id, file
679 * mode, access/modification times
689 * append to the archive
695 * file name substitution name pattern
697 if (rep_add(optarg
) < 0) {
704 * list contents of the tape
710 * verbose operation mode
716 * interactive file rename
722 * write an archive, preserve ids if root
730 * use gzip. Non standard option.
733 gzip_program
= GZIP_CMD
;
737 * Nothing to do here, this is pax default
745 * follow command line symlinks only
757 * do not remove leading '/' from pathnames
763 * do not pass over mount points in the file system
772 gzip_program
= COMPRESS_CMD
;
800 /* Traditional tar behaviour (pax wants to read filelist from stdin) */
801 if ((act
== ARCHIVE
|| act
== APPND
) && argc
== 0)
805 * if we are writing (ARCHIVE) specify tar, otherwise run like pax
806 * (unless -o specified)
808 if (act
== ARCHIVE
|| act
== APPND
)
809 frmt
= &(fsub
[Oflag
? F_OTAR
: F_TAR
]);
811 paxwarn(1, "The -O/-o options are only valid when writing an archive");
812 tar_usage(); /* only valid when writing */
816 * process the args as they are interpreted by the operation mode
825 while (*argv
!= NULL
) {
826 if (strcmp(*argv
, "-C") == 0) {
833 if (pat_add(*argv
++, chdname
) < 0)
838 * if patterns were added, we are doing chdir()
839 * on a file-by-file basis, else, just one
840 * global chdir (if any) after opening input.
848 if (chdname
!= NULL
) { /* initial chdir() */
849 if (ftree_add(chdname
, 1) < 0)
853 while (*argv
!= NULL
) {
854 if (!strcmp(*argv
, "-C")) {
857 if (ftree_add(*argv
++, 1) < 0)
860 if (ftree_add(*argv
++, 0) < 0)
865 * no read errors allowed on updates/append operation!
870 if (!fstdin
&& ((arcname
== NULL
) || (*arcname
== '\0'))) {
871 arcname
= getenv("TAPE");
872 if ((arcname
== NULL
) || (*arcname
== '\0'))
873 arcname
= _PATH_DEFTAPE
;
882 register char *slash
;
888 slash
+= strspn(slash
, "/");
889 slash
+= strcspn(slash
, "/");
891 done
= (*slash
== '\0');
894 if (stat(path
, &sb
)) {
895 if (errno
!= ENOENT
|| mkdir(path
, 0777)) {
896 paxwarn(1, "%s", path
);
899 } else if (!S_ISDIR(sb
.st_mode
)) {
900 syswarn(1, ENOTDIR
, "%s", path
);
912 * look at the user specified flags. set globals as required and check if
913 * the user specified a legal set of flags. If not, complain and exit
918 cpio_options(register int argc
, register char **argv
)
921 cpio_options(argc
, argv
)
923 register char **argv
;
940 while ((c
=getopt(argc
,argv
,"abcdfiklmoprstuvzABC:E:F:H:I:LO:SZ6")) != EOF
)
944 * preserve access time on files read
950 * swap bytes and half-words when reading data
957 frmt
= &(fsub
[F_ACPIO
]);
961 * create directories as needed
967 * invert meaning of pattern list
981 * use links instead of copies when possible
987 * preserve modification time
996 frmt
= &(fsub
[F_CPIO
]);
1006 * interactively rename files
1012 * swap bytes after reading data
1017 * list contents of archive
1023 * replace newer files
1029 * verbose operation mode
1035 * use gzip. Non standard option.
1038 gzip_program
= GZIP_CMD
;
1048 * Use 5120 byte block size
1054 * set block size in bytes
1056 wrblksz
= atoi(optarg
);
1060 * file with patterns to extract or list
1062 if ((fp
= fopen(optarg
, "r")) == NULL
) {
1063 paxwarn(1, "Unable to open file '%s' for read", optarg
);
1066 while ((str
= fgetln(fp
, &len
)) != NULL
) {
1067 str
[len
- 1] = '\0';
1076 * filename where the archive is stored
1078 if ((optarg
[0] == '-') && (optarg
[1]== '\0')) {
1080 * treat a - as stdin
1089 * specify an archive format on write
1092 if ((frmt
= (FSUB
*)bsearch((void *)&tmp
, (void *)fsub
,
1093 sizeof(fsub
)/sizeof(FSUB
), sizeof(FSUB
), c_frmt
)) != NULL
)
1095 paxwarn(1, "Unknown -H format: %s", optarg
);
1096 (void)fputs("cpio: Known -H formats are:", stderr
);
1097 for (i
= 0; i
< (sizeof(fsub
)/sizeof(FSUB
)); ++i
)
1098 (void)fprintf(stderr
, " %s", fsub
[i
].name
);
1099 (void)fputs("\n\n", stderr
);
1104 * follow symbolic links
1110 * swap halfwords after reading data
1115 * use compress. Non standard option.
1118 gzip_program
= COMPRESS_CMD
;
1122 * process Version 6 cpio format
1124 frmt
= &(fsub
[F_OCPIO
]);
1135 * process the args as they are interpreted by the operation mode
1140 while (*argv
!= NULL
)
1141 if (pat_add(*argv
++, NULL
) < 0)
1145 if (*argv
== NULL
) {
1146 paxwarn(0, "Destination directory was not supplied");
1150 if (mkpath(dirptr
) < 0)
1160 * no read errors allowed on updates/append operation!
1163 while ((str
= fgetln(stdin
, &len
)) != NULL
) {
1164 str
[len
- 1] = '\0';
1165 ftree_add(strdup(str
), NULL
);
1176 * print out those invalid flag sets found to the user
1181 printflg(unsigned int flg
)
1191 (void)fprintf(stderr
,"%s: Invalid combination of options:", argv0
);
1192 while ((nxt
= ffs(flg
)) != 0) {
1195 (void)fprintf(stderr
, " -%c", flgch
[pos
-1]);
1197 (void)putc('\n', stderr
);
1202 * comparison routine used by bsearch to find the format specified
1208 c_frmt(const void *a
, const void *b
)
1216 return(strcmp(((FSUB
*)a
)->name
, ((FSUB
*)b
)->name
));
1221 * called by format specific options routines to get each format specific
1222 * flag and value specified with -o
1224 * pointer to next OPLIST entry or NULL (end of list).
1237 if ((opt
= ophead
) != NULL
)
1238 ophead
= ophead
->fow
;
1244 * generic routine used to complain about a format specific options
1245 * when the format does not support options.
1256 register OPLIST
*opt
;
1261 * print all we were given
1263 paxwarn(1,"These format options are not supported");
1264 while ((opt
= opt_next()) != NULL
)
1265 (void)fprintf(stderr
, "\t%s = %s\n", opt
->name
, opt
->value
);
1272 * breaks the value supplied to -o into a option name and value. options
1273 * are given to -o in the form -o name-value,name=value
1274 * mulltiple -o may be specified.
1276 * 0 if format in name=value format, -1 if -o is passed junk
1281 opt_add(register char *str
)
1288 register OPLIST
*opt
;
1289 register char *frpt
;
1291 register char *endpt
;
1293 if ((str
== NULL
) || (*str
== '\0')) {
1294 paxwarn(0, "Invalid option name");
1297 if ((str
= strdup(str
)) == NULL
) {
1298 paxwarn(0, "Unable to allocate space for option list");
1304 * break into name and values pieces and stuff each one into a
1305 * OPLIST structure. When we know the format, the format specific
1306 * option function will go through this list
1308 while ((frpt
!= NULL
) && (*frpt
!= '\0')) {
1309 if ((endpt
= strchr(frpt
, ',')) != NULL
)
1311 if ((pt
= strchr(frpt
, '=')) == NULL
) {
1312 paxwarn(0, "Invalid options format");
1316 if ((opt
= (OPLIST
*)malloc(sizeof(OPLIST
))) == NULL
) {
1317 paxwarn(0, "Unable to allocate space for option list");
1329 if (ophead
== NULL
) {
1330 optail
= ophead
= opt
;
1341 * Convert an expression of the following forms to an off_t > 0.
1342 * 1) A positive decimal number.
1343 * 2) A positive decimal number followed by a b (mult by 512).
1344 * 3) A positive decimal number followed by a k (mult by 1024).
1345 * 4) A positive decimal number followed by a m (mult by 512).
1346 * 5) A positive decimal number followed by a w (mult by sizeof int)
1347 * 6) Two or more positive decimal numbers (with/without k,b or w).
1348 * seperated by x (also * for backwards compatibility), specifying
1349 * the product of the indicated values.
1351 * 0 for an error, a positive value o.w.
1367 num
= strtol(val
, &expr
, 0);
1368 if ((num
== LONG_MAX
) || (num
<= 0) || (expr
== val
))
1370 num
= strtoq(val
, &expr
, 0);
1371 if ((num
== QUAD_MAX
) || (num
<= 0) || (expr
== val
))
1412 num
*= str_offt(expr
+ 1);
1424 * for those option functions where the archive format has nothing to do.
1442 * print the usage summary to the user
1453 (void)fputs("usage: pax [-cdnv] [-E limit] [-f archive] ", stderr
);
1454 (void)fputs("[-s replstr] ... [-U user] ...", stderr
);
1455 (void)fputs("\n [-G group] ... ", stderr
);
1456 (void)fputs("[-T [from_date][,to_date]] ... ", stderr
);
1457 (void)fputs("[pattern ...]\n", stderr
);
1458 (void)fputs(" pax -r [-cdiknuvDYZ] [-E limit] ", stderr
);
1459 (void)fputs("[-f archive] [-o options] ... \n", stderr
);
1460 (void)fputs(" [-p string] ... [-s replstr] ... ", stderr
);
1461 (void)fputs("[-U user] ... [-G group] ...\n ", stderr
);
1462 (void)fputs("[-T [from_date][,to_date]] ... ", stderr
);
1463 (void)fputs(" [pattern ...]\n", stderr
);
1464 (void)fputs(" pax -w [-dituvHLPX] [-b blocksize] ", stderr
);
1465 (void)fputs("[ [-a] [-f archive] ] [-x format] \n", stderr
);
1466 (void)fputs(" [-B bytes] [-s replstr] ... ", stderr
);
1467 (void)fputs("[-o options] ... [-U user] ...", stderr
);
1468 (void)fputs("\n [-G group] ... ", stderr
);
1469 (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr
);
1470 (void)fputs("[file ...]\n", stderr
);
1471 (void)fputs(" pax -r -w [-diklntuvDHLPXYZ] ", stderr
);
1472 (void)fputs("[-p string] ... [-s replstr] ...", stderr
);
1473 (void)fputs("\n [-U user] ... [-G group] ... ", stderr
);
1474 (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr
);
1475 (void)fputs("\n [file ...] directory\n", stderr
);
1481 * print the usage summary to the user
1492 (void)fputs("usage: tar -{txru}[cevfbmopswzBHLPXZ014578] [tapefile] ",
1494 (void)fputs("[blocksize] [replstr] [-C directory] file1 file2...\n",
1501 * print the usage summary to the user
1512 (void)fputs("usage: cpio -o [-aABcLvVzZ] [-C bytes] [-H format] [-O archive]\n", stderr
);
1513 (void)fputs(" [-F archive] < name-list [> archive]\n", stderr
);
1514 (void)fputs(" cpio -i [-bBcdfmnrsStuvVzZ6] [-C bytes] [-E file] [-H format]\n", stderr
);
1515 (void)fputs(" [-I archive] [-F archive] [pattern...] [< archive]\n", stderr
);
1516 (void)fputs(" cpio -p [-adlLmuvV] destination-directory < name-list\n", stderr
);