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