X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fbuffer.c;h=80bbe829b4d031ed0ea7b47a527f818515550e4b;hb=ba08e339a6e05e2a0d1432efdadd67ff2c63f834;hp=7fd43f647e694020fa82f35265416d2229c70926;hpb=37400fa94ef4d2928ebf7206c4cd9fadd4e7e245;p=chaz%2Ftar diff --git a/src/buffer.c b/src/buffer.c index 7fd43f6..80bbe82 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -75,7 +75,7 @@ static int checkpoint; Declared in update.c As least EXTERN like this one as possible. (?? --gray) - FIXME: Either eliminate it or move it to common.h. + FIXME: Either eliminate it or move it to common.h. */ extern bool time_to_start_writing; @@ -109,7 +109,7 @@ static off_t real_s_sizeleft; /* Functions. */ void -clear_read_error_count () +clear_read_error_count (void) { read_error_count = 0; } @@ -599,7 +599,7 @@ archive_read_error (void) } static void -short_read (ssize_t status) +short_read (size_t status) { size_t left; /* bytes left */ char *more; /* pointer to next byte to read */ @@ -611,23 +611,23 @@ short_read (ssize_t status) || (left && status && read_full_records_option)) { if (status) - while ((status = rmtread (archive, more, left)) < 0) + while ((status = rmtread (archive, more, left)) == SAFE_READ_ERROR) archive_read_error (); if (status == 0) { char buf[UINTMAX_STRSIZE_BOUND]; - + WARN((0, 0, _("Read %s bytes from %s"), STRINGIFY_BIGINT (record_size - left, buf), *archive_name_cursor)); break; } - + if (! read_full_records_option) { unsigned long rest = record_size - left; - + FATAL_ERROR ((0, 0, ngettext ("Unaligned block (%lu byte) in archive", "Unaligned block (%lu bytes) in archive", @@ -644,8 +644,8 @@ short_read (ssize_t status) /* FIXME: for size=0, multi-volume support. On the first record, warn about the problem. */ - if (!read_full_records_option && verbose_option - && record_start_block == 0 && status > 0) + if (!read_full_records_option && verbose_option > 1 + && record_start_block == 0 && status != 0) { unsigned long rsize = (record_size - left) / BLOCKSIZE; WARN ((0, 0, @@ -663,7 +663,7 @@ short_read (ssize_t status) void flush_read (void) { - ssize_t status; /* result from system call */ + size_t status; /* result from system call */ if (checkpoint_option && !(++checkpoint % 10)) WARN ((0, 0, _("Read checkpoint %d"), checkpoint)); @@ -710,9 +710,9 @@ flush_read (void) This is incorrect since even if new_volume() succeeds, the subsequent call to rmtread will overwrite the chunk of data already read in the buffer, so the processing will fail */ - + if ((status == 0 - || (status < 0 && errno == ENOSPC)) + || (status == SAFE_READ_ERROR && errno == ENOSPC)) && multi_volume_option) { union block *cursor; @@ -733,12 +733,12 @@ flush_read (void) break; } - while ((status = - rmtread (archive, record_start->buffer, record_size)) < 0) + while ((status = rmtread (archive, record_start->buffer, record_size)) + == SAFE_READ_ERROR) archive_read_error (); - + if (status != record_size) - short_read (status); + short_read (status); cursor = record_start; @@ -806,7 +806,7 @@ flush_read (void) records_read++; return; } - else if (status < 0) + else if (status == SAFE_READ_ERROR) { archive_read_error (); goto error_loop; /* try again */ @@ -888,6 +888,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) @@ -896,7 +932,7 @@ close_archive (void) flush_archive (); sys_drain_input_pipe (); - + if (verify_option) verify_volume (); @@ -904,7 +940,7 @@ close_archive (void) close_warn (*archive_name_cursor); sys_wait_for_child (child_pid); - + tar_stat_destroy (¤t_stat_info); if (save_name) free (save_name); @@ -956,7 +992,7 @@ closeout_volume_number (void) Return nonzero on success. */ static bool -new_volume (enum access_mode access) +new_volume (enum access_mode mode) { static FILE *read_file; static int looped; @@ -1085,7 +1121,7 @@ new_volume (enum access_mode access) archive = rmtopen (*archive_name_cursor, O_RDWR | O_CREAT, MODE_RW, rsh_command_option); else - switch (access) + switch (mode) { case ACCESS_READ: archive = rmtopen (*archive_name_cursor, O_RDONLY, MODE_RW, @@ -1108,7 +1144,7 @@ new_volume (enum access_mode access) if (archive < 0) { open_warn (*archive_name_cursor); - if (!verify_option && access == ACCESS_WRITE && backup_option) + if (!verify_option && mode == ACCESS_WRITE && backup_option) undo_last_backup (); goto tryagain; }