[pacman-dev] [PATCH] makepkg: Handle errors when canonicalizing paths
Luke Shumaker
lukeshu at lukeshu.com
Thu Aug 9 18:49:09 UTC 2018
From: Luke Shumaker <lukeshu at parabola.nu>
If you don't have adequate permission to `cd` to one of the DEST
directories, it's clear that that something's not doing error handling
right:
$ install -d -m0000 srcdest
$ SRCDEST=$PWD/srcdest makepkg
/usr/share/makepkg/util/util.sh: line 75: cd: /.../srcdest: Permission denied
==> ERROR: Failed to change to directory /.../srcdest
Aborting...
==> ERROR: Failed to create the directory $SRCDEST ().
Aborting...
The first error comes from cd_safe() inside of canonicalize_path().
Because that bit runs in a subshell, it doesn't actually abort right there.
Then, makepkg.sh doesn't check for failures from canonicalize_path. So
then the variable gets set to an empty string (which makes the next error
message from ensure_writable_dir() look funny), and keeps going.
As an additional "fun" quirk, canonicalize_path doesn't canonicalize it if
ensure_writable_dir has any work to do. That's probably not intended, but
I'm not sure it is wrong either (see below).
1. Combine canonicalize_path() and ensure_writable_dir() in to
canonicalize_and_ensure_writable_dir(). Both are only ever called on
exactly the same variables (except that ensure_writable_dir() might
skip PKGDEST, SRCPKGDEST, or LOGDEST; depending on the flags).
2. Use plain `cd` and check the status ourselves, rather than `cd_safe`.
We can come up with a better (context-aware) error message than
`cd_safe`, and we avoid duplicating the "Aborting..." message.
This has a few consequences:
a. We no longer canonicalize dirpaths that we don't ensure are writable.
That's probably safe. This means that makepkg might now error in fewer
cases; for example:
$ install -d -m0000 pkgdest
$ PKGDEST=$PWD/pkgdest makepkg -g
There's no reason for it to care that it can't `cd` to PKGDEST; it
won't be using it.
b. We now canonicalize paths that we create that didn't exist before.
That said, I'm not sure why we ever need to canonicalize the paths; I'm not
sure why c0f58ea was necessary even after 960c2cd was already applied.
---
scripts/libmakepkg/util/util.sh.in | 31 +++++++++++-------------------
scripts/makepkg.sh.in | 14 +++++++-------
2 files changed, 18 insertions(+), 27 deletions(-)
diff --git a/scripts/libmakepkg/util/util.sh.in b/scripts/libmakepkg/util/util.sh.in
index e1ca5cb7..1dfe6da9 100644
--- a/scripts/libmakepkg/util/util.sh.in
+++ b/scripts/libmakepkg/util/util.sh.in
@@ -49,20 +49,6 @@ is_array() {
return $ret
}
-# Canonicalize a directory path if it exists
-canonicalize_path() {
- local path="$1";
-
- if [[ -d $path ]]; then
- (
- cd_safe "$path"
- pwd -P
- )
- else
- printf "%s\n" "$path"
- fi
-}
-
dir_is_empty() {
(
shopt -s dotglob nullglob
@@ -79,10 +65,10 @@ cd_safe() {
fi
}
-# Try to create directory if one does not yet exist. Fails if the directory
-# exists but has no write permissions, or if there is an existing file with
-# the same name.
-ensure_writable_dir() {
+# Try to create directory if one does not yet exist, and prints the
+# canonical path to the directory. Fails if the directory exists but has no
+# write permissions, or if there is an existing file with the same name.
+canonicalize_and_ensure_writable_dir() {
local dirtype="$1" dirpath="$2"
if ! mkdir -p "$dirpath" 2>/dev/null; then
@@ -92,6 +78,11 @@ ensure_writable_dir() {
error "$(gettext "You do not have write permission for the directory \$%s (%s).")" "$dirtype" "$dirpath"
return 1
fi
-
- return 0
+ (
+ if ! cd "$dirpath"; then
+ error "$(gettext "Could not canonicalize the directory \$%s (%s).")" "$dirtype" "$dirpath"
+ return 1
+ fi
+ pwd -P
+ )
}
diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index 8ee0f5c5..62c2db80 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -1353,9 +1353,9 @@ if (( ${#extra_environment[*]} )); then
export "${extra_environment[@]}"
fi
-# canonicalize paths and provide defaults if anything is still undefined
+# provide defaults if anything is still undefined
for var in PKGDEST SRCDEST SRCPKGDEST LOGDEST BUILDDIR; do
- printf -v "$var" "$(canonicalize_path "${!var:-$startdir}")"
+ printf -v "$var" "${!var:-$startdir}"
done
unset var
PACKAGER=${PACKAGER:-"Unknown Packager"}
@@ -1378,23 +1378,23 @@ lint_config || exit $E_CONFIG_ERROR
# check that all settings directories are user-writable
-if ! ensure_writable_dir "BUILDDIR" "$BUILDDIR"; then
+if ! BUILDDIR=$(canonicalize_and_ensure_writable_dir "BUILDDIR" "$BUILDDIR"); then
plain "$(gettext "Aborting...")"
exit $E_FS_PERMISSIONS
fi
-if (( ! (NOBUILD || GENINTEG) )) && ! ensure_writable_dir "PKGDEST" "$PKGDEST"; then
+if (( ! (NOBUILD || GENINTEG) )) && ! PKGDEST=$(canonicalize_and_ensure_writable_dir "PKGDEST" "$PKGDEST"); then
plain "$(gettext "Aborting...")"
exit $E_FS_PERMISSIONS
fi
-if ! ensure_writable_dir "SRCDEST" "$SRCDEST" ; then
+if ! SRCDEST=$(canonicalize_and_ensure_writable_dir "SRCDEST" "$SRCDEST"); then
plain "$(gettext "Aborting...")"
exit $E_FS_PERMISSIONS
fi
if (( SOURCEONLY )); then
- if ! ensure_writable_dir "SRCPKGDEST" "$SRCPKGDEST"; then
+ if ! SRCPKGDEST=$(canonicalize_and_ensure_writable_dir "SRCPKGDEST" "$SRCPKGDEST"); then
plain "$(gettext "Aborting...")"
exit $E_FS_PERMISSIONS
fi
@@ -1404,7 +1404,7 @@ if (( SOURCEONLY )); then
IGNOREARCH=1
fi
-if (( LOGGING )) && ! ensure_writable_dir "LOGDEST" "$LOGDEST"; then
+if (( LOGGING )) && ! LOGDEST=$(canonicalize_and_ensure_writable_dir "LOGDEST" "$LOGDEST"); then
plain "$(gettext "Aborting...")"
exit $E_FS_PERMISSIONS
fi
--
2.18.0
More information about the pacman-dev
mailing list