[comp.unix.questions] finding NFS dirs in csh?

brad@gcc-milo.ARPA (Brad Parker) (12/02/86)

Does anyone know how to tell if a file is "remote" in a csh (or sh) script?

I need to tell if a directory is a remote mount point or below a remote
mount point. I want to exclude remote directories in a script which
spans the file systems from root (/) - you know... "find / ..."

Any ideas?

(Like wow - these transparent file systems are *really* transparent!)

-- 

J Bradford Parker
General Computer (HyperDrive Beach, 3rd Cabana)
harvard!gcc-milo!brad

Good Sex is easier than a good slow roll. ("Left Stick! Right Rudder!...")

mlandau@Diamond.BBN.COM (Matt Landau) (12/02/86)

In comp.unix.questions (article <772@gcc-milo.ARPA>), brad@gcc-milo.ARPA 
(Brad Parker) writes:
>Does anyone know how to tell if a file is "remote" in a csh (or sh) script?
>
>I need to tell if a directory is a remote mount point or below a remote
>mount point. I want to exclude remote directories in a script which
>spans the file systems from root (/) - you know... "find / ..."

From "man find" on a Sun 3 running SunOS 3.0:

     find recursively descends the directory hierarchy  for  each
     pathname  in  the  pathname-list (that is, one or more path-
     names) seeking files that match a boolean expression written
     in  the  primaries  given  below....

     -fstype type
               True if the  filesystem  to  which  the  the  file
               belongs  is  of type type, where type is typically
               4.2 or nfs

That ought to about do it, don't you think?
-- 
 Matt Landau      	 		BBN Laboratories, Inc.
    mlandau@diamond.bbn.com		10 Moulton Street, Cambridge MA 02238
 ...seismo!diamond.bbn.com!mlandau      (617) 497-2429

roy@phri.UUCP (Roy Smith) (12/03/86)

In article <772@gcc-milo.ARPA> brad@gcc-milo.ARPA (Brad Parker) writes:
> I need to tell if a directory is a remote mount point or below a remote
> mount point. I want to exclude remote directories in a script which
> spans the file systems from root (/) - you know... "find / ..."

	I usually do a "df ." to find out if the current directory is local
or remote.  You could grab the output of df inside your program (grody!) or
grab the source for Sun's df (assuming you have source) and see how df
figures it out.
-- 
Roy Smith, {allegra,cmcl2,philabs}!phri!roy
System Administrator, Public Health Research Institute
455 First Avenue, New York, NY 10016

"you can't spell deoxyribonucleic without unix!"

simon@its63b.ed.ac.uk (ECSC68 S Brown CS) (12/04/86)

In article <772@gcc-milo.ARPA> brad@gcc-milo.ARPA (Brad Parker) writes:
>Does anyone know how to tell if a file is "remote" in a csh (or sh) script?
>
>I need to tell if a directory is a remote mount point or below a remote
>mount point. I want to exclude remote directories in a script which
>spans the file systems from root (/) - you know... "find / ..."
>
>
>(Like wow - these transparent file systems are *really* transparent!) 

Well, I havn't found this to be the case at all! (At least using
NFS between SUNs and a Pyramid).
It seems that if you open(2) a remote directory for reading, any read(2)
will return 0 bytes - it looks like a totally empty directory! - there isn't
even "." or ".." entries.
You have to use the getdirentries(2) call to actually read remote directories.

So, you could check if a file is remote by:
     1.	If its a directory (stat => st_mode&S_IFDIR), then try to read
	something from it. If it looks empty then it's remote.
     2.	If its a non-directory, just apply step 1 to its parent.

Of course, it might be a bit more tricky to do things like this in
a shell script... Perhaps something like:

	#
	#	shell function to see if a file is remote
	#
	isremote(){
		if [ -d $1 ]
		then	if [ `cat $1 | wc -c` == 0 ]	# it looks empty
			then return 0			#  true
			else return 1			#  false
			fi
		elif isremote $1/..			# is parent remote?
		then	return 0
		else	return 1
		fi
	}

Of course, this might just only work 'cos NFS is set up wrong here. :-)

--
Simon Brown
Department of Computer Science, University of Edinburgh, Scotland.
...!{decvax,ihnp4,seismo}!mcvax!ukc!cstvax(!its63b)!simon

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"Life is full of woe, don't you know..." [Anon.]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

