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