]> 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 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.name,
601 strlen (head->header.name), 0, 0) < 0) {
602 msg ("Volume mismatch! %s!=%s", f_volhdr,
603 head->header.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.name,"%s Volume 1",f_volhdr);
619 else
620 strcpy(ar_block->header.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.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.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.name,
923 strlen (head->header.name),
924 0, 0) < 0) {
925 msg("Volume mismatch! %s!=%s",f_volhdr,
926 head->header.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.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.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.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 }
This page took 0.104984 seconds and 5 git commands to generate.