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