@@ -144,23 +144,34 @@ pub fn os_open(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
144
144
}
145
145
}
146
146
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 ( ) {
148
156
ErrorKind :: NotFound => {
149
157
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 ( ) )
151
159
}
152
160
ErrorKind :: PermissionDenied => {
153
161
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 ( ) )
155
163
}
156
164
ErrorKind :: AlreadyExists => {
157
165
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 ( ) )
159
167
}
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
164
175
}
165
176
166
177
fn os_error ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
@@ -182,8 +193,7 @@ fn os_error(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
182
193
183
194
fn os_fsync ( fd : PyIntRef , vm : & VirtualMachine ) -> PyResult < ( ) > {
184
195
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) ) ?;
187
197
// Avoid closing the fd
188
198
raw_file_number ( file) ;
189
199
Ok ( ( ) )
@@ -192,10 +202,8 @@ fn os_fsync(fd: PyIntRef, vm: &VirtualMachine) -> PyResult<()> {
192
202
fn os_read ( fd : PyIntRef , n : PyIntRef , vm : & VirtualMachine ) -> PyResult {
193
203
let mut buffer = vec ! [ 0u8 ; n. as_bigint( ) . to_usize( ) . unwrap( ) ] ;
194
204
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) ) ?;
199
207
200
208
// Avoid closing the fd
201
209
raw_file_number ( file) ;
@@ -204,10 +212,7 @@ fn os_read(fd: PyIntRef, n: PyIntRef, vm: &VirtualMachine) -> PyResult {
204
212
205
213
fn os_write ( fd : PyIntRef , data : PyBytesRef , vm : & VirtualMachine ) -> PyResult {
206
214
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) ) ?;
211
216
212
217
// Avoid closing the fd
213
218
raw_file_number ( file) ;
@@ -216,21 +221,21 @@ fn os_write(fd: PyIntRef, data: PyBytesRef, vm: &VirtualMachine) -> PyResult {
216
221
217
222
fn os_remove ( path : PyStringRef , dir_fd : DirFd , vm : & VirtualMachine ) -> PyResult < ( ) > {
218
223
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 ) )
220
225
}
221
226
222
227
fn os_mkdir ( path : PyStringRef , dir_fd : DirFd , vm : & VirtualMachine ) -> PyResult < ( ) > {
223
228
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 ) )
225
230
}
226
231
227
232
fn 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 ) )
229
234
}
230
235
231
236
fn os_rmdir ( path : PyStringRef , dir_fd : DirFd , vm : & VirtualMachine ) -> PyResult < ( ) > {
232
237
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 ) )
234
239
}
235
240
236
241
fn os_listdir ( path : PyStringRef , vm : & VirtualMachine ) -> PyResult {
@@ -239,7 +244,7 @@ fn os_listdir(path: PyStringRef, vm: &VirtualMachine) -> PyResult {
239
244
let res: PyResult < Vec < PyObjectRef > > = iter
240
245
. map ( |entry| match entry {
241
246
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 ) ) ,
243
248
} )
244
249
. collect ( ) ;
245
250
Ok ( vm. ctx . new_list ( res?) )
@@ -309,7 +314,7 @@ impl DirEntryRef {
309
314
true => fs:: metadata ( self . entry . path ( ) ) ,
310
315
false => fs:: symlink_metadata ( self . entry . path ( ) ) ,
311
316
} ;
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 ) ) ?;
313
318
Ok ( action ( meta) )
314
319
}
315
320
@@ -333,7 +338,7 @@ impl DirEntryRef {
333
338
Ok ( self
334
339
. entry
335
340
. file_type ( )
336
- . map_err ( |s| vm . new_os_error ( s . to_string ( ) ) ) ?
341
+ . map_err ( |err| convert_io_error ( vm , err ) ) ?
337
342
. is_symlink ( ) )
338
343
}
339
344
@@ -366,7 +371,7 @@ impl ScandirIterator {
366
371
match self . entries . borrow_mut ( ) . next ( ) {
367
372
Some ( entry) => match entry {
368
373
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 ) ) ,
370
375
} ,
371
376
None => Err ( objiter:: new_stop_iteration ( vm) ) ,
372
377
}
@@ -385,7 +390,7 @@ fn os_scandir(path: PyStringRef, vm: &VirtualMachine) -> PyResult {
385
390
}
386
391
. into_ref ( vm)
387
392
. into_object ( ) ) ,
388
- Err ( s) => Err ( vm . new_os_error ( s . to_string ( ) ) ) ,
393
+ Err ( s) => Err ( convert_io_error ( vm , s ) ) ,
389
394
}
390
395
}
391
396
@@ -496,7 +501,7 @@ macro_rules! os_unix_stat_inner {
496
501
}
497
502
498
503
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 ) )
500
505
} } ;
501
506
}
502
507
@@ -609,7 +614,7 @@ fn os_symlink(
609
614
) -> PyResult < ( ) > {
610
615
use std:: os:: unix:: fs as unix_fs;
611
616
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 ) )
613
618
}
614
619
615
620
#[ cfg( windows) ]
@@ -632,7 +637,7 @@ fn os_symlink(
632
637
}
633
638
Err ( _) => win_fs:: symlink_file ( & src. value , & dst. value ) ,
634
639
} ;
635
- ret. map_err ( |s| vm . new_os_error ( s . to_string ( ) ) )
640
+ ret. map_err ( |err| convert_io_error ( vm , err ) )
636
641
}
637
642
638
643
#[ cfg( all( not( unix) , not( windows) ) ) ]
@@ -647,15 +652,15 @@ fn os_symlink(
647
652
648
653
fn os_getcwd ( vm : & VirtualMachine ) -> PyResult < String > {
649
654
Ok ( env:: current_dir ( )
650
- . map_err ( |s| vm . new_os_error ( s . to_string ( ) ) ) ?
655
+ . map_err ( |err| convert_io_error ( vm , err ) ) ?
651
656
. as_path ( )
652
657
. to_str ( )
653
658
. unwrap ( )
654
659
. to_string ( ) )
655
660
}
656
661
657
662
fn 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 ) )
659
664
}
660
665
661
666
fn os_fspath ( path : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
@@ -672,7 +677,7 @@ fn os_fspath(path: PyObjectRef, vm: &VirtualMachine) -> PyResult {
672
677
}
673
678
674
679
fn 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 ) )
676
681
}
677
682
678
683
pub fn make_module ( vm : & VirtualMachine ) -> PyObjectRef {
0 commit comments