Skip to content

Commit eb71c5c

Browse files
host_env: os.mkdir for Windows, Redox
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.
1 parent fe2a7db commit eb71c5c

4 files changed

Lines changed: 48 additions & 48 deletions

File tree

‎crates/host_env/Cargo.toml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ paste = { workspace = true }
2020

2121
[target.'cfg(unix)'.dependencies]
2222
nix = { workspace = true }
23+
24+
[target.'cfg(any(unix, target_os = "macos", target_os = "redox", target_os = "wasi"))'.dependencies]
2325
rustix = { workspace = true }
2426

2527
[target.'cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))'.dependencies]

‎crates/host_env/src/posix.rs‎

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use std::os::fd::FromRawFd;
1010
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, IntoRawFd, OwnedFd};
1111
use std::path::Path;
1212

13+
use crate::crt_fd;
14+
1315
pub struct UnameInfo {
1416
pub sysname: String,
1517
pub nodename: String,
@@ -174,24 +176,25 @@ pub fn fcopyfile(in_fd: i32, out_fd: i32, flags: u32) -> std::io::Result<()> {
174176
}
175177
}
176178

177-
#[cfg(not(windows))]
178-
pub fn make_dir(path: &CStr, mode: u32) -> std::io::Result<()> {
179-
let ret = unsafe { libc::mkdir(path.as_ptr(), mode as _) };
180-
if ret < 0 {
181-
Err(std::io::Error::last_os_error())
182-
} else {
183-
Ok(())
184-
}
179+
#[cfg(not(unix))]
180+
pub fn make_dir(
181+
dir_fd: Option<crt_fd::Borrowed<'_>>,
182+
path: &impl AsRef<Path>,
183+
_mode: i32,
184+
) -> std::io::Result<()> {
185+
debug_assert!(dir_fd.is_none());
186+
// TODO: On Windows, Python has an override if the mode is 0o700
187+
std::fs::create_dir(path)
185188
}
186189

187-
#[cfg(all(not(windows), not(target_os = "redox")))]
188-
pub fn make_dir_at(dir_fd: i32, path: &CStr, mode: u32) -> std::io::Result<()> {
189-
let ret = unsafe { libc::mkdirat(dir_fd, path.as_ptr(), mode as _) };
190-
if ret < 0 {
191-
Err(std::io::Error::last_os_error())
192-
} else {
193-
Ok(())
194-
}
190+
#[cfg(unix)]
191+
pub fn make_dir(
192+
dir_fd: Option<crt_fd::Borrowed<'_>>,
193+
path: &impl AsRef<Path>,
194+
mode: libc::mode_t,
195+
) -> std::io::Result<()> {
196+
let dir_fd = dir_fd.as_ref().map_or(rustix::fs::CWD, AsFd::as_fd);
197+
rustix::fs::mkdirat(dir_fd, path.as_ref(), mode.into()).map_err(Into::into)
195198
}
196199

197200
#[cfg(unix)]

‎crates/host_env/src/posix_wasi.rs‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
use alloc::ffi::CString;
22
use core::{ffi::CStr, time::Duration};
3-
use std::{ffi::OsStr, io};
3+
use rustix::fd::AsFd;
4+
use std::{ffi::OsStr, io, path::Path};
45

5-
use crate::os::CheckLibcResult;
6+
use crate::{crt_fd, os::CheckLibcResult};
67

7-
pub fn make_dir(path: &CStr, mode: u32) -> io::Result<()> {
8-
unsafe { libc::mkdir(path.as_ptr(), mode as _) }.check_libc_neg()?;
9-
Ok(())
10-
}
11-
12-
pub fn make_dir_at(dir_fd: i32, path: &CStr, mode: u32) -> io::Result<()> {
13-
unsafe { libc::mkdirat(dir_fd, path.as_ptr(), mode as _) }.check_libc_neg()?;
14-
Ok(())
8+
pub fn make_dir(
9+
dir_fd: Option<crt_fd::Borrowed<'_>>,
10+
path: &impl AsRef<Path>,
11+
mode: libc::mode_t,
12+
) -> std::io::Result<()> {
13+
let dir_fd = dir_fd.as_ref().map_or(rustix::fs::CWD, AsFd::as_fd);
14+
rustix::fs::mkdirat(dir_fd, path.as_ref(), mode.into()).map_err(Into::into)
1515
}
1616

1717
pub fn remove_dir_at(dir_fd: i32, path: &CStr) -> io::Result<()> {

‎crates/vm/src/stdlib/os.rs‎

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ use crate::{
1010
};
1111
use std::{io, path::Path};
1212

13+
#[cfg(not(windows))]
14+
use libc::mode_t;
15+
16+
#[cfg(windows)]
17+
type mode_t = i32;
18+
1319
pub(crate) fn fs_metadata<P: AsRef<Path>>(
1420
path: P,
1521
follow_symlink: bool,
@@ -29,7 +35,7 @@ pub struct TargetIsDirectory {
2935
}
3036

3137
cfg_select! {
32-
all(any(unix, target_os = "wasi"), not(target_os = "redox")) => {
38+
any(unix, target_os = "wasi") => {
3339
use libc::AT_FDCWD;
3440
}
3541
_ => {
@@ -154,7 +160,7 @@ impl ToPyObject for crt_fd::Borrowed<'_> {
154160

155161
#[pymodule(sub)]
156162
pub(super) mod _os {
157-
use super::{DirFd, FollowSymlinks, SupportFunc};
163+
use super::{DirFd, FollowSymlinks, SupportFunc, mode_t};
158164
use crate::host_env::fileutils::StatStruct;
159165
#[cfg(any(unix, windows))]
160166
use crate::utils::ToCString;
@@ -184,7 +190,7 @@ pub(super) mod _os {
184190
use std::{fs, io, path::PathBuf, time::SystemTime};
185191

186192
const OPEN_DIR_FD: bool = cfg!(not(any(windows, target_os = "redox")));
187-
pub(crate) const MKDIR_DIR_FD: bool = cfg!(not(any(windows, target_os = "redox")));
193+
pub(crate) const MKDIR_DIR_FD: bool = cfg!(any(unix, target_os = "wasi"));
188194
const STAT_DIR_FD: bool = cfg!(not(any(windows, target_os = "redox")));
189195
const UTIME_DIR_FD: bool = cfg!(not(any(windows, target_os = "redox")));
190196
pub(crate) const SYMLINK_DIR_FD: bool = cfg!(not(any(windows, target_os = "redox")));
@@ -338,32 +344,21 @@ pub(super) mod _os {
338344
}
339345
}
340346

341-
#[cfg(not(windows))]
342347
#[pyfunction]
343348
fn mkdir(
344349
path: OsPath,
345-
mode: OptionalArg<i32>,
350+
mode: OptionalArg<mode_t>,
346351
dir_fd: DirFd<'_, { MKDIR_DIR_FD as usize }>,
347352
vm: &VirtualMachine,
348353
) -> PyResult<()> {
349354
let mode = mode.unwrap_or(0o777);
350-
let c_path = path.clone().into_cstring(vm)?;
351-
#[cfg(not(target_os = "redox"))]
352-
if let Some(fd) = dir_fd.raw_opt() {
353-
return if let Err(err) =
354-
crate::host_env::posix::make_dir_at(fd, c_path.as_c_str(), mode as u32)
355-
{
356-
Err(OSErrorBuilder::with_filename(&err, path, vm))
357-
} else {
358-
Ok(())
359-
};
360-
}
361-
#[cfg(target_os = "redox")]
362-
let [] = dir_fd.0;
363-
if let Err(err) = crate::host_env::posix::make_dir(c_path.as_c_str(), mode as u32) {
364-
return Err(OSErrorBuilder::with_filename(&err, path, vm));
365-
}
366-
Ok(())
355+
#[cfg(any(unix, target_os = "wasi"))]
356+
let dir_fd = dir_fd.get_opt();
357+
#[cfg(not(any(unix, target_os = "wasi")))]
358+
let dir_fd = None;
359+
360+
crate::host_env::posix::make_dir(dir_fd, &path.path, mode)
361+
.map_err(|err| OSErrorBuilder::with_filename(&err, path, vm))
367362
}
368363

369364
#[pyfunction]

0 commit comments

Comments
 (0)