Pseudo Files & Pseudo Directories
Virtual files backed by callbacks
Overview
Pseudo files are virtual files that don't store content directly. Instead, when accessed (read, written, or opened), they call functions in your program. The return value becomes the file content that other programs see.
This allows you to create dynamic files that generate content on-the-fly, act as interfaces to hardware or system state, or provide inter-process communication channels.
Creating a Pseudo File
Use fs:createPseudoFile(path) to create a pseudo file. It returns a pseudo file object that you can attach callbacks to.
-- Create a pseudo file at /tmp/time
local pseudoFile = fs:createPseudoFile("/tmp/time")
-- Set the onRead callback - called when the file is read
pseudoFile.onRead = function()
return os.date("%Y-%m-%d %H:%M:%S")
end
-- Now any program reading /tmp/time gets the current time
local content = fs:read("/tmp/time")
print(content) -- "2024-01-15 14:30:45"
Callbacks
Pseudo files support several callbacks:
onRead(args)
Called when the file is read. Returns the content that the reader sees.
pseudoFile.onRead = function(args)
-- args is optional string after the filename
-- e.g., reading "/tmp/myfile arg1 arg2" passes "arg1 arg2"
if args then
return "You requested: " .. args
end
return "Default content"
end
onWrite(data)
Called when data is written to the file. Receives the written content.
pseudoFile.onWrite = function(data)
-- Process the written data
print("Received: " .. data)
-- Could trigger actions, update state, etc.
end
-- Writing to the file triggers onWrite
fs:write("/tmp/myfile", "Hello World")
onOpen(path, mode)
Called when the file is opened with fs:open(). Should return a file handle object with read/write/seek/close methods. If not set, a default handle is created using onRead/onWrite.
pseudoFile.onOpen = function(path, mode)
-- Return a custom file handle
return {
read = function(self, format)
return "custom read"
end,
write = function(self, data)
print("custom write: " .. data)
end,
seek = function(self, whence, offset)
return 0
end,
close = function(self)
print("handle closed")
end
}
end
onDelete()
Called when the pseudo file is deleted. Allows cleanup.
pseudoFile.onDelete = function()
print("Pseudo file being deleted, cleaning up...")
end
Deleting a Pseudo File
You can delete a pseudo file either through the filesystem or by calling its delete method:
-- Method 1: Through filesystem
fs:delete("/tmp/myfile")
-- Method 2: Direct delete method
pseudoFile:delete()
Pseudo Directories
You can also create pseudo directories that dynamically list their contents:
local pseudoDir = fs:createPseudoDir("/tmp/dynamic")
-- Return list of virtual files in this directory
pseudoDir.onFiles = function()
return {"file1.txt", "file2.txt", "status.log"}
end
-- Return list of virtual subdirectories
pseudoDir.onDirs = function()
return {"subdir1", "subdir2"}
end
-- Handle reads of files in this directory
pseudoDir.onRead = function(filename)
if filename == "status.log" then
return "System OK"
end
return "Content of " .. filename
end
-- Handle writes to files in this directory
pseudoDir.onWrite = function(filename, data)
print("Writing to " .. filename .. ": " .. data)
end
-- Refresh must be called to populate the virtual contents
pseudoDir:refresh()
Example: System Info File
-- Create a pseudo file that shows system information
local sysinfo = fs:createPseudoFile("/sys/info")
sysinfo.onRead = function()
local info = {}
table.insert(info, "LuajitOS System Information")
table.insert(info, "============================")
table.insert(info, "Memory: " .. collectgarbage("count") .. " KB")
table.insert(info, "Time: " .. os.date())
return table.concat(info, "\n")
end
-- Reading /sys/info now shows live system stats
Example: Command Interface
-- Create a pseudo file that executes commands
local cmdFile = fs:createPseudoFile("/tmp/cmd")
local lastResult = ""
cmdFile.onWrite = function(command)
-- Execute the command and store result
if command == "hello" then
lastResult = "Hello, World!"
elseif command == "time" then
lastResult = os.date()
else
lastResult = "Unknown command: " .. command
end
end
cmdFile.onRead = function()
return lastResult
end
-- Usage:
fs:write("/tmp/cmd", "hello")
print(fs:read("/tmp/cmd")) -- "Hello, World!"
Arguments in File Paths
Pseudo files can receive arguments by appending them after a space in the path:
local greeter = fs:createPseudoFile("/tmp/greet")
greeter.onRead = function(args)
if args then
return "Hello, " .. args .. "!"
end
return "Hello, stranger!"
end
-- Read with arguments
print(fs:read("/tmp/greet Alice")) -- "Hello, Alice!"
print(fs:read("/tmp/greet")) -- "Hello, stranger!"