"Fossies" - the Fresh Open Source Software Archive 
Member "afio-2.5.2/afio.c" (30 Nov 2018, 132555 Bytes) of package /linux/misc/afio-2.5.2.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "afio.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
2.5.1_vs_2.5.2.
1 /*
2 * afio.c
3 *
4 * Manipulate archives and files.
5 *
6 * This software was written by Mark Brukhartz at Lachman Associates,
7 * Inc.. Additional code was written by a large cast of people.
8 *
9 * Licensing and (re)distribution
10 * ------------------------------
11 *
12 * THE SUMMARY INFORMATION BELOW WAS WRITTEN FOR THE BENEFIT OF
13 * SOFTWARE DISTRIBUTORS
14 *
15 * Because of historical reasons, different parts of this software
16 * package are covered by different licenses. As of 2012, my (Koen
17 * Holtman's) intepretation of the license status is as follows.
18 *
19 * - The main authors and maintainers all intend afio to be free and
20 * freely distributable. It has been distributed widely and for
21 * free since at least 1987, when it was posted to the
22 * comp.sources.unix newsgroup.
23 *
24 * - The legal risks to re-distributers, coming from the licence, are
25 * effectively zero.
26 *
27 * - The afio license is not a standard OSI/FSF approved free software
28 * license, it predates these license texts. Unfortunately, the
29 * afio license includes wording that is considered to be
30 * problematic by several of todays open source licensing legal
31 * experts, because the wording leaves too much room for
32 * interpretation. It is impossible to upgrade this problematic
33 * license text.
34 *
35 * - Therefore, if your software redistribution or package labeling
36 * policy implies a rejection of non-standard OSI/FSF approved free
37 * software licenses, you need to be careful about handling afio.
38 *
39 * See the file afio_license_issues_v5.txt for more legal
40 * discussion.
41 *
42 * END OF SUMMARY INFORMATION
43 *
44 * ------------------------------------------------------------------
45 *
46 * License notice 1, covering part of this software package.
47 *
48 * [Covers the original 1985 afio code]
49 *
50 * Copyright (c) 1985 Lachman Associates, Inc..
51 *
52 * This software was written by Mark Brukhartz at Lachman Associates,
53 * Inc.. It may be distributed within the following restrictions:
54 * (1) It may not be sold at a profit.
55 * (2) This credit and notice must remain intact.
56 * This software may be distributed with other software by a commercial
57 * vendor, provided that it is included at no additional charge.
58 *
59 *
60 * [Note: it is believed that condition 5 of the Perl "Artistic
61 * License" implies the intent of restriction (1) above.]
62 *
63 * --------
64 *
65 * ** License notice 2, covering part of this software package.
66 *
67 * [Covers the tempnam function]
68 *
69 * Copyright: Copyright (c) 1989 by Monty Walls.
70 * Not derived from licensed software.
71 *
72 * Permission to copy and/or distribute granted under the
73 * following conditions:
74 *
75 * 1). This notice must remain intact.
76 * 2). The author is not responsible for the consequences of use
77 * this software, no matter how awful, even if they
78 * arise from defects in it.
79 * 3). Altered version must not be represented as being the
80 * original software.
81 *
82 * --------
83 *
84 * ** License notice 3, covering part of this software package.
85 *
86 * [Covers the contents of the gnu.fnmatch.tar.gz file]
87 *
88 * Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
89 *
90 * This library is free software; you can redistribute it and/or
91 * modify it under the terms of the GNU Library General Public License as
92 * published by the Free Software Foundation; either version 2 of the
93 * License, or (at your option) any later version.
94 *
95 * This library is distributed in the hope that it will be useful,
96 * but WITHOUT ANY WARRANTY; without even the implied warranty of
97 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
98 * Library General Public License for more details.
99 *
100 * You should have received a copy of the GNU Library General Public
101 * License along with this library; see the file COPYING.LIB. If
102 * not, write to the Free Software Foundation, Inc., 675 Mass Ave,
103 * Cambridge, MA 02139, USA.
104 *
105 * --------
106 *
107 * ** License notice 4, covering part of this software package.
108 *
109 * [Covers the remainder of this software package]
110 *
111 * Additional code was written by a large cast of people.
112 *
113 * All additional code may be redistributed under the conditions of
114 * license notice 1.
115 *
116 * Note that the authors of the additional code retain the right to
117 * allow for the re-distribution of their code under weaker (and less
118 * exotic) conditions.
119 *
120 * --------
121 *
122 * ** WARRANTY NOTICE
123 *
124 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
125 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
126 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
127 *
128 *
129 * [End of licensing and redistribution section]
130 *
131 * ---------------------------------------------------------------------
132 *
133 * Makefile options:
134 * o Define INDEX to use index() in place of strchr() (v7, BSD).
135 * o Define MEMCPY when an efficient memcpy() exists (SysV).
136 * o Define MKDIR when a mkdir() system call is present (4.2BSD, SysVr3).
137 * o Define NOVOID if your compiler doesn't like void casts.
138 * o Define SYSTIME to use <sys/time.h> rather than <time.h> (4.2BSD).
139 * o Define VOIDFIX to allow pointers to functions returning void (non-PCC).
140 * o Define CTC3B2 to support AT&T 3B2 streaming cartridge tape.
141 * o Define HAVEFCNTL if you have <fcntl.h>
142 * o Define MYTEMPNAM if you don't have tempnam()
143 * o Define UNIXPC if you are on a 3b1, 7300, etc.
144 * o Define HAVEMEMCMP if you have memcmp otherwise assumes bcmp
145 * o Define DEFFMTCMD to being how to format the media you use the most.
146 * o Define LONGZFILE if you want .Z to be tagged on the end of a 14 char
147 *
148 * BUGS:
149 * See the manpage.
150 *
151 * Added by Jeff Buhrt:
152 * Floppy Verify/format/restart output in the middle of a set,
153 * compress files on output, extended error messages and logging
154 *
155 * Added by Dave Gymer:
156 * Lotsa bugfixes, Linux support, recognition of .Z files in an archive
157 * that were compressed already (and shouldn't be uncompressed).
158 * Displays compression ratios.
159 *
160 * See the HISTORY file for more revision info. */
161
162
163 #include <stdio.h>
164 #include <errno.h>
165
166 #ifdef sun
167 #include <sys/types.h>
168 #include <utime.h>
169 #include <signal.h>
170 #include <strings.h>
171 #include <sys/wait.h>
172 #define linux_tstamp 1
173 #if 0
174 /* fix SunOS errno.h not declaring what the manpage says it declares
175 bogosity. */
176 extern int sys_nerr;
177 extern char *sys_errlist[];
178 #endif
179 #endif
180
181 #ifdef hpux
182 #if 0
183 /* Fix that HPUX dosent have sys_nerr or sys_errlist
184 Added by Daniel Andersson, daniel.andersson@sto.sema.se
185 */
186 extern int sys_nerr;
187 extern char *sys_errlist[];
188 #endif
189 #endif
190
191 #include <unistd.h>
192 #include <string.h>
193 #include <stdlib.h>
194 #ifdef __CYGWIN32__
195 #include <signal.h>
196 #else
197 #include <sys/signal.h>
198 #endif
199 #include <sys/types.h>
200 #include <sys/ioctl.h>
201 #include <sys/stat.h>
202 #include <pwd.h>
203 #include <grp.h>
204 #include "patchlevel.h"
205
206 #ifdef linux
207
208 #define linux_tstamp 1
209
210 #include <utime.h>
211 #include <sys/wait.h>
212
213 /* for flushing floppy cache */
214 #include <linux/fd.h>
215 #endif
216
217 /* compatibility fixes for IRIX native c compiler. */
218 #ifdef irix_cc_compatibility
219 #define linux_tstamp 1
220 #include <strings.h>
221 #endif
222
223 #ifndef major
224 #ifdef sun
225 #include <sys/mkdev.h>
226 #else
227 #include <sys/sysmacros.h>
228 #endif
229 #endif /* major */
230
231 #include "afio.h"
232
233
234 /* define 1 to enable file descriptor leak debugging code */
235 #define FDDEBUG 0
236
237 /*
238 * Static variables.
239 */
240 STATIC short Fflag; /*
241 * floppy flag (write when buf full)
242 * set -sdisk_size as well
243 */
244 STATIC short Zflag; /* compress the files that we can */
245 STATIC short verifyflag; /* Verify (floppy) flag */
246 STATIC short verifycnt;
247 #ifdef CTC3B2
248 STATIC short Cflag; /* Enable 3B2 CTC streaming (kludge) */
249 #endif /* CTC3B2 */
250 STATIC short aflag; /* Preserve atime (while munging ctime) */
251 STATIC short dflag; /* Don't create missing directories */
252 STATIC short fflag; /* Fork before writing to archive */
253 STATIC short gflag; /* Change to input file directories */
254 short hflag; /* Follow symbolic links */
255 STATIC short jflag; /* Don't generate sparse filesystem blocks */
256 STATIC short kflag; /* Skip initial junk to find a header */
257 short lflag; /* Link rather than copying (when possible) */
258 STATIC short mflag; /* Ignore archived timestamps */
259 STATIC short nflag; /* Keep newer existing files */
260 STATIC short uflag; /* Report files with unseen links */
261 STATIC short vflag; /* Verbose */
262 STATIC short xflag; /* Retain file ownership */
263 STATIC short zflag; /* Print final statistics */
264 STATIC short flag0; /* Input names terminated with '\0' */
265 STATIC short Jflag=0; /* Keep going after archive write error */
266 STATIC short hidequit; /* show the quit option? */
267 STATIC short abspaths; /* allow absolute path names? */
268 STATIC uint arbsize = BLOCK; /* Archive block size */
269 STATIC short areof; /* End of input volume reached */
270 STATIC int arfd = -1; /* Archive file descriptor */
271 STATIC ulonglong arleft; /* Space remaining within current volume */
272 STATIC char *arname; /* Expanded archive name */
273 STATIC uint arpad; /* Final archive block padding boundary */
274 STATIC char arspec[PATHSIZE]; /* Specified archive name */
275 STATIC char proc_arname[PATHSIZE+10];/* %-processed archive name */
276 STATIC ulonglong aruntil=0; /* Volume size limit */
277 STATIC int sflagused=0; /* flag if -s flag was used */
278 STATIC int roundaruntil=1; /* Round aruntil to multiple of arbsize? */
279 STATIC ulonglong maxsizetocompress=200L*1024L*1024L; /* ==0, then no max */
280 STATIC int askfornext=0; /* Ask for next disk on input eof? */
281 STATIC uint arvolume = 1; /* Volume number */
282 STATIC off_t buflen; /* Archive buffer length */
283 STATIC char *buffer; /* Archive buffer */
284 STATIC char *bufidx; /* Archive buffer index */
285 STATIC char *bufend; /* End of data within archive buffer */
286 STATIC Child *children; /* Child processes */
287 STATIC char *formatcmd = DEFFMTCMD; /* how to format */
288 STATIC gid_t gid; /* Group ID */
289 STATIC Link *linkbase[1024];/* Unresolved link information */
290 STATIC unsigned char ino16bitused[256*256/8]; /* bitmap of 16 bit inode numbers */
291 STATIC ino_t freshino = 0; /* counter to make fresh inos */
292 STATIC FILE *logfile = NULL; /* log same errors as stderr would */
293 STATIC ushort mask; /* File creation mask */
294 STATIC char *myname; /* Arg0 */
295 extern char *optarg; /* Option argument */
296 extern int optind; /* Command line index */
297 STATIC int outpid; /* Process ID of outstanding outflush() */
298 STATIC char pwd[PATHSIZE]; /* Working directory (with "-g") */
299 STATIC int pipepid; /* Pipeline process ID */
300 STATIC time_t timenow; /* Current time */
301 STATIC time_t timewait; /* Time spent awaiting new media */
302 STATIC ulonglong total; /* Total number of bytes transferred */
303 STATIC int ttyf = -1; /* For interactive queries (yuk) */
304 STATIC uid_t uid; /* User ID */
305 int uncompressrun = 0; /* is uncompress running? its pid if so */
306 char uncompto[PATHSIZE]; /* name we uncompressed to */
307 STATIC int anycorrupt = 0; /* if any data is corrupted */
308 STATIC int warnings = 0; /* if any data is corrupted */
309 int printbytepos = 0; /* print position of each file in archive */
310 ulonglong bytepos; /* position of first byte of current file */
311 STATIC char *controlscript=NULL; /* script to pipe control files to */
312 STATIC char *promptscript=NULL; /* name of disk-change script */
313 STATIC ushort extfmt = 0; /* Use extended ASCII format */
314 STATIC ushort cpiocompat = 0; /* Never use large ASCII format headers */
315 STATIC ushort cpiowarned = 0; /* warning given? */
316 STATIC char *email=NULL; /* email address to notify of volume change requests */
317 STATIC int rewindfd = -1; /* file descriptor to rewind before
318 (un)compress invocations */
319 STATIC char *ignorewarnings="mc"; /* data for -1 option */
320 STATIC char *aruntil_string=NULL; /* -s option string given by user */
321 STATIC int extcasesens=0; /* Case sensitive matching in -E option? */
322 STATIC Dir *DirP=NULL; /* list of directories with their saved timestamps */
323 STATIC char firstfilename[PATHSIZE]=""; /* for temp storage during -o */
324 STATIC int useoutmodetoc=0; /* used in tocentry() */
325 STATIC short noglob=0; /* disable globbing */
326 STATIC int allowinsecurepaths=0;
327 STATIC int allowinsecuresymlinks=0;
328 STATIC int nosymlinks=0;
329
330 int main (int ac, char **av)
331 {
332 reg int c;
333 reg uint group = 1;
334 VOIDFN (*fn)(char **) = NULL;
335 time_t timedone;
336 auto char remote[PATHSIZE];
337 char *exitmsg;
338 int status;
339 Stat tmpstat;
340
341 #if 0
342 printf("sizeof off_t = %d\n",sizeof(off_t));
343 printf("sizeof size_t = %d\n",sizeof(size_t));
344 #endif
345
346 if ((myname = strrchr (*av, '/')))
347 ++myname;
348 else
349 myname = *av;
350 mask = umask (0);
351 uid = getuid ();
352 gid = getgid ();
353 if (uid == 0)
354 xflag = 1;
355
356 /* ignore SIGPIPE to deal with gzip -d exiting prematurely */
357 VOID signal (SIGPIPE, SIG_IGN);
358
359 /* All letters have been used as options, now eating into the numbers....
360 */
361
362 while ((c = options (ac, av,
363 "aioprtIOVCb:c:de:fghjklmns:uvxXy:Y:zFKZL:R:qAE:G:M:w:W:T:SBD:P:Q:U4JH:0@:N:3:1:92:56:78:"))
364 )
365 {
366 switch (c)
367 {
368 case 'r':
369 if (fn)
370 usage ();
371 fn = readcheck;
372 allowinsecurepaths=allowinsecuresymlinks=1;
373 break;
374 case 'i':
375 if (fn)
376 usage ();
377 fn = in;
378 break;
379 case 'o':
380 if (fn)
381 usage ();
382 fn = out;
383 useoutmodetoc=1;
384 break;
385 case 'p':
386 if (fn)
387 usage ();
388 fn = pass;
389 break;
390 case 't':
391 if (fn)
392 usage ();
393 fn = toc;
394 allowinsecurepaths=allowinsecuresymlinks=1;
395 break;
396 case 'I':
397 if (fn)
398 usage ();
399 fn = copyin;
400 break;
401 case 'O':
402 if (fn)
403 usage ();
404 fn = copyout;
405 break;
406 case 'V':
407 VOID printf ("%s: Version %s dated %s\n",
408 myname, VERSION, DATE);
409 exit (0);
410 #ifdef CTC3B2
411 case 'C':
412 ++Cflag;
413 arbsize = 31 * 512;
414 group = 10;
415 aruntil = 1469 * 31 * 512;
416 break;
417 #endif /* CTC3B2 */
418 case 'a':
419 ++aflag;
420 break;
421 case 'b':
422 if ((arbsize = (uint) optsize (optarg)) == 0)
423 fatal (optarg, "Bad block size");
424 break;
425 case 'c':
426 if ((group = (uint) optsize (optarg)) == 0)
427 fatal (optarg, "Bad buffer count");
428 break;
429 case 'd':
430 ++dflag;
431 break;
432 case 'e':
433 arpad = (uint) optsize (optarg);
434 break;
435 case 'f':
436 ++fflag;
437 break;
438 case 'g':
439 ++gflag;
440 break;
441 case 'h':
442 ++hflag;
443 break;
444 case 'j':
445 ++jflag;
446 break;
447 case 'k':
448 ++kflag;
449 break;
450 case 'l':
451 ++lflag;
452 break;
453 case 'm':
454 ++mflag;
455 break;
456 case 'n':
457 ++nflag;
458 break;
459 case 's':
460 sflagused = 1;
461 /* Do a 'dry run' to check all values for syntax errors */
462 aruntil_string = strdup(optarg);
463 while(aruntil_string) update_aruntil();
464 /* Now the real initialisation */
465 aruntil_string = optarg;
466 update_aruntil();
467 if (aruntil == 0) askfornext = 1;
468 break;
469 case 'F':
470 ++Fflag;
471 break;
472 case 'Z':
473 ++Zflag;
474 break;
475 case 'K':
476 ++verifyflag;
477 break;
478 case 'u':
479 ++uflag;
480 break;
481 case 'v':
482 ++vflag;
483 break;
484 case 'x':
485 xflag = 1;
486 break;
487 case 'X':
488 xflag = 0;
489 break;
490 case 'y':
491 nameadd (optarg, PATTYPE_MATCH);
492 break;
493 case 'Y':
494 nameadd (optarg, PATTYPE_NOMATCH);
495 break;
496 case 'z':
497 ++zflag;
498 break;
499 case 'L':
500 if ((logfile = fopen (optarg, "a")) == (FILE *) 0)
501 {
502 fprintf (stderr,
503 "Can't open %s to append, get help\n",
504 optarg);
505 exit (1);
506 }
507 break;
508 case 'R':
509 formatcmd = optarg;
510 break;
511 case 'q':
512 hidequit = TRUE;
513 break;
514 case 'A':
515 abspaths = TRUE;
516 break;
517 case 'E':
518 if(strcmp(optarg,"CS")==0) extcasesens=1;
519 else if(strcmp(optarg,"CI")==0) extcasesens=0;
520 else if(!readcompexts(optarg))
521 {
522 exit (1);
523 }
524 break;
525 case 'G':
526 gzipfactor=(uint) optsize(optarg);
527 if((gzipfactor <1) || (gzipfactor >9))
528 {
529 fprintf (stderr,
530 "%s: Illegal gzip speed factor (Must be 1--9)\n",
531 optarg);
532 exit (1);
533 }
534 break;
535 case 'M':
536 maxmem=(off_t) optsize(optarg);
537 break;
538 case 'T':
539 compthreshold=(uint) optsize(optarg);
540 break;
541 case 'w':
542 if(!nameaddfile(optarg,PATTYPE_MATCH,flag0))
543 {
544 fprintf (stderr,
545 "Can't read configuration file %s\n",
546 optarg);
547 exit (1);
548 }
549 break;
550 case 'W':
551 if(!nameaddfile(optarg,PATTYPE_NOMATCH,flag0))
552 {
553 fprintf (stderr,
554 "Can't read configuration file %s\n",
555 optarg);
556 exit (1);
557 }
558 break;
559 case '6':
560 if(!nameaddfile(optarg,PATTYPE_EXT,0))
561 {
562 fprintf (stderr,
563 "Can't read configuration file %s\n",
564 optarg);
565 exit (1);
566 }
567 break;
568 case 'S':
569 ignoreslash=0;
570 break;
571 case 'B':
572 printbytepos=1;
573 break;
574 case 'D':
575 controlscript=optarg;
576 break;
577 case 'Q':
578 compressargs=1;
579 add_arg(optarg);
580 break;
581 case 'P':
582 compressprog=optarg;
583 break;
584 case 'U': /* compress All files */
585 forceZflag=1;
586 lflag=1; /* Due to internal limitations we need to set this */
587 break;
588 case '0':
589 flag0 = 1-flag0;
590 break;
591 case '4': /* Use extended ASCII format */
592 extfmt = 1;
593 break;
594 case '5':
595 cpiocompat = 1;
596 break;
597 case 'J':
598 Jflag = 1;
599 break;
600 case 'H':
601 promptscript=optarg; /* name or definition of the promptscript */
602 break;
603 case '@':
604 email=optarg;
605 break;
606 case '3':
607 rewindfd=(int)optsize(optarg);
608 break;
609 case '1':
610 ignorewarnings=optarg;
611 break;
612 case '9':
613 roundaruntil=0;
614 break;
615 case '2':
616 maxsizetocompress=optsize(optarg);
617 break;
618 case '7':
619 noglob = 1-noglob;
620 break;
621 case '8':
622 if (strcmp(optarg, "allowinsecurepaths") == 0) allowinsecurepaths=1;
623 else if(strcmp(optarg, "allowinsecuresymlinks") == 0) allowinsecuresymlinks=1;
624 else if (strcmp(optarg, "nosymlinks") == 0) nosymlinks=1;
625 else fatal (optarg, "unknown value for -8 option");
626 break;
627
628 default:
629 usage ();
630 }
631 }
632 if (fn == NULL || av[optind] == NULL)
633 usage ();
634
635 if (extfmt && cpiocompat)
636 {
637 warn(av[0], "Options -4 and -5 cannot be specified at the same time.");
638 usage ();
639 }
640
641 if(fflag && aruntil==0)
642 {
643 fprintf (stderr,"Fatal: must supply nonzero -s [volsize] to use -f\n");
644 usage();
645 }
646
647 if(compressprog && (rewindfd==-1))
648 if(strstr(compressprog,"pgp") || strstr(compressprog,"gpg"))
649 {
650 fatal(compressprog,"Must use -3 flag if -P program matches 'pgp' or 'gpg', see the afio manual page.");
651 }
652
653 if(!compressprog) compressprog = PRG_COMPRESS;
654 compress_arg_list[0] = compressprog;
655
656 if(maxmem/1024L/1024L > (1024+512))
657 {
658 /* afio uses uints and ints and size_t at several places that
659 may make it (on architectures with 32 bit ints and size_t)
660 fail to do the right calculations when the buffer size is
661 >2GB. This 1.5 GB limit is somewhat conservative, but better
662 safe than sorry.
663
664 If you have an os/compile environment witrh 64 bit size_t
665 and int, things might be OK if you disable this test, but
666 I have not tested it.
667 If you disable here see also the code in memwrite().
668 */
669 fatal (arspec, "In-memory compression buffer size above 1.5GB not supported");
670 }
671
672 if (Fflag)
673 {
674 if ((buflen = (off_t) aruntil) == 0)
675 usage ();
676 }
677 else
678 buflen = (off_t)arbsize * (off_t)group;
679
680 if( roundaruntil )
681 {
682 /* round aruntil down to a multiple of arbsize: some devices
683 (like ftape) puke on a smaller-than-blocksize last write to
684 the volume */
685 aruntil = ( aruntil / (ulonglong) arbsize );
686 aruntil = aruntil * arbsize;
687 }
688
689 if (aruntil && (aruntil < arbsize))
690 {
691 #ifdef hpux
692 /* HPUX gcc dosent like the (ulong) fixed by Daniel Andersson
693 daniel.andersson@sto.sema.se */
694 fprintf (stderr, "Media size %ld is less than block size %d\n",
695 aruntil, arbsize);
696 #else
697 fprintf (stderr, "Media size %ld is less than block size %d\n",
698 (unsigned long) aruntil, arbsize);
699 #endif
700 usage ();
701 }
702 if (arpad == 0)
703 arpad = arbsize;
704 if (fn != pass)
705 {
706 reg char *colon;
707 reg char *perc;
708 reg char *equal;
709 char *host;
710 reg int isoutput = (fn == out || fn == copyout);
711
712 arname = strcpy (arspec, av[optind++]);
713 if ((colon = strchr (arspec, ':')))
714 {
715 *colon++ = '\0';
716 if ((perc = strchr (arspec, '%')))
717 *perc++ = '\0';
718 if ((equal = strchr ((perc ? perc : arspec), '=')))
719 *equal++ = '\0';
720 if ((host=strchr(arspec,'@')))
721 *host++ = 0;
722 VOID sprintf (arname = remote,
723 "!%s %s%s %s '%s -%c -b %u -c %u %s'",
724 perc ? perc : "rsh",
725 host ? "-l ":"",
726 host ? arspec : "",
727 host ? host : arspec,
728 equal ? equal : myname,
729 isoutput ? 'O' : 'I', arbsize,
730 group, colon);
731 if( host )
732 *--host = '@';
733 if (equal)
734 *--equal = '=';
735 if (perc)
736 *--perc = '%';
737 *--colon = ':';
738 }
739 if (gflag && *arname != '/' && *arname != '!')
740 fatal (arspec, "Relative pathname");
741 VOID signal (SIGINT, goodbye);
742
743 if(buflen/1024L/1024L > (1024+512))
744 {
745 /* afio uses uints and ints at several places that make it
746 (on architectures with 32 bit ints and size_t) fail to do
747 the right calculations when the buffer size is >2GB.
748 This 1.5GB limit is somewhat conservative, but better
749 safe than sorry.
750
751 If you have an os/compile environment witrh 64 bit size_t
752 and int, things might be OK if you disable this test, but
753 I have not tested it.
754 */
755 fatal (arspec, "In-memory I/O buffer size above 1.5GB not supported");
756 }
757
758 /*
759 * +BLOCK is added to make sure we don't overrun buffer on a
760 * read (internal read(1) length is thus met)
761 */
762
763 if ((buffer = bufidx = bufend = malloc ((size_t)buflen + BLOCK)) == NULL)
764 fatal (arspec, "Cannot allocate enough memory for I/O buffer");
765
766 /* if in -o mode, do a sanity check on the input now. This
767 should prevent deletion of the archive file contents in most
768 cases when people who want to do afio -i accidentally type
769 afio -o. If not reading from a terminal, ignore check -- this
770 allows backup scripts to create empty archives.
771 */
772 if((fn == out)&&isatty(STDIN))
773 {
774 while(1)
775 {
776 if (lineget (stdin, firstfilename, PATHSIZE) < 0)
777 {
778 fatal("-o (write archive) mode", "could not read any file names from stdin");
779 }
780 if(strncmp(firstfilename,"//--",4)==0) break;
781 if (STAT (firstfilename, &tmpstat) < 0)
782 {
783 VOID warn (firstfilename, syserr ());
784 VOID warn (firstfilename, "-o (write archive) mode needs file names on stdin");
785 }
786 else break;
787 }
788 /* OK, if there was a good file name, then
789 now firstfilename[] has a non-NULL string, this indicates
790 to the openin function that it needs to use that string, not
791 read from stdin */
792 }
793
794 /*
795 * open the archive file
796 *
797 * open a floppy at the last moment (if output), otherwise now
798 * note we set arleft prematurely so we don't have to open the
799 * disk now
800 */
801 if (!Fflag || !isoutput)
802 {
803 if (nextopen (isoutput ? O_WRONLY : O_RDONLY) < 0)
804 goodbye (1);
805 }
806 else
807 arleft = aruntil;
808
809 }
810 timenow = time ((time_t *) NULL);
811 (*fn) (av + optind);
812 timedone = time ((time_t *) NULL);
813 if (uflag)
814 linkleft ();
815 if (vflag || (fn == toc))
816 fflush(stdout);
817
818 if(cpiowarned)
819 {
820 /* repeat warning message at end */
821 VOID warn_nocount(arspec,"Warning: Created archive is not fully compatible with cpio or afio versions 2.4.7 and lower.");
822 VOID warn_nocount(arspec,"See the ARCHIVE PORTABILITY section of the manpage.");
823 }
824
825 exitmsg="The operation was successful.";
826 if(warnings)
827 {
828 exitmsg=malloc(80);
829 if(exitmsg==NULL)
830 exitmsg="The operation HAD WARNINGS ABOUT ERRORS.";
831 else
832 sprintf(exitmsg,"The operation HAD %d WARNING%s ABOUT ERRORS.",warnings,warnings==1?"":"S");
833 }
834 if(anycorrupt) exitmsg="The operation FAILED.";
835
836
837 if (zflag)
838 {
839 reg FILE *stream;
840
841 stream = fn == toc || fn == copyin || arfd == STDOUT ? stderr : stdout;
842 VOID fprintf (stream, "%s: ", myname);
843 prsize (stream, total);
844 VOID fprintf (stream, " bytes %s in %lu seconds. %s\n",
845 fn == pass
846 ? "transferred"
847 : fn == out || fn == copyout
848 ? "written"
849 : "read",
850 timedone - timenow - timewait,
851 exitmsg);
852 }
853 if (logfile != (FILE *) 0)
854 {
855 VOID fprintf (logfile, "%s: Final count: ", myname);
856 prsize (logfile, total);
857 VOID fprintf (logfile,
858 " bytes %s in %lu seconds (+waited %lu seconds for disk swapping (%u disks)) finished at %s",
859 (fn == pass ? "transferred" : (fn == out
860 || fn == copyout ? "written" : "read")),
861 timedone - timenow - timewait,
862 timewait, arvolume, ctime (&timedone));
863 VOID fprintf (logfile,"%s\n",exitmsg);
864 }
865 nextclos ();
866
867 /* Added to lower chance of race condition (?) in rsh processing
868 when reading remote files */
869 if(fn==copyin) { fflush(stdout); fclose(stdout); sleep(2); }
870 if (email) mail(email,-1,arspec);
871
872 status=0;
873 if(anycorrupt) status=1;
874 if(warnings) if(index(ignorewarnings,(int)'a')==NULL) status=1;
875
876 goodbye (status);
877 /* NOTREACHED */
878 return 0; /* silence gcc -Wall */
879 }
880
881
882
883 /*
884 * update_aruntil()
885 *
886 * Sets the next aruntil-value out of the options-list
887 */
888 void update_aruntil()
889 {
890 char *next_aruntil_string = aruntil_string;
891
892 if(aruntil_string)
893 {
894 aruntil_string = strchr (aruntil_string, ',');
895 if(aruntil_string) *aruntil_string++='\0';
896
897 aruntil = optsize (next_aruntil_string);
898 }
899 }
900
901 /*
902 * mail()
903 *
904 * Mail tape change message
905 */
906 void mail(char *who,int vol,char *archive)
907 {
908 FILE *fp;
909 char cmd[1024];
910 char hostname[256];
911 gethostname(hostname,sizeof(hostname));
912 sprintf(cmd,"sendmail %s",who);
913 fp = popen(cmd,"w");
914 if (fp == NULL ) {
915 perror(cmd);
916 return;
917 }
918 fprintf(fp,"From: Afio archiver\n");
919 fprintf(fp,"Subject: %s %s: %s\n\n",hostname,archive,vol<0?"operation complete":"volume change needed");
920 fprintf(fp,"Hostname: %s\n",hostname);
921 fprintf(fp,"Archive : %s\n\n",archive);
922 if(vol>=0)
923 fprintf(fp,"Need change to volume #%d.\n\n",vol);
924 else
925 fprintf(fp,"Operation complete.\n\n");
926 pclose(fp);
927 }
928
929
930 /*
931 * copyin()
932 *
933 * Copy directly from the archive to the standard output.
934 */
935 STATIC VOIDFN
936 copyin (char **av)
937 {
938 reg ssize_t got;
939 reg ssize_t have;
940
941 if (*av)
942 fatal (*av, "Extraneous argument");
943 while (!areof || askfornext)
944 {
945 VOID infill ();
946 while ((have = bufend - bufidx))
947 if ((got = writeall (STDOUT, bufidx, have)) < 0)
948 fatal ("<stdout>", syserr ());
949 else
950 {
951 total+=have;
952 if (got > 0)
953 bufidx += got;
954 else
955 return;
956 }
957 }
958 }
959
960 /*
961 * copyout()
962 *
963 * Copy directly from the standard input to the archive.
964 */
965 STATIC VOIDFN
966 copyout (char **av)
967 {
968 reg int got;
969 reg uint want;
970
971 if (*av)
972 fatal (*av, "Extraneous argument");
973 for (;;)
974 {
975 while ((want = bufend - bufidx) == 0)
976 outflush (NOTDONE);
977 if ((got = read (STDIN, bufidx, want)) < 0)
978 fatal ("<stdin>", syserr ());
979 else if (got == 0)
980 break;
981 else
982 {
983 bufidx += got;
984 total += got; /* actually a bit too early for bytes written count */
985 }
986 }
987 outflush (DONE);
988 if (fflag)
989 outwait ();
990 }
991
992 /*
993 * dirchg()
994 *
995 * Change to the directory containing a given file.
996 */
997 STATIC int
998 dirchg (char *name, char *local)
999 {
1000 reg char *last;
1001 reg int len;
1002 auto char dir[PATHSIZE];
1003
1004 if (*name != '/')
1005 return (warn (name, "Relative pathname"));
1006 for (last = name + strlen (name); last[-1] != '/'; --last)
1007 ;
1008 len = last - name;
1009 strncpy (dir, name, (size_t)len)[len] = '\0';
1010 VOID strcpy (local, *last ? last : ".");
1011 if (strcmp (dir, pwd) == 0)
1012 return (0);
1013 if (chdir (dir) < 0)
1014 return (warn (name, syserr ()));
1015 VOID strcpy (pwd, dir);
1016 return (0);
1017 }
1018
1019 /*
1020 * dirmake()
1021 *
1022 * Make a directory. Returns zero if successful, -1 otherwise.
1023 */
1024 STATIC int
1025 dirmake (char *name, Stat *asb)
1026 {
1027 if (mkdir (name, asb->sb_mode & S_IPOPN) < 0)
1028 return (-1);
1029 /* First do the chown, then the chmod, because the chown may clear
1030 the suid/sgid bits we want to set.
1031 */
1032 if (xflag)
1033 VOID chown (name,
1034 (uid == 0 ? asb->sb_uid : uid),
1035 asb->sb_gid);
1036 if (asb->sb_mode & S_IPEXE)
1037 VOID chmod (name, asb->sb_mode & S_IPERM);
1038 return (0);
1039 }
1040
1041 /*
1042 * dirneed()
1043 *
1044 * Recursively create missing directories (with the same permissions
1045 * as their first existing parent). Temporarily modifies the 'name'
1046 * argument string. Returns zero if successful, -1 otherwise.
1047 */
1048 STATIC int
1049 dirneed (char *name)
1050 {
1051 reg char *cp;
1052 reg char *last;
1053 reg int ok;
1054 static Stat sb;
1055
1056 last = NULL;
1057 for (cp = name; *cp;)
1058 if (*cp++ == '/')
1059 last = cp;
1060 if (last == NULL)
1061 return (STAT (".", &sb));
1062 *--last = '\0';
1063 ok = STAT (*name ? name : "/", &sb) == 0
1064 ? ((sb.sb_mode & S_IFMT) == S_IFDIR)
1065 : (!dflag && dirneed (name) == 0 && dirmake (name, &sb) == 0);
1066 *last = '/';
1067 return (ok ? 0 : -1);
1068 }
1069
1070 /*
1071 * fatal()
1072 *
1073 * Print fatal message and exit.
1074 */
1075 STATIC void
1076 fatal (char *what, char *why)
1077 {
1078 /* print position in archive if some data was transferred */
1079 if(total>0)
1080 VOID warnarch ("Fatal error:",(off_t)0);
1081 VOID warn (what, why);
1082 goodbye (1);
1083 }
1084
1085
1086
1087 /*
1088 * writeall()
1089 *
1090 * Write all bytes in buf or return -1. Used to fix invalid assumptions
1091 * about write() elsewhere.
1092 */
1093 STATIC
1094 ssize_t writeall(int fd, const char *buf, size_t count)
1095 {
1096 ssize_t put;
1097 size_t totalput;
1098
1099 totalput=0;
1100 while(totalput<count)
1101 {
1102 put=write(fd,buf+totalput,count-totalput);
1103
1104 if(put<0) return put;
1105 totalput+=put;
1106 }
1107
1108 return count;
1109 }
1110
1111 /*
1112 * readall()
1113 *
1114 * Read, completely filling buf if we can, or return short size or -1.
1115 * Used to fix invalid assumptions
1116 * about read() elsewhere.
1117 */
1118 STATIC
1119 ssize_t readall(int fd, char *buf, size_t count)
1120 {
1121 ssize_t got;
1122 size_t totalgot;
1123
1124 totalgot=0;
1125 while(totalgot<count)
1126 {
1127 got=read(fd,buf+totalgot,count-totalgot);
1128 /* if(got!=count) printf("got on %d = %d\n",fd,got); */
1129 if(got<=0)
1130 {
1131 if(got==0) return totalgot;
1132 if(got<0) return got;
1133 }
1134 totalgot+=got;
1135 }
1136
1137 return count;
1138 }
1139
1140
1141 /*
1142 * mayberewind()
1143 *
1144 * implement -3 option
1145 */
1146 STATIC
1147 void mayberewind()
1148 {
1149 if(rewindfd>=1)
1150 {
1151 if(lseek(rewindfd,(off_t)0,SEEK_SET)<0)
1152 {
1153 fatal("-3 option",syserr());
1154 }
1155 }
1156 }
1157
1158
1159 /*
1160 * savedirstamp()
1161 *
1162 * Remember necessary timestamps for a directory,
1163 * so they can be restored afterwards.
1164 */
1165 STATIC void
1166 savedirstamp (char *name, time_t mtime)
1167 {
1168 Dir *dirp;
1169
1170 /* Note that the cast below is necessary since memget() is pre-C89. */
1171 if((dirp=(Dir *)memget(sizeof(Dir))) != NULL) {
1172 if ((dirp->d_name=memstr(name)) == NULL) {
1173 free(dirp);
1174 } else {
1175 dirp->d_mtime=mtime;
1176 dirp->d_forw=DirP;
1177 DirP=dirp;
1178 }
1179 }
1180 }
1181
1182 /*
1183 * restoredirstamps()
1184 *
1185 * Restore timestamps for the saved list of directories.
1186 */
1187 STATIC void
1188 restoredirstamps (void)
1189 {
1190 #ifdef linux_tstamp
1191 auto struct utimbuf tstamp;
1192 #else
1193 auto time_t tstamp[2];
1194 #endif
1195 Dir *DirP_curr = DirP; /* keep DirP reachable */
1196 Dir *DirP_forw;
1197 while(DirP_curr!=NULL)
1198 {
1199 #ifdef linux_tstamp
1200 tstamp.actime = DirP_curr->d_mtime;
1201 tstamp.modtime = DirP_curr->d_mtime;
1202 /* no error code checking on purpose */
1203 VOID utime (DirP_curr->d_name, &tstamp);
1204 #else
1205 tstamp[0] = DirP_curr->d_mtime;
1206 tstamp[1] = DirP_curr->d_mtime;
1207 /* no error code checking on purpose */
1208 VOID utime (DirP_curr->d_name, tstamp);
1209 #endif
1210 /* We don't call free because we are about to exit anyway.
1211 Not calling free should make things a bit more robust if the
1212 memory pool is corrupted due to a bug */
1213 /* free(DirP_curr->d_name); */
1214 DirP_forw=DirP_curr->d_forw;
1215 /* free(DirP_curr); */
1216 DirP_curr=DirP_forw;
1217 }
1218 }
1219
1220
1221 /*
1222 * in()
1223 *
1224 * Read an archive.
1225 */
1226 STATIC VOIDFN
1227 in (av)
1228 reg char **av;
1229 {
1230 auto Stat sb;
1231 auto char name[PATHSIZE];
1232 int sel,sel2,res;
1233
1234 if (*av)
1235 fatal (*av, "Extraneous argument");
1236 name[0] = '\0';
1237 while (inhead (name, &sb) == 0)
1238 {
1239 sel = (namecmp (name,&sb));
1240 if (sel)
1241 {
1242 if (inskip (sb.sb_size) < 0)
1243 VOID warn (name, "Skipped file data is corrupt");
1244 }
1245 else
1246 {
1247 if((sel2 = inentry (name, &sb)) != 0)
1248 VOID warn (name, "unpacking error");
1249 else
1250 if (vflag)
1251 {
1252 /* we cast to double and print as floating point because
1253 %Lu printing is buggy above 4G (at least with my C library). */
1254 if(printbytepos) fprintf(stderr,"%.0f ",(double)bytepos);
1255
1256 if (*uncompto)
1257 res = fprintf (stderr, "%s -- uncompressed\n", uncompto);
1258 else
1259 res = fprintf (stderr, "%s -- okay\n", name);
1260
1261 /* check for broken pipe on stderr */
1262 if(res<0) {
1263 if(errno == EPIPE)
1264 fatal("<stderr>", syserr());
1265 }
1266 }
1267 }
1268 }
1269 restoredirstamps();
1270 }
1271
1272
1273 /*
1274 * readcheck()
1275 *
1276 * Read an archive and check contents against existing files
1277 */
1278
1279 Stat atime_sb; /* set in openincheck */
1280 int atime_sb_valid; /* set in openincheck */
1281
1282 STATIC VOIDFN
1283 readcheck (av)
1284 reg char **av;
1285 {
1286 auto Stat sb;
1287 auto char name[PATHSIZE];
1288 auto char local[PATHSIZE];
1289 int sel, res;
1290 #ifdef linux_tstamp
1291 auto struct utimbuf tstamp;
1292 #else
1293 auto time_t tstamp[2];
1294 #endif
1295
1296 if (*av)
1297 fatal (*av, "Extraneous argument");
1298 name[0] = '\0';
1299 while (inhead (name, &sb) == 0)
1300 {
1301 if ((sel = namecmp (name,&sb)) < 0) {
1302 if (inskip (sb.sb_size) < 0)
1303 VOID warn (name, "Skipped file data is corrupt");
1304 continue;
1305 }
1306 if (vflag) {
1307 strcpy(local, name);
1308 tocentry (local, &sb);
1309 }
1310
1311 atime_sb_valid=0;
1312 if ((res = incheckentry(name, &sb)) < 0)
1313 inskip (sb.sb_size);
1314
1315 if(aflag && atime_sb_valid && ((sb.sb_mode & S_IFMT)==S_IFREG))
1316 {
1317 /* reset access time, this distroys the ctime btw. */
1318 #ifdef linux_tstamp
1319 tstamp.actime = atime_sb.sb_atime;
1320 tstamp.modtime = atime_sb.sb_mtime;
1321 VOID utime (name, &tstamp);
1322 #else
1323 tstamp[0] = atime_sb.sb_atime;
1324 tstamp[1] = atime_sb.sb_mtime;
1325 VOID utime (name, tstamp);
1326 #endif
1327 }
1328
1329
1330 }
1331 }
1332
1333 /*
1334 * inalloc()
1335 *
1336 * Allocate input buffer space (which was previously indexed
1337 * by inavail()).
1338 */
1339 STATIC void
1340 inalloc (uint len)
1341 {
1342 bufidx += len;
1343 total += len;
1344 }
1345
1346 /*
1347 * inascii()
1348 *
1349 * Read an ASCII header. Returns zero if successful;
1350 * -1 otherwise. Assumes that the entire magic number
1351 * has been read.
1352 */
1353
1354 STATIC int
1355 inascii (magic, name, asb)
1356 reg char *magic;
1357 reg char *name;
1358 reg Stat *asb;
1359 {
1360 auto uint namelen;
1361 auto char header[H_STRLEN + 1];
1362 PStat pasb;
1363
1364 if (strncmp (magic, M_ASCII, M_STRLEN) != 0)
1365 return (-1);
1366
1367 if (inread (header, H_STRLEN) < 0)
1368 return (warnarch ("Corrupt ASCII header", (off_t) H_STRLEN));
1369 header[H_STRLEN] = '\0';
1370
1371 if (sscanf (header, PH_SCAN, &pasb.PSt_dev,
1372 &pasb.PSt_ino, &pasb.PSt_mode, &pasb.PSt_uid,
1373 &pasb.PSt_gid, &pasb.PSt_nlink, &pasb.PSt_rdev,
1374 &pasb.PSt_mtime, &namelen, &pasb.PSt_size) != H_COUNT)
1375 return (warnarch ("Bad ASCII header", (off_t) H_STRLEN));
1376 /* now, we let the compiler cast the info to the right types (field sizes) */
1377 asb->sb_dev = pasb.PSt_dev;
1378 asb->sb_ino = pasb.PSt_ino;
1379 asb->sb_mode = pasb.PSt_mode;
1380 asb->sb_uid = pasb.PSt_uid;
1381 asb->sb_gid = pasb.PSt_gid;
1382 asb->sb_nlink = pasb.PSt_nlink;
1383 asb->sb_rdev = pasb.PSt_rdev;
1384 asb->sb_mtime = pasb.PSt_mtime;
1385 asb->sb_size = pasb.PSt_size;
1386 if (namelen == 0 || namelen >= PATHSIZE)
1387 return (warnarch ("Bad ASCII pathname length", (off_t) H_STRLEN));
1388 if (inread (name, namelen) < 0)
1389 return (warnarch ("Corrupt ASCII pathname", (off_t) namelen));
1390 if (name[namelen - 1] != '\0')
1391 return (warnarch ("Bad ASCII pathname", (off_t) namelen));
1392 return (0);
1393 }
1394
1395
1396
1397 /*
1398 * inascii2()
1399 *
1400 * Read an ASCII header (new format). Returns zero if successful;
1401 * -1 otherwise. Assumes that the entire magic number
1402 * has been read.
1403 */
1404
1405 STATIC int
1406 inascii2 (char *magic, char *name, Stat *asb)
1407 {
1408 auto uint namelen;
1409 auto char header[H_STRLEN2 + 1];
1410 PStat pasb;
1411
1412 if (strncmp (magic, M_ASCII2, M_STRLEN) != 0)
1413 return (-1);
1414 if (inread (header, H_STRLEN2) < 0)
1415 return (warnarch ("Corrupt extended ASCII header", (off_t) H_STRLEN2));
1416 header[H_STRLEN2] = '\0';
1417 if (sscanf (header, PH_SCAN2, &pasb.PSt_dev,
1418 &pasb.PSt_ino, &pasb.PSt_mode, &pasb.PSt_uid,
1419 &pasb.PSt_gid, &pasb.PSt_nlink, &pasb.PSt_rdev,
1420 &pasb.PSt_mtime, &namelen, &pasb.PSt_size) != H_COUNT)
1421 return (warnarch ("Bad extended ASCII header", (off_t) H_STRLEN));
1422 /* now, we let the compiler cast the info to the right types (field sizes) */
1423 asb->sb_dev = pasb.PSt_dev;
1424 asb->sb_ino = pasb.PSt_ino;
1425 asb->sb_mode = pasb.PSt_mode;
1426 asb->sb_uid = pasb.PSt_uid;
1427 asb->sb_gid = pasb.PSt_gid;
1428 asb->sb_nlink = pasb.PSt_nlink;
1429 asb->sb_rdev = pasb.PSt_rdev;
1430 asb->sb_mtime = pasb.PSt_mtime;
1431 asb->sb_size = pasb.PSt_size;
1432
1433 if (namelen == 0 || namelen >= PATHSIZE)
1434 return (warnarch ("Bad ASCII pathname length", (off_t) H_STRLEN));
1435 if (inread (name, namelen) < 0)
1436 return (warnarch ("Corrupt ASCII pathname", (off_t) namelen));
1437 if (name[namelen - 1] != '\0')
1438 return (warnarch ("Bad ASCII pathname", (off_t) namelen));
1439 return (0);
1440 }
1441
1442
1443 /*
1444 * inascii3()
1445 *
1446 * Read an ASCII header (large format). Returns zero if successful;
1447 * -1 otherwise. Assumes that the entire magic number
1448 * has been read.
1449 */
1450
1451 STATIC int
1452 inascii3 (magic, name, asb)
1453 reg char *magic;
1454 reg char *name;
1455 reg Stat *asb;
1456 {
1457 auto uint namelen;
1458 auto char header[H_STRLEN3 + 1];
1459 PHStat pasb;
1460 uint specialflags;
1461 uint extraheaderlen;
1462
1463 if (strncmp (magic, M_ASCII3, M_STRLEN) != 0)
1464 return (-1);
1465 if (inread (header, H_STRLEN3) < 0)
1466 return (warnarch ("Corrupt extended ASCII3 header", (off_t) H_STRLEN3));
1467 header[H_STRLEN3] = '\0';
1468 if (sscanf (header, PH_SCAN3, &pasb.PSt_dev,
1469 &pasb.PSt_ino, &pasb.PSt_mode, &pasb.PSt_uid,
1470 &pasb.PSt_gid, &pasb.PSt_nlink, &pasb.PSt_rdev,
1471 &pasb.PSt_mtime, &namelen, &specialflags, &extraheaderlen, &pasb.PSt_size) != H_COUNT3)
1472 return (warnarch ("Bad extended ASCII3 header", (off_t) H_STRLEN));
1473 /* now, we let the compiler cast the info to the right types (field sizes) */
1474 asb->sb_dev = pasb.PSt_dev;
1475 asb->sb_ino = pasb.PSt_ino;
1476 asb->sb_mode = pasb.PSt_mode;
1477 asb->sb_uid = pasb.PSt_uid;
1478 asb->sb_gid = pasb.PSt_gid;
1479 asb->sb_nlink = pasb.PSt_nlink;
1480 asb->sb_rdev = pasb.PSt_rdev;
1481 asb->sb_mtime = pasb.PSt_mtime;
1482 asb->sb_size = pasb.PSt_size;
1483
1484 if (namelen == 0 || namelen >= PATHSIZE)
1485 return (warnarch ("Bad ASCII pathname length", (off_t) H_STRLEN));
1486 if (inread (name, namelen) < 0)
1487 return (warnarch ("Corrupt ASCII pathname", (off_t) namelen));
1488 if (name[namelen - 1] != '\0')
1489 return (warnarch ("Bad ASCII pathname", (off_t) namelen));
1490 if (inskip ((off_t)extraheaderlen) < 0)
1491 return (warnarch ("Corrupt header", (off_t) 0));
1492 return (0);
1493 }
1494
1495
1496 /*
1497 * inavail()
1498 *
1499 * Index availible input data within the buffer. Stores a pointer
1500 * to the data and its length in given locations. Returns zero with
1501 * valid data, -1 if unreadable portions were replaced with nulls.
1502 */
1503 STATIC int
1504 inavail (bufp, lenp)
1505 reg char **bufp;
1506 uint *lenp;
1507 {
1508 reg uint have;
1509 reg int corrupt = 0;
1510
1511 while ((have = bufend - bufidx) == 0)
1512 corrupt |= infill ();
1513 *bufp = bufidx;
1514 *lenp = have;
1515 return (corrupt);
1516 }
1517
1518 /*
1519 * inbinary()
1520 *
1521 * Read a binary header. Returns the number of trailing alignment
1522 * bytes to skip; -1 if unsuccessful.
1523 */
1524 STATIC int
1525 inbinary (magic, name, asb)
1526 reg char *magic;
1527 reg char *name;
1528 reg Stat *asb;
1529 {
1530 reg uint namefull;
1531 auto Binary binary;
1532
1533 if ((int) *((ushort *) magic) != M_BINARY)
1534 return (-1);
1535 memcpy ((char *) &binary,
1536 magic + sizeof (ushort),
1537 M_STRLEN - sizeof (ushort));
1538 if (inread ((char *) &binary + M_STRLEN - sizeof (ushort),
1539 sizeof (binary) - (M_STRLEN - sizeof (ushort))) < 0)
1540 return (warnarch ("Corrupt binary header",
1541 (off_t) sizeof (binary) - (M_STRLEN - sizeof (ushort))));
1542 asb->sb_dev = binary.b_dev;
1543 asb->sb_ino = binary.b_ino;
1544 asb->sb_mode = binary.b_mode;
1545 asb->sb_uid = binary.b_uid;
1546 asb->sb_gid = binary.b_gid;
1547 asb->sb_nlink = binary.b_nlink;
1548 asb->sb_rdev = binary.b_rdev;
1549 asb->sb_mtime = binary.b_mtime[0] << 16 | binary.b_mtime[1];
1550 asb->sb_size = binary.b_size[0] << 16 | binary.b_size[1];
1551 if (binary.b_name == 0 || binary.b_name >= PATHSIZE)
1552 return (warnarch ("Bad binary pathname length",
1553 (off_t) sizeof (binary) - (M_STRLEN - sizeof (ushort))));
1554 if (inread (name, namefull = binary.b_name + binary.b_name % 2) < 0)
1555 return (warnarch ("Corrupt binary pathname", (off_t) namefull));
1556 if (name[binary.b_name - 1] != '\0')
1557 return (warnarch ("Bad binary pathname", (off_t) namefull));
1558 return (asb->sb_size % 2);
1559 }
1560
1561 /*
1562 * indata()
1563 *
1564 * Install data from an archive. Returns given file descriptor.
1565 */
1566 STATIC int
1567 indata (fd, size, name)
1568 int fd;
1569 reg off_t size;
1570 char *name;
1571 {
1572 reg size_t chunk;
1573 reg char *oops;
1574 reg ssize_t sparse;
1575 reg int corrupt;
1576 auto char *buf;
1577 auto uint avail;
1578
1579 corrupt = sparse = 0;
1580 oops = NULL;
1581 while (size)
1582 {
1583 corrupt |= inavail (&buf, &avail);
1584 size -= (chunk = size < (off_t)avail ? (uint) size : avail);
1585 if (oops == NULL && (sparse = fswrite (fd, buf, chunk)) < 0)
1586 oops = syserr ();
1587 inalloc (chunk);
1588 }
1589 if (corrupt)
1590 VOID warn (name, "Corrupt archive data");
1591 if (oops)
1592 VOID warn (name, oops);
1593 else if (sparse > 0
1594 && (lseek (fd, (off_t) - 1, 1) < 0
1595 || write (fd, "", 1) != 1))
1596 VOID warn (name, syserr ());
1597 return (fd);
1598 }
1599
1600 /*
1601 * incheckdata()
1602 *
1603 * Check data from an archive. Returns given file descriptor.
1604 */
1605 STATIC int
1606 incheckdata (int fd, off_t size, char *name, Stat *asb, int comp)
1607 {
1608 reg uint chunk;
1609 reg char *oops;
1610 reg int corrupt, warned = 0;
1611 auto char *buf;
1612 auto uint avail;
1613 auto int pfd[2], pfdc[2];
1614 auto int pid, comppid;
1615
1616 corrupt = 0;
1617 oops = NULL;
1618 if (comp) {
1619 /* if compressed, we process data with the following setup:
1620 - child 1 is the comparator
1621 - child 2 is the gunzip (gzip -c -d)
1622 - the main process reads data from the archive and writes it
1623 to child 2 to be uncompressed
1624 - child 2 writes the uncompressed data to child 1
1625 - child 1 reads from the file in the filesystem and from child 2,
1626 compares, and exits nonzero if is a discrepancy.
1627 */
1628
1629 if (pipe(pfd) < 0) {
1630 perror("pipe"); exit(1);
1631 }
1632 switch ((pid = xfork("incheckdata, decompressing", NODIE))) {
1633 case -1:
1634 perror("fork");
1635 exit(1);
1636 /* child 1 start ======================== */
1637 case 0: /* child */
1638 VOID close (pfd[1]);
1639 if (arfd != STDIN && arfd != STDOUT) VOID close (arfd);
1640 if (pipe(pfdc) < 0) {
1641 perror("pipe"); exit(1);
1642 }
1643 switch ((comppid = xfork ("incheckdata, decomp", NODIE))) {
1644 case -1:
1645 perror("fork");
1646 exit(1);
1647 /* child 2 start ======================== */
1648 case 0: /* child */
1649 VOID close (pfdc[0]);
1650 VOID close (fileno (stdin));
1651 VOID dup (pfd[0]);
1652 VOID close (pfd[0]);
1653 VOID close (fileno (stdout));
1654 if (dup (pfdc[1]) < 0)
1655 exit(1);
1656 close(pfdc[1]);
1657 mayberewind();
1658 if(compressargs)
1659 execvp (compressprog, compress_arg_list);
1660 else
1661 execlp (compressprog, compressprog, "-d", "-c", NULL);
1662 fprintf (stderr, "Could not uncompress, errno %d\n", errno);
1663 exit(1);
1664 break;
1665 /* child 2 end ======================== */
1666 /* child 1 continued ======================== */
1667 default:
1668 {
1669 char buff1[40960];
1670 char buff2[40960];
1671 size_t n;
1672 ssize_t n1, n2;
1673
1674 close(pfdc[1]);
1675 n1 = n2 = 1;
1676 while ((n1 > 0) && (n2 > 0)) {
1677 n = sizeof(buff1);
1678 n1 = readall(fd, buff1, n);
1679 n2 = readall(pfdc[0], buff2, n);
1680 size -= n1;
1681 if (n1 < 0 || n2 < 0 || n1 != n2) {
1682 VOID warn_nocount (name, "File in archive has different length than file on filesystem");
1683 corrupt = 1;
1684 break;
1685 }
1686 else {
1687 if (memcmp(buff1, buff2, (size_t)n1) != 0) {
1688 if (!warned++)
1689 VOID warn_nocount (name, "File in archive has different data than file on filesystem");
1690 corrupt = 1;
1691 }
1692 }
1693 }
1694 if (corrupt)
1695 kill(comppid, SIGTERM);
1696 close(pfdc[0]);
1697 close(fd);
1698 if (xwait (comppid, "incheckentry xwait() gunzip", FALSE) != 0) {
1699 warn(name, "uncompressing failure");
1700 corrupt = 1;
1701 }
1702 exit(corrupt ? 2 : 0);
1703 }
1704 }
1705 /* child 2 end ======================== */
1706 default:
1707 /* main process continue ======================== */
1708 close(pfd[0]);
1709 uncompressrun = pid;
1710 while (asb->sb_size) {
1711 corrupt |= inavail (&buf, &avail);
1712 if (corrupt) {
1713 break;
1714 }
1715 asb->sb_size -= (chunk = asb->sb_size < (off_t)avail ? (uint) asb->sb_size : avail);
1716 if (writeall (pfd[1], buf, chunk) < 0)
1717 oops = syserr();
1718 inalloc(chunk);
1719 }
1720 close(pfd[1]);
1721 corrupt |= (xwait (pid, "incheckentry xwait()", FALSE) != 0);
1722 break;
1723 }
1724 }
1725 else { /* not compressed */
1726 char buff1[40960];
1727 ssize_t n1, n2;
1728 ssize_t n;
1729 while (asb->sb_size && !corrupt) {
1730 if (!(corrupt |= inavail (&buf, &avail))) {
1731 /* cast of asb->sb_size (which can be 8 byte) only happens when
1732 the value fits in size_t (which is usually 4 byte) */
1733 n2 = asb->sb_size < (off_t)avail ? (size_t) asb->sb_size : avail;
1734 n = (n2 < (ssize_t)sizeof(buff1)) ? n2 : (ssize_t)sizeof(buff1);
1735 n1 = readall(fd, buff1, n);
1736 asb->sb_size -= n;
1737 if (n1 < 0 || n2 < 0 || n1 != n)
1738 {
1739 if(n1!=n)
1740 VOID warn_nocount (name, "File in archive has different length than file on filesystem");
1741 corrupt = 1;
1742 }
1743 else
1744 {
1745 if( memcmp(buff1, buf, n) != 0 )
1746 {
1747 VOID warn_nocount (name, "File in archive has different data than file on filesystem");
1748 corrupt = 1;
1749 }
1750 }
1751 inalloc((uint)n);
1752 }
1753 }
1754 /* See if the file is _longer_ then our backup. */
1755 if (read(fd, buff1, 1) > 0)
1756 {
1757 VOID warn_nocount (name, "File in archive is shorter than file on filesystem");
1758 corrupt = 1;
1759 }
1760 }
1761 close(fd);
1762 if (oops)
1763 VOID warn (name, oops);
1764 if (corrupt) {
1765 /*
1766 file : Stat atime_sb
1767 archive : Stat *asb
1768 */
1769 if ( (atime_sb.sb_mtime==asb->sb_mtime) &&
1770 (atime_sb.sb_size==asb->sb_size))
1771 {
1772 /* file has same mod time and length --> should have verified OK,
1773 so this is very probably a real error in the backup medium.
1774 */
1775 VOID warn (name, "File data in archive is corrupt");
1776 anycorrupt=1;
1777 }
1778 else
1779 {
1780 VOID warn (name, "Archive headers indicate that file on filesystem was modified during or after archive was made");
1781
1782 if(index(ignorewarnings,(int)'r'))
1783 {
1784 warn_nocount(name, "Not counting this as a verification error");
1785 warnings--;
1786 }
1787 else
1788 anycorrupt=1;
1789
1790 }
1791
1792 return -1;
1793 }
1794 return 0;
1795 }
1796
1797 /*
1798 * inentry()
1799 *
1800 * Install a single archive entry. Returns zero if successful, -1 otherwise.
1801 */
1802 STATIC int
1803 inentry (name, asb)
1804 char *name;
1805 reg Stat *asb;
1806 {
1807 reg Link *linkp;
1808 reg int ifd;
1809 reg int ofd;
1810 #ifdef linux_tstamp
1811 auto struct utimbuf tstamp;
1812 #else
1813 auto time_t tstamp[2];
1814 #endif
1815 int result;
1816 result=0;
1817
1818 if ((ofd = openotty (name, asb, linkp = linkfrom (asb,1), 0, Zflag)) > 0)
1819 {
1820 if (asb->sb_size || linkp == NULL || linkp->l_size == 0)
1821 VOID close (indata (ofd, asb->sb_size, name));
1822 else if ((ifd = open (linkp->l_path->p_name, O_RDONLY)) < 0)
1823 VOID warn (linkp->l_path->p_name, syserr ());
1824 else
1825 {
1826 passdata (linkp->l_path->p_name, ifd, name, ofd);
1827 VOID close (ifd);
1828 VOID close (ofd);
1829 }
1830 /* safety */
1831 if (uncompressrun)
1832 {
1833 result = xwait (uncompressrun, "inentry xwait()", TRUE);
1834 uncompressrun = 0;
1835 if(result!=0) result=-1;
1836 }
1837 }
1838 else if (ofd < 0)
1839 return (-1);
1840 else if (inskip (asb->sb_size) < 0)
1841 VOID warn (name, "Redundant file data is corrupt");
1842
1843 /* Cannot set utime on symlink (at least not under Linux) */
1844 if((asb->sb_mode & S_IFMT) != S_IFLNK)
1845 {
1846 #ifdef linux_tstamp
1847 tstamp.actime = tstamp.modtime = mflag ? timenow : asb->sb_mtime;
1848 VOID utime (name, &tstamp);
1849 #else
1850 tstamp[0] = tstamp[1] = mflag ? timenow : asb->sb_mtime;
1851 VOID utime (name, tstamp);
1852 #endif
1853 }
1854
1855 return (result);
1856 }
1857
1858 /*
1859 * incheckentry()
1860 *
1861 * Check a single archive entry. Returns zero if successful, -1 otherwise.
1862 */
1863 STATIC int
1864 incheckentry (name, asb)
1865 char *name;
1866 reg Stat *asb;
1867 {
1868 reg int ifd;
1869 auto int compression;
1870
1871 if (ISCONTROL(asb))
1872 {
1873 /* process control file */
1874 if(inentry (name, asb) < 0)
1875 if (inskip (asb->sb_size) < 0)
1876 VOID warn (name, "Skipped file data is corrupt");
1877
1878 /* do not verify the control file, return success */
1879 return(0);
1880 }
1881
1882 uncompressrun = 0;
1883
1884 /* The exact logic below here, and inside openincheck and
1885 incheckdata, is questionable -- it will not catch all faulty
1886 situations as being a definate error. It will work in 99.9% of
1887 the error cases though, so I am not touching it... -- KH */
1888
1889 if ((ifd = openincheck (name, asb, &compression, Zflag)) > 0)
1890 {
1891 if (asb->sb_size)
1892 return incheckdata(ifd, asb->sb_size, name, asb, compression);
1893 }
1894 else if (ifd < 0) /* some strangeness occured in in archive file */
1895 {
1896 anycorrupt = -1;
1897 return (-1);
1898 }
1899 else if (inskip (asb->sb_size) < 0)
1900 VOID warn (name, "Redundant file data is corrupt");
1901 if (ifd > 0)
1902 close(ifd);
1903 return (0);
1904 }
1905
1906 /*
1907 * infill()
1908 *
1909 * Fill the archive buffer. Remembers mid-buffer read failures and
1910 * reports them the next time through. Replaces unreadable data with
1911 * null characters. Returns zero with valid data, -1 otherwise.
1912 */
1913 STATIC int
1914 infill ()
1915 {
1916 reg int got;
1917 static int failed;
1918 ulonglong ullreadsize;
1919 size_t readsize;
1920
1921 bufend = bufidx = buffer;
1922 if (!failed)
1923 {
1924 if (areof)
1925 {
1926 if (total == 0)
1927 {
1928 fatal (arspec, "No input");
1929 }
1930 else
1931 {
1932 if((aruntil!=0) || askfornext)
1933 {
1934 next (O_RDONLY, "Input EOF");
1935 }
1936 else
1937 {
1938 fatal (arspec, "Premature input EOF");
1939 }
1940 }
1941 }
1942 #if 0
1943 fprintf(stderr,"aruntil=%lld arleft=%lld arbsize=%d\n",aruntil,arleft,arbsize);
1944 #endif
1945 if (aruntil && (arleft == 0))
1946 next (O_RDONLY, "Input limit reached");
1947
1948 if(aruntil) ullreadsize=arleft; else ullreadsize=buffer + buflen - bufend;
1949 if(ullreadsize>arbsize) ullreadsize=arbsize;
1950
1951 readsize=(size_t)ullreadsize;
1952
1953
1954 while (!failed
1955 && !areof
1956 && (aruntil == 0 || arleft >= (ulonglong)readsize)
1957 && (off_t)(buffer - bufend) + buflen >= (off_t)readsize)
1958 {
1959 if ((got = read (arfd, bufend, readsize)) > 0)
1960 {
1961 bufend += got;
1962 arleft -= got;
1963 }
1964 else if (got < 0)
1965 failed = warnarch (syserr (),
1966 (off_t) 0 - (bufend - bufidx));
1967 else
1968 ++areof;
1969 }
1970 }
1971 if (failed && bufend == buffer)
1972 {
1973 failed = 0;
1974 for (got = 0; (uint)got < arbsize; ++got)
1975 *bufend++ = '\0';
1976 return (-1);
1977 }
1978 return (0);
1979 }
1980
1981
1982 /*
1983 * fixinsecure()
1984 *
1985 * Rewrite .. subpath components in path names into XX,
1986 * making them more secure for restoring. For more info see the -8 option
1987 * in the manpage.
1988 */
1989 STATIC int
1990 fixinsecure (name)
1991 char *name;
1992 {
1993 int changed=0;
1994 int l=strlen(name);
1995 int i;
1996 if(strcmp("..",name)==0)
1997 {
1998 changed=1;
1999 name[0]=name[1]='X';
2000 }
2001 if(strncmp("../",name,3)==0)
2002 {
2003 changed=1;
2004 name[0]=name[1]='X';
2005 }
2006
2007 for(i=0; i<l-3; i++)
2008 {
2009 if(name[i]=='/')
2010 {
2011 if(strncmp("/../",name+i,4)==0)
2012 {
2013 changed=1;
2014 name[i+1]=name[i+2]='X';
2015 }
2016 }
2017 }
2018
2019
2020 if(l>=3) if(strncmp("/..",name+l-3,3)==0)
2021 {
2022 changed=1;
2023 name[l-2]=name[l-1]='X';
2024 }
2025
2026 return changed;
2027 }
2028
2029 /*
2030 * inhead()
2031 *
2032 * Read a header. Quietly translates old-fashioned binary cpio headers
2033 * (and arranges to skip the possible alignment byte). Returns zero if
2034 * successful, -1 upon archive trailer.
2035 */
2036 STATIC int
2037 inhead (name, asb)
2038 reg char *name;
2039 reg Stat *asb;
2040 {
2041 reg off_t skipped;
2042 auto char magic[M_STRLEN];
2043 static int align;
2044 char *name2;
2045 int rewritten;
2046
2047 #if FDDEBUG
2048 /* debug code added by KH. Are we leaking file descriptors? */
2049 { int i; i=dup(0); close(i); fprintf(stderr,"%d",i); }
2050 #endif
2051
2052 if (align > 0)
2053 VOID inskip ((off_t) align);
2054 align = 0;
2055
2056 bytepos=total; /* position of current file */
2057
2058 for (;;)
2059 {
2060 VOID inread (magic, M_STRLEN);
2061 skipped = 0;
2062
2063 while ( ((align = inascii (magic, name, asb)) < 0)
2064 && ((align = inascii2 (magic, name, asb)) < 0)
2065 && ((align = inascii3 (magic, name, asb)) < 0)
2066 && ((align = inbinary (magic, name, asb)) < 0)
2067 && ((align = inswab (magic, name, asb)) < 0))
2068 {
2069 if (++skipped == 1)
2070 {
2071 if (!kflag && total - sizeof (magic) == 0)
2072 {
2073 warn(arspec,"Input does not start with valid archive header.");
2074 warn(arspec,"Use the -k option to start reading in the middle of an archive.");
2075 fatal (arspec, "Unrecognizable archive");
2076
2077 }
2078 VOID warnarch ("Bad magic number",
2079 (off_t) sizeof (magic));
2080 if (name[0])
2081 VOID warn (name, "May be corrupt");
2082 }
2083 memcpy (magic, magic + 1, sizeof (magic) - 1);
2084 VOID inread (magic + sizeof (magic) - 1, 1);
2085 }
2086 if (skipped)
2087 {
2088 VOID warnarch ("Apparently resynchronized",
2089 (off_t) sizeof (magic));
2090 VOID warn (name, "Continuing");
2091 }
2092 if (strcmp (name, TRAILER) == 0)
2093 return (-1);
2094 if (nameopt (name) >= 0)
2095 break;
2096 VOID inskip (asb->sb_size + align);
2097 }
2098 #ifdef S_IFLNK
2099 if ((asb->sb_mode & S_IFMT) == S_IFLNK)
2100 {
2101 /* buffer overflow protection */
2102 if((uint) asb->sb_size > sizeof(asb->sb_link)-1)
2103 {
2104 VOID warn (name, "Corrupt symbolic link");
2105 return (inhead (name, asb));
2106 }
2107 if (inread (asb->sb_link, (uint) asb->sb_size) < 0)
2108 {
2109 VOID warn (name, "Corrupt symbolic link");
2110 return (inhead (name, asb));
2111 }
2112 asb->sb_link[asb->sb_size] = '\0';
2113 asb->sb_size = 0;
2114
2115 rewritten=0;
2116 if(!allowinsecuresymlinks)
2117 {
2118 if(asb->sb_link[0]=='/')
2119 {
2120 asb->sb_link[0]='X';
2121 rewritten=1;
2122 }
2123 if(fixinsecure (asb->sb_link)) rewritten=1;
2124 if(rewritten)
2125 {
2126 VOID warn_nocount (name,"potentially insecure symlink destination path, rewriting:");;
2127 VOID warn(asb->sb_link,"is the rewritten destination value used");
2128 if(index(ignorewarnings,(int)'s')) warnings--;
2129 }
2130 }
2131 }
2132 #endif /* S_IFLNK */
2133 if ((name[0] == '/') && !abspaths)
2134 {
2135 /* if there was more than 1 leading /, nameopt() has already
2136 removed all leading / but one */
2137 if (name[1])
2138 {
2139 name2=name;
2140 while ((name2[0] = name2[1])) ++name2;
2141 }
2142 else
2143 {
2144 name[0] = '.';
2145 }
2146 }
2147 if(!allowinsecurepaths)
2148 {
2149 if(fixinsecure(name))
2150 {
2151 VOID warn (name,"potentially insecure destination path rewritten");
2152 if(index(ignorewarnings,(int)'s')) warnings--;
2153 }
2154 }
2155
2156 asb->sb_atime = asb->sb_ctime = asb->sb_mtime;
2157 return (0);
2158 }
2159
2160 /*
2161 * inread()
2162 *
2163 * Read a given number of characters from the input archive. Returns
2164 * zero with valid data, -1 if unreadable portions were replaced by
2165 * null characters.
2166 */
2167 STATIC int
2168 inread (dst, len)
2169 reg char *dst;
2170 uint len;
2171 {
2172 reg uint have;
2173 reg uint want;
2174 reg int corrupt = 0;
2175 char *endx = dst + len;
2176
2177 while ((want = endx - dst))
2178 {
2179 while ((have = bufend - bufidx) == 0)
2180 corrupt |= infill ();
2181 if (have > want)
2182 have = want;
2183 memcpy (dst, bufidx, have);
2184 bufidx += have;
2185 dst += have;
2186 total += have;
2187 }
2188 return (corrupt);
2189 }
2190
2191 /*
2192 * inskip()
2193 *
2194 * Skip input archive data. Returns zero under normal circumstances,
2195 * -1 if unreadable data is encountered.
2196 */
2197 STATIC int
2198 inskip (len)
2199 reg off_t len;
2200 {
2201 reg uint chunk;
2202 reg int corrupt = 0;
2203
2204 while (len)
2205 {
2206 while ((chunk = bufend - bufidx) == 0)
2207 corrupt |= infill ();
2208 if ((off_t)chunk > len)
2209 chunk = len;
2210 bufidx += chunk;
2211 len -= chunk;
2212 total += chunk;
2213 }
2214 return (corrupt);
2215 }
2216
2217 /*
2218 * inswab()
2219 *
2220 * Read a reversed byte order binary header. Returns the number
2221 * of trailing alignment bytes to skip; -1 if unsuccessful.
2222 */
2223 STATIC int
2224 inswab (magic, name, asb)
2225 reg char *magic;
2226 reg char *name;
2227 reg Stat *asb;
2228 {
2229 reg ushort namesize;
2230 reg uint namefull;
2231 auto Binary binary;
2232
2233 if ((int) *((ushort *) magic) != swab (M_BINARY))
2234 return (-1);
2235 memcpy ((char *) &binary,
2236 magic + sizeof (ushort),
2237 M_STRLEN - sizeof (ushort));
2238 if (inread ((char *) &binary + M_STRLEN - sizeof (ushort),
2239 sizeof (binary) - (M_STRLEN - sizeof (ushort))) < 0)
2240 return (warnarch ("Corrupt swapped header",
2241 (off_t) sizeof (binary) - (M_STRLEN - sizeof (ushort))));
2242 asb->sb_dev = (dev_t) swab (binary.b_dev);
2243 asb->sb_ino = (ino_t) swab (binary.b_ino);
2244 asb->sb_mode = swab (binary.b_mode);
2245 asb->sb_uid = swab (binary.b_uid);
2246 asb->sb_gid = swab (binary.b_gid);
2247 asb->sb_nlink = swab (binary.b_nlink);
2248 asb->sb_rdev = (dev_t) swab (binary.b_rdev);
2249 asb->sb_mtime = swab (binary.b_mtime[0]) << 16 | swab (binary.b_mtime[1]);
2250 asb->sb_size = swab (binary.b_size[0]) << 16 | swab (binary.b_size[1]);
2251 if ((namesize = swab (binary.b_name)) == 0 || namesize >= PATHSIZE)
2252 return (warnarch ("Bad swapped pathname length",
2253 (off_t) sizeof (binary) - (M_STRLEN - sizeof (ushort))));
2254 if (inread (name, namefull = namesize + namesize % 2) < 0)
2255 return (warnarch ("Corrupt swapped pathname", (off_t) namefull));
2256 if (name[namesize - 1] != '\0')
2257 return (warnarch ("Bad swapped pathname", (off_t) namefull));
2258 return (asb->sb_size % 2);
2259 }
2260
2261 /*
2262 * lineget()
2263 *
2264 * Get a line from a given stream. Returns 0 if successful, -1 at EOF.
2265 */
2266 STATIC int
2267 lineget (stream, buf, bufsize)
2268 reg FILE *stream;
2269 reg char *buf;
2270 int bufsize;
2271 {
2272 reg int c;
2273 int size;
2274 char *bufstart;
2275
2276 size=0;
2277 bufstart=buf;
2278
2279 for (;;)
2280 {
2281 if ((c = getc (stream)) == EOF)
2282 return (-1);
2283 if ((!flag0 && c == '\n') || (flag0 && c == '\0'))
2284 break;
2285 if(size<bufsize-1)
2286 *buf++ = c;
2287 size++;
2288
2289 }
2290 *buf = '\0';
2291
2292 if(size>bufsize-1)
2293 warn(bufstart,"Path name too long, truncated");
2294
2295 return (0);
2296 }
2297
2298 /*
2299 * linkalso()
2300 *
2301 * Add a destination pathname to an existing chain. Assumes that
2302 * at least one element is present.
2303 */
2304 STATIC void
2305 linkalso (linkp, name)
2306 reg Link *linkp;
2307 char *name;
2308 {
2309 reg Path *path;
2310
2311 if (((path = (Path *) memget (sizeof (Path))) == NULL)
2312 || ((path->p_name = memstr (name)) == NULL))
2313 return;
2314 path->p_forw = NULL;
2315 path->p_back = linkp->l_path->p_back;
2316 path->p_back->p_forw = path;
2317 linkp->l_path->p_back = path;
2318 }
2319
2320 /*
2321 * linkfrom()
2322 *
2323 * Find a file to link from. Returns a pointer to a link
2324 * structure, or NULL if unsuccessful.
2325 */
2326 /* In v2.4.4: added some checks which would be redundant if not
2327 for the fact that the standard archive format only stores the
2328 lower 16 bits of the inode number.
2329 The checks reduce the chance of false matches when, reading archives
2330 produced by older afio versions and by cpio in the old ascii
2331 format.
2332 */
2333 STATIC Link *
2334 linkfrom (asb, installing)
2335 reg Stat *asb;
2336 int installing;
2337 {
2338 reg Link *linkp;
2339 reg Link *linknext;
2340 reg Link **abase;
2341
2342 /* check: could file be hard-linked at all? */
2343 if(asb->sb_nlink<=1) return NULL;
2344 /* check: if is a directory, then cannot be hard-linked to something */
2345 if((asb->sb_mode & S_IFMT) == S_IFDIR) return NULL;
2346 /* check: sb_size==0 for entry in archive which should produce hardlink */
2347 if(installing && (asb->sb_size!=0)) return NULL;
2348
2349 for (linkp = *(abase = linkhash (asb->sb_ino)); linkp; linkp = linknext)
2350 {
2351
2352 if (linkp->l_ino == asb->sb_ino
2353 && linkp->l_dev == asb->sb_dev
2354 /* check: do mtimes also match? */
2355 && linkp->l_mtime == asb->sb_mtime
2356 /* check: do modes also match? */
2357 && linkp->l_mode == asb->sb_mode
2358 )
2359 {
2360 --linkp->l_nlink; /* reference count for -u option */
2361
2362 /* in older versions of afio, if l_nlink drops to 0, then the
2363 link entry is removed from the hash table.
2364 We don't do this anymore because that would break things
2365 if the same hard linked directory entry was included
2366 multiple times in the archive. Also it allows us to call
2367 linkfrom as often as we want for each file
2368 */
2369
2370 return (linkp);
2371 }
2372
2373 linknext = linkp->l_forw;
2374 }
2375
2376 return (NULL);
2377 }
2378
2379
2380 /*
2381 * linkleft()
2382 *
2383 * Complain about files with unseen links.
2384 */
2385 STATIC void
2386 linkleft ()
2387 {
2388 reg Link *lp;
2389 reg Link **base;
2390
2391 for (base = linkbase; base < linkbase + nel (linkbase); ++base)
2392 for (lp = *base; lp; lp = lp->l_forw)
2393 {
2394 /* printf("%s ino=%ld nl=%d\n",lp->l_path->p_name,(long int)lp->l_ino,(int)lp->l_nlink); */
2395 if (lp->l_nlink)
2396 VOID warn (lp->l_path->p_name, "Unseen link(s)");
2397
2398 }
2399 }
2400
2401 /*
2402 * linkto()
2403 *
2404 * Remember a file with outstanding links. Returns a
2405 * pointer to the associated link structure, or NULL
2406 * when linking is not possible.
2407 *
2408 * except in extfmt mode,
2409 * updates asb->sb_ino to create an (inode number,device number) pair that
2410 * is unique for each set of hard linked files in the archive,
2411 * while keeping the inode number <16bits as long as possible.
2412 * before calling linkto, asb->sb_ino should contain the inode number
2413 * from the filesystem, as obtained with a stat call.
2414 */
2415 STATIC Link *
2416 linkto (name, asb)
2417 char *name;
2418 reg Stat *asb;
2419 {
2420 reg Link *linkp;
2421 reg Path *path;
2422 reg Link **abase;
2423 ino_t ino;
2424 int ino16;
2425
2426 if ((asb->sb_mode & S_IFMT) == S_IFDIR)
2427 return (NULL);
2428
2429 if(!extfmt)
2430 {
2431 /* the old ASCII format only stores the least significant 16
2432 bits of the inode. We need to avoid duplicate ino numbers
2433 for different files in the archive or else the restore can
2434 have all kinds of horrible failure modes */
2435
2436 /* first, try the inode that is the inode from the fs, truncated */
2437 ino = asb->sb_ino & 0x0ffff;
2438
2439 /* check if that has been used, if so choose other one */
2440 while(1)
2441 {
2442 ino16=ino&0xffff;
2443
2444 /* if the bit for ino16 is 0, then this value has not been used yet
2445 in the archive, so we can break out of the loop and use it */
2446 if((ino16bitused[ino16/8]&((unsigned char)(1)<<(ino16&0x7)))==0) break;
2447
2448 /* choose other one */
2449 ino=freshino++;
2450
2451 if(freshino>0xffff)
2452 {
2453 /* break out of loop, no need to check if has been used */
2454 break;
2455 }
2456 }
2457
2458 }
2459 else
2460 {
2461 ino = asb->sb_ino;
2462 }
2463
2464 /* add this number to the table of used 16-bit inode numbers */
2465 /* this operation is unneccessary in some cases of the control
2466 flow of the above if statements, but it is nice to put it here */
2467 ino16=ino&0xffff;
2468 ino16bitused[ino16/8]=ino16bitused[ino16/8]|((unsigned char)(1)<<(ino16&0x7));
2469 /* add this inode to table of hard links (under filesystem inode number) */
2470
2471 if( ((linkp = (Link *) memget (sizeof (Link))) == NULL)
2472 || ((path = (Path *) memget (sizeof (Path))) == NULL)
2473 || ((path->p_name = memstr (name)) == NULL))
2474 return (NULL);
2475
2476 linkp->l_dev = asb->sb_dev;
2477 linkp->l_ino = asb->sb_ino; /* original ino from fs */
2478 linkp->l_nlink = asb->sb_nlink - 1;
2479 linkp->l_size = asb->sb_size;
2480 linkp->l_mtime = asb->sb_mtime;
2481 linkp->l_mode = asb->sb_mode;
2482 linkp->l_path = path;
2483 path->p_forw = NULL;
2484 path->p_back = path;
2485
2486 linkp->l_ino_ar = asb->sb_ino = ino;
2487
2488 if ((linkp->l_forw = *(abase = linkhash (linkp->l_ino))))
2489 linkp->l_forw->l_back = linkp;
2490 linkp->l_back = NULL;
2491
2492 return (*abase = linkp);
2493 }
2494
2495 #ifndef MEMCPY
2496
2497 /*
2498 * memcpy()
2499 *
2500 * A simple block move.
2501 */
2502 STATIC char *
2503 memcpy (to, from, len)
2504 reg char *to;
2505 reg char *from;
2506 uint len;
2507 {
2508 reg char *toend;
2509
2510 for (toend = to + len; to < toend; *to++ = *from++)
2511 ;
2512 return (to);
2513 }
2514
2515 #endif /* MEMCPY */
2516
2517 /*
2518 * memget()
2519 *
2520 * Allocate memory.
2521 */
2522 STATIC char *
2523 memget (len)
2524 uint len;
2525 {
2526 reg char *mem;
2527 static short outofmem;
2528
2529 if ((mem = malloc (len)) == NULL && !outofmem)
2530 outofmem = warn ("memget()", "Out of memory");
2531 return (mem);
2532 }
2533
2534 /*
2535 * memstr()
2536 *
2537 * Duplicate a string into dynamic memory.
2538 */
2539 STATIC char *
2540 memstr (str)
2541 reg char *str;
2542 {
2543 reg char *mem;
2544
2545 if ((mem = memget ((uint) strlen (str) + 1)))
2546 VOID strcpy (mem, str);
2547 return (mem);
2548 }
2549
2550 #ifndef MKDIR
2551
2552 /*
2553 * mkdir()
2554 *
2555 * Make a directory via "/bin/mkdir". Sets errno to a
2556 * questionably sane value upon failure.
2557 */
2558 STATIC int
2559 mkdir (name, mode)
2560 reg char *name;
2561 reg ushort mode;
2562 {
2563 reg int pid;
2564
2565 if ((pid = xfork ("mkdir()", DIE)) == 0)
2566 {
2567 VOID close (fileno (stdin));
2568 VOID close (fileno (stdout));
2569 VOID close (fileno (stderr));
2570 VOID open ("/dev/null", O_RDWR);
2571 VOID dup (fileno (stdin));
2572 VOID dup (fileno (stdin));
2573 VOID umask (~mode);
2574 VOID execl ("/bin/mkdir", "mkdir", name, (char *) NULL);
2575 exit (1);
2576 }
2577 if (xwait (pid, "mkdir()", TRUE) == 0)
2578 return (0);
2579 errno = EACCES;
2580 return (-1);
2581 }
2582
2583 #endif /* MKDIR */
2584
2585
2586 /*
2587 * nameopt()
2588 *
2589 * Used to optimize a pathname in a complicated way, trying to remove
2590 * redundant ../ components, now just simplifies leading //// into one
2591 * leading /. Returns 1 always.
2592 */
2593 STATIC int
2594 nameopt (name)
2595 char *name;
2596 {
2597 char *name2;
2598 while((name[0]=='/')&&(name[1]=='/'))
2599 {
2600 name2=name;
2601 while ((name2[0] = name2[1])) ++name2;
2602 }
2603 return 1;
2604 }
2605
2606 /*
2607 * next()
2608 *
2609 * Advance to the next archive volume.
2610 *
2611 */
2612 STATIC void
2613 next (mode, why)
2614 reg int mode;
2615 reg char *why;
2616 {
2617 reg time_t began;
2618 char *msg;
2619 int msgsize;
2620 char answer[20];
2621
2622 msgsize = 200 + strlen(myname) * 2 + strlen(arspec);
2623 msg = memget (msgsize);
2624
2625 began = time ((time_t *) NULL);
2626 nextclos ();
2627 if(!index(ignorewarnings,(int)'M'))
2628 {
2629 VOID warnarch (why, (off_t) 0);
2630 warnings--; /* above warnach call is not an error condition */
2631 }
2632 if (arfd == STDIN || arfd == STDOUT)
2633 goodbye (1);
2634 ++arvolume; /* change disk # here */
2635
2636 if (email) mail(email,(int)arvolume,arspec);
2637
2638 if(promptscript)
2639 {
2640 for (;;)
2641 {
2642 auto int result;
2643
2644 result=runpromptscript(why);
2645 if (result==1)
2646 fatal(arspec,"Aborted");
2647 if (result!=0)
2648 fatal(arspec,"Promptscript failed");
2649 if (nextopen(mode)==0)
2650 break;
2651 }
2652 }
2653 else
2654 {
2655 if(Fflag)
2656 {
2657 VOID sprintf (msg, "\
2658 %s: Ready for disk %u on %s\n\
2659 %s: \"quit\" to abort,\"f\" to format, anything else to proceed. > \07",
2660 myname,
2661 arvolume,
2662 arspec,
2663 myname);
2664 }
2665 else
2666 {
2667 VOID sprintf (msg, "\
2668 %s: Ready for volume %u on %s\n\
2669 %s: \"quit\" to abort, anything else to proceed. > \07",
2670 myname,
2671 arvolume,
2672 arspec,
2673 myname);
2674 }
2675
2676 for (;;)
2677 {
2678 nextask (msg, answer, sizeof (answer));
2679 if (strcmp (answer, "quit") == 0)
2680 fatal (arspec, "Aborted");
2681 else
2682 {
2683 while (Fflag && strcmp(answer,"f") == 0) {
2684 fprintf (stderr, "formatting using %s ...\n",formatcmd);
2685 if (system (formatcmd) != 0)
2686 {
2687 strcpy(msg,"\n");
2688 strcat(msg,myname);
2689 strcat(msg,": Format failed! Try again (y/n)? > ");
2690 nextask (msg, answer, sizeof (answer));
2691 if (answer[0] == 'y') answer[0] = 'f';
2692 else exit(1);
2693 }
2694 else break;
2695 }
2696
2697 if (nextopen (mode) == 0)
2698 break;
2699 }
2700 }
2701 }
2702 if(!index(ignorewarnings,(int)'M'))
2703 {
2704 VOID warnarch ("Continuing", (off_t) 0);
2705 warnings--; /* above warnach call is not an error condition */
2706 }
2707 timewait += time ((time_t *) NULL) - began;
2708 free(msg);
2709 }
2710
2711
2712 /*
2713 * runpromptscript()
2714 *
2715 * Utility function to run the promptscript
2716 *
2717 */
2718 STATIC int
2719 runpromptscript (why)
2720 char *why;
2721 {
2722 int pid,result;
2723 char vol[100];
2724
2725 /* run info-script with volume number and archive spec,
2726 and reason for calling it as arguments.
2727 the script should return 0 for ok and 1 for abort, other
2728 return codes will be treated as errors. */
2729
2730 /* connect prompt script to /dev/tty if it can be opened, else
2731 connect it to /dev/null (for crontab/at job use) */
2732
2733 sprintf(vol,"%d",arvolume);
2734
2735 if ((pid = xfork (promptscript, DIE)) == 0)
2736 {
2737 VOID close (fileno (stdin));
2738 VOID close (fileno (stdout));
2739 VOID close (fileno (stderr));
2740
2741 if ((open (TTY, O_RDWR)) < 0)
2742 {
2743 VOID open ("/dev/null", O_RDWR);
2744 }
2745 VOID dup (fileno (stdin));
2746 VOID dup (fileno (stdin));
2747
2748 execlp(promptscript,promptscript,vol,arspec,why,(char *)NULL);
2749 exit (1);
2750 }
2751 result=xwait (pid, "promptscript", TRUE);
2752 return(result);
2753 }
2754
2755
2756 /*
2757 * nextask()
2758 *
2759 * Ask a question and get a response. Ignores spaces and tabs.
2760 */
2761 STATIC void
2762 nextask (msg, answer, limit)
2763 reg char *msg;
2764 reg char *answer;
2765 reg int limit;
2766 {
2767 reg int idx;
2768 reg int got;
2769 auto char c;
2770
2771 if (ttyf < 0)
2772 ttyf = openqtty ();
2773 if (ttyf < 0)
2774 fatal (TTY, "Unavailable");
2775 VOID writeall (ttyf, msg, (uint) strlen (msg));
2776 idx = 0;
2777 while ((got = read (ttyf, &c, 1)) == 1)
2778 if (c == '\04' || c == '\n')
2779 break;
2780 else if (c == ' ' || c == '\t')
2781 continue;
2782 else if (idx < limit - 1)
2783 answer[idx++] = c;
2784 if (got < 0)
2785 fatal (TTY, syserr ());
2786 answer[idx] = '\0';
2787 }
2788
2789 /*
2790 * nextclos()
2791 *
2792 * Close an archive.
2793 */
2794 STATIC void
2795 nextclos ()
2796 {
2797 if (arfd != STDIN && arfd != STDOUT && !fflag)
2798 {
2799 VOID close (arfd);
2800 arfd = -1;
2801 }
2802 areof = 0;
2803 if (arname && *arname == '!')
2804 pipewait ();
2805
2806 /* the volume is complete, need to adjust the volume limit for the
2807 * following volume.
2808 */
2809 if (aruntil != 0)
2810 {
2811 update_aruntil();
2812 if (aruntil == 0) askfornext = 1;
2813
2814 if( roundaruntil )
2815 {
2816 /* round aruntil down to a multiple of arbsize: some devices
2817 (like ftape) puke on a smaller-than-blocksize last write to
2818 the volume */
2819 aruntil = ( aruntil / (ulonglong) arbsize );
2820 aruntil = aruntil * arbsize;
2821 }
2822
2823 /* error check... */
2824 if (aruntil && (aruntil < arbsize))
2825 {
2826 fatal(arspec,"-s option value for this volume smaller than block (-b) size");
2827 }
2828
2829 }
2830 }
2831
2832 /*
2833 * nextopen()
2834 *
2835 * Open an archive. Returns 0 if successful, -1 otherwise.
2836 */
2837 STATIC int
2838 nextopen (mode)
2839 int mode;
2840 {
2841 #if 1
2842 if (arfd != -1)
2843 close (arfd);
2844 #endif
2845 if (*arname == '!')
2846 arfd = pipeopen (mode);
2847 else if (strcmp (arname, "-") == 0)
2848 arfd = mode ? STDOUT : STDIN;
2849 else
2850 {
2851 process_arname(arname);
2852 #ifdef CTC3B2
2853 if (Cflag)
2854 {
2855 reg int oops;
2856 reg int fd;
2857
2858 oops = ((fd = open (proc_arname, O_RDWR | O_CTSPECIAL)) < 0
2859 || ioctl (fd, STREAMON) < 0);
2860 VOID close (fd);
2861 if (oops)
2862 return (warnarch (syserr (), (off_t) 0));
2863 }
2864 #endif /* CTC3B2 */
2865
2866 #ifdef linux
2867 /* Do O_SYNC writing to the floppy drive */
2868 if(Fflag && mode)
2869 arfd = open (proc_arname, mode | O_CREAT | O_TRUNC | O_SYNC, 0666 & ~mask);
2870 else
2871 arfd = mode ? creat (proc_arname, (mode_t)(0666 & ~mask)) : open (proc_arname, mode);
2872 #else
2873 arfd = mode ? creat (proc_arname, (mode_t)(0666 & ~mask)) : open (proc_arname, mode);
2874 #endif /* linux */
2875
2876 }
2877 if (arfd < 0)
2878 return (warnarch (syserr (), (off_t) 0));
2879 arleft = aruntil;
2880 return (0);
2881 }
2882
2883 /*
2884 * openin()
2885 *
2886 * Open the next input file. Returns a file descriptor, 0 if no data
2887 * exists, or -1 at EOF. This kludge works because standard input is
2888 * in use, preventing open() from returning zero.
2889 *
2890 * if fsname is non-NULL, copy filename on local filesystem into it,
2891 * if not a control file, for later use by -a option.
2892 */
2893 STATIC int
2894 openin (name, fsname, asb, cratio)
2895 char *name,*fsname;
2896 reg Stat *asb;
2897 int *cratio;
2898 {
2899 int fd;
2900 auto char local[PATHSIZE];
2901 char *label;
2902
2903 if(fsname) *fsname='\0';
2904
2905 if (cratio)
2906 *cratio = 100;
2907 for (;;)
2908 {
2909 if(firstfilename[0]!=0)
2910 {
2911 /* special case to suport input sanity check code in main() */
2912 strcpy(name,firstfilename);
2913 firstfilename[0]=0;
2914 }
2915 else
2916 {
2917 if (lineget (stdin, name, PATHSIZE) < 0)
2918 return (-1);
2919 }
2920
2921 /* control file syntax is //--SOURCEFILE[ LABEL] */
2922 if(strncmp(name,"//--",4)==0)
2923 {
2924 strcpy(local,&name[4]);
2925
2926 label=index(local,(int)' ');
2927 if(label!=NULL)
2928 {
2929 *label='\000'; /* separate filename and label */
2930 label++;
2931 }
2932 else
2933 label=NOLABEL;
2934 if(*label=='\000') label=NOLABEL;
2935
2936 sprintf(name,"%s/%s",CONTROLNAME,label);
2937
2938 /* Now, local is the filename, label is the label, and name is
2939 the filename in the archive, with the label embedded.
2940 */
2941
2942 if (STAT (local, asb) < 0)
2943 {
2944 VOID warn (local, syserr ());
2945 continue;
2946 }
2947
2948 /* Sun machines put trash in sb_rdev in stead of setting it to 0
2949 for regular files. Afio wants a 0 */
2950 if(! (S_ISBLK(asb->sb_mode)||S_ISCHR(asb->sb_mode)) ) asb->sb_rdev=0;
2951
2952 if ((asb->sb_mode & S_IFMT) != S_IFREG)
2953 {
2954 VOID warn (local, "Cannot read control file from this source.");
2955 continue;
2956 }
2957
2958 /* Flag that this is a control file.
2959 An archive entry is a control file if it is a regular file and
2960 if the ISCONTROL flag is set. The filename is not important.
2961 */
2962 asb->sb_rdev |= RDEV_ISCONTROL;
2963
2964 if (asb->sb_size == 0)
2965 return (0);
2966 if ((fd = open (local, O_RDONLY)) >= 0)
2967 return (fd);
2968 VOID warn (local, syserr ());
2969 continue;
2970 }
2971
2972 /* not a control file, make a normal archive entry */
2973
2974 if (namecmp (name,NULL) < 0)
2975 continue;
2976 if (nameopt (name) < 0)
2977 continue;
2978 if (!gflag)
2979 VOID strcpy (local, name);
2980 else if (dirchg (name, local) < 0)
2981 continue;
2982
2983 if(fsname) strcpy(fsname,local); /* for use by utime() in -a option */
2984
2985 if ((hflag ? STAT (local, asb) : LSTAT (local, asb)) < 0)
2986 {
2987 VOID warn (name, syserr ());
2988 if(index(ignorewarnings,(int)'m')) warnings--;
2989 #ifdef EOVERFLOW
2990 /* try to catch (in a portable way we hope) the case of
2991 statting a >2GB file with a regular 4-byte off_t stat
2992 call, this gives an EOVERFLOW on Linux. We do not want
2993 to count this case as a missing file, so print extra
2994 warning so that warnings counter gets increased properly. */
2995 if(errno==EOVERFLOW)
2996 VOID warn (name, "Can't archive file with size >= 2GB");
2997 #endif
2998 continue;
2999 }
3000
3001 /* Sun machines put trash in sb_rdev in stead of setting it to 0
3002 for regular files. Afio wants a 0 */
3003 if(! (S_ISBLK(asb->sb_mode)||S_ISCHR(asb->sb_mode)) ) asb->sb_rdev=0;
3004
3005 switch (asb->sb_mode & S_IFMT)
3006 {
3007 case S_IFDIR:
3008 asb->sb_nlink = 1;
3009 asb->sb_size = 0;
3010 return (0);
3011 #ifdef S_IFLNK
3012 case S_IFLNK:
3013 if ((asb->sb_size = readlink (local,
3014 asb->sb_link, sizeof (asb->sb_link) - 1)) < 0)
3015 {
3016 VOID warn (name, syserr ());
3017 continue;
3018 }
3019 asb->sb_link[asb->sb_size] = '\0';
3020 return (0);
3021 #endif /* S_IFLNK */
3022 case S_IFREG:
3023 if (asb->sb_size == 0)
3024 {
3025 /* indicate that file is not suitable for compression */
3026 asb->sb_rdev |= RDEV_NOTCOMPR;
3027 return (0);
3028 }
3029
3030 if (cpiocompat && (asb->sb_size != (asb->sb_size&0x7fffffff)))
3031 {
3032 /* >=2GB file. Can't handle this and remain cpio compatible */
3033 VOID fatal (name, "Archiving file with size >= 2GB not allowed by -5 option");
3034 continue;
3035 }
3036
3037 if ((fd = open (local, O_RDONLY)) >= 0)
3038 {
3039 if (Zflag)
3040 compressfile (&fd, name, asb, cratio);
3041
3042 return (fd);
3043 }
3044 VOID warn (name, syserr ());
3045 break;
3046 default:
3047 asb->sb_size = 0;
3048 return (0);
3049 }
3050 }
3051 }
3052
3053 /*
3054 * openincheck()
3055 *
3056 * Open the input file. Returns a file descriptor, 0 if no data
3057 * exists, or -1 at EOF. This kludge works because standard input is
3058 * in use, preventing open() from returning zero.
3059 */
3060 STATIC int
3061 openincheck (name, asb, comp, dozflag)
3062 char *name;
3063 reg Stat *asb;
3064 int *comp;
3065 int dozflag;
3066 {
3067 int fd;
3068 auto char local[PATHSIZE];
3069 auto char archlink[PATHSIZE];
3070 char* namedot;
3071
3072 *uncompto = '\0';
3073 *comp = 0;
3074 if (dozflag && ((asb->sb_mode & S_IFMT) == S_IFREG) &&
3075 ((namedot = strrchr (name, '.')) != NULL) &&
3076 (asb->sb_rdev & RDEV_NOTCOMPR) == 0 &&
3077 (asb->sb_size > 0) &&
3078 (strcmp (namedot, ".z") == 0))
3079 {
3080 *namedot = '\0';
3081 strcpy(uncompto, name);
3082 *comp = 1;
3083 }
3084 else
3085 namedot = NULL; /* not uncompressing */
3086 if (nameopt (name) < 0)
3087 return -1;
3088 if (!gflag)
3089 VOID strcpy (local, name);
3090 else if (dirchg (name, local) < 0)
3091 return 0;
3092 switch (asb->sb_mode & S_IFMT)
3093 {
3094 case S_IFDIR:
3095 asb->sb_nlink = 1;
3096 asb->sb_size = 0;
3097 /* do not check if directory exists */
3098 /* do not check directory permissions and access times */
3099 return (0);
3100 #ifdef S_IFLNK
3101 case S_IFLNK:
3102 /* if sb_size==0 then it is a hardlink to a symlink earlier
3103 in the archive, so don't check. */
3104 if (asb->sb_size == 0)
3105 return (0);
3106
3107 strcpy(archlink,asb->sb_link);
3108
3109 if ((asb->sb_size =
3110 readlink (local, asb->sb_link, sizeof (asb->sb_link) - 1)) < 0)
3111 {
3112 VOID warn (name, syserr ());
3113 asb->sb_size = 0;
3114 return 0;
3115 }
3116 asb->sb_link[asb->sb_size] = '\0';
3117
3118 if(strcmp(archlink,asb->sb_link)!=0)
3119 VOID warn (name, "Difference in symlink destination filename");
3120
3121 asb->sb_size = 0;
3122 return (0);
3123 #endif /* S_IFLNK */
3124 case S_IFREG:
3125 /* does not check file permissions and access times */
3126
3127 /* get last access time if we want to restore it */
3128 if(aflag)
3129 {
3130 if (STAT (local, &atime_sb) < 0)
3131 {
3132 /* silently fail, the open below will report an error */
3133 }
3134 else
3135 {
3136 atime_sb_valid=1;
3137 }
3138 }
3139
3140 if ((fd = open (local, O_RDONLY)) >= 0)
3141 {
3142 /* check for larger file on filesystem if file has 0 size */
3143 /* special handling of hard links: non-first archive entries
3144 for hardlinked files, which have 0 size, are not checked.
3145 If the hardlinked file has 0 size originally, the first
3146 archive entry for it also has 0 size, which means that
3147 the code below does not then check if the file on the
3148 filesystem grew larger. Fixing this would be too much
3149 work, we have to figure out correct coding of hard link
3150 inode/file name administration (see e.g. code in
3151 tocentry()) in order to detect whether the entry
3152 represents a first entry. */
3153 if ((asb->sb_size == 0)&&(asb->sb_nlink == 1))
3154 {
3155 if (STAT (local, &atime_sb) >= 0)
3156 {
3157 if (asb->sb_size != atime_sb.sb_size)
3158 {
3159 VOID warn (name, "File in archive has different length than file on filesystem");
3160 if(index(ignorewarnings,(int)'r'))
3161 {
3162 warn_nocount(name, "Not counting this as a verification error");
3163 warnings--;
3164 }
3165 }
3166 }
3167 }
3168 return (fd);
3169 }
3170 VOID warn_nocount (name, syserr ());
3171 VOID warn (name, "File on filesystem could not be opened for verify");
3172 if(index(ignorewarnings,(int)'r'))
3173 {
3174 warn_nocount(name, "Not counting this as a verification error");
3175 warnings--;
3176 }
3177
3178 return 0;
3179 default:
3180 asb->sb_size = 0;
3181 return (0);
3182 }
3183 }
3184
3185 /*
3186 * opencontrolscript()
3187 *
3188 * Start a control script. Returns the stdin of the script,
3189 * -1 if unsuccessful.
3190 * If no control script option given, return file handle of /dev/null.
3191 */
3192 STATIC int
3193 opencontrolscript (char *name)
3194 {
3195 auto int pfd[2];
3196 int comppid;
3197 char *label;
3198
3199 *uncompto='\000'; /* for -v output on restore, verify */
3200
3201 if(controlscript == NULL )
3202 {
3203 /* ignore data */
3204 warnarch("No -D option given, ignoring control file.",(off_t)0);
3205 return open("/dev/null",O_WRONLY);
3206 }
3207
3208 if(strcmp(controlscript,"")==0)
3209 {
3210 /* silently ignore data */
3211 return open("/dev/null",O_WRONLY);
3212 }
3213
3214 label=index(name,(int)'/');
3215 if(label==NULL) label=NOLABEL; else label++;
3216
3217 if (pipe (pfd) < 0)
3218 {
3219 warn("Control script",syserr());
3220 return -1;
3221 }
3222
3223 if ((comppid = xfork ("opencontrolscript(in), running control script", NODIE)) == 0)
3224 {
3225 /* Ignoring SIGPIPE may cause strange results in some shell scripts */
3226 VOID signal (SIGPIPE, SIG_DFL);
3227
3228 if (arfd != STDIN && arfd != STDOUT) VOID close (arfd);
3229 VOID close (pfd[1]); /* child */
3230 VOID close (fileno (stdin));
3231 VOID dup (pfd[0]);
3232 VOID close (pfd[0]);
3233
3234 execlp (controlscript, controlscript, label, NULL);
3235
3236 warnarch("Problems running control script:",(off_t)0);
3237 warn(controlscript,syserr());
3238 exit (1);
3239 }
3240
3241 /*parent*/
3242
3243 if (comppid < 0)
3244 {
3245 warn("Control script",syserr());
3246 return -1;
3247 }
3248
3249 close (pfd[0]);
3250
3251 /* this enables some safety checks */
3252 uncompressrun = comppid;
3253
3254 return pfd[1];
3255 }
3256
3257 /*
3258 * openotty()
3259 *
3260 * Open an output file. Returns the output file descriptor,
3261 * 0 if no data is required or -1 if unsuccessful. Note that
3262 * UNIX open() will never return 0 because the standard input
3263 * is in use.
3264 */
3265 STATIC int
3266 openotty (name, asb, linkp, ispass, dozflag)
3267 char *name;
3268 reg Stat *asb;
3269 Link *linkp;
3270 reg int ispass;
3271 int dozflag;
3272 {
3273 reg int exists;
3274 reg int fd;
3275 reg ushort perm;
3276 ushort operm=0; /* this one and next two initialised to */
3277 uid_t ouid=9999; /* suppress compiler warnings */
3278 gid_t ogid=9999;
3279 Path *path;
3280 auto Stat osb;
3281 #ifdef S_IFLNK
3282 reg int ssize;
3283 auto char sname[PATHSIZE];
3284 #endif /* S_IFLNK */
3285 char *namedot;
3286 auto int pfd[2];
3287 int comppid;
3288
3289 if(ISCONTROL(asb))
3290 return opencontrolscript(name);
3291
3292 *uncompto = '\0';
3293 /*
3294 * -iZ try to uncompress a compress'd regular file
3295 */
3296 if (dozflag && !linkp && ((asb->sb_mode & S_IFMT) == S_IFREG) &&
3297 ((namedot = strrchr (name, '.')) != NULL) &&
3298 (asb->sb_rdev & RDEV_NOTCOMPR) == 0 &&
3299 (asb->sb_size > 0) &&
3300 (strcmp (namedot, ".z") == 0))
3301 {
3302 *namedot = '\0';
3303 }
3304 else
3305 namedot = NULL; /* not uncompressing */
3306 if ((exists = (LSTAT (name, &osb) == 0)))
3307 {
3308 /* The asb.sb_ino here has not been truncated to 16 bits, so the check is
3309 safe and may even add some protection. */
3310 if (ispass
3311 && osb.sb_ino == asb->sb_ino
3312 && osb.sb_dev == asb->sb_dev)
3313 return (warn (name, "Same file"));
3314 else if ((osb.sb_mode & S_IFMT) == (asb->sb_mode & S_IFMT))
3315 operm = osb.sb_mode & (xflag ? S_IPERM : S_IPOPN);
3316 else if (afremove (name, &osb) < 0)
3317 return (warn (name, syserr ()));
3318 else
3319 exists = 0;
3320 }
3321 if (linkp)
3322 {
3323 if (exists)
3324 {
3325 #if 0
3326 /* Bogus check commented out.
3327 This check is bogus and dangerous because we only get the
3328 least significant 16 bits of the ino of the archived file from
3329 the archive header. So the file this check would prevent
3330 overwriting (replacing with a link) if true will probably be a different
3331 file altogether, which we wanted overwritten, not preserved.
3332 Also, the check is bogus anyway when installing the files on a
3333 different computer system. Ho hum.
3334 */
3335 printf("asb->sb_ino == osb.sb_ino %d %d\n",asb->sb_ino, osb.sb_ino);
3336 if (asb->sb_ino == osb.sb_ino
3337 && asb->sb_dev == osb.sb_dev)
3338 return (0);
3339 else
3340 #endif
3341 if (unlink (name) < 0)
3342 return (warn (name, syserr ()));
3343 else
3344 exists = 0;
3345 }
3346 for (path = linkp->l_path; path; path = path->p_forw)
3347 if (link (path->p_name, name) == 0
3348 || (errno == ENOENT
3349 && dirneed (name) == 0
3350 && link (path->p_name, name) == 0))
3351 return (0);
3352 else if (errno != EXDEV)
3353 return (warn (name, syserr ()));
3354 VOID warn (name, "Link broken");
3355 linkalso (linkp, name);
3356 }
3357 perm = asb->sb_mode & (xflag ? S_IPERM : S_IPOPN);
3358 if (exists)
3359 {
3360 ouid = osb.sb_uid;
3361 ogid = osb.sb_gid;
3362 }
3363 switch (asb->sb_mode & S_IFMT)
3364 {
3365 case S_IFBLK:
3366 case S_IFCHR:
3367 fd = 0;
3368 /* rdev==0 means that dev_t value does not fit in 16 bits,
3369 and is encoded in dev and ino instead
3370 see out().
3371 */
3372 if(asb->sb_rdev==0) asb->sb_rdev=(asb->sb_dev << 16) + asb->sb_ino;
3373
3374 if (exists)
3375 {
3376 if (asb->sb_rdev == osb.sb_rdev)
3377 if (perm != operm && chmod (name, perm) < 0)
3378 return (warn (name, syserr ()));
3379 else
3380 break;
3381 else if (afremove (name, &osb) < 0)
3382 return (warn (name, syserr ()));
3383 else
3384 exists = 0;
3385 }
3386
3387 if (mknod (name, asb->sb_mode, asb->sb_rdev) < 0
3388 && (errno != ENOENT
3389 || dirneed (name) < 0
3390 || mknod (name, asb->sb_mode, asb->sb_rdev) < 0))
3391 return (warn (name, syserr ()));
3392 break;
3393 case S_IFDIR:
3394 if (exists)
3395 {
3396 if (xflag && (asb->sb_uid != ouid || asb->sb_gid != ogid) &&
3397 chown (name, asb->sb_uid, asb->sb_gid) < 0)
3398 return (warn (name, syserr ()));
3399 else if (perm != operm && chmod (name, perm) < 0)
3400 return (warn (name, syserr ()));
3401 else { ; }
3402 if(osb.sb_mtime <= (mflag ? timenow : asb->sb_mtime))
3403 savedirstamp(name, mflag ? timenow : asb->sb_mtime);
3404 }
3405 else
3406 {
3407 savedirstamp(name, mflag ? timenow : asb->sb_mtime);
3408 if (dirneed (name) < 0 || dirmake (name, asb) < 0)
3409 return (warn (name, syserr ()));
3410 }
3411 return (0);
3412 #ifdef S_IFIFO
3413 case S_IFIFO:
3414 fd = 0;
3415 if (exists)
3416 if (perm != operm && chmod (name, perm) < 0)
3417 return (warn (name, syserr ()));
3418 else { ; }
3419 else if (mkfifo (name, asb->sb_mode) < 0
3420 && (errno != ENOENT
3421 || dirneed (name) < 0
3422 || mkfifo (name, asb->sb_mode) < 0))
3423 return (warn (name, syserr ()));
3424 break;
3425 #endif /* S_IFIFO */
3426 #ifdef S_IFSOCK
3427 case S_IFSOCK:
3428 fd = 0;
3429 if (exists)
3430 if (perm != operm && chmod (name, perm) < 0)
3431 return (warn (name, syserr ()));
3432 else { ; }
3433 else if (mknod (name, asb->sb_mode, (dev_t) 0) < 0
3434 && (errno != ENOENT
3435 || dirneed (name) < 0
3436 || mknod (name, asb->sb_mode, (dev_t) 0) < 0))
3437 return (warn (name, syserr ()));
3438 break;
3439 #endif /* S_IFSOCK */
3440 #ifdef S_IFLNK
3441 case S_IFLNK:
3442 fd = 0;
3443 if (nosymlinks)
3444 {
3445 warn (name, "Not unpacking this symlink because of -8 nosymlinks");
3446 if(index(ignorewarnings,(int)'l')) warnings--;
3447 break;
3448 }
3449 if (exists)
3450 {
3451 if ((ssize = readlink (name, sname, sizeof (sname))) < 0)
3452 return (warn (name, syserr ()));
3453 else if (strncmp (sname, asb->sb_link, (size_t)ssize) == 0)
3454 break;
3455 else if (afremove (name, &osb) < 0)
3456 return (warn (name, syserr ()));
3457 else
3458 exists = 0;
3459 }
3460 if (symlink (asb->sb_link, name) < 0
3461 && (errno != ENOENT
3462 || dirneed (name) < 0
3463 || symlink (asb->sb_link, name) < 0))
3464 return (warn (name, syserr ()));
3465 break;
3466 #endif /* S_IFLNK */
3467 case S_IFREG:
3468 if (exists)
3469 {
3470 if (nflag && osb.sb_mtime > asb->sb_mtime)
3471 return (warn_nocount (name, "Newer file exists"));
3472 else if (unlink (name) < 0)
3473 return (warn (name, syserr ()));
3474 else
3475 exists = 0;
3476 }
3477
3478 if ((fd = creat (name, perm)) < 0
3479 && (errno != ENOENT
3480 || dirneed (name) < 0
3481 || (fd = creat (name, perm)) < 0))
3482 return (warn (name, syserr ()));
3483 if (dozflag && !linkp && namedot)
3484 {
3485 if (pipe (pfd) >= 0)
3486 {
3487 if ((comppid = xfork ("openotty(in), compressing", NODIE)) == 0)
3488 {
3489 if (arfd != STDIN && arfd != STDOUT) VOID close (arfd);
3490 VOID close (pfd[1]); /* child */
3491 VOID close (fileno (stdin));
3492 VOID dup (pfd[0]);
3493 VOID close (pfd[0]);
3494
3495 VOID close (fileno (stdout));
3496 if (dup (fd) < 0)
3497 exit (1);
3498 VOID close (fd);
3499 mayberewind();
3500 if(compressargs)
3501 execvp (compressprog, compress_arg_list);
3502 else
3503 execlp (compressprog, compressprog, "-d", "-c", NULL);
3504 fprintf (stderr, "Could not uncompress, errno %d\n", errno);
3505 exit (1);
3506 }
3507 else
3508 /* life seems ok */
3509 if (comppid > 0)
3510 {
3511 close (fd);
3512 fd = pfd[1];
3513 close (pfd[0]);
3514 uncompressrun = comppid;
3515 strcpy (uncompto, name);
3516 #if 0
3517 *namedot = '.';
3518 #endif
3519 break;
3520 }
3521 }
3522 /* we failed try again, not uncompressing the file */
3523 unlink (name);
3524 *namedot = '.';
3525 return (openotty (name, asb, linkp, ispass, FALSE));
3526 }
3527
3528 break;
3529 default:
3530 return (warn (name, "Unknown filetype"));
3531 }
3532
3533 /* Can't chown()/chmod() a symbolic link, but for all others... */
3534 if((asb->sb_mode & S_IFMT) != S_IFLNK)
3535 {
3536 if (xflag && (!exists || asb->sb_uid != osb.sb_uid
3537 || asb->sb_gid != osb.sb_gid))
3538 {
3539 if (chown (name, (uid == 0 ? asb->sb_uid : uid),
3540 asb->sb_gid))
3541 perror (name);
3542 else /* chown may have cleared suid/sgid flags; restore them */
3543 if(perm&S_IPEXE)
3544 if(chmod (name, perm) < 0)
3545 return (warn (name, syserr ()));
3546 }
3547 }
3548 else
3549 {
3550 /* but if we have an lchown call, we _can_ chown a symbolic link.. */
3551 /* note: the lchown call is like chown, except that lchown does
3552 not follow a symlink. lchown is not present in all unix systems.
3553 Therefore, an ifdef is used below, the symbol is defined in the
3554 makefile */
3555 #ifdef HAVE_LCHOWN
3556 if (xflag && (!exists || asb->sb_uid != osb.sb_uid
3557 || asb->sb_gid != osb.sb_gid))
3558 {
3559 if (lchown (name, (uid == 0 ? asb->sb_uid : uid),
3560 asb->sb_gid))
3561 perror (name);
3562 }
3563 #endif
3564 }
3565
3566 if (linkp == NULL && asb->sb_nlink > 1)
3567 VOID linkto (name, asb);
3568 return (fd);
3569 }
3570
3571 /*
3572 * openqtty()
3573 *
3574 * Open the terminal for interactive queries (sigh). Assumes that
3575 * background processes ignore interrupts and that the open() or
3576 * the isatty() will fail for processes which are not attached to
3577 * terminals. Returns a file descriptor (-1 if unsuccessful).
3578 */
3579 int
3580 openqtty (void)
3581 {
3582 reg VOIDFN (*intr) (int);
3583 int fd;
3584
3585 fd = -1;
3586 if (!Fflag)
3587 {
3588 if ((intr = signal (SIGINT, SIG_IGN)) == SIG_IGN)
3589 return (fd);
3590 VOID signal (SIGINT, intr);
3591 }
3592
3593 if ((fd = open (TTY, O_RDWR)) < 0)
3594 {
3595 VOID warn (TTY, syserr ());
3596 }
3597 else if (!isatty (fd))
3598 VOID warn (TTY, "Is not a tty");
3599 return (fd);
3600 }
3601
3602 /*
3603 * options()
3604 *
3605 * Decode most reasonable forms of UNIX option syntax. Takes main()-
3606 * style argument indices (argc/argv) and a string of valid option
3607 * letters. Letters denoting options with arguments must be followed
3608 * by colons. With valid options, returns the option letter and points
3609 * "optarg" at the associated argument (if any). Returns '?' for bad
3610 * options and missing arguments. Returns zero when no options remain,
3611 * leaving "optind" indexing the first remaining argument.
3612 */
3613 STATIC int
3614 options (ac, av, proto)
3615 int ac;
3616 register char **av;
3617 char *proto;
3618 {
3619 register int c;
3620 register char *idx;
3621 static int optsub;
3622
3623 if (optind == 0)
3624 {
3625 optind = 1;
3626 optsub = 0;
3627 }
3628 optarg = NULL;
3629 if (optind >= ac)
3630 return (0);
3631 if (optsub == 0 && (av[optind][0] != '-' || av[optind][1] == '\0'))
3632 return (0);
3633 switch (c = av[optind][++optsub])
3634 {
3635 case '\0':
3636 ++optind;
3637 optsub = 0;
3638 return (options (ac, av, proto));
3639 case '-':
3640 ++optind;
3641 optsub = 0;
3642 return (0);
3643 case ':':
3644 return ('?');
3645 }
3646 if ((idx = strchr (proto, c)) == NULL)
3647 return ('?');
3648 if (idx[1] != ':')
3649 return (c);
3650 optarg = &av[optind][++optsub];
3651 ++optind;
3652 optsub = 0;
3653 if (*optarg)
3654 return (c);
3655 if (optind >= ac)
3656 return ('?');
3657 optarg = av[optind++];
3658 return (c);
3659 }
3660
3661 /*
3662 * optsize()
3663 *
3664 * Interpret a "size" argument. Recognizes suffices for blocks
3665 * (512-byte), kilobytes, megabytes, gigabytes and blocksize. Returns
3666 * the size in bytes.
3667 */
3668 STATIC ulonglong
3669 optsize (str)
3670 char *str;
3671 {
3672 reg char *idx;
3673 ulonglong number;
3674 ulonglong result;
3675
3676 result = 0;
3677 idx = str;
3678 for (;;)
3679 {
3680 number = 0;
3681 while (*idx >= '0' && *idx <= '9')
3682 number = number * 10 + *idx++ - '0';
3683 switch (*idx++)
3684 {
3685 case 'b':
3686 result += number * (ulonglong)512;
3687 continue;
3688 case 'k':
3689 result += number * (ulonglong)1024;
3690 continue;
3691 case 'm':
3692 result += number * (ulonglong)(1024L * 1024L);
3693 continue;
3694 case 'g':
3695 result += number * (ulonglong)(1024L * 1024L * 1024L);
3696 continue;
3697 case 'x':
3698 result += number * (ulonglong)arbsize;
3699 continue;
3700 case '+':
3701 result += number;
3702 continue;
3703 case '\0':
3704 result += number;
3705 break;
3706 default:
3707 break;
3708 }
3709 break;
3710 }
3711 if (*--idx)
3712 fatal (str, "Unrecognizable value");
3713 return (result);
3714 }
3715
3716 /*
3717 * out()
3718 *
3719 * Write an archive.
3720 */
3721 STATIC VOIDFN
3722 out (av)
3723 char **av;
3724 {
3725 reg int fd;
3726 auto Stat sb;
3727 auto char name[PATHSIZE];
3728 auto char fsname[PATHSIZE];
3729 auto int compression;
3730 #ifdef linux_tstamp
3731 auto struct utimbuf tstamp;
3732 #else
3733 auto time_t tstamp[2];
3734 #endif
3735 int wantlarge;
3736 Link *linkp;
3737
3738 if (*av)
3739 fatal (*av, "Extraneous argument");
3740
3741 while ((fd = openin (name, fsname, &sb, &compression)) >= 0)
3742 {
3743 bytepos=total; /* offset of this file in archive */
3744
3745 sb.ino_orig=sb.sb_ino;
3746 if (!lflag && sb.sb_nlink > 1)
3747 {
3748 if ((linkp = linkfrom (&sb,0)))
3749 {
3750 /* this file is a had link to a file we stored before */
3751 sb.sb_size = 0;
3752 sb.sb_ino=linkp->l_ino_ar;
3753 }
3754 else
3755 {
3756 /* linkto also updates sb.sb_ino to equal l_ino_ar */
3757 VOID linkto (name, &sb);
3758 }
3759 }
3760
3761 /* Some systems have a dev_t larger than 16 bits. If the
3762 dev_t value is larger, then encode it in the dev and ino fields
3763 of the archive header, and set rdev to 0 to signify special
3764 case. */
3765 /* for symmetry, and to reduce the amount of conditional logic
3766 needed in afio, this re-encoding measure is also used if we
3767 produce an outhead3 large ascii header, even though the
3768 outhead3 header has more room in its rdev field. */
3769
3770 if( (S_ISBLK(sb.sb_mode)||S_ISCHR(sb.sb_mode))&&
3771 ( ((sb.sb_rdev|0xffff)!=0xffff) || (sb.sb_rdev==0)) )
3772 {
3773 sb.sb_dev=sb.sb_rdev>>16;
3774 sb.sb_ino=sb.sb_rdev&0xffff;
3775 sb.sb_rdev=(dev_t)0;
3776 }
3777
3778 /* calculate if we want to use a large ASCII header.
3779 * Use them only when the data won't fit into the
3780 * default header.
3781 */
3782 wantlarge=(sb.sb_size != (sb.sb_size&0x7FFFFFFF));
3783
3784 /* also need large archive header to correctly store
3785 hard linked files (if inode numbers assigned by linkto()
3786 go above 16 bits) */
3787
3788 if (!lflag && (sb.sb_nlink > 1) && !extfmt)
3789 wantlarge = wantlarge || ((sb.sb_ino&0x0ffff)!=sb.sb_ino);
3790
3791 /* also need it for big uid/gid values */
3792 wantlarge=wantlarge || ((sb.sb_uid&0x0ffff)!=sb.sb_uid);
3793 wantlarge=wantlarge || ((sb.sb_gid&0x0ffff)!=sb.sb_gid);
3794
3795 /* When on a system with sizeof(time_t)>4bytes, and if the time
3796 on the file is >2038, also use large archive header
3797 (Linux right now has a 4-byte time_t, but we want to be
3798 future-proof.)
3799 */
3800 wantlarge=wantlarge || ((sb.sb_mtime&0x7fffffff)!=sb.sb_mtime);
3801
3802 if(cpiocompat && wantlarge)
3803 {
3804 /* if this was the >2GB case we already had a fatal elsewhere.. */
3805 VOID fatal (name, "Cannot create cpio-compatible file header for this input, aborting because of -5 option");
3806 }
3807
3808 if(wantlarge && !cpiowarned && !index(ignorewarnings,(int)'C'))
3809 {
3810 VOID warn_nocount(name, "Cannot create cpio-compatible file header for this input");
3811 VOID warnarch("Continuing, archive will not be fully compatible with cpio or afio versions 2.4.7 and lower",(off_t)0);
3812 if(index(ignorewarnings,(int)'c')) warnings--;
3813 cpiowarned=1;
3814 }
3815
3816 #ifdef S_IFLNK
3817 if ((sb.sb_mode & S_IFMT) == S_IFLNK)
3818 if (nosymlinks)
3819 {
3820 warn (fsname, "Not including symlink because of -8 nosymlinks");
3821 if(index(ignorewarnings,(int)'l')) warnings--;
3822 continue;
3823 }
3824 #endif /* S_IFLNK */
3825
3826 if(wantlarge)
3827 {
3828 outhead3 (name, &sb);
3829 }
3830 else
3831 {
3832 if(extfmt)
3833 outhead2 (name, &sb);
3834 else
3835 outhead (name, &sb);
3836 }
3837
3838 if (fd)
3839 {
3840 if (fd==ZIPFD)
3841 {
3842 outdatazip(zipfdfd,name,sb.sb_size);
3843 close(zipfdfd);
3844 }
3845 else if (fd==MEMFD)
3846 {
3847 outdatamem(name,sb.sb_size);
3848 }
3849 else
3850 VOID close (outdata (fd, name, sb.sb_size));
3851 }
3852
3853 if ((vflag>1)&&((arfd!=STDOUT)))
3854 {
3855 /* You can use -vv for full ls-style listings on stdout. */
3856 char toc_name[PATHSIZE];
3857 Stat toc_sb;
3858 /* Copy data structures first, because tocentry modifies them */
3859 strncpy(toc_name,name,PATHSIZE);
3860 memcpy(&toc_sb,&sb,sizeof(Stat));
3861 tocentry (toc_name, &toc_sb);
3862 }
3863 else if (vflag)
3864 {
3865 if(printbytepos) fprintf(stderr,"%.0f ",(double)bytepos);
3866
3867 if ((name[0] == '/') && !abspaths && (name[1]!=0))
3868 fprintf (stderr, "%s -- ", &name[1]);
3869 else
3870 fprintf (stderr, "%s -- ", name);
3871
3872 /* We do not check for a broken pipe on stderr, we wouldn't want
3873 to stop making the archive if this happens.
3874 */
3875
3876 if ((fd==ZIPFD)||(fd==MEMFD))
3877 VOID fprintf (stderr, "(%02d%%)\n", compression);
3878 else
3879 VOID fputs ("okay\n", stderr);
3880 }
3881
3882 /* ASX check if file changed between the begining
3883 and end of the backup */
3884 /* if *fsname==0, it was a control file, so do not check then */
3885 if (*fsname!=0)
3886 {
3887 struct stat st;
3888 /* I must check fsname !
3889 but error must be reported as fsname or name ?????
3890 I chosed to use fsname */
3891 if ((hflag ? stat(fsname, &st) : lstat(fsname, &st))<0)
3892 {
3893 warn (fsname, syserr());
3894 }
3895 else
3896 {
3897 if (st.st_mtime!=sb.sb_mtime)
3898 {
3899 warn (fsname, "File was modified during its backup");
3900 if(index(ignorewarnings,(int)'d')) warnings--;
3901 }
3902 }
3903 }
3904
3905 if(aflag && *fsname && ((sb.sb_mode & S_IFMT)==S_IFREG))
3906 {
3907 /* reset access time, this distroys the ctime btw. */
3908 #ifdef linux_tstamp
3909 tstamp.actime = sb.sb_atime;
3910 tstamp.modtime = sb.sb_mtime;
3911 VOID utime (fsname, &tstamp);
3912 #else
3913 tstamp[0] = sb.sb_atime;
3914 tstamp[1] = sb.sb_mtime;
3915 VOID utime (fsname, tstamp);
3916 #endif
3917 }
3918 }
3919 outeof (TRAILER, TRAILZ);
3920 }
3921
3922 /*
3923 * outalloc()
3924 *
3925 * Allocate buffer space previously referenced by outavail().
3926 */
3927 STATIC void
3928 outalloc (len)
3929 reg size_t len;
3930 {
3931 bufidx += len;
3932 total += len;
3933 }
3934
3935 /*
3936 * outavail()
3937 *
3938 * Index buffer space for archive output. Stores a buffer pointer
3939 * at a given location. Returns the number of bytes available.
3940 */
3941 STATIC size_t
3942 outavail (bufp)
3943 reg char **bufp;
3944 {
3945 reg size_t have;
3946
3947 while ((have = bufend - bufidx) == 0)
3948 {
3949 outflush (NOTDONE);
3950 }
3951
3952 *bufp = bufidx;
3953 return (have);
3954 }
3955
3956 /*
3957 * outdata()
3958 *
3959 * Write archive data. Continues after file read errors, padding with
3960 * null characters if neccessary. Always returns the given input file
3961 * descriptor.
3962 */
3963 STATIC int
3964 outdata (fd, name, size)
3965 int fd;
3966 char *name;
3967 reg off_t size;
3968 {
3969 reg size_t chunk;
3970 reg ssize_t got;
3971 reg int oops;
3972 reg size_t avail;
3973 auto char *buf;
3974
3975 oops = got = 0;
3976 while (size)
3977 {
3978 avail = outavail (&buf);
3979 size -= (chunk = size < (off_t)avail ? size : avail);
3980 if (oops == 0 && (got = readall (fd, buf, chunk)) < 0)
3981 {
3982 oops = warn (name, syserr ());
3983 if(index(ignorewarnings,(int)'n')) warnings--;
3984 got = 0;
3985 }
3986 if ((size_t)got < chunk)
3987 {
3988 if (oops == 0)
3989 oops = warn (name, "Early EOF");
3990 while ((size_t)got < chunk)
3991 buf[got++] = '\0';
3992 }
3993 outalloc (chunk);
3994 }
3995 return (fd);
3996 }
3997
3998 /*
3999 * outdatazip()
4000 *
4001 * Write archive data. Continues after file read errors, padding with
4002 * null characters if neccessary.
4003 *
4004 * Special version for reading from gzip through a pipe.
4005 */
4006 void
4007 outdatazip (fd, name, size)
4008 int fd;
4009 char *name;
4010 reg off_t size;
4011 {
4012 reg size_t chunk;
4013 reg ssize_t got;
4014 reg size_t avail;
4015 auto char *buf;
4016 char localbuf[4096];
4017 int overflow=0;
4018
4019 while (size>0)
4020 {
4021 avail = outavail (&buf);
4022 chunk = (size < (off_t)avail ? size : avail);
4023
4024 got = read (fd, buf, chunk);
4025 if(got<=0) break;
4026
4027 outalloc (got);
4028 size-=got;
4029 }
4030
4031 /* read the end of the stream, if the data changed on the second gzip */
4032 overflow=0;
4033 while (read (fd, localbuf, sizeof(localbuf))>0) overflow=1;
4034
4035 waitforgzip(); /* wait for child to exit */
4036
4037 if(size>0 || overflow)
4038 warn (name, "Error zipping file, written damaged copy to archive.");
4039
4040 /* pad with zeros, if necessary */
4041 while (size>0)
4042 {
4043 avail = outavail (&buf);
4044 size -= (chunk = size < (off_t)avail ? size : avail);
4045 got=0;
4046 while (got < chunk)
4047 buf[got++] = '\0';
4048 outalloc (chunk);
4049 }
4050
4051 }
4052
4053 /*
4054 * outdatamem()
4055 *
4056 * Write archive data.
4057 *
4058 * Special version for reading from internal memory buffer.
4059 */
4060 void
4061 outdatamem (name, size)
4062 char *name;
4063 reg off_t size;
4064 {
4065 reg uint chunk;
4066 reg uint got;
4067 reg uint avail;
4068 auto char *buf;
4069
4070 /* read from memory */
4071 memreset();
4072
4073 while (size)
4074 {
4075 avail = outavail (&buf);
4076 chunk = (size < (off_t)avail ? (uint) size : avail);
4077
4078 got=memread (buf, (int)chunk);
4079 if (got==0) break;
4080
4081 outalloc (got);
4082 size-=got;
4083 }
4084
4085 memfree();
4086 }
4087
4088 /*
4089 * outeof()
4090 *
4091 * Write an archive trailer.
4092 */
4093 STATIC void
4094 outeof (name, namelen)
4095 char *name;
4096 reg uint namelen;
4097 {
4098 ulonglong pad;
4099 auto char header[M_STRLEN + H_STRLEN + 1];
4100
4101 if ((pad = (total + M_STRLEN + H_STRLEN + namelen) % arpad))
4102 pad = arpad - pad;
4103 VOID strcpy (header, M_ASCII);
4104 VOID sprintf (header + M_STRLEN, H_PRINT, 0, 0,
4105 0, 0, 0, 1, 0, ulo(0) , namelen, (long unsigned int)pad);
4106 outwrite (header, M_STRLEN + H_STRLEN);
4107 outwrite (name, namelen);
4108 outpad ((off_t)pad);
4109 outflush (DONE);
4110 if (fflag)
4111 outwait ();
4112 }
4113
4114 /*
4115 * outflush()
4116 *
4117 * Flush the output buffer. Optionally fork()s to allow the
4118 * parent to refill the buffer while the child waits for the
4119 * write() to complete.
4120 */
4121 STATIC void
4122 outflush (done)
4123 int done;
4124 {
4125 /*
4126 * in this case we are a floppy and want to write the floppy from one
4127 * buffer (to have a copy of the data to verify against)
4128 */
4129 bufend = buffer + ((aruntil!=0) ? min ((ulonglong)buflen, arleft) : (ulonglong)buflen);
4130 if (Fflag && (done == NOTDONE) && ((bufend - bufidx) > 0))
4131 {
4132 return;
4133 }
4134
4135 /*
4136 * Otherwise open up the next volume once we've run out of space
4137 */
4138 if ( !Fflag && aruntil && arleft == 0)
4139 next (O_WRONLY, "Output limit reached");
4140
4141 /* writedisk will report errors, no need to check return code */
4142 VOID writedisk (1);
4143 bufend = (bufidx = buffer) + ((aruntil!=0) ? min ((ulonglong)buflen, arleft) : (ulonglong)buflen);
4144 }
4145
4146 /*
4147 * outhead()
4148 *
4149 * Write an archive header.
4150 */
4151 STATIC void
4152 outhead (name, asb)
4153 reg char *name;
4154 reg Stat *asb;
4155 {
4156 reg uint namelen;
4157 auto char header[M_STRLEN + H_STRLEN + 1];
4158
4159 if ((name[0] == '/') && !abspaths)
4160 {
4161 if (name[1])
4162 ++name;
4163 else
4164 name = ".";
4165 }
4166 namelen = (uint) strlen (name) + 1;
4167 VOID strcpy (header, M_ASCII);
4168 VOID sprintf (header + M_STRLEN, H_PRINT, ush (asb->sb_dev),
4169 ush (asb->sb_ino), ush (asb->sb_mode), ush (asb->sb_uid),
4170 ush (asb->sb_gid), ush (asb->sb_nlink), ush (asb->sb_rdev),
4171 ulo(mflag ? timenow : asb->sb_mtime), namelen, (long unsigned int) asb->sb_size);
4172 outwrite (header, M_STRLEN + H_STRLEN);
4173 outwrite (name, namelen);
4174 #ifdef S_IFLNK
4175 if ((asb->sb_mode & S_IFMT) == S_IFLNK)
4176 outwrite (asb->sb_link, (uint) asb->sb_size);
4177 #endif /* S_IFLNK */
4178 }
4179
4180 /*
4181 * outhead2()
4182 *
4183 * Write an archive header.
4184 */
4185 STATIC void
4186 outhead2 (name, asb)
4187 reg char *name;
4188 reg Stat *asb;
4189 {
4190 reg uint namelen;
4191 auto char header[M_STRLEN + H_STRLEN2 + 1];
4192
4193 if ((name[0] == '/') && !abspaths)
4194 {
4195 if (name[1])
4196 ++name;
4197 else
4198 name = ".";
4199 }
4200 namelen = (uint) strlen (name) + 1;
4201 VOID strcpy (header, M_ASCII2);
4202 VOID sprintf (header + M_STRLEN, H_PRINT2, ush (asb->sb_dev),
4203 (long unsigned int)(asb->sb_ino), ush (asb->sb_mode), ush (asb->sb_uid),
4204 ush (asb->sb_gid), ush (asb->sb_nlink), ush (asb->sb_rdev),
4205 ulo(mflag ? timenow : asb->sb_mtime), namelen, (long unsigned int)(asb->sb_size));
4206 outwrite (header, M_STRLEN + H_STRLEN2);
4207 outwrite (name, namelen);
4208 #ifdef S_IFLNK
4209 if ((asb->sb_mode & S_IFMT) == S_IFLNK)
4210 outwrite (asb->sb_link, (uint) asb->sb_size);
4211 #endif /* S_IFLNK */
4212 }
4213
4214 /*
4215 * outhead3()
4216 *
4217 * Write a large ASCII archive header.
4218 */
4219 STATIC void
4220 outhead3 (name, asb)
4221 reg char *name;
4222 reg Stat *asb;
4223 {
4224 reg uint namelen;
4225 auto char header[M_STRLEN + H_STRLEN3 + 1];
4226
4227 if ((name[0] == '/') && !abspaths)
4228 {
4229 if (name[1])
4230 ++name;
4231 else
4232 name = ".";
4233 }
4234 namelen = (uint) strlen (name) + 1;
4235 VOID strcpy (header, M_ASCII3);
4236
4237 VOID sprintf (header + M_STRLEN, H_PRINT3, ulo (asb->sb_dev),
4238 ull (asb->sb_ino), ulo (asb->sb_mode), ulo (asb->sb_uid),
4239 ulo (asb->sb_gid), ulo (asb->sb_nlink), ulo (asb->sb_rdev),
4240 mflag ? ull (timenow) : ull (asb->sb_mtime), namelen, 0, 0,
4241 ull (asb->sb_size));
4242 outwrite (header, M_STRLEN + H_STRLEN3);
4243 outwrite (name, namelen);
4244 #ifdef S_IFLNK
4245 if ((asb->sb_mode & S_IFMT) == S_IFLNK)
4246 outwrite (asb->sb_link, (uint) asb->sb_size);
4247 #endif /* S_IFLNK */
4248 }
4249
4250
4251 /*
4252 * outpad()
4253 *
4254 * Pad the archive.
4255 */
4256 STATIC void
4257 outpad (pad)
4258 reg off_t pad;
4259 {
4260 reg int idx;
4261 reg int len;
4262
4263 while (pad)
4264 {
4265 if ((len = bufend - bufidx) > pad)
4266 len = pad;
4267 for (idx = 0; idx < len; ++idx)
4268 *bufidx++ = '\0';
4269 total += len;
4270 outflush (NOTDONE);
4271 pad -= len;
4272 }
4273 }
4274
4275 /*
4276 * outwait()
4277 *
4278 * Wait for the last background outflush() process (if any). The child
4279 * exit value is zero if successful, 255 if a write() returned zero or
4280 * the value of errno if a write() was unsuccessful.
4281 */
4282 STATIC void
4283 outwait ()
4284 {
4285 auto int status;
4286
4287 if (outpid == 0)
4288 return;
4289 status = xwait (outpid, "outwait()", TRUE);
4290 outpid = 0;
4291 if (status)
4292 fatal (arspec, "Child error");
4293 }
4294
4295 /*
4296 * outwrite()
4297 *
4298 * Write archive data.
4299 */
4300 STATIC void
4301 outwrite (idx, len)
4302 reg char *idx;
4303 uint len;
4304 {
4305 reg uint have;
4306 reg uint want;
4307 reg char *endx = idx + len;
4308
4309 while ((want = endx - idx))
4310 {
4311 while ((have = bufend - bufidx) == 0)
4312 outflush (NOTDONE);
4313 if (have > want)
4314 have = want;
4315 memcpy (bufidx, idx, have);
4316 bufidx += have;
4317 idx += have;
4318 total += have;
4319 }
4320 }
4321
4322 /*
4323 * pass()
4324 *
4325 * Copy within the filesystem.
4326 */
4327 STATIC VOIDFN
4328 pass (av)
4329 reg char **av;
4330 {
4331 reg int fd;
4332 reg char **avx;
4333 auto Stat sb;
4334 auto char name[PATHSIZE];
4335
4336 for (avx = av; *avx; ++avx)
4337 {
4338 if (gflag && **avx != '/')
4339 fatal (*avx, "Relative pathname");
4340 if (STAT (*avx, &sb) < 0)
4341 fatal (*avx, syserr ());
4342 if ((sb.sb_mode & S_IFMT) != S_IFDIR)
4343 fatal (*avx, "Not a directory");
4344 }
4345 while ((fd = openin (name, NULL, &sb, (int *) 0)) >= 0)
4346 {
4347 if (passitem (name, &sb, fd, av))
4348 VOID close (fd);
4349 if (vflag)
4350 {
4351 if (*uncompto)
4352 VOID fprintf (stderr, "%s -- uncompressed\n", uncompto);
4353 else
4354 VOID fprintf (stderr, "%s -- okay\n", name);
4355 }
4356 }
4357 }
4358
4359 /*
4360 * passdata()
4361 *
4362 * Copy data to one file. Doesn't believe in input file
4363 * descriptor zero (see description of kludge in openin()
4364 * comments). Closes the provided output file descriptor.
4365 */
4366 STATIC void
4367 passdata (from, ifd, to, ofd)
4368 char *from;
4369 reg int ifd;
4370 char *to;
4371 reg int ofd;
4372 {
4373 reg ssize_t got;
4374 reg ssize_t sparse;
4375 auto char block[FSBUF];
4376
4377 if (ifd)
4378 {
4379 VOID lseek (ifd, (off_t) 0, 0);
4380 sparse = 0;
4381 while ((got = read (ifd, block, sizeof (block))) > 0
4382 && (sparse = fswrite (ofd, block, (uint) got)) >= 0)
4383 total += got;
4384 if (got)
4385 VOID warn (got < 0 ? from : to, syserr ());
4386 else if (sparse > 0
4387 && (lseek (ofd, (off_t) - sparse, 1) < 0
4388 || writeall (ofd, block, sparse) != sparse))
4389 VOID warn (to, syserr ());
4390 }
4391 VOID close (ofd);
4392 }
4393
4394 /*
4395 * passitem()
4396 *
4397 * Copy one file. Returns given input file descriptor.
4398 */
4399 STATIC int
4400 passitem (from, asb, ifd, dir)
4401 char *from;
4402 Stat *asb;
4403 reg int ifd;
4404 reg char **dir;
4405 {
4406 reg int ofd;
4407
4408 #ifdef linux_tstamp
4409 auto struct utimbuf tstamp;
4410 #else
4411 auto time_t tstamp[2];
4412 #endif
4413 auto char to[PATHSIZE];
4414
4415 while (*dir)
4416 {
4417 if (nameopt (strcat (strcat (strcpy (to, *dir++), "/"), from)) < 0)
4418 continue;
4419 if ((ofd = openotty (to, asb,
4420 lflag ? linkto (from, asb) : linkfrom (asb,0), 1, Zflag)) < 0)
4421 continue;
4422 if (ofd > 0)
4423 passdata (from, ifd, to, ofd);
4424 #ifdef linux_tstamp
4425 tstamp.actime = tstamp.modtime = mflag ? timenow : asb->sb_mtime;
4426 VOID utime (to, &tstamp);
4427 #else
4428 tstamp[0] = tstamp[1] = mflag ? timenow : asb->sb_mtime;
4429 VOID utime (to, tstamp);
4430 #endif
4431 /* safety */
4432 if (uncompressrun)
4433 {
4434 VOID xwait (uncompressrun, "passitem xwait()", TRUE);
4435 uncompressrun = 0;
4436 }
4437 }
4438 return (ifd);
4439 }
4440
4441 STATIC VOIDFN
4442 process_arname (template)
4443 char *template;
4444 {
4445 int remain, len;
4446 char *sptr, *dptr;
4447
4448 sptr=template;
4449 dptr=proc_arname;
4450
4451 if(!sflagused)
4452 {
4453 strcpy(dptr,sptr);
4454 return;
4455 }
4456
4457 remain = sizeof(proc_arname)-10;
4458
4459 for (; remain>=0; sptr++) {
4460 *dptr = '\0';
4461 if (*sptr == '%') {
4462 switch (*++sptr) {
4463 case 'V': /* volume number */
4464 if (remain < 40) break;
4465 len = sprintf(dptr,"%u", arvolume);
4466 dptr += len;
4467 remain -= len;
4468 break;
4469 case 'S': /* volume size */
4470 if (remain < 40) break;
4471 len = sprintf(dptr,"%llu", (unsigned long long) aruntil);
4472 dptr += len;
4473 remain -= len;
4474 break;
4475 default:
4476 *dptr++ = *sptr;
4477 remain--;
4478 break;
4479 }
4480 }
4481 else {
4482 *dptr++ = *sptr;
4483 remain--;
4484 }
4485 if (*sptr == '\0') break;
4486 }
4487
4488 }
4489
4490 /*
4491 * pipechld()
4492 *
4493 * Child portion of pipeline fork.
4494 */
4495 STATIC int
4496 pipechld (mode, pfd)
4497 int mode;
4498 reg int *pfd;
4499 {
4500 reg char **av;
4501 auto char *arg[32];
4502
4503 av = arg;
4504 if ((*av = getenv ("SHELL")) && **av)
4505 ++av;
4506 else
4507 *av++ = "/bin/sh";
4508 *av++ = "-c";
4509 process_arname(arname + 1);
4510 *av++ = proc_arname;
4511 *av = NULL;
4512 if (mode)
4513 {
4514 VOID close (pfd[1]);
4515 VOID close (STDIN);
4516 VOID dup (pfd[0]);
4517 VOID close (pfd[0]);
4518 VOID close (STDOUT);
4519 VOID open ("/dev/null", O_WRONLY);
4520 }
4521 else
4522 {
4523 VOID close (STDIN);
4524 VOID open ("/dev/null", O_RDONLY);
4525 VOID close (pfd[0]);
4526 VOID close (STDOUT);
4527 VOID dup (pfd[1]);
4528 VOID close (pfd[1]);
4529 }
4530 if (ttyf >= 0)
4531 VOID close (ttyf);
4532 VOID execvp (arg[0], arg);
4533 VOID warn (arg[0], syserr ());
4534 _exit (1);
4535 return 0; /* to avoid compiler warning */
4536 }
4537
4538 /*
4539 * pipeopen()
4540 *
4541 * Open an archive via a pipeline. Returns a file
4542 * descriptor, or -1 if unsuccessful.
4543 */
4544 STATIC int
4545 pipeopen (mode)
4546 reg int mode;
4547 {
4548 auto int pfd[2];
4549
4550 if (pipe (pfd) < 0)
4551 return (-1);
4552 if ((pipepid = xfork ("pipeopen()", DIE)) == 0)
4553 pipechld (mode, pfd);
4554 if (mode)
4555 {
4556 VOID close (pfd[0]);
4557 return (pfd[1]);
4558 }
4559 else
4560 {
4561 VOID close (pfd[1]);
4562 return (pfd[0]);
4563 }
4564 }
4565
4566 /*
4567 * pipewait()
4568 *
4569 * Await a pipeline.
4570 */
4571 STATIC void
4572 pipewait ()
4573 {
4574 reg int status;
4575
4576 if (pipepid == 0)
4577 return;
4578 status = xwait (pipepid, "pipewait()", TRUE);
4579 pipepid = 0;
4580 if (status)
4581 fatal (arspec, "Pipeline error");
4582 }
4583
4584 /*
4585 * prsize()
4586 *
4587 * Print a file offset.
4588 */
4589 STATIC void
4590 prsize (stream, size)
4591 FILE *stream;
4592 reg ulonglong size;
4593 {
4594 reg ulonglong n;
4595
4596 if ((n = (size / (1024L * 1024L))))
4597 {
4598 VOID fprintf (stream, "%lum+", (unsigned long)n);
4599 size -= n * 1024 * 1024;
4600 }
4601 if ((n = (size / 1024)))
4602 {
4603 VOID fprintf (stream, "%luk+", (unsigned long)n);
4604 size -= n * 1024;
4605 }
4606 VOID fprintf (stream, "%lu", (unsigned long) size);
4607 }
4608
4609 #ifndef MKDIR
4610
4611 /*
4612 * rmdir()
4613 *
4614 * Remove a directory via "/bin/rmdir". Sets errno to a
4615 * questionably sane value upon failure.
4616 */
4617 STATIC int
4618 rmdir (name)
4619 reg char *name;
4620 {
4621 reg int pid;
4622
4623 if ((pid = xfork ("rmdir()", DIE)) == 0)
4624 {
4625 VOID close (fileno (stdin));
4626 VOID close (fileno (stdout));
4627 VOID close (fileno (stderr));
4628 VOID open ("/dev/null", O_RDWR);
4629 VOID dup (fileno (stdin));
4630 VOID dup (fileno (stdin));
4631 VOID execl ("/bin/rmdir", "rmdir", name, (char *) NULL);
4632 exit (1);
4633 }
4634 if (xwait (pid, "rmdir()", TRUE) == 0)
4635 return (0);
4636 errno = EACCES;
4637 return (-1);
4638 }
4639
4640 #endif /* MKDIR */
4641
4642 /*
4643 * fswrite()
4644 *
4645 * Write a filesystem block. Seeks past sparse blocks. Returns
4646 * 0 if the block was written, the given length for a sparse
4647 * block or -1 if unsuccessful.
4648 */
4649 STATIC ssize_t
4650 fswrite (fd, buf, len)
4651 int fd;
4652 char *buf;
4653 size_t len;
4654 {
4655 reg char *bidx;
4656 reg char *bend;
4657
4658 /*
4659 * if -j (no sparse blocks) or compressrun (piping to uncompress utility)
4660 * then do not bother looking for empty buffers, just write the data.
4661 */
4662 if (jflag || uncompressrun)
4663 return (writeall (fd, buf, len) == (int)len ? 0 : -1);
4664 bend = (bidx = buf) + len;
4665 while (bidx < bend)
4666 if (*bidx++)
4667 return (writeall (fd, buf, len) == (int)len ? 0 : -1);
4668 return (lseek (fd, (off_t) len, 1) < 0 ? -1 : (int)len);
4669 }
4670
4671 /*
4672 * syserr()
4673 *
4674 * Return pointer to appropriate system error message.
4675 */
4676 STATIC char *
4677 syserr ()
4678 {
4679 static char msg[40];
4680 #if 0
4681 /* older version */
4682 if (errno > 0 && errno < sys_nerr)
4683 return ((char *) sys_errlist[errno]);
4684 VOID sprintf (msg, "Unknown error (errno %d)", errno);
4685 return (msg);
4686 #else
4687 /* newer version, should be posix compliant and eliminate
4688 some compiler warnings
4689 */
4690 char *pTmp = NULL;
4691 if (! (pTmp = strerror(errno)))
4692 {
4693 VOID sprintf (msg, "Unknown error (errno %d)", errno);
4694 pTmp = msg;
4695 }
4696 return (pTmp);
4697 #endif
4698 }
4699
4700 /*
4701 * toc()
4702 *
4703 * Print archive table of contents.
4704 */
4705 STATIC VOIDFN
4706 toc (av)
4707 reg char **av;
4708 {
4709 auto Stat sb;
4710 auto char name[PATHSIZE];
4711
4712 if (*av)
4713 fatal (*av, "Extraneous argument");
4714 name[0] = '\0';
4715 while (inhead (name, &sb) == 0)
4716 {
4717 if (ISCONTROL(&sb))
4718 {
4719 /* list it */
4720 if (namecmp (name,&sb) == 0)
4721 tocentry (name, &sb);
4722
4723 /* process control file */
4724 if(inentry (name, &sb) < 0)
4725 if (inskip (sb.sb_size) < 0)
4726 VOID warn (name, "Skipped file data is corrupt");
4727
4728 continue;
4729 }
4730
4731 if (namecmp (name,&sb) == 0)
4732 tocentry (name, &sb);
4733 if (inskip (sb.sb_size) < 0)
4734 VOID warn (name, "File data is corrupt");
4735 }
4736 }
4737
4738 /*
4739 * tocentry()
4740 *
4741 * Print a single table-of-contents entry.
4742 */
4743 STATIC void
4744 tocentry (name, asb)
4745 char *name;
4746 reg Stat *asb;
4747 {
4748 reg Time *atm;
4749 reg Link *from;
4750 reg Passwd *pwp;
4751 reg Group *grp;
4752 static char *month[] =
4753 {
4754 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4755 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4756 };
4757 int res;
4758 Link *linkp;
4759 Link *linknext;
4760
4761 if(printbytepos) printf("%.0f ",(double)bytepos);
4762
4763 if (vflag)
4764 {
4765 tocmode (asb->sb_mode);
4766 VOID printf (" %2d", (int)asb->sb_nlink);
4767 atm = localtime (&asb->sb_mtime);
4768 if ((pwp = getpwuid (asb->sb_uid)))
4769 VOID printf (" %-8s", pwp->pw_name);
4770 else
4771 VOID printf (" %-8u", (unsigned int)(asb->sb_uid));
4772 if ((grp = getgrgid (asb->sb_gid)))
4773 VOID printf (" %-8s", grp->gr_name);
4774 else
4775 VOID printf (" %-8u", (unsigned int)(asb->sb_gid));
4776 switch (asb->sb_mode & S_IFMT)
4777 {
4778 case S_IFBLK:
4779 case S_IFCHR:
4780 /* rdev==0 means that rdev is encoded in dev and ino,
4781 see out().
4782 */
4783 if(asb->sb_rdev==0) asb->sb_rdev=(asb->sb_dev<<16) + asb->sb_ino;
4784 VOID printf (" %3d, %3d",
4785 (int)major (asb->sb_rdev), (int)minor (asb->sb_rdev));
4786 break;
4787 case S_IFREG:
4788 VOID printf (" %8lld", (long long int)(asb->sb_size));
4789 /* VOID printf (" %8ld", (long unsigned int)(asb->sb_size)); */
4790 break;
4791 default:
4792 VOID printf (" ");
4793 }
4794 VOID printf (" %3s %2d %02d:%02d:%02d %4d ",
4795 month[atm->tm_mon], atm->tm_mday, atm->tm_hour,
4796 atm->tm_min, atm->tm_sec, atm->tm_year + 1900);
4797 }
4798
4799 {
4800 char *namedot = strrchr (name, '.');
4801
4802 if (Zflag && (asb->sb_mode & S_IFMT) == S_IFREG
4803 && (asb->sb_rdev & RDEV_NOTCOMPR) == 0
4804 && (asb->sb_size > 0)
4805 && namedot && namedot[1] == 'z' && !namedot[2])
4806 *namedot = '\0';
4807 else
4808 namedot = 0;
4809
4810 if (ISCONTROL(asb)) res = printf("//--");
4811
4812 if ((!useoutmodetoc) && flag0)
4813 res = printf ("%s%c", name, 0);
4814 else
4815 res = printf ("%s", name);
4816
4817 /* to find out about broken pipe as early as possible */
4818 if(res > 0) res = fflush(stdout);
4819 /* check for broken pipe on stdout, this ends the listing */
4820 if(res<0) {
4821 if(errno == EPIPE)
4822 fatal("<stdout>", syserr());
4823 }
4824
4825
4826 if (vflag && namedot)
4827 VOID printf (" -- compressed");
4828 }
4829
4830 if (!flag0 && (vflag || lflag))
4831 {
4832 from=NULL;
4833 if (asb->sb_nlink > 1)
4834 {
4835
4836 if(!useoutmodetoc)
4837 {
4838 if ((from = linkfrom (asb,1)))
4839 VOID printf (" -> %s", from->l_path->p_name);
4840 else
4841 VOID linkto (name, asb);
4842 }
4843 else
4844 {
4845 /* need special logic to resolve hard link info
4846 when in -o mode: because
4847 of side effects of linkfrom and linkto, which were
4848 already called for the file entry, we cannot use
4849 them here again */
4850 if((asb->sb_mode & S_IFMT) != S_IFDIR)
4851 {
4852 for (linkp = *(linkhash (asb->ino_orig)); linkp; linkp = linknext)
4853 {
4854 if (linkp->l_ino == asb->ino_orig
4855 && linkp->l_dev == asb->sb_dev
4856 && strcmp(linkp->l_path->p_name,name)
4857 )
4858 {
4859 VOID printf (" -> %s", linkp->l_path->p_name);
4860 break;
4861 }
4862
4863 linknext = linkp->l_forw;
4864 }
4865 }
4866 }
4867
4868 }
4869
4870 #ifdef S_IFLNK
4871 if (((asb->sb_mode & S_IFMT) == S_IFLNK)&&(from==NULL))
4872 VOID printf (" S-> %s", asb->sb_link);
4873 #endif /* S_IFLNK */
4874 }
4875
4876 if ((!flag0)||useoutmodetoc)
4877 putchar ('\n');
4878 }
4879
4880 /*
4881 * tocmode()
4882 *
4883 * Fancy file mode display.
4884 */
4885 STATIC void
4886 tocmode (mode)
4887 reg mode_t mode;
4888 {
4889 switch (mode & S_IFMT)
4890 {
4891 case S_IFREG:
4892 putchar ('-');
4893 break;
4894 case S_IFDIR:
4895 putchar ('d');
4896 break;
4897 #ifdef S_IFLNK
4898 case S_IFLNK:
4899 putchar ('l');
4900 break;
4901 #endif /* S_IFLNK */
4902 #ifdef S_IFSOCK
4903 case S_IFSOCK:
4904 putchar ('s');
4905 break;
4906 #endif /* S_IFSOCK */
4907 case S_IFBLK:
4908 putchar ('b');
4909 break;
4910 case S_IFCHR:
4911 putchar ('c');
4912 break;
4913 #ifdef S_IFIFO
4914 case S_IFIFO:
4915 putchar ('p');
4916 break;
4917 #endif /* S_IFIFO */
4918 default:
4919 VOID printf ("[%o]", (uint)(mode >> S_IFSHF));
4920 }
4921 putchar (mode & 0400 ? 'r' : '-');
4922 putchar (mode & 0200 ? 'w' : '-');
4923 putchar (mode & 0100
4924 ? mode & 04000 ? 's' : 'x'
4925 : mode & 04000 ? 'S' : '-');
4926 putchar (mode & 0040 ? 'r' : '-');
4927 putchar (mode & 0020 ? 'w' : '-');
4928 putchar (mode & 0010
4929 ? mode & 02000 ? 's' : 'x'
4930 : mode & 02000 ? 'S' : '-');
4931 putchar (mode & 0004 ? 'r' : '-');
4932 putchar (mode & 0002 ? 'w' : '-');
4933 putchar (mode & 0001
4934 ? mode & 01000 ? 't' : 'x'
4935 : mode & 01000 ? 'T' : '-');
4936 }
4937
4938 /*
4939 * usage()
4940 *
4941 * Print a helpful message and exit.
4942 */
4943 STATIC void
4944 usage ()
4945 {
4946 VOID fprintf (stderr, "\n\
4947 Usage: [filename generator] | %s -o [options] archive : write archive\n\
4948 %s -i [options] archive : install archive\n\
4949 %s -t [options] archive : list table-of-contents of archive\n\
4950 %s -r [options] archive : verify archive against filesystem\n\
4951 Frequently used options:\n\
4952 General: -v : verbose\n\
4953 -Z : with -o: gzip files when writing them to the archive,\n\
4954 with -i/t/r: handle archive written with -Z option\n\
4955 -5 : abort instead of creating archive incompatible with cpio\n\
4956 Tape: -s [volsize] : size of volume, can have suffix k or m or g\n\
4957 -b [blocksize] : block size (default is 5120)\n\
4958 -c [count] : buffer count blocks between doing I/O\n\
4959 Install: -n : protect newer files -k : skip corrupt data at beginning\n\
4960 Select: -y [pattern] : only process files matching pattern\n\
4961 -Y [pattern] : do not process files matching pattern\n",
4962 myname, myname, myname, myname);
4963 VOID fprintf (stderr,"Version %s dated %s\n", VERSION, DATE);
4964 exit (1);
4965 }
4966
4967 /*
4968 * warn()
4969 *
4970 * Print a warning message. Always returns -1.
4971 */
4972 STATIC int
4973 warn (what, why)
4974 char *what;
4975 char *why;
4976 {
4977 time_t dietime;
4978 warnings++;
4979 dietime = time ((time_t *) NULL);
4980
4981 VOID fprintf (stderr,
4982 "%s: \"%s\": %s\n",
4983 myname, what, why);
4984 /* ctime() provides the \n for the fprintf. */
4985 if (logfile != (FILE *) 0)
4986 VOID fprintf (logfile, "%s: \"%s\": %s (disk %u) at %s",
4987 myname, what, why, arvolume, ctime (&dietime));
4988 return (-1);
4989 }
4990
4991 STATIC int warn_nocount (what, why)
4992 char *what;
4993 char *why;
4994 {
4995 warnings--;
4996 return warn(what,why);
4997 }
4998
4999 /*
5000 * warnarch()
5001 *
5002 * Print an archive-related warning message, including
5003 * an adjusted file offset. Always returns -1.
5004 */
5005 STATIC int
5006 warnarch (msg, adjust)
5007 char *msg;
5008 off_t adjust;
5009 {
5010 warnings++;
5011 VOID fprintf (stderr, "%s: \"%s\" [offset ", myname, arspec);
5012 prsize (stderr, total - adjust);
5013 VOID fprintf (stderr, "]: %s\n", msg);
5014 return (-1);
5015 }
5016
5017 /*
5018 * xfork()
5019 *
5020 * Create a child.
5021 */
5022 STATIC int
5023 xfork (what, die)
5024 reg char *what;
5025 int die;
5026 {
5027 reg int pid;
5028 reg Child *cp;
5029 reg int idx;
5030 static uint delay[] =
5031 {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144};
5032
5033 /* flush error logfile before fork */
5034 if(logfile != (FILE *)0) fflush(logfile);
5035 /* also flush stdout and stderr */
5036 fflush(stdout);
5037 fflush(stderr);
5038
5039
5040 #ifdef SIGCHLD
5041 VOID signal (SIGCHLD, SIG_DFL); /* SysV mostly... */
5042 #else
5043 VOID signal (SIGCLD, SIG_DFL); /* some SysV's... */
5044 #endif
5045 for (idx = 0; (pid = fork ()) < 0; ++idx)
5046 {
5047 if (idx == sizeof (delay))
5048 {
5049 if (die)
5050 fatal (arspec, syserr ());
5051 else
5052 return (-1);
5053 }
5054
5055 VOID warn_nocount (what, "Trouble forking...");
5056 if (Fflag && !die) /* give up and go on... */
5057 return (-1);
5058 sleep (delay[idx]);
5059 }
5060 if (idx)
5061 VOID warn_nocount (what, "...successful fork");
5062 cp = (Child *) memget (sizeof (*cp));
5063 cp->c_pid = pid;
5064 cp->c_flags = 0;
5065 cp->c_status = 0;
5066 cp->c_forw = children;
5067 children = cp;
5068 return (pid);
5069 }
5070
5071 /*
5072 * xpause()
5073 *
5074 * Await a child.
5075 */
5076 STATIC void
5077 xpause ()
5078 {
5079 reg Child *cp;
5080 reg int pid;
5081 auto int status;
5082
5083 do
5084 {
5085 while ((pid = wait (&status)) < 0)
5086 ;
5087 for (cp = children; cp && cp->c_pid != pid; cp = cp->c_forw)
5088 ;
5089 }
5090 while (cp == NULL);
5091 cp->c_flags |= CF_EXIT;
5092 cp->c_status = status;
5093 }
5094
5095 /*
5096 * xwait()
5097 *
5098 * Find the status of a child.
5099 */
5100 STATIC int
5101 xwait (pid, what, compstat2)
5102 reg int pid;
5103 char *what;
5104 int compstat2;
5105 {
5106 reg int status;
5107 reg Child *cp;
5108 reg Child **acp;
5109 auto char why[100];
5110
5111 for (acp = &children; (cp = *acp); acp = &cp->c_forw)
5112 if (cp->c_pid == pid)
5113 break;
5114 if (cp == NULL)
5115 fatal (what, "Lost child");
5116 while ((cp->c_flags & CF_EXIT) == 0)
5117 xpause ();
5118 status = cp->c_status;
5119 *acp = cp->c_forw;
5120 free ((char *) cp);
5121 if (status == 0)
5122 return (0);
5123 if (status & 0377)
5124 VOID sprintf (why, "Killed by signal %d%s",
5125 status & 0177, status & 0200 ? " -- core dumped" : "");
5126 else
5127 VOID sprintf (why, "Exit %d", (status >> 8) & 0377);
5128
5129 if ((!compstat2 && (((status >> 8) & 0377) != 2)) || compstat2)
5130 return (warn (what, why));
5131 else
5132 return ((status >> 8) & 0377);
5133 }
5134
5135
5136 /* right now we verify the whole disk */
5137 void
5138 verify (error)
5139 int error;
5140 {
5141 char *verbuf;
5142 char *buf;
5143 reg time_t began;
5144 int got, len;
5145 uint readamt;
5146 auto char msg[200];
5147 auto char answer[20];
5148
5149 if (*arname == '!')
5150 {
5151 VOID warn ("Can't verify a piped command", "");
5152 return;
5153 }
5154 if (!error)
5155 {
5156 if ((verbuf = malloc (arbsize)) == NULL)
5157 fatal (arspec, "Cannot allocate Verify I/O buffer");
5158
5159 /*
5160 * close as O_WRONLY and reopen as O_RDONLY to verify (on a
5161 * disk this is a good thing)
5162 */
5163 /* fprintf(stderr,"closing..\n"); */
5164
5165 nextclos ();
5166 verifycnt++;
5167
5168 if (nextopen (O_RDONLY) < 0)
5169 {
5170 VOID warn ("re-open for verify failed", "");
5171 error = 1;
5172 }
5173 else
5174 {
5175 #ifdef linux
5176 /* flush the floppy cache. (added by KH) */
5177 if(Fflag)
5178 { /* fprintf(stderr,"flushing..\n"); */
5179 if (ioctl(arfd,FDFLUSH,NULL) < 0)
5180 warn(arname,"can't flush device cache.");
5181
5182 }
5183 #endif
5184 fprintf (stderr, "Verifying disk %u...\n", arvolume );
5185 for (buf = buffer; (len = bufidx - buf);)
5186 {
5187 readamt = min ((uint)len, arbsize);
5188 if ((uint)(got = read (arfd, verbuf, readamt)) == readamt)
5189 {
5190 #ifdef HAVEMEMCMP
5191 if (memcmp (verbuf, buf, (size_t)got) != 0)
5192 #else
5193 if (bcmp (verbuf, buf, got) != 0)
5194 #endif
5195 {
5196 VOID warn ("Verify failed", "");
5197 error = 1;
5198 break;
5199 }
5200 else
5201 buf += got;
5202 }
5203 else
5204 {
5205 VOID warn ("Read returned short", "");
5206 fprintf (stderr, "Read %d wanted %d bytes\n", got,
5207 readamt);
5208 error = 1;
5209 break;
5210 }
5211 }
5212 }
5213 free (verbuf);
5214 }
5215 if (error)
5216 {
5217 int answernum = 0;
5218 nextclos ();
5219
5220 for (;;)
5221 {
5222 began = time ((time_t *) NULL);
5223 VOID sprintf (msg, "\
5224 %s: %s of disk %u has FAILED!\07\n\
5225 \tEnter 1 to RETRY this disk\n\
5226 \tEnter 2 to REFORMAT this disk before a RETRY\n\07\n%s",
5227 myname,
5228 ((error && (verifycnt == 0)) ? "Writing" :
5229 "Verify"),
5230 arvolume, hidequit ? "" :
5231 "\tEnter \"quit\" to ABORT the backup\n\07");
5232 nextask (msg, answer, sizeof (answer));
5233 timewait += time ((time_t *) NULL) - began;
5234 answernum = atoi (answer);
5235
5236 if (answernum == 1) /* note: recursive here... */
5237 {
5238 /* if we can't open, try again */
5239 if (nextopen (O_WRONLY) < 0)
5240 continue;
5241 }
5242 else if ((answernum == 2) )
5243 {
5244 if (system (formatcmd) != 0)
5245 {
5246 fprintf (stderr, "Format failed!\n");
5247 answernum = 0;/* error, don't autowrite */
5248 }
5249 else
5250 {
5251 fprintf (stderr, "Format successful!\n");
5252 /* if we can't open, try again */
5253 if (nextopen (O_WRONLY) < 0)
5254 continue;
5255 return;
5256 }
5257 }
5258 else if (strcmp (answer, "quit") == 0)
5259 fatal (arspec, "Quitting during a verify");
5260 }
5261 }
5262 }
5263
5264
5265 int
5266 writedisk (realwrite)
5267 int realwrite;
5268 {
5269 reg char *buf;
5270 reg int got;
5271 reg uint len;
5272 int wrstat;
5273 static int firsttime = 1;
5274 /*
5275 * If we're double buffering wait for any pending writes to
5276 * complete before starting next writing
5277 */
5278
5279 if (fflag)
5280 outwait ();
5281
5282 /*
5283 * if we are a floppy open the disk at the last moment
5284 * call verify w/ an error if the disk can't be opened
5285 */
5286 if (Fflag)
5287 {
5288 /* There's something funny in the program in that writedisk() gets
5289 called when there is nothing in the buffer to write; it
5290 apparently gets called twice for each buffer when using the -s
5291 double buffer option. I can't figure out the complex and
5292 undocumented definitions of bufidx and bufend well enough to
5293 stop this double calling, but the only harm done by the second
5294 call is if we call for another disk to be loaded. So we make
5295 sure we only call for a disk if there's actually data to write
5296 on it (i.e. bufidx > buffer). - Bryan Henderson 98.08.12
5297 */
5298 if( ! firsttime && bufidx > buffer )
5299 next( O_WRONLY, "Next disk needed");
5300 else
5301 while( nextopen (O_WRONLY) < 0)
5302 {
5303 verifycnt = 0;
5304 verify (1);
5305 }
5306 firsttime = 0;
5307 }
5308
5309 /*
5310 * If we're double buffering spawn a child to do the
5311 * actual writing, and return immediately
5312 */
5313
5314 if( fflag )
5315 {
5316 outpid = xfork ("outflush()", DIE);
5317 if( outpid != 0 )
5318 {
5319 /* what does this do? It seems to be needed to let -s -f work */
5320 arleft -= bufidx - buffer;
5321
5322 nextclos(); /* added by KH to make verify work */
5323
5324 return(0);
5325 }
5326 else
5327 VOID nice (-10);
5328 }
5329
5330 do
5331 {
5332 wrstat = 0 ;
5333
5334 for (buf = buffer; (len = bufidx - buf);)
5335 {
5336 if ((got = write (arfd, buf,
5337 *arname == '!' ? len : min (len, arbsize))) > 0)
5338 {
5339 buf += got;
5340 if (realwrite)
5341 arleft -= got;
5342 }
5343 else if (fflag)
5344 {
5345 VOID warn (arspec, got < 0
5346 ? syserr ()
5347 : "Apparently full -- archive will be incomplete");
5348 _exit (1);
5349 }
5350 else if (got < 0)
5351 {
5352 if(errno==EPIPE)
5353 fatal(arspec, syserr());
5354
5355 if(errno==ENOSPC) { /* For DAT/DDS -- RAM, 1998/05/19 */
5356 next (O_WRONLY, "No space left on device");
5357 continue; /* Redo failed write on new volume */
5358 }
5359
5360 if(!Jflag)
5361 VOID fatal (arspec, syserr ());
5362 else
5363 {
5364 VOID warn (arspec, syserr ());
5365 anycorrupt=1;
5366 }
5367 wrstat = 1;
5368 break;
5369 }
5370 else
5371 {
5372 if (Fflag && verifyflag)
5373 {
5374 /* can't recover from this one, break out of loop
5375 and let verify detect the mess */
5376 VOID warn (arspec,
5377 "Apparently full already");
5378 wrstat = 1;
5379 break;
5380 }
5381
5382 next (O_WRONLY, "Apparently full");
5383 /* added continue, this creates correct behavior
5384 (no unwritten data) when changing to next volume on
5385 write()=0 -- KH */
5386 continue;
5387 }
5388 }
5389 if (Fflag && verifyflag)
5390 {
5391 verifycnt = 0;
5392 verify ( wrstat );
5393 }
5394
5395 /* Added KH: bug fix for double prompting bug if no -K and -f given */
5396 /* It took me far too long to find this. IMO it was a big mistake to
5397 use arleft, which usually denotes the space left in the buffer, to
5398 denote the space left on the device in this routine.
5399 Talking about spaghetti variables. I'd rather not think about what
5400 will happen if the write/verify error handling stuff gets used.
5401 */
5402 if (Fflag && !verifyflag) arleft = aruntil;
5403
5404
5405 } while( wrstat && Fflag && verifyflag );
5406
5407 if( fflag )
5408 _exit( wrstat );
5409 else
5410 return ( wrstat );
5411
5412 return 0; /* to avoid compiler warning */
5413 }
5414
5415 void
5416 goodbye (status)
5417 int status;
5418 {
5419 /* log that we died */
5420 if (status && (logfile != (FILE *) 0))
5421 {
5422 time_t dietime;
5423 dietime = time ((time_t *) NULL);
5424
5425 VOID fprintf (logfile, "%s: the backup has failed (status %d), died at %s",
5426 myname, status, ctime (&dietime));
5427
5428 }
5429 exit (status);
5430 }
5431
5432 #ifdef MYTEMPNAM
5433 /* author: Monty Walls
5434 * written: 4/17/89
5435 * Copyright: Copyright (c) 1989 by Monty Walls.
5436 * Not derived from licensed software.
5437 *
5438 * Permission to copy and/or distribute granted under the
5439 * following conditions:
5440 *
5441 * 1). This notice must remain intact.
5442 * 2). The author is not responsible for the consequences of use
5443 * this software, no matter how awful, even if they
5444 * arise from defects in it.
5445 * 3). Altered version must not be represented as being the
5446 * original software.
5447 */
5448
5449 #define MAXPREFIX 5
5450 #define TMPNAME "tmp"
5451 #ifndef P_tmpdir
5452 #define P_tmpdir "/tmp"
5453 #define L_tmpnam 14
5454 #endif
5455
5456 extern char *mktemp ();
5457 extern char *strcat ();
5458 extern char *strcpy ();
5459 extern char *getenv ();
5460
5461 char *
5462 tempnam (dir, name)
5463 char *dir;
5464 char *name;
5465 {
5466 char *buf, *tmpdir;
5467
5468 /*
5469 * This is kind of like the chicken & the egg.
5470 * Do we use the users preference or the programmers?
5471 */
5472 #ifdef USE_ENV_VAR
5473 if ((tmpdir = getenv ("TMPDIR")) == (char *) NULL)
5474 {
5475 if ((tmpdir = dir) == (char *) NULL)
5476 tmpdir = P_tmpdir;
5477 }
5478 #else
5479 if ((tmpdir = dir) == (char *) NULL)
5480 {
5481 if ((tmpdir = getenv ("TMPDIR")) == (char *) NULL)
5482 tmpdir = P_tmpdir;
5483 }
5484 #endif
5485 /* now lets check and see if we can work there */
5486 if (access (tmpdir, R_OK + W_OK + X_OK) < 0)
5487 return ((char *) NULL);
5488
5489 if (name == (char *) NULL)
5490 name = TMPNAME;
5491 else if (strlen (name) > MAXPREFIX)
5492 name[5] = '\0'; /* this is according to SYS5 */
5493
5494 /* the magic value 2 is for '\0' & '/' */
5495 if ((buf = (char *) malloc (L_tmpnam + strlen (tmpdir) + 2)) == (char *) NULL)
5496 return ((char *) NULL);
5497
5498 strcpy (buf, tmpdir);
5499 strcat (buf, "/");
5500 strcat (buf, name);
5501 strcat (buf, ".XXXXXX");
5502
5503 /* pass our completed pattern to mktemp */
5504 return (mktemp (buf));
5505 }
5506
5507 #endif /* MYTEMPNAM */