Skip to content

Commit cba3a25

Browse files
authored
Merge pull request RustPython#2515 from deantvv/os-enhancement
Implement dir_fd in os.open
2 parents cb90ddb + 9963bf9 commit cba3a25

File tree

3 files changed

+45
-15
lines changed

3 files changed

+45
-15
lines changed

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vm/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,5 +149,8 @@ features = [
149149
[target.'cfg(target_arch = "wasm32")'.dependencies]
150150
wasm-bindgen = "0.2"
151151

152+
[target.'cfg(any(target_os = "linux", target_os = "macos", windows))'.dependencies]
153+
filepath = "0.1.1"
154+
152155
[build-dependencies]
153156
itertools = "0.9"

vm/src/stdlib/os.rs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ use std::time::{Duration, SystemTime};
77
use std::{env, fs};
88

99
use crossbeam_utils::atomic::AtomicCell;
10+
#[cfg(any(target_os = "linux", target_os = "macos", windows))]
11+
use filepath::FilePath;
1012
use num_bigint::BigInt;
1113

1214
use super::errno::errors;
@@ -161,11 +163,25 @@ fn make_path<'a>(
161163
vm: &VirtualMachine,
162164
path: &'a PyPathLike,
163165
dir_fd: &DirFd,
164-
) -> PyResult<&'a ffi::OsStr> {
165-
if dir_fd.0.is_some() {
166-
Err(vm.new_os_error("dir_fd not supported yet".to_owned()))
167-
} else {
168-
Ok(path.path.as_os_str())
166+
) -> PyResult<std::borrow::Cow<'a, ffi::OsStr>> {
167+
let path = &path.path;
168+
if dir_fd.0.is_none() || path.is_absolute() {
169+
return Ok(path.as_os_str().into());
170+
}
171+
172+
cfg_if::cfg_if! {
173+
if #[cfg(any(target_os = "linux", target_os = "macos", windows))] {
174+
let dir_path = match rust_file(dir_fd.0.unwrap().into()).path() {
175+
Ok(dir_path) => dir_path,
176+
Err(_) => {
177+
return Err(vm.new_os_error(format!("Cannot determine path of dir_fd: {:?}", dir_fd.0)));
178+
}
179+
};
180+
let p: PathBuf = vec![dir_path, path.to_path_buf()].iter().collect();
181+
Ok(p.into_os_string().into())
182+
} else {
183+
return Err(vm.new_os_error("dir_fd not supported on wasi yet".to_owned()));
184+
}
169185
}
170186
}
171187

@@ -349,7 +365,7 @@ mod _os {
349365
vm: &VirtualMachine,
350366
) -> PyResult<i64> {
351367
let fname = make_path(vm, &name, &dir_fd)?;
352-
if osstr_contains_nul(fname) {
368+
if osstr_contains_nul(&fname) {
353369
return Err(vm.new_value_error("embedded null character".to_owned()));
354370
}
355371

@@ -504,14 +520,14 @@ mod _os {
504520
fn remove(path: PyPathLike, dir_fd: DirFd, vm: &VirtualMachine) -> PyResult<()> {
505521
let path = make_path(vm, &path, &dir_fd)?;
506522
let is_junction = cfg!(windows)
507-
&& fs::symlink_metadata(path).map_or(false, |meta| {
523+
&& fs::symlink_metadata(&path).map_or(false, |meta| {
508524
let ty = meta.file_type();
509525
ty.is_dir() && ty.is_symlink()
510526
});
511527
let res = if is_junction {
512-
fs::remove_dir(path)
528+
fs::remove_dir(&path)
513529
} else {
514-
fs::remove_file(path)
530+
fs::remove_file(&path)
515531
};
516532
res.map_err(|err| err.into_pyexception(vm))
517533
}
@@ -1221,7 +1237,7 @@ mod _os {
12211237
pub(super) fn support_funcs(vm: &VirtualMachine) -> Vec<SupportFunc> {
12221238
let mut supports = super::platform::support_funcs(vm);
12231239
supports.extend(vec![
1224-
SupportFunc::new(vm, "open", open, None, Some(false), None),
1240+
SupportFunc::new(vm, "open", open, None, Some(true), None),
12251241
SupportFunc::new(
12261242
vm,
12271243
"access",
@@ -1800,10 +1816,10 @@ mod posix {
18001816
let path = make_path(vm, &path, &dir_fd)?;
18011817
let body = move || {
18021818
use std::os::unix::fs::PermissionsExt;
1803-
let meta = fs_metadata(path, follow_symlinks.0)?;
1819+
let meta = fs_metadata(&path, follow_symlinks.0)?;
18041820
let mut permissions = meta.permissions();
18051821
permissions.set_mode(mode);
1806-
fs::set_permissions(path, permissions)
1822+
fs::set_permissions(&path, permissions)
18071823
};
18081824
body().map_err(|err| err.into_pyexception(vm))
18091825
}
@@ -2675,14 +2691,14 @@ mod nt {
26752691
const S_IWRITE: u32 = 128;
26762692
let path = make_path(vm, &path, &dir_fd)?;
26772693
let metadata = if follow_symlinks.0 {
2678-
fs::metadata(path)
2694+
fs::metadata(&path)
26792695
} else {
2680-
fs::symlink_metadata(path)
2696+
fs::symlink_metadata(&path)
26812697
};
26822698
let meta = metadata.map_err(|err| err.into_pyexception(vm))?;
26832699
let mut permissions = meta.permissions();
26842700
permissions.set_readonly(mode & S_IWRITE != 0);
2685-
fs::set_permissions(path, permissions).map_err(|err| err.into_pyexception(vm))
2701+
fs::set_permissions(&path, permissions).map_err(|err| err.into_pyexception(vm))
26862702
}
26872703

26882704
// cwait is available on MSVC only (according to CPython)

0 commit comments

Comments
 (0)