summaryrefslogtreecommitdiff
path: root/archives/bin/createmsgid.pl
blob: 9dcbc2746e08b896731e946914dbe580d78ad6db (plain)
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: $!";
	}
}