@@ -10,6 +10,7 @@ use crate::host::syscall_types::{PluginPtr, SysCallArgs, TypedPluginPtr};
1010use crate :: host:: syscall_types:: { SyscallError , SyscallResult } ;
1111use crate :: utility:: event_queue:: EventQueue ;
1212
13+ use std:: convert:: { TryFrom , TryInto } ;
1314use std:: sync:: Arc ;
1415
1516use atomic_refcell:: AtomicRefCell ;
@@ -21,72 +22,56 @@ pub fn close(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
2122
2223 trace ! ( "Trying to close fd {}" , fd) ;
2324
24- // scope used to make sure that desc cannot be used after deregistering it
25- {
26- // get the descriptor, or return early if it doesn't exist
27- let desc = unsafe { & * syscall:: get_descriptor ( fd, ctx. process . raw_mut ( ) ) ? } ;
28-
29- // if it's a legacy descriptor, use the C syscall handler instead
30- if let CompatDescriptor :: Legacy ( _) = desc {
31- return unsafe {
32- c:: syscallhandler_close ( ctx. thread . csyscallhandler ( ) , args as * const c:: SysCallArgs )
33- }
34- . into ( ) ;
35- }
36- }
25+ let fd: u32 = fd. try_into ( ) . map_err ( |_| nix:: errno:: Errno :: EBADF ) ?;
3726
3827 // according to "man 2 close", in Linux any errors that may occur will happen after the fd is
39- // released, so we should always deregister the descriptor
40- let desc = unsafe { c:: process_deregisterCompatDescriptor ( ctx. process . raw_mut ( ) , fd) } ;
41- let desc = CompatDescriptor :: from_raw ( desc) . unwrap ( ) ;
42- let desc = match * desc {
43- CompatDescriptor :: New ( d) => d,
44- _ => unreachable ! ( ) ,
45- } ;
46-
47- let result = EventQueue :: queue_and_run ( |event_queue| desc. close ( event_queue) ) ;
28+ // released, so we should always deregister the descriptor even if there's an error while
29+ // closing
30+ let desc = ctx
31+ . process
32+ . deregister_descriptor ( fd)
33+ . ok_or ( nix:: errno:: Errno :: EBADF ) ?;
4834
49- if let Some ( result) = result {
50- result. into ( )
51- } else {
52- Ok ( 0 . into ( ) )
53- }
35+ // if there are still valid descriptors to the posix file, close() will do nothing
36+ // and return None
37+ EventQueue :: queue_and_run ( |event_queue| desc. close ( ctx. host . chost ( ) , event_queue) )
38+ . unwrap_or ( Ok ( 0 . into ( ) ) )
5439}
5540
5641pub fn dup ( ctx : & mut ThreadContext , args : & SysCallArgs ) -> SyscallResult {
5742 let fd = libc:: c_int:: from ( args. get ( 0 ) ) ;
5843
5944 // get the descriptor, or return early if it doesn't exist
60- let desc = unsafe { & * syscall:: get_descriptor ( fd, ctx. process . raw_mut ( ) ) ? } ;
61-
62- match desc {
63- CompatDescriptor :: New ( desc) => dup_helper ( ctx, fd, desc) ,
45+ let desc = match syscall:: get_descriptor ( ctx. process , fd) ? {
46+ CompatDescriptor :: New ( desc) => desc,
6447 // if it's a legacy descriptor, use the C syscall handler instead
6548 CompatDescriptor :: Legacy ( _) => unsafe {
66- c:: syscallhandler_dup ( ctx. thread . csyscallhandler ( ) , args as * const c:: SysCallArgs )
67- . into ( )
49+ return c:: syscallhandler_dup (
50+ ctx. thread . csyscallhandler ( ) ,
51+ args as * const c:: SysCallArgs ,
52+ )
53+ . into ( ) ;
6854 } ,
69- }
70- }
55+ } ;
7156
72- pub fn dup_helper ( ctx : & mut ThreadContext , fd : libc:: c_int , desc : & Descriptor ) -> SyscallResult {
73- trace ! ( "Duping fd {} ({:?})" , fd, desc) ;
57+ // duplicate the descriptor
58+ let new_desc = CompatDescriptor :: New ( dup_helper ( desc, None ) ) ;
59+ let new_fd = ctx. process . register_descriptor ( new_desc) ;
7460
61+ // return the new fd
62+ Ok ( libc:: c_int:: try_from ( new_fd) . unwrap ( ) . into ( ) )
63+ }
64+
65+ pub fn dup_helper ( desc : & Descriptor , flags : Option < DescriptorFlags > ) -> Descriptor {
7566 // clone the descriptor (but not the flags)
7667 let mut new_desc = desc. clone ( ) ;
7768 new_desc. set_flags ( DescriptorFlags :: empty ( ) ) ;
7869
79- // register the descriptor
80- let new_desc = CompatDescriptor :: New ( new_desc) ;
81- let new_fd = unsafe {
82- c:: process_registerCompatDescriptor (
83- ctx. process . raw_mut ( ) ,
84- CompatDescriptor :: into_raw ( Box :: new ( new_desc) ) ,
85- )
86- } ;
70+ if let Some ( flags) = flags {
71+ new_desc. set_flags ( flags) ;
72+ }
8773
88- // return the new fd
89- Ok ( new_fd. into ( ) )
74+ new_desc
9075}
9176
9277pub fn read ( ctx : & mut ThreadContext , args : & SysCallArgs ) -> SyscallResult {
@@ -96,10 +81,11 @@ pub fn read(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
9681 let offset = 0 ;
9782
9883 // get the descriptor, or return early if it doesn't exist
99- let desc = unsafe { & * syscall:: get_descriptor ( fd, ctx. process . raw_mut ( ) ) ? } ;
100-
101- match desc {
102- CompatDescriptor :: New ( desc) => read_helper ( ctx, fd, desc, buf_ptr, buf_size, offset) ,
84+ match syscall:: get_descriptor ( ctx. process , fd) ? {
85+ CompatDescriptor :: New ( desc) => {
86+ let file = desc. get_file ( ) . clone ( ) ;
87+ read_helper ( ctx, fd, & file, buf_ptr, buf_size, offset)
88+ }
10389 // if it's a legacy descriptor, use the C syscall handler instead
10490 CompatDescriptor :: Legacy ( _) => unsafe {
10591 c:: syscallhandler_read ( ctx. thread . csyscallhandler ( ) , args as * const SysCallArgs ) . into ( )
@@ -114,10 +100,11 @@ pub fn pread64(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
114100 let offset = libc:: off_t:: from ( args. get ( 3 ) ) ;
115101
116102 // get the descriptor, or return early if it doesn't exist
117- let desc = unsafe { & * syscall:: get_descriptor ( fd, ctx. process . raw_mut ( ) ) ? } ;
118-
119- match desc {
120- CompatDescriptor :: New ( desc) => read_helper ( ctx, fd, desc, buf_ptr, buf_size, offset) ,
103+ match syscall:: get_descriptor ( ctx. process , fd) ? {
104+ CompatDescriptor :: New ( desc) => {
105+ let file = desc. get_file ( ) . clone ( ) ;
106+ read_helper ( ctx, fd, & file, buf_ptr, buf_size, offset)
107+ }
121108 // if it's a legacy descriptor, use the C syscall handler instead
122109 CompatDescriptor :: Legacy ( _) => unsafe {
123110 c:: syscallhandler_pread64 ( ctx. thread . csyscallhandler ( ) , args as * const c:: SysCallArgs )
@@ -129,12 +116,11 @@ pub fn pread64(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
129116fn read_helper (
130117 ctx : & mut ThreadContext ,
131118 _fd : libc:: c_int ,
132- desc : & Descriptor ,
119+ posix_file : & PosixFile ,
133120 buf_ptr : PluginPtr ,
134121 buf_size : libc:: size_t ,
135122 offset : libc:: off_t ,
136123) -> SyscallResult {
137- let posix_file = desc. get_file ( ) ;
138124 let file_flags = posix_file. borrow ( ) . get_flags ( ) ;
139125
140126 let result =
@@ -164,10 +150,11 @@ pub fn write(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
164150 let offset = 0 ;
165151
166152 // get the descriptor, or return early if it doesn't exist
167- let desc = unsafe { & * syscall:: get_descriptor ( fd, ctx. process . raw_mut ( ) ) ? } ;
168-
169- match desc {
170- CompatDescriptor :: New ( desc) => write_helper ( ctx, fd, desc, buf_ptr, buf_size, offset) ,
153+ match syscall:: get_descriptor ( ctx. process , fd) ? {
154+ CompatDescriptor :: New ( desc) => {
155+ let file = desc. get_file ( ) . clone ( ) ;
156+ write_helper ( ctx, fd, & file, buf_ptr, buf_size, offset)
157+ }
171158 // if it's a legacy descriptor, use the C syscall handler instead
172159 CompatDescriptor :: Legacy ( _) => unsafe {
173160 c:: syscallhandler_write ( ctx. thread . csyscallhandler ( ) , args as * const c:: SysCallArgs )
@@ -183,10 +170,11 @@ pub fn pwrite64(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
183170 let offset = libc:: off_t:: from ( args. get ( 3 ) ) ;
184171
185172 // get the descriptor, or return early if it doesn't exist
186- let desc = unsafe { & * syscall:: get_descriptor ( fd, ctx. process . raw_mut ( ) ) ? } ;
187-
188- match desc {
189- CompatDescriptor :: New ( desc) => write_helper ( ctx, fd, desc, buf_ptr, buf_size, offset) ,
173+ match syscall:: get_descriptor ( ctx. process , fd) ? {
174+ CompatDescriptor :: New ( desc) => {
175+ let file = desc. get_file ( ) . clone ( ) ;
176+ write_helper ( ctx, fd, & file, buf_ptr, buf_size, offset)
177+ }
190178 // if it's a legacy descriptor, use the C syscall handler instead
191179 CompatDescriptor :: Legacy ( _) => unsafe {
192180 c:: syscallhandler_pwrite64 ( ctx. thread . csyscallhandler ( ) , args as * const SysCallArgs )
@@ -198,15 +186,14 @@ pub fn pwrite64(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
198186fn write_helper (
199187 ctx : & mut ThreadContext ,
200188 _fd : libc:: c_int ,
201- desc : & Descriptor ,
189+ posix_file : & PosixFile ,
202190 buf_ptr : PluginPtr ,
203191 buf_size : libc:: size_t ,
204192 offset : libc:: off_t ,
205193) -> SyscallResult {
206- let posix_file = desc. get_file ( ) ;
207194 let file_flags = posix_file. borrow ( ) . get_flags ( ) ;
208195
209- let result=
196+ let result =
210197 // call the file's write(), and run any resulting events
211198 EventQueue :: queue_and_run ( |event_queue| {
212199 posix_file. borrow_mut ( ) . write (
0 commit comments