@@ -144,23 +144,34 @@ pub fn os_open(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
144144 }
145145 }
146146
147- let handle = options. open ( & fname) . map_err ( |err| match err. kind ( ) {
147+ let handle = options
148+ . open ( & fname)
149+ . map_err ( |err| convert_io_error ( vm, err) ) ?;
150+
151+ Ok ( vm. ctx . new_int ( raw_file_number ( handle) ) )
152+ }
153+
154+ fn convert_io_error ( vm : & VirtualMachine , err : io:: Error ) -> PyObjectRef {
155+ let os_error = match err. kind ( ) {
148156 ErrorKind :: NotFound => {
149157 let exc_type = vm. ctx . exceptions . file_not_found_error . clone ( ) ;
150- vm. new_exception ( exc_type, format ! ( "No such file or directory: {}" , & fname ) )
158+ vm. new_exception ( exc_type, err . to_string ( ) )
151159 }
152160 ErrorKind :: PermissionDenied => {
153161 let exc_type = vm. ctx . exceptions . permission_error . clone ( ) ;
154- vm. new_exception ( exc_type, format ! ( "Permission denied: {}" , & fname ) )
162+ vm. new_exception ( exc_type, err . to_string ( ) )
155163 }
156164 ErrorKind :: AlreadyExists => {
157165 let exc_type = vm. ctx . exceptions . file_exists_error . clone ( ) ;
158- vm. new_exception ( exc_type, format ! ( "File exists: {}" , & fname ) )
166+ vm. new_exception ( exc_type, err . to_string ( ) )
159167 }
160- _ => vm. new_value_error ( "Unhandled file IO error" . to_string ( ) ) ,
161- } ) ?;
162-
163- Ok ( vm. ctx . new_int ( raw_file_number ( handle) ) )
168+ _ => vm. new_os_error ( err. to_string ( ) ) ,
169+ } ;
170+ if let Some ( errno) = err. raw_os_error ( ) {
171+ vm. set_attr ( & os_error, "errno" , vm. ctx . new_int ( errno) )
172+ . unwrap ( ) ;
173+ }
174+ os_error
164175}
165176
166177fn os_error ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
@@ -182,8 +193,7 @@ fn os_error(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
182193
183194fn os_fsync ( fd : PyIntRef , vm : & VirtualMachine ) -> PyResult < ( ) > {
184195 let file = rust_file ( fd. as_bigint ( ) . to_i64 ( ) . unwrap ( ) ) ;
185- file. sync_all ( )
186- . map_err ( |s| vm. new_os_error ( s. to_string ( ) ) ) ?;
196+ file. sync_all ( ) . map_err ( |err| convert_io_error ( vm, err) ) ?;
187197 // Avoid closing the fd
188198 raw_file_number ( file) ;
189199 Ok ( ( ) )
@@ -192,10 +202,8 @@ fn os_fsync(fd: PyIntRef, vm: &VirtualMachine) -> PyResult<()> {
192202fn os_read ( fd : PyIntRef , n : PyIntRef , vm : & VirtualMachine ) -> PyResult {
193203 let mut buffer = vec ! [ 0u8 ; n. as_bigint( ) . to_usize( ) . unwrap( ) ] ;
194204 let mut file = rust_file ( fd. as_bigint ( ) . to_i64 ( ) . unwrap ( ) ) ;
195- match file. read_exact ( & mut buffer) {
196- Ok ( _) => ( ) ,
197- Err ( s) => return Err ( vm. new_os_error ( s. to_string ( ) ) ) ,
198- } ;
205+ file. read_exact ( & mut buffer)
206+ . map_err ( |err| convert_io_error ( vm, err) ) ?;
199207
200208 // Avoid closing the fd
201209 raw_file_number ( file) ;
@@ -204,10 +212,7 @@ fn os_read(fd: PyIntRef, n: PyIntRef, vm: &VirtualMachine) -> PyResult {
204212
205213fn os_write ( fd : PyIntRef , data : PyBytesRef , vm : & VirtualMachine ) -> PyResult {
206214 let mut file = rust_file ( fd. as_bigint ( ) . to_i64 ( ) . unwrap ( ) ) ;
207- let written = match file. write ( & data) {
208- Ok ( written) => written,
209- Err ( s) => return Err ( vm. new_os_error ( s. to_string ( ) ) ) ,
210- } ;
215+ let written = file. write ( & data) . map_err ( |err| convert_io_error ( vm, err) ) ?;
211216
212217 // Avoid closing the fd
213218 raw_file_number ( file) ;
@@ -216,21 +221,21 @@ fn os_write(fd: PyIntRef, data: PyBytesRef, vm: &VirtualMachine) -> PyResult {
216221
217222fn os_remove ( path : PyStringRef , dir_fd : DirFd , vm : & VirtualMachine ) -> PyResult < ( ) > {
218223 let path = make_path ( vm, path, & dir_fd) ;
219- fs:: remove_file ( & path. value ) . map_err ( |s| vm . new_os_error ( s . to_string ( ) ) )
224+ fs:: remove_file ( & path. value ) . map_err ( |err| convert_io_error ( vm , err ) )
220225}
221226
222227fn os_mkdir ( path : PyStringRef , dir_fd : DirFd , vm : & VirtualMachine ) -> PyResult < ( ) > {
223228 let path = make_path ( vm, path, & dir_fd) ;
224- fs:: create_dir ( & path. value ) . map_err ( |s| vm . new_os_error ( s . to_string ( ) ) )
229+ fs:: create_dir ( & path. value ) . map_err ( |err| convert_io_error ( vm , err ) )
225230}
226231
227232fn os_mkdirs ( path : PyStringRef , vm : & VirtualMachine ) -> PyResult < ( ) > {
228- fs:: create_dir_all ( & path. value ) . map_err ( |s| vm . new_os_error ( s . to_string ( ) ) )
233+ fs:: create_dir_all ( & path. value ) . map_err ( |err| convert_io_error ( vm , err ) )
229234}
230235
231236fn os_rmdir ( path : PyStringRef , dir_fd : DirFd , vm : & VirtualMachine ) -> PyResult < ( ) > {
232237 let path = make_path ( vm, path, & dir_fd) ;
233- fs:: remove_dir ( & path. value ) . map_err ( |s| vm . new_os_error ( s . to_string ( ) ) )
238+ fs:: remove_dir ( & path. value ) . map_err ( |err| convert_io_error ( vm , err ) )
234239}
235240
236241fn os_listdir ( path : PyStringRef , vm : & VirtualMachine ) -> PyResult {
@@ -239,7 +244,7 @@ fn os_listdir(path: PyStringRef, vm: &VirtualMachine) -> PyResult {
239244 let res: PyResult < Vec < PyObjectRef > > = iter
240245 . map ( |entry| match entry {
241246 Ok ( path) => Ok ( vm. ctx . new_str ( path. file_name ( ) . into_string ( ) . unwrap ( ) ) ) ,
242- Err ( s) => Err ( vm . new_os_error ( s . to_string ( ) ) ) ,
247+ Err ( s) => Err ( convert_io_error ( vm , s ) ) ,
243248 } )
244249 . collect ( ) ;
245250 Ok ( vm. ctx . new_list ( res?) )
@@ -309,7 +314,7 @@ impl DirEntryRef {
309314 true => fs:: metadata ( self . entry . path ( ) ) ,
310315 false => fs:: symlink_metadata ( self . entry . path ( ) ) ,
311316 } ;
312- let meta = metadata. map_err ( |s| vm . new_os_error ( s . to_string ( ) ) ) ?;
317+ let meta = metadata. map_err ( |err| convert_io_error ( vm , err ) ) ?;
313318 Ok ( action ( meta) )
314319 }
315320
@@ -333,7 +338,7 @@ impl DirEntryRef {
333338 Ok ( self
334339 . entry
335340 . file_type ( )
336- . map_err ( |s| vm . new_os_error ( s . to_string ( ) ) ) ?
341+ . map_err ( |err| convert_io_error ( vm , err ) ) ?
337342 . is_symlink ( ) )
338343 }
339344
@@ -366,7 +371,7 @@ impl ScandirIterator {
366371 match self . entries . borrow_mut ( ) . next ( ) {
367372 Some ( entry) => match entry {
368373 Ok ( entry) => Ok ( DirEntry { entry } . into_ref ( vm) . into_object ( ) ) ,
369- Err ( s) => Err ( vm . new_os_error ( s . to_string ( ) ) ) ,
374+ Err ( s) => Err ( convert_io_error ( vm , s ) ) ,
370375 } ,
371376 None => Err ( objiter:: new_stop_iteration ( vm) ) ,
372377 }
@@ -385,7 +390,7 @@ fn os_scandir(path: PyStringRef, vm: &VirtualMachine) -> PyResult {
385390 }
386391 . into_ref ( vm)
387392 . into_object ( ) ) ,
388- Err ( s) => Err ( vm . new_os_error ( s . to_string ( ) ) ) ,
393+ Err ( s) => Err ( convert_io_error ( vm , s ) ) ,
389394 }
390395}
391396
@@ -496,7 +501,7 @@ macro_rules! os_unix_stat_inner {
496501 }
497502
498503 get_stats( & $path. value, $follow_symlinks. follow_symlinks)
499- . map_err( |s| $vm. new_os_error ( s . to_string ( ) ) )
504+ . map_err( |err| convert_io_error ( $vm, err ) )
500505 } } ;
501506}
502507
@@ -609,7 +614,7 @@ fn os_symlink(
609614) -> PyResult < ( ) > {
610615 use std:: os:: unix:: fs as unix_fs;
611616 let dst = make_path ( vm, dst, & dir_fd) ;
612- unix_fs:: symlink ( & src. value , & dst. value ) . map_err ( |s| vm . new_os_error ( s . to_string ( ) ) )
617+ unix_fs:: symlink ( & src. value , & dst. value ) . map_err ( |err| convert_io_error ( vm , err ) )
613618}
614619
615620#[ cfg( windows) ]
@@ -632,7 +637,7 @@ fn os_symlink(
632637 }
633638 Err ( _) => win_fs:: symlink_file ( & src. value , & dst. value ) ,
634639 } ;
635- ret. map_err ( |s| vm . new_os_error ( s . to_string ( ) ) )
640+ ret. map_err ( |err| convert_io_error ( vm , err ) )
636641}
637642
638643#[ cfg( all( not( unix) , not( windows) ) ) ]
@@ -647,15 +652,15 @@ fn os_symlink(
647652
648653fn os_getcwd ( vm : & VirtualMachine ) -> PyResult < String > {
649654 Ok ( env:: current_dir ( )
650- . map_err ( |s| vm . new_os_error ( s . to_string ( ) ) ) ?
655+ . map_err ( |err| convert_io_error ( vm , err ) ) ?
651656 . as_path ( )
652657 . to_str ( )
653658 . unwrap ( )
654659 . to_string ( ) )
655660}
656661
657662fn os_chdir ( path : PyStringRef , vm : & VirtualMachine ) -> PyResult < ( ) > {
658- env:: set_current_dir ( & path. value ) . map_err ( |s| vm . new_os_error ( s . to_string ( ) ) )
663+ env:: set_current_dir ( & path. value ) . map_err ( |err| convert_io_error ( vm , err ) )
659664}
660665
661666fn os_fspath ( path : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
@@ -672,7 +677,7 @@ fn os_fspath(path: PyObjectRef, vm: &VirtualMachine) -> PyResult {
672677}
673678
674679fn os_rename ( src : PyStringRef , dst : PyStringRef , vm : & VirtualMachine ) -> PyResult < ( ) > {
675- fs:: rename ( & src. value , & dst. value ) . map_err ( |s| vm . new_os_error ( s . to_string ( ) ) )
680+ fs:: rename ( & src. value , & dst. value ) . map_err ( |err| convert_io_error ( vm , err ) )
676681}
677682
678683pub fn make_module ( vm : & VirtualMachine ) -> PyObjectRef {
0 commit comments