diff --git a/src/header/sys_stat/mod.rs b/src/header/sys_stat/mod.rs index aa09ef21c0..6925cb5a81 100644 --- a/src/header/sys_stat/mod.rs +++ b/src/header/sys_stat/mod.rs @@ -160,6 +160,15 @@ pub unsafe extern "C" fn lstat(path: *const c_char, buf: *mut stat) -> c_int { res } +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn mkdirat(dirfd: c_int, path: *const c_char, mode: mode_t) -> c_int { + let path = CStr::from_ptr(path); + Sys::mkdirat(dirfd, path, mode) + .map(|()| 0) + .or_minus_one_errno() +} + /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn mkdir(path: *const c_char, mode: mode_t) -> c_int { diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 9bc285d11b..aa5636f684 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -504,8 +504,12 @@ impl Pal for Sys { e_raw(unsafe { syscall!(LSEEK, fildes, offset, whence) }).map(|o| o as off_t) } + fn mkdirat(dir_fildes: c_int, path: CStr, mode: mode_t) -> Result<()> { + e_raw(unsafe { syscall!(MKDIRAT, dir_fildes, path.as_ptr(), mode) }).map(|_| ()) + } + fn mkdir(path: CStr, mode: mode_t) -> Result<()> { - e_raw(unsafe { syscall!(MKDIRAT, AT_FDCWD, path.as_ptr(), mode) }).map(|_| ()) + Sys::mkdirat(AT_FDCWD, path, mode) } fn mknodat(dir_fildes: c_int, path: CStr, mode: mode_t, dev: dev_t) -> Result<()> { diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs index c0ed81c666..44602a6e9f 100644 --- a/src/platform/pal/mod.rs +++ b/src/platform/pal/mod.rs @@ -171,6 +171,8 @@ pub trait Pal { fn lseek(fildes: c_int, offset: off_t, whence: c_int) -> Result; + fn mkdirat(fildes: c_int, path: CStr, mode: mode_t) -> Result<()>; + fn mkdir(path: CStr, mode: mode_t) -> Result<()>; fn mkfifo(path: CStr, mode: mode_t) -> Result<()>; diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 2f59dc9002..ee2ede005f 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -681,6 +681,24 @@ impl Pal for Sys { Ok(syscall::lseek(fd as usize, offset as isize, whence as usize)? as off_t) } + fn mkdirat(dir_fd: c_int, path_name: CStr, mode: mode_t) -> Result<()> { + let mut dir_path_buf = [0; 4096]; + let res = Sys::fpath(dir_fd, &mut dir_path_buf)?; + + let dir_path = str::from_utf8(&dir_path_buf[..res as usize]).map_err(|_| Errno(EBADR))?; + + let resource_path = + path::canonicalize_using_cwd(Some(&dir_path), &path_name.to_string_lossy()) + // Since parent_dir_path is resolved by fpath, it is more likely that + // the problem was with path. + .ok_or(Errno(ENOENT))?; + + Sys::mkdir( + CStr::borrow(&CString::new(resource_path.as_bytes()).unwrap()), + mode, + ) + } + fn mkdir(path: CStr, mode: mode_t) -> Result<()> { File::create( path,