#!/bin/bash

################################################################################
# Script name:  free_space_dated_dirs_v1.2beta.sh                              #
# Author:       SoD                                                            #
# Contact:      SoD- @ EFNet                                                   #
# Releasedate:  2001-08-22                                                     #
#                                                                              #
# This script is labeled as beta since I haven't got any response from other   #
# users success/failure in using it. It works fine for me in slackware though. #
# This script runs in crontab at an approperiate interval and then deletes     #
# directorys in a DATED DIR STRUCTRE until a specified amount of space is free.#
# If all/some of your sections doesn't use dated dirs you should use another   #
# script, for example my free_space_v1.1.beta.sh. You can specify how much     #
# space the section is allowed to contain, letting you have multiple sections  #
# on one device. It deletes the dated dirs by their name (hence the dated dirs #
# only) and all other dirs/files by their date. It (almost) only deletes dated #
# dirs (ie. 0311) so dirs named otherwise then a dated dir wont be touched. It #
# will delete a dir named 0000 and a few more not-dated-dirs. You can set      #
# groups that you don't want deleted by the script (eg, don't delete any of    #
# CORE's or SND's releases). Nuked dirs from "VIP groups" won't get deleted    #
# either. It writes to glftpd.log so that a botscript can announce it (see     #
# below on how to configure the botscripts).                                   #
# The script does something like this:                                         #
# * Deleting any files directly inside the oldest dated dir                    #
# * Deleting any nuked directorys inside the oldest dated dir                  #
# * Deleting oldest directory inside oldest dated dir                          #
# * Moving any "VIP groups" releases to a specified dir                        #
# * Deleting the oldest dated dir if it's empty                                #
# * Repeats above in the "next" dated dir until enough space is free           #
#                                                                              #
# Installation: -Put this file in some approperiate place, for example         #
#                /glftpd/bin/free_space_v1.2beta.sh                            #
#               -Make it executable                                            #
#                (chmod 755 /glftpd/bin/free_space_v1.2beta.sh)                #
#               -Edit your crontab (crontab -e) and write something like:      #
#                0,20,40 * * * * /glftpd/bin/free_space_v1.2beta.sh            #
#               -Edit this script to suit your setup                           #
#               -Test the script -ADViCE: EXECUTE THiS SCRiPT MANUALLY (ROW BY #
#                ROW) THE FiRST TiME (use /bin/ls instead of just ls)          #
#               -If you are using Darkheart's botscript you should add the     #
#                following 8 lines to sitebot-glftpd.api and then rehash it.:  #
#                set chans(sectionname-AUTODEL) " #channelname "               #
#                               ^-edit                 ^-edit                  #
#                set chans(sectionname-RMDIR) " #channelname "                 #
#                               ^-edit                 ^-edit                  #
#                set echovars(AUTODEL) "size section deldir"                   #
#                set echovars(RMDIR) "section"                                 #
#                set enabled_announce(AUTODEL) 1                               #
#                set enabled_announce(RMDIR) 1                                 #
#                set mask(AUTODEL) "[b]\[%sitein AUTO-DELETE\][b] System freed [b]%size[b]MB in [b]%section[b] by deleting [b]%deldir[b]."
#                set mask(RMDIR) "[b]\[%sitein AUTO-DELETE\][b] System deleted [b]%section[b]. Now continuing in next dated dir."
#               -If you are using vShit's botscript you should add the         #
#                following 2 lines in the scanlog proc and then rehash it.:    #
#                AUTODEL: {sndall "[b]\[$sitename AUTO-DELETE\][b] System freed [b][lindex $args 0][b]MB in [b][lindex $args 1][b] by deleting [b][lindex $args 2][b]."}
#                RMDIR: {sndall "[b]\[$sitename AUTO-DELETE\][b] System deleted [b][lindex $args 0][b]. Now continuing in next dated dir."}
#               -If you are using vrpack (1.6.0 Beta) botscript you should add #
#                the following 2 lines in the scanlog proc and then rehash it.:#
#                AUTODEL: {sndall "\002\[$sns AUTO-DELETE\]\002 System freed \002[lindex $args 0]\002MB in \002[lindex $args 1]\002 by deleting \002[lindex $args 2]\002."}
#                RMDIR: {sndall "\002\[$sns AUTO-DELETE\]\002 System deleted \002[lindex $args 0]\002. Now continuing in next dated dir."}
#                                                                              #
# Requirements: awk, cut, date, df, du, echo, expand, expr, find, grep, ls,    #
#               mv, rm, rmdir, tail, tr                                        #
#                                                                              #
# Limitations:  -Can only handle dirnames without spaces (dirs that are inside #
#                the releases (like CD1, sample and "[COMPLETE 100%]") can     #
#                contain spaces.                                               #
#               -Only handles dated dirs named like 1127 (not 11-27, 11.27 ...)#
#               -No more than 1 month can be handled due to the if-expression  #
#                beneath (JANUARY_CHECK and DECEMBER_CHECK). Fix it if you     #
#                need it.                                                      #
#               -Only one section can be handled, use multiple instances of    #
#                this script, 1 per section if you have multiple sections.     #
#               -Deletion of nuked dirs doesn't get announced, this is more a  #
#                choice than a limitation. I'll add it if someone asks me.     #
#                                                                              #
# Changelog:    v1.0 -> v1.1.beta:    Certain groups releases can now be set   #
#                                     to not be deleted.                       #
#               Changes in settings:  Specify $VIP_GROUPS and $VIP_DESTINATION #
#               v1.1.beta -> v1.2beta:Announcing can now be set to 2 levels.   #
#                                     Level 2 announes all deleted dirs, level #
#                                     1 only announces when a complete dated   #
#                                     dir gets been deleted.                   #
#                                     Free space in $VIP_DESTINATION is now    #
#                                     checked before "VIP DIRS" are moved, it  #
#                                     would cause the script to run forever if #
#                                     $VIP_DESTINATION didnt have enough space.#
#               Changes in settings:  Change $ANNOUNCE if you want to.         #
#                                     Update botscript so it triggers on RMDIR #
################################################################################

