tape: add file format definitions

This commit is contained in:
Dietmar Maurer 2020-12-05 10:45:08 +01:00
parent 327e93711f
commit 8c15560b68
3 changed files with 144 additions and 0 deletions

View File

@ -30,3 +30,5 @@ pub mod auth_helpers;
pub mod auth; pub mod auth;
pub mod rrd; pub mod rrd;
pub mod tape;

141
src/tape/file_formats.rs Normal file
View File

@ -0,0 +1,141 @@
use anyhow::{bail, Error};
use ::serde::{Deserialize, Serialize};
use endian_trait::Endian;
use bitflags::bitflags;
use proxmox::tools::Uuid;
/// We use 256KB blocksize (always)
pub const PROXMOX_TAPE_BLOCK_SIZE: usize = 256*1024;
// openssl::sha::sha256(b"Proxmox Tape Block Header v1.0")[0..8]
pub const PROXMOX_TAPE_BLOCK_HEADER_MAGIC_1_0: [u8; 8] = [220, 189, 175, 202, 235, 160, 165, 40];
// openssl::sha::sha256(b"Proxmox Backup Content Header v1.0")[0..8];
pub const PROXMOX_BACKUP_CONTENT_HEADER_MAGIC_1_0: [u8; 8] = [99, 238, 20, 159, 205, 242, 155, 12];
// openssl::sha::sha256(b"Proxmox Backup Tape Label v1.0")[0..8];
pub const PROXMOX_BACKUP_DRIVE_LABEL_MAGIC_1_0: [u8; 8] = [42, 5, 191, 60, 176, 48, 170, 57];
// openssl::sha::sha256(b"Proxmox Backup MediaSet Label v1.0")
pub const PROXMOX_BACKUP_MEDIA_SET_LABEL_MAGIC_1_0: [u8; 8] = [8, 96, 99, 249, 47, 151, 83, 216];
// openssl::sha::sha256(b"Proxmox Backup Chunk Archive v1.0")[0..8]
pub const PROXMOX_BACKUP_CHUNK_ARCHIVE_MAGIC_1_0: [u8; 8] = [62, 173, 167, 95, 49, 76, 6, 110];
// 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];
// openssl::sha::sha256(b"Proxmox Backup Snapshot Archive v1.0")[0..8];
pub const PROXMOX_BACKUP_SNAPSHOT_ARCHIVE_MAGIC_1_0: [u8; 8] = [9, 182, 2, 31, 125, 232, 114, 133];
/// Note: this struct is large, never put this on the stack!
/// so we use an unsized type to avoid that.
#[repr(C,packed)]
pub struct BlockHeader {
pub magic: [u8; 8],
pub flags: BlockHeaderFlags,
/// size as 3 bytes unsigned, little endian
pub size: [u8; 3],
/// block sequence number
pub seq_nr: u32,
pub payload: [u8],
}
bitflags! {
pub struct BlockHeaderFlags: u8 {
/// Marks the last block in a stream.
const END_OF_STREAM = 0b00000001;
/// Mark multivolume streams (when set in the last block)
const INCOMPLETE = 0b00000010;
}
}
#[derive(Endian)]
#[repr(C,packed)]
pub struct ChunkArchiveEntryHeader {
pub magic: [u8; 8],
pub digest: [u8; 32],
pub size: u64,
}
#[derive(Endian, Copy, Clone, Debug)]
#[repr(C,packed)]
pub struct MediaContentHeader {
pub magic: [u8; 8],
pub content_magic: [u8; 8],
pub uuid: [u8; 16],
pub ctime: i64,
pub size: u32,
pub part_number: u8,
pub reserved_0: u8,
pub reserved_1: u8,
pub reserved_2: u8,
}
impl MediaContentHeader {
pub fn new(content_magic: [u8; 8], size: u32) -> Self {
let uuid = *proxmox::tools::uuid::Uuid::generate()
.into_inner();
Self {
magic: PROXMOX_BACKUP_CONTENT_HEADER_MAGIC_1_0,
content_magic,
uuid,
ctime: proxmox::tools::time::epoch_i64(),
size,
part_number: 0,
reserved_0: 0,
reserved_1: 0,
reserved_2: 0,
}
}
pub fn check(&self, content_magic: [u8; 8], min_size: u32, max_size: u32) -> Result<(), Error> {
if self.magic != PROXMOX_BACKUP_CONTENT_HEADER_MAGIC_1_0 {
bail!("MediaContentHeader: wrong magic");
}
if self.content_magic != content_magic {
bail!("MediaContentHeader: wrong content magic");
}
if self.size < min_size || self.size > max_size {
bail!("MediaContentHeader: got unexpected size");
}
Ok(())
}
pub fn content_uuid(&self) -> Uuid {
Uuid::from(self.uuid)
}
}
#[derive(Serialize,Deserialize,Clone,Debug)]
pub struct DriveLabel {
/// Unique ID
pub uuid: Uuid,
/// Media Changer ID or Barcode
pub changer_id: String,
/// Creation time stamp
pub ctime: i64,
}
#[derive(Serialize,Deserialize,Clone,Debug)]
pub struct MediaSetLabel {
pub pool: String,
/// MediaSet Uuid. We use the all-zero Uuid to reseve an empty media for a specific pool
pub uuid: Uuid,
/// MediaSet media sequence number
pub seq_nr: u64,
/// Creation time stamp
pub ctime: i64,
}
impl MediaSetLabel {
pub fn with_data(pool: &str, uuid: Uuid, seq_nr: u64, ctime: i64) -> Self {
Self {
pool: pool.to_string(),
uuid,
seq_nr,
ctime,
}
}
}

1
src/tape/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod file_formats;