1
- use std:: fs;
2
1
use std:: io;
3
2
use std:: path:: PathBuf ;
3
+ use thiserror:: Error ;
4
4
5
5
use wasmer:: { DeserializeError , Module , Store } ;
6
6
7
7
use crate :: checksum:: Checksum ;
8
8
use crate :: errors:: { VmError , VmResult } ;
9
9
10
+ use crate :: filesystem:: mkdir_p;
10
11
use crate :: modules:: current_wasmer_module_version;
11
12
12
13
/// Bump this version whenever the module system changes in a way
@@ -42,6 +43,20 @@ pub struct FileSystemCache {
42
43
wasmer_module_version : u32 ,
43
44
}
44
45
46
+ /// An error type that hides system specific error information
47
+ /// to ensure deterministic errors across operating systems.
48
+ #[ derive( Error , Debug ) ]
49
+ pub enum NewFileSystemCacheError {
50
+ #[ error( "Could not get metadata of cache path" ) ]
51
+ CouldntGetMetadata ,
52
+ #[ error( "The supplied path is readonly" ) ]
53
+ ReadonlyPath ,
54
+ #[ error( "The supplied path already exists but is no directory" ) ]
55
+ ExistsButNoDirectory ,
56
+ #[ error( "Could not create cache path" ) ]
57
+ CouldntCreatePath ,
58
+ }
59
+
45
60
impl FileSystemCache {
46
61
/// Construct a new `FileSystemCache` around the specified directory.
47
62
/// The contents of the cache are stored in sub-versioned directories.
@@ -50,38 +65,29 @@ impl FileSystemCache {
50
65
///
51
66
/// This method is unsafe because there's no way to ensure the artifacts
52
67
/// stored in this cache haven't been corrupted or tampered with.
53
- pub unsafe fn new ( path : impl Into < PathBuf > ) -> io :: Result < Self > {
68
+ pub unsafe fn new ( path : impl Into < PathBuf > ) -> Result < Self , NewFileSystemCacheError > {
54
69
let wasmer_module_version = current_wasmer_module_version ( ) ;
55
70
56
71
let path: PathBuf = path. into ( ) ;
57
72
if path. exists ( ) {
58
- let metadata = path. metadata ( ) ?;
73
+ let metadata = path
74
+ . metadata ( )
75
+ . map_err ( |_e| NewFileSystemCacheError :: CouldntGetMetadata ) ?;
59
76
if metadata. is_dir ( ) {
60
77
if !metadata. permissions ( ) . readonly ( ) {
61
78
Ok ( Self {
62
79
base_path : path,
63
80
wasmer_module_version,
64
81
} )
65
82
} else {
66
- // This directory is readonly.
67
- Err ( io:: Error :: new (
68
- io:: ErrorKind :: PermissionDenied ,
69
- format ! ( "the supplied path is readonly: {}" , path. display( ) ) ,
70
- ) )
83
+ Err ( NewFileSystemCacheError :: ReadonlyPath )
71
84
}
72
85
} else {
73
- // This path points to a file.
74
- Err ( io:: Error :: new (
75
- io:: ErrorKind :: PermissionDenied ,
76
- format ! (
77
- "the supplied path already points to a file: {}" ,
78
- path. display( )
79
- ) ,
80
- ) )
86
+ Err ( NewFileSystemCacheError :: ExistsButNoDirectory )
81
87
}
82
88
} else {
83
89
// Create the directory and any parent directories if they don't yet exist.
84
- fs :: create_dir_all ( & path) ?;
90
+ mkdir_p ( & path) . map_err ( |_e| NewFileSystemCacheError :: CouldntCreatePath ) ?;
85
91
Ok ( Self {
86
92
base_path : path,
87
93
wasmer_module_version,
@@ -115,8 +121,9 @@ impl FileSystemCache {
115
121
/// Stores a serialized module to the file system. Returns the size of the serialized module.
116
122
pub fn store ( & mut self , checksum : & Checksum , module : & Module ) -> VmResult < ( ) > {
117
123
let modules_dir = self . latest_modules_path ( ) ;
118
- fs:: create_dir_all ( & modules_dir)
119
- . map_err ( |e| VmError :: cache_err ( format ! ( "Error creating directory: {}" , e) ) ) ?;
124
+ mkdir_p ( & modules_dir)
125
+ . map_err ( |_e| VmError :: cache_err ( "Error creating modules directory" ) ) ?;
126
+
120
127
let filename = checksum. to_hex ( ) ;
121
128
let path = modules_dir. join ( filename) ;
122
129
module
@@ -137,6 +144,8 @@ impl FileSystemCache {
137
144
138
145
#[ cfg( test) ]
139
146
mod tests {
147
+ use std:: fs;
148
+
140
149
use super :: * ;
141
150
use crate :: size:: Size ;
142
151
use crate :: wasm_backend:: { compile, make_runtime_store} ;
0 commit comments