# How many Megabyte shall be kept free? ( free space when script exits )
MIN_FREE_SPACE=1000

# If you only want to use a part of the device for the section this script keeps
# free you can set that amount (in MB) here. If you want to use the entire
# device, set this to 0 (zero). The above setting is nescessary too.
# WARNING! This setting forces the script to use this value as the capacity of
# the device, so make shure there's at least this much space free.
MAX_SPACE_ALLOWED=0

# Where are the dirs to be freed located? ( eg, /glftpd/site/mp3/ )
# Use a trailing frontslash (/).
INCOMINGPATH="/glftpd/site/mp3/"

# What groups releases don't you want this script to delete? Use lowercase and
# separate with space.
VIP_GROUPS="snd bmi mtc"

# If $VIP_GROUPS is set, then you must specify a location to where these will be
# moved when the oldest dated dir only consists of $VIP_GROUPS.
VIP_DESTINATION="/glftpd/site/private/"

# Do you want the script to write to glftpd.log (for announcing)? Set to '1' if
# you only want dated-dir-deletion announced, '2' if you want all deletions
# announced or 'n' if you don't want any announcing at all.
ANNOUNCE=1

# What do you want the botscript to call the section? ( eg, MP3, iSO, DivX )
SECTION_NAME=MP3

# What's the location of glftpd.conf?
GL_CONFIG_FILE="/etc/glftpd.conf"

# What's the location of glftpd.log?
GL_LOG_FILE="/glftpd/ftp-data/logs/glftpd.log"

################################################################################
# No more specifications needed below,just some editing if the script won't work
################################################################################

# Scan glftpd.conf for the nukestyle
NUKED_DIR_NAMES=`grep nukedir_style -i $GL_CONFIG_FILE | grep -v '#' | \
awk '{print $2}' | awk -F "-%" '{print $1}'`

# Check for disk usage/free space
if [ $MAX_SPACE_ALLOWED -eq 0 ]; then
    FREE_ON_DEVICE=`df -m $INCOMINGPATH | grep "/dev/" | awk '{print $4}'`
else
    SPACE_USED=`du -sm $INCOMINGPATH | awk '{print $1}'`
    FREE_ON_DEVICE=`expr $MAX_SPACE_ALLOWED - $SPACE_USED`
fi

