[comp.lang.perl] getfsent

hakanson@ogicse.ogi.edu (Marion Hakanson) (03/30/90)

Well, I needed it, and Larry wasn't forthcoming.  It works quite
nicely, but isn't real fast (but how often does one do this?).
It successfully mimics the real getfsent(3) on a few systems
I've tested here.  Note it lacks getfsspec, getfsfile, & getfstype
functions, but I had no need for them yet.  Please bash on it,
and feedback is welcome.

First, an example of its use:

==========testfsent.pl===========
#!/usr/bin/perl
do ($_='fstab.pl') || die "Can't load $_: " . ($@?$@:$!) . " aborted";

$, = ':';

while ( @flds = &getfsent ) {
  print '|';
  print @flds;
  print "|\n";
}
==========end of testfsent.pl===========

Now the subroutine:

==========fstab.pl=============
;#
;# $Id: fstab.pl,v 1.2 90/03/29 17:42:40 hakanson Exp $
;#
;# Perl subroutines to read fstab for you.
;#   Marion Hakanson (hakanson@cse.ogi.edu)
;#   Oregon Graduate Institute of Science and Technology
;#
;# Understands the old v7-style fstab lines ("spec:dir:xx:0:0"),
;# as well as the new NFS-style ("spec dir type opts 0 0"), the
;# latter of which it maps to the former, as is done by getfsent(3)
;# on NFS systems.  See below for details.

package fsent;

$fstab = '/etc/fstab';
$is_open = 0;
$nfspat = '^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s*$';
$v7pat = '^(.*):(.*):(.*):(\d*):(\d*).*$';


sub main'setfsent {
  &main'endfsent;
  $is_open = open(FSTAB, "<$fstab");
}



sub main'endfsent {
  close(FSTAB);
  $is_open = 0;
  $fstab_type = '';
  $error = 0;
  1;
}



sub main'getfsent {
  local (@fields);
  local ($[);

  $[ = 1;

  $is_open || &main'setfsent || ($error = 1);
  return () if ( $error );

  dline: while ( <FSTAB> ) {
 #print STDERR "   $_";
    chop;	# strip newline
    next dline if /^#/;	# skip comment line

    unless ( $fstab_type ) {
      # nfs or normal?
      if ( /$nfspat/o ) {
        $fstab_type = 'nfs';
      } else {
        $fstab_type = 'v7';
      }
    }

    #print STDERR "fstab_type: $fstab_type\n";
    if ( $fstab_type eq 'nfs' ) {
      @fields = /$nfspat/o;

      #print STDERR "#fields: $#fields\n";
      if ( $#fields != 6 ) {
        $error = 1;
      } else {
        # map mntent types & opts to fsent types
        $fstype = splice(@fields, 3, 1);
        # old-style fstab doesn't grok NFS entries
        if ( $fstype eq 'nfs' ) {
          @fields = ();	# in case it's the last
          next dline;
        }
        typ: {
          if ( $fstype eq 'ignore' ) {
            $fstype = 'xx';
            last typ;
          }
          if ( $fstype eq 'swap' ) {
            $fstype = 'sw';
            last typ;
          }
          if ( $fields[3] =~ /(^|,)ro\b/ ) {
            $fstype = 'ro';
            last typ;
          }
          if ( $fields[3] =~ /(^|,)quota\b/ ) {
            $fstype = 'rq';
            last typ;
          }
          $fstype = 'rw';
        }
        $fields[3] = $fstype;
      }
    } else {
      @fields = /$v7pat/o;
 #print STDERR "#fields: $#fields\n";
      if ( $#fields == 5 ) {
        $fields[4] = 0 unless ( $fields[4] > 0 );
        $fields[5] = 0 unless ( $fields[5] > 0 );
      } else {
        $error = 1;
      }
    }
    last dline;
  }
  $error ? () : @fields;
}


1;

==========end of fstab.pl=============

-- 
Marion Hakanson         Domain: hakanson@cse.ogi.edu
                        UUCP  : {hp-pcd,tektronix}!ogicse!hakanson