#!/usr/bin/perl

$Index="/files/filebase/index";
$IndexMode="664";
#$IndexOwner="fnet.uucp";
$IndexOwner="serg.boss";
$Areas="dirs.frq";
$Aliases="aliases.frq";
$DescDir="";
$HeadList="/files/filebase/index/banner.txt";

#$UseGDBM_File = 0;
#use GDBM_File;


$ListCols=70;
format ALIAS_HDR = 
+--------------------------------------------------------------------+
!@|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||!
 $AreaName
!       Freq's for systems: p - protected; l - listed; a - all       !                          
!                                                                    !
.
format ALIAS_END =
!                                                                    !
!@|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||!
 $AreaEnd
+--------------------------------------------------------------------+
.
format AREA_HDR = 
+--------------------------------------------------------------------+
!@|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||!
 $AreaName
!@|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||!
 $FreqStatus
!                                                                    !
.
format AREA_END =
!                                                                    !
!@|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||!
 $AreaEnd
+--------------------------------------------------------------------+
.
format LIST_END =

+--------------------------------------------------------------------+
!@|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||!
 $AreaEnd
+--------------------------------------------------------------------+
.

if( ! open( HeadList )) {
	print STDERR "Warning: Cannot open $HeadList. $!\n";
} else {
	while( <HeadList> ) {
		print $_;
	}
	close( HeadList );
}

if( $UseGDBM_File ) {
	rename( $Index."/files", $Index."/files.bak" );
} else {
	rename( $Index."/files.dir", $Index."/files.bak" );
	unlink( $Index."/files.pag" );
}
if( ! dbmopen( Files, $Index."/files", 0664 )) {
	print STDERR "Error: Cannot create dbm files. $!\n";
	&RestoreIndex();
}

#$DescDir = $DescDir."/" if( $DescDir ne "" );

if( ! &ProcessAliases()) {
	&RestoreIndex();
}

$TotalFiles = 0;
$TotalSize = 0;

if( ! &ProcessAreas()) {
	&RestoreIndex();
}

$AreaEnd = "Total $TotalSize bytes in $TotalFiles files.";
$~ = LIST_END;
write;

dbmclose( Files );
if( $UseGDBM_File ) {
	system "chmod $IndexMode $Index/files ; chown $IndexOwner $Index/files";
} else {
	system "chmod $IndexMode $Index/files.* ; chown $IndexOwner $Index/files.*";
}
exit( 0 );


sub RestoreIndex {
	if( $UseGDBM_File ) {
		rename( $Index."/files.bak", $Index."/files" );
		system "chmod $IndexMode $Index/files ; chown $IndexOwner $Index/files";
	} else {
		rename( $Index."/files.bak", $Index."/files.dir" );
		link( $Index."/files.dir", $Index."/files.pag" );
		system "chmod $IndexMode $Index/files.* ; chown $IndexOwner $Index/files.*";
	}
	exit( 1 );
}

