]> 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 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(eof) {
157 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 (eof)
174 return (union record *)NULL; /* EOF */
175 flush_archive();
176 if (ar_record == ar_last) {
177 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
550 #ifndef __MSDOS__
551 if(!_isrmt(archive)) {
552 struct stat tmp_stat;
553
554 fstat(archive,&tmp_stat);
555 if(S_ISREG(tmp_stat.st_mode)) {
556 ar_dev=tmp_stat.st_dev;
557 ar_ino=tmp_stat.st_ino;
558 }
559 }
560 #endif
561
562 #ifdef __MSDOS__
563 setmode(archive, O_BINARY);
564 #endif
565
566 if (reading) {
567 ar_last = ar_block; /* Set up for 1st block = # 0 */
568 (void) findrec(); /* Read it in, check for EOF */
569
570 if(f_volhdr) {
571 union record *head;
572 #if 0
573 char *ptr;
574
575 if(f_multivol) {
576 ptr=malloc(strlen(f_volhdr)+20);
577 sprintf(ptr,"%s Volume %d",f_volhdr,1);
578 } else
579 ptr=f_volhdr;
580 #endif
581 head=findrec();
582 if(!head) {
583 msg("Archive not labelled to match %s",f_volhdr);
584 exit(EX_BADVOL);
585 }
586 if (re_match (label_pattern, head->header.name,
587 strlen (head->header.name), 0, 0) < 0) {
588 msg ("Volume mismatch! %s!=%s", f_volhdr,
589 head->header.name);
590 exit (EX_BADVOL);
591 }
592 #if 0
593 if(strcmp(ptr,head->header.name)) {
594 msg("Volume mismatch! %s!=%s",ptr,head->header.name);
595 exit(EX_BADVOL);
596 }
597 if(ptr!=f_volhdr)
598 free(ptr);
599 #endif
600 }
601 } else if(f_volhdr) {
602 bzero((void *)ar_block,RECORDSIZE);
603 if(f_multivol)
604 sprintf(ar_block->header.name,"%s Volume 1",f_volhdr);
605 else
606 strcpy(ar_block->header.name,f_volhdr);
607 ar_block->header.linkflag = LF_VOLHDR;
608 to_oct(time(0), 1+12, ar_block->header.mtime);
609 finish_header(ar_block);
610 /* ar_record++; */
611 }
612 }
613
614
615 /*
616 * Remember a union record * as pointing to something that we
617 * need to keep when reading onward in the file. Only one such
618 * thing can be remembered at once, and it only works when reading
619 * an archive.
620 *
621 * We calculate "offset" then add it because some compilers end up
622 * adding (baserec+ar_record), doing a 9-bit shift of baserec, then
623 * subtracting ar_block from that, shifting it back, losing the top 9 bits.
624 */
625 void
626 saverec(pointer)
627 union record **pointer;
628 {
629 long offset;
630
631 save_rec = pointer;
632 offset = ar_record - ar_block;
633 saved_recno = baserec + offset;
634 }
635
636 /*
637 * Perform a write to flush the buffer.
638 */
639
640 /*send_buffer_to_file();
641 if(new_volume) {
642 deal_with_new_volume_stuff();
643 send_buffer_to_file();
644 }
645 */
646
647 void
648 fl_write()
649 {
650 int err;
651 int copy_back;
652 static long bytes_written = 0;
653
654 if(tape_length && bytes_written >= tape_length * 1024) {
655 errno = ENOSPC;
656 err = 0;
657 } else
658 err = rmtwrite(archive, ar_block->charptr,(int) blocksize);
659 if(err!=blocksize && !f_multivol)
660 writeerror(err);
661 else if (f_totals)
662 tot_written += blocksize;
663
664 if(err>0)
665 bytes_written+=err;
666 if (err == blocksize) {
667 if(f_multivol) {
668 if(!save_name) {
669 real_s_name[0]='\0';
670 real_s_totsize=0;
671 real_s_sizeleft = 0;
672 return;
673 }
674 #ifdef __MSDOS__
675 if(save_name[1]==':')
676 save_name+=2;
677 #endif
678 while(*save_name=='/')
679 save_name++;
680
681 strcpy(real_s_name,save_name);
682 real_s_totsize = save_totsize;
683 real_s_sizeleft = save_sizeleft;
684 }
685 return;
686 }
687
688 /* We're multivol Panic if we didn't get the right kind of response */
689 /* ENXIO is for the UNIX PC */
690 if(err>0 || (err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO))
691 writeerror(err);
692
693 if(new_volume(0)<0)
694 return;
695 bytes_written=0;
696 if(f_volhdr && real_s_name[0]) {
697 copy_back=2;
698 ar_block-=2;
699 } else if(f_volhdr || real_s_name[0]) {
700 copy_back = 1;
701 ar_block--;
702 } else
703 copy_back = 0;
704 if(f_volhdr) {
705 bzero((void *)ar_block,RECORDSIZE);
706 sprintf(ar_block->header.name,"%s Volume %d",f_volhdr,volno);
707 to_oct(time(0), 1+12, ar_block->header.mtime);
708 ar_block->header.linkflag = LF_VOLHDR;
709 finish_header(ar_block);
710 }
711 if(real_s_name[0]) {
712 int tmp;
713
714 if(f_volhdr)
715 ar_block++;
716 bzero((void *)ar_block,RECORDSIZE);
717 strcpy(ar_block->header.name,real_s_name);
718 ar_block->header.linkflag = LF_MULTIVOL;
719 to_oct((long)real_s_sizeleft,1+12,
720 ar_block->header.size);
721 to_oct((long)real_s_totsize-real_s_sizeleft,
722 1+12,ar_block->header.offset);
723 tmp=f_verbose;
724 f_verbose=0;
725 finish_header(ar_block);
726 f_verbose=tmp;
727 if(f_volhdr)
728 ar_block--;
729 }
730
731 err = rmtwrite(archive, ar_block->charptr,(int) blocksize);
732 if(err!=blocksize)
733 writeerror(err);
734 else if (f_totals)
735 tot_written += blocksize;
736
737
738 bytes_written = blocksize;
739 if(copy_back) {
740 ar_block+=copy_back;
741 bcopy((void *)(ar_block+blocking-copy_back),
742 (void *)ar_record,
743 copy_back*RECORDSIZE);
744 ar_record+=copy_back;
745
746 if(real_s_sizeleft>=copy_back*RECORDSIZE)
747 real_s_sizeleft-=copy_back*RECORDSIZE;
748 else if((real_s_sizeleft+RECORDSIZE-1)/RECORDSIZE<=copy_back)
749 real_s_name[0] = '\0';
750 else {
751 #ifdef __MSDOS__
752 if(save_name[1]==':')
753 save_name+=2;
754 #endif
755 while(*save_name=='/')
756 save_name++;
757
758 strcpy(real_s_name,save_name);
759 real_s_sizeleft = save_sizeleft;
760 real_s_totsize=save_totsize;
761 }
762 copy_back = 0;
763 }
764 }
765
766 /* Handle write errors on the archive. Write errors are always fatal */
767 /* Hitting the end of a volume does not cause a write error unless the write
768 * was the first block of the volume */
769
770 void
771 writeerror(err)
772 int err;
773 {
774 if (err < 0) {
775 msg_perror("can't write to %s",ar_file);
776 exit(EX_BADARCH);
777 } else {
778 msg("only wrote %u of %u bytes to %s",err,blocksize,ar_file);
779 exit(EX_BADARCH);
780 }
781 }
782
783 /*
784 * Handle read errors on the archive.
785 *
786 * If the read should be retried, readerror() returns to the caller.
787 */
788 void
789 readerror()
790 {
791 # define READ_ERROR_MAX 10
792
793 read_error_flag++; /* Tell callers */
794
795 msg_perror("read error on %s",ar_file);
796
797 if (baserec == 0) {
798 /* First block of tape. Probably stupidity error */
799 exit(EX_BADARCH);
800 }
801
802 /*
803 * Read error in mid archive. We retry up to READ_ERROR_MAX times
804 * and then give up on reading the archive. We set read_error_flag
805 * for our callers, so they can cope if they want.
806 */
807 if (r_error_count++ > READ_ERROR_MAX) {
808 msg("Too many errors, quitting.");
809 exit(EX_BADARCH);
810 }
811 return;
812 }
813
814
815 /*
816 * Perform a read to flush the buffer.
817 */
818 void
819 fl_read()
820 {
821 int err; /* Result from system call */
822 int left; /* Bytes left */
823 char *more; /* Pointer to next byte to read */
824
825 /*
826 * Clear the count of errors. This only applies to a single
827 * call to fl_read. We leave read_error_flag alone; it is
828 * only turned off by higher level software.
829 */
830 r_error_count = 0; /* Clear error count */
831
832 /*
833 * If we are about to wipe out a record that
834 * somebody needs to keep, copy it out to a holding
835 * area and adjust somebody's pointer to it.
836 */
837 if (save_rec &&
838 *save_rec >= ar_record &&
839 *save_rec < ar_last) {
840 record_save_area = **save_rec;
841 *save_rec = &record_save_area;
842 }
843 if(write_archive_to_stdout && baserec!=0) {
844 err=rmtwrite(1, ar_block->charptr, blocksize);
845 if(err!=blocksize)
846 writeerror(err);
847 }
848 if(f_multivol) {
849 if(save_name) {
850 if(save_name!=real_s_name) {
851 #ifdef __MSDOS__
852 if(save_name[1]==':')
853 save_name+=2;
854 #endif
855 while(*save_name=='/')
856 save_name++;
857
858 strcpy(real_s_name,save_name);
859 save_name=real_s_name;
860 }
861 real_s_totsize = save_totsize;
862 real_s_sizeleft = save_sizeleft;
863
864 } else {
865 real_s_name[0]='\0';
866 real_s_totsize=0;
867 real_s_sizeleft = 0;
868 }
869 }
870
871 error_loop:
872 err = rmtread(archive, ar_block->charptr, (int)blocksize);
873 if (err == blocksize)
874 return;
875
876 if((err == 0 || (err<0 && errno==ENOSPC)) && f_multivol) {
877 union record *head;
878
879 try_volume:
880 if(new_volume((cmd_mode==CMD_APPEND || cmd_mode==CMD_CAT || cmd_mode==CMD_UPDATE) ? 2 : 1)<0)
881 return;
882 vol_error:
883 err = rmtread(archive, ar_block->charptr,(int) blocksize);
884 if(err < 0) {
885 readerror();
886 goto vol_error;
887 }
888 if(err!=blocksize)
889 goto short_read;
890
891 head=ar_block;
892
893 if(head->header.linkflag==LF_VOLHDR) {
894 if(f_volhdr) {
895 #if 0
896 char *ptr;
897
898 ptr=(char *)malloc(strlen(f_volhdr)+20);
899 sprintf(ptr,"%s Volume %d",f_volhdr,volno);
900 #endif
901 if (re_match (label_pattern, head->header.name,
902 strlen (head->header.name),
903 0, 0) < 0) {
904 msg("Volume mismatch! %s!=%s",f_volhdr,
905 head->header.name);
906 --volno;
907 goto try_volume;
908 }
909
910 #if 0
911 if(strcmp(ptr,head->header.name)) {
912 msg("Volume mismatch! %s!=%s",ptr,head->header.name);
913 --volno;
914 free(ptr);
915 goto try_volume;
916 }
917 free(ptr);
918 #endif
919 }
920 if(f_verbose)
921 fprintf(msg_file,"Reading %s\n",head->header.name);
922 head++;
923 } else if(f_volhdr) {
924 msg("Warning: No volume header!");
925 }
926
927 if(real_s_name[0]) {
928 long from_oct();
929
930 if(head->header.linkflag!=LF_MULTIVOL || strcmp(head->header.name,real_s_name)) {
931 msg("%s is not continued on this volume!",real_s_name);
932 --volno;
933 goto try_volume;
934 }
935 if(real_s_totsize!=from_oct(1+12,head->header.size)+from_oct(1+12,head->header.offset)) {
936 msg("%s is the wrong size (%ld!=%ld+%ld)",
937 head->header.name,save_totsize,
938 from_oct(1+12,head->header.size),
939 from_oct(1+12,head->header.offset));
940 --volno;
941 goto try_volume;
942 }
943 if(real_s_totsize-real_s_sizeleft!=from_oct(1+12,head->header.offset)) {
944 msg("This volume is out of sequence");
945 --volno;
946 goto try_volume;
947 }
948 head++;
949 }
950 ar_record=head;
951 return;
952 } else if (err < 0) {
953 readerror();
954 goto error_loop; /* Try again */
955 }
956
957 short_read:
958 more = ar_block->charptr + err;
959 left = blocksize - err;
960
961 again:
962 if (0 == (((unsigned)left) % RECORDSIZE)) {
963 /* FIXME, for size=0, multi vol support */
964 /* On the first block, warn about the problem */
965 if (!f_reblock && baserec == 0 && f_verbose && err > 0) {
966 /* msg("Blocksize = %d record%s",
967 err / RECORDSIZE, (err > RECORDSIZE)? "s": "");*/
968 msg("Blocksize = %d records", err / RECORDSIZE);
969 }
970 ar_last = ar_block + ((unsigned)(blocksize - left))/RECORDSIZE;
971 return;
972 }
973 if (f_reblock) {
974 /*
975 * User warned us about this. Fix up.
976 */
977 if (left > 0) {
978 error2loop:
979 err = rmtread(archive, more, (int)left);
980 if (err < 0) {
981 readerror();
982 goto error2loop; /* Try again */
983 }
984 if (err == 0) {
985 msg("archive %s EOF not on block boundary",ar_file);
986 exit(EX_BADARCH);
987 }
988 left -= err;
989 more += err;
990 goto again;
991 }
992 } else {
993 msg("only read %d bytes from archive %s",err,ar_file);
994 exit(EX_BADARCH);
995 }
996 }
997
998
999 /*
1000 * Flush the current buffer to/from the archive.
1001 */
1002 void
1003 flush_archive()
1004 {
1005 int c;
1006
1007 baserec += ar_last - ar_block; /* Keep track of block #s */
1008 ar_record = ar_block; /* Restore pointer to start */
1009 ar_last = ar_block + blocking; /* Restore pointer to end */
1010
1011 if (ar_reading) {
1012 if(time_to_start_writing) {
1013 time_to_start_writing=0;
1014 ar_reading=0;
1015
1016 if(file_to_switch_to>=0) {
1017 if((c=rmtclose(archive))<0)
1018 msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c);
1019
1020 archive=file_to_switch_to;
1021 } else
1022 (void)backspace_output();
1023 fl_write();
1024 } else
1025 fl_read();
1026 } else {
1027 fl_write();
1028 }
1029 }
1030
1031 /* Backspace the archive descriptor by one blocks worth.
1032 If its a tape, MTIOCTOP will work. If its something else,
1033 we try to seek on it. If we can't seek, we lose! */
1034 int
1035 backspace_output()
1036 {
1037 long cur;
1038 /* int er; */
1039 extern char *output_start;
1040
1041 #ifdef MTIOCTOP
1042 struct mtop t;
1043
1044 t.mt_op = MTBSR;
1045 t.mt_count = 1;
1046 if((rmtioctl(archive,MTIOCTOP,&t))>=0)
1047 return 1;
1048 if(errno==EIO && (rmtioctl(archive,MTIOCTOP,&t))>=0)
1049 return 1;
1050 #endif
1051
1052 cur=rmtlseek(archive,0L,1);
1053 cur-=blocksize;
1054 /* Seek back to the beginning of this block and
1055 start writing there. */
1056
1057 if(rmtlseek(archive,cur,0)!=cur) {
1058 /* Lseek failed. Try a different method */
1059 msg("Couldn't backspace archive file. It may be unreadable without -i.");
1060 /* Replace the first part of the block with nulls */
1061 if(ar_block->charptr!=output_start)
1062 bzero(ar_block->charptr,output_start-ar_block->charptr);
1063 return 2;
1064 }
1065 return 3;
1066 }
1067
1068
1069 /*
1070 * Close the archive file.
1071 */
1072 void
1073 close_archive()
1074 {
1075 int child;
1076 int status;
1077 int c;
1078
1079 if (time_to_start_writing || !ar_reading)
1080 flush_archive();
1081 if(cmd_mode==CMD_DELETE) {
1082 off_t pos;
1083
1084 pos = rmtlseek(archive,0L,1);
1085 #ifndef __MSDOS__
1086 (void) ftruncate(archive,pos);
1087 #else
1088 (void)rmtwrite(archive,"",0);
1089 #endif
1090 }
1091 if(f_verify)
1092 verify_volume();
1093
1094 if((c=rmtclose(archive))<0)
1095 msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c);
1096
1097 #ifndef __MSDOS__
1098 if (childpid) {
1099 /*
1100 * Loop waiting for the right child to die, or for
1101 * no more kids.
1102 */
1103 while (((child = wait(&status)) != childpid) && child != -1)
1104 ;
1105
1106 if (child != -1) {
1107 switch (WTERMSIG(status)) {
1108 case 0:
1109 /* Child voluntarily terminated -- but why? */
1110 if (WEXITSTATUS(status) == MAGIC_STAT) {
1111 exit(EX_SYSTEM);/* Child had trouble */
1112 }
1113 if (WEXITSTATUS(status) == (SIGPIPE + 128)) {
1114 /*
1115 * /bin/sh returns this if its child
1116 * dies with SIGPIPE. 'Sok.
1117 */
1118 break;
1119 } else if (WEXITSTATUS(status))
1120 msg("child returned status %d",
1121 WEXITSTATUS(status));
1122 case SIGPIPE:
1123 break; /* This is OK. */
1124
1125 default:
1126 msg("child died with signal %d%s",
1127 WTERMSIG(status),
1128 WIFCOREDUMPED(status)? " (core dumped)": "");
1129 }
1130 }
1131 }
1132 #endif /* __MSDOS__ */
1133 }
1134
1135
1136 #ifdef DONTDEF
1137 /*
1138 * Message management.
1139 *
1140 * anno writes a message prefix on stream (eg stdout, stderr).
1141 *
1142 * The specified prefix is normally output followed by a colon and a space.
1143 * However, if other command line options are set, more output can come
1144 * out, such as the record # within the archive.
1145 *
1146 * If the specified prefix is NULL, no output is produced unless the
1147 * command line option(s) are set.
1148 *
1149 * If the third argument is 1, the "saved" record # is used; if 0, the
1150 * "current" record # is used.
1151 */
1152 void
1153 anno(stream, prefix, savedp)
1154 FILE *stream;
1155 char *prefix;
1156 int savedp;
1157 {
1158 # define MAXANNO 50
1159 char buffer[MAXANNO]; /* Holds annorecment */
1160 # define ANNOWIDTH 13
1161 int space;
1162 long offset;
1163 int save_e;
1164
1165 save_e=errno;
1166 /* Make sure previous output gets out in sequence */
1167 if (stream == stderr)
1168 fflush(stdout);
1169 if (f_sayblock) {
1170 if (prefix) {
1171 fputs(prefix, stream);
1172 putc(' ', stream);
1173 }
1174 offset = ar_record - ar_block;
1175 (void) sprintf(buffer, "rec %d: ",
1176 savedp? saved_recno:
1177 baserec + offset);
1178 fputs(buffer, stream);
1179 space = ANNOWIDTH - strlen(buffer);
1180 if (space > 0) {
1181 fprintf(stream, "%*s", space, "");
1182 }
1183 } else if (prefix) {
1184 fputs(prefix, stream);
1185 fputs(": ", stream);
1186 }
1187 errno=save_e;
1188 }
1189 #endif
1190
1191 /* We've hit the end of the old volume. Close it and open the next one */
1192 /* Values for type: 0: writing 1: reading 2: updating */
1193 int
1194 new_volume(type)
1195 int type;
1196 {
1197 int c;
1198 char inbuf[80];
1199 char *p;
1200 static FILE *read_file = 0;
1201 extern int now_verifying;
1202 extern char TTY_NAME[];
1203 char *getenv();
1204
1205 if(!read_file && !f_run_script_at_end)
1206 read_file = (archive==0) ? fopen(TTY_NAME, "r") : stdin;
1207
1208 if(now_verifying)
1209 return -1;
1210 if(f_verify)
1211 verify_volume();
1212 if((c=rmtclose(archive))<0)
1213 msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c);
1214
1215 volno++;
1216 tryagain:
1217 if (f_run_script_at_end)
1218 system(info_script);
1219 else for(;;) {
1220 fprintf(msg_file,"\007Prepare volume #%d and hit return: ",volno);
1221 fflush(msg_file);
1222 if(fgets(inbuf,sizeof(inbuf),read_file)==0) {
1223 fprintf(msg_file,"EOF? What does that mean?");
1224 if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF)
1225 msg("Warning: Archive is INCOMPLETE!");
1226 exit(EX_BADARCH);
1227 }
1228 if(inbuf[0]=='\n' || inbuf[0]=='y' || inbuf[0]=='Y')
1229 break;
1230
1231 switch(inbuf[0]) {
1232 case '?':
1233 {
1234 fprintf(msg_file,"\
1235 n [name] Give a new filename for the next (and subsequent) volume(s)\n\
1236 q Abort tar\n\
1237 ! Spawn a subshell\n\
1238 ? Print this list\n");
1239 }
1240 break;
1241
1242 case 'q': /* Quit */
1243 fprintf(msg_file,"No new volume; exiting.\n");
1244 if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF)
1245 msg("Warning: Archive is INCOMPLETE!");
1246 exit(EX_BADARCH);
1247
1248 case 'n': /* Get new file name */
1249 {
1250 char *q,*r;
1251 static char *old_name;
1252
1253 for(q= &inbuf[1];*q==' ' || *q=='\t';q++)
1254 ;
1255 for(r=q;*r;r++)
1256 if(*r=='\n')
1257 *r='\0';
1258 if(old_name)
1259 free(old_name);
1260 old_name=p=(char *)malloc((unsigned)(strlen(q)+2));
1261 if(p==0) {
1262 msg("Can't allocate memory for name");
1263 exit(EX_SYSTEM);
1264 }
1265 (void) strcpy(p,q);
1266 ar_file=p;
1267 }
1268 break;
1269
1270 case '!':
1271 #ifdef __MSDOS__
1272 spawnl(P_WAIT,getenv("COMSPEC"),"-",0);
1273 #else
1274 /* JF this needs work! */
1275 switch(fork()) {
1276 case -1:
1277 msg_perror("can't fork!");
1278 break;
1279 case 0:
1280 p=getenv("SHELL");
1281 if(p==0) p="/bin/sh";
1282 execlp(p,"-sh","-i",0);
1283 msg_perror("can't exec a shell %s",p);
1284 _exit(55);
1285 default:
1286 wait(0);
1287 break;
1288 }
1289 #endif
1290 break;
1291 }
1292 }
1293
1294 if(type==2 || f_verify)
1295 archive=rmtopen(ar_file,O_RDWR|O_CREAT,0666);
1296 else if(type==1)
1297 archive=rmtopen(ar_file,O_RDONLY,0666);
1298 else if(type==0)
1299 archive=rmtcreat(ar_file,0666);
1300 else
1301 archive= -1;
1302
1303 if(archive<0) {
1304 msg_perror("can't open %s",ar_file);
1305 goto tryagain;
1306 }
1307 #ifdef __MSDOS__
1308 setmode(archive,O_BINARY);
1309 #endif
1310 return 0;
1311 }
1312
1313 /* this is a useless function that takes a buffer returned by wantbytes
1314 and does nothing with it. If the function called by wantbytes returns
1315 an error indicator (non-zero), this function is called for the rest of
1316 the file.
1317 */
1318 int
1319 no_op(size,data)
1320 int size;
1321 char *data;
1322 {
1323 return 0;
1324 }
1325
1326 /* Some other routine wants SIZE bytes in the archive. For each chunk of
1327 the archive, call FUNC with the size of the chunk, and the address of
1328 the chunk it can work with.
1329 */
1330 int
1331 wantbytes(size,func)
1332 long size;
1333 int (*func)();
1334 {
1335 char *data;
1336 long data_size;
1337
1338 while(size) {
1339 data = findrec()->charptr;
1340 if (data == NULL) { /* Check it... */
1341 msg("Unexpected EOF on archive file");
1342 return -1;
1343 }
1344 data_size = endofrecs()->charptr - data;
1345 if(data_size>size)
1346 data_size=size;
1347 if((*func)(data_size,data))
1348 func=no_op;
1349 userec((union record *)(data + data_size - 1));
1350 size-=data_size;
1351 }
1352 return 0;
1353 }
This page took 0.090767 seconds and 5 git commands to generate.