#!/usr/bin/perl -w
#
# vim:tabstop=3:syntax=perl:
#
# ---------
## Script  : bdf.pl
## Version : 2.0
## Objet   : bdf ameliore
##----------------------------------------------------------------------------
# 0.1 27-aou-09 - Creation Cedrick Gaillard
# 2.0 31-aou-09 - Optimisation du temps d'execution
#               - Prise en compte des arguments de bdf
#               - n'affiche plus le total s'il n'y a qu'une ligne
#               - n'affiche plus l'entete si pas de FS a afficher.
#-----------------------------------------------------------------------------
#
# ce script remet en forme l'output de bdf:
#   - les tailles sont humainement lisible
#   - afiche en colonne claires et espacees
#   - affiche l'utilisation des inodes
#   - affiche le total de l'espace existant/utilise/disponible
#   - prend en compte tous les arguments de bdf ( -t nfs | -l | -s ...)
#-----------------------------------------------------------------------------

use strict ;
use warnings ;
use Time::HiRes qw( gettimeofday tv_interval) ;

# Initialisations
my (@suff) = qw(K M G T P E Z Y);
my $max_iterations = $#suff;

# On recupere la sortie du bdf
open (BDF,"bdf -i @ARGV |") or die "bdf: $!\n" ;

# On recupere les types de FS presents montés sur le systeme
open(MNTTAB,"</etc/mnttab") or die "/etc/mnttab: $!\n" ;
my @mnt_brut = <MNTTAB> ;
my (%fs_type) ;
foreach my $mnt_line (@mnt_brut) {
	my @mnt_line = split(' ',$mnt_line) ;
	next if( $mnt_line[2] =~ m/autofs/ ) ;
	$fs_type{$mnt_line[0]} = ( $mnt_line[2] ) ;
}
close( MNTTAB );

# Fonction retournant les nombres convertis avec leur suffixe.
sub calc_number {
	my ($number) = @_;
	my $iteration = 0;
	while ( $number > 1023 ) {
		last if ($iteration >= $max_iterations);
		$iteration++ ;
		$number = ($number / 1024);
	}
	$number = sprintf("%.2f",$number) ;
	if( $number =~ m/\.00/ ){
		$number = sprintf("%d",$number) ;
	}
	$number = sprintf("%s%s",$number, $suff[$iteration]) ;
	return ($number) ;
}

# generation d'un tableau, sort un pointeur vers ce tableau
sub generateur_ref_tab {
	my @t = () ;
	return \@t ;
}

# pour la premiere ligne
my @entte = (
	'File System',
	'Size',
	'Used',
	'Avail',
	'%Used',
	'Inodes',
	'IFree',
	'%IUsed',
	'Mounted on',
	'Type'
) ;

my $index = 1 ;
my $seconde_passe = 0 ;
my $length = 10 ;
my ($bdf_line, $nb_elem, $ref_bdf, @bdf_temp_1, @bdf_one_line) ;
my ($ttotal, $utotal, $atotal) = 0 ;

# Le premier enregistrement contenant le header
($bdf_one_line[0]) = (\@entte) ;

foreach $bdf_line (<BDF>) {
	next if( $bdf_line =~ m/^Filesystem/ ) ;
	chomp $bdf_line ;

	if( $seconde_passe == 0 ){
		@bdf_temp_1  = split(' ',$bdf_line) ;
		$ref_bdf = generateur_ref_tab() ;
	}
	else {
		$seconde_passe = 0 ;
		my $bdf_temp = join(' ', @bdf_temp_1, $bdf_line) ;
		@bdf_temp_1  = split(' ',$bdf_temp) ;
	}

	($nb_elem) = $#bdf_temp_1 ;
	if( $nb_elem <= 1 ) {
		$seconde_passe = 1 ;
		next ;
	}

	# Calcul de la taille la plus grande
	if( length($bdf_temp_1[0]) > $length ) {
		$length = length($bdf_temp_1[0]) ;
	}

	# Total des valeurs
	$ttotal += $bdf_temp_1[1] ;
	$utotal += $bdf_temp_1[2] ;
	$atotal += $bdf_temp_1[3] ;

	# Valeurs calculees
	$bdf_temp_1[1] = calc_number($bdf_temp_1[1]) ;
	$bdf_temp_1[2] = calc_number($bdf_temp_1[2]) ;
	$bdf_temp_1[3] = calc_number($bdf_temp_1[3]) ;

	# On rajoute un champ pour garder l'ordre
	$bdf_temp_1[9] = $bdf_temp_1[8] ;

	# Type de FS
	$bdf_temp_1[8] = $fs_type{$bdf_temp_1[0]} ;

	# On place toute la ligne dans le tableau reference
	(@$ref_bdf) = (@bdf_temp_1) ;
	($bdf_one_line[$index]) = ($ref_bdf) ;

	# On incremente
	$index++ ;
}

if ( $index <= 1 ) {
	print "Pas de FileSysteme a afficher\n" ;
	exit(0) ;
}

#Format
my $lengthFS = $length ;
my $lengthNB = 8 ;

$index = 0 ;

my ($t, $tk, $u, $uk, $a, $ak) ;
my ($fs, $pu, $iu, $if, $pi, $mo, $ty) ;
foreach (@bdf_one_line) {
	$fs = $bdf_one_line[$index][0] ;
	$t  = $bdf_one_line[$index][1] ;
	$u  = $bdf_one_line[$index][2] ;
	$a  = $bdf_one_line[$index][3] ;
	$pu = $bdf_one_line[$index][4] ;
	$iu = $bdf_one_line[$index][5] ;
	$if = $bdf_one_line[$index][6] ;
	$pi = $bdf_one_line[$index][7] ;
	$ty = $bdf_one_line[$index][8] ;
	$mo = $bdf_one_line[$index][9] ;

	printf( "%-${lengthFS}s %${lengthNB}s %${lengthNB}s %${lengthNB}s %5s %${lengthNB}s %${lengthNB}s %6s %4s %-${lengthNB}s\n",$fs, $t, $u, $a, $pu, $iu, $if, $pi, $ty, $mo) ;
	$index++ ;
}

# On affiche pas le total s'il n'y a qu'une ligne
if ( $index > 2 ) {
	($ttotal) = calc_number($ttotal) ;
	($utotal) = calc_number($utotal) ;
	($atotal) = calc_number($atotal) ;
	printf( "%${lengthFS}s %${lengthNB}s %${lengthNB}s %${lengthNB}s\n","Total:", $ttotal, $utotal, $atotal);
}
