summaryrefslogtreecommitdiff
path: root/lib/fileutil/loopcheck+posixy.myr
diff options
context:
space:
mode:
Diffstat (limited to 'lib/fileutil/loopcheck+posixy.myr')
-rw-r--r--lib/fileutil/loopcheck+posixy.myr65
1 files changed, 65 insertions, 0 deletions
diff --git a/lib/fileutil/loopcheck+posixy.myr b/lib/fileutil/loopcheck+posixy.myr
new file mode 100644
index 0000000..784fe3f
--- /dev/null
+++ b/lib/fileutil/loopcheck+posixy.myr
@@ -0,0 +1,65 @@
+use std
+use sys
+
+/* plan 9 can't have directory loops, by construction, so this is nops */
+pkg fileutil =
+ type loopcheck = std.htab((int64, int64), void)#
+
+ const mkloopcheck : (cwd : byte[:] -> loopcheck)
+ const freeloopcheck : (l : loopcheck -> void)
+ const looped : (l : loopcheck, p : byte[:] -> bool)
+;;
+
+const mkloopcheck = {cwd
+ var ht : std.htab((int64, int64), void)#
+ var l
+
+ ht = std.mkht(fidhash, fideq)
+ l = (ht : loopcheck)
+ looped(l, cwd)
+ -> l
+}
+
+const freeloopcheck = {l
+ std.htfree((l : std.htab((int64, int64), void)#))
+}
+
+const looped = {l, p
+ var ht, has
+
+ ht = (l : std.htab((int64, int64), void)#)
+ match fid(p)
+ | `std.Err e:
+ -> false
+ | `std.Ok id:
+ has = std.hthas(ht, id)
+ std.htput(ht, id, void)
+ -> has
+ ;;
+}
+
+const fid = {p
+ var sb
+
+ if sys.stat(p, &sb) != 0
+ -> `std.Err void
+ else
+ -> `std.Ok ((sb.dev : int64), (sb.ino : int64))
+ ;;
+}
+
+const fidhash = {fid
+ var dev, ino
+
+ (dev, ino) = fid
+ -> std.inthash(dev) ^ std.inthash(ino)
+}
+
+const fideq = {a, b
+ var adev, aino
+ var bdev, bino
+
+ (adev, aino) = a
+ (bdev, bino) = b
+ -> adev == bdev && aino == bino
+}