#!/usr/bin/env bash
#
#   prtreverse - create a crux package from files already installed
#                on the hard disk.
#
#   Copyright (c) 2003 by Simone Rota                  <sip@varlock.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 2 of the License, or     *
#   * (at your option) any later version.                                   *
#   *                                                                       *
#   *************************************************************************
#
#   **** USE AT YOUR OWN RISK ****
#

VERSION="0.2"

info() {
    echo "=======> $1"
}

note() {
    echo "=======> NOTE: $1"
}

error() {
    echo "=======> ERROR: $1"
    exit 1
}

usage() {
    echo "Usage: prtreverse [-r] [-k] [-o] [-p] [-f] <path>"
    exit 1
}

showversion() {
    echo "prtreverse" $VERSION
    echo "(c) 2003 by Simone Rota"
    echo "This program is distributed under the GNU GPL license"
}

interrupted() {
    echo "=======> operation interrupted."
    exit 1
}

checkparams() {
# Do some test on given parameters.
    [ "$prtdir" ] || usage

    [ -d "$prtdir" ] || { echo "'$prtdir': directory not found"; exit 1; }

    [ -f "$prtdir"/Pkgfile ] || { echo "no Pkgfile found in $prtdir. Skipping."; \
        exit 1; }

    [ -f "$prtdir"/.footprint ] || { echo "no .footprint found in $prtdir. Skipping."; \
        exit 1; }
}

getoptions () {
# Name says it all.
    while getopts rhvkfpo opt; do
      case "$opt" in
        r) userejected=1;;
	k) keepworking=1;;
	f) forcecreation=1;;
	o) leaveowner=1;;
	p) leaveperms=1;;
	h) usage ;;
	v) showversion
	   exit 0
	   ;;
        \?) usage ;;
      esac
    done
    shift $((OPTIND - 1))
    prtdir="$1"
}

adjustperms(){
# changes file permissions according to given string
# (taken from footprint)
    chmod $(tonum "$2") "reverse/$1"
}

adjustowner(){
# changes file user/group according to given string
# (taken from footprint)
    chown "${2/\//:}" "reverse/$1"
}

tonum() {
# change rxwrxwrxw permission format with
# numeric one (777). 
# I know, this code sucks.
    us=0
    gr=0
    ot=0
    str=$(echo "$1" | tr "rwx-" "4210")
	
    for i in 0 1 2; do
	((us=us+${str:$i:1}))
    done
    for i in 3 4 5; do
	((gr=gr+${str:$i:1}))
    done
    for i in 6 7 8; do
	((ot=ot+${str:$i:1}))
    done
	
    echo "$us$gr$ot"
}

createpkg(){
# create tarred package
(cd reverse && info "Creating $PKGTAR" && tar cfz ../"$PKGTAR" -- *)
}

###################################################
# Main
###################################################

main() {
trap "interrupted" SIGHUP SIGINT SIGQUIT SIGTERM

[ $# -ge 1 ] || usage

userejected=0
keepworking=0
forcecreation=0
goterror=0
leaveowner=0
leaveperms=0

getoptions "$@"
checkparams "$@"

# remove existing working directory
if [ -d "$prtdir"/reverse ]; then
    rm -rf "$prtdir"/reverse
fi

# make working directory and initialize Pkgfile vars
mkdir -p "$prtdir"/reverse
. "$prtdir"/Pkgfile
if [ -f /etc/pkgmk.conf ]; then
	PKGMK_COMPRESSION_MODE=$(. /etc/pkgmk.conf && echo "$PKGMK_COMPRESSION_MODE")
else
	eval $(grep "^\s*PKGMK_COMPRESSION_MODE=" /usr/bin/pkgmk)
fi
[ "$PKGMK_COMPRESSION_MODE" ] || PKGMK_COMPRESSION_MODE="gz"
PKGTAR="${name}#${version}-${release}.pkg.tar.$PKGMK_COMPRESSION_MODE"

cd "$prtdir" || { echo "Cannot cd to $prtdir"; exit 1; }

# package already exists, exit if not in force method
[ -f "$PKGTAR" ] && [ $forcecreation = 0 ] && \
	{ echo "$PKGTAR" exists, skipping.; exit 1; }

# the main loop to read entries in .footprint
# and copy files to the <path>/reverse directory.
# Could be implemented better.
info "Copying files..."
while read -r f; do
    [ -e "/$f" ] || [ $forcecreation = 1 ] || error "/$f does not seem to be installed!"
		
    [ -d "/$f" ] && mkdir -p reverse/"$f"
    if [ ! -d "/$f" ] && [ -e "/$f" ]; then
    	cp -p -R "/$f" "reverse/$f" || goterror=1
	[ $userejected = 1 ] && [ -f "/var/lib/pkg/rejected/$f" ] && \
	    { note "Using /$f from rejected dir";
       		cp -p -R -f "/var/lib/pkg/rejected/$f" "reverse/$f" || goterror=1; }
    fi
done < <(grep -v -f <(awk '($1 == "INSTALL") && ($3 == "NO") {print $2}' /etc/pkgadd.conf) \
	<(cut -f3 .footprint | sed 's/ ->.*//; s/ (EMPTY)//'))

# now we create the package
if [ $goterror = 0 ] || [ $forcecreation = 1 ]; then
    (( leaveperms + leaveowner == 0 )) || note "Adjusting owner/group/permissions"
    while IFS=$'\t' read -r fperms fowner fname; do
	[ $leaveperms = 1 ] || [ ! -e "reverse/$fname" ] || adjustperms "$fname" "${fperms:1:9}"
	[ $leaveowner = 1 ] || [ ! -e "reverse/$fname" ] || adjustowner "$fname" "$fowner"
    done < <(sed 's/ ->.*//; s/ (EMPTY)//' .footprint)
	
    # finally create the package
    createpkg

    # removes the working directory
    if [ ! $keepworking = 1 ]; then
	info "Removing working dir"
        rm -r reverse
    fi
fi
}

main "$@"
