summaryrefslogtreecommitdiffstats
path: root/scripts/dpkg-realpath.sh
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xscripts/dpkg-realpath.sh178
1 files changed, 178 insertions, 0 deletions
diff --git a/scripts/dpkg-realpath.sh b/scripts/dpkg-realpath.sh
new file mode 100755
index 0000000..bb78610
--- /dev/null
+++ b/scripts/dpkg-realpath.sh
@@ -0,0 +1,178 @@
+#!/bin/sh
+#
+# Copyright © 2020 Helmut Grohne <helmut@subdivi.de>
+# Copyright © 2020 Guillem Jover <guillem@debian.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+PROGNAME=$(basename "$0")
+version="unknown"
+EOL="\n"
+
+PKGDATADIR_DEFAULT=scripts
+PKGDATADIR="${DPKG_DATADIR:-$PKGDATADIR_DEFAULT}"
+
+. "$PKGDATADIR/sh/dpkg-error.sh"
+
+show_version()
+{
+ cat <<END
+Debian $PROGNAME version $version.
+
+This is free software; see the GNU General Public License version 2 or
+later for copying conditions. There is NO warranty.
+END
+}
+
+show_usage()
+{
+ cat <<END
+Usage: $PROGNAME [<option>...] <pathname>
+
+Options:
+ -z, --zero end output line with NUL, not newline.
+ --instdir <directory> set the root directory.
+ --root <directory> set the root directory.
+ --version show the version.
+ -?, --help show this help message.
+END
+}
+
+canonicalize() {
+ local src="$1"
+ local root="$DPKG_ROOT"
+ local loop=0
+ local result="$root"
+ local dst
+
+ # Check whether the path is relative and make it absolute otherwise.
+ if [ "$src" = "${src#/}" ]; then
+ src="$(pwd)/$src"
+ src="${src#"$root"}"
+ fi
+
+ # Remove prefixed slashes.
+ while [ "$src" != "${src#/}" ]; do
+ src=${src#/}
+ done
+ while [ -n "$src" ]; do
+ # Get the first directory component.
+ prefix=${src%%/*}
+ # Remove the first directory component from src.
+ src=${src#"$prefix"}
+ # Remove prefixed slashes.
+ while [ "$src" != "${src#/}" ]; do
+ src=${src#/}
+ done
+ # Resolve the first directory component.
+ if [ "$prefix" = . ]; then
+ # Ignore, stay at the same directory.
+ :
+ elif [ "$prefix" = .. ]; then
+ # Go up one directory.
+ result=${result%/*}
+ if [ -n "$root" ] && [ "${result#"$root"}" = "$result" ]; then
+ result="$root"
+ fi
+ elif [ -h "$result/$prefix" ]; then
+ loop=$((loop + 1))
+ if [ "$loop" -gt 25 ]; then
+ error "too many levels of symbolic links"
+ fi
+ # Resolve the symlink within $result.
+ dst=$(readlink "$result/$prefix")
+ case "$dst" in
+ /*)
+ # Absolute pathname, reset result back to $root.
+ result=$root
+ src="$dst${src:+/$src}"
+ # Remove prefixed slashes.
+ while [ "$src" != "${src#/}" ]; do
+ src=${src#/}
+ done
+ ;;
+ *)
+ # Relative pathname.
+ src="$dst${src:+/$src}"
+ ;;
+ esac
+ else
+ # Otherwise append the prefix.
+ result="$result/$prefix"
+ fi
+ done
+ # We are done, print the resolved pathname, w/o $root.
+ result="${result#"$root"}"
+ printf "%s$EOL" "${result:-/}"
+}
+
+setup_colors
+
+DPKG_ROOT="${DPKG_ROOT:-}"
+export DPKG_ROOT
+
+while [ $# -ne 0 ]; do
+ case "$1" in
+ -z|--zero)
+ EOL="\0"
+ ;;
+ --instdir|--root)
+ shift
+ DPKG_ROOT=$1
+ ;;
+ --instdir=*)
+ DPKG_ROOT="${1#--instdir=}"
+ ;;
+ --root=*)
+ DPKG_ROOT="${1#--root=}"
+ ;;
+ --version)
+ show_version
+ exit 0
+ ;;
+ --help|-\?)
+ show_usage
+ exit 0
+ ;;
+ --)
+ shift
+ pathname="$1"
+ ;;
+ -*)
+ badusage "unknown option: $1"
+ ;;
+ *)
+ pathname="$1"
+ ;;
+ esac
+ shift
+done
+
+# Normalize root directory.
+DPKG_ROOT="${DPKG_ROOT:+$(realpath "$DPKG_ROOT")}"
+# Remove default root dir.
+if [ "$DPKG_ROOT" = "/" ]; then
+ DPKG_ROOT=""
+fi
+
+[ -n "$pathname" ] || badusage "missing pathname"
+if [ "${pathname#"$DPKG_ROOT"}" != "$pathname" ]; then
+ error "link '$pathname' includes root prefix '$DPKG_ROOT'"
+fi
+
+canonicalize "$pathname"
+
+exit 0