#/bin/bash

################################################################################
# Script name:  free_space_v1.1beta3.sh                                        #
# Author:       SoD-                                                           #
# Contact:      SoD- @ EFNet                                                   #
# Releasedate:  2002-05-01                                                     #
#                                                                              #
# This script is labeled as beta since I haven't got much 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 until a specified amount of space is free. This script only       #
# deletes directly inside the specified incomingpath, thus it cannot be used   #
# were you have "nested" dirs (CD1, CD2, sample and such does not qualify as   #
# nested). If you have a dated dir structure you should use my other script,   #
# free_space_dated_dirs_v1.3beta.sh. This script is meant for iso/vcd/divx/    #
# and sections were you normally dont have dated dirs. You can specify how     #
# much space the section is allowed to contain, letting you have multiple      #
# sections on one device and you can set the time you want nuked dirs to stay  #
# on the site. You can set groups that you don't want deleted by the script    #
# (eg, don't delete any of RiSC's or FLT's releases) and of course "special"   #
# dirs that you want excluded. Nuked dirs gets deleted even if they are from   #
# "VIP groups". The script deletes the dirs by their modification time and     #
# 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 nuked directorys inside incomingpath if they are older than   #
#   specified by $DELETE_NUKES_TIME.                                           #
# * Deleting oldest directory inside incomingpath.                             #
# * Repeats the above until enough space is free.                              #
#                                                                              #
# Installation: -Put this file in some approperiate place, for example         #
#                /glftpd/bin/free_space_v1.1beta3.sh                           #
#               -Make it executable                                            #
#                (chmod 755 /glftpd/bin/free_space_v1.1beta3.sh)               #
#               -Edit your crontab (crontab -e) and write something like:      #
#                0,20,40 * * * * /glftpd/bin/free_space_v1.1beta3.sh           #
#               -Edit this script to suit your setup.                          #
#               -Execute the script manually to spot any obvious errors.       #
#               -If the execution went fine, set DEBUG to 0 (DEBUG=0).         #
#               -If you are using Darkheart's botscript you should add the     #
#                following 4 lines to sitebot-glftpd.api and then rehash it.:  #
#                set chans(sectionname-AUTODEL) " #channelname "               #
#                               ^-edit                 ^-edit                  #
#                set echovars(AUTODEL) "size section deldir"                   #
#                set enabled_announce(AUTODEL) 1                               #
#                set mask(AUTODEL) "[b]\[%sitein AUTO-DELETE\][b] system freed [b]%size MB[b] in [b]%section[b] by deleting [b]%deldir[b]"
#               -If you are using vShit's botscript you should add the         #
#                following line in the scanlog proc and then rehash it.:       #
#                AUTODEL: {sndall "[b]\[$sitename AUTO-DELETE\][b] system freed [b][lindex $args 0] MB[b] in [b][lindex $args 1][b] by deleting [b][lindex $args 2][b]"}
#               -If you are using vrpack (1.6.0 Beta) botscript you should add #
#                the following line in the scanlog proc and then rehash it.:   #
#                AUTODEL: {sndall "\002\[$sns AUTO-DELETE\]\002 system freed \002[lindex $args 0] MB\002 in \002[lindex $args 1]\002 by deleting \002[lindex $args 2]\002"}
#               -If you are using Dark0n3's botscript you should add 'AUTODEL' #
#                to the list in 'set msgtypes(DEFAULT) "..."'. Also add the    #
#                following 4 lines to dZSbot.tcl and then rehash it.:          #
#                set chanlist(AUTODEL) "#channelname"                          #
#                                            ^-edit                            #
#                set disable(AUTODEL) 0                                        #
#                set variables(AUTODEL) "%size %section %deldir"               #
#                set announce(AUTODEL) "%bold\[%sitename AUTO-DELETE\]%bold system freed %bold%size%bold MB in %bold%section%bold by deleting %bold%deldir%bold"
#                                                                              #
# Requirements: awk, cut, date, df, du, echo, expand, expr, grep, ls, rm, tail,#
#               tr                                                             #
#                                                                              #
# Limitations:  -Can only handle dirnames without spaces (dirs that are inside #
#                the releases (like CD1, sample and "[COMPLETE 100%]") can     #
#                have spaces in them).                                         #
#               -Only one section can be handled, use multiple instances of    #
#                this script, one per section if you have multiple sections.   #
#                                                                              #
# Changelog:    v1.0 -> v1.1.beta:        Certain groups releases can now be   #
#                                         set to not be deleted.               #
#               Changes in settings:      N/A.                                 #
#               v1.1.beta -> v1.1.beta.2: A bug in $VIP_DIRS was fixed.        #
#               Changes in settings:      None.                                #
#               v1.1.beta.2 -> v1.1beta3: Some checks have been implemented to #
#                                         make the script less sensitive to    #
#                                         faulty settings/dirnames/filenames.  #
#                                         Added a DEBUG setting that disables  #
#                                         the actual deleting.                 #
#                                         Also made the script send any errors #
#                                         to glftpd's error.log.               #
#                                         On some systems, 'df -m' didn't work #
#                                         as planned. Changed it to 'df -Pm'.  #
#                                         Also added braces around the para-   #
#                                         meters that are sent to glftpd.log.  #
#               Changes in settings:      Specify $ERROR_LOG_FILE.             #
################################################################################
# This setting disables the actual deleting of the dirs. Set to 0 for no debug.
DEBUG=1

