Can one find a mount point just knowing the volume name?

William Setzer William_Setzer@ncsu.edu
08 Feb 2001 15:26:57 -0500


Here's a version of the "traverse cell looking for mount points" that
I wrote.  It pretty much handles all the scary cases that have been
pointed out.  It also uses the AFS module maintained by Norbert E
Gruener (http://www.Mpa-Garching.MPG.DE/~nog/) rather than forking fs
each time.

It outputs the information to a particularly named file, called
"mntpt-<cell>-<path>", and will read in any other similar files in
order to build the exclusion list of already-visited volumes.  The
only place where it might be (Unix) OS specific is where I use the
mode flags to find out if it's a directory or not.

For other features, read the source; there's not that much.  No
warranty expressed or implied.  Void where prohibited by law.


William

8<-8<-8<-8<- Cut 8<-8<-8<-8<-
#!/ncsu/perl56/bin/perl
##
##  Copyright (c) 2000  William Setzer
##
##  You may distribute under the terms of either the Artistic License
##  or the GNU General Public License, ie, the same terms as perl.
##
##  This program is distributed in the hope that it will be useful,
##  but WITHOUT ANY WARRANTY; without even the implied warranty of
##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##  Artistic License for more details. 
#
#
#  dump-mntpt-cell: generate a list of mount points along a path
#
#  Usage: dump-mntpt-cell [-f] <mount point>
#  where
#      -f -- force (see below)
#
#  This script walks the given path and dumps the list of mount points
#  found to a file.  Normally, it looks for other files generated by
#  this script and preloads them so that AFS volumes aren't walked
#  more than once. Also, the argument must be a mount point, so that
#  all mount points will be found.
#
#  When "force" is set via -f, this preloading is not done, and
#  the script does not require the argument to be a mount point.

use AFS qw(lsmount whichcell);

##  lsmount modifies its arg.  bleh.
#
sub fs_lsmount   { my $path = shift; lsmount   $path, 0 }
sub fs_whichcell { my $path = shift; whichcell $path, 0 }

my $base = shift;
my $force;
if ($base eq '-f') {
    $force++;
    $base = shift;
}

die "Usage: $0 [-f] <mount point>\n" unless defined $base;
die "Usage: $0 [-f] <mount point>\n" if not $force and not fs_lsmount $base;

my $cell = fs_whichcell $base;
die "Can't find base cell: $AFS:CODE\n" if $AFS::CODE or $cell eq '';

my %mnt = { "$cell:root.afs" => 1};
unless ($force) {
    opendir DIR, "."  or die "Can't opendir .: $!\n";
    while (1) {
	my $entry = readdir DIR;
	last unless defined $entry;
	next unless $entry =~ /^mntpt-$cell/;

	open IN, $entry or die "Can't open $entry: $!\n";
	while (<IN>) {
	    next unless /^[\#%](?:(\S+):)?(\S+)\s/;

	    my $pcell = $1 || $cell;
	    $mnt{"$pcell:$2"}++;
	}						     
	close IN;
    }
    close DIR;
}

my @path = ( $base );
   $base =~ s!/afs/!!;
   $base =~ s!^/*!!;
   $base =~ s!/*$!!;
   $base =~ s!/+!-!g;

open OUT, ">> mntpt-$base" or die "Can't open mntpt-$base: $!\n";
open ERR, ">> err-$base"   or die "Can't open err-$base: $!\n";
select OUT;  $| = 1;
select ERR;  $| = 1;

while (1) {
    my $path = pop @path;
    last unless defined $path;

    print STDOUT $path, "\n";

    my $mount = fs_lsmount $path;
    if ($AFS::CODE and $AFS::CODE != 22) {
	print ERR "lsmount $path: $AFS::CODE\n";
	next;
    }
    if ($mount) {
	print OUT $mount, " " x (40 - length $mount), $path, "\n";

	my $mcell = fs_whichcell $path;
	if ($AFS::CODE) {
	    print ERR "whichcell $path: $AFS::CODE\n";
	    next;
	}
	next if $mcell ne $cell;

	$mount =~ s/^[#%]//;
	$mount =~ s/^\S+://;

	next if $mnt{"$mcell:$mount"}++;
	next if $mount =~ /\.readonly$/;
	next if $mount =~ /\.backup$/;
    }

    opendir DIR, $path or print ERR "$path: $!\n" and next;
    while (1) {
	my $entry = readdir DIR;
	last unless defined $entry;
	next if $entry eq '.';
	next if $entry eq '..';

	my $new   = "$path/$entry";
	my $mode  = (lstat $new)[2] or print ERR "$new: $!\n";
	next unless ($mode & 0170000) == 040000;

	push @path, $new;
    }
    closedir DIR;

    ##  Be nice to the filesystem
    #
    select undef, undef, undef, 0.25;

}
close ERR;
close OUT;