summaryrefslogtreecommitdiff
path: root/ext/fs/std_fs.rs
diff options
context:
space:
mode:
authorNathan Whitaker <17734409+nathanwhit@users.noreply.github.com>2024-07-05 11:32:51 -0700
committerGitHub <noreply@github.com>2024-07-05 18:32:51 +0000
commitd4d3a3c54f5e26dec0cc79e273dc488f8a47f2b3 (patch)
treee6ff88b550211257ea7a7997e221d10fdf22e242 /ext/fs/std_fs.rs
parent28d2ff7bdc023a3b7aff47503aa03a8dd65fe87f (diff)
fix(node): Implement `fs.lchown` (and `process.getegid`) (#24418)
Closes https://github.com/denoland/deno/issues/21260. Part of https://github.com/denoland/deno/issues/18218. Implements `node:fs.lchown`, and enables the node_compat test for it. The test uses `process.getegid`, which we didn't have implemented, so I went ahead and implemented that as well to get the test working.
Diffstat (limited to 'ext/fs/std_fs.rs')
-rw-r--r--ext/fs/std_fs.rs43
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)?;