1# 2# 3# 4# Copyright (c) 1998 Alan R. Barclay. All rights reserved. This program 5# is free software; you can redistribute it and/or modify it under 6# the same terms as Perl itself. 7 8package Filesys::DiskFree; 9 10use Carp; 11use strict; 12 13#qw(); 14 15use vars qw($VERSION $Format %Df); 16 17$VERSION = 0.06; 18 19# 20# The format table 21# 22# Note, the format names are not gauranteed. If I find that there 23# is a reason to rename one, then they be renamed. 24# 25 26%Df = ( 27 'linux' => { 28 'blocks' => "df -P", 29 'inodes' => "df -Pi", 30 'format' => "linuxish", 31 }, 32 'solaris' => { 33 'blocks' => "df -k", 34 'inodes' => "df -k -o i -F ufs", 35 'format' => "svish", 36 }, 37 'bsdos' => { 38 'blocks' => "df -i", 39 'inodes' => "df -i", 40 'format' => 'bsdish', 41 }, 42 'freebsd' => { 43 'blocks' => "df -Pi", 44 'inodes' => "df -Pi", 45 'format' => 'bsdish', 46 }, 47 'irix' => { 48 'blocks' => "df", 49 'inodes' => "df -i", 50 'format' => "irixish", 51 }, 52 'hpux' => { 53 'blocks' => "bdf -l -i", 54 'inodes' => "bdf -l -i", 55 'format' => 'hpuxish', 56 }, 57 'dec_osf' => { 58 'blocks' => "df", 59 'inodes' => "df -i", 60 'format' => 'svish', 61 }, 62); 63 64use strict; 65 66BEGIN { 67 $Format = $^O; 68} 69 70sub new { 71 my $proto = shift; 72 my $class = ref($proto) || $proto; 73 my $self = { 74 FORMAT => $Format, 75 DEVICES => undef, 76 MOUNTS => undef, 77 MODE => 'blocks' 78 }; 79 80 bless ($self, $class); 81 return $self; 82} 83 84sub set(){ 85 my $self=shift; 86 my @return; 87 88 return undef if(defined $self->{'DEVICES'}); 89 90 if(@_){ 91 if($_[0] =~ m/format/i){ 92 push(@return,$self->{'FORMAT'}); 93 $self->{'FORMAT'}=$_[1] if(defined $_[1]); 94 } 95 96 if($_[0] =~ m/mode/i){ 97 push(@return,$self->{'MODE'}); 98 $self->{'MODE'}='blocks' if($_[1] =~ m/block/i and defined $_[1]); 99 $self->{'MODE'}='inodes' if($_[1] =~ m/inode/i and defined $_[1]); 100 } 101 } 102 return @return; 103} 104 105sub command () { 106 my $self=shift; 107 return $Df{"\L".$self->{'FORMAT'}."\E"}{$self->{'MODE'}}; 108} 109sub df(){ 110 my $self=shift; 111 my $cmd="df"; 112 113 $cmd=$self->command() or 114 croak "No df command known for format ".$self->{'FORMAT'}; 115 open(HANDLE,"$cmd|") or croak("Cannot fork $!"); 116 return $self->load(\*HANDLE); 117 close(HANDLE) or croak("Cannot df $!"); 118} 119 120sub load() { 121 my $self=shift; 122 my $handle=shift; 123 124 if(ref $handle eq "GLOB"){ 125 while(<$handle>){ 126 $self->readline($_); 127 } 128 } else { 129 map { $self->readline($_) } split(/$\//,$handle); 130 } 131 return 'true'; 132} 133 134sub readline() { 135 my $self=shift; 136 my $line=shift; 137 my ($device,$btotal,$bused,$bavail,$iused,$iavail,$mount, 138 $total,$used,$avail); 139 140 chomp($line); 141 142 $_=$Df{"\L".$self->{'FORMAT'}."\E"}{'format'}; 143 144 if(/linuxish/i){ 145 return undef if($line =~ /^Filesystem.*Mounted on/i); 146 ($device,$total,$used,$avail,undef,$mount)=split(' ',$line); 147 if($self->{'MODE'} eq 'blocks'){ 148 $total *= 1024; 149 $used *= 1024; 150 $avail *= 1024; 151 } 152 } elsif(/svish/i){ 153 return undef if($line =~ /^Filesystem.*Mounted on/i); 154 if($self->{'MODE'} eq 'blocks'){ 155 ($device,$total,$used,$avail,undef,$mount)=split(' ',$line); 156 $total *= 1024; 157 $used *= 1024; 158 $avail *= 1024; 159 } else { 160 ($device,$used,$avail,undef,$mount)=split(' ',$line); 161 $total=$used+$avail; 162 } 163 } elsif(/bsdish/){ 164 return undef if($line =~ /^Filesystem.*Mounted on/i); 165 ($device,$btotal,$bused,$bavail,undef,$iused,$iavail,undef,$mount)= 166 split(' ',$line); 167 if($self->{'MODE'} eq 'blocks'){ 168 $total=$btotal*512; 169 $used=$bused*512; 170 $avail=$bavail*512; 171 } elsif($self->{'MODE'} eq 'inodes'){ 172 $total=undef; 173 $used=$iused*512; 174 $avail=$iavail*512; 175 } 176 } elsif(/irixish/){ 177 return undef if($line =~ /^Filesystem.*Mounted on/i); 178 if($self->{'MODE'} eq 'blocks'){ 179 ($device,undef,$btotal,$bused,$bavail,undef,$mount)=split(' ',$line); 180 $total=$btotal*512; 181 $used=$bused*512; 182 $avail=$bavail*512; 183 } elsif($self->{'MODE'} eq 'inodes'){ 184 ($device,undef,$btotal,$bused,$bavail,undef,$iused,$iavail,undef,$mount)= 185 split(' ',$line); 186 return undef if $iused =~ /[A-Za-z]+/ or $iused == 0; 187 $total = ($iused + $iavail) * 512; 188 $used=$iused*512; 189 $avail=$iavail*512; 190 } 191 } elsif(/hpuxish/){ 192 return undef if($line =~ /^Filesystem.*Mounted on/i); 193 ($device,$btotal,$bused,$bavail,undef,$iused,$iavail,undef,$mount)= 194 split(' ',$line); 195 if($self->{'MODE'} eq 'blocks'){ 196 $total=$btotal*1024; 197 $used=$bused*1024; 198 $avail=$bavail*1024; 199 } elsif($self->{'MODE'} eq 'inodes'){ 200 $total=($iused + $iavail); 201 $used=$iused; 202 $avail=$iavail; 203 } 204 } else { 205 croak "Unknown encoding ".$Df{"\L".$self->{'FORMAT'}."\E"}{'format'}. 206 " for format ".$self->{'FORMAT'}; 207 } 208 $self->{'MOUNTS'}{$mount}=$device; 209 $self->{'DEVICES'}{$device}={}; 210 $self->{'DEVICES'}{$device}{'device'}=$device; 211 $self->{'DEVICES'}{$device}{'total'} =$total; 212 $self->{'DEVICES'}{$device}{'used'} =$used; 213 $self->{'DEVICES'}{$device}{'avail'} =$avail; 214 $self->{'DEVICES'}{$device}{'mount'} =$mount; 215} 216 217sub device() { return extract(@_,'device'); } 218sub total() { return extract(@_,'total'); } 219sub used() { return extract(@_,'used'); } 220sub avail() { return extract(@_,'avail'); } 221sub mount() { return extract(@_,'mount'); } 222 223sub extract () { 224 my $self=shift; 225 my $device; 226 if(@_) { 227 my $thingy=shift; 228 if(defined($self->{'DEVICES'}{$thingy})){ 229 $device=$thingy; 230 } else { 231 return undef unless(defined($self->{'MOUNTS'})); 232 while(not defined($self->{'MOUNTS'}{$thingy})){ 233 return undef if($thingy eq '/'); 234 $thingy =~ s!/[^/]*?$!! unless($thingy =~ s!/$!!); 235 $thingy = "/" unless($thingy =~ "/"); 236 } 237 $device=$self->{'MOUNTS'}{$thingy} 238 } 239 return $self->{'DEVICES'}{$device}{$_[0]}; 240 } 241 return undef; 242} 243 244sub disks () { 245 my $self=shift; 246 return undef unless(defined($self->{'MOUNTS'})); 247 return keys %{$self->{'MOUNTS'}}; 248} 249 2501; 251__END__ 252 253 254=head1 NAME 255 256Filesys::DiskFree -- perform the Unix command 'df' in a portable fashion 257 258=head1 SYNOPSIS 259 260 use Filesys::DiskFree; 261 262 $handle = new Filesys::DiskFree; 263 $handle->df(); 264 print "The root device is ".$handle->device("/")."\n"; 265 print "It has ".$handle->avail("/")." bytes available\n"; 266 print "It has ".$handle->total("/")." bytes total\n"; 267 print "It has ".$handle->used("/")." bytes used\n"; 268 269=head1 DESCRIPTION 270 271Filesys::DiskFree does about what the unix command df(1) does, listing 272the mounted disks, and the amount of free space used & available. 273 274=head2 Functions 275 276=over 4 277 278=item Filesys::DiskFree->set('option' => 'value') 279 280Sets various options within the module. 281 282The most common option to change is the mode, which can be either 283blocks or inodes. By default, blocks is used. 284 285If reading a file from a 'foreign' OS using the load() function, 286format may be used, which takes the name of an OS as set in the $^O 287variable. 288 289Returns the previous values of the options. 290 291=item Filesys::DiskFree->df() 292 293Perfoms a 'df' command, and stores the values for later use. 294 295=item Filesys::DiskFree->command() 296 297Returns the appropriate command to do a 'df' command, for the current 298format. This is used when you wish to call a df on a remote system. 299Use the df() method for local df's. 300 301Returns undef if there isn't an appropriate command. 302 303=item Filesys::DiskFree->load($line) 304 305Reads in the output of a 'df', $line can be either a scalar or a filehandle. 306If $line is a filehandle, then the filehandle is read until EOF. 307 308Returns undef on failure 309 310=item Filesys::DiskFree->disks() 311 312Returns all the disks known about 313 314=item Filesys::DiskFree->device($id) 315 316Returns the device for $id, which is a scalar containing the device name of 317a disk or a filename, in which case the disk that filename in stored upon 318is used. If a filename doesn't begin with '/', then it is treated as 319if is '/'. 320 321=item Filesys::DiskFree->mount($id) 322 323Returns the mount point for $id, which is a scalar containing the device 324name of a disk or a filename, in which case the disk that filename in 325stored upon is used. 326 327=item Filesys::DiskFree->avail($id) 328 329Returns the amount of available space in bytes for $id, which is a scalar 330containing the device name of a disk or a filename, in which case the 331disk that filename in stored upon is used. 332 333=item Filesys::DiskFree->total($id) 334 335Returns the amount of total space in bytes for $id, which is a scalar 336containing the device name of a disk or a filename, in which case the 337disk that filename in stored upon is used. 338 339=item Filesys::DiskFree->used($id) 340 341Returns the amount of used space in bytes for $id, which is a scalar 342containing the device name of a disk or a filename, in which case the 343disk that filename in stored upon is used. 344 345=head1 BUGS 346 347It should support more formats, currently only Linux, Irix, Solaris & 348BSD are supported. Other formats will be added as available. Please sent 349your OS Name & version, the 'best' df options to use, and the output of 350df with those options, and the contents of $^O if you have access to a 351non-supported format. 352 353=head1 AUTHOR 354 355Alan R. Barclay <gorilla@drink.com> 356