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