--- ./lib/Sys/Filesystem/Freebsd.pm.orig	Thu Jun  1 14:10:48 2006
+++ ./lib/Sys/Filesystem/Freebsd.pm	Fri Nov 30 11:53:45 2007
@@ -26,32 +26,46 @@
 use FileHandle;
 use Carp qw(croak);
 
+# For access to the getfsstat system call
+require 'sys/syscall.ph';
+require 'sys/mount.ph';
+
 use vars qw($VERSION);
 $VERSION = '1.05' || sprintf('%d', q$Revision: 364 $ =~ /(\d+)/g);
 
+my $sizeof;
+if ( &STATFS_VERSION == 0x20030518 ) {
+	$sizeof = 472; # The size in bytes of the statfs structure
+} else {
+	croak "The statfs strucuture changed version (" . &STATFS_VERSION . ")\n";
+}
+# unpack format, we want the 3rd and the last 3 fields.
+my $format = 'x8L' . 'x268' . 'A' . &MFSNAMELEN . ('A' . &MNAMELEN ) x 2 ;
+  
 sub new {
 	ref(my $class = shift) && croak 'Class name required';
 	my %args = @_;
 	my $self = { };
+	my (@vals, $i);
 
 	$args{fstab} ||= '/etc/fstab';
-	$args{mtab} ||= '/etc/mtab';
-	$args{xtab} ||= '/etc/lib/nfs/xtab';
+	# $args{mtab} ||= '/etc/mtab';  # Does not exist on FreeBSD
+	$args{xtab} ||= '/var/db/mountdtab';
 
 	my @keys = qw(fs_spec fs_file fs_vfstype fs_mntops fs_freq fs_passno);
-	my @special_fs = qw(swap proc devpts tmpfs);
+	push (@Sys::Filesystem::special_fs, qw(procfs devpts devfs));
 
 	# Read the fstab
 	my $fstab = new FileHandle;
 	if ($fstab->open($args{fstab})) {
 		while (<$fstab>) {
 			next if (/^\s*#/ || /^\s*$/);
-			my @vals = split(/\s+/, $_);
+			@vals = split(/\s+/, $_);
 			$self->{$vals[1]}->{mount_point} = $vals[1];
 			$self->{$vals[1]}->{device} = $vals[0];
 			$self->{$vals[1]}->{unmounted} = 1;
-			$self->{$vals[1]}->{special} = 1 if grep(/^$vals[2]$/,@special_fs);
-			for (my $i = 0; $i < @keys; $i++) {
+			$self->{$vals[1]}->{special} = 1 if grep(/^$vals[2]$/,@Sys::Filesystem::special_fs);
+			for ($i = 0; $i < @keys; $i++) {
 				$self->{$vals[1]}->{$keys[$i]} = $vals[$i];
 			}
 		}
@@ -60,24 +74,42 @@
 		croak "Unable to open fstab file ($args{fstab})\n";
 	}
 
-	# Read the mtab
-	my $mtab = new FileHandle;
-	if ($mtab->open($args{mtab})) {
-		while (<$mtab>) {
-			next if (/^\s*#/ || /^\s*$/);
-			my @vals = split(/\s+/, $_);
-			delete $self->{$vals[1]}->{unmounted} if exists $self->{$vals[1]}->{unmounted};
-			$self->{$vals[1]}->{mounted} = 1;
-			$self->{$vals[1]}->{mount_point} = $vals[1];
-			$self->{$vals[1]}->{device} = $vals[0];
-			$self->{$vals[1]}->{special} = 1 if grep(/^$vals[2]$/,qw(swap proc devpts tmpfs));
-			for (my $i = 0; $i < @keys; $i++) {
-				$self->{$vals[1]}->{$keys[$i]} = $vals[$i];
-			}
+	# Get the number of mounted fileystems we have
+	my $buf = '';
+	my $cnt = syscall(&SYS_getfsstat, $buf, length $buf, &MNT_NOWAIT);
+
+	# Fix a bug on some 5.x systems, the previous syscall may return 0...
+	$cnt = 20 if ( ! $cnt );
+
+	# Preallocate the buffer memory per the syscall() requreiments
+	$buf = ' ' x ( $sizeof * $cnt );
+
+	if ( ($cnt=syscall(&SYS_getfsstat, $buf, length $buf, &MNT_NOWAIT)) ) {
+		for (($i) = 0; $i < $cnt; $i++) {
+
+			my $offset = ($i)? 'x' . ($i * $sizeof): '';
+			@vals = unpack ( $offset . $format, $buf);
+
+			delete $self->{$vals[3]}->{unmounted} if exists $self->{$vals[3]}->{unmounted};
+			$self->{$vals[3]}->{mounted} = 1;
+			$self->{$vals[3]}->{mount_point} = $vals[3];
+			$self->{$vals[3]}->{device} = $vals[2];
+			$self->{$vals[3]}->{special} = 1 if grep(/^$vals[1]$/,@Sys::Filesystem::special_fs);
+
+			$self->{$vals[3]}->{fs_spec} = $vals[2];
+			$self->{$vals[3]}->{fs_file} = $vals[3];
+			$self->{$vals[3]}->{fs_vfstype} = $vals[1];
+			$self->{$vals[3]}->{fs_mntops} = 
+				($vals[0] & &MNT_RDONLY)? 'ro': 'rw';
+			$self->{$vals[3]}->{fs_mntops} .= ',noexec'
+				if ($vals[0] & &MNT_NOEXEC);
+			$self->{$vals[3]}->{fs_mntops} .= ',nosuid'
+				if ($vals[0] & &MNT_NOSUID);
+			$self->{$vals[3]}->{fs_mntops} .= ',nodev'
+				if ($vals[0] & &MNT_NODEV);
 		}
-		$mtab->close;
 	} else {
-		croak "Unable to open mtab file ($args{mtab})\n";
+		croak "Unable to retrieve mounted filesystem information\n";
 	}
 
 	# Bless and return


syntax highlighted by Code2HTML, v. 0.9.1