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