#! /bin/bash

# GPL (c) IVK 2022
# SWAPS defined in config file

CONFIG=/etc/swap_cleaner.conf
PNAME=${0##*\/}

MSG_HELP="Usage: \n
without arguments config file /etc/swap_cleaner.conf will be used. If file empty do nothing. \n
If config does not exist (main usage) it zeroing all from /proc/swaps \n
It is possible to use name of swap partition or swap file as argument (or \"list of arguments\") - \n
manually zeroing one or more parttions or files \n
Good instruction in Russian see at /usr/share/doc/swap_cleaner... \n"
MSG_START2CLEAN="Started to clean a"
MSG_START="Started to clean"
MSG_FROM="from"
MSG_AUTO="in auto mode"
MSG_NOTFILE_NOTDEV="not a file or block device, skip it"
MSG_NOTSWAP="not a swap device, skip it"
MSG_NOTHING="Nothing to do, exiting"
MSG_DONE="done"
MSG_ASDEV="as a block device"
MSG_ZERO="Zeroing"
MSG_ASFILE="as a file"

if [ "${LANG%.*}" == "ru_RU" ] ; then 

    MSG_HELP="Использование: \n
При вызове без аргументов будет использован файл конфигурации /etc/swap_cleaner.conf. \n
Если файл пустой, никаких действий не будет выполнено. \n
Если файл отсутствует (основной способ использования, автоматический режим) \n
будут очищены все области из /proc/swaps \n
Можно использовать как имена разделов, так и имена файлов подкачки как аргументы командной строки \n 
(или \"список разделенный пробелами в кавычках\") для \n
ручного зануления единичного раздела или файла или списка  \n
Подробная инструкция /usr/share/doc/swap_cleaner... \n"
    MSG_START2CLEAN="Запущена очистка"
    MSG_START="Начата очистка"
    MSG_FROM="из"
    MSG_AUTO="в автоматическом режиме"
    MSG_NOTFILE_NOTDEV="не файл и не блочное устройство, проигнорировано"
    MSG_NOTSWAP="не является разделом подкачки, проигнорировано"
    MSG_NOTHING="Нечего делать, завершение"
    MSG_DONE="готово"
    MSG_ASDEV="как блочного устройства"
    MSG_ZERO="Зануление"
    MSG_ASFILE="как файла"
fi

# Cleaning single file or partition
sclean()
{
    local BS=1M
    if [ "$2" = "device" ] ; then
	echo "$MSG_ZERO $1 $MSG_ASDEV"
	UUID="`blkid -s UUID -o value $1`"
	LABEL="`blkid -s LABEL -o value $1`"
	swapoff $1 2> /dev/null
	dd if=/dev/zero of=$1 bs="$BS" count=1 2>/dev/null
	mkswap -U "$UUID" -L "$LABEL" $1 1>/dev/null
	dd if=/dev/zero of=$1 bs="$BS" seek=1 2>/dev/null
    else
	BS=4096
	echo "$MSG_ZERO $1 $MSG_ASFILE"
	swapoff $1 2> /dev/null
	local BLOCKS="$((( $(stat -c%s "$1") + 4095 ) / 4096 ))"
	dd if=/dev/zero of=$1 bs="$BS" count="$BLOCKS" 2>/dev/null
	mkswap $1 1>/dev/null
	sync
    fi
    echo "$1 $MSG_DONE"
}

mclean()
{
    local i
    if [ -z "$1" ] ; then 
	echo $MSG_NOTHING
	return
    fi
    for i in $1 ; do
	if [ -f $i  ] ; then
	    sclean $i "file" &
	elif [ -b $i  ] ; then
	    MON_KEY="`blkid -s TYPE $i`"
	    if [ "${MON_KEY#*=}" == '"swap"' ] ; then
		sclean $i "device" &
	    else
		echo "$i $MSG_NOTSWAP"
	    fi
	else
	    echo "$i $MSG_NOTFILE_NOTDEV"
	fi
    done
    wait
}

## main()
if [ -n "$1"  ] ; then
    if [ "$1" == "-h" -o "$1" == "--help" ] ; then
	echo -e "$MSG_HELP"
	exit
    fi
    echo "$MSG_START2CLEAN $1"
    mclean $1
    exit
fi

if [ -f "$CONFIG" ] ; then
    . "$CONFIG"
    echo "$MSG_START $SWAPS $MSG_FROM $CONFIG"
else
# No config file
    SWAPS="$(cat /proc/swaps |grep \/ | cut -d ' ' -f1)"
    echo "$MSG_START $SWAPS $MSG_AUTO"
fi
mclean "${SWAPS}"
