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