diff options
Diffstat (limited to 'ext/fs/std_fs.rs')
-rw-r--r-- | ext/fs/std_fs.rs | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/ext/fs/std_fs.rs b/ext/fs/std_fs.rs index c501b8928..7903700c3 100644 --- a/ext/fs/std_fs.rs +++ b/ext/fs/std_fs.rs @@ -303,6 +303,24 @@ impl FileSystem for RealFs { .await? } + fn lchown_sync( + &self, + path: &Path, + uid: Option<u32>, + gid: Option<u32>, + ) -> FsResult<()> { + lchown(path, uid, gid) + } + + async fn lchown_async( + &self, + path: PathBuf, + uid: Option<u32>, + gid: Option<u32>, + ) -> FsResult<()> { + spawn_blocking(move || lchown(&path, uid, gid)).await? + } + fn write_file_sync( &self, path: &Path, @@ -431,6 +449,31 @@ fn chown(_path: &Path, _uid: Option<u32>, _gid: Option<u32>) -> FsResult<()> { Err(FsError::NotSupported) } +#[cfg(unix)] +fn lchown(path: &Path, uid: Option<u32>, gid: Option<u32>) -> FsResult<()> { + use std::os::unix::ffi::OsStrExt; + let c_path = std::ffi::CString::new(path.as_os_str().as_bytes()).unwrap(); + // -1 = leave unchanged + let uid = uid + .map(|uid| uid as libc::uid_t) + .unwrap_or(-1i32 as libc::uid_t); + let gid = gid + .map(|gid| gid as libc::gid_t) + .unwrap_or(-1i32 as libc::gid_t); + // SAFETY: `c_path` is a valid C string and lives throughout this function call. + let result = unsafe { libc::lchown(c_path.as_ptr(), uid, gid) }; + if result != 0 { + return Err(io::Error::last_os_error().into()); + } + Ok(()) +} + +// TODO: implement lchown for Windows +#[cfg(not(unix))] +fn lchown(_path: &Path, _uid: Option<u32>, _gid: Option<u32>) -> FsResult<()> { + Err(FsError::NotSupported) +} + fn remove(path: &Path, recursive: bool) -> FsResult<()> { // TODO: this is racy. This should open fds, and then `unlink` those. let metadata = fs::symlink_metadata(path)?; |