diff --git a/Cargo.toml b/Cargo.toml index a3306ba1..79278c7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,4 +26,6 @@ lazy_static = "1.1.0" regex = "1.0.6" rust-crypto = "0.2.36" nix = "0.12.0" -shellwords = "1.0.0" \ No newline at end of file +shellwords = "1.0.0" +uuid = { version = "0.7", features = ["v4"] } + diff --git a/src/backup/image_index.rs b/src/backup/image_index.rs index ffd2f86a..623bd22b 100644 --- a/src/backup/image_index.rs +++ b/src/backup/image_index.rs @@ -2,9 +2,20 @@ use failure::*; use super::chunk_store::*; +use std::io::Write; use std::path::{Path, PathBuf}; use std::os::unix::io::AsRawFd; +use uuid::Uuid; +#[repr(C)] +pub struct ImageIndexHeader { + pub magic: [u8; 12], + pub version: u32, + pub uuid: [u8; 16], + pub ctime: i64, + pub size: u64, + reserved: [u8; 4048], // oversall size is one page (4096 bytes) +} // split image into fixed size chunks @@ -13,6 +24,8 @@ pub struct ImageIndex<'a> { chunk_size: usize, size: usize, index: *mut u8, + uuid: [u8; 16], + ctime: i64, } impl <'a> ImageIndex<'a> { @@ -23,15 +36,39 @@ impl <'a> ImageIndex<'a> { println!("FULLPATH: {:?} {}", full_path, size); let mut file = std::fs::OpenOptions::new() - .create_new(true) + //FIXME: use .create_new(true) + .create(true).truncate(true) .read(true) .write(true) .open(&full_path)?; let chunk_size = 64*1024; + + let header_size = std::mem::size_of::(); + + // todo: use static assertion when available in rust + if header_size != 4096 { panic!("got unexpected header size"); } + + let ctime = std::time::SystemTime::now().duration_since( + std::time::SystemTime::UNIX_EPOCH)?.as_secs() as i64; + + let uuid = Uuid::new_v4(); + + let mut buffer = vec![0u8; header_size]; + let header = unsafe { &mut * (buffer.as_ptr() as *mut ImageIndexHeader) }; + + header.magic = *b"PROXMOX-BIDX"; + header.version = u32::to_be(1); + header.ctime = i64::to_be(ctime); + header.size = u64::to_be(size as u64); + header.uuid = *uuid.as_bytes(); + + file.write_all(&buffer); + let index_size = ((size + chunk_size - 1)/chunk_size)*32; - nix::unistd::ftruncate(file.as_raw_fd(), index_size as i64)?; - println!("SIZES: {}", index_size); + nix::unistd::ftruncate(file.as_raw_fd(), (header_size + index_size) as i64)?; + + println!("SIZES: {} {}", index_size, header_size); let data = unsafe { nix::sys::mman::mmap( std::ptr::null_mut(), @@ -39,13 +76,16 @@ impl <'a> ImageIndex<'a> { nix::sys::mman::ProtFlags::PROT_READ | nix::sys::mman::ProtFlags::PROT_WRITE, nix::sys::mman::MapFlags::MAP_SHARED, file.as_raw_fd(), - 0) }? as *mut u8; + header_size as i64) }? as *mut u8; + Ok(Self { store, chunk_size, size, index: data, + ctime, + uuid: *uuid.as_bytes(), }) }