diff options
author | Patrick J Volkerding <volkerdi@slackware.com> | 2009-08-26 10:00:38 -0500 |
---|---|---|
committer | Eric Hameleers <alien@slackware.com> | 2018-05-31 22:41:17 +0200 |
commit | 5a12e7c134274dba706667107d10d231517d3e05 (patch) | |
tree | 55718d5acb710fde798d9f38d0bbaf594ed4b296 /source/a/pkgtools/scripts/installpkg | |
download | current-5a12e7c134274dba706667107d10d231517d3e05.tar.gz current-5a12e7c134274dba706667107d10d231517d3e05.tar.xz |
Slackware 13.0slackware-13.0
Wed Aug 26 10:00:38 CDT 2009
Slackware 13.0 x86_64 is released as stable! Thanks to everyone who
helped make this release possible -- see the RELEASE_NOTES for the
credits. The ISOs are off to the replicator. This time it will be a
6 CD-ROM 32-bit set and a dual-sided 32-bit/64-bit x86/x86_64 DVD.
We're taking pre-orders now at store.slackware.com. Please consider
picking up a copy to help support the project. Once again, thanks to
the entire Slackware community for all the help testing and fixing
things and offering suggestions during this development cycle.
As always, have fun and enjoy! -P.
Diffstat (limited to 'source/a/pkgtools/scripts/installpkg')
-rw-r--r-- | source/a/pkgtools/scripts/installpkg | 568 |
1 files changed, 568 insertions, 0 deletions
diff --git a/source/a/pkgtools/scripts/installpkg b/source/a/pkgtools/scripts/installpkg new file mode 100644 index 000000000..31bb0b717 --- /dev/null +++ b/source/a/pkgtools/scripts/installpkg @@ -0,0 +1,568 @@ +#!/bin/sh +# Copyright 1994, 1998, 2000 Patrick Volkerding, Concord, CA, USA +# Copyright 2001, 2003 Slackware Linux, Inc., Concord, CA, USA +# Copyright 2007, 2009 Patrick Volkerding, Sebeka, MN, USA +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Sat Apr 25 21:18:53 UTC 2009 +# Converted to use new pkgbase() function to remove pathname and +# valid package extensions. +# +# Sat Apr 4 22:58:06 CDT 2009 +# Support additional compression formats if the supporting utilities exist: +# .tbz - bzip2 +# .tlz - lzma +# .txz - xz (also LZMA) +# And of course, .tgz (gzip) is not going anywhere. :-) <volkerdi> +# Add command switches to determine the uncompressed package size even if +# that will slow things down, and to add the package's md5sum to the +# metadata stored in /var/log/packages/. +# +# Fri Dec 21 17:21:35 CST 2007 +# Added a patch from Johnny Morano to work around package removal issues +# caused by packages that do not comply with FHS combined with a grep +# regex error in installpkg. Any package with a single-letter top- +# level directory could not be removed. +# +# Shortened some of the top-line dialog output to avoid overflowing the +# textbox (needed as some of the packages, especially in X, have very +# long base package names now). <pjv> +# +# Sun Nov 26 12:38:25 CST 1995 +# Added patch from Glenn Moloney <glenn@physics.unimelb.edu.au> to allow +# packages to be installed to directories other than /. +# +# Wed Mar 18 15:15:51 CST 1998 +# Changed $TMP directory to /var/log/setup/tmp, and chmod'ed it 700 to close +# some security holes. + +# Return a package name that has been stripped of the dirname portion +# and any of the valid extensions (only): +pkgbase() { + PKGEXT=$(echo $1 | rev | cut -f 1 -d . | rev) + case $PKGEXT in + 'tgz' ) + PKGRETURN=$(basename $1 .tgz) + ;; + 'tbz' ) + PKGRETURN=$(basename $1 .tbz) + ;; + 'tlz' ) + PKGRETURN=$(basename $1 .tlz) + ;; + 'txz' ) + PKGRETURN=$(basename $1 .txz) + ;; + *) + PKGRETURN=$(basename $1) + ;; + esac + echo $PKGRETURN +} + +# If installpkg encounters a problem, it will return a non-zero error code. +# If it finds more than one problem (i.e. with a list of packages) you'll only +# hear about the most recent one. :) +# 1 = tar returned error code +# 2 = corrupt compression envelope +# 3 = does not end in .tgz +# 4 = no such file +# 5 = external compression utility missing +# 99 = user abort from menu mode +EXITSTATUS=0 + +# Do not store md5sums by default: +MD5SUM=0 + +# So that we know what to expect... +umask 022 +TAR=tar-1.13 +$TAR --help 1> /dev/null 2> /dev/null +if [ ! $? = 0 ]; then + TAR=tar +fi +if [ ! "$(LC_MESSAGES=C $TAR --version)" = "tar (GNU tar) 1.13 + +Copyright (C) 1988, 92,93,94,95,96,97,98, 1999 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +Written by John Gilmore and Jay Fenlason." ]; then + echo "WARNING: pkgtools are unstable with tar > 1.13." + echo " You should provide a \"tar-1.13\" in your \$PATH." + sleep 5 +fi + +usage() { + cat << EOF +Usage: installpkg [options] <package_filename> + +Installpkg is used to install a .t{gz,bz,lz,xz} package like this: + installpkg slackware-package-1.0.0-i486-1.tgz (or .tbz, .tlz, .txz) + +options: --warn (warn if files will be overwritten, but do not install) + --root /mnt (install someplace else, like /mnt) + --infobox (use dialog to draw an info box) + --menu (confirm package installation with a menu, unless + the priority is [required] or ADD) + --ask (used with menu mode: always ask if a package should be + installed regardless of what the package's priority is) + --priority ADD|REC|OPT|SKP (provide a priority for the entire + package list to use instead of the priority in the + tagfile) + --tagfile /somedir/tagfile (specify a different file to use + for package priorities. The default is "tagfile" in + the package's directory) + --md5sum (record the package's md5sum in the metadata file) + +EOF +} + +# Eliminate whitespace function: +crunch() { + while read FOO ; do + echo $FOO + done +} + +package_name() { + STRING=$(pkgbase $1) + # Check for old style package name with one segment: + if [ "$(echo $STRING | cut -f 1 -d -)" = "$(echo $STRING | cut -f 2 -d -)" ]; then + echo $STRING + else # has more than one dash delimited segment + # Count number of segments: + INDEX=1 + while [ ! "$(echo $STRING | cut -f $INDEX -d -)" = "" ]; do + INDEX=$(expr $INDEX + 1) + done + INDEX=$(expr $INDEX - 1) # don't include the null value + # If we don't have four segments, return the old-style (or out of spec) package name: + if [ "$INDEX" = "2" -o "$INDEX" = "3" ]; then + echo $STRING + else # we have four or more segments, so we'll consider this a new-style name: + NAME=$(expr $INDEX - 3) + NAME="$(echo $STRING | cut -f 1-$NAME -d -)" + echo $NAME + # cruft for later ;) + #VER=$(expr $INDEX - 2) + #VER="$(echo $STRING | cut -f $VER -d -)" + #ARCH=$(expr $INDEX - 1) + #ARCH="$(echo $STRING | cut -f $ARCH -d -)" + #BUILD="$(echo $STRING | cut -f $INDEX -d -)" + fi + fi +} + +# Parse options: +MODE=install # standard text-mode +while [ 0 ]; do + if [ "$1" = "-warn" -o "$1" = "--warn" ]; then + MODE=warn + shift 1 + elif [ "$1" = "-md5sum" -o "$1" = "--md5sum" ]; then + MD5SUM=1 + shift 1 + elif [ "$1" = "-infobox" -o "$1" = "--infobox" ]; then + MODE=infobox + shift 1 + elif [ "$1" = "-menu" -o "$1" = "--menu" ]; then + MODE=menu + shift 1 + elif [ "$1" = "-ask" -o "$1" = "--ask" ]; then + ALWAYSASK="yes" + shift 1 + elif [ "$1" = "-tagfile" -o "$1" = "--tagfile" ]; then + if [ -r "$2" ]; then + USERTAGFILE="$2" + elif [ -r "$(pwd)/$2" ]; then + USERTAGFILE="$(pwd)/$2" + else + usage + exit + fi + shift 2 + elif [ "$1" = "-priority" -o "$1" = "--priority" ]; then + if [ "$2" = "" ]; then + usage + exit + fi + USERPRIORITY="$2" + shift 2 + elif [ "$1" = "-root" -o "$1" = "--root" ]; then + if [ "$2" = "" ]; then + usage + exit + fi + ROOT="$2" + shift 2 + else + break + fi +done + +# Set the prefix for the package database directories (packages, scripts). +ADM_DIR="$ROOT/var/log" +# If the directories don't exist, "initialize" the package database: +for PKGDBDIR in packages removed_packages removed_scripts scripts setup ; do + if [ ! -d $ADM_DIR/$PKGDBDIR ]; then + rm -rf $ADM_DIR/$PKGDBDIR # make sure it's not a symlink or something stupid + mkdir -p $ADM_DIR/$PKGDBDIR + chmod 755 $ADM_DIR/$PKGDBDIR + fi +done + +# Make sure there's a proper temp directory: +TMP=$ADM_DIR/setup/tmp +# If the $TMP directory doesn't exist, create it: +if [ ! -d $TMP ]; then + rm -rf $TMP # make sure it's not a symlink or something stupid + mkdir -p $TMP + chmod 700 $TMP # no need to leave it open +fi + +# usage(), exit if called with no arguments: +if [ $# = 0 ]; then + usage; + exit +fi + +# If -warn mode was requested, produce the output and then exit: +if [ "$MODE" = "warn" ]; then + while [ -f "$1" ]; do + echo "#### Scanning the contents of $1..." + mkdir -p $TMP/scan$$ + # Determine extension: + packageext="$( echo $1 | rev | cut -f 1 -d . | rev)" + # Determine compressor utility: + case $packageext in + 'tgz' ) + packagecompression=gzip + ;; + 'tbz' ) + packagecompression=bzip2 + ;; + 'tlz' ) + packagecompression=lzma + ;; + 'txz' ) + packagecompression=xz + ;; + esac + ( cd $TMP/scan$$ ; $packagecompression -dc | $TAR xf - install ) < $1 2> /dev/null + if [ -r $TMP/scan$$/install/doinst.sh ]; then + if cat $TMP/scan$$/install/doinst.sh | grep ' rm -rf ' 1>/dev/null 2>/dev/null ; then + cat $TMP/scan$$/install/doinst.sh | grep ' rm -rf ' > $TMP/scan$$/install/delete + echo "The following locations will be completely WIPED OUT to allow symbolic" + echo "links to be made. (We're talking 'rm -rf') These locations may be files," + echo "or entire directories. Be sure you've backed up anything at these" + echo "locations that you want to save before you install this package:" + cat $TMP/scan$$/install/delete | cut -f 3,7 -d ' ' | tr ' ' '/' + fi + if [ -d $TMP/scan$$ ]; then + ( cd $TMP/scan$$ ; rm -rf install ) 2> /dev/null + ( cd $TMP ; rmdir scan$$ ) 2> /dev/null + fi + fi + echo "The following files will be overwritten when installing this package." + echo "Be sure they aren't important before you install this package:" + ( $packagecompression -dc | $TAR tvvf - ) < $1 | grep -v 'drwx' + echo + shift 1 + done + exit +fi + +# Main loop: +for package in $* ; do + + # Simple package integrity check: + if [ ! -f $package ]; then + EXITSTATUS=4 + if [ "$MODE" = "install" ]; then + echo "Cannot install $package: file not found" + fi + continue; + fi + + # "shortname" isn't really THAT short... + # it's just the full name without ".t{gz,bz,lz,xz}" + shortname="$(pkgbase $package)" + packagedir="$(dirname $package)" + # This is the base package name, used for grepping tagfiles and descriptions: + packagebase="$(package_name $shortname)" + + # Reject package if it does not end in '.t{gz,bz,lz,xz}': + if [ "$shortname" = "$(basename $package)" ]; then + EXITSTATUS=3 + if [ "$MODE" = "install" ]; then + echo "Cannot install $package: file does not end in .tgz, .tbz, .tlz, or .txz" + fi + continue; + fi + + # Determine extension: + packageext="$(echo $package | rev | cut -f 1 -d . | rev)" + + # Determine compressor utility: + case $packageext in + 'tgz' ) + packagecompression=gzip + ;; + 'tbz' ) + packagecompression=bzip2 + ;; + 'tlz' ) + packagecompression=lzma + ;; + 'txz' ) + packagecompression=xz + ;; + esac + + # Test presence of external compression utility: + if ! $packagecompression --help 1> /dev/null 2> /dev/null ; then + EXITSTATUS=5 + if [ "$MODE" = "install" ]; then + echo "Cannot install $package: external compression utility $packagecompression missing" + fi + continue; + fi + + # Determine package's priority: + unset PRIORITY + if [ "$USERTAGFILE" = "" ]; then + TAGFILE="$packagedir/tagfile" + else + TAGFILE="$USERTAGFILE" + fi + if [ ! -r "$TAGFILE" ]; then + TAGFILE=/dev/null + fi + if grep "^$packagebase:" "$TAGFILE" | grep ADD > /dev/null 2> /dev/null ; then + PRIORITY="ADD" + elif grep "^$packagebase:" "$TAGFILE" | grep REC > /dev/null 2> /dev/null ; then + PRIORITY="REC" + elif grep "^$packagebase:" "$TAGFILE" | grep OPT > /dev/null 2> /dev/null ; then + PRIORITY="OPT" + elif grep "^$packagebase:" "$TAGFILE" | grep SKP > /dev/null 2> /dev/null ; then + PRIORITY="SKP" + fi + if [ "$PRIORITY" = "ADD" ]; then + PMSG="[ADD]" + elif [ "$PRIORITY" = "REC" ]; then + PMSG="[REC]" + elif [ "$PRIORITY" = "OPT" ]; then + PMSG="[OPT]" + elif [ "$PRIORITY" = "SKP" ]; then + PMSG="[SKP]" + else + PMSG="" + fi + + # If a tagfile wants this package to be skipped, do that now before + # wasting any more CPU on it: + if [ "$PRIORITY" = "SKP" -a ! "$ALWAYSASK" = "yes" ]; then + continue # next package + fi + + # Figure out some package information, like the compressed and uncompressed + # sizes, and where to find the package description: + COMPRESSED="$(du -s $package | cut -f 1)K" + DESCRIPTION="" + # First check for .txt file next to the package, since this is faster: + if grep "^$packagebase:" "$packagedir/$shortname.txt" 1> /dev/null 2> /dev/null ; then + DESCRIPTION="$packagedir/$shortname.txt" + elif grep "^$shortname:" "$packagedir/$shortname.txt" 1> /dev/null 2> /dev/null ; then + DESCRIPTION="$packagedir/$shortname.txt" + fi + + # Test tarball integrity and get uncompressed package size: + if [ "$MODE" = "install" ]; then + echo "Verifying package $(basename $package)." + fi + cat $package | $packagecompression -dc | dd 2> $TMP/tmpsize$$ | $TAR tf - 1> $TMP/tmplist$$ 2> /dev/null + TARERROR=$? + if [ ! "$TARERROR" = "0" ]; then + EXITSTATUS=1 # tar file corrupt + if [ "$MODE" = "install" ]; then + echo "Unable to install $package: tar archive is corrupt (tar returned error code $TARERROR)" + fi + rm -f $TMP/tmplist$$ $TMP/tmpsize$$ + continue + fi + UNCOMPRESSED="$(expr $(cat $TMP/tmpsize$$ | head -n 1 | cut -f 1 -d +) / 2)K" + rm -f $TMP/tmpsize$$ + + # If we still don't have a package description, look inside the package. + # This requires a costly untar. + if [ "$DESCRIPTION" = "" ]; then + mkdir -p $TMP/scan$$ + ( cd $TMP/scan$$ ; $packagecompression -dc | $TAR xf - install ) < $package 2> /dev/null + if grep "^$packagebase:" "$TMP/scan$$/install/slack-desc" 1> /dev/null 2> /dev/null ; then + DESCRIPTION="$TMP/scan$$/install/slack-desc" + elif grep "^$shortname:" "$TMP/scan$$/install/slack-desc" 1> /dev/null 2> /dev/null ; then + DESCRIPTION="$TMP/scan$$/install/slack-desc" + fi + fi + + if [ "$DESCRIPTION" = "" ]; then + #echo "WARNING NO SLACK-DESC" + DESCRIPTION="/dev/null" + fi + + # Gather package infomation into a temporary file: + cat $DESCRIPTION | grep "^$packagebase:" | cut -f 2- -d : | cut -b2- 1> $TMP/tmpmsg$$ 2> /dev/null + if [ "$shortname" != "$packagebase" ]; then + cat $DESCRIPTION | grep "^$shortname:" | cut -f 2- -d : | cut -b2- 1>> $TMP/tmpmsg$$ 2> /dev/null + fi + # Adjust the length here. This allows a slack-desc to be any size up to 13 lines instead of fixed at 11. + LENGTH=$(cat $TMP/tmpmsg$$ | wc -l) + while [ $LENGTH -lt 12 ]; do + echo >> $TMP/tmpmsg$$ + LENGTH=$(expr $LENGTH + 1) + done + echo "Size: Compressed: ${COMPRESSED}, uncompressed: ${UNCOMPRESSED}." >> $TMP/tmpmsg$$ + # For recent versions of dialog it is necessary to add \n to the end of each line + # or it will remove repeating spaces and mess up our careful formatting: + cat << EOF > $TMP/controlns$$ +\n +\n +\n +\n +\n +\n +\n +\n +\n +\n +\n +\n +\n +EOF + paste -d "" $TMP/tmpmsg$$ $TMP/controlns$$ > $TMP/pasted$$ + rm -f $TMP/controlns$$ + mv $TMP/pasted$$ $TMP/tmpmsg$$ + # Emit information to the console: + if [ "$MODE" = "install" ]; then + if [ "$PMSG" = "" ]; then + echo "Installing package $(basename $package):" + else + echo "Installing package $(basename $package) $PMSG:" + fi + echo "PACKAGE DESCRIPTION:" + cat $DESCRIPTION | grep "^$packagebase:" | uniq | sed "s/^$packagebase:/#/g" + if [ "$shortname" != "$packagebase" ]; then + cat $DESCRIPTION | grep "^$shortname:" | uniq | sed "s/^$shortname:/#/g" + fi + elif [ "$MODE" = "infobox" ]; then # install infobox package + dialog --title "Installing package $shortname $PMSG" --infobox "$(cat $TMP/tmpmsg$$)" 0 0 + elif [ "$MODE" = "menu" -a "$PRIORITY" = "ADD" -a ! "$ALWAYSASK" = "yes" ]; then # ADD overrides menu mode unless -ask was used + dialog --title "Installing package $shortname $PMSG" --infobox "$(cat $TMP/tmpmsg$$)" 0 0 + elif [ "$MODE" = "menu" -a "$USERPRIORITY" = "ADD" ]; then # install no matter what $PRIORITY + dialog --title "Installing package $shortname $PMSG" --infobox "$(cat $TMP/tmpmsg$$)" 0 0 + else # we must need a full menu: + dialog --title "Package Name: $shortname $PMSG" --menu "$(cat $TMP/tmpmsg$$)" 0 0 3 \ + "Yes" "Install package $shortname" \ + "No" "Do not install package $shortname" \ + "Quit" "Abort software installation completely" 2> $TMP/reply$$ + if [ ! $? = 0 ]; then + echo "No" > $TMP/reply$$ + fi + REPLY="$(cat $TMP/reply$$)" + rm -f $TMP/reply$$ $TMP/tmpmsg$$ + if [ "$REPLY" = "Quit" ]; then + exit 99 # EXIT STATUS 99 = ABORT! + elif [ "$REPLY" = "No" ]; then + continue # skip the package + fi + fi + + # Make sure there are no symbolic links sitting in the way of + # incoming package files: + cat $TMP/tmplist$$ | grep -v "/$" | while read file ; do + if [ -L "$ROOT/$file" ]; then + rm -f "$ROOT/$file" + fi + done + rm -f $TMP/tmplist$$ + + # Write the package file database entry and install the package: + echo "PACKAGE NAME: $shortname" > $ADM_DIR/packages/$shortname + echo "COMPRESSED PACKAGE SIZE: $COMPRESSED" >> $ADM_DIR/packages/$shortname + echo "UNCOMPRESSED PACKAGE SIZE: $UNCOMPRESSED" >> $ADM_DIR/packages/$shortname + echo "PACKAGE LOCATION: $package" >> $ADM_DIR/packages/$shortname + # Record the md5sum if that's a selected option: + if [ $MD5SUM = 1 ]; then + echo "PACKAGE MD5SUM: $(md5sum $package | cut -f 1 -d ' ')" >> $ADM_DIR/packages/$shortname + fi + echo "PACKAGE DESCRIPTION:" >> $ADM_DIR/packages/$shortname + cat $DESCRIPTION | grep "^$packagebase:" >> $ADM_DIR/packages/$shortname 2> /dev/null + if [ "$shortname" != "$packagebase" ]; then + cat $DESCRIPTION | grep "^$shortname:" >> $ADM_DIR/packages/$shortname 2> /dev/null + fi + echo "FILE LIST:" >> $ADM_DIR/packages/$shortname + ( cd $ROOT/ ; $packagecompression -dc | $TAR -xlUpvf - ) < $package >> $TMP/$shortname 2> /dev/null + if [ "$(cat $TMP/$shortname | grep '^\./' | wc -l | tr -d ' ')" = "1" ]; then + # Good. We have a package that meets the Slackware spec. + cat $TMP/$shortname >> $ADM_DIR/packages/$shortname + else + # Some dumb bunny built a package with something other than makepkg. Bad! + # Oh well. Bound to happen. Par for the course. Fix it and move on... + echo "WARNING: Package has not been created with 'makepkg'" + echo './' >> $ADM_DIR/packages/$shortname + cat $TMP/$shortname >> $ADM_DIR/packages/$shortname + fi + rm -f $TMP/$shortname + + # It's a good idea to make sure those newly installed libraries + # are properly activated for use: + if [ -x /sbin/ldconfig ]; then + /sbin/ldconfig + fi + + if [ -f $ROOT/install/doinst.sh ]; then + if [ "$MODE" = "install" ]; then + echo "Executing install script for $(basename $package)." + fi + ( cd $ROOT/ ; sh install/doinst.sh -install; ) + fi + # Clean up the mess... + if [ -d $ROOT/install ]; then + if [ -r $ROOT/install/doinst.sh ]; then + cp $ROOT/install/doinst.sh $ADM_DIR/scripts/$shortname + chmod 755 $ADM_DIR/scripts/$shortname + fi + # /install/doinst.sh and /install/slack-* are reserved locations for the package system. + ( cd $ROOT/install ; rm -f doinst.sh slack-* 1> /dev/null 2>&1 ) + rmdir $ROOT/install 1> /dev/null 2>&1 + fi + # If we used a scan directory, get rid of it: + if [ -d "$TMP/scan$$" ]; then + rm -rf "$TMP/scan$$" + fi + rm -f $TMP/tmpmsg$$ $TMP/reply$$ + if [ "$MODE" = "install" ]; then + echo "Package $(basename $package) installed." + echo + fi +done + +exit $EXITSTATUS |