commit 7bb8ad6a430050e6951811914ce54ce6c806c7e0
parent b941cad582645e7153bac8fdc0b5f761ebffa239
Author: Drew DeVault <sir@cmpwn.com>
Date: Wed, 24 Feb 2021 16:16:18 -0500
os::dirfdfs: add subdir
Diffstat:
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 { ... };