X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2Fbuffer.c;h=69812ec71597cfc502f207ef86cb7fab3ce71869;hb=75bf036edc1425eb66dcc9623846c7204f943ce6;hp=f3cebc0aed908a5450a26404c927fd817164f2ae;hpb=2bda83b48d8a6807632312403561b11b79048443;p=chaz%2Ftar diff --git a/src/buffer.c b/src/buffer.c index f3cebc0..69812ec 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "system.h" +#include #include @@ -28,7 +28,7 @@ #include #include "common.h" -#include "rmt.h" +#include /* Number of retries before giving up on read. */ #define READ_ERROR_MAX 10 @@ -40,6 +40,7 @@ static tarlong prev_written; /* bytes written on previous volumes */ static tarlong bytes_written; /* bytes written on this volume */ +static void *record_buffer; /* allocated memory */ /* FIXME: The following variables should ideally be static to this module. However, this cannot be done yet. The cleanup continues! */ @@ -114,32 +115,53 @@ clear_read_error_count (void) read_error_count = 0; } + +/* Time-related functions */ + +double duration; + void -print_total_written (void) +set_start_time () { - tarlong written = prev_written + bytes_written; - char bytes[sizeof (tarlong) * CHAR_BIT]; - char abbr[LONGEST_HUMAN_READABLE + 1]; - char rate[LONGEST_HUMAN_READABLE + 1]; - double seconds; - int human_opts = human_autoscale | human_base_1024 | human_SI | human_B; +#if HAVE_CLOCK_GETTIME + if (clock_gettime (CLOCK_REALTIME, &start_timespec) != 0) +#endif + start_time = time (0); +} +void +compute_duration () +{ #if HAVE_CLOCK_GETTIME struct timespec now; if (clock_gettime (CLOCK_REALTIME, &now) == 0) - seconds = ((now.tv_sec - start_timespec.tv_sec) - + (now.tv_nsec - start_timespec.tv_nsec) / 1e9); + duration += ((now.tv_sec - start_timespec.tv_sec) + + (now.tv_nsec - start_timespec.tv_nsec) / 1e9); else #endif - seconds = time (0) - start_time; + duration += time (NULL) - start_time; + set_start_time (); +} + + + +void +print_total_written (void) +{ + tarlong written = prev_written + bytes_written; + char bytes[sizeof (tarlong) * CHAR_BIT]; + char abbr[LONGEST_HUMAN_READABLE + 1]; + char rate[LONGEST_HUMAN_READABLE + 1]; + + int human_opts = human_autoscale | human_base_1024 | human_SI | human_B; sprintf (bytes, TARLONG_FORMAT, written); /* Amanda 2.4.1p1 looks for "Total bytes written: [0-9][0-9]*". */ fprintf (stderr, _("Total bytes written: %s (%s, %s/s)\n"), bytes, human_readable (written, abbr, human_opts, 1, 1), - (0 < seconds && written / seconds < (uintmax_t) -1 - ? human_readable (written / seconds, rate, human_opts, 1, 1) + (0 < duration && written / duration < (uintmax_t) -1 + ? human_readable (written / duration, rate, human_opts, 1, 1) : "?")); } @@ -270,17 +292,12 @@ open_archive (enum access_mode wanted_access) save_name = 0; real_s_name = 0; + record_start = + page_aligned_alloc (&record_buffer, + (record_size + + (multi_volume_option ? 2 * BLOCKSIZE : 0))); if (multi_volume_option) - { - record_start = valloc (record_size + (2 * BLOCKSIZE)); - if (record_start) - record_start += 2; - } - else - record_start = valloc (record_size); - if (!record_start) - FATAL_ERROR ((0, 0, _("Cannot allocate memory for blocking factor %d"), - blocking_factor)); + record_start += 2; current_block = record_start; record_end = record_start + blocking_factor; @@ -293,7 +310,6 @@ open_archive (enum access_mode wanted_access) { case ACCESS_READ: child_pid = sys_child_open_for_uncompress (); - read_full_records_option = false; break; case ACCESS_WRITE: @@ -515,13 +531,18 @@ flush_write (void) if (volume_label_option) record_start++; + if (strlen (real_s_name) > NAME_FIELD_SIZE) + FATAL_ERROR ((0, 0, + _("%s: file name too long to be stored in a GNU multivolume header"), + quotearg_colon (real_s_name))); + 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); + strncpy (record_start->header.name, real_s_name, NAME_FIELD_SIZE); 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, @@ -768,7 +789,7 @@ flush_read (void) { uintmax_t s1, s2; if (cursor->header.typeflag != GNUTYPE_MULTIVOL - || strcmp (cursor->header.name, real_s_name)) + || strncmp (cursor->header.name, real_s_name, NAME_FIELD_SIZE)) { WARN ((0, 0, _("%s is not continued on this volume"), quote (real_s_name))); @@ -889,6 +910,42 @@ backspace_output (void) } } +off_t +seek_archive (off_t size) +{ + off_t start = current_block_ordinal (); + off_t offset; + off_t nrec, nblk; + off_t skipped = (blocking_factor - (current_block - record_start)); + + size -= skipped * BLOCKSIZE; + + if (size < record_size) + return 0; + /* FIXME: flush? */ + + /* Compute number of records to skip */ + nrec = size / record_size; + offset = rmtlseek (archive, nrec * record_size, SEEK_CUR); + if (offset < 0) + return offset; + + if (offset % record_size) + FATAL_ERROR ((0, 0, _("rmtlseek not stopped at a record boundary"))); + + /* Convert to number of records */ + offset /= BLOCKSIZE; + /* Compute number of skipped blocks */ + nblk = offset - start; + + /* Update buffering info */ + records_read += nblk / blocking_factor; + record_start_block = offset - blocking_factor; + current_block = record_end; + + return nblk; +} + /* Close the archive file. */ void close_archive (void) @@ -898,7 +955,8 @@ close_archive (void) sys_drain_input_pipe (); - if (verify_option) + compute_duration (); + if (verify_option) verify_volume (); if (rmtclose (archive) != 0) @@ -911,7 +969,7 @@ close_archive (void) free (save_name); if (real_s_name) free (real_s_name); - free (multi_volume_option ? record_start - 2 : record_start); + free (record_buffer); } /* Called to initialize the global volume number. */