#! /usr/bin/perl
# lowercase: rename files to all lowercase filenames

# Copyright (C) 2005-2007 by Brian Lindholm.  This file is part of the
# littleutils utility set.
#
# The lowercase 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 lowercase 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 <http://www.gnu.org/licenses/>.

use Fcntl;
use Getopt::Std;
use locale;

# get input arguments
$opt_h = ""; $opt_q = "";
$opt_v = "";
$good_opt = getopts("hqv");

# print help if requested or if bad options used, then quit
if (not ($good_opt) or ($opt_h) or ($#ARGV < 0)) {
  print "lowercase 1.0.30\n";
  print "usage: lowercase [-h(elp)] [-q(uiet)] [-v(erbose)] file...\n";
  exit ($good_opt eq "");
}

# determine if we're running under DOS or Windows
$dos_win = (($^O eq "dos") or ($^O eq "MSWin32") or ($^O eq "cygwin"));

# run through list of files
LOOP: foreach $old_name (@ARGV) {
  # clean up filename
  $old_name =~ s://+:/:;     # collapse multiple "/"
  $old_name =~ s:^(\./)+::;  # remove leading "./"
  $old_name =~ s:/$::;       # remove trailing "/"
  # skip certain cases
  next LOOP if (($old_name eq ".") || ($old_name eq ".."));
  # split into path and filename
  if ($old_name =~ /^(.*)\/(.+)$/) {
    $path = $1;
    $name = $2;
  }
  else {
    $path = ".";
    $name = $old_name;
  }
  # convert to lowercase
  if ("$path" eq ".") {
    $new_name = lc($name);
  }
  else {
    $new_name = $path . '/' . lc($name);
  }
  # determine if rename should actually happen
  if ($new_name eq $old_name) {
    if ($opt_v) {
      print STDOUT "lowercase message: $old_name already lowercase\n";
    }
  }
  elsif (not (-w $old_name)) {
    print STDERR "lowercase warning: you don't have write permissions to $old_name\n";
  }
  elsif (not (-w $path)) {
    print STDERR "lowercase warning: you don't have write permissions in $path\n";
  }
  elsif ((not $dos_win) && (-e $new_name)) {
    print STDERR "lowercase warning: new name for $old_name already exists\n";
  }
  else {
    if ((not $dos_win) && (-f $old_name)) {
      # the sysopen is for security in world-writeable directories
      sysopen(HANDLE, $new_name, O_RDWR | O_CREAT | O_EXCL, 0600)
        or die "lowercase ERROR: possible SYMLINK ATTACK!!\n";
      close(HANDLE);
    }
    rename($old_name, $new_name)
      or die "lowercase ERROR: move from $old_name to $new_name FAILED!!\n";
    if (not $opt_q) {
      print STDOUT "$old_name moved to $new_name\n";
    }
  }
}
