1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1987-2013 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *               Glenn Fowler <glenn.s.fowler@gmail.com>                *
18 *                                                                      *
19 ***********************************************************************/
20 #pragma prototyped
21 /*
22  * Glenn Fowler
23  * AT&T Research
24  *
25  * pax -- portable archive interchange
26  *
27  * test registry:
28  *
29  *	0000010	dump option table
30  *	0000020	force DELTA_TEMP to file
31  *	0000040	pretend io device is char special
32  *	0000100	don't copy in holes
33  *	0000200	sleep(1) between meter displays
34  */
35 
36 static const char usage[] =
37 "[-?\n@(#)$Id: pax (AT&T Research) 2013-06-24 $\n]"
38 USAGE_LICENSE
39 "[+NAME?pax - read, write, and list file archives]"
40 "[+DESCRIPTION?The pax command reads, writes, and lists archive files in "
41     "various formats. There are four operation modes controlled by "
42     "combinations of the -\br\b and -\bw\b options.]"
43 "[+?\bpax -w\b writes the files and directories named by the "
44     "\apathname\a arguments to the standard output together with pathname "
45     "and status information. A directory \apathname\a argument refers to the "
46     "files and (recursively) subdirectories of that directory. If no "
47     "\apathname\a arguments are given then the standard input is read to get "
48     "a list of pathnames to copy, one pathname per line. In this case only "
49     "those pathnames appearing on the standard input are copied.]"
50 "[+?\bpax -r\b reads the standard input that is assumed to be the result "
51     "of a previous \bpax -w\b command. Only member files with names that "
52     "match any of the \apattern\a arguments are selected. Matching is done "
53     "before any \b-i\b or \b-s\b options are applied. A \apattern\a is given "
54     "in the name-generating notation of \bsh\b(1), except that the \b/\b "
55     "character is also matched. The default if no \apattern\a is given is "
56     "\b*\b which selects all files. The selected files are conditionally "
57     "created and copied relative to the current directory tree, subject to "
58     "the options described below. By default the owner and group of selected "
59     "files will be that of the current user, and the permissions and modify "
60     "times will be the same as those in the archive.]"
61 "[+?\bpax -rw\b reads the files and directories named in the "
62     "\apathname\a arguments and copies them to the destination "
63     "\adirectory\a. A directory \apathname\a argument refers to the files "
64     "and (recursively) subdirectories of that directory. If no \apathname\a "
65     "arguments are given then the standard input is read to get a list of "
66     "pathnames to copy, one pathname per l, lineine. In this case only those "
67     "pathnames appearing on the standard input are copied. \adirectory\a "
68     "must exist before the copy.]"
69 "[+?\bpax\b (\b-r\b and \b-w\b omitted) reads the standard input that is "
70     "assumed to be the result of a previous \bpax -w\b command and lists "
71     "table of contents of the selected member files on the standard output.]"
72 "[+?The standard archive formats and compression methods are "
73     "automatically detected on input. The default output archive format is "
74     "\b\fdefault\f\b, but may be overridden by the \b-x\b option described "
75     "below. \bpax\b archives may be concatenated to combine multiple volumes "
76     "on a single tape or file. This is accomplished by forcing any format "
77     "prescribed pad data to be null bytes. Hard links are not maintained "
78     "between volumes, and delta and base archives cannot be multi-volume.]"
79 "[+?A single archive may span many files/devices. The second and "
80     "subsequent file names are prompted for on the terminal input. The "
81     "response may be:]"
82     "{"
83         "[+!command?Execute \acommand\a via \bsystem\b(3) and prompt "
84             "again for file name.]"
85         "[+EOF?Terminate processing and exit.]"
86         "[+CR?An empty input line retains the previous file name.]"
87         "[+pathname?The file name for the next archive part.]"
88     "}"
89 "[+?\bgetconf PATH_RESOLVE\b determines how symbolic links are handled. "
90     "This can be explicitly overridden by the \b--logical\b, "
91     "\b--metaphysical\b, and \b--physical\b options below. \bPATH_RESOLVE\b "
92     "can be one of:]"
93     "{"
94         "[+logical?Follow all symbolic links.]"
95         "[+metaphysical?Follow command argument symbolic links, "
96             "otherwise don't follow.]"
97         "[+physical?Don't follow symbolic links.]"
98     "}"
99 ;
100 
101 /* state.usage is generated at runtime from usage+options+usage2 */
102 
103 static const char usage2[] =
104 "\n"
105 "[ pathname ... ]\n"
106 "[ pattern ... ]\n"
107 "[ pathname ... directory ]\n"
108 "\n"
109 "[+DIAGNOSTICS?The number of files, blocks, and optionally the number of "
110     "volumes and media parts are listed on the standard error. For -\bv\b "
111     "the input archive formats are also listed on the standard error.]"
112 "[+EXAMPLES]"
113     "{"
114         "[+pax -w -t 1m .?Copies the contents of the current directory "
115             "to tape drive 1, medium density.]"
116         "[+mkdir newdir; cd olddir; pax -rw . newdir?Copies the "
117             "\aolddir\a directory hierarchy to \anewdir\a.]"
118     "}"
119 "[+SEE ALSO?\bar\b(1), \bcpio\b(1), \bfind\b(1), \bgetconf\b(1), "
120     "\bgzip\b(1), \bksh\b(1), \bratz\b(1), \bstar\b(1), \btar\b(1), "
121     "\btw\b(1), \bfsync\b(2), \blibdelta\b(3), \bcpio\b(5), \btar\b(5)]"
122 "[+BUGS?Special privileges may be required to copy special files. Some "
123     "archive formats have hard upper limits on member string, numeric and "
124     "data sizes. Attribute values larger than the standard min-max values "
125     "may cause additional header or embedded data records to be output for "
126     "some formats; these records are ignored by old versions of \bcpio\b(1) "
127     "and \btar\b(1). \b--format=pax\b avoids size and portability "
128     "limitations \abut\a requires a working reader on the receiving side.]"
129 ;
130 
131 #include "pax.h"
132 
133 #include <ardir.h>
134 #include <iconv.h>
135 #include <tm.h>
136 
137 char*			definput = "/dev/stdin";
138 char*			defoutput = "/dev/stdout";
139 char*			eomprompt = "Change to part %d and hit RETURN: ";
140 
141 State_t			state;
142 
143 static int		signals[] =	/* signals caught by interrupt() */
144 {
145 	SIGHUP,
146 	SIGINT,
147 #if !DEBUG
148 	SIGQUIT,
149 #endif
150 	SIGALRM,
151 	SIGTERM,
152 };
153 
154 static struct
155 {
156 	char*		arg0;
157 	Sfio_t*		ignore_all;
158 	Sfio_t*		ignore_ext;
159 	Map_t*		lastmap;
160 	Sfio_t*		listformat;
161 	char*		owner;
162 } opt;
163 
164 /*
165  * clean up dir info before exit
166  */
167 
168 static void
interrupt(int sig)169 interrupt(int sig)
170 {
171 	signal(sig, SIG_IGN);
172 	switch (sig)
173 	{
174 	case SIGINT:
175 	case SIGQUIT:
176 		sfprintf(sfstderr, "\n");
177 		break;
178 	}
179 	state.interrupt = sig;
180 	finish(1);
181 }
182 
183 /*
184  * enter new substitute expression(s)
185  */
186 
187 static void
substitute(Map_t ** lastmap,register char * s)188 substitute(Map_t** lastmap, register char* s)
189 {
190 	register Map_t*	mp;
191 	int		c;
192 
193 	for (;;)
194 	{
195 		while (isspace(*s))
196 			s++;
197 		if (!*s)
198 			break;
199 		if (!(mp = newof(0, Map_t, 1, 0)))
200 			error(3, "no space [substitution]");
201 		if (!(c = regcomp(&mp->re, s, REG_DELIMITED|REG_LENIENT|REG_NULL)))
202 		{
203 			s += mp->re.re_npat;
204 			if (!(c = regsubcomp(&mp->re, s, NiL, 0, 0)))
205 				s += mp->re.re_npat;
206 		}
207 		if (c)
208 			regfatal(&mp->re, 4, c);
209 		for (;;)
210 		{
211 			switch (*s++)
212 			{
213 			case 'i':
214 				mp->flags |= MAP_INDEX;
215 				continue;
216 			}
217 			s--;
218 			break;
219 		}
220 		if (*s && !isspace(*s))
221 			error(1, "invalid character after substitution: %s", s);
222 		if (*lastmap)
223 			*lastmap = (*lastmap)->next = mp;
224 		else
225 			state.maps = *lastmap = mp;
226 	}
227 }
228 
229 /*
230  * clear meter line for each error message
231  */
232 
233 static ssize_t
meterror(int fd,const void * buf,size_t n)234 meterror(int fd, const void* buf, size_t n)
235 {
236 	if (state.meter.last)
237 	{
238 		sfprintf(sfstderr, "%*s\r", state.meter.last, "");
239 		state.meter.last = 0;
240 	}
241 	return write(fd, buf, n);
242 }
243 
244 /*
245  * construct an action from command
246  */
247 
248 static Filter_t*
action(const char * command,int pattern)249 action(const char* command, int pattern)
250 {
251 	register Filter_t*	fp;
252 	register char*		s;
253 	register char*		t;
254 	register int		c;
255 	register int		q;
256 	register int		n;
257 	regex_t*		re;
258 
259 	s = (char*)command;
260 	if (pattern && *s && *s == *(s + 1))
261 	{
262 		s += 2;
263 		pattern = 0;
264 	}
265 	if (pattern)
266 	{
267 		if (!(re = newof(0, regex_t, 1, 0)))
268 			nospace();
269 		if (c = regcomp(re, s, REG_SHELL|REG_AUGMENTED|REG_DELIMITED|REG_LENIENT|REG_NULL|REG_LEFT|REG_RIGHT))
270 			regfatal(re, 4, c);
271 		s += re->re_npat;
272 	}
273 	else
274 		re = 0;
275 	command = (const char*)s;
276 	q = 0;
277 	n = 3;
278 	while (c = *s++)
279 		if (c == '"' || c == '\'')
280 		{
281 			if (!q)
282 				q = c;
283 			else if (q == c)
284 				q = 0;
285 		}
286 		else if (c == '\\')
287 		{
288 			if (q != '\'' && *s)
289 				s++;
290 		}
291 		else if (!q && isspace(c))
292 		{
293 			n++;
294 			while (isspace(*s))
295 				s++;
296 		}
297 	if (!(fp = newof(0, Filter_t, 1, n * sizeof(char**) + 2 * (s - (char*)command))))
298 		nospace();
299 	fp->re = re;
300 	fp->argv = (char**)(fp + 1);
301 	fp->command = (char*)(fp->argv + n);
302 	s = stpcpy(fp->command, command) + 1;
303 	strcpy(s, command);
304 	fp->argv[0] = s;
305 	q = 0;
306 	n = 1;
307 	t = s;
308 	while (c = *s++)
309 		if (c == '"' || c == '\'')
310 		{
311 			if (!q)
312 				q = c;
313 			else if (q == c)
314 				q = 0;
315 			else
316 				*t++ = c;
317 		}
318 		else if (c == '\\')
319 		{
320 			if (q == '\'')
321 				*t++ = c;
322 			else if (*s)
323 				*t++ = *s++;
324 		}
325 		else if (q || !isspace(c))
326 			*t++ = c;
327 		else
328 		{
329 			*t++ = 0;
330 			while (isspace(*s))
331 				s++;
332 			if (*(t = s))
333 				fp->argv[n++] = s;
334 		}
335 	*t = 0;
336 	fp->patharg = fp->argv + n;
337 	return fp;
338 }
339 
340 /*
341  * return action for f, 0 if no match
342  */
343 
344 Filter_t*
filter(Archive_t * ap,File_t * f)345 filter(Archive_t* ap, File_t* f)
346 {
347 	register Filter_t*	fp;
348 
349 	if (f->st->st_size && (fp = state.filter.list))
350 		do
351 		{
352 			if (!fp->re || !regexec(fp->re, f->name, NiL, 0, 0))
353 				return fp;
354 		} while (fp = fp->next);
355 	return 0;
356 }
357 
358 /*
359  * set options from line if != 0 or argv according to usage
360  * type: 0:command EXTTYPE:extended GLBTYPE:global
361  */
362 
363 void
setoptions(char * line,size_t hdr,char ** argv,char * usage,Archive_t * ap,int type)364 setoptions(char* line, size_t hdr, char** argv, char* usage, Archive_t* ap, int type)
365 {
366 	intmax_t	n;
367 	int		c;
368 	int		y;
369 	int		assignment;
370 	int		cvt;
371 	int		index;
372 	int		offset;
373 	int		from;
374 	int		to;
375 	char*		e;
376 	char*		s;
377 	char*		v;
378 	char*		o;
379 	char*		end;
380 	Filter_t*	xp;
381 	Format_t*	fp;
382 	Option_t*	op;
383 	Sfio_t*		sp;
384 	Value_t*	vp;
385 	char		tmp1[PATH_MAX];
386 	char		tmp2[PATH_MAX];
387 
388 	cvt = 0;
389 	index = opt_info.index;
390 	offset = opt_info.offset;
391 	if (line && hdr)
392 		end = line + hdr;
393 	for (;;)
394 	{
395 		if (hdr)
396 		{
397 			if (!*line)
398 				break;
399 			while (isspace(*line))
400 				line++;
401 			s = line;
402 			y = 0;
403 			while ((c = *line++) >= '0' && c <= '9')
404 				y = y * 10 + (c - '0');
405 			if ((e = (s + y - 1)) > end)
406 				e = end;
407 			else
408 				*e++ = 0;
409 			while (isspace(*line))
410 				line++;
411 			o = line;
412 			assignment = 0;
413 			for (;;)
414 			{
415 				switch (*line++)
416 				{
417 				case 0:
418 					line--;
419 					break;
420 				case '=':
421 					*(line - 1) = 0;
422 					break;
423 				case ':':
424 					if (*line == '=')
425 					{
426 						*(line - 1) = 0;
427 						line++;
428 						assignment = 1;
429 						break;
430 					}
431 					continue;
432 				default:
433 					continue;
434 				}
435 				break;
436 			}
437 			v = line;
438 			line = e;
439 			y = 1;
440 			if (!(op = (Option_t*)hashget(state.options, o)))
441 			{
442 				s = o;
443 				if (strneq(o, VENDOR ".", sizeof(VENDOR)))
444 				{
445 					o += sizeof(VENDOR);
446 					op = (Option_t*)hashget(state.options, o);
447 				}
448 				if (!op && *o == 'n' && *(o + 1) == 'o')
449 				{
450 					o += 2;
451 					y = 0;
452 					op = (Option_t*)hashget(state.options, o);
453 				}
454 				if (!op)
455 				{
456 					if (islower(*s) && !strchr(s, '.'))
457 						error(2, "%s: unknown option", s);
458 					continue;
459 				}
460 			}
461 			if (!y)
462 				n = 0;
463 			else if (!(op->flags & OPT_NUMBER))
464 				n = 1;
465 			else
466 			{
467 				n = strtonll(v, &e, NiL, 0);
468 				if (*e)
469 					error(2, "%s: %s: invalid numeric option value", op->name, v);
470 			}
471 		}
472 		else if (!(c = line ? optstr(line, usage) : optget(argv, usage)))
473 			break;
474 		else if (c > 0)
475 		{
476 			if (c == '?')
477 				error(ERROR_USAGE|4, "%s", opt_info.arg);
478 			if (c == ':' && (!type || islower(*opt_info.name) && !strchr(opt_info.name, '.')))
479 				error(2, "%s", opt_info.arg);
480 			continue;
481 		}
482 		else
483 		{
484 			assignment = opt_info.assignment == ':';
485 			y = (n = opt_info.number) != 0;
486 			if (!(v = opt_info.arg))
487 				v = "";
488 			else if (!n)
489 				y = 1;
490 			op = options - c;
491 		}
492 
493 		/*
494 		 * option precedence levels
495 		 *
496 		 *	8	ignore all
497 		 *	7	command:=
498 		 *	6	ignore extended
499 		 *	5	extended:=
500 		 *	4	extended=
501 		 *	3	command=
502 		 *	2	global:=
503 		 *	1	global=
504 		 */
505 
506 		switch (type)
507 		{
508 		case EXTTYPE:
509 			c = 4;
510 			vp = &op->temp;
511 			break;
512 		case GLBTYPE:
513 			c = 1;
514 			vp = &op->perm;
515 			break;
516 		default:
517 			c = 3;
518 			vp = &op->perm;
519 			break;
520 		}
521 		c += assignment;
522 		message((-5, "option: %c %s level=%d:%d", type ? type : '-', op->name, op->level, c));
523 		if (op->level > c)
524 			continue;
525 		if (y && (op->flags & (OPT_HEADER|OPT_READONLY)) == OPT_HEADER)
526 		{
527 			if (vp == &op->temp)
528 				op->entry = ap->entry;
529 			else
530 				op->level = c;
531 			if (*v)
532 			{
533 				op->flags |= OPT_SET;
534 				if (op->flags & OPT_NUMBER)
535 					vp->number = n;
536 				stash(vp, v, 0);
537 			}
538 			else
539 				vp = 0;
540 		}
541 		else
542 			vp = 0;
543 		message((-4, "option: %c %s%s%s=%s entry=%d:%d level=%d:%d number=%I*u", type ? type : '-', y ? "" : "no", op->name, assignment ? ":" : "", v, op->entry, ap ? ap->entry : 0, op->level, c, sizeof(n), n));
544 		switch (op->index)
545 		{
546 		case OPT_action:
547 			if (*v)
548 			{
549 				xp = action(v, 1);
550 				if (!xp->re)
551 					state.filter.all = xp;
552 				else
553 				{
554 					if (state.filter.last)
555 						state.filter.last->next = xp;
556 					else
557 						state.filter.list = xp;
558 					state.filter.last = xp;
559 				}
560 			}
561 			break;
562 		case OPT_append:
563 			state.append = y;
564 			break;
565 		case OPT_atime:
566 			if (vp)
567 			{
568 			settime:
569 				vp->number = strtoul(vp->string, &e, 10);
570 				vp->fraction = 0;
571 				if (*e)
572 				{
573 					if (*e != '.')
574 						vp->number = tmdate(vp->string, &e, NiL);
575 					if (*e == '.')
576 						vp->fraction = strtoul(s = e + 1, &e, 10);
577 					if (*e)
578 						error(2, "%s: invalid %s date string", vp->string, options[op->index].name);
579 					else if (vp->fraction)
580 					{
581 						y = e - s;
582 						for (y = e - s; y < 9; y++)
583 							vp->fraction *= 10;
584 						for (; y > 9; y--)
585 							vp->fraction /= 10;
586 					}
587 				}
588 			}
589 			break;
590 		case OPT_base:
591 			ap = getarchive(state.operation);
592 			if (ap->delta)
593 				error(3, "base archive already specified");
594 			if (y)
595 			{
596 				initdelta(ap, NiL);
597 				if (!*v || streq(v, "-"))
598 				{
599 					state.delta2delta++;
600 					if (!(state.operation & OUT))
601 					{
602 						ap->delta->format = getformat(FMT_IGNORE, 1);
603 						break;
604 					}
605 					v = "/dev/null";
606 				}
607 				ap->delta->base = initarchive(strdup(v), O_RDONLY);
608 			}
609 			break;
610 		case OPT_blocksize:
611 			if (y)
612 			{
613 				state.blocksize = n;
614 				if (state.blocksize < MINBLOCK)
615 					error(3, "block size must be at least %d", MINBLOCK);
616 				if (state.blocksize & (BLOCKSIZE - 1))
617 					error(1, "block size should probably be a multiple of %d", BLOCKSIZE);
618 			}
619 			else
620 				state.blocksize = DEFBLOCKS * BLOCKSIZE;
621 			break;
622 		case OPT_blok:
623 			if (!*v)
624 				getarchive(IN)->io->blok = getarchive(OUT)->io->blok = n;
625 			else
626 				while (*v) switch (*v++)
627 				{
628 				case 'i':
629 					getarchive(IN)->io->blok = 1;
630 					break;
631 				case 'o':
632 					getarchive(OUT)->io->blok = 1;
633 					break;
634 				default:
635 					error(3, "%s: [io] expected", op->name);
636 					break;
637 				}
638 			break;
639 		case OPT_checksum:
640 			if (y)
641 			{
642 				if (e = strchr(v, ':'))
643 					*e++ = 0;
644 				else
645 				{
646 					e = v;
647 					v = "md5";
648 				}
649 				state.checksum.name = strdup(e);
650 				if (!(state.checksum.sum = sumopen(v)))
651 					error(3, "%s: %s: unknown checksum algorithm", e, v);
652 			}
653 			else
654 				state.checksum.name = 0;
655 			break;
656 		case OPT_chmod:
657 			if (y && *v)
658 			{
659 				strperm(v, &e, 0);
660 				if (*e)
661 					error(3, "%s: invalid file mode expression", v);
662 				state.mode = strdup(v);
663 			}
664 			else
665 				state.mode = 0;
666 			break;
667 		case OPT_clobber:
668 			state.clobber = y;
669 			break;
670 		case OPT_comment:
671 			state.header.comment = y ? strdup(v) : (char*)0;
672 			break;
673 		case OPT_complete:
674 			state.complete = y;
675 			break;
676 		case OPT_crossdevice:
677 			if (!y)
678 				state.ftwflags |= FTW_MOUNT;
679 			else
680 				state.ftwflags &= ~FTW_MOUNT;
681 			break;
682 		case OPT_ctime:
683 			if (vp)
684 				goto settime;
685 			break;
686 		case OPT_debug:
687 			if (y)
688 			{
689 				y = error_info.trace;
690 				error_info.trace = -(int)n;
691 				if (!y)
692 					message((-10, "usage %s", usage));
693 			}
694 			else
695 				error_info.trace = 0;
696 			break;
697 		case OPT_delete:
698 			if (y && *v)
699 				sfprintf(opt.ignore_all, "%s(%s)", sfstrtell(opt.ignore_all) ? "|" : "", v);
700 			break;
701 		case OPT_delta_base_checksum:
702 			if (ap && ap->delta)
703 				ap->delta->checksum = n;
704 			break;
705 		case OPT_delta_base_size:
706 			if (ap && ap->delta)
707 				ap->delta->size = n;
708 			break;
709 		case OPT_delta_checksum:
710 			if (ap)
711 				ap->file.delta.checksum = n;
712 			break;
713 		case OPT_delta_compress:
714 			if (ap && ap->delta)
715 				ap->delta->compress = 1;
716 			break;
717 		case OPT_delta_index:
718 			if (ap)
719 			{
720 				if (type == GLBTYPE)
721 				{
722 					if (ap->delta && (c = n - ap->delta->index - 1))
723 					{
724 						if (c > 0)
725 							error(2, "%s: corrupt archive: %d missing file%s", ap->name, c, c == 1 ? "" : "s");
726 						else
727 							error(2, "%s: corrupt archive: %d extra file%s", ap->name, -c, -c == 1 ? "" : "s");
728 					}
729 				}
730 				else
731 					ap->file.delta.index = n;
732 			}
733 			break;
734 		case OPT_delta_method:
735 			if (ap)
736 			{
737 				if (!(fp = getformat(v, 0)) || !(fp->flags & DELTA))
738 					error(3, "%s: %s: delta method not supported", ap->name, v);
739 				initdelta(ap, fp);
740 			}
741 			break;
742 		case OPT_delta_op:
743 			if (ap && ap->delta)
744 				ap->file.delta.op = line ? *v : n;
745 			break;
746 		case OPT_delta_ordered:
747 			if (ap && ap->delta)
748 				ap->delta->ordered = n;
749 			break;
750 		case OPT_delta_update:
751 			state.delta.update = y;
752 			break;
753 		case OPT_delta_version:
754 			break;
755 		case OPT_descend:
756 			state.descend = y;
757 			break;
758 		case OPT_different:
759 		case OPT_newer:
760 		case OPT_update:
761 			state.update = y ? op->index : 0;
762 			break;
763 		case OPT_dots:
764 			state.drop = y;
765 			break;
766 		case OPT_edit:
767 			substitute(&opt.lastmap, (char*)v);
768 			break;
769 		case OPT_eom:
770 			eomprompt = y ? strdup(v) : (char*)0;
771 			break;
772 		case OPT_exact:
773 			state.exact = y;
774 			break;
775 		case OPT_extended_name:
776 			state.header.extended = y ? strdup(v) : (char*)0;
777 			break;
778 		case OPT_file:
779 			ap = getarchive(state.operation);
780 			if (ap->name)
781 				error(3, "%s: %s: archive name already specified", v, ap->name);
782 			ap->name = strdup(v);
783 			break;
784 		case OPT_filter:
785 			if (y && *v)
786 			{
787 				state.filter.command = v;
788 				state.descend = 0;
789 			}
790 			else
791 				state.filter.command = 0;
792 			break;
793 		case OPT_format:
794 			ap = getarchive(state.operation);
795 			if (!y)
796 				ap->format = 0;
797 			else if (s = strdup(v))
798 			{
799 				v = s;
800 				do
801 				{
802 					for (e = s, o = 0;;)
803 					{
804 						switch (*e++)
805 						{
806 						case 0:
807 							e = 0;
808 							break;
809 						case ' ':
810 						case '\t':
811 						case '\n':
812 						case ':':
813 						case ',':
814 						case '.':
815 							*(e - 1) = 0;
816 							if (*s)
817 								break;
818 							s = e;
819 							continue;
820 						case '=':
821 							if (!o)
822 							{
823 								*(e - 1) = 0;
824 								o = e;
825 							}
826 							continue;
827 						default:
828 							continue;
829 						}
830 						break;
831 					}
832 					if (!(fp = getformat(s, 0)) && s == v && s[0] == 't' && !strchr(s, ':') && (fp = getformat(s + 1, 0)))
833 					{
834 						if (ap->format = getformat("tar", 0))
835 							s++;
836 						else
837 							fp = 0;
838 					}
839 					if (!fp)
840 					{
841 						if (!pathpath("lib/pax", opt.arg0, PATH_EXECUTE, tmp1, sizeof(tmp1)) || sfsprintf(tmp2, sizeof(tmp2) - 1, "%s/%s.fmt", tmp1, s) <= 0 || !(sp = sfopen(NiL, tmp2, "r")))
842 							error(3, "%s: unknown archive format", s);
843 						while (e = sfgetr(sp, '\n', 1))
844 							if (*e != '#')
845 							{
846 								setoptions(e, sfvalue(sp), NiL, state.usage, ap, type);
847 								if (line && !hdr)
848 									line += opt_info.offset;
849 							}
850 						sfclose(sp);
851 					}
852 					else
853 					{
854 						fp->details = o;
855 						switch (fp->flags & (ARCHIVE|COMPRESS|DELTA))
856 						{
857 						case ARCHIVE:
858 							ap->format = fp;
859 							break;
860 						case COMPRESS:
861 							ap->compress = fp;
862 							break;
863 						case DELTA:
864 							initdelta(ap, fp);
865 							break;
866 						}
867 					}
868 				} while (s = e);
869 			}
870 			ap->expected = ap->format;
871 			if (!state.operation)
872 				state.format = ap->format;
873 			break;
874 		case OPT_from:
875 		case OPT_to:
876 			if (!cvt)
877 			{
878 				cvt = 1;
879 				from = to = CC_NATIVE;
880 			}
881 			ap = getarchive(state.operation);
882 			if ((y = ccmapid(v)) < 0)
883 				error(3, "%s: unknown character code set", v);
884 			switch (op->index)
885 			{
886 			case OPT_from:
887 				from = y;
888 				break;
889 			case OPT_to:
890 				to = y;
891 				break;
892 			}
893 			break;
894 		case OPT_global_name:
895 			state.header.global = y ? strdup(v) : (char*)0;
896 			break;
897 		case OPT_header:
898 			v = y ? strdup(v) : (char*)0;
899 			if (assignment)
900 				state.header.extended = v;
901 			else
902 				state.header.global = v;
903 			break;
904 		case OPT_ignore:
905 			if (y && *v)
906 			{
907 				if (assignment)
908 					sfprintf(opt.ignore_ext, "%s(%s)", sfstrtell(opt.ignore_ext) ? "|" : "", v);
909 				else
910 					sfprintf(opt.ignore_all, "%s(%s)", sfstrtell(opt.ignore_all) ? "|" : "", v);
911 			}
912 			break;
913 		case OPT_install:
914 			state.install.name = y ? strdup(v) : (char*)0;
915 			break;
916 		case OPT_intermediate:
917 			state.intermediate = y;
918 			break;
919 		case OPT_invalid:
920 			if (line)
921 			{
922 				n = 0;
923 				y = strlen(v);
924 				s = op->details;
925 				while (s = strchr(s, '['))
926 				{
927 					c = *++s;
928 					o = ++s;
929 					for (;;)
930 					{
931 						if (strneq(v, o, y))
932 						{
933 							s = "";
934 							n = c;
935 							break;
936 						}
937 						if (!(o = strchr(o, '|')))
938 							break;
939 						o++;
940 					}
941 				}
942 			}
943 			switch ((int)n)
944 			{
945 			case 'b':
946 				state.header.invalid = INVALID_binary;
947 				break;
948 			case 'i':
949 				state.header.invalid = INVALID_ignore;
950 				break;
951 			case 'p':
952 				state.header.invalid = INVALID_prompt;
953 				break;
954 			case 't':
955 				state.header.invalid = INVALID_translate;
956 				break;
957 			case 'u':
958 				state.header.invalid = INVALID_UTF8;
959 				break;
960 			default:
961 				error(2, "%s: %s: unknown option value", op->name, v);
962 				break;
963 			}
964 			break;
965 		case OPT_invert:
966 			state.matchsense = !y;
967 			break;
968 		case OPT_keepgoing:
969 			state.keepgoing = y;
970 			break;
971 		case OPT_label:
972 			if (*state.volume)
973 			{
974 				if (assignment)
975 					sfsprintf(tmp1, sizeof(tmp1), "%s %s", v, state.volume);
976 				else
977 					sfsprintf(tmp1, sizeof(tmp1), "%s %s", state.volume, v);
978 				v = tmp1;
979 			}
980 			strncpy(state.volume, v, sizeof(state.volume) - 2);
981 			break;
982 		case OPT_link:
983 			if (y)
984 				state.linkf = link;
985 			else
986 				state.linkf = 0;
987 			break;
988 		case OPT_linkdata:
989 			state.header.linkdata = y;
990 			break;
991 		case OPT_listformat:
992 			if (y && *v)
993 				sfputr(opt.listformat, v, ' ');
994 			break;
995 		case OPT_listmacro:
996 			if (y && *v)
997 			{
998 				if (s = strchr(v, '='))
999 					*s++ = 0;
1000 				if (!(op = (Option_t*)hashget(state.options, v)))
1001 				{
1002 					if (!s)
1003 						break;
1004 					if (!(op = newof(0, Option_t, 1, 0)))
1005 						nospace();
1006 					op->name = hashput(state.options, 0, op);
1007 				}
1008 				if (s)
1009 				{
1010 					op->macro = strdup(s);
1011 					*(s - 1) = 0;
1012 				}
1013 				else
1014 					op->macro = 0;
1015 			}
1016 			break;
1017 		case OPT_local:
1018 			state.local = 1;
1019 			break;
1020 		case OPT_logical:
1021 			if (y)
1022 				state.ftwflags &= ~FTW_PHYSICAL;
1023 			else
1024 				state.ftwflags |= FTW_PHYSICAL;
1025 			break;
1026 		case OPT_maxout:
1027 			state.maxout = n;
1028 			break;
1029 		case OPT_metaphysical:
1030 			if (y)
1031 				state.ftwflags |= FTW_META|FTW_PHYSICAL;
1032 			else
1033 				state.ftwflags &= ~(FTW_META|FTW_PHYSICAL);
1034 			break;
1035 		case OPT_meter:
1036 			if (state.meter.on = y)
1037 			{
1038 				if (!(state.meter.tmp = sfstropen()))
1039 					nospace();
1040 				if (state.meter.fancy = isatty(sffileno(sfstderr)))
1041 				{
1042 					error_info.write = meterror;
1043 					astwinsize(1, NiL, &state.meter.width);
1044 					if (state.meter.width < 2 * (METER_width + 1))
1045 						state.meter.width = 2 * (METER_width + 1);
1046 				}
1047 			}
1048 			break;
1049 		case OPT_mkdir:
1050 			state.mkdir = y;
1051 			break;
1052 		case OPT_mtime:
1053 			if (vp)
1054 				goto settime;
1055 			break;
1056 		case OPT_options:
1057 			if (v)
1058 			{
1059 				setoptions(v, 0, NiL, usage, ap, type);
1060 				if (line && !hdr)
1061 					line += opt_info.offset;
1062 			}
1063 			break;
1064 		case OPT_ordered:
1065 			state.ordered = y;
1066 			break;
1067 		case OPT_owner:
1068 			if (!(state.owner = y))
1069 				opt.owner = 0;
1070 			else if (*v)
1071 				opt.owner = strdup(v);
1072 			break;
1073 		case OPT_passphrase:
1074 			state.passphrase = y ? strdup(v) : (char*)0;
1075 			break;
1076 		case OPT_physical:
1077 			if (y)
1078 			{
1079 				state.ftwflags &= ~FTW_META;
1080 				state.ftwflags |= FTW_PHYSICAL;
1081 			}
1082 			else
1083 				state.ftwflags &= ~FTW_PHYSICAL;
1084 			break;
1085 		case OPT_preserve:
1086 			for (;;)
1087 			{
1088 				switch (*v++)
1089 				{
1090 				case 0:
1091 					break;
1092 				case 'a':
1093 					state.acctime = 0;
1094 					continue;
1095 				case 'e':
1096 					state.acctime = 1;
1097 					state.modtime = 1;
1098 					state.owner = 1;
1099 					state.modemask = 0;
1100 					state.modekeep = 1;
1101 					continue;
1102 				case 'm':
1103 					state.modtime = 0;
1104 					continue;
1105 				case 'o':
1106 					state.owner = 1;
1107 					continue;
1108 				case 'p':
1109 					state.modemask &= (S_ISUID|S_ISGID);
1110 					state.modekeep = 1;
1111 					continue;
1112 				case 's':
1113 					state.modemask &= ~(S_ISUID|S_ISGID);
1114 					continue;
1115 				default:
1116 					error(1, "%s=%c: unknown flag", op->name, *(v - 1));
1117 					continue;
1118 				}
1119 				break;
1120 			}
1121 			break;
1122 		case OPT_read:
1123 			if (y)
1124 				state.operation |= IN;
1125 			else
1126 				state.operation &= ~IN;
1127 			break;
1128 		case OPT_record_charset:
1129 			state.record.charset = y;
1130 			break;
1131 		case OPT_record_delimiter:
1132 			if (!y)
1133 				state.record.delimiter = 0;
1134 			else
1135 				state.record.delimiter = *v;
1136 			break;
1137 		case OPT_record_format:
1138 			state.record.format = y ? *v : 0;
1139 			break;
1140 		case OPT_record_header:
1141 			if (!y)
1142 			{
1143 				state.record.header = 0;
1144 				state.record.headerlen = 0;
1145 			}
1146 			else if (!(state.record.headerlen = stresc(state.record.header = strdup(v))))
1147 				state.record.headerlen = 1;
1148 			break;
1149 		case OPT_record_line:
1150 			state.record.line = y;
1151 			break;
1152 		case OPT_record_match:
1153 			state.record.pattern = y ? strdup(v) : (char*)0;
1154 			break;
1155 		case OPT_record_pad:
1156 			state.record.pad = y;
1157 			break;
1158 		case OPT_record_size:
1159 			state.record.size = n;
1160 			break;
1161 		case OPT_record_trailer:
1162 			if (!y)
1163 			{
1164 				state.record.trailer = 0;
1165 				state.record.trailerlen = 0;
1166 			}
1167 			else if (!(state.record.trailerlen = stresc(state.record.trailer = strdup(v))))
1168 				state.record.trailerlen = 1;
1169 			break;
1170 		case OPT_reset_atime:
1171 			state.resetacctime = y;
1172 			break;
1173 		case OPT_size:
1174 			break;
1175 		case OPT_strict:
1176 			state.strict = y;
1177 			break;
1178 		case OPT_summary:
1179 			state.summary = y;
1180 			break;
1181 		case OPT_symlink:
1182 			if (y)
1183 				state.linkf = pathsetlink;
1184 			else
1185 				state.linkf = 0;
1186 			break;
1187 		case OPT_sync:
1188 #if _lib_fsync
1189 			state.sync = y;
1190 #else
1191 			error(1, "%s not implemented on this system", op->name);
1192 #endif
1193 			break;
1194 		case OPT_tape:
1195 			ap = getarchive(state.operation);
1196 			if (ap->name)
1197 				error(3, "%s: %s: archive name already specified", v, ap->name);
1198 			s = strtape(v, &e);
1199 			if (*s)
1200 				ap->name = s;
1201 			for (;;)
1202 			{
1203 				switch (*e++)
1204 				{
1205 				case 'k':
1206 					if (!(n = strtonll(e, &e, 0, 1)))
1207 						n = -1;
1208 					ap->io->keep = n;
1209 					ap->io->mode = O_RDWR;
1210 					continue;
1211 				case 's':
1212 					if (!(n = strtonll(e, &e, 0, 1)))
1213 						n = -1;
1214 					ap->io->skip = n;
1215 					ap->io->mode = O_RDWR;
1216 					continue;
1217 				}
1218 				e--;
1219 				break;
1220 			}
1221 			if (*e)
1222 				error(3, "%s: invalid tape unit specification [%s]", v, e);
1223 			break;
1224 		case OPT_test:
1225 			if (y)
1226 				state.test |= (unsigned long)n;
1227 			else
1228 				state.test = 0;
1229 			break;
1230 		case OPT_testdate:
1231 			if (y)
1232 			{
1233 				state.testdate = tmdate(v, &e, NiL);
1234 				if (*e)
1235 					error(3, "%s: invalid %s date string", v, options[op->index].name);
1236 			}
1237 			else
1238 				state.testdate = ~0;
1239 			break;
1240 		case OPT_times:
1241 			if (y)
1242 			{
1243 				setoptions("atime:= ctime:= mtime:=", 0, NiL, usage, ap, type);
1244 				if (line && !hdr)
1245 					line += opt_info.offset;
1246 			}
1247 			break;
1248 		case OPT_unblocked:
1249 			if (!*v)
1250 				getarchive(IN)->io->unblocked = getarchive(OUT)->io->unblocked = y;
1251 			else
1252 				while (*v) switch (*v++)
1253 				{
1254 				case 'i':
1255 					getarchive(IN)->io->unblocked = 1;
1256 					break;
1257 				case 'o':
1258 					getarchive(OUT)->io->unblocked = 1;
1259 					break;
1260 				default:
1261 					error(3, "%s: [io] expected", op->name);
1262 					break;
1263 				}
1264 			break;
1265 		case OPT_uncompressed:
1266 			ap->file.uncompressed = n;
1267 			break;
1268 		case OPT_verbose:
1269 			state.verbose = y;
1270 			break;
1271 		case OPT_verify:
1272 			state.verify = y;
1273 			break;
1274 		case OPT_warn:
1275 			state.warn = y;
1276 			break;
1277 		case OPT_write:
1278 			if (y)
1279 				state.operation |= OUT;
1280 			else
1281 				state.operation &= ~OUT;
1282 			if (!(state.operation & IN) && state.in && !state.out)
1283 			{
1284 				state.out = state.in;
1285 				state.in = 0;
1286 				state.out->io->mode = O_CREAT|O_TRUNC|O_WRONLY;
1287 			}
1288 			break;
1289 		case OPT_yes:
1290 			state.verify = state.yesno = y;
1291 			break;
1292 		default:
1293 			if (!type && !(op->flags & OPT_HEADER) || !(op->flags & (OPT_IGNORE|OPT_SET)))
1294 				error(1, "%s: option ignored [index=%d]", op->name, op->index);
1295 			break;
1296 		}
1297 	}
1298 	if (line && !hdr)
1299 	{
1300 		opt_info.index = index;
1301 		opt_info.offset = offset;
1302 	}
1303 	if (cvt)
1304 	{
1305 		ap->convert[0].on = 1;
1306 		convert(ap, SECTION_DATA, from, to);
1307 	}
1308 }
1309 
1310 /*
1311  * option match with VENDOR check
1312  */
1313 
1314 static int
matchopt(const char * name,const char * pattern,Option_t * op)1315 matchopt(const char* name, const char* pattern, Option_t* op)
1316 {
1317 	return strmatch(name, pattern) || (op->flags & OPT_VENDOR) && strmatch(sfprints("%s.%s", VENDOR, name), pattern);
1318 }
1319 
1320 /*
1321  * mark ignored header keywords
1322  */
1323 
1324 static void
ignore(void)1325 ignore(void)
1326 {
1327 	register Option_t*	op;
1328 	Hash_position_t*	pos;
1329 	char*			all;
1330 	char*			ext;
1331 	int			lev;
1332 
1333 	if (!sfstrtell(opt.ignore_all))
1334 		all = 0;
1335 	else if (!(all = sfstruse(opt.ignore_all)))
1336 		nospace();
1337 	if (!sfstrtell(opt.ignore_ext))
1338 		ext = 0;
1339 	else if (!(ext = sfstruse(opt.ignore_ext)))
1340 		nospace();
1341 	if ((all || ext) && (pos = hashscan(state.options, 0)))
1342 	{
1343 		while (hashnext(pos))
1344 		{
1345 			op = (Option_t*)pos->bucket->value;
1346 			if (!(op->flags & OPT_READONLY) && (all && matchopt(pos->bucket->name, all, op) && (lev = 8) || ext && matchopt(pos->bucket->name, ext, op) && (lev = 6)) && op->level < lev)
1347 				op->level = lev;
1348 		}
1349 		hashdone(pos);
1350 	}
1351 	sfstrclose(opt.ignore_all);
1352 	sfstrclose(opt.ignore_ext);
1353 }
1354 
1355 /*
1356  * list fp for optinfo()
1357  */
1358 
1359 static void
listformat(register Sfio_t * sp,register Format_t * fp)1360 listformat(register Sfio_t* sp, register Format_t* fp)
1361 {
1362 	register const char*	p;
1363 	register int		c;
1364 
1365 	sfprintf(sp, "[+%s", fp->name);
1366 	if (p = fp->match)
1367 	{
1368 		sfputc(sp, '|');
1369 		if (*p == '(')
1370 			p++;
1371 		while (c = *p++)
1372 		{
1373 			if (c == ')' && !*p)
1374 				break;
1375 			if (c == '?' || c == ']')
1376 				sfputc(sp, c);
1377 			sfputc(sp, c);
1378 		}
1379 	}
1380 	sfputc(sp, '?');
1381 	p = fp->desc;
1382 	while (c = *p++)
1383 	{
1384 		if (c == ']')
1385 			sfputc(sp, c);
1386 		sfputc(sp, c);
1387 	}
1388 	switch (fp->flags & (IN|OUT))
1389 	{
1390 	case 0:
1391 		sfputr(sp, "; for listing only", -1);
1392 		break;
1393 	case IN:
1394 		sfputr(sp, "; for input only", -1);
1395 		break;
1396 	case OUT:
1397 		sfputr(sp, "; for output only", -1);
1398 		break;
1399 	}
1400 	sfputc(sp, ']');
1401 }
1402 
1403 /*
1404  * optget() info discipline function
1405  */
1406 
1407 static int
optinfo(Opt_t * op,Sfio_t * sp,const char * s,Optdisc_t * dp)1408 optinfo(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
1409 {
1410 	register Format_t*	fp;
1411 	register iconv_list_t*	ic;
1412 	register const char*	p;
1413 	register int		i;
1414 	register int		c;
1415 	Ardirmeth_t*		ar;
1416 
1417 	switch (*s)
1418 	{
1419 	case 'c':
1420 		for (ic = iconv_list(NiL); ic; ic = iconv_list(ic))
1421 		{
1422 			sfputc(sp, '[');
1423 			sfputc(sp, '+');
1424 			sfputc(sp, '\b');
1425 			p = ic->match;
1426 			if (*p == '(')
1427 				p++;
1428 			while (c = *p++)
1429 			{
1430 				if (c == ')' && !*p)
1431 					break;
1432 				if (c == '?' || c == ']')
1433 					sfputc(sp, c);
1434 				sfputc(sp, c);
1435 			}
1436 			sfputc(sp, '?');
1437 			p = ic->desc;
1438 			while (c = *p++)
1439 			{
1440 				if (c == ']')
1441 					sfputc(sp, c);
1442 				sfputc(sp, c);
1443 			}
1444 			sfputc(sp, ']');
1445 		}
1446 		break;
1447 	case 'd':
1448 		sfputr(sp, FMT_DEFAULT, -1);
1449 		break;
1450 	case 'D':
1451 		fp = 0;
1452 		while (fp = nextformat(fp))
1453 			if (fp->flags & DELTA)
1454 			{
1455 				sfprintf(sp, "[+%s", fp->name);
1456 				sfputc(sp, '?');
1457 				p = fp->desc;
1458 				while (c = *p++)
1459 				{
1460 					if (c == ']')
1461 						sfputc(sp, c);
1462 					sfputc(sp, c);
1463 				}
1464 				sfputc(sp, ']');
1465 			}
1466 		break;
1467 	case 'f':
1468 		fp = 0;
1469 		while (fp = nextformat(fp))
1470 			if (fp->flags & ARCHIVE)
1471 				listformat(sp, fp);
1472 		ar = 0;
1473 		while (ar = ardirlist(ar))
1474 			sfprintf(sp, "[+%s?%s; for input only]", ar->name, ar->description);
1475 		sfprintf(sp, "[+----?compression methods ----]");
1476 		fp = 0;
1477 		while (fp = nextformat(fp))
1478 			if (fp->flags & COMPRESS)
1479 				listformat(sp, fp);
1480 		sfprintf(sp, "[+----?delta methods ----]");
1481 		fp = 0;
1482 		while (fp = nextformat(fp))
1483 			if (fp->flags & DELTA)
1484 				listformat(sp, fp);
1485 				break;
1486 		break;
1487 	case 'l':
1488 		for (i = 1; options[i].name; i++)
1489 			if ((options[i].flags & (OPT_GLOBAL|OPT_READONLY)) == OPT_READONLY)
1490 			{
1491 				sfprintf(sp, "[+%s?%s]\n", options[i].name, options[i].description);
1492 				if (options[i].details)
1493 					sfprintf(sp, "{\n%s\n}", options[i].details);
1494 			}
1495 		sfprintf(sp, "%s",
1496 "	[+----?subformats ----]"
1497 "	[+case\b::\bp\b\a1\a::\bs\b\a1\a::...::\bp\b\an\a::\bs\b\an\a?Expands"
1498 "		to \bs\b\ai\a if the value of \aid\a matches the shell"
1499 "		pattern \bp\b\ai\a, or the empty string if there is no"
1500 "		match.]"
1501 "	[+mode?The integral value as a \bfmtmode\b(3) string.]"
1502 "	[+perm?The integral value as a \bfmtperm\b(3) string.]"
1503 "	[+time[=\aformat\a]]?The integral value as a \bstrftime\b(3)"
1504 "		string. For example,"
1505 "		\b--format=\"%8(mtime)u %(ctime:time=%H:%M:%S)s\"\b"
1506 "		lists the mtime in seconds since the epoch and the"
1507 "		ctime as hours:minutes:seconds.]");
1508 		break;
1509 	}
1510 	return 0;
1511 }
1512 
1513 int
main(int argc,char ** argv)1514 main(int argc, char** argv)
1515 {
1516 	register int		i;
1517 	register char*		s;
1518 	register Archive_t*	ap;
1519 	char*			p;
1520 	Hash_position_t*	pos;
1521 	Option_t*		op;
1522 	int			n;
1523 	int			pass = 0;
1524 	unsigned long		blocksize;
1525 	struct stat		st;
1526 	Optdisc_t		optdisc;
1527 
1528 	static Format_t		rw = { "rw", 0, 0, 0, IN|OUT };
1529 
1530 	setlocale(LC_ALL, "");
1531 	paxinit(&state, error_info.id = "pax");
1532 	optinit(&optdisc, optinfo);
1533 	state.strict = !!conformance(0, 0);
1534 	state.gid = getegid();
1535 	state.uid = geteuid();
1536 	state.pid = getpid();
1537 	umask(state.modemask = umask(0));
1538 	state.modemask |= S_ISUID|S_ISGID;
1539 	state.ftwflags = ftwflags()|FTW_DOT;
1540 	state.acctime = 1;
1541 	state.buffersize = DEFBUFFER * DEFBLOCKS;
1542 	state.clobber = 1;
1543 	state.delta.buffersize = DELTA_WINDOW >> 1;
1544 	state.descend = RESETABLE;
1545 	state.format = getformat(FMT_DEFAULT, 1);
1546 	state.header.extended = state.strict ? HEADER_EXTENDED_STD : HEADER_EXTENDED;
1547 	state.header.global = state.strict ? HEADER_GLOBAL_STD : HEADER_GLOBAL;
1548 	state.map.a2n = ccmap(CC_ASCII, CC_NATIVE);
1549 	state.map.e2n = ccmap(CC_EBCDIC, CC_NATIVE);
1550 	state.map.n2e = ccmap(CC_NATIVE, CC_EBCDIC);
1551 	if (!(opt.ignore_all = sfstropen()) || !(opt.ignore_ext = sfstropen()))
1552 		nospace();
1553 	if (!(opt.listformat = sfstropen()))
1554 		nospace();
1555 	state.matchsense = 1;
1556 	state.mkdir = 1;
1557 	state.modtime = 1;
1558 	if (!(state.tmp.fmt = sfstropen()) || !(state.tmp.lst = sfstropen()) || !(state.tmp.str = sfstropen()))
1559 		nospace();
1560 	stash(&options[OPT_release].perm, release(), 0);
1561 	options[OPT_release].flags |= OPT_SET;
1562 	if (!(state.options = hashalloc(NiL, HASH_name, "options", 0)))
1563 		nospace();
1564 	for (i = 1; options[i].name; i++)
1565 	{
1566 		p = options[i].name;
1567 		if (strchr(p, '|'))
1568 			p = strdup(p);
1569 		do
1570 		{
1571 			if (s = strchr(p, '|'))
1572 				*s++ = 0;
1573 			hashput(state.options, p, &options[options[i].index]);
1574 		} while (p = s);
1575 	}
1576 	hashset(state.options, HASH_ALLOCATE);
1577 	state.record.charset = 1;
1578 	state.record.line = 1;
1579 	state.summary = 1;
1580 	state.testdate = ~0;
1581 	if (!(state.tmp.file = pathtemp(NiL, 0, NiL, error_info.id, NiL)))
1582 		nospace();
1583 	sfputr(state.tmp.str, usage, -1);
1584 	for (i = 1; options[i].name; i++)
1585 		if ((options[i].flags & (OPT_GLOBAL|OPT_READONLY)) != OPT_READONLY)
1586 		{
1587 			sfputc(state.tmp.str, '[');
1588 			if (options[i].flag)
1589 			{
1590 				sfputc(state.tmp.str, options[i].flag);
1591 				if (options[i].flags & OPT_INVERT)
1592 					sfputc(state.tmp.str, '!');
1593 			}
1594 			sfprintf(state.tmp.str, "=%d:%s", options[i].index, options[i].name);
1595 			if (options[i].flags & OPT_VENDOR)
1596 			{
1597 				for (s = (char*)options[i].name; p = strchr(s, '|'); s = p + 1)
1598 					sfprintf(state.tmp.str, "|%s.%-.*s", VENDOR, p - s, s);
1599 				sfprintf(state.tmp.str, "|%s.%s", VENDOR, s);
1600 			}
1601 			sfprintf(state.tmp.str, "?%s]", options[i].description);
1602 			if (options[i].argument)
1603 			{
1604 				sfputc(state.tmp.str, (options[i].flags & OPT_NUMBER) ? '#' : ':');
1605 				if (options[i].flags & OPT_OPTIONAL)
1606 					sfputc(state.tmp.str, '?');
1607 				sfprintf(state.tmp.str, "[%s]", options[i].argument);
1608 			}
1609 			if (options[i].details)
1610 				sfprintf(state.tmp.str, "\n{%s}", options[i].details);
1611 			sfputc(state.tmp.str, '\n');
1612 		}
1613 	sfputr(state.tmp.str, usage2, -1);
1614 	if (!(state.usage = sfstruse(state.tmp.str)))
1615 		nospace();
1616 	opt.arg0 = argv[0];
1617 	setoptions(NiL, 0, argv, state.usage, NiL, 0);
1618 	argv += opt_info.index;
1619 	argc -= opt_info.index;
1620 	if (error_info.errors)
1621 		error(ERROR_USAGE|4, "%s", optusage(NiL));
1622 	if (!state.operation)
1623 	{
1624 		state.operation = IN;
1625 		state.list = 1;
1626 	}
1627 	if (!sfstrtell(opt.listformat))
1628 		sfputr(opt.listformat, (state.list && state.verbose) ? "%(mode)s %2(nlink)d %-8(uname)s %-8(gname)s%8(device:case::%(size)llu:*:%(device)s)s %(mtime)s %(delta.op:case:?*:%(delta.op)s )s%(path)s%(linkop:case:?*: %(linkop)s %(linkpath)s)s" : "%(delta.op:case:?*:%(delta.op)s )s%(path)s%(linkop:case:?*: %(linkop)s %(linkpath)s)s", ' ');
1629 	sfstrseek(opt.listformat, -1, SEEK_CUR);
1630 	if (!state.meter.on)
1631 		sfputc(opt.listformat, '\n');
1632 	if (!(state.listformat = strdup(sfstruse(opt.listformat))))
1633 		nospace();
1634 	sfstrclose(opt.listformat);
1635 	ignore();
1636 	if (s = state.filter.command)
1637 	{
1638 		if (streq(s, "-"))
1639 		{
1640 			state.filter.line = -1;
1641 			s = "sh -c";
1642 		}
1643 		state.filter.all = action(s, 0);
1644 	}
1645 	if (state.filter.last)
1646 		state.filter.last->next = state.filter.all;
1647 	else
1648 		state.filter.list = state.filter.all;
1649 	state.statf = (state.ftwflags & FTW_PHYSICAL) ? lstat : pathstat;
1650 
1651 	/*
1652 	 * determine the buffer sizes
1653 	 */
1654 
1655 	switch (state.operation)
1656 	{
1657 	case IN|OUT:
1658 		if (!state.in)
1659 			break;
1660 		/*FALLTHROUGH*/
1661 	case IN:
1662 	case OUT:
1663 		getarchive(state.operation);
1664 		break;
1665 	}
1666 	blocksize = state.blocksize;
1667 	if (ap = state.out)
1668 	{
1669 		if (!ap->format)
1670 			ap->format = state.format;
1671 		else if (state.operation == (IN|OUT))
1672 			pass = 1;
1673 		if (state.operation == OUT)
1674 		{
1675 			if (state.files)
1676 				state.ftwflags |= FTW_POST;
1677 		}
1678 		if (state.append || state.update)
1679 			ap->io->mode = O_RDWR|O_CREAT;
1680 		ap->io->fd = 1;
1681 		if (!ap->name || streq(ap->name, "-"))
1682 			ap->name = defoutput;
1683 		else
1684 		{
1685 			close(1);
1686 			if (open(ap->name, ap->io->mode|O_BINARY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) != 1)
1687 				error(ERROR_SYSTEM|3, "%s: cannot write", ap->name);
1688 		}
1689 		if (fstat(ap->io->fd, &st))
1690 			error(ERROR_SYSTEM|3, "%s: cannot stat", ap->name);
1691 		if (S_ISREG(st.st_mode))
1692 		{
1693 			ap->io->seekable = 1;
1694 			ap->io->size = st.st_size;
1695 		}
1696 		if (!state.blocksize)
1697 		{
1698 			st.st_mode = modex(st.st_mode);
1699 			if (state.test & 0000040)
1700 				st.st_mode = X_IFCHR;
1701 			if (X_ITYPE(st.st_mode) == X_IFREG)
1702 			{
1703 				state.blocksize = ap->format->regular;
1704 				ap->io->unblocked = 1;
1705 			}
1706 			else
1707 				state.blocksize = ap->format->special;
1708 			state.buffersize = state.blocksize *= BLOCKSIZE;
1709 		}
1710 	}
1711 	else
1712 	{
1713 		if (state.blocksize)
1714 			state.buffersize = state.blocksize;
1715 		else
1716 			state.blocksize = (state.operation == (IN|OUT) ? FILBLOCKS : DEFBLOCKS) * BLOCKSIZE;
1717 		if (state.record.size)
1718 			error(1, "record size automatically determined on archive read");
1719 	}
1720 	if (ap = state.in)
1721 	{
1722 		if (!ap->name || streq(ap->name, "-"))
1723 			ap->name = definput;
1724 		else
1725 		{
1726 			close(0);
1727 			if (open(ap->name, ap->io->mode|O_BINARY))
1728 				error(ERROR_SYSTEM|3, "%s: cannot read", ap->name);
1729 		}
1730 		if (fstat(ap->io->fd, &st))
1731 			error(ERROR_SYSTEM|3, "%s: cannot stat", ap->name);
1732 		if (S_ISREG(st.st_mode))
1733 		{
1734 			ap->io->seekable = 1;
1735 			ap->io->size = st.st_size;
1736 		}
1737 		if (state.meter.on && !(state.meter.size = ap->io->size))
1738 			state.meter.on = 0;
1739 	}
1740 	if (!blocksize && (blocksize = bblock(!state.in)))
1741 		state.blocksize = blocksize;
1742 	if (state.buffersize < state.blocksize)
1743 		state.buffersize = state.blocksize;
1744 	state.tmp.buffersize = state.buffersize;
1745 	if (!(state.tmp.buffer = newof(0, char, state.tmp.buffersize, 0)))
1746 		nospace();
1747 	if (state.maxout && state.maxout <= state.blocksize)
1748 		error(3, "--maxout=%#i must be greater than --blocksize=%#i", state.maxout, state.blocksize);
1749 	message((-1, "blocksize=%d buffersize=%d recordsize=%d", state.blocksize, state.buffersize, state.record.size));
1750 
1751 	/*
1752 	 * initialize the main io
1753 	 */
1754 
1755 	switch (state.operation)
1756 	{
1757 	case IN:
1758 	case OUT:
1759 		getarchive(state.operation);
1760 		break;
1761 	}
1762 	if (ap = state.in)
1763 	{
1764 		binit(ap);
1765 		if (state.append && !state.out)
1766 		{
1767 			error(1, "append ignored for archive read");
1768 			state.append = 0;
1769 		}
1770 	}
1771 	if (ap = state.out)
1772 	{
1773 		if (!ap->format)
1774 			ap->format = state.format;
1775 		if (state.append || state.update)
1776 		{
1777 			if (ap->delta)
1778 			{
1779 				error(1, "append/update ignored for archive delta");
1780 				state.update = 0;
1781 			}
1782 			if (state.append && state.update)
1783 			{
1784 				error(1, "append ignored for archive update");
1785 				state.append = 0;
1786 			}
1787 			if (!ap->io->seekable)
1788 				error(3, "%s: append/update requires seekable archive", ap->name);
1789 			else if (!ap->io->size)
1790 				state.append = state.update = 0;
1791 			else
1792 			{
1793 				initdelta(ap, NiL);
1794 				ap->delta->base = ap;
1795 			}
1796 		}
1797 		binit(ap);
1798 		if (ap->compress)
1799 		{
1800 			Proc_t*		proc;
1801 			List_t*		p;
1802 			char*		cmd[4];
1803 
1804 			cmd[0] = ap->compress->name;
1805 			i = 1;
1806 			if (cmd[i] = ((Compress_format_t*)ap->compress->data)->variant)
1807 				i++;
1808 			if (cmd[i] = ap->compress->details)
1809 				i++;
1810 			cmd[i] = 0;
1811 			if (!(proc = procopen(*cmd, cmd, NiL, NiL, PROC_WRITE)))
1812 				error(3, "%s: cannot execute %s filter", ap->name, ap->compress->name);
1813 			n = proc->wfd;
1814 			proc->wfd = 1;
1815 			close(1);
1816 			if (dup(n) != 1)
1817 				error(3, "%s: cannot redirect %s filter output", ap->name, ap->compress->name);
1818 			close(n);
1819 			if (!(p = newof(0, List_t, 1, 0)))
1820 				nospace();
1821 			p->item = (void*)proc;
1822 			p->next = state.proc;
1823 			state.proc = p;
1824 		}
1825 		if (state.checksum.name)
1826 		{
1827 			if (!(state.checksum.path = pathtemp(NiL, 0, NiL, error_info.id, NiL)))
1828 				nospace();
1829 			if (!(state.checksum.sp = sfopen(NiL, state.checksum.path, "w")))
1830 				error(3, "%s: cannot write checksum temporary", state.checksum.path);
1831 			sfprintf(state.checksum.sp, "method=%s\n", state.checksum.sum->name);
1832 			sfprintf(state.checksum.sp, "permissions\n");
1833 		}
1834 		if (state.install.name)
1835 		{
1836 			if (!(state.install.path = pathtemp(NiL, 0, NiL, error_info.id, NiL)))
1837 				nospace();
1838 			if (!(state.install.sp = sfopen(NiL, state.install.path, "w")))
1839 				error(3, "%s: cannot write install temporary", state.install.path);
1840 		}
1841 	}
1842 	if (!(state.linktab = hashalloc(NiL, HASH_set, HASH_ALLOCATE, HASH_namesize, sizeof(Fileid_t), HASH_name, "links", 0)))
1843 		error(3, "cannot allocate hard link table");
1844 	if ((state.operation & IN) && !state.list && !(state.restore = hashalloc(NiL, HASH_set, HASH_ALLOCATE, HASH_name, "restore", 0)))
1845 		error(3, "cannot allocate directory table");
1846 	if (state.owner)
1847 	{
1848 		if (state.operation & IN)
1849 		{
1850 			state.modemask = 0;
1851 			if (opt.owner)
1852 			{
1853 				if ((state.setuid = struid(opt.owner)) < 0 || (state.setgid = strgid(opt.owner)) < 0)
1854 					error(3, "%s: invalid user name", opt.owner);
1855 				state.flags |= SETIDS;
1856 			}
1857 		}
1858 		else
1859 			error(1, "ownership assignment ignored on archive write");
1860 	}
1861 	if (state.verify)
1862 		interactive();
1863 	if (!(state.modemask &= (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)))
1864 		umask(0);
1865 	state.modemask = ~state.modemask;
1866 #if DEBUG
1867 	if ((state.test & 0000010) && (pos = hashscan(state.options, 0)))
1868 	{
1869 		while (hashnext(pos))
1870 		{
1871 			op = (Option_t*)pos->bucket->value;
1872 			if (op->name == pos->bucket->name)
1873 				sfprintf(sfstderr, "%-16s %c %2d %d perm=%ld:%s temp=%ld:%s%s%s\n", op->name, op->flag ? op->flag : '-', op->index, op->level, op->perm.number, op->perm.string, op->temp.number, op->temp.string, (op->flags & OPT_HEADER) ? " HEADER" : "", (op->flags & OPT_READONLY) ? " READONLY" : "");
1874 		}
1875 		hashdone(pos);
1876 	}
1877 #endif
1878 	for (i = 0; i < elementsof(signals); i++)
1879 		if (signal(signals[i], interrupt) == SIG_IGN)
1880 			signal(signals[i], SIG_IGN);
1881 	switch (state.operation)
1882 	{
1883 	case IN:
1884 		if (*argv)
1885 		{
1886 			initmatch(argv);
1887 			if (state.exact)
1888 				state.matchsense = 1;
1889 		}
1890 		else if (state.exact)
1891 			error(3, "file arguments expected");
1892 		getcwd(state.pwd, PATH_MAX);
1893 		state.pwdlen = strlen(state.pwd);
1894 		if (state.pwdlen > 1)
1895 			state.pwd[state.pwdlen++] = '/';
1896 		copyin(state.in);
1897 		if (state.exact)
1898 			for (state.pattern = state.patterns; state.pattern->pattern; state.pattern++)
1899 				if (!state.pattern->matched)
1900 					error(2, "%s: %s: file not found in archive", state.in->name, state.pattern->pattern);
1901 		break;
1902 
1903 	case OUT:
1904 		if (*argv)
1905 			state.files = argv;
1906 		if (!state.maxout && state.complete)
1907 			error(3, "maximum block count required");
1908 		copy(state.out, copyout);
1909 		break;
1910 
1911 	case (IN|OUT):
1912 		if (pass || state.in || state.out)
1913 		{
1914 			state.pass = 1;
1915 			if (*argv)
1916 				initmatch(argv);
1917 			deltapass(getarchive(IN), getarchive(OUT));
1918 		}
1919 		else
1920 		{
1921 			if (--argc < 0)
1922 			{
1923 				error(2, "destination directory required for pass mode");
1924 				error(ERROR_USAGE|4, "%s", optusage(NiL));
1925 			}
1926 			state.destination = argv[argc];
1927 			argv[argc] = 0;
1928 			if (*argv)
1929 				state.files = argv;
1930 			if (state.record.size)
1931 				error(1, "record size ignored in pass mode");
1932 
1933 			/*
1934 			 * initialize destination dir
1935 			 */
1936 
1937 			pathcanon(state.destination, 0, 0);
1938 			if (stat(state.destination, &st) || !S_ISDIR(st.st_mode))
1939 				error(3, "%s: destination must be a directory", state.destination);
1940 			state.dev = st.st_dev;
1941 			strcpy(state.pwd, state.destination);
1942 			if (state.pwdlen = strlen(state.pwd))
1943 				state.pwd[state.pwdlen++] = '/';
1944 			if (state.update < 0)
1945 				state.update = OPT_newer;
1946 			getarchive(OUT);
1947 			state.out->format = &rw;
1948 			copy(NiL, copyinout);
1949 		}
1950 		break;
1951 	}
1952 	finish(0);
1953 }
1954 
1955 /*
1956  * print number of blocks actually copied and exit
1957  */
1958 
1959 void
finish(int code)1960 finish(int code)
1961 {
1962 	register Archive_t*	ap;
1963 	size_t			x = state.buffersize / 4;
1964 	register char*		x1 = &state.tmp.buffer[0];
1965 	register char*		x2 = x1 + x;
1966 	register char*		x3 = x2 + x;
1967 	register char*		x4 = x3 + x;
1968 	register off_t		n;
1969 
1970 	while (state.proc)
1971 	{
1972 		procclose((Proc_t*)state.proc->item);
1973 		state.proc = state.proc->next;
1974 	}
1975 	remove(state.tmp.file);
1976 	if (state.checksum.path)
1977 		remove(state.checksum.path);
1978 	if (state.install.path)
1979 		remove(state.install.path);
1980 	if (state.restore)
1981 		hashwalk(state.restore, 0, restore, NiL);
1982 	sfsync(sfstdout);
1983 	if (state.meter.last)
1984 	{
1985 		sfprintf(sfstderr, "%*s\r", state.meter.last, "");
1986 		state.meter.last = 0;
1987 	}
1988 	else if (state.dropcount)
1989 	{
1990 		sfprintf(sfstderr, "\n");
1991 		sfsync(sfstderr);
1992 	}
1993 	if (state.summary)
1994 	{
1995 		ap = getarchive(state.operation);
1996 		n = ap->io->count + ap->io->expand + ap->io->offset;
1997 		message((-1, "%s totals entries=%d count=%I*d expand=%I*d offset=%I*d BLOCKSIZE=%I*d n=%I*d blocks=%I*d", ap->name, ap->entries, sizeof(ap->io->count), ap->io->count, sizeof(ap->io->expand), ap->io->expand, sizeof(ap->io->offset), ap->io->offset, sizeof(BLOCKSIZE), BLOCKSIZE, sizeof(n), n, sizeof(n), (n + BLOCKSIZE - 1) / BLOCKSIZE));
1998 		if (ap->entries)
1999 		{
2000 			if (ap->volume > 1)
2001 				sfsprintf(x1, x, ", %d volumes", ap->volume);
2002 			else
2003 				*x1 = 0;
2004 			if (ap->volume > 0 && ap->part > ap->volume)
2005 				sfsprintf(x2, x, ", %d parts", ap->part - ap->volume + 1);
2006 			else
2007 				*x2 = 0;
2008 			n = (n + BLOCKSIZE - 1) / BLOCKSIZE;
2009 			if (state.verbose || state.meter.on)
2010 			{
2011 				sfsprintf(x3, x, "%I*u file%s, ", sizeof(ap->selected), ap->selected, ap->selected == 1 ? "" : "s");
2012 				if (state.update)
2013 					sfsprintf(x4, x, "%I*u updated, ", sizeof(ap->updated), ap->updated);
2014 				else
2015 					*x4 = 0;
2016 			}
2017 			else
2018 				*x3 = *x4 = 0;
2019 			sfprintf(sfstderr, "%s%s%I*d block%s%s%s\n", x3, x4, sizeof(n), n, n == 1 ? "" : "s", x1, x2);
2020 		}
2021 	}
2022 	sfsync(sfstderr);
2023 	if (state.interrupt)
2024 	{
2025 		signal(state.interrupt, SIG_DFL);
2026 		kill(getpid(), state.interrupt);
2027 		pause();
2028 	}
2029 	exit(code ? code : error_info.errors != 0);
2030 }
2031 
2032 /*
2033  * return release stamp
2034  */
2035 
2036 char*
release(void)2037 release(void)
2038 {
2039 	register char*	b;
2040 	register char*	s;
2041 	register char*	t;
2042 
2043 	if ((s = strchr(usage, '@')) && (t = strchr(s, '\n')) && (b = fmtbuf(t - s + 1)))
2044 	{
2045 		memcpy(b, s, t - s);
2046 		b[t - s] = 0;
2047 	}
2048 	else
2049 		b = fmtident(usage);
2050 	return b;
2051 }
2052