mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-12 16:57:32 -04:00
mount bind point support
This commit is contained in:
parent
ebb7dcc0d2
commit
89abb6f30b
@ -1,18 +1,37 @@
|
||||
local fs = require("filesystem")
|
||||
local shell = require("shell")
|
||||
|
||||
local args, ops = shell.parse(...)
|
||||
local argc = #args
|
||||
local function usage()
|
||||
io.stderr:write([==[
|
||||
Usage: mount [OPTIONS] [device path]")
|
||||
If no args are given, all current mount points are printed.
|
||||
<Options> Note that multiple options can be used together
|
||||
-r, --ro Mount the filesystem read only
|
||||
--bind Create a mount bind point, folder to folder
|
||||
<Args>
|
||||
device Specify filesystem device by one of:
|
||||
a. label
|
||||
b. address (can be abbreviated)
|
||||
c. folder path (requires --bind)
|
||||
path Target folder path to mount to
|
||||
|
||||
if ops and (ops.h or ops.help) then
|
||||
print("see `man mount` for help");
|
||||
See `man mount` for more details
|
||||
]==])
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
if argc == 0 then
|
||||
|
||||
-- smart parse, follow arg after -o
|
||||
local args, opts = shell.parse(...)
|
||||
opts.readonly = opts.r or opts.readonly
|
||||
|
||||
if opts.h or opts.help then
|
||||
usage()
|
||||
end
|
||||
|
||||
local function print_mounts()
|
||||
-- for each mount
|
||||
local mounts = {}
|
||||
|
||||
|
||||
for proxy,path in fs.mounts() do
|
||||
local device = {}
|
||||
|
||||
@ -25,7 +44,7 @@ if argc == 0 then
|
||||
local dev_mounts = mounts[device.dev_path]
|
||||
table.insert(dev_mounts, device)
|
||||
end
|
||||
|
||||
|
||||
local smounts = {}
|
||||
for key,value in pairs(mounts) do
|
||||
smounts[#smounts+1] = {key, value}
|
||||
@ -38,29 +57,40 @@ if argc == 0 then
|
||||
local rw_ro = "(" .. device.rw_ro .. ")"
|
||||
local fs_label = "\"" .. device.fs_label .. "\""
|
||||
|
||||
io.write(string.format("%s on %-10s %s %s\n",
|
||||
io.write(string.format("%-8s on %-10s %s %s\n",
|
||||
dev_path:sub(1,8),
|
||||
device.mount_path,
|
||||
rw_ro,
|
||||
fs_label))
|
||||
end
|
||||
end
|
||||
elseif argc ~= 2 then
|
||||
print("Usage: mount [<label|address> <path>]")
|
||||
print("Note that the address may be abbreviated.")
|
||||
return 1 -- error code
|
||||
else
|
||||
local proxy, reason = fs.proxy(args[1])
|
||||
end
|
||||
|
||||
local function do_mount()
|
||||
-- bind converts a path to a proxy
|
||||
local proxy, reason = fs.proxy(args[1], opts)
|
||||
if not proxy then
|
||||
io.stderr:write(reason,"\n")
|
||||
return 1
|
||||
elseif ops.r then
|
||||
proxy = dofile("/lib/core/ro_wrapper.lua").wrap(proxy)
|
||||
io.stderr:write("Failed to mount: ", tostring(reason), "\n")
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
local result, mount_failure = fs.mount(proxy, shell.resolve(args[2]))
|
||||
if not result then
|
||||
io.stderr:write(mount_failure, "\n")
|
||||
return 2 -- error code
|
||||
os.exit(2) -- error code
|
||||
end
|
||||
end
|
||||
|
||||
if #args == 0 then
|
||||
if next(opts) then
|
||||
io.stderr:write("Missing argument\n")
|
||||
usage()
|
||||
else
|
||||
print_mounts()
|
||||
end
|
||||
elseif #args == 2 then
|
||||
do_mount()
|
||||
else
|
||||
io.stderr:write("wrong number of arguments: ", #args, "\n")
|
||||
usage()
|
||||
end
|
||||
|
@ -1,4 +1,5 @@
|
||||
local filesystem = require("filesystem")
|
||||
local component = require("component")
|
||||
|
||||
function filesystem.makeDirectory(path)
|
||||
if filesystem.exists(path) then
|
||||
@ -136,3 +137,101 @@ function filesystem.copy(fromPath, toPath)
|
||||
return data == nil, reason
|
||||
end
|
||||
|
||||
local function readonly_wrap(proxy)
|
||||
checkArg(1, proxy, "table")
|
||||
if proxy.isReadOnly() then
|
||||
return proxy
|
||||
end
|
||||
|
||||
local function roerr() return nil, "filesystem is readonly" end
|
||||
return setmetatable({
|
||||
rename = roerr,
|
||||
open = function(path, mode)
|
||||
checkArg(1, path, "string")
|
||||
checkArg(2, mode, "string")
|
||||
if mode:match("[wa]") then
|
||||
return roerr()
|
||||
end
|
||||
return proxy.open(path, mode)
|
||||
end,
|
||||
isReadOnly = function()
|
||||
return true
|
||||
end,
|
||||
write = roerr,
|
||||
setLabel = roerr,
|
||||
makeDirectory = roerr,
|
||||
remove = roerr,
|
||||
}, {__index=proxy})
|
||||
end
|
||||
|
||||
local function bind_proxy(path)
|
||||
local real, reason = filesystem.realPath(path)
|
||||
if not real then
|
||||
return nil, reason
|
||||
end
|
||||
local real_fs, real_fs_path = filesystem.get(real)
|
||||
if real == real_fs_path then
|
||||
return real_fs
|
||||
end
|
||||
-- turn /tmp/foo into foo
|
||||
local rest = real:sub(#real_fs_path + 1)
|
||||
local function wrap_relative(fp)
|
||||
return function(path, ...)
|
||||
return fp(filesystem.concat(rest, path), ...)
|
||||
end
|
||||
end
|
||||
local bind = {
|
||||
address = real,
|
||||
isReadOnly = real_fs.isReadOnly,
|
||||
list = wrap_relative(real_fs.list),
|
||||
isDirectory = wrap_relative(real_fs.isDirectory),
|
||||
size = wrap_relative(real_fs.size),
|
||||
lastModified = wrap_relative(real_fs.lastModified),
|
||||
exists = wrap_relative(real_fs.exists),
|
||||
open = wrap_relative(real_fs.open),
|
||||
read = real_fs.read,
|
||||
write = real_fs.write,
|
||||
close = real_fs.close,
|
||||
getLabel = function() return "" end,
|
||||
setLabel = function() return nil, "cannot set the label of a bind point" end,
|
||||
}
|
||||
setmetatable(bind, { __index = function(...)
|
||||
print("missing bind method", ...)
|
||||
end
|
||||
})
|
||||
return bind
|
||||
end
|
||||
|
||||
filesystem.internal = {}
|
||||
function filesystem.internal.proxy(filter, options)
|
||||
checkArg(1, filter, "string")
|
||||
checkArg(2, options, "table", "nil")
|
||||
options = options or {}
|
||||
local address, proxy, reason
|
||||
if options.bind then
|
||||
proxy, reason = bind_proxy(filter)
|
||||
else
|
||||
-- no options: filter should be a label or partial address
|
||||
for c in component.list("filesystem", true) do
|
||||
if component.invoke(c, "getLabel") == filter then
|
||||
address = c
|
||||
break
|
||||
end
|
||||
if c:sub(1, filter:len()) == filter then
|
||||
address = c
|
||||
break
|
||||
end
|
||||
end
|
||||
if not address then
|
||||
return nil, "no such file system"
|
||||
end
|
||||
proxy, reason = component.proxy(address)
|
||||
end
|
||||
if not proxy then
|
||||
return proxy, reason
|
||||
end
|
||||
if options.readonly then
|
||||
proxy = readonly_wrap(proxy)
|
||||
end
|
||||
return proxy
|
||||
end
|
||||
|
@ -1,30 +0,0 @@
|
||||
local lib = {}
|
||||
|
||||
function lib.wrap(proxy)
|
||||
checkArg(1, proxy, "table")
|
||||
if proxy.isReadOnly() then
|
||||
return proxy
|
||||
end
|
||||
|
||||
local function roerr() return nil, "filesystem is readonly" end
|
||||
return setmetatable({
|
||||
rename = roerr,
|
||||
open = function(path, mode)
|
||||
checkArg(1, path, "string")
|
||||
checkArg(2, mode, "string")
|
||||
if mode:match("[wa]") then
|
||||
return roerr()
|
||||
end
|
||||
return proxy.open(path, mode)
|
||||
end,
|
||||
isReadOnly = function()
|
||||
return true
|
||||
end,
|
||||
write = roerr,
|
||||
setLabel = roerr,
|
||||
makeDirectory = roerr,
|
||||
remove = roerr,
|
||||
}, {__index=proxy})
|
||||
end
|
||||
|
||||
return lib
|
@ -234,23 +234,13 @@ function filesystem.name(path)
|
||||
return parts[#parts]
|
||||
end
|
||||
|
||||
function filesystem.proxy(filter)
|
||||
function filesystem.proxy(filter, options)
|
||||
checkArg(1, filter, "string")
|
||||
local address
|
||||
for c in component.list("filesystem", true) do
|
||||
if component.invoke(c, "getLabel") == filter then
|
||||
address = c
|
||||
break
|
||||
end
|
||||
if c:sub(1, filter:len()) == filter then
|
||||
address = c
|
||||
break
|
||||
end
|
||||
if not component.list("filesystem")[filter] then
|
||||
-- if not, load fs full library, it has a smarter proxy that also supports options
|
||||
return filesystem.internal.proxy(filter, options)
|
||||
end
|
||||
if not address then
|
||||
return nil, "no such file system"
|
||||
end
|
||||
return component.proxy(address)
|
||||
return component.proxy(filter) -- it might be a perfect match
|
||||
end
|
||||
|
||||
function filesystem.exists(path)
|
||||
|
@ -72,9 +72,9 @@ end
|
||||
function package.delay(lib, file)
|
||||
local mt = {
|
||||
__index = function(tbl, key)
|
||||
dofile(file)
|
||||
setmetatable(lib, nil)
|
||||
setmetatable(lib.internal or {}, nil)
|
||||
dofile(file)
|
||||
return tbl[key]
|
||||
end
|
||||
}
|
||||
|
@ -5,9 +5,12 @@ SYNOPSIS
|
||||
mount
|
||||
mount LABEL PATH
|
||||
mount ADDRESS PATH
|
||||
mount --bind PATH PATH
|
||||
|
||||
OPTIONS
|
||||
-r mount filesystem readonly
|
||||
-r, --readonly mount filesystem readonly
|
||||
--bind mount a bind point (folder to folder)
|
||||
-h, --help print help message
|
||||
|
||||
DESCRIPTION
|
||||
All files accessible in OpenOS are arranged in one big tree, starting with the root node, '/'. The files are the leaves of the tree, directories are inner nodes of the tree. Files can be distributed across several devices (file system components, such as hard drives and floppies). The `mount` command is used to attach a file system to this tree. The `umount` command can be used to remove a mounted file system from the tree (note that `rm` works for this, too).
|
||||
@ -22,5 +25,8 @@ EXAMPLES
|
||||
mount 56f /var
|
||||
Mounts the file system of which the address starts with `56f` at `/var`.
|
||||
|
||||
mount -r tmpfs /tmp_ro
|
||||
Mounts a readonly access path of tmpfs to /tmp_ro
|
||||
mount --readonly tmpfs /tmp_ro
|
||||
Mounts a readonly access path of tmpfs to /tmp_ro
|
||||
|
||||
mount --bind /mnt/fa4/home /home
|
||||
Mounts /mnt/fa5/home to /home
|
||||
|
Loading…
x
Reference in New Issue
Block a user