#!/usr/bin/perl

# dfplus - prints info from df combined with
#          info from fdisk -l

# output format:
# device type size used avail %capacity mountpoint options status

# Set a sane path

$ENV{'PATH'} = "/sbin:/usr/sbin:/bin:/usr/bin";

%labeltypenames =     ( "0", "unused",
			"4", "System V",
			"ext2", "Linux_native",
			"c", "ISO-9660",
			"swap", "Linux_swap",
			"5", "4.1BSD",
			"9", "4.4LFS",
			"d", "boot",
			"2", "Version 6",
			"6", "Eighth Edition",
			"a", "unknown",
			"e", "ADOS",
			"3", "Version 7",
			"7", "4.2BSD",
			"b", "OS/2_HPFS",
			"f", "HFS");


%partitiontypenames = ("0", "Empty",
		       "1", "DOS_12-bit_FAT",
		       "2", "XENIX_root",
		       "3", "XENIX_usr",
		       "4", "DOS_16-bit_<32M",
		       "5", "Extended",
		       "6", "DOS_16-bit_>=32",
		       "7", "OS/2_HPFS",
		       "8", "AIX",
		       "9", "AIX_bootable",
		       "a", "OPUS",
		       "40", "Venix_80286",
		       "51", "Novell",
		       "52", "Microport",
		       "63", "GNU_HURD",
		       "64", "Novell",
		       "75", "PC/IX",
		       "80", "Old_MINIX",
		       "81", "Linux/MINIX",
		       "82", "Linux_swap",
		       "83", "Linux_native",
		       "93", "Amoeba",
		       "94", "Amoeba_BBT",
		       "b7", "BSDI_fs",
		       "b8", "BSDI_swap",
		       "c7", "Syrinx",
		       "db", "CP/M",
		       "e1", "DOS_access",
		       "e3", "DOS_R/O",
		       "f2", "DOS_secondary",
		       "ff", "BBT");

open(DF, "df -aP |");
<DF>;				# skip the header
while(<DF>) {
    chop;
    split;
## This was before the -P option
#    $number_of_fields = @_;
#    if ($number_of_fields ==  1) {     # entry is continued on next line
#	$rest_of_line = <DF>;          # read next line
#	chop($rest_of_line);           # strip new line
#	$rest_of_line =~ s/^[ \t]+//;  # strip leading spaces
#	@extra_fields = split(/[ \t]+/, $rest_of_line);
#	@_ = (@_, @extra_fields);      # concatenate
#    }
    $n = $fsnames{$_[0]} = $_[0];
    ($fssize{$n}, $fsused{$n}, $fsavail{$n}, $fscapacity{$n}, $fsmounted{$n}) = @_[1,2,3,4,5];
    chop($fscapacity{$n});	# remove the % sign
}
close(DF);

open(FDISK, "fdisk -l 2> /dev/null |");
while (<FDISK>) {
    chop;
    
    if (/BSD label for.*: *(\/[^ ]+)/) {
	$bsddev = $1;
    } elsif (/^\/dev/) {
	s/\*/ /g;
	s/\+/ /g;

	split;

	$n = $fsnames{$_[0]} = $_[0];
	($fssize{$n}, $fspartitiontype{$n}) = @_[4,5];
	$fspartitiontype{$n} = $partitiontypenames{$fspartitiontype{$n}};
    } elsif (/^ *([a-z]):/) { 
	# labeled partition
	$n = $bsddev . (ord($1) - ord("a") + 1);
	$fsnames{$n} = $n;

	split;
	$fspartitiontype{$n} = $labeltypenames{@_[3]};
    }
}
close(FDISK);

open(MOUNT, "mount |");
while (<MOUNT>) {
    chop;
    split;
    $fsnames{$_[0]} = $_[0];
    $_[5] =~ /\((.*)\)/;
    $fsopts{$_[0]} = $1;
}

while (($n) = each(%fsnames)) {
    $fsmounted{$n} eq "" && ($fsmounted{$n} = "<none>");
    $fsused{$n} eq "" && ($fsused{$n} = "na");
    $fsavail{$n} eq "" && ($fsavail{$n} = "na");
    $fscapacity{$n} eq "" && ($fscapacity{$n} = "na");
    $fsopts{$n} eq "" && ($fsopts{$n} = "na");
    if ($fspartitiontype{$n} eq "") {
	$fspartitiontype{$n} = ($n =~ /:/) ? "nfs" : "unknown";
    }
}

@sortedfsnames = sort nice_order keys(%fsnames);
sub nice_order {
    return 1 if (($fsmounted{$a} eq "<none>") && ($fsmounted{$b} ne "<none>"));
    return -1 if (($fsmounted{$a} ne "<none>") && ($fsmounted{$b} eq "<none>"));
    return 1 if (($fspartitiontype{$a} eq "nfs") && ($fspartitiontype{$b} ne "nfs"));
    return -1 if (($fspartitiontype{$a} ne "nfs") && ($fspartitiontype{$b} eq "nfs"));
    if ($fsmounted{$a} eq "<none>") {
	$a cmp $b;
    } else {
	$fsmounted{$a} cmp $fsmounted{$b}
    }
}

foreach (@sortedfsnames) {
    printf "%-15s %-15s %7s %7s %7s %3s %s %s %d %d\n",
    $_, $fspartitiontype{$_}, $fssize{$_}, $fsused{$_}, $fsavail{$_}, $fscapacity{$_}, $fsmounted{$_}, $fsopts{$_};
}
