Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Dearest Monks,

Is there a perl-ish way to determine whether a given file is on a local disk as opposed to being NFS/Samba/etc mounted? Or do I just have to go parse the output of commands like "mount" and compare paths or something? I'm trying to make my code not be dependent on external system commands.
  • Comment on How to Determine If A File Is On NFS? Local? Etc?

Replies are listed 'Best First'.
Re: How to Determine If A File Is On NFS? Local? Etc?
by Fletch (Bishop) on Sep 21, 2004 at 14:13 UTC

    This is really something that's not easily made platform independent. If you can limit yourself to a single OS you might can find some pattern to the dev_t numbers (negative for NFS apparently doesn't hold on your platform). One way which only depends on a single external command would be:

    • parse the output from df to build a list of filesystems and their type
    • for each filesystem save off the dev_t value from (stat( "$mountpoint/." ))[0]
    • compare (stat( $file_in_question ))[0] to your saved dev_t list

    More of a long shot would be to use Inline::C to get a version of the major()/minor() macros (or hand-roll them), and then compare those against disk device files in /dev. If there's one with the same major/minor, it's a local file; if not it's probably remote (but then you probably wouldn't be able to figure out NFS vs SMB vs . . .).

      Perhaps someone whould mutter on p5p about having new -X tests to get the major/minor numbers for a device.
Re: How to Determine If A File Is On NFS? Local? Etc?
by borisz (Canon) on Sep 21, 2004 at 13:27 UTC
    my $d = (stat($filename))[0]; if ( $d < 0 ) { print "$filename is nfs file\n"; }
    Boris
      Looking at the first element returned by stat() doesn't seem to work. I tried:
      my $nfs_file = '/auto/somewhere/testfile.txt'; my $local_file = '/tmp/testfile.txt'; my @stat_stuff = stat("$nfs_file"); print "Device for nfs file is $stuff[0]."; @stat_stuff = stat("$local_file"); print "Device for local file is $stuff[0].\n";
      When I ran it, I got 14 for the NFS mounted file and 10 for the local file. Both greater than 0. Have I misunderstood something?
        This method depends on the way devices are numbered in your
        OS. All it means is that you're using an OS which does
        not list NFS as a negative device number.

        No big deal, just adapt the code to fit.
        Hmm, no that was what borisz wrote. /me goes to read perldoc -f stat.
Re: How to Determine If A File Is On NFS? Local? Etc?
by jaco (Pilgrim) on Sep 21, 2004 at 16:14 UTC
    I'm not sure if it'll help, but you could consider using something like Filesys::Statfs in combonation with some sort or cwd from the file you're looking for.
Re: How to Determine If A File Is On NFS? Local? Etc?
by radiantmatrix (Parson) on Sep 21, 2004 at 19:33 UTC
    If it's only external commands you're worried about, you could read from /proc/mtab, as it contains the same information that mount provides (though in a different format).
    --
    $me = rand($hacker{perl});

    All code, unless otherwise noted, is untested
      while a good idea it's also very platform specific.
      Which it appears is something that he's trying to avoid.
      That is to say at least writing the code to deal with the
      multiple platforms <is to be avoided.

      I don't think there's anyway around this. You're either going to have to use an exec
      (in which case you'll still have very platform specific output) Or code out the values
      of the devices based on OS, or some other such nonsense. No matter how you look
      at it you're going to have to deal with the fact that OS' don't treat mount points or
      device numbers the same way.
        Since he mentioned NFS and Samba, I presumed that platform-specifity wasn't as much an issue as relying on external commands.

        I agree that there is pretty much no way of accomplishing the given task reliably in a cross-platform manner. However "an OS with /proc filesystem support" is a much better qualifier than "an OS which has a 'mount' command that produces output in a specific format". So, using the mtab file is still better than using the output from mount.

        The closest one could get to "cross-platform" would be checking the most likely OS targets to see which you are running under, and perform the logic that works for that OS. That's an unmaintainable curmudgeon, though.

        --
        $me = rand($hacker{perl});

        All code, unless otherwise noted, is untested
Re: How to Determine If A File Is On NFS? Local? Etc?
by TedPride (Priest) on Sep 21, 2004 at 19:50 UTC
    Well, if you know what the path of the file is, you should be able to just do:
    if (-e $filepath) { }
    Filepaths have to be made with : instead of / on the Mac, though, so you'll need to do an OS test and a $filepath convert if you want this platform independent.
      FWIW, the old Mac OS (9.2.2 or earlier) used ':' as a path delimiter but in Perl on Mac OS X the '/' is used since the OS is based on BSD.