#!/usr/bin/perl
#############################################################################
## Crytek Source File
## Copyright (C) 2007, Crytek Studios
##
## Creator: Sascha Demetrio
## Date: Sep 28, 2007
## Description: GNU-make based build system
#############################################################################

# This script performs a single log rotation step on the specified log
# directory.  The log directory is created if it does not exist.  The script
# operates on all files with the extension '.log', all other files are
# ignored.

use warnings;
use strict;

use Getopt::Long qw(:config no_auto_abbrev);

# Default value for the maximum index option.
my $defaultMaxIndex = 9;

# Parse the command line.
my $logDir;
my $maxIndex = $defaultMaxIndex;
my $optionHelp = 0;
my $optionVerbose = 0;
GetOptions(
    'l|logdir|log-dir=s' => \$logDir,
    'm|maxindex|max-index=s' => \$maxIndex,
    'h|help' => \$optionHelp,
    'v|verbose!' => \$optionVerbose
    ) or exit 1;
if ($optionHelp)
{
  print <<EOF;
logrotate.pl:
Perform a log rotation step on the log files in the specified log directory.
Synopsis:
  \$PERL logrotate.pl (Options)
Options:
-l|--log-dir DIR
  The log directory.
-m|--max-index INDEX
  The maximum log rotation index.  The default value is $defaultMaxIndex.  The
  value 0 disables the rotation (this will simply delete all log files).
-v|--verbose
  Verbose operation.
-h|--help
  Display this help screen and exit.
EOF
  exit 0;
}
if (not defined $logDir)
{
  print STDERR "logrotate: no log directory specified!\n";
  exit 1;
}
$maxIndex = $maxIndex + 0; # Force to numeric.
$maxIndex = 0 if ($maxIndex < 0);

# Scan the specified directory for log files and return a list of full paths.
sub scanLog ($)
{
  my $dir = shift;
  my @dirList = ( );
  local *DIR;

  opendir(DIR, $dir) or die "logrotate: can not read directory '$dir': $!";
  foreach my $file (readdir DIR)
  {
    next unless $file =~ /\.log$/;
    push @dirList, "$dir/$file";
  }
  closedir DIR;
  return @dirList;
}

# Rotate the specified log file.
sub rotateLog ($)
{
  my $logFile = shift;

  print "logrotate: $logFile\n" if ($optionVerbose);
  if ($maxIndex > 0)
  {
    unlink "$logFile.$maxIndex";
    for (my $i = $maxIndex - 1; $i >= 0; --$i)
    {
      my $oldIndex = $i;
      my $newIndex = $i + 1;
      my $oldSuffix = "";
      $oldSuffix = ".$oldIndex" if ($oldIndex > 0);
      my $newSuffix = ".$newIndex";
      rename "$logFile$oldSuffix", "$logFile$newSuffix";
    }
  }
  else
  {
    unlink "$logFile";
  }
}

# Normalize the log directory name and make sure the log directory exists.
$logDir =~ s/\\/\//g;
$logDir =~ s/\/\//\//g;
$logDir =~ s/\/*$/\//;
while ($logDir =~ s/\/\.\//\//) { }
while ($logDir =~ s/\/[^\/]+\/\.\.\//\//) { }
print "logrotate: log directory '$logDir'\n" if ($optionVerbose);
if (not -d $logDir)
{
  my @logDirComponents = split '/', $logDir;
  my $logDirPrefix = "";
  foreach my $component (@logDirComponents)
  {
    $logDirPrefix .= "$component/";
    if (not -d $logDirPrefix)
    {
      print "logrotate: creating '$logDirPrefix'\n" if ($optionVerbose);
      mkdir $logDirPrefix;
    }
  }
}

# Rotate all logs.
foreach my $logFile (scanLog $logDir) { rotateLog $logFile; }

# Tools/logrotate.pl
# vim:ts=2:sw=2:expandtab

