#! /usr/bin/perl # # This script decodes NFS file handles on the form # 2240005 3e7 a0000 1fa04 26 a0000 2 0 # The first 32 bits are the device number (split 18/14 major/minor), # the inode number is in the forth group (0x1fa04 in the above handle) # # Reverse engineering was done on a Solaris 2.6 server running NFS 3. # If this doesn't work on your system, please let me know. # # This script is put into the Public Domain. # # Kjetil T. Homme, 2001-06-05 # require "find.pl"; sub usage { print STDERR "Usage: $0 numbers\n"; print STDERR "This needs to run on the NFS server.\n"; exit (64); } &usage unless $#ARGV == 7; $dev = hex(shift); # $major = $dev >> 18; $minor = $dev & (1<<18 - 1); @devlist = (); &find("/dev"); unless ($#devlist >= 0) { print "Sorry, can't find device.\n"; exit (1); } open (MNTTAB, "/etc/mnttab") || die; mount: while () { ($rdev, $mount) = (split (/\t/))[0,1]; for (@devlist) { last mount if $rdev eq $_; } } unless ($mount) { print STDERR "Sorry, can't find mount point.\n"; exit (1); } $inum = hex($ARGV[2]); print STDERR "Looking for inode $inum in $mount.\n"; &find($mount); print STDERR "Sorry, couldn't find file.\n"; exit (1); # This function can be run from two different calls to &find() # Perl 5's File::Find would be much nicer, but this works in Perl 4 ... sub wanted { if ($inum) { # Mode 1 (the last call) if ($inum == (lstat($_))[1]) { print "$dir/$_\n"; exit (0); } elsif ($dev != (lstat(_))[0]) { $prune = 1; } } else { # Mode 2 (the first call) if ($dev == (stat($_))[6] && -b _) { push (@devlist, "$dir/$_"); } } }