hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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:
Mfs/fs.ha | 8++++++++
Mfs/types.ha | 4++++
Mos/+linux/dirfdfs.ha | 9+++++++++
Mos/fs.ha | 3+++
Mrt/+linux/syscalls.ha | 14++++++++++++++
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; };