]> git.proxmox.com Git - proxmox-backup.git/blame - src/backup/verify.rs
bump proxmox to 0.3, cleanup http_err macro usage
[proxmox-backup.git] / src / backup / verify.rs
CommitLineData
c2009e53
DM
1use anyhow::{bail, Error};
2
3use crate::server::WorkerTask;
4
5use super::{
6 DataStore, BackupGroup, BackupDir, BackupInfo, IndexFile,
7 ENCR_COMPR_BLOB_MAGIC_1_0, ENCRYPTED_BLOB_MAGIC_1_0,
8 FileInfo, ArchiveType, archive_type,
9};
10
11fn verify_blob(datastore: &DataStore, backup_dir: &BackupDir, info: &FileInfo) -> Result<(), Error> {
12
39f18b30 13 let blob = datastore.load_blob(backup_dir, &info.filename)?;
c2009e53 14
39f18b30 15 let raw_size = blob.raw_size();
c2009e53
DM
16 if raw_size != info.size {
17 bail!("wrong size ({} != {})", info.size, raw_size);
18 }
19
39f18b30 20 let csum = openssl::sha::sha256(blob.raw_data());
c2009e53
DM
21 if csum != info.csum {
22 bail!("wrong index checksum");
23 }
24
c2009e53
DM
25 let magic = blob.magic();
26
27 if magic == &ENCR_COMPR_BLOB_MAGIC_1_0 || magic == &ENCRYPTED_BLOB_MAGIC_1_0 {
28 return Ok(());
29 }
30
31 blob.decode(None)?;
32
33 Ok(())
34}
35
fdaab0df
DM
36fn verify_index_chunks(
37 datastore: &DataStore,
38 index: Box<dyn IndexFile>,
39 worker: &WorkerTask,
40) -> Result<(), Error> {
41
42 for pos in 0..index.index_count() {
43
44 worker.fail_on_abort()?;
fdaab0df
DM
45
46 let info = index.chunk_info(pos).unwrap();
47 let size = info.range.end - info.range.start;
48 datastore.verify_stored_chunk(&info.digest, size)?;
49 }
50
51 Ok(())
52}
53
8ea00f6e 54fn verify_fixed_index(datastore: &DataStore, backup_dir: &BackupDir, info: &FileInfo, worker: &WorkerTask) -> Result<(), Error> {
c2009e53
DM
55
56 let mut path = backup_dir.relative_path();
57 path.push(&info.filename);
58
59 let index = datastore.open_fixed_reader(&path)?;
60
61 let (csum, size) = index.compute_csum();
62 if size != info.size {
63 bail!("wrong size ({} != {})", info.size, size);
64 }
65
66 if csum != info.csum {
67 bail!("wrong index checksum");
68 }
69
fdaab0df 70 verify_index_chunks(datastore, Box::new(index), worker)
c2009e53
DM
71}
72
8ea00f6e 73fn verify_dynamic_index(datastore: &DataStore, backup_dir: &BackupDir, info: &FileInfo, worker: &WorkerTask) -> Result<(), Error> {
c2009e53
DM
74 let mut path = backup_dir.relative_path();
75 path.push(&info.filename);
76
77 let index = datastore.open_dynamic_reader(&path)?;
78
79 let (csum, size) = index.compute_csum();
80 if size != info.size {
81 bail!("wrong size ({} != {})", info.size, size);
82 }
83
84 if csum != info.csum {
85 bail!("wrong index checksum");
86 }
87
fdaab0df 88 verify_index_chunks(datastore, Box::new(index), worker)
c2009e53
DM
89}
90
91/// Verify a single backup snapshot
92///
93/// This checks all archives inside a backup snapshot.
94/// Errors are logged to the worker log.
95///
8ea00f6e
DM
96/// Returns
97/// - Ok(true) if verify is successful
98/// - Ok(false) if there were verification errors
99/// - Err(_) if task was aborted
100pub fn verify_backup_dir(datastore: &DataStore, backup_dir: &BackupDir, worker: &WorkerTask) -> Result<bool, Error> {
c2009e53
DM
101
102 let manifest = match datastore.load_manifest(&backup_dir) {
521a0acb 103 Ok((manifest, _crypt_mode, _)) => manifest,
c2009e53
DM
104 Err(err) => {
105 worker.log(format!("verify {}:{} - manifest load error: {}", datastore.name(), backup_dir, err));
8ea00f6e 106 return Ok(false);
c2009e53
DM
107 }
108 };
109
110 worker.log(format!("verify {}:{}", datastore.name(), backup_dir));
111
112 let mut error_count = 0;
113
114 for info in manifest.files() {
115 let result = proxmox::try_block!({
116 worker.log(format!(" check {}", info.filename));
117 match archive_type(&info.filename)? {
8ea00f6e
DM
118 ArchiveType::FixedIndex => verify_fixed_index(&datastore, &backup_dir, info, worker),
119 ArchiveType::DynamicIndex => verify_dynamic_index(&datastore, &backup_dir, info, worker),
c2009e53
DM
120 ArchiveType::Blob => verify_blob(&datastore, &backup_dir, info),
121 }
122 });
8ea00f6e
DM
123
124 worker.fail_on_abort()?;
8ea00f6e 125
c2009e53
DM
126 if let Err(err) = result {
127 worker.log(format!("verify {}:{}/{} failed: {}", datastore.name(), backup_dir, info.filename, err));
128 error_count += 1;
129 }
130 }
131
8ea00f6e 132 Ok(error_count == 0)
c2009e53
DM
133}
134
8ea00f6e
DM
135/// Verify all backups inside a backup group
136///
137/// Errors are logged to the worker log.
138///
139/// Returns
140/// - Ok(true) if verify is successful
141/// - Ok(false) if there were verification errors
142/// - Err(_) if task was aborted
143pub fn verify_backup_group(datastore: &DataStore, group: &BackupGroup, worker: &WorkerTask) -> Result<bool, Error> {
c2009e53
DM
144
145 let mut list = match group.list_backups(&datastore.base_path()) {
146 Ok(list) => list,
147 Err(err) => {
148 worker.log(format!("verify group {}:{} - unable to list backups: {}", datastore.name(), group, err));
8ea00f6e 149 return Ok(false);
c2009e53
DM
150 }
151 };
152
153 worker.log(format!("verify group {}:{}", datastore.name(), group));
154
155 let mut error_count = 0;
156
157 BackupInfo::sort_list(&mut list, false); // newest first
158 for info in list {
8ea00f6e 159 if !verify_backup_dir(datastore, &info.backup_dir, worker)? {
c2009e53
DM
160 error_count += 1;
161 }
162 }
163
8ea00f6e 164 Ok(error_count == 0)
c2009e53
DM
165}
166
8ea00f6e
DM
167/// Verify all backups inside a datastore
168///
169/// Errors are logged to the worker log.
170///
171/// Returns
172/// - Ok(true) if verify is successful
173/// - Ok(false) if there were verification errors
174/// - Err(_) if task was aborted
175pub fn verify_all_backups(datastore: &DataStore, worker: &WorkerTask) -> Result<bool, Error> {
c2009e53
DM
176
177 let list = match BackupGroup::list_groups(&datastore.base_path()) {
178 Ok(list) => list,
179 Err(err) => {
180 worker.log(format!("verify datastore {} - unable to list backups: {}", datastore.name(), err));
8ea00f6e 181 return Ok(false);
c2009e53
DM
182 }
183 };
184
185 worker.log(format!("verify datastore {}", datastore.name()));
186
187 let mut error_count = 0;
188 for group in list {
8ea00f6e 189 if !verify_backup_group(datastore, &group, worker)? {
c2009e53
DM
190 error_count += 1;
191 }
192 }
193
8ea00f6e 194 Ok(error_count == 0)
c2009e53 195}