File Coverage

blib/lib/Sys/Filesystem.pm
Criterion Covered Total %
statement 96 109 88.0
branch 38 58 65.5
condition 22 32 68.7
subroutine 20 25 80.0
pod 7 9 77.7
total 183 233 78.5


line stmt bran cond sub pod time code
1             ############################################################
2             #
3             # $Id$
4             # Sys::Filesystem - Retrieve list of filesystems and their properties
5             #
6             # Copyright 2004,2005,2006 Nicola Worthington
7             # Copyright 2008,2009 Jens Rehsack
8             #
9             # Licensed under the Apache License, Version 2.0 (the "License");
10             # you may not use this file except in compliance with the License.
11             # You may obtain a copy of the License at
12             #
13             # http://www.apache.org/licenses/LICENSE-2.0
14             #
15             # Unless required by applicable law or agreed to in writing, software
16             # distributed under the License is distributed on an "AS IS" BASIS,
17             # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18             # See the License for the specific language governing permissions and
19             # limitations under the License.
20             #
21             ############################################################
22              
23             package Sys::Filesystem;
24              
25             # vim:ts=4:sw=4:tw=78
26              
27 6     6   167575 use 5.008001;
  6         28  
  6         300  
28              
29             my @query_order;
30              
31 6     6   39 use strict;
  6         13  
  6         220  
32 6     6   41 use warnings;
  6         14  
  6         307  
33 6     6   35 use vars qw($VERSION $AUTOLOAD $CANONDEV $FSTAB $MTAB);
  6         12  
  6         775  
34 6     6   43 use Carp qw(croak cluck confess);
  6         11  
  6         1260  
35             use Module::Pluggable
36 18         97 require => 1,
37 6 50       81 only => [ @query_order = map { __PACKAGE__ . '::' . $_ } ( ucfirst( lc $^O ), $^O =~ m/Win32/i ? 'Win32' : 'Unix', 'Dummy' ) ],
38             inner => 0,
39             search_path => ['Sys::Filesystem'],
40 6     6   5556 sub_name => '_plugins';
  6         104385  
41 6     6   6424 use Params::Util qw(_INSTANCE);
  6         43861  
  6         612  
42 6     6   55 use Scalar::Util qw(blessed);
  6         14  
  6         265  
43 6     6   34 use List::Util qw(first);
  6         13  
  6         738  
44              
45 6 50   6   620 use constant DEBUG => $ENV{SYS_FILESYSTEM_DEBUG} ? 1 : 0;
  6         11  
  6         558  
46 6 50   6   31 use constant SPECIAL => ( 'darwin' eq $^O ) ? 0 : undef;
  6         9  
  6         786  
