#!/usr/bin/perl

# Set default options
$opt_s=0; # 1 : Show only diskspace usage
$opt_f=0; # 1 : Show only number of files
$opt_k=0; # 1 : Show space in Kbytes, 
          # 2 : Show space in Mbytes,
          # 3 : Show space in Gbytes 

if (!$ARGV[0]) {
  print "dmdu [-s,-f] [-k|-m|-g] files\n";
  print " Prints statistics on tape/disk usage for given directories\n";
  print " Options: \n";
  print "   -s : Show space used in each subdirectory\n";
  print "   -f : Show number of files in each directory\n";
  print "   -k : Show space in Kbytes\n"; 
  print "   -m : Show space in Mbytes\n";
  print "   -g : Show space in Gbytes\n";
  print " The default is to print a summary for the given directory(tree), with\n";
  print " size in bytes.\n";
  print " Space conversion between b/Kb/Mb/Gb is in 1024-base.\n";
  print " Note that space size and number of files include those that are found\n";
  print " both \"On disk\" and \"On tape\", but only counted once in \"Total\".\n";
  print " The numbers written by -s and -f do not include content of subdirectories.\n";
  print " Requires that dmls is in search path\n";
  print " This program is not very efficient or robust, improvements are welcomed\n";
  print "\n Written by Arild Burud, July 2001\n"; 
  print " arild.burud\@dnmi.no\n";

  
} else {
  while ($f = $ARGV[0]) {
    chomp($f);

#    print "argv0=" , $f , "\n";

    if ($f eq "-s") {
	$opt_s=1;
    } elsif ($f eq "-f") {
	$opt_f=1;
    } elsif ($f eq "-k") {
	$opt_k=1;
    } elsif ($f eq "-m") {
	$opt_k=2;
    } elsif ($f eq "-g") {
	$opt_k=3;
    } else {
    $sumreg = 0;    # Total diskspace used
    $sumofl = 0;    # Total tapespace used
    $sumdul = 0;    # Total space only for files both on disk and on tape
    $sumtot = 0;    # Total space for all files
    $nfreg=0;       # Total number files on disk
    $nfofl=0;       # Total number files on tape
    $nfdul=0;       # Total number files only on disk and tape
    $nfoth=0;       # Total number files otherwise
    $nftot=0;       # Total number files alltogether
    $nfdir=0;       # Total number of directories

    print "\n";
    #      123456789 123456789 123456789 xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 
    print " Total     On disk   On tape      Directory\n";

    traverse_dir($f);
    
    # Separate gross total from the rest with a blank line
    print "\n";
    # First print for space
    view_stat($sumtot,$sumreg,$sumofl,$opt_k,$f);
    # then for files/directories
    view_stat($nftot,$nfreg,$nfofl,-1,$nfdir);

    }

    shift;
  }
}

# Method to print statistics :

sub view_stat {
    # Take arguments 
    local($total,$ondisk,$ontape,$opt,$dirname)=@_;
       # Print space statistics for directory

           if ( $opt == 1 ) {
	       $type="Kb";
	       $total/=1024;
	       $ondisk/=1024;
	       $ontape/=1024;
	   }
           elsif ( $opt == 2 ) {
	       $type="Mb";
	       $total/=(1024*1024);
	       $ondisk/=(1024*1024);
	       $ontape/=(1024*1024);
	   }
           elsif ( $opt == 3 ) {
	       $type="Gb";
	       $total/=(1024*1024*1024);
	       $ondisk/=(1024*1024*1024);
	       $ontape/=(1024*1024*1024);
	   }
           elsif ( $opt == 0 ) { 
               $type="b";
           }
           # Special case for files/directories statistics
           elsif ( $opt == -1 ) {
               $type="#";
               if ($dirname == 1) { 
                   $text=sprintf("files and %d directory",$dirname); 
               }
               elsif ($dirname > 1) {
                   $text=sprintf("files and %d directories",$dirname); 
               }
               else {
                   $text="files "; 
               }
               $dirname=$text;               
      	   }

           $output=sprintf("%9.0f %9.0f %9.0f %2s %s",$total,$ondisk,$ontape,$type,$dirname);
           print "$output\n";

}

sub traverse_dir {
  local($f)=@_;   # input argument
  local($dreg)=0;
  local($dofl)=0;
  local($ddul)=0;
  local($doth)=0;
  local($dtot)=0;
  local($dftot)=0;
  local($dfreg)=0;
  local($dfofl)=0;
  local($dfdir)=0;
  local($dfdul)=0;
  local($dfoth)=0;

  if (-d $f) {
#   print "opening $f \n";

   open(DIRLIS,"dmls -lRa $f |");
   @dir = <DIRLIS>;
   close(DIRLIS);
#   print "dir: ",@dir,"\n";

   $i=0;
   $current=$f;
   while ($dir[$i]){
   # Skip first line ("total xxx")
   if ($line = $dir[$i]) {
       $i++;
       # Read each filename
       while ($line = $dir[$i]) {
#          print "line ",$i,":",$line;
          chomp($line);
          @ord=split(/ +/,$line);
          if (!$ord[8]) { last; }
#	  print "ord:",$ord[0],"/",$ord[4],"/",$ord[8],"/",$ord[9],"\n";
          # Skip current and parent directory in stat's
          if (!($ord[9] eq ".") && !($ord[9] eq "..")) {
          # Count number of directories
          if (substr($ord[0],0,1) eq "d") { $dfdir++; } 
          if ($ord[8] eq "(REG)") {
	      $dreg+=$ord[4];
	      if (substr($ord[0],0,1) ne "d") { $dfreg++; } }
          elsif ($ord[8] eq "(OFL)") {
              $dofl+=$ord[4]; 
              if (substr($ord[0],0,1) ne "d") { $dfofl++; } }
          elsif ($ord[8] eq "(DUL)") {
              $ddul+=$ord[4]; 
              if (substr($ord[0],0,1) ne "d") { $dfdul++; } }
          else {
	      if (substr($ord[0],0,1) ne "d") { $dfoth++; } }
      }
          $i++; 
      }
       # Complete total statistics
       $dtot=$dreg+$dofl+$ddul+$doth;
       $dftot=$dfreg+$dfofl+$dfdul+$dfoth;
       $sumreg+=$dreg+$ddul;
       $sumofl+=$dofl+$ddul;
       $sumdul+=$ddul;
       $sumoth+=$doth;
       $sumtot+=$dreg+$dofl+$ddul+$doth;
       $nfdir+=$dfdir;
       $nfreg+=$dfreg+$dfdul;
       $nfofl+=$dfofl+$dfdul;
       $nfdul+=$dfdul;
       $nfoth+=$dfoth;
       $nftot+=$dfreg+$dfofl+$dfdul+$dfoth;

       # Print space statistics for each directory?
       if ($opt_s) {
           view_stat($dtot,($dreg+$ddul),($dofl+$ddul),$opt_k,$current);
       }
       # Print file number statistics for each directory?
       if ($opt_f) {
           view_stat($dftot,($dfreg+$dfdul),($dfofl+$dfdul),-1,$dfdir);
       }

       $dreg=0;
       $dofl=0;
       $ddul=0;
       $dfreg=0;
       $dfofl=0;
       $dfdul=0;
       $dfoth=0;
       $dfdir=0;

       # Get next directory name - if any
       if (!$ord[0]) { $i++; }
       $line = $dir[$i];
       chomp($line);
       chop($line); # delete ":"
       $current=$line;
       if (! $current) { last; }
       $i++;
   }
}

  } else {
      die " No such directory: $f \n";
  }  
  
}


























