hare

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

commit 7bb8ad6a430050e6951811914ce54ce6c806c7e0
parent b941cad582645e7153bac8fdc0b5f761ebffa239
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed, 24 Feb 2021 16:16:18 -0500

os::dirfdfs: add subdir

Diffstat:
Mos/+linux/dirfdfs.ha | 38++++++++++++++++++++++++++++++++------
Mos/+linux/fs.ha | 2+-
2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/os/+linux/dirfdfs.ha b/os/+linux/dirfdfs.ha @@ -54,16 +54,20 @@ fn static_dirfdopen(fd: int, filesystem: *os_filesystem) *fs::fs = { }; // Opens a file descriptor as an [fs::fs]. This file descriptor must be a -// directory file. +// directory file. The file will be closed when the fs is closed. export fn dirfdopen(fd: int, resolve: resolve...) *fs::fs = { - let fs = alloc(os_filesystem { ... }); - let fsfs = static_dirfdopen(fd, fs); + let ofs = alloc(os_filesystem { ... }); + let fs = static_dirfdopen(fd, ofs); for (let i = 0z; i < len(resolve); i += 1) { - fs.resolve |= resolve[i]; + ofs.resolve |= resolve[i]; }; - return fsfs; + fs.close = &fs_close; + return fs; }; +// Opens a directory as a filesystem. +export fn diropen(path: fs::path) (*fs::fs | fs::error) = fs::subdir(cwd, path); + // Clones a dirfd filesystem, optionally adding additional [resolve] // constraints. export fn dirfs_clone(fs: *fs::fs, resolve: resolve...) *fs::fs = { @@ -160,5 +164,27 @@ fn fs_stat(fs: *fs::fs, path: fs::path) (fs::filestat | fs::error) = { }; fn fs_subdir(fs: *fs::fs, path: fs::path) (*fs::fs | fs::error) = { - abort(); + let fs = fs: *os_filesystem; + const p: []u8 = match (path) { + s: str => strings::to_utf8(s), + b: []u8 => b, + }; + + let oh = rt::open_how { + flags = (rt::O_RDONLY | rt::O_CLOEXEC | rt::O_DIRECTORY): u64, + ... + }; + + let fd: int = match (rt::openat2(fs.dirfd, p: *[*]u8: *const char, + &oh, size(rt::open_how))) { + err: rt::errno => return errno_to_io(err), + n: int => n, + }; + + return dirfdopen(fd); +}; + +fn fs_close(fs: *fs::fs) void = { + let fs = fs: *os_filesystem; + rt::close(fs.dirfd); }; diff --git a/os/+linux/fs.ha b/os/+linux/fs.ha @@ -4,7 +4,7 @@ use rt; @init fn init() void = { static let root_fs = os_filesystem { ... }; let dirfd = rt::open("/": *const char, - rt::O_RDONLY | rt::O_DIRECTORY, 0u) as int; + rt::O_RDONLY | rt::O_DIRECTORY | rt::O_CLOEXEC, 0u) as int; root = static_dirfdopen(dirfd, &root_fs); static let cwd_fs = os_filesystem { ... };