#!/usr/bin/perl -w # # Creates hard links to Mhonarc-generated message files, named after # the Message-Ids. # # There are two mandatory arguments: # # -i dir: the input directory (where .mhonarc.db and msg files reside) # -o dir: the output directory (where the msgid links are created) # # The links are named tr/y./xyzw1234foobar@try.example.com where the last part # is the Message-Id, and the subdirectories are two-letter substrings from the # part after the first @. If there's no @ present (say the Message-Id is # ACBEF123ABC) then we place the file at AC/BE/ACBEF123ABC. # # (This is to avoid having huge directories, which are known to cause problems # on filesystems.) # # It relies on .mhonarc.db which is a file generated by MHonarc. use Getopt::Std; getopt('i:o:', \%opts); die "input dir not defined" unless defined $opts{'i'}; die "output dir not defined" unless defined $opts{'o'}; $msgdir = $opts{'i'}; $dbfile = "$opts{'i'}/.mhonarc.db"; $odir = $opts{'o'}; if (! -d $odir) { mkdir $odir or die "can't mkdir $odir: $!"; } die "input mhonarc DB not found" unless -f $dbfile; $IndexNum = {}; # keep compiler quiet require $dbfile; foreach my $msgid (keys %MsgId) { $msgfile = sprintf "$msgdir/msg%05d.php", $IndexNum{$MsgId{$msgid}}; # Swap / to _, because it's difficult to deal with that in filenames $msgid =~ s{/}{_}g; # Split the Message-Id in left and right parts ($left, $right) = split /@/, $msgid; # cope with empty or missing right part $right = $left if $right eq ""; $rightlen = length($right); if ($rightlen < 4) { # right parts shorter than 4 chars are not supported yet # (Needs .htaccess fix) warn "short right part in $msgid"; next; } $firstdir = sprintf "%s/%s", $odir, substr $right, 0, 2; if (! -d $firstdir) { mkdir "$firstdir" or die "can't mkdir $firstdir: $!"; } $seconddir = substr $right, 2, 2; $seconddir = "$firstdir/$seconddir"; if (! -d $seconddir) { mkdir "$seconddir" or die "can't mkdir $$seconddir: $!"; } $link = "$seconddir/$msgid"; # If the link already exists but its hardlink count is 1, it means # Majordomo updated the message page, so we need to remove our link # and create a new one. $dev = ""; $ino = ""; $mode = ""; # keep compiler quiet ($dev, $ino, $mode, $nlink) = stat($link); unlink $link if defined $nlink and $nlink == 1; if (! -f $link) { link $msgfile, $link or warn "can't link $msgfile $link: $!"; } }