#! /bin/bash
# vim: set filetype=bash:

# wipe-free: overwrite all free space in a filesystem with zeros

# Copyright (C) 2011-2012 by Brian Lindholm.  This file is part of the
# littleutils utility set.
#
# The wipe-free utility 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, or (at your option) any later version.
#
# The wipe-free utility 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
# the littleutils.  If not, see <https://www.gnu.org/licenses/>.

# set up traps
trap 'rm -f zero*_$$_*.dat ; exit 1' 1 2 3 13 15
trap 'rm -f zero*_$$_*.dat ; exit 0' 0

# get command-line options
MAXCHUNKS=4096
BS=4096
COUNT=262144
while getopts b:c:hm: opts
do
  case $opts in
    b) BS=${OPTARG} ;;
    c) COUNT=${OPTARG} ;;
    h) echo 'wipe-free 1.2.3'
       echo 'usage: wipe-free [-b block_size] [-c count] [-m max_chunks] [-h(elp)]'
       echo '  default: wipe-free -b 4096 -c 262144 -m 4096'
       exit 0 ;;
    m) MAXCHUNKS=${OPTARG} ;;
    *) echo 'wipe-free 1.2.3'
       echo 'usage: wipe-free [-b block_size] [-c count] [-m max_chunks] [-h(elp)]'
       echo '  default: wipe-free -b 4096 -c 262144 -m 4096'
       exit 1 ;;
  esac
done
shift `expr ${OPTIND} - 1`
TARGET=$(($BS*$COUNT))

# write files until max_chunk files are written or space is filled
DONE='no'
echo 'wipe-free message: beginning zero-file writes...'
for IDX in `seq -w 0001 ${MAXCHUNKS}` ; do
  if [ "$DONE" = 'no' ]; then
    TMPNAME=`tempname -d . -s .dat zero${IDX}_$$` || exit 99
    TIME0=`date +%s.%N`
    dd bs=${BS} count=${COUNT} if=/dev/zero of=${TMPNAME} >& /dev/null
    sync
    TIME1=`date +%s.%N`
    ELAPSED=`echo $TIME0 $TIME1 | awk '{printf "%.3f\n", $2 - $1}'`
    SIZE=`filesize "$TMPNAME"`
    echo "  file $IDX: $SIZE bytes in $ELAPSED seconds as $TMPNAME"
    if [ "$SIZE" -lt "$TARGET" ]; then
      echo 'wipe-free message: free space filled with zeros'
      DONE='yes'
    fi
  fi
done

# report on final results and remove space-filling zero files
if [ "$DONE" = 'no' ]; then
  echo 'wipe-free warning: free space possibly not filled'
fi
echo 'wipe-free message: deleting zero files'
rm -f zero*_$$_*.dat
