@@ -2,11 +2,11 @@ use flate2::Compression;
2
2
use flate2:: { read:: GzDecoder , write:: GzEncoder } ;
3
3
use mithril_common:: StdResult ;
4
4
use slog_scope:: { info, warn} ;
5
- use std:: fs:: File ;
6
- use std:: io:: { self , Seek , SeekFrom } ;
5
+ use std:: fs:: { self , File } ;
6
+ use std:: io:: { self , Read , Seek , SeekFrom } ;
7
7
use std:: path:: { Path , PathBuf } ;
8
8
use std:: sync:: RwLock ;
9
- use tar:: Archive ;
9
+ use tar:: { Archive , Entry , EntryType } ;
10
10
use thiserror:: Error ;
11
11
12
12
use crate :: dependency_injection:: DependenciesBuilderError ;
@@ -57,6 +57,10 @@ pub enum SnapshotError {
57
57
#[ error( "Invalid archive error: {0}" ) ]
58
58
InvalidArchiveError ( String ) ,
59
59
60
+ /// Set when the snapshotter fails verifying a snapshot.
61
+ #[ error( "Archive verification error: {0}" ) ]
62
+ VerifyArchiveError ( String ) ,
63
+
60
64
/// Set when the snapshotter fails at uploading the snapshot.
61
65
#[ error( "Upload file error: `{0}`" ) ]
62
66
UploadFileError ( String ) ,
@@ -165,12 +169,56 @@ impl GzipSnapshotter {
165
169
let snapshot_file_tar = GzDecoder :: new ( snapshot_file_tar_gz) ;
166
170
let mut snapshot_archive = Archive :: new ( snapshot_file_tar) ;
167
171
168
- match snapshot_archive. entries ( ) ?. find ( |e| e. is_err ( ) ) {
169
- Some ( Err ( e) ) => Err ( SnapshotError :: InvalidArchiveError ( format ! (
170
- "invalid entry with error: '{e:?}'"
171
- ) ) ) ,
172
- _ => Ok ( ( ) ) ,
172
+ let unpack_temp_dir = std:: env:: temp_dir ( ) . join ( "mithril_snapshotter_verify_archive" ) ;
173
+ if unpack_temp_dir. exists ( ) {
174
+ fs:: remove_dir_all ( & unpack_temp_dir)
175
+ . map_err ( |e| SnapshotError :: VerifyArchiveError ( e. to_string ( ) ) ) ?;
176
+ }
177
+ fs:: create_dir_all ( & unpack_temp_dir)
178
+ . map_err ( |e| SnapshotError :: VerifyArchiveError ( e. to_string ( ) ) ) ?;
179
+ let unpack_temp_file = & unpack_temp_dir. join ( "unpack.tmp" ) ;
180
+
181
+ for e in snapshot_archive. entries ( ) ? {
182
+ match e {
183
+ Err ( e) => {
184
+ return Err ( SnapshotError :: InvalidArchiveError ( format ! (
185
+ "invalid entry with error: '{:?}'" ,
186
+ e
187
+ ) ) )
188
+ }
189
+ Ok ( entry) => Self :: unpack_and_delete_file_from_entry ( entry, unpack_temp_file) ?,
190
+ }
191
+ }
192
+
193
+ Ok ( ( ) )
194
+ }
195
+
196
+ // Helper to unpack and delete a file from en entry, for archive verification purpose
197
+ fn unpack_and_delete_file_from_entry < R : Read > (
198
+ entry : Entry < R > ,
199
+ unpack_file_path : & Path ,
200
+ ) -> Result < ( ) , SnapshotError > {
201
+ if entry. header ( ) . entry_type ( ) != EntryType :: Directory {
202
+ let mut file = entry;
203
+ match file. unpack ( unpack_file_path) {
204
+ Err ( e) => {
205
+ return Err ( SnapshotError :: InvalidArchiveError ( format ! (
206
+ "can't unpack entry with error: '{:?}'" ,
207
+ e
208
+ ) ) )
209
+ }
210
+ Ok ( _) => {
211
+ if let Err ( e) = fs:: remove_file ( unpack_file_path) {
212
+ return Err ( SnapshotError :: VerifyArchiveError ( format ! (
213
+ "can't remove temporary unpacked file with error: '{:?}'" ,
214
+ e
215
+ ) ) ) ;
216
+ }
217
+ }
218
+ }
173
219
}
220
+
221
+ Ok ( ( ) )
174
222
}
175
223
}
176
224
0 commit comments