1
1
use std:: {
2
- collections:: HashMap ,
2
+ collections:: { HashMap , HashSet } ,
3
3
ffi:: { CString , OsString } ,
4
4
fs:: canonicalize,
5
5
io:: ErrorKind ,
@@ -20,6 +20,7 @@ pub struct UhyveFileMap {
20
20
files : HashMap < String , OsString > ,
21
21
tempdir : TempDir ,
22
22
fdmap : BiHashMap < RawFd , String > ,
23
+ unlinkedfd : HashSet < RawFd > ,
23
24
}
24
25
25
26
impl UhyveFileMap {
@@ -36,6 +37,7 @@ impl UhyveFileMap {
36
37
. collect ( ) ,
37
38
tempdir : create_temp_dir ( ) ,
38
39
fdmap : BiHashMap :: new ( ) ,
40
+ unlinkedfd : HashSet :: new ( ) ,
39
41
}
40
42
}
41
43
@@ -123,8 +125,20 @@ impl UhyveFileMap {
123
125
ret
124
126
}
125
127
126
- pub fn get_fd_presence ( & mut self , fd : RawFd ) -> bool {
127
- debug ! ( "get_fd_presence: {:#?}" , & self . fdmap) ;
128
+ /// Checks whether the fd is mapped to a guest path or belongs
129
+ /// to an unlinked file.
130
+ ///
131
+ /// * `fd` - The opened guest path's file descriptor.
132
+ pub fn is_fd_closable ( & mut self , fd : RawFd ) -> bool {
133
+ debug ! ( "is_fd_closable: {:#?}" , & self . fdmap) ;
134
+ self . is_fd_present ( fd) || self . unlinkedfd . contains ( & fd)
135
+ }
136
+
137
+ /// Checks whether the fd is mapped to a guest path.
138
+ ///
139
+ /// * `fd` - The opened guest path's file descriptor.
140
+ pub fn is_fd_present ( & mut self , fd : RawFd ) -> bool {
141
+ debug ! ( "is_fd_present: {:#?}" , & self . fdmap) ;
128
142
if ( fd >= 0 && self . fdmap . contains_left ( & fd) ) || ( 0 ..=2 ) . contains ( & fd) {
129
143
return true ;
130
144
}
@@ -136,10 +150,28 @@ impl UhyveFileMap {
136
150
/// * `fd` - The opened guest path's file descriptor.
137
151
/// * `guest_path` - The guest path.
138
152
pub fn insert_fd_path ( & mut self , fd : RawFd , guest_path : & str ) {
139
- debug ! ( "insert_fd_path: {:#?}" , & self . fdmap) ;
140
153
if fd > 2 {
141
154
self . fdmap . insert ( fd, guest_path. into ( ) ) ;
142
155
}
156
+ debug ! ( "insert_fd_path: {:#?}" , & self . fdmap) ;
157
+ }
158
+
159
+ /// Removes an fd from UhyveFileMap. This is only used by [crate::hypercall::close],
160
+ /// under the expectation that a new temporary file will be created if the guest
161
+ /// attempts to open a file of the same path again.
162
+ ///
163
+ /// * `fd` - The file descriptor of the file being removed.
164
+ pub fn close_fd ( & mut self , fd : RawFd ) {
165
+ debug ! ( "close_fd: {:#?}" , & self . fdmap) ;
166
+ // The file descriptor in fdclosed is supposedly still alive.
167
+ // It is safe to assume that the host OS will not assign the
168
+ // same file descriptor to another opened file, until _after_
169
+ // the file has been closed.
170
+ if let Some ( & fd) = self . unlinkedfd . get ( & fd) {
171
+ self . unlinkedfd . remove ( & fd) ;
172
+ } else {
173
+ self . remove_fd ( fd) ;
174
+ }
143
175
}
144
176
145
177
/// Removes an fd from UhyveFileMap. This is only used by [crate::hypercall::close],
@@ -159,10 +191,13 @@ impl UhyveFileMap {
159
191
/// attempts to open a file of the same path again.
160
192
///
161
193
/// * `guest_path` - The path of the file being removed.
162
- pub fn remove_guest_path ( & mut self , guest_path : & str ) {
163
- debug ! ( "remove_guest_path: {:#?}" , guest_path) ;
194
+ pub fn unlink_guest_path ( & mut self , guest_path : & str ) {
195
+ debug ! ( "unlink_guest_path: {:#?}" , & guest_path) ;
196
+ if let Some ( fd) = self . fdmap . get_by_right ( guest_path) {
197
+ self . unlinkedfd . insert ( * fd) ;
198
+ self . fdmap . remove_by_right ( guest_path) ;
199
+ }
164
200
self . files . remove ( guest_path) ;
165
- self . fdmap . remove_by_right ( guest_path) ;
166
201
}
167
202
}
168
203
0 commit comments