RFS/NFS file detection - possible solution

Chris Lewis clewis at eci386.uucp
Fri Feb 23 09:28:46 AEST 1990


For those of you who've expressed some interest in detecting RFS/NFS
files, I got a couple of leads by mail, plus I've discovered a few 
things on my own, plus I have some testcode if you're interested....

This was from Larry Wall:

> I don't know that it's documented either, but everywhere I've looked the
> dev of NFS is negative (treating it as a signed value).  This includes
> Vaxen, Suns, Masscomps and Pyramids.  I suspect that anyone that uses
> Sun's code will end up doing this, unless they've already reserved
> negative devices for some other purpose.
 
> If we make enough programs that rely on it, they might make it a standard. :-)
 
> I have no idea about RFS.
 
> Larry Wall
> lwall at jpl-devvax.jpl.nasa.gov

Thank you Larry!

This was sort of what I expected.  I also discovered on System VR3 (386/ix
1.0.6 specifically) and AIX that in /usr/include/sys/sysmacros.h (which
is where major() and minor() is defined on System Vish systems), has some
wierdishness that may imply similar functionality.  On 386/ix major()
returns a unsigned int that has bit 8 very carefully masked off:

    #define	major(x)	(int)((unsigned)((x)>>8)&0x7F)

(older code (eg: SCO pre-286 days) had 0xFF)

On AIX, they don't do the masking, but they define a "bmajor()" that does.
(on 386/ix, bmajor and major are the same).  On the system running AIX
I've had access to, the following was true for files/directories on 
networked file systems:

	major(stb.st_dev) != bmajor(stb.st_dev)

I have no access to a SVR3 with RFS actually running, but I suspect that
the upper bit would be turned on.

On HP9000, dev_t is a long, but they only use 8 bits for minor, and I believe
6 bits for major, and there are other bits that are set for NFS files.  

On HP9000, bmajor is defined, and I paraphrase:

    #define bmajor(x) major(x) /* Unsure of AT&T's intentions here,
				  bmajor masked off bits in porting base */

I betcha that the following would be fairly universal without having to
resort to individual #ifdef's for each variant of UNIX:

	if (makedev(major(stb.st_dev),minor(stb.st_dev)) != stb.st_dev) {
	    aha - NFS/RFS file!
	} else {
	    local disk file
	}

Anywho, could I get a few people to try the following C program on their
systems that have NFS and/or RFS partitions mounted on them and mail the
results to me?

This is what you would have to do:

	- unshar this file.
	- undef USG if you aren't a UNIX System V variant (if you get
	  major or minor undefined messages from cc, you probably need
	  to define USG)
	- compile the program ala:
		cc -o teststat teststat.c
	- Find the names of a couple of files on your local disks, plus
	  a few of them on filesystems mounted from other systems, and
	  run teststat with these file names as arguments.

	  Eg:
		./teststat / /etc <filename on NFS>
    
    To make the results perfectly clear, could you also include your
    teststat command line and the output of df from your system?

Thank you very much

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  teststat.c
# Wrapped by clewis at eci386 on Thu Feb 22 17:19:16 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'teststat.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'teststat.c'\"
else
echo shar: Extracting \"'teststat.c'\" \(685 characters\)
sed "s/^X//" >'teststat.c' <<'END_OF_FILE'
X/* %I% %E% */
X#define	USG	/* undef if you aren't some sort of System V */
X#include <stdio.h>
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#ifdef	USG
X#include <sys/sysmacros.h>
X#endif
X
Xstruct stat stb;
X
Xmain(argc, argv, envp)
Xint argc;
Xchar **argv; 
Xchar **envp; {
Xint i = 1;
X    for (;argv[i]; i++) {
X	if (stat(argv[i], &stb) == 0) {
X	    printf("file: %s dev: %x major: %x minor: %x\n", argv[i], 
X		stb.st_dev, major(stb.st_dev), minor(stb.st_dev));
X	    if (makedev(major(stb.st_dev),minor(stb.st_dev)) != stb.st_dev)
X		printf("I think %s is a networked file\n", argv[i]);
X	    else
X		printf("I don't think %s is a networked file\n", argv[i]);
X	} else
X	    perror(argv[i]);
X    }
X}
END_OF_FILE
if test 685 -ne `wc -c <'teststat.c'`; then
    echo shar: \"'teststat.c'\" unpacked with wrong size!
fi
# end of 'teststat.c'
fi
exit 0
-- 
Chris Lewis, Elegant Communications Inc, {uunet!attcan,utzoo}!lsuc!eci386!clewis
Ferret mailing list: eci386!ferret-list, psroff mailing list: eci386!psroff-list



More information about the Comp.unix.wizards mailing list