tape: rust fmt

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Thomas Lamprecht
2022-04-10 17:49:03 +02:00
parent 429bc9d0a2
commit 4de1c42c20
29 changed files with 1183 additions and 1116 deletions

View File

@ -4,19 +4,9 @@ use std::io::Read;
use proxmox_sys::error::SysError;
use proxmox_uuid::Uuid;
use pbs_tape::{
PROXMOX_TAPE_BLOCK_SIZE,
TapeWrite, MediaContentHeader,
};
use pbs_tape::{MediaContentHeader, TapeWrite, PROXMOX_TAPE_BLOCK_SIZE};
use crate::{
tape::{
file_formats::{
PROXMOX_BACKUP_CATALOG_ARCHIVE_MAGIC_1_0,
CatalogArchiveHeader,
},
},
};
use crate::tape::file_formats::{CatalogArchiveHeader, PROXMOX_BACKUP_CATALOG_ARCHIVE_MAGIC_1_0};
/// Write a media catalog to the tape
///
@ -32,17 +22,20 @@ pub fn tape_write_catalog<'a>(
seq_nr: usize,
file: &mut File,
) -> Result<Option<Uuid>, std::io::Error> {
let archive_header = CatalogArchiveHeader {
uuid: uuid.clone(),
media_set_uuid: media_set_uuid.clone(),
seq_nr: seq_nr as u64,
};
let header_data = serde_json::to_string_pretty(&archive_header)?.as_bytes().to_vec();
let header_data = serde_json::to_string_pretty(&archive_header)?
.as_bytes()
.to_vec();
let header = MediaContentHeader::new(
PROXMOX_BACKUP_CATALOG_ARCHIVE_MAGIC_1_0, header_data.len() as u32);
PROXMOX_BACKUP_CATALOG_ARCHIVE_MAGIC_1_0,
header_data.len() as u32,
);
let content_uuid: Uuid = header.uuid.into();
let leom = writer.write_header(&header, &header_data)?;
@ -54,7 +47,6 @@ pub fn tape_write_catalog<'a>(
let mut file_copy_buffer = proxmox_io::vec::undefined(PROXMOX_TAPE_BLOCK_SIZE);
let result: Result<(), std::io::Error> = proxmox_lang::try_block!({
let file_size = file.metadata()?.len();
let mut remaining = file_size;
@ -71,7 +63,7 @@ pub fn tape_write_catalog<'a>(
}
Ok(())
});
match result {
Ok(()) => {
writer.finish(false)?;

View File

@ -7,16 +7,11 @@ use proxmox_io::ReadExt;
use proxmox_uuid::Uuid;
use pbs_datastore::DataBlob;
use pbs_tape::{
PROXMOX_TAPE_BLOCK_SIZE,
TapeWrite, MediaContentHeader,
};
use pbs_tape::{MediaContentHeader, TapeWrite, PROXMOX_TAPE_BLOCK_SIZE};
use crate::tape::file_formats::{
ChunkArchiveEntryHeader, ChunkArchiveHeader, PROXMOX_BACKUP_CHUNK_ARCHIVE_ENTRY_MAGIC_1_0,
PROXMOX_BACKUP_CHUNK_ARCHIVE_MAGIC_1_1,
PROXMOX_BACKUP_CHUNK_ARCHIVE_ENTRY_MAGIC_1_0,
ChunkArchiveHeader,
ChunkArchiveEntryHeader,
};
/// Writes chunk archives to tape.
@ -32,8 +27,7 @@ pub struct ChunkArchiveWriter<'a> {
close_on_leom: bool,
}
impl <'a> ChunkArchiveWriter<'a> {
impl<'a> ChunkArchiveWriter<'a> {
pub const MAGIC: [u8; 8] = PROXMOX_BACKUP_CHUNK_ARCHIVE_MAGIC_1_1;
/// Creates a new instance
@ -41,10 +35,13 @@ impl <'a> ChunkArchiveWriter<'a> {
mut writer: Box<dyn TapeWrite + 'a>,
store: &str,
close_on_leom: bool,
) -> Result<(Self,Uuid), Error> {
let archive_header = ChunkArchiveHeader { store: store.to_string() };
let header_data = serde_json::to_string_pretty(&archive_header)?.as_bytes().to_vec();
) -> Result<(Self, Uuid), Error> {
let archive_header = ChunkArchiveHeader {
store: store.to_string(),
};
let header_data = serde_json::to_string_pretty(&archive_header)?
.as_bytes()
.to_vec();
let header = MediaContentHeader::new(Self::MAGIC, header_data.len() as u32);
writer.write_header(&header, &header_data)?;
@ -69,8 +66,9 @@ impl <'a> ChunkArchiveWriter<'a> {
fn write_all(&mut self, data: &[u8]) -> Result<bool, std::io::Error> {
match self.writer {
Some(ref mut writer) => writer.write_all(data),
None => proxmox_lang::io_bail!(
"detected write after archive finished - internal error"),
None => {
proxmox_lang::io_bail!("detected write after archive finished - internal error")
}
}
}
@ -80,10 +78,9 @@ impl <'a> ChunkArchiveWriter<'a> {
/// In that case the archive only contains parts of the last chunk.
pub fn try_write_chunk(
&mut self,
digest: &[u8;32],
digest: &[u8; 32],
blob: &DataBlob,
) -> Result<bool, std::io::Error> {
if self.writer.is_none() {
return Ok(false);
}
@ -95,9 +92,11 @@ impl <'a> ChunkArchiveWriter<'a> {
};
let head = head.to_le();
let data = unsafe { std::slice::from_raw_parts(
&head as *const ChunkArchiveEntryHeader as *const u8,
std::mem::size_of::<ChunkArchiveEntryHeader>())
let data = unsafe {
std::slice::from_raw_parts(
&head as *const ChunkArchiveEntryHeader as *const u8,
std::mem::size_of::<ChunkArchiveEntryHeader>(),
)
};
self.write_all(data)?;
@ -150,8 +149,7 @@ pub struct ChunkArchiveDecoder<R> {
reader: R,
}
impl <R: Read> ChunkArchiveDecoder<R> {
impl<R: Read> ChunkArchiveDecoder<R> {
/// Creates a new instance
pub fn new(reader: R) -> Self {
Self { reader }
@ -163,8 +161,7 @@ impl <R: Read> ChunkArchiveDecoder<R> {
}
/// Returns the next chunk (if any).
pub fn next_chunk(&mut self) -> Result<Option<([u8;32], DataBlob)>, Error> {
pub fn next_chunk(&mut self) -> Result<Option<([u8; 32], DataBlob)>, Error> {
let mut header = ChunkArchiveEntryHeader {
magic: [0u8; 8],
digest: [0u8; 32],
@ -173,11 +170,12 @@ impl <R: Read> ChunkArchiveDecoder<R> {
let data = unsafe {
std::slice::from_raw_parts_mut(
(&mut header as *mut ChunkArchiveEntryHeader) as *mut u8,
std::mem::size_of::<ChunkArchiveEntryHeader>())
std::mem::size_of::<ChunkArchiveEntryHeader>(),
)
};
match self.reader.read_exact_or_eof(data) {
Ok(true) => {},
Ok(true) => {}
Ok(false) => {
// last chunk is allowed to be incomplete - simply report EOD
return Ok(None);
@ -189,7 +187,7 @@ impl <R: Read> ChunkArchiveDecoder<R> {
bail!("wrong magic number");
}
let raw_data = match self.reader.read_exact_allocated(header.size as usize) {
let raw_data = match self.reader.read_exact_allocated(header.size as usize) {
Ok(data) => data,
Err(err) if err.kind() == std::io::ErrorKind::UnexpectedEof => {
// last chunk is allowed to be incomplete - simply report EOD

View File

@ -37,7 +37,8 @@ pub const PROXMOX_BACKUP_CHUNK_ARCHIVE_MAGIC_1_0: [u8; 8] = [62, 173, 167, 95, 4
pub const PROXMOX_BACKUP_CHUNK_ARCHIVE_MAGIC_1_1: [u8; 8] = [109, 49, 99, 109, 215, 2, 131, 191];
// openssl::sha::sha256(b"Proxmox Backup Chunk Archive Entry v1.0")[0..8]
pub const PROXMOX_BACKUP_CHUNK_ARCHIVE_ENTRY_MAGIC_1_0: [u8; 8] = [72, 87, 109, 242, 222, 66, 143, 220];
pub const PROXMOX_BACKUP_CHUNK_ARCHIVE_ENTRY_MAGIC_1_0: [u8; 8] =
[72, 87, 109, 242, 222, 66, 143, 220];
// openssl::sha::sha256(b"Proxmox Backup Snapshot Archive v1.0")[0..8];
// only used in unreleased version - no longer supported
@ -46,9 +47,10 @@ pub const PROXMOX_BACKUP_SNAPSHOT_ARCHIVE_MAGIC_1_0: [u8; 8] = [9, 182, 2, 31, 1
pub const PROXMOX_BACKUP_SNAPSHOT_ARCHIVE_MAGIC_1_1: [u8; 8] = [218, 22, 21, 208, 17, 226, 154, 98];
// openssl::sha::sha256(b"Proxmox Backup Catalog Archive v1.0")[0..8];
pub const PROXMOX_BACKUP_CATALOG_ARCHIVE_MAGIC_1_0: [u8; 8] = [183, 207, 199, 37, 158, 153, 30, 115];
pub const PROXMOX_BACKUP_CATALOG_ARCHIVE_MAGIC_1_0: [u8; 8] =
[183, 207, 199, 37, 158, 153, 30, 115];
lazy_static::lazy_static!{
lazy_static::lazy_static! {
// Map content magic numbers to human readable names.
static ref PROXMOX_TAPE_CONTENT_NAME: HashMap<&'static [u8;8], &'static str> = {
let mut map = HashMap::new();
@ -65,10 +67,11 @@ lazy_static::lazy_static!{
/// Map content magic numbers to human readable names.
pub fn proxmox_tape_magic_to_text(magic: &[u8; 8]) -> Option<String> {
PROXMOX_TAPE_CONTENT_NAME.get(magic).map(|s| String::from(*s))
PROXMOX_TAPE_CONTENT_NAME
.get(magic)
.map(|s| String::from(*s))
}
#[derive(Deserialize, Serialize)]
/// Header for chunk archives
pub struct ChunkArchiveHeader {
@ -77,7 +80,7 @@ pub struct ChunkArchiveHeader {
}
#[derive(Endian)]
#[repr(C,packed)]
#[repr(C, packed)]
/// Header for data blobs inside a chunk archive
pub struct ChunkArchiveEntryHeader {
/// fixed value `PROXMOX_BACKUP_CHUNK_ARCHIVE_ENTRY_MAGIC_1_0`
@ -108,7 +111,7 @@ pub struct CatalogArchiveHeader {
pub seq_nr: u64,
}
#[derive(Serialize,Deserialize,Clone,Debug)]
#[derive(Serialize, Deserialize, Clone, Debug)]
/// Media Label
///
/// Media labels are used to uniquely identify a media. They are
@ -122,8 +125,7 @@ pub struct MediaLabel {
pub ctime: i64,
}
#[derive(Serialize,Deserialize,Clone,Debug)]
#[derive(Serialize, Deserialize, Clone, Debug)]
/// `MediaSet` Label
///
/// Used to uniquely identify a `MediaSet`. They are stored as second
@ -138,12 +140,11 @@ pub struct MediaSetLabel {
/// Creation time stamp
pub ctime: i64,
/// Encryption key finkerprint (if encryped)
#[serde(skip_serializing_if="Option::is_none")]
#[serde(skip_serializing_if = "Option::is_none")]
pub encryption_key_fingerprint: Option<Fingerprint>,
}
impl MediaSetLabel {
pub fn with_data(
pool: &str,
uuid: Uuid,
@ -160,4 +161,3 @@ impl MediaSetLabel {
}
}
}

View File

@ -1,33 +1,33 @@
use std::io::{Read};
use std::io::Read;
use anyhow::{bail, Error};
use proxmox_io::ReadExt;
use pbs_tape::{TapeRead, MediaContentHeader};
use pbs_tape::{MediaContentHeader, TapeRead};
/// Read multi volume data streams written by `MultiVolumeWriter`
///
/// Note: We do not use this feature currently.
pub struct MultiVolumeReader<'a> {
reader: Option<Box<dyn TapeRead + 'a>>,
next_reader_fn: Box<dyn 'a + FnMut() -> Result<Box<dyn TapeRead +'a>, Error>>,
next_reader_fn: Box<dyn 'a + FnMut() -> Result<Box<dyn TapeRead + 'a>, Error>>,
complete: bool,
header: MediaContentHeader,
}
impl <'a> MultiVolumeReader<'a> {
impl<'a> MultiVolumeReader<'a> {
/// Creates a new instance
pub fn new(
reader: Box<dyn TapeRead +'a>,
reader: Box<dyn TapeRead + 'a>,
header: MediaContentHeader,
next_reader_fn: Box<dyn 'a + FnMut() -> Result<Box<dyn TapeRead +'a>, Error>>,
next_reader_fn: Box<dyn 'a + FnMut() -> Result<Box<dyn TapeRead + 'a>, Error>>,
) -> Result<Self, Error> {
if header.part_number != 0 {
bail!("MultiVolumeReader::new - got wrong header part_number ({} != 0)",
header.part_number);
bail!(
"MultiVolumeReader::new - got wrong header part_number ({} != 0)",
header.part_number
);
}
Ok(Self {
@ -39,8 +39,7 @@ impl <'a> MultiVolumeReader<'a> {
}
}
impl <'a> Read for MultiVolumeReader<'a> {
impl<'a> Read for MultiVolumeReader<'a> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
if self.complete {
return Ok(0);
@ -57,43 +56,45 @@ impl <'a> Read for MultiVolumeReader<'a> {
if part_header.uuid != self.header.uuid {
proxmox_lang::io_bail!("got wrong part uuid");
}
if part_header.content_magic!= self.header.content_magic {
if part_header.content_magic != self.header.content_magic {
proxmox_lang::io_bail!("got wrong part content magic");
}
let expect_part_number = self.header.part_number + 1;
if part_header.part_number != expect_part_number {
proxmox_lang::io_bail!("got wrong part number ({} != {})",
part_header.part_number, expect_part_number);
proxmox_lang::io_bail!(
"got wrong part number ({} != {})",
part_header.part_number,
expect_part_number
);
}
self.header.part_number = expect_part_number;
Ok(())
}).map_err(|err| {
})
.map_err(|err| {
proxmox_lang::io_format_err!("multi-volume read content header failed: {}", err)
})?;
}
}
match self.reader {
None => unreachable!(),
Some(ref mut reader) => {
match reader.read(buf) {
Ok(0) => {
if reader.is_incomplete()? {
self.reader = None;
self.read(buf)
} else {
self.reader = None;
self.complete = true;
Ok(0)
}
Some(ref mut reader) => match reader.read(buf) {
Ok(0) => {
if reader.is_incomplete()? {
self.reader = None;
self.read(buf)
} else {
self.reader = None;
self.complete = true;
Ok(0)
}
Ok(n) => Ok(n),
Err(err) => Err(err)
}
}
Ok(n) => Ok(n),
Err(err) => Err(err),
},
}
}
}

View File

@ -2,14 +2,14 @@ use anyhow::Error;
use proxmox_uuid::Uuid;
use pbs_tape::{TapeWrite, MediaContentHeader};
use pbs_tape::{MediaContentHeader, TapeWrite};
/// Writes data streams using multiple volumes
///
/// Note: We do not use this feature currently.
pub struct MultiVolumeWriter<'a> {
writer: Option<Box<dyn TapeWrite + 'a>>,
next_writer_fn: Box<dyn 'a + FnMut() -> Result<Box<dyn TapeWrite +'a>, Error>>,
next_writer_fn: Box<dyn 'a + FnMut() -> Result<Box<dyn TapeWrite + 'a>, Error>>,
got_leom: bool,
finished: bool,
wrote_header: bool,
@ -18,16 +18,14 @@ pub struct MultiVolumeWriter<'a> {
bytes_written: usize, // does not include bytes from current writer
}
impl <'a> MultiVolumeWriter<'a> {
impl<'a> MultiVolumeWriter<'a> {
/// Creates a new instance
pub fn new(
writer: Box<dyn TapeWrite +'a>,
writer: Box<dyn TapeWrite + 'a>,
content_magic: [u8; 8],
header_data: Vec<u8>,
next_writer_fn: Box<dyn 'a + FnMut() -> Result<Box<dyn TapeWrite + 'a>, Error>>,
) -> Self {
let header = MediaContentHeader::new(content_magic, header_data.len() as u32);
Self {
@ -48,21 +46,21 @@ impl <'a> MultiVolumeWriter<'a> {
}
}
impl <'a> TapeWrite for MultiVolumeWriter<'a> {
impl<'a> TapeWrite for MultiVolumeWriter<'a> {
fn write_all(&mut self, buf: &[u8]) -> Result<bool, std::io::Error> {
if self.finished {
proxmox_lang::io_bail!("multi-volume writer already finished: internal error");
}
if self.got_leom {
if !self.wrote_header {
proxmox_lang::io_bail!("multi-volume writer: got LEOM before writing anything - internal error");
proxmox_lang::io_bail!(
"multi-volume writer: got LEOM before writing anything - internal error"
);
}
let mut writer = match self.writer.take() {
Some(writer) => writer,
None => proxmox_lang::io_bail!("multi-volume writer: no writer -internal error"),
None => proxmox_lang::io_bail!("multi-volume writer: no writer -internal error"),
};
self.bytes_written = writer.bytes_written();
writer.finish(true)?;
@ -72,10 +70,9 @@ impl <'a> TapeWrite for MultiVolumeWriter<'a> {
if self.header.part_number == u8::MAX {
proxmox_lang::io_bail!("multi-volume writer: too many parts");
}
self.writer = Some(
(self.next_writer_fn)()
.map_err(|err| proxmox_lang::io_format_err!("multi-volume get next volume failed: {}", err))?
);
self.writer = Some((self.next_writer_fn)().map_err(|err| {
proxmox_lang::io_format_err!("multi-volume get next volume failed: {}", err)
})?);
self.got_leom = false;
self.wrote_header = false;
self.header.part_number += 1;
@ -92,7 +89,9 @@ impl <'a> TapeWrite for MultiVolumeWriter<'a> {
}
};
if leom { self.got_leom = true; }
if leom {
self.got_leom = true;
}
Ok(false)
}
@ -108,12 +107,14 @@ impl <'a> TapeWrite for MultiVolumeWriter<'a> {
fn finish(&mut self, incomplete: bool) -> Result<bool, std::io::Error> {
if incomplete {
proxmox_lang::io_bail!(
"incomplete flag makes no sense for multi-volume stream: internal error");
"incomplete flag makes no sense for multi-volume stream: internal error"
);
}
match self.writer.take() {
None if self.finished => proxmox_lang::io_bail!(
"multi-volume writer already finished: internal error"),
None if self.finished => {
proxmox_lang::io_bail!("multi-volume writer already finished: internal error")
}
None => Ok(false),
Some(ref mut writer) => {
self.finished = true;
@ -129,5 +130,4 @@ impl <'a> TapeWrite for MultiVolumeWriter<'a> {
fn logical_end_of_media(&self) -> bool {
self.got_leom
}
}

View File

@ -5,17 +5,10 @@ use std::task::{Context, Poll};
use proxmox_sys::error::SysError;
use proxmox_uuid::Uuid;
use pbs_tape::{
PROXMOX_TAPE_BLOCK_SIZE,
TapeWrite, MediaContentHeader,
};
use pbs_datastore::SnapshotReader;
use pbs_tape::{MediaContentHeader, TapeWrite, PROXMOX_TAPE_BLOCK_SIZE};
use crate::tape::file_formats::{
PROXMOX_BACKUP_SNAPSHOT_ARCHIVE_MAGIC_1_1,
SnapshotArchiveHeader,
};
use crate::tape::file_formats::{SnapshotArchiveHeader, PROXMOX_BACKUP_SNAPSHOT_ARCHIVE_MAGIC_1_1};
/// Write a set of files as `pxar` archive to the tape
///
@ -29,17 +22,20 @@ pub fn tape_write_snapshot_archive<'a>(
writer: &mut (dyn TapeWrite + 'a),
snapshot_reader: &SnapshotReader,
) -> Result<Option<Uuid>, std::io::Error> {
let snapshot = snapshot_reader.snapshot().to_string();
let store = snapshot_reader.datastore_name().to_string();
let file_list = snapshot_reader.file_list();
let archive_header = SnapshotArchiveHeader { snapshot, store };
let header_data = serde_json::to_string_pretty(&archive_header)?.as_bytes().to_vec();
let header_data = serde_json::to_string_pretty(&archive_header)?
.as_bytes()
.to_vec();
let header = MediaContentHeader::new(
PROXMOX_BACKUP_SNAPSHOT_ARCHIVE_MAGIC_1_1, header_data.len() as u32);
PROXMOX_BACKUP_SNAPSHOT_ARCHIVE_MAGIC_1_1,
header_data.len() as u32,
);
let content_uuid = header.uuid.into();
let root_metadata = pxar::Metadata::dir_builder(0o0664).build();
@ -47,18 +43,20 @@ pub fn tape_write_snapshot_archive<'a>(
let mut file_copy_buffer = proxmox_io::vec::undefined(PROXMOX_TAPE_BLOCK_SIZE);
let result: Result<(), std::io::Error> = proxmox_lang::try_block!({
let leom = writer.write_header(&header, &header_data)?;
if leom {
return Err(std::io::Error::from_raw_os_error(nix::errno::Errno::ENOSPC as i32));
return Err(std::io::Error::from_raw_os_error(
nix::errno::Errno::ENOSPC as i32,
));
}
let mut encoder = pxar::encoder::sync::Encoder::new(PxarTapeWriter::new(writer), &root_metadata)?;
let mut encoder =
pxar::encoder::sync::Encoder::new(PxarTapeWriter::new(writer), &root_metadata)?;
for filename in file_list.iter() {
let mut file = snapshot_reader.open_file(filename)
.map_err(|err| proxmox_lang::io_format_err!("open file '{}' failed - {}", filename, err))?;
let mut file = snapshot_reader.open_file(filename).map_err(|err| {
proxmox_lang::io_format_err!("open file '{}' failed - {}", filename, err)
})?;
let metadata = file.metadata()?;
let file_size = metadata.len();
@ -77,7 +75,6 @@ pub fn tape_write_snapshot_archive<'a>(
}
out.write_all(&file_copy_buffer[..got])?;
remaining -= got as u64;
}
if remaining > 0 {
proxmox_lang::io_bail!("file '{}' shrunk while reading", filename);
@ -117,7 +114,6 @@ impl<'a, T: TapeWrite + ?Sized> PxarTapeWriter<'a, T> {
}
impl<'a, T: TapeWrite + ?Sized> pxar::encoder::SeqWrite for PxarTapeWriter<'a, T> {
fn poll_seq_write(
self: Pin<&mut Self>,
_cx: &mut Context,
@ -127,7 +123,9 @@ impl<'a, T: TapeWrite + ?Sized> pxar::encoder::SeqWrite for PxarTapeWriter<'a, T
Poll::Ready(match this.inner.write_all(buf) {
Ok(leom) => {
if leom {
Err(std::io::Error::from_raw_os_error(nix::errno::Errno::ENOSPC as i32))
Err(std::io::Error::from_raw_os_error(
nix::errno::Errno::ENOSPC as i32,
))
} else {
Ok(buf.len())
}