]> Dogcows Code - chaz/tar/blob - src/buffer.c
*** empty log message ***
[chaz/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
262 int kidpipe[2];
263 int kidchildpid;
264
265 #define READ 0
266 #define WRITE 1
267
268 ck_pipe(pipe);
269
270 childpid=fork();
271 if(childpid<0) {
272 msg_perror("cannot fork");
273 exit(EX_SYSTEM);
274 }
275 if(childpid>0) {
276 /* We're the parent. Clean up and be happy */
277 /* This, at least, is easy */
278
279 if(ar_reading) {
280 f_reblock++;
281 archive=pipe[READ];
282 ck_close(pipe[WRITE]);
283 } else {
284 archive = pipe[WRITE];
285 ck_close(pipe[READ]);
286 }
287 return;
288 }
289
290 /* We're the kid */
291 if(ar_reading) {
292 dupto(pipe[WRITE],STDOUT,"(child) pipe to stdout");
293 ck_close(pipe[READ]);
294 } else {
295 dupto(pipe[READ],STDIN,"(child) pipe to stdin");
296 ck_close(pipe[WRITE]);
297 }
298
299 /* We need a child tar only if
300 1: we're reading/writing stdin/out (to force reblocking)
301 2: the file is to be accessed by rmt (compress doesn't know how)
302 3: the file is not a plain file */
303 #ifdef NO_REMOTE
304 if(!(ar_file[0]=='-' && ar_file[1]=='\0') && isfile(ar_file))
305 #else
306 if(!(ar_file[0]=='-' && ar_file[1]=='\0') && !_remdev(ar_file) && isfile(ar_file))
307 #endif
308 {
309 /* We don't need a child tar. Open the archive */
310 if(ar_reading) {
311 archive=open(ar_file, O_RDONLY|O_BINARY, 0666);
312 if(archive<0) {
313 msg_perror("can't open archive %s",ar_file);
314 exit(EX_BADARCH);
315 }
316 dupto(archive,STDIN,"archive to stdin");
317 /* close(archive); */
318 } else {
319 archive=creat(ar_file,0666);
320 if(archive<0) {
321 msg_perror("can't open archive %s",ar_file);
322 exit(EX_BADARCH);
323 }
324 dupto(archive,STDOUT,"archive to stdout");
325 /* close(archive); */
326 }
327 } else {
328 /* We need a child tar */
329 ck_pipe(kidpipe);
330
331 kidchildpid=fork();
332 if(kidchildpid<0) {
333 msg_perror("child can't fork");
334 exit(EX_SYSTEM);
335 }
336
337 if(kidchildpid>0) {
338 /* About to exec compress: set up the files */
339 if(ar_reading) {
340 dupto(kidpipe[READ],STDIN,"((child)) pipe to stdin");
341 ck_close(kidpipe[WRITE]);
342 /* dup2(pipe[WRITE],STDOUT); */
343 } else {
344 /* dup2(pipe[READ],STDIN); */
345 dupto(kidpipe[WRITE],STDOUT,"((child)) pipe to stdout");
346 ck_close(kidpipe[READ]);
347 }
348 /* ck_close(pipe[READ]); */
349 /* ck_close(pipe[WRITE]); */
350 /* ck_close(kidpipe[READ]);
351 ck_close(kidpipe[WRITE]); */
352 } else {
353 /* Grandchild. Do the right thing, namely sit here and
354 read/write the archive, and feed stuff back to compress */
355 tar="tar (child)";
356 if(ar_reading) {
357 dupto(kidpipe[WRITE],STDOUT,"[child] pipe to stdout");
358 ck_close(kidpipe[READ]);
359 } else {
360 dupto(kidpipe[READ],STDIN,"[child] pipe to stdin");
361 ck_close(kidpipe[WRITE]);
362 }
363
364 if (ar_file[0] == '-' && ar_file[1] == '\0') {
365 if (ar_reading)
366 archive = STDIN;
367 else
368 archive = STDOUT;
369 } else /* This can't happen if (ar_reading==2)
370 archive = rmtopen(ar_file, O_RDWR|O_CREAT|O_BINARY, 0666);
371 else */if(ar_reading)
372 archive = rmtopen(ar_file, O_RDONLY|O_BINARY, 0666);
373 else
374 archive = rmtcreat(ar_file, 0666);
375
376 if (archive < 0) {
377 msg_perror("can't open archive %s",ar_file);
378 exit(EX_BADARCH);
379 }
380
381 if(ar_reading) {
382 for(;;) {
383 char *ptr;
384 int max,count;
385
386 r_error_count = 0;
387 error_loop:
388 err=rmtread(archive, ar_block->charptr,(int)(blocksize));
389 if(err<0) {
390 readerror();
391 goto error_loop;
392 }
393 if(err==0)
394 break;
395 ptr = ar_block->charptr;
396 max = err;
397 while(max) {
398 count = (max<RECORDSIZE) ? max : RECORDSIZE;
399 err=write(STDOUT,ptr,count);
400 if(err!=count) {
401 if(err<0) {
402 msg_perror("can't write to compress");
403 exit(EX_SYSTEM);
404 } else
405 msg("write to compress short %d bytes",count-err);
406 count = (err<0) ? 0 : err;
407 }
408 ptr+=count;
409 max-=count;
410 }
411 }
412 } else {
413 for(;;) {
414 int n;
415 char *ptr;
416
417 n=blocksize;
418 ptr = ar_block->charptr;
419 while(n) {
420 err=read(STDIN,ptr,(n<RECORDSIZE) ? n : RECORDSIZE);
421 if(err<=0)
422 break;
423 n-=err;
424 ptr+=err;
425 }
426 /* EOF */
427 if(err==0) {
428 if(f_compress<2)
429 blocksize-=n;
430 else
431 bzero(ar_block->charptr+blocksize-n,n);
432 err=rmtwrite(archive,ar_block->charptr,blocksize);
433 if(err!=(blocksize))
434 writeerror(err);
435 if(f_compress<2)
436 blocksize+=n;
437 break;
438 }
439 if(n) {
440 msg_perror("can't read from compress");
441 exit(EX_SYSTEM);
442 }
443 err=rmtwrite(archive, ar_block->charptr, (int)blocksize);
444 if(err!=blocksize)
445 writeerror(err);
446 }
447 }
448
449 /* close_archive(); */
450 exit(0);
451 }
452 }
453 /* So we should exec compress (-d) */
454 if(ar_reading)
455 execlp("compress", "compress", "-d", (char *)0);
456 else
457 execlp("compress", "compress", (char *)0);
458 msg_perror("can't exec compress");
459 _exit(EX_SYSTEM);
460 }
461
462
463 /* return non-zero if p is the name of a directory */
464 int
465 isfile(p)
466 char *p;
467 {
468 struct stat stbuf;
469
470 if(stat(p,&stbuf)<0)
471 return 1;
472 if(S_ISREG(stbuf.st_mode))
473 return 1;
474 return 0;
475 }
476
477 #endif
478
479 /*
480 * Open an archive file. The argument specifies whether we are
481 * reading or writing.
482 */
483 /* JF if the arg is 2, open for reading and writing. */
484 void
485 open_archive(reading)
486 int reading;
487 {
488 msg_file = f_exstdout ? stderr : stdout;
489
490 if (blocksize == 0) {
491 msg("invalid value for blocksize");
492 exit(EX_ARGSBAD);
493 }
494
495 if(ar_file==0) {
496 msg("No archive name given, what should I do?");
497 exit(EX_BADARCH);
498 }
499
500 /*NOSTRICT*/
501 if(f_multivol) {
502 ar_block = (union record *) valloc((unsigned)(blocksize+(2*RECORDSIZE)));
503 if(ar_block)
504 ar_block += 2;
505 } else
506 ar_block = (union record *) valloc((unsigned)blocksize);
507 if (!ar_block) {
508 msg("could not allocate memory for blocking factor %d",
509 blocking);
510 exit(EX_ARGSBAD);
511 }
512
513 ar_record = ar_block;
514 ar_last = ar_block + blocking;
515 ar_reading = reading;
516
517 if (f_compress) {
518 if(reading==2 || f_verify) {
519 msg("cannot update or verify compressed archives");
520 exit(EX_ARGSBAD);
521 }
522 child_open();
523 if(!reading && ar_file[0]=='-' && ar_file[1]=='\0')
524 msg_file = stderr;
525 /* child_open(rem_host, rem_file); */
526 } else if (ar_file[0] == '-' && ar_file[1] == '\0') {
527 f_reblock++; /* Could be a pipe, be safe */
528 if(f_verify) {
529 msg("can't verify stdin/stdout archive");
530 exit(EX_ARGSBAD);
531 }
532 if(reading==2) {
533 archive=STDIN;
534 msg_file=stderr;
535 write_archive_to_stdout++;
536 } else if (reading)
537 archive = STDIN;
538 else {
539 archive = STDOUT;
540 msg_file = stderr;
541 }
542 } else if (reading==2 || f_verify) {
543 archive = rmtopen(ar_file, O_RDWR|O_CREAT|O_BINARY, 0666);
544 } else if(reading) {
545 archive = rmtopen(ar_file, O_RDONLY|O_BINARY, 0666);
546 } else {
547 archive = rmtcreat(ar_file, 0666);
548 }
549 if (archive < 0) {
550 msg_perror("can't open %s",ar_file);
551 exit(EX_BADARCH);
552 }
553 #ifndef __MSDOS__
554 if(!_isrmt(archive)) {
555 struct stat tmp_stat;
556
557 fstat(archive,&tmp_stat);
558 if(S_ISREG(tmp_stat.st_mode)) {
559 ar_dev=tmp_stat.st_dev;
560 ar_ino=tmp_stat.st_ino;
561 }
562 }
563 #endif
564
565 #ifdef __MSDOS__
566 setmode(archive, O_BINARY);
567 #endif
568
569 if (reading) {
570 ar_last = ar_block; /* Set up for 1st block = # 0 */
571 (void) findrec(); /* Read it in, check for EOF */
572
573 if(f_volhdr) {
574 union record *head;
575 #if 0
576 char *ptr;
577
578 if(f_multivol) {
579 ptr=malloc(strlen(f_volhdr)+20);
580 sprintf(ptr,"%s Volume %d",f_volhdr,1);
581 } else
582 ptr=f_volhdr;
583 #endif
584 head=findrec();
585 if(!head) {
586 msg("Archive not labelled to match %s",f_volhdr);
587 exit(EX_BADVOL);
588 }
589 if (re_match (label_pattern, head->header.name,
590 strlen (head->header.name), 0, 0) < 0) {
591 msg ("Volume mismatch! %s!=%s", f_volhdr,
592 head->header.name);
593 exit (EX_BADVOL);
594 }
595 #if 0
596 if(strcmp(ptr,head->header.name)) {
597 msg("Volume mismatch! %s!=%s",ptr,head->header.name);
598 exit(EX_BADVOL);
599 }
600 if(ptr!=f_volhdr)
601 free(ptr);
602 #endif
603 }
604 } else if(f_volhdr) {
605 bzero((void *)ar_block,RECORDSIZE);
606 if(f_multivol)
607 sprintf(ar_block->header.name,"%s Volume 1",f_volhdr);
608 else
609 strcpy(ar_block->header.name,f_volhdr);
610 ar_block->header.linkflag = LF_VOLHDR;
611 to_oct(time(0), 1+12, ar_block->header.mtime);
612 finish_header(ar_block);
613 /* ar_record++; */
614 }
615 }
616
617
618 /*
619 * Remember a union record * as pointing to something that we
620 * need to keep when reading onward in the file. Only one such
621 * thing can be remembered at once, and it only works when reading
622 * an archive.
623 *
624 * We calculate "offset" then add it because some compilers end up
625 * adding (baserec+ar_record), doing a 9-bit shift of baserec, then
626 * subtracting ar_block from that, shifting it back, losing the top 9 bits.
627 */
628 void
629 saverec(pointer)
630 union record **pointer;
631 {
632 long offset;
633
634 save_rec = pointer;
635 offset = ar_record - ar_block;
636 saved_recno = baserec + offset;
637 }
638
639 /*
640 * Perform a write to flush the buffer.
641 */
642
643 /*send_buffer_to_file();
644 if(new_volume) {
645 deal_with_new_volume_stuff();
646 send_buffer_to_file();
647 }
648 */
649
650 void
651 fl_write()
652 {
653 int err;
654 int copy_back;
655 static long bytes_written = 0;
656
657 if (f_checkpoint && ! (++checkpoint % 10))
658 msg ("Write checkpoint %d\n", checkpoint);
659 if(tape_length && bytes_written >= tape_length * 1024) {
660 errno = ENOSPC;
661 err = 0;
662 } else
663 err = rmtwrite(archive, ar_block->charptr,(int) blocksize);
664 if(err!=blocksize && !f_multivol)
665 writeerror(err);
666 else if (f_totals)
667 tot_written += blocksize;
668
669 if(err>0)
670 bytes_written+=err;
671 if (err == blocksize) {
672 if(f_multivol) {
673 if(!save_name) {
674 real_s_name[0]='\0';
675 real_s_totsize=0;
676 real_s_sizeleft = 0;
677 return;
678 }
679 #ifdef __MSDOS__
680 if(save_name[1]==':')
681 save_name+=2;
682 #endif
683 while(*save_name=='/')
684 save_name++;
685
686 strcpy(real_s_name,save_name);
687 real_s_totsize = save_totsize;
688 real_s_sizeleft = save_sizeleft;
689 }
690 return;
691 }
692
693 /* We're multivol Panic if we didn't get the right kind of response */
694 /* ENXIO is for the UNIX PC */
695 if(err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO)
696 writeerror(err);
697
698 /* If error indicates a short write, we just move to the next tape. */
699
700 if(new_volume(0)<0)
701 return;
702 bytes_written=0;
703 if(f_volhdr && real_s_name[0]) {
704 copy_back=2;
705 ar_block-=2;
706 } else if(f_volhdr || real_s_name[0]) {
707 copy_back = 1;
708 ar_block--;
709 } else
710 copy_back = 0;
711 if(f_volhdr) {
712 bzero((void *)ar_block,RECORDSIZE);
713 sprintf(ar_block->header.name,"%s Volume %d",f_volhdr,volno);
714 to_oct(time(0), 1+12, ar_block->header.mtime);
715 ar_block->header.linkflag = LF_VOLHDR;
716 finish_header(ar_block);
717 }
718 if(real_s_name[0]) {
719 int tmp;
720
721 if(f_volhdr)
722 ar_block++;
723 bzero((void *)ar_block,RECORDSIZE);
724 strcpy(ar_block->header.name,real_s_name);
725 ar_block->header.linkflag = LF_MULTIVOL;
726 to_oct((long)real_s_sizeleft,1+12,
727 ar_block->header.size);
728 to_oct((long)real_s_totsize-real_s_sizeleft,
729 1+12,ar_block->header.offset);
730 tmp=f_verbose;
731 f_verbose=0;
732 finish_header(ar_block);
733 f_verbose=tmp;
734 if(f_volhdr)
735 ar_block--;
736 }
737
738 err = rmtwrite(archive, ar_block->charptr,(int) blocksize);
739 if(err!=blocksize)
740 writeerror(err);
741 else if (f_totals)
742 tot_written += blocksize;
743
744
745 bytes_written = blocksize;
746 if(copy_back) {
747 ar_block+=copy_back;
748 bcopy((void *)(ar_block+blocking-copy_back),
749 (void *)ar_record,
750 copy_back*RECORDSIZE);
751 ar_record+=copy_back;
752
753 if(real_s_sizeleft>=copy_back*RECORDSIZE)
754 real_s_sizeleft-=copy_back*RECORDSIZE;
755 else if((real_s_sizeleft+RECORDSIZE-1)/RECORDSIZE<=copy_back)
756 real_s_name[0] = '\0';
757 else {
758 #ifdef __MSDOS__
759 if(save_name[1]==':')
760 save_name+=2;
761 #endif
762 while(*save_name=='/')
763 save_name++;
764
765 strcpy(real_s_name,save_name);
766 real_s_sizeleft = save_sizeleft;
767 real_s_totsize=save_totsize;
768 }
769 copy_back = 0;
770 }
771 }
772
773 /* Handle write errors on the archive. Write errors are always fatal */
774 /* Hitting the end of a volume does not cause a write error unless the write
775 * was the first block of the volume */
776
777 void
778 writeerror(err)
779 int err;
780 {
781 if (err < 0) {
782 msg_perror("can't write to %s",ar_file);
783 exit(EX_BADARCH);
784 } else {
785 msg("only wrote %u of %u bytes to %s",err,blocksize,ar_file);
786 exit(EX_BADARCH);
787 }
788 }
789
790 /*
791 * Handle read errors on the archive.
792 *
793 * If the read should be retried, readerror() returns to the caller.
794 */
795 void
796 readerror()
797 {
798 # define READ_ERROR_MAX 10
799
800 read_error_flag++; /* Tell callers */
801
802 msg_perror("read error on %s",ar_file);
803
804 if (baserec == 0) {
805 /* First block of tape. Probably stupidity error */
806 exit(EX_BADARCH);
807 }
808
809 /*
810 * Read error in mid archive. We retry up to READ_ERROR_MAX times
811 * and then give up on reading the archive. We set read_error_flag
812 * for our callers, so they can cope if they want.
813 */
814 if (r_error_count++ > READ_ERROR_MAX) {
815 msg("Too many errors, quitting.");
816 exit(EX_BADARCH);
817 }
818 return;
819 }
820
821
822 /*
823 * Perform a read to flush the buffer.
824 */
825 void
826 fl_read()
827 {
828 int err; /* Result from system call */
829 int left; /* Bytes left */
830 char *more; /* Pointer to next byte to read */
831
832 if (f_checkpoint && ! (++checkpoint % 10))
833 msg ("Read checkpoint %d\n", checkpoint);
834
835 /*
836 * Clear the count of errors. This only applies to a single
837 * call to fl_read. We leave read_error_flag alone; it is
838 * only turned off by higher level software.
839 */
840 r_error_count = 0; /* Clear error count */
841
842 /*
843 * If we are about to wipe out a record that
844 * somebody needs to keep, copy it out to a holding
845 * area and adjust somebody's pointer to it.
846 */
847 if (save_rec &&
848 *save_rec >= ar_record &&
849 *save_rec < ar_last) {
850 record_save_area = **save_rec;
851 *save_rec = &record_save_area;
852 }
853 if(write_archive_to_stdout && baserec!=0) {
854 err=rmtwrite(1, ar_block->charptr, blocksize);
855 if(err!=blocksize)
856 writeerror(err);
857 }
858 if(f_multivol) {
859 if(save_name) {
860 if(save_name!=real_s_name) {
861 #ifdef __MSDOS__
862 if(save_name[1]==':')
863 save_name+=2;
864 #endif
865 while(*save_name=='/')
866 save_name++;
867
868 strcpy(real_s_name,save_name);
869 save_name=real_s_name;
870 }
871 real_s_totsize = save_totsize;
872 real_s_sizeleft = save_sizeleft;
873
874 } else {
875 real_s_name[0]='\0';
876 real_s_totsize=0;
877 real_s_sizeleft = 0;
878 }
879 }
880
881 error_loop:
882 err = rmtread(archive, ar_block->charptr, (int)blocksize);
883 if (err == blocksize)
884 return;
885
886 if((err == 0 || (err<0 && errno==ENOSPC) || (err > 0 && !f_reblock)) && f_multivol) {
887 union record *head;
888
889 try_volume:
890 if(new_volume((cmd_mode==CMD_APPEND || cmd_mode==CMD_CAT || cmd_mode==CMD_UPDATE) ? 2 : 1)<0)
891 return;
892 vol_error:
893 err = rmtread(archive, ar_block->charptr,(int) blocksize);
894 if(err < 0) {
895 readerror();
896 goto vol_error;
897 }
898 if(err!=blocksize)
899 goto short_read;
900
901 head=ar_block;
902
903 if(head->header.linkflag==LF_VOLHDR) {
904 if(f_volhdr) {
905 #if 0
906 char *ptr;
907
908 ptr=(char *)malloc(strlen(f_volhdr)+20);
909 sprintf(ptr,"%s Volume %d",f_volhdr,volno);
910 #endif
911 if (re_match (label_pattern, head->header.name,
912 strlen (head->header.name),
913 0, 0) < 0) {
914 msg("Volume mismatch! %s!=%s",f_volhdr,
915 head->header.name);
916 --volno;
917 --global_volno;
918 goto try_volume;
919 }
920
921 #if 0
922 if(strcmp(ptr,head->header.name)) {
923 msg("Volume mismatch! %s!=%s",ptr,head->header.name);
924 --volno;
925 --global_volno;
926 free(ptr);
927 goto try_volume;
928 }
929 free(ptr);
930 #endif
931 }
932 if(f_verbose)
933 fprintf(msg_file,"Reading %s\n",head->header.name);
934 head++;
935 } else if(f_volhdr) {
936 msg("Warning: No volume header!");
937 }
938
939 if(real_s_name[0]) {
940 long from_oct();
941
942 if(head->header.linkflag!=LF_MULTIVOL || strcmp(head->header.name,real_s_name)) {
943 msg("%s is not continued on this volume!",real_s_name);
944 --volno;
945 --global_volno;
946 goto try_volume;
947 }
948 if(real_s_totsize!=from_oct(1+12,head->header.size)+from_oct(1+12,head->header.offset)) {
949 msg("%s is the wrong size (%ld!=%ld+%ld)",
950 head->header.name,save_totsize,
951 from_oct(1+12,head->header.size),
952 from_oct(1+12,head->header.offset));
953 --volno;
954 --global_volno;
955 goto try_volume;
956 }
957 if(real_s_totsize-real_s_sizeleft!=from_oct(1+12,head->header.offset)) {
958 msg("This volume is out of sequence");
959 --volno;
960 --global_volno;
961 goto try_volume;
962 }
963 head++;
964 }
965 ar_record=head;
966 return;
967 } else if (err < 0) {
968 readerror();
969 goto error_loop; /* Try again */
970 }
971
972 short_read:
973 more = ar_block->charptr + err;
974 left = blocksize - err;
975
976 again:
977 if (0 == (((unsigned)left) % RECORDSIZE)) {
978 /* FIXME, for size=0, multi vol support */
979 /* On the first block, warn about the problem */
980 if (!f_reblock && baserec == 0 && f_verbose && err > 0) {
981 /* msg("Blocksize = %d record%s",
982 err / RECORDSIZE, (err > RECORDSIZE)? "s": "");*/
983 msg("Blocksize = %d records", err / RECORDSIZE);
984 }
985 ar_last = ar_block + ((unsigned)(blocksize - left))/RECORDSIZE;
986 return;
987 }
988 if (f_reblock) {
989 /*
990 * User warned us about this. Fix up.
991 */
992 if (left > 0) {
993 error2loop:
994 err = rmtread(archive, more, (int)left);
995 if (err < 0) {
996 readerror();
997 goto error2loop; /* Try again */
998 }
999 if (err == 0) {
1000 msg("archive %s EOF not on block boundary",ar_file);
1001 exit(EX_BADARCH);
1002 }
1003 left -= err;
1004 more += err;
1005 goto again;
1006 }
1007 } else {
1008 msg("only read %d bytes from archive %s",err,ar_file);
1009 exit(EX_BADARCH);
1010 }
1011 }
1012
1013
1014 /*
1015 * Flush the current buffer to/from the archive.
1016 */
1017 void
1018 flush_archive()
1019 {
1020 int c;
1021
1022 baserec += ar_last - ar_block; /* Keep track of block #s */
1023 ar_record = ar_block; /* Restore pointer to start */
1024 ar_last = ar_block + blocking; /* Restore pointer to end */
1025
1026 if (ar_reading) {
1027 if(time_to_start_writing) {
1028 time_to_start_writing=0;
1029 ar_reading=0;
1030
1031 if(file_to_switch_to>=0) {
1032 if((c=rmtclose(archive))<0)
1033 msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c);
1034
1035 archive=file_to_switch_to;
1036 } else
1037 (void)backspace_output();
1038 fl_write();
1039 } else
1040 fl_read();
1041 } else {
1042 fl_write();
1043 }
1044 }
1045
1046 /* Backspace the archive descriptor by one blocks worth.
1047 If its a tape, MTIOCTOP will work. If its something else,
1048 we try to seek on it. If we can't seek, we lose! */
1049 int
1050 backspace_output()
1051 {
1052 long cur;
1053 /* int er; */
1054 extern char *output_start;
1055
1056 #ifdef MTIOCTOP
1057 struct mtop t;
1058
1059 t.mt_op = MTBSR;
1060 t.mt_count = 1;
1061 if((rmtioctl(archive,MTIOCTOP,&t))>=0)
1062 return 1;
1063 if(errno==EIO && (rmtioctl(archive,MTIOCTOP,&t))>=0)
1064 return 1;
1065 #endif
1066
1067 cur=rmtlseek(archive,0L,1);
1068 cur-=blocksize;
1069 /* Seek back to the beginning of this block and
1070 start writing there. */
1071
1072 if(rmtlseek(archive,cur,0)!=cur) {
1073 /* Lseek failed. Try a different method */
1074 msg("Couldn't backspace archive file. It may be unreadable without -i.");
1075 /* Replace the first part of the block with nulls */
1076 if(ar_block->charptr!=output_start)
1077 bzero(ar_block->charptr,output_start-ar_block->charptr);
1078 return 2;
1079 }
1080 return 3;
1081 }
1082
1083
1084 /*
1085 * Close the archive file.
1086 */
1087 void
1088 close_archive()
1089 {
1090 int child;
1091 int status;
1092 int c;
1093
1094 if (time_to_start_writing || !ar_reading)
1095 flush_archive();
1096 if(cmd_mode==CMD_DELETE) {
1097 off_t pos;
1098
1099 pos = rmtlseek(archive,0L,1);
1100 #ifndef __MSDOS__
1101 (void) ftruncate(archive,pos);
1102 #else
1103 (void)rmtwrite(archive,"",0);
1104 #endif
1105 }
1106 if(f_verify)
1107 verify_volume();
1108
1109 if((c=rmtclose(archive))<0)
1110 msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c);
1111
1112 #ifndef __MSDOS__
1113 if (childpid) {
1114 /*
1115 * Loop waiting for the right child to die, or for
1116 * no more kids.
1117 */
1118 while (((child = wait(&status)) != childpid) && child != -1)
1119 ;
1120
1121 if (child != -1) {
1122 switch (WTERMSIG(status)) {
1123 case 0:
1124 /* Child voluntarily terminated -- but why? */
1125 if (WEXITSTATUS(status) == MAGIC_STAT) {
1126 exit(EX_SYSTEM);/* Child had trouble */
1127 }
1128 if (WEXITSTATUS(status) == (SIGPIPE + 128)) {
1129 /*
1130 * /bin/sh returns this if its child
1131 * dies with SIGPIPE. 'Sok.
1132 */
1133 break;
1134 } else if (WEXITSTATUS(status))
1135 msg("child returned status %d",
1136 WEXITSTATUS(status));
1137 case SIGPIPE:
1138 break; /* This is OK. */
1139
1140 default:
1141 msg("child died with signal %d%s",
1142 WTERMSIG(status),
1143 WIFCOREDUMPED(status)? " (core dumped)": "");
1144 }
1145 }
1146 }
1147 #endif /* __MSDOS__ */
1148 }
1149
1150
1151 #ifdef DONTDEF
1152 /*
1153 * Message management.
1154 *
1155 * anno writes a message prefix on stream (eg stdout, stderr).
1156 *
1157 * The specified prefix is normally output followed by a colon and a space.
1158 * However, if other command line options are set, more output can come
1159 * out, such as the record # within the archive.
1160 *
1161 * If the specified prefix is NULL, no output is produced unless the
1162 * command line option(s) are set.
1163 *
1164 * If the third argument is 1, the "saved" record # is used; if 0, the
1165 * "current" record # is used.
1166 */
1167 void
1168 anno(stream, prefix, savedp)
1169 FILE *stream;
1170 char *prefix;
1171 int savedp;
1172 {
1173 # define MAXANNO 50
1174 char buffer[MAXANNO]; /* Holds annorecment */
1175 # define ANNOWIDTH 13
1176 int space;
1177 long offset;
1178 int save_e;
1179
1180 save_e=errno;
1181 /* Make sure previous output gets out in sequence */
1182 if (stream == stderr)
1183 fflush(stdout);
1184 if (f_sayblock) {
1185 if (prefix) {
1186 fputs(prefix, stream);
1187 putc(' ', stream);
1188 }
1189 offset = ar_record - ar_block;
1190 (void) sprintf(buffer, "rec %d: ",
1191 savedp? saved_recno:
1192 baserec + offset);
1193 fputs(buffer, stream);
1194 space = ANNOWIDTH - strlen(buffer);
1195 if (space > 0) {
1196 fprintf(stream, "%*s", space, "");
1197 }
1198 } else if (prefix) {
1199 fputs(prefix, stream);
1200 fputs(": ", stream);
1201 }
1202 errno=save_e;
1203 }
1204 #endif
1205
1206 /* Called to initialize the global volume number. */
1207 int
1208 init_volume_number ()
1209 {
1210 FILE *vf;
1211
1212 vf = fopen (f_volno_file, "r");
1213 if (!vf && errno != ENOENT)
1214 msg_perror ("%s", f_volno_file);
1215
1216 if (vf)
1217 {
1218 fscanf (vf, "%d", &global_volno);
1219 fclose (vf);
1220 }
1221 }
1222
1223 /* Called to write out the closing global volume number. */
1224 int
1225 closeout_volume_number ()
1226 {
1227 FILE *vf;
1228
1229 vf = fopen (f_volno_file, "w");
1230 if (!vf)
1231 msg_perror ("%s", f_volno_file);
1232 else
1233 {
1234 fprintf (vf, "%d\n", global_volno);
1235 fclose (vf);
1236 }
1237 }
1238
1239 /* We've hit the end of the old volume. Close it and open the next one */
1240 /* Values for type: 0: writing 1: reading 2: updating */
1241 int
1242 new_volume(type)
1243 int type;
1244 {
1245 int c;
1246 char inbuf[80];
1247 char *p;
1248 static FILE *read_file = 0;
1249 extern int now_verifying;
1250 extern char TTY_NAME[];
1251 char *getenv();
1252
1253 if(!read_file && !f_run_script_at_end)
1254 read_file = (archive==0) ? fopen(TTY_NAME, "r") : stdin;
1255
1256 if(now_verifying)
1257 return -1;
1258 if(f_verify)
1259 verify_volume();
1260 if((c=rmtclose(archive))<0)
1261 msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c);
1262
1263 global_volno++;
1264 volno++;
1265 tryagain:
1266 if (f_run_script_at_end)
1267 system(info_script);
1268 else for(;;) {
1269 fprintf(msg_file,"\007Prepare volume #%d and hit return: ",global_volno);
1270 fflush(msg_file);
1271 if(fgets(inbuf,sizeof(inbuf),read_file)==0) {
1272 fprintf(msg_file,"EOF? What does that mean?");
1273 if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF)
1274 msg("Warning: Archive is INCOMPLETE!");
1275 exit(EX_BADARCH);
1276 }
1277 if(inbuf[0]=='\n' || inbuf[0]=='y' || inbuf[0]=='Y')
1278 break;
1279
1280 switch(inbuf[0]) {
1281 case '?':
1282 {
1283 fprintf(msg_file,"\
1284 n [name] Give a new filename for the next (and subsequent) volume(s)\n\
1285 q Abort tar\n\
1286 ! Spawn a subshell\n\
1287 ? Print this list\n");
1288 }
1289 break;
1290
1291 case 'q': /* Quit */
1292 fprintf(msg_file,"No new volume; exiting.\n");
1293 if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF)
1294 msg("Warning: Archive is INCOMPLETE!");
1295 exit(EX_BADARCH);
1296
1297 case 'n': /* Get new file name */
1298 {
1299 char *q,*r;
1300 static char *old_name;
1301
1302 for(q= &inbuf[1];*q==' ' || *q=='\t';q++)
1303 ;
1304 for(r=q;*r;r++)
1305 if(*r=='\n')
1306 *r='\0';
1307 if(old_name)
1308 free(old_name);
1309 old_name=p=(char *)malloc((unsigned)(strlen(q)+2));
1310 if(p==0) {
1311 msg("Can't allocate memory for name");
1312 exit(EX_SYSTEM);
1313 }
1314 (void) strcpy(p,q);
1315 ar_file=p;
1316 }
1317 break;
1318
1319 case '!':
1320 #ifdef __MSDOS__
1321 spawnl(P_WAIT,getenv("COMSPEC"),"-",0);
1322 #else
1323 /* JF this needs work! */
1324 switch(fork()) {
1325 case -1:
1326 msg_perror("can't fork!");
1327 break;
1328 case 0:
1329 p=getenv("SHELL");
1330 if(p==0) p="/bin/sh";
1331 execlp(p,"-sh","-i",0);
1332 msg_perror("can't exec a shell %s",p);
1333 _exit(55);
1334 default:
1335 wait(0);
1336 break;
1337 }
1338 #endif
1339 break;
1340 }
1341 }
1342
1343 if(type==2 || f_verify)
1344 archive=rmtopen(ar_file,O_RDWR|O_CREAT,0666);
1345 else if(type==1)
1346 archive=rmtopen(ar_file,O_RDONLY,0666);
1347 else if(type==0)
1348 archive=rmtcreat(ar_file,0666);
1349 else
1350 archive= -1;
1351
1352 if(archive<0) {
1353 msg_perror("can't open %s",ar_file);
1354 goto tryagain;
1355 }
1356 #ifdef __MSDOS__
1357 setmode(archive,O_BINARY);
1358 #endif
1359 return 0;
1360 }
1361
1362 /* this is a useless function that takes a buffer returned by wantbytes
1363 and does nothing with it. If the function called by wantbytes returns
1364 an error indicator (non-zero), this function is called for the rest of
1365 the file.
1366 */
1367 int
1368 no_op(size,data)
1369 int size;
1370 char *data;
1371 {
1372 return 0;
1373 }
1374
1375 /* Some other routine wants SIZE bytes in the archive. For each chunk of
1376 the archive, call FUNC with the size of the chunk, and the address of
1377 the chunk it can work with.
1378 */
1379 int
1380 wantbytes(size,func)
1381 long size;
1382 int (*func)();
1383 {
1384 char *data;
1385 long data_size;
1386
1387 while(size) {
1388 data = findrec()->charptr;
1389 if (data == NULL) { /* Check it... */
1390 msg("Unexpected EOF on archive file");
1391 return -1;
1392 }
1393 data_size = endofrecs()->charptr - data;
1394 if(data_size>size)
1395 data_size=size;
1396 if((*func)(data_size,data))
1397 func=no_op;
1398 userec((union record *)(data + data_size - 1));
1399 size-=data_size;
1400 }
1401 return 0;
1402 }
This page took 0.094334 seconds and 5 git commands to generate.