added basic support for symbolic links, pretty untested as of yet, though. they're kind of like mounts in that they have to be re-created after a reboot.

This commit is contained in:
Florian Nücke 2014-01-21 01:40:28 +01:00
parent 9d5f44919b
commit 7f8f216682
3 changed files with 108 additions and 26 deletions

View File

@ -0,0 +1,22 @@
local component = require("component")
local fs = require("filesystem")
local shell = require("shell")
local dirs = shell.parse(...)
if #dirs == 0 then
print("Usage: ln <target> [<name>]")
return
end
local target = shell.resolve(dirs[1])
local linkpath
if #dirs > 1 then
linkpath = shell.resolve(dirs[2])
else
linkpath = fs.concat(shell.getWorkingDirectory(), fs.name(target))
end
local result, reason = fs.link(target, linkpath)
if not result then
print(reason)
end

View File

@ -43,7 +43,9 @@ for i = 1, #dirs do
end
end
for _, f in ipairs(lsf) do
if f:sub(-4) == ".lua" then
if fs.isLink(fs.concat(path, f)) then
setColor(0xFFAA00)
elseif f:sub(-4) == ".lua" then
setColor(0x00FF00)
else
setColor(0xFFFFFF)

View File

@ -3,7 +3,7 @@ local unicode = require("unicode")
local filesystem, fileStream = {}, {}
local isAutorunEnabled = true
local mtab = {children={}}
local mtab = {children={}, links={}}
local function segments(path)
path = path:gsub("\\", "/")
@ -31,19 +31,29 @@ local function segments(path)
return parts
end
local function findNode(path, create)
local function findNode(path, create, depth)
checkArg(1, path, "string")
depth = depth or 0
if depth > 100 then
error("link cycle detected")
end
local parts = segments(path)
local node = mtab
for i = 1, #parts do
if not node.children[parts[i]] then
if create then
node.children[parts[i]] = {children={}, parent=node}
while #parts > 0 do
local part = parts[1]
if not node.children[part] then
if node.links[part] then
return findNode(filesystem.concat(node.links[part], table.concat(parts, "/", 2)), create, depth + 1)
else
return node, table.concat(parts, "/", i)
if create then
node.children[part] = {children={}, links={}, parent=node}
else
return node, table.concat(parts, "/")
end
end
node = node.children[parts[i]]
end
node = node.children[part]
table.remove(parts, 1)
end
return node
end
@ -111,6 +121,24 @@ function filesystem.get(path)
return nil, "no such file system"
end
function filesystem.isLink(path)
local node, rest = findNode(filesystem.path(path))
return not rest and node.links[filesystem.name(path)] ~= nil
end
function filesystem.link(target, linkpath)
checkArg(1, target, "string")
checkArg(2, linkpath, "string")
if filesystem.exists(linkpath) then
return nil, "file already exists"
end
local node = findNode(filesystem.path(linkpath), true)
node.links[filesystem.name(linkpath)] = target
return true
end
function filesystem.mount(fs, path)
checkArg(1, fs, "string", "table")
if type(fs) == "string" then
@ -119,6 +147,10 @@ function filesystem.mount(fs, path)
assert(type(fs) == "table", "bad argument #1 (file system proxy or address expected)")
checkArg(2, path, "string")
if path ~= "/" and filesystem.exists(path) then
return nil, "file already exists"
end
local node = findNode(path, true)
if node.fs then
return nil, "another filesystem is already mounted here"
@ -217,7 +249,7 @@ end
function filesystem.exists(path)
local node, rest = findNode(path)
if not rest then -- virtual directory
if not rest or node.links[rest] then -- virtual directory or symbolic link
return true
end
if node.fs then
@ -266,9 +298,12 @@ function filesystem.list(path)
result = {}
end
if not rest then
for k, _ in pairs(node.children) do
for k in pairs(node.children) do
table.insert(result, k .. "/")
end
for k in pairs(node.links) do
table.insert(result, k)
end
end
table.sort(result)
local i = 0
@ -279,6 +314,9 @@ function filesystem.list(path)
end
function filesystem.makeDirectory(path)
if filesystem.exists(path) then
return nil, "file or directory with that name already exists"
end
local node, rest = findNode(path)
if node.fs and rest then
return node.fs.makeDirectory(rest)
@ -290,14 +328,33 @@ function filesystem.makeDirectory(path)
end
function filesystem.remove(path)
local node, rest = findNode(path)
local node, rest = findNode(filesystem.path(path))
local name = filesystem.name(path)
if node.children[name] then
node.children[name] = nil
return true
elseif node.links[name] then
node.links[name] = nil
return true
else
node, rest = findNode(path)
if node.fs and rest then
return node.fs.remove(rest)
end
return nil, "no such non-virtual directory"
return nil, "no such file or directory"
end
end
function filesystem.rename(oldPath, newPath)
if filesystem.isLink(oldPath) then
local node, rest = findNode(filesystem.path(oldPath))
local target = node.links[filesystem.name(oldPath)]
local result, reason = filesystem.link(target, newPath)
if result then
filesystem.remove(oldPath)
end
return result, reason
else
local oldNode, oldRest = findNode(oldPath)
local newNode, newRest = findNode(newPath)
if oldNode.fs and oldRest and newNode.fs and newRest then
@ -314,6 +371,7 @@ function filesystem.rename(oldPath, newPath)
end
return nil, "trying to read from or write to virtual directory"
end
end
function filesystem.copy(fromPath, toPath)
if filesystem.isDirectory(fromPath) then