tape: add magic number to identify media catalog files

This commit is contained in:
Dietmar Maurer 2020-12-16 08:59:27 +01:00
parent 39478aa52c
commit 42298d5896

View File

@ -1,6 +1,7 @@
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fs::File; use std::fs::File;
use std::io::{Write, Read, BufReader}; use std::io::{Write, Read, BufReader, Seek, SeekFrom};
use std::os::unix::io::AsRawFd;
use std::path::Path; use std::path::Path;
use std::collections::HashMap; use std::collections::HashMap;
@ -25,6 +26,9 @@ use crate::{
tape::drive::MediaLabelInfo, tape::drive::MediaLabelInfo,
}; };
// openssl::sha::sha256(b"Proxmox Backup Media Catalog v1.0")[0..8]
pub const PROXMOX_BACKUP_MEDIA_CATALOG_MAGIC_1_0: [u8; 8] = [221, 29, 164, 1, 59, 69, 19, 40];
/// The Media Catalog /// The Media Catalog
/// ///
/// Stores what chunks and snapshots are stored on a specific media, /// Stores what chunks and snapshots are stored on a specific media,
@ -109,12 +113,9 @@ impl MediaCatalog {
.create(create) .create(create)
.open(&path)?; .open(&path)?;
use std::os::unix::io::AsRawFd;
let backup_user = crate::backup::backup_user()?; let backup_user = crate::backup::backup_user()?;
if let Err(err) = fchown(file.as_raw_fd(), Some(backup_user.uid), Some(backup_user.gid)) { fchown(file.as_raw_fd(), Some(backup_user.uid), Some(backup_user.gid))
bail!("fchown on media catalog {:?} failed - {}", path, err); .map_err(|err| format_err!("fchown failed - {}", err))?;
}
let mut me = Self { let mut me = Self {
uuid: uuid.clone(), uuid: uuid.clone(),
@ -127,7 +128,11 @@ impl MediaCatalog {
pending: Vec::new(), pending: Vec::new(),
}; };
me.load_catalog(&mut file)?; let found_magic_number = me.load_catalog(&mut file)?;
if !found_magic_number {
me.pending.extend(&PROXMOX_BACKUP_MEDIA_CATALOG_MAGIC_1_0);
}
if write { if write {
me.file = Some(file); me.file = Some(file);
@ -147,49 +152,53 @@ impl MediaCatalog {
log_to_stdout: bool, log_to_stdout: bool,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
Self::create_basedir(base_path)?;
let uuid = &label_info.label.uuid; let uuid = &label_info.label.uuid;
let mut tmp_path = base_path.to_owned(); let mut tmp_path = base_path.to_owned();
tmp_path.push(uuid.to_string()); tmp_path.push(uuid.to_string());
tmp_path.set_extension("tmp"); tmp_path.set_extension("tmp");
let file = std::fs::OpenOptions::new() let me = proxmox::try_block!({
.read(true)
.write(true)
.create(true)
.truncate(true)
.open(&tmp_path)?;
use std::os::unix::io::AsRawFd; Self::create_basedir(base_path)?;
let backup_user = crate::backup::backup_user()?; let file = std::fs::OpenOptions::new()
if let Err(err) = fchown(file.as_raw_fd(), Some(backup_user.uid), Some(backup_user.gid)) { .read(true)
bail!("fchown on media catalog {:?} failed - {}", tmp_path, err); .write(true)
} .create(true)
.truncate(true)
.open(&tmp_path)?;
let mut me = Self { let backup_user = crate::backup::backup_user()?;
uuid: uuid.clone(), fchown(file.as_raw_fd(), Some(backup_user.uid), Some(backup_user.gid))
file: Some(file), .map_err(|err| format_err!("fchown failed - {}", err))?;
log_to_stdout: false,
current_archive: None,
last_entry: None,
chunk_index: HashMap::new(),
snapshot_index: HashMap::new(),
pending: Vec::new(),
};
me.log_to_stdout = log_to_stdout; let mut me = Self {
uuid: uuid.clone(),
file: Some(file),
log_to_stdout: false,
current_archive: None,
last_entry: None,
chunk_index: HashMap::new(),
snapshot_index: HashMap::new(),
pending: Vec::new(),
};
me.register_label(&label_info.label_uuid, 0)?; me.log_to_stdout = log_to_stdout;
if let Some((_, ref content_uuid)) = label_info.media_set_label { me.register_label(&label_info.label_uuid, 0)?;
me.register_label(&content_uuid, 1)?;
}
me.commit()?; if let Some((_, ref content_uuid)) = label_info.media_set_label {
me.register_label(&content_uuid, 1)?;
}
me.pending.extend(&PROXMOX_BACKUP_MEDIA_CATALOG_MAGIC_1_0);
me.commit()?;
Ok(me)
}).map_err(|err: Error| {
format_err!("unable to create temporary media catalog {:?} - {}", tmp_path, err)
})?;
Ok(me) Ok(me)
} }
@ -525,11 +534,28 @@ impl MediaCatalog {
Ok(()) Ok(())
} }
fn load_catalog(&mut self, file: &mut File) -> Result<(), Error> { fn load_catalog(&mut self, file: &mut File) -> Result<bool, Error> {
let mut file = BufReader::new(file); let mut file = BufReader::new(file);
let mut found_magic_number = false;
loop { loop {
let pos = file.seek(SeekFrom::Current(0))?;
if pos == 0 { // read/check magic number
let mut magic = [0u8; 8];
match file.read_exact_or_eof(&mut magic) {
Ok(false) => { /* EOF */ break; }
Ok(true) => { /* OK */ }
Err(err) => bail!("read failed - {}", err),
}
if magic != PROXMOX_BACKUP_MEDIA_CATALOG_MAGIC_1_0 {
bail!("wrong magic number");
}
found_magic_number = true;
continue;
}
let mut entry_type = [0u8; 1]; let mut entry_type = [0u8; 1];
match file.read_exact_or_eof(&mut entry_type) { match file.read_exact_or_eof(&mut entry_type) {
Ok(false) => { /* EOF */ break; } Ok(false) => { /* EOF */ break; }
@ -597,7 +623,7 @@ impl MediaCatalog {
} }
Ok(()) Ok(found_magic_number)
} }
} }