#!/bin/bash # # scratchpkg # # Copyright (c) 2018 by Emmett1 (emmett1.2miligrams@gmail.com) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # trap "interrupted" SIGHUP SIGINT SIGQUIT SIGTERM export LC_ALL=C interrupted() { echo ret 1 } msg() { echo -e "==> $1" } msg2() { echo -e " -> $1" } msgerr() { echo -e "==> ERROR: $1" } msgwarn() { echo -e "==> WARNING: $1" } runremovehooks() { if [ "${#runthishook[@]}" -gt 0 ]; then for hook in ${runthishook[@]}; 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 . $hook if [ "`type -t exechook`" = "function" ]; then exechook fi fi unset description operation target unset -f exechook done fi } runpreremovehooks() { for hook in $HOOK_DIR/*.hook; do [ -f $hook ] || continue operation=$(cat "$hook" | grep ^"# operation" | sed 's/\://' | cut -d ' ' -f 3-) target=$(cat "$hook" | grep ^"# target" | sed 's/\://' | cut -d ' ' -f 3-) if [ "$(echo $operation | grep -w "remove" )" ]; then if [ "$(grep $target $INDEX_DIR/$1/.files)" ]; then runthishook+=($hook) fi fi unset operation target done } help() { cat << EOF Usage: $(basename $0) [ ] Options: -h, --help show this help message --no-preremove don't run pre-remove script --no-postremove don't run post-remove script --no-hook skip executing hook --root= remove package from custom root directory EOF } extract_opt() { for opt in $@; do case $opt in --*) OPTS+=($opt) ;; -*) for (( i=1; i<${#opt}; i++ )); do OPTS+=(-${opt:$i:1}); done ;; *) OPTS+=($opt) ;; esac done echo ${OPTS[@]} } parse_opts() { if [ -z "$1" ]; then SHOWHELP=yes else while [ "$1" ]; do case $1 in -h | --help) SHOWHELP=yes ;; -v | --verbose) VERBOSE_REMOVE=yes ;; --no-preremove) NO_PREREMOVE=yes ;; --no-postremove) NO_POSTREMOVE=yes ;; --no-hook) NOHOOK=yes ;; --root=*) ROOT="${1#*=}" ;; -*) msg "Invalid option: ($1)"; exit 1 ;; *) RMNAME=$1 ;; esac shift done fi } ret() { # remove lock file on exit rm -f $LOCK_FILE exit $1 } isinstalled() { if [ -s $INDEX_DIR/$1/.pkginfo ] && [[ $(grep $1 $INDEX_DIR/$1/.pkginfo) ]]; then return 0 else return 1 fi } parse_opts $(extract_opt $@) INDEX_DIR="$ROOT/var/lib/scratchpkg/index" PKGDEL_DIR="$ROOT/var/lib/scratchpkg" LOCK_FILE="$PKGDEL_DIR/spkg.lock" HOOK_DIR="/etc/hooks" # show help page if [ "$SHOWHELP" ] || [ -z "$RMNAME" ]; then help ret 0 fi # check for lock file if [ -f $LOCK_FILE ]; then msgerr "Cant install/remove package simultaneously." msgerr "remove '$LOCK_FILE' if no install/remove package process running." exit 1 else touch $LOCK_FILE if [ "$?" != 0 ]; then msgerr "Cant create lock file in '$LOCK_FILE'" exit 1 fi fi if ! isinstalled $RMNAME; then msgerr "Package '$RMNAME' not installed." ret 1 fi # check for root access if [ "$UID" != "0" ]; then echo "Installing package need root access!" ret 1 fi name=$(cat $INDEX_DIR/$RMNAME/.pkginfo | grep ^name | cut -d " " -f3-) version=$(cat $INDEX_DIR/$RMNAME/.pkginfo | grep ^version | cut -d " " -f3-) release=$(cat $INDEX_DIR/$RMNAME/.pkginfo | grep ^release | cut -d " " -f3-) if [ -z $name ] && [ -z $version ] && [ -z $release ]; then msgerr "Package '$RMNAME' not installed but exist in database." ret 1 fi echo "Removing '$name-$version-$release'..." # source .install script if [ "$ROOT" = "" ]; then if [ -f $INDEX_DIR/$name/.pkginstall ]; then source $INDEX_DIR/$name/.pkginstall fi fi if [ ! "$NO_PREREMOVE" ]; then if [ "`type -t pre_remove`" = "function" ]; then pre_remove "$version" &>/dev/null fi fi if [ "$ROOT" = "" ] && [ "$NOHOOK" != "yes" ]; then runpreremovehooks $name &>/dev/null fi if [ -f "$INDEX_DIR/$name/.bkpfiles" ]; then while IFS=' ' read -r line; do if [ -e "$ROOT/$line" ] || [ -L "$ROOT/$line" ]; then [ "$VERBOSE_REMOVE" = yes ] && echo "<<< $line" rm "$ROOT/$line" fi done < <(tac $INDEX_DIR/$name/.bkpfiles) fi while IFS=' ' read -r line; do if [ -e "$ROOT/$line" ] || [ -L "$ROOT/$line" ]; then [ "$VERBOSE_REMOVE" = yes ] && echo "<<< $line" rm "$ROOT/$line" fi done < <(tac $INDEX_DIR/$name/.files | grep -v '/$') while IFS=' ' read -r line; do if [ ! "$(grep -R --exclude-dir="$name" -w "$line" "$INDEX_DIR")" ]; then if [ -d "$ROOT/$line" ]; then [ "$VERBOSE_REMOVE" = yes ] && echo "<<< $line" rmdir "$ROOT/$line" fi fi done < <(tac $INDEX_DIR/$name/.files | grep '/$') if [ ! "$NO_POSTREMOVE" ]; then if [ "`type -t post_remove`" = "function" ]; then post_remove "$version" &>/dev/null fi fi rm -rf $INDEX_DIR/$name if [ "$ROOT" = "" ] && [ "$NOHOOK" != "yes" ]; then runremovehooks fi # running ldconfig if [ -x /sbin/ldconfig ]; then /sbin/ldconfig -r $ROOT/ fi ret 0