*** empty log message ***
[debian/tar] / src / buffer.c
1 /* Buffer management for tar.
2    Copyright (C) 1988, 1992 Free Software Foundation
3
4 This file is part of GNU Tar.
5
6 GNU Tar is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Tar is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Tar; see the file COPYING.  If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 /*
21  * Buffer management for tar.
22  *
23  * Written by John Gilmore, ihnp4!hoptoad!gnu, on 25 August 1985.
24  */
25
26 #include <stdio.h>
27 #include <errno.h>
28 #ifndef STDC_HEADERS
29 extern int errno;
30 #endif
31 #include <sys/types.h>          /* For non-Berkeley systems */
32 #include <signal.h>
33 #include <time.h>
34 time_t time();
35
36 #ifdef HAVE_SYS_MTIO_H
37 #include <sys/ioctl.h>
38 #include <sys/mtio.h>
39 #endif
40
41 #ifdef BSD42
42 #include <sys/file.h>
43 #else
44 #ifndef V7
45 #include <fcntl.h>
46 #endif
47 #endif
48
49 #ifdef  __MSDOS__
50 #include <process.h>
51 #endif
52
53 #ifdef XENIX
54 #include <sys/inode.h>
55 #endif
56
57 #include "tar.h"
58 #include "port.h"
59 #include "rmt.h"
60 #include "regex.h"
61
62 /* Either stdout or stderr:  The thing we write messages (standard msgs, not
63    errors) to.  Stdout unless we're writing a pipe, in which case stderr */
64 FILE *msg_file = stdout;
65
66 #define STDIN   0               /* Standard input  file descriptor */
67 #define STDOUT  1               /* Standard output file descriptor */
68
69 #define PREAD   0               /* Read  file descriptor from pipe() */
70 #define PWRITE  1               /* Write file descriptor from pipe() */
71
72 #define MAGIC_STAT      105     /* Magic status returned by child, if
73                                    it can't exec.  We hope compress/sh
74                                    never return this status! */
75
76 char *valloc();
77
78 void writeerror();
79 void readerror();
80
81 void ck_pipe();
82 void ck_close();
83
84 int backspace_output();
85 extern void finish_header();
86 void flush_archive();
87 int isfile();
88 int new_volume();
89 void verify_volume();
90 extern void to_oct();
91
92 #ifndef __MSDOS__
93 /* Obnoxious test to see if dimwit is trying to dump the archive */
94 dev_t ar_dev;
95 ino_t ar_ino;
96 #endif
97
98 /*
99  * The record pointed to by save_rec should not be overlaid
100  * when reading in a new tape block.  Copy it to record_save_area first, and
101  * change the pointer in *save_rec to point to record_save_area.
102  * Saved_recno records the record number at the time of the save.
103  * This is used by annofile() to print the record number of a file's
104  * header record.
105  */
106 static union record **save_rec;
107  union record record_save_area;
108 static long         saved_recno;
109
110 /*
111  * PID of child program, if f_compress or remote archive access.
112  */
113 static int      childpid = 0;
114
115 /*
116  * Record number of the start of this block of records
117  */
118 long    baserec;
119
120 /*
121  * Error recovery stuff
122  */
123 static int      r_error_count;
124
125 /*
126  * Have we hit EOF yet?
127  */
128 static int      hit_eof;
129
130 /* Checkpointing counter */
131 static int checkpoint;
132
133 /* JF we're reading, but we just read the last record and its time to update */
134 extern time_to_start_writing;
135 int file_to_switch_to= -1;      /* If remote update, close archive, and use
136                                    this descriptor to write to */
137
138 static int volno = 1;           /* JF which volume of a multi-volume tape
139                                    we're on */
140 static int global_volno = 1;    /* Volume number to print in external messages. */
141
142 char *save_name = 0;            /* Name of the file we are currently writing */
143 long save_totsize;              /* total size of file we are writing.  Only
144                                    valid if save_name is non_zero */
145 long save_sizeleft;             /* Where we are in the file we are writing.
146                                    Only valid if save_name is non-zero */
147
148 int write_archive_to_stdout;
149
150 /* Used by fl_read and fl_write to store the real info about saved names */
151 static char real_s_name[NAMSIZ];
152 static long real_s_totsize;
153 static long real_s_sizeleft;
154
155 /* Reset the EOF flag (if set), and re-set ar_record, etc */
156
157 void
158 reset_eof()
159 {
160         if(hit_eof) {
161                 hit_eof=0;
162                 ar_record=ar_block;
163                 ar_last=ar_block+blocking;
164                 ar_reading=0;
165         }
166 }
167
168 /*
169  * Return the location of the next available input or output record.
170  * Return NULL for EOF.  Once we have returned NULL, we just keep returning
171  * it, to avoid accidentally going on to the next file on the "tape".
172  */
173 union record *
174 findrec()
175 {
176         if (ar_record == ar_last) {
177                 if (hit_eof)
178                         return (union record *)NULL;    /* EOF */
179                 flush_archive();
180                 if (ar_record == ar_last) {
181                         hit_eof++;
182                         return (union record *)NULL;    /* EOF */
183                 }
184         }
185         return ar_record;
186 }
187
188
189 /*
190  * Indicate that we have used all records up thru the argument.
191  * (should the arg have an off-by-1? XXX FIXME)
192  */
193 void
194 userec(rec)
195         union record *rec;
196 {
197         while(rec >= ar_record)
198                 ar_record++;
199         /*
200          * Do NOT flush the archive here.  If we do, the same
201          * argument to userec() could mean the next record (if the
202          * input block is exactly one record long), which is not what
203          * is intended.
204          */
205         if (ar_record > ar_last)
206                 abort();
207 }
208
209
210 /*
211  * Return a pointer to the end of the current records buffer.
212  * All the space between findrec() and endofrecs() is available
213  * for filling with data, or taking data from.
214  */
215 union record *
216 endofrecs()
217 {
218         return ar_last;
219 }
220
221
222 /*
223  * Duplicate a file descriptor into a certain slot.
224  * Equivalent to BSD "dup2" with error reporting.
225  */
226 void
227 dupto(from, to, msg)
228         int from, to;
229         char *msg;
230 {
231         int err;
232
233         if (from != to) {
234                 err=close(to);
235                 if(err<0 && errno!=EBADF) {
236                         msg_perror("Cannot close descriptor %d",to);
237                         exit(EX_SYSTEM);
238                 }
239                 err = dup(from);
240                 if (err != to) {
241                         msg_perror("cannot dup %s",msg);
242                         exit(EX_SYSTEM);
243                 }
244                 ck_close(from);
245         }
246 }
247
248 #ifdef __MSDOS__
249 void
250 child_open()
251 {
252         fprintf(stderr,"MS-DOS %s can't use compressed or remote archives\n",tar);
253         exit(EX_ARGSBAD);
254 }
255 #else
256 void
257 child_open()
258 {
259         int pipe[2];
260         int err = 0;
261         int nar;
262
263         int kidpipe[2];
264         int kidchildpid;
265
266 #define READ    0
267 #define WRITE   1
268
269         ck_pipe(pipe);
270
271         childpid=fork();
272         if(childpid<0) {
273                 msg_perror("cannot fork");
274                 exit(EX_SYSTEM);
275         }
276         if(childpid>0) {
277                 /* We're the parent.  Clean up and be happy */
278                 /* This, at least, is easy */
279
280                 if(ar_reading) {
281                         f_reblock++;
282                         archive=pipe[READ];
283                         ck_close(pipe[WRITE]);
284                 } else {
285                         archive = pipe[WRITE];
286                         ck_close(pipe[READ]);
287                 }
288                 return;
289         }
290
291         /* We're the kid */
292         if(ar_reading) {
293                 dupto(pipe[WRITE],STDOUT,"(child) pipe to stdout");
294                 ck_close(pipe[READ]);
295         } else {
296                 dupto(pipe[READ],STDIN,"(child) pipe to stdin");
297                 ck_close(pipe[WRITE]);
298         }
299
300         /* We need a child tar only if
301            1: we're reading/writing stdin/out (to force reblocking)
302            2: the file is to be accessed by rmt (compress doesn't know how)
303            3: the file is not a plain file */
304 #ifdef NO_REMOTE
305         if(!(ar_files[0][0]=='-' && ar_files[0][1]=='\0') && isfile(ar_files[0]))
306 #else
307         if(!(ar_files[0][0]=='-' && ar_files[0][1]=='\0') && !_remdev(ar_files[0]) && isfile(ar_files[0]))
308 #endif
309         {
310                 /* We don't need a child tar.  Open the archive */
311                 if(ar_reading) {
312                         archive=open(ar_files[0], O_RDONLY|O_BINARY, 0666);
313                         if(archive<0) {
314                                 msg_perror("can't open archive %s",ar_files[0]);
315                                 exit(EX_BADARCH);
316                         }
317                         dupto(archive,STDIN,"archive to stdin");
318                         /* close(archive); */
319                 } else {
320                         archive=creat(ar_files[0],0666);
321                         if(archive<0) {
322                                 msg_perror("can't open archive %s",ar_files[0]);
323                                 exit(EX_BADARCH);
324                         }
325                         dupto(archive,STDOUT,"archive to stdout");
326                         /* close(archive); */
327                 }
328         } else {
329                 /* We need a child tar */
330                 ck_pipe(kidpipe);
331
332                 kidchildpid=fork();
333                 if(kidchildpid<0) {
334                         msg_perror("child can't fork");
335                         exit(EX_SYSTEM);
336                 }
337
338                 if(kidchildpid>0) {
339                         /* About to exec compress:  set up the files */
340                         if(ar_reading) {
341                                 dupto(kidpipe[READ],STDIN,"((child)) pipe to stdin");
342                                 ck_close(kidpipe[WRITE]);
343                                 /* dup2(pipe[WRITE],STDOUT); */
344                         } else {
345                                 /* dup2(pipe[READ],STDIN); */
346                                 dupto(kidpipe[WRITE],STDOUT,"((child)) pipe to stdout");
347                                 ck_close(kidpipe[READ]);
348                         }
349                         /* ck_close(pipe[READ]); */
350                         /* ck_close(pipe[WRITE]); */
351                         /* ck_close(kidpipe[READ]);
352                         ck_close(kidpipe[WRITE]); */
353                 } else {
354                 /* Grandchild.  Do the right thing, namely sit here and
355                    read/write the archive, and feed stuff back to compress */
356                         tar="tar (child)";
357                         if(ar_reading) {
358                                 dupto(kidpipe[WRITE],STDOUT,"[child] pipe to stdout");
359                                 ck_close(kidpipe[READ]);
360                         } else {
361                                 dupto(kidpipe[READ],STDIN,"[child] pipe to stdin");
362                                 ck_close(kidpipe[WRITE]);
363                         }
364
365                         if (ar_files[0][0] == '-' && ar_files[0][1] == '\0') {
366                                 if (ar_reading)
367                                         archive = STDIN;
368                                 else
369                                         archive = STDOUT;
370                         } else /* This can't happen if (ar_reading==2)
371                                 archive = rmtopen(ar_files[0], O_RDWR|O_CREAT|O_BINARY, 0666);
372                         else */if(ar_reading)
373                                 archive = rmtopen(ar_files[0], O_RDONLY|O_BINARY, 0666);
374                         else
375                                 archive = rmtcreat(ar_files[0], 0666);
376
377                         if (archive < 0) {
378                                 msg_perror("can't open archive %s",ar_files[0]);
379                                 exit(EX_BADARCH);
380                         }
381
382                         if(ar_reading) {
383                                 for(;;) {
384                                         char *ptr;
385                                         int max,count;
386                 
387                                         r_error_count = 0;
388                                 error_loop:
389                                         err=rmtread(archive, ar_block->charptr,(int)(blocksize));
390                                         if(err<0) {
391                                                 readerror();
392                                                 goto error_loop;
393                                         }
394                                         if(err==0)
395                                                 break;
396                                         ptr = ar_block->charptr;
397                                         max = err;
398                                         while(max) {
399                                                 count = (max<RECORDSIZE) ? max : RECORDSIZE;
400                                                 err=write(STDOUT,ptr,count);
401                                                 if(err!=count) {
402                                                         if(err<0) {
403                                                                 msg_perror("can't write to compress");
404                                                                 exit(EX_SYSTEM);
405                                                         } else
406                                                                 msg("write to compress short %d bytes",count-err);
407                                                         count = (err<0) ? 0 : err;
408                                                 }
409                                                 ptr+=count;
410                                                 max-=count;
411                                         }
412                                 }
413                         } else {
414                                 for(;;) {
415                                         int n;
416                                         char *ptr;
417                 
418                                         n=blocksize;
419                                         ptr = ar_block->charptr;
420                                         while(n) {
421                                                 err=read(STDIN,ptr,(n<RECORDSIZE) ? n : RECORDSIZE);
422                                                 if(err<=0)
423                                                         break;
424                                                 n-=err;
425                                                 ptr+=err;
426                                         }
427                                                 /* EOF */
428                                         if(err==0) {
429                                                 if(f_compress<2)
430                                                         blocksize-=n;
431                                                 else
432                                                         bzero(ar_block->charptr+blocksize-n,n);
433                                                 err=rmtwrite(archive,ar_block->charptr,blocksize);
434                                                 if(err!=(blocksize))
435                                                         writeerror(err);
436                                                 if(f_compress<2)
437                                                         blocksize+=n;
438                                                 break;
439                                         }
440                                         if(n) {
441                                                 msg_perror("can't read from compress");
442                                                 exit(EX_SYSTEM);
443                                         }
444                                         err=rmtwrite(archive, ar_block->charptr, (int)blocksize);
445                                         if(err!=blocksize)
446                                                 writeerror(err);
447                                 }
448                         }
449                 
450                         /* close_archive(); */
451                         exit(0);
452                 }
453         }
454                 /* So we should exec compress (-d) */
455         if(ar_reading)
456                 execlp("compress", "compress", "-d", (char *)0);
457         else
458                 execlp("compress", "compress", (char *)0);
459         msg_perror("can't exec compress");
460         _exit(EX_SYSTEM);
461 }
462
463
464 /* return non-zero if p is the name of a directory */
465 int
466 isfile(p)
467 char *p;
468 {
469         struct stat stbuf;
470
471         if(stat(p,&stbuf)<0)
472                 return 1;
473         if(S_ISREG(stbuf.st_mode))
474                 return 1;
475         return 0;
476 }
477
478 #endif
479
480 /*
481  * Open an archive file.  The argument specifies whether we are
482  * reading or writing.
483  */
484 /* JF if the arg is 2, open for reading and writing. */
485 void
486 open_archive(reading)
487         int reading;
488 {
489         msg_file = f_exstdout ? stderr : stdout;
490
491         if (blocksize == 0) {
492                 msg("invalid value for blocksize");
493                 exit(EX_ARGSBAD);
494         }
495
496         if(n_ar_files==0) {
497                 msg("No archive name given, what should I do?");
498                 exit(EX_BADARCH);
499         }
500
501         /*NOSTRICT*/
502         if(f_multivol) {
503                 ar_block = (union record *) valloc((unsigned)(blocksize+(2*RECORDSIZE)));
504                 if(ar_block)
505                         ar_block += 2;
506         } else
507                 ar_block = (union record *) valloc((unsigned)blocksize);
508         if (!ar_block) {
509                 msg("could not allocate memory for blocking factor %d",
510                         blocking);
511                 exit(EX_ARGSBAD);
512         }
513
514         ar_record = ar_block;
515         ar_last   = ar_block + blocking;
516         ar_reading = reading;
517
518         if (f_multivol && f_verify)
519           {
520             msg ("cannot verify multi-volume archives");
521             exit (EX_ARGSBAD);
522           }
523         
524         if (f_compress) {
525                 if(reading==2 || f_verify) {
526                         msg("cannot update or verify compressed archives");
527                         exit(EX_ARGSBAD);
528                 }
529                 if (f_multivol) {
530                         msg ("cannot use multi-volume compressed archives");
531                         exit (EX_ARGSBAD);
532                 }
533                 child_open();
534                 if(!reading && ar_files[0][0]=='-' && ar_files[0][1]=='\0')
535                         msg_file = stderr;
536                 /* child_open(rem_host, rem_file); */
537         } else if (ar_files[0][0] == '-' && ar_files[0][1] == '\0') {
538                 f_reblock++;    /* Could be a pipe, be safe */
539                 if(f_verify) {
540                         msg("can't verify stdin/stdout archive");
541                         exit(EX_ARGSBAD);
542                 }
543                 if(reading==2) {
544                         archive=STDIN;
545                         msg_file=stderr;
546                         write_archive_to_stdout++;
547                 } else if (reading)
548                         archive = STDIN;
549                 else {
550                         archive = STDOUT;
551                         msg_file = stderr;
552                 }
553         } else if (reading==2 || f_verify) {
554                 archive = rmtopen(ar_files[0], O_RDWR|O_CREAT|O_BINARY, 0666);
555         } else if(reading) {
556                 archive = rmtopen(ar_files[0], O_RDONLY|O_BINARY, 0666);
557         } else {
558                 archive = rmtcreat(ar_files[0], 0666);
559         }
560         if (archive < 0) {
561                 msg_perror("can't open %s",ar_files[0]);
562                 exit(EX_BADARCH);
563         }
564 #ifndef __MSDOS__
565         if(!_isrmt(archive)) {
566                 struct stat tmp_stat;
567
568                 fstat(archive,&tmp_stat);
569                 if(S_ISREG(tmp_stat.st_mode)) {
570                         ar_dev=tmp_stat.st_dev;
571                         ar_ino=tmp_stat.st_ino;
572                 }
573         }
574 #endif
575
576 #ifdef  __MSDOS__
577         setmode(archive, O_BINARY);
578 #endif
579
580         if (reading) {
581                 ar_last = ar_block;             /* Set up for 1st block = # 0 */
582                 (void) findrec();               /* Read it in, check for EOF */
583
584                 if(f_volhdr) {
585                         union record *head;
586 #if 0
587                         char *ptr;
588
589                         if(f_multivol) {
590                                 ptr=malloc(strlen(f_volhdr)+20);
591                                 sprintf(ptr,"%s Volume %d",f_volhdr,1);
592                         } else
593                                 ptr=f_volhdr;
594 #endif
595                         head=findrec();
596                         if(!head) {
597                                 msg("Archive not labelled to match %s",f_volhdr);
598                                 exit(EX_BADVOL);
599                         }
600                         if (re_match (label_pattern, head->header.arch_name,
601                                       strlen (head->header.arch_name), 0, 0) < 0) {
602                                 msg ("Volume mismatch!  %s!=%s", f_volhdr,
603                                      head->header.arch_name);
604                                 exit (EX_BADVOL);
605                         }
606 #if 0                   
607                         if(strcmp(ptr,head->header.name)) {
608                                 msg("Volume mismatch!  %s!=%s",ptr,head->header.name);
609                                 exit(EX_BADVOL);
610                         }
611                         if(ptr!=f_volhdr)
612                                 free(ptr);
613 #endif
614                 }
615         } else if(f_volhdr) {
616                 bzero((void *)ar_block,RECORDSIZE);
617                 if(f_multivol)
618                         sprintf(ar_block->header.arch_name,"%s Volume 1",f_volhdr);
619                 else
620                         strcpy(ar_block->header.arch_name,f_volhdr);
621                 ar_block->header.linkflag = LF_VOLHDR;
622                 to_oct(time(0), 1+12, ar_block->header.mtime);
623                 finish_header(ar_block);
624                 /* ar_record++; */
625         }
626 }
627
628
629 /*
630  * Remember a union record * as pointing to something that we
631  * need to keep when reading onward in the file.  Only one such
632  * thing can be remembered at once, and it only works when reading
633  * an archive.
634  *
635  * We calculate "offset" then add it because some compilers end up
636  * adding (baserec+ar_record), doing a 9-bit shift of baserec, then
637  * subtracting ar_block from that, shifting it back, losing the top 9 bits.
638  */
639 void
640 saverec(pointer)
641         union record **pointer;
642 {
643         long offset;
644
645         save_rec = pointer;
646         offset = ar_record - ar_block;
647         saved_recno = baserec + offset;
648 }
649
650 /*
651  * Perform a write to flush the buffer.
652  */
653
654 /*send_buffer_to_file();
655   if(new_volume) {
656         deal_with_new_volume_stuff();
657         send_buffer_to_file();
658   }
659  */
660
661 void
662 fl_write()
663 {
664         int err;
665         int copy_back;
666         static long bytes_written = 0;
667
668         if (f_checkpoint && ! (++checkpoint % 10))
669           msg ("Write checkpoint %d\n", checkpoint);
670         if(tape_length && bytes_written >= tape_length * 1024) {
671                 errno = ENOSPC;
672                 err = 0;
673         } else
674                 err = rmtwrite(archive, ar_block->charptr,(int) blocksize);
675         if(err!=blocksize && !f_multivol)
676                 writeerror(err);
677         else if (f_totals)
678                 tot_written += blocksize;
679
680         if(err>0)
681                 bytes_written+=err;
682         if (err == blocksize) {
683                 if(f_multivol) {
684                         if(!save_name) {
685                                 real_s_name[0]='\0';
686                                 real_s_totsize=0;
687                                 real_s_sizeleft = 0;
688                                 return;
689                         }
690 #ifdef __MSDOS__
691                         if(save_name[1]==':')
692                                 save_name+=2;
693 #endif
694                         while(*save_name=='/')
695                                 save_name++;
696
697                         strcpy(real_s_name,save_name);
698                         real_s_totsize = save_totsize;
699                         real_s_sizeleft = save_sizeleft;
700                 }
701                 return;
702         }
703
704         /* We're multivol  Panic if we didn't get the right kind of response */
705         /* ENXIO is for the UNIX PC */
706         if(err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO)
707                 writeerror(err);
708
709         /* If error indicates a short write, we just move to the next tape. */
710
711         if(new_volume(0)<0)
712                 return;
713         bytes_written=0;
714         if(f_volhdr && real_s_name[0]) {
715                 copy_back=2;
716                 ar_block-=2;
717         } else if(f_volhdr || real_s_name[0]) {
718                 copy_back = 1;
719                 ar_block--;
720         } else
721                 copy_back = 0;
722         if(f_volhdr) {
723                 bzero((void *)ar_block,RECORDSIZE);
724                 sprintf(ar_block->header.arch_name,"%s Volume %d",f_volhdr,volno);
725                 to_oct(time(0), 1+12, ar_block->header.mtime);
726                 ar_block->header.linkflag = LF_VOLHDR;
727                 finish_header(ar_block);
728         }
729         if(real_s_name[0]) {
730                 int tmp;
731
732                 if(f_volhdr)
733                         ar_block++;
734                 bzero((void *)ar_block,RECORDSIZE);
735                 strcpy(ar_block->header.arch_name,real_s_name);
736                 ar_block->header.linkflag = LF_MULTIVOL;
737                 to_oct((long)real_s_sizeleft,1+12,
738                        ar_block->header.size);
739                 to_oct((long)real_s_totsize-real_s_sizeleft,
740                        1+12,ar_block->header.offset);
741                 tmp=f_verbose;
742                 f_verbose=0;
743                 finish_header(ar_block);
744                 f_verbose=tmp;
745                 if(f_volhdr)
746                         ar_block--;
747         }
748
749         err = rmtwrite(archive, ar_block->charptr,(int) blocksize);
750         if(err!=blocksize)
751                 writeerror(err);
752         else if (f_totals)
753                 tot_written += blocksize;
754                 
755
756         bytes_written = blocksize;
757         if(copy_back) {
758                 ar_block+=copy_back;
759                 bcopy((void *)(ar_block+blocking-copy_back),
760                       (void *)ar_record,
761                       copy_back*RECORDSIZE);
762                 ar_record+=copy_back;
763
764                 if(real_s_sizeleft>=copy_back*RECORDSIZE)
765                         real_s_sizeleft-=copy_back*RECORDSIZE;
766                 else if((real_s_sizeleft+RECORDSIZE-1)/RECORDSIZE<=copy_back)
767                         real_s_name[0] = '\0';
768                 else {
769 #ifdef __MSDOS__
770                         if(save_name[1]==':')
771                                 save_name+=2;
772 #endif
773                         while(*save_name=='/')
774                                 save_name++;
775
776                         strcpy(real_s_name,save_name);
777                         real_s_sizeleft = save_sizeleft;
778                         real_s_totsize=save_totsize;
779                 }
780                 copy_back = 0;
781         }
782 }
783
784 /* Handle write errors on the archive.  Write errors are always fatal */
785 /* Hitting the end of a volume does not cause a write error unless the write
786 *  was the first block of the volume */
787
788 void
789 writeerror(err)
790 int err;
791 {
792         if (err < 0) {
793                 msg_perror("can't write to %s",ar_files[cur_ar_file]);
794                 exit(EX_BADARCH);
795         } else {
796                 msg("only wrote %u of %u bytes to %s",err,blocksize,ar_files[cur_ar_file]);
797                 exit(EX_BADARCH);
798         }
799 }
800
801 /*
802  * Handle read errors on the archive.
803  *
804  * If the read should be retried, readerror() returns to the caller.
805  */
806 void
807 readerror()
808 {
809 #       define  READ_ERROR_MAX  10
810
811         read_error_flag++;              /* Tell callers */
812
813         msg_perror("read error on %s",ar_files[cur_ar_file]);
814
815         if (baserec == 0) {
816                 /* First block of tape.  Probably stupidity error */
817                 exit(EX_BADARCH);
818         }
819
820         /*
821          * Read error in mid archive.  We retry up to READ_ERROR_MAX times
822          * and then give up on reading the archive.  We set read_error_flag
823          * for our callers, so they can cope if they want.
824          */
825         if (r_error_count++ > READ_ERROR_MAX) {
826                 msg("Too many errors, quitting.");
827                 exit(EX_BADARCH);
828         }
829         return;
830 }
831
832
833 /*
834  * Perform a read to flush the buffer.
835  */
836 void
837 fl_read()
838 {
839         int err;                /* Result from system call */
840         int left;               /* Bytes left */
841         char *more;             /* Pointer to next byte to read */
842
843         if (f_checkpoint && ! (++checkpoint % 10))
844           msg ("Read checkpoint %d\n", checkpoint);
845
846         /*
847          * Clear the count of errors.  This only applies to a single
848          * call to fl_read.  We leave read_error_flag alone; it is
849          * only turned off by higher level software.
850          */
851         r_error_count = 0;      /* Clear error count */
852
853         /*
854          * If we are about to wipe out a record that
855          * somebody needs to keep, copy it out to a holding
856          * area and adjust somebody's pointer to it.
857          */
858         if (save_rec &&
859             *save_rec >= ar_record &&
860             *save_rec < ar_last) {
861                 record_save_area = **save_rec;
862                 *save_rec = &record_save_area;
863         }
864         if(write_archive_to_stdout && baserec!=0) {
865                 err=rmtwrite(1, ar_block->charptr, blocksize);
866                 if(err!=blocksize)
867                         writeerror(err);
868         }
869         if(f_multivol) {
870                 if(save_name) {
871                         if(save_name!=real_s_name) {
872 #ifdef __MSDOS__
873                                 if(save_name[1]==':')
874                                         save_name+=2;
875 #endif
876                                 while(*save_name=='/')
877                                         save_name++;
878
879                                 strcpy(real_s_name,save_name);
880                                 save_name=real_s_name;
881                         }
882                         real_s_totsize = save_totsize;
883                         real_s_sizeleft = save_sizeleft;
884                                 
885                 } else {
886                         real_s_name[0]='\0';
887                         real_s_totsize=0;
888                         real_s_sizeleft = 0;
889                 }
890         }
891
892 error_loop:
893         err = rmtread(archive, ar_block->charptr, (int)blocksize);
894         if (err == blocksize)
895                 return;
896
897         if((err == 0 || (err<0 && errno==ENOSPC) || (err > 0 && !f_reblock)) && f_multivol) {
898                 union record *head;
899
900         try_volume:
901                 if(new_volume((cmd_mode==CMD_APPEND || cmd_mode==CMD_CAT || cmd_mode==CMD_UPDATE) ? 2 : 1)<0)
902                         return;
903         vol_error:
904                 err = rmtread(archive, ar_block->charptr,(int) blocksize);
905                 if(err < 0) {
906                         readerror();
907                         goto vol_error;
908                 }
909                 if(err!=blocksize)
910                         goto short_read;
911
912                 head=ar_block;
913
914                 if(head->header.linkflag==LF_VOLHDR) {
915                         if(f_volhdr) {
916 #if 0
917                                 char *ptr;
918
919                                 ptr=(char *)malloc(strlen(f_volhdr)+20);
920                                 sprintf(ptr,"%s Volume %d",f_volhdr,volno);
921 #endif
922                                 if (re_match (label_pattern, head->header.arch_name,
923                                               strlen (head->header.arch_name),
924                                               0, 0) < 0) {
925                                         msg("Volume mismatch! %s!=%s",f_volhdr,
926                                             head->header.arch_name);
927                                         --volno;
928                                         --global_volno;
929                                         goto try_volume;
930                                       }
931                                     
932 #if 0
933                                 if(strcmp(ptr,head->header.name)) {
934                                         msg("Volume mismatch! %s!=%s",ptr,head->header.name);
935                                         --volno;
936                                         --global_volno;
937                                         free(ptr);
938                                         goto try_volume;
939                                 }
940                                 free(ptr);
941 #endif
942                         }
943                         if(f_verbose)
944                                 fprintf(msg_file,"Reading %s\n",head->header.arch_name);
945                         head++;
946                 } else if(f_volhdr) {
947                         msg("Warning:  No volume header!");
948                 }
949
950                 if(real_s_name[0]) {
951                         long from_oct();
952
953                         if(head->header.linkflag!=LF_MULTIVOL || strcmp(head->header.arch_name,real_s_name)) {
954                                 msg("%s is not continued on this volume!",real_s_name);
955                                 --volno;
956                                 --global_volno;
957                                 goto try_volume;
958                         }
959                         if(real_s_totsize!=from_oct(1+12,head->header.size)+from_oct(1+12,head->header.offset)) {
960                                 msg("%s is the wrong size (%ld!=%ld+%ld)",
961                                        head->header.arch_name,save_totsize,
962                                        from_oct(1+12,head->header.size),
963                                        from_oct(1+12,head->header.offset));
964                                 --volno;
965                                 --global_volno;
966                                 goto try_volume;
967                         }
968                         if(real_s_totsize-real_s_sizeleft!=from_oct(1+12,head->header.offset)) {
969                                 msg("This volume is out of sequence");
970                                 --volno;
971                                 --global_volno;
972                                 goto try_volume;
973                         }
974                         head++;
975                 }
976                 ar_record=head;
977                 return;
978         } else if (err < 0) {
979                 readerror();
980                 goto error_loop;        /* Try again */
981         }
982
983  short_read:
984         more = ar_block->charptr + err;
985         left = blocksize - err;
986
987 again:
988         if (0 == (((unsigned)left) % RECORDSIZE)) {
989                 /* FIXME, for size=0, multi vol support */
990                 /* On the first block, warn about the problem */
991                 if (!f_reblock && baserec == 0 && f_verbose && err > 0) {
992                 /*      msg("Blocksize = %d record%s",
993                                 err / RECORDSIZE, (err > RECORDSIZE)? "s": "");*/
994                         msg("Blocksize = %d records", err / RECORDSIZE);
995                 }
996                 ar_last = ar_block + ((unsigned)(blocksize - left))/RECORDSIZE;
997                 return;
998         }
999         if (f_reblock) {
1000                 /*
1001                  * User warned us about this.  Fix up.
1002                  */
1003                 if (left > 0) {
1004 error2loop:
1005                         err = rmtread(archive, more, (int)left);
1006                         if (err < 0) {
1007                                 readerror();
1008                                 goto error2loop;        /* Try again */
1009                         }
1010                         if (err == 0) {
1011                                 msg("archive %s EOF not on block boundary",ar_files[cur_ar_file]);
1012                                 exit(EX_BADARCH);
1013                         }
1014                         left -= err;
1015                         more += err;
1016                         goto again;
1017                 }
1018         } else {
1019                 msg("only read %d bytes from archive %s",err,ar_files[cur_ar_file]);
1020                 exit(EX_BADARCH);
1021         }
1022 }
1023
1024
1025 /*
1026  * Flush the current buffer to/from the archive.
1027  */
1028 void
1029 flush_archive()
1030 {
1031         int c;
1032
1033         baserec += ar_last - ar_block;  /* Keep track of block #s */
1034         ar_record = ar_block;           /* Restore pointer to start */
1035         ar_last = ar_block + blocking;  /* Restore pointer to end */
1036
1037         if (ar_reading) {
1038                 if(time_to_start_writing) {
1039                         time_to_start_writing=0;
1040                         ar_reading=0;
1041
1042                         if(file_to_switch_to>=0) {
1043                                 if((c=rmtclose(archive))<0)
1044                                         msg_perror("Warning: can't close %s(%d,%d)",ar_files[cur_ar_file],archive,c);
1045
1046                                 archive=file_to_switch_to;
1047                         } else
1048                                 (void)backspace_output();
1049                         fl_write();
1050                 } else
1051                         fl_read();
1052         } else {
1053                 fl_write();
1054         }
1055 }
1056
1057 /* Backspace the archive descriptor by one blocks worth.
1058    If its a tape, MTIOCTOP will work.  If its something else,
1059    we try to seek on it.  If we can't seek, we lose! */
1060 int
1061 backspace_output()
1062 {
1063         long cur;
1064         /* int er; */
1065         extern char *output_start;
1066
1067 #ifdef MTIOCTOP
1068         struct mtop t;
1069
1070         t.mt_op = MTBSR;
1071         t.mt_count = 1;
1072         if((rmtioctl(archive,MTIOCTOP,&t))>=0)
1073                 return 1;
1074         if(errno==EIO && (rmtioctl(archive,MTIOCTOP,&t))>=0)
1075                 return 1;
1076 #endif
1077
1078                 cur=rmtlseek(archive,0L,1);
1079         cur-=blocksize;
1080         /* Seek back to the beginning of this block and
1081            start writing there. */
1082
1083         if(rmtlseek(archive,cur,0)!=cur) {
1084                 /* Lseek failed.  Try a different method */
1085                 msg("Couldn't backspace archive file.  It may be unreadable without -i.");
1086                 /* Replace the first part of the block with nulls */
1087                 if(ar_block->charptr!=output_start)
1088                         bzero(ar_block->charptr,output_start-ar_block->charptr);
1089                 return 2;
1090         }
1091         return 3;
1092 }
1093
1094
1095 /*
1096  * Close the archive file.
1097  */
1098 void
1099 close_archive()
1100 {
1101         int child;
1102         int status;
1103         int c;
1104
1105         if (time_to_start_writing || !ar_reading)
1106                 flush_archive();
1107         if(cmd_mode==CMD_DELETE) {
1108                 off_t pos;
1109
1110                 pos = rmtlseek(archive,0L,1);
1111 #ifndef __MSDOS__
1112                 (void) ftruncate(archive,pos);
1113 #else
1114                 (void)rmtwrite(archive,"",0);
1115 #endif
1116         }
1117         if(f_verify)
1118                 verify_volume();
1119
1120         if((c=rmtclose(archive))<0)
1121                 msg_perror("Warning: can't close %s(%d,%d)",ar_files[cur_ar_file],archive,c);
1122
1123 #ifndef __MSDOS__
1124         if (childpid) {
1125                 /*
1126                  * Loop waiting for the right child to die, or for
1127                  * no more kids.
1128                  */
1129                 while (((child = wait(&status)) != childpid) && child != -1)
1130                         ;
1131
1132                 if (child != -1) {
1133                         switch (WTERMSIG(status)) {
1134                         case 0:
1135                                 /* Child voluntarily terminated  -- but why? */
1136                                 if (WEXITSTATUS(status) == MAGIC_STAT) {
1137                                         exit(EX_SYSTEM);/* Child had trouble */
1138                                 }
1139                                 if (WEXITSTATUS(status) == (SIGPIPE + 128)) {
1140                                         /*
1141                                          * /bin/sh returns this if its child
1142                                          * dies with SIGPIPE.  'Sok.
1143                                          */
1144                                         break;
1145                                 } else if (WEXITSTATUS(status))
1146                                         msg("child returned status %d",
1147                                                 WEXITSTATUS(status));
1148                         case SIGPIPE:
1149                                 break;          /* This is OK. */
1150
1151                         default:
1152                                 msg("child died with signal %d%s",
1153                                  WTERMSIG(status),
1154                                  WIFCOREDUMPED(status)? " (core dumped)": "");
1155                         }
1156                 }
1157         }
1158 #endif  /* __MSDOS__ */
1159 }
1160
1161
1162 #ifdef DONTDEF
1163 /*
1164  * Message management.
1165  *
1166  * anno writes a message prefix on stream (eg stdout, stderr).
1167  *
1168  * The specified prefix is normally output followed by a colon and a space.
1169  * However, if other command line options are set, more output can come
1170  * out, such as the record # within the archive.
1171  *
1172  * If the specified prefix is NULL, no output is produced unless the
1173  * command line option(s) are set.
1174  *
1175  * If the third argument is 1, the "saved" record # is used; if 0, the
1176  * "current" record # is used.
1177  */
1178 void
1179 anno(stream, prefix, savedp)
1180         FILE    *stream;
1181         char    *prefix;
1182         int     savedp;
1183 {
1184 #       define  MAXANNO 50
1185         char    buffer[MAXANNO];        /* Holds annorecment */
1186 #       define  ANNOWIDTH 13
1187         int     space;
1188         long    offset;
1189         int     save_e;
1190
1191         save_e=errno;
1192         /* Make sure previous output gets out in sequence */
1193         if (stream == stderr)
1194                 fflush(stdout);
1195         if (f_sayblock) {
1196                 if (prefix) {
1197                         fputs(prefix, stream);
1198                         putc(' ', stream);
1199                 }
1200                 offset = ar_record - ar_block;
1201                 (void) sprintf(buffer, "rec %d: ",
1202                         savedp? saved_recno:
1203                                 baserec + offset);
1204                 fputs(buffer, stream);
1205                 space = ANNOWIDTH - strlen(buffer);
1206                 if (space > 0) {
1207                         fprintf(stream, "%*s", space, "");
1208                 }
1209         } else if (prefix) {
1210                 fputs(prefix, stream);
1211                 fputs(": ", stream);
1212         }
1213         errno=save_e;
1214 }
1215 #endif
1216
1217 /* Called to initialize the global volume number. */
1218 int
1219 init_volume_number ()
1220 {
1221   FILE *vf;
1222   
1223   vf = fopen (f_volno_file, "r");
1224   if (!vf && errno != ENOENT)
1225     msg_perror ("%s", f_volno_file);
1226   
1227   if (vf)
1228     {
1229       fscanf (vf, "%d", &global_volno);
1230       fclose (vf);
1231     }
1232 }
1233
1234 /* Called to write out the closing global volume number. */
1235 int
1236 closeout_volume_number ()
1237 {
1238   FILE *vf;
1239   
1240   vf = fopen (f_volno_file, "w");
1241   if (!vf)
1242     msg_perror ("%s", f_volno_file);
1243   else
1244     {
1245       fprintf (vf, "%d\n", global_volno);
1246       fclose (vf);
1247     }
1248 }
1249   
1250 /* We've hit the end of the old volume.  Close it and open the next one */
1251 /* Values for type:  0: writing  1: reading  2: updating */
1252 int
1253 new_volume(type)
1254 int     type;
1255 {
1256         int     c;
1257         char    inbuf[80];
1258         char    *p;
1259         static FILE *read_file = 0;
1260         extern int now_verifying;
1261         extern char TTY_NAME[];
1262         char *getenv();
1263         static int looped = 0;
1264
1265         if(!read_file && !f_run_script_at_end)
1266                 read_file = (archive==0) ? fopen(TTY_NAME, "r") : stdin;
1267
1268         if(now_verifying)
1269                 return -1;
1270         if(f_verify)
1271                 verify_volume();
1272         if((c=rmtclose(archive))<0)
1273                 msg_perror("Warning: can't close %s(%d,%d)",ar_files[cur_ar_file],archive,c);
1274
1275         global_volno++;
1276         volno++;
1277         cur_ar_file++;
1278         if (cur_ar_file == n_ar_files)
1279           {
1280             cur_ar_file = 0;
1281             looped = 1;
1282           }
1283         
1284  tryagain:
1285         if (looped)
1286           {
1287             /* We have to prompt from now on. */
1288             if (f_run_script_at_end)
1289                     system(info_script);
1290             else for(;;) {
1291                     fprintf(msg_file,"\007Prepare volume #%d for %s and hit return: ",global_volno, ar_files[cur_ar_file]);
1292                     fflush(msg_file);
1293                     if(fgets(inbuf,sizeof(inbuf),read_file)==0) {
1294                             fprintf(msg_file,"EOF?  What does that mean?");
1295                             if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF)
1296                                     msg("Warning:  Archive is INCOMPLETE!");
1297                             exit(EX_BADARCH);
1298                     }
1299                     if(inbuf[0]=='\n' || inbuf[0]=='y' || inbuf[0]=='Y')
1300                             break;
1301
1302                     switch(inbuf[0]) {
1303                     case '?':
1304                     {
1305                             fprintf(msg_file,"\
1306  n [name]   Give a new filename for the next (and subsequent) volume(s)\n\
1307  q          Abort tar\n\
1308  !          Spawn a subshell\n\
1309  ?          Print this list\n");
1310                     }
1311                             break;
1312
1313                     case 'q':   /* Quit */
1314                             fprintf(msg_file,"No new volume; exiting.\n");
1315                             if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF)
1316                                     msg("Warning:  Archive is INCOMPLETE!");
1317                             exit(EX_BADARCH);
1318
1319                     case 'n':   /* Get new file name */
1320                     {
1321                             char *q,*r;
1322                             static char *old_name;
1323
1324                             for(q= &inbuf[1];*q==' ' || *q=='\t';q++)
1325                                     ;
1326                             for(r=q;*r;r++)
1327                                     if(*r=='\n')
1328                                             *r='\0';
1329                             old_name=p=(char *)malloc((unsigned)(strlen(q)+2));
1330                             if(p==0) {
1331                                     msg("Can't allocate memory for name");
1332                                     exit(EX_SYSTEM);
1333                             }
1334                             (void) strcpy(p,q);
1335                             ar_files[cur_ar_file]=p;
1336                     }
1337                             break;
1338
1339                     case '!':
1340 #ifdef __MSDOS__
1341                             spawnl(P_WAIT,getenv("COMSPEC"),"-",0);
1342 #else
1343                                     /* JF this needs work! */
1344                             switch(fork()) {
1345                             case -1:
1346                                     msg_perror("can't fork!");
1347                                     break;
1348                             case 0:
1349                                     p=getenv("SHELL");
1350                                     if(p==0) p="/bin/sh";
1351                                     execlp(p,"-sh","-i",0);
1352                                     msg_perror("can't exec a shell %s",p);
1353                                     _exit(55);
1354                             default:
1355                                     wait(0);
1356                                     break;
1357                             }
1358 #endif
1359                             break;
1360                   }
1361                   }
1362         }
1363         
1364
1365         if(type==2 || f_verify)
1366                 archive=rmtopen(ar_files[cur_ar_file],O_RDWR|O_CREAT,0666);
1367         else if(type==1)
1368                 archive=rmtopen(ar_files[cur_ar_file],O_RDONLY,0666);
1369         else if(type==0)
1370                 archive=rmtcreat(ar_files[cur_ar_file],0666);
1371         else
1372                 archive= -1;
1373
1374         if(archive<0) {
1375                 msg_perror("can't open %s",ar_files[cur_ar_file]);
1376                 goto tryagain;
1377         }
1378 #ifdef __MSDOS__
1379         setmode(archive,O_BINARY);
1380 #endif
1381         return 0;
1382 }
1383
1384 /* this is a useless function that takes a buffer returned by wantbytes
1385    and does nothing with it.  If the function called by wantbytes returns
1386    an error indicator (non-zero), this function is called for the rest of
1387    the file.
1388  */
1389 int
1390 no_op(size,data)
1391 int size;
1392 char *data;
1393 {
1394         return 0;
1395 }
1396
1397 /* Some other routine wants SIZE bytes in the archive.  For each chunk of
1398    the archive, call FUNC with the size of the chunk, and the address of
1399    the chunk it can work with.
1400  */
1401 int
1402 wantbytes(size,func)
1403 long size;
1404 int (*func)();
1405 {
1406         char *data;
1407         long    data_size;
1408
1409         while(size) {
1410                 data = findrec()->charptr;
1411                 if (data == NULL) {     /* Check it... */
1412                         msg("Unexpected EOF on archive file");
1413                         return -1;
1414                 }
1415                 data_size = endofrecs()->charptr - data;
1416                 if(data_size>size)
1417                         data_size=size;
1418                 if((*func)(data_size,data))
1419                         func=no_op;
1420                 userec((union record *)(data + data_size - 1));
1421                 size-=data_size;
1422         }
1423         return 0;
1424 }