]> Dogcows Code - chaz/tar/blob - src/buffer.c
e98ec0408b7d5977d580aaed9f21427a7000bd8e
[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_file[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_file[0] == '-' && ar_file[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_compress) {
519 if(reading==2 || f_verify) {
520 msg("cannot update or verify compressed archives");
521 exit(EX_ARGSBAD);
522 }
523 if (f_multivol) {
524 msg ("cannot use multi-volume compressed archives");
525 exit (EX_ARGSBAD);
526 }
527 child_open();
528 if(!reading && ar_files[0][0]=='-' && ar_files[0][1]=='\0')
529 msg_file = stderr;
530 /* child_open(rem_host, rem_file); */
531 } else if (ar_files[0][0] == '-' && ar_files[0][1] == '\0') {
532 f_reblock++; /* Could be a pipe, be safe */
533 if(f_verify) {
534 msg("can't verify stdin/stdout archive");
535 exit(EX_ARGSBAD);
536 }
537 if(reading==2) {
538 archive=STDIN;
539 msg_file=stderr;
540 write_archive_to_stdout++;
541 } else if (reading)
542 archive = STDIN;
543 else {
544 archive = STDOUT;
545 msg_file = stderr;
546 }
547 } else if (reading==2 || f_verify) {
548 archive = rmtopen(ar_files[0], O_RDWR|O_CREAT|O_BINARY, 0666);
549 } else if(reading) {
550 archive = rmtopen(ar_files[0], O_RDONLY|O_BINARY, 0666);
551 } else {
552 archive = rmtcreat(ar_files[0], 0666);
553 }
554 if (archive < 0) {
555 msg_perror("can't open %s",ar_files[0]);
556 exit(EX_BADARCH);
557 }
558 #ifndef __MSDOS__
559 if(!_isrmt(archive)) {
560 struct stat tmp_stat;
561
562 fstat(archive,&tmp_stat);
563 if(S_ISREG(tmp_stat.st_mode)) {
564 ar_dev=tmp_stat.st_dev;
565 ar_ino=tmp_stat.st_ino;
566 }
567 }
568 #endif
569
570 #ifdef __MSDOS__
571 setmode(archive, O_BINARY);
572 #endif
573
574 if (reading) {
575 ar_last = ar_block; /* Set up for 1st block = # 0 */
576 (void) findrec(); /* Read it in, check for EOF */
577
578 if(f_volhdr) {
579 union record *head;
580 #if 0
581 char *ptr;
582
583 if(f_multivol) {
584 ptr=malloc(strlen(f_volhdr)+20);
585 sprintf(ptr,"%s Volume %d",f_volhdr,1);
586 } else
587 ptr=f_volhdr;
588 #endif
589 head=findrec();
590 if(!head) {
591 msg("Archive not labelled to match %s",f_volhdr);
592 exit(EX_BADVOL);
593 }
594 if (re_match (label_pattern, head->header.name,
595 strlen (head->header.name), 0, 0) < 0) {
596 msg ("Volume mismatch! %s!=%s", f_volhdr,
597 head->header.name);
598 exit (EX_BADVOL);
599 }
600 #if 0
601 if(strcmp(ptr,head->header.name)) {
602 msg("Volume mismatch! %s!=%s",ptr,head->header.name);
603 exit(EX_BADVOL);
604 }
605 if(ptr!=f_volhdr)
606 free(ptr);
607 #endif
608 }
609 } else if(f_volhdr) {
610 bzero((void *)ar_block,RECORDSIZE);
611 if(f_multivol)
612 sprintf(ar_block->header.name,"%s Volume 1",f_volhdr);
613 else
614 strcpy(ar_block->header.name,f_volhdr);
615 ar_block->header.linkflag = LF_VOLHDR;
616 to_oct(time(0), 1+12, ar_block->header.mtime);
617 finish_header(ar_block);
618 /* ar_record++; */
619 }
620 }
621
622
623 /*
624 * Remember a union record * as pointing to something that we
625 * need to keep when reading onward in the file. Only one such
626 * thing can be remembered at once, and it only works when reading
627 * an archive.
628 *
629 * We calculate "offset" then add it because some compilers end up
630 * adding (baserec+ar_record), doing a 9-bit shift of baserec, then
631 * subtracting ar_block from that, shifting it back, losing the top 9 bits.
632 */
633 void
634 saverec(pointer)
635 union record **pointer;
636 {
637 long offset;
638
639 save_rec = pointer;
640 offset = ar_record - ar_block;
641 saved_recno = baserec + offset;
642 }
643
644 /*
645 * Perform a write to flush the buffer.
646 */
647
648 /*send_buffer_to_file();
649 if(new_volume) {
650 deal_with_new_volume_stuff();
651 send_buffer_to_file();
652 }
653 */
654
655 void
656 fl_write()
657 {
658 int err;
659 int copy_back;
660 static long bytes_written = 0;
661
662 if (f_checkpoint && ! (++checkpoint % 10))
663 msg ("Write checkpoint %d\n", checkpoint);
664 if(tape_length && bytes_written >= tape_length * 1024) {
665 errno = ENOSPC;
666 err = 0;
667 } else
668 err = rmtwrite(archive, ar_block->charptr,(int) blocksize);
669 if(err!=blocksize && !f_multivol)
670 writeerror(err);
671 else if (f_totals)
672 tot_written += blocksize;
673
674 if(err>0)
675 bytes_written+=err;
676 if (err == blocksize) {
677 if(f_multivol) {
678 if(!save_name) {
679 real_s_name[0]='\0';
680 real_s_totsize=0;
681 real_s_sizeleft = 0;
682 return;
683 }
684 #ifdef __MSDOS__
685 if(save_name[1]==':')
686 save_name+=2;
687 #endif
688 while(*save_name=='/')
689 save_name++;
690
691 strcpy(real_s_name,save_name);
692 real_s_totsize = save_totsize;
693 real_s_sizeleft = save_sizeleft;
694 }
695 return;
696 }
697
698 /* We're multivol Panic if we didn't get the right kind of response */
699 /* ENXIO is for the UNIX PC */
700 if(err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO)
701 writeerror(err);
702
703 /* If error indicates a short write, we just move to the next tape. */
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_files[cur_ar_file]);
788 exit(EX_BADARCH);
789 } else {
790 msg("only wrote %u of %u bytes to %s",err,blocksize,ar_files[cur_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_files[cur_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 void
831 fl_read()
832 {
833 int err; /* Result from system call */
834 int left; /* Bytes left */
835 char *more; /* Pointer to next byte to read */
836
837 if (f_checkpoint && ! (++checkpoint % 10))
838 msg ("Read checkpoint %d\n", checkpoint);
839
840 /*
841 * Clear the count of errors. This only applies to a single
842 * call to fl_read. We leave read_error_flag alone; it is
843 * only turned off by higher level software.
844 */
845 r_error_count = 0; /* Clear error count */
846
847 /*
848 * If we are about to wipe out a record that
849 * somebody needs to keep, copy it out to a holding
850 * area and adjust somebody's pointer to it.
851 */
852 if (save_rec &&
853 *save_rec >= ar_record &&
854 *save_rec < ar_last) {
855 record_save_area = **save_rec;
856 *save_rec = &record_save_area;
857 }
858 if(write_archive_to_stdout && baserec!=0) {
859 err=rmtwrite(1, ar_block->charptr, blocksize);
860 if(err!=blocksize)
861 writeerror(err);
862 }
863 if(f_multivol) {
864 if(save_name) {
865 if(save_name!=real_s_name) {
866 #ifdef __MSDOS__
867 if(save_name[1]==':')
868 save_name+=2;
869 #endif
870 while(*save_name=='/')
871 save_name++;
872
873 strcpy(real_s_name,save_name);
874 save_name=real_s_name;
875 }
876 real_s_totsize = save_totsize;
877 real_s_sizeleft = save_sizeleft;
878
879 } else {
880 real_s_name[0]='\0';
881 real_s_totsize=0;
882 real_s_sizeleft = 0;
883 }
884 }
885
886 error_loop:
887 err = rmtread(archive, ar_block->charptr, (int)blocksize);
888 if (err == blocksize)
889 return;
890
891 if((err == 0 || (err<0 && errno==ENOSPC) || (err > 0 && !f_reblock)) && f_multivol) {
892 union record *head;
893
894 try_volume:
895 if(new_volume((cmd_mode==CMD_APPEND || cmd_mode==CMD_CAT || cmd_mode==CMD_UPDATE) ? 2 : 1)<0)
896 return;
897 vol_error:
898 err = rmtread(archive, ar_block->charptr,(int) blocksize);
899 if(err < 0) {
900 readerror();
901 goto vol_error;
902 }
903 if(err!=blocksize)
904 goto short_read;
905
906 head=ar_block;
907
908 if(head->header.linkflag==LF_VOLHDR) {
909 if(f_volhdr) {
910 #if 0
911 char *ptr;
912
913 ptr=(char *)malloc(strlen(f_volhdr)+20);
914 sprintf(ptr,"%s Volume %d",f_volhdr,volno);
915 #endif
916 if (re_match (label_pattern, head->header.name,
917 strlen (head->header.name),
918 0, 0) < 0) {
919 msg("Volume mismatch! %s!=%s",f_volhdr,
920 head->header.name);
921 --volno;
922 --global_volno;
923 goto try_volume;
924 }
925
926 #if 0
927 if(strcmp(ptr,head->header.name)) {
928 msg("Volume mismatch! %s!=%s",ptr,head->header.name);
929 --volno;
930 --global_volno;
931 free(ptr);
932 goto try_volume;
933 }
934 free(ptr);
935 #endif
936 }
937 if(f_verbose)
938 fprintf(msg_file,"Reading %s\n",head->header.name);
939 head++;
940 } else if(f_volhdr) {
941 msg("Warning: No volume header!");
942 }
943
944 if(real_s_name[0]) {
945 long from_oct();
946
947 if(head->header.linkflag!=LF_MULTIVOL || strcmp(head->header.name,real_s_name)) {
948 msg("%s is not continued on this volume!",real_s_name);
949 --volno;
950 --global_volno;
951 goto try_volume;
952 }
953 if(real_s_totsize!=from_oct(1+12,head->header.size)+from_oct(1+12,head->header.offset)) {
954 msg("%s is the wrong size (%ld!=%ld+%ld)",
955 head->header.name,save_totsize,
956 from_oct(1+12,head->header.size),
957 from_oct(1+12,head->header.offset));
958 --volno;
959 --global_volno;
960 goto try_volume;
961 }
962 if(real_s_totsize-real_s_sizeleft!=from_oct(1+12,head->header.offset)) {
963 msg("This volume is out of sequence");
964 --volno;
965 --global_volno;
966 goto try_volume;
967 }
968 head++;
969 }
970 ar_record=head;
971 return;
972 } else if (err < 0) {
973 readerror();
974 goto error_loop; /* Try again */
975 }
976
977 short_read:
978 more = ar_block->charptr + err;
979 left = blocksize - err;
980
981 again:
982 if (0 == (((unsigned)left) % RECORDSIZE)) {
983 /* FIXME, for size=0, multi vol support */
984 /* On the first block, warn about the problem */
985 if (!f_reblock && baserec == 0 && f_verbose && err > 0) {
986 /* msg("Blocksize = %d record%s",
987 err / RECORDSIZE, (err > RECORDSIZE)? "s": "");*/
988 msg("Blocksize = %d records", err / RECORDSIZE);
989 }
990 ar_last = ar_block + ((unsigned)(blocksize - left))/RECORDSIZE;
991 return;
992 }
993 if (f_reblock) {
994 /*
995 * User warned us about this. Fix up.
996 */
997 if (left > 0) {
998 error2loop:
999 err = rmtread(archive, more, (int)left);
1000 if (err < 0) {
1001 readerror();
1002 goto error2loop; /* Try again */
1003 }
1004 if (err == 0) {
1005 msg("archive %s EOF not on block boundary",ar_files[cur_ar_file]);
1006 exit(EX_BADARCH);
1007 }
1008 left -= err;
1009 more += err;
1010 goto again;
1011 }
1012 } else {
1013 msg("only read %d bytes from archive %s",err,ar_files[cur_ar_file]);
1014 exit(EX_BADARCH);
1015 }
1016 }
1017
1018
1019 /*
1020 * Flush the current buffer to/from the archive.
1021 */
1022 void
1023 flush_archive()
1024 {
1025 int c;
1026
1027 baserec += ar_last - ar_block; /* Keep track of block #s */
1028 ar_record = ar_block; /* Restore pointer to start */
1029 ar_last = ar_block + blocking; /* Restore pointer to end */
1030
1031 if (ar_reading) {
1032 if(time_to_start_writing) {
1033 time_to_start_writing=0;
1034 ar_reading=0;
1035
1036 if(file_to_switch_to>=0) {
1037 if((c=rmtclose(archive))<0)
1038 msg_perror("Warning: can't close %s(%d,%d)",ar_files[cur_ar_file],archive,c);
1039
1040 archive=file_to_switch_to;
1041 } else
1042 (void)backspace_output();
1043 fl_write();
1044 } else
1045 fl_read();
1046 } else {
1047 fl_write();
1048 }
1049 }
1050
1051 /* Backspace the archive descriptor by one blocks worth.
1052 If its a tape, MTIOCTOP will work. If its something else,
1053 we try to seek on it. If we can't seek, we lose! */
1054 int
1055 backspace_output()
1056 {
1057 long cur;
1058 /* int er; */
1059 extern char *output_start;
1060
1061 #ifdef MTIOCTOP
1062 struct mtop t;
1063
1064 t.mt_op = MTBSR;
1065 t.mt_count = 1;
1066 if((rmtioctl(archive,MTIOCTOP,&t))>=0)
1067 return 1;
1068 if(errno==EIO && (rmtioctl(archive,MTIOCTOP,&t))>=0)
1069 return 1;
1070 #endif
1071
1072 cur=rmtlseek(archive,0L,1);
1073 cur-=blocksize;
1074 /* Seek back to the beginning of this block and
1075 start writing there. */
1076
1077 if(rmtlseek(archive,cur,0)!=cur) {
1078 /* Lseek failed. Try a different method */
1079 msg("Couldn't backspace archive file. It may be unreadable without -i.");
1080 /* Replace the first part of the block with nulls */
1081 if(ar_block->charptr!=output_start)
1082 bzero(ar_block->charptr,output_start-ar_block->charptr);
1083 return 2;
1084 }
1085 return 3;
1086 }
1087
1088
1089 /*
1090 * Close the archive file.
1091 */
1092 void
1093 close_archive()
1094 {
1095 int child;
1096 int status;
1097 int c;
1098
1099 if (time_to_start_writing || !ar_reading)
1100 flush_archive();
1101 if(cmd_mode==CMD_DELETE) {
1102 off_t pos;
1103
1104 pos = rmtlseek(archive,0L,1);
1105 #ifndef __MSDOS__
1106 (void) ftruncate(archive,pos);
1107 #else
1108 (void)rmtwrite(archive,"",0);
1109 #endif
1110 }
1111 if(f_verify)
1112 verify_volume();
1113
1114 if((c=rmtclose(archive))<0)
1115 msg_perror("Warning: can't close %s(%d,%d)",ar_files[cur_ar_file],archive,c);
1116
1117 #ifndef __MSDOS__
1118 if (childpid) {
1119 /*
1120 * Loop waiting for the right child to die, or for
1121 * no more kids.
1122 */
1123 while (((child = wait(&status)) != childpid) && child != -1)
1124 ;
1125
1126 if (child != -1) {
1127 switch (WTERMSIG(status)) {
1128 case 0:
1129 /* Child voluntarily terminated -- but why? */
1130 if (WEXITSTATUS(status) == MAGIC_STAT) {
1131 exit(EX_SYSTEM);/* Child had trouble */
1132 }
1133 if (WEXITSTATUS(status) == (SIGPIPE + 128)) {
1134 /*
1135 * /bin/sh returns this if its child
1136 * dies with SIGPIPE. 'Sok.
1137 */
1138 break;
1139 } else if (WEXITSTATUS(status))
1140 msg("child returned status %d",
1141 WEXITSTATUS(status));
1142 case SIGPIPE:
1143 break; /* This is OK. */
1144
1145 default:
1146 msg("child died with signal %d%s",
1147 WTERMSIG(status),
1148 WIFCOREDUMPED(status)? " (core dumped)": "");
1149 }
1150 }
1151 }
1152 #endif /* __MSDOS__ */
1153 }
1154
1155
1156 #ifdef DONTDEF
1157 /*
1158 * Message management.
1159 *
1160 * anno writes a message prefix on stream (eg stdout, stderr).
1161 *
1162 * The specified prefix is normally output followed by a colon and a space.
1163 * However, if other command line options are set, more output can come
1164 * out, such as the record # within the archive.
1165 *
1166 * If the specified prefix is NULL, no output is produced unless the
1167 * command line option(s) are set.
1168 *
1169 * If the third argument is 1, the "saved" record # is used; if 0, the
1170 * "current" record # is used.
1171 */
1172 void
1173 anno(stream, prefix, savedp)
1174 FILE *stream;
1175 char *prefix;
1176 int savedp;
1177 {
1178 # define MAXANNO 50
1179 char buffer[MAXANNO]; /* Holds annorecment */
1180 # define ANNOWIDTH 13
1181 int space;
1182 long offset;
1183 int save_e;
1184
1185 save_e=errno;
1186 /* Make sure previous output gets out in sequence */
1187 if (stream == stderr)
1188 fflush(stdout);
1189 if (f_sayblock) {
1190 if (prefix) {
1191 fputs(prefix, stream);
1192 putc(' ', stream);
1193 }
1194 offset = ar_record - ar_block;
1195 (void) sprintf(buffer, "rec %d: ",
1196 savedp? saved_recno:
1197 baserec + offset);
1198 fputs(buffer, stream);
1199 space = ANNOWIDTH - strlen(buffer);
1200 if (space > 0) {
1201 fprintf(stream, "%*s", space, "");
1202 }
1203 } else if (prefix) {
1204 fputs(prefix, stream);
1205 fputs(": ", stream);
1206 }
1207 errno=save_e;
1208 }
1209 #endif
1210
1211 /* Called to initialize the global volume number. */
1212 int
1213 init_volume_number ()
1214 {
1215 FILE *vf;
1216
1217 vf = fopen (f_volno_file, "r");
1218 if (!vf && errno != ENOENT)
1219 msg_perror ("%s", f_volno_file);
1220
1221 if (vf)
1222 {
1223 fscanf (vf, "%d", &global_volno);
1224 fclose (vf);
1225 }
1226 }
1227
1228 /* Called to write out the closing global volume number. */
1229 int
1230 closeout_volume_number ()
1231 {
1232 FILE *vf;
1233
1234 vf = fopen (f_volno_file, "w");
1235 if (!vf)
1236 msg_perror ("%s", f_volno_file);
1237 else
1238 {
1239 fprintf (vf, "%d\n", global_volno);
1240 fclose (vf);
1241 }
1242 }
1243
1244 /* We've hit the end of the old volume. Close it and open the next one */
1245 /* Values for type: 0: writing 1: reading 2: updating */
1246 int
1247 new_volume(type)
1248 int type;
1249 {
1250 int c;
1251 char inbuf[80];
1252 char *p;
1253 static FILE *read_file = 0;
1254 extern int now_verifying;
1255 extern char TTY_NAME[];
1256 char *getenv();
1257 static int looped = 0;
1258
1259 if(!read_file && !f_run_script_at_end)
1260 read_file = (archive==0) ? fopen(TTY_NAME, "r") : stdin;
1261
1262 if(now_verifying)
1263 return -1;
1264 if(f_verify)
1265 verify_volume();
1266 if((c=rmtclose(archive))<0)
1267 msg_perror("Warning: can't close %s(%d,%d)",ar_files[cur_ar_file],archive,c);
1268
1269 global_volno++;
1270 volno++;
1271 cur_ar_file++;
1272 if (cur_ar_file == n_ar_files)
1273 {
1274 cur_ar_file = 0;
1275 looped = 1;
1276 }
1277
1278 tryagain:
1279 if (looped)
1280 {
1281 /* We have to prompt from now on. */
1282 if (f_run_script_at_end)
1283 system(info_script);
1284 else for(;;) {
1285 fprintf(msg_file,"\007Prepare volume #%d for %s and hit return: ",global_volno, ar_files[cur_ar_file]);
1286 fflush(msg_file);
1287 if(fgets(inbuf,sizeof(inbuf),read_file)==0) {
1288 fprintf(msg_file,"EOF? What does that mean?");
1289 if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF)
1290 msg("Warning: Archive is INCOMPLETE!");
1291 exit(EX_BADARCH);
1292 }
1293 if(inbuf[0]=='\n' || inbuf[0]=='y' || inbuf[0]=='Y')
1294 break;
1295
1296 switch(inbuf[0]) {
1297 case '?':
1298 {
1299 fprintf(msg_file,"\
1300 n [name] Give a new filename for the next (and subsequent) volume(s)\n\
1301 q Abort tar\n\
1302 ! Spawn a subshell\n\
1303 ? Print this list\n");
1304 }
1305 break;
1306
1307 case 'q': /* Quit */
1308 fprintf(msg_file,"No new volume; exiting.\n");
1309 if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF)
1310 msg("Warning: Archive is INCOMPLETE!");
1311 exit(EX_BADARCH);
1312
1313 case 'n': /* Get new file name */
1314 {
1315 char *q,*r;
1316 static char *old_name;
1317
1318 for(q= &inbuf[1];*q==' ' || *q=='\t';q++)
1319 ;
1320 for(r=q;*r;r++)
1321 if(*r=='\n')
1322 *r='\0';
1323 old_name=p=(char *)malloc((unsigned)(strlen(q)+2));
1324 if(p==0) {
1325 msg("Can't allocate memory for name");
1326 exit(EX_SYSTEM);
1327 }
1328 (void) strcpy(p,q);
1329 ar_files[cur_ar_file]=p;
1330 }
1331 break;
1332
1333 case '!':
1334 #ifdef __MSDOS__
1335 spawnl(P_WAIT,getenv("COMSPEC"),"-",0);
1336 #else
1337 /* JF this needs work! */
1338 switch(fork()) {
1339 case -1:
1340 msg_perror("can't fork!");
1341 break;
1342 case 0:
1343 p=getenv("SHELL");
1344 if(p==0) p="/bin/sh";
1345 execlp(p,"-sh","-i",0);
1346 msg_perror("can't exec a shell %s",p);
1347 _exit(55);
1348 default:
1349 wait(0);
1350 break;
1351 }
1352 #endif
1353 break;
1354 }
1355 }
1356 }
1357
1358
1359 if(type==2 || f_verify)
1360 archive=rmtopen(ar_files[cur_ar_file],O_RDWR|O_CREAT,0666);
1361 else if(type==1)
1362 archive=rmtopen(ar_files[cur_ar_file],O_RDONLY,0666);
1363 else if(type==0)
1364 archive=rmtcreat(ar_file[cur_ar_file],0666);
1365 else
1366 archive= -1;
1367
1368 if(archive<0) {
1369 msg_perror("can't open %s",ar_files[cur_ar_file]);
1370 goto tryagain;
1371 }
1372 #ifdef __MSDOS__
1373 setmode(archive,O_BINARY);
1374 #endif
1375 return 0;
1376 }
1377
1378 /* this is a useless function that takes a buffer returned by wantbytes
1379 and does nothing with it. If the function called by wantbytes returns
1380 an error indicator (non-zero), this function is called for the rest of
1381 the file.
1382 */
1383 int
1384 no_op(size,data)
1385 int size;
1386 char *data;
1387 {
1388 return 0;
1389 }
1390
1391 /* Some other routine wants SIZE bytes in the archive. For each chunk of
1392 the archive, call FUNC with the size of the chunk, and the address of
1393 the chunk it can work with.
1394 */
1395 int
1396 wantbytes(size,func)
1397 long size;
1398 int (*func)();
1399 {
1400 char *data;
1401 long data_size;
1402
1403 while(size) {
1404 data = findrec()->charptr;
1405 if (data == NULL) { /* Check it... */
1406 msg("Unexpected EOF on archive file");
1407 return -1;
1408 }
1409 data_size = endofrecs()->charptr - data;
1410 if(data_size>size)
1411 data_size=size;
1412 if((*func)(data_size,data))
1413 func=no_op;
1414 userec((union record *)(data + data_size - 1));
1415 size-=data_size;
1416 }
1417 return 0;
1418 }
This page took 0.108461 seconds and 4 git commands to generate.