@@ -7,28 +7,149 @@ use generational_arena::{Arena, Index as Inode};
7
7
use hashbrown:: hash_map:: { Entry , HashMap } ;
8
8
use std:: {
9
9
cell:: Cell ,
10
- io:: { self , Write } ,
10
+ fs,
11
+ io:: { self , Read , Seek , Write } ,
11
12
time:: SystemTime ,
12
13
} ;
13
14
use wasmer_runtime_core:: debug;
14
- use zbox:: { init_env as zbox_init_env, File , FileType , OpenOptions , Repo , RepoOpener } ;
15
+ use zbox:: { init_env as zbox_init_env, FileType , OpenOptions , Repo , RepoOpener } ;
15
16
16
17
pub const MAX_SYMLINKS : usize = 100 ;
17
18
19
+ #[ derive( Debug ) ]
20
+ pub enum WasiFile {
21
+ ZboxFile ( zbox:: File ) ,
22
+ HostFile ( fs:: File ) ,
23
+ }
24
+
25
+ impl Write for WasiFile {
26
+ fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
27
+ match self {
28
+ WasiFile :: ZboxFile ( zbf) => zbf. write ( buf) ,
29
+ WasiFile :: HostFile ( hf) => hf. write ( buf) ,
30
+ }
31
+ }
32
+
33
+ fn flush ( & mut self ) -> io:: Result < ( ) > {
34
+ match self {
35
+ WasiFile :: ZboxFile ( zbf) => zbf. flush ( ) ,
36
+ WasiFile :: HostFile ( hf) => hf. flush ( ) ,
37
+ }
38
+ }
39
+
40
+ fn write_all ( & mut self , buf : & [ u8 ] ) -> io:: Result < ( ) > {
41
+ match self {
42
+ WasiFile :: ZboxFile ( zbf) => zbf. write_all ( buf) ,
43
+ WasiFile :: HostFile ( hf) => hf. write_all ( buf) ,
44
+ }
45
+ }
46
+
47
+ fn write_fmt ( & mut self , fmt : :: std:: fmt:: Arguments ) -> io:: Result < ( ) > {
48
+ match self {
49
+ WasiFile :: ZboxFile ( zbf) => zbf. write_fmt ( fmt) ,
50
+ WasiFile :: HostFile ( hf) => hf. write_fmt ( fmt) ,
51
+ }
52
+ }
53
+ }
54
+
55
+ impl Read for WasiFile {
56
+ fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
57
+ match self {
58
+ WasiFile :: ZboxFile ( zbf) => zbf. read ( buf) ,
59
+ WasiFile :: HostFile ( hf) => hf. read ( buf) ,
60
+ }
61
+ }
62
+
63
+ fn read_to_end ( & mut self , buf : & mut Vec < u8 > ) -> io:: Result < usize > {
64
+ match self {
65
+ WasiFile :: ZboxFile ( zbf) => zbf. read_to_end ( buf) ,
66
+ WasiFile :: HostFile ( hf) => hf. read_to_end ( buf) ,
67
+ }
68
+ }
69
+
70
+ fn read_to_string ( & mut self , buf : & mut String ) -> io:: Result < usize > {
71
+ match self {
72
+ WasiFile :: ZboxFile ( zbf) => zbf. read_to_string ( buf) ,
73
+ WasiFile :: HostFile ( hf) => hf. read_to_string ( buf) ,
74
+ }
75
+ }
76
+
77
+ fn read_exact ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < ( ) > {
78
+ match self {
79
+ WasiFile :: ZboxFile ( zbf) => zbf. read_exact ( buf) ,
80
+ WasiFile :: HostFile ( hf) => hf. read_exact ( buf) ,
81
+ }
82
+ }
83
+ }
84
+
85
+ impl Seek for WasiFile {
86
+ fn seek ( & mut self , pos : io:: SeekFrom ) -> io:: Result < u64 > {
87
+ match self {
88
+ WasiFile :: ZboxFile ( zbf) => zbf. seek ( pos) ,
89
+ WasiFile :: HostFile ( hf) => hf. seek ( pos) ,
90
+ }
91
+ }
92
+ }
93
+
94
+ #[ derive( Debug ) ]
18
95
pub struct InodeVal {
19
96
pub stat : __wasi_filestat_t ,
20
97
pub is_preopened : bool ,
21
98
pub name : String ,
22
99
pub kind : Kind ,
23
100
}
24
101
102
+ impl InodeVal {
103
+ // TODO: clean this up
104
+ pub fn from_file_metadata (
105
+ metadata : & std:: fs:: Metadata ,
106
+ name : String ,
107
+ is_preopened : bool ,
108
+ kind : Kind ,
109
+ ) -> Self {
110
+ InodeVal {
111
+ stat : __wasi_filestat_t {
112
+ st_filetype : if metadata. is_dir ( ) {
113
+ __WASI_FILETYPE_DIRECTORY
114
+ } else {
115
+ __WASI_FILETYPE_REGULAR_FILE
116
+ } ,
117
+ st_size : metadata. len ( ) ,
118
+ st_atim : metadata
119
+ . accessed ( )
120
+ . ok ( )
121
+ . and_then ( |sys_time| sys_time. duration_since ( SystemTime :: UNIX_EPOCH ) . ok ( ) )
122
+ . map ( |duration| duration. as_nanos ( ) as u64 )
123
+ . unwrap_or ( 0 ) ,
124
+ st_ctim : metadata
125
+ . created ( )
126
+ . ok ( )
127
+ . and_then ( |sys_time| sys_time. duration_since ( SystemTime :: UNIX_EPOCH ) . ok ( ) )
128
+ . map ( |duration| duration. as_nanos ( ) as u64 )
129
+ . unwrap_or ( 0 ) ,
130
+ st_mtim : metadata
131
+ . modified ( )
132
+ . ok ( )
133
+ . and_then ( |sys_time| sys_time. duration_since ( SystemTime :: UNIX_EPOCH ) . ok ( ) )
134
+ . map ( |duration| duration. as_nanos ( ) as u64 )
135
+ . unwrap_or ( 0 ) ,
136
+ ..__wasi_filestat_t:: default ( )
137
+ } ,
138
+ is_preopened,
139
+ name,
140
+ kind,
141
+ }
142
+ }
143
+ }
144
+
25
145
#[ allow( dead_code) ]
146
+ #[ derive( Debug ) ]
26
147
pub enum Kind {
27
148
File {
28
- handle : File ,
149
+ handle : WasiFile ,
29
150
} ,
30
151
Dir {
31
- handle : File ,
152
+ handle : WasiFile ,
32
153
/// The entries of a directory are lazily filled.
33
154
entries : HashMap < String , Inode > ,
34
155
} ,
@@ -40,7 +161,7 @@ pub enum Kind {
40
161
} ,
41
162
}
42
163
43
- #[ derive( Clone ) ]
164
+ #[ derive( Clone , Debug ) ]
44
165
pub struct Fd {
45
166
pub rights : __wasi_rights_t ,
46
167
pub rights_inheriting : __wasi_rights_t ,
@@ -50,7 +171,7 @@ pub struct Fd {
50
171
}
51
172
52
173
pub struct WasiFs {
53
- // pub repo: Repo,
174
+ //pub repo: Repo,
54
175
pub name_map : HashMap < String , Inode > ,
55
176
pub inodes : Arena < InodeVal > ,
56
177
pub fd_map : HashMap < u32 , Fd > ,
@@ -59,26 +180,56 @@ pub struct WasiFs {
59
180
}
60
181
61
182
impl WasiFs {
62
- pub fn new ( ) -> Result < Self , String > {
183
+ pub fn new ( preopened_files : & [ String ] ) -> Result < Self , String > {
63
184
debug ! ( "wasi::fs::init" ) ;
64
185
zbox_init_env ( ) ;
65
186
debug ! ( "wasi::fs::repo" ) ;
66
- // let repo = RepoOpener::new()
67
- // .create(true)
68
- // .open("mem://wasmer-test-fs", "")
69
- // .map_err(|e| e.to_string())?;
187
+ /* let repo = RepoOpener::new()
188
+ .create(true)
189
+ .open("mem://wasmer-test-fs", "")
190
+ .map_err(|e| e.to_string())?;*/
70
191
debug ! ( "wasi::fs::inodes" ) ;
71
192
let inodes = Arena :: new ( ) ;
72
- let res = Ok ( Self {
73
- // repo: repo,
193
+ let mut wasi_fs = Self {
194
+ //repo: repo,
74
195
name_map : HashMap :: new ( ) ,
75
196
inodes : inodes,
76
197
fd_map : HashMap :: new ( ) ,
77
198
next_fd : Cell :: new ( 3 ) ,
78
199
inode_counter : Cell :: new ( 1000 ) ,
79
- } ) ;
200
+ } ;
201
+ for file in preopened_files {
202
+ debug ! ( "Attempting to preopen {}" , & file) ;
203
+ // TODO: think about this
204
+ let default_rights = 0x1FFFFFFF ; // all rights
205
+ let cur_file: fs:: File = fs:: OpenOptions :: new ( )
206
+ . read ( true )
207
+ . open ( file)
208
+ . expect ( "Could not find file" ) ;
209
+ let cur_file_metadata = cur_file. metadata ( ) . unwrap ( ) ;
210
+ let kind = if cur_file_metadata. is_dir ( ) {
211
+ Kind :: Dir {
212
+ handle : WasiFile :: HostFile ( cur_file) ,
213
+ entries : Default :: default ( ) ,
214
+ }
215
+ } else {
216
+ return Err ( format ! (
217
+ "WASI only supports pre-opened directories right now; found \" {}\" " ,
218
+ file
219
+ ) ) ;
220
+ } ;
221
+ // TODO: handle nested pats in `file`
222
+ let inode_val =
223
+ InodeVal :: from_file_metadata ( & cur_file_metadata, file. clone ( ) , true , kind) ;
224
+
225
+ let inode = wasi_fs. inodes . insert ( inode_val) ;
226
+ wasi_fs. inodes [ inode] . stat . st_ino = wasi_fs. inode_counter . get ( ) ;
227
+ wasi_fs
228
+ . create_fd ( default_rights, default_rights, 0 , inode)
229
+ . expect ( "Could not open fd" ) ;
230
+ }
80
231
debug ! ( "wasi::fs::end" ) ;
81
- res
232
+ Ok ( wasi_fs )
82
233
}
83
234
84
235
#[ allow( dead_code) ]
@@ -195,6 +346,8 @@ impl WasiFs {
195
346
pub fn fdstat ( & self , fd : __wasi_fd_t ) -> Result < __wasi_fdstat_t , __wasi_errno_t > {
196
347
let fd = self . fd_map . get ( & fd) . ok_or ( __WASI_EBADF) ?;
197
348
349
+ debug ! ( "fdstat: {:?}" , fd) ;
350
+
198
351
Ok ( __wasi_fdstat_t {
199
352
fs_filetype : match self . inodes [ fd. inode ] . kind {
200
353
Kind :: File { .. } => __WASI_FILETYPE_REGULAR_FILE,
@@ -204,20 +357,22 @@ impl WasiFs {
204
357
} ,
205
358
fs_flags : fd. flags ,
206
359
fs_rights_base : fd. rights ,
207
- fs_rights_inheriting : fd. rights , // TODO(lachlan): Is this right?
360
+ fs_rights_inheriting : fd. rights_inheriting , // TODO(lachlan): Is this right?
208
361
} )
209
362
}
210
363
211
364
pub fn prestat_fd ( & self , fd : __wasi_fd_t ) -> Result < __wasi_prestat_t , __wasi_errno_t > {
212
365
let fd = self . fd_map . get ( & fd) . ok_or ( __WASI_EBADF) ?;
213
366
367
+ debug ! ( "in prestat_fd {:?}" , fd) ;
214
368
let inode_val = & self . inodes [ fd. inode ] ;
215
369
216
370
if inode_val. is_preopened {
217
371
Ok ( __wasi_prestat_t {
218
372
pr_type : __WASI_PREOPENTYPE_DIR,
219
373
u : PrestatEnum :: Dir {
220
- pr_name_len : inode_val. name . len ( ) as u32 ,
374
+ // REVIEW:
375
+ pr_name_len : inode_val. name . len ( ) as u32 + 1 ,
221
376
}
222
377
. untagged ( ) ,
223
378
} )
0 commit comments