#!/bin/sh

   #########################################################
  # Written Nov 13, 2007 and released under the GNU/GPLv2 ##
 # (c) Jeff Schroeder (jeffschroeder@computer.org)       # #
#########################################################  #
#                                                       #  #
# restoreperms - restore permissions and fix ownership  #  #
#                on changed files from info in the rpm  #  #
#                database. Uses / Abuses rpm -V feature #  #
#                                                       # # 
##########################################################

# Idea inspired from a blog posting from Russell Coker
# http://etbe.coker.com.au/2007/11/13/restorecon-equivalent-for-unix-permissions/

usage() {
cat << EOF >&2
Usage: $0 -p rpmpackagename <options>
       -f   fix the permissions and file ownership back to what they
            should be if anything has changed
       -n   dry-run mode. Don't actually do anything
       -l   list the permissions on every file in a package from the rpmdb
       -c   checks the permissions and ownership on every file against the
            same information in the rpm database. Displays any discrepancies
EOF
exit 1
}

while getopts 'lfncp:' opt 2>/dev/null; do
    case "$opt" in
        l)    LIST=true ;;
        p)    PACKAGE="$OPTARG" ;;
        f)    FIX=true ;;
        n)    DRYRUN=true ;;
        c)    COMPARE=true ;;
        *)    usage ;;
    esac
done

### Lets do some sanity checks

# If called with 0 arguments
test -z "$*" && usage

# Is the package even installed?
if (! /bin/rpm --quiet -q "$PACKAGE"); then
    echo "'${PACKAGE}' is not installed" >&2
    usage
fi

if [ -z "$LIST" -a -z "$FIX" -a -z "$COMPARE" ]; then
    echo "Nothing to do..." >&2
    usage
fi

if (! [ "$LIST" ] && /bin/rpm --quiet -V "$PACKAGE"); then
    echo "Nothing wrong with '${PACKAGE}'"
    exit 0
fi

# -n option. Same as rsync shorthand
if [ "$DRYRUN" = "true" ]; then
    RPM="echo /bin/rpm"
else
    RPM=/bin/rpm
fi

# -l option
if [ "$LIST" = "true" -a ! "$COMPARE" ]; then
    (echo "Listing of proper file permissions and ownership for '${PACKAGE}':"; \
    /bin/rpm -q --qf '[%-15{FILEMODES:perms} %-9{FILEUSERNAME} %-9{FILEGROUPNAME} %{FILENAMES}\n]' $PACKAGE)
    exit 0
fi

# -c option
if [ "$COMPARE" = "true" ]; then
    # Put this all in a subshell so we can pipe it all to less
    (
    echo "These files in '${PACKAGE}' have incorrect permissions or ownership:"

    # This is the magic that lets you seperate on newlines for the rpm --qf ... command
    IFS="
"
    # rpm doesn't have a perfect printf implementation so fudge a little to make it all match up with awk
    for properperms in `/bin/rpm -q --qf '[%-15{FILEMODES:perms} %-9{FILEUSERNAME} %-9{FILEGROUPNAME} %{FILENAMES}\n]' $PACKAGE`; do
        file=$(echo $properperms | awk '{print $NF}')
        realperms=$(ls -Al $file | awk '{printf "%-15s %-10s%-10s%s\n", $1, $3, $4, $NF }')
        if [ "$realperms" != "$properperms" ]; then
            echo "Current Info:      $realperms"
            echo "Proper  Info:      $properperms"
        fi
    done )
fi

# -f option to fix changed files permissions and ownership
if [ "$FIX" = "true" ]; then
status=$(/bin/rpm -V $PACKAGE 2>&1 | awk '{print $1}' | grep -o '[A-Z]')
for opt in $status; do
    case "$opt" in
        M)
            $RPM --setperms $PACKAGE
        ;;
        U|G)
            # No point in setting them twice if the user and group are
            # both messed up. Be all intelligent and do it only once
            if [ "$PERMS" != "fixed" ]; then
                $RPM --setugids $PACKAGE && PERMS=fixed
            fi
        ;;
    esac
done
fi
