modules/programs: add support for 'autodetectCliPaths = parent'

This commit is contained in:
Colin 2024-02-14 04:31:59 +00:00
parent f12b7afa1e
commit 8b32f2f231
2 changed files with 28 additions and 12 deletions

View File

@ -328,12 +328,13 @@ let
sandbox.autodetectCliPaths = mkOption {
type = types.coercedTo types.bool
(b: if b then "existing" else null)
(types.nullOr (types.enum [ "existing" "existingFileOrParent" ]));
(types.nullOr (types.enum [ "existing" "existingFileOrParent" "parent" ]));
default = null;
description = ''
if a CLI argument looks like a PATH, should we add it to the sandbox?
- null => never
- "existing" => only if the file exists
- "parent" => allow access to the directory containing any file (whether that file exists or not). useful for certain media viewers/library managers.
- "existingFileOrParent" => add the file if it exists; if not, add its parent if that exists. useful for programs which create files.
'';
};

View File

@ -74,6 +74,28 @@ parent() {
realpath --logical --no-symlinks --canonicalize-missing "$1/.."
}
# subroutine of `tryArgAsPath` for after the arg has been converted into a valid (but possibly not existing) path.
# adds an entry to `cliPathArgs` and evals `true` on success;
# evals `false` if the path couldn't be added, for any reason.
tryPath() {
_path="$1"
_how="$2"
if [ "$_how" = "existing" ]; then
if [ -e "$_path" ]; then
cliPathArgs+=("$_path")
true
fi
false
elif [ "$_how" = "parent" ]; then
# the caller wants access to the entire directory containing this directory regardless of the file's existence.
tryPath "$(parent "$_path")" "existing"
elif [ "$_how" = "existingFileOrParent" ]; then
# the caller wants access to the file, or write access to the directory so it may create the file if it doesn't exist.
tryPath "$_path" "existing" || tryPath "$_path" "parent"
fi
}
# if the argument looks path-like, then add it to cliPathArgs.
# this function ingests absolute, relative, or file:///-type URIs.
# but it converts any such path into an absolute path before adding it to cliPathArgs.
@ -89,22 +111,15 @@ tryArgAsPath() {
# commonly found when xdg-open/mimeo passes a path on to an application
# if URIs to relative paths exist, this implementation doesn't support them
_path="/$(urldecode "${_arg:8}")"
elif [ "${_path:0:1}" = "-" ]; then
# 99% chance it's a CLI argument. if not, use `./-<...>`
return
else
# assume relative path
_path="$(pwd)/$_arg"
fi
if [ -e "$_path" ]; then
cliPathArgs+=("$_path")
elif [ "$_how" = "existingFileOrParent" ]; then
# the path doesn't exist, but that's because the program might create it.
if [ "${_path:0:1}" = "-" ]; then
# 99% chance it's a CLI argument. if not, use `./-<...>`
return
elif [ -e "$(parent "$_path/..")" ]; then
cliPathArgs+=("$_path/..")
fi
fi
tryPath "$_path" "$_how"
}
# remove duplicate //, reduce '.' and '..' (naively).