#!/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" } help() { cat << EOF Usage: $(basename $0) [ ] Options: -h, --help show this help message -v, --verbose print removed files --no-preremove don't run pre-remove script --no-postremove don't run post-remove script --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="-v" ;; --no-preremove) NO_PREREMOVE=yes ;; --no-postremove) NO_POSTREMOVE=yes ;; --root=*) ROOT_DIR="${1#*=}" ;; -*) msg "Invalid option: ($1)"; exit 1 ;; *) RMNAME=$1 ;; esac shift done fi } ret() { # remove lock file on exit rm -f $LOCK_FILE $reserve $dirs $remove $files exit $1 } isinstalled() { if [ -s $INDEX_DIR/$1/.pkginfo ] && grep -q $1 $INDEX_DIR/$1/.pkginfo; then return 0 else return 1 fi } parse_opts $(extract_opt $@) INDEX_DIR="$ROOT_DIR/var/lib/scratchpkg/index" LOCK_FILE="$ROOT_DIR/var/lib/scratchpkg/spkg.lock" # disable pre/post remove script when remove from custom root location if [ "$ROOT_DIR" != "" ]; then NO_PREREMOVE=yes NO_POSTREMOVE=yes fi # show help page if [ "$SHOWHELP" ] || [ -z "$RMNAME" ]; then help ret 0 fi # check for root access if [ "$UID" != "0" ]; then echo "Removing package need root access!" ret 1 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 name=$(grep ^name $INDEX_DIR/$RMNAME/.pkginfo | cut -d " " -f3-) version=$(grep ^version $INDEX_DIR/$RMNAME/.pkginfo | cut -d " " -f3-) release=$(grep ^release $INDEX_DIR/$RMNAME/.pkginfo | cut -d " " -f3-) if [ -z $name ] && [ -z $version ] && [ -z $release ]; then msgerr "Package '$RMNAME' not installed but exist in database." ret 1 fi # create list for reserve and remove (dirs and files) reserve=$(mktemp) || { msgerr "Failed create tmp files"; ret 1; } remove=$(mktemp) || { msgerr "Failed create tmp files"; ret 1; } dirs=$(mktemp) || { msgerr "Failed create tmp files"; ret 1; } files=$(mktemp) || { msgerr "Failed create tmp files"; ret 1; } grep '/$' $INDEX_DIR/*/.files | grep -v $INDEX_DIR/$name | awk -F : '{print $2}' | sort | uniq > $reserve grep '/$' $INDEX_DIR/$name/.files > $remove grep -Fxv -f $reserve $remove | tac > $dirs grep -v '/$' $INDEX_DIR/$name/.files | tac >> $files echo "remove: $name-$version-$release..." # pre-remove script if [ ! "$NO_PREREMOVE" ] && [ -f $INDEX_DIR/$name/.pkginstall ]; then pushd "$ROOT_DIR"/ >/dev/null sh $INDEX_DIR/$name/.pkginstall pre-remove "$version" popd >/dev/null fi # remove files and dirs pushd "$ROOT_DIR"/ >/dev/null [ -s $files ] && xargs -a $files -d'\n' rm $VERBOSE_REMOVE [ -s $dirs ] && xargs -a $dirs -d'\n' rmdir $VERBOSE_REMOVE popd >/dev/null rm -f $reserve $dirs $remove $files # post-remove script if [ ! "$NO_POSTREMOVE" ] && [ -f $INDEX_DIR/$name/.pkginstall ]; then pushd "$ROOT_DIR"/ >/dev/null sh $INDEX_DIR/$name/.pkginstall post-remove "$version" popd >/dev/null fi # remove from database rm -rf $INDEX_DIR/$name # running ldconfig if [ -x "$ROOT_DIR"/sbin/ldconfig ]; then "$ROOT_DIR"/sbin/ldconfig -r "$ROOT_DIR"/ fi ret 0