diff options
author | Lauri Aarnio <Lauri.Aarnio@iki.fi> | 2008-03-12 08:45:19 +0200 |
---|---|---|
committer | Lauri Leukkunen <lle@rahina.org> | 2008-03-14 07:41:00 +0200 |
commit | 6e880fd4c8c8deaafc00a8bc0030f0307cbc9164 (patch) | |
tree | ed1d977e849b5b4b444cc1e0b5b179e0960e8ae7 /utils | |
parent | a272c2848d168cddab58709fa4d89f0cac575031 (diff) |
Refactored sb2's dpkg-checkbuilddeps wrapper.
- not perfect, but with these modifications "dpkg-checkbuilddeps"
becomes finally usable in "maemo" mode (this needs mode-specific
configuration, which is currently available only for "maemo")
- dpkg-buildpackage can now be used without the "-d" option.
- see comments in utils/dpkg-checkbuilddeps for list of missing features
Diffstat (limited to 'utils')
-rwxr-xr-x | utils/dpkg-checkbuilddeps | 284 | ||||
-rw-r--r-- | utils/sb2-check-pkg-mappings | 134 | ||||
-rw-r--r-- | utils/sb2-show.c | 100 |
3 files changed, 472 insertions, 46 deletions
diff --git a/utils/dpkg-checkbuilddeps b/utils/dpkg-checkbuilddeps index e87f9f2..2651d05 100755 --- a/utils/dpkg-checkbuilddeps +++ b/utils/dpkg-checkbuilddeps @@ -1,59 +1,177 @@ #!/bin/bash # # Copyright (C) 2007 Lauri Leukkunen <lle@rahina.org> +# +# Redesigned/refactored by Lauri T. Aarnio; +# Portion Copyright (c) 2008 Nokia Corporation. +# All rights reserved. +# # Licensed under GPL version 2 # -# Idea behind operation is to use debian package tags to identify -# libraries, headers and other such "obviously" target stuff from -# build tools (gcc, doxygen, etc). This means that the build dependencies -# need to be checked against both target and host debian package databases -# and irrelevant failures need to be filtered from the results. -# This is far from ideal, but hopefully adequate for now. - +# ------------------- +# Idea behind operation is to first check target's package db, +# then check if missing packages are tools that could be used +# from the host (or SBOX_TOOLS_ROOT, if that has been set) +# +# FIXME: This implementation is still incomplete, as this does not +# check package versions while checking host/tools_root tools. +# Also, it would be a good idea to do a "visibility check" for host packages, +# too (see how sb2-check-pkg-mappings does it for target's pkg db) args="$*" -function run_dpkg_checkbuilddeps() -{ - missing_deps=$(/usr/bin/dpkg-checkbuilddeps $args 2>&1 | \ - grep "^dpkg-checkbuilddeps: Unmet build dependencies:" | \ - sed 's/dpkg-checkbuilddeps: Unmet build dependencies: //') -} +# Target's real package db: +TARGET_DPKG_ADMINDIR_ALL_PKGS=$SBOX_TARGET_ROOT/var/lib/dpkg -# takes two lists, one containing packages which are ok to miss, -# the other the list of packages that are missing -function check_missing_deps() +# Host (or built env.) package db: +HOST_DPKG_ADMINDIR=$SBOX_TOOLS_ROOT/var/lib/dpkg + +# A generated, temporary package db which only contains packages that +# are usable thru the current mapping mode: +SB2_TEMP_DPKG_ADMIN_DIR=$HOME/.scratchbox2/$SBOX_TARGET.tmp-pkg-db.$SBOX_MAPMODE +TARGET_DPKG_ADMINDIR_USABLE_PKGS=$SB2_TEMP_DPKG_ADMIN_DIR + +cfgfile_host_accepted_pkgs=$SBOX_DIR/share/scratchbox2/modeconf/host-accepted-packages.$SBOX_MAPMODE +cfgfile_host_ignored_pkgs=$SBOX_DIR/share/scratchbox2/modeconf/host-ignored-packages.$SBOX_MAPMODE + +# Check if a named package exists of the host. +# Returns result in three variables: +# - $installed_to_host is either "yes" or "no" +# - $check_result_msg and $check_result_msg2 return a more detailed +# explanation of the result (strings). +# This must be called with SBOX_DISABLE_MAPPING=1!! +function check_host_pkg() { - ok_list="$1" - missing_list="$2" - list_ok=0 - not_ok_missing_list="" - - for m in $(echo $missing_list | sed 's/([^)]\+)//g') ; do - m_ok=1 - for o in $ok_list ; do - if [ "$m" == "$o" ]; then - m_ok=0 + pkgname=$1 + + installed_to_host="no" # default + check_result_msg="'$pkgname' not found." + check_result_msg2="" + + # Check if it can be accepted from the host: + g=`grep "^$pkgname\$" $cfgfile_host_accepted_pkgs` + if [ -z "$g" ] + then + # No, the package has not been aproved to be used from the host. + + # first check if this requirement should be ignored completely: + if [ -f $cfgfile_host_ignored_pkgs ] + then + # ignorelist exists + g=`grep "^$pkgname\$" $cfgfile_host_ignored_pkgs` + if [ -z "$g" ] + then + check_result_msg="'$pkgname' is missing (must be installed to the rootstrap)" + else + check_result_msg="'$pkgname' is missing, but this is ignored by configuration" + installed_to_host="yes" + return fi - printf "Problem with: %s\n" $m - done - if [ $m_ok != 0 ]; then - list_ok=1 fi - done + + pkg_stat_tmp=/tmp/dpkg.$$.tmp + # next check again if the package exists on the target, + # just to be able to give a better error message. + if dpkg-query -s --admindir=$TARGET_DPKG_ADMINDIR_ALL_PKGS \ + "$pkgname" >$pkg_stat_tmp 2>&1 + then + if grep -q "ok installed" $pkg_stat_tmp + then + rm $pkg_stat_tmp + check_result_msg="'$pkgname': OOPS. Needed from the the rootstrap (installed there)," + check_result_msg2=" but unusable (not fully visible due to SB2 mapping rules)" + return + fi + fi + rm $pkg_stat_tmp + + check_result_msg="'$pkgname' is missing, must be istalled to the rootstrap" + return + fi + + # package is not present in the rootstrap, but + # it can be accepted from the host environment. + if dpkg-query -s --admindir=$HOST_DPKG_ADMINDIR "$pkgname" >/dev/null 2>&1 + then + installed_to_host="yes" + check_result_msg="'$pkgname' found from the host environment" + return + fi + + # not installed. Test if this can be ignored. + if [ -f $cfgfile_host_ignored_pkgs ] + then + g=`grep "^$pkgname\$" $cfgfile_host_ignored_pkgs` + if [ -n "$g" ] + then + check_result_msg="'$pkgname' is not available (ignored by configuration)" + return + fi + fi + + check_result_msg="'$pkgname' is missing (can be installed to the host)" + return 1 } function check_host_builddeps() { + missing="$1" ret=0 export SBOX_DISABLE_MAPPING=1 # do the magic here - echo "SB2 Checking host build deps..." - run_dpkg_checkbuilddeps - check_missing_deps "crap" "$missing_deps" + echo "SB2 Checking host build deps.." + + list_ok=1 # default to ok + # $m will be the package to test, or pkg/pkg[/...] if there are + # alternatives (unfortunately '|' has special meaning in shell's + # "case" statement, so we'll have to replace it by '/') + for m in $(echo $missing | sed -e 's/([^)]\+)//g' | \ + sed -e 's:[ ]*|[ ]*:/:g') + do + ## echo " Testing $m:" + case "$m" in + */*) # alternatives.. + has_one_alternative=0 + for mmm in $(echo $m | sed -e 's:/: :') + do + echo " ...$mmm" + check_host_pkg $mmm + if [ $? == 0 ] + then + # nothing is missing = nothing needed from the host side + echo " $mmm = ok" + has_one_alternative=1 + else + echo " no $mmm.." + fi + done + if [ $has_one_alternative == 0 ] + then + echo " Requirement $m failed; none of the alternatives were found." + list_ok=0 + else + echo " '$m': At least one alternative found, ok." + fi + ;; + + *) # No alternatives. + check_host_pkg $m + echo " $check_result_msg" + if [ -n "$check_result_msg2" ] + then + echo " $check_result_msg2" + fi + if [ "$installed_to_host" = "no" ] + then + list_ok=0 + fi + esac + + done + unset SBOX_DISABLE_MAPPING - if [ $list_ok != 0 ]; then + if [ $list_ok == 0 ]; then # somethings missing false else @@ -65,28 +183,106 @@ function check_target_builddeps() { ret=0 echo "SB2 Checking target build deps..." - run_dpkg_checkbuilddeps - check_missing_deps "crap2" "$missing_deps" - if [ $list_ok != 0 ]; then - echo "failing target deps" - false + + # call dpkg-checkbuilddeps with mapping disabled, because the + # version which is available in /usr/bin may not know about the + # --admindir option. Can't use a pipeline here, we want to the + # dpkg-checkbuilddeps' return status. + SBOX_DISABLE_MAPPING=1 /usr/bin/dpkg-checkbuilddeps \ + --admindir=$TARGET_DPKG_ADMINDIR_USABLE_PKGS $args \ + > /tmp/missing_deps.$$ 2>&1 + if [ $? == 0 ] + then + # real dpkg-checkbuilddeps says "all ok" + rm /tmp/missing_deps.$$ + return 0 + fi + + # else real dpkg-checkbuilddeps failed. + sed -e 's/^/ /' < /tmp/missing_deps.$$ + missing_deps=$(egrep \ + "^dpkg-checkbuilddeps: Unmet build dependencies:" \ + /tmp/missing_deps.$$ | \ + sed 's/dpkg-checkbuilddeps: Unmet build dependencies: //') + rm /tmp/missing_deps.$$ + + if [ -n "$missing_deps" ]; then + # failing target deps, and missing packages are listed + # in $missing_deps = continue by checking if those are + # available on the host environment + return 1 else - echo "target deps ok" - true + # failing target deps, but $missing_deps is empty. Something + # is fatally wrong. + exit 1 fi } +# First, make sure we are in a correct directory: +if [ ! -f debian/control ] +then + echo "Error: Can't find file debian/control" + exit 1 +fi + +# Next, check that the list of usable packages exists and is up-to-date. +# That list is really a temporary package database, which contains only +# packages that are usable thru this mapping mode. + +if [ ! -f $TARGET_DPKG_ADMINDIR_USABLE_PKGS/status ] +then + echo "$TARGET_DPKG_ADMINDIR_USABLE_PKGS/status does not exist." + echo "going to create it now. This is going to take a while.." + echo + sb2-check-pkg-mappings -a +elif [ $TARGET_DPKG_ADMINDIR_USABLE_PKGS/status -ot \ + $TARGET_DPKG_ADMINDIR_ALL_PKGS/status ] +then + echo "Target's primary package database has been updated =>" + echo "$TARGET_DPKG_ADMINDIR_USABLE_PKGS/status is out of date." + echo "going to update it now. This is going to take a while.." + echo + sb2-check-pkg-mappings -a +elif [ $TARGET_DPKG_ADMINDIR_USABLE_PKGS/status -ot \ + $SBOX_DIR/share/scratchbox2/lua_scripts/pathmaps/$SBOX_MAPMODE/00_default.lua ] +then + echo "SB2's mapping rules have been updated =>" + echo "$TARGET_DPKG_ADMINDIR_USABLE_PKGS/status might be out of date." + echo "going to update it now. This is going to take a while.." + echo + sb2-check-pkg-mappings -a +fi + check_target_builddeps -if [ $? != 0 ]; then +if [ $? == 0 ]; then + # nothing is missing = nothing needed from the host side + echo "Target rootstrap => all dependencies OK" + exit 0 +fi + +echo "Build dependencies missing from the target environment:" +echo " $missing_deps" + +# Something is missing. To be able to get the missing packages from the +# host environment, at least the list of allowed packages is needed: +# +if [ ! -f $cfgfile_host_accepted_pkgs ] +then + echo + echo "Configuration file $cfgfile_host_accepted_pkgs" + echo "does not exist. This means that no packages have been approved to be used" + echo "from the host environment in this mapping mode ($SBOX_MAPMODE)." exit 1 fi -check_host_builddeps +check_host_builddeps "$missing_deps" if [ $? != 0 ]; then + echo "Failed. Host environment did not meet all requirements." exit 1 fi # since we're here, everything is more or less ok +echo "All OK." exit 0 diff --git a/utils/sb2-check-pkg-mappings b/utils/sb2-check-pkg-mappings new file mode 100644 index 0000000..f09dcd1 --- /dev/null +++ b/utils/sb2-check-pkg-mappings @@ -0,0 +1,134 @@ +#!/bin/bash +# +# This script checks which .deb packages can be used from the rootstrap. +# +# dpkg-checkbuilddeps uses this to builds a new temporary "status" file of +# all usable packages. +# +# Copyright (c) 2008 Nokia Corporation. All rights reserved. +# Author: Lauri T. Aarnio +# Licensed under LGPL version 2.1, see top level LICENSE file for details. + +function usage() +{ + cat <<EOF +sb2-check-pkg-mappings - check usability of target's .deb packages +Usage: + sb2-check-pkg-mappings pkg1 [pkg2..] + sb2-check-pkg-mappings -a + +Options: + -a check all packages and write results to a temporary + database, to be used by sb2's dpkg-checkbuilddeps + +When started with list of package names, checks named packages and prints +results, but does not create or modify the temporary database. +EOF + exit 1 +} + +if [ -z "$*" ]; then + usage +fi + +check_all_pkgs="no" +status_file="" + +while getopts ah foo +do + case $foo in + (a) check_all_pkgs="yes" ;; + (h) usage ;; + (*) usage ;; + esac +done +shift $(($OPTIND - 1)) + +pkgs2check="$*" +tstamp=`/bin/date +%Y%m%d-%H%M` + +if [ -z "$pkgs2check" -a "$check_all_pkgs" = "yes" ] +then + # check all installed packages + pkgs2check=`dpkg --get-selections | grep 'install$' | sed -e 's/install$//'` + status_file=STATUS-NEW.$tstamp.$$ +elif [ "$check_all_pkgs" = "yes" ] +then + # -a and package names - illegal + usage +fi + +function remove_temp_files +{ + if [ -n "$status_file" -a -f "$status_file" ] + then + echo "removing temp file '$$status_file'" + rm $status_file + fi +} +trap remove_temp_files EXIT + +pkgnum=0 +num_ok=0 +num_failed=0 + +# Read the mode-specific path ignore list. +SB2_CHECK_PKG_MAPPINGS_IGNORE_LIST="" +if [ -f $SBOX_DIR/share/scratchbox2/modeconf/sb2rc.$SBOX_MAPMODE ] +then + . $SBOX_DIR/share/scratchbox2/modeconf/sb2rc.$SBOX_MAPMODE +fi + +# for all installed packages.. +for pkg in $pkgs2check +do + pkgnum=`expr $pkgnum + 1` + echo "=========== $pkgnum. Checking $pkg ===========" + + # get list of files intalled by this package (dpkg -L), + # and feed it to sb2-show to be verified (-D causes directories + # to be ignored). Also ignore all files which are installed + # to these diretories listed in $SB2_CHECK_PKG_MAPPINGS_IGNORE_LIST. + dpkg -L $pkg >/tmp/sb2-pkg-chk.$tstamp.$$ + if [ $? != 0 ] + then + num_failed=`expr $num_failed + 1` + echo " $pkg is not available" + else + sed < /tmp/sb2-pkg-chk.$tstamp.$$ \ + -e 's/diverted by .* to: //' \ + -e 's/package diverts others to: //' | + sb2-show -D verify-pathlist-mappings \ + $SBOX_TARGET_ROOT $SB2_CHECK_PKG_MAPPINGS_IGNORE_LIST + if [ $? == 0 ] + then + echo " $pkg = OK" + num_ok=`expr $num_ok + 1` + if [ $check_all_pkgs = "yes" ] + then + if [ -f $status_file ] + then + echo >>$status_file + fi + dpkg -s $pkg >>$status_file + fi + else + num_failed=`expr $num_failed + 1` + echo " $pkg can not be used in this mode ($SBOX_MAPMODE)" + fi + fi + rm /tmp/sb2-pkg-chk.$tstamp.$$ +done + +echo "Checked $pkgnum packages: Ok=$num_ok, unusable=$num_failed" + +if [ $check_all_pkgs = "yes" ] +then + SB2_TEMP_DPKG_ADMIN_DIR=$HOME/.scratchbox2/$SBOX_TARGET.tmp-pkg-db.$SBOX_MAPMODE + if [ ! -d $SB2_TEMP_DPKG_ADMIN_DIR ] + then + mkdir $SB2_TEMP_DPKG_ADMIN_DIR + fi + mv $status_file $SB2_TEMP_DPKG_ADMIN_DIR/status + echo "Results have been written to $SB2_TEMP_DPKG_ADMIN_DIR/status" +fi diff --git a/utils/sb2-show.c b/utils/sb2-show.c index 45ae35b..a5cc6bf 100644 --- a/utils/sb2-show.c +++ b/utils/sb2-show.c @@ -1,5 +1,5 @@ /* sb2-show: - * SB2 Mapping rule testingutility + * SB2 Mapping rule testing utility * * Copyright (c) 2008 Nokia Corporation. All rights reserved. * Author: Lauri T. Aarnio @@ -27,6 +27,8 @@ static void usage_exit(const char *progname, const char *errmsg, int exitstatus) "\t-m mode\t\tshow using named mapping mode " "(default=current mode)\n" "\t-f function\tshow using 'function' as callers name\n" + "\t-D\tignore directories while verifying path lists\n" + "\t-v\tverbose.\n" "\nCommands:\n" "\tpath [path1] [path2].." "\tShow mappings of pathnames\n" @@ -36,6 +38,9 @@ static void usage_exit(const char *progname, const char *errmsg, int exitstatus) "\tAdd an error message to the log\n" "\tlog-warning 'message'" "\tAdd a warning message to the log\n" + "\tverify-pathlist-mappings required-prefix [ignorelist]" + "\tread list of paths from stdin and/n" + "\t\tcheck that all paths will be mapped to required prefix/n" "\n'%s' must be executed inside sb2 sandbox" " (see the 'sb2' command)\n", progname, progname, progname); @@ -93,6 +98,89 @@ static void command_show_path(const char *binary_name, } } +/* read paths from stdin, report paths that are not mapped to specified + * directory. + * returns 0 if all OK, 1 if one or more paths were not mapped. +*/ +static int command_verify_pathlist_mappings( + const char *binary_name, + const char *mapping_mode, + const char *fn_name, + int ignore_directories, + int verbose, + const char *progname, + char **argv) +{ + int destination_prefix_len; + char path_buf[PATH_MAX + 1]; + const char *required_destination_prefix = argv[0]; + int result = 0; + + if (!required_destination_prefix) { + usage_exit(progname, "'destination_prefix' is missing", 1); + } + destination_prefix_len = strlen(required_destination_prefix); + + while (fgets(path_buf, sizeof(path_buf), stdin)) { + int len = strlen(path_buf); + char *mapped_path = NULL; + int readonly_flag; + int destination_prefix_cmp_result; + char **ignore_path; + int ignore_this = 0; + + if ((len > 0) && (path_buf[len-1] == '\n')) { + path_buf[--len] = '\0'; + } + if (len == 0) continue; + + for (ignore_path = argv+1; *ignore_path; ignore_path++) { + int ign_len = strlen(*ignore_path); + + if (!strncmp(path_buf, *ignore_path, ign_len)) { + ignore_this = 1; + if (verbose) + printf("IGNORED by prefix: %s\n", + path_buf); + break; + } + } + + if (ignore_this) continue; + + mapped_path = sb2show__map_path2__(binary_name, mapping_mode, + fn_name, path_buf, &readonly_flag); + + if (ignore_directories) { + struct stat statbuf; + + if ((stat(mapped_path, &statbuf) == 0) && + S_ISDIR(statbuf.st_mode)) { + if (verbose) + printf("%s => %s: dir, ignored\n", + path_buf, mapped_path); + continue; + } + } + + destination_prefix_cmp_result = strncmp(mapped_path, + required_destination_prefix, destination_prefix_len); + if (destination_prefix_cmp_result) { + result = 1; + printf("%s => %s%s: NOT OK\n", + path_buf, mapped_path, + (readonly_flag ? " (readonly)" : "")); + } else { + /* mapped OK. */ + if (verbose) + printf("%s => %s%s: Ok\n", + path_buf, mapped_path, + (readonly_flag ? " (readonly)" : "")); + } + } + return (result); +} + static void command_log(char **argv, int loglevel) { SB_LOG(loglevel, "%s", argv[0]); @@ -105,6 +193,8 @@ int main(int argc, char *argv[]) char *mapping_mode = NULL; char *function_name = "ANYFUNCTION"; char *binary_name = "ANYBINARY"; + int ignore_directories = 0; + int verbose = 0; #if 0 || defined(enable_this_after_sb2_preload_library_startup_has_been_fixed) /* FIXME: this should be able to check if we are inside the sb2 @@ -122,12 +212,14 @@ int main(int argc, char *argv[]) } #endif - while ((opt = getopt(argc, argv, "hm:f:b:")) != -1) { + while ((opt = getopt(argc, argv, "hm:f:b:Dv")) != -1) { switch (opt) { case 'h': usage_exit(progname, NULL, 0); break; case 'm': mapping_mode = optarg; break; case 'f': function_name = optarg; break; case 'b': binary_name = optarg; break; + case 'D': ignore_directories = 1; break; + case 'v': verbose = 1; break; default: usage_exit(progname, "Illegal option", 1); break; } } @@ -149,6 +241,10 @@ int main(int argc, char *argv[]) command_log(argv + optind + 1, SB_LOGLEVEL_ERROR); } else if (!strcmp(argv[optind], "log-warning")) { command_log(argv + optind + 1, SB_LOGLEVEL_WARNING); + } else if (!strcmp(argv[optind], "verify-pathlist-mappings")) { + return command_verify_pathlist_mappings(binary_name, + mapping_mode, function_name, ignore_directories, + verbose, progname, argv + optind + 1); } else { usage_exit(progname, "Unknown command", 1); } |