hare

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

commit ab15ef5930b0fdccd3323b2bb80e72d8087ac877
parent a4036327707bc4a69d35eeb3f929b32d89cb62da
Author: Alexey Yerin <yyp@disroot.org>
Date:   Sun, 21 Mar 2021 16:58:58 +0300

fs: implement chmod

Example usage: os::chmod("harec", fs::mode::USER_RWX);

Diffstat:
Mfs/fs.ha | 10++++++++++
Mfs/types.ha | 4++++
Mos/+linux/dirfdfs.ha | 9+++++++++
Mos/fs.ha | 3+++
Mrt/+linux/syscalls.ha | 14++++++++++++++
5 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/fs/fs.ha b/fs/fs.ha @@ -146,6 +146,16 @@ export fn mksubdir(fs: *fs, path: str) (*fs | error) = { }; }; +// Changes mode flags on a file or directory. Type bits are discared. +export fn chmod(fs: *fs, path: str, mode: mode) (void | error) = { + mode &= 0o755; + + return match (fs.chmod) { + f: *chmodfunc => f(fs, path, mode), + 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 @@ -179,6 +179,7 @@ export type subdirfunc = fn(fs: *fs, path: str) (*fs | error); 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 resolvefunc = fn(fs: *fs, path: str) str; export type openfunc = fn( @@ -233,6 +234,9 @@ export type fs = struct { // Creates a directory and returns a subdir for it. mksubdir: nullable *mksubdirfunc, + // Changes mode flags on a file or directory. + chmod: nullable *chmodfunc, + // 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 @@ -53,6 +53,7 @@ fn static_dirfdopen(fd: int, filesystem: *os_filesystem) *fs::fs = { subdir = &fs_subdir, mkdir = &fs_mkdir, rmdir = &fs_rmdir, + chmod = &fs_chmod, resolve = &fs_resolve, ... }, @@ -277,6 +278,14 @@ fn fs_mkdir(fs: *fs::fs, path: str) (void | fs::error) = { }; }; +fn fs_chmod(fs: *fs::fs, path: str, mode: fs::mode) (void | fs::error) = { + let fs = fs: *os_filesystem; + return match (rt::fchmodat(fs.dirfd, path, mode: uint)) { + 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 @@ -40,6 +40,9 @@ export fn rmdirall(path: str) (void | fs::error) = fs::rmdirall(cwd, path); // doing this operation atomically, but if not, a fallback is used. 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); + // 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 @@ -81,6 +81,20 @@ export fn unlinkat(dirfd: int, path: path, flags: int) (void | errno) = { return; }; +export fn chmod(path: path, mode: uint) (void | errno) = { + let path = kpath(path)?; + wrap_return(syscall3(SYS_fchmodat, + AT_FDCWD: u64, path: uintptr: u64, mode: u64)); + return; +}; + +export fn fchmodat(dirfd: int, path: path, mode: uint) (void | errno) = { + let path = kpath(path)?; + wrap_return(syscall3(SYS_fchmodat, + dirfd: u64, path: uintptr: u64, mode: u64))?; + return; +}; + export fn dup(fd: int) (int | errno) = { return wrap_return(syscall1(SYS_dup, fd: u64))?: int; };