liminix/pkgs/anoia/fs.fnl

95 lines
2.3 KiB
Plaintext
Raw Normal View History

(local ll (require :lualinux))
(import-macros { : define-tests : expect : expect= } :anoia.assert)
(local S_IFMT 0xf000)
(local S_IFSOCK 0xc000)
(local S_IFLNK 0xa000)
(local S_IFREG 0x8000)
(local S_IFBLK 0x6000)
(local S_IFDIR 0x4000)
(local S_IFCHR 0x2000)
(local S_IFIFO 0x1000)
2024-08-08 10:36:47 +00:00
(macro errno-check [x]
`(match ,x
val# val#
(nil errno#) (assert nil (.. "system call failed, errno=" errno#))
))
(fn ifmt-bits [mode] (and mode (band mode 0xf000)))
2023-09-08 20:03:18 +00:00
2024-04-25 20:14:37 +00:00
(fn file-type [pathname]
(. {
S_IFDIR :directory
S_IFSOCK :socket
S_IFLNK :link
S_IFREG :file
S_IFBLK :block-device
S_IFCHR :character-device
S_IFIFO :fifo
}
(ifmt-bits (ll.lstat3 pathname))))
(fn directory? [pathname]
2024-04-25 20:14:37 +00:00
(= (file-type pathname) :directory))
(fn mktree [pathname]
(if (or (= pathname "") (= pathname "/"))
(error (.. "can't mkdir " pathname)))
(or (directory? pathname)
(let [parent (string.gsub pathname "/[^/]+/?$" "")]
(or (directory? parent) (mktree parent))
2024-08-08 10:36:47 +00:00
(errno-check (ll.mkdir pathname)))))
2024-04-25 20:14:37 +00:00
(fn dir [name]
2024-08-08 10:36:47 +00:00
(let [dp (errno-check (ll.opendir name) name)]
2024-04-25 20:14:37 +00:00
(fn []
(case (ll.readdir dp)
(name filetype) (values name filetype)
(nil err) (do (if (> err 0) (print "ERR" err)) (ll.closedir dp) nil)
))))
2024-04-25 20:14:37 +00:00
2023-09-08 20:03:18 +00:00
(fn rmtree [pathname]
2024-04-25 20:14:37 +00:00
(case (file-type pathname)
2023-09-08 20:03:18 +00:00
nil true
2024-04-25 20:14:37 +00:00
:directory
2023-09-08 20:03:18 +00:00
(do
2024-04-25 20:14:37 +00:00
(each [f (dir pathname)]
2023-09-08 20:03:18 +00:00
(when (not (or (= f ".") (= f "..")))
(rmtree ( .. pathname "/" f)))
2024-04-25 20:14:37 +00:00
(ll.rmdir pathname)))
:file
2023-09-08 20:03:18 +00:00
(os.remove pathname)
2024-04-25 20:14:37 +00:00
:link
2023-09-08 20:03:18 +00:00
(os.remove pathname)
unknown
(error (.. "can't remove " pathname " of mode \"" unknown "\""))))
2023-09-08 20:03:18 +00:00
;; lualinux doesn't publish access(2), this is not exactly
;; the same but will suffice until we can add it
(fn executable? [f]
(let [statbuf {}
stat (ll.lstat f statbuf 1)]
(and stat (> (band (. stat 3) 73) 0)))) ; \0111
(fn find-executable [exe search-path]
(accumulate [full-path nil
p (string.gmatch search-path "(.-):")]
(or full-path (let [f (.. p "/" exe)] (and (executable? f) f)))))
(define-tests
(let [p (find-executable "yes" (os.getenv "PATH"))]
(expect (string.match p "coreutils.+bin/yes$"))))
2023-09-08 20:03:18 +00:00
{
: mktree
: rmtree
: directory?
2024-04-25 20:14:37 +00:00
: dir
: file-type
: find-executable
:symlink (fn [from to] (ll.symlink from to))
}