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