Filesystem Structure
Directory layout and SafeFS API
Root Directory Layout
/
├── apps/ # Installed applications
│ └── com.developer.app/ # App directory (reverse domain naming)
│ ├── manifest.lua # App manifest (required)
│ ├── icon.png # App icon (optional, PNG or BMP)
│ └── src/ # Source code directory
│ └── init.lua # Entry point (or as specified in manifest)
│
├── home/ # User home directory (~)
│ └── Documents/ # User documents
│
├── keys/ # Developer signing keys (LAM)
│ └── developer_name/ # Per-developer key storage
│ ├── public.key # ED25519 public key (base64)
│ └── secret.key # ED25519 secret key (base64)
│
├── os/ # Operating system files
│ ├── init.lua # OS initialization
│ ├── postinit.lua # Post-initialization (starts apps)
│ ├── libs/ # System libraries
│ │ ├── Application.lua # App framework
│ │ ├── safefs.lua # SafeFS implementation
│ │ ├── run.lua # App launcher
│ │ ├── scheduler.lua # Process scheduler
│ │ ├── sys.lua # System APIs
│ │ ├── dialogs.lua # Dialog system
│ │ ├── LAM.lua # Application manager
│ │ ├── Hook.lua # Event hook system
│ │ ├── Image.lua # Image handling
│ │ ├── PNG.lua # PNG decoder
│ │ └── ...
│ ├── public/ # Public OS resources
│ │ └── res/ # Resources (backgrounds, etc.)
│ └── res/ # System resources
│ └── default.bmp # Default app icon
│
├── proc/ # Process information (virtual)
│ └── <pid>/ # Per-process directory
│ └── process # Contains app path
│
└── scripts/ # Shell scripts (.lua)
Path Shortcuts
| Shortcut | Expands To | Description |
|---|---|---|
~ |
/home | User home directory |
$ |
/apps/com.dev.app | Current app's directory (in shell) |
. |
Current directory | Relative to CWD |
.. |
Parent directory | Go up one level |
SafeFS (Sandboxed Filesystem)
SafeFS provides a secure, sandboxed filesystem interface for applications. It restricts access based on the app's declared permissions and allowedPaths in the manifest.
Getting SafeFS
Apps with the "filesystem" permission receive a fs object in their sandbox:
-- In app code
if fs then
local content, err = fs:read("/home/Documents/file.txt")
end
SafeFS Methods
Reading Files
-- Read entire file contents
local content, err = fs:read(path)
-- Check if file/directory exists
local exists = fs:exists(path)
-- Get file information
local info, err = fs:stat(path)
-- Returns: { size = number, type = "file"|"directory", ... }
Writing Files
-- Write content to file (creates or overwrites)
local success, err = fs:write(path, content)
-- Append to file
local success, err = fs:append(path, content)
Directory Operations
-- List directory contents
local entries, err = fs:list(path)
-- Returns array of: { name = string, type = "file"|"directory" }
-- Create directory
local success, err = fs:mkdir(path)
-- Remove file or empty directory
local success, err = fs:remove(path)
Path Operations
-- Join path components
local fullPath = fs:join("/home", "Documents", "file.txt")
-- Returns: "/home/Documents/file.txt"
-- Get parent directory
local parent = fs:dirname("/home/Documents/file.txt")
-- Returns: "/home/Documents"
-- Get filename
local name = fs:basename("/home/Documents/file.txt")
-- Returns: "file.txt"
-- Get file extension
local ext = fs:extension("file.txt")
-- Returns: "txt"
Access Control
SafeFS enforces two levels of access control:
1. Permission Check
The app must have "filesystem" in its permissions array:
-- manifest.lua
return {
permissions = { "filesystem" };
}
2. Path Restrictions
If allowedPaths is specified, access is restricted to matching paths:
-- manifest.lua
return {
allowedPaths = {
"/home/*"; -- Access to all of /home
"/apps/*"; -- Access to all apps
};
}
Path pattern syntax:
Access Denied Behavior
When access is denied, SafeFS returns nil and an error message:
local content, err = fs:read("/etc/secret")
if not content then
print("Access denied: " .. err)
end
Example Usage
-- Read a configuration file
local config, err = fs:read("~/config.lua")
if config then
-- Parse config...
end
-- Save user data
local data = "user preferences here"
local ok, err = fs:write("~/Documents/prefs.txt", data)
if not ok then
print("Failed to save: " .. err)
end
-- List home directory
local files, err = fs:list("~")
if files then
for _, entry in ipairs(files) do
print(entry.name .. " (" .. entry.type .. ")")
end
end
-- Create a directory structure
fs:mkdir("~/Documents/MyDir")
-- Check before overwriting
if fs:exists("~/Documents/important.txt") then
print("File already exists!")
end
Direct Ramdisk Access
Apps with the "ramdisk" permission can bypass SafeFS and use low-level functions:
-- Only with "ramdisk" permission - bypasses all security!
local handle = CRamdiskOpen("/path/to/file", "r")
local content = CRamdiskRead(handle)
CRamdiskClose(handle)
Warning: Direct ramdisk access bypasses all security checks. Only use for system-level applications that require unrestricted access.