aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/revdep-rebuild')
-rw-r--r--src/revdep-rebuild/99revdep-rebuild21
-rw-r--r--src/revdep-rebuild/AUTHORS2
-rw-r--r--src/revdep-rebuild/ChangeLog9
-rw-r--r--src/revdep-rebuild/Makefile23
-rw-r--r--src/revdep-rebuild/README4
-rw-r--r--src/revdep-rebuild/TODO7
-rwxr-xr-xsrc/revdep-rebuild/find_pkgs.py22
-rwxr-xr-xsrc/revdep-rebuild/revdep-rebuild1094
-rwxr-xr-xsrc/revdep-rebuild/revdep-rebuild-old720
-rwxr-xr-xsrc/revdep-rebuild/revdep-rebuild-sh332
-rw-r--r--src/revdep-rebuild/revdep-rebuild.1101
11 files changed, 2335 insertions, 0 deletions
diff --git a/src/revdep-rebuild/99revdep-rebuild b/src/revdep-rebuild/99revdep-rebuild
new file mode 100644
index 0000000..bdaecc7
--- /dev/null
+++ b/src/revdep-rebuild/99revdep-rebuild
@@ -0,0 +1,21 @@
+# Default revdep-rebuild configuration file
+#
+# revdep-rebuild no longer uses hardcoded paths. To change the default
+# behavior the following variables can be changed:
+#
+# LD_LIBRARY_MASK - Mask of specially evaluated libraries
+#
+# SEARCH_DIRS - List of directories to search for executables and libraries
+# Use this for directories that are not included in PATH or ld.so.conf.
+# An application should normally not have to set this variable
+#
+# SEARCH_DIRS_MASK - List of directories to not search
+# Use this for directories that should not be searched by revdep-rebuild
+# This is normally used by binary packages such as openoffice-bin
+#
+# Note: This file is sourced using bash by the revdep-rebuild script
+
+LD_LIBRARY_MASK="libodbcinst.so libodbc.so libjava.so libjvm.so"
+SEARCH_DIRS="/bin /sbin /usr/bin /usr/sbin /lib* /usr/lib*"
+SEARCH_DIRS_MASK="/lib*/modules"
+
diff --git a/src/revdep-rebuild/AUTHORS b/src/revdep-rebuild/AUTHORS
new file mode 100644
index 0000000..b3d9b32
--- /dev/null
+++ b/src/revdep-rebuild/AUTHORS
@@ -0,0 +1,2 @@
+Stanislav Brabec (original author)
+Paul Varner <fuzzyray@gentoo.org>
diff --git a/src/revdep-rebuild/ChangeLog b/src/revdep-rebuild/ChangeLog
new file mode 100644
index 0000000..9060781
--- /dev/null
+++ b/src/revdep-rebuild/ChangeLog
@@ -0,0 +1,9 @@
+2005-06-05 Paul Varner <fuzzyray@gentoo.org>
+
+ * ChangeLog moved to main gentoolkit ChangeLog
+
+2004-01-07 Karl Trygve Kalleberg <karltk@gentoo.org>
+
+ * Added Makefile
+ * Copied revdep-rebuild script from app-portage/gentoolkit
+
diff --git a/src/revdep-rebuild/Makefile b/src/revdep-rebuild/Makefile
new file mode 100644
index 0000000..d509681
--- /dev/null
+++ b/src/revdep-rebuild/Makefile
@@ -0,0 +1,23 @@
+# Copyright 2004 Karl Trygve Kalleberg <karltk@gentoo.org>
+# Copyright 2004 Gentoo Technologies, Inc.
+# Distributed under the terms of the GNU General Public License v2
+#
+# $Header$
+
+include ../../makedefs.mak
+
+all:
+ echo "AIGBURTH (AYG-berth n.) Any piece of readily identifiable anatomy found among cooked meat."
+
+dist:
+ mkdir -p ../../$(distdir)/src/revdep-rebuild
+ cp Makefile AUTHORS README TODO ChangeLog revdep-rebuild revdep-rebuild.1 99revdep-rebuild ../../$(distdir)/src/revdep-rebuild/
+
+install:
+
+ install -m 0755 revdep-rebuild $(bindir)/
+ install -d $(docdir)/revdep-rebuild
+ install -m 0644 AUTHORS README TODO $(docdir)/revdep-rebuild/
+ install -m 0644 revdep-rebuild.1 $(mandir)/
+ install -d $(sysconfdir)/revdep-rebuild
+ install -m 0644 99revdep-rebuild $(sysconfdir)/revdep-rebuild/
diff --git a/src/revdep-rebuild/README b/src/revdep-rebuild/README
new file mode 100644
index 0000000..3a51d9f
--- /dev/null
+++ b/src/revdep-rebuild/README
@@ -0,0 +1,4 @@
+This tool scans libraries and binaries for broken shared lib dependencies
+and fixes them by re-emerging those broken binaries and shared libraries.
+
+- Alastair Tse <liquidx@gentoo.org>
diff --git a/src/revdep-rebuild/TODO b/src/revdep-rebuild/TODO
new file mode 100644
index 0000000..d9f6350
--- /dev/null
+++ b/src/revdep-rebuild/TODO
@@ -0,0 +1,7 @@
+- revdep cache in /var/cache
+ - list all .so files this package depends on
+ - use timestamps of files to know when to rebuild
+ - if ts of cache is older than any of the package's contained
+ files, we must rebuild
+- update to use equery/gentoolkit
+- rewrite in python and/or eclectic module
diff --git a/src/revdep-rebuild/find_pkgs.py b/src/revdep-rebuild/find_pkgs.py
new file mode 100755
index 0000000..7013813
--- /dev/null
+++ b/src/revdep-rebuild/find_pkgs.py
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+# Copyright 1999-2005 Gentoo Foundation
+# $Header$
+
+# Temporary script to find package versions and slot for revdep-rebuild
+
+import sys
+
+sys.path.insert(0, "/usr/lib/gentoolkit/pym")
+import gentoolkit
+
+for pkgname in sys.argv[1:]:
+ matches = gentoolkit.find_packages(pkgname)
+ for pkg in matches:
+ (cat, name, ver, rev) = gentoolkit.split_package_name(pkg.get_cpv())
+ slot = pkg.get_env_var("SLOT")
+ if rev == "r0":
+ fullversion = ver
+ else:
+ fullversion = ver + "-" + rev
+
+ print name + " " + fullversion + " (" + slot + ")"
diff --git a/src/revdep-rebuild/revdep-rebuild b/src/revdep-rebuild/revdep-rebuild
new file mode 100755
index 0000000..3ffe904
--- /dev/null
+++ b/src/revdep-rebuild/revdep-rebuild
@@ -0,0 +1,1094 @@
+#!/bin/bash
+# Copyright 1999-2008 Gentoo Foundation
+
+# revdep-rebuild: Reverse dependency rebuilder.
+# Original Author: Stanislav Brabec
+# Rewrite Author: Michael A. Smith
+# Current Maintainer: Paul Varner <fuzzyray@gentoo.org>
+
+# TODO:
+# - Use more /etc/init.d/functions.sh
+# - Try to reduce the number of global vars
+
+##
+# Global Variables:
+
+# Must-be-blank:
+unset GREP_OPTIONS
+
+# Readonly variables:
+declare -r APP_NAME="${0##*/}" # The name of this application
+declare -r OIFS="$IFS" # Save the IFS
+declare -r ENV_FILE=0_env.rr # Contains environment variables
+declare -r FILES_FILE=1_files.rr # Contains a list of files to search
+declare -r LDPATH_FILE=2_ldpath.rr # Contains the LDPATH
+declare -r BROKEN_FILE=3_broken.rr # Contains the list of broken files
+declare -r ERRORS_FILE=3_errors.rr # Contains the ldd error output
+declare -r RAW_FILE=4_raw.rr # Contains the raw list of packages
+declare -r OWNERS_FILE=4_owners.rr # Contains the file owners
+declare -r PKGS_FILE=4_pkgs.rr # Contains the unsorted bare package names
+declare -r EBUILDS_FILE=4_ebuilds.rr # Contains the unsorted atoms
+ # (Appropriately slotted or versioned)
+declare -r ORDER_FILE=5_order.rr # Contains the sorted atoms
+declare -r STATUS_FILE=6_status.rr # Contains the ldd error output
+declare -ra FILES=(
+ "$ENV_FILE"
+ "$FILES_FILE"
+ "$LDPATH_FILE"
+ "$BROKEN_FILE"
+ "$ERRORS_FILE"
+ "$RAW_FILE"
+ "$OWNERS_FILE"
+ "$PKGS_FILE"
+ "$EBUILDS_FILE"
+ "$ORDER_FILE"
+ "$STATUS_FILE"
+)
+
+# "Boolean" variables: Considered "true" if it has any value at all
+# "True" indicates we should...
+declare FULL_LD_PATH # ...search across the COMPLETE_LD_LIBRARY_PATH
+declare KEEP_TEMP # ...not delete tempfiles from the current run
+declare ORDER_PKGS # ...sort the atoms in deep dependency order
+declare PACKAGE_NAMES # ...emerge by slot, not by versionated atom
+declare RM_OLD_TEMPFILES # ...remove tempfiles from prior runs
+declare SEARCH_BROKEN # ...search for broken libraries and binaries
+declare VERBOSE # ...give verbose output
+
+# Globals that impact portage directly:
+declare EMERGE_DEFAULT_OPTS # String of options portage assumes to be set
+declare EMERGE_OPTIONS # Array of options to pass to portage
+declare PORTAGE_NICENESS # Renice to this value
+declare PORTAGE_ROOT # The root path for portage
+
+# Customizable incremental variables:
+# These variables can be prepended to either by setting the variable in
+# your environment prior to execution, or by placing an entry in
+# /etc/make.conf.
+#
+# An entry of "-*" means to clear the variable from that point forward.
+# Example: env SEARCH_DIRS="/usr/bin -*" revdep-rebuild will set SEARCH_DIRS
+# to contain only /usr/bin
+declare LD_LIBRARY_MASK # Mask of specially evaluated libraries
+declare SEARCH_DIRS # List of dirs to search for executables and libraries
+declare SEARCH_DIRS_MASK # List of dirs not to search
+
+# Other globals:
+declare OLDPROG # Previous pass through the progress meter
+declare EXACT_PKG # Versionated atom to emerge
+declare HEAD_TEXT # Feedback string about the search
+declare NOCOLOR # Set to "true" not to output term colors
+declare OK_TEXT # Feedback about a search which found no errors
+declare RC_NOCOLOR # Hack to insure we respect NOCOLOR
+declare REBUILD_LIST # Array of atoms to emerge
+declare SKIP_LIST # Array of atoms that cannot be emerged (masked?)
+declare SONAME # Soname/soname path pattern given on commandline
+declare SONAME_SEARCH # Value of SONAME modified to match ldd's output
+declare WORKING_TEXT # Feedback about the search
+declare WORKING_DIR # Working directory where cache files are kept
+
+main() {
+ # preliminary setup
+ get_opts "$@"
+ setup_portage
+ setup_search_paths_and_masks
+ get_search_env
+ echo
+
+ # Search for broken binaries
+ get_files
+ get_ldpath
+ main_checks
+
+ # Associate broken binaries with packages to rebuild
+ if [[ $PACKAGE_NAMES ]]; then
+ get_packages
+ clean_packages
+ assign_packages_to_ebuilds
+ else
+ get_exact_ebuilds
+ fi
+
+ # Rebuild packages owning broken binaries
+ get_build_order
+ rebuild
+
+ # All done
+ cleanup
+}
+##
+# Refuse to delete anything before we cd to our tmpdir
+# (See mkdir_and_cd_to_tmpdir()
+rm() {
+ eerror "I was instructed to rm '$@'"
+ die 1 "Refusing to delete anything before changing to temporary directory."
+}
+##
+# GNU find has -executable, but if our users' finds do not have that flag
+# we emulate it with this function. Also emulates -writable and -readable.
+# Usage: find PATH ARGS -- use find like normal, except use -executable instead
+# of various versions of -perm /+ blah blah and hacks
+find() {
+ hash find || { die 1 'find not found!'; }
+ # We can be pretty sure find itself should be executable.
+ local testsubject="$(type -P find)"
+ if [[ $(command find "$testsubject" -executable 2> /dev/null) ]]; then
+ unset -f find # We can just use the command find
+ elif [[ $(command find "$testsubject" -perm /u+x 2> /dev/null) ]]; then
+ find() {
+ a=(${@//-executable/-perm \/u+x})
+ a=(${a[@]//-writable/-perm \/u+w})
+ a=(${a[@]//-readable/-perm \/r+w})
+ command find "${a[@]}"
+ }
+ elif [[ $(command find "$testsubject" -perm +u+x 2> /dev/null) ]]; then
+ find() {
+ a=(${@//-executable/-perm +u+x})
+ a=(${a[@]//-writable/-perm +u+w})
+ a=(${a[@]//-readable/-perm +r+w})
+ command find "${a[@]}"
+ }
+ else # Last resort
+ find() {
+ a=(${@//-executable/-exec test -x '{}' \; -print})
+ a=(${a[@]//-writable/-exec test -w '{}' \; -print})
+ a=(${a[@]//-readable/-exec test -r '{}' \; -print})
+ command find "${a[@]}"
+ }
+ fi
+ find "$@"
+}
+
+print_usage() {
+cat << EOF
+Usage: $APP_NAME [OPTIONS] [--] [EMERGE_OPTIONS]
+
+Broken reverse dependency rebuilder.
+
+ -C, --nocolor Turn off colored output
+ -d, --debug Print way too much information (uses bash's set -xv)
+ -e, --exact Emerge based on exact package version
+ -h, --help Print this usage
+ -i, --ignore Ignore temporary files from previous runs
+ -k, --keep-temp Do not delete temporary files on exit
+ -L, --library NAME Emerge existing packages that use the library with NAME
+ --library=NAME NAME can be a full path to the library or a basic
+ regular expression (man grep)
+ -l, --no-ld-path Do not set LD_LIBRARY_PATH
+ -o, --no-order Do not check the build order
+ (Saves time, but may cause breakage.)
+ -p, --pretend Do a trial run without actually emerging anything
+ (also passed to emerge command)
+ -P, --no-progress Turn off the progress meter
+ -q, --quiet Be less verbose (also passed to emerge command)
+ -v, --verbose Be more verbose (also passed to emerge command)
+
+Calls emerge, options after -- are ignored by $APP_NAME
+and passed directly to emerge.
+
+Report bugs to <http://bugs.gentoo.org>
+EOF
+}
+##
+# Usage: progress i n
+# i: current item
+# n: total number of items to process
+progress() {
+ if [[ -t 1 ]]; then
+ progress() {
+ local curProg=$(( $1 * 100 / $2 ))
+ (( curProg == OLDPROG )) && return # no change, output nothing
+ OLDPROG="$curProg" # must be a global variable
+ (( $1 == $2 )) && local lb=$'\n'
+ echo -ne '\r \r'"[ $curProg% ] $lb"
+ }
+ progress $@
+ else # STDOUT is not a tty. Disable progress meter.
+ progress() { :; }
+ fi
+}
+##
+# Usage: countdown n
+# n: number of seconds to count
+countdown() {
+ local i
+ for ((i=1; i<$1; i++)); do
+ echo -ne '\a.'
+ ((i<$1)) && sleep 1
+ done
+ echo -e '\a.'
+}
+##
+# Replace whitespace with linebreaks, normalize repeated '/' chars, and sort -u
+# (If any libs have whitespace in their filenames, someone needs punishment.)
+clean_var() {
+ awk 'BEGIN {RS="[[:space:]]"}
+ /-\*/ {exit}
+ /[^[:space:]]/ {gsub(/\/\/+/, "/"); print}' | sort -u
+}
+##
+# Exit and optionally output to sterr
+die() {
+ local status=$1
+ shift
+ eerror "$@"
+ exit $status
+}
+##
+# What to do when dynamic linking is consistent
+clean_exit() {
+ if [[ ! $KEEP_TEMP ]]; then
+ rm -f "${FILES[@]}"
+ if [[ "$WORKING_DIR" != "/var/cache/${APP_NAME}" ]]; then
+ # Remove the working directory
+ builtin cd; rmdir "$WORKING_DIR"
+ fi
+ fi
+ echo
+ einfo "$OK_TEXT... All done. "
+ exit 0
+}
+##
+# Get the name of the package that owns a file or list of files given as args.
+get_file_owner() {
+ local IFS=$'\n'
+ # ${*/%/ } adds a space to the end of each object name to prevent false
+ # matches, for example /usr/bin/dia matching /usr/bin/dialog (bug #196460).
+ find -L /var/db/pkg -name CONTENTS -print0 |
+ xargs -0 grep -Fl "${*/%/ }" |
+ sed 's:/var/db/pkg/\(.*\)/CONTENTS:\1:'
+}
+##
+# Normalize some EMERGE_OPTIONS
+normalize_emerge_opts() {
+ # Normalize some EMERGE_OPTIONS
+ EMERGE_OPTIONS=(${EMERGE_OPTIONS[@]/%-p/--pretend})
+ EMERGE_OPTIONS=(${EMERGE_OPTIONS[@]/%-f/--fetchonly})
+ EMERGE_OPTIONS=(${EMERGE_OPTIONS[@]/%-f/--verbose})
+}
+##
+# Use the color preference from portage
+setup_color() {
+ # This should still work if NOCOLOR is set by the -C flag or in the user's
+ # environment.
+ export NOCOLOR=$(portageq envvar NOCOLOR)
+ [[ $NOCOLOR = yes || $NOCOLOR = true ]] && export RC_NOCOLOR=yes # HACK! (grr)
+ . /etc/init.d/functions.sh
+}
+##
+# Die if an argument is missing.
+die_if_missing_arg() {
+ [[ ! $2 || $2 = -* ]] && die 1 "Missing expected argument to $1"
+}
+##
+# Die because an option is not recognized.
+die_invalid_option() {
+ # Can't use eerror and einfo because this gets called before function.sh
+ # is sourced
+ echo
+ echo "Encountered unrecognized option $1." >&2
+ echo
+ echo "$APP_NAME no longer automatically passes unrecognized options to portage."
+ echo "Separate emerge-only options from revdep-rebuild options with the -- flag."
+ echo
+ echo "For example, $APP_NAME -v -- --ask"
+ echo
+ echo "See the man page or $APP_NAME -h for more detail."
+ echo
+ exit 1
+}
+##
+# Warn about deprecated options.
+warn_deprecated_opt() {
+ # Can't use eerror and einfo because this gets called before function.sh
+ # is sourced
+ echo
+ echo "Encountered deprecated option $1." >&2
+ [[ $2 ]] && echo "Please use $2 instead." >&2
+}
+##
+# Get whole-word commandline options preceded by two dashes.
+get_longopts() {
+ case $1 in
+ --nocolor) export NOCOLOR="yes";;
+ --no-color) warn_deprecated_opt "$1" "--nocolor"
+ export NOCOLOR="yes";;
+ --debug) set -xv;;
+ --exact) unset PACKAGE_NAMES;;
+ --help) print_usage
+ exit 0;;
+ --ignore) RM_OLD_TEMPFILES=1;;
+ --keep-temp) KEEP_TEMP=1;;
+ --library=*) # TODO: check for invalid values
+ SONAME="${1#*=}"
+ unset SEARCH_BROKEN;;
+ --soname=*|--soname-regexp=*) # TODO: check for invalid values
+ warn_deprecated_opt "${1%=*}" "--library"
+ SONAME="${1#*=}"
+ unset SEARCH_BROKEN;;
+ --library) # TODO: check for invalid values
+ die_if_missing_arg $1 $2
+ shift
+ SONAME="$1"
+ unset SEARCH_BROKEN;;
+ --soname|--soname-regexp) # TODO: check for invalid values
+ warn_deprecated_opt "$1" "--library"
+ die_if_missing_arg $1 $2
+ shift
+ SONAME="$1"
+ unset SEARCH_BROKEN;;
+ --no-ld-path) unset FULL_LD_PATH;;
+ --no-order) unset ORDER_PKGS;;
+ --no-progress) progress() { :; };;
+ --pretend) EMERGE_OPTIONS+=("--pretend");;
+ --quiet) echo_v() { :; }
+ progress() { :; }
+ quiet=1
+ EMERGE_OPTIONS+=($1);;
+ --verbose) VERBOSE=1
+ EMERGE_OPTIONS+=("--verbose");;
+ --extra-verbose) warn_deprecated_opt "$1" "--verbose"
+ VERBOSE=1
+ EMERGE_OPTIONS+=("--verbose");;
+ --package-names) # No longer used, since it is the
+ # default. We accept it for
+ # backwards compatibility.
+ warn_deprecated_opt "$1"
+ PACKAGE_NAMES=1;;
+ *) die_invalid_option $1;;
+ esac
+}
+
+##
+# Get single-letter commandline options preceded by a single dash.
+get_shortopts() {
+ local OPT OPTSTRING OPTARG OPTIND
+ while getopts ":CdehikL:loPpqu:vX" OPT; do
+ case "$OPT" in
+ C) # TODO: Match syntax with the rest of gentoolkit
+ export NOCOLOR="yes";;
+ d) set -xv;;
+ e) unset PACKAGE_NAMES;;
+ h) print_usage
+ exit 0;;
+ i) RM_OLD_TEMPFILES=1;;
+ k) KEEP_TEMP=1;;
+ L) # TODO: Check for invalid values
+ SONAME="${OPTARG#*=}"
+ unset SEARCH_BROKEN;;
+ l) unset FULL_LD_PATH;;
+ o) unset ORDER_PKGS;;
+ P) progress() { :; };;
+ p) EMERGE_OPTIONS+=("--pretend");;
+ q) echo_v() { :; }
+ progress() { :; }
+ quiet=1
+ EMERGE_OPTIONS+=("--quiet");;
+ v) VERBOSE=1
+ EMERGE_OPTIONS+=("--verbose");;
+ X) # No longer used, since it is the default.
+ # We accept it for backwards compatibility.
+ warn_deprecated_opt "-X"
+ PACKAGE_NAMES=1;;
+ *) die_invalid_option "-$OPTARG";;
+ esac
+ done
+}
+##
+# Get command-line options.
+get_opts() {
+ local avoid_utils
+ local -a args
+ echo_v() { ewarn "$@"; }
+ unset VERBOSE KEEP_TEMP EMERGE_OPTIONS RM_OLD_TEMPFILES
+ ORDER_PKGS=1
+ PACKAGE_NAMES=1
+ SONAME="not found"
+ SEARCH_BROKEN=1
+ FULL_LD_PATH=1
+ while [[ $1 ]]; do
+ case $1 in
+ --) shift
+ EMERGE_OPTIONS+=("$@")
+ break;;
+ -*) while true; do
+ args+=("$1")
+ shift
+ [[ ${1:--} = -* ]] && break
+ done
+ if [[ ${args[0]} = --* ]]; then
+ get_longopts "${args[@]}"
+ else
+ get_shortopts "${args[@]}"
+ fi;;
+ *) die_invalid_option "$1";;
+ esac
+ unset args
+ done
+
+ setup_color
+ normalize_emerge_opts
+
+ # If the user is not super, add --pretend to EMERGE_OPTIONS
+ if [[ ${EMERGE_OPTIONS[@]} != *--pretend* && $UID -ne 0 ]]; then
+ ewarn "You are not superuser. Adding --pretend to emerge options."
+ EMERGE_OPTIONS+=(--pretend)
+ fi
+}
+##
+# Is there a --pretend or --fetchonly flag in the EMERGE_OPTIONS array?
+is_real_merge() {
+ [[ ${EMERGE_OPTIONS[@]} != *--pretend* &&
+ ${EMERGE_OPTIONS[@]} != *--fetchonly* ]]
+}
+##
+# Clean up temporary files and exit
+cleanup_and_die() {
+ rm -f "$@"
+ die 1 " ...terminated. Removing incomplete $@."
+}
+##
+# Clean trap
+clean_trap() {
+ trap "cleanup_and_die $*" SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM
+ rm -f "$@"
+}
+##
+# Returns 0 if the first arg is found in the remaining args, 1 otherwise
+# (Returns 2 if given fewer than 2 arguments)
+has() {
+ (( $# > 1 )) || return 2
+ local IFS=$'\a' target="$1"
+ shift
+ [[ $'\a'"$*"$'\a' = *$'\a'$target$'\a'* ]]
+}
+##
+# Dies when it can't change directories
+cd() {
+ if builtin cd -P "$@"; then
+ if [[ $1 != $PWD ]]; then
+ # Some symlink malfeasance is going on
+ die 1 "Working directory expected to be $1, but it is $PWD"
+ fi
+ else
+ die 1 "Unable to change working directory to '$@'"
+ fi
+}
+##
+# Tries not to delete any files or directories it shouldn't
+setup_rm() {
+ ##
+ # Anything in the FILES array in tmpdir is fair game for removal
+ rm() {
+ local i IFS=$'\a'
+ [[ $APP_NAME ]] || die 1 '$APP_NAME is not defined! (This is a bug.)'
+ case $@ in
+ */*|*-r*|*-R*) die 1 "Oops, I'm not allowed to delete that. ($@)";;
+ esac
+ for i; do
+ # Don't delete files that are not listed in the array
+ # Allow no slashes or recursive deletes at all.
+ case $i in
+ */*|-*r*|-*R*) :;; # Not OK
+ -*) continue;; # OK
+ esac
+ has "$i" "${FILES[@]}" && continue
+ die 1 "Oops, I'm not allowed to delete that. ($@)"
+ done
+ command rm "$@"
+ }
+ # delete this setup function so it's harmless to re-run
+ setup_rm() { :; }
+}
+##
+# Make our temporary files directory
+# $1 - directory name
+# $2 - user name
+verify_tmpdir() {
+ umask 007 || die $? "Unable to set umask 007"
+ if [[ ! $1 ]]; then
+ die 1 'Temporary file path is unset! (This is a bug.)'
+ elif [[ -d $1 ]]; then
+ # HACK: I hate using find this way
+ if [[ $(find "$1" -type d ! \( -user $2 -perm -0700 \) ) ]]; then
+ eerror "Incorrect permissions on $1"
+ eerror "or at least one file in $1."
+ die 1 "Please make sure it's not a symlink and then remove it."
+ fi
+ cd "$1"
+ else
+ die 1 "Unable to find a satisfactory location for temporary files ($1)"
+ fi
+ [[ $VERBOSE ]] && einfo "Temporary cache files are located in $PWD"
+ setup_rm
+}
+get_search_env() {
+ local new_env
+ local old_env
+ local uid=$(python -c 'import os; import pwd; print pwd.getpwuid(os.getuid())[0]')
+ # Find a place to put temporary files
+ if [[ "$uid" == "root" ]]; then
+ local tmp_target="/var/cache/${APP_NAME}"
+ else
+ local tmp_target="$(mktemp -d -t revdep-rebuild.XXXXXXXXXX)"
+ fi
+
+ # From here on all work is done inside the temporary directory
+ verify_tmpdir "$tmp_target" "$uid"
+ WORKING_DIR="$tmp_target"
+
+ if [[ $SEARCH_BROKEN ]]; then
+ SONAME_SEARCH="$SONAME"
+ HEAD_TEXT="broken by a package update"
+ OK_TEXT="Dynamic linking on your system is consistent"
+ WORKING_TEXT="consistency"
+ else
+ # first case is needed to test against /path/to/foo.so
+ if [[ $SONAME = /* ]]; then
+ # Set to "<space>$SONAME<space>"
+ SONAME_SEARCH=" $SONAME "
+ # Escape the "/" characters
+ SONAME_SEARCH="${SONAME_SEARCH//\//\\/}"
+ else
+ # Set to "<tab>$SONAME<space>"
+ SONAME_SEARCH=$'\t'"$SONAME "
+ fi
+ HEAD_TEXT="using $SONAME"
+ OK_TEXT="There are no dynamic links to $SONAME"
+ unset WORKING_TEXT
+ fi
+
+ # If any of our temporary files are older than 1 day, remove them all
+ if [[ ! $KEEP_TEMP ]]; then
+ while read; do
+ RM_OLD_TEMPFILES=1
+ break
+ done < <(find -L . -maxdepth 1 -type f -name '*.rr' -mmin +1440 -print 2>/dev/null)
+ fi
+
+ # Compare old and new environments
+ # Don't use our previous files if environment doesn't match
+ new_env=$(
+ # We do not care if these emerge options change
+ EMERGE_OPTIONS=(${EMERGE_OPTIONS[@]//--pretend/})
+ EMERGE_OPTIONS=(${EMERGE_OPTIONS[@]//--fetchonly/})
+ EMERGE_OPTIONS=(${EMERGE_OPTIONS[@]//--verbose/})
+ cat <<- EOF
+ SEARCH_DIRS="$SEARCH_DIRS"
+ SEARCH_DIRS_MASK="$SEARCH_DIRS_MASK"
+ LD_LIBRARY_MASK="$LD_LIBRARY_MASK"
+ PORTAGE_ROOT="$PORTAGE_ROOT"
+ EMERGE_OPTIONS="${EMERGE_OPTIONS[@]}"
+ ORDER_PKGS="$ORDER_PKGS"
+ FULL_LD_PATH="$FULL_LD_PATH"
+ EOF
+ )
+ if [[ -r "$ENV_FILE" && -s "$ENV_FILE" ]]; then
+ old_env=$(<"$ENV_FILE")
+ if [[ $old_env != $new_env ]]; then
+ ewarn 'Environment mismatch from previous run, deleting temporary files...'
+ RM_OLD_TEMPFILES=1
+ fi
+ else
+ # No env file found, silently delete any other tempfiles that may exist
+ RM_OLD_TEMPFILES=1
+ fi
+
+ # If we should remove old tempfiles, do so
+ if [[ $RM_OLD_TEMPFILES ]]; then
+ rm -f "${FILES[@]}"
+ else
+ for file in "${FILES[@]}"; do
+ if [ -e "$file" ]; then
+ chown ${uid}:portage "$file"
+ chmod 700 "$file"
+ fi
+ done
+ fi
+
+ # Save the environment in a file for next time
+ echo "$new_env" > "$ENV_FILE"
+
+ [[ $VERBOSE ]] && echo $'\n'"$APP_NAME environment:"$'\n'"$new_env"
+
+ echo
+ einfo "Checking reverse dependencies"
+ einfo "Packages containing binaries and libraries $HEAD_TEXT"
+ einfo "will be emerged."
+}
+
+get_files() {
+ einfo "Collecting system binaries and libraries"
+ if [[ -r "$FILES_FILE" && -s "$FILES_FILE" ]]; then
+ einfo "Found existing $FILES_FILE"
+ else
+ # Be safe and remove any extraneous temporary files
+ # Don't remove 0_env.rr - The first file in the array
+ rm -f "${FILES[@]:1}"
+
+ clean_trap "$FILES_FILE"
+
+ if [[ $SEARCH_DIRS_MASK ]]; then
+ findMask=($SEARCH_DIRS_MASK)
+ findMask="${findMask[@]/#/-o -path }"
+ findMask="( ${findMask#-o } ) -prune -o"
+ fi
+ # TODO: Check this
+ find ${SEARCH_DIRS[@]} $findMask -type f \( -executable -o \
+ -name '*.so' -o -name '*.so.*' -o -name '*.la' \) -print 2> /dev/null |
+ sort -u > "$FILES_FILE" ||
+ die $? "find failed to list binary files (This is a bug.)"
+ einfo "Generated new $FILES_FILE"
+ fi
+}
+get_ldpath() {
+ local COMPLETE_LD_LIBRARY_PATH
+ [[ $SEARCH_BROKEN && $FULL_LD_PATH ]] || return
+ einfo 'Collecting complete LD_LIBRARY_PATH'
+ if [[ -r "$LDPATH_FILE" && -s "$LDPATH_FILE" ]]; then
+ einfo "Found existing $LDPATH_FILE."
+ else
+ clean_trap "$LDPATH_FILE"
+ # Ensure that the "trusted" lib directories are at the start of the path
+ COMPLETE_LD_LIBRARY_PATH=(
+ /lib*
+ /usr/lib*
+ $(sed '/^#/d;s/#.*$//' < /etc/ld.so.conf)
+ $(sed 's:/[^/]*$::' < "$FILES_FILE" | sort -ru)
+ )
+ IFS=':'
+ COMPLETE_LD_LIBRARY_PATH="${COMPLETE_LD_LIBRARY_PATH[*]}"
+ IFS="$OIFS"
+ echo "$COMPLETE_LD_LIBRARY_PATH" > "$LDPATH_FILE"
+ einfo "Generated new $LDPATH_FILE"
+ fi
+}
+main_checks() {
+ local target_file
+ local -a files
+ local i=0
+ local ldd_output
+ local ldd_status
+ local numFiles
+ local COMPLETE_LD_LIBRARY_PATH
+ if [[ $SEARCH_BROKEN && $FULL_LD_PATH ]]; then
+ [[ -r "$LDPATH_FILE" && -s "$LDPATH_FILE" ]] ||
+ die 1 "Unable to find $LDPATH_FILE"
+ COMPLETE_LD_LIBRARY_PATH=$(<"$LDPATH_FILE")
+ fi
+ einfo "Checking dynamic linking $WORKING_TEXT"
+ if [[ -r "$BROKEN_FILE" && -s "$BROKEN_FILE" ]]; then
+ einfo "Found existing $BROKEN_FILE."
+ else
+ clean_trap "$BROKEN_FILE" "$ERRORS_FILE"
+ files=($(<"$FILES_FILE"))
+ numFiles="${#files[@]}"
+ for target_file in "${files[@]}"; do
+ if [[ $target_file != *.la ]]; then
+ # Note: double checking seems to be faster than single with complete path
+ # (special add ons are rare).
+ ldd_output=$(ldd "$target_file" 2>> "$ERRORS_FILE" | sort -u)
+ ldd_status=$? # TODO: Check this for problems with sort
+ # HACK: if LD_LIBRARY_MASK is null or undefined grep -vF doesn't work
+ if grep -vF "${LD_LIBRARY_MASK:=$'\a'}" <<< "$ldd_output" |
+ grep -q "$SONAME_SEARCH"; then
+ if [[ $SEARCH_BROKEN && $FULL_LD_PATH ]]; then
+ if LD_LIBRARY_PATH="$COMPLETE_LD_LIBRARY_PATH" ldd "$target_file" 2>/dev/null |
+ grep -vF "$LD_LIBRARY_MASK" | grep -q "$SONAME_SEARCH"; then
+ # FIXME: I hate duplicating code
+ # Only build missing direct dependencies
+ MISSING_LIBS=$(
+ expr='s/[[:space:]]*\([^[:space:]]*\) => not found/\1/p'
+ sed -n "$expr" <<< "$ldd_output"
+ )
+ REQUIRED_LIBS=$(
+ expr='s/^[[:space:]]*NEEDED[[:space:]]*\([^[:space:]]*\).*/\1/p';
+ objdump -x "$target_file" | grep NEEDED | sed "$expr" | sort -u
+ )
+ MISSING_LIBS=$(grep -F "$REQUIRED_LIBS" <<< "$MISSING_LIBS")
+ if [[ $MISSING_LIBS ]]; then
+ echo "obj $target_file" >> "$BROKEN_FILE"
+ echo_v " broken $target_file (requires $MISSING_LIBS)"
+ fi
+ fi
+ else
+ # FIXME: I hate duplicating code
+ # Only rebuild for direct dependencies
+ MISSING_LIBS=$(
+ expr="/$SONAME_SEARCH/s/^[[:space:]]*\([^[:space:]]*\).*$/\1/p"
+ sort -u <<< "$ldd_output" | sed -n "$expr"
+ )
+ REQUIRED_LIBS=$(
+ expr='s/^[[:space:]]*NEEDED[[:space:]]*\([^[:space:]]*\).*/\1/p';
+ objdump -x "$target_file" | grep NEEDED | sed "$expr" | sort -u
+ )
+ MISSING_LIBS=$(grep -F "$REQUIRED_LIBS" <<< "$MISSING_LIBS")
+ if [[ $MISSING_LIBS ]]; then
+ echo "obj $target_file" >> "$BROKEN_FILE"
+ if [[ $SEARCH_BROKEN ]]; then
+ echo_v " broken $target_file (requires $MISSING_LIBS)"
+ else
+ echo_v " found $target_file"
+ fi
+ fi
+ fi
+ fi
+ elif [[ $SEARCH_BROKEN ]]; then
+ # Look for broken .la files
+ for depend in $(
+ awk -F"[=']" '/^dependency_libs/{
+ gsub("^-[^[:space:]]*", "", $3);
+ gsub("[[:space:]]-[^[:space:]]*", "", $3);
+ print $3
+ }' "$target_file"
+ ); do
+ if [[ $depend = /* && ! -e $depend ]]; then
+ echo "obj $target_file" >> "$BROKEN_FILE"
+ echo_v " broken $target_file (requires $depend)"
+ fi
+ done
+ fi
+ [[ $VERBOSE ]] &&
+ progress $((++i)) $numFiles $target_file ||
+ progress $((++i)) $numFiles
+ done
+ if [[ $SEARCH_BROKEN ]]; then
+ # Look for missing version
+ while read target_file; do
+ echo "obj $target_file" >> "$BROKEN_FILE"
+ echo_v " broken $target_file (no version information available)"
+ done < <(
+ # Regexify LD_LIBRARY_MASK. Exclude it from the search.
+ LD_LIBRARY_MASK="${LD_LIBRARY_MASK//$'\n'/|}"
+ awk -v ldmask="(${LD_LIBRARY_MASK//./\\\.})" '
+ /no version information available/ && $0 !~ ldmask {
+ gsub(/[()]/, "", $NF)
+ if (seen[$NF]++) next
+ print $NF
+ }' "$ERRORS_FILE"
+ )
+ fi
+ [[ -r "$BROKEN_FILE" && -s "$BROKEN_FILE" ]] || clean_exit
+ sort -u "$BROKEN_FILE" -o "$BROKEN_FILE"
+ einfo "Generated new $BROKEN_FILE"
+ fi
+}
+get_packages() {
+ local target_file
+ local EXACT_PKG
+ local PKG
+ local obj
+ einfo 'Assigning files to packages'
+ if [[ -r "$RAW_FILE" && -s "$RAW_FILE" ]]; then
+ einfo "Found existing $RAW_FILE"
+ else
+ clean_trap "$RAW_FILE" "$OWNERS_FILE"
+ while read obj target_file; do
+ EXACT_PKG=$(get_file_owner $target_file)
+ if [[ $EXACT_PKG ]]; then
+ # Strip version information
+ PKG="${EXACT_PKG%%-r[[:digit:]]*}"
+ PKG="${PKG%-*}"
+ echo "$EXACT_PKG" >> "$RAW_FILE"
+ echo "$target_file -> $EXACT_PKG" >> "$OWNERS_FILE"
+ echo_v " $target_file -> $PKG"
+ else
+ ewarn " !!! $target_file not owned by any package is broken !!!"
+ echo "$target_file -> (none)" >> "$OWNERS_FILE"
+ echo_v " $target_file -> (none)"
+ fi
+ done < "$BROKEN_FILE"
+ einfo "Generated new $RAW_FILE and $OWNERS_FILE"
+ fi
+ # if we find '(none)' on every line, exit out
+ if ! grep -qvF '(none)' "$OWNERS_FILE"; then
+ ewarn "Found some broken files, but none of them were associated with known packages"
+ ewarn "Unable to proceed with automatic repairs."
+ ewarn "The broken files are listed in $OWNERS_FILE"
+ if [[ $VERBOSE ]]; then
+ ewarn "The broken files are:"
+ while read filename junk; do
+ ewarn " $filename"
+ done < "$OWNERS_FILE"
+ fi
+ exit 0 # FIXME: Should we exit 1 here?
+ fi
+}
+clean_packages() {
+ einfo 'Cleaning list of packages to rebuild'
+ if [[ -r "$PKGS_FILE" && -s "$PKGS_FILE" ]]; then
+ einfo "Found existing $PKGS_FILE"
+ else
+ sort -u "$RAW_FILE" > "$PKGS_FILE"
+ einfo "Generated new $PKGS_FILE"
+ fi
+}
+assign_packages_to_ebuilds() {
+ local EXACT_PKG
+ local PKG
+ local SLOT
+ einfo 'Assigning packages to ebuilds'
+ if [[ -r "$EBUILDS_FILE" && -s "$EBUILDS_FILE" ]]; then
+ einfo "Found existing $EBUILDS_FILE"
+ elif [[ -r "$PKGS_FILE" && -s "$PKGS_FILE" ]]; then
+ clean_trap "$EBUILDS_FILE"
+ while read EXACT_PKG; do
+ # Get the slot
+ PKG="${EXACT_PKG%%-r[[:digit:]]*}"
+ PKG="${PKG%-*}"
+ SLOT=$(</var/db/pkg/$EXACT_PKG/SLOT)
+ echo "$PKG:$SLOT"
+ done < "$PKGS_FILE" > "$EBUILDS_FILE"
+ einfo "Generated new $EBUILDS_FILE"
+ else
+ einfo 'Nothing to rebuild.'
+ die 1 '(The program should have already quit, so this is a minor bug.)'
+ fi
+}
+get_exact_ebuilds() {
+ einfo 'Assigning files to ebuilds'
+ if [[ -r $EBUILDS_FILE && -s $EBUILDS_FILE ]]; then
+ einfo "Found existing $EBUILDS_FILE"
+ elif [[ -r $BROKEN_FILE && -s $BROKEN_FILE ]]; then
+ rebuildList=" $(<"$BROKEN_FILE") "
+ rebuildList=(${rebuildList//[[:space:]]obj[[:space:]]/ })
+ get_file_owner "${rebuildList[@]}" | sed 's/^/=/' > "$EBUILDS_FILE"
+ einfo "Generated new $EBUILDS_FILE"
+ else
+ einfo 'Nothing to rebuild.'
+ die 1 '(The program should have already quit, so this is a minor bug.)'
+ fi
+}
+list_skipped_packages() {
+ ewarn
+ ewarn 'Portage could not find any version of the following packages it could build:'
+ ewarn "${SKIP_LIST[@]}"
+ ewarn
+ ewarn '(Perhaps they are masked, blocked, or removed from portage.)'
+ ewarn 'Try to emerge them manually.'
+ ewarn
+}
+get_build_order() {
+ local -r OLD_EMERGE_DEFAULT_OPTS="$EMERGE_DEFAULT_OPTS"
+ local RAW_REBUILD_LIST
+ local REBUILD_GREP
+ local i
+ if [[ ! $ORDER_PKGS ]]; then
+ einfo 'Skipping package ordering'
+ return
+ fi
+ einfo 'Evaluating package order'
+ if [[ -r "$ORDER_FILE" && -s "$ORDER_FILE" ]]; then
+ einfo "Found existing $ORDER_FILE"
+ else
+ clean_trap "$ORDER_FILE"
+ RAW_REBUILD_LIST=$(<"$EBUILDS_FILE")
+ if [[ $RAW_REBUILD_LIST ]]; then
+ export EMERGE_DEFAULT_OPTS="--nospinner --pretend --oneshot --quiet"
+ RAW_REBUILD_LIST=($RAW_REBUILD_LIST) # convert into array
+ # If PACKAGE_NAMES is defined we're using slots, not versions
+ if [[ $PACKAGE_NAMES ]]; then
+ # Eliminate atoms that can't be built
+ for i in "${!RAW_REBUILD_LIST[@]}"; do
+ if [[ "${RAW_REBUILD_LIST[i]}" = *[A-Za-z]* ]]; then
+ portageq best_visible "$PORTAGE_ROOT" "${RAW_REBUILD_LIST[i]}" >/dev/null && continue
+ SKIP_LIST+=("${RAW_REBUILD_LIST[i]}")
+ fi
+ unset RAW_REBUILD_LIST[i]
+ done
+ # If RAW_REBUILD_LIST is empty, then we have nothing to build.
+ if (( ${#RAW_REBUILD_LIST[@]} == 0 )); then
+ if (( ${#SKIP_LIST[@]} == 0 )); then
+ ewarn "The list of packages to skip is empty, but there are no"
+ ewarn "packages listed to rebuild either. (This is a bug.)"
+ else
+ list_skipped_packages
+ fi
+ die 1 'Warning: Portage cannot rebuild any of the necessary packages.'
+ fi
+ fi
+ RAW_REBUILD_LIST="${RAW_REBUILD_LIST[@]}"
+ REBUILD_GREP=$(emerge --nodeps $RAW_REBUILD_LIST | sed 's/\[[^]]*\]//g')
+ if (( ${PIPESTATUS[0]} == 0 )); then
+ emerge --deep $RAW_REBUILD_LIST |
+ sed 's/\[[^]]*\]//g' |
+ grep -F "$REBUILD_GREP" > "$ORDER_FILE"
+ fi
+
+ # Here we use the PIPESTATUS from the second emerge, the --deep one.
+ if (( ${PIPESTATUS[0]} != 0 )); then
+ eerror
+ eerror 'Warning: Failed to resolve package order.'
+ eerror 'Will merge in arbitrary order'
+ eerror
+ cat <<- EOF
+ Possible reasons:
+ - An ebuild is no longer in the portage tree.
+ - An ebuild is masked, use /etc/portage/packages.keyword
+ and/or /etc/portage/package.unmask to unmask it
+ EOF
+ countdown 5
+ rm -f "$ORDER_FILE"
+ fi
+ export EMERGE_DEFAULT_OPTS="$OLD_EMERGE_DEFAULT_OPTS"
+ else
+ einfo 'Nothing to rebuild.'
+ die 1 '(The program should have already quit, so this is a minor bug.)'
+ fi
+ fi
+ [[ -r "$ORDER_FILE" && -s "$ORDER_FILE" ]] && einfo "Generated new $ORDER_FILE"
+}
+
+show_unowned_files() {
+ if grep -qF '(none)' "$OWNERS_FILE"; then
+ ewarn "Found some broken files that weren't associated with known packages"
+ ewarn "The broken files are:"
+ while read filename junk; do
+ [[ $junk = *none* ]] && ewarn " $filename"
+ done < "$OWNERS_FILE" | awk '!s[$0]++' # (omit dupes)
+ fi
+}
+##
+# Setup portage and the search paths
+setup_portage() {
+ local PORTAGE_NICENESS=$(portageq envvar PORTAGE_NICENESS)
+ PORTAGE_ROOT=$(portageq envvar ROOT)
+
+ # Obey PORTAGE_NICENESS
+ if [[ $PORTAGE_NICENESS ]]; then
+ renice $PORTAGE_NICENESS $$ > /dev/null
+ # Since we have already set our nice value for our processes,
+ # reset PORTAGE_NICENESS to zero to avoid having emerge renice again.
+ export PORTAGE_NICENESS="0"
+ fi
+
+ PORTAGE_ROOT="${PORTAGE_ROOT:-/}"
+}
+
+##
+# Setup the paths to search (and filter the ones to avoid)
+setup_search_paths_and_masks() {
+ local configfile sdir mdir skip_me filter_SEARCH_DIRS
+
+ einfo "Configuring search environment for $APP_NAME"
+
+ # Update the incremental variables using /etc/profile.env, /etc/ld.so.conf,
+ # portage, and the environment
+
+ # Read the incremental variables from environment and portage
+ # Until such time as portage supports these variables as incrementals
+ # The value will be what is in /etc/make.conf
+ SEARCH_DIRS+=" "$(unset SEARCH_DIRS; portageq envvar SEARCH_DIRS)
+ SEARCH_DIRS_MASK+=" "$(unset SEARCH_DIRS_MASK; portageq envvar SEARCH_DIRS_MASK)
+ LD_LIBRARY_MASK+=" "$(unset LD_LIBRARY_MASK; portageq envvar LD_LIBRARY_MASK)
+
+ # Add the defaults
+ if [[ -d /etc/revdep-rebuild ]]; then
+ for configfile in /etc/revdep-rebuild/*; do
+ SEARCH_DIRS+=" "$(. $configfile; echo $SEARCH_DIRS)
+ SEARCH_DIRS_MASK+=" "$(. $configfile; echo $SEARCH_DIRS_MASK)
+ LD_LIBRARY_MASK+=" "$(. $configfile; echo $LD_LIBRARY_MASK)
+ done
+ else
+ SEARCH_DIRS+=" /bin /sbin /usr/bin /usr/sbin /lib* /usr/lib*"
+ SEARCH_DIRS_MASK+=" /opt/OpenOffice /usr/lib/openoffice"
+ LD_LIBRARY_MASK+=" libodbcinst.so libodbc.so libjava.so libjvm.so"
+ fi
+
+ # Get the ROOTPATH and PATH from /etc/profile.env
+ if [[ -r "/etc/profile.env" && -s "/etc/profile.env" ]]; then
+ SEARCH_DIRS+=" "$(. /etc/profile.env; /usr/bin/tr ':' ' ' <<< "$ROOTPATH $PATH")
+ fi
+
+ # Get the directories from /etc/ld.so.conf
+ if [[ -r /etc/ld.so.conf && -s /etc/ld.so.conf ]]; then
+ SEARCH_DIRS+=" "$(sed '/^#/d;s/#.*$//' /etc/ld.so.conf)
+ fi
+
+ # Set the final variables
+ SEARCH_DIRS=$(clean_var <<< "$SEARCH_DIRS")
+ SEARCH_DIRS_MASK=$(clean_var <<< "$SEARCH_DIRS_MASK")
+ LD_LIBRARY_MASK=$(clean_var <<< "$LD_LIBRARY_MASK")
+ # Filter masked paths from SEARCH_DIRS
+ for sdir in ${SEARCH_DIRS} ; do
+ skip_me=
+ for mdir in ${SEARCH_DIRS_MASK}; do
+ [[ ${sdir} == ${mdir}/* ]] && skip_me=1 && break
+ done
+ [[ -n ${skip_me} ]] || filter_SEARCH_DIRS+=" ${sdir}"
+ done
+ SEARCH_DIRS=$(clean_var <<< "${filter_SEARCH_DIRS}")
+ [[ $SEARCH_DIRS ]] || die 1 "No search defined -- this is a bug."
+}
+##
+# Rebuild packages owning broken binaries
+rebuild() {
+ if [[ -r $LIST.5_order && -s $LIST.5_order ]]; then
+ REBUILD_LIST=( $(<"$LIST.5_order") )
+ REBUILD_LIST="${REBUILD_LIST[@]/#/=}"
+ else
+ REBUILD_LIST=$(sort -u "$EBUILDS_FILE")
+ fi
+
+ trap - SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM
+
+ einfo 'All prepared. Starting rebuild'
+ echo "emerge --oneshot ${EMERGE_OPTIONS[@]} $REBUILD_LIST"
+
+ is_real_merge && countdown 10
+
+ # Link file descriptor #6 with stdin so --ask will work
+ exec 6<&0
+
+ # Run in background to correctly handle Ctrl-C
+ {
+ EMERGE_DEFAULT_OPTS="--oneshot ${EMERGE_OPTIONS[@]}" emerge $REBUILD_LIST <&6
+ echo $? > "$STATUS_FILE"
+ } &
+ wait
+
+ # Now restore stdin from fd #6, where it had been saved, and close fd #6 ( 6<&- ) to free it for other processes to use.
+ exec 0<&6 6<&-
+}
+##
+# Finish up
+cleanup() {
+ if (( $(<"$STATUS_FILE") != 0 )); then
+ ewarn
+ ewarn "$APP_NAME failed to emerge all packages."
+ ewarn 'you have the following choices:'
+ einfo "- If emerge failed during the build, fix the problems and re-run $APP_NAME."
+ einfo '- Use /etc/portage/package.keywords to unmask a newer version of the package.'
+ einfo " (and remove $ORDER_FILE to be evaluated again)"
+ einfo '- Modify the above emerge command and run it manually.'
+ einfo '- Compile or unmerge unsatisfied packages manually,'
+ einfo ' remove temporary files, and try again.'
+ einfo ' (you can edit package/ebuild list first)'
+ einfo
+ einfo 'To remove temporary files, please run:'
+ einfo "rm ${WORKING_DIR}/*.rr"
+ show_unowned_files
+ exit $EMERGE_STATUS
+ elif is_real_merge; then
+ trap_cmd() {
+ eerror "terminated. Please remove the temporary files manually:"
+ eerror "rm ${WORKING_DIR}/*.rr"
+ exit 1
+ }
+ [[ "${SKIP_LIST[@]}" != "" ]] && list_skipped_packages
+ trap trap_cmd SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM
+ einfo 'Build finished correctly. Removing temporary files...'
+ einfo
+ einfo 'You can re-run revdep-rebuild to verify that all libraries and binaries'
+ einfo 'are fixed. If some inconsistency remains, it can be orphaned file, deep'
+ einfo 'dependency, binary package or specially evaluated library.'
+ if [[ -r "$OWNERS_FILE" && -s "$OWNERS_FILE" ]]; then
+ show_unowned_files
+ fi
+ [[ $KEEP_TEMP ]] || rm "${FILES[@]}"
+ else
+ einfo 'Now you can remove -p (or --pretend) from arguments and re-run revdep-rebuild.'
+ fi
+}
+
+main "$@"
diff --git a/src/revdep-rebuild/revdep-rebuild-old b/src/revdep-rebuild/revdep-rebuild-old
new file mode 100755
index 0000000..52d6d19
--- /dev/null
+++ b/src/revdep-rebuild/revdep-rebuild-old
@@ -0,0 +1,720 @@
+#!/bin/bash
+# Copyright 1999-2007 Gentoo Foundation
+# $Header$
+
+# revdep-rebuild: Reverse dependency rebuilder.
+# Original Author: Stanislav Brabec
+# Current Maintainer: Paul Varner <fuzzyray@gentoo.org>
+
+# Known problems:
+#
+# In exact ebuild mode revdep-rebuild can fail to properly order packages,
+# which are not up to date.
+# http://bugs.gentoo.org/show_bug.cgi?id=23018
+#
+# Rebuilding using --package-names mode should be default, but emerge has no
+# feature to update to latest version of defined SLOT.
+# http://bugs.gentoo.org/show_bug.cgi?id=4698
+
+# Customizable variables:
+#
+# LD_LIBRARY_MASK - Mask of specially evaluated libraries
+# SEARCH_DIRS - List of directories to search for executables and libraries
+# SEARCH_DIRS_MASK - List of directories to not search
+#
+# These variables can be prepended to either by setting the variable in
+# your environment prior to execution, or by placing an entry in
+# /etc/make.conf.
+#
+# An entry of "-*" means to clear the variable from that point forward.
+# Example: env SEARCH_DIRS="/usr/bin -*" revdep-rebuild will set SEARCH_DIRS
+# to contain only /usr/bin
+
+if [ "$1" = "-h" -o "$1" = "--help" ]
+then
+ echo "Usage: $0 [OPTIONS] [--] [EMERGE_OPTIONS]"
+ echo
+ echo "Broken reverse dependency rebuilder."
+ echo
+ echo " -X, --package-names Emerge based on package names, not exact versions"
+ echo " --library NAME Emerge existing packages that use the library with NAME"
+ echo " --library=NAME NAME can be a full path to the library or a basic"
+ echo " regular expression (man grep)"
+ echo " -np, --no-ld-path Do not set LD_LIBRARY_PATH"
+ echo " -nc, --nocolor Turn off colored output"
+ echo " -i, --ignore Ignore temporary files from previous runs"
+ echo " -q, --quiet Be less verbose (also passed to emerge command)"
+ echo " -vv, --extra-verbose Be extra verbose"
+ echo
+ echo "Calls emerge, all other options are used for it (e. g. -p, --pretend)."
+ echo
+ echo "Report bugs to <http://bugs.gentoo.org>"
+ exit 0
+fi
+
+echo "Configuring search environment for revdep-rebuild"
+
+# Obey PORTAGE_NICENESS
+PORTAGE_NICENESS=$(portageq envvar PORTAGE_NICENESS)
+if [ ! -z "$PORTAGE_NICENESS" ]
+then
+ renice $PORTAGE_NICENESS $$ > /dev/null
+ # Since we have already set our nice value for our processes,
+ # reset PORTAGE_NICENESS to zero to avoid having emerge renice again.
+ export PORTAGE_NICENESS="0"
+fi
+
+PORTAGE_ROOT=$(portageq envvar ROOT)
+[ -z "$PORTAGE_ROOT" ] && PORTAGE_ROOT="/"
+
+# Update the incremental variables using /etc/profile.env, /etc/ld.so.conf,
+# portage, and the environment
+
+# Read the incremental variables from environment and portage
+# Until such time as portage supports these variables as incrementals
+# The value will be what is in /etc/make.conf
+PRELIMINARY_SEARCH_DIRS="$SEARCH_DIRS $(unset SEARCH_DIRS; portageq envvar SEARCH_DIRS)"
+PRELIMINARY_SEARCH_DIRS_MASK="$SEARCH_DIRS_MASK $(unset SEARCH_DIRS_MASK; portageq envvar SEARCH_DIRS_MASK)"
+PRELIMINARY_LD_LIBRARY_MASK="$LD_LIBRARY_MASK $(unset LD_LIBRARY_MASK; portageq envvar LD_LIBRARY_MASK)"
+
+# Add the defaults
+if [ -d /etc/revdep-rebuild ]
+then
+ for file in $(ls /etc/revdep-rebuild)
+ do
+ PRELIMINARY_SEARCH_DIRS="$PRELIMINARY_SEARCH_DIRS $(. /etc/revdep-rebuild/${file}; echo $SEARCH_DIRS)"
+ PRELIMINARY_SEARCH_DIRS_MASK="$PRELIMINARY_SEARCH_DIRS_MASK $(. /etc/revdep-rebuild/${file}; echo $SEARCH_DIRS_MASK)"
+ PRELIMINARY_LD_LIBRARY_MASK="$PRELIMINARY_LD_LIBRARY_MASK $(. /etc/revdep-rebuild/${file}; echo $LD_LIBRARY_MASK)"
+ done
+else
+ PRELIMINARY_SEARCH_DIRS="$PRELIMINARY_SEARCH_DIRS /bin /sbin /usr/bin /usr/sbin /lib* /usr/lib*"
+ PRELIMINARY_SEARCH_DIRS_MASK="$PRELIMINARY_SEARCH_DIRS_MASK /opt/OpenOffice /usr/lib/openoffice"
+ PRELIMINARY_LD_LIBRARY_MASK="$PRELIMINARY_LD_LIBRARY_MASK libodbcinst.so libodbc.so libjava.so libjvm.so"
+fi
+
+# Get the ROOTPATH and PATH from /etc/profile.env
+if [ -e "/etc/profile.env" ]
+then
+ PRELIMINARY_SEARCH_DIRS="$PRELIMINARY_SEARCH_DIRS $((. /etc/profile.env; echo ${ROOTPATH}:${PATH}) | tr ':' ' ')"
+fi
+
+# Get the directories from /etc/ld.so.conf
+if [ -e /etc/ld.so.conf ]
+then
+ PRELIMINARY_SEARCH_DIRS="$PRELIMINARY_SEARCH_DIRS $(grep -v "^#" /etc/ld.so.conf | tr '\n' ' ')"
+fi
+
+# Set the final variables
+# Note: Using $(echo $variable) removes extraneous spaces from variable assignment
+unset SEARCH_DIRS
+for i in $(echo $PRELIMINARY_SEARCH_DIRS)
+do
+ [ "$i" = "-*" ] && break
+ # Append a / at the end so that links and directories are treated the same by find
+ # Remove any existing trailing slashes to prevent double-slashes
+ SEARCH_DIRS="$(echo $SEARCH_DIRS ${i/%\//}/)"
+done
+# Remove any double-slashes from the path
+SEARCH_DIRS="$(echo $SEARCH_DIRS | sed 's:/\+:/:g')"
+
+unset SEARCH_DIRS_MASK
+for i in $(echo $PRELIMINARY_SEARCH_DIRS_MASK)
+do
+ [ "$i" = "-*" ] && break
+ SEARCH_DIRS_MASK="$(echo $SEARCH_DIRS_MASK $i)"
+done
+
+unset LD_LIBRARY_MASK
+for i in $(echo $PRELIMINARY_LD_LIBRARY_MASK)
+do
+ [ "$i" = "-*" ] && break
+ LD_LIBRARY_MASK="$(echo $LD_LIBRARY_MASK $i)"
+done
+
+# Use the color preference from portage
+NOCOLOR=$(portageq envvar NOCOLOR)
+
+# Base of temporary files names.
+touch ${HOME}/.revdep-rebuild_0.test 2>/dev/null
+if [ $? -eq 0 ]
+then
+ LIST="${HOME}/.revdep-rebuild"
+ rm ~/.revdep-rebuild_0.test
+else
+ # Try to use /var/tmp since $HOME is not available
+ touch /var/tmp/.revdep-rebuild_0.test 2>/dev/null
+ if [ $? -eq 0 ]
+ then
+ LIST="/var/tmp/.revdep-rebuild"
+ rm /var/tmp/.revdep-rebuild_0.test
+ else
+ echo
+ echo "!!! Unable to write temporary files to either $HOME or /var/tmp !!!"
+ echo
+ exit 1
+ fi
+fi
+
+shopt -s nullglob
+shopt -s expand_aliases
+unalias -a
+
+# Color Definitions
+NO="\x1b[0m"
+BR="\x1b[0;01m"
+CY="\x1b[36;01m"
+GR="\x1b[32;01m"
+RD="\x1b[31;01m"
+YL="\x1b[33;01m"
+BL="\x1b[34;01m"
+
+# Check if portage-utils are installed
+portageq has_version $PORTAGE_ROOT portage-utils
+if [ "$?" -eq 0 ]
+then
+ PORTAGE_UTILS=true
+else
+ PORTAGE_UTILS=false
+fi
+
+alias echo_v=echo
+
+PACKAGE_NAMES=false
+SONAME="not found"
+SONAME_GREP=grep
+SEARCH_BROKEN=true
+EXTRA_VERBOSE=false
+KEEP_TEMP=false
+FULL_LD_PATH=true
+
+EMERGE_OPTIONS=""
+PRELIMINARY_CALLED_OPTIONS=""
+while [ ! -z "$1" ] ; do
+ case "$1" in
+ -X | --package-names )
+ PACKAGE_NAMES=true
+ PRELIMINARY_CALLED_OPTIONS="${PRELIMINARY_CALLED_OPTIONS} --package_names"
+ shift
+ ;;
+ -q | --quiet )
+ alias echo_v=:
+ EMERGE_OPTIONS="${EMERGE_OPTIONS} $1"
+ shift
+ ;;
+ --library=* | --soname=* | --soname-regexp=* )
+ SONAME="${1#*=}"
+ SEARCH_BROKEN=false
+ PRELIMINARY_CALLED_OPTIONS="${PRELIMINARY_CALLED_OPTIONS} --library=${SONAME}"
+ shift
+ ;;
+ --library | --soname | --soname-regexp )
+ SONAME="$2"
+ SEARCH_BROKEN=false
+ PRELIMINARY_CALLED_OPTIONS="${PRELIMINARY_CALLED_OPTIONS} --library=${SONAME}"
+ shift 2
+ ;;
+ -nc | --no-color | --nocolor )
+ NOCOLOR=true
+ shift
+ ;;
+ -np | --no-ld-path )
+ FULL_LD_PATH=false
+ PRELIMINARY_CALLED_OPTIONS="${PRELIMINARY_CALLED_OPTIONS} --no-ld-path"
+ shift
+ ;;
+ -i | --ignore )
+ rm -f ${LIST}*
+ shift
+ ;;
+ --keep-temp )
+ KEEPTEMP=true
+ shift
+ ;;
+ -vv | --extra-verbose )
+ EXTRA_VERBOSE=true
+ shift
+ ;;
+ -- )
+ shift
+ ;;
+ * )
+ EMERGE_OPTIONS="${EMERGE_OPTIONS} $1"
+ shift
+ ;;
+ esac
+done
+
+EMERGE_OPTIONS=$(echo $EMERGE_OPTIONS | sed 's/^ //')
+
+if [ -z "$PRELIMINARY_CALLED_OPTIONS" ]
+then
+ CALLED_OPTIONS=""
+else
+ for i in $(echo $PRELIMINARY_CALLED_OPTIONS | tr ' ' '\n'| sort)
+ do
+ CALLED_OPTIONS="$(echo $CALLED_OPTIONS $i)"
+ done
+fi
+
+if [ "$NOCOLOR" = "yes" -o "$NOCOLOR" = "true" ]
+then
+ NOCOLOR=true
+else
+ NOCOLOR=false
+fi
+
+# Make the NOCOLOR variable visible to emerge
+export NOCOLOR
+
+if $NOCOLOR
+then
+ NO=""
+ BR=""
+ CY=""
+ GR=""
+ RD=""
+ YL=""
+ BL=""
+fi
+
+function set_trap () {
+ trap "rm_temp $1" SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM
+}
+
+function rm_temp () {
+ echo " terminated."
+ echo "Removing incomplete $1."
+ rm $1
+ echo
+ exit 1
+}
+
+if $SEARCH_BROKEN ; then
+ SONAME_SEARCH="$SONAME"
+ LLIST=$LIST
+ HEAD_TEXT="broken by a package update"
+ OK_TEXT="Dynamic linking on your system is consistent"
+ WORKING_TEXT=" consistency"
+else
+ # first case is needed to test against /path/to/foo.so
+ if [ ${SONAME:0:1} == '/' ] ; then
+ # Set to "<space>$SONAME<space>"
+ SONAME_SEARCH=" $SONAME "
+ else
+ # Set to "<tab>$SONAME<space>"
+ SONAME_SEARCH=" $SONAME "
+ fi
+ LLIST=${LIST}_$(echo "$SONAME_SEARCH$SONAME" | md5sum | head -c 8)
+ HEAD_TEXT="using $SONAME"
+ OK_TEXT="There are no dynamic links to $SONAME"
+ WORKING_TEXT=""
+fi
+
+# If any of our temporary files are older than 1 day, remove them all
+[ "$(find "${LIST%/*}/." ! -name . -prune -name "${LIST##*/}*" -type f -mmin +1440)" != "" ] && rm -f ${LIST}*
+
+# Don't use our previous files if environment doesn't match
+if [ -f $LIST.0_env ]
+then
+ PREVIOUS_SEARCH_DIRS=$(. ${LIST}.0_env; echo "$SEARCH_DIRS")
+ PREVIOUS_SEARCH_DIRS_MASK=$(. ${LIST}.0_env; echo "$SEARCH_DIRS_MASK")
+ PREVIOUS_LD_LIBRARY_MASK=$(. ${LIST}.0_env; echo "$LD_LIBRARY_MASK")
+ PREVIOUS_PORTAGE_ROOT=$(. ${LIST}.0_env; echo "$PORTAGE_ROOT")
+ PREVIOUS_OPTIONS=$(. ${LIST}.0_env; echo "$CALLED_OPTIONS")
+ if [ "$PREVIOUS_SEARCH_DIRS" != "$SEARCH_DIRS" ] || \
+ [ "$PREVIOUS_SEARCH_DIRS_MASK" != "$SEARCH_DIRS_MASK" ] || \
+ [ "$PREVIOUS_LD_LIBRARY_MASK" != "$LD_LIBRARY_MASK" ] || \
+ [ "$PREVIOUS_PORTAGE_ROOT" != "$PORTAGE_ROOT" ] || \
+ [ "$PREVIOUS_OPTIONS" != "$CALLED_OPTIONS" ]
+ then
+ echo
+ echo "Environment mismatch from previous run, deleting temporary files..."
+ rm -f ${LIST}*
+ fi
+fi
+
+# Clean up no longer needed environment variables
+unset PREVIOUS_SEARCH_DIRS PREVIOUS_SEARCH_DIRS_MASK PREVIOUS_LD_LIBRARY_MASK PREVIOUS_PORTAGE_ROOT PREVIOUS_OPTIONS
+unset PRELIMINARY_SEARCH_DIRS PRELIMINARY_SEARCH_DIRS_MASK PRELIMINARY_LD_LIBRARY_MASK PRELIMINARY_CALLED_OPTIONS
+
+# Log our environment
+echo "SEARCH_DIRS=\"$SEARCH_DIRS\"" > $LIST.0_env
+echo "SEARCH_DIRS_MASK=\"$SEARCH_DIRS_MASK\"" >> $LIST.0_env
+echo "LD_LIBRARY_MASK=\"$LD_LIBRARY_MASK\"" >> $LIST.0_env
+echo "PORTAGE_ROOT=\"$PORTAGE_ROOT\"" >> $LIST.0_env
+echo "CALLED_OPTIONS=\"$CALLED_OPTIONS\"" >> $LIST.0_env
+echo "EMERGE_OPTIONS=\"$EMERGE_OPTIONS\"" >> $LIST.0_env
+
+if $EXTRA_VERBOSE
+then
+ echo
+ echo "revdep-rebuild environment:"
+ cat $LIST.0_env
+fi
+
+echo
+echo "Checking reverse dependencies..."
+echo
+echo "Packages containing binaries and libraries $HEAD_TEXT"
+echo "will be emerged."
+
+echo
+echo -n -e "${GR}Collecting system binaries and libraries...${NO}"
+
+if [ -f $LIST.1_files ]
+then
+ echo " using existing $LIST.1_files."
+else
+ # Be safe and remove any extraneous temporary files
+ rm -f ${LIST}.[1-9]_*
+
+ set_trap "$LIST.1_*"
+
+ # Hack for the different versions of find.
+ # Be extra paranoid and pipe results through sed to remove multiple slashes
+ find_results=$(find /usr/bin/revdep-rebuild -type f -perm /u+x 2>/dev/null)
+ if [ -z $find_results ]
+ then
+ find_results=$(find /usr/bin/revdep-rebuild -type f -perm +u+x 2>/dev/null)
+ if [ -z $find_results ]
+ then
+ echo -e "\n"
+ echo -e "${RD}Unable to determine how to use find to locate executable files${NO}"
+ echo -e "${RD}Open a bug at http://bugs.gentoo.org${NO}"
+ echo
+ exit 1
+ else
+ # using -perm +u+x for find command
+ find $SEARCH_DIRS -type f \( -perm +u+x -o -name '*.so' -o -name '*.so.*' -o -name '*.la' \) 2>/dev/null | sort | uniq | sed 's:/\+:/:g' >$LIST.0_files
+ fi
+ else
+ # using -perm /u+x for find command
+ find $SEARCH_DIRS -type f \( -perm /u+x -o -name '*.so' -o -name '*.so.*' -o -name '*.la' \) 2>/dev/null | sort | uniq | sed 's:/\+:/:g' >$LIST.0_files
+ fi
+
+ # Remove files that match SEARCH_DIR_MASK
+ for dir in $SEARCH_DIRS_MASK
+ do
+ grep -v "^$dir" $LIST.0_files > $LIST.1_files
+ mv $LIST.1_files $LIST.0_files
+ done
+
+ mv $LIST.0_files $LIST.1_files
+ echo -e " done.\n ($LIST.1_files)"
+fi
+
+if $SEARCH_BROKEN && $FULL_LD_PATH ; then
+ echo
+ echo -n -e "${GR}Collecting complete LD_LIBRARY_PATH...${NO}"
+ if [ -f $LIST.2_ldpath ] ; then
+ echo " using existing $LIST.2_ldpath."
+ else
+ set_trap "$LIST.2_ldpath"
+ # Ensure that the "trusted" lib directories are at the start of the path
+ (
+ echo /lib* /usr/lib* | sed 's/ /:/g'
+ sed '/^#/d;s/#.*$//' </etc/ld.so.conf
+ sed 's:/[^/]*$::' <$LIST.1_files | sort -ru
+ ) | tr '\n' : | tr -d '\r' | sed 's/:$//' >$LIST.2_ldpath
+ echo -e " done.\n ($LIST.2_ldpath)"
+ fi
+ COMPLETE_LD_LIBRARY_PATH="$(cat $LIST.2_ldpath)"
+fi
+
+echo
+echo -n -e "${GR}Checking dynamic linking$WORKING_TEXT...${NO}"
+if [ -f $LLIST.3_rebuild ] ; then
+ echo " using existing $LLIST.3_rebuild."
+else
+ echo_v
+ set_trap "$LLIST.3_rebuild"
+ LD_MASK="\\( $(echo "$LD_LIBRARY_MASK" | sed 's/\./\\./g;s/ / \\| /g') \\)"
+ echo -n >$LLIST.3_rebuild
+ echo -n >$LLIST.3_ldd_errors
+ cat $LIST.1_files | egrep -v '*\.la$' | while read FILE ; do
+ # Note: double checking seems to be faster than single
+ # with complete path (special add ons are rare).
+ if ldd "$FILE" 2>>$LLIST.3_ldd_errors | grep -v "$LD_MASK" | $SONAME_GREP -q "$SONAME_SEARCH" ; then
+ if $SEARCH_BROKEN && $FULL_LD_PATH ; then
+ if LD_LIBRARY_PATH="$COMPLETE_LD_LIBRARY_PATH" ldd "$FILE" 2>/dev/null | grep -v "$LD_MASK" | $SONAME_GREP -q "$SONAME_SEARCH" ; then
+ # FIX: I hate duplicating code
+ # Only build missing direct dependencies
+ ALL_MISSING_LIBS=$(ldd "$FILE" 2>/dev/null | sort -u | sed -n 's/ \(.*\) => not found/\1/p' | tr '\n' ' ' | sed 's/ $//' )
+ REQUIRED_LIBS=$(objdump -x $FILE | grep NEEDED | awk '{print $2}' | tr '\n' ' ' | sed 's/ $//')
+ MISSING_LIBS=""
+ for lib in $ALL_MISSING_LIBS
+ do
+ if echo $REQUIRED_LIBS | grep -q $lib
+ then
+ MISSING_LIBS="$MISSING_LIBS $lib"
+ fi
+ done
+ if [ "$MISSING_LIBS" != "" ]
+ then
+ echo "obj $FILE" >>$LLIST.3_rebuild
+ echo_v " broken $FILE (requires ${MISSING_LIBS})"
+ fi
+ fi
+ else
+ # FIX: I hate duplicating code
+ # Only rebuild for direct dependencies
+ ALL_MISSING_LIBS=$(ldd "$FILE" 2>/dev/null | sort -u | $SONAME_GREP "$SONAME_SEARCH" | awk '{print $1}' | tr '\n' ' ' | sed 's/ $//' )
+ REQUIRED_LIBS=$(objdump -x $FILE | grep NEEDED | awk '{print $2}' | tr '\n' ' ' | sed 's/ $//')
+ MISSING_LIBS=""
+ for lib in $ALL_MISSING_LIBS
+ do
+ if echo $REQUIRED_LIBS | grep -q $lib
+ then
+ MISSING_LIBS="$MISSING_LIBS $lib"
+ fi
+ done
+ if [ "$MISSING_LIBS" != "" ]
+ then
+ echo "obj $FILE" >>$LLIST.3_rebuild
+ if $SEARCH_BROKEN ; then
+ echo_v " broken $FILE (requires ${MISSING_LIBS})"
+ else
+ echo_v " found $FILE"
+ fi
+ fi
+ fi
+ fi
+ done
+ if $SEARCH_BROKEN ; then
+ # Look for missing version
+ for FILE in $(grep "no version information available" $LLIST.3_ldd_errors | awk '{print $NF}' | sed 's/[()]//g' | sort -u) ; do
+ echo "obj $FILE" >>$LLIST.3_rebuild
+ echo_v " broken $FILE (no version information available)"
+ done
+ # Look for broken .la files
+ cat $LIST.1_files | egrep '*\.la$' | while read FILE ; do
+ for depend in $(grep '^dependency_libs' $FILE | awk -F'=' '{print $2}' | sed "s/'//g") ; do
+ [ ${depend:0:1} != '/' ] && continue
+ if [ ! -e $depend ] ; then
+ echo "obj $FILE" >>$LLIST.3_rebuild
+ echo_v " broken $FILE (requires ${depend})"
+ fi
+ done
+ done
+ fi
+ echo -e " done.\n ($LLIST.3_rebuild)"
+fi
+
+if $PACKAGE_NAMES ; then
+ EXACT_EBUILDS=false
+
+ echo
+ echo -n -e "${GR}Assigning files to packages...${NO}"
+ if [ -f $LLIST.4_packages_raw ] ; then
+ echo " using existing $LLIST.4_packages_raw."
+ else
+ set_trap "$LLIST.4_packages*"
+ echo -n >$LLIST.4_packages_raw
+ echo -n >$LLIST.4_package_owners
+ cat $LLIST.3_rebuild | while read obj FILE ; do
+ if $PORTAGE_UTILS ; then
+ EXACT_PKG="$(qfile -qvC ${FILE} )"
+ else
+ EXACT_PKG=$(find /var/db/pkg -name CONTENTS | xargs fgrep -l "obj $FILE " | sed -e 's:/var/db/pkg/\(.*\)/CONTENTS:\1:g')
+ fi
+ # Ugly sed hack to strip version information
+ PKG="$(echo $EXACT_PKG | sed 's/-r[0-9].*$//;s/\(^.*\/*\)-.*$/\1/')"
+ if [ -z "$PKG" ] ; then
+ echo -n -e "\n ${RD}*** $FILE not owned by any package is broken! ***${NO}"
+ echo "$FILE -> (none)" >> $LLIST.4_package_owners
+ echo_v -n -e "\n $FILE -> (none)"
+ else
+ echo "$EXACT_PKG" >> $LLIST.4_packages_raw
+ echo "$FILE -> $EXACT_PKG" >> $LLIST.4_package_owners
+ echo_v -n -e "\n $FILE -> $PKG"
+ fi
+ done
+ echo_v
+ echo -e " done.\n ($LLIST.4_packages_raw, $LLIST.4_package_owners)"
+ fi
+
+ echo
+ echo -n -e "${GR}Cleaning list of packages to rebuild...${NO}"
+ if [ -f $LLIST.4_packages ] ; then
+ echo " using existing $LLIST.4_packages."
+ else
+ sort -u $LLIST.4_packages_raw >$LLIST.4_packages
+ echo -e " done.\n ($LLIST.4_packages)"
+ fi
+
+ echo
+ echo -n -e "${GR}Assigning packages to ebuilds...${NO}"
+ if [ -f $LLIST.4_ebuilds ] ; then
+ echo " using existing $LLIST.4_ebuilds."
+ else
+ if [ -s "$LLIST.4_packages" ]
+ then
+ set_trap "$LLIST.4_ebuilds"
+ cat $LLIST.4_packages | while read EXACT_PKG
+ do
+ PKG="$(echo $EXACT_PKG | sed 's/-r[0-9].*$//;s/\(^.*\/*\)-.*$/\1/')"
+ SLOT=$(cat /var/db/pkg/${EXACT_PKG}/SLOT)
+ best_visible=$(portageq best_visible $PORTAGE_ROOT ${PKG}:${SLOT})
+ [ "x" != "x$best_visible" ] && echo $best_visible
+ done > $LLIST.4_ebuilds
+ echo -e " done.\n ($LLIST.4_ebuilds)"
+ else
+ echo " Nothing to rebuild"
+ echo -n > $LLIST.4_ebuilds
+ fi
+ fi
+else
+ EXACT_EBUILDS=true
+
+ echo
+ echo -n -e "${GR}Assigning files to ebuilds...${NO}"
+ if [ -f $LLIST.4_ebuilds ] ; then
+ echo " using existing $LLIST.4_ebuilds."
+ else
+ if [ -s "$LLIST.3_rebuild" ] ; then
+ set_trap "$LLIST.4_ebuilds"
+ find /var/db/pkg -name CONTENTS | xargs fgrep -l -f $LLIST.3_rebuild |
+ sed 's:/var/db/pkg/\(.*\)/CONTENTS:\1:' > $LLIST.4_ebuilds
+ echo -e " done.\n ($LLIST.4_ebuilds)"
+ else
+ echo " Nothing to rebuild"
+ echo -n > $LLIST.4_ebuilds
+ fi
+ fi
+
+fi
+
+echo
+echo -n -e "${GR}Evaluating package order...${NO}"
+if [ -f $LLIST.5_order ] ; then
+ echo " using existing $LLIST.5_order."
+else
+ set_trap "$LLIST.5_order"
+ RAW_REBUILD_LIST="$(cat $LLIST.4_ebuilds | sed s/^/=/ | tr '\n' ' ')"
+ if [ ! -z "$RAW_REBUILD_LIST" ] ; then
+ REBUILD_GREP="^\\($( (EMERGE_DEFAULT_OPTS="" emerge --nospinner --pretend --oneshot --nodeps --quiet $RAW_REBUILD_LIST ; echo $? >$LLIST.5a_status ) | sed -n 's/\./\\&/g;s/ //g;s/$/\\/;s/\[[^]]*\]//gp' | tr '\n' '|' | sed 's/|$//'))\$"
+ if [ $(cat $LLIST.5a_status) -gt 0 ] ; then
+ echo ""
+ echo -e "${RD}Warning: Failed to resolve package order."
+ echo -e "Will merge in \"random\" order!${NO}"
+ echo "Possible reasons:"
+ echo "- An ebuild is no longer in the portage tree."
+ echo "- An ebuild is masked, use /etc/portage/packages.keyword"
+ echo " and/or /etc/portage/package.unmask to unmask it"
+ for i in . . . . . ; do
+ echo -n -e '\a.'
+ sleep 1
+ done
+ ln -f $LLIST.4_ebuilds $LLIST.5_order
+ else
+ (EMERGE_DEFAULT_OPTS="" emerge --nospinner --pretend --oneshot --deep --quiet $RAW_REBUILD_LIST ; echo $? >$LLIST.5b_status ) | sed -n 's/ *$//;s/^\[.*\] //p' | awk '{print $1}' | grep "$REBUILD_GREP" >$LLIST.5_order
+ if [ $(cat $LLIST.5b_status) -gt 0 ] ; then
+ echo ""
+ echo -e "${RD}Warning: Failed to resolve package order."
+ echo -e "Will merge in \"random\" order!${NO}"
+ echo "Possible reasons:"
+ echo "- An ebuild is no longer in the portage tree."
+ echo "- An ebuild is masked, use /etc/portage/packages.keyword"
+ echo " and/or /etc/portage/package.unmask to unmask it"
+ for i in . . . . . ; do
+ echo -n -e '\a.'
+ sleep 1
+ done
+ rm -f $LLIST.5_order
+ ln -f $LLIST.4_ebuilds $LLIST.5_order
+ fi
+ fi
+ else
+ echo -n "" >$LLIST.5_order
+ fi
+ echo -e " done.\n ($LLIST.5_order)"
+fi
+
+# Clean up no longer needed environment variables
+unset COMPLETE_LD_LIBRARY_PATH SEARCH_DIRS SEARCH_DIRS_MASK LD_LIBRARY_MASK PORTAGE_ROOT CALLED_OPTIONS
+
+REBUILD_LIST="$(cat $LLIST.5_order | sed s/^/=/ | tr '\n' ' ')"
+
+trap - SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM
+
+if [ -z "$REBUILD_LIST" ] ; then
+ echo -e "\n${GR}$OK_TEXT... All done.${NO} "
+ if [ ! $KEEPTEMP ]
+ then
+ rm $LIST.[0-2]_*
+ rm $LLIST.[3-9]_*
+ fi
+ exit 0
+fi
+
+IS_REAL_MERGE=true
+echo " $EMERGE_OPTIONS " | grep -q '\( -p \| --pretend \| -f \| --fetchonly \)' && IS_REAL_MERGE=false
+
+echo
+echo -e "${GR}All prepared. Starting rebuild...${NO}"
+
+echo "emerge --oneshot $EMERGE_OPTIONS $REBUILD_LIST"
+
+if $IS_REAL_MERGE ; then
+ for i in . . . . . . . . . . ; do
+ echo -n -e '\a.'
+ sleep 1
+ done
+ echo
+fi
+
+# Link file descriptor #6 with stdin
+exec 6<&0
+
+# Run in background to correctly handle Ctrl-C
+(
+ EMERGE_DEFAULT_OPTS="" emerge --oneshot $EMERGE_OPTIONS $REBUILD_LIST <&6
+ echo $? >$LLIST.6_status
+) &
+wait
+
+# Now restore stdin from fd #6, where it had been saved, and close fd #6 ( 6<&- ) to free it for other processes to use.
+exec 0<&6 6<&-
+
+#if $EXACT_EBUILDS ; then
+# mv -i /usr/portage/profiles/package.mask.hidden /usr/portage/profiles/package.mask
+# trap - SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM
+#fi
+
+if [ "$(cat $LLIST.6_status)" -gt 0 ] ; then
+ echo
+ echo -e "${RD}revdep-rebuild failed to emerge all packages${NO}"
+ echo -e "${RD}you have the following choices:${NO}"
+ echo
+ echo "- if emerge failed during the build, fix the problems and re-run revdep-rebuild"
+ echo " or"
+ echo "- use -X or --package-names as first argument (trys to rebuild package, not exact"
+ echo " ebuild)"
+ echo " or"
+ echo "- set ACCEPT_KEYWORDS=\"~<your platform>\" and/or /etc/portage/package.unmask"
+ echo " (and remove $LLIST.5_order to be evaluated again)"
+ echo " or"
+ echo "- modify the above emerge command and run it manually"
+ echo " or"
+ echo "- compile or unmerge unsatisfied packages manually, remove temporary files and"
+ echo " try again (you can edit package/ebuild list first)"
+ echo
+ echo -e "${GR}To remove temporary files, please run:${NO}"
+ echo "rm $LIST*.?_*"
+ exit $(cat $LLIST.6_status)
+else
+ if $IS_REAL_MERGE ; then
+ trap "echo -e \" terminated. Please remove them manually:\nrm $LIST*.?_*\" ; exit 1" \
+ SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM
+ echo -n -e "${GR}Build finished correctly. Removing temporary files...${NO} "
+ echo
+ rm $LIST.[0-2]_*
+ rm $LLIST.[3-9]_*
+ echo "You can re-run revdep-rebuild to verify that all libraries and binaries"
+ echo "are fixed. If some inconsistency remains, it can be orphaned file, deep"
+ echo "dependency, binary package or specially evaluated library."
+ else
+ echo -e "${GR}Now you can remove -p (or --pretend) from arguments and re-run revdep-rebuild.${NO}"
+ fi
+fi
+exit 0
diff --git a/src/revdep-rebuild/revdep-rebuild-sh b/src/revdep-rebuild/revdep-rebuild-sh
new file mode 100755
index 0000000..c7acdc6
--- /dev/null
+++ b/src/revdep-rebuild/revdep-rebuild-sh
@@ -0,0 +1,332 @@
+#!/bin/sh
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+appname=${0##*/}
+
+# If baselayout is broken, define our own functions
+[ -r /etc/init.d/functions.sh ] && . /etc/init.d/functions.sh
+if ! type eend >/dev/null 2>&1 || ! eend 0 >/dev/null 2>&1; then
+ einfo() { echo " * $*"; }
+ eerror() { echo " * $*" >&2; return 1; }
+ eindent() { :; }
+ eoutdent() { :; }
+fi
+
+# No temporary files used, so nothing to clean up :)
+trap "export RC_EINDENT=; echo; eerror 'Caught interrupt'; exit 1" \
+ SIGINT SIGQUIT
+
+print_usage() {
+ cat << EOF
+Usage: ${appname} [OPTIONS] [--] [EMERGE_OPTIONS]
+
+Broken reverse dependency rebuilder.
+
+ -h, --help Print this usage
+ -e, --exact Emerge based on exact package version
+ -C, --nocolor Turn off colored output
+ -L, --library NAME Emerge existing packages that use the library with NAME
+ --library=NAME NAME can be a full path to the library or a basic
+ regular expression (man grep)
+
+Calls emerge, all other options are used for it (e. g. -p, --pretend).
+
+Report bugs to <http://bugs.gentoo.org>
+EOF
+}
+
+# Have we linked to this library?
+elf_linked() {
+ local f=$1
+ shift
+ while [ -n "$1" ]; do
+ ldd "${f}" 2>/dev/null | grep -q "=> $1 " && return 0
+ shift
+ done
+ return 1
+}
+
+# Work out of we really need this library or not
+elf_needed() {
+ local f=$1
+ shift
+ while [ -n "$1" ]; do
+ objdump -p "${f}" 2>/dev/null | \
+ grep -vF "${ld_mask:=$'\a'}" | \
+ grep -q "^ NEEDED ${1##*/}" && return 0
+ shift
+ done
+ return 1
+}
+
+elf_broken() {
+ local lib=
+
+ for lib in $(ldd "$1" 2>/dev/null | \
+ sed -n -e 's/[[:space:]]*\(.*\) => not found.*/\1/p'); do
+ if elf_needed "$1" "${lib}"; then
+ echo "(missing ${lib})"
+ return 0
+ fi
+ done
+ return 1
+}
+
+# Check that all direct files exist in .la files
+la_broken() {
+ local x=
+ for x in $(sed -n -e "s/^dependency_libs=\'\(.*\)'\$/\1/p" "$1"); do
+ case "${x}" in
+ /*)
+ if [ ! -e "${x}" ]; then
+ echo "(missing ${x})"
+ return 0
+ fi
+ ;;
+ esac
+ done
+
+ return 1
+}
+
+# Return a $PATH style variable based on ld.so.conf
+read_so_conf() {
+ local line=
+ while read line; do
+ case "${line}" in
+ "#"*) ;;
+ *) printf ":%s" "${line}";;
+ esac
+ done < /etc/ld.so.conf
+}
+
+# Check to see if we have already scanned a dir or not
+scanned() {
+ local dir=$1 IFS=:
+ set -- ${scanned}
+
+ while [ -n "$1" ]; do
+ [ "$1" = "$dir" ] && return 0
+ shift
+ done
+
+ scanned="${scanned}${scanned:+:}${dir}"
+ return 1
+}
+
+# Hit the portage vdb to work out our ebuilds
+# If everything is 100% then this happens in one very fast pass
+# Otherwise we have to take the slow approach to inform the user which files
+# are orphans
+get_exact_ebuilds() {
+ local regex= ebuilds= x= IFS=:
+ set -- $@
+ IFS=" "
+
+ # Hit the vdb in one go - this is fast!
+ regex=$(printf "%s|" "$@")
+ regex=${regex%*|}
+ find /var/db/pkg -name CONTENTS | \
+ xargs egrep "^obj (${regex}) " | \
+ sed -e 's,/var/db/pkg/\(.*\/.*\)/CONTENTS:.*,=\1,g' | \
+ tr '\n' ' '
+}
+
+# Get our args
+libs=
+exact=false
+order=true
+while [ -n "$1" ]; do
+ case "$1" in
+ --*=*)
+ arg1=${1%%=*}
+ arg2=${1#*=}
+ shift
+ set -- ${arg1} ${arg2} $@
+ continue
+ ;;
+ -h|--help) print_usage; exit 0;;
+ -L|--library|--soname|--soname-regexp)
+ if [ -z "$2" ]; then
+ eerror "Missing expected argument to $1"
+ exit 1
+ fi
+ libs="${libs}${libs:+ }$2"
+ shift
+ ;;
+ -e|--exact) exact=true;;
+ -X|--package-names) ;; #compat
+ --) shift; emerge_opts="$@"; break;;
+ *) eerror "$0: unknown option $1"; exit 1;;
+ esac
+ shift
+done
+
+einfo "Configuring search environment for ${appname}"
+# OK, this truely sucks. Paths can have spaces in, but our config format
+# is space separated?
+sdirs=$(unset SEARCH_DIRS; portageq envvar SEARCH_DIRS)
+sdirs_mask=$(unset SEARCH_DIRS_MASK; portageq envvar SEARCH_DIRS_MASK)
+ld_mask=$(unset LD_LIBRARY_MASK; portageq envvar LD_LIBRARY_MASK)
+
+if [ -d /etc/revdep-rebuild ]; then
+ for x in /etc/revdep-rebuild/*; do
+ sdirs="${sdirs}${sdirs:+ }$(unset SEARCH_DIRS; . "${x}"; echo "${SEARCH_DIRS}")"
+ sdirs_mask="${sdirs_mask}${sdirs_mask:+ }$(unset SEARCH_DIRS_MASK; . "${x}" ; echo "${SEARCH_DIRS_MASK}")"
+ ld_mask="${ld_mask}${ld_mask:+ }$(unset LD_LIBRARY_MASK; . "${x}"; echo "${LD_LIBRARY_MASK}")"
+ done
+else
+ sdirs="${sdirs}${sdirs:+ }/bin /sbin /usr/bin /usr/sbin /lib* /usr/lib*"
+ sdirs_mask="${sdirs_mask}${sdirs_mask:+ }/opt/OpenOffice /usr/lib/openoffice"
+ ld_mask="${ld_mask}${ld_mask:+ }libodbcinst.so libodbc.so libjava.so libjvm.so"
+fi
+
+sdirs=$(find ${sdirs} -type d)
+
+einfo "Starting scan"
+eindent
+# Mark our masked dirs already scanned
+scanned=
+for dir in ${sdirs_mask}; do
+ scanned "${dir}"
+done
+
+# Now scan our dirs
+for dir in ${sdirs}; do
+ scanned "${dir}" && continue
+
+ einfo "in ${dir}"
+ eindent
+ for x in "${dir}"/*; do
+ [ -d "${x}" ] && continue
+ [ -L "${x}" ] && continue
+
+ scan=true
+ process=false
+ reason=
+ case "${x}" in
+ *.so|*.so.*) process=true;;
+ *.la)
+ scan=false
+ if [ -z "${libs}" ]; then
+ reason=$(la_broken "${x}")
+ [ $? = 0 ] && process=true
+ fi
+ ;;
+ esac
+ [ -x "${x}" ] && ${scan} && process=true
+ ${process} || continue
+
+ if ${scan}; then
+ process=false
+ if [ -n "${libs}" ]; then
+ for lib in ${libs}; do
+ if [ "${lib#/}" != "${lib}" ]; then
+ # If lib starts with / then check if the exact
+ # lib is linked
+ elf_linked "${x}" "${lib}" || continue
+ fi
+ if elf_needed "${x}" ${lib}; then
+ process=true
+ break
+ fi
+ done
+ else
+ reason=$(elf_broken "${x}")
+ [ $? = 0 ] && process=true
+ fi
+ fi
+
+ ${process} || continue
+ einfo "found ${x} ${reason}"
+ files="${files}${files:+:}${x}"
+ done
+ eoutdent
+done
+eoutdent
+
+if [ -z "${files}" ]; then
+ if [ -z "${libs}" ]; then
+ einfo "Nothing found that needs rebuilding"
+ else
+ einfo "No dynamic binaries found with these libraries"
+ fi
+ exit 0
+fi
+
+einfo "Assigning files to packages"
+eindent
+ebuilds=$(get_exact_ebuilds "${files}")
+
+if [ -z "${ebuilds}" ]; then
+ eerror "No packages own these files"
+ exit 1
+fi
+
+# Work out the best visible package for the slot
+if ! ${exact}; then
+ root=$(portageq envvar ROOT)
+ root=${root:-/}
+
+ set -- ${ebuilds}
+ ebuilds=
+ for x in "$@"; do
+ x=${x#=*}
+ pkg=${x%-r[0-9]*}
+ pkg=${pkg%-*}
+ slot=$(cat "/var/db/pkg/${x}/SLOT")
+ ebd=$(portageq best_visible "${root}" "${pkg}:${slot}")
+ if [ -z "${ebd}" ]; then
+ eerror "Cannot find an ebuild visible for ${x}"
+ else
+ ebuilds="${ebuilds}${ebuilds:+ }=${ebd}"
+ fi
+ done
+fi
+eoutdent
+
+# Work out the build order
+if ${order}; then
+ einfo "Ordering packages"
+ order="$(EMERGE_DEFAULT_OPTS="" \
+ emerge --nospinner --pretend --deep --quiet ${ebuilds})"
+ if [ $? = 0 ]; then
+ ebuilds=$(echo "${order}" | \
+ sed -e 's:^\[.*\] \([^ ]*\)[ ].*$:=\1:' | \
+ grep -F "$(printf "%s\n" ${ebuilds})" | \
+ tr '\n' ' ')
+ else
+ eerror "Unable to order packages!"
+ fi
+fi
+
+if [ -z "${ebuilds}" ]; then
+ eerror "Don't know how to find which package owns what file :/"
+ exit 1
+fi
+
+echo
+einfo "About to execute"
+echo "emerge --oneshot ${emerge_opts} ${ebuilds}"
+echo
+
+i=5
+printf "in"
+while [ ${i} -gt 0 ]; do
+ printf " ${i}"
+ sleep 1
+ i=$((${i} - 1))
+done
+printf "\n\n"
+
+EMERGE_DEFAULT_OPTS="" emerge --oneshot ${emerge_opts} ${ebuilds}
+retval=$?
+
+if [ "${retval}" = 0 ]; then
+ einfo "All done"
+ exit 0
+fi
+
+eerror "There was an error trying to emerge the broken packages"
+exit "${retval}"
diff --git a/src/revdep-rebuild/revdep-rebuild.1 b/src/revdep-rebuild/revdep-rebuild.1
new file mode 100644
index 0000000..267f7f1
--- /dev/null
+++ b/src/revdep-rebuild/revdep-rebuild.1
@@ -0,0 +1,101 @@
+.TH "revdep\-rebuild" "1" "" "gentoolkit" ""
+.SH "NAME"
+revdep\-rebuild \- Gentoo: Reverse Dependency Rebuilder
+.SH "SYNOPSIS"
+.B revdep\-rebuild
+[OPTIONS] [\-\-] [EMERGE OPTIONS]
+.SH "DESCRIPTION"
+revdep\-rebuild scans libraries and binaries for missing shared library dependencies and attempts to fix them by re\-emerging those broken binaries and shared libraries. It is useful when an upgraded package breaks other software packages that are dependent upon the upgraded package.
+.SH "OPTIONS"
+.TP
+.B \-C | \-\-nocolor
+Turn off colored output. (This option is also passed to portage.)
+.TP
+.B \-e | \-\-exact
+Emerge the most recent version of found packages, without regard to SLOT.
+.TP
+.B \-h | \-\-help
+Print usage.
+.TP
+.B \-i | \-\-ignore
+Delete temporary files from previous runs.
+.TP
+.B \-k | \-\-keep\-temp
+Force revdep\-rebuild not to delete temporary files after it successfully rebuilds packages. This option will NOT prevent revdep\-rebuild from deleting inconsistent or out\-of\-date temporary files.
+.TP
+.B \-\-library NAME | -L NAME
+Search for reverse dependencies for a particular library or group of libraries, rather than every library on the system. Emerge packages that use the named library. NAME can be a full path to a library or basic regular expression. (See regex(7).)
+.TP
+.B \-l | \-\-no\-ld\-path
+Do not set LD_LIBRARY_PATH. \fBNote:\fR Using this option will cause revdep-rebuild to report some false positives.
+.TP
+.B \-o | \-\-no-order
+Do not check the build order against the deep dependency list. This will make revdep-rebuild faster, but it can cause emerge failures. Please try revdep\-rebuild without \-o before reporting any bugs.
+.TP
+.B \-p | \-\-pretend
+Do a dry-run. Do not delete temporary files. (\-k \-p is redundant, but harmless.) \-\-pretend is assumed when not running revdep\-rebuild as root.
+.TP
+.B \-P | \-\-no\-progress
+Turn off the progress meter
+.TP
+.B \-q | \-\-quiet
+Print less output and disable the progress meter. (This option is also passed to portage.)
+.TP
+.B \-u UTIL | \-\-no-util UTIL
+Do not use features provided by UTIL.
+UTIL can be one of portage-utils or pkgcore, or it can be a \fBquoted\fR space-delimited list.
+.TP
+.B \-v | \-\-verbose
+More output. (Prints the revdep\-rebuild search environment.)
+.TP
+.B All other options (including unrecognized ones) are passed to the emerge command. Single\-letter options may not be combined, so for example, \-pv is not valid. Please use \-p \-v.
+.SH "CONFIGURATION"
+revdep\-rebuild no longer uses hardcoded paths. To change the default behavior the following variables can be changed by the user.
+
+LD_LIBRARY_MASK \- Mask of specially evaluated libraries
+.LP
+SEARCH_DIRS \- List of directories to search for executables and libraries
+.LP
+SEARCH_DIRS_MASK \- List of directories to not search
+
+You can prepend to these variables by setting the variable in your environment prior to execution, by placing an entry in /etc/make.conf, or by placing a file in /etc/revdep\-rebuild containing the appropriate variables.
+
+The variables are read and set in the following order:
+
+environment settings \- one time changes by user
+.br
+/etc/make.conf \- persistent changes by user
+.br
+/etc/revdep\-rebuild/* \- persistent changes by ebuild authors
+
+While a user can edit and modify the files in the /etc/revdep\-rebuild directory, please be aware that the /etc/revdep\-rebuild directory is not under configuration protection and files can be removed and/or overwritten by an ebuild. To change this add /etc/revdep\-rebuild to the CONFIG_PROTECT variable in /etc/make.conf.
+
+An entry of "\-*" means to clear the variable from that point forward.
+Example: SEARCH_DIRS="/usr/bin \-*" will set SEARCH_DIRS to contain only /usr/bin
+
+revdep\-rebuild honors the NOCOLOR and PORTAGE_NICENESS variables from /etc/make.conf
+.SH "EXAMPLES"
+It is recommended that when running revdep\-rebuild that the following command be used initially:
+.br
+\fBrevdep\-rebuild \-\-ignore \-\-pretend\fR
+
+To search the entire system, while excluding /mnt and /home:
+.br
+\fBenv SEARCH_DIRS="/ \-*" SEARCH_DIRS_MASK="/mnt /home" revdep\-rebuild\fR
+
+To rebuild packages that depend on libkdecore.so.4 from KDE 3.3:
+.br
+\fBrevdep\-rebuild \-\-library /usr/kde/3.3/lib/libkdecore.so.4\fR
+
+To rebuild packages that depend upon libImlib.so and libImlib2.so:
+.br
+\fBrevdep\-rebuild \-\-library libImlib[2]*.so.*\fR
+
+.SH "EXIT STATUS"
+revdep\-rebuild returns a zero exit status if it \fBand emerge\fR succeeds, and a nonzero exit status otherwise.
+.SH "BUGS"
+.LP
+Report bugs to <http://bugs.gentoo.org>. Please do not report emerge failures caused by \-o or \-e. Please include your .revdep\-rebuild* files, your emerge \-\-info, and patches. ;)
+
+.SH "SEE ALSO"
+emerge(1), portage(5), regex(7)