fs.fnl (2392B)
1 (local ll (require :lualinux)) 2 (import-macros { : define-tests : expect : expect= } :anoia.assert) 3 4 (local S_IFMT 0xf000) 5 (local S_IFSOCK 0xc000) 6 (local S_IFLNK 0xa000) 7 (local S_IFREG 0x8000) 8 (local S_IFBLK 0x6000) 9 (local S_IFDIR 0x4000) 10 (local S_IFCHR 0x2000) 11 (local S_IFIFO 0x1000) 12 13 (macro errno-check [x] 14 `(match ,x 15 val# val# 16 (nil errno#) (assert nil (.. "system call failed, errno=" errno#)) 17 )) 18 19 (fn ifmt-bits [mode] (and mode (band mode 0xf000))) 20 21 (fn file-type [pathname] 22 (. { 23 S_IFDIR :directory 24 S_IFSOCK :socket 25 S_IFLNK :link 26 S_IFREG :file 27 S_IFBLK :block-device 28 S_IFCHR :character-device 29 S_IFIFO :fifo 30 } 31 (ifmt-bits (ll.lstat3 pathname)))) 32 33 (fn directory? [pathname] 34 (= (file-type pathname) :directory)) 35 36 (fn mktree [pathname] 37 (if (or (= pathname "") (= pathname "/")) 38 (error (.. "can't mkdir " pathname))) 39 40 (or (directory? pathname) 41 (let [parent (string.gsub pathname "/[^/]+/?$" "")] 42 (or (directory? parent) (mktree parent)) 43 (errno-check (ll.mkdir pathname))))) 44 45 (fn dir [name] 46 (let [dp (errno-check (ll.opendir name) name)] 47 (fn [] 48 (case (ll.readdir dp) 49 (name filetype) (values name filetype) 50 (nil err) (do (if (> err 0) (print "ERR" err)) (ll.closedir dp) nil) 51 )))) 52 53 (fn rmtree [pathname] 54 (case (file-type pathname) 55 nil true 56 :directory 57 (do 58 (each [f (dir pathname)] 59 (when (not (or (= f ".") (= f ".."))) 60 (rmtree ( .. pathname "/" f))) 61 (ll.rmdir pathname))) 62 :file 63 (os.remove pathname) 64 :link 65 (os.remove pathname) 66 unknown 67 (error (.. "can't remove " pathname " of mode \"" unknown "\"")))) 68 69 ;; lualinux doesn't publish access(2), this is not exactly 70 ;; the same but will suffice until we can add it 71 (fn executable? [f] 72 (let [statbuf {} 73 stat (ll.lstat f statbuf 1)] 74 (and stat (> (band (. stat 3) 73) 0)))) ; \0111 75 76 (fn find-executable [exe search-path] 77 (accumulate [full-path nil 78 p (string.gmatch search-path "(.-):")] 79 (or full-path (let [f (.. p "/" exe)] (and (executable? f) f))))) 80 81 (define-tests 82 (let [p (find-executable "yes" (os.getenv "PATH"))] 83 (expect (string.match p "coreutils.+bin/yes$")))) 84 85 { 86 : mktree 87 : rmtree 88 : directory? 89 : dir 90 : file-type 91 : find-executable 92 :symlink (fn [from to] (ll.symlink from to)) 93 }