mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-13 01:10:19 -04:00
mount bind point support
This commit is contained in:
parent
ebb7dcc0d2
commit
89abb6f30b
@ -1,15 +1,34 @@
|
|||||||
local fs = require("filesystem")
|
local fs = require("filesystem")
|
||||||
local shell = require("shell")
|
local shell = require("shell")
|
||||||
|
|
||||||
local args, ops = shell.parse(...)
|
local function usage()
|
||||||
local argc = #args
|
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
|
See `man mount` for more details
|
||||||
print("see `man mount` for help");
|
]==])
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
end
|
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
|
-- for each mount
|
||||||
local mounts = {}
|
local mounts = {}
|
||||||
|
|
||||||
@ -38,29 +57,40 @@ if argc == 0 then
|
|||||||
local rw_ro = "(" .. device.rw_ro .. ")"
|
local rw_ro = "(" .. device.rw_ro .. ")"
|
||||||
local fs_label = "\"" .. device.fs_label .. "\""
|
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),
|
dev_path:sub(1,8),
|
||||||
device.mount_path,
|
device.mount_path,
|
||||||
rw_ro,
|
rw_ro,
|
||||||
fs_label))
|
fs_label))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif argc ~= 2 then
|
end
|
||||||
print("Usage: mount [<label|address> <path>]")
|
|
||||||
print("Note that the address may be abbreviated.")
|
local function do_mount()
|
||||||
return 1 -- error code
|
-- bind converts a path to a proxy
|
||||||
else
|
local proxy, reason = fs.proxy(args[1], opts)
|
||||||
local proxy, reason = fs.proxy(args[1])
|
|
||||||
if not proxy then
|
if not proxy then
|
||||||
io.stderr:write(reason,"\n")
|
io.stderr:write("Failed to mount: ", tostring(reason), "\n")
|
||||||
return 1
|
os.exit(1)
|
||||||
elseif ops.r then
|
|
||||||
proxy = dofile("/lib/core/ro_wrapper.lua").wrap(proxy)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local result, mount_failure = fs.mount(proxy, shell.resolve(args[2]))
|
local result, mount_failure = fs.mount(proxy, shell.resolve(args[2]))
|
||||||
if not result then
|
if not result then
|
||||||
io.stderr:write(mount_failure, "\n")
|
io.stderr:write(mount_failure, "\n")
|
||||||
return 2 -- error code
|
os.exit(2) -- error code
|
||||||
end
|
end
|
||||||
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 filesystem = require("filesystem")
|
||||||
|
local component = require("component")
|
||||||
|
|
||||||
function filesystem.makeDirectory(path)
|
function filesystem.makeDirectory(path)
|
||||||
if filesystem.exists(path) then
|
if filesystem.exists(path) then
|
||||||
@ -136,3 +137,101 @@ function filesystem.copy(fromPath, toPath)
|
|||||||
return data == nil, reason
|
return data == nil, reason
|
||||||
end
|
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]
|
return parts[#parts]
|
||||||
end
|
end
|
||||||
|
|
||||||
function filesystem.proxy(filter)
|
function filesystem.proxy(filter, options)
|
||||||
checkArg(1, filter, "string")
|
checkArg(1, filter, "string")
|
||||||
local address
|
if not component.list("filesystem")[filter] then
|
||||||
for c in component.list("filesystem", true) do
|
-- if not, load fs full library, it has a smarter proxy that also supports options
|
||||||
if component.invoke(c, "getLabel") == filter then
|
return filesystem.internal.proxy(filter, options)
|
||||||
address = c
|
|
||||||
break
|
|
||||||
end
|
end
|
||||||
if c:sub(1, filter:len()) == filter then
|
return component.proxy(filter) -- it might be a perfect match
|
||||||
address = c
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not address then
|
|
||||||
return nil, "no such file system"
|
|
||||||
end
|
|
||||||
return component.proxy(address)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function filesystem.exists(path)
|
function filesystem.exists(path)
|
||||||
|
@ -72,9 +72,9 @@ end
|
|||||||
function package.delay(lib, file)
|
function package.delay(lib, file)
|
||||||
local mt = {
|
local mt = {
|
||||||
__index = function(tbl, key)
|
__index = function(tbl, key)
|
||||||
dofile(file)
|
|
||||||
setmetatable(lib, nil)
|
setmetatable(lib, nil)
|
||||||
setmetatable(lib.internal or {}, nil)
|
setmetatable(lib.internal or {}, nil)
|
||||||
|
dofile(file)
|
||||||
return tbl[key]
|
return tbl[key]
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,12 @@ SYNOPSIS
|
|||||||
mount
|
mount
|
||||||
mount LABEL PATH
|
mount LABEL PATH
|
||||||
mount ADDRESS PATH
|
mount ADDRESS PATH
|
||||||
|
mount --bind PATH PATH
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-r mount filesystem readonly
|
-r, --readonly mount filesystem readonly
|
||||||
|
--bind mount a bind point (folder to folder)
|
||||||
|
-h, --help print help message
|
||||||
|
|
||||||
DESCRIPTION
|
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).
|
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
|
mount 56f /var
|
||||||
Mounts the file system of which the address starts with `56f` at `/var`.
|
Mounts the file system of which the address starts with `56f` at `/var`.
|
||||||
|
|
||||||
mount -r tmpfs /tmp_ro
|
mount --readonly tmpfs /tmp_ro
|
||||||
Mounts a readonly access path of tmpfs to /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