# 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 available.
MAX_SPACE_ALLOWED=0

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

# Put any dirs you don't want deleted here (directly inside INCOMINGPATH). Case
# sensitive. Separate them with space and DON'T use a trailing frontslash (/).
VIP_DIRS="temp pics.of.my.gf predir"

# What groups releases don't you want this script to delete? Use lowercase and
# separate with space.
VIP_GROUPS="risc deviance flt tfe"

# Do you want the script to write to glftpd.log? (for announcing) [y/n]
ANNOUNCE=y

# How long shall a nuked dir stay on site (in hours) before it's deleted?
DELETE_NUKES_TIME=48

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

# 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"

# What's the location of glftpd's error.log?
ERROR_LOG_FILE="/glftpd/ftp-data/logs/error.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 -Pm $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

# Just make shure some things exist...
if [ ! -r $GL_CONFIG_FILE ] || [ ! -w $GL_LOG_FILE ] || \
[ ! -w $ERROR_LOG_FILE ] || [ ! -d $INCOMINGPATH ]; then
  if [ $DEBUG != 0 ]; then
    echo "One or more of your settings are faulty, aborting."
  elif [ -w $ERROR_LOG_FILE ]; then
    echo `date +"%a %b %d %T %Y"` "[        ] Error: $0 failed to execute:" \
    "one or more of your settings are faulty" >> $ERROR_LOG_FILE
  fi
  exit 1
fi
if [ -z $NUKED_DIR_NAMES ] || [ -z $MIN_FREE_SPACE ] || \
[ -z $FREE_ON_DEVICE ]; then
  if [ $DEBUG != 0 ]; then
    echo "Error in script: variables not set properly, aborting."
  elif [ -w $ERROR_LOG_FILE ]; then
    echo `date +"%a %b %d %T %Y"` "[        ] Error: $0 failed to execute:" \
    "error in script, variables not set properly" >> $ERROR_LOG_FILE
  fi
  exit 1
fi

# Loop until enough space has been freed
until [ $FREE_ON_DEVICE -gt $MIN_FREE_SPACE ]; do
  # Find oldest nuked dir and its modification time
  DEL_DIR=`ls -lt $EXCLUDE_DIRS $INCOMINGPATH | grep $NUKED_DIR_NAMES | \
  tail -n 1 | awk '{print $9}' | tr -d '/'`
  TMP=`date -d "\`ls -lt --full-time $EXCLUDE_DIRS $INCOMINGPATH | \
  grep $NUKED_DIR_NAMES | tail -n 1 | expand | tr -s " " | \
  cut -d " " -f6-10\`" +%s`

  # Delete oldest nuked dir if it's older then $DELETE_NUKES_TIME. Otherwise
  # delete the oldest dir. Also get the size for the botscript.
  if [ `expr '(' \`date +%s\` - $TMP ')' / 3600` -gt $DELETE_NUKES_TIME ] \
  && [ $DEL_DIR ]; then
    DEL_DIR_SIZE=`du -sm $INCOMINGPATH$DEL_DIR | awk '{print $1}'`
    if [ $DEBUG == 0 ]; then
      rm -rf $INCOMINGPATH$DEL_DIR
    fi
  else
    # Create a list for use in $DEL_DIR with rel's that aren't to be deleted
    EXCLUDE_DIRS=""
    if [ "$VIP_GROUPS" ] || [ "$VIP_DIRS" ]; 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 $VIP_DIRS | \
      awk '{ for (i=1; i <= NF; i++) printf " -I %s", $i ; printf "\n" }'`
    fi

    DEL_DIR=`ls -lt $EXCLUDE_DIRS $INCOMINGPATH | tail -n1 | \
    awk '{print $9}' | tr -d '/'`

    if [ "$DEL_DIR" ]; then
      DEL_DIR_SIZE=`du -sm $INCOMINGPATH$DEL_DIR | awk '{print $1}'`
      if [ $DEBUG == 0 ]; then
        rm -rf $INCOMINGPATH$DEL_DIR
      fi
    fi
  fi

  # Announce deletion if $ANNOUNCE is set to "y"
  if [ $ANNOUNCE = y ]; then
    echo `date +"%a %b %d %T %Y"` AUTODEL: \""$DEL_DIR_SIZE"\" \
    \""$SECTION_NAME"\" \""$DEL_DIR"\" >> $GL_LOG_FILE
  fi

  # Are enough files deleted?
  if [ $MAX_SPACE_ALLOWED -eq 0 ]; then
    FREE_ON_DEVICE=`df -Pm $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
  if [ -z $FREE_ON_DEVICE ] || [ -z $MIN_FREE_SPACE ]; then
    if [ $DEBUG != 0 ]; then
      echo "Error in script: variables not set properly, aborting."
    elif [ -w $ERROR_LOG_FILE ]; then
      echo `date +"%a %b %d %T %Y"` "[        ] Error: $0 failed to execute:" \
      "error in script, variables not set properly" >> $ERROR_LOG_FILE
    fi
    exit 1
  fi
done
exit