commit 03dfff2f8ead1006cf5c81cdff7ebfd820efc0ea
parent 5af7c7492be23d17f8b25a3669f15d380b383f76
Author: Drew DeVault <sir@cmpwn.com>
Date: Thu, 11 Mar 2021 12:07:54 -0500
os: add os::resolve
Diffstat:
2 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/os/+linux/dirfdfs.ha b/os/+linux/dirfdfs.ha
@@ -12,7 +12,7 @@ use strings;
//
// Note that on Linux, specifying BENEATH or IN_ROOT will also disable magic
// symlinks.
-export type resolve = enum {
+export type resolve_flags = enum {
NORMAL,
// Does not allow symlink resolution to occur for any symlinks which
@@ -38,7 +38,7 @@ export type resolve = enum {
type os_filesystem = struct {
fs: fs::fs,
dirfd: int,
- resolve: resolve,
+ resolve: resolve_flags,
};
fn static_dirfdopen(fd: int, filesystem: *os_filesystem) *fs::fs = {
@@ -67,7 +67,7 @@ fn static_dirfdopen(fd: int, filesystem: *os_filesystem) *fs::fs = {
// a dirfdfs, [fs::flags::NOCTTY] and [fs::flags::CLOEXEC] are used when opening
// the file. If you pass your own flags, it is recommended that you add these
// unless you know that you do not want them.
-export fn dirfdopen(fd: int, resolve: resolve...) *fs::fs = {
+export fn dirfdopen(fd: int, resolve: resolve_flags...) *fs::fs = {
let ofs = alloc(os_filesystem { ... });
let fs = static_dirfdopen(fd, ofs);
for (let i = 0z; i < len(resolve); i += 1) {
@@ -77,9 +77,9 @@ export fn dirfdopen(fd: int, resolve: resolve...) *fs::fs = {
return fs;
};
-// Clones a dirfd filesystem, optionally adding additional [resolve]
+// Clones a dirfd filesystem, optionally adding additional [resolve_flags]
// constraints.
-export fn dirfs_clone(fs: *fs::fs, resolve: resolve...) *fs::fs = {
+export fn dirfs_clone(fs: *fs::fs, resolve: resolve_flags...) *fs::fs = {
assert(fs.open == &fs_open);
let fs = fs: *os_filesystem;
let new = alloc(*fs);
@@ -99,16 +99,16 @@ fn _fs_open(
let fs = fs: *os_filesystem;
oh.resolve = 0u64;
- if (fs.resolve & resolve::BENEATH == resolve::BENEATH) {
+ if (fs.resolve & resolve_flags::BENEATH == resolve_flags::BENEATH) {
oh.resolve |= rt::RESOLVE_BENEATH | rt::RESOLVE_NO_MAGICLINKS;
};
- if (fs.resolve & resolve::IN_ROOT == resolve::IN_ROOT) {
+ if (fs.resolve & resolve_flags::IN_ROOT == resolve_flags::IN_ROOT) {
oh.resolve |= rt::RESOLVE_IN_ROOT | rt::RESOLVE_NO_MAGICLINKS;
};
- if (fs.resolve & resolve::NO_SYMLINKS == resolve::NO_SYMLINKS) {
+ if (fs.resolve & resolve_flags::NO_SYMLINKS == resolve_flags::NO_SYMLINKS) {
oh.resolve |= rt::RESOLVE_NO_SYMLINKS;
};
- if (fs.resolve & resolve::NO_XDEV == resolve::NO_XDEV) {
+ if (fs.resolve & resolve_flags::NO_XDEV == resolve_flags::NO_XDEV) {
oh.resolve |= rt::RESOLVE_NO_XDEV;
};
diff --git a/os/fs.ha b/os/fs.ha
@@ -39,3 +39,8 @@ export fn rmdirall(path: str) (void | fs::error) = fs::rmdirall(cwd, path);
// Creates a directory and returns a subdir for it. Some filesystems support
// doing this operation atomically, but if not, a fallback is used.
export fn mksubdir(path: str) (*fs::fs | fs::error) = fs::mksubdir(cwd, path);
+
+// 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.
+export fn resolve(path: str) str = fs::resolve(cwd, path);