Skip to content

Commit e877e21

Browse files
(WIP) Add tmpfs filesystem type
1 parent 4eff3f6 commit e877e21

2 files changed

Lines changed: 128 additions & 3 deletions

File tree

vfs/init.lisp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
(import lua/basic (set-idx!))
22
(import vfs/ccfs ccfs)
3+
(import vfs/tmpfs tmpfs)
34

45
(defun create-vfs (vfs-mounts)
56
(let* [(mounts {})
@@ -26,9 +27,10 @@
2627
[(elem? "t" attributes) 'tmpfs ]
2728
[true (error! "file system type not found.")]))
2829
(read-only (not (elem? "w" attributes)))]
29-
(if (eq? fs-type 'realfs)
30-
(.<! mounts mount-point (ccfs/create dir read-only))
31-
(error! "unimplemented."))))
30+
(case fs-type
31+
[realfs (.<! mounts mount-point (ccfs/create dir read-only))]
32+
[tmpfs (.<! mounts mount-point (tmpfs/create dir))]
33+
[else (error! "unimplemented.")])))
3234

3335
{ :list dir-list
3436
:exists (wrap-fun :exists)

vfs/tmpfs.lisp

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
(import lua/basic (type#))
2+
(import util (log!))
3+
4+
(defun access-tree! (inode path contents) :hidden
5+
(log! (.. "path: " path))
6+
(if (= path "")
7+
inode
8+
(let* [(path-parts (string/split path "%/"))
9+
(child-inode (.> inode (car path-parts)))]
10+
(if (> (n path-parts) 1)
11+
(if (= (type# child-inode) "table")
12+
(access-tree! inode (string/concat (cdr path-parts) "/") contents)
13+
(error! "No such file or directory"))
14+
(if (/= (type# contents) "nil")
15+
(.<! inode (car path-parts) (or contents nil))
16+
(if (/= (type# child-inode) "nil")
17+
child-inode
18+
(error! "No such file or directory")))))))
19+
20+
(defun create-handle (methods) :hidden
21+
(let* [(handle {})
22+
(closed false)
23+
(handle-methods
24+
(merge methods
25+
{ :close (lambda () (set! closed true)) })) ]
26+
(do [(method-name (keys handle-methods))]
27+
(.<! handle method-name
28+
(lambda (&args)
29+
(if (not closed)
30+
((.> handle-methods method-name) (splice args))
31+
(error! "Attempt to use a closed file")))))
32+
handle))
33+
34+
(defun open-read-file! (fs-tree path binary) :hidden
35+
(with (inode (access-tree! fs-tree path))
36+
(if (/= (type# inode) "string")
37+
(error! "Could not open file for reading")
38+
(if binary
39+
(with (index 1)
40+
(create-handle
41+
{ :read (lambda ()
42+
(with (result (string/byte (string/sub inode index index)))
43+
(inc! index)
44+
result)) }))
45+
(with (left-contents inode)
46+
(create-handle
47+
{ :readLine (lambda ()
48+
(if left-contents
49+
(with (lines (string/split left-contents "\n"))
50+
(if (and (> (n lines) 1) (or (/= (n lines) 2) (/= (cadr lines) "")))
51+
(set! left-contents (string/concat (cdr lines) "\n"))
52+
(set! left-contents nil))
53+
(car lines))
54+
nil))
55+
:readAll (lambda ()
56+
(with (result (or left-contents ""))
57+
(set! left-contents nil)
58+
result)) }))))))
59+
60+
(defun open-write-file! (fs-tree path append binary) :hidden
61+
(let* [(contents (if append
62+
(access-tree! fs-tree path)
63+
""))
64+
(write-contents! (lambda ()
65+
(access-tree! fs-tree path contents)))]
66+
(if (/= (type# contents) "string")
67+
(error! "Could not open file for writing")
68+
(progn
69+
(access-tree! fs-tree path contents)
70+
; TODO: Optimise this so it doesn't traverse the tree on every write.
71+
(if binary
72+
(create-handle
73+
{ :write (lambda (b)
74+
(set! contents (.. contents (string/char b)))
75+
(write-contents!)) })
76+
(create-handle
77+
{ :write (lambda (str)
78+
(set! contents (.. contents str))
79+
(write-contents!))
80+
:writeLine (lambda (str)
81+
(set! contents (.. contents str "\n"))
82+
(write-contents!)) }))))))
83+
84+
(defun open-file! (fs-tree path mode) :hidden
85+
(log! (.. "open file " path " mode " mode))
86+
(let* [(f-mode (string/sub mode 1 1))
87+
(binary (= (string/sub mode 2 2) "b"))
88+
((success handle)
89+
(pcall (lambda ()
90+
(if (= f-mode "r")
91+
(open-read-file! fs-tree path binary)
92+
(open-write-file! fs-tree path (= f-mode "a") binary)))))]
93+
(if success
94+
handle
95+
(splice (list nil handle)))))
96+
97+
98+
(defun create (file)
99+
(let* [(fs-tree {})]
100+
{ :list (lambda (path)
101+
(with (inode (access-tree! fs-tree path))
102+
(if (= (type# inode) "table")
103+
(list->struct (keys inode))
104+
(error! "Not a directory"))))
105+
:exists (lambda (path)
106+
(with ((ok inode) (pcall (lambda () (access-tree! fs-tree path))))
107+
ok))
108+
:isDir (lambda (path)
109+
(with ((ok inode) (pcall (lambda () (access-tree! fs-tree path))))
110+
(and ok
111+
(= (type# inode) "table"))))
112+
:isReadOnly (const false)
113+
:getSize (const 0)
114+
:getFreeSpace (const 1000000000)
115+
:makeDir (lambda (path)
116+
(access-tree! fs-tree path {})
117+
(log! (.. "tree: " (pretty fs-tree))))
118+
:move (const nil)
119+
:copy (const nil)
120+
:delete (lambda (path) (access-tree! fs-tree path false))
121+
:open (cut open-file! fs-tree <> <>) }))
122+
123+

0 commit comments

Comments
 (0)