diff options
Diffstat (limited to '')
-rwxr-xr-x | scripts/dpkg-realpath.sh | 178 |
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 |