]> git.proxmox.com Git - proxmox-backup.git/blob - src/tape/file_formats/mod.rs
de43d6bcc9593c49978e6a4fe73e40c4685f2ffa
[proxmox-backup.git] / src / tape / file_formats / mod.rs
1 //! File format definitions and implementations for data written to
2 //! tapes
3
4 use std::collections::HashMap;
5
6 use endian_trait::Endian;
7 use serde::{Deserialize, Serialize};
8
9 use proxmox::tools::Uuid;
10
11 use pbs_api_types::Fingerprint;
12
13 mod chunk_archive;
14 pub use chunk_archive::*;
15
16 mod snapshot_archive;
17 pub use snapshot_archive::*;
18
19 mod catalog_archive;
20 pub use catalog_archive::*;
21
22 mod multi_volume_writer;
23 pub use multi_volume_writer::*;
24
25 mod multi_volume_reader;
26 pub use multi_volume_reader::*;
27
28 // openssl::sha::sha256(b"Proxmox Backup Tape Label v1.0")[0..8];
29 pub const PROXMOX_BACKUP_MEDIA_LABEL_MAGIC_1_0: [u8; 8] = [42, 5, 191, 60, 176, 48, 170, 57];
30 // openssl::sha::sha256(b"Proxmox Backup MediaSet Label v1.0")
31 pub const PROXMOX_BACKUP_MEDIA_SET_LABEL_MAGIC_1_0: [u8; 8] = [8, 96, 99, 249, 47, 151, 83, 216];
32
33 // openssl::sha::sha256(b"Proxmox Backup Chunk Archive v1.0")[0..8]
34 // only used in unreleased version - no longer supported
35 pub const PROXMOX_BACKUP_CHUNK_ARCHIVE_MAGIC_1_0: [u8; 8] = [62, 173, 167, 95, 49, 76, 6, 110];
36 // openssl::sha::sha256(b"Proxmox Backup Chunk Archive v1.1")[0..8]
37 pub const PROXMOX_BACKUP_CHUNK_ARCHIVE_MAGIC_1_1: [u8; 8] = [109, 49, 99, 109, 215, 2, 131, 191];
38
39 // openssl::sha::sha256(b"Proxmox Backup Chunk Archive Entry v1.0")[0..8]
40 pub const PROXMOX_BACKUP_CHUNK_ARCHIVE_ENTRY_MAGIC_1_0: [u8; 8] = [72, 87, 109, 242, 222, 66, 143, 220];
41
42 // openssl::sha::sha256(b"Proxmox Backup Snapshot Archive v1.0")[0..8];
43 // only used in unreleased version - no longer supported
44 pub const PROXMOX_BACKUP_SNAPSHOT_ARCHIVE_MAGIC_1_0: [u8; 8] = [9, 182, 2, 31, 125, 232, 114, 133];
45 // openssl::sha::sha256(b"Proxmox Backup Snapshot Archive v1.1")[0..8];
46 pub const PROXMOX_BACKUP_SNAPSHOT_ARCHIVE_MAGIC_1_1: [u8; 8] = [218, 22, 21, 208, 17, 226, 154, 98];
47
48 // openssl::sha::sha256(b"Proxmox Backup Catalog Archive v1.0")[0..8];
49 pub const PROXMOX_BACKUP_CATALOG_ARCHIVE_MAGIC_1_0: [u8; 8] = [183, 207, 199, 37, 158, 153, 30, 115];
50
51 lazy_static::lazy_static!{
52 // Map content magic numbers to human readable names.
53 static ref PROXMOX_TAPE_CONTENT_NAME: HashMap<&'static [u8;8], &'static str> = {
54 let mut map = HashMap::new();
55 map.insert(&PROXMOX_BACKUP_MEDIA_LABEL_MAGIC_1_0, "Proxmox Backup Tape Label v1.0");
56 map.insert(&PROXMOX_BACKUP_MEDIA_SET_LABEL_MAGIC_1_0, "Proxmox Backup MediaSet Label v1.0");
57 map.insert(&PROXMOX_BACKUP_CHUNK_ARCHIVE_MAGIC_1_0, "Proxmox Backup Chunk Archive v1.0");
58 map.insert(&PROXMOX_BACKUP_CHUNK_ARCHIVE_MAGIC_1_1, "Proxmox Backup Chunk Archive v1.1");
59 map.insert(&PROXMOX_BACKUP_SNAPSHOT_ARCHIVE_MAGIC_1_0, "Proxmox Backup Snapshot Archive v1.0");
60 map.insert(&PROXMOX_BACKUP_SNAPSHOT_ARCHIVE_MAGIC_1_1, "Proxmox Backup Snapshot Archive v1.1");
61 map.insert(&PROXMOX_BACKUP_CATALOG_ARCHIVE_MAGIC_1_0, "Proxmox Backup Catalog Archive v1.0");
62 map
63 };
64 }
65
66 /// Map content magic numbers to human readable names.
67 pub fn proxmox_tape_magic_to_text(magic: &[u8; 8]) -> Option<String> {
68 PROXMOX_TAPE_CONTENT_NAME.get(magic).map(|s| String::from(*s))
69 }
70
71
72 #[derive(Deserialize, Serialize)]
73 /// Header for chunk archives
74 pub struct ChunkArchiveHeader {
75 // Datastore name
76 pub store: String,
77 }
78
79 #[derive(Endian)]
80 #[repr(C,packed)]
81 /// Header for data blobs inside a chunk archive
82 pub struct ChunkArchiveEntryHeader {
83 /// fixed value `PROXMOX_BACKUP_CHUNK_ARCHIVE_ENTRY_MAGIC_1_0`
84 pub magic: [u8; 8],
85 /// Chunk digest
86 pub digest: [u8; 32],
87 /// Chunk size
88 pub size: u64,
89 }
90
91 #[derive(Deserialize, Serialize)]
92 /// Header for snapshot archives
93 pub struct SnapshotArchiveHeader {
94 /// Snapshot name
95 pub snapshot: String,
96 /// Datastore name
97 pub store: String,
98 }
99
100 #[derive(Deserialize, Serialize)]
101 /// Header for Catalog archives
102 pub struct CatalogArchiveHeader {
103 /// The uuid of the media the catalog is for
104 pub uuid: Uuid,
105 /// The media set uuid the catalog is for
106 pub media_set_uuid: Uuid,
107 /// Media sequence number
108 pub seq_nr: u64,
109 }
110
111 #[derive(Serialize,Deserialize,Clone,Debug)]
112 /// Media Label
113 ///
114 /// Media labels are used to uniquely identify a media. They are
115 /// stored as first file on the tape.
116 pub struct MediaLabel {
117 /// Unique ID
118 pub uuid: Uuid,
119 /// Media label text (or Barcode)
120 pub label_text: String,
121 /// Creation time stamp
122 pub ctime: i64,
123 }
124
125
126 #[derive(Serialize,Deserialize,Clone,Debug)]
127 /// `MediaSet` Label
128 ///
129 /// Used to uniquely identify a `MediaSet`. They are stored as second
130 /// file on the tape.
131 pub struct MediaSetLabel {
132 /// The associated `MediaPool`
133 pub pool: String,
134 /// Uuid. We use the all-zero Uuid to reseve an empty media for a specific pool
135 pub uuid: Uuid,
136 /// Media sequence number
137 pub seq_nr: u64,
138 /// Creation time stamp
139 pub ctime: i64,
140 /// Encryption key finkerprint (if encryped)
141 #[serde(skip_serializing_if="Option::is_none")]
142 pub encryption_key_fingerprint: Option<Fingerprint>,
143 }
144
145 impl MediaSetLabel {
146
147 pub fn with_data(
148 pool: &str,
149 uuid: Uuid,
150 seq_nr: u64,
151 ctime: i64,
152 encryption_key_fingerprint: Option<Fingerprint>,
153 ) -> Self {
154 Self {
155 pool: pool.to_string(),
156 uuid,
157 seq_nr,
158 ctime,
159 encryption_key_fingerprint,
160 }
161 }
162 }
163