void verify_volume (void) { int status; #ifdef MTIOCTOP struct mtop t; int er; #endif if (!diff_buf) diff_init (); #ifdef MTIOCTOP t.mt_op = MTBSF; t.mt_count = 1; if (er = rmtioctl (archive, MTIOCTOP, (char *) &t), er < 0) { if (errno != EIO || (er = rmtioctl (archive, MTIOCTOP, (char *) &t), er < 0)) { #endif if (rmtlseek (archive, 0L, 0) != 0) { /* Lseek failed. Try a different method. */ WARN ((0, errno, _("Could not rewind archive file for verify"))); return; } #ifdef MTIOCTOP } } #endif ar_reading = 1; now_verifying = 1; fl_read (); while (1) { status = read_header (); if (status == 0) { unsigned n; n = 0; do { n++; status = read_header (); } while (status == 0); ERROR ((0, 0, _("VERIFY FAILURE: %d invalid header(s) detected"), n)); } if (status == 2 || status == EOF) break; diff_archive (); } ar_reading = 0; now_verifying = 0; }
/* Move archive descriptor by COUNT records worth. If COUNT is positive we move forward, else we move negative. If it's a tape, MTIOCTOP had better work. If it's something else, we try to seek on it. If we can't seek, we lose! */ static void move_archive (off_t count) { if (count == 0) return; #ifdef MTIOCTOP { struct mtop operation; if (count < 0 ? (operation.mt_op = MTBSR, operation.mt_count = -count, operation.mt_count == -count) : (operation.mt_op = MTFSR, operation.mt_count = count, operation.mt_count == count)) { if (0 <= rmtioctl (archive, MTIOCTOP, (char *) &operation)) return; if (errno == EIO && 0 <= rmtioctl (archive, MTIOCTOP, (char *) &operation)) return; } } #endif /* MTIOCTOP */ { off_t position0 = rmtlseek (archive, (off_t) 0, SEEK_CUR); off_t increment = record_size * (off_t) count; off_t position = position0 + increment; if (increment / count != record_size || (position < position0) != (increment < 0) || (position = position < 0 ? 0 : position, rmtlseek (archive, position, SEEK_SET) != position)) seek_error_details (archive_name_array[0], position); return; } }
static void move_archive (int count) { #ifdef MTIOCTOP { struct mtop operation; int status; if (count > 0) { operation.mt_op = MTFSR; operation.mt_count = count; } else { operation.mt_op = MTBSR; operation.mt_count = -count; } if (status = rmtioctl (archive, MTIOCTOP, (char *) &operation), status >= 0) return; if (errno == EIO) if (status = rmtioctl (archive, MTIOCTOP, (char *) &operation), status >= 0) return; } #endif /* MTIOCTOP */ { off_t position = rmtlseek (archive, 0L, 1); position += record_size * count; if (rmtlseek (archive, position, 0) != position) FATAL_ERROR ((0, 0, _("Could not re-position archive file"))); return; } }
void verify_volume (void) { if (!diff_buffer) diff_init (); /* Verifying an archive is meant to check if the physical media got it correctly, so try to defeat clever in-memory buffering pertaining to this particular media. On Linux, for example, the floppy drive would not even be accessed for the whole verification. The code was using fsync only when the ioctl is unavailable, but Marty Leisner says that the ioctl does not work when not preceded by fsync. So, until we know better, or maybe to please Marty, let's do it the unbelievable way :-). */ #if HAVE_FSYNC fsync (archive); #endif #ifdef FDFLUSH ioctl (archive, FDFLUSH); #endif #ifdef MTIOCTOP { struct mtop operation; int status; operation.mt_op = MTBSF; operation.mt_count = 1; if (status = rmtioctl (archive, MTIOCTOP, (char *) &operation), status < 0) { if (errno != EIO || (status = rmtioctl (archive, MTIOCTOP, (char *) &operation), status < 0)) { #endif if (rmtlseek (archive, 0L, 0) != 0) { /* Lseek failed. Try a different method. */ WARN ((0, errno, _("Could not rewind archive file for verify"))); return; } #ifdef MTIOCTOP } } } #endif access_mode = ACCESS_READ; now_verifying = 1; flush_read (); while (1) { enum read_header status = read_header (); if (status == HEADER_FAILURE) { int counter = 0; while (status == HEADER_FAILURE); { counter++; status = read_header (); } ERROR ((0, 0, _("VERIFY FAILURE: %d invalid header(s) detected"), counter)); } if (status == HEADER_ZERO_BLOCK || status == HEADER_END_OF_FILE) break; diff_archive (); } access_mode = ACCESS_WRITE; now_verifying = 0; }