File Coverage

lib/Filesys/DiskSpace.pm
Criterion Covered Total %
statement 15 72 20.8
branch 0 34 0.0
condition 0 24 0.0
subroutine 5 6 83.3
pod 0 1 0.0
total 20 137 14.6


line stmt bran cond sub pod time code
1             # -*- Mode: Perl -*-
2              
3             package Filesys::DiskSpace;
4              
5 5     5   2480 use strict;
  5         8  
  5         182  
6 5     5   25 use vars qw(@ISA @EXPORT $VERSION $DEBUG);
  5         8  
  5         426  
7 5     5   25 use Exporter;
  5         11  
  5         199  
8 5     5   24 use Config;
  5         9  
  5         209  
9 5     5   22 use Carp;
  5         10  
  5         4983  
10             require 5.003;
11              
12             @ISA = qw(Exporter);
13             @EXPORT = qw(df);
14             $VERSION = "0.05";
15              
16             # known FS type numbers
17             my %fs_type = (
18             0 => "4.2", # 0x00000000
19             256 => "UFS", # 0x00000100
20             2560 => "ADVFS", # 0x00000A00
21             4989 => "EXT_SUPER_MAGIC", # 0x0000137D
22             4991 => "MINIX_SUPER_MAGIC", # 0x0000137F
23             5007 => "MINIX_SUPER_MAGIC2", # 0x0000138F
24             9320 => "MINIX2_SUPER_MAGIC", # 0x00002468
25             9336 => "MINIX2_SUPER_MAGIC2", # 0x00002478
26             19780 => "MSDOS_SUPER_MAGIC", # 0x00004d44
27             20859 => "SMB_SUPER_MAGIC", # 0x0000517B
28             22092 => "NCP_SUPER_MAGIC", # 0x0000564c
29             26985 => "NFS_SUPER_MAGIC", # 0x00006969
30             38496 => "ISOFS_SUPER_MAGIC", # 0x00009660
31             40864 => "PROC_SUPER_MAGIC", # 0x00009fa0
32             44543 => "AFFS_SUPER_MAGIC", # 0x0000ADFF
33             61265 => "EXT2_OLD_SUPER_MAGIC", # 0x0000EF51
34             61267 => "EXT2_SUPER_MAGIC", # 0x0000EF53
35             72020 => "UFS_MAGIC", # 0x00011954
36             19911021 => "_XIAFS_SUPER_MAGIC", # 0x012FD16D
37             19920820 => "XENIX_SUPER_MAGIC", # 0x012FF7B4
38             19920821 => "SYSV4_SUPER_MAGIC", # 0x012FF7B5
39             19920822 => "SYSV2_SUPER_MAGIC", # 0x012FF7B6
40             19920823 => "COH_SUPER_MAGIC", # 0x012FF7B7
41             4187351113 => "HPFS_SUPER_MAGIC", # 0xF995E849
42             );
43              
44             sub df ($) {
45 0     0 0   my $dir = shift;
46              
47 0           my ($fmt, $res, $type, $flags, $osvers, $w);
48              
49             # struct fields for statfs or statvfs....
50 0           my ($bsize, $frsize, $blocks, $bfree, $bavail, $files, $ffree, $favail);
51              
52 0 0         Carp::croak "Usage: df '\$dir'" unless $dir;
53 0 0         Carp::croak "Error: $dir is not a directory" unless -d $dir;
54              
55             # try with statvfs..
56             eval { # will work for Solaris 2.*, OSF1 v3.2, OSF1 v4.0 and HP-UX 10.*.
57             {
58 0           package main;
59 0           require "sys/syscall.ph";
60             }
61 0           $fmt = "\0" x 512;
62 0           $res = syscall (&main::SYS_statvfs, $dir, $fmt) ;
63 0           ($bsize, $frsize, $blocks, $bfree, $bavail, $files, $ffree, $favail) =
64             unpack "L8", $fmt;
65             # bsize: fundamental file system block size
66             # frsize: fragment size
67             # blocks: total blocks of frsize on fs
68             # bfree: total free blocks of frsize
69             # bavail: free blocks avail to non-superuser
70             # files: total file nodes (inodes)
71             # ffree: total free file nodes
72             # favail: free nodes avail to non-superuser
73              
74             # to stay ok with statfs..
75 0           $type = 0; # should we try to read it from the structure ? it looks
76             # possible at least under Solaris.
77 0           $ffree = $favail;
78 0           $bsize = $frsize;
79             # $blocks -= $bfree - $bavail;
80 0 0         $res == 0 && defined $fs_type{$type};
81             }
82             # try with statfs..
83             || eval { # will work for SunOS 4, Linux 2.0.* and 2.2.*
84             {
85 0           package main;
86 0           require "sys/syscall.ph";
87             }
88 0           $fmt = "\0" x 512;
89 0           $res = syscall (&main::SYS_statfs, $dir, $fmt);
90             # statfs...
91              
92 0 0         if ($^O eq 'freebsd') {
93             # only tested with FreeBSD 3.0. Should also work with 4.0.
94 0           my ($f1, $f2);
95 0           ($f1, $bsize, $f2, $blocks, $bfree, $bavail, $files, $ffree) =
96             unpack "L8", $fmt;
97 0           $type = 0; # read it from 'f_type' field ?
98             }
99             else {
100 0           ($type, $bsize, $blocks, $bfree, $bavail, $files, $ffree) =
101             unpack "L7", $fmt;
102             }
103             # type: type of filesystem (see below)
104             # bsize: optimal transfer block size
105             # blocks: total data blocks in file system
106             # bfree: free blocks in fs
107             # bavail: free blocks avail to non-superuser
108             # files: total file nodes in file system
109             # ffree: free file nodes in fs
110              
111 0 0         $res == 0 && defined $fs_type{$type};
112             }
113             || eval {
114             {
115 0           package main;
116 0           require "sys/syscall.ph";
117             }
118             # The previous try gives an unknown fs type, it must be a different
119             # structure format..
120 0           $fmt = "\0" x 512;
121             # Try this : n2i7L119
122 0           $res = syscall (&main::SYS_statfs, $dir, $fmt);
123 0           ($type, $flags, $bsize, $frsize, $blocks,
124             $bfree, $bavail, $files, $ffree) = unpack "n2i7", $fmt;
125 0 0         $res == 0 && defined $fs_type{$type};
126             }
127             # Neither statfs nor statvfs.. too bad.
128 0 0 0       || eval {
      0        
      0        
129 0           $osvers = $Config{'osvers'};
130 0           $w = 0;
131             # These system normaly works but there was a problem...
132             # Trying to inform the user...
133 0 0 0       if ($^O eq 'solaris' || $^O eq 'dec_osf') {
134             # Tested. No problem if syscall.ph is present.
135 0           warn "An error occured. statvfs failed. Did you run h2ph?\n";
136 0           $w = 2;
137             }
138 0 0 0       if ($^O eq 'linux' || $^O eq 'freebsd') {
139             # Tested with linux 2.0.0 and 2.2.2
140             # No problem if syscall.ph is present.
141 0           warn "An error occured. statfs failed. Did you run h2ph?\n";
142             }
143 0 0         if ($^O eq 'hpux') {
144 0 0         if ($osvers == 9) {
    0          
145             # Tested. You have to change a line in syscall.ph.
146 0           warn "An error occured. statfs failed. Did you run h2ph?\n" .
147             "If you are using a hp9000s700, see the Df documentation\n";
148             }
149             elsif ($osvers == 10) {
150             # Tested. No problem if syscall.ph is present.
151 0           warn "An error occured. statvfs failed. Did you run h2ph?\n";
152             }
153             else {
154             # Untested
155 0           warn "An error occured. df failed. Please, submit a bug report.\n";
156             }
157 0           $w = 3;
158             }
159 0           $w;
160             }
161             || Carp::croak "Cannot use df on this machine (untested or unsupported).";
162              
163 0 0 0       exit if defined $w && $w > 0;
164              
165 0           $blocks -= $bfree - $bavail;
166              
167 0 0         if ($files == $ffree) {
168 0           $files = 1;
169 0           $ffree = 0;
170             }
171              
172 0 0 0       warn "Warning : type $fs_type{$type} untested.. results may be incorrect\n"
173             unless $type != 2560 && defined $fs_type{$type};
174              
175 0 0         if ($DEBUG) {
176 0           warn "Fs type : [$type] $fs_type{$type}\n" .
177             "total space : ", $blocks * $bsize / 1024, " Kb\n" .
178             "available space : ", $bavail * $bsize / 1024, " Kb\n\n";
179 0 0 0       if ($files == 1 && $ffree == 0) {
180 0           warn "inodes : no information available\n";
181             }
182             else {
183 0           warn "inodes : $files\nfree inodes : $ffree\n" .
184             "used inodes : ", $files - $ffree, "\n";
185             }
186             }
187              
188 0           ($type, $fs_type{$type}, ($blocks - $bavail) * $bsize / 1024,
189             $bavail * $bsize / 1024, $files - $ffree, $ffree);
190             }
191              
192             1;
193              
194             =head1 NAME
195              
196             Filesys::DiskSpace - Perl df
197              
198             =head1 SYNOPSIS
199              
200             use Filesys::DiskSpace;
201             ($fs_type, $fs_desc, $used, $avail, $fused, $favail) = df $dir;
202              
203             =head1 DESCRIPTION
204              
205             This routine displays information on a file system such as its type, the
206             amount of disk space occupied, the total disk space and the number of inodes.
207             It tries C and C in several ways.
208             If all fails, it Cs.
209              
210             =head1 OPTIONS
211              
212             =over 4
213              
214             =item $fs_type
215              
216             [number] type of the filesystem.
217              
218             =item $fs_desc
219              
220             [string] description of this fs.
221              
222             =item $used
223              
224             [number] size used (in Kb).
225              
226             =item $avail
227              
228             [number] size available (in Kb).
229              
230             =item $ffree
231              
232             [number] free inodes.
233              
234             =item $fused
235              
236             [number] inodes used.
237              
238             =back
239              
240             =head1 Installation
241              
242             See the INSTALL file.
243              
244             =head1 COPYRIGHT
245              
246             Copyright (c) 1996-1999 Fabien Tassin. All rights reserved.
247             This program is free software; you can redistribute it and/or
248             modify it under the same terms as Perl itself.
249              
250             =head1 AUTHOR
251              
252             Fabien Tassin Efta@oleane.netE
253              
254             =head1 NOTES
255              
256             This module was formerly called File::Df. It has been renamed into
257             Filesys::DiskSpace. It could have be Filesys::Df but unfortunatly
258             another module created in the meantime uses this name.
259              
260             Tested with Perl 5.003 under these systems :
261              
262             - Solaris 2.[4/5]
263             - SunOS 4.1.[2/3/4]
264             - HP-UX 9.05, 10.[1/20] (see below)
265             - OSF1 3.2, 4.0
266             - Linux 2.0.*, 2.2.*
267              
268             Note for HP-UX users :
269              
270             if you obtain this message :
271             "Undefined subroutine &main::SYS_statfs called at Filesys/DiskSpace.pm
272             line XXX" and if you are using a hp9000s700, then edit the syscall.ph file
273             (in the Perl lib tree) and copy the line containing "SYS_statfs {196;}"
274             outside the "if (defined &__hp9000s800)" block (around line 356).
275              
276             =cut