bzs@bu-cs.BU.EDU (Barry Shein) (12/05/86)

I realize that the original question was how to find out if a file is
across an NFS system from the csh. Find does it if that's applicable.
Now there's wondering out loud how it is done from a C program. I
suppose both questions are answered by a simple C command that can
be used in a csh script to test nfsness.

	-Barry Shein, Boston University

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

/*
 * given a file name on the command line this program:
 *
 *	Prints NFS or LOCAL if the file is on an NFS or LOCAL file
 *	system respectively.
 *	Silently exits with a non-zero exit status if the file could
 *	not be accessed.
 */

/*
 * This magic cookie is gleaned from nfs_vnodeops.c
 * (is it likely to change? I dunno.)
 */
#define NFS_DEV 0xff

main(argc,argv) int argc; char **argv;
{
	struct stat sbuf;

	if(argc != 2) exit(1);
	if(stat(*++argv,&sbuf) < 0)
	  exit(1);

	/* Here's what you're looking for */
	if(major(sbuf.st_dev) == NFS_DEV)
	  printf("NFS\n",*argv);
	else printf("LOCAL\n");
	exit(0);
}

gwyn@brl-smoke.ARPA (Doug Gwyn ) (12/05/86)

In article <160@its63b.ed.ac.uk> simon@its63b.ed.ac.uk (ECSC68 S Brown CS) writes:
-		if [ -d $1 ]
-		then	;#...
-		elif isremote $1/..
-		then	;#...
-		fi

But (regular_file)/.. is an illegal pathname!
Does NFS really support this?

simon@its63b.ed.ac.uk (ECSC68 S Brown CS) (12/07/86)

In article <5430@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>In article <160@its63b.ed.ac.uk> simon@its63b.ed.ac.uk (ECSC68 S Brown CS) writes:
>-		if [ -d $1 ]
>-		then	;#...
>-		elif isremote $1/..
>-		then	;#...
>-		fi
>
>But (regular_file)/.. is an illegal pathname!
>Does NFS really support this?

Whoops. No, probably not. A typo, I am forced to admit :-)

--
Simon Brown
Computer Science Department, University of Edinburgh, Scotland.
...!{decvax,ihnp4,seismo}!mcvax!ukc!cstvax(!its63b?)!simon

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"Life's a load of tripe - that's my gripe". [Anon.]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

mouse@mcgill-vision.UUCP (der Mouse) (12/09/86)

In article <772@gcc-milo.ARPA>, brad@gcc-milo.ARPA (Brad Parker) writes:
> Does anyone know how to tell if a file is "remote" in a csh (or sh) script?

> I need to tell if a directory is a remote mount point or below a remote
> mount point.  I want to exclude remote directories in a script which
> spans the file systems from root (/) - you know... "find / ..."

> Any ideas?

> (Like wow - these transparent file systems are *really* transparent!)

