#!/usr/bin/perl

use File::Find;
use Locale::gettext;
use POSIX();

@ARGV == 0 || @ARGV == 1 && -d $ARGV[0] or die "usage: convert-filenames-to-utf8 [<dir>]\n";
my $dir = $ARGV[0] || $ENV{HOME};

-d $dir or die "$dir is not a directory\n";

{
    my ($LC) = grep { $ENV{$_} } 'LC_ALL', 'LC_CTYPE';
    my $new_LC = $ENV{$LC};
    $ENV{$LC} =~ s/.UTF-8$//i or die "$LC=$ENV{$LC} does not contain UTF-8\n";
    POSIX::setlocale(LC_CTYPE, "");
    print STDERR "converting file names from $LC=$ENV{$LC} to $LC=$new_LC starting from directory $dir\n";
}

finddepth({ 
    wanted => sub {
	my $s = to_utf8($_);
	if ($s ne $_ && from_utf8($_) eq $_) {
	    print STDERR "$File::Find::dir: renaming $_ to $s\n";
	    my $ok = rename($_, $s);
	    if (!$ok && $! == 13) {
		my $mode = (lstat('.'))[2] & 07777;
		if ($mode && chmod($mode | 0700, '.')) {
		    printf STDERR "retrying after setting mode to 0%o\n", $mode | 0700;
		    $ok ||= rename($_, $s);
		}
	    }
	    $ok or warn "renaming failed: $!\n";
	}
    },
}, $dir);


sub from_utf8 {
    my ($s) = @_;
    Locale::gettext::iconv($s, "utf-8", undef); #- undef = locale charmap = nl_langinfo(CODESET)
}
sub to_utf8 { 
    my ($s) = @_;
    Locale::gettext::iconv($s, undef, "utf-8"); #- undef = locale charmap = nl_langinfo(CODESET)
}
