Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/host_env/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
22 changes: 11 additions & 11 deletions crates/host_env/src/crt_fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down
3 changes: 3 additions & 0 deletions crates/host_env/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
28 changes: 10 additions & 18 deletions crates/host_env/src/posix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)]
Expand Down
20 changes: 10 additions & 10 deletions crates/host_env/src/posix_wasi.rs
Original file line number Diff line number Diff line change
@@ -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<()> {
Expand Down
22 changes: 22 additions & 0 deletions crates/host_env/src/posix_windows.rs
Original file line number Diff line number Diff line change
@@ -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)
}
44 changes: 21 additions & 23 deletions crates/vm/src/stdlib/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
}
_ => {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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")));
Expand Down Expand Up @@ -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]
Expand Down
Loading