Not transparent enough :-(.

Some versions of find have an option for this:

	find / -fstype nfs -prune ....

Without this, I know of no easy way to tell whether a *file* is remote
or not.  From a shell script, that is.  From a C program, just call
stat() (or lstat()); a remote file will show a major device number of
255 (true of MtXinu 4.3+NFS and SunOS 3.0, presumably of SunOS other
numbers as well).  For a *directory*, things are easier.  NFS breaks
the directory-as-a-file paradigm (one of the reasons I hate NFS), so an
attempt to open() and read() a directory will produce errors.  Since
standard I/O insulates programs from these errors, a remote directory
will look like an empty file to many programs.  For example, you can
use

(Bourne shell)
	if cmp -s suspect-directory /dev/null; then
	  echo suspect-directory is remote
	else
	  echo suspect-directory is local
	fi
(C shell)
	if { cmp -s suspect-directory /dev/null } then
	  echo suspect-directory is remote
	else
	  echo suspect-directory is local
	endif

					der Mouse

USA: {ihnp4,decvax,akgua,utzoo,etc}!utcsri!mcgill-vision!mouse
     think!mosart!mcgill-vision!mouse
Europe: mcvax!decvax!utcsri!mcgill-vision!mouse
ARPAnet: think!mosart!mcgill-vision!mouse@harvard.harvard.edu

[USA NSA food: terrorist, cryptography, DES, drugs, CIA, secret, decode]

guy@sun.uucp (Guy Harris) (12/12/86)

> NFS breaks the directory-as-a-file paradigm 

DIRECTORIES AREN'T FILES!!!!!!!!  They may happen to be implemented on UNIX
in such a fashion that they can be treated as such in some cases, but they
can't always be treated as such.

When you read a directory entry, you want the i-number (and any other
numbers in the directory entry) to be presented in the format of the machine
and operating system doing the *reading*, *not* the format of the machine
and operating system on which they are stored.  (Otherwise, it would
*really* be non-transparent.)  As such, you must use a system call that
knows you're trying to read directory entries, so that they can be put into
a standard form at the sending site and put into the native form at the
receiving site.

If "read" worked on directories over NFS, any program that tried to use
"read" to read directory entries from a directory, rather than
"getdirentries" (SunOS) or "getdents" (System V, Release 3, and probably
some future SunOS release) would be quite likely to get wrong answers.  In
fact, if the two machines are, say, a Sun and a VAX, it would pretty much be
*guaranteed* to get wrong answers!

> so an attempt to open() and read() a directory will produce errors.  Since
> standard I/O insulates programs from these errors,

Standard I/O does no such thing.  If "read" gets an I/O error, the standard
I/O call doing the reading will return whatever its error/EOF indication is.
The program can then use "ferror" or "feof" to distinguish between error and
EOF.  A program using standard I/O can do the same error checking that a
program using "open()" and "read()" can.

> a remote directory will look like an empty file to many programs.

Only to *broken* and *incorrect* programs, i.e. programs that assume that
any error/EOF indication from standard I/O is an EOF indication.  Such
programs should be fixed!

FYI, the way "find" does it is to "stat" the file in question and search
through the mount table (see GETMNTENT(3), at least in the SunOS
documentation), "stat"ing the "mnt_dir" field for each entry in the mount
table and comparing its "st_dev" with the "st_dev" for the file in question.
When they're equal, it's found the file system on which the file in question
appears; the "mnt_type" entry contains the file system type for that file
system.  "nfs" indicates an NFS file system.
-- 
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com (or guy@sun.arpa)

djl@winchester.UUCP (Dan Levin) (12/16/86)

In article <10398@sun.uucp>, guy@sun.uucp (Guy Harris) writes:
> DIRECTORIES AREN'T FILES!!!!!!!!  They may happen to be implemented on UNIX
> in such a fashion that they can be treated as such in some cases, but they
> can't always be treated as such.

Here here.  You cannot expect to find UNIX semantics in a heterogeneous
environment.

Now the humorous thing is that NFS goes to great lengths to virtualize
the directory paradigm (as it clearly must), only to make the totally
unsupportable and false assumption that the server is able to return a
"cookie" that points to the "next" directory entry.  This happens to
work in UNIX, where removing a directory entry results in simply
marking the entry as free.  However, in some other systems, this is not
the case.  A counter-example is VMS, where removing a directory entry
changes the physical size of the directory, thus invalidating any
outstanding "cookies" being held by clients.
-- 
			***dan

{decwrl, glacier}!mips!djl    mips!djl@{decwrl.dec.com, glacier.stanford.edu}
It Isn't 75 degrees in New Jersey in November; I'm Glad To Be Home!

csg@pyramid.UUCP (Carl S. Gutekunst) (12/17/86)

Gee, dare I put my foot in my mouth again? Sure, what the hey.... :-)

In article <10398@sun.uucp> guy@sun.uucp (Guy Harris) writes:
>> NFS breaks the directory-as-a-file paradigm 
>
>DIRECTORIES AREN'T FILES!!!!!!!!  They may happen to be implemented on UNIX
>in such a fashion that they can be treated as such in some cases, but they
>can't always be treated as such.

Granted, a program that does its own directory operations is non-portable. But
why establish an artificial restriction in the kernel? And it *is* artificial;
the restriction didn't exist in SunOS 2.2, and in 3.0 a one-word adb poke was
all that was needed to permit NFS directory reads to work again.

