diff --git a/src/api2/tape/restore.rs b/src/api2/tape/restore.rs index afce3449..28757ab4 100644 --- a/src/api2/tape/restore.rs +++ b/src/api2/tape/restore.rs @@ -525,7 +525,7 @@ fn restore_archive<'a>( } } - reader.skip_to_end()?; // read all data + reader.skip_data()?; // read all data if let Ok(false) = reader.is_incomplete() { catalog.register_snapshot(Uuid::from(header.uuid), current_file_number, &datastore_name, &snapshot)?; catalog.commit_if_large()?; @@ -566,7 +566,7 @@ fn restore_archive<'a>( task_log!(worker, "skipping..."); } - reader.skip_to_end()?; // read all data + reader.skip_data()?; // read all data } PROXMOX_BACKUP_CATALOG_ARCHIVE_MAGIC_1_0 => { let header_data = reader.read_exact_allocated(header.size as usize)?; @@ -576,7 +576,7 @@ fn restore_archive<'a>( task_log!(worker, "File {}: skip catalog '{}'", current_file_number, archive_header.uuid); - reader.skip_to_end()?; // read all data + reader.skip_data()?; // read all data } _ => bail!("unknown content magic {:?}", header.content_magic), } @@ -849,7 +849,7 @@ pub fn fast_catalog_restore( if &archive_header.media_set_uuid != media_set.uuid() { task_log!(worker, "skipping unrelated catalog at pos {}", current_file_number); - reader.skip_to_end()?; // read all data + reader.skip_data()?; // read all data continue; } @@ -868,7 +868,7 @@ pub fn fast_catalog_restore( if !wanted { task_log!(worker, "skip catalog because media '{}' not inventarized", catalog_uuid); - reader.skip_to_end()?; // read all data + reader.skip_data()?; // read all data continue; } @@ -878,7 +878,7 @@ pub fn fast_catalog_restore( // only restore if catalog does not exist if MediaCatalog::exists(status_path, catalog_uuid) { task_log!(worker, "catalog for media '{}' already exists", catalog_uuid); - reader.skip_to_end()?; // read all data + reader.skip_data()?; // read all data continue; } } diff --git a/src/bin/proxmox-tape.rs b/src/bin/proxmox-tape.rs index 8eca5fcf..e1b87e35 100644 --- a/src/bin/proxmox-tape.rs +++ b/src/bin/proxmox-tape.rs @@ -622,8 +622,15 @@ fn debug_scan(mut param: Value) -> Result<(), Error> { println!("unable to read content header - {}", err); } } - let bytes = reader.skip_to_end()?; + let bytes = reader.skip_data()?; println!("skipped {}", HumanByte::from(bytes)); + if let Ok(true) = reader.has_end_marker() { + if reader.is_incomplete()? { + println!("WARNING: file is incomplete"); + } + } else { + println!("WARNING: file without end marker"); + } } } } diff --git a/src/tape/file_formats/blocked_reader.rs b/src/tape/file_formats/blocked_reader.rs index 1689d250..ce2fc9aa 100644 --- a/src/tape/file_formats/blocked_reader.rs +++ b/src/tape/file_formats/blocked_reader.rs @@ -129,14 +129,14 @@ impl BlockedReader { } } - fn read_block(&mut self) -> Result { + fn read_block(&mut self, check_end_marker: bool) -> Result { match Self::read_block_frame(&mut self.buffer, &mut self.reader) { Ok(()) => { /* ok */ } Err(BlockReadError::EndOfFile) => { self.got_eod = true; self.read_pos = self.buffer.payload.len(); - if !self.found_end_marker { + if !self.found_end_marker && check_end_marker { proxmox::io_bail!("detected tape stream without end marker"); } return Ok(0); // EOD @@ -185,6 +185,23 @@ impl TapeRead for BlockedReader { Ok(self.found_end_marker) } + + // like ReadExt::skip_to_end(), but does not raise an error if the + // stream has no end marker. + fn skip_data(&mut self) -> Result { + let mut bytes = 0; + let buffer_size = self.buffer.size(); + let rest = (buffer_size as isize) - (self.read_pos as isize); + if rest > 0 { + bytes = rest as usize; + } + loop { + if self.got_eod { + return Ok(bytes); + } + bytes += self.read_block(false)?; + } + } } impl Read for BlockedReader { @@ -199,7 +216,7 @@ impl Read for BlockedReader { let mut rest = (buffer_size as isize) - (self.read_pos as isize); if rest <= 0 && !self.got_eod { // try to refill buffer - buffer_size = match self.read_block() { + buffer_size = match self.read_block(true) { Ok(len) => len, err => { self.read_error = true; diff --git a/src/tape/tape_read.rs b/src/tape/tape_read.rs index c617ec61..8142081c 100644 --- a/src/tape/tape_read.rs +++ b/src/tape/tape_read.rs @@ -13,6 +13,12 @@ pub trait TapeRead: Read { /// /// Raises an error if you query this flag before reaching EOF. fn has_end_marker(&self) -> Result; + + /// Skip data by reading to EOF (position after EOF marker) + /// + // Returns the number of bytes skipped. This does not raise an + // error if the stream has no end marker. + fn skip_data(&mut self) -> Result; } #[derive(thiserror::Error, Debug)]