tape: implement locate_file without LOCATE(10)
This commit is contained in:
		| @ -17,7 +17,7 @@ pub use sg_tape::*; | ||||
| use std::fs::{OpenOptions, File}; | ||||
| use std::os::unix::fs::OpenOptionsExt; | ||||
| use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; | ||||
| use std::convert::TryFrom; | ||||
| use std::convert::TryInto; | ||||
|  | ||||
| use anyhow::{bail, format_err, Error}; | ||||
| use nix::fcntl::{fcntl, FcntlArg, OFlag}; | ||||
| @ -38,7 +38,6 @@ use crate::{ | ||||
|         MamAttribute, | ||||
|         LtoDriveAndMediaStatus, | ||||
|         LtoTapeDrive, | ||||
|         TapeDensity, | ||||
|     }, | ||||
|     tape::{ | ||||
|         TapeRead, | ||||
| @ -133,7 +132,7 @@ impl LtoTapeHandle { | ||||
|             blocksize: drive_status.block_length, | ||||
|             compression: drive_status.compression, | ||||
|             buffer_mode: drive_status.buffer_mode, | ||||
|             density: TapeDensity::try_from(drive_status.density_code)?, | ||||
|             density: drive_status.density_code.try_into()?, | ||||
|             alert_flags, | ||||
|             write_protect: None, | ||||
|             file_number: None, | ||||
| @ -188,19 +187,47 @@ impl LtoTapeHandle { | ||||
|     } | ||||
|  | ||||
|     pub fn forward_space_count_files(&mut self, count: usize) -> Result<(), Error> { | ||||
|         self.sg_tape.space_filemarks(isize::try_from(count)?) | ||||
|         self.sg_tape.space_filemarks(count.try_into()?) | ||||
|     } | ||||
|  | ||||
|     pub fn backward_space_count_files(&mut self, count: usize) -> Result<(), Error> { | ||||
|         self.sg_tape.space_filemarks(-isize::try_from(count)?) | ||||
|         self.sg_tape.space_filemarks(-count.try_into()?) | ||||
|     } | ||||
|  | ||||
|     pub fn forward_space_count_records(&mut self, count: usize) -> Result<(), Error> { | ||||
|         self.sg_tape.space_blocks(isize::try_from(count)?) | ||||
|         self.sg_tape.space_blocks(count.try_into()?) | ||||
|     } | ||||
|  | ||||
|     pub fn backward_space_count_records(&mut self, count: usize) -> Result<(), Error> { | ||||
|         self.sg_tape.space_blocks(-isize::try_from(count)?) | ||||
|         self.sg_tape.space_blocks(-count.try_into()?) | ||||
|     } | ||||
|  | ||||
|     /// Position the tape after filemark count. Count 0 means BOT. | ||||
|     /// | ||||
|     /// Note: we dont use LOCATE(10), because that needs LTO5 | ||||
|     pub fn locate_file(&mut self, position: u64) ->  Result<(), Error> { | ||||
|  | ||||
|         if position == 0 { | ||||
|             return self.rewind(); | ||||
|         } | ||||
|  | ||||
|         let current_position = self.current_file_number()?; | ||||
|  | ||||
|         if current_position == position { | ||||
|             // make sure we are immediated afer the filemark | ||||
|             self.sg_tape.space_filemarks(-1)?; | ||||
|             self.sg_tape.space_filemarks(1)?; | ||||
|         } else if current_position < position { | ||||
|             let diff = position - current_position; | ||||
|             self.sg_tape.space_filemarks(diff.try_into()?)?; | ||||
|         } else { | ||||
|             let diff = current_position - position + 1; | ||||
|             self.sg_tape.space_filemarks(-diff.try_into()?)?; | ||||
|             // move to EOT side of filemark | ||||
|             self.sg_tape.space_filemarks(1)?; | ||||
|         } | ||||
|  | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     pub fn erase_media(&mut self, fast: bool) -> Result<(), Error> { | ||||
|  | ||||
| @ -257,28 +257,6 @@ impl SgTape { | ||||
|         Ok(position.logical_file_id) | ||||
|     } | ||||
|  | ||||
|     // fixme: dont use - needs LTO5 | ||||
|     pub fn locate_file(&mut self, position: u64) ->  Result<(), Error> { | ||||
|         let mut sg_raw = SgRaw::new(&mut self.file, 16)?; | ||||
|         sg_raw.set_timeout(Self::SCSI_TAPE_DEFAULT_TIMEOUT); | ||||
|         let mut cmd = Vec::new(); | ||||
|         cmd.extend(&[0x92, 0b000_01_000, 0, 0]); // LOCATE(16) filemarks | ||||
|         cmd.extend(&position.to_be_bytes()); | ||||
|         cmd.extend(&[0, 0, 0, 0]); | ||||
|  | ||||
|         sg_raw.do_command(&cmd) | ||||
|             .map_err(|err| format_err!("locate file {} failed - {}", position, err))?; | ||||
|  | ||||
|         // move to other side of filemark | ||||
|         cmd.truncate(0); | ||||
|         cmd.extend(&[0x11, 0x01, 0, 0, 1, 0]); // SPACE(6) one filemarks | ||||
|  | ||||
|         sg_raw.do_command(&cmd) | ||||
|             .map_err(|err| format_err!("locate file {} (space) failed - {}", position, err))?; | ||||
|  | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     /// Check if we are positioned after a filemark (or BOT) | ||||
|     pub fn check_filemark(&mut self) -> Result<bool, Error> { | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user