1 use anyhow
::{bail, Error}
;
3 use crate::server
::WorkerTask
;
6 DataStore
, BackupGroup
, BackupDir
, BackupInfo
, IndexFile
,
7 ENCR_COMPR_BLOB_MAGIC_1_0
, ENCRYPTED_BLOB_MAGIC_1_0
,
8 FileInfo
, ArchiveType
, archive_type
,
11 fn verify_blob(datastore
: &DataStore
, backup_dir
: &BackupDir
, info
: &FileInfo
) -> Result
<(), Error
> {
13 let (blob
, raw_size
) = datastore
.load_blob(backup_dir
, &info
.filename
)?
;
15 let csum
= openssl
::sha
::sha256(blob
.raw_data());
16 if raw_size
!= info
.size
{
17 bail
!("wrong size ({} != {})", info
.size
, raw_size
);
20 if csum
!= info
.csum
{
21 bail
!("wrong index checksum");
26 let magic
= blob
.magic();
28 if magic
== &ENCR_COMPR_BLOB_MAGIC_1_0
|| magic
== &ENCRYPTED_BLOB_MAGIC_1_0
{
37 fn verify_fixed_index(datastore
: &DataStore
, backup_dir
: &BackupDir
, info
: &FileInfo
, worker
: &WorkerTask
) -> Result
<(), Error
> {
39 let mut path
= backup_dir
.relative_path();
40 path
.push(&info
.filename
);
42 let index
= datastore
.open_fixed_reader(&path
)?
;
44 let (csum
, size
) = index
.compute_csum();
45 if size
!= info
.size
{
46 bail
!("wrong size ({} != {})", info
.size
, size
);
49 if csum
!= info
.csum
{
50 bail
!("wrong index checksum");
53 for pos
in 0..index
.index_count() {
55 worker
.fail_on_abort()?
;
56 crate::tools
::fail_on_shutdown()?
;
58 let (start
, end
, digest
) = index
.chunk_info(pos
).unwrap();
59 let size
= end
- start
;
60 datastore
.verify_stored_chunk(&digest
, size
)?
;
66 fn verify_dynamic_index(datastore
: &DataStore
, backup_dir
: &BackupDir
, info
: &FileInfo
, worker
: &WorkerTask
) -> Result
<(), Error
> {
67 let mut path
= backup_dir
.relative_path();
68 path
.push(&info
.filename
);
70 let index
= datastore
.open_dynamic_reader(&path
)?
;
72 let (csum
, size
) = index
.compute_csum();
73 if size
!= info
.size
{
74 bail
!("wrong size ({} != {})", info
.size
, size
);
77 if csum
!= info
.csum
{
78 bail
!("wrong index checksum");
81 for pos
in 0..index
.index_count() {
83 worker
.fail_on_abort()?
;
84 crate::tools
::fail_on_shutdown()?
;
86 let chunk_info
= index
.chunk_info(pos
).unwrap();
87 let size
= chunk_info
.range
.end
- chunk_info
.range
.start
;
88 datastore
.verify_stored_chunk(&chunk_info
.digest
, size
)?
;
94 /// Verify a single backup snapshot
96 /// This checks all archives inside a backup snapshot.
97 /// Errors are logged to the worker log.
100 /// - Ok(true) if verify is successful
101 /// - Ok(false) if there were verification errors
102 /// - Err(_) if task was aborted
103 pub fn verify_backup_dir(datastore
: &DataStore
, backup_dir
: &BackupDir
, worker
: &WorkerTask
) -> Result
<bool
, Error
> {
105 let manifest
= match datastore
.load_manifest(&backup_dir
) {
106 Ok((manifest
, _
)) => manifest
,
108 worker
.log(format
!("verify {}:{} - manifest load error: {}", datastore
.name(), backup_dir
, err
));
113 worker
.log(format
!("verify {}:{}", datastore
.name(), backup_dir
));
115 let mut error_count
= 0;
117 for info
in manifest
.files() {
118 let result
= proxmox
::try_block
!({
119 worker
.log(format
!(" check {}", info
.filename
));
120 match archive_type(&info
.filename
)?
{
121 ArchiveType
::FixedIndex
=> verify_fixed_index(&datastore
, &backup_dir
, info
, worker
),
122 ArchiveType
::DynamicIndex
=> verify_dynamic_index(&datastore
, &backup_dir
, info
, worker
),
123 ArchiveType
::Blob
=> verify_blob(&datastore
, &backup_dir
, info
),
127 worker
.fail_on_abort()?
;
128 crate::tools
::fail_on_shutdown()?
;
130 if let Err(err
) = result
{
131 worker
.log(format
!("verify {}:{}/{} failed: {}", datastore
.name(), backup_dir
, info
.filename
, err
));
139 /// Verify all backups inside a backup group
141 /// Errors are logged to the worker log.
144 /// - Ok(true) if verify is successful
145 /// - Ok(false) if there were verification errors
146 /// - Err(_) if task was aborted
147 pub fn verify_backup_group(datastore
: &DataStore
, group
: &BackupGroup
, worker
: &WorkerTask
) -> Result
<bool
, Error
> {
149 let mut list
= match group
.list_backups(&datastore
.base_path()) {
152 worker
.log(format
!("verify group {}:{} - unable to list backups: {}", datastore
.name(), group
, err
));
157 worker
.log(format
!("verify group {}:{}", datastore
.name(), group
));
159 let mut error_count
= 0;
161 BackupInfo
::sort_list(&mut list
, false); // newest first
163 if !verify_backup_dir(datastore
, &info
.backup_dir
, worker
)?
{
171 /// Verify all backups inside a datastore
173 /// Errors are logged to the worker log.
176 /// - Ok(true) if verify is successful
177 /// - Ok(false) if there were verification errors
178 /// - Err(_) if task was aborted
179 pub fn verify_all_backups(datastore
: &DataStore
, worker
: &WorkerTask
) -> Result
<bool
, Error
> {
181 let list
= match BackupGroup
::list_groups(&datastore
.base_path()) {
184 worker
.log(format
!("verify datastore {} - unable to list backups: {}", datastore
.name(), err
));
189 worker
.log(format
!("verify datastore {}", datastore
.name()));
191 let mut error_count
= 0;
193 if !verify_backup_group(datastore
, &group
, worker
)?
{