Merge pull request #2515 from deantvv/os-enhancement

Implement dir_fd in os.open
This commit is contained in:
Noah
2021-03-19 21:49:17 -05:00
committed by GitHub
3 changed files with 45 additions and 15 deletions

11
Cargo.lock generated
View File

@@ -749,6 +749,16 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]]
name = "filepath"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dd50318458226958db06f173610f54f01d26f0a9ccfa3d38bd60f70bc9939ff"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "fixedbitset"
version = "0.2.0"
@@ -1986,6 +1996,7 @@ dependencies = [
"digest",
"dns-lookup",
"exitcode",
"filepath",
"flame",
"flamer",
"flate2",

View File

@@ -149,5 +149,8 @@ features = [
[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen = "0.2"
[target.'cfg(any(target_os = "linux", target_os = "macos", windows))'.dependencies]
filepath = "0.1.1"
[build-dependencies]
itertools = "0.9"

View File

@@ -7,6 +7,8 @@ use std::time::{Duration, SystemTime};
use std::{env, fs};
use crossbeam_utils::atomic::AtomicCell;
#[cfg(any(target_os = "linux", target_os = "macos", windows))]
use filepath::FilePath;
use num_bigint::BigInt;
use super::errno::errors;
@@ -161,11 +163,25 @@ fn make_path<'a>(
vm: &VirtualMachine,
path: &'a PyPathLike,
dir_fd: &DirFd,
) -> PyResult<&'a ffi::OsStr> {
if dir_fd.0.is_some() {
Err(vm.new_os_error("dir_fd not supported yet".to_owned()))
} else {
Ok(path.path.as_os_str())
) -> PyResult<std::borrow::Cow<'a, ffi::OsStr>> {
let path = &path.path;
if dir_fd.0.is_none() || path.is_absolute() {
return Ok(path.as_os_str().into());
}
cfg_if::cfg_if! {
if #[cfg(any(target_os = "linux", target_os = "macos", windows))] {
let dir_path = match rust_file(dir_fd.0.unwrap().into()).path() {
Ok(dir_path) => dir_path,
Err(_) => {
return Err(vm.new_os_error(format!("Cannot determine path of dir_fd: {:?}", dir_fd.0)));
}
};
let p: PathBuf = vec![dir_path, path.to_path_buf()].iter().collect();
Ok(p.into_os_string().into())
} else {
return Err(vm.new_os_error("dir_fd not supported on wasi yet".to_owned()));
}
}
}
@@ -349,7 +365,7 @@ mod _os {
vm: &VirtualMachine,
) -> PyResult<i64> {
let fname = make_path(vm, &name, &dir_fd)?;
if osstr_contains_nul(fname) {
if osstr_contains_nul(&fname) {
return Err(vm.new_value_error("embedded null character".to_owned()));
}
@@ -504,14 +520,14 @@ mod _os {
fn remove(path: PyPathLike, dir_fd: DirFd, vm: &VirtualMachine) -> PyResult<()> {
let path = make_path(vm, &path, &dir_fd)?;
let is_junction = cfg!(windows)
&& fs::symlink_metadata(path).map_or(false, |meta| {
&& fs::symlink_metadata(&path).map_or(false, |meta| {
let ty = meta.file_type();
ty.is_dir() && ty.is_symlink()
});
let res = if is_junction {
fs::remove_dir(path)
fs::remove_dir(&path)
} else {
fs::remove_file(path)
fs::remove_file(&path)
};
res.map_err(|err| err.into_pyexception(vm))
}
@@ -1221,7 +1237,7 @@ mod _os {
pub(super) fn support_funcs(vm: &VirtualMachine) -> Vec<SupportFunc> {
let mut supports = super::platform::support_funcs(vm);
supports.extend(vec![
SupportFunc::new(vm, "open", open, None, Some(false), None),
SupportFunc::new(vm, "open", open, None, Some(true), None),
SupportFunc::new(
vm,
"access",
@@ -1800,10 +1816,10 @@ mod posix {
let path = make_path(vm, &path, &dir_fd)?;
let body = move || {
use std::os::unix::fs::PermissionsExt;
let meta = fs_metadata(path, follow_symlinks.0)?;
let meta = fs_metadata(&path, follow_symlinks.0)?;
let mut permissions = meta.permissions();
permissions.set_mode(mode);
fs::set_permissions(path, permissions)
fs::set_permissions(&path, permissions)
};
body().map_err(|err| err.into_pyexception(vm))
}
@@ -2675,14 +2691,14 @@ mod nt {
const S_IWRITE: u32 = 128;
let path = make_path(vm, &path, &dir_fd)?;
let metadata = if follow_symlinks.0 {
fs::metadata(path)
fs::metadata(&path)
} else {
fs::symlink_metadata(path)
fs::symlink_metadata(&path)
};
let meta = metadata.map_err(|err| err.into_pyexception(vm))?;
let mut permissions = meta.permissions();
permissions.set_readonly(mode & S_IWRITE != 0);
fs::set_permissions(path, permissions).map_err(|err| err.into_pyexception(vm))
fs::set_permissions(&path, permissions).map_err(|err| err.into_pyexception(vm))
}
// cwait is available on MSVC only (according to CPython)