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