Changes such as this unnecessarally provoke user irritation. Most users will
be patient and understanding when five-year-old code breaks because of a hard-
ware change, like adding a machine with a new architecture to the network.
They will also tolerate OS changes that provide a lot of new functionality.
But an arbitrary restriction where none existed previously is a nuisance,
especially when you've got a lot of binaries around for which you don't have
source. 

The best example of this was Interleaf, which did its own directory ops. True,
I could not run Interleaf with a Pyramid or a VAX as a server, because of the
different directory formats. But you can bet that everyone in Sun's technical
support group knew that adb poke for SunOS 3.0, for all the customers who had
Sun servers and couldn't do their desktop publishing anymore. 

In the tradition of the Unix libertarian, I say, let the developer be respon-
sible for his own stupidity or daring, such as the case may be. Don't impose
restrictions that don't absolutely need to be there.

(BTW, Interleaf 2.5 does directory calls properly.)

<csg>

david@elroy.UUCP (David Robinson) (12/17/86)

In article <33@winchester.UUCP>, djl@winchester.UUCP (Dan Levin) writes:
> In article <10398@sun.uucp>, guy@sun.uucp (Guy Harris) writes:
> > DIRECTORIES AREN'T FILES!!!!!!!!  They may happen to be implemented on UNIX
> > in such a fashion that they can be treated as such in some cases, but they
> > can't always be treated as such.
> 
> Here here.  You cannot expect to find UNIX semantics in a heterogeneous
> environment.
Here Here!
> 
> Now the humorous thing is that NFS goes to great lengths to virtualize
> the directory paradigm (as it clearly must), only to make the totally
> unsupportable and false assumption that the server is able to return a
> "cookie" that points to the "next" directory entry.
I can invision an OS without a marker to the next entry.  I would not
like to use one of these! ;-)

>  This happens to
> work in UNIX, where removing a directory entry results in simply
> marking the entry as free.  However, in some other systems, this is not
> the case.  A counter-example is VMS, where removing a directory entry
> changes the physical size of the directory, thus invalidating any
> outstanding "cookies" being held by clients.

WRONG!  The NFS directory structure fits into the VMS filesystem
quite nicely (provided you go under RMS).  The VMS directory is
a set of disk blocks (512bytes). That contain in alphabetical order
all the files in a directory by name and pointers to the headers
in the File header file at the root of the filesystem.  The QIO
call to read a directory takes the file id of the directory and
a "wcc".  This is a magic number which roughly translates into
an offset like pointer.  A wcc of zero is the start of the directory.
When a file is deleted the directory size may change but the wcc
for any individual entry will stay the same.  Most direcrtories after
quite a bit of use will have a bunch of unused numbers in the sequence of
wccs.  The wcc of a file will change if an entry is added.  Because
the files are in alphabetical order (UGH!), you may insert a file
AAB between AAA and AAC which have a wccs differing by only one.  In this
case AAB gets AAC's wcc and AAC is bumped up by one as is the next file's
until either the rest of the directory is incremented or a "hole" in
the numbering sequence is found.

This has potential for problems on a heavily modified directory but the
dirent cache routines on the client can be set so that this won't
be much of a problem.  Occasionally you might get a directory with
one file listed twice.
-- 
	David Robinson		elroy!david@csvax.caltech.edu     ARPA
				seismo-------!cit-vax!elroy!david UUCP
				ihnp4!cithep/
Disclaimer: No one listens to me anyway!

mouse@mcgill-vision.UUCP (der Mouse) (12/21/86)

In article <10398@sun.uucp>, guy@sun.uucp (Guy Harris) quotes:
>> NFS breaks the directory-as-a-file paradigm
and writes:
> DIRECTORIES AREN'T FILES!!!!!!!!  They may happen to be implemented
> on UNIX in such a fashion that they can be treated as such in some
> cases, but they can't always be treated as such.

Directories are, conceptually, not files.  However, I know of no
operating system on which a directory is *not* a file, albeit usually
with an imposed format and special flags set in its inode analogue.

> When you read a directory entry, you want [certain numbers] to be
> presented in the format of the machine and operating system doing the
> *reading*, *not* the format of the machine and operating system on
> which they are stored.

Sounds like a good reason not to mix big-endian and little-endian
machines on a LAN.  Sigh, if only the world could agree on a byte
order....if everyone else went, I would even be willing to switch.

> As such, you must use a system call that knows you're trying to read
> directory entries,

