#!/bin/bash export LC_ALL=C . /usr/share/scratchpkg/functions || exit 1 spkglock() { if [ ! -f /tmp/spkg.lock ]; then touch /tmp/spkg.lock else rm /tmp/spkg.lock fi } installpkg() { msg "Installing ${color_green}$packagename${color_reset}..." # noextract file into system for noextr in ${NO_EXTRACT[@]}; do excludefile+=(--exclude=$noextr) done #ignore dependency check if [ ! "$IGNORE_DEP" ]; then msg2 "Checking package dependencies..." checkdeps fi #ignore conflict if [ ! "$IGNORE_CONFLICT" ]; then msg2 "Checking package/file conflict..." if [ "$UPGRADE_PKG" ] || [ "$REINSTALL_PKG" ]; then upcheckconflict else checkconflict fi checkpkgconflict fi # create lock file prevent simultaneous install package spkglock # backup conf as set in spkgbuld if upgrade or reinstall package if [ "$UPGRADE_PKG" ] || [ "$REINSTALL_PKG" ]; then if [ ! "$NO_BACKUP" ]; then backupconf fi fi # source .install file inside package if [ $(tar -tf "$PKGNAME" | grep -x ".pkginstall") ] && [ ! "$REINSTALL_PKG" ]; then source <(tar -xf "$PKGNAME" .pkginstall -O) fi # run preinstall script if no --no-preinstall flag and not upgrade package if [ ! "$NO_PREINSTALL" ] && [ ! "$UPGRADE_PKG" ]; then run_preinstall fi # run preupgrade script if package upgrade if [ "$UPGRADE_PKG" ] && [ ! "$NO_PREUPGRADE" ]; then run_preupgrade fi #installing package into system msg2 "Extracting package..." if [ "$VERBOSE_INSTALL" ]; then tar --keep-directory-symlink --no-overwrite-dir -p -x -v -f $PKGNAME -C $ROOT_DIR --exclude=.pkginfo --exclude=.pkginstall --exclude=.pkgreadme ${excludefile[@]} else tar --keep-directory-symlink --no-overwrite-dir -p -x -f $PKGNAME -C $ROOT_DIR --exclude=.pkginfo --exclude=.pkginstall --exclude=.pkgreadme ${excludefile[@]} fi if [ $? != 0 ]; then msgerr "Failed install ${color_red}$packagename${color_reset}." while IFS=' ' read -r line; do pushd $ROOT_DIR rm_silent "$line" || rmdir_silent --ignore-fail-on-non-empty "$line" popd done < <(tar -tf "$PKGNAME" --exclude=.pkginfo --exclude=.pkginstall --exclude=.pkgreadme ${excludefile[@]} | tac) spkglock exit 1 fi if [ "$UPGRADE_PKG" ] || [ "$REINSTALL_PKG" ]; then removeoldfiles fi registerpkg if [ ! "$NO_POSTINSTALL" ] && [ ! "$UPGRADE_PKG" ]; then run_postinstall fi if [ "$UPGRADE_PKG" ] && [ ! "$NO_POSTUPGRADE" ]; then run_postupgrade fi restoreconf case $PREINSTALL_STATUS in OK) msg "preinstall : ${color_green}OK${color_reset}" ;; KO) msg "preinstall : ${color_red}FAIL${color_reset}" ;; esac case $PREUPGRADE_STATUS in OK) msg "preupgrade : ${color_green}OK${color_reset}" ;; KO) msg "preupgrade : ${color_red}FAIL${color_reset}" ;; esac case $POSTINSTALL_STATUS in OK) msg "postinstall : ${color_green}OK${color_reset}" ;; KO) msg "postinstall : ${color_red}FAIL${color_reset}" ;; esac case $POSTUPGRADE_STATUS in OK) msg "postupgrade : ${color_green}OK${color_reset}" ;; KO) msg "postupgrade : ${color_red}FAIL${color_reset}" ;; esac runhooks if [ -f $INDEX_DIR/$name/.pkgreadme ]; then msg "This package has ${color_green}readme${color_reset}" fi # remove lock file spkglock } removeoldfiles() { TMP_TARLIST="/tmp/$name.tarlist.spkg" tar -tf "$PKGNAME" --exclude=.pkginfo --exclude=.pkginstall --exclude=.pkgreadme ${excludefile[@]} > $TMP_TARLIST msg2 "Removing old files & dirs..." grep -v '/$' $INDEX_DIR/$name/.files | while read line; do if [ ! "$(grep -Fx "$line" $TMP_TARLIST)" ]; then pushd $ROOT_DIR if [ "$VERBOSE_INSTALL" = "yes" ]; then rm_silent "$line" && echo "$line" && OLDFILEREMOVE=yes || msgwarn "Failed remove $line" else rm_silent "$line" && OLDFILEREMOVE=yes || msgwarn "Failed remove $line" fi popd fi done while IFS=' ' read -r line; do if [ ! "$(tac $TMP_TARLIST | grep -x "$line")" ] && [ ! "$(grep -Rx --exclude-dir="$name" -w "$line" "$INDEX_DIR")" ]; then pushd $ROOT_DIR if [ "$VERBOSE_INSTALL" = "yes" ]; then rmdir_silent "$line" && echo "$line" || msgwarn "Failed remove $line" else rmdir_silent "$line" || msgwarn "Failed remove $line" fi popd fi done < <(tac $INDEX_DIR/$name/.files | grep '/$') rm $TMP_TARLIST } registerpkg() { [ ! -d $INDEX_DIR/$name ] && mkdir $INDEX_DIR/$name tar -x -f $PKGNAME -C $INDEX_DIR/$name .pkginfo tar -t -f $PKGNAME --exclude=.pkginfo --exclude=.pkginstall --exclude=.pkgreadme ${excludefile[@]} > $INDEX_DIR/$name/.files tar -x -f $PKGNAME -C $INDEX_DIR/$name .pkginstall .pkgreadme >/dev/null 2>&1 msg "Successfully install ${color_green}$packagename${color_reset}." } checkdeps() { for dep in ${depends[@]}; do if [ ! -d $INDEX_DIR/$dep ]; then MSGDEP+=($dep) fi done if [ "${#MSGDEP[@]}" -gt 0 ]; then msg "Missing dependencies:" for msdp in ${MSGDEP[@]}; do msg2 "$msdp" done exit 1 fi } checkpkgconflict() { for pkg in ${conflict[@]}; do if [ -d $INDEX_DIR/$pkg ]; then msg "Conflict package!: ${color_yellow}$pkg${color_reset}" PKG_CONFLICT=yes fi done if [ "$PKG_CONFLICT" ]; then exit 1 fi } checkconflict() { while IFS=' ' read -r line; do pushd $ROOT_DIR if [ -e "$line" ]; then fileconflict+=(${line}) fi popd done < <(tar -tf "$PKGNAME" --exclude=.pkginfo --exclude=.pkginstall --exclude=.pkgreadme ${excludefile[@]} | grep -v '/$') if [ "${#fileconflict[@]}" -gt 0 ]; then msgerr "File conflict found:" for fc in ${fileconflict[@]}; do msg2 "$fc" done exit 1 fi } upcheckconflict() { while IFS=' ' read -r line; do pushd $ROOT_DIR if [ -e "$line" ]; then if [ ! "$(grep -Fx "$line" "$INDEX_DIR/$name/.files")" ]; then fileconflict+=(${line}) fi fi popd done < <(tar -tf "$PKGNAME" --exclude=.pkginfo --exclude=.pkginstall --exclude=.pkgreadme ${excludefile[@]} | grep -v '/$') if [ "${#fileconflict[@]}" -gt 0 ]; then msgerr "File conflict found:" for fc in ${fileconflict[@]}; do msg2 "$fc" done exit 1 fi } getname() { name=$(tar xf $PKGNAME .pkginfo -O | grep ^name | cut -d " " -f3) version=$(tar xf $PKGNAME .pkginfo -O | grep ^version | cut -d " " -f3) release=$(tar xf $PKGNAME .pkginfo -O | grep ^release | cut -d " " -f3) depends=$(tar xf $PKGNAME .pkginfo -O | grep ^depends | cut -d " " -f3-) makedepends=$(tar xf $PKGNAME .pkginfo -O | grep ^makedepends | cut -d " " -f3-) conflict=$(tar xf $PKGNAME .pkginfo -O | grep ^conflict | cut -d " " -f3-) packagename=$name-$version-$release } getoldname() { iname=$(cat $INDEX_DIR/$name/.pkginfo | grep ^name | cut -d " " -f3) iversion=$(cat $INDEX_DIR/$name/.pkginfo | grep ^version | cut -d " " -f3) irelease=$(cat $INDEX_DIR/$name/.pkginfo | grep ^release | cut -d " " -f3) backup=$(cat $INDEX_DIR/$name/.pkginfo | grep ^backup | cut -d " " -f3-) ipackagename=$iname-$iversion-$irelease } backupconf() { pushd $ROOT_DIR for bkp in ${backup[@]}; do if [ -e $bkp ]; then msg2 "Backup ${color_purple}$bkp${color_reset}" cp $bkp $BACKUP_DIR FILEBACKUP+=($bkp) fi done popd } restoreconf() { if [ "${#FILEBACKUP[@]}" -gt 0 ]; then pushd $ROOT_DIR for b in ${FILEBACKUP[@]}; do if [ -e $b ]; then mkdir -p $REJECTED_DIR/${b%/*} mv $b $REJECTED_DIR/$b msg2 "Restore ${color_purple}$b${color_reset}" mv $BACKUP_DIR/$(basename ${b}) $b fi done popd fi } checkoutdate() { if [ $packagename = $ipackagename ]; then msg "Package ${color_green}$packagename${color_reset} is up-to-date." exit 1 fi } check_directory() { for dir in $INDEX_DIR $BACKUP_DIR $REJECTED_DIR; do if [ ! -d $dir ]; then msgwarn "Directory ${color_yellow}$dir${color_reset} not exist." DIR_ERROR=yes elif [ ! -w $dir ]; then msgwarn "Directory ${color_yellow}$dir${color_reset} not writable." DIR_ERROR=yes elif [ ! -x $dir ] || [ ! -r $1 ]; then msgwarn "Directory ${color_yellow}$dir${color_reset} not readable." DIR_ERROR=yes fi done [ "$DIR_ERROR" ] && exit 1 } run_preinstall() { if [ "`type -t pre_install`" = "function" ]; then msg "Running preinstall script..." pre_install "$version" && PREINSTALL_STATUS=OK || PREINSTALL_STATUS=KO fi } run_postinstall() { if [ "`type -t post_install`" = "function" ]; then msg "Running postinstall script..." post_install "$version" && POSTINSTALL_STATUS=OK || POSTINSTALL_STATUS=KO fi } run_preupgrade() { if [ "`type -t pre_upgrade`" = "function" ]; then msg "Running preupgrade script..." pre_upgrade "$version" "$iversion" && PREUPGRADE_STATUS=OK || PREUPGRADE_STATUS=KO fi } run_postupgrade() { if [ "`type -t post_upgrade`" = "function" ]; then msg "Running postupgrade script..." post_upgrade "$version" "$iversion" && POSTUPGRADE_STATUS=OK || POSTUPGRADE_STATUS=KO fi } checkneworphan() { for md in ${makedepends[@]}; do removemakedepends $md done if [ "${#saferemove[@]}" -gt 0 ]; then msg "Package safe for remove:" for saferem in ${saferemove[@]}; do msg2 "$saferem" done fi } runhooks() { if [ "$UPGRADE_PKG" ]; then opr=upgrade else opr=install fi if [ "$(ls $HOOK_DIR/*.hook 2>/dev/null)" ]; then for hook in $(ls $HOOK_DIR/*.hook); do description=$(cat "$hook" | grep ^"# description" | sed 's/\://' | cut -d ' ' -f 3-) operation=$(cat "$hook" | grep ^"# operation" | sed 's/\://' | cut -d ' ' -f 3-) target=$(cat "$hook" | grep ^"# target" | sed 's/\://' | cut -d ' ' -f 3-) if [ -n "$description" ] && [ -n "$operation" ] && [ -n "$target" ]; then if [ "$(echo $operation | grep -w "$opr" )" ]; then if [ "$(grep -E $target $INDEX_DIR/$name/.files)" ]; then msg "$description" . $hook if [ "`type -t exechook`" = "function" ]; then exechook fi fi fi fi unset description operation target done fi } removemakedepends() { ORPHAN="yes" for all_installed in $(ls $INDEX_DIR); do depend=$(cat $INDEX_DIR/$all_installed/.pkginfo | grep ^depends | cut -d " " -f3-) for dep in ${depend[@]}; do if [ $dep = $1 ]; then ORPHAN="no" fi done done [ "$ORPHAN" = "yes" ] && [ -d $INDEX_DIR/$1 ] && saferemove+=($1) } help() { echo "Usage:" echo " $(basename $0) package.spkg.txz [ ]" echo echo "Options:" echo " -u, --upgrade update package" echo " -r, --reinstall reinstall package" echo " -id, --ignore-dependency skip dependency check" echo " -ic, --ignore-conflict ignore conflict when installing package" echo " -v, --verbose verbose install process" echo " --no-preinstall don't run pre-install script" echo " --no-postinstall don't run post-install script" echo " --no-preupgrade don't run pre-upgrade script" echo " --no-postupgrade don't run post-upgrade script" echo " --no-backup skip backup when upgrading package" echo " --no-orphan-check skip orphaned package check after install package" echo " --no-color disable colour for output" echo " -h, --help show this help message" echo echo "Example:" echo " $(basename $0) foobar-1.0-1.spkg.txz -u --no-backup upgrade package foobar-1.0-1 without backup" echo " its old configuration files" } parse_options() { while [ "$1" ]; do case $1 in -u|--upgrade) UPGRADE_PKG=yes ;; -r|--reinstall) REINSTALL_PKG=yes ;; -id|--ignore-dependency) IGNORE_DEP=yes ;; -ic|--ignore-conflict) IGNORE_CONFLICT=yes ;; -v|--verbose) VERBOSE_INSTALL=yes ;; --no-preinstall) NO_PREINSTALL=yes ;; --no-postinstall) NO_POSTINSTALL=yes ;; --no-preupgrade) NO_PREUPGRADE=yes ;; --no-postupgrade) NO_POSTUPGRADE=yes ;; --no-backup) NO_BACKUP=yes ;; --no-color) NO_COLOR=yes ;; --no-orphan-check) NO_ORPHAN_CHECK=yes ;; *.spkg.txz) PKGNAME="$1" ;; -h|--help) SHOW_HELP=yes ;; *) msg "Invalid option!" exit 1 ;; esac shift done } main() { parse_options "$@" ### DISABLE COLOR ### if [ "$NO_COLOR" ]; then nocolor fi ### SHOW HELP ### if [ "$SHOW_HELP" ]; then help exit 0 fi ### NOT STATED PACKAGE ### if [ -z $PKGNAME ]; then msgerr "Please state the package to install." exit 1 fi ### CHECK EXISTANT OF PACKAGE FILE ### if [ ! -f $PKGNAME ]; then msgerr "Package ${color_red}$1${color_reset} not exist!" exit 1 fi ### CHECK FOR ROOT ACCESS ### needroot "Installing package" ### CHECK DIRECTORY ### checkdirexist "$INDEX_DIR" "$BACKUP_DIR" "$REJECTED_DIR" checkdirwrite "$INDEX_DIR" "$BACKUP_DIR" "$REJECTED_DIR" checkdirread "$INDEX_DIR" "$BACKUP_DIR" "$REJECTED_DIR" ### CHECK FOR LOCK FILE ### if [ -f /tmp/spkg.lock ]; then msgerr "Cant install/remove package simultaneously." msgerr "remove ${color_yellow}/tmp/spkg.lock${color_reset} if no install/remove package process running." exit 1 fi ### GET NAME, VERSION, RELEASE FROM PACKAGE ### getname # get info from package ### IF INSTALLED & NO UPGRADE & NO REINSTALL ### if [ -d $INDEX_DIR/$name ] && [ ! "$UPGRADE_PKG" ] && [ ! "$REINSTALL_PKG" ]; then getoldname # get info from package index msg "Package ${color_green}$ipackagename${color_reset} already installed." exit 0 fi ### IF UPGRADE OR REINSTALL PACKAGE ### if [ "$UPGRADE_PKG" ] || [ "$REINSTALL_PKG" ]; then if [ ! -d $INDEX_DIR/$name ]; then msg "Package ${color_red}$name${color_reset} is not installed." exit 1 fi getoldname # UPGRADE PACKAGE if [ "$UPGRADE_PKG" ]; then checkoutdate msg "Upgrading package: ${color_yellow}$ipackagename${color_reset} -> ${color_green}$packagename${color_reset}" # REINSTALL PACKAGE elif [ "$REINSTALL_PKG" ]; then msg "Reinstall package ${color_green}$packagename${color_reset}." fi fi ### INSTALL PACKAGE INTO SYSTEM ### installpkg # check orphan package (usually makedepends package) if [ ! "$NO_ORPHAN_CHECK" ]; then checkneworphan fi # msg2 "Running ldconfig..." if [ -x /sbin/ldconfig ]; then /sbin/ldconfig fi exit 0 } main "$@"