#! /usr/bin/perl
#
#	mbx_chk - Mailbox Consistency Check
#
# Last Change: Mon Nov  6 20:02:14 GMT 2000

require "getopts.pl";
require "ctime.pl";

($clx_user_uid,$home) = (getpwnam('clx_us'))[2,7];

$db_name = "clx_db";
$psql = "psql -d $db_name -F \" \" -qAtc";
$psql_batch = "psql -d $db_name -qAt";
$pgtmp = "/tmp/postgres.input";
$quiet = 0;

die "You must be user clx_us to run $0" if ($< != $clx_user_uid);
die "Postmaster is not running" if (!(`ps auxw | grep postmaster | grep -v grep`));

&Getopts('q');

if (length($opt_q) > 0) {
    $quiet = 1;
}

open(PG,"> $pgtmp") || die "Cannot open temporary file $pgtmp.\n";

#
# Lese alle vorhanden im ~/box-Dateisystem vorhandenen Dateinamen 
# in $filelist ein
#
&printerr("checking files");

$select = "select d_name,d_flag from ml_dir\;";
open(IN,"$psql \"$select\" |") || die "Postmaster not running.";
while(<IN>) {
	chop;
	($d_name,$d_flag) = split;
	if ($d_flag <= 1 || $d_name eq 'bulletin') { 
		push(@dir,$d_name); 
		printerr("adding directory $d_name to check list.");
	}
}
close IN;

foreach $i (@dir) {
	open(IN,"find $home/box/$i -type f -print |");
	while (<IN>) {
		chop;
		$s=(-s);
		$filelist{$_}=1;
		&printerr("  $_ ($s Bytes)");
	}
	close IN;
}

#
# Lese alle in der Datenbank verzeichneten Dateien
# in $dblist ein. Dateien mit 0 Byte Gre werden dabei ignoriert (da fr
# sie keine Datei angelegt wird). 
#
&printerr("checking database for non-existing entries");
$select = "select f_name,f_thema,f_ldir,f_size from ml_file\;";
open(IN,"$psql \"$select\" |") || die "Postmaster not running.";
while (<IN>) {
	($f_name,$f_thema,$f_ldir,$f_size) = split(' ');
	$f="$home/box/$f_thema/$f_ldir/$f_name";
	$dblist{"$f"}=1 unless ($f_size == 0);
	&printerr("  $f ($f_size Bytes)");
}
close IN;

#
# Dateien mit negativer Dateigre und lter als 1 Tag sind 
# unvollstndig und werden in die $incompletelist aufgenommen
#
&printerr("checking database for negative filesizes");
$select = "select f_name,f_thema,f_ldir,f_size from ml_file \
		where \
		f_size < 0 
		and \
		timepl(f_dact,'@ 1 day') < 'now'\;";
open(IN,"$psql \"$select\" |");
while (<IN>) {
	($f_name,$f_thema,$f_ldir,$f_size) = split(' ');
	$f="$home/box/$f_thema/$f_ldir/$f_name";
	$incompletelist{"$f"}=1;
	&printerr("  $f ($f_size Bytes)");
}
close IN;

#
# Suche zu jedem Datenbankeintrag die zugehrige Datei im
# ~/box-Filesystem und wenn gefunden aus beiden Vektoren lschen.
# Zurck bleiben die jeweils an einer Stelle fehlenden Dateien.
#
foreach $i (keys (%dblist)) {
    delete $filelist{$i} && delete $dblist{$i}
}

#
# Alle in den drei Vektoren verbliebenen Dateien knnen nun
# weggeworfen werden.
#

if (%filelist) {
	print "list of unassigned files:\n";
	foreach $i (sort keys (%filelist)) {
		if ($i =~ /bulletin/) {
			&collect_bulletin($i);
		} elsif ($i =~ /batch/) {
			&collect_batch($i);
		} else {
			&rm_file($i);
		}
	}
}

if (%dblist) {
	print "list of non existing files:\n";
	foreach $i (sort keys (%dblist)) {
		&rm_db($i);
	}
}

if (%incompletelist) {
	print "list of incomplete files:\n";
	foreach $i (sort keys (%incompletelist)) {
		&rm_file($i);
		&rm_db($i);
	}
}

close(PG);
#
# Nun werden die Datenbankkommandos ausgefhrt 
#
&printerr("updating database");
system("$psql_batch < $pgtmp");
unlink $pgtmp;



sub printerr {
	if (! $quiet) { print "@_\n" };
}

sub rm_db {
	print("  rm_db @_\n");
        $_=@_[0];
	s/$home\/box\///;
	s/\// /g;
	&printerr("  rm_db $_");
	($f_thema,$f_ldir,$f_name) = split(/ /);

	$cmd = "delete from ml_file where f_name='$f_name' and f_thema='$f_thema' and f_ldir='$f_ldir'";

	print PG "$cmd;\n\n";
}

sub rm_file {
	print("  @_[0] (deleted)\n");
	unlink @_[0];
}

sub collect_bulletin {
	$f = @_[0];
	print("  $f (collected)\n");
        $f_size = (stat($f))[7];
	$f_date = &ctime((stat($f))[9]);
	chop($f_date);

	if ($f_size > 0) {
		$f =~ s/.*bulletin\///;
		($f_ldir,$f_name) = split(/\//,$f);
		$cmd = "insert into ml_file (f_thema,f_name,f_ldir,f_size,f_date,f_dact,f_readc) values('bulletin','$f_name','$f_ldir','$f_size','$f_date','now','0')";

		print PG "$cmd;\n\n";
	} else { 
		&rm_file($f);
	}
}

sub collect_batch {
	$f = @_[0];
	print("  $f (collected)\n");
        $f_size = (stat($f))[7];
	$f_date = &ctime((stat($f))[9]);
	chop($f_date);

	if ($f_size > 0) {
		$f =~ s/.*batch\///;
		($f_ldir,$f_name) = split(/\//,$f);
		$cmd = "insert into ml_file (f_thema,f_name,f_auth,f_ldir,f_size,f_date,f_dact,f_readc) values('batch','$f_name','$f_name','$f_ldir','$f_size','$f_date','now','0')";

		print PG "$cmd;\n\n";
	} else { 
		&rm_file($f);
	}
}