# Loop until enough space has been freed
until [ $FREE_ON_DEVICE -gt $MIN_FREE_SPACE ]; do

    # Get the oldest dir (sorted by NAME not date) ( eg: 1115 )
    DECEMBER_CHECK=`ls -lr $INCOMINGPATH | awk '{print $9}' | \
    grep -x "12[0123][[:digit:]]" | tail -n1`
    JANUARY_CHECK=`ls -lr $INCOMINGPATH | awk '{print $9}' | \
    grep -x "01[0123][[:digit:]]" | tail -n1`
    if [ $DECEMBER_CHECK ] && [ $JANUARY_CHECK ]; then
        OLDEST_DIR=$DECEMBER_CHECK
    else
        OLDEST_DIR=`ls -lr $INCOMINGPATH | awk '{print $9}' | \
        grep -x "[01][[:digit:]][0123][[:digit:]]" | tail -n1`
    fi
    # Make shure $OLDEST_DIR contains something
    if [ ! $OLDEST_DIR ]; then
        exit 1
    fi

    # Remove any files lying directly in $OLDEST_DIR ( eg: 1115/01-MrMjao.mp3 )
    while [ "`find $INCOMINGPATH$OLDEST_DIR -mindepth 1 -maxdepth 1 -type f | \
    tail -n 1`" ]; do
        rm -f "`find $INCOMINGPATH$OLDEST_DIR -mindepth 1 -maxdepth 1 -type f |\
        tail -n 1`"
    done

    # Remove any nuked dirs in $OLDEST_DIR ( eg, !NUKED-VA-MrMjao-2001-KvEMP3 )
    rm -fr $INCOMINGPATH$OLDEST_DIR/$NUKED_DIR_NAMES*

    # Create a list for use in $DEL_DIR with releases that aren't to be deleted
    EXCLUDE_DIRS=""
    if [ "$VIP_GROUPS" ]; then
        for VIP_GROUP in $VIP_GROUPS; do
            EXCLUDE_DIR=`echo $EXCLUDE_DIRS | ls $INCOMINGPATH$OLDEST_DIR | \
            grep -i "$VIP_GROUP$"`
            EXCLUDE_DIRS=`echo $EXCLUDE_DIRS$EXCLUDE_DIR" "`
        done
        EXCLUDE_DIRS=`echo $EXCLUDE_DIRS | \
        awk '{ for (i=1; i <= NF; i++) printf " -I %s", $i ; printf "\n" }'`
    fi

    # Remove oldest dir in $OLDEST_DIR, get the size for the botscript and
    # announce deletion if $ANNOUNCE is set to "y"
    DEL_DIR=`ls -lt $EXCLUDE_DIRS $INCOMINGPATH$OLDEST_DIR | tail -n1 | \
    awk '{print $9}' | tr -d '/'`
    if [ "$DEL_DIR" ]; then
        DEL_DIR_SIZE=`du -sm $INCOMINGPATH$OLDEST_DIR/$DEL_DIR | \
        awk '{print $1}'`
        rm -fr $INCOMINGPATH$OLDEST_DIR/$DEL_DIR
        if [ $ANNOUNCE = 2 ]; then
            echo `date +"%a %b %d %T %Y"` AUTODEL: "$DEL_DIR_SIZE" \
            "$SECTION_NAME/$OLDEST_DIR" "$DEL_DIR" >> $GL_LOG_FILE
        fi
    fi

    # Check if OLDEST_DIR is empty and delete it if so
    if [ `ls -l $EXCLUDE_DIRS $INCOMINGPATH$OLDEST_DIR | awk /^total/ | \
    awk '{print $2}'` = 0 ]; then
        # Move "VIP DIRS" if there's enough space free in $VIP_DESTINATION
        if [ `df -m $VIP_DESTINATION | grep "/dev/" | awk '{print $4}'` -gt \
        `du -sm $INCOMINGPATH$OLDEST_DIR | awk '{print $1}'` ] && [ `ls -l \
        $INCOMINGPATH$OLDEST_DIR | awk /^total/ | awk '{print $2}'` != 0 ]; then
            mv -f $INCOMINGPATH$OLDEST_DIR/* $VIP_DESTINATION
        else
            rm -fr $INCOMINGPATH$OLDEST_DIR/*
        fi
        rmdir $INCOMINGPATH$OLDEST_DIR
        if [ $ANNOUNCE = 1 ] || [ $ANNOUNCE = 2 ]; then
            echo `date +"%a %b %d %T %Y"` RMDIR: "$SECTION_NAME/$OLDEST_DIR" \
            >> $GL_LOG_FILE
        fi
    fi

    # Are enough files deleted?
    if [ $MAX_SPACE_ALLOWED -eq 0 ]; then
        FREE_ON_DEVICE=`df -m $INCOMINGPATH | grep "/dev/" | awk '{print $4}'`
    else
        SPACE_USED=`du -sm $INCOMINGPATH | awk '{print $1}'`
        FREE_ON_DEVICE=`expr $MAX_SPACE_ALLOWED - $SPACE_USED`
    fi
done
exit