#!/bin/bash
# -----------------------------------------------------------------------------
# zzzwipe -- "securely" delete a file,
#             by overwriting it with randomness
# Copyright (C) 2003 Fabian "zzznowman" Pietsch <fabian@zzznowman.dyndns.org>
#
# Distributed under the GNU GPL (General Public Licence)
# zzzwipe 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.
#
# zzzwipe 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.
# -----------------------------------------------------------------------------
#
# Version 0.1.1 (2003-10-13)
#
# ChangeLog:
#   0.1.1  o Use sync(1) to flush kernel buffers
#
# TODO:  o Wipe whole inode FILE currently occupies in case it has been
#          shrinked before
#

BASENAME="`basename "$0"`"
ZWVERSION="0.1.1 (2003-10-13)"
ZWENTROPY="/dev/urandom"
ZWFORCE=""
ZWINT=""
ZWVERBOSE=""


zwfail() {
    [ -n "$*" ] && if [ "$1" == "usage" ]; then
        zwusage 1>&2
    else
        zwwarn "$@"
    fi
    exit 1
}

zwinfo() {
    echo "$BASENAME: $*"
}

zwusage() {
    echo -e "\
$BASENAME: usage: $0 [-fhi] FILES\n\
zzzwipe $ZWVERSION -- secure file deletion\n\
-f\tforce deletion\n\
-h\tdisplay this usage information\n\
-i\tinteractive: prompt for deletion"
}

zwwarn() {
    echo "$BASENAME: $*" 1>&2
}


# process command line options
while getopts "fhiv" ZWOPT; do
    case "$ZWOPT" in
    f)  ZWFORCE="${ZWFORCE}f";;
    i)  ZWINT="${ZWINT}i";;
    h)  zwusage; exit 0;;
    v)  ZWVERBOSE="${ZWVERBOSE}v";;
    *)  zwfail usage;;
    esac
done
#[ $(($# - $OPTIND)) -ge 0 ] || zwfail "no files given"
[ "$#" -ge "$OPTIND" ] || zwfail "no files given"

# process every file supplied
for FILE in "${@:$OPTIND}"; do
    # check for existence & whether we should really continue
    [ -f "$FILE" ] || {
        zwwarn "$FILE: no such file"
        continue
    }
    [ -n "$ZWINT" ] && {
        read -p "wipe (delete) $FILE? "
        case "$REPLY" in
        y|Y|j|J) ;;
        *) continue;;
        esac
    }

    # get FILE's size and overwrite it with randomness
    FILESIZE="`find "$FILE" -maxdepth 0 -printf %s`"
    FILERUNS=3
    [ -n "$ZWVERBOSE" ] \
      && zwinfo "wiping $FILE with $FILESIZE bytes of randomness ($FILERUNS times)"
    declare -i I="$FILERUNS"
    while [ "$I" -gt 0 ]; do
        dd if="$ZWENTROPY" of="$FILE" bs=1 count="$FILESIZE" 2>/dev/null \
          || zwwarn "$FILE: dd exited $?"
        sync
        I=I-1
    done
    
    # finally unlink file
    if [ -n "$ZWFORCE" -o -n "$ZWVERBOSE" ]; then
        rm -"${ZWFORCE}$ZWVERBOSE" "$FILE"
    else
        rm "$FILE"
    fi
done

