1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
#!/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: $!";
}
}
|