sub ProcessAliases {
	local( $ls );
	local( $File, $file, $path, $desc );
	local( $ipath, $tmp );
	local( $freqstat, $size, $date, $s );
	local( $count ) = 0;

	if( ! open( ls, $Index."/".$Aliases )) {
		print STDERR "Error: Cannot open $Aliases. $!\n";
		return 0;
	}
	$AreaName = "Area: Aliases";
	$~ = ALIAS_HDR;
	write;
	while( <ls> ) {
		chop;
		next if( /^[ \t]*$/ );
		next if( /^[ \t]*#/ );
		( $file, $path, $desc ) = split( /[ \t]+/, $_, 3 );
		$File = $file;
		$File =~ tr/[a-z]/[A-Z]/;
		if( defined( $Files{$File} )) {
			( $ipath, $tmp ) = split( /[ \t]+/, $Files{$File}, 2 );
			print STDERR "Warning: $File($path) already defined. First define $ipath\n";
			next;
		}
		$tmp = substr( $path, 0, rindex( $path, "/" ));
		if( ! $desc ) {
			$desc = &ReadDesc( $tmp."/", substr( $path, rindex( $path, "/" )));
		}
		$freqstat = ( &ReadADesc( $tmp ))[0];
		( $size, $date ) = &SizeDate( $path );
		$Files{$File} = $path." ".$freqstat." ".$size." ".$date." ".$desc;
		&PrintList( $File, 1 );
		$count++;
	}
	close( ls );
	$AreaEnd = "Total ".$count." aliases.";
	$~ = ALIAS_END;
	write;
	return 1;
}

sub ProcessAreas {
	local( $dir ) = $Index."/".$Areas;

	if( ! open( dir )) {
		print STDERR "Error: Cannot open $dir. $!\n";
		return 0;
	}
	while( <dir> ) {
		chop;
		next if( /^[ \t]*$/ );
		next if( /^[ \t]*#/ );
		&ProcessArea( $_ );
	}
	close( dir );
	return 1;
}

sub ProcessArea {
	local( $areapath ) = $_[0];
	local( $files, $bytes );
	local( $ls, $ipath, $tmp );
	local( $File, $file, $path, $fstat, $size, $date, $desc );

	( $FreqStatus, $AreaName ) = &ReadADesc( $areapath );
	$AreaName = "Area: ".$AreaName;
	$fstat = $FreqStatus;
	if( $FreqStatus =~ /^p$/ ) {
		$FreqStatus = "File requests enabled for protected links only.";
	} elsif( $FreqStatus =~ /^l$/ ) {
		$FreqStatus = "File requests enabled for listed systems.";
	} elsif( $FreqStatus =~ /^a$/ ) {
		$FreqStatus = "File requests enabled for all systems.";
	} else {
		$FreqStatus = "File requests disabled.";
	}
	$~ = AREA_HDR;
	write;
	$files = 0;
	$bytes = 0;
	if( open( ls, "ls -1tr $areapath/ |" )) {
		while( <ls> ) {
			chop;
			next if( /^\.*$/ );
			next if( /\.desc$/ );
			next if( /^files\..../i );
			$file = $_;
			$path = $areapath."/".$file;
			next if( ! ( -f $path ));
			$File = $file;
			$File =~ tr/[a-z]/[A-Z]/;
			if( defined( $Files{$File} )) {
				( $ipath, $tmp ) = split( /[ \t]+/, $Files{$File}, 2 );
				print STDERR "Warning: $File($path) already defined. First define $ipath\n";
				next;
			}
			$desc = &ReadDesc( $areapath."/", "/".$file );
			( $size, $date ) = &SizeDate( $path );
			$Files{$File} = $path." ".$fstat." ".$size." ".$date." ".$desc;
			&PrintList( $File, 0 );
			$files++;
			$bytes += $size if( $size =~ /^[0-9]+$/ );
		}
		close( ls );
	} else {
		print STDERR "Warning: Cannot read $areapath. $!\n";
	}
	$TotalFiles += $files;
	$TotalSize += $bytes;
	$AreaEnd = "Total $bytes bytes in $files files.";
	$~ = AREA_END;
	write;
	return 1;
}

sub ReadDesc {
	local( $path ) = $_[0].$DescDir.$_[1].".desc";
	local( $tmp );
#print $path."\n";
	if( !open( path )) {
		return "Description missing, $!";
	} else {
		while( <path> ) {
			chop;
			$tmp .= $_." ";
		}
		close( path );
		return $tmp ;
	}
}

sub ReadADesc {
	local( $path ) = $_[0]."/".$DescDir."/.desc";
	local( @ret, $tmp );
#print $path."\n";
	
	if( ! open( path )) {
		$ret[0] = "-";
		$ret[1] = "No name";
	} else {
		$tmp = "";
		while( <path> ) {
			chop;
			next if( /^[ \t]*$/ );
			next if( /^[ \t]*#/ );
			$tmp = $_;
			last;
		}
		@ret = split( /[ \t]+/, $tmp, 2 );
		if( $ret[0] =~ /^[pP]/ ) {
			$ret[0] = "p";
		} elsif( $ret[0] =~ /^[lL]/ ) {
			$ret[0] = "l";
		} elsif( $ret[0] =~ /^[aA]/ ) {
			$ret[0] = "a";
		} else {
			$ret[0] = "-";
		}
		close( path );
	}
	return @ret;
}

sub SizeDate {
	local( $file ) = $_[0];
	local( @st, @ret, @tm );
	local( @month ) = ( Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec );

	if( @st = stat( $file )) {
		$ret[0] = $st[7];
		@tm = localtime( $st[9] );
		$ret[1] = sprintf( "%02d-%3s-%02d", $tm[3], $month[$tm[4]], $tm[5] );
	} else {
		$ret[0] = "off";
		$ret[1] = "line";
	}
	return @ret;
}

sub PrintList {
	local( $file ) = $_[0];
	local( $mode ) = $_[1];
	local( $fstat, $size, $date, $path, $desc );
	local( @_desc, @adesc, $str, $l, $w, $s );

	if( ! defined( $Files{$file} )) {
		return;
	}
	( $path, $fstat, $size, $date, $desc ) = split( /[ \t]+/, $Files{$file}, 5 );
	@_desc = split( /[ \t]+/, $desc );
	if( $mode ) {
		$str = sprintf( "%1s %-12s %7s %-8s", $fstat, $file, $size, $date );
	} else {
		$str = sprintf( "%-12s %7s %-8s", $file, $size, $date );
	}
	$l = length( $str ) + 1;
	$adesc[0] = "";
	for( $w = 0, $s = 0;; $w++ ) {
		if(((( length( $adesc[$s] ) + $l + length( $_desc[$w] )) < $ListCols )) && ( $w <= $#_desc )) {
			$adesc[$s] .= " ".$_desc[$w];
		} else {
			if( $s == 0 ) {
				print $str.$adesc[$s]."\n";
			} else {
				print " " x $l, $adesc[$s]."\n";
			}
			$s++;
			$adesc[$s] = $_desc[$w];
			last if( $w > $#_desc );
		}
	}
}