47              
48             $VERSION = '1.406';
49              
50             my ( $FsPlugin, $Supported );
51              
52             BEGIN
53             {
54 6     6   57 Sys::Filesystem->_plugins();
55              
56 6         22559 foreach my $qo (@query_order)
57             {
58 6 50       67 next unless ( UNIVERSAL::isa( $qo, $qo ) );
59 6         16 $FsPlugin = $qo;
60 6         16 last;
61             }
62              
63 6 50       9868 $Supported = $FsPlugin ne 'Sys::Filesystem::Unix' and $FsPlugin ne 'Sys::Filesystem::Dummy';
64             }
65              
66             sub new
67             {
68             # Check we're being called correctly with a class name
69 12 100   12 1 13533 ref( my $class = shift ) and croak 'Class name required';
70              
71             # Check we've got something sane passed
72 11 100       174 croak 'Odd number of elements passed when even number was expected' if ( @_ % 2 );
73 10         34 my %args = @_;
74              
75 10 50 33     366 exists $args{xtab} and carp("Using xtab is depreciated") and delete $args{xtab};
76 10 50 33     146 defined $FSTAB and not exists $args{fstab} and $args{fstab} = $FSTAB;
77 10 50 33     49 defined $MTAB and not exists $args{mtab} and $args{mtab} = $MTAB;
78 10 100 66     57 defined $CANONDEV and not exists $args{canondev} and $args{canondev} = $CANONDEV;
79              
80             # Double check the key pairs for stuff we recognise
81 10         52 my @sane_keys = qw(aliases canondev fstab mtab);
82 10         23 my %sane_args;
83 10         104 @sane_args{@sane_keys} = delete @args{@sane_keys};
84 10 100       199 scalar keys %args and croak( "Unrecognised parameter(s) '" . join( "', '", sort keys %args ) . "' passed to module $class" );
85              
86 9         49 my $self = {%sane_args};
87              
88             # Filesystem property aliases - unless caller knows better ...
89 9 50       277 defined $self->{aliases}
90             or $self->{aliases} = {
91             device => [qw(fs_spec dev)],
92             filesystem => [qw(fs_file mount_point)],
93             mount_point => [qw(fs_file filesystem)],
94             type => [qw(fs_vfstype vfs)],
95             format => [qw(fs_vfstype vfs vfstype)],
96             options => [qw(fs_mntops)],
97             check_frequency => [qw(fs_freq)],
98             check_order => [qw(fs_passno)],
99             boot_order => [qw(fs_mntno)],
100             volume => [qw(fs_volume fs_vol vol)],
101             label => [qw(fs_label)],
102             };
103              
104             # Debug
105 9         197 DUMP( '$self', $self ) if (DEBUG);
106              
107 9         108 $self->{filesystems} = $FsPlugin->new(%sane_args);
108              
109             # Maybe upchuck a little
110 9 50       49 croak "Unable to create object for OS type '$self->{osname}'" unless ( $self->{filesystems} );
111              
112             # Bless and return
113 9         34 bless( $self, $class );
114 9         64 return $self;
115             }
116              
117             sub filesystems
118             {
119 14     14 1 1182 my $self = shift;
120 14 100       151 unless ( defined( _INSTANCE( $self, __PACKAGE__ ) ) )
121             {
122 1 50       8 unshift @_, $self unless ( 0 == ( scalar(@_) % 2 ) );
123 1         8 $self = __PACKAGE__->new();
124             }
125              
126             # Check we've got something sane passed
127 14 50       48 @_ % 2 and croak 'Odd number of elements passed when even number was expected';
128              
129 14         124 my $params = {@_};
130 14         30 for my $param ( keys %{$params} )
  14         53  
131             {
132 9 50       184 croak "Illegal paramater '$param' passed to filesystems() method"
133             unless grep( m/^$param$/, qw(mounted unmounted special device regular) );
134             }
135              
136             # Invert logic for regular
137 14 50       48 if ( exists $params->{regular} )
138             {
139 0         0 delete $params->{regular};
140 0 0       0 exists( $params->{special} )
141             and carp("Mutual exclusive parameters 'special' and 'regular' specified together");
142 0         0 $params->{special} = SPECIAL;
143             }
144              
145 14         26 my @filesystems = ();
146              
147             # Return list of all filesystems
148 14 100       19 keys %{$params} or return sort( keys( %{ $self->{filesystems} } ) );
  5         105  
  14         45  
149              
150 9         15 for my $fsname ( sort( keys( %{ $self->{filesystems} } ) ) )
  9         124  
151             {
152 153         168 for my $requirement ( keys( %{$params} ) )
  153         241  
153             {
154 153         208 my $fs = $self->{filesystems}->{$fsname};
155             my $fsreqname =
156             ( !exists $fs->{$requirement} and exists $self->{aliases}->{$requirement} )
157 153 50 66 0   1220 ? first { exists $fs->{$_} } @{ $self->{aliases}->{$requirement} }
  0         0  
  0         0  
158             : $requirement;
159              
160 153 100 100     1071 defined $params->{$requirement}
      100        
      66        
161             and exists $fs->{$fsreqname}
162             and $fs->{$fsreqname} eq $params->{$requirement}
163             and push( @filesystems, $fsname )
164             and last;
165 79 100 50     385 push( @filesystems, $fsname ) and last
      100        
166             unless defined( $params->{$requirement} )
167             or exists( $fs->{$fsreqname} );
168             }
169             }
170              
171             # Return
172 9         106 return @filesystems;
173             }
174              
175             sub supported
176             {
177 0     0 1 0 return $Supported;
178             }
179              
180             sub mounted_filesystems
181             {
182 1     1 1 1040 return $_[0]->filesystems( mounted => 1 );
183             }
184              
185             sub unmounted_filesystems
186             {
187 1     1 1 417 return $_[0]->filesystems( unmounted => 1 );
188             }
189              
190             sub special_filesystems
191             {
192 2     2 1 484 return $_[0]->filesystems( special => 1 );
193             }
194              
195             sub regular_filesystems
196             {
197 2     2 1 14 return $_[0]->filesystems( special => SPECIAL );
198             }
199              
200 0     0   0 sub DESTROY { }
201              
202             sub AUTOLOAD
203             {
204 222     222   76409 my ( $self, $fsname ) = @_;
205              
206 222 50       793 croak "$self is not an object" unless ( blessed($self) );
207 222 50       475 croak "No filesystem passed where expected" unless ($fsname);
208              
209 222         1016 ( my $name = $AUTOLOAD ) =~ s/.*://;
210              
211             # No such filesystem
212 222 50       608 exists $self->{filesystems}->{$fsname} or croak "No such filesystem";
213              
214             # Found the property
215 222         443 my $fs = $self->{filesystems}->{$fsname};
216              
217 222 100       807 exists $fs->{$name} and return $fs->{$name};
218              
219             # Didn't find the property, but check any aliases
220             exists $self->{aliases}->{$name}
221 97 100 100 119   575 and $name = first { exists $fs->{$_} } @{ $self->{aliases}->{$name} }
  119         559  
  85         259  
222             and return $fs->{$name};
223              
224 46         158 return;
225             }
226              
227             sub TRACE
228             {
229 0     0 0   return unless DEBUG;
230 0           warn( $_[0] );
231             }
232              
233             sub DUMP
234             {
235 0     0 0   return unless DEBUG;
236 0           eval {
237 0           require Data::Dumper;
238 0           warn( shift() . ': ' . Data::Dumper::Dumper( shift() ) );
239             };
240             }
241              
242             1;
243              
244             =pod
245              
246             =head1 NAME
247              
248             Sys::Filesystem - Retrieve list of filesystems and their properties
249              
250             =head1 SYNOPSIS
251              
252             use strict;
253             use Sys::Filesystem ();
254            
255             # Method 1
256             my $fs = Sys::Filesystem->new();
257             my @filesystems = $fs->filesystems();
258             for (@filesystems)
259             {
260             printf("%s is a %s filesystem mounted on %s\n",
261             $fs->mount_point($_),
262             $fs->format($_),
263             $fs->device($_)
264             );
265             }
266            
267             # Method 2
268             my $weird_fs = Sys::Filesystem->new(
269             fstab => '/etc/weird/vfstab.conf',
270             mtab => '/etc/active_mounts',
271             xtab => '/etc/nfs/mounts'
272             );
273             my @weird_filesystems = $weird_fs->filesystems();
274            
275             # Method 3 (nice but naughty)
276             my @filesystems = Sys::Filesystem->filesystems();
277              
278             =head1 DESCRIPTION
279              
280             Sys::Filesystem is intended to be a portable interface to list and query
281             filesystem names and their properties. At the time of writing there were only
282             Solaris and Win32 modules available on CPAN to perform this kind of operation.
283             This module hopes to provide a consistent API to list all, mounted, unmounted
284             and special filesystems on a system, and query as many properties as possible
285             with common aliases wherever possible.
286              
287             =head1 INHERITANCE
288              
289             Sys::Filesystem
290             ISA UNIVERSAL
291              
292             =head1 METHODS
293              
294             =over 4
295              
296             =item new
297              
298             Creates a new Sys::Filesystem object. C accepts following optional key
299             value pairs to help or force where mount information is gathered from. These
300             values are not otherwise defaulted by the main Sys::Filesystem object, but
301             left to the platform specific helper modules to determine as an exercise of
302             common sense.
303              
304             =over 4
305              
306             =item canondev
307              
308             Specify whether device path's shall be resolved when they're a symbolic
309             link.
310              
311             C<$Sys::Filesystem::CANONDEV> is used when no key C is passed.
312              
313             =item fstab
314              
315             Specify the full path and filename of the filesystem table (or fstab for
316             short). Not all platforms have such a file and so this option may be
317             ignored on some systems.
318              
319             C<$Sys::Filesystem::FSTAB> is used when no key C is passed.
320              
321             =item mtab
322              
323             Specify the full path and filename of the mounted filesystem table (or mtab
324             for short). Not all platforms have such a file and so this option may be
325             ignored on some systems.
326              
327             C<$Sys::Filesystem::MTAB> is used when no key C is passed.
328              
329             =item xtab
330              
331             B Specify the full path and filename of the mounted NFS
332             filesystem table (or xtab for short). This is usually only pertinant
333             to Unix bases systems. Not all helper modules will query NFS mounts
334             as a separate exercise, and therefore this option may be ignored on
335             some systems.
336              
337             B of the OS plugins use that tunable (anymore?), so it now a warning
338             is raised when it's used. The entire support will be removed not before
339             2015. Once that happened, using C will raise an exception.
340              
341             =item aliases
342              
343             Overrides internal aliasing table used to match queries against OS
344             plugin. This should be used only when dealing with closed source platform
345             helper module(s).
346              
347             =back
348              
349             =item supported
350              
351             Returns true if the operating system is supported by Sys::Filesystem.
352             Unsupported operating systems may get less information, e.g. the mount
353             state couldn't determined or which file system type is special ins't
354             known.
355              
356             =back
357              
358             =head2 Listing Filesystems
359              
360             =over 4
361              
362             =item filesystems()
363              
364             Returns a list of all filesystem. May accept an optional list of key pair
365             values in order to filter/restrict the results which are returned. The
366             restrictions are evaluated to match as much as possible, so asking for
367             regular and special file system (or mounted and special file systems),
368             you'll get all.
369              
370             For better understanding, please imagine the parameters like:
371              
372             @fslist = $fs->filesystems( mounted => 1, special => 1 );
373             # results similar as
374             SELECT mountpoint FROM filesystems WHERE mounted = 1 OR special = 1
375              
376             If you need other selection choices, please take a look at L.
377              
378             Valid values are as follows:
379              
380             =over 4
381              
382             =item device => "string"
383              
384             Returns only filesystems that are mounted using the device of "string".
385             For example:
386              
387             my $fdd_filesytem = Sys::Filesystem->filesystems(device => "/dev/fd0");
388              
389             =item mounted => 1
390              
391             Returns only filesystems which can be confirmed as actively mounted.
392             (Filesystems which are mounted).
393              
394             The mounted_filesystems() method is an alias for this syntax.
395              
396             =item unmounted => 1
397              
398             Returns only filesystems which cannot be confirmed as actively mounted.
399             (Filesystems which are not mounted).
400              
401             The unmounted_filesystems() method is an alias for this syntax.
402              
403             =item special => 1
404              
405             Returns only filesystems which are regarded as special in some way. A
406             filesystem is marked as special by the operating specific helper
407             module. For example, a tmpfs type filesystem on one operating system
408             might be regarded as a special filesystem, but not on others. Consult
409             the documentation of the operating system specific helper module for
410             further information about your system. (Sys::Filesystem::Linux for Linux
411             or Sys::Filesystem::Solaris for Solaris etc).
412              
413             This parameter is mutually exclusive to C.
414              
415             The special_filesystems() method is an alias for this syntax.
416              
417             =item regular => 1
418              
419             Returns only fileystems which are not regarded as special. (Normal
420             filesystems).
421              
422             This parameter is mutually exclusive to C.
423              
424             The regular_filesystems() method is an alias for this syntax.
425              
426             =back
427              
428             =item mounted_filesystems()
429              
430             Returns a list of all filesystems which can be verified as currently
431             being mounted.
432              
433             =item unmounted_filesystems()
434              
435             Returns a list of all filesystems which cannot be verified as currently
436             being mounted.
437              
438             =item special_filesystems()
439              
440             Returns a list of all fileystems which are considered special. This will
441             usually contain meta and swap partitions like /proc and /dev/shm on Linux.
442              
443             =item regular_filesystems()
444              
445             Returns a list of all filesystems which are not considered to be special.
446              
447             =back
448              
449             =head2 Filesystem Properties
450              
451             Available filesystem properties and their names vary wildly between platforms.
452             Common aliases have been provided wherever possible. You should check the
453             documentation of the specific platform helper module to list all of the
454             properties which are available for that platform. For example, read the
455             Sys::Filesystem::Linux documentation for a list of all filesystem properties
456             available to query under Linux.
457              
458             =over 4
459              
460             =item mount_point() or filesystem()
461              
462             Returns the friendly name of the filesystem. This will usually be the same
463             name as appears in the list returned by the filesystems() method.
464              
465             =item mounted()
466              
467             Returns boolean true if the filesystem is mounted.
468              
469             =item label()
470              
471             Returns the fileystem label.
472              
473             This functionality may need to be retrofitted to some original OS specific
474             helper modules as of Sys::Filesystem 1.12.
475              
476             =item volume()
477              
478             Returns the volume that the filesystem belongs to or is mounted on.
479              
480             This functionality may need to be retrofitted to some original OS specific
481             helper modules as of Sys::Filesystem 1.12.
482              
483             =item device()
484              
485             Returns the physical device that the filesystem is connected to.
486              
487             =item special()
488              
489             Returns boolean true if the filesystem type is considered "special".
490              
491             =item type() or format()
492              
493             Returns the type of filesystem format. fat32, ntfs, ufs, hpfs, ext3, xfs etc.
494              
495             =item options()
496              
497             Returns the options that the filesystem was mounted with. This may commonly
498             contain information such as read-write, user and group settings and
499             permissions.
500              
501             =item mount_order()
502              
503             Returns the order in which this filesystem should be mounted on boot.
504              
505             =item check_order()
506              
507             Returns the order in which this filesystem should be consistency checked
508             on boot.
509              
510             =item check_frequency()
511              
512             Returns how often this filesystem is checked for consistency.
513              
514             =back
515              
516             =head1 OS SPECIFIC HELPER MODULES
517              
518             =head2 Dummy
519              
520             The Dummy module is there to provide a default failover result to the main
521             Sys::Filesystem module if no suitable platform specific module can be found
522             or successfully loaded. This is the last module to be tried, in order of
523             platform, Unix (if not on Win32), and then Dummy.
524              
525             =head2 Unix
526              
527             The Unix module is intended to provide a "best guess" failover result to the
528             main Sys::Filesystem module if no suitable platform specific module can be
529             found, and the platform is not 'MSWin32'.
530              
531             This module requires additional work to improve it's guestimation abilities.
532              
533             =head2 Darwin
534              
535             First written by Christian Renz .
536              
537             =head2 Win32
538              
539             Provides C and C of mounted filesystems on Windows.
540              
541             =head2 AIX
542              
543             Please be aware that the AIX /etc/filesystems file has both a "type" and
544             "vfs" field. The "type" field should not be confused with the filesystem
545             format/type (that is stored in the "vfs" field). You may wish to use the
546             "format" field when querying for filesystem types, since it is aliased to
547             be more reliable accross different platforms.
548              
549             =head2 Other
550              
551             Linux, Solaris, Cygwin, FreeBSD, NetBSD, HP-UX.
552              
553             =head2 OS Identifiers
554              
555             The following list is taken from L. Please refer to the original
556             source for the most up to date version. This information should help anyone
557             who wishes to write a helper module for a new platform. Modules should have
558             the same name as ^O in title caps. Thus 'openbsd' becomes 'Openbsd.pm'.
559              
560             =head1 REQUIREMENTS
561              
562             Sys::Filesystem requires Perl >= 5.6 to run.
563              
564             =head1 TODO
565              
566             Add support for Tru64, MidnightBSD, Haiku, Minix, DragonflyBSD and OpenBSD.
567             Please contact me if you would like to provide code for these operating
568             systems.
569              
570             =head1 SUPPORT
571              
572             You can find documentation for this module with the perldoc command.
573              
574             perldoc Sys::Filesystem
575              
576             You can also look for information at:
577              
578             =over 4
579              
580             =item * RT: CPAN's request tracker
581              
582             L
583              
584             =item * AnnoCPAN: Annotated CPAN documentation
585              
586             L
587              
588             =item * CPAN Ratings
589              
590             L
591              
592             =item * Search CPAN
593              
594             L
595              
596             =back
597              
598             =head1 SEE ALSO
599              
600             L, L, L
601              
602             =head1 VERSION
603              
604             $Id$
605              
606             =head1 AUTHOR
607              
608             Nicola Worthington - L
609              
610             Jens Rehsack - L
611              
612             =head1 ACKNOWLEDGEMENTS
613              
614             See CREDITS in the distribution tarball.
615              
616             =head1 COPYRIGHT
617              
618             Copyright 2004,2005,2006 Nicola Worthington.
619              
620             Copyright 2008-2014 Jens Rehsack.
621              
622             This software is licensed under The Apache Software License, Version 2.0.
623              
624             L
625              
626             =cut
627