#!/bin/sh
#
# lint-shlibs.sh -- quick and dirty script to check shared libraries
#
# Copyright (c) 2019-2021 David Demelier <markand@malikania.fr>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

. $(busybox dirname $0)/scripts.subr

dependencies()
{
	vpk info -l $1 | while read -r file; do
		if ! file /$file | grep -q "dynamically linked"; then
			continue
		fi

		# TODO: this is absolutely insane.
		readelf -d /$file | grep -E 'Shared library' | awk '{ print $5 }' | sed -e "s/\[//" | sed -e "s/\]//" | while read -r library; do
			echo "$library"
		done
	done | sort | uniq
}

check()
{
	printf "${BOLD}==> checking shared libraries for $1:${RESET}\n"

	if ! vpk info $1 > /dev/null 2>&1; then
		echo "warning: not installed, can't verify" 1>&2
		return 1;
	fi

	dependencies $1 | while read -r lib; do
		# Skip implicit dependencies
		case $lib in
		"libc.so"*|"libc++.so"*|"libc++abi.so"*|"libunwind.so"*)
			continue
			;;
		esac

		# Find in which package this library belong to.
		local pkg=$(basename $(grep -l $lib /var/lib/vpk/* | head -n1))

		# Skip the dependency for itself.
		if [ "$pkg" = "$1" ]; then
			continue
		fi

		# Check if this package is dependency of it.
		if ! vpk info -m "depends" $1 | grep -q $pkg; then
			echo "$pkg dependency missing (shared library: $lib)"
		fi
	done
}

list()
{
	if [ "$#" -eq 0 ]; then
		vpk list | tr '\n' ' '
	else
		echo "$@"
	fi
}

for pkg in $(list "$@"); do
	check $pkg
done