Read() certainly has that information available.  It can look at the
inode and say "hey, this call is reading from a directory!".  Just
because it hasn't had to historically doesn't mean it isn't allowed to.

> so that they can be put into a standard form at the sending site and
> put into the native form at the receiving site.

EXACTLY.  *Why* can't you just present a directory in what has always
been the standard form - read() returning directory entries?  You can
ship it around the net however you like - I'm not fussing about NFS
using a different rpc call to read directory entries, I'm talking about
the user program level.

Todd Brunhoff's RFS did this right; when read() is done on a directory
it notices and byteswaps the i-numbers.  What I would like to see NFS
do is get the directory entries (how is immaterial) and then construct
something that looks like what a local directory looks like.

> If "read" worked on directories over NFS, any program that tried to
> use "read" to read directory entries from a directory, rather than
> "getdirentries" (SunOS) or "getdents" (System V, Release 3, and
> probably some future SunOS release) would be quite likely to get
> wrong answers.

Only if read() weren't careful to check whether it's reading a
directory.

>> so an attempt to open() and read() a directory will produce errors.
>> Since standard I/O insulates programs from these errors,
> Standard I/O does no such thing.  [...]  The program can then use
> "ferror" or "feof" to distinguish between error and EOF.

Bad choice of words on my part.  Lots of programs (eg, cat) simply do
something like
	while ((c=getchar()) != EOF)
assuming that EOF means eof (a very easy trap to fall into).

>> a remote directory will look like an empty file to many programs.
> Only to *broken* and *incorrect* programs, i.e. programs that assume
> that any error/EOF indication from standard I/O is an EOF indication.
> Such programs should be fixed!

Easy to say.  There are a lot of such programs.  Even your SunOS (3.0)
cat does this.  If I cat an nfs directory it exits after printing zero
bytes (no error message); it even exits with status 0.

I'll be glad to fix it - but I need source.  Not only do you not ship
source by default, you want us to pay (and pay lots!) for it.  And
we're not even for-profit.

					der Mouse

USA: {ihnp4,decvax,akgua,utzoo,etc}!utcsri!mcgill-vision!mouse
     think!mosart!mcgill-vision!mouse
Europe: mcvax!decvax!utcsri!mcgill-vision!mouse
ARPAnet: think!mosart!mcgill-vision!mouse@harvard.harvard.edu

lindsay@cheviot.newcastle.ac.uk (Lindsay F. Marshall) (12/22/86)

In article <10398@sun.uucp> guy@sun.uucp (Guy Harris) writes:
>When you read a directory entry, you want the i-number (and any other
>numbers in the directory entry) to be presented in the format of the machine
>and operating system doing the *reading*, *not* the format of the machine
>and operating system on which they are stored.  (Otherwise, it would
>*really* be non-transparent.)

Quite Right.

>As such, you must use a system call that
>knows you're trying to read directory entries, so that they can be put into
>a standard form at the sending site and put into the native form at the
>receiving site.

Also quite right - the "read" system call is exactly that kind of system call.
The Newcastle Connection supports these semantics for read and will cope with
V7 style access to directories on remote systems of many kinds. Yes there are
some things that cant be done - long file names, 32 bit i numbers, but in
general these dont cause a problem - most people just want to be able to say
"ls /remote/dir" and this works fine. Oh yes, the getdirentries system
call is supported as well for those who like need that kinf of thing.


>If "read" worked on directories over NFS, any program that tried to use
>"read" to read directory entries from a directory, rather than
>"getdirentries" (SunOS) or "getdents" (System V, Release 3, and probably
>some future SunOS release) would be quite likely to get wrong answers.  In
>fact, if the two machines are, say, a Sun and a VAX, it would pretty much be
>*guaranteed* to get wrong answers!

Quite wrong - this type of thing is very easy to do.

	Lindsay
------------------------------------------------------------------------------
Lindsay F. Marshall, Computing Lab., U of Newcastle upon Tyne, Tyne & Wear, UK
  ARPA  : lindsay%cheviot.newcastle.ac.uk@ucl-cs.arpa
  JANET : lindsay@uk.ac.newcastle.cheviot
  UUCP  : <UK>!ukc!cheviot!lindsay
-------------------------------------------------------------------------------