I pointed out the (obvious) problem of determining *requested* automount mount
points as opposed to *actual* mount points. I received many responses to my
request for solutions/workarounds.
Here's a message from Matt Cohen <chron!magic706!sysnmc@uunet.uu.net>, which best describes the problem:
----- Begin Included Message -----
You have in fact run across a major limitation of the automounter,
which is not so much an automounter problem, but one with symbolic links.
When the kernel does an NFS lookup through an automount point (such
as /vol/prj), the automounter mounts the real disk in the temporary location
(such as /tmp_mnt/vol/prj) and then replies to the kernel that /vol/prj is
actually a link to /tmp_mnt/vol/prj. Note that /vol/prj never actually
exists.
The getcwd() function finds its way to the root by repeatedly checking
the inode of all of the directories in ".." to that of ".":
set path = "."
set cwd = ""
while (inode(path) != inode(path/..)) /* Only equal for "/" */
foreach directory d in path/..
if (inode(d) == inode(.))
if (cwd == "")
set cwd = d
else
set cwd = d/cwd
end if
end if
end for
set path = path/..
end while
set cwd = /cwd
So getcwd() finds the "real" path up the tree from your current
working directory, ignoring any symbolic links you may have used to get there.
So what is the solution? The best solution, which is probably more work
that you're willing to do, is to write an automounter that instead of doing
the mount and returning a link in response to NFS queries, actually acts as
a proxy NFS server and returns the actual information requested. This would
require implementing all of the NFS operations (read, write, lookup, etc.)
in the automounter and it's quite a bit of work.
The next best thing is a workaround, and requires changing the way your
program goes about its business, and is admittedly not a great solution.
First, don't use relative (ones that don't start with "/") pathnames
and don't use getcwd(). If you can do this, then you're fine. This often
requires the user to pass you a directory to start with, either on the command
line or in an environment variable. Then keep track of the current path
yourself when changing directories.
If you can't do that, you can rely on a feature of csh (or simulate
it with /bin/sh). The csh keeps an environment variable PWD (see csh(1))
containing the current path, as you set it with "cd". So if you execute
"cd /vol/prj", $PWD will equal "/vol/prj" although running "pwd" will return
"/tmp_mnt/vol/prj". (/bin/pwd is just a wrapper for getcwd().)
If that's not good enough, you have to fall back to heuristic
solutions, such as second-guessing the automounter about mount points.
It is possible to do this right, by actually reading the automount config
file or map, but it's a lot of hassle.
----- End Included Message -----
For you shell hackers, here's some code from Michael S. Maiten <msm@energetic.com> which might be helpful:
----- Begin Included Message -----
One time, long ago, when the initial version of the automounter was
not even so nice as to report /tmp_mnt/full_name_of_automounted_path
(it only said /tmp_mnt/strange_number/path_from_mount_point)
I wrote a script (autopwd) that was a to be used as a suppliment to
pwd to determine the "real and true" path (ie; the automounted path).
It did read in the relevant yp maps (starting with auto.master and the
ones referenced therein) and then checked where "df ." said we were
with those maps. As you said "Yucky!", but it worked. Later, when
the automounter improved to where all you have to do is strip off
/tmp_mnt, this code was discarded (but I did find an earlier version
that looked only at specific indirect mount points -- I have attached
it to the end of this message. I don't know it it still works; but it
did work in SUN OS 4.0.0)
In all environments I have seen, no one has ever changed /tmp_mnt to
something else, so it is a minimal concern in most places. This is
also a matter of site-wide system administration discipline (ie; don't
allow non-standard places). (You could scan rc.local to see how
automounter is invoked and then check the settings, but it is probably
unnecessary (and doesn't allow for the fact tha automounter may have
been started by hand with different arguments)).
#! /bin/csh -fb
# Shell to Print the Working Directory in a form that is readable
# when using the SUN OS/4 automounter.
#
# Written by Michael S. Maiten, 31 May 1989.
#
# Usage: autopwd
# This will print the current working directory (like the pwd command)
# but will change the automounter's /tmp_mnt references to a form that
# the user understands (ie; /n, /net, /homes).
#
# get the current working directory.
# $pwd is the actual path,
# and $pwddirs is an array with each element containing one dir of the path.
set pwd = `/bin/pwd`
set pwddirs = ( ` echo $pwd | sed 's./. .g'`)
# if the first element of $pwddpath is not /tmp_mnt, then it is a normal
# directory on the local machine.
if ($pwddirs[1] != "tmp_mnt") then
echo $pwd
exit 0
endif
# first extract the current configuration from YP auto.master
# each element in $automounts (mount point for automounter)
# corresponds to one in $automaps (YP map containing mount details).
set automounts
set automaps
eval `ypcat -k auto.master | awk '{printf("set automounts=($automounts %s); set automaps=($automaps %s)\n", $1, $2)}'`
set iicount=0
foreach ii ($automaps)
# scan each map
@ iicount++
# $mountname is the the mount point for the automounted directory.
# (run the output of df through an additional filter since sometimes
# if the filesystem name is too long, it puts \n after it).
set mountname = `df . | awk 'NF==1 {printf("%s ",$1)};NF!=1{print $0}'| awk 'NR==2 {print $1}' `
if ($ii == "-hosts") then
# A special -hosts entry
if ("/$pwddirs[2]" == $automounts[$iicount]) then
echo /$pwddirs[2-] | sed 's. ./.g'
exit 0
endif
else
# a normal YP map.
set here = `ypcat -k $ii | egrep "${mountname}"'$' | awk '{printf("%s/%s\n","'${automounts[$iicount]}'",$1)}' `
if ($here != "") then
# It found something, so print it and exit
# if pwd has 3 or more components, show them all.
if ($#pwddirs >= 3) then
echo $here/$pwddirs[3-] | sed 's. ./.g'
else
echo $here
endif
exit 0
endif
endif
end
# couldn't find a match
echo $pwd
exit 1
----- End Included Message -----
Thanks also to:
Dan Franklin <dfranklin@bbn.com>
Tony Robinson <ajr@eng.cam.ac.uk>
Paul Humphreys <paul@hydres.uucp>
Ron Vasey <vasey@mcc.com>
Kerry Duke <duke@dsp.analog.com>
Malcolm Strickland <chuck-strickland@orl.mmc.com>
David Lee <T.D.Lee@durham.ac.uk>
Jim Ziobro <JAMES_M._ZIOBRO.WBST102A@xerox.com>
My only idea is a real kludge -- reading in the automount map source
files and normalizing all pathnames within the application. Unfortunately,
I don't have time to do this right (if one can do a kludge correctly :-).
Neil
This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:06:19 CDT