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