mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
host_env: os.mkdir for Windows, Redox (#8128)
Python supports `mkdir` on Windows. I deferred to calling Rust's implementation for now. However, like `rename`, Python's implementation supports additional features that are currently unsupported on RustPython. I added a note for future reference. Redox supports `mkdirat` which significantly cleans up the implementation.
This commit is contained in:
1 parent
4caf959e58
commit
f32e96ce90
7 files changed
+79
-62
No files matched your search
@@ -20,6 +20,8 @@ paste = { workspace = true }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
nix = { workspace = true }
|
||||
|
||||
[target.'cfg(any(unix, target_os = "macos", target_os = "redox", target_os = "wasi"))'.dependencies]
|
||||
rustix = { workspace = true }
|
||||
|
||||
[target.'cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))'.dependencies]
|
||||
|
||||
@@ -5,7 +5,7 @@ use alloc::fmt;
|
||||
use core::cmp;
|
||||
use std::{ffi, io};
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
use std::os::fd::AsFd;
|
||||
#[cfg(not(windows))]
|
||||
use std::os::fd::{AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
||||
@@ -209,42 +209,42 @@ impl Owned {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
impl From<Owned> for OwnedFd {
|
||||
fn from(fd: Owned) -> Self {
|
||||
fd.inner
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
impl From<OwnedFd> for Owned {
|
||||
fn from(fd: OwnedFd) -> Self {
|
||||
Self { inner: fd }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
impl AsFd for Owned {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.inner.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
impl AsRawFd for Owned {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_raw()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
impl FromRawFd for Owned {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Self {
|
||||
unsafe { Self::from_raw(fd) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
impl IntoRawFd for Owned {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_raw()
|
||||
@@ -287,28 +287,28 @@ impl Borrowed<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
impl<'fd> From<Borrowed<'fd>> for BorrowedFd<'fd> {
|
||||
fn from(fd: Borrowed<'fd>) -> Self {
|
||||
fd.inner
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
impl<'fd> From<BorrowedFd<'fd>> for Borrowed<'fd> {
|
||||
fn from(fd: BorrowedFd<'fd>) -> Self {
|
||||
Self { inner: fd }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
impl AsFd for Borrowed<'_> {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.inner.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
impl AsRawFd for Borrowed<'_> {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_raw()
|
||||
|
||||
@@ -52,6 +52,9 @@ pub mod posix;
|
||||
#[cfg(target_os = "wasi")]
|
||||
#[path = "posix_wasi.rs"]
|
||||
pub mod posix;
|
||||
#[cfg(windows)]
|
||||
#[path = "posix_windows.rs"]
|
||||
pub mod posix;
|
||||
#[cfg(unix)]
|
||||
pub mod pwd;
|
||||
#[cfg(unix)]
|
||||
|
||||
@@ -10,6 +10,8 @@ use std::os::fd::FromRawFd;
|
||||
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, IntoRawFd, OwnedFd};
|
||||
use std::path::Path;
|
||||
|
||||
use crate::crt_fd;
|
||||
|
||||
pub struct UnameInfo {
|
||||
pub sysname: String,
|
||||
pub nodename: String,
|
||||
@@ -174,24 +176,14 @@ pub fn fcopyfile(in_fd: i32, out_fd: i32, flags: u32) -> std::io::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub fn make_dir(path: &CStr, mode: u32) -> std::io::Result<()> {
|
||||
let ret = unsafe { libc::mkdir(path.as_ptr(), mode as _) };
|
||||
if ret < 0 {
|
||||
Err(std::io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(not(windows), not(target_os = "redox")))]
|
||||
pub fn make_dir_at(dir_fd: i32, path: &CStr, mode: u32) -> std::io::Result<()> {
|
||||
let ret = unsafe { libc::mkdirat(dir_fd, path.as_ptr(), mode as _) };
|
||||
if ret < 0 {
|
||||
Err(std::io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
pub fn make_dir(
|
||||
dir_fd: Option<crt_fd::Borrowed<'_>>,
|
||||
path: &impl AsRef<Path>,
|
||||
mode: libc::mode_t,
|
||||
) -> std::io::Result<()> {
|
||||
let dir_fd = dir_fd.as_ref().map_or(rustix::fs::CWD, AsFd::as_fd);
|
||||
rustix::fs::mkdirat(dir_fd, path.as_ref(), mode.into()).map_err(Into::into)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
use alloc::ffi::CString;
|
||||
use core::{ffi::CStr, time::Duration};
|
||||
use std::{ffi::OsStr, io};
|
||||
use rustix::fd::AsFd;
|
||||
use std::{ffi::OsStr, io, path::Path};
|
||||
|
||||
use crate::os::CheckLibcResult;
|
||||
use crate::{crt_fd, os::CheckLibcResult};
|
||||
|
||||
pub fn make_dir(path: &CStr, mode: u32) -> io::Result<()> {
|
||||
unsafe { libc::mkdir(path.as_ptr(), mode as _) }.check_libc_neg()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn make_dir_at(dir_fd: i32, path: &CStr, mode: u32) -> io::Result<()> {
|
||||
unsafe { libc::mkdirat(dir_fd, path.as_ptr(), mode as _) }.check_libc_neg()?;
|
||||
Ok(())
|
||||
pub fn make_dir(
|
||||
dir_fd: Option<crt_fd::Borrowed<'_>>,
|
||||
path: &impl AsRef<Path>,
|
||||
mode: libc::mode_t,
|
||||
) -> std::io::Result<()> {
|
||||
let dir_fd = dir_fd.as_ref().map_or(rustix::fs::CWD, AsFd::as_fd);
|
||||
rustix::fs::mkdirat(dir_fd, path.as_ref(), mode.into()).map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn remove_dir_at(dir_fd: i32, path: &CStr) -> io::Result<()> {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
//! POSIX-compatible API for Windows.
|
||||
//!
|
||||
//! Python wraps POSIX syscalls such as `mkdir` and `open`. Windows doesn't directly implement
|
||||
//! these syscalls, but they can be emulated with a mix of the Windows API and the Rust standard
|
||||
//! library, the latter of which calls the former.
|
||||
|
||||
use std::{fs, io, path::Path};
|
||||
|
||||
use crate::crt_fd;
|
||||
|
||||
#[expect(non_camel_case_types)]
|
||||
pub type mode_t = u32;
|
||||
|
||||
pub fn make_dir(
|
||||
dir_fd: Option<crt_fd::Borrowed<'_>>,
|
||||
path: &impl AsRef<Path>,
|
||||
_mode: mode_t,
|
||||
) -> io::Result<()> {
|
||||
debug_assert!(dir_fd.is_none());
|
||||
// TODO: On Windows, Python has an override if the mode is 0o700
|
||||
fs::create_dir(path)
|
||||
}
|
||||
+21
-23
@@ -10,6 +10,12 @@ use crate::{
|
||||
};
|
||||
use std::{io, path::Path};
|
||||
|
||||
#[cfg(not(windows))]
|
||||
use libc::mode_t;
|
||||
|
||||
#[cfg(windows)]
|
||||
use crate::host_env::posix::mode_t;
|
||||
|
||||
pub(crate) fn fs_metadata<P: AsRef<Path>>(
|
||||
path: P,
|
||||
follow_symlink: bool,
|
||||
@@ -29,7 +35,7 @@ pub struct TargetIsDirectory {
|
||||
}
|
||||
|
||||
cfg_select! {
|
||||
all(any(unix, target_os = "wasi"), not(target_os = "redox")) => {
|
||||
any(unix, target_os = "wasi") => {
|
||||
use libc::AT_FDCWD;
|
||||
}
|
||||
_ => {
|
||||
@@ -154,7 +160,7 @@ impl ToPyObject for crt_fd::Borrowed<'_> {
|
||||
|
||||
#[pymodule(sub)]
|
||||
pub(super) mod _os {
|
||||
use super::{DirFd, FollowSymlinks, SupportFunc};
|
||||
use super::{DirFd, FollowSymlinks, SupportFunc, mode_t};
|
||||
use crate::host_env::fileutils::StatStruct;
|
||||
#[cfg(any(unix, windows))]
|
||||
use crate::utils::ToCString;
|
||||
@@ -184,7 +190,7 @@ pub(super) mod _os {
|
||||
use std::{fs, io, path::PathBuf, time::SystemTime};
|
||||
|
||||
const OPEN_DIR_FD: bool = cfg!(not(any(windows, target_os = "redox")));
|
||||
pub(crate) const MKDIR_DIR_FD: bool = cfg!(not(any(windows, target_os = "redox")));
|
||||
pub(crate) const MKDIR_DIR_FD: bool = cfg!(any(unix, target_os = "wasi"));
|
||||
const STAT_DIR_FD: bool = cfg!(not(any(windows, target_os = "redox")));
|
||||
const UTIME_DIR_FD: bool = cfg!(not(any(windows, target_os = "redox")));
|
||||
pub(crate) const SYMLINK_DIR_FD: bool = cfg!(not(any(windows, target_os = "redox")));
|
||||
@@ -338,32 +344,24 @@ pub(super) mod _os {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[pyfunction]
|
||||
fn mkdir(
|
||||
path: OsPath,
|
||||
mode: OptionalArg<i32>,
|
||||
dir_fd: DirFd<'_, { MKDIR_DIR_FD as usize }>,
|
||||
mode: OptionalArg<mode_t>,
|
||||
#[cfg_attr(not(any(unix, target_os = "wasi")), expect(unused_variables))] dir_fd: DirFd<
|
||||
'_,
|
||||
{ MKDIR_DIR_FD as usize },
|
||||
>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
let mode = mode.unwrap_or(0o777);
|
||||
let c_path = path.clone().into_cstring(vm)?;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
if let Some(fd) = dir_fd.raw_opt() {
|
||||
return if let Err(err) =
|
||||
crate::host_env::posix::make_dir_at(fd, c_path.as_c_str(), mode as u32)
|
||||
{
|
||||
Err(OSErrorBuilder::with_filename(&err, path, vm))
|
||||
} else {
|
||||
Ok(())
|
||||
};
|
||||
}
|
||||
#[cfg(target_os = "redox")]
|
||||
let [] = dir_fd.0;
|
||||
if let Err(err) = crate::host_env::posix::make_dir(c_path.as_c_str(), mode as u32) {
|
||||
return Err(OSErrorBuilder::with_filename(&err, path, vm));
|
||||
}
|
||||
Ok(())
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
let dir_fd = dir_fd.get_opt();
|
||||
#[cfg(not(any(unix, target_os = "wasi")))]
|
||||
let dir_fd = None;
|
||||
|
||||
crate::host_env::posix::make_dir(dir_fd, &path.path, mode)
|
||||
.map_err(|err| OSErrorBuilder::with_filename(&err, path, vm))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
|
||||
Reference in new issue
Block a user