#!/bin/bash

# Task: go through the files in $RPM_BUILD_ROOT and
# relink symbolic links so that all are relative
#
# NOTE: we're not doing this to fix a problem (as no matter how you
#   do it you fix one problem by creating another). We're doing it
#   so we can document this as policy - so you can rely on it

# Additional Task: check some usual errors arround symlinks e.g.
#   dangling symlinks or symlinks to init scripts in wrong location

# Author: Stephan Kulow <coolo@suse.de>
#
# major speedup: Tomas Cech <sleep_walker@suse.cz> and Michal Kubecek <mkubecek@suse.cz>
# migration to C++: Stephan Kulow <coolo@suse.de>

# If using normal root, avoid changing anything.
if [ -z "$RPM_BUILD_ROOT" ]; then
	exit 0
fi

LC_ALL=
LANG=
LC_TIME=POSIX

cd $RPM_BUILD_ROOT

had_errors=0

follow() {
# poor man's endless recursion checker
    follow=0
    _follow $1
}

_follow() {
    local file=$1
    local base=$(basename $file)
    local dir=$(dirname $file)
    local link

    test $(( ++follow )) -gt 16 && return 1
    test "$dir" = "/" && return 1
    if test -L "$dir"; then
	link=$(readlink $dir) || return 1
    elif test -L "./$dir"; then
	link=$(readlink ./$dir) || return 1
    fi
    if test -n "$link"; then
	if [[ $link =~ ^/ ]]; then
	    dir=$link
	else
	    dir=$(dirname $dir)/$link
	    dir=$(realpath -m $dir)
	fi
	if test -e ./$dir/$base || test -e $dir/$base; then
	    echo $dir/$base
	   return 0
	fi
    fi
    if dir=$(_follow $dir) && test -e ./$dir/$base -o -e $dir/$base; then
	echo $dir/$base
	return 0
    fi
    return 1
}

while IFS="|" read link link_orig link_dest link_absolut
do
    if test "$link" = "$link_dest"; then
        echo "ERROR: $link points to itself (as $orig_link_dest)"
        had_errors=1
        continue
    fi

    case "$link_absolut" in
        /etc/alternatives/*) # update alternative links are special
            link_dest=$link_absolut
            ;;
        /opt/kde3/share/doc*/HTML/*/common) # white listed for not existant
            ;;
        /usr/share/doc/kde/HTML/*/common) # white listed for not existant
            ;;
        /proc/*|/dev/*|/sys/*) # links pointing into kernel file system should be absolute
            link_dest=$link_absolut
            ;;
        /usr/src/linux*) # bsc#1186710 - usrmerge in combination of fixed /lib/modules
            link_dest=$link_absolut
            ;;
        ${RPM_BUILD_ROOT}*)
            echo "ERROR: Link $link -> $link_orig points inside build root!"
            had_errors=1
            continue
            ;;
        *share/automake-*)
            echo "ERROR: link target $link points into automake directory"
            echo " You might want to add a -c to the automake call (or just"
            echo " skip the files from packaging)"
            had_errors=1
            continue
            ;;
        *)
            if test ! -L ./"$link_absolut" && test ! -e "$link_absolut" && test ! -e ./"$link_absolut"; then
		if ! follow $link_absolut >/dev/null; then
                    echo "ERROR: link target doesn't exist (neither in build root nor in installed system):"
                    echo "  $link -> $link_orig"
                    echo "Add the package providing the target to BuildRequires and Requires"
                    if [ "$NO_BRP_STALE_LINK_ERROR" != "yes" ]; then
			had_errors=1
			continue
		    fi
                fi
            fi
            ;;
    esac

    if [ "$link_orig" != "$link_dest" ]; then
        echo "INFO: relinking $link -> $link_dest (was $link_orig)"
        # we need to remove the link first because it may point to a directory
        # and then semantic changes
        rm ./"$link" && ln -s "$link_dest" ./"$link"
    fi
done < <(find . -type l -printf '%P|%l\n' | sort | brp-symlink.prg)

if test "$had_errors" = 1; then
    exit 1
fi
