diff options
Diffstat (limited to 'ext/fs')
-rw-r--r-- | ext/fs/in_memory_fs.rs | 18 | ||||
-rw-r--r-- | ext/fs/interface.rs | 13 | ||||
-rw-r--r-- | ext/fs/std_fs.rs | 43 |
3 files changed, 74 insertions, 0 deletions
diff --git a/ext/fs/in_memory_fs.rs b/ext/fs/in_memory_fs.rs index e2babf40a..027539e84 100644 --- a/ext/fs/in_memory_fs.rs +++ b/ext/fs/in_memory_fs.rs @@ -178,6 +178,24 @@ impl FileSystem for InMemoryFs { self.chown_sync(&path, uid, gid) } + fn lchown_sync( + &self, + _path: &Path, + _uid: Option<u32>, + _gid: Option<u32>, + ) -> FsResult<()> { + Err(FsError::NotSupported) + } + + async fn lchown_async( + &self, + path: PathBuf, + uid: Option<u32>, + gid: Option<u32>, + ) -> FsResult<()> { + self.lchown_sync(&path, uid, gid) + } + fn remove_sync(&self, _path: &Path, _recursive: bool) -> FsResult<()> { Err(FsError::NotSupported) } diff --git a/ext/fs/interface.rs b/ext/fs/interface.rs index cb6fc4f63..f639a700b 100644 --- a/ext/fs/interface.rs +++ b/ext/fs/interface.rs @@ -146,6 +146,19 @@ pub trait FileSystem: std::fmt::Debug + MaybeSend + MaybeSync { gid: Option<u32>, ) -> FsResult<()>; + fn lchown_sync( + &self, + path: &Path, + uid: Option<u32>, + gid: Option<u32>, + ) -> FsResult<()>; + async fn lchown_async( + &self, + path: PathBuf, + uid: Option<u32>, + gid: Option<u32>, + ) -> FsResult<()>; + fn remove_sync(&self, path: &Path, recursive: bool) -> FsResult<()>; async fn remove_async(&self, path: PathBuf, recursive: bool) -> FsResult<()>; 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)?; |