diff options
author | Ori Bernstein <ori@eigenstate.org> | 2017-09-13 15:04:40 -0700 |
---|---|---|
committer | Ori Bernstein <ori@mmarkovcorp.com> | 2017-09-13 15:04:40 -0700 |
commit | 943c865bcfacb00af4c681fc36fbcab2b7f9a55f (patch) | |
tree | cf56947f5cad8e3c5197499d4943295c1f1a3e0a /lib | |
parent | 1f4389df622ed274371d0c134ffd3b1c5a94bd48 (diff) | |
download | mc-943c865bcfacb00af4c681fc36fbcab2b7f9a55f.tar.gz |
Add loop checking to libfileutil.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/fileutil/bld.sub | 3 | ||||
-rw-r--r-- | lib/fileutil/loopcheck+plan9.myr | 21 | ||||
-rw-r--r-- | lib/fileutil/loopcheck+posixy.myr | 65 | ||||
-rw-r--r-- | lib/fileutil/walk.myr | 19 |
4 files changed, 106 insertions, 2 deletions
diff --git a/lib/fileutil/bld.sub b/lib/fileutil/bld.sub index f308f6a..e54f88d 100644 --- a/lib/fileutil/bld.sub +++ b/lib/fileutil/bld.sub @@ -3,6 +3,9 @@ lib fileutil = homedir.myr tmpdir.myr + loopcheck+posixy.myr + loopcheck+plan9.myr + lib ../sys:sys lib ../std:std ;; diff --git a/lib/fileutil/loopcheck+plan9.myr b/lib/fileutil/loopcheck+plan9.myr new file mode 100644 index 0000000..64bc79f --- /dev/null +++ b/lib/fileutil/loopcheck+plan9.myr @@ -0,0 +1,21 @@ +use std + +/* plan 9 can't have directory loops, by construction, so this is nops */ +pkg fileutil = + type loopcheck = void + + const mkloopcheck : (cwd : byte[:] -> loopcheck) + const freeloopcheck : (l : loopcheck -> void) + const looped : (l : loopcheck, p : byte[:] -> bool) +;; + +const mkloopcheck = {cwd + -> (void : loopcheck) +} + +const freeloopcheck = {l, l +} + +const looped = {p + -> false +} 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 +} diff --git a/lib/fileutil/walk.myr b/lib/fileutil/walk.myr index 851c1f1..6af2af6 100644 --- a/lib/fileutil/walk.myr +++ b/lib/fileutil/walk.myr @@ -1,9 +1,12 @@ use std +use "loopcheck" + pkg fileutil = type walkiter = struct dirstk : std.dir#[:] curdir : byte[:][:] + loopck : loopcheck ;; impl iterable walkiter -> byte[:] @@ -13,9 +16,16 @@ pkg fileutil = const bywalk = {p match std.diropen(p) | `std.Ok d: - -> [.dirstk = std.sldup([d][:]), .curdir = std.sldup([std.sldup(p)][:])] + -> [ + .dirstk = std.sldup([d][:]), + .curdir = std.sldup([std.sldup(p)][:]), + .loopck = mkloopcheck(p), + ] | `std.Err e: - -> [.dirstk = [][:], .curdir = [][:]] + -> [ + .dirstk = [][:], + .curdir = [][:] + ] ;; } @@ -25,6 +35,7 @@ impl iterable walkiter -> byte[:] = :nextfile if itp.dirstk.len < 1 + freeloopcheck(itp.loopck) -> false ;; cur = itp.dirstk[itp.dirstk.len - 1] @@ -33,6 +44,10 @@ impl iterable walkiter -> byte[:] = | `std.Some "..": goto nextfile | `std.Some ent: p = std.pathcat(itp.curdir[itp.curdir.len - 1], ent) + if looped(itp.loopck, p) + std.slfree(p) + goto nextfile + ;; if std.fisdir(p) match std.diropen(p) | `std.Ok d: |