commit 73c1f66606a123d995d5bcab177b5b37f8d85186
parent e1260c73c34647d4841a27b59811a0f7150157bd
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 9 Jan 2022 16:29:15 +0100
fs: tweak fs::resolve
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
3 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/fs/fs.ha b/fs/fs.ha
@@ -252,16 +252,19 @@ export fn chown(fs: *fs, path: str, uid: uint, gid: uint) (void | error) = {
};
};
-// 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.
+// Resolves a path to its absolute, normalized value. Relative paths will be
+// rooted (if supported by the fs implementation), and "." and ".." components
+// will be reduced. This function does not follow symlinks: see [[realpath]] if
+// you need this behavior.
export fn resolve(fs: *fs, path: str) str = {
match (fs.resolve) {
case null => void;
case let f: *resolvefunc =>
return f(fs, path);
};
- abort(); // TODO
+ static let buf = path::buffer { ... };
+ path::set(&buf, path)!;
+ return path::string(&buf);
};
// Returns the next directory entry from an interator, or void if none remain.
diff --git a/hare/module/scan.ha b/hare/module/scan.ha
@@ -41,9 +41,10 @@ export fn scan(ctx: *context, path: str) (version | error) = {
case let ft: filetype =>
yield ft;
};
+ let path = fs::resolve(ctx.fs, path);
let st = fs::stat(ctx.fs, path)?;
let in = input {
- path = fs::resolve(ctx.fs, path),
+ path = strings::dup(path),
stat = st,
ft = ft,
hash = scan_file(ctx, path, &deps)?,
@@ -57,7 +58,7 @@ export fn scan(ctx: *context, path: str) (version | error) = {
return version {
hash = sumbuf,
- basedir = path::dirname(fs::resolve(ctx.fs, path)),
+ basedir = strings::dup(path::dirname(path)),
depends = deps,
inputs = inputs,
...
@@ -303,9 +304,10 @@ fn scan_directory(
let iter = fs::iter(ctx.fs, path)?;
scan_directory(ctx, ver, sha, path, iter)?;
} else {
+ let path = fs::resolve(ctx.fs, path);
let st = fs::stat(ctx.fs, path)?;
let in = input {
- path = fs::resolve(ctx.fs, path),
+ path = strings::dup(path),
stat = st,
ft = type_for_ext(path) as filetype,
hash = scan_file(ctx, path, &ver.depends)?,
diff --git a/os/+linux/dirfdfs.ha b/os/+linux/dirfdfs.ha
@@ -362,42 +362,13 @@ fn fs_chown(fs: *fs::fs, path: str, uid: uint, gid: uint) (void | fs::error) = {
};
};
-fn resolve_part(parts: *[]str, part: str) void = {
- if (part == ".") {
- // no-op
- void;
- } else if (part == "..") {
- if (len(parts) != 0) {
- delete(parts[len(parts) - 1]);
- };
- } else {
- append(parts, part);
- };
-};
-
fn fs_resolve(fs: *fs::fs, path: str) str = {
- let parts: []str = [];
- if (!path::abs(path)) {
- let iter = path::iter(getcwd());
- for (true) {
- match (path::next(&iter)) {
- case void =>
- break;
- case let p: str =>
- resolve_part(&parts, p);
- };
- };
- };
- let iter = path::iter(path);
- for (true) {
- match (path::next(&iter)) {
- case void =>
- break;
- case let p: str =>
- resolve_part(&parts, p);
- };
+ if (path::abs(path)) {
+ return path;
};
- return path::join(parts...);
+ static let buf = path::buffer { ... };
+ path::set(&buf, os::getcwd(), path)!;
+ return path::string(&buf);
};
fn fs_close(fs: *fs::fs) void = {