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