376 lines
13 KiB
Bash
Executable File
376 lines
13 KiB
Bash
Executable File
#!/bin/sh
|
|
set -e
|
|
export LC_ALL=C
|
|
|
|
type=$1
|
|
preversion=$2
|
|
|
|
kernel_compare_versions () {
|
|
verA=$(($(echo "$1" | sed 's/\([0-9]*\)\.\([0-9]*\).*/\1 \* 100 + \2/')))
|
|
verB=$(($(echo "$3" | sed 's/\([0-9]*\)\.\([0-9]*\).*/\1 \* 100 + \2/')))
|
|
|
|
test $verA -$2 $verB
|
|
}
|
|
|
|
# Sanity check.
|
|
# If there are versions of glibc outside of the normal installation
|
|
# location (/lib, /lib64, etc.) then things may break very badly
|
|
# as soon as ld.so is replaced by a new version. This check is not
|
|
# foolproof, but it's pretty accurate. This script ignores libraries
|
|
# with different sonames, and libraries incompatible with the
|
|
# to-be-installed ld.so.
|
|
check_dir () {
|
|
msg=$1
|
|
dir=$2
|
|
|
|
# Follow symlinks
|
|
dir=$(readlink -e $dir || true)
|
|
|
|
# Ignore inexistent directories
|
|
if ! test -d "$dir" ; then
|
|
return
|
|
fi
|
|
|
|
# Detect possible candidates
|
|
files=$(ls $dir | egrep '^(ld|lib(d|c|m|pthread|rt|dl))-2.*.so' 2>/dev/null || true)
|
|
if test -z "$files" ; then
|
|
return
|
|
fi
|
|
|
|
for file in $files ; do
|
|
lib=$dir/$file
|
|
|
|
# Skip if it is a symlink (as installed by lsb-core)
|
|
if test -L "$lib" ; then
|
|
continue
|
|
fi
|
|
|
|
# Skip if it is the currently dynamic loader
|
|
if test "$lib" = "$ldfile" ; then
|
|
continue
|
|
fi
|
|
|
|
# See if the found libraries are compatible with the system ld.so;
|
|
# if they aren't, they'll be ignored. Check e_ident, e_type (which
|
|
# will just be ET_DYN), and e_machine. If a match is found, there
|
|
# is a risk of breakage.
|
|
libbytes=`head -c 20 $lib | od -c`
|
|
if test "$ldbytes" != "$libbytes" ; then
|
|
continue
|
|
fi
|
|
|
|
# Binaries owned packages are considered to do the right thing
|
|
# First try a quick lookup which should catch all cases on a
|
|
# normal system
|
|
if echo $libcfiles | grep -q "[ ^]$lib[ $]" ; then
|
|
continue
|
|
fi
|
|
|
|
# Slower lookup to confirm
|
|
if dpkg-query -S "$lib" >/dev/null 2>&1 ; then
|
|
continue
|
|
fi
|
|
|
|
# Output an error message and exit
|
|
echo
|
|
echo "A copy of the C library was found $msg:"
|
|
echo " '$lib'"
|
|
echo "It is not safe to upgrade the C library in this situation;"
|
|
echo "please remove that copy of the C library or get it out of"
|
|
echo "'$dir' and try again."
|
|
echo
|
|
exit 1
|
|
done
|
|
}
|
|
|
|
if [ "$type" != abort-upgrade ]
|
|
then
|
|
# Load debconf module if available
|
|
if [ -f /usr/share/debconf/confmodule ] ; then
|
|
. /usr/share/debconf/confmodule
|
|
fi
|
|
|
|
# See if LD_LIBRARY_PATH contains the traditional /lib, but not the
|
|
# multiarch path
|
|
dirs=$(echo $LD_LIBRARY_PATH | sed 's/:/ /g')
|
|
for dir in $dirs ; do
|
|
dir=$(readlink -e $dir || true)
|
|
case "$dir" in
|
|
/lib)
|
|
seen_traditional=1
|
|
;;
|
|
/lib/aarch64-linux-gnu)
|
|
seen_multiarch=1
|
|
;;
|
|
esac
|
|
done
|
|
if test -n "$seen_traditional" && test -z "$seen_multiarch" ; then
|
|
echo
|
|
echo "LD_LIBRARY_PATH contains the traditional /lib directory,"
|
|
echo "but not the multiarch directory /lib/aarch64-linux-gnu."
|
|
echo "It is not safe to upgrade the C library in this situation;"
|
|
echo "please remove the /lib/directory from LD_LIBRARY_PATH and"
|
|
echo "try again."
|
|
echo
|
|
exit 1
|
|
fi
|
|
|
|
# glibc kernel version check
|
|
system=`uname -s`
|
|
if [ "$system" = "Linux" ]
|
|
then
|
|
# sanity checking for the appropriate kernel on each architecture.
|
|
kernel_ver=`uname -r`
|
|
case ${DPKG_MAINTSCRIPT_ARCH:-$(dpkg --print-architecture)} in
|
|
*)
|
|
# The GNU libc requires a >= 3.2 kernel, found in wheezy
|
|
kernel_ver_min=3.2
|
|
kernel_ver_rec=3.2
|
|
;;
|
|
esac
|
|
|
|
if kernel_compare_versions "$kernel_ver" lt $kernel_ver_min
|
|
then
|
|
if [ -f /usr/share/debconf/confmodule ]
|
|
then
|
|
db_version 2.0
|
|
db_fset glibc/kernel-too-old seen false
|
|
db_reset glibc/kernel-too-old
|
|
db_subst glibc/kernel-too-old kernel_ver $kernel_ver_rec
|
|
db_input critical glibc/kernel-too-old || true
|
|
db_go
|
|
db_stop
|
|
else
|
|
echo "ERROR: This version of the GNU libc requires kernel version"
|
|
echo "$kernel_ver_rec or later. Please upgrade your kernel before installing"
|
|
echo "glibc."
|
|
echo
|
|
fi
|
|
exit 1
|
|
fi
|
|
|
|
if kernel_compare_versions "$kernel_ver" lt $kernel_ver_rec
|
|
then
|
|
if [ -f /usr/share/debconf/confmodule ]
|
|
then
|
|
db_version 2.0
|
|
db_fset glibc/kernel-not-supported seen false
|
|
db_reset glibc/kernel-not-supported
|
|
db_subst glibc/kernel-not-supported kernel_ver $kernel_ver_rec
|
|
db_input critical glibc/kernel-not-supported || true
|
|
db_go
|
|
db_stop
|
|
else
|
|
echo "WARNING: This version of the GNU libc requires kernel version"
|
|
echo "$kernel_ver_rec or later. Older versions might work but are not officially"
|
|
echo "supported. Please consider upgrading your kernel."
|
|
echo
|
|
fi
|
|
fi
|
|
|
|
elif [ $system = "GNU/kFreeBSD" ]
|
|
then
|
|
kernel_ver=`uname -r`
|
|
kernel_ver_min=8.3
|
|
if kernel_compare_versions "$kernel_ver" lt $kernel_ver_min
|
|
then
|
|
if [ -f /usr/share/debconf/confmodule ]
|
|
then
|
|
db_version 2.0
|
|
db_version 2.0
|
|
db_fset glibc/kernel-too-old seen false
|
|
db_reset glibc/kernel-too-old
|
|
db_subst glibc/kernel-too-old kernel_ver $kernel_ver_min
|
|
db_input critical glibc/kernel-too-old || true
|
|
db_go
|
|
db_stop
|
|
else
|
|
echo "ERROR: This version of the GNU libc requires kernel version"
|
|
echo "$kernel_ver_min or later. Please upgrade your kernel before installing"
|
|
echo "glibc."
|
|
echo
|
|
fi
|
|
exit 1
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if [ "$type" = upgrade ]
|
|
then
|
|
# Try to detect copies of the libc library in the various places
|
|
# the dynamic linker uses.
|
|
ldfile=$(readlink -m /lib/ld-linux-aarch64.so.1)
|
|
if test -f "$file"; then
|
|
ldbytes=$(head -c 20 /lib/ld-linux-aarch64.so.1 | od -c)
|
|
else
|
|
# If the symlink to the dynamic linker is dangling or missing, set
|
|
# ldbytes to an empty string, the test below will fail and all the
|
|
# libraries found will be ignored.
|
|
ldbytes=""
|
|
fi
|
|
libcfiles=$(dpkg-query -L ${DPKG_MAINTSCRIPT_PACKAGE}:${DPKG_MAINTSCRIPT_ARCH} 2>/dev/null)
|
|
|
|
dirs="/lib/aarch64-linux-gnu /lib /lib/tls /lib32 /lib64 /usr/local/lib /usr/local/lib32 /usr/local/lib64"
|
|
for dir in $dirs ; do
|
|
check_dir "in an unexpected directory" $dir
|
|
done
|
|
|
|
if test -n "$LD_LIBRARY_PATH"; then
|
|
dirs=$(echo $LD_LIBRARY_PATH | sed 's/:/ /g')
|
|
for dir in $dirs ; do
|
|
check_dir "via LD_LIBRARY_PATH" $dir
|
|
done
|
|
fi
|
|
|
|
if test -e /etc/ld.so.conf; then
|
|
dirs=$(echo $(cat /etc/ld.so.conf))
|
|
if test -n "$dirs" ; then
|
|
for dir in $dirs ; do
|
|
check_dir "via /etc/ld.so.conf" $dir
|
|
done
|
|
fi
|
|
fi
|
|
|
|
if [ -e /lib/tls/i686/cmov/libc.so.6 ] || [ -e /lib/i686/cmov/libc.so.6 ] ; then
|
|
status_i686=$(dpkg -s libc6-i686 2>/dev/null | grep ^Status: | sed -e 's/^Status: \(.*\) \(.*\) \(.*\)/\3/g')
|
|
status_xen=$(dpkg -s libc6-xen 2>/dev/null | grep ^Status: | sed -e 's/^Status: \(.*\) \(.*\) \(.*\)/\3/g')
|
|
if ([ -z "$status_i686" ] || [ "$status_i686" = "not-installed" ] || [ "$status_i686" = "config-files" ]) && \
|
|
([ -z "$status_xen" ] || [ "$status_xen" = "not-installed" ] || [ "$status_xen" = "config-files" ]); then
|
|
echo
|
|
echo "A non-dpkg owned copy of the libc6-i686 package was found."
|
|
echo "It is not safe to upgrade the C library in this situation;"
|
|
echo "please remove that copy of the C library and try again."
|
|
echo
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [ -n "$preversion" ] && [ -x "$(which ischroot)" ] && ! ischroot; then
|
|
# NSS authentication trouble guard
|
|
if dpkg --compare-versions "$preversion" lt 2.28; then
|
|
if pidof xscreensaver xlockmore >/dev/null; then
|
|
if [ -f /usr/share/debconf/confmodule ] ; then
|
|
db_version 2.0
|
|
db_reset glibc/disable-screensaver
|
|
db_input critical glibc/disable-screensaver || true
|
|
db_go || true
|
|
else
|
|
echo "xscreensaver and xlockmore must be restarted before upgrading"
|
|
echo
|
|
echo "One or more running instances of xscreensaver or xlockmore have been"
|
|
echo "detected on this system. Because of incompatible library changes, the"
|
|
echo "upgrade of the GNU C library will leave you unable to authenticate to"
|
|
echo "these programs. You should arrange for these programs to be restarted"
|
|
echo "or stopped before continuing this upgrade, to avoid locking your users"
|
|
echo "out of their current sessions."
|
|
echo
|
|
frontend=`echo "$DEBIAN_FRONTEND" | tr '[:upper:]' '[:lower:]'`
|
|
if [ "$frontend" = noninteractive ]; then
|
|
echo "Non-interactive mode, upgrade glibc forcibly"
|
|
else
|
|
echo -n "Press a key to continue"
|
|
read answer
|
|
fi
|
|
echo
|
|
fi
|
|
fi
|
|
|
|
check="kdm postgresql xdm"
|
|
# NSS services check:
|
|
echo -n "Checking for services that may need to be restarted..."
|
|
# Only get the ones that are installed, and configured
|
|
check=$(dpkg -s $check 2> /dev/null | egrep '^Package:|^Status:' | awk '{if ($1 ~ /^Package:/) { package=$2 } else if ($0 ~ /^Status: .* installed$/) { print package }}')
|
|
# some init scripts don't match the package names
|
|
check=$(echo $check | \
|
|
sed -e's/\bapache2.2-common\b/apache2/g' \
|
|
-e's/\bat\b/atd/g' \
|
|
-e's/\bdovecot-common\b/dovecot/g' \
|
|
-e's/\bexim4-base\b/exim4/g' \
|
|
-e's/\blpr\b/lpd/g' \
|
|
-e's/\blpr-ppd\b/lpd-ppd/g' \
|
|
-e's/\bmysql-server\b/mysql/g' \
|
|
-e's/\bsasl2-bin\b/saslauthd/g' \
|
|
-e's/\bsamba\b/smbd/g' \
|
|
-e's/\bpostgresql-common\b/postgresql/g' \
|
|
)
|
|
echo
|
|
echo "Checking init scripts..."
|
|
for service in $check; do
|
|
invoke-rc.d ${service} status >/dev/null 2>/dev/null && status=0 || status=$?
|
|
if [ "$status" = "0" ] || [ "$status" = "2" ] ; then
|
|
services="$service $services"
|
|
elif [ "$status" = "100" ] ; then
|
|
echo "WARNING: init script for $service not found."
|
|
fi
|
|
done
|
|
|
|
if [ -n "$services" ]; then
|
|
if [ -f /usr/share/debconf/confmodule ] ; then
|
|
db_version 2.0
|
|
db_reset glibc/upgrade
|
|
db_subst glibc/upgrade services $services
|
|
db_input critical glibc/upgrade || true
|
|
db_go || true
|
|
db_get glibc/upgrade
|
|
answer=$RET
|
|
else
|
|
echo "Do you want to upgrade glibc now?"
|
|
echo
|
|
echo "Running services and programs that are using NSS need to be restarted,"
|
|
echo "otherwise they might not be able to do lookup or authentication any more."
|
|
echo "The installation process is able to restart some services (such as ssh or"
|
|
echo "telnetd), but other programs cannot be restarted automatically. One such"
|
|
echo "program that needs manual stopping and restart after the glibc upgrade by"
|
|
echo "yourself is xdm - because automatic restart might disconnect your active"
|
|
echo "X11 sessions."
|
|
echo
|
|
echo "This script detected the following installed services which must be"
|
|
echo "stopped before the upgrade: $services"
|
|
echo
|
|
echo "If you want to interrupt the upgrade now and continue later, please"
|
|
echo "answer No to the question below."
|
|
echo
|
|
frontend=`echo "$DEBIAN_FRONTEND" | tr '[:upper:]' '[:lower:]'`
|
|
if [ "$frontend" = noninteractive ]; then
|
|
echo "Non-interactive mode, upgrade glibc forcibly"
|
|
answer=true
|
|
else
|
|
echo -n "Do you want to upgrade glibc now? [Y/n] "
|
|
read answer
|
|
case $answer in
|
|
Y*|y*) answer=true ;;
|
|
N*|n*) answer=false ;;
|
|
*) answer=true ;;
|
|
esac
|
|
fi
|
|
echo
|
|
fi
|
|
|
|
if [ "x$answer" != "xtrue" ]; then
|
|
echo "Stopped glibc upgrade. Please retry the upgrade after you have"
|
|
echo "checked or stopped services by hand."
|
|
exit 1
|
|
fi
|
|
fi
|
|
fi # end upgrading and $preversion lt 2.28
|
|
fi # Upgrading
|
|
|
|
# This will keep us from using hwcap libs (optimized) during an
|
|
# upgrade.
|
|
touch /etc/ld.so.nohwcap
|
|
fi
|
|
|
|
|
|
|
|
if [ -n "$preversion" ]; then
|
|
if dpkg --compare-versions "$preversion" lt 2.28; then
|
|
# unconditionally wipe ld.so.cache on major version upgrades; this
|
|
# makes those upgrades a bit slower, but is less error-prone than
|
|
# hoping we notice every time the cache format is changed upstream
|
|
rm -f /etc/ld.so.cache
|
|
rm -f /var/cache/ldconfig/aux-cache
|
|
fi
|
|
fi
|
|
|
|
exit 0
|