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