]> Dogcows Code - chaz/tar/blob - src/buffer.c
Do not try to drain the input pipe before closing the archive.
[chaz/tar] / src / buffer.c
1 /* Buffer management for tar.
2
3 Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
4 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5
6 Written by John Gilmore, on 1985-08-25.
7
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16 Public License for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
21
22 #include <system.h>
23 #include <system-ioctl.h>
24
25 #include <signal.h>
26
27 #include <closeout.h>
28 #include <fnmatch.h>
29 #include <human.h>
30 #include <quotearg.h>
31
32 #include "common.h"
33 #include <rmt.h>
34
35 /* Number of retries before giving up on read. */
36 #define READ_ERROR_MAX 10
37
38 /* Globbing pattern to append to volume label if initial match failed. */
39 #define VOLUME_LABEL_APPEND " Volume [1-9]*"
40
41 /* Variables. */
42
43 static tarlong prev_written; /* bytes written on previous volumes */
44 static tarlong bytes_written; /* bytes written on this volume */
45 static void *record_buffer[2]; /* allocated memory */
46 union block *record_buffer_aligned[2];
47 static int record_index;
48
49 /* FIXME: The following variables should ideally be static to this
50 module. However, this cannot be done yet. The cleanup continues! */
51
52 union block *record_start; /* start of record of archive */
53 union block *record_end; /* last+1 block of archive record */
54 union block *current_block; /* current block of archive */
55 enum access_mode access_mode; /* how do we handle the archive */
56 off_t records_read; /* number of records read from this archive */
57 off_t records_written; /* likewise, for records written */
58 extern off_t records_skipped; /* number of records skipped at the start
59 of the archive, defined in delete.c */
60
61 static off_t record_start_block; /* block ordinal at record_start */
62
63 /* Where we write list messages (not errors, not interactions) to. */
64 FILE *stdlis;
65
66 static void backspace_output (void);
67
68 /* PID of child program, if compress_option or remote archive access. */
69 static pid_t child_pid;
70
71 /* Error recovery stuff */
72 static int read_error_count;
73
74 /* Have we hit EOF yet? */
75 static bool hit_eof;
76
77 static bool read_full_records = false;
78
79 /* We're reading, but we just read the last block and it's time to update.
80 Declared in update.c
81
82 As least EXTERN like this one as possible. (?? --gray)
83 FIXME: Either eliminate it or move it to common.h.
84 */
85 extern bool time_to_start_writing;
86
87 bool write_archive_to_stdout;
88
89 void (*flush_write_ptr) (size_t);
90 void (*flush_read_ptr) (void);
91
92 \f
93 char *volume_label;
94 char *continued_file_name;
95 uintmax_t continued_file_size;
96 uintmax_t continued_file_offset;
97
98 \f
99 static int volno = 1; /* which volume of a multi-volume tape we're
100 on */
101 static int global_volno = 1; /* volume number to print in external
102 messages */
103
104 bool write_archive_to_stdout;
105
106 /* Used by flush_read and flush_write to store the real info about saved
107 names. */
108 static char *real_s_name;
109 static off_t real_s_totsize;
110 static off_t real_s_sizeleft;
111
112 \f
113 /* Multi-volume tracking support */
114 static char *save_name; /* name of the file we are currently writing */
115 static off_t save_totsize; /* total size of file we are writing, only
116 valid if save_name is nonzero */
117 static off_t save_sizeleft; /* where we are in the file we are writing,
118 only valid if save_name is nonzero */
119
120 \f
121 static struct tar_stat_info dummy;
122
123 void
124 buffer_write_global_xheader ()
125 {
126 xheader_write_global (&dummy.xhdr);
127 }
128
129 void
130 mv_begin (struct tar_stat_info *st)
131 {
132 if (multi_volume_option)
133 {
134 assign_string (&save_name, st->orig_file_name);
135 save_totsize = save_sizeleft = st->stat.st_size;
136 }
137 }
138
139 void
140 mv_end ()
141 {
142 if (multi_volume_option)
143 assign_string (&save_name, 0);
144 }
145
146 void
147 mv_total_size (off_t size)
148 {
149 save_totsize = size;
150 }
151
152 void
153 mv_size_left (off_t size)
154 {
155 save_sizeleft = size;
156 }
157
158 \f
159 /* Functions. */
160
161 void
162 clear_read_error_count (void)
163 {
164 read_error_count = 0;
165 }
166
167 \f
168 /* Time-related functions */
169
170 double duration;
171
172 void
173 set_start_time ()
174 {
175 gettime (&start_time);
176 volume_start_time = start_time;
177 last_stat_time = start_time;
178 }
179
180 void
181 set_volume_start_time ()
182 {
183 gettime (&volume_start_time);
184 last_stat_time = volume_start_time;
185 }
186
187 void
188 compute_duration ()
189 {
190 struct timespec now;
191 gettime (&now);
192 duration += ((now.tv_sec - last_stat_time.tv_sec)
193 + (now.tv_nsec - last_stat_time.tv_nsec) / 1e9);
194 gettime (&last_stat_time);
195 }
196
197 \f
198 /* Compression detection */
199
200 enum compress_type {
201 ct_tar, /* Plain tar file */
202 ct_none, /* Unknown compression type */
203 ct_compress,
204 ct_gzip,
205 ct_bzip2,
206 ct_lzma,
207 ct_lzop
208 };
209
210 struct zip_magic
211 {
212 enum compress_type type;
213 size_t length;
214 char *magic;
215 char *program;
216 char *option;
217 };
218
219 static struct zip_magic const magic[] = {
220 { ct_tar },
221 { ct_none, },
222 { ct_compress, 2, "\037\235", "compress", "-Z" },
223 { ct_gzip, 2, "\037\213", "gzip", "-z" },
224 { ct_bzip2, 3, "BZh", "bzip2", "-j" },
225 { ct_lzma, 6, "\xFFLZMA", "lzma", "-J" }, /* FIXME: ???? */
226 { ct_lzop, 4, "\211LZO", "lzop", "--lzop" },
227 };
228
229 #define NMAGIC (sizeof(magic)/sizeof(magic[0]))
230
231 #define compress_option(t) magic[t].option
232 #define compress_program(t) magic[t].program
233
234 /* Check if the file ARCHIVE is a compressed archive. */
235 enum compress_type
236 check_compressed_archive (bool *pshort)
237 {
238 struct zip_magic const *p;
239 bool sfr;
240 bool temp;
241
242 if (!pshort)
243 pshort = &temp;
244
245 /* Prepare global data needed for find_next_block: */
246 record_end = record_start; /* set up for 1st record = # 0 */
247 sfr = read_full_records;
248 read_full_records = true; /* Suppress fatal error on reading a partial
249 record */
250 *pshort = find_next_block () == 0;
251
252 /* Restore global values */
253 read_full_records = sfr;
254
255 if (tar_checksum (record_start, true) == HEADER_SUCCESS)
256 /* Probably a valid header */
257 return ct_tar;
258
259 for (p = magic + 2; p < magic + NMAGIC; p++)
260 if (memcmp (record_start->buffer, p->magic, p->length) == 0)
261 return p->type;
262
263 return ct_none;
264 }
265
266 /* Open an archive named archive_name_array[0]. Detect if it is
267 a compressed archive of known type and use corresponding decompression
268 program if so */
269 int
270 open_compressed_archive ()
271 {
272 archive = rmtopen (archive_name_array[0], O_RDONLY | O_BINARY,
273 MODE_RW, rsh_command_option);
274 if (archive == -1)
275 return archive;
276
277 if (!multi_volume_option)
278 {
279 if (!use_compress_program_option)
280 {
281 bool shortfile;
282 enum compress_type type = check_compressed_archive (&shortfile);
283
284 switch (type)
285 {
286 case ct_tar:
287 if (shortfile)
288 ERROR ((0, 0, _("This does not look like a tar archive")));
289 return archive;
290
291 case ct_none:
292 if (shortfile)
293 ERROR ((0, 0, _("This does not look like a tar archive")));
294 set_comression_program_by_suffix (archive_name_array[0], NULL);
295 if (!use_compress_program_option)
296 return archive;
297 break;
298
299 default:
300 use_compress_program_option = compress_program (type);
301 break;
302 }
303 }
304
305 /* FD is not needed any more */
306 rmtclose (archive);
307
308 hit_eof = false; /* It might have been set by find_next_block in
309 check_compressed_archive */
310
311 /* Open compressed archive */
312 child_pid = sys_child_open_for_uncompress ();
313 read_full_records = true;
314 }
315
316 records_read = 0;
317 record_end = record_start; /* set up for 1st record = # 0 */
318
319 return archive;
320 }
321 \f
322
323 static void
324 print_stats (FILE *fp, const char *text, tarlong numbytes)
325 {
326 char bytes[sizeof (tarlong) * CHAR_BIT];
327 char abbr[LONGEST_HUMAN_READABLE + 1];
328 char rate[LONGEST_HUMAN_READABLE + 1];
329
330 int human_opts = human_autoscale | human_base_1024 | human_SI | human_B;
331
332 sprintf (bytes, TARLONG_FORMAT, numbytes);
333
334 fprintf (fp, "%s: %s (%s, %s/s)\n",
335 text, bytes,
336 human_readable (numbytes, abbr, human_opts, 1, 1),
337 (0 < duration && numbytes / duration < (uintmax_t) -1
338 ? human_readable (numbytes / duration, rate, human_opts, 1, 1)
339 : "?"));
340 }
341
342 void
343 print_total_stats ()
344 {
345 switch (subcommand_option)
346 {
347 case CREATE_SUBCOMMAND:
348 case CAT_SUBCOMMAND:
349 case UPDATE_SUBCOMMAND:
350 case APPEND_SUBCOMMAND:
351 /* Amanda 2.4.1p1 looks for "Total bytes written: [0-9][0-9]*". */
352 print_stats (stderr, _("Total bytes written"),
353 prev_written + bytes_written);
354 break;
355
356 case DELETE_SUBCOMMAND:
357 {
358 char buf[UINTMAX_STRSIZE_BOUND];
359 print_stats (stderr, _("Total bytes read"),
360 records_read * record_size);
361 print_stats (stderr, _("Total bytes written"),
362 prev_written + bytes_written);
363 fprintf (stderr, _("Total bytes deleted: %s\n"),
364 STRINGIFY_BIGINT ((records_read - records_skipped)
365 * record_size
366 - (prev_written + bytes_written), buf));
367 }
368 break;
369
370 case EXTRACT_SUBCOMMAND:
371 case LIST_SUBCOMMAND:
372 case DIFF_SUBCOMMAND:
373 print_stats (stderr, _("Total bytes read"),
374 records_read * record_size);
375 break;
376
377 default:
378 abort ();
379 }
380 }
381
382 /* Compute and return the block ordinal at current_block. */
383 off_t
384 current_block_ordinal (void)
385 {
386 return record_start_block + (current_block - record_start);
387 }
388
389 /* If the EOF flag is set, reset it, as well as current_block, etc. */
390 void
391 reset_eof (void)
392 {
393 if (hit_eof)
394 {
395 hit_eof = false;
396 current_block = record_start;
397 record_end = record_start + blocking_factor;
398 access_mode = ACCESS_WRITE;
399 }
400 }
401
402 /* Return the location of the next available input or output block.
403 Return zero for EOF. Once we have returned zero, we just keep returning
404 it, to avoid accidentally going on to the next file on the tape. */
405 union block *
406 find_next_block (void)
407 {
408 if (current_block == record_end)
409 {
410 if (hit_eof)
411 return 0;
412 flush_archive ();
413 if (current_block == record_end)
414 {
415 hit_eof = true;
416 return 0;
417 }
418 }
419 return current_block;
420 }
421
422 /* Indicate that we have used all blocks up thru BLOCK. */
423 void
424 set_next_block_after (union block *block)
425 {
426 while (block >= current_block)
427 current_block++;
428
429 /* Do *not* flush the archive here. If we do, the same argument to
430 set_next_block_after could mean the next block (if the input record
431 is exactly one block long), which is not what is intended. */
432
433 if (current_block > record_end)
434 abort ();
435 }
436
437 /* Return the number of bytes comprising the space between POINTER
438 through the end of the current buffer of blocks. This space is
439 available for filling with data, or taking data from. POINTER is
440 usually (but not always) the result of previous find_next_block call. */
441 size_t
442 available_space_after (union block *pointer)
443 {
444 return record_end->buffer - pointer->buffer;
445 }
446
447 /* Close file having descriptor FD, and abort if close unsuccessful. */
448 void
449 xclose (int fd)
450 {
451 if (close (fd) != 0)
452 close_error (_("(pipe)"));
453 }
454
455 static void
456 init_buffer ()
457 {
458 if (! record_buffer_aligned[record_index])
459 record_buffer_aligned[record_index] =
460 page_aligned_alloc (&record_buffer[record_index], record_size);
461
462 record_start = record_buffer_aligned[record_index];
463 current_block = record_start;
464 record_end = record_start + blocking_factor;
465 }
466
467 /* Open an archive file. The argument specifies whether we are
468 reading or writing, or both. */
469 static void
470 _open_archive (enum access_mode wanted_access)
471 {
472 int backed_up_flag = 0;
473
474 if (record_size == 0)
475 FATAL_ERROR ((0, 0, _("Invalid value for record_size")));
476
477 if (archive_names == 0)
478 FATAL_ERROR ((0, 0, _("No archive name given")));
479
480 tar_stat_destroy (&current_stat_info);
481 save_name = 0;
482 real_s_name = 0;
483
484 record_index = 0;
485 init_buffer ();
486
487 /* When updating the archive, we start with reading. */
488 access_mode = wanted_access == ACCESS_UPDATE ? ACCESS_READ : wanted_access;
489
490 read_full_records = read_full_records_option;
491
492 records_read = 0;
493
494 if (use_compress_program_option)
495 {
496 switch (wanted_access)
497 {
498 case ACCESS_READ:
499 child_pid = sys_child_open_for_uncompress ();
500 read_full_records = true;
501 record_end = record_start; /* set up for 1st record = # 0 */
502 break;
503
504 case ACCESS_WRITE:
505 child_pid = sys_child_open_for_compress ();
506 break;
507
508 case ACCESS_UPDATE:
509 abort (); /* Should not happen */
510 break;
511 }
512
513 if (!index_file_name
514 && wanted_access == ACCESS_WRITE
515 && strcmp (archive_name_array[0], "-") == 0)
516 stdlis = stderr;
517 }
518 else if (strcmp (archive_name_array[0], "-") == 0)
519 {
520 read_full_records = true; /* could be a pipe, be safe */
521 if (verify_option)
522 FATAL_ERROR ((0, 0, _("Cannot verify stdin/stdout archive")));
523
524 switch (wanted_access)
525 {
526 case ACCESS_READ:
527 {
528 bool shortfile;
529 enum compress_type type;
530
531 archive = STDIN_FILENO;
532
533 type = check_compressed_archive (&shortfile);
534 if (type != ct_tar && type != ct_none)
535 FATAL_ERROR ((0, 0,
536 _("Archive is compressed. Use %s option"),
537 compress_option (type)));
538 if (shortfile)
539 ERROR ((0, 0, _("This does not look like a tar archive")));
540 }
541 break;
542
543 case ACCESS_WRITE:
544 archive = STDOUT_FILENO;
545 if (!index_file_name)
546 stdlis = stderr;
547 break;
548
549 case ACCESS_UPDATE:
550 archive = STDIN_FILENO;
551 write_archive_to_stdout = true;
552 record_end = record_start; /* set up for 1st record = # 0 */
553 if (!index_file_name)
554 stdlis = stderr;
555 break;
556 }
557 }
558 else if (verify_option)
559 archive = rmtopen (archive_name_array[0], O_RDWR | O_CREAT | O_BINARY,
560 MODE_RW, rsh_command_option);
561 else
562 switch (wanted_access)
563 {
564 case ACCESS_READ:
565 archive = open_compressed_archive ();
566 break;
567
568 case ACCESS_WRITE:
569 if (backup_option)
570 {
571 maybe_backup_file (archive_name_array[0], 1);
572 backed_up_flag = 1;
573 }
574 archive = rmtcreat (archive_name_array[0], MODE_RW,
575 rsh_command_option);
576 break;
577
578 case ACCESS_UPDATE:
579 archive = rmtopen (archive_name_array[0],
580 O_RDWR | O_CREAT | O_BINARY,
581 MODE_RW, rsh_command_option);
582
583 switch (check_compressed_archive (NULL))
584 {
585 case ct_none:
586 case ct_tar:
587 break;
588
589 default:
590 FATAL_ERROR ((0, 0,
591 _("Cannot update compressed archives")));
592 }
593 break;
594 }
595
596 if (archive < 0
597 || (! _isrmt (archive) && !sys_get_archive_stat ()))
598 {
599 int saved_errno = errno;
600
601 if (backed_up_flag)
602 undo_last_backup ();
603 errno = saved_errno;
604 open_fatal (archive_name_array[0]);
605 }
606
607 sys_detect_dev_null_output ();
608 sys_save_archive_dev_ino ();
609 SET_BINARY_MODE (archive);
610
611 switch (wanted_access)
612 {
613 case ACCESS_READ:
614 find_next_block (); /* read it in, check for EOF */
615 break;
616
617 case ACCESS_UPDATE:
618 case ACCESS_WRITE:
619 records_written = 0;
620 break;
621 }
622 }
623
624 /* Perform a write to flush the buffer. */
625 ssize_t
626 _flush_write (void)
627 {
628 ssize_t status;
629
630 checkpoint_run (true);
631 if (tape_length_option && tape_length_option <= bytes_written)
632 {
633 errno = ENOSPC;
634 status = 0;
635 }
636 else if (dev_null_output)
637 status = record_size;
638 else
639 status = sys_write_archive_buffer ();
640
641 return status;
642 }
643
644 /* Handle write errors on the archive. Write errors are always fatal.
645 Hitting the end of a volume does not cause a write error unless the
646 write was the first record of the volume. */
647 void
648 archive_write_error (ssize_t status)
649 {
650 /* It might be useful to know how much was written before the error
651 occurred. */
652 if (totals_option)
653 {
654 int e = errno;
655 print_total_stats ();
656 errno = e;
657 }
658
659 write_fatal_details (*archive_name_cursor, status, record_size);
660 }
661
662 /* Handle read errors on the archive. If the read should be retried,
663 return to the caller. */
664 void
665 archive_read_error (void)
666 {
667 read_error (*archive_name_cursor);
668
669 if (record_start_block == 0)
670 FATAL_ERROR ((0, 0, _("At beginning of tape, quitting now")));
671
672 /* Read error in mid archive. We retry up to READ_ERROR_MAX times and
673 then give up on reading the archive. */
674
675 if (read_error_count++ > READ_ERROR_MAX)
676 FATAL_ERROR ((0, 0, _("Too many errors, quitting")));
677 return;
678 }
679
680 static void
681 short_read (size_t status)
682 {
683 size_t left; /* bytes left */
684 char *more; /* pointer to next byte to read */
685
686 more = record_start->buffer + status;
687 left = record_size - status;
688
689 if (left && left % BLOCKSIZE == 0
690 && verbose_option
691 && record_start_block == 0 && status != 0)
692 {
693 unsigned long rsize = status / BLOCKSIZE;
694 WARN ((0, 0,
695 ngettext ("Record size = %lu block",
696 "Record size = %lu blocks",
697 rsize),
698 rsize));
699 }
700
701 while (left % BLOCKSIZE != 0
702 || (left && status && read_full_records))
703 {
704 if (status)
705 while ((status = rmtread (archive, more, left)) == SAFE_READ_ERROR)
706 archive_read_error ();
707
708 if (status == 0)
709 break;
710
711 if (! read_full_records)
712 {
713 unsigned long rest = record_size - left;
714
715 FATAL_ERROR ((0, 0,
716 ngettext ("Unaligned block (%lu byte) in archive",
717 "Unaligned block (%lu bytes) in archive",
718 rest),
719 rest));
720 }
721
722 left -= status;
723 more += status;
724 }
725
726 record_end = record_start + (record_size - left) / BLOCKSIZE;
727 records_read++;
728 }
729
730 /* Flush the current buffer to/from the archive. */
731 void
732 flush_archive (void)
733 {
734 size_t buffer_level = current_block->buffer - record_start->buffer;
735 record_start_block += record_end - record_start;
736 current_block = record_start;
737 record_end = record_start + blocking_factor;
738
739 if (access_mode == ACCESS_READ && time_to_start_writing)
740 {
741 access_mode = ACCESS_WRITE;
742 time_to_start_writing = false;
743 backspace_output ();
744 }
745
746 switch (access_mode)
747 {
748 case ACCESS_READ:
749 flush_read ();
750 break;
751
752 case ACCESS_WRITE:
753 flush_write_ptr (buffer_level);
754 break;
755
756 case ACCESS_UPDATE:
757 abort ();
758 }
759 }
760
761 /* Backspace the archive descriptor by one record worth. If it's a
762 tape, MTIOCTOP will work. If it's something else, try to seek on
763 it. If we can't seek, we lose! */
764 static void
765 backspace_output (void)
766 {
767 #ifdef MTIOCTOP
768 {
769 struct mtop operation;
770
771 operation.mt_op = MTBSR;
772 operation.mt_count = 1;
773 if (rmtioctl (archive, MTIOCTOP, (char *) &operation) >= 0)
774 return;
775 if (errno == EIO && rmtioctl (archive, MTIOCTOP, (char *) &operation) >= 0)
776 return;
777 }
778 #endif
779
780 {
781 off_t position = rmtlseek (archive, (off_t) 0, SEEK_CUR);
782
783 /* Seek back to the beginning of this record and start writing there. */
784
785 position -= record_size;
786 if (position < 0)
787 position = 0;
788 if (rmtlseek (archive, position, SEEK_SET) != position)
789 {
790 /* Lseek failed. Try a different method. */
791
792 WARN ((0, 0,
793 _("Cannot backspace archive file; it may be unreadable without -i")));
794
795 /* Replace the first part of the record with NULs. */
796
797 if (record_start->buffer != output_start)
798 memset (record_start->buffer, 0,
799 output_start - record_start->buffer);
800 }
801 }
802 }
803
804 off_t
805 seek_archive (off_t size)
806 {
807 off_t start = current_block_ordinal ();
808 off_t offset;
809 off_t nrec, nblk;
810 off_t skipped = (blocking_factor - (current_block - record_start));
811
812 size -= skipped * BLOCKSIZE;
813
814 if (size < record_size)
815 return 0;
816 /* FIXME: flush? */
817
818 /* Compute number of records to skip */
819 nrec = size / record_size;
820 offset = rmtlseek (archive, nrec * record_size, SEEK_CUR);
821 if (offset < 0)
822 return offset;
823
824 if (offset % record_size)
825 FATAL_ERROR ((0, 0, _("rmtlseek not stopped at a record boundary")));
826
827 /* Convert to number of records */
828 offset /= BLOCKSIZE;
829 /* Compute number of skipped blocks */
830 nblk = offset - start;
831
832 /* Update buffering info */
833 records_read += nblk / blocking_factor;
834 record_start_block = offset - blocking_factor;
835 current_block = record_end;
836
837 return nblk;
838 }
839
840 /* Close the archive file. */
841 void
842 close_archive (void)
843 {
844 if (time_to_start_writing || access_mode == ACCESS_WRITE)
845 {
846 flush_archive ();
847 if (current_block > record_start)
848 flush_archive ();
849 }
850
851 compute_duration ();
852 if (verify_option)
853 verify_volume ();
854
855 if (rmtclose (archive) != 0)
856 close_error (*archive_name_cursor);
857
858 sys_wait_for_child (child_pid, hit_eof);
859
860 tar_stat_destroy (&current_stat_info);
861 if (save_name)
862 free (save_name);
863 if (real_s_name)
864 free (real_s_name);
865 free (record_buffer[0]);
866 free (record_buffer[1]);
867 }
868
869 /* Called to initialize the global volume number. */
870 void
871 init_volume_number (void)
872 {
873 FILE *file = fopen (volno_file_option, "r");
874
875 if (file)
876 {
877 if (fscanf (file, "%d", &global_volno) != 1
878 || global_volno < 0)
879 FATAL_ERROR ((0, 0, _("%s: contains invalid volume number"),
880 quotearg_colon (volno_file_option)));
881 if (ferror (file))
882 read_error (volno_file_option);
883 if (fclose (file) != 0)
884 close_error (volno_file_option);
885 }
886 else if (errno != ENOENT)
887 open_error (volno_file_option);
888 }
889
890 /* Called to write out the closing global volume number. */
891 void
892 closeout_volume_number (void)
893 {
894 FILE *file = fopen (volno_file_option, "w");
895
896 if (file)
897 {
898 fprintf (file, "%d\n", global_volno);
899 if (ferror (file))
900 write_error (volno_file_option);
901 if (fclose (file) != 0)
902 close_error (volno_file_option);
903 }
904 else
905 open_error (volno_file_option);
906 }
907
908 \f
909 static void
910 increase_volume_number ()
911 {
912 global_volno++;
913 if (global_volno < 0)
914 FATAL_ERROR ((0, 0, _("Volume number overflow")));
915 volno++;
916 }
917
918 void
919 change_tape_menu (FILE *read_file)
920 {
921 char *input_buffer = NULL;
922 size_t size = 0;
923 bool stop = false;
924
925 while (!stop)
926 {
927 fputc ('\007', stderr);
928 fprintf (stderr,
929 _("Prepare volume #%d for %s and hit return: "),
930 global_volno + 1, quote (*archive_name_cursor));
931 fflush (stderr);
932
933 if (getline (&input_buffer, &size, read_file) <= 0)
934 {
935 WARN ((0, 0, _("EOF where user reply was expected")));
936
937 if (subcommand_option != EXTRACT_SUBCOMMAND
938 && subcommand_option != LIST_SUBCOMMAND
939 && subcommand_option != DIFF_SUBCOMMAND)
940 WARN ((0, 0, _("WARNING: Archive is incomplete")));
941
942 fatal_exit ();
943 }
944
945 if (input_buffer[0] == '\n'
946 || input_buffer[0] == 'y'
947 || input_buffer[0] == 'Y')
948 break;
949
950 switch (input_buffer[0])
951 {
952 case '?':
953 {
954 fprintf (stderr, _("\
955 n name Give a new file name for the next (and subsequent) volume(s)\n\
956 q Abort tar\n\
957 y or newline Continue operation\n"));
958 if (!restrict_option)
959 fprintf (stderr, _(" ! Spawn a subshell\n"));
960 fprintf (stderr, _(" ? Print this list\n"));
961 }
962 break;
963
964 case 'q':
965 /* Quit. */
966
967 WARN ((0, 0, _("No new volume; exiting.\n")));
968
969 if (subcommand_option != EXTRACT_SUBCOMMAND
970 && subcommand_option != LIST_SUBCOMMAND
971 && subcommand_option != DIFF_SUBCOMMAND)
972 WARN ((0, 0, _("WARNING: Archive is incomplete")));
973
974 fatal_exit ();
975
976 case 'n':
977 /* Get new file name. */
978
979 {
980 char *name;
981 char *cursor;
982
983 for (name = input_buffer + 1;
984 *name == ' ' || *name == '\t';
985 name++)
986 ;
987
988 for (cursor = name; *cursor && *cursor != '\n'; cursor++)
989 ;
990 *cursor = '\0';
991
992 if (name[0])
993 {
994 /* FIXME: the following allocation is never reclaimed. */
995 *archive_name_cursor = xstrdup (name);
996 stop = true;
997 }
998 else
999 fprintf (stderr, "%s",
1000 _("File name not specified. Try again.\n"));
1001 }
1002 break;
1003
1004 case '!':
1005 if (!restrict_option)
1006 {
1007 sys_spawn_shell ();
1008 break;
1009 }
1010 /* FALL THROUGH */
1011
1012 default:
1013 fprintf (stderr, _("Invalid input. Type ? for help.\n"));
1014 }
1015 }
1016 free (input_buffer);
1017 }
1018
1019 /* We've hit the end of the old volume. Close it and open the next one.
1020 Return nonzero on success.
1021 */
1022 static bool
1023 new_volume (enum access_mode mode)
1024 {
1025 static FILE *read_file;
1026 static int looped;
1027 int prompt;
1028
1029 if (!read_file && !info_script_option)
1030 /* FIXME: if fopen is used, it will never be closed. */
1031 read_file = archive == STDIN_FILENO ? fopen (TTY_NAME, "r") : stdin;
1032
1033 if (now_verifying)
1034 return false;
1035 if (verify_option)
1036 verify_volume ();
1037
1038 assign_string (&volume_label, NULL);
1039 assign_string (&continued_file_name, NULL);
1040 continued_file_size = continued_file_offset = 0;
1041 current_block = record_start;
1042
1043 if (rmtclose (archive) != 0)
1044 close_error (*archive_name_cursor);
1045
1046 archive_name_cursor++;
1047 if (archive_name_cursor == archive_name_array + archive_names)
1048 {
1049 archive_name_cursor = archive_name_array;
1050 looped = 1;
1051 }
1052 prompt = looped;
1053
1054 tryagain:
1055 if (prompt)
1056 {
1057 /* We have to prompt from now on. */
1058
1059 if (info_script_option)
1060 {
1061 if (volno_file_option)
1062 closeout_volume_number ();
1063 if (sys_exec_info_script (archive_name_cursor, global_volno+1))
1064 FATAL_ERROR ((0, 0, _("%s command failed"),
1065 quote (info_script_option)));
1066 }
1067 else
1068 change_tape_menu (read_file);
1069 }
1070
1071 if (strcmp (archive_name_cursor[0], "-") == 0)
1072 {
1073 read_full_records = true;
1074 archive = STDIN_FILENO;
1075 }
1076 else if (verify_option)
1077 archive = rmtopen (*archive_name_cursor, O_RDWR | O_CREAT, MODE_RW,
1078 rsh_command_option);
1079 else
1080 switch (mode)
1081 {
1082 case ACCESS_READ:
1083 archive = rmtopen (*archive_name_cursor, O_RDONLY, MODE_RW,
1084 rsh_command_option);
1085 break;
1086
1087 case ACCESS_WRITE:
1088 if (backup_option)
1089 maybe_backup_file (*archive_name_cursor, 1);
1090 archive = rmtcreat (*archive_name_cursor, MODE_RW,
1091 rsh_command_option);
1092 break;
1093
1094 case ACCESS_UPDATE:
1095 archive = rmtopen (*archive_name_cursor, O_RDWR | O_CREAT, MODE_RW,
1096 rsh_command_option);
1097 break;
1098 }
1099
1100 if (archive < 0)
1101 {
1102 open_warn (*archive_name_cursor);
1103 if (!verify_option && mode == ACCESS_WRITE && backup_option)
1104 undo_last_backup ();
1105 prompt = 1;
1106 goto tryagain;
1107 }
1108
1109 SET_BINARY_MODE (archive);
1110
1111 return true;
1112 }
1113
1114 static bool
1115 read_header0 (struct tar_stat_info *info)
1116 {
1117 enum read_header rc;
1118
1119 tar_stat_init (info);
1120 rc = read_header_primitive (false, info);
1121 if (rc == HEADER_SUCCESS)
1122 {
1123 set_next_block_after (current_header);
1124 return true;
1125 }
1126 ERROR ((0, 0, _("This does not look like a tar archive")));
1127 return false;
1128 }
1129
1130 bool
1131 try_new_volume ()
1132 {
1133 size_t status;
1134 union block *header;
1135 enum access_mode acc;
1136
1137 switch (subcommand_option)
1138 {
1139 case APPEND_SUBCOMMAND:
1140 case CAT_SUBCOMMAND:
1141 case UPDATE_SUBCOMMAND:
1142 acc = ACCESS_UPDATE;
1143 break;
1144
1145 default:
1146 acc = ACCESS_READ;
1147 break;
1148 }
1149
1150 if (!new_volume (acc))
1151 return true;
1152
1153 while ((status = rmtread (archive, record_start->buffer, record_size))
1154 == SAFE_READ_ERROR)
1155 archive_read_error ();
1156
1157 if (status != record_size)
1158 short_read (status);
1159
1160 header = find_next_block ();
1161 if (!header)
1162 return false;
1163
1164 switch (header->header.typeflag)
1165 {
1166 case XGLTYPE:
1167 {
1168 if (!read_header0 (&dummy))
1169 return false;
1170 xheader_decode (&dummy); /* decodes values from the global header */
1171 tar_stat_destroy (&dummy);
1172 if (!real_s_name)
1173 {
1174 /* We have read the extended header of the first member in
1175 this volume. Put it back, so next read_header works as
1176 expected. */
1177 current_block = record_start;
1178 }
1179 break;
1180 }
1181
1182 case GNUTYPE_VOLHDR:
1183 if (!read_header0 (&dummy))
1184 return false;
1185 tar_stat_destroy (&dummy);
1186 assign_string (&volume_label, current_header->header.name);
1187 set_next_block_after (header);
1188 header = find_next_block ();
1189 if (header->header.typeflag != GNUTYPE_MULTIVOL)
1190 break;
1191 /* FALL THROUGH */
1192
1193 case GNUTYPE_MULTIVOL:
1194 if (!read_header0 (&dummy))
1195 return false;
1196 tar_stat_destroy (&dummy);
1197 assign_string (&continued_file_name, current_header->header.name);
1198 continued_file_size =
1199 UINTMAX_FROM_HEADER (current_header->header.size);
1200 continued_file_offset =
1201 UINTMAX_FROM_HEADER (current_header->oldgnu_header.offset);
1202 break;
1203
1204 default:
1205 break;
1206 }
1207
1208 if (real_s_name)
1209 {
1210 uintmax_t s;
1211 if (!continued_file_name
1212 || strcmp (continued_file_name, real_s_name))
1213 {
1214 if ((archive_format == GNU_FORMAT || archive_format == OLDGNU_FORMAT)
1215 && strlen (real_s_name) >= NAME_FIELD_SIZE
1216 && strncmp (continued_file_name, real_s_name,
1217 NAME_FIELD_SIZE) == 0)
1218 WARN ((0, 0,
1219 _("%s is possibly continued on this volume: header contains truncated name"),
1220 quote (real_s_name)));
1221 else
1222 {
1223 WARN ((0, 0, _("%s is not continued on this volume"),
1224 quote (real_s_name)));
1225 return false;
1226 }
1227 }
1228
1229 s = continued_file_size + continued_file_offset;
1230
1231 if (real_s_totsize != s || s < continued_file_offset)
1232 {
1233 char totsizebuf[UINTMAX_STRSIZE_BOUND];
1234 char s1buf[UINTMAX_STRSIZE_BOUND];
1235 char s2buf[UINTMAX_STRSIZE_BOUND];
1236
1237 WARN ((0, 0, _("%s is the wrong size (%s != %s + %s)"),
1238 quote (continued_file_name),
1239 STRINGIFY_BIGINT (save_totsize, totsizebuf),
1240 STRINGIFY_BIGINT (continued_file_size, s1buf),
1241 STRINGIFY_BIGINT (continued_file_offset, s2buf)));
1242 return false;
1243 }
1244
1245 if (real_s_totsize - real_s_sizeleft != continued_file_offset)
1246 {
1247 char totsizebuf[UINTMAX_STRSIZE_BOUND];
1248 char s1buf[UINTMAX_STRSIZE_BOUND];
1249 char s2buf[UINTMAX_STRSIZE_BOUND];
1250
1251 WARN ((0, 0, _("This volume is out of sequence (%s - %s != %s)"),
1252 STRINGIFY_BIGINT (real_s_totsize, totsizebuf),
1253 STRINGIFY_BIGINT (real_s_sizeleft, s1buf),
1254 STRINGIFY_BIGINT (continued_file_offset, s2buf)));
1255
1256 return false;
1257 }
1258 }
1259
1260 increase_volume_number ();
1261 return true;
1262 }
1263
1264 \f
1265 /* Check the LABEL block against the volume label, seen as a globbing
1266 pattern. Return true if the pattern matches. In case of failure,
1267 retry matching a volume sequence number before giving up in
1268 multi-volume mode. */
1269 static bool
1270 check_label_pattern (union block *label)
1271 {
1272 char *string;
1273 bool result;
1274
1275 if (! memchr (label->header.name, '\0', sizeof label->header.name))
1276 return false;
1277
1278 if (fnmatch (volume_label_option, label->header.name, 0) == 0)
1279 return true;
1280
1281 if (!multi_volume_option)
1282 return false;
1283
1284 string = xmalloc (strlen (volume_label_option)
1285 + sizeof VOLUME_LABEL_APPEND + 1);
1286 strcpy (string, volume_label_option);
1287 strcat (string, VOLUME_LABEL_APPEND);
1288 result = fnmatch (string, label->header.name, 0) == 0;
1289 free (string);
1290 return result;
1291 }
1292
1293 /* Check if the next block contains a volume label and if this matches
1294 the one given in the command line */
1295 static void
1296 match_volume_label (void)
1297 {
1298 union block *label = find_next_block ();
1299
1300 if (!label)
1301 FATAL_ERROR ((0, 0, _("Archive not labeled to match %s"),
1302 quote (volume_label_option)));
1303 if (!check_label_pattern (label))
1304 FATAL_ERROR ((0, 0, _("Volume %s does not match %s"),
1305 quote_n (0, label->header.name),
1306 quote_n (1, volume_label_option)));
1307 }
1308
1309 /* Mark the archive with volume label STR. */
1310 static void
1311 _write_volume_label (const char *str)
1312 {
1313 if (archive_format == POSIX_FORMAT)
1314 xheader_store ("GNU.volume.label", &dummy, str);
1315 else
1316 {
1317 union block *label = find_next_block ();
1318
1319 memset (label, 0, BLOCKSIZE);
1320
1321 strcpy (label->header.name, str);
1322 assign_string (&current_stat_info.file_name,
1323 label->header.name);
1324 current_stat_info.had_trailing_slash =
1325 strip_trailing_slashes (current_stat_info.file_name);
1326
1327 label->header.typeflag = GNUTYPE_VOLHDR;
1328 TIME_TO_CHARS (start_time.tv_sec, label->header.mtime);
1329 finish_header (&current_stat_info, label, -1);
1330 set_next_block_after (label);
1331 }
1332 }
1333
1334 #define VOL_SUFFIX "Volume"
1335
1336 /* Add a volume label to a part of multi-volume archive */
1337 static void
1338 add_volume_label (void)
1339 {
1340 char buf[UINTMAX_STRSIZE_BOUND];
1341 char *p = STRINGIFY_BIGINT (volno, buf);
1342 char *s = xmalloc (strlen (volume_label_option) + sizeof VOL_SUFFIX
1343 + strlen (p) + 2);
1344 sprintf (s, "%s %s %s", volume_label_option, VOL_SUFFIX, p);
1345 _write_volume_label (s);
1346 free (s);
1347 }
1348
1349 static void
1350 add_chunk_header ()
1351 {
1352 if (archive_format == POSIX_FORMAT)
1353 {
1354 off_t block_ordinal;
1355 union block *blk;
1356 struct tar_stat_info st;
1357 static size_t real_s_part_no; /* FIXME */
1358
1359 real_s_part_no++;
1360 memset (&st, 0, sizeof st);
1361 st.orig_file_name = st.file_name = real_s_name;
1362 st.stat.st_mode = S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;
1363 st.stat.st_uid = getuid ();
1364 st.stat.st_gid = getgid ();
1365 st.orig_file_name = xheader_format_name (&st,
1366 "%d/GNUFileParts.%p/%f.%n",
1367 real_s_part_no);
1368 st.file_name = st.orig_file_name;
1369 st.archive_file_size = st.stat.st_size = real_s_sizeleft;
1370
1371 block_ordinal = current_block_ordinal ();
1372 blk = start_header (&st);
1373 if (!blk)
1374 abort (); /* FIXME */
1375 finish_header (&st, blk, block_ordinal);
1376 free (st.orig_file_name);
1377 }
1378 }
1379
1380
1381 /* Add a volume label to the current archive */
1382 static void
1383 write_volume_label (void)
1384 {
1385 if (multi_volume_option)
1386 add_volume_label ();
1387 else
1388 _write_volume_label (volume_label_option);
1389 }
1390
1391 /* Write GNU multi-volume header */
1392 static void
1393 gnu_add_multi_volume_header (void)
1394 {
1395 int tmp;
1396 union block *block = find_next_block ();
1397
1398 if (strlen (real_s_name) > NAME_FIELD_SIZE)
1399 WARN ((0, 0,
1400 _("%s: file name too long to be stored in a GNU multivolume header, truncated"),
1401 quotearg_colon (real_s_name)));
1402
1403 memset (block, 0, BLOCKSIZE);
1404
1405 /* FIXME: Michael P Urban writes: [a long name file] is being written
1406 when a new volume rolls around [...] Looks like the wrong value is
1407 being preserved in real_s_name, though. */
1408
1409 strncpy (block->header.name, real_s_name, NAME_FIELD_SIZE);
1410 block->header.typeflag = GNUTYPE_MULTIVOL;
1411
1412 OFF_TO_CHARS (real_s_sizeleft, block->header.size);
1413 OFF_TO_CHARS (real_s_totsize - real_s_sizeleft,
1414 block->oldgnu_header.offset);
1415
1416 tmp = verbose_option;
1417 verbose_option = 0;
1418 finish_header (&current_stat_info, block, -1);
1419 verbose_option = tmp;
1420 set_next_block_after (block);
1421 }
1422
1423 /* Add a multi volume header to the current archive. The exact header format
1424 depends on the archive format. */
1425 static void
1426 add_multi_volume_header (void)
1427 {
1428 if (archive_format == POSIX_FORMAT)
1429 {
1430 off_t d = real_s_totsize - real_s_sizeleft;
1431 xheader_store ("GNU.volume.filename", &dummy, real_s_name);
1432 xheader_store ("GNU.volume.size", &dummy, &real_s_sizeleft);
1433 xheader_store ("GNU.volume.offset", &dummy, &d);
1434 }
1435 else
1436 gnu_add_multi_volume_header ();
1437 }
1438
1439 /* Synchronize multi-volume globals */
1440 static void
1441 multi_volume_sync ()
1442 {
1443 if (multi_volume_option)
1444 {
1445 if (save_name)
1446 {
1447 assign_string (&real_s_name,
1448 safer_name_suffix (save_name, false,
1449 absolute_names_option));
1450 real_s_totsize = save_totsize;
1451 real_s_sizeleft = save_sizeleft;
1452 }
1453 else
1454 {
1455 assign_string (&real_s_name, 0);
1456 real_s_totsize = 0;
1457 real_s_sizeleft = 0;
1458 }
1459 }
1460 }
1461
1462 \f
1463 /* Low-level flush functions */
1464
1465 /* Simple flush read (no multi-volume or label extensions) */
1466 static void
1467 simple_flush_read (void)
1468 {
1469 size_t status; /* result from system call */
1470
1471 checkpoint_run (false);
1472
1473 /* Clear the count of errors. This only applies to a single call to
1474 flush_read. */
1475
1476 read_error_count = 0; /* clear error count */
1477
1478 if (write_archive_to_stdout && record_start_block != 0)
1479 {
1480 archive = STDOUT_FILENO;
1481 status = sys_write_archive_buffer ();
1482 archive = STDIN_FILENO;
1483 if (status != record_size)
1484 archive_write_error (status);
1485 }
1486
1487 for (;;)
1488 {
1489 status = rmtread (archive, record_start->buffer, record_size);
1490 if (status == record_size)
1491 {
1492 records_read++;
1493 return;
1494 }
1495 if (status == SAFE_READ_ERROR)
1496 {
1497 archive_read_error ();
1498 continue; /* try again */
1499 }
1500 break;
1501 }
1502 short_read (status);
1503 }
1504
1505 /* Simple flush write (no multi-volume or label extensions) */
1506 static void
1507 simple_flush_write (size_t level __attribute__((unused)))
1508 {
1509 ssize_t status;
1510
1511 status = _flush_write ();
1512 if (status != record_size)
1513 archive_write_error (status);
1514 else
1515 {
1516 records_written++;
1517 bytes_written += status;
1518 }
1519 }
1520
1521 \f
1522 /* GNU flush functions. These support multi-volume and archive labels in
1523 GNU and PAX archive formats. */
1524
1525 static void
1526 _gnu_flush_read (void)
1527 {
1528 size_t status; /* result from system call */
1529
1530 checkpoint_run (false);
1531
1532 /* Clear the count of errors. This only applies to a single call to
1533 flush_read. */
1534
1535 read_error_count = 0; /* clear error count */
1536
1537 if (write_archive_to_stdout && record_start_block != 0)
1538 {
1539 archive = STDOUT_FILENO;
1540 status = sys_write_archive_buffer ();
1541 archive = STDIN_FILENO;
1542 if (status != record_size)
1543 archive_write_error (status);
1544 }
1545
1546 multi_volume_sync ();
1547
1548 for (;;)
1549 {
1550 status = rmtread (archive, record_start->buffer, record_size);
1551 if (status == record_size)
1552 {
1553 records_read++;
1554 return;
1555 }
1556
1557 /* The condition below used to include
1558 || (status > 0 && !read_full_records)
1559 This is incorrect since even if new_volume() succeeds, the
1560 subsequent call to rmtread will overwrite the chunk of data
1561 already read in the buffer, so the processing will fail */
1562 if ((status == 0
1563 || (status == SAFE_READ_ERROR && errno == ENOSPC))
1564 && multi_volume_option)
1565 {
1566 while (!try_new_volume ())
1567 ;
1568 if (current_block == record_end)
1569 /* Necessary for blocking_factor == 1 */
1570 flush_archive();
1571 return;
1572 }
1573 else if (status == SAFE_READ_ERROR)
1574 {
1575 archive_read_error ();
1576 continue;
1577 }
1578 break;
1579 }
1580 short_read (status);
1581 }
1582
1583 static void
1584 gnu_flush_read (void)
1585 {
1586 flush_read_ptr = simple_flush_read; /* Avoid recursion */
1587 _gnu_flush_read ();
1588 flush_read_ptr = gnu_flush_read;
1589 }
1590
1591 static void
1592 _gnu_flush_write (size_t buffer_level)
1593 {
1594 ssize_t status;
1595 union block *header;
1596 char *copy_ptr;
1597 size_t copy_size;
1598 size_t bufsize;
1599 tarlong wrt;
1600
1601 status = _flush_write ();
1602 if (status != record_size && !multi_volume_option)
1603 archive_write_error (status);
1604 else
1605 {
1606 if (status)
1607 records_written++;
1608 bytes_written += status;
1609 }
1610
1611 if (status == record_size)
1612 {
1613 multi_volume_sync ();
1614 return;
1615 }
1616
1617 if (status % BLOCKSIZE)
1618 {
1619 ERROR ((0, 0, _("write did not end on a block boundary")));
1620 archive_write_error (status);
1621 }
1622
1623 /* In multi-volume mode. */
1624 /* ENXIO is for the UNIX PC. */
1625 if (status < 0 && errno != ENOSPC && errno != EIO && errno != ENXIO)
1626 archive_write_error (status);
1627
1628 real_s_sizeleft -= status;
1629 if (!new_volume (ACCESS_WRITE))
1630 return;
1631
1632 tar_stat_destroy (&dummy);
1633
1634 increase_volume_number ();
1635 prev_written += bytes_written;
1636 bytes_written = 0;
1637
1638 copy_ptr = record_start->buffer + status;
1639 copy_size = buffer_level - status;
1640
1641 /* Switch to the next buffer */
1642 record_index = !record_index;
1643 init_buffer ();
1644
1645 if (volume_label_option)
1646 add_volume_label ();
1647
1648 if (real_s_name)
1649 add_multi_volume_header ();
1650
1651 write_extended (true, &dummy, find_next_block ());
1652 tar_stat_destroy (&dummy);
1653
1654 if (real_s_name)
1655 add_chunk_header ();
1656 wrt = bytes_written;
1657 header = find_next_block ();
1658 bufsize = available_space_after (header);
1659 while (bufsize < copy_size)
1660 {
1661 memcpy (header->buffer, copy_ptr, bufsize);
1662 copy_ptr += bufsize;
1663 copy_size -= bufsize;
1664 set_next_block_after (header + (bufsize - 1) / BLOCKSIZE);
1665 header = find_next_block ();
1666 bufsize = available_space_after (header);
1667 }
1668 memcpy (header->buffer, copy_ptr, copy_size);
1669 memset (header->buffer + copy_size, 0, bufsize - copy_size);
1670 set_next_block_after (header + (copy_size - 1) / BLOCKSIZE);
1671 if (multi_volume_option && wrt < bytes_written)
1672 {
1673 /* The value of bytes_written has changed while moving data;
1674 that means that flush_archive was executed at least once in
1675 between, and, as a consequence, copy_size bytes were not written
1676 to disk. We need to update sizeleft variables to compensate for
1677 that. */
1678 save_sizeleft += copy_size;
1679 multi_volume_sync ();
1680 }
1681 find_next_block ();
1682 }
1683
1684 static void
1685 gnu_flush_write (size_t buffer_level)
1686 {
1687 flush_write_ptr = simple_flush_write; /* Avoid recursion */
1688 _gnu_flush_write (buffer_level);
1689 flush_write_ptr = gnu_flush_write;
1690 }
1691
1692 void
1693 flush_read ()
1694 {
1695 flush_read_ptr ();
1696 }
1697
1698 void
1699 flush_write ()
1700 {
1701 flush_write_ptr (record_size);
1702 }
1703
1704 void
1705 open_archive (enum access_mode wanted_access)
1706 {
1707 flush_read_ptr = gnu_flush_read;
1708 flush_write_ptr = gnu_flush_write;
1709
1710 _open_archive (wanted_access);
1711 switch (wanted_access)
1712 {
1713 case ACCESS_READ:
1714 if (volume_label_option)
1715 match_volume_label ();
1716 break;
1717
1718 case ACCESS_WRITE:
1719 records_written = 0;
1720 if (volume_label_option)
1721 write_volume_label ();
1722 break;
1723
1724 default:
1725 break;
1726 }
1727 set_volume_start_time ();
1728 }
This page took 0.10633 seconds and 5 git commands to generate.