SAFEFS_EXAMPLE.lua (5654B)
1 -- SafeFS Usage Examples 2 -- Demonstrates how to use the SafeFS sandboxed filesystem 3 4 local SafeFS = require("os.libs.safefs") 5 6 -- Assume we have a root filesystem node 7 -- local root_fs = ... (your RamDisk root node) 8 9 -- Example 1: Create SafeFS instance with allowed directories 10 local sfs = SafeFS.new(root_fs, { 11 "/tmp/*", -- Allow all of /tmp 12 "/apps/com.dev.app/data/*", -- Allow app data directory 13 "~/documents/*" -- Allow user documents (expands to /home/username/documents) 14 }, "alice") -- Current user is "alice" 15 16 -- Example 2: Writing files 17 local success, err = sfs:write("/tmp/test.txt", "Hello, SafeFS!") 18 if success then 19 print("File written successfully") 20 else 21 print("Error: " .. err) 22 end 23 24 -- Example 3: Reading files 25 local content, err = sfs:read("/tmp/test.txt") 26 if content then 27 print("Content: " .. content) 28 else 29 print("Error: " .. err) 30 end 31 32 -- Example 4: Opening files with handles 33 local file, err = sfs:open("/tmp/data.txt", "w") 34 if file then 35 file:write("Line 1\n") 36 file:write("Line 2\n") 37 file:write("Line 3\n") 38 file:close() 39 print("File written with handle") 40 end 41 42 -- Read with handle 43 local file, err = sfs:open("/tmp/data.txt", "r") 44 if file then 45 local line = file:read("*l") 46 while line do 47 print("Line: " .. line) 48 line = file:read("*l") 49 end 50 file:close() 51 end 52 53 -- Example 5: Directory listing 54 local dirs, err = sfs:dirs("/tmp") 55 if dirs then 56 print("Directories in /tmp:") 57 for _, dir in ipairs(dirs) do 58 print(" " .. dir) 59 end 60 end 61 62 local files, err = sfs:files("/tmp") 63 if files then 64 print("Files in /tmp:") 65 for _, file in ipairs(files) do 66 print(" " .. file) 67 end 68 end 69 70 -- Example 6: Path traversal protection 71 -- This will NOT work - trying to escape the sandbox 72 local content, err = sfs:read("/tmp/../etc/passwd") 73 if not content then 74 print("Correctly blocked: " .. err) 75 end 76 77 -- Example 7: Relative path within sandbox (this DOES work) 78 sfs:mkdir("/tmp/subdir") 79 sfs:write("/tmp/subdir/file.txt", "test") 80 -- Navigate using .. 81 local content, err = sfs:read("/tmp/subdir/../test.txt") 82 if content then 83 print("Relative path worked: " .. content) 84 end 85 86 -- Example 8: Tilde expansion 87 local success, err = sfs:write("~/documents/note.txt", "My personal note") 88 -- This writes to /home/alice/documents/note.txt 89 90 -- Example 9: Check existence 91 if sfs:exists("/tmp/test.txt") then 92 print("File exists") 93 end 94 95 local fileType = sfs:getType("/tmp/test.txt") 96 print("Type: " .. (fileType or "not found")) 97 98 -- Example 10: Delete files 99 local success, err = sfs:delete("/tmp/test.txt") 100 if success then 101 print("File deleted") 102 end 103 104 -- Example 11: Create nested directories 105 sfs:mkdir("/tmp/a/b/c") -- Creates entire path 106 sfs:write("/tmp/a/b/c/deep.txt", "Deep file") 107 108 -- Example 12: Append mode 109 local file = sfs:open("/tmp/log.txt", "w") 110 file:write("Initial log entry\n") 111 file:close() 112 113 local file = sfs:open("/tmp/log.txt", "a") 114 file:write("Second log entry\n") 115 file:write("Third log entry\n") 116 file:close() 117 118 -- Example 13: Read entire file 119 local content = sfs:read("/tmp/log.txt") 120 print("Full log:\n" .. content) 121 122 -- Example 14: Use in LPM app sandbox 123 -- In your LPM implementation, create SafeFS for each app: 124 --[[ 125 function LPM:run(app_name) 126 local app_dir = "/apps/com.example.myapp" 127 128 -- Create SafeFS with only app's directories 129 local safeFS = SafeFS.new(root_fs, { 130 app_dir .. "/data/*", 131 app_dir .. "/tmp/*", 132 app_dir .. "/settings/*", 133 "/tmp/*" -- Optional: allow system tmp 134 }) 135 136 -- Pass to sandbox 137 local sandbox = { 138 fs = safeFS, 139 -- ... other sandbox globals 140 } 141 142 -- App can now use: 143 -- fs:write("$/data/save.txt", data) -- After resolving $ to app_dir 144 -- fs:read("$/settings/config.txt") 145 end 146 ]]-- 147 148 -- Example 15: Multiple isolated instances 149 local app1_fs = SafeFS.new(root_fs, {"/apps/com.app1/data/*"}) 150 local app2_fs = SafeFS.new(root_fs, {"/apps/com.app2/data/*"}) 151 152 -- App 1 can only access its own data 153 app1_fs:write("/apps/com.app1/data/secret.txt", "App 1 secret") 154 155 -- App 2 cannot access App 1's data 156 local content, err = app2_fs:read("/apps/com.app1/data/secret.txt") 157 -- This will fail: "Path not in SafeFS" 158 159 -- Example 16: Path manipulation with fileName() and parentDir() 160 local filename = sfs:fileName("/tmp/subdir/data.txt") 161 print("Filename: " .. filename) -- Output: "data.txt" 162 163 local parent = sfs:parentDir("/tmp/subdir/data.txt") 164 print("Parent: " .. parent) -- Output: "/tmp/subdir" 165 166 -- Get grandparent 167 local grandparent = sfs:parentDir(parent) 168 print("Grandparent: " .. grandparent) -- Output: "/tmp" 169 170 -- Example 17: List all files with their full paths 171 local function listFilesRecursive(safeFS, path, prefix) 172 prefix = prefix or "" 173 local files = safeFS:files(path) 174 local dirs = safeFS:dirs(path) 175 176 if files then 177 for _, file in ipairs(files) do 178 print(prefix .. path .. "/" .. file) 179 end 180 end 181 182 if dirs then 183 for _, dir in ipairs(dirs) do 184 listFilesRecursive(safeFS, path .. "/" .. dir, prefix .. " ") 185 end 186 end 187 end 188 189 print("\nAll files in /tmp:") 190 listFilesRecursive(sfs, "/tmp") 191 192 -- Example 18: Check if dirs() and files() return names only 193 local dirs = sfs:dirs("/tmp") 194 print("\nDirectories in /tmp (names only):") 195 for _, dir in ipairs(dirs) do 196 print(" " .. dir) -- Just the name, not a node object 197 end 198 199 local files = sfs:files("/tmp") 200 print("\nFiles in /tmp (names only):") 201 for _, file in ipairs(files) do 202 print(" " .. file) -- Just the name, not a node object 203 end 204 205 print("\nSafeFS examples complete!")