commit 7a79d0aa656d657142fca3831c2d65203f481a1a
parent 415c21046bb783f8b258f4e68a5c387382ea5a2a
Author: Alexey Yerin <yyp@disroot.org>
Date: Sun, 21 Mar 2021 22:16:39 +0300
fs: implement chown
Example usage:
os::chown("flag", 0, 0); // Change ownership of flag to root
To make this more useful, standard library also needs functions for
getting a user id and group id from their names, but that's for another
time.
Diffstat:
5 files changed, 38 insertions(+), 0 deletions(-)
diff --git a/fs/fs.ha b/fs/fs.ha
@@ -156,6 +156,14 @@ export fn chmod(fs: *fs, path: str, mode: mode) (void | error) = {
};
};
+// Changes ownership of a file.
+export fn chown(fs: *fs, path: str, uid: uint, gid: uint) (void | error) = {
+ return match (fs.chown) {
+ f: *chownfunc => f(fs, path, uid, gid),
+ null => abort(),
+ };
+};
+
// Resolves a path to its absolute, normalized value. This consoldates ./ and
// ../ sequences, roots the path, and returns a new path. The caller must free
// the return value.
diff --git a/fs/types.ha b/fs/types.ha
@@ -180,6 +180,7 @@ export type mkdirfunc = fn(fs: *fs, path: str) (void | error);
export type rmdirfunc = fn(fs: *fs, path: str) (void | error);
export type mksubdirfunc = fn(fs: *fs, path: str) (*fs | error);
export type chmodfunc = fn(fs: *fs, path: str, mode: mode) (void | error);
+export type chownfunc = fn(fs: *fs, path: str, uid: uint, gid: uint) (void | error);
export type resolvefunc = fn(fs: *fs, path: str) str;
export type openfunc = fn(
@@ -237,6 +238,9 @@ export type fs = struct {
// Changes mode flags on a file or directory.
chmod: nullable *chmodfunc,
+ // Changes ownership of a file.
+ chown: nullable *chownfunc,
+
// Resolves a path to its absolute, normalized value. If the fs
// implementation does not provide this, [resolve] presumes that
// relative paths are rooted (i.e. "foo" == "/foo").
diff --git a/os/+linux/dirfdfs.ha b/os/+linux/dirfdfs.ha
@@ -54,6 +54,7 @@ fn static_dirfdopen(fd: int, filesystem: *os_filesystem) *fs::fs = {
mkdir = &fs_mkdir,
rmdir = &fs_rmdir,
chmod = &fs_chmod,
+ chown = &fs_chown,
resolve = &fs_resolve,
...
},
@@ -286,6 +287,14 @@ fn fs_chmod(fs: *fs::fs, path: str, mode: fs::mode) (void | fs::error) = {
};
};
+fn fs_chown(fs: *fs::fs, path: str, uid: uint, gid: uint) (void | fs::error) = {
+ let fs = fs: *os_filesystem;
+ return match (rt::fchownat(fs.dirfd, path, uid, gid)) {
+ err: rt::errno => return errno_to_fs(err),
+ void => void,
+ };
+};
+
fn resolve_part(parts: *[]str, part: str) void = {
if (part == ".") {
// no-op
diff --git a/os/fs.ha b/os/fs.ha
@@ -43,6 +43,9 @@ export fn mksubdir(path: str) (*fs::fs | fs::error) = fs::mksubdir(cwd, path);
// Changes mode flags on a file or directory. Type bits are discared.
export fn chmod(path: str, mode: fs::mode) (void | fs::error) = fs::chmod(cwd, path, mode);
+// Changes ownership of a file.
+export fn chown(path: str, uid: uint, gid: uint) (void | fs::error) = fs::chown(cwd, path, uid, gid);
+
// Resolves a path to its absolute, normalized value. This consoldates ./ and
// ../ sequences, roots the path, and returns a new path. The caller must free
// the return value.
diff --git a/rt/+linux/syscalls.ha b/rt/+linux/syscalls.ha
@@ -95,6 +95,20 @@ export fn fchmodat(dirfd: int, path: path, mode: uint) (void | errno) = {
return;
};
+export fn chown(path: path, uid: uint, gid: uint) (void | errno) = {
+ let path = kpath(path)?;
+ wrap_return(syscall4(SYS_fchownat,
+ AT_FDCWD: u64, path: uintptr: u64, uid: u32, gid: u32));
+ return;
+};
+
+export fn fchownat(dirfd: int, path: path, uid: uint, gid: uint) (void | errno) = {
+ let path = kpath(path)?;
+ wrap_return(syscall4(SYS_fchownat,
+ dirfd: u64, path: uintptr: u64, uid: u32, gid: u32))?;
+ return;
+};
+
export fn dup(fd: int) (int | errno) = {
return wrap_return(syscall1(SYS_dup, fd: u64))?: int;
};