Skip to content

Commit 2f408f2

Browse files
committed
Add conversion from io::Error to OSError
1 parent 700d7d4 commit 2f408f2

File tree

1 file changed

+38
-33
lines changed

1 file changed

+38
-33
lines changed

vm/src/stdlib/os.rs

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -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

166177
fn os_error(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -182,8 +193,7 @@ fn os_error(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
182193

183194
fn 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<()> {
192202
fn 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

205213
fn 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

217222
fn 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

222227
fn 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

227232
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))
229234
}
230235

231236
fn 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

236241
fn 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

648653
fn 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

657662
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))
659664
}
660665

661666
fn os_fspath(path: PyObjectRef, vm: &VirtualMachine) -> PyResult {
@@ -672,7 +677,7 @@ fn os_fspath(path: PyObjectRef, vm: &VirtualMachine) -> PyResult {
672677
}
673678

674679
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))
676681
}
677682

678683
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {

0 commit comments

Comments
 (0)