1 /*	$OpenBSD: options.c,v 1.75 2012/03/04 04:05:15 fgsch Exp $	*/
2 /*	$NetBSD: options.c,v 1.6 1996/03/26 23:54:18 mrg Exp $	*/
3 
4 /*-
5  * Copyright (c) 2005, 2006, 2007, 2012, 2014
6  *	Thorsten Glaser <tg@mirbsd.org>
7  * Copyright (c) 1992 Keith Muller.
8  * Copyright (c) 1992, 1993
9  *	The Regents of the University of California.  All rights reserved.
10  *
11  * This code is derived from software contributed to Berkeley by
12  * Keith Muller of the University of California, San Diego.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  */
38 
39 #include <sys/param.h>
40 #include <sys/time.h>
41 #include <sys/stat.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <err.h>
45 #include <errno.h>
46 #include <fcntl.h>
47 #include <unistd.h>
48 #include <stdlib.h>
49 #include <limits.h>
50 #include <paths.h>
51 #include <time.h>
52 #include "pax.h"
53 #include "options.h"
54 #include "cpio.h"
55 #include "tar.h"
56 #include "ar.h"
57 #include "extern.h"
58 
59 #if HAS_TAPE
60 #include <sys/mtio.h>
61 #endif
62 
63 __RCSID("$MirOS: src/bin/pax/options.c,v 1.52 2014/07/03 19:36:25 tg Exp $");
64 
65 #ifndef _PATH_DEFTAPE
66 #define _PATH_DEFTAPE "/dev/rmt0"
67 #endif
68 
69 #ifdef __GLIBC__
70 char *fgetln(FILE *, size_t *);
71 #endif
72 
73 /*
74  * Routines which handle command line options
75  */
76 
77 static char flgch[] = FLGCH;	/* list of all possible flags */
78 static OPLIST *ophead = NULL;	/* head for format specific options -x */
79 static OPLIST *optail = NULL;	/* option tail */
80 
81 static int no_op(void);
82 static int no_op_i(int);
83 static void printflg(unsigned int);
84 static int c_frmt(const void *, const void *);
85 static off_t str_offt(char *);
86 static void pax_options(int, char **);
87 static void pax_usage(void) __attribute__((__noreturn__));
88 static void tar_set_action(int);
89 static void tar_options(int, char **);
90 static void tar_usage(void) __attribute__((__noreturn__));
91 static void cpio_set_action(int);
92 static void cpio_options(int, char **);
93 static void cpio_usage(void) __attribute__((__noreturn__));
94 int mkpath(char *);
95 
96 static void process_M(const char *, void (*)(void));
97 
98 /* command to run as gzip */
99 static const char GZIP_CMD[] = "gzip";
100 /* command to run as compress */
101 static const char COMPRESS_CMD[] = "compress";
102 /* command to run as bzip2 */
103 static const char BZIP2_CMD[] = "bzip2";
104 /* command to run as lzma and xz */
105 static const char XZ_CMD[] = "xz";
106 /* command used for creating lzma archives */
107 static const char LZMA_WRCMD[] = "lzma";
108 /* command to run as lzop */
109 static const char LZOP_CMD[] = "lzop";
110 /* used as flag value */
111 #define COMPRESS_GUESS_CMD ((const void *)&compress_program)
112 
113 /*
114  *	Format specific routine table - MUST BE IN SORTED ORDER BY NAME
115  *	(see pax.h for description of each function)
116  *
117  * 	name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
118  *	read, end_read, st_write, write, end_write, trail,
119  *	rd_data, wr_data, options, is_uar
120  */
121 
122 FSUB fsub[] = {
123 /* 0: UNIX ARCHIVER */
124 	{"ar", 512, sizeof(HD_AR), 0, 0, 0, 0, uar_id, no_op,
125 	uar_rd, uar_endrd, uar_stwr, uar_wr, no_op, uar_trail,
126 	rd_wrfile, uar_wr_data, bad_opt, 1},
127 
128 /* 1: OLD BINARY CPIO */
129 	{"bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
130 	bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, cpio_trail,
131 	rd_wrfile, wr_rdfile, bad_opt, 0},
132 
133 /* 2: OLD OCTAL CHARACTER CPIO */
134 	{"cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
135 	cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, cpio_trail,
136 	rd_wrfile, wr_rdfile, bad_opt, 0},
137 
138 /* 3: OLD OCTAL CHARACTER CPIO, UID/GID CLEARED (ANONYMISED) */
139 	{"dist", 512, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
140 	cpio_rd, cpio_endrd, dist_stwr, cpio_wr, cpio_endwr, cpio_trail,
141 	rd_wrfile, wr_rdfile, bad_opt, 0},
142 
143 /* 4: SVR4 HEX CPIO */
144 	{"sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd,
145 	vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, cpio_trail,
146 	rd_wrfile, wr_rdfile, bad_opt, 0},
147 
148 /* 5: SVR4 HEX CPIO WITH CRC */
149 	{"sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
150 	vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, cpio_trail,
151 	rd_wrfile, wr_rdfile, bad_opt, 0},
152 
153 /* 6: OLD TAR */
154 	{"tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
155 	tar_rd, tar_endrd, no_op_i, tar_wr, tar_endwr, tar_trail,
156 	rd_wrfile, wr_rdfile, tar_opt, 0},
157 
158 /* 7: POSIX USTAR */
159 	{"ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd,
160 	ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail,
161 	rd_wrfile, wr_rdfile, bad_opt, 0},
162 
163 /* 8: SVR4 HEX CPIO WITH CRC, UID/GID/MTIME CLEARED (NORMALISED) */
164 	{"v4norm", 512, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
165 	vcpio_rd, vcpio_endrd, v4norm_stwr, vcpio_wr, cpio_endwr, cpio_trail,
166 	rd_wrfile, wr_rdfile, bad_opt, 0},
167 
168 /* 9: SVR4 HEX CPIO WITH CRC, UID/GID CLEARED (ANONYMISED) */
169 	{"v4root", 512, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
170 	vcpio_rd, vcpio_endrd, v4root_stwr, vcpio_wr, cpio_endwr, cpio_trail,
171 	rd_wrfile, wr_rdfile, bad_opt, 0},
172 };
173 #define	F_OCPIO	1	/* format when called as cpio -6 */
174 #define	F_ACPIO	2	/* format when called as cpio -c */
175 #define	F_NCPIO	4	/* format when called as tar -R */
176 #define	F_CPIO	5	/* format when called as cpio or tar -S */
177 #define F_OTAR	6	/* format when called as tar -o */
178 #define F_TAR	7	/* format when called as tar */
179 int F_UAR = 0;
180 #define DEFLT	7	/* default write format from list above */
181 
182 /*
183  * ford is the archive search order used by get_arc() to determine what kind
184  * of archive we are dealing with. This helps to properly id archive formats
185  * some formats may be subsets of others....
186  */
187 int ford[] = { 7, 6, 5, 4, 2, 1, -1 };
188 
189 /* normalise archives */
190 int anonarch = 0;
191 
192 /* extract to standard output */
193 int to_stdout = 0;
194 
195 /*
196  * Do we have -C anywhere?
197  */
198 int havechd = 0;
199 
200 /*
201  * options()
202  *	figure out if we are pax, tar or cpio. Call the appropriate options
203  *	parser
204  */
205 
206 void
options(int argc,char ** argv)207 options(int argc, char **argv)
208 {
209 	size_t n;
210 
211 	/*
212 	 * are we acting like pax, tar or cpio (based on argv[0])
213 	 */
214 	if ((n = strlen(argv[0])) >= 3 && !strcmp(argv[0] + n - 3, NM_TAR)) {
215 		argv0 = NM_TAR;
216 		tar_options(argc, argv);
217 	} else if (n >= 4 && !strcmp(argv[0] + n - 4, NM_CPIO)) {
218 		argv0 = NM_CPIO;
219 		cpio_options(argc, argv);
220 	} else {
221 		argv0 = NM_PAX;
222 		pax_options(argc, argv);
223 	}
224 }
225 
226 /*
227  * pax_options()
228  *	look at the user specified flags. set globals as required and check if
229  *	the user specified a legal set of flags. If not, complain and exit
230  */
231 
232 static void
pax_options(int argc,char ** argv)233 pax_options(int argc, char **argv)
234 {
235 	int c;
236 	size_t i;
237 	unsigned int flg = 0;
238 	unsigned int bflg = 0;
239 	char *pt;
240 	FSUB tmp;
241 
242 	/*
243 	 * process option flags
244 	 */
245 	while ((c = getopt(argc, argv,
246 	    "0aB:b:cDdE:f:G:HiJjkLlM:nOo:Pp:rs:T:tU:uvwXx:YZz")) != -1) {
247 		switch (c) {
248 		case 'a':
249 			/*
250 			 * append
251 			 */
252 			flg |= AF;
253 			break;
254 		case 'b':
255 			/*
256 			 * specify blocksize
257 			 */
258 			flg |= BF;
259 			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
260 				paxwarn(1, "Invalid block size %s", optarg);
261 				pax_usage();
262 			}
263 			break;
264 		case 'c':
265 			/*
266 			 * inverse match on patterns
267 			 */
268 			cflag = 1;
269 			flg |= CF;
270 			break;
271 		case 'd':
272 			/*
273 			 * match only dir on extract, not the subtree at dir
274 			 */
275 			dflag = 1;
276 			flg |= DF;
277 			break;
278 		case 'f':
279 			/*
280 			 * filename where the archive is stored
281 			 */
282 			arcname = optarg;
283 			flg |= FF;
284 			break;
285 		case 'i':
286 			/*
287 			 * interactive file rename
288 			 */
289 			iflag = 1;
290 			flg |= IF;
291 			break;
292 		case 'J':
293 			/*
294 			 * use xz (non-standard option)
295 			 */
296 			compress_program = XZ_CMD;
297 			break;
298 		case 'j':
299 			/*
300 			 * use bzip2 (non-standard option)
301 			 */
302 			compress_program = BZIP2_CMD;
303 			break;
304 		case 'k':
305 			/*
306 			 * do not clobber files that exist
307 			 */
308 			kflag = 1;
309 			flg |= KF;
310 			break;
311 		case 'l':
312 			/*
313 			 * try to link src to dest with copy (-rw)
314 			 */
315 			lflag = 1;
316 			flg |= LF;
317 			break;
318 		case 'n':
319 			/*
320 			 * select first match for a pattern only
321 			 */
322 			nflag = 1;
323 			flg |= NF;
324 			break;
325 		case 'o':
326 			/*
327 			 * pass format specific options
328 			 */
329 			flg |= OF;
330 			if (opt_add(optarg) < 0)
331 				pax_usage();
332 			break;
333 		case 'p':
334 			/*
335 			 * specify file characteristic options
336 			 */
337 			for (pt = optarg; *pt != '\0'; ++pt) {
338 				switch (*pt) {
339 				case 'a':
340 					/*
341 					 * do not preserve access time
342 					 */
343 					patime = 0;
344 					break;
345 				case 'e':
346 					/*
347 					 * preserve user id, group id, file
348 					 * mode, access/modification times
349 					 */
350 					pids = 1;
351 					pmode = 1;
352 					patime = 1;
353 					pmtime = 1;
354 					break;
355 				case 'm':
356 					/*
357 					 * do not preserve modification time
358 					 */
359 					pmtime = 0;
360 					break;
361 				case 'o':
362 					/*
363 					 * preserve uid/gid
364 					 */
365 					pids = 1;
366 					break;
367 				case 'p':
368 					/*
369 					 * preserve file mode bits
370 					 */
371 					pmode = 1;
372 					break;
373 				default:
374 					paxwarn(1, "Invalid -p string: %c", *pt);
375 					pax_usage();
376 					break;
377 				}
378 			}
379 			flg |= PF;
380 			break;
381 		case 'r':
382 			/*
383 			 * read the archive
384 			 */
385 			flg |= RF;
386 			break;
387 		case 's':
388 			/*
389 			 * file name substitution name pattern
390 			 */
391 			if (rep_add(optarg) < 0) {
392 				pax_usage();
393 				break;
394 			}
395 			flg |= SF;
396 			break;
397 		case 't':
398 			/*
399 			 * preserve access time on filesystem nodes we read
400 			 */
401 			tflag = 1;
402 			flg |= TF;
403 			break;
404 		case 'u':
405 			/*
406 			 * ignore those older files
407 			 */
408 			uflag = 1;
409 			flg |= UF;
410 			break;
411 		case 'v':
412 			/*
413 			 * verbose operation mode
414 			 */
415 			vflag++;
416 			flg |= VF;
417 			break;
418 		case 'w':
419 			/*
420 			 * write an archive
421 			 */
422 			flg |= WF;
423 			break;
424 		case 'x':
425 			/*
426 			 * specify an archive format on write
427 			 */
428 			tmp.name = optarg;
429 			if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
430 			    sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) != NULL) {
431 				flg |= XF;
432 				break;
433 			}
434 			paxwarn(1, "Unknown -x format: %s", optarg);
435 			(void)fputs("pax: Known -x formats are:", stderr);
436 			for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
437 				(void)fprintf(stderr, " %s", fsub[i].name);
438 			(void)fputs("\n\n", stderr);
439 			pax_usage();
440 			break;
441 		case 'z':
442 			/*
443 			 * use gzip (non-standard option)
444 			 */
445 			compress_program = GZIP_CMD;
446 			break;
447 		case 'B':
448 			/*
449 			 * non-standard option on number of bytes written on a
450 			 * single archive volume.
451 			 */
452 			if ((wrlimit = str_offt(optarg)) <= 0) {
453 				paxwarn(1, "Invalid write limit %s", optarg);
454 				pax_usage();
455 			}
456 			if (wrlimit % BLKMULT) {
457 				paxwarn(1, "Write limit is not a %d byte multiple",
458 				    BLKMULT);
459 				pax_usage();
460 			}
461 			flg |= CBF;
462 			break;
463 		case 'D':
464 			/*
465 			 * on extraction check file inode change time before the
466 			 * modification of the file name (non-standard option)
467 			 */
468 			Dflag = 1;
469 			flg |= CDF;
470 			break;
471 		case 'E':
472 			/*
473 			 * non-standard limit on read faults
474 			 * 0 indicates stop after first error, values
475 			 * indicate a limit, "NONE" try forever
476 			 */
477 			flg |= CEF;
478 			if (strcmp(NONE, optarg) == 0)
479 				maxflt = -1;
480 			else if ((maxflt = atoi(optarg)) < 0) {
481 				paxwarn(1, "Error count value must be positive");
482 				pax_usage();
483 			}
484 			break;
485 		case 'G':
486 			/*
487 			 * non-standard option for selecting files within an
488 			 * archive by group (gid or name)
489 			 */
490 			if (grp_add(optarg) < 0) {
491 				pax_usage();
492 				break;
493 			}
494 			flg |= CGF;
495 			break;
496 		case 'H':
497 			/*
498 			 * follow command line symlinks only
499 			 */
500 			Hflag = 1;
501 			flg |= CHF;
502 			break;
503 		case 'L':
504 			/*
505 			 * follow symlinks
506 			 */
507 			Lflag = 1;
508 			flg |= CLF;
509 			break;
510 		case 'M':
511 			/*
512 			 * MirOS extension: archive normaliser
513 			 */
514 			process_M(optarg, pax_usage);
515 			break;
516 		case 'O':
517 			/*
518 			 * Force one volume.  Non standard option.
519 			 */
520 			force_one_volume = 1;
521 			break;
522 		case 'P':
523 			/*
524 			 * do NOT follow symlinks (default)
525 			 */
526 			Lflag = 0;
527 			flg |= CPF;
528 			break;
529 		case 'T':
530 			/*
531 			 * non-standard option for selecting files within an
532 			 * archive by modification time range (lower,upper)
533 			 */
534 			if (trng_add(optarg) < 0) {
535 				pax_usage();
536 				break;
537 			}
538 			flg |= CTF;
539 			break;
540 		case 'U':
541 			/*
542 			 * non-standard option for selecting files within an
543 			 * archive by user (uid or name)
544 			 */
545 			if (usr_add(optarg) < 0) {
546 				pax_usage();
547 				break;
548 			}
549 			flg |= CUF;
550 			break;
551 		case 'X':
552 			/*
553 			 * do not pass over mount points in the file system
554 			 */
555 			Xflag = 1;
556 			flg |= CXF;
557 			break;
558 		case 'Y':
559 			/*
560 			 * On extraction check file inode change time after the
561 			 * modification of the file name. Non standard option.
562 			 */
563 			Yflag = 1;
564 			flg |= CYF;
565 			break;
566 		case 'Z':
567 			/*
568 			 * On extraction check modification time after the
569 			 * modification of the file name. Non standard option.
570 			 */
571 			Zflag = 1;
572 			flg |= CZF;
573 			break;
574 		case '0':
575 			/*
576 			 * Use \0 as pathname terminator.
577 			 * (For use with the -print0 option of find(1).)
578 			 */
579 			zeroflag = 1;
580 			flg |= C0F;
581 			break;
582 		default:
583 			pax_usage();
584 			break;
585 		}
586 	}
587 
588 	/*
589 	 * figure out the operation mode of pax read,write,extract,copy,append
590 	 * or list. check that we have not been given a bogus set of flags
591 	 * for the operation mode.
592 	 */
593 	if (ISLIST(flg)) {
594 		act = LIST;
595 		listf = stdout;
596 		bflg = flg & BDLIST;
597 	} else if (ISEXTRACT(flg)) {
598 		act = EXTRACT;
599 		bflg = flg & BDEXTR;
600 	} else if (ISARCHIVE(flg)) {
601 		act = ARCHIVE;
602 		bflg = flg & BDARCH;
603 	} else if (ISAPPND(flg)) {
604 		act = APPND;
605 		bflg = flg & BDARCH;
606 	} else if (ISCOPY(flg)) {
607 		act = COPY;
608 		bflg = flg & BDCOPY;
609 	} else
610 		pax_usage();
611 	if (bflg) {
612 		printflg(flg);
613 		pax_usage();
614 	}
615 
616 	/*
617 	 * if we are writing (ARCHIVE) we use the default format if the user
618 	 * did not specify a format. when we write during an APPEND, we will
619 	 * adopt the format of the existing archive if none was supplied.
620 	 */
621 	if (!(flg & XF) && (act == ARCHIVE))
622 		frmt = &(fsub[DEFLT]);
623 
624 	/*
625 	 * process the args as they are interpreted by the operation mode
626 	 */
627 	switch (act) {
628 	case LIST:
629 	case EXTRACT:
630 		for (; optind < argc; optind++)
631 			if (pat_add(argv[optind], NULL) < 0)
632 				pax_usage();
633 		break;
634 	case COPY:
635 		if (optind >= argc) {
636 			paxwarn(0, "Destination directory was not supplied");
637 			pax_usage();
638 		}
639 		--argc;
640 		dirptr = argv[argc];
641 		/* FALLTHROUGH */
642 	case ARCHIVE:
643 	case APPND:
644 		for (; optind < argc; optind++)
645 			if (ftree_add(argv[optind], 0) < 0)
646 				pax_usage();
647 		/*
648 		 * no read errors allowed on updates/append operation!
649 		 */
650 		maxflt = 0;
651 		break;
652 	}
653 }
654 
655 
656 /*
657  * tar_options()
658  *	look at the user specified flags. set globals as required and check if
659  *	the user specified a legal set of flags. If not, complain and exit
660  */
661 
662 static void
tar_set_action(int op)663 tar_set_action(int op)
664 {
665 	if (act != ERROR && act != op)
666 		tar_usage();
667 	act = op;
668 }
669 
670 static void
tar_options(int argc,char ** argv)671 tar_options(int argc, char **argv)
672 {
673 	int c;
674 	int fstdin = 0;
675 	int Oflag = 0;
676 	int nincfiles = 0;
677 	int incfiles_max = 0;
678 	struct incfile {
679 		char *file;
680 		char *dir;
681 	};
682 	struct incfile *incfiles = NULL;
683 
684 	/*
685 	 * set default values
686 	 */
687 	rmleadslash = 1;
688 
689 	/*
690 	 * process option flags
691 	 */
692 	while ((c = getoldopt(argc, argv,
693 	    "014578AaBb:C:cef:HhI:JjLM:mNOoPpqRrSs:tuvwXxZz")) != -1) {
694 		switch (c) {
695 		case 'A':
696 			Oflag = 5;
697 			break;
698 		case 'a':
699 			/*
700 			 * use compression dependent on arcname
701 			 * (non-standard option, gtar extension)
702 			 */
703 			compress_program = COMPRESS_GUESS_CMD;
704 			break;
705 		case 'b':
706 			/*
707 			 * specify blocksize in 512-byte blocks
708 			 */
709 			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
710 				paxwarn(1, "Invalid block size %s", optarg);
711 				tar_usage();
712 			}
713 			/* XXX - check for integer overflow */
714 			wrblksz *= 512;
715 			break;
716 		case 'c':
717 			/*
718 			 * create an archive
719 			 */
720 			tar_set_action(ARCHIVE);
721 			break;
722 		case 'e':
723 			/*
724 			 * stop after first error
725 			 */
726 			maxflt = 0;
727 			break;
728 		case 'f':
729 			/*
730 			 * filename where the archive is stored
731 			 */
732 			if ((optarg[0] == '-') && (optarg[1]== '\0')) {
733 				/*
734 				 * treat a - as stdin
735 				 */
736 				fstdin = 1;
737 				arcname = NULL;
738 				break;
739 			}
740 			fstdin = 0;
741 			arcname = optarg;
742 			break;
743 		case 'h':
744 			/*
745 			 * follow symlinks
746 			 */
747 			Lflag = 1;
748 			break;
749 		case 'J':
750 			/*
751 			 * use xz (non-standard option)
752 			 */
753 			compress_program = XZ_CMD;
754 			break;
755 		case 'j':
756 			/*
757 			 * use bzip2 (non-standard option)
758 			 */
759 			compress_program = BZIP2_CMD;
760 			break;
761 		case 'm':
762 			/*
763 			 * do not preserve modification time
764 			 */
765 			pmtime = 0;
766 			break;
767 		case 'O':
768 			Oflag = 1;
769 			to_stdout = 2;
770 			break;
771 		case 'o':
772 			Oflag = 2;
773 			break;
774 		case 'p':
775 			/*
776 			 * preserve uid/gid and file mode, regardless of umask
777 			 */
778 			pmode = 1;
779 			pids = 1;
780 			break;
781 		case 'q':
782 			/*
783 			 * select first match for a pattern only
784 			 */
785 			nflag = 1;
786 			break;
787 		case 'r':
788 		case 'u':
789 			/*
790 			 * append to the archive
791 			 */
792 			tar_set_action(APPND);
793 			break;
794 		case 'R':
795 			Oflag = 3;
796 			anonarch |= ANON_INODES | ANON_HARDLINKS;
797 			break;
798 		case 'S':
799 			Oflag = 4;
800 			anonarch |= ANON_INODES | ANON_HARDLINKS;
801 			break;
802 		case 's':
803 			/*
804 			 * file name substitution name pattern
805 			 */
806 			if (rep_add(optarg) < 0) {
807 				tar_usage();
808 				break;
809 			}
810 			break;
811 		case 't':
812 			/*
813 			 * list contents of the tape
814 			 */
815 			tar_set_action(LIST);
816 			break;
817 		case 'v':
818 			/*
819 			 * verbose operation mode
820 			 */
821 			vflag++;
822 			break;
823 		case 'w':
824 			/*
825 			 * interactive file rename
826 			 */
827 			iflag = 1;
828 			break;
829 		case 'x':
830 			/*
831 			 * extract an archive, preserving mode,
832 			 * and mtime if possible.
833 			 */
834 			tar_set_action(EXTRACT);
835 			pmtime = 1;
836 			break;
837 		case 'z':
838 			/*
839 			 * use gzip (non-standard option)
840 			 */
841 			compress_program = GZIP_CMD;
842 			break;
843 		case 'B':
844 			/*
845 			 * nothing to do here, this is pax default
846 			 */
847 			break;
848 		case 'C':
849 			havechd++;
850 			chdname = optarg;
851 			break;
852 		case 'H':
853 			/*
854 			 * follow command line symlinks only
855 			 */
856 			Hflag = 1;
857 			break;
858 		case 'I':
859 			if (++nincfiles > incfiles_max) {
860 				size_t n = nincfiles + 3;
861 				struct incfile *p;
862 
863 				p = realloc(incfiles,
864 				    sizeof(*incfiles) * n);
865 				if (p == NULL) {
866 					free(incfiles);
867 					incfiles = NULL;
868 					paxwarn(0, "Unable to allocate space "
869 					    "for option list");
870 					exit(1);
871 				}
872 				incfiles = p;
873 				incfiles_max = n;
874 			}
875 			incfiles[nincfiles - 1].file = optarg;
876 			incfiles[nincfiles - 1].dir = chdname;
877 			break;
878 		case 'L':
879 			/*
880 			 * follow symlinks
881 			 */
882 			Lflag = 1;
883 			break;
884 		case 'M':
885 			/*
886 			 * MirOS extension: archive normaliser
887 			 */
888 			process_M(optarg, tar_usage);
889 			break;
890 		case 'N':
891 			/*
892 			 * numeric uid and gid only
893 			 */
894 			anonarch |= ANON_NUMID;
895 			break;
896 		case 'P':
897 			/*
898 			 * do not remove leading '/' from pathnames
899 			 */
900 			rmleadslash = 0;
901 			break;
902 		case 'X':
903 			/*
904 			 * do not pass over mount points in the file system
905 			 */
906 			Xflag = 1;
907 			break;
908 		case 'Z':
909 			/*
910 			 * use compress
911 			 */
912 			compress_program = COMPRESS_CMD;
913 			break;
914 		case '0':
915 			arcname = DEV_0;
916 			break;
917 		case '1':
918 			arcname = DEV_1;
919 			break;
920 		case '4':
921 			arcname = DEV_4;
922 			break;
923 		case '5':
924 			arcname = DEV_5;
925 			break;
926 		case '7':
927 			arcname = DEV_7;
928 			break;
929 		case '8':
930 			arcname = DEV_8;
931 			break;
932 		default:
933 			tar_usage();
934 			break;
935 		}
936 	}
937 	argc -= optind;
938 	argv += optind;
939 
940 	/* tar requires an action. */
941 	if (act == ERROR)
942 		tar_usage();
943 
944 	/* traditional tar behaviour (pax uses stderr unless in list mode) */
945 	if (fstdin == 1 && act == ARCHIVE)
946 		listf = stderr;
947 	else
948 		listf = stdout;
949 
950 	/* traditional tar behaviour (pax wants to read file list from stdin) */
951 	if ((act == ARCHIVE || act == APPND) && argc == 0 && nincfiles == 0)
952 		exit(0);
953 
954 	/*
955 	 * process the args as they are interpreted by the operation mode
956 	 */
957 	switch (act) {
958 	case EXTRACT:
959 		if (to_stdout == 2)
960 			to_stdout = 1;
961 	case LIST:
962 	default:
963 		{
964 			int sawpat = 0;
965 			char *file, *dir = NULL;
966 
967 			while (nincfiles || *argv != NULL) {
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)
982 						break;
983 					file = *argv++;
984 					dir = chdname;
985 				} else
986 					file = NULL;
987 				if (file != NULL) {
988 					int fd;
989 					char *str;
990 
991 					if (strcmp(file, "-") == 0)
992 						fd = STDIN_FILENO;
993 					else if ((fd = open(file, O_RDONLY)) == -1) {
994 						paxwarn(1, "Unable to open file '%s' for read", file);
995 						tar_usage();
996 					}
997 					while ((str = fdgetline(fd)) != NULL) {
998 						if (pat_add(str, dir) < 0)
999 							tar_usage();
1000 						sawpat = 1;
1001 					}
1002 					if (fd != STDIN_FILENO)
1003 						close(fd);
1004 					if (fdgetline_err) {
1005 						paxwarn(1, "Problem with file '%s'",
1006 						    file);
1007 						tar_usage();
1008 					}
1009 				} else if (strcmp(*argv, "-C") == 0) {
1010 					if (*++argv == NULL)
1011 						break;
1012 					chdname = *argv++;
1013 					havechd++;
1014 				} else if (pat_add(*argv++, chdname) < 0)
1015 					tar_usage();
1016 				else
1017 					sawpat = 1;
1018 			}
1019 			/*
1020 			 * if patterns were added, we are doing	chdir()
1021 			 * on a file-by-file basis, else, just one
1022 			 * global chdir (if any) after opening input.
1023 			 */
1024 			if (sawpat > 0)
1025 				chdname = NULL;
1026 		}
1027 		break;
1028 	case ARCHIVE:
1029 	case APPND:
1030 		switch(Oflag) {
1031 		    case 0:
1032 			frmt = &(fsub[F_TAR]);
1033 			break;
1034 		    case 1:
1035 			frmt = &(fsub[F_OTAR]);
1036 			break;
1037 		    case 2:
1038 			frmt = &(fsub[F_OTAR]);
1039 			if (opt_add("write_opt=nodir") < 0)
1040 				tar_usage();
1041 			break;
1042 		    case 3:
1043 			frmt = &(fsub[F_NCPIO]);
1044 			break;
1045 		    case 4:
1046 			frmt = &(fsub[F_CPIO]);
1047 			break;
1048 		    case 5:
1049 			frmt = &(fsub[F_UAR]);
1050 			break;
1051 		    default:
1052 			tar_usage();
1053 			break;
1054 		}
1055 
1056 		if (chdname != NULL) {
1057 			/* initial chdir() */
1058 			if (ftree_add(chdname, 1) < 0)
1059 				tar_usage();
1060 		}
1061 
1062 		while (nincfiles || *argv != NULL) {
1063 			char *file, *dir = NULL;
1064 
1065 			/*
1066 			 * If we queued up any include files, pull them in
1067 			 * now.  Otherwise, check for -I and -C positional
1068 			 * flags.  Anything else must be a file to include
1069 			 * in the archive.
1070 			 */
1071 			if (nincfiles) {
1072 				file = incfiles->file;
1073 				dir = incfiles->dir;
1074 				incfiles++;
1075 				nincfiles--;
1076 			} else if (strcmp(*argv, "-I") == 0) {
1077 				if (*++argv == NULL)
1078 					break;
1079 				file = *argv++;
1080 				dir = NULL;
1081 			} else
1082 				file = NULL;
1083 			if (file != NULL) {
1084 				char *str;
1085 				int fd;
1086 
1087 				/* set directory if needed */
1088 				if (dir) {
1089 					if (ftree_add(dir, 1) < 0)
1090 						tar_usage();
1091 				}
1092 
1093 				if (strcmp(file, "-") == 0)
1094 					fd = STDIN_FILENO;
1095 				else if ((fd = open(file, O_RDONLY)) == -1) {
1096 					paxwarn(1, "Unable to open file '%s' for read", file);
1097 					tar_usage();
1098 				}
1099 				while ((str = fdgetline(fd)) != NULL) {
1100 					if (ftree_add(str, 0) < 0)
1101 						tar_usage();
1102 				}
1103 				if (fd != STDIN_FILENO)
1104 					close(fd);
1105 				if (fdgetline_err) {
1106 					paxwarn(1, "Problem with file '%s'",
1107 					    file);
1108 					tar_usage();
1109 				}
1110 			} else if (strcmp(*argv, "-C") == 0) {
1111 				if (*++argv == NULL)
1112 					break;
1113 				if (ftree_add(*argv++, 1) < 0)
1114 					tar_usage();
1115 				havechd++;
1116 			} else if (ftree_add(*argv++, 0) < 0)
1117 				tar_usage();
1118 		}
1119 		/*
1120 		 * no read errors allowed on updates/append operation!
1121 		 */
1122 		maxflt = 0;
1123 		break;
1124 	}
1125 	if (to_stdout != 1)
1126 		to_stdout = 0;
1127 	if (!fstdin && ((arcname == NULL) || (*arcname == '\0'))) {
1128 		arcname = getenv("TAPE");
1129 		if ((arcname == NULL) || (*arcname == '\0'))
1130 			arcname = _PATH_DEFTAPE;
1131 	}
1132 }
1133 
1134 int
mkpath(char * path)1135 mkpath(char *path)
1136 {
1137 	struct stat sb;
1138 	char *slash;
1139 	int done = 0;
1140 
1141 	slash = path;
1142 
1143 	while (!done) {
1144 		slash += strspn(slash, "/");
1145 		slash += strcspn(slash, "/");
1146 
1147 		done = (*slash == '\0');
1148 		*slash = '\0';
1149 
1150 		if (stat(path, &sb)) {
1151 			if (errno != ENOENT || mkdir(path, 0777)) {
1152 				paxwarn(1, "%s", path);
1153 				return (-1);
1154 			}
1155 		} else if (!S_ISDIR(sb.st_mode)) {
1156 			syswarn(1, ENOTDIR, "%s", path);
1157 			return (-1);
1158 		}
1159 
1160 		if (!done)
1161 			*slash = '/';
1162 	}
1163 
1164 	return (0);
1165 }
1166 
1167 static void
cpio_set_action(int op)1168 cpio_set_action(int op)
1169 {
1170 	if ((act == APPND && op == ARCHIVE) || (act == ARCHIVE && op == APPND))
1171 		act = APPND;
1172 	else if ((act == LIST && op == EXTRACT) || (act == EXTRACT && op == LIST))
1173 		act = LIST;
1174 	else if (act != ERROR && act != op)
1175 		cpio_usage();
1176 	else
1177 		act = op;
1178 }
1179 
1180 /*
1181  * cpio_options()
1182  *	look at the user specified flags. set globals as required and check if
1183  *	the user specified a legal set of flags. If not, complain and exit
1184  */
1185 
1186 static void
cpio_options(int argc,char ** argv)1187 cpio_options(int argc, char **argv)
1188 {
1189 	int c;
1190 	size_t i;
1191 	char *str;
1192 	FSUB tmp;
1193 	int fd;
1194 	const char *optstr;
1195 
1196 	kflag = 1;
1197 	pids = 1;
1198 	pmode = 1;
1199 	pmtime = 0;
1200 	arcname = NULL;
1201 	dflag = 1;
1202 	nodirs = 1;
1203 	optstr = "iop";
1204 	opterr = 0;
1205 	while ((c = getopt(argc, argv, optstr)) != -1) {
1206 		switch (c) {
1207 		case 'a':
1208 			/*
1209 			 * preserve access time on files read
1210 			 */
1211 			tflag = 1;
1212 			break;
1213 		case 'b':
1214 			/*
1215 			 * swap bytes and half-words when reading data
1216 			 */
1217 			break;
1218 		case 'c':
1219 			/*
1220 			 * ASCII cpio header
1221 			 */
1222 			frmt = &(fsub[F_ACPIO]);
1223 			break;
1224 		case 'd':
1225 			/*
1226 			 * create directories as needed
1227 			 */
1228 			nodirs = 0;
1229 			break;
1230 		case 'f':
1231 			/*
1232 			 * invert meaning of pattern list
1233 			 */
1234 			cflag = 1;
1235 			break;
1236 		case 'i':
1237 			/*
1238 			 * restore an archive
1239 			 */
1240 			cpio_set_action(EXTRACT);
1241 			break;
1242 		case 'J':
1243 			/*
1244 			 * use xz (non-standard option)
1245 			 */
1246 			compress_program = XZ_CMD;
1247 			break;
1248 		case 'j':
1249 			/*
1250 			 * use bzip2 (non-standard option)
1251 			 */
1252 			compress_program = BZIP2_CMD;
1253 			break;
1254 		case 'k':
1255 			break;
1256 		case 'l':
1257 			/*
1258 			 * use links instead of copies when possible
1259 			 */
1260 			lflag = 1;
1261 			break;
1262 		case 'm':
1263 			/*
1264 			 * preserve modification time
1265 			 */
1266 			pmtime = 1;
1267 			break;
1268 		case 'o':
1269 			/*
1270 			 * create an archive
1271 			 */
1272 			cpio_set_action(ARCHIVE);
1273 			frmt = &(fsub[F_CPIO]);
1274 			break;
1275 		case 'p':
1276 			/*
1277 			 * copy-pass mode
1278 			 */
1279 			cpio_set_action(COPY);
1280 			break;
1281 		case 'r':
1282 			/*
1283 			 * interactively rename files
1284 			 */
1285 			iflag = 1;
1286 			break;
1287 		case 's':
1288 			/*
1289 			 * swap bytes after reading data
1290 			 */
1291 			break;
1292 		case 't':
1293 			/*
1294 			 * list contents of archive
1295 			 */
1296 			cpio_set_action(LIST);
1297 			listf = stdout;
1298 			break;
1299 		case 'u':
1300 			/*
1301 			 * replace newer files
1302 			 */
1303 			kflag = 0;
1304 			break;
1305 		case 'V':
1306 			/*
1307 			 * print a dot for each file processed
1308 			 */
1309 			Vflag++;
1310 			break;
1311 		case 'v':
1312 			/*
1313 			 * verbose operation mode
1314 			 */
1315 			vflag++;
1316 			break;
1317 		case 'z':
1318 			/*
1319 			 * use gzip (non-standard option)
1320 			 */
1321 			compress_program = GZIP_CMD;
1322 			break;
1323 		case 'A':
1324 			/*
1325 			 * append mode
1326 			 */
1327 			cpio_set_action(APPND);
1328 			break;
1329 		case 'B':
1330 			/*
1331 			 * use 5120 byte block size
1332 			 */
1333 			wrblksz = 5120;
1334 			break;
1335 		case 'C':
1336 			/*
1337 			 * set block size in bytes
1338 			 */
1339 			wrblksz = atoi(optarg);
1340 			break;
1341 		case 'E':
1342 			/*
1343 			 * file with patterns to extract or list
1344 			 */
1345 			if ((fd = open(optarg, O_RDONLY)) == -1) {
1346 				paxwarn(1, "Unable to open file '%s' for read", optarg);
1347 				cpio_usage();
1348 			}
1349 			while ((str = fdgetline(fd)) != NULL) {
1350 				pat_add(str, NULL);
1351 			}
1352 			close(fd);
1353 			if (fdgetline_err) {
1354 				paxwarn(1, "Problem with file '%s'", optarg);
1355 				cpio_usage();
1356 			}
1357 			break;
1358 		case 'F':
1359 		case 'I':
1360 		case 'O':
1361 			/*
1362 			 * filename where the archive is stored
1363 			 */
1364 			if ((optarg[0] == '-') && (optarg[1]== '\0')) {
1365 				/*
1366 				 * treat a - as stdin
1367 				 */
1368 				arcname = NULL;
1369 				break;
1370 			}
1371 			arcname = optarg;
1372 			break;
1373 		case 'H':
1374 			/*
1375 			 * specify an archive format on write
1376 			 */
1377 			if (!strcmp(optarg, "bin")) {
1378 				tmp.name = "bcpio";
1379 			} else if (!strcmp(optarg, "crc")) {
1380 				tmp.name = "sv4crc";
1381 			} else if (!strcmp(optarg, "newc")) {
1382 				tmp.name = "sv4cpio";
1383 			} else if (!strcmp(optarg, "odc")) {
1384 				tmp.name = "cpio";
1385 			} else {
1386 				tmp.name = optarg;
1387 			}
1388 			if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
1389 			    sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) != NULL)
1390 				break;
1391 			paxwarn(1, "Unknown -H format: %s", optarg);
1392 			(void)fputs("cpio: Known -H formats are:", stderr);
1393 			for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
1394 				(void)fprintf(stderr, " %s", fsub[i].name);
1395 			(void)fputs("\n\n", stderr);
1396 			cpio_usage();
1397 			break;
1398 		case 'L':
1399 			/*
1400 			 * follow symbolic links
1401 			 */
1402 			Lflag = 1;
1403 			break;
1404 		case 'M':
1405 			/*
1406 			 * MirOS extension: archive normaliser
1407 			 */
1408 			process_M(optarg, cpio_usage);
1409 			break;
1410 		case 'S':
1411 			/*
1412 			 * swap halfwords after reading data
1413 			 */
1414 			break;
1415 		case 'Z':
1416 			/*
1417 			 * use compress (non-standard option)
1418 			 */
1419 			compress_program = COMPRESS_CMD;
1420 			break;
1421 		case '0':
1422 			/*
1423 			 * Use \0 as pathname terminator.
1424 			 * (For use with the -print0 option of find(1).)
1425 			 */
1426 			zeroflag = 1;
1427 			break;
1428 		case '6':
1429 			/*
1430 			 * process Version 6 cpio format
1431 			 */
1432 			frmt = &(fsub[F_OCPIO]);
1433 			break;
1434 		case '?':
1435 		default:
1436 			if (opterr == 0) {
1437 				paxwarn(1, "need -i or -o or -p option first");
1438 			}
1439 			cpio_usage();
1440 			break;
1441 		}
1442 		if (opterr == 0) {
1443 			optstr = "06AaBbC:cdE:F:fH:I:iJjkLlM:mO:oprSstuVvZz";
1444 			opterr = 1;
1445 		}
1446 	}
1447 	argc -= optind;
1448 	argv += optind;
1449 
1450 	/*
1451 	 * process the args as they are interpreted by the operation mode
1452 	 */
1453 	switch (act) {
1454 	case LIST:
1455 	case EXTRACT:
1456 		while (*argv != NULL)
1457 			if (pat_add(*argv++, NULL) < 0)
1458 				cpio_usage();
1459 		break;
1460 	case COPY:
1461 		if (*argv == NULL) {
1462 			paxwarn(0, "Destination directory was not supplied");
1463 			cpio_usage();
1464 		}
1465 		dirptr = *argv;
1466 		if (mkpath(dirptr) < 0)
1467 			cpio_usage();
1468 		--argc;
1469 		++argv;
1470 		/* FALLTHROUGH */
1471 	case ARCHIVE:
1472 	case APPND:
1473 		if (*argv != NULL)
1474 			cpio_usage();
1475 		/*
1476 		 * no read errors allowed on updates/append operation!
1477 		 */
1478 		maxflt = 0;
1479 		while ((str = fdgetline(STDIN_FILENO)) != NULL) {
1480 			ftree_add(str, 0);
1481 		}
1482 		if (fdgetline_err) {
1483 			paxwarn(1, "Problem while reading stdin");
1484 			cpio_usage();
1485 		}
1486 		break;
1487 	default:
1488 		cpio_usage();
1489 		break;
1490 	}
1491 }
1492 
1493 /*
1494  * printflg()
1495  *	print out those invalid flag sets found to the user
1496  */
1497 
1498 static void
printflg(unsigned int flg)1499 printflg(unsigned int flg)
1500 {
1501 	int nxt;
1502 	int pos = 0;
1503 
1504 	(void)fprintf(stderr,"%s: Invalid combination of options:", argv0);
1505 	while ((nxt = ffs(flg)) != 0) {
1506 		flg = flg >> nxt;
1507 		pos += nxt;
1508 		(void)fprintf(stderr, " -%c", flgch[pos-1]);
1509 	}
1510 	(void)putc('\n', stderr);
1511 }
1512 
1513 /*
1514  * c_frmt()
1515  *	comparison routine used by bsearch to find the format specified
1516  *	by the user
1517  */
1518 
1519 static int
c_frmt(const void * a,const void * b)1520 c_frmt(const void *a, const void *b)
1521 {
1522 	return(strcmp(((const FSUB *)a)->name, ((const FSUB *)b)->name));
1523 }
1524 
1525 /*
1526  * opt_next()
1527  *	called by format specific options routines to get each format specific
1528  *	flag and value specified with -o
1529  * Return:
1530  *	pointer to next OPLIST entry or NULL (end of list).
1531  */
1532 
1533 OPLIST *
opt_next(void)1534 opt_next(void)
1535 {
1536 	OPLIST *opt;
1537 
1538 	if ((opt = ophead) != NULL)
1539 		ophead = ophead->fow;
1540 	return(opt);
1541 }
1542 
1543 /*
1544  * bad_opt()
1545  *	generic routine used to complain about a format specific options
1546  *	when the format does not support options.
1547  */
1548 
1549 int
bad_opt(void)1550 bad_opt(void)
1551 {
1552 	OPLIST *opt;
1553 
1554 	if (ophead == NULL)
1555 		return(0);
1556 	/*
1557 	 * print all we were given
1558 	 */
1559 	paxwarn(1,"These format options are not supported");
1560 	while ((opt = opt_next()) != NULL)
1561 		(void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
1562 	pax_usage();
1563 	return(0);
1564 }
1565 
1566 /*
1567  * opt_add()
1568  *	breaks the value supplied to -o into a option name and value. options
1569  *	are given to -o in the form -o name-value,name=value
1570  *	multiple -o may be specified.
1571  * Return:
1572  *	0 if format in name=value format, -1 if -o is passed junk
1573  */
1574 
1575 int
opt_add(const char * str)1576 opt_add(const char *str)
1577 {
1578 	OPLIST *opt;
1579 	char *frpt;
1580 	char *pt;
1581 	char *endpt;
1582 	char *dstr;
1583 
1584 	if ((str == NULL) || (*str == '\0')) {
1585 		paxwarn(0, "Invalid option name");
1586 		return(-1);
1587 	}
1588 	if ((dstr = strdup(str)) == NULL) {
1589 		paxwarn(0, "Unable to allocate space for option list");
1590 		return(-1);
1591 	}
1592 	frpt = endpt = dstr;
1593 
1594 	/*
1595 	 * break into name and values pieces and stuff each one into a
1596 	 * OPLIST structure. When we know the format, the format specific
1597 	 * option function will go through this list
1598 	 */
1599 	while ((frpt != NULL) && (*frpt != '\0')) {
1600 		if ((endpt = strchr(frpt, ',')) != NULL)
1601 			*endpt = '\0';
1602 		if ((pt = strchr(frpt, '=')) == NULL) {
1603 			paxwarn(0, "Invalid options format");
1604 			free(dstr);
1605 			return(-1);
1606 		}
1607 		if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
1608 			paxwarn(0, "Unable to allocate space for option list");
1609 			free(dstr);
1610 			return(-1);
1611 		}
1612 		/* parts of string going onto the OPLIST */
1613 		dstr = NULL;
1614 		*pt++ = '\0';
1615 		opt->name = frpt;
1616 		opt->value = pt;
1617 		opt->fow = NULL;
1618 		if (endpt != NULL)
1619 			frpt = endpt + 1;
1620 		else
1621 			frpt = NULL;
1622 		if (ophead == NULL) {
1623 			optail = ophead = opt;
1624 			continue;
1625 		}
1626 		optail->fow = opt;
1627 		optail = opt;
1628 	}
1629 	free(dstr);
1630 	return(0);
1631 }
1632 
1633 /*
1634  * str_offt()
1635  *	Convert an expression of the following forms to an off_t > 0.
1636  * 	1) A positive decimal number.
1637  *	2) A positive decimal number followed by a b (mult by 512).
1638  *	3) A positive decimal number followed by a k (mult by 1024).
1639  *	4) A positive decimal number followed by a m (mult by 512).
1640  *	5) A positive decimal number followed by a w (mult by sizeof int)
1641  *	6) Two or more positive decimal numbers (with/without k,b or w).
1642  *	   separated by x (also * for backwards compatibility), specifying
1643  *	   the product of the indicated values.
1644  * Return:
1645  *	0 for an error, a positive value o.w.
1646  */
1647 
1648 #ifndef LONG_OFF_T
1649 #define OT_MAX	ULLONG_MAX
1650 #define strtoot	strtoull
1651 #else
1652 #define OT_MAX	ULONG_MAX
1653 #define strtoot	strtoul
1654 #endif
1655 
1656 static off_t
str_offt(char * val)1657 str_offt(char *val)
1658 {
1659 	char *expr;
1660 	ot_type num, t;
1661 
1662 	num = strtoot(val, &expr, 0);
1663 	if ((num == OT_MAX) || (num <= 0) || (expr == val))
1664 		return (0);
1665 
1666 	switch (*expr) {
1667 	case 'b':
1668 		t = num;
1669 		num *= 512;
1670 		if (t > num)
1671 			return (0);
1672 		++expr;
1673 		break;
1674 	case 'k':
1675 		t = num;
1676 		num *= 1024;
1677 		if (t > num)
1678 			return (0);
1679 		++expr;
1680 		break;
1681 	case 'm':
1682 		t = num;
1683 		num *= 1048576;
1684 		if (t > num)
1685 			return (0);
1686 		++expr;
1687 		break;
1688 	case 'w':
1689 		t = num;
1690 		num *= sizeof(int);
1691 		if (t > num)
1692 			return (0);
1693 		++expr;
1694 		break;
1695 	}
1696 
1697 	switch (*expr) {
1698 	case '\0':
1699 		break;
1700 	case '*':
1701 	case 'x':
1702 		t = num;
1703 		num *= str_offt(expr + 1);
1704 		if (t > num)
1705 			return (0);
1706 		break;
1707 	default:
1708 		return (0);
1709 	}
1710 	return ((off_t)num);
1711 }
1712 
1713 /*
1714  * no_op()
1715  *	for those option functions where the archive format has nothing to do.
1716  * Return:
1717  *	0
1718  */
1719 
1720 static int
no_op(void)1721 no_op(void)
1722 {
1723 	return(0);
1724 }
1725 
1726 static int
no_op_i(int is_app)1727 no_op_i(int is_app __attribute__((__unused__)))
1728 {
1729 	return(0);
1730 }
1731 
1732 /*
1733  * pax_usage()
1734  *	print the usage summary to the user
1735  */
1736 
1737 void
pax_usage(void)1738 pax_usage(void)
1739 {
1740 	(void)fputs(
1741 	    "usage: pax [-0cdJjnOvz] [-E limit] [-f archive] [-G group] [-s replstr]\n"
1742 	    "           [-T range] [-U user] [pattern ...]\n"
1743 	    "       pax -r [-0cDdiJjknOuvYZz] [-E limit] [-f archive] [-G group] [-M flag]\n"
1744 	    "           [-o options] [-p string] [-s replstr] [-T range] [-U user]\n"
1745 	    "           [pattern ...]\n"
1746 	    "       pax -w [-0adHiJjLOPtuvXz] [-B bytes] [-b blocksize] [-f archive]\n"
1747 	    "           [-G group] [-M flag] [-o options] [-s replstr] [-T range]\n"
1748 	    "           [-U user] [-x format] [file ...]\n"
1749 	    "       pax -rw [-0DdHikLlnOPtuvXYZ] [-G group] [-p string] [-s replstr]\n"
1750 	    "           [-T range] [-U user] [file ...] directory\n",
1751 	    stderr);
1752 	exit(1);
1753 }
1754 
1755 /*
1756  * tar_usage()
1757  *	print the usage summary to the user
1758  */
1759 
1760 void
tar_usage(void)1761 tar_usage(void)
1762 {
1763 	(void)fputs(
1764 	    "usage: tar {crtux}[014578AabefHhJjLmNOoPpqRSsvwXZz]\n"
1765 	    "           [blocking-factor | archive | replstr] [-C directory] [-I file]\n"
1766 	    "           [file ...]\n"
1767 	    "       tar {-crtux} [-014578AaeHhJjLmNOoPpqRSvwXZz] [-b blocking-factor]\n"
1768 	    "           [-C directory] [-f archive] [-I file] [-M flag] [-s replstr]\n"
1769 	    "           [file ...]\n",
1770 	    stderr);
1771 	exit(1);
1772 }
1773 
1774 /*
1775  * cpio_usage()
1776  *	print the usage summary to the user
1777  */
1778 
1779 void
cpio_usage(void)1780 cpio_usage(void)
1781 {
1782 	(void)fputs(
1783 	    "usage: cpio -o [-0AaBcJjLVvZz] [-C bytes] [-F archive] [-H format]\n"
1784 	    "               [-M flag] [-O archive] <name-list [>archive]\n"
1785 	    "       cpio -i [-06BbcdfJjmrSstuVvZz] [-C bytes] [-E file] [-F archive]\n"
1786 	    "               [-H format] [-I archive] [-M flag] [pattern ...] [<archive]\n"
1787 	    "       cpio -p [-0adLlmuVv] destination-directory <name-list\n",
1788 	    stderr);
1789 	exit(1);
1790 }
1791 
1792 void
anonarch_init(void)1793 anonarch_init(void)
1794 {
1795 	if (anonarch & ANON_VERBOSE) {
1796 		anonarch &= ~ANON_VERBOSE;
1797 		paxwarn(0, "debug: -M 0x%08X -x %s", anonarch, frmt->name);
1798 	}
1799 }
1800 
1801 static void
process_M(const char * arg,void (* call_usage)(void))1802 process_M(const char *arg, void (*call_usage)(void))
1803 {
1804 	int j, k = 0;
1805 
1806 	if ((arg[0] >= '0') && (arg[0] <= '9')) {
1807 #ifdef __OpenBSD__
1808 		const char *s;
1809 		int64_t i = strtonum(arg, 0,
1810 		    ANON_MAXVAL, &s);
1811 		if (s)
1812 			errx(1, "%s M value: %s", s,
1813 			    arg);
1814 #else
1815 		char *ep;
1816 		long long i = strtoll(arg, &ep, 0);
1817 		if ((ep == arg) || (*ep != '\0') ||
1818 		    (i < 0) || (i > ANON_MAXVAL))
1819 			errx(1, "impossible M value:"
1820 			    " %s", arg);
1821 #endif
1822 		anonarch = i;
1823 		return;
1824 	}
1825 
1826 	if (!strncmp(arg, "no-", 3)) {
1827 		j = 0;
1828 		arg += 3;
1829 	} else
1830 		j = 1;
1831 	if (!strncmp(arg, "uid", 3) ||
1832 	    !strncmp(arg, "gid", 3)) {
1833 		k = ANON_UIDGID;
1834 	} else if (!strncmp(arg, "ino", 3)) {
1835 		k = ANON_INODES;
1836 	} else if (!strncmp(arg, "mtim", 4)) {
1837 		k = ANON_MTIME;
1838 	} else if (!strncmp(arg, "link", 4)) {
1839 		k = ANON_HARDLINKS;
1840 	} else if (!strncmp(arg, "norm", 4)) {
1841 		k = ANON_UIDGID | ANON_INODES | ANON_NUMID |
1842 		    ANON_MTIME | ANON_HARDLINKS;
1843 	} else if (!strncmp(arg, "root", 4)) {
1844 		k = ANON_UIDGID | ANON_INODES | ANON_NUMID;
1845 	} else if (!strncmp(arg, "dist", 4)) {
1846 		k = ANON_UIDGID | ANON_INODES | ANON_NUMID |
1847 		    ANON_HARDLINKS;
1848 	} else if (!strncmp(arg, "set", 3)) {
1849 		k = ANON_INODES | ANON_HARDLINKS;
1850 	} else if (!strncmp(arg, "v", 1)) {
1851 		k = ANON_VERBOSE;
1852 	} else if (!strncmp(arg, "debug", 5)) {
1853 		k = ANON_DEBUG;
1854 	} else if (!strncmp(arg, "lncp", 4)) {
1855 		k = ANON_LNCP;
1856 	} else if (!strncmp(arg, "numid", 5)) {
1857 		k = ANON_NUMID;
1858 	} else if (!strncmp(arg, "gslash", 6)) {
1859 		k = ANON_DIRSLASH;
1860 	} else
1861 		call_usage();
1862 	if (j)
1863 		anonarch |= k;
1864 	else
1865 		anonarch &= ~k;
1866 }
1867 
1868 void
guess_compress_program(int wr)1869 guess_compress_program(int wr)
1870 {
1871 	const char *ccp;
1872 
1873 	if (compress_program != COMPRESS_GUESS_CMD)
1874 		return;
1875 
1876 	if (arcname == NULL || (ccp = strrchr(arcname, '.')) == NULL) {
1877 		compress_program = NULL;
1878 		return;
1879 	}
1880 	++ccp;
1881 
1882 	/* guess standard format gzip */
1883 	if (!strcmp(ccp, "gz") ||
1884 	    !strcmp(ccp, "tgz") ||
1885 	    !strcmp(ccp, "cgz") ||
1886 	    !strcmp(ccp, "ngz") ||
1887 	    !strcmp(ccp, "taz")) {
1888 		compress_program = GZIP_CMD;
1889 		return;
1890 	}
1891 
1892 	/* guess extended format xz */
1893 	if (!strcmp(ccp, "xz") ||
1894 	    !strcmp(ccp, "txz") ||
1895 	    !strcmp(ccp, "cxz") ||
1896 	    !strcmp(ccp, "nxz")) {
1897 		compress_program = XZ_CMD;
1898 		return;
1899 	}
1900 
1901 	/* guess extended format bzip2 (not bzip) */
1902 	if (!strcmp(ccp, "bz2") ||
1903 	    !strcmp(ccp, "tbz") ||
1904 	    !strcmp(ccp, "tz2") ||
1905 	    !strcmp(ccp, "tbz2") ||
1906 	    !strcmp(ccp, "cbz") ||
1907 	    !strcmp(ccp, "nbz")) {
1908 		compress_program = BZIP2_CMD;
1909 		return;
1910 	}
1911 
1912 	/* guess standard format Unix compress */
1913 	if (!strcmp(ccp, "Z") ||
1914 	    !strcmp(ccp, "mcz") ||
1915 	    !strcmp(ccp, "taZ")) {
1916 		compress_program = COMPRESS_CMD;
1917 		return;
1918 	}
1919 
1920 	/* guess extended format lzma (using xz for decompression) */
1921 	if (!strcmp(ccp, "lz") ||
1922 	    !strcmp(ccp, "lzma") ||
1923 	    !strcmp(ccp, "tlz") ||
1924 	    !strcmp(ccp, "clz") ||
1925 	    !strcmp(ccp, "nlz")) {
1926 		compress_program = wr ? LZMA_WRCMD : XZ_CMD;
1927 		return;
1928 	}
1929 
1930 	/* guess extended format lzop */
1931 	if (!strcmp(ccp, "lzo")) {
1932 		compress_program = LZOP_CMD;
1933 		return;
1934 	}
1935 
1936 	/* no sugar */
1937 	compress_program = NULL;
1938 }
1939