#!/bin/bash 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..." checkconflict checkpkgconflict fi # create lock file prevent simultaneous install package spkglock # source .install file inside package if [ $(tar -tf "$PKGNAME" | grep -w ^".pkginstall") ]; 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}." pushd $ROOT_DIR while IFS=' ' read -r line; do rm_silent "$line" || rmdir_silent --ignore-fail-on-non-empty "$line" done < <(tar -tf "$PKGNAME" --exclude=.pkginfo --exclude=.pkginstall --exclude=.pkgreadme ${excludefile[@]} | tac) popd spkglock exit 1 fi 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}." 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 if [ -f $INDEX_DIR/$name/readme ]; then msg "This package has ${color_green}readme${color_reset}" fi # remove lock file spkglock } 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 [ -f "$line" ] || [ -L "$line" ]; then fileconflict+=(${line}) fi popd done < <(tar -tf "$PKGNAME" --exclude=.pkginfo --exclude=.pkginstall --exclude=.pkgreadme ${excludefile[@]}) 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 } updateinfopages() { pushd /usr/share/info if [ -f dir ]; then rm dir fi for f in *; do install-info $f dir 2>/dev/null done popd } upgradepkg() { if [ ! "$NO_BACKUP" ]; then backupconf fi ROOT="$ROOT" removepkg $name -id --no-preremove --no-postremove --no-orphan-check NO_PREINSTALL=yes NO_POSTINSTALL=yes } backupconf() { pushd $ROOT_DIR for bkp in ${backup[@]}; do if [ -e $bkp ]; then msg2 "Backup ${color_purple}$bkp${color_reset}" cp $bkp $BACKUP_DIR DONE_BACKUP=yes fi done popd } restoreconf() { if [ "$DONE_BACKUP" ]; then pushd $ROOT_DIR for b in ${backup[@]}; 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 } 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 -e "Usage:" echo -e "\t`basename $0` packagefile < options >" echo -e "" echo -e "Example:" echo -e "\t`basename $0` foobar-1.0-1.spkg.txz -u --no-backup this will upgrade package foobar-1.0-1 without \n\t\t\t\t\t\t\t\tbackup its old configuration file" echo -e "" echo -e "Options:" echo -e "\t-u,\t--upgrade update package" echo -e "\t-r,\t--reinstall reinstall package" echo -e "\t-id,\t--ignore-dependency ignore dependency" echo -e "\t-ic,\t--ignore-conflict ignore conflict when installing package" echo -e "\t-v,\t--verbose verbose install process" echo -e "\t\t--no-preinstall skip preinstall script when build/install package" echo -e "\t\t--no-postinstall skip postinstall script after install package" } 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-preupgrade) NO_POSTUPGRADE=yes ;; --no-backup) NO_BACKUP=yes ;; --no-color) NO_COLOR=yes ;; --no-orphan-check) NO_ORPHAN_CHECK=yes ;; *.spkg.txz) [ -f $1 ] && PKGNAME=$1 || msg "${color_red}$1${color_reset} not exist." ;; --root) if [ ! "$2" ]; then msg "Option '$1' require an argument (root path)." exit 1 fi ROOT="$2" shift ;; -h|--help) SHOW_HELP=yes ;; *) msg "Invalid option!" exit 1 ;; esac shift done } main() { . /usr/share/scratchpkg/functions || exit 1 parse_options "$@" ### DISABLE COLOR ### if [ "$NO_COLOR" ]; then nocolor fi loadconfigfile # CHANGE ROOT PATH ### if [ "$ROOT" ]; then ROOT_DIR="$ROOT" INDEX_DIR="$ROOT_DIR/$INDEX_DIR" BACKUP_DIR="$ROOT_DIR/$BACKUP_DIR" REJECTED_DIR="$ROOT_DIR/$REJECTED_DIR" fi ### SHOW HELP ### if [ "$SHOW_HELP" ]; then help exit 0 fi ### CHECK FOR ROOT ACCESS ### if [ "$UID" != "0" ]; then msgerr "${color_red}Installing package need root access!${color_reset}" exit 1 fi check_directory ### 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 ### NOT STATED PACKAGE ### if [ -z $PKGNAME ]; then msgerr "${color_red}Please state the package to install.${color_reset}" 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 upgradepkg fi ### INSTALL PACKAGE INTO SYSTEM ### installpkg # check orphan package (usually makedepends package) if [ ! "$NO_ORPHAN_CHECK" ]; then checkneworphan fi ### RUN THINGS THAT NEED UPDATE AFTER INSTALL PACKAGE ### updatesystemdb ### UPDATE INFO PAGES ### if [ "$(grep -w usr/share/info/ $INDEX_DIR/$name/.files)" ]; then updateinfopages fi exit 0 } main "$@"