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