1.6 rc version 2

advanced install features as well as simplified install for common usage
renamed .osprop to .prop
support for named installed
cp link copy fixes
fix /bin/less pgdown and space
package delay lookup no longer weak value
fixed regression in sh tab complete for first arg completion
This commit is contained in:
payonel 2016-06-10 22:52:00 -07:00
parent 3e86a32783
commit 80e25f7be7
8 changed files with 318 additions and 202 deletions

View File

@ -1 +0,0 @@
return {name = "OpenOS"}

View File

@ -0,0 +1 @@
return {label = "OpenOS", reboot=true, setlabel=true, setboot=true}

View File

@ -64,8 +64,15 @@ end
local function recurse(fromPath, toPath, origin) local function recurse(fromPath, toPath, origin)
local isLink, target = fs.isLink(fromPath) local isLink, target = fs.isLink(fromPath)
if isLink and options.P then local toIsLink, toLinkTarget = fs.isLink(toPath)
local same_path = fs.canonical(isLink and target or fromPath) == fs.canonical(toIsLink and toLinkTarget or toPath)
local toExists = fs.exists(toPath)
if isLink and options.P and (not toExists or not same_path) then
status(fromPath, toPath) status(fromPath, toPath)
if toIsLink then
fs.remove(toPath)
end
return fs.link(target, toPath) return fs.link(target, toPath)
elseif fs.isDirectory(fromPath) then elseif fs.isDirectory(fromPath) then
if not options.r then if not options.r then
@ -95,35 +102,34 @@ local function recurse(fromPath, toPath, origin)
end end
return true return true
elseif fs.exists(fromPath) then elseif fs.exists(fromPath) then
if fs.exists(toPath) then if toExists then
if fs.canonical(fromPath) == fs.canonical(toPath) then if same_path then
return nil, "`" .. fromPath .. "' and `" .. toPath .. "' are the same file" return nil, "`" .. fromPath .. "' and `" .. toPath .. "' are the same file"
end end
if fs.isDirectory(toPath) then
if options.i then if options.n then
if not prompt("overwrite `" .. toPath .. "'?") then return true
return true
end
elseif options.n then
return true
else -- yes, even for -f
return nil, "cannot overwrite directory `" .. toPath .. "' with non-directory"
end
else
if options.u then
if areEqual(fromPath, toPath) then
return true
end
end
if options.i then
if not prompt("overwrite `" .. toPath .. "'?") then
return true
end
elseif options.n then
return true
end
-- else: default to overwriting
end end
-- if target is link, we are updating the target
if toIsLink then
toPath = toLinkTarget
end
if options.u and not fs.isDirectory(toPath) and areEqual(fromPath, toPath) then
return true
end
if options.i then
if not prompt("overwrite `" .. toPath .. "'?") then
return true
end
end
if fs.isDirectory(toPath) then
return nil, "cannot overwrite directory `" .. toPath .. "' with non-directory"
end
fs.remove(toPath) fs.remove(toPath)
end end
status(fromPath, toPath) status(fromPath, toPath)

View File

