tape: implement locate_file without LOCATE(10)
This commit is contained in:
parent
566b946f9b
commit
5d6379f8db
@ -36,6 +36,12 @@ pub const FILE_MARK_COUNT_SCHEMA: Schema =
|
|||||||
.maximum(i32::MAX as isize)
|
.maximum(i32::MAX as isize)
|
||||||
.schema();
|
.schema();
|
||||||
|
|
||||||
|
pub const FILE_MARK_POSITION_SCHEMA: Schema =
|
||||||
|
IntegerSchema::new("File mark position (0 is BOT).")
|
||||||
|
.minimum(0)
|
||||||
|
.maximum(i32::MAX as isize)
|
||||||
|
.schema();
|
||||||
|
|
||||||
pub const RECORD_COUNT_SCHEMA: Schema =
|
pub const RECORD_COUNT_SCHEMA: Schema =
|
||||||
IntegerSchema::new("Record count.")
|
IntegerSchema::new("Record count.")
|
||||||
.minimum(1)
|
.minimum(1)
|
||||||
@ -128,22 +134,18 @@ fn get_tape_handle(param: &Value) -> Result<LtoTapeHandle, Error> {
|
|||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
count: {
|
count: {
|
||||||
schema: FILE_MARK_COUNT_SCHEMA,
|
schema: FILE_MARK_POSITION_SCHEMA,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)]
|
)]
|
||||||
/// Position the tape at the beginning of the count file.
|
/// Position the tape at the beginning of the count file (after
|
||||||
///
|
/// filemark count)
|
||||||
/// Positioning is done by first rewinding the tape and then spacing
|
fn asf(count: u64, param: Value) -> Result<(), Error> {
|
||||||
/// forward over count file marks.
|
|
||||||
fn asf(count: usize, param: Value) -> Result<(), Error> {
|
|
||||||
|
|
||||||
let mut handle = get_tape_handle(¶m)?;
|
let mut handle = get_tape_handle(¶m)?;
|
||||||
|
|
||||||
handle.rewind()?;
|
handle.locate_file(count)?;
|
||||||
|
|
||||||
handle.forward_space_count_files(count)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ pub use sg_tape::*;
|
|||||||
use std::fs::{OpenOptions, File};
|
use std::fs::{OpenOptions, File};
|
||||||
use std::os::unix::fs::OpenOptionsExt;
|
use std::os::unix::fs::OpenOptionsExt;
|
||||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
use anyhow::{bail, format_err, Error};
|
use anyhow::{bail, format_err, Error};
|
||||||
use nix::fcntl::{fcntl, FcntlArg, OFlag};
|
use nix::fcntl::{fcntl, FcntlArg, OFlag};
|
||||||
@ -38,7 +38,6 @@ use crate::{
|
|||||||
MamAttribute,
|
MamAttribute,
|
||||||
LtoDriveAndMediaStatus,
|
LtoDriveAndMediaStatus,
|
||||||
LtoTapeDrive,
|
LtoTapeDrive,
|
||||||
TapeDensity,
|
|
||||||
},
|
},
|
||||||
tape::{
|
tape::{
|
||||||
TapeRead,
|
TapeRead,
|
||||||
@ -133,7 +132,7 @@ impl LtoTapeHandle {
|
|||||||
blocksize: drive_status.block_length,
|
blocksize: drive_status.block_length,
|
||||||
compression: drive_status.compression,
|
compression: drive_status.compression,
|
||||||
buffer_mode: drive_status.buffer_mode,
|
buffer_mode: drive_status.buffer_mode,
|
||||||
density: TapeDensity::try_from(drive_status.density_code)?,
|
density: drive_status.density_code.try_into()?,
|
||||||
alert_flags,
|
alert_flags,
|
||||||
write_protect: None,
|
write_protect: None,
|
||||||
file_number: None,
|
file_number: None,
|
||||||
@ -188,19 +187,47 @@ impl LtoTapeHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn forward_space_count_files(&mut self, count: usize) -> Result<(), Error> {
|
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> {
|
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> {
|
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> {
|
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> {
|
pub fn erase_media(&mut self, fast: bool) -> Result<(), Error> {
|
||||||
|
@ -257,28 +257,6 @@ impl SgTape {
|
|||||||
Ok(position.logical_file_id)
|
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)
|
/// Check if we are positioned after a filemark (or BOT)
|
||||||
pub fn check_filemark(&mut self) -> Result<bool, Error> {
|
pub fn check_filemark(&mut self) -> Result<bool, Error> {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user