hare

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

commit 6f18f08a09d74f724fb0ffafc4a4618d44933f5b
parent 356b923c76e5abd1b2afb4bef24a8e478791b985
Author: Drew DeVault <sir@cmpwn.com>
Date:   Tue,  2 Jan 2024 12:34:00 +0100

os, fs: add fstat

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Mfs/fs.ha | 10++++++++++
Mfs/types.ha | 4++++
Mos/+linux/dirfdfs.ha | 16++++++++++++++++
Mos/os.ha | 3+++
4 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/fs/fs.ha b/fs/fs.ha @@ -176,6 +176,16 @@ export fn stat(fs: *fs, path: str) (filestat | error) = { }; }; +// Obtains information about an [[io::file]]. +export fn fstat(fs: *fs, fd: io::file) (filestat | error) = { + match (fs.fstat) { + case null => + return errors::unsupported; + case let f: *fstatfunc => + return f(fs, fd); + }; +}; + // Returns true if a node exists at the given path, or false if not. // // Note that testing for file existence before using the file can often lead to diff --git a/fs/types.ha b/fs/types.ha @@ -203,6 +203,7 @@ export type removefunc = fn(fs: *fs, path: str) (void | error); export type renamefunc = fn(fs: *fs, oldpath: str, newpath: str) (void | error); export type iterfunc = fn(fs: *fs, path: str) (*iterator | error); export type statfunc = fn(fs: *fs, path: str) (filestat | error); +export type fstatfunc = fn(fs: *fs, file: io::file) (filestat | error); export type mkdirfunc = fn(fs: *fs, path: str, mode: mode) (void | error); export type rmdirfunc = fn(fs: *fs, path: str) (void | error); export type chmodfunc = fn(fs: *fs, path: str, mode: mode) (void | error); @@ -279,6 +280,9 @@ export type fs = struct { // target. stat: nullable *statfunc, + // Obtains information about an [[io::file]]. + fstat: nullable *fstatfunc, + // Returns the path referred to by a symbolic link. The caller will free // the return value. readlink: nullable *readlinkfunc, diff --git a/os/+linux/dirfdfs.ha b/os/+linux/dirfdfs.ha @@ -70,6 +70,7 @@ fn static_dirfdopen(fd: io::file, filesystem: *os_filesystem) *fs::fs = { rename = &fs_rename, iter = &fs_iter, stat = &fs_stat, + fstat = &fs_fstat, readlink = &fs_readlink, mkdir = &fs_mkdir, rmdir = &fs_rmdir, @@ -259,6 +260,21 @@ fn fs_stat(fs: *fs::fs, path: str) (fs::filestat | fs::error) = { return errno_to_fs(err); case void => void; }; + return st_to_filestat(&st); +}; + +fn fs_fstat(fs: *fs::fs, fd: io::file) (fs::filestat | fs::error) = { + let fs = fs: *os_filesystem; + let st = rt::st { ... }; + match (rt::fstatat(fd, "", &st, rt::AT_EMPTY_PATH)) { + case let err: rt::errno => + return errno_to_fs(err); + case void => void; + }; + return st_to_filestat(&st); +}; + +fn st_to_filestat(st: *rt::st) fs::filestat = { return fs::filestat { mask = fs::stat_mask::UID | fs::stat_mask::GID diff --git a/os/os.ha b/os/os.ha @@ -35,6 +35,9 @@ export fn readdir(path: str) ([]fs::dirent | fs::error) = fs::readdir(cwd, path) // information is returned about the link, not its target. export fn stat(path: str) (fs::filestat | fs::error) = fs::stat(cwd, path); +// Returns file information for an [[io::file]]. +export fn fstat(fd: io::file) (fs::filestat | fs::error) = fs::fstat(cwd, fd); + // Returns true if a node exists at the given path, or false if not. // // Note that testing for file existence before using the file can often lead to