@ -7,12 +7,21 @@ local shell = require("shell")
local tx = require("transforms") local tx = require("transforms")
local text = require("text") local text = require("text")
local args, options = shell.parse(...) local lib = {}
local sources = {} lib.args, lib.options = shell.parse(...)
local targets = {}
if options.help then lib.sources = {}
lib.targets = {}
lib.source_label = lib.args[1]
lib.stdout = io.stdout
lib.stderr = io.stderr
lib.stdin = io.stdin
lib.exit = os.exit
if lib.options.help then
print([[Usage: install [OPTION]... print([[Usage: install [OPTION]...
--from=ADDR install filesystem at ADDR --from=ADDR install filesystem at ADDR
default: builds list of default: builds list of
@ -22,25 +31,57 @@ if options.help then
--root=PATH same as --fromDir but target --root=PATH same as --fromDir but target
--toDir=PATH same as --root --toDir=PATH same as --root
-u, --update update files interactively -u, --update update files interactively
The following only pertain when .osprop exists --label override label from .prop
--nolabelset do not label target --nosetlabel do not label target
--name override label from .osprop --nosetboot do not use target for boot
--noboot do not use target for boot
--noreboot do not reboot after install]]) --noreboot do not reboot after install]])
return nil -- exit success return nil -- exit success
end end
local rootfs = fs.get("/") local rootfs = fs.get("/")
if not rootfs then if not rootfs then
io.stderr:write("no root filesystem, aborting\n"); lib.stderr:write("no root filesystem, aborting\n");
return 1 lib.exit(1)
end
function lib.up_deprecate(old_key, new_key)
if lib.options[new_key] == nil then
lib.options[new_key] = lib.options[old_key]
end
lib.options[old_key] = nil
end
function lib.cleanPath(path)
if path then
local rpath = shell.resolve(path)
if fs.isDirectory(rpath) then
return fs.canonical(rpath):gsub("/+$", "") .. '/'
end
end
end
function lib.load_options()
lib.up_deprecate('noboot', 'nosetboot')
lib.up_deprecate('nolabelset', 'nosetlabel')
lib.up_deprecate('name', 'label')
lib.source_root = lib.cleanPath(lib.options.from)
lib.target_root = lib.cleanPath(lib.options.to)
lib.source_dir = (lib.options.fromDir or "") .. '/.'
lib.target_dir = (lib.options.root or lib.options.toDir or "") .. "/."
lib.update = lib.options.u or lib.options.update
lib.source_dev = lib.source_root and fs.get(lib.source_root)
lib.target_dev = lib.target_root and fs.get(lib.target_root)
end end
local rootAddress = rootfs.address local rootAddress = rootfs.address
-- if the rootfs is read only, it is probably the loot disk! -- if the rootfs is read only, it is probably the loot disk!
local rootException = rootAddress lib.rootException = rootAddress
if rootfs.isReadOnly() then if rootfs.isReadOnly() then
rootException = nil lib.rootException = nil
end end
-- this may be OpenOS specific, default to "" in case no /dev mount point -- this may be OpenOS specific, default to "" in case no /dev mount point
@ -49,72 +90,96 @@ local devfsAddress = (fs.get("/dev/") or {}).address or ""
-- tmp is only valid if specified as an option -- tmp is only valid if specified as an option
local tmpAddress = computer.tmpAddress() local tmpAddress = computer.tmpAddress()
local fromAddress = options.from function lib.load(path, env)
local toAddress = options.to if fs.exists(path) then
local fromDir = (options.fromDir or "") .. '/.' local loader, reason = loadfile(path, "bt", setmetatable(env or {}, {__index=_G}))
local root = (options.root or options.toDir or "") .. "/." if not loader then
options.update = options.u or options.update return nil, reason
local function cleanPath(path)
if path then
local rpath = shell.resolve(path)
if fs.isDirectory(rpath) then
return fs.canonical(rpath):gsub("/+$", "") .. '/'
end end
local ok, loaded = pcall(loader)
return ok and loaded, ok or loaded
end end
return path
end end
fromAddress = cleanPath(fromAddress) function lib.validDevice(candidate, exceptions, specified, existing)
toAddress = cleanPath(toAddress)
local function validDevice(candidate, exceptions, specified, existing)
local address = candidate.dev.address local address = candidate.dev.address
if tx.first(existing, function(e) return e.dev.address == address end) then if tx.first(existing, function(e) return e.dev.address == address end) then
return return
end end
local path = candidate.path
if specified then if specified then
return address:find(specified, 1, true) == 1 or specified == path if type(specified) == "string" and address:find(specified, 1, true) == 1 or specified == candidate.dev then
return true
end
else else
return not tx.find(exceptions, {address}) return not tx.find(exceptions, {address})
end end
end end
function lib.relevant(candidate, path)
if not path or fs.get(path) ~= candidate.dev then
return candidate.path
end
return path
end
-- use a single for loop of all filesystems to build the list of candidates of sources and targets -- use a single for loop of all filesystems to build the list of candidates of sources and targets
for dev, path in fs.mounts() do function lib.load_candidates()
local candidate = {dev=dev, path=path} for dev, path in fs.mounts() do
local candidate = {dev=dev, path=path:gsub("/+$","")..'/'}
if validDevice(candidate, {devfsAddress, tmpAddress, rootException}, fromAddress, sources) then if lib.validDevice(candidate, {devfsAddress, tmpAddress, lib.rootException}, lib.source_dev or lib.options.from, lib.sources) then
if fromAddress or fs.list(path)() then local root_path = lib.relevant(candidate, lib.source_root)
table.insert(sources, candidate) if (lib.options.from or fs.list(root_path)()) then -- ignore empty sources unless specified
candidate.prop = lib.load(root_path .. "/.prop") or {}
if not lib.source_label or lib.source_label:lower() == (candidate.prop.label or candidate.dev.getLabel()):lower() then
table.insert(lib.sources, candidate)
end
end
end
-- in case candidate is valid for BOTH, we want a new table
candidate = {dev=candidate.dev, path=candidate.path} -- but not the prop
if lib.validDevice(candidate, {devfsAddress, tmpAddress}, lib.target_dev or lib.options.to, lib.targets) then
if not dev.isReadOnly() then
table.insert(lib.targets, candidate)
elseif lib.options.to then
lib.stderr:write("Cannot install to " .. lib.options.to .. ", it is read only\n")
lib.exit(1)
return false -- in lib mode this can be hit
end
end end
end end
if validDevice(candidate, {devfsAddress, tmpAddress}, toAddress, targets) then return true
if not dev.isReadOnly() then end
table.insert(targets, candidate)
elseif toAddress then function lib.check_sources()
io.stderr:write("Cannot install to " .. toAddress .. ", it is read only\n") if #lib.sources == 0 then
return 1 if lib.source_label then
lib.stderr:write("No filesystem to matched given label: " .. lib.source_label .. '\n')
elseif lib.options.from then
lib.stderr:write("No such filesystem to install from: " .. lib.options.from .. '\n')
else
lib.stderr:write("Could not find and available installations\n")
end end
lib.exit(1)
end end
return true
end end
if fromAddress and #sources == 0 then function lib.check_targets()
io.stderr:write("No such filesystem to install from: " .. fromAddress .. "\n") if #lib.targets == 0 then
return 1 if lib.options.to then
end lib.stderr:write("No such filesystem to install to: " .. lib.options.to .. '\n')
else
if #targets == 0 then lib.stderr:write("No writable disks found, aborting\n")
if toAddress then end
io.stderr:write("No such filesystem to install to: " .. toAddress .. "\n") lib.exit(1)
else
io.stderr:write("No writable disks found, aborting\n")
end end
return 1 return true
end end
----- For now, I am allowing source==target -- cp can handle it if the user prepares conditions correctly ----- For now, I am allowing source==target -- cp can handle it if the user prepares conditions correctly
@ -124,11 +189,12 @@ end
-- return 1 -- return 1
--end --end
local function prompt_select(devs, direction) function lib.prompt_select(devs, direction)
table.sort(devs, function(a, b) return a.path<b.path end)
local choice = devs[1] local choice = devs[1]
if #devs > 1 then if #devs > 1 then
print("Select the device to install " .. direction) lib.stdout:write("Select the device to install " .. direction .. '\n')
for i = 1, #devs do for i = 1, #devs do
local src = devs[i] local src = devs[i]
@ -138,118 +204,141 @@ local function prompt_select(devs, direction)
else else
label = src.dev.address label = src.dev.address
end end
print(i .. ") " .. label .. " at " .. src.path) lib.stdout:write(i .. ") " .. label .. " at " .. src.path .. '\n')
end end
print("Please enter a number between 1 and " .. #devs) lib.stdout:write("Please enter a number between 1 and " .. #devs .. '\n')
io.write("Enter 'q' to cancel the installation: ") lib.stdout:write("Enter 'q' to cancel the installation: ")
local choice local choice
while not choice do while not choice do
result = io.read() result = lib.stdin:read()
if result:sub(1, 1):lower() == "q" then if result:sub(1, 1):lower() == "q" then
os.exit() lib.exit()
return false
end end
local number = tonumber(result) local number = tonumber(result)
if number and number > 0 and number <= #devs then if number and number > 0 and number <= #devs then
choice = devs[number] choice = devs[number]
else else
io.write("Invalid input, please try again: ") lib.stdout:write("Invalid input, please try again: ")
end end
end end
end end
choice.display = (choice.path == '/' and "the root filesystem") or choice.dev.getLabel() or choice.path -- normally it is helpful to call / the root filesystem
-- but if rootfs is readonly, then we know we are using rootfs as a source
if #devs == 1 then -- in which case, it's label takes priority
print("Selecting " .. choice.display .. " (only option)") choice.display =
end not choice.dev.isReadOnly() and (choice.path == '/' and "the root filesystem") or
-- everything has props by this point, except for targets
(choice.prop or {}).label or
choice.dev.getLabel() or
choice.path
return choice return choice
end end
table.sort(sources, function(a, b) return a.path<b.path end) function lib.load_env()
table.sort(targets, function(a, b) return a.path<b.path end) lib.env =
local source = prompt_select(sources, "from")
local target = prompt_select(targets, "to")
-- load .osprop (optional) settings
local osprop = nil
if fs.exists(source.path .. ".osprop") then
local osprop_data, reason = loadfile(source.path .. ".osprop", "bt", setmetatable({}, {__index=_G}))
if not osprop_data then
io.stderr:write("Failed to load .osprop: " .. tostring(reason) .. '\n')
return 1
end
osprop = osprop_data()
options.name = options.name or osprop.name
source.display = options.name or source.display
end
-- if .lootprop exists
if fs.exists(source.path .. ".lootprop") then
local env = setmetatable(
{ {
lootprop = from=lib.source_root,
{ to=lib.target_root,
from=source.path, fromDir=lib.source_dir,
to=target.path, root=lib.target_dir,
fromDir=fromDir, update=lib.options.update,
root=root, label=lib.options.label or lib.source.prop.label,
update=options.update, setlabel=lib.source.prop.setlabel and not lib.options.nosetlabel,
nolabelset=options.nolabelset, setboot=lib.source.prop.setboot and not lib.options.nosetboot,
name=options.name, reboot=lib.source.prop.reboot and not lib.options.noreboot,
noboot=options.noboot, }
noreboot=options.noreboot, end
}
}, {__index=_G}) function lib.init()
local lootprop, reason = loadfile(source.path .. ".lootprop", "bt", env) lib.load_options()
if not lootprop then if not lib.load_candidates() then return false end
io.stderr:write("Failed to load .lootprop: " .. tostring(reason) .. '\n') if not lib.check_sources() then return false end
return 1 if not lib.check_targets() then return false end
lib.source = lib.prompt_select(lib.sources, "from")
if not lib.source then return false end
lib.source_root = lib.source_root or lib.source.path
lib.target = lib.prompt_select(lib.targets, "to")
if not lib.target then return false end
lib.target_root = lib.target_root or lib.target.path
lib.load_env()
local reason
lib.installer, reason = lib.load(lib.source_root .. '/.install', {install=lib.env})
if not lib.installer then
if reason then
lib.stderr:write("installer failed to load: " .. tostring(reason) .. '\n')
lib.exit(1)
return false
else
lib.installer = lib.run
end
end end
return lootprop()
return true
end end
local cp = shell.resolve("cp", "lua") function lib.run()
local cp_options = "-vrx" .. (options.update and "ui" or "") local cp = shell.resolve("cp", "lua")
local cp_source = (source.path .. fromDir):gsub("/+","/") local cp_options = "-vrx" .. (lib.options.update and "ui" or "")
local cp_dest = (target.path .. root):gsub("/+","/") local cp_source = (lib.source_root .. lib.source_dir):gsub("/+","/")
local cp_dest = (lib.target_root .. lib.target_dir):gsub("/+","/")
io.write("Install " .. source.display .. " to " .. target.display .. "? [Y/n] ") io.write("Install " .. lib.source.display .. " to " .. lib.target.display .. "? [Y/n] ")
local choice = text.trim(io.read()):lower() local choice = text.trim(lib.stdin:read()):lower()
if choice == "" then if choice == "" then
choice = "y" choice = "y"
end
if choice ~= "y" then
print("Installation cancelled")
return
end
local message = string.format("Installing %s [%s] to %s [%s]", source.display, cp_source, target.display, cp_dest)
local cmd = cp .. ' ' .. cp_options .. ' ' .. cp_source .. ' ' .. cp_dest
print(message)
print(cmd)
os.sleep(0.25)
local result, reason = os.execute(cmd)
if not result then
error(reason, 0)
end
if osprop then
if not options.nolabelset then
pcall(target.dev.setLabel, options.name)
end end
if not options.noreboot then if choice ~= "y" then
io.write("All done! " .. ((not options.noboot) and "Set as boot device and r" or "R") .. "eboot now? [Y/n] ") lib.stdout:write("Installation cancelled\n")
local result = io.read() lib.exit()
return false
end
local message = string.format("Installing %s [%s] to %s [%s]", lib.source.display, cp_source, lib.target.display, cp_dest)
local cmd = cp .. ' ' .. cp_options .. ' ' .. cp_source .. ' ' .. cp_dest
lib.stdout:write(message .. '\n')
lib.stdout:write(cmd .. '\n')
os.sleep(0.25)
local result, reason = os.execute(cmd)
if not result then
error(reason, 0)
end
lib.stdout:write("Installation complete!\n")
if lib.env.setlabel then
pcall(lib.target.dev.setLabel, lib.env.label)
end
local prereboot = function()end
if lib.env.setboot then
prereboot = computer.setBootAddress
end
if lib.env.reboot then
lib.stdout:write("Reboot now? [Y/n] ")
local result = lib.stdin:read()
if not result or result == "" or result:sub(1, 1):lower() == "y" then if not result or result == "" or result:sub(1, 1):lower() == "y" then
if not options.noboot then computer.setBootAddress(target.dev.address)end prereboot(lib.target.dev.address)
io.write("\nRebooting now!\n") lib.stdout:write("\nRebooting now!\n")
computer.shutdown(true) computer.shutdown(true)
end end
end end
lib.stdout:write("Returning to shell.\n")
end end
io.write("Returning to shell.\n")
if lib.options.lib then
return lib
end
lib.init()
lib.run()

View File

@ -277,7 +277,7 @@ while true do
if code == keyboard.keys.q or code == keyboard.keys.d and keyboard.isControlDown() then if code == keyboard.keys.q or code == keyboard.keys.d and keyboard.isControlDown() then
break break
elseif code == keyboard.keys.space or code == keyboard.keys.pageDown then elseif code == keyboard.keys.space or code == keyboard.keys.pageDown then
num = nil num = max_display
elseif code == keyboard.keys.pageUp then elseif code == keyboard.keys.pageUp then
num = -max_display num = -max_display
elseif code == keyboard.keys.enter or code == keyboard.keys.down then elseif code == keyboard.keys.enter or code == keyboard.keys.down then

View File

@ -64,9 +64,8 @@ local delay_tools = setmetatable({},{__mode="v"})
package.delay_data = delay_data package.delay_data = delay_data
function delay_data.__index(tbl,key) function delay_data.__index(tbl,key)
local lookup = delay_tools.lookup or loadfile("/lib/tools/delayLookup.lua") delay_data.lookup = delay_data.lookup or loadfile("/lib/tools/delayLookup.lua")
delay_tools.lookup = lookup return delay_data.lookup(delay_data, tbl, key)
return lookup(delay_data, tbl, key)
end end
delay_data.__pairs = delay_data.__index -- nil key acts like pairs delay_data.__pairs = delay_data.__index -- nil key acts like pairs

View File

@ -642,7 +642,7 @@ function --[[@delayloaded-start@]] sh.internal.hintHandlerImpl(full_line, cursor
local resultSuffix = suffix local resultSuffix = suffix
if #result > 0 and unicode.sub(result[1], -1) ~= "/" and if #result > 0 and unicode.sub(result[1], -1) ~= "/" and
not suffix:sub(1,1):find('%s') and not suffix:sub(1,1):find('%s') and
(#result == 1 or cmd) then #result == 1 or searchInPath then
resultSuffix = " " .. resultSuffix resultSuffix = " " .. resultSuffix
end end

View File

@ -2,20 +2,20 @@ NAME
install - installs files from a source filesystem to a target filesystem install - installs files from a source filesystem to a target filesystem
SYNOPSIS SYNOPSIS
install [OPTIONS]... install [name] [OPTIONS]...
DESCRIPTION DESCRIPTION
install builds a list of candidate source and target mounted filesystems. If there are multiple candidates, the user is prompted for selections. By default, install copies all files from the source filesystem's root to the target filesystem's root path. If the source filesystem contains an .osprop, and unless command line options specify otherwise, the target filesystem's label is set and the user is prompted for reboot when install is complete. Alternatively, If a .lootprop file exists in the source filesystem, all default behavior is superceded and .lootprop is run as a script. .lootprop may copy files, set labels, prompt for reboot, etc. on its own. Developers creating their own .lootprop files for devices should respect environment variables set by install as per options it is given, such as ROOT. This manual page details the environment variables set by install when calling .lootprop. install builds a list of candidate source and target mounted filesystems. If there are multiple candidates, the user is prompted for selections. By default, install copies all files from the source filesystem's root to the target filesystem's root path. The source filesystem can define label, boot, and reboot behavior via .prop and a fully custom install experience via .install which supercedes install running cp from source to target filesystems. Developers creating their own .install files for devices should respect environment variables set by install as per options it is given, such as the root path. This manual page details those environment variables.
OPTIONS OPTIONS
--from=ADDR --from=ADDR
When searching for candidate source filesystems, if specified, only mounted filesystem device addresses or their mount point paths that match ADDR will be included. By default, all filesystems except the rootfs are valid sources for install. If the user is trying to install rootfs to another filesystem, --from=ADDR is required where ADDR matches the rootfs device address or --from=/ Specifies the source filesystem or its root path. ADDR can be the device guid or a directory path. If this is a directory path, it represents a root path to install from. This option can also be used to specify source paths that would otherwise be ignored, those being devfs, tmpfs, and the rootfs. e.g. --from=/tmp . Note that if both --from and a [name] is given, install expects the source path to have a .prop defining the same name. See .prop for more details.
--to=ADDR --to=ADDR
same as --from but used when selecting target filesystem candidates. Note that the tmpfs is not a valid target filesystem by default, but must be specified explicitly if needed: i.e. --to=ADDR where ADDR matches the tmpfs device address or its mount point path, e.g. --to=/tmp . Note that install allows TO to equal FROM, also note that /bin/cp does not. But this detail may be noteworthy for .lootprop Same as --from but specifies the target filesystem by guid or its root path. This option can also be used to specify filesystems that are otherwise ignored including tmpfs. i.e. --to=ADDR where ADDR matches the tmpfs device address or its mount point path. e.g. --to=/tmp
--fromDir=PATH --fromDir=PATH
Install PATH from source. PATH is relative to the root of the source filesystem. The default is . Install PATH from source. PATH is relative to the root of the source filesystem or path given by --from. The default is .
--root=PATH --root=PATH
Same as --fromDir but for the target filesystem. Same as --fromDir but for the target filesystem.
@ -26,56 +26,78 @@ OPTIONS
-u, --update -u, --update
Indicates that install should prompt the user before modifying files. This invokes -i and -u for /bin/cp. Indicates that install should prompt the user before modifying files. This invokes -i and -u for /bin/cp.
The following only pertain when .osprop exists in the source filesystem. All environment variables are set for .lootprop regardless of the presense of .osprop The following can override settings defined in .prop in the source filesystem.
--nolabelset --label=NAME
do not set target label use NAME for label instead of any value specified by .prop, --name is deprecated
--name=NAME --nosetlabel
use NAME for label instead of any value specified by .osprop. This option is ignored if there is no .osprop (in which case, no label is set at all) do not set target label. --nolabelset is deprecated
--noboot --nosetboot
do not set target as default boot device when rebooting do not set target as default boot device when rebooting. --noboot is deprecated
--noreboot --noreboot
do not reboot after install do not reboot after install
.lootprop ENVIRONMENT .prop
When .lootprop is loaded and executed, a custom table is added to the environment: ENV_.lootprop .prop should have valid lua code that returns a table of keys and their values: e.g. "return {name='OpenOS'}"
name=string
Declares an identifying name of the installation. This is displayed by install during source selection and also can be used on the commandline: e.g. (where {name="tape"} is given) `install tape`. If setlabel is true, this value is used for the target filesystem label. --name overrides this value. Note that install uses a case insensitive search: e.g. install TAPE works the same as install tape.
setlabel=boolean
Determines whether the install should set the target filesystem's label. If .prop does not define a name key and the user does not define a command line --name=VALUE, setlabel has no action. --nosetlabel overrides this value
setboot=boolean
Determines if the target filesystem should be set as the machine's default boot device. Default is false, overriden by --nosetboot
reboot=boolean
Determines if the machine should reboot after the install completes. Overriden by --noreboot
EXAMPLE:
return {name='OpenOS', setlabel=true, setboot=true, reboot=true}
.install ENVIRONMENT
When .install is loaded and executed, a custom table is added to the environment: ENV_.install
These are the keys of the table as populated by install These are the keys of the table as populated by install
ENV_.lootprop.from: ENV_.install.from:
This is the path of the selected source filesystem to install from. It should be the path to the executing .lootprop This is the path of the selected source filesystem to install from. It should be the path to the executing .install
example: /mnt/ABC example: /mnt/ABC
ENV_.lootprop.to: ENV_.install.to:
This is the path of the selected target filesystem to install to. This is the path of the selected target filesystem to install to.
example: / example: /
_ENV.lootprop.fromdir _ENV.install.fromdir
This is the relative path to use in the source filesysterm as passed by command line to install. If unspecified to install it defaults to "." This is the relative path to use in the source filesysterm as passed by command line to install. If unspecified to install it defaults to "."
example: . example: .
_ENV.lootprop.root _ENV.install.root
This is the relative path to use in the target filesystem as passed by command line to install. If unspecified to install it defaults to "." This is the relative path to use in the target filesystem as passed by command line to install. If unspecified to install it defaults to "."
example: . example: .
_ENV.lootprop.update _ENV.install.update
Assigned value of --update, see OPTIONS Assigned value of --update, see OPTIONS
_ENV.lootprop.nolabelset _ENV.install.label
Assigned value of --nolabelset, see OPTIONS Assigned value of --name or .prop's label, see OPTIONS
_ENV.lootprop.name _ENV.install.setlabel
Assigned value of --name, see OPTIONS Assigned value of .prop's setlabel unless --nolabelset, see OPTIONS
_ENV.lootprop.noboot _ENV.install.setboot
Assigned value of --noboot, see OPTIONS Assigned value of .prop's boot unless --nosetboot, see OPTIONS
--noreboot _ENV.install.reboot
Assigned value of --noreboot, see OPTIONS Assigned value of .prop's reboot unless --noreboot, see OPTIONS
EXAMPLES EXAMPLES
install install
Searches all non rootfs filesystems to install from, and all non tmpfs filesystems to install to. Prompts the user for a selection, and copies. If .osprop is defined in source, sets label and will prompt for reboot when completed. Searches all non rootfs filesystems to install from, and all non tmpfs filesystems to install to. Prompts the user for a selection, and copies. If .prop is defined in source, sets label and will prompt for reboot when completed.
install openos
Searches candidates source filesystems that have .prop's that define name="OpenOS" and prompts the user to confirm install to candidate target filesystems.