- if(f_multivol) {
- ptr=malloc(strlen(f_volhdr)+20);
- sprintf(ptr,"%s Volume %d",f_volhdr,1);
- } else
- ptr=f_volhdr;
-#endif
- head=findrec();
- if(!head) {
- msg("Archive not labelled to match %s",f_volhdr);
- exit(EX_BADVOL);
- }
- if (re_match (label_pattern, head->header.name,
- strlen (head->header.name), 0, 0) < 0) {
- msg ("Volume mismatch! %s!=%s", f_volhdr,
- head->header.name);
- exit (EX_BADVOL);
- }
-#if 0
- if(strcmp(ptr,head->header.name)) {
- msg("Volume mismatch! %s!=%s",ptr,head->header.name);
- exit(EX_BADVOL);
- }
- if(ptr!=f_volhdr)
- free(ptr);
-#endif
- }
- } else if(f_volhdr) {
- bzero((void *)ar_block,RECORDSIZE);
- if(f_multivol)
- sprintf(ar_block->header.name,"%s Volume 1",f_volhdr);
- else
- strcpy(ar_block->header.name,f_volhdr);
- ar_block->header.linkflag = LF_VOLHDR;
- to_oct(time(0), 1+12, ar_block->header.mtime);
- finish_header(ar_block);
- /* ar_record++; */
+/* Perform a write to flush the buffer. */
+void
+flush_write (void)
+{
+ int copy_back;
+ ssize_t status;
+
+ if (checkpoint_option && !(++checkpoint % 10))
+ WARN ((0, 0, _("Write checkpoint %d"), checkpoint));
+
+ if (tape_length_option && tape_length_option <= bytes_written)
+ {
+ errno = ENOSPC;
+ status = 0;
+ }
+ else if (dev_null_output)
+ status = record_size;
+ else
+ status = sys_write_archive_buffer ();
+ if (status != record_size && !multi_volume_option)
+ archive_write_error (status);
+
+ if (status > 0)
+ {
+ records_written++;
+ bytes_written += status;
+ }
+
+ if (status == record_size)
+ {
+ if (multi_volume_option)
+ {
+ if (save_name)
+ {
+ assign_string (&real_s_name, safer_name_suffix (save_name, false));
+ real_s_totsize = save_totsize;
+ real_s_sizeleft = save_sizeleft;
+ }
+ else
+ {
+ assign_string (&real_s_name, 0);
+ real_s_totsize = 0;
+ real_s_sizeleft = 0;
+ }
+ }
+ return;
+ }
+
+ /* We're multivol. Panic if we didn't get the right kind of response. */
+
+ /* ENXIO is for the UNIX PC. */
+ if (status < 0 && errno != ENOSPC && errno != EIO && errno != ENXIO)
+ archive_write_error (status);
+
+ /* If error indicates a short write, we just move to the next tape. */
+
+ if (!new_volume (ACCESS_WRITE))
+ return;
+
+ if (totals_option)
+ prev_written += bytes_written;
+ bytes_written = 0;
+
+ if (volume_label_option && real_s_name)
+ {
+ copy_back = 2;
+ record_start -= 2;
+ }
+ else if (volume_label_option || real_s_name)
+ {
+ copy_back = 1;
+ record_start--;
+ }
+ else
+ copy_back = 0;
+
+ if (volume_label_option)
+ {
+ memset (record_start, 0, BLOCKSIZE);
+ sprintf (record_start->header.name, "%s Volume %d",
+ volume_label_option, volno);
+ TIME_TO_CHARS (start_time, record_start->header.mtime);
+ record_start->header.typeflag = GNUTYPE_VOLHDR;
+ finish_header (¤t_stat_info, record_start, -1);
+ }
+
+ if (real_s_name)
+ {
+ int tmp;
+
+ if (volume_label_option)
+ record_start++;
+
+ memset (record_start, 0, BLOCKSIZE);
+
+ /* FIXME: Michael P Urban writes: [a long name file] is being written
+ when a new volume rolls around [...] Looks like the wrong value is
+ being preserved in real_s_name, though. */
+
+ strcpy (record_start->header.name, real_s_name);
+ record_start->header.typeflag = GNUTYPE_MULTIVOL;
+ OFF_TO_CHARS (real_s_sizeleft, record_start->header.size);
+ OFF_TO_CHARS (real_s_totsize - real_s_sizeleft,
+ record_start->oldgnu_header.offset);
+ tmp = verbose_option;
+ verbose_option = 0;
+ finish_header (¤t_stat_info, record_start, -1);
+ verbose_option = tmp;
+
+ if (volume_label_option)
+ record_start--;
+ }
+
+ status = sys_write_archive_buffer ();
+ if (status != record_size)
+ archive_write_error (status);
+
+ bytes_written += status;
+
+ if (copy_back)
+ {
+ record_start += copy_back;
+ memcpy (current_block,
+ record_start + blocking_factor - copy_back,
+ copy_back * BLOCKSIZE);
+ current_block += copy_back;
+
+ if (real_s_sizeleft >= copy_back * BLOCKSIZE)
+ real_s_sizeleft -= copy_back * BLOCKSIZE;
+ else if ((real_s_sizeleft + BLOCKSIZE - 1) / BLOCKSIZE <= copy_back)
+ assign_string (&real_s_name, 0);
+ else
+ {
+ assign_string (&real_s_name, safer_name_suffix (save_name, false));
+ real_s_sizeleft = save_sizeleft;
+ real_s_totsize = save_totsize;