local args = {...} local apis = args[1] local bootdrive = args[2] local bootaddr = args[3] local disks = {} local internal = {} local function createDisk(id, hw) local disk = { address = id, isReadOnly = function() return hw.isReadOnly() end } function disk:spaceUsed() return hw.spaceUsed() end function disk:spaceTotal() return hw.spaceTotal() end function disk:list(path) if not hw.exists(path) or not hw.isDirectory(path) then return nil, "not directory" end return hw.list(path) end function disk:fileExists(path) return hw.exists(path) and not hw.isDirectory(path) end function disk:directoryExists(path) return hw.exists(path) and hw.isDirectory(path) end function disk:type(path) if not hw.exists(path) then return nil elseif hw.isDirectory(path) then return "directory" else return "file" end end function disk:makeDirectory(path) hw.makeDirectory(path) end function disk:remove(path) if hw.exists(path) then hw.remove(path) end end function disk:setLabel(label) hw.setLabel(label) end function disk:getLabel() return hw.getLabel() end function disk:attributes(path) return { size = hw.size(path), isDir = hw.isDirectory(path), isReadOnly = hw.isReadOnly(), modified = hw.lastModified(path), created = hw.lastModified(path) } end function disk:open(path, mode) local fd = hw.open(path, mode) if not fd then local dir = path:match("^(.*)/[^/]+$") if dir and not hw.exists(dir) then local ok, err = hw.makeDirectory(dir) if not ok then return nil, err or "could not create parent directory" end end fd = hw.open(path, mode) if not fd then return nil, "file not found or access denied" end end return { read = function(num) return hw.read(fd, num) end, readAll = function() local data = {} while true do local chunk = hw.read(fd, math.huge) if not chunk then break end data[#data + 1] = chunk end return table.concat(data) end, write = function(data) return hw.write(fd, data) end, seek = function(whence, offset) return hw.seek(fd, whence, offset) end, flush = function() hw.close(fd) fd = hw.open(path, mode) end, close = function() hw.close(fd) fd = nil end } end return disk end internal["$"] = createDisk("$", bootdrive) local function refresh() disks = {} for addr in apis.component.list("filesystem") do if addr ~= bootaddr then disks[addr] = createDisk(addr, apis.component.proxy(addr)) end end end local function iter() refresh() local combined = {} for id, obj in pairs(internal) do combined[id] = obj end for id, obj in pairs(disks) do combined[id] = obj end return pairs(combined) end return {refresh = refresh, list = iter}