This commit was generated by cvs2svn to compensate for changes in r174294,

which included commits to RCS files with non-trunk default branches.
This commit is contained in:
David E. O'Brien 2007-12-05 15:48:03 +00:00
commit 16fdd0c062
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=174295
129 changed files with 21009 additions and 9896 deletions

View File

@ -12,6 +12,11 @@ The most significant changes were made by Erez Zadok in terms of bug fixes,
ports, and new features added. Erez Zadok is the current maintainer of
am-utils, as of January 1997.
* Ion Badulescu <ion@cs.columbia.edu>
Co-maintainer of am-utils since late 1999: Linux and Solaris autofs support,
Linux NFSv3 support, major code reorganization, etc...
* Randall S. Winchester <rsw@glue.umd.edu>
May 7, 1997: contributed a special version of upl102 that included NFS V.3
@ -154,7 +159,7 @@ that do not allow forwarding of RPC messages to other services.
August 10, 1997: netbsd and other bsd systems have a mask flag for
pcfs_args (msdos mount).
* Christos Zoulas <christos@deshaw.com>
* Christos Zoulas <christos@zoulas.com>
September 25, 1997: fix to initialize uid/gid fields of pcfs_args_t on
netbsd.
@ -163,9 +168,19 @@ October 10, 1997: compile time cleanups of printf()s in hlfsd code. If nfs
server is down or does not support a portmapper call, then mark it down as
version 2, and try again later.
November 29, 2002: compile fixes for NetBSD, a couple of bug fixes (one
already fixed by maintainers)
April 12, 2003: support new "unmount" option, useful to timeout removable
local media mounts.
October 12, 2004: patch to support two new amd.conf options, domain_strip
and auto_attrcache. Patch to cleanup NFS attribute-cache flag computation.
Patch to fix an inconsistency in timeouts in the RPC code between socket and
TLI implementations. Patch to print version string (amd -v) after all
options had been initialized, so we can print domain, host, and hostd.
Linux patch to use umount2(2) if umount(2) fails.
* Bill Paul <wpaul@ctr.columbia.edu>
November 5, 1997: NFS v.3 support for AIX 4.2.1, which does *not* include
@ -191,6 +206,8 @@ and proto.
January 12, 1998: minor bug in output of amd -H.
June 23, 2005: assortment of small compile bugs on aix4, and solaris 5/6/7.
* Thomas Richter <richter@chemie.fu-berlin.de>
January 13, 1998: use case insensitive comparisons for variables that need
@ -302,9 +319,13 @@ January 25, 2000: allow browsable auto maps.
* Wolfram Klaus <klaus@physik.fu-berlin.de>.
November 21, 2000: recognize proplist mnttab flag.
* Thomas Klausner <wiz@danbala.ifoer.tuwien.ac.at>
* Thomas Klausner <tk@giga.or.at>
November 21, 2000: lots of NetBSD fixes (many of which are generic).
April 18, 2003: patch to reference am-utils info pages in man page.
November 28, 2004: small fixes to typos in amd.conf(5) man page.
* Olaf Kirch <okir@caldera.de>
February 1, 2001: important Linux NFS error number mapping fixed
@ -318,20 +339,92 @@ March 27, 2002: LDAP bug and port to HPUX-11.
* Philippe Troin <phil@fifi.org>
July 12, 2001: Proper handling of GNU getopt, support for optionally
disabling LDAP/Hesiod, fixes for the dev/nodev option on Linux
disabling LDAP/Hesiod, fixes for the dev/nodev option on Linux. Texi
documentation fix.
November 28, 2001: Bug fix. Support "nolock" as an NFS option, not a
generic mount option.
July 17, 2003: Debian fixes. Null am_pref free.
July 17, 2003: pref:=null core dump fix. libgdbm portability. tcpd/librap
support. And a few other things for the 6.0 branch.
* Trond Myklebust <trond.myklebust@fys.uio.no>
January 10, 2002: Proper initialization of the timeo parameter on Linux, TCP
_must_ have a timeout 2 orders of magnitude larger than UDP
* George Ross <gdmr@dcs.ed.ac.uk>
April 29, 2002: Rework of old code, support for wildcards in LDAP queries,
and an FD leak fix. Amd -A support.
October 21, 2002: ldap_unbind fix for SIGPIPE, and support for LDAPv3
protocol version parameter (with Tim Colles <timc@inf.ed.ac.uk>).
* Matthias Scheler <tron@zhadum.de>
June 14, 2002: patch to use "xlatecookie" NFS mount option.
* Jun-ichiro itojun Hagino <itojun@iijlab.net>.
June 11, 2002: minor fixes to support NetBSD 1.6A.
* Sean Fagan <sef@apple.com>
March 14, 2003: detect and use the MNT2_GEN_OPT_AUTOMNTFS mount flag
on OS X / Darwin.
* Hendrik Scholz <hscholz@raisdorf.net>
June 9, 2003: mk-amd-map should open temp db file using O_EXCL.
* Mark Davies <mark@mcs.vuw.ac.nz>
July 14, 2003: define "xlatecookie" mnttab option if not defined (for
NetBSD). Support null hesiod entries if they start with a ".".
* Eric S. Raymond <esr@thyrsus.com>
December 9, 2003: fix unbalanced [] typo in fsinfo man page.
* Martin Blapp <mb@imp.ch>
July 6, 2004: recognize fields in pcfs_args_t in FreeBSD 5.
* Dan Nelson <dnelson@allantgroup.com>
August 2, 2004: pawd to recognize "host" type mounts.
* Hauke Fath <hauke@Espresso.Rhein-Neckar.DE>
August 3, 2004: pawd to recognize "linkx" type mounts.
* Michael van Elst <M.van.Elst@science-computing.de>
September 1, 2004: bug fix to avoid race condition in calls to mntctl on
AIX.
* Jonathan Chen <jon+amd@spock.org>
October 22, 2004: patch/fix to move mlock/mlockall/plock code after the
fork().
June 29, 2005: core dump going off end of exported_ap[] array.
September 29, 2005: patch/fix for pawd not to go into an infinite loop.
October 25, 2005: patch/fix for pawd to repeatedly resolve path.
* David Rage <rage@ucl.ac.uk>
January 17, 2005: prevent Amd from logging 'Read-only filesystem' errors
when the mount point has an ancestor (i.e. '/') that is mounted read-only.
* Kevin Layer <layer@franz.com>
January 28, 2005: basic instructions how to setup Amd on Mac OS-X.
* Dan Ottavio <dottavio@ic.sunysb.edu>
March 2, 2005: new global amd.conf option debug_mtab_file, to set the debug
mtab file when using debug_options=mtab. Default has changed from "./mtab"
to "/tmp/mtab" to avoid security problem. Bug fixed to ensure that Amd
terminates properly even mtab file doesn't exist.
* Erik Kline <ekline at ekline dot com>
January 3, 2005: implementation of executable maps for Amd.
* Jim Zajkowski <jim.zajkowski@gmail.com>
March 14, 2005: small patch to amd2ldif.
* Adam Morley <adam at gmi dot com>
January 27, 2005: synchronize what amd2ldif does vs. what the ldap.schema
expects.
* Graeme Wilford <G.Wilford@surrey.ac.uk>
July 4, 2005: buffer overflow in pawd.
* Steve Plite <splite-amutils@sigint.cs.purdue.edu>
September 22, 2005: repair reversed meaning of D_AMQ, so amq will unregister
on exit.

View File

@ -1,5 +1,8 @@
LIST OF KNOWN BUGS IN AM-UTILS OR OPERATING SYSTEMS
Note: report am-utils bugs via Bugzilla to https://bugzilla.am-utils.org/ or
by email to the am-utils@am-utils.org mailing list.
(1) mips-sgi-irix*
@ -163,12 +166,15 @@ kernel will panic.
The Linux kernels don't support Amd's direct mounts very well, leading to
erratic behavior: shares that don't get remounted after the first timeout,
inability to restart Amd because its mount points cannot be unmounted,
etc. There are some kernel patches on the am-utils Web site, which solve
these problems. See http://www.am-utils.org/patches/.
inability to restart Amd because its mount points cannot be unmounted, etc.
There are some kernel patches on the am-utils Web site, which solve these
problems. See http://www.am-utils.org/patches/.
UPDATE: kernels 2.4.10 and later completely disallow the direct mount hack,
so direct mounts are simply not possible on those Linux kernels.
Later 2.4.x kernels completely disallow the hack amd was using for direct
mounts, so another solution will have to be found.
Note: the above is for the old-style amd mount_type = nfs. The autofs mounts
don't support direct mounts at all (due to lack of kernel support).
(12) *-aix5.1.0.0 and *-hpux9*
@ -177,14 +183,24 @@ to use /bin/ksh instead. The buildall script will do it for you; if for some
reason you need to run configure directly, run it using 'ksh configure'
instead of just 'configure'.
[12A] *-aix5.1.*
[12A] *-aix5.2.*
Apparently there is an NFS client side bug in vmount() which causes amd to
hang when it starts (and tries to NFS-mount itself). According to IBM
engineers, this has to do with partial support code for IPv6: the NFS kernel
code doesn't appear to recognize the sin_family of the amd vmount(),
although amd does the right thing. The bug appears to have been fixed in
AIX 5.2. No known fix/patch is available for AIX 5.1 as of now (1/25/2003).
although amd does the right thing. The bug doesn't appear to be in 5.1 or
4.3.3. A fix from IBM is available, APAR number IY41417.
A binary built on 4.3.3 will not work on 5.2, because the kernel ABIs have
changed.
[12C] *-aix*
It is important that you install bos.net.nfs.adt before configuring and
building am-utils. If you don't, you will get compile-time or
configure-time errors, especially when configure tries to find AIX's
definition of struct nfs_args.
(13) *-linux and *-darwin6.0
@ -201,6 +217,87 @@ default). Nonetheless, if a TCP connection breaks, under certain unclear
circumstances the kernel might "forget" about that flag and start using
unprivileged ports, causing the same EPERM error above.
(14) Solaris
Erez & Ion.
The line "%option" in *.l files may cause Solaris /usr/ccs/bin/lex to abort
with the error "missing translation value." This is a bug in Solaris lex.
Moreover, both Solaris yacc and lex produce code that does not pass strict
compilation such as "gcc -Wall -Werror".
Use GNU Flex and Bison instead. You can download ready-made binaries from
www.sunfreeware.com. Note, however, that sometimes the binaries on
sunfreeware.com don't seem to work, often because they are built against an
older revision of Solaris or build tools. In that case, build a fresh
version of GNU flex and/or bison from the latest stable sources. See
http://www.gnu.org/software/flex/ and http://www.gnu.org/software/bison/.
(15) Solaris 8 + patch 10899[34]-xx (18 <= xx < 25) or patch 11260[56]-xx
With this patch, Sun updated the autofs kernel module and automountd
userspace daemon from version 3 to version 4. They also updated the
/usr/include/rpcsvc/autofs_prot.x file, but forgot to regenerate the
autofs_prot.h file. Thus, when amd is compiled, it uses the old header and
thinks it should use autofs version 3, when in fact the kernel now supports
(and expects) only version 4.
The workaround is to run 'rpcgen -C -h /usr/include/rpcsvc/autofs_prot.x >
/usr/include/rpcsvc/autofs_prot.h' and completely reconfigure and rebuild
am-utils (removing config.cache before running configure).
The problem is fixed in patch revisions 10899[34]-25 and up.
(16) Linux kernel 2.4+ and lofs mounts
Lofs mounts are not supported by the linux kernel, at all, but since 2.4.0
the kernel supports a similar type of mount called a bind mount. Its
semantics are closer to those of a hardlink than to those of lofs, and one
of the results is that bind mounts ignore any mount options paseed to them.
Amd uses bind mounts internally to emulate lofs mounts, which means that
lofs mounts on linux will effectively ignore their mount parameters and
inherit whatever options the original filesystem mounted upon had.
(17) autoconf 2.57
If you see configure warnings of the following kind:
configure: WARNING: sys/proc.h: present but cannot be compiled
configure: WARNING: sys/proc.h: check for missing prerequisite headers?
configure: WARNING: sys/proc.h: proceeding with the preprocessor's result
configure: WARNING: ## ------------------------------------ ##
configure: WARNING: ## Report this to bug-autoconf@gnu.org. ##
configure: WARNING: ## ------------------------------------ ##
please ignore them. They are not real errors, and neither
bug-autoconf@gnu.org nor the am-utils maintainers are interested in hearing
about them. Autoconf simply tries to do more than we need and attempts to
compile each header in isolation, which fails for many system headers.
That's ok, because we only need to know if a header file exists -- we know
how to use it properly ourselves.
While autoconf does offer a way to specify other files to be included with
the tested header, in order to avoid these warnings, using it would enlarge
the resulting configure script by an order of magnitude, and for no real
gain. Configure is big enough as it is, we don't need any more useless
baggage in it.
(18) NetBSD 2.0.2, FreeBSD 5.4, OpenBSD 3.7, and quite possibly most other
BSDs and other OSs (as of September 2005)
Some BSD kernels don't have a way to turn off the NFS attribute cache. They
don't have a 'noac' mount flag, and setting various cache timeout fields in
struct nfs_args doesn't turn off the attribute cache; instead, it sets the
attribute cache timeout to some internal hard-coded default (usually
anywhere from 5-30 seconds). If Amd cannot turn off the NFS attribute
cache, under heavy Amd usage, users could get ESTALE errors from automounted
symlinks, or find that those symlinks point to the wrong place. One
workaround which would minimize this effect is to set auto_attrcache=1 in
your amd.conf, but it doesn't eliminate the problem! The best solutions are
(1) to use Amd in Autofs mode, if it's supported in your OS, and (2) talk to
your OS vendor to support a true "noac" flag. See README.attrcache for more
details.
Erez & the am-utils team.

View File

@ -1,4 +1,4 @@
Copyright (c) 1997-2004 Erez Zadok
Copyright (c) 1997-2006 Erez Zadok
Copyright (c) 1989 Jan-Simon Pendry
Copyright (c) 1989 Imperial College of Science, Technology & Medicine
Copyright (c) 1989 The Regents of the University of California.

File diff suppressed because it is too large Load Diff

69
contrib/amd/FAQ Normal file
View File

@ -0,0 +1,69 @@
Am-utils Frequently Asked Questions
Note: we started this FAQ only on March 15, 2005; so it's not long or
comprehensive, yet. Amd is much older than that, and so there's a lot of
information that's already available in other forms. If this FAQ doesn't
answer your questions, see information in the following sources:
1. The Am-utils book: http://www.am-utils.org/docs/amd-book/
2. The Am-utils user manual, which is part of the distribution and is also
available from www.am-utils.org.
3. The www.am-utils.org Web site resources, especially the "am-utils" mailing
list (and its archives).
4. In the am-utils distribution (always use the latest ones), see all of the
various README files (README, README.autofs, README.ldap, README.osx, and
README.y2k). The "BUGS" file also lists useful information about bugs
and problems with specific OSs which affect Amd. All of these text files
are also available from www.am-utils.org.
5. Some FAQ questions (including newbie questions) are available here:
http://www.kernelcorp.com/resources_faqs.html
6. Some problems are known bugs but have not been fixed yet: this are
listed in bugzilla in https://bugzilla.am-utils.org/
If you have additions to this FAQ, please let us know at
am-utils@am-utils.org.
Thank you,
The Am-utils development team.
<FAQ>
*** Linux Questions
Q1. When I use Amd with Autofs and I restart Amd, how come it cannot remount
the Autofs partitions?
A1. This is a limitation of the Linux Autofs kernel module (for both autofs
v2. and v3). The Linux Autofs does not allow restarting automounted
points. There's nothing Amd can do about this. In fact, the same
problem exists if you use the userland "automount" daemon instead of
Amd. Hopefully Autofs-v4 or the separate effort of Autofs-NG will
address this serious problem.
Note that Amd itself can restart autofs automounted points just fine on
OSs that support it, for example Solaris.
Q2. When I use Amd, I get this console message frequently: "mount version
older than kernel." Is it a problem?
A2. No, it's a harmless warning message that the Linux kernel prints for NFS
mounts. The intent was to alert administrators that the kernel has
supposedly a different version of the mount(2) code than a userland
program used. This happens if you compile Amd against kernel headers
that are different than the kernel you're running. If the message
really bothers you, then one way to "fix" the problem is to recompile
Amd against the same kernel headers as the running kernel.
Nevertheless, it is a relatively useless message because as far as we
know, the NFS v2 and v3 mount codes have been in perfect sync between
the userland and kernel sides, and were "standardized" for years
already. This warning message caused more unnecessary worry among
administrators than helping alert them to legitimate problems.
</FAQ>

View File

@ -1,113 +1,91 @@
am-utils 6.0 compatibility list
am-utils 6.1 compatibility list
For each system, list if it autoconfigures, compiles, or runs. Fill in
email id of person who confirms the fact. A missing entry means unverified.
A 'no' or 'X' means verified broken or nonexistent (static library).
SYSTEM CONFIG COMPILE RUN SHLIB
========================= ====== ======= ===== =====
alpha-dec-osf2.1 ezk[0] ezk ezk ezk[X]
alpha-dec-osf4.0 ezk[0] ezk dsr[3] ezk
alpha-dec-osf4.0f ezk[0] ezk dsr[3] ezk
alpha-dec-osf5.1 ro[0] ro ro ro
alphaev5-unknown-linux ezk[0] ezk finkel ezk
alphaev5-unknown-linux-rh5.2 ezk[0] ezk ezk ezk
alphaev6-dec-osf5.0 ezk[0] ezk dsr[3] ezk
hppa1.0-hp-hpux11.00 ezk[0] ezk ezk ezk
hppa1.1-hp-hpux10.10 ezk[0] ezk ezk ezk
hppa1.1-hp-hpux10.20 ezk[0] ezk ezk ezk
hppa1.1-hp-hpux11.00 ezk[0] ezk ezk ezk
hppa1.1-hp-hpux9.01 ezk[0,4]ezk[4] nrh/ezk ezk
hppa1.1-hp-hpux9.05 ezk[0,4]ezk[4] nrh/ezk ezk
hppa1.1-hp-hpux9.07 ezk[0,4]ezk[4] nrh/ezk ezk
hppa2.0w-hp-hpux11.00 ezk[0] ezk ezk ezk
i386-pc-bsdi2.1 ion ion ion ion[X]
i386-pc-bsdi3.0 ezk[0] ezk ezk ezk[X]
i386-pc-bsdi3.1 ezk[0] ezk ezk ezk[X]
i386-pc-bsdi4.0 ezk[0] ezk ezk ezk
i386-pc-bsdi4.0.1 ezk[0] ezk ezk ezk
i386-pc-bsdi4.1 ezk[0] ezk ezk ezk
i386-pc-linux ezk[0] ezk ezk ezk
i386-pc-linux-libc1 ezk[0] ezk ezk ezk
i386-pc-linux-libc1-rh4.2 ezk[0] ezk ezk ezk
i386-pc-linux-rh5.2 ezk[0] ezk ezk ezk
i386-pc-linux-rh6.0 ezk[0] ezk ezk ezk
i386-pc-linux-rh6.1 ezk[0] ezk ezk ezk
i386-pc-linux-rh6.2 ion ion ion ion
i386-pc-linux-rh7.1 ion ion ion ion
i386-pc-linux-rh7.2 ion ion ion ion
i386-pc-linux-rh7.3 ion ion ion ion
i386-pc-solaris2.5.1 ezk[0] ezk ezk ezk
i386-pc-solaris2.6 ezk[0] ezk ezk ezk
i386-pc-solaris2.7 ezk[0] ezk ezk ezk
i386-unknown-freebsd2.1.0 ezk[0] ezk ezk
i386-unknown-freebsd2.2.1 ezk[0] ezk ezk ezk
i386-unknown-freebsd2.2.6 ezk[0] ezk ezk ezk
i386-unknown-freebsd2.2.7 ezk[0] ezk ezk ezk
i386-unknown-freebsd2.2.8 ezk[0] ezk ezk ezk
i386-unknown-freebsd3.0 ezk[0] ezk ezk ezk
i386-unknown-freebsd4.2 ezk[0] ezk ezk ezk
i386-unknown-freebsd4.4 ezk[0] ezk ezk ezk
i386-unknown-freebsd5.0 ezk[0] ezk ezk ezk
i386-unknown-freebsdelf3.0 ezk[0] ezk ezk ezk
i386-unknown-freebsdelf3.1 ezk[0] ezk ezk ezk
i386-unknown-freebsdelf3.2 ezk[0] ezk ezk ezk
i386-unknown-freebsdelf3.3 ezk[0] ezk ezk ezk
i386-unknown-freebsdelf3.4 ezk[0] ezk ezk ezk
i386-unknown-freebsdelf4.0 ezk[0] ezk ezk ezk
i386-unknown-netbsd1.2.1 ezk[0] ezk ezk ezk
i386-unknown-netbsd1.3 ezk[0] ezk ezk ezk
i386-unknown-netbsd1.3.1 ezk[0] ezk ezk ezk
i386-unknown-netbsd1.3.2 ezk[0] ezk ezk ezk
i386-unknown-netbsd1.3.3 ezk[0] ezk ezk ezk
i386-unknown-netbsd1.4 ezk[0] ezk ezk ezk
i386-unknown-netbsd1.4.1 ezk[0] ezk ezk ezk
i386-unknown-openbsd2.1 ezk[0] ezk ezk ezk
i386-unknown-openbsd2.2 ezk[0] ezk ezk ezk
i386-unknown-openbsd2.3 ezk[0] ezk ezk ezk
i386-unknown-openbsd2.4 ezk[0] ezk ezk ezk
i386-unknown-openbsd2.5 ezk[0] ezk ezk ezk
i486-ncr-sysv4.3.03 ezk[0] ezk ezk
ia64-hp-hpux11.20 ezk[0] ezk ezk ezk
ia64-unknown-linux-rh7.1 ezk[0] ezk ezk ezk
ia64-unknown-linux-rh7.2 ezk[0] ezk ezk ezk
ia64-unknown-linux-rh2.1AS ezk[0] ezk ezk ezk
ia64-unknown-linux-rh2.1AW ezk[0] ezk ezk ezk
m68k-hp-hpux9.00 ezk[0,4]ezk[4] nrh/ezk
m68k-next-nextstep3 ezk[0] ezk ezk ezk[X]
m68k-sun-sunos4.1.1 ezk[0] ezk ezk[X]
mips-dec-ultrix4.3 ro[0] ro ro
mips-sgi-irix5.3 ezk[0] ezk ezk ezk
mips-sgi-irix6.2 ezk[0,1]ezk[1] ezk[1] ezk
mips-sgi-irix6.4 ezk[0] ezk ezk ezk
mips-sgi-irix6.5 ezk[0] ezk ezk
powerpc-ibm-aix4.1.5.0 ezk[0] ezk wpaul ezk[X]
powerpc-ibm-aix4.2.1.0 ezk[0] ezk ezk ezk[X]
powerpc-ibm-aix4.3.1.0 ezk[0] ezk ezk[X]
powerpc-ibm-aix5.1.0.0 ion ion ion ion[X]
powerpc-unknown-linux jose[0] jose jose
rs6000-ibm-aix3.2 ezk[0] ezk ezk
rs6000-ibm-aix3.2.5 ezk[0] ezk ezk
rs6000-ibm-aix4.1.4.0 ezk[0] ezk ezk[X]
rs6000-ibm-aix4.1.5.0 ezk[0] ezk ezk[X]
sparc-sun-solaris2.3 ezk[0] ezk ezk ezk
sparc-sun-solaris2.4 ezk[0] ezk ezk ezk
sparc-sun-solaris2.5 ezk[0] ezk ezk ezk
sparc-sun-solaris2.5.1 ion ion ion ion
sparc-sun-solaris2.6 ion ion ion ion
sparc-sun-solaris2.7 ion ion ion ion
sparc-sun-solaris2.8 ion ion ion ion
sparc-sun-sunos4.1.1 ezk[0] ezk ezk ezk
sparc-sun-sunos4.1.3 ezk[0] ezk ezk ezk
sparc-sun-sunos4.1.3C ezk[0] ezk ezk ezk
sparc-sun-sunos4.1.3_U1 ezk[0] ezk ezk ezk
sparc-sun-sunos4.1.4 ezk[0] ezk ezk ezk
sparc-unknown-linux-libc1 ezk[0] ezk ezk ezk
sparc-unknown-linux-rh6.2 ion ion ion ion
sparc-unknown-netbsd1.2E ezk[0] ezk ezk
sparc-unknown-netbsd1.2G ezk[0] ezk ezk
sparc64-unknown-linux-rh6.2 ion ion ion ion
sparc64-unknown-linux-suse7.3 ezk[0] ezk ezk ezk
SYSTEM CONFIG COMPILE RUN SHLIB AUTOFS
========================= ======= ======= ======= ======= ======
alpha-dec-osf4.0f ro ro ro - -
alpha-dec-osf5.1 ro ro ro - -
alpha-unknown-linux-gentoo1.4.16 ezk ezk ezk ezk -
alphaev56-dec-osf4.0f ezk ezk ezk ezk -
i386-apple-darwin6.0 ezk ezk ezk ezk -
i386-pc-bsdi2.1 ion ion ion ion[X] ion[X]
i386-pc-linux-deb3.0 ezk ezk ezk ezk -
i386-pc-linux-deb3.1 ezk ezk ezk ezk -
i386-pc-linux-fc1 ezk ezk ezk ezk -
i386-pc-linux-fc2 ezk ezk ezk ezk -
i386-pc-linux-fc3 ezk ezk ezk ezk -
i386-pc-linux-fc4 ezk ezk ezk ezk -
i386-pc-linux-gentoo1.4.16 ezk ezk ezk ezk -
i386-pc-linux-rh6.2 ion ion ion ion ion
i386-pc-linux-rh7.1 ion ion ion ion ion
i386-pc-linux-rh7.2 ion ion ion ion ion
i386-pc-linux-rh7.3 ion ion ion ion ion
i386-pc-linux-rh8.0 ezk ezk ezk ezk -
i386-pc-linux-rh9 ion ion ion ion ion
i386-pc-linux-rhel3 ezk ezk ezk ezk -
i386-pc-linux-rhel4 ezk ezk ezk ezk -
i386-pc-linux-suse8.2 ezk ezk ezk ezk -
i386-pc-linux-suse9.1 ezk ezk ezk ezk -
i386-pc-linux-suse9.2 ezk ezk ezk ezk -
i386-pc-linux-suse9.3 ezk ezk ezk ezk -
i386-pc-solaris2.10 ro ro ro - -
i386-pc-solaris2.9 ro ro ro - -
i386-unknown-freebsd4.10 ezk ezk ezk ezk -
i386-unknown-freebsd4.11 ezk ezk ezk ezk -
i386-unknown-freebsd4.8 ezk ezk ezk ezk -
i386-unknown-freebsd4.9 ezk ezk ezk ezk -
i386-unknown-freebsd5.0 ezk ezk - ezk -
i386-unknown-freebsd5.1 ezk ezk ezk ezk -
i386-unknown-freebsd5.2 ezk ezk ezk ezk -
i386-unknown-freebsd5.2.1 ezk ezk ezk ezk -
i386-unknown-freebsd5.3 ezk ezk ezk ezk -
i386-unknown-freebsd5.4 ezk ezk ezk ezk -
i386-unknown-freebsd6 (BETA5) ezk ezk ezk ezk -
i386-unknown-netbsd1.6A ezk ezk ezk ezk -
i386-unknown-netbsdelf1.6.1 ezk ezk ezk ezk -
i386-unknown-netbsdelf1.6.2 ezk ezk ezk ezk -
i386-unknown-netbsdelf2.0 ezk ezk ezk ezk -
i386-unknown-netbsdelf2.0.2 ezk ezk ezk ezk -
i386-unknown-netbsdelf3.0 ezk ezk ezk ezk -
i386-unknown-openbsd3.3 ezk ezk ezk ezk -
i386-unknown-openbsd3.6 ezk ezk ezk ezk -
i386-unknown-openbsd3.7 ezk ezk ezk ezk -
i686-apple-darwin6.6 ezk ezk ezk ezk -
ia64-hp-hpux11.20 ezk ezk ezk ezk -
ia64-unknown-linux-rh2.1AS ezk ezk - ezk -
ia64-unknown-linux-rh2.1AW ezk ezk ezk ezk -
ia64-unknown-linux-rhel4 ezk ezk ezk ezk -
mips-sgi-irix6.2 ro ro ro - -[3]
mips-sgi-irix6.5 ro ro ro - -[3]
mips-unknown-linux-gentoo1.4.16 ezk ezk ezk ezk -
mipsel-unknown-linux-rhPS2 ezk ezk ezk ezk -
powerpc-apple-darwin7.6.0 ezk ezk ezk ezk -
powerpc-apple-darwin7.7.0 ezk ezk ezk ezk -
powerpc-apple-darwin7.8.0 ezk ezk ezk ezk -
powerpc-apple-darwin7.9.0 ezk ezk ezk ezk -
powerpc-apple-darwin8.2.0 ezk ezk ezk ezk -
powerpc-ibm-aix5.1.0.0 ion ion ion ion[X] ion[1,2]
powerpc-ibm-aix5.2.0.0 ezk ezk ezk ezk -
powerpc-ibm-aix5.3.0.0 ezk ezk ezk ezk -
powerpc-unknown-linux-yellowdog2.3 ezk ezk ezk ezk -
sparc-sun-solaris2.10 ro ro ro - -
sparc-sun-solaris2.5.1 ion ion ion ion ion[1]
sparc-sun-solaris2.6 ion ion ion ion ion
sparc-sun-solaris2.7 ion ion ion ion ion
sparc-sun-solaris2.8 ion ion ion ion ion
sparc-sun-solaris2.9 ro ro ro - -
sparc-unknown-linux-rh62 ion ion ion ion ion
sparc64-unknown-linux-aurora10 ion ion ion ion ion
sparc64-unknown-linux-deb3.0 ezk ezk ezk ezk -
sparc64-unknown-linux-gentoo1.4.16 ezk ezk ezk ezk -
sparc64-unknown-linux-rh62 ion ion ion ion ion
sparc64-unknown-linux-suse7.3 ezk ezk - ezk -
x86_64-unknown-linux-rh2.9.5AS ezk ezk ezk ezk -
x86_64-unknown-linux-rh3.0.0AS ion ion ion ion ion
EMAIL ID LEGEND:
@ -125,39 +103,22 @@ wpaul: Bill Paul <wpaul@ctr.columbia.edu>
FOOTNOTES:
[0] These entries were tested with older 6.0 releases, but not with the
latest version. They probably still work, however.
[1] Due to limitations in the Sun autofs v1 implementation, some amd features
cannot be properly supported. More precisely, trying to access a link mount
pointing to another amd entry will result in failure and/or deadlock.
Ordinary nfs and link mounts work well, however.
[1] If compiling with cc on Irix 6, then use
[2] AIX autofs appears to be a variant of the Sun autofs v1 protocol, but
IBM don't provide any sort of documentation or even header files from it.
It is currently unsupported; we may add some experimental support for it at
some point, though it won't be pretty. Assistance from IBM-ers would be
highly appreciated, hint hint.
CC="cc -32 -Wl,-woff,84" ./buildall
[3] IRIX 6 autofs uses the Sun autofs v1 protocol, too. The header files
are part of the onc3_eoe.sw.autofs (IRIX 6.2) or nfs.sw.autofs (IRIX 6.5)
package, which may not be installed. The autofs code is known to compile,
but hasn't been run yet. SGI's autofsd uses a barely documented system
call, syssgi(SGI_AUTOFS_SYS, ...), which may be required to get working
autofs support. Additional help from SGI would be highly appreciated.
to build (good) "old style" 32 bit code and suppress stupid linker warnings
about unused libraries.
Also, to get NFS V3 working, you need these two patches from SGI:
patch 1615: NFS over TCP
patch 2041: NFS roll-up patch
and then add "-p tcp" to /etc/config/nfsd.options.
[2] ... has gone missing ...
[3] DU-4.0 may not use NFS (server-side) V3 by default. You may need to
adjust /etc/init.d/nfs, and change the nfsd startup line from to
if /usr/sbin/nfsd $NUM_NFSD; then
to
if /usr/sbin/nfsd -t 8 -u 8 ; then
[4] HPUX 9.X has a bad /bin/sh that runs out of fixed memory allocations.
If you use the configure script, you must run it as
/bin/ksh ./configure
Also, this system has a bad /bin/make that cannot handle VPATH well. You
cannot use --srcdir or the buildall script with it. I suggest you install
GNU make or configure locally with "/bin/ksh ./configure".
Erez.
Erez & Ion

View File

@ -1,147 +1,663 @@
*** Notes specific to am-utils version 6.0.10-pre:
*** Notes specific to am-utils version 6.1.5
New amd.conf global parameter: nfs_allow_any_interface. By default it is
set to 'no' which means that Amd accepts local NFS packets only from
127.0.0.1. If set to 'yes' then Amd will accept local NFS packets from any
local interface; this is useful on hosts that may have multiple interfaces
where the system is forced to send all outgoing packets (even those bound to
the same host) via an address other than 127.0.0.1.
Add support for specifying the host to match in the mount selectors netgrp
and netgrpd. Now one can use either netgrp(<group-name>) or
netgrp(<group-name>,<host-name>).
- Bugs fixed:
* handle old-style filehandles correctly (for mount points longer
than 28 chars)
* don't turn off attribute cache for regular NFS mounts (improves
performance)
* detect G/DBM support via gdbm_compat library (Debian)
* detect NDBM support in libc (FreeBSD 6)
- minor new ports:
ia64-unknown-linux-rh2.1AS (Red Hat Itanium Advanced Server)
i386-unknown-freebsd5.0 (5.0-RELEASE)
sparc64-unknown-linux-suse7.3
i386-unknown-freebsd4.9
i386-unknown-freebsd5.2 (5.2-RELEASE)
i386-unknown-freebsd6.1 (RELEASE)
i386-unknown-openbsd3.9
powerpc-apple-darwin8.6.0
- new amd.conf directive "nfs_allow_insecure_port". Used to work around
*** Notes specific to am-utils version 6.1.4
Support new mount options for type:=pcfs mounts: longname, nowin95,
shortname, user=N, group=N, mask=N, and dirmask=N.
Two new amd.conf [global] parameters: nfs_retry_interval_toplvl and
nfs_retransmit_counter_toplvl. They are similar to nfs_retry_interval and
nfs_retransmit_counter, and allow you to set the "timeo" and "retrans" NFS
mount parameters, respectively, but ONLY for Amd's top-level mounts (which
are NFSv2/UDP currently). This is useful because on some systems you may
wish to set these parameters differently than the OS default, so as to
better tune Amd's responsiveness under heavy scheduler loads.
- minor new ports:
i386-pc-linux-fc5 (Fedora Core 5)
i386-pc-linux-suse10.1 (beta 8)
i386-unknown-freebsd6.0 (RELEASE)
i386-unknown-netbsdelf2.1
i386-unknown-netbsdelf3.0 (RELEASE)
i386-unknown-openbsd3.8
powerpc-apple-darwin8.5.0
- Bugs fixed:
* one serious memory leak in amfs_generic (caught by Coverity)
* assorted potential (but rare) NULL pointer dereferences (Coverity)
* correctly print nfs_args->addr info (sin_family/port/addr)
* pawd should resolve path repeatedly until no more to do
* use-after-free bug in amfs_lookup_mntfs (Coverity)
*** Notes specific to am-utils version 6.1.3
- Bugs fixed:
* amq should de-register properly on exit
* convert all sprintf to safer xsnprintf
* convert all strcat to safer xstrlcat
* convert all strcpy to safer xstrlcpy
* fix three buffer overruns in expand_op (amd/opts.c)
* pawd was trying UDP only, now try TCP if UDP failed
Moved pawd's path-matching functionality into Amd, where it can be done a
lot more efficiently (we no longer need to construct and send the whole
mounted tree, only to match small parts of it). This will lessen the CPU
and network load on systems that use pawd heavily, and also minimize the
chance that we exceed default or hard-coded UDP/TCP RPC packet sizes.
*** Notes specific to am-utils version 6.1.2.1
- Bugs fixed:
* properly turn off the attrcache in freebsd and openbsd
* can turn off attrcache on netbsd, but need kernel patch, see
README.attrcache
* pawd goes into an infinite loop on type:=auto
* consistent search for file system mnttab/mount names
*** Notes specific to am-utils version 6.1.2
MAJOR BUG FIXES: Synchronize Amd's view of its file systems with the
kernel's NFS client-side DNLC/dcache. Amd changes its view when it reloads
maps (automatically or via "amq -f") because new map entries could be added,
old one removed, or existing ones changed. Amd also changes its view when a
simple entry has expired and was flushed, or was forced out via "amq -u".
Amd was not updating the mtime of its parent directory (often the amd
automount point): this resulted in the kernel re-using cached entries, which
are now possibly stale. Many users had seen this problem in the form of
occasional ESTALE errors, or dangling/broken automounted symlinks,
especially on systems under heavy use. To tell the kernel to ignore (flush)
its old entries for an directory, the mtime of the directory must be updated
(monotonically incremented). Amd was indeed doing so in several places, but
unfortunately it was using time(2) which only provides a one-second
resolution clock: this was fine a decade ago, but not good enough on today's
fast systems; using only a one-second resolution clock meant that on busy
systems that invoke Amd many times a second, some rapidly changing entries
do not get flushed from the kernel, and the kernel thus uses stale entries.
The solution to all of these was to rework the whole clock timer updates to
use gettimeofday(), using a micro-second resolution timer, and to use that
time whenever Amd needs to update an mtime/atime/ctime of any node.
Finally, we now update the mtime in places that were never updated before
(when a whole map is flushed or a single entry times out).
Warning: some OSs, we discovered, are incapable of turning off their
NFS attribute cache entirely. This means that Amd cannot work fully
reliability on these systems, not under heavy load. This is documented in
detail in the README.attrcache file included with this distribution.
Include test-attrcache script to test the NFS attribute cache behavior using
Amd.
Tell syslog not to log automatically to /dev/console; it's unfriendly. If
user really wants to, they can set it in /etc/syslog.conf.
- minor new ports:
i386-pc-linux-deb3.1
i386-unknown-netbsdelf3.0
powerpc-apple-darwin8.2.0
- bugs fixed:
* minor documentation corrections
*** Notes specific to am-utils version 6.1.1
New amd.conf global parameter: forced_unmounts (default to "no"). If set to
"yes," and the client OS supports forced or lazy unmounts, then Amd will
attempt to use them if it gets any of three serious error conditions when
trying to unmount an existing mount point or mount on top of one: EIO,
ESTALE, or EBUSY. This could be useful to recover from serious conditions
such as hardware failure of mounted disks, or NFS servers which are down
permanently, were migrated, or changed their IP address. Only
"type:=toplvl" mounts hung with EBUSY are forcibly unmounted using this
option: this is useful to ensure that a new Amd can mount itself even if a
previous Amd died and left its mount points hung, or to force Amd to
shutdown cleanly, even if some processes (i.e., user shells) have their CWD
on Amd's own mount point. This functionality is available for Linux, BSD44
systems, Solaris, OSF/1, and partially for AIX.
New amd.conf global parameter: truncate_log (default to "no"). If set to
"yes", then Amd will truncate the log file (if it's a regular file) on
startup. This could be useful when conducting extensive testing on Amd maps
(or Amd itself) and you don't want to see log data from a previous run in
the same file.
- minor new ports:
i386-pc-linux-fc4
i386-pc-linux-suse9.3
i386-pc-linuxoldld-deb3.1
- bugs fixed:
* safer mtab handling for Linux (locks + handles /proc/mounts)
* small compile problems on Solaris 6 (rpcvers_t)
* small compile problems on HPUX 10 (h_errno)
* possibly missing definition of INADDR_NONE in wire.c
* extern for sleep(3) may be missing on older gcc systems
* updated nfs_args structure on aix4.
* possible running off end of exported_ap[] array.
* buffer overflow in pawd.
* aix4 clean build.
* use strlcat/snprintf in a few places for safety.
* recover from IP address change of a down NFS server
* don't discard restarted mntfs that was used.
*** Notes specific to am-utils version 6.1
- bugs fixed:
* set timeo/retrans for type:=nfs only if user asked
Also, if you want to know what's new in 6.1 compared to 6.0.x, it's
EVERYTHING below this line, up to "6.0.4." Yes, that's a lot of stuff.
*** Notes specific to am-utils version 6.1-rc7
Remove alloca from am-utils, and rewrite code that used it.
Assorted minor code cleanups.
- minor new ports:
alpha-unknown-linux-gentoo1.4.16
alphaev56-dec-osf4.0f (using both cc and gcc)
mips-sgi-irix6.5 (using both cc and gcc)
mips-unknown-linux-gentoo1.4.16
sparc64-unknown-linux-gentoo1.4.16
- bugs fixed:
* getwire() detects networks correctly on OSF/1
*** Notes specific to am-utils version 6.1-rc6
- minor new ports:
i386-pc-linux-deb3.0
i386-pc-linux-gentoo1.4.16
i386-pc-linux-suse9.2
i386-unknown-freebsd5.4
i386-unknown-netbsdelf2.0.2
i386-unknown-openbsd3.7
powerpc-unknown-linux-yellowdog2.3
- bugs fixed:
* minor compile error of nfs_subr.c on some systems.
* AIX 5.2/5.3 PPC compile fixes.
*** Notes specific to am-utils version 6.1-rc5
For NetBSD systems, $os used to say "netbsdelf1" or "netbsdelf2." Now it
just says "netbsd."
- minor new ports:
powerpc-apple-darwin7.9.0
- bugs fixed:
* silly (but nasty) null pointer dereferencing
* improved fix for '-opts' syntax for resetting map options
*** Notes specific to am-utils version 6.1-rc4
- bugs fixed:
* check for "macosx" in M4 macros properly
* minor memory leaks (thanks to Valgrind)
*** Notes specific to am-utils version 6.1-rc3
Minor fix to configure.in. Reran bootstrap to get a working configure
script that indeed checks for certain Linux nfs/autofs headers.
*** Notes specific to am-utils version 6.1-rc2
New amd.conf global parameter: normalize_slashes (default to "yes"). If set
to "no," then Amd will not condense repeated slashes or remove trailing ones
from strings representing pathnames. This is sometimes useful with SMB
mounts, which often require multiple slash characters in pathnames.
Using a custom version of strlcpy instead of strncpy (but only where it
makes sense), to minimize string overflow changes. Audited all use of
strncpy/strlcpy to ensure safety.
On Apple machines, use "powerpc" for $arch, instead of "Power Macintosh".
Also, use sw_vers to find out more appropriate OS name (macosx) and OS
version (10.3.x) than uname(3) reports.
- minor new ports:
powerpc64-unknown-linux-rhel4
powerpc64-unknown-linux-sles9
- bugs fixed:
* pawd handles all file systems
* fix double-free in type:=nfsx
* timeo and retrans shouldn't be set for type:=toplvl
* fix inconsistency in handling filehandle generation number
* document proper use of hosts.allow (don't spawn)
* single dash '-' map entry now resets the defaults
*** Notes specific to am-utils version 6.1-rc1
- minor new ports:
i386-pc-linux-fc2 (Fedora Core 2).
i386-pc-linux-fc3 (Fedora Core 3).
i386-pc-linux-rhel3
i386-pc-linux-rhel4
i386-pc-linux-suse8.2
i386-pc-linux-suse9.1
i386-pc-solaris2.10
i386-unknown-freebsd4.8
i386-unknown-freebsd4.9
i386-unknown-freebsd4.10
i386-unknown-freebsd4.11
i386-unknown-freebsd5.1 (5.1-RELEASE)
i386-unknown-freebsd5.2 (5.2-RELEASE)
i386-unknown-freebsd5.2.1 (5.2.1-RELEASE)
i386-unknown-freebsd5.3 (5.3-RELEASE)
i386-unknown-freebsd6.0 (6.0-CURRENT-SNAP001)
i386-unknown-netbsdelf1.6.1
i386-unknown-netbsdelf2.0
i386-unknown-openbsd3.6
ia64-hp-hpux11.20
ia64-unknown-linux-rhel4
mipsel-unknown-linux-rhPS2 (Linux on Sony PlayStation 2)
powerpc-apple-darwin7.6.0
powerpc-apple-darwin7.7.0
powerpc-apple-darwin7.8.0
powerpc-ibm-aix5.2.0.0
powerpc-ibm-aix5.3.0.0
sparc-sun-solaris2.10
sparc64-unknown-linux-deb3.0
x86_64-unknown-linux-rh2.9.5AS
- support for executable maps ala Sun automounter. Set map_type=exec in
amd.conf, and map_name to a program/script that takes a key as argv[1],
and returns key-value pair on stdout. See also exec_map_timeout [global]
parameter which defines how many seconds (default 10 sec) Amd will wait
for an executable map program to return output before timing out. See
am-utils manual for full details.
- new amd.conf parameter "nfs_allow_insecure_port". Used to work around
bugs in certain kernels, which cause them to try and talk to amd from
unprivileged ports.
- bug fixes:
rename log() in fsinfo to avoid glibc/gcc-3.3 conflict
am_pref free NULL pointer
compiles with modern bison/flex versions
handles sites with various combos of db, n/dbm, and gdbm
- new amd.conf parameter: localhost_address. Used to override the localhost
(often 127.0.0.1) address Amd uses to connect to for the local NFS server
and RPC server.
*** Notes specific to am-utils version 6.0.9:
- new amd.conf [global] parameter: domain_strip (default "yes"). If set to
"no," Amd won't strip domain names from host names, which is useful if
your Amd maps are served by multiple domains and you want to tell from the
logs which exact host did what.
- Minor new ports:
i386-apple-darwin6.0
sparc-sun-solaris2.9
- new amd.conf [global] parameter: auto_attrcache (default to 0). Sets
Amd's own NFS attribute-cache timeout in seconds. A value of 0 turns off
attribute caching, meaning that Amd will be consulted via a kernel-RPC
each time someone stat's the mount point (which could be abused as a
denial-of-service attack). If you're concerned, set this to something
greater than zero (a value of 1 second is currently recommended).
Warning: if you set this option to any non-zero value, especially a large
value, and you get ESTALE errors on your particular OS, then set this
value back to 0 seconds.
- four new amd.conf [global] parameters, similar to nfs_retry_interval and
nfs_retransmit_counter, which allow you to set the "timeo" and "retrans"
NFS mount parameters, respectively. Now you can set those parameters
globally and separately for UDP vs. TCP, using any of these:
nfs_retry_interval_udp, nfs_retransmit_counter_udp nfs_retry_interval_tcp,
and nfs_retransmit_counter_tcp.
- new amd.conf [global] parameter: preferred_amq_port. Allows you to select
the UDP+TCP port that Amd's amq service will use with the RPC portmapper.
Useful with firewalls and NAT'ed environments.
- new amd.conf option "debug_mtab_file". Allows user to define the mtab
file during debug-mtab mode. The default path is "/tmp/mnttab".
- new function selector xhost(ARG) which will match ARG against the current
host name. This works even if ARG is a CNAME (unlike the host==ARG
selector).
- support restarting the automounter's own mount points (only over NFS,
for now).
- fully support WebNFS as per RFC 2054. It now tries v3/TCP first, falling
back to v2/UDP if this doesn't work. The "webnfs" pseudo-mount options
has been renamed (again) to "public" to match Solaris 2.
- restructured the restarting of already-mounted filesystems, in the process
also fixing a problem with restarting nfsx components.
- support escaped slashes, needed for SMB mounts. Use '\\\/\\\/' in a
string to get a double slash.
- amd -v now prints domain, host, and hostd values: foo, example.com, and
foo.example.com, respectively.
- On Linux, if umount(2) failed with EIO or ESTALE, try the new umount2(2)
system call with MNT_FORCE+MNT_DETACH. This could be quite helpful to
unmounting hung mount points that otherwise cannot be fixed without a
reboot.
- The ping=N mount option now works. N defaults to 30 seconds for all NFS
servers. It can now be set to any value for each server separately.
Setting it to a large value can reduce the amount of NFS_NULL chatter on
your network considerably, especially in large sites. Setting this to -1
will turn off pings for that server (useful in NFS-HA setups). Setting N
to 0 will pick the default ping value in Amd (currently 30 seconds). Note
that if you have multiple Amd entries using the same file server, and each
entry sets a different value of N, then each time Amd mounts a new entry,
the ping value will be re-evaluated (and updated, turned off, or turned
back on as needed). Note that NFS_NULL pings are sent for both UDP and
TCP mounts, because even a hung TCP mount can cause user processes to
hang.
- file system inheritance code restructured, so it's no longer a pseudo file
system, but actually integrated into Amd (as it should have been).
- for type:=program, the "umount" program doesn't have to be defined; it'll
default to "unmount ${fs}".
- "amd -v" now prints the distribution name if it's known (e.g., rh9, fc3,
suse8, etc.).
- bugs fixed:
* various memory management problems (leaks, etc)
* fixed nfsx support
* fixed a race involving late replies to network queries which
arrive after the file system has already been mounted
* recognize pcfs_args_t fields in FreeBSD 5
* recognize other mount types in pawd: host, linkx, and nfsx
* allow exactly one of umount and unmount in type:=program
* race condition between calls to mntctl() on AIX
* plock/mlockall wasn't inherited by fork(); moved after
daemonizing.
* fix inconsistency between Socket and TLI RPC timeouts.
* don't warn when couldn't rmdir a dir with a readonly ancestor.
* avoid hangs of amd in ctl-amd (must chdir to /)
* workaround occasional daemonizing problems (parent won't die)
* don't hang on exit if debug_options=mtab was used
* utimeout=N mount option works with non-nfs types (ufs, pcfs, etc.)
* SEGV (null pointer deref) in type:=program and type:=cachefs
* unmount_on_exit of type:=program caused amd to hang
* match amd2ldif output with ldap.schema
*** Notes specific to am-utils version 6.1b4
- minor new ports:
i686-apple-darwin6.6
- speed up the recovery of inherited (restarted) filesystems by using the
proper waiting channels
- added support for mounting webnfs filesystems, see entry below. It doesn't
do any probing currently, so it will default to v2/UDP unless another
version and/or protocol are explicitly specified.
- pseudo-mount option "ignore_portmapper" renamed to "webnfs"
- bugs fixed:
* properly time out autofs filesystems on Linux
* link mounts with relative targets weren't working on autofs
* the link side of the nfsl file system wasn't working on autofs
* umount code was accidentally turning all symlinks into directories
during attempted umounts, causing stale filehandles
* various minor build fixes for "impossible" configurations
* prevent ldap code from dereferencing a null pointer
*** Notes specific to am-utils version 6.1b3
- new amd.conf option autofs_use_lofs, set by default to "yes". "yes" means
using in-place mounts (lofs, bind mounts, etc.), thus utilizing one of
Autofs's main advantages. "no" means using symlinks instead, which has
the "/bin/pwd" problem and certain efficiency issues on Solaris 2.6+ and
is also not supported on Solaris Autofs v1 and derivatives; however, the
autofs code that uses symlinks is simpler and more thoroughly tested.
- new amd.conf option map_default (can be used in [global] and overwritten
in the per-map section). This will overwrite the /defaults entry of the
map itself, to allow people to set defaults in amd.conf (useful when you
cannot control your amd maps, or you'd rather not modify them globally).
- for type:=program, you can use either unmount:=XXX or umount:=XXX (but not
both). This new 'unmount' name is an alias for convenience.
- fixed the "multiple matching sub-entries in a map entry" semantics to try
mounting those sub-entries one by one, until either one succeeds or all
fail. The old semantics of trying to mount everything in parallel and use
the one that mounted fastest hasn't worked in a long time; in fact, 6.0
currently simply ignores all but the first matching sub-entry.
- made amd fail much faster (instantly, in fact) if the remote server
doesn't have a functional portmapper or NFS service. Also reduced the
total timeout to 3 seconds for a completely downed server.
- new pseudo-mount option "ignore_portmapper"; not very useful currently,
will make more sense when we also accept hard-coded ports for mountd and
nfsd.
- amd will no longer query the portmapper for all possible NFS versions and
protocols if the user requested to use specific ones.
- increased the major number for the library, so that 6.0 and 6.1 can't
share libraries anymore.
- support tcpd/libwrap tcpwrappers. If your system supports libwrap, then
you can use /etc/hosts.allow and /etc/hosts.deny to control remote Amq
access to Amd. The new amd.conf parameter use_tcpwrappers is set to "yes"
by default.
- support NULL entries in Hesiod maps, if they start with a ".".
- code reorganization
- documentation cleanup, corrections, and general updates. Better
references to all man pages. Support newer texi2html. Proper building of
DVI and PSI files. Allow building of am-utils manual in one long Web
page.
- minor new ports:
ia64-unknown-linux-rh2.1AS (Red Hat Itanium Advanced Server)
i386-unknown-freebsd5.0 (5.0-RELEASE)
sparc64-unknown-linux-suse7.3
i386-unknown-netbsdelf1.6.1
i386-unknown-openbsd3.3
i386-pc-solaris2.9
- bugs fixed:
* autofs mode on Linux was segfaulting on a silly error (and noone
complained, which proves that I'm probably the only one testing
these beta releases, tsk tsk).
* fixed handling of host entries over autofs.
* fixed handling of nfsl entries over autofs.
* the matching in find_mntfs() was causing problems for inherited
filesystems, so make an exception for them. Tighten the
matching even more, to take into account the f/s type as well.
* recognize xlatecookie mnttab option on netbsd
* document Solaris lex bug (use flex)
* document AIX 5.x NFS bug (need patch)
* document Solaris 8 autofs version change (need to fix system
header file)
* ensure lex doesn't run out of output slots
* support GNU flex-2.5.31+
* force version.texi to be rebuilt unconditionally
* mk-amd-map open db file exclusively (security)
* turn off maintainer-only rules in distros
* don't core dump if log_file is NULL (Solaris)
* don't include malloc.h if stdlib.h exists
* recognize file system failures (EIO) upon reading file maps
*** Notes specific to am-utils version 6.1b2
- new mount flag "softlookup", which determines how amd will respond to
lookups of NFS shares already mounted (return a valid symlink or return
EIO). The default, if "softlookup" is not specified, depends on whether the
mount is "soft" or "hard".
- return EIO instead of ENOENT if amd thinks the server is down; this allows
well-written applications to sleep and retry the operation.
- minor new ports:
i386-apple-darwin6.0
i386-pc-linux-rh8.0
ia64-unknown-linux-rh2.1AW
sparc-sun-solaris2.9
- automatic support for loop mounts on Linux (deprecates the "loop" mount
option)
- new amd.conf parameter ldap_proto_version (default 2) for setting the LDAP
protocol version to use.
- bugs fixed:
* redundancy mode (multiple servers for the same share) wasn't working
* non-autofs mode had some rather nasty hangs on downed file servers
* double-free'ing problem in assign_error_mntfs and free_continuation
* free'ing non-malloc'ed memory in amfs_auto_mount
* late server ping replies were not ignored
* amfs_auto_lookup_mntfs wasn't propagating errors up to callers
* autofs-v4 on Solaris 9 works
* handle std{in,out,err} correctly when releasing controlling tty
(for real this time)
* don't cast pointers between enum_t and u_long, it doesn't work on
64-bit big-endian platforms
* fix compile problem with mlockall() on Darwin
*** Notes specific to am-utils version 6.0.8:
*** Notes specific to am-utils version 6.1b1
- Major Autofs work
Partial support for Sun Autofs v1
Documented known problems with Sun Autofs v1 (possible deadlocks)
Fixes for Sun Autofs v2/v3
Preliminary support for Sun Autofs v4 (Solaris 9)
Kernel-based expirations for Linux Autofs
- Minor new ports:
i386-pc-linux-rh7.2
i386-pc-linux-rh7.3
i386-unknown-freebsd4.4
i386-unknown-freebsd5.0
ia64-hp-hpux11.20
ia64-unknown-linux-rh7.1
powerpc-ibm-aix5.1.0.0
i386-unknown-netbsd1.6A
- Work around IBM's NFSv3 ABI change in aix4.3
- Support network/netmask and network/masklen syntax in in_network()
- trivial regression test suite started: run "make check" on a built
am-utils to execute tests. Currently only one test which checks to see if
"amd -v" executes correctly.
- Support disabling LDAP and Hesiod support using configure
- Support xfs on Linux
- Red Hat specific Amd startup script included
- Remove (non-functional) autofs code and detection support. If you want
autofs support, use am-utils-6.1.
- new command line option "amd -A arch" to overwrite the value of $arch.
- bugs fixed:
* Linux loop mounts of ISO images
* assorted LDAP fixes
* strerror not found on some systems
* small fixes for hpux9 and aix43
* exclude ldap/hesiod support unless both libraries+headers exist
* fully support "xlatecookie" mount option
* security: if -D noamq option, don't listen on socket.
*** Notes specific to am-utils version 6.1a5:
- browsable_dirs support for Solaris autofs, *without* mount storms!
- new amd.conf global parameter: map_reload_interval (default 1 hour).
Determines how often Amd checks to see if maps have changed at the source
(and then reloading only those that have changed).
- "amd -v" now lists bug-reporting address.
- assorted code cleanups and porting to use latest versions of GNU
Autotools.
- opts:=loop works for type:=cdfs, for mounting ISO-9660 files on Linux.
- bugs fixed:
* fixed sublink support in Linux autofs (broken in a4)
* hlfsd takes uid 0's home from root's passwd entry instead of
defaulting to '/'
* (not really our bug) Linux ignores the microseconds field in
mtime, so hlfsd and amd need to increment the seconds field all
the time to prevent symlink caching
* generic map parsing bug which was rejecting a numerical mount option
if it was the last option in the string
* MacOS X compile bug
* minor fix for GNU getopt
* Linux has no "dev" mtab option
* "nolock" is an NFS mount option, not a generic one
* Irix N32 ABI fixes with cc
* security: use mkstemp instead of mktemp
* correct timeo values for Linux tcp/udp NFS mounts
* hlfsd use of setuid() not seteuid()
* AIX ABI changes to nfs_args fixes
* generic map parsing bug which was rejecting a numerical mount
option if it was the last option in the string.
* file descriptor leak in Linux autofs.
* "nolock" is an NFS mount option, not a generic one.
* use mlockall(2) on systems that have it, for plock=yes. Now
pinning Amd's pages in memory works on Linux.
* ctl-amd/ctl-hlfsd correctly refer to @sysconfdir@ for alternate
location of configuration files.
*** Notes specific to am-utils version 6.0.7:
*** Notes specific to am-utils version 6.1a4:
- minor new ports: i386-unknown-freebsd5.0
- full autofs support for Solaris 2.[67], including symlinks, sublinks and
direct mounts
- bug fixes:
type:=host, don't fail mount if one share is already mounted
don't report NFS NE_IO error as success (Linux)
- fixed mount/umount deadlock in Linux autofs
*** Notes specific to am-utils version 6.0.6:
- fixed sublinks in Linux autofs
- new ports:
Mac OS X support (Darwin, Rhapsody)
- support for network/netmask pairs in the in_network() selector
- reworked autoconf scripts so that newer versions of known OSs will default
their configuration to the last known version (better chance that it will
pass autoconf and work).
- support disabling LDAP and Hesiod support using configure
- linux support for lofs and "bind" mounts, so type:=lofs can work (whether
you're using autofs or not)
- forward-ported all the fixes from the stable branch (MacOS X support,
minor Linux fixes)
- renamed amd.conf option "selectors_on_default" to "selectors_in_defaults"
(on -> in, and added "s"). Old name remains in place for compatibility.
- bind-mount support for type==link and type==lofs with Linux 2.4+
- lots of cleanups of debugging and logging messages
- FiST lofs support under Linux (also in 6.0.6s2)
- Bugs fixed:
lots of Linux-related ones, so it compiles for recent kernels
better checking on various mount options of the form foo=N or foo=STR
fixed NFS errno mapping bug which mapped ENOENT to success on Linux
*** Notes specific to am-utils version 6.1a3:
*** Notes specific to am-utils version 6.0.5:
- various things from the 6.0 branch:
compile fixes for Linux 2.4-ac and 2.2.19pre+
Darwin/Rhapsody/OS X support
much reduced configure script (works around a bug in Darwin's cpp)
- Minor ports:
alphaev6-dec-osf5.1
i386-unknown-freebsd4.2
support for Linux 2.4 kernels and newer GLIBC versions
cleanup of AIX and IRIX6 ports
*** Notes specific to am-utils version 6.1a2:
- Support new mount options:
proplist (ACLs over NFS, DU-4.0)
kerb, rdirplus, readdirsize, and xlatecookie (NetBSD-1.5K+)
nonlm, lock, nolock (Linux)
- working autofs support for Solaris 2.[67], but incomplete
- Don't force rsize/wsize on Linux 2.2.18+ and 2.4.x. Improves performance
a lot.
- forward-ported all the changes up to 6.0.5s2
- Lots of documentation updates: texinfo, man pages, scripts, and more.
- removed support for amq -M
- LDAP: included proposed Schema and Internet Draft for LDAP Schema. See
README.ldap for more information.
- known bugs
nfsx support is broken
linux NFS codes fixes
NFS cache aliasing fixes
lots of stuff ported from 6.0 branch
- Removed all remains of the dangerous amq -M code.
*** Notes specific to am-utils version 6.1a1:
- Major bug fix: initialize NFS fileid field correctly, to avoid cache
aliasing problems, esp. on Linux.
- working autofs (v3 and v4) support for Linux!
- Major Linux bug fix: map errnos to NFS errors (mistakenly turned off a
while back). Also support unused errno 41.
- forward-ported all the changes in 6.0.4s4
- Other bugs fixes:
default MAXHOSTNAMELEN (if undefined) is 256, not 64
truncate hostnames to MAXHOSTNAMELEN (security fix)
alignment problem in getwire() on ALPHA
other buf overflow problems (security fixes)
ctl-amd supports "condrestart" (Red Hat)
bell char is \g not \a
lostaltmail verify MAILDIR is defined
am-eject accepts "floppy" and "cdrom" as args
other assorted small bug fixes
- bugs fixed
client-side fail-over to NFSv2/UDP
- known bugs
autofs v3 will probably break with host maps
*** Notes specific to am-utils version 6.0.4:
@ -514,7 +1030,7 @@ the functions compute_nfs_args() and compute_automounter_nfs_args().
- bugs fixed:
mnttab name ufs/cdfs/pcfs/etc filesystems corrected
use pmap_ping for amq (a must for secure portmappers, bsdi2/3)
test for xfs (irix) as a disk-based filesystem
test for xfs (irix) as a disk-based file system
set correct nfs_prot headers for Solaris 2.5
removed stale code from lostaltmail.in
lostaltmail will look for conf file in multiple locations
@ -931,11 +1447,11 @@ used anywhere were removed.
--enable-libs[=ARG]
configure/compile with ARG (-L/-l) library flags
- filesystem, mount table entries, and mount type tests can now look in
- file system, mount table entries, and mount type tests can now look in
/lib/modules and /proc/filesystems for statically/dyadically loadable kernel
modules (linux)
- prefer vfat over msdos/pc/etc filesystem for PCFS.
- prefer vfat over msdos/pc/etc file system for PCFS.
- moved all fixed headers to include/am_defs. Left only #define/#undef
entries in aux/acconfig.h.

View File

@ -0,0 +1,129 @@
NFS Attribute Caching OS Problems and Amd
Last updated September 18, 2005
* Summary:
Some OSs don't seem to have a way to turn off the NFS attribute cache, which
breaks the Amd automounter so badly that it is not recommend using Amd on
such OS for heavy use, not until this is fixed.
* Details:
Amd is a user-level NFSv2 server that manages automounts of all other file
systems. The kernel contacts Amd via RPCs, and Amd in turn performs the
actual mounts, and then responds back to the kernel's RPCs. Every kernel
caches attributes of files, in a cache called the Directory Name Lookup
Cache (DNLC), or a Directory Cache (dcache).
Amd manages its namespace in the user level, but the kernel caches names
itself. So the two must coordinate to ensure that both namespaces are in
sync. If the kernel uses a cached entry from the DNLC, without consulting
Amd, users may see corruption of the automounter namespace (symlinks
pointing to the wrong places, ESTALE errors, and more). For example,
suppose Amd timed out an entry and removed the entry from Amd's namespace.
Amd has to tell the kernel to purge its corresponding DNLC entry too. The
way Amd often does that is by incrementing the last modification time
(mtime) of the parent directory. This is the most common method for kernels
to check if their DNLC entries are stale: if the parent directory mtime is
newer, the kernel will discard all cached entries for that directory, and
will re-issue lookup methods. Those lookups will result in
NFS_GETATTR/NFS_LOOKUP calls sent from the kernel down to Amd, and Amd can
then properly inform the kernel of the new state of automounted entries.
In order to ensure that Amd is "in charge" of its namespace without
interference from the kernel, Amd will try to turn off the NFS attribute
cache. It does so by using the NFSMNT_NOAC flag, if it exists, or by
setting various "cache timeout" fields in struct nfs_args to 0 (acregmin,
acregmax, acdirmin, or acdirmax).
We have released a major new version of am-utils, version 6.1, in June 2005.
Since then, a lot of people have experimented with Amd, in anticipation of
migrating from the very old am-utils 6.0 to the new 6.1. For a couple of
months since the release of 6.1, we have received reports of problems with
Amd, especially under heavy use. Users reported getting ESTALE errors from
time to time, or seeing automounted entries whose symlinks don't point to
where it should be. After much debugging, we traced it to a few places in
Amd where it wasn't updating the parent directory mtime as it should have;
in some places where Amd was indeed updating the mtime, it was using a
resolution of only 1 second, which was not fine enough under heavy load. We
fixed this problem and switched to using a microsecond resolution mtime.
After fixing this in Amd, we went on to verify that things work for other
OSs. When we got to test certain BSDs, we found out that they always cache
directory entries, and there is no way to turn it off completely.
Specifically, if we set the ac{reg,dir}{min,max} fields in struct nfs_args
all to zero, the kernel seems to cache the entries for a default number of
seconds (something like 5-30 seconds). On some OSs, setting these four
fields to 0 turns off the attribute cache, but not on some BSDs. We were
able to verify this using Amd and a script that exercises the interaction of
the kernel's attrcache and Amd. (If you're interested, the script can be
made available.)
We then experimented by setting the ac{reg,dir}{min,max} fields in struct
nfs_args all to 1, the smallest non-zero value we could. When we ran the
Amd exercising script, we found that the value of 1 reduced the race between
the DNLC and Amd, and the script took a little longer to run before it
detected an incoherency. That makes sense: the smaller the DNLC cache
interval is, the shorter the window of vulnerability is. (BTW, the man
pages on some OSs say that the ac{reg,dir}{min,max} fields use a 1 second
resolution, but experimentation indicated it was in 0.1 second units.)
Clearly, setting the ac{reg,dir}{min,max} fields to 0 is worse than setting
it to 1 on those OSs that don't have a way to turn off the attribute cache.
So the current workaround I've implemented in am-utils is to create a
configuration parameter called "broken_attrcache" which, if turned on, will
set these nfs_args fields to 1 instead of 0. I wish I didn't have to create
such ugly workaround features in Amd, but I've got no choice.
The near term solution is for every OS to support a true 'noac' flag, which
can be added fairly easily. This'd make Amd work reliably.
The long term solution is to implement Autofs support for all OSs and to
support it in Amd. Currently, Amd supports autofs on Solaris and Linux;
FreeBSD is next. Still, we found that even with autofs support, many
sysadmins still prefer to use the good 'ol non-autofs mode.
* Confirmed Status
This is the confirmed status of various OSs' vulnerability to this attribute
cache bug. We are slowly checking the status of other OSs. The status of
any OS not listed is unknown as of the date at the top of this file.
** Not Vulnerable (support a proper "noac" flag):
Sun Solaris 8 and 9 (10 probably works fine)
Linux: 2.6.11 kernel (2.4.latest probably works fine)
FreeBSD 5.4 and 6.0-SNAP001 (older versions probably work fine)
OpenBSD 3.7 (older versions probably work fine)
** Vulnerable (don't support a proper "noac" flag natively):
NetBSD 2.0.2 (older versions are also probably affected)
Note: NetBSD has promised to support a noac flag hopefully after 2.1.0 is
released (maybe in 3.0 or 2.2). In the mean time, you can apply one of
these two kernel patchs to support a 'noac' flag in NetBSD 2.x or 3.x:
ftp://ftp.netbsd.org/pub/NetBSD/misc/christos/2x.nfs.noac.diff
ftp://ftp.netbsd.org/pub/NetBSD/misc/christos/3x.nfs.noac.diff
After applying this patch and rebuilding your kernel, reboot with the new
kernel. Then copy the new nfs.h and nfsmount.h from /sys/nfs/ to
/usr/include/nfs/, and finally rebuild am-utils from scratch.
** Testing
When you build am-utils, a script named scripts/test-attrcache is built,
which can be used to test the NFS attribute cache behavior of the current
OS. You can run this script as root as follows:
# make install
# cd scripts
# sh test-attrcache
If you run this script on an OS whose status is known (and not listed
above), please report it to am-utils@am-utils.org, so we can record it in
this file.
Sincerely,
Erez.

View File

@ -2,14 +2,17 @@ LDAP support for am-utils was originally done by Leif Johansson
<leifj@it.su.se>. He no longer maintains it.
The current LDAP support for am-utils is for LDAPv2 only. Reportedly,
small changes are needed to support LDAPv3. Volunteers and patches are
welcome.
LDAPv3 mostly works. Volunteers and patches are welcome.
The IANA has assigned the following Private Enterprise Number to:
10180 Am-utils Organization Erez Zadok ezk@am-utils.org
There are two files in this directory that relate to LDAP:
There are three files in this directory that relate to LDAP:
ldap.schema:
This is the most current schema.
ldap-id.txt:

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: am_ops.c,v 1.6.2.7 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/am_ops.c
*
*/
@ -87,9 +86,6 @@ static am_ops *vops[] =
#ifdef HAVE_AMU_FS_UNION
&amfs_union_ops, /* union F/S */
#endif /* HAVE_AMU_FS_UNION */
#ifdef HAVE_AMU_FS_INHERIT
&amfs_inherit_ops, /* inheritance F/S */
#endif /* HAVE_AMU_FS_INHERIT */
/*
* A few more native filesystems.
@ -126,7 +122,7 @@ static am_ops *vops[] =
#endif /* HAVE_FS_UMAPFS */
/*
* These 5 should be last, in the order:
* These 4 should be last, in the order:
* (1) amfs_auto
* (2) amfs_direct
* (3) amfs_toplvl
@ -149,107 +145,111 @@ static am_ops *vops[] =
void
ops_showamfstypes(char *buf)
ops_showamfstypes(char *buf, size_t l)
{
struct am_ops **ap;
int l = 0;
int linesize = 0;
buf[0] = '\0';
for (ap = vops; *ap; ap++) {
strcat(buf, (*ap)->fs_type);
xstrlcat(buf, (*ap)->fs_type, l);
if (ap[1])
strcat(buf, ", ");
l += strlen((*ap)->fs_type) + 2;
if (l > 62) {
l = 0;
strcat(buf, "\n ");
xstrlcat(buf, ", ", l);
linesize += strlen((*ap)->fs_type) + 2;
if (linesize > 62) {
linesize = 0;
xstrlcat(buf, "\n ", l);
}
}
}
static void
ops_show1(char *buf, int *lp, const char *name)
ops_show1(char *buf, size_t l, int *linesizep, const char *name)
{
strcat(buf, name);
strcat(buf, ", ");
*lp += strlen(name) + 2;
if (*lp > 60) {
strcat(buf, "\t\n");
*lp = 0;
xstrlcat(buf, name, l);
xstrlcat(buf, ", ", l);
*linesizep += strlen(name) + 2;
if (*linesizep > 60) {
xstrlcat(buf, "\t\n", l);
*linesizep = 0;
}
}
void
ops_showfstypes(char *buf)
ops_showfstypes(char *buf, size_t l)
{
int l = 0;
int linesize = 0;
buf[0] = '\0';
#ifdef MNTTAB_TYPE_AUTOFS
ops_show1(buf, l, &linesize, MNTTAB_TYPE_AUTOFS);
#endif /* MNTTAB_TYPE_AUTOFS */
#ifdef MNTTAB_TYPE_CACHEFS
ops_show1(buf, &l, MNTTAB_TYPE_CACHEFS);
ops_show1(buf, l, &linesize, MNTTAB_TYPE_CACHEFS);
#endif /* MNTTAB_TYPE_CACHEFS */
#ifdef MNTTAB_TYPE_CDFS
ops_show1(buf, &l, MNTTAB_TYPE_CDFS);
ops_show1(buf, l, &linesize, MNTTAB_TYPE_CDFS);
#endif /* MNTTAB_TYPE_CDFS */
#ifdef MNTTAB_TYPE_CFS
ops_show1(buf, &l, MNTTAB_TYPE_CFS);
ops_show1(buf, l, &linesize, MNTTAB_TYPE_CFS);
#endif /* MNTTAB_TYPE_CFS */
#ifdef MNTTAB_TYPE_LOFS
ops_show1(buf, &l, MNTTAB_TYPE_LOFS);
ops_show1(buf, l, &linesize, MNTTAB_TYPE_LOFS);
#endif /* MNTTAB_TYPE_LOFS */
#ifdef MNTTAB_TYPE_EFS
ops_show1(buf, &l, MNTTAB_TYPE_EFS);
ops_show1(buf, l, &linesize, MNTTAB_TYPE_EFS);
#endif /* MNTTAB_TYPE_EFS */
#ifdef MNTTAB_TYPE_MFS
ops_show1(buf, &l, MNTTAB_TYPE_MFS);
ops_show1(buf, l, &linesize, MNTTAB_TYPE_MFS);
#endif /* MNTTAB_TYPE_MFS */
#ifdef MNTTAB_TYPE_NFS
ops_show1(buf, &l, MNTTAB_TYPE_NFS);
ops_show1(buf, l, &linesize, MNTTAB_TYPE_NFS);
#endif /* MNTTAB_TYPE_NFS */
#ifdef MNTTAB_TYPE_NFS3
ops_show1(buf, &l, "nfs3"); /* always hard-code as nfs3 */
ops_show1(buf, l, &linesize, "nfs3"); /* always hard-code as nfs3 */
#endif /* MNTTAB_TYPE_NFS3 */
#ifdef MNTTAB_TYPE_NULLFS
ops_show1(buf, &l, MNTTAB_TYPE_NULLFS);
ops_show1(buf, l, &linesize, MNTTAB_TYPE_NULLFS);
#endif /* MNTTAB_TYPE_NULLFS */
#ifdef MNTTAB_TYPE_PCFS
ops_show1(buf, &l, MNTTAB_TYPE_PCFS);
ops_show1(buf, l, &linesize, MNTTAB_TYPE_PCFS);
#endif /* MNTTAB_TYPE_PCFS */
#ifdef MNTTAB_TYPE_TFS
ops_show1(buf, &l, MNTTAB_TYPE_TFS);
ops_show1(buf, l, &linesize, MNTTAB_TYPE_TFS);
#endif /* MNTTAB_TYPE_TFS */
#ifdef MNTTAB_TYPE_TMPFS
ops_show1(buf, &l, MNTTAB_TYPE_TMPFS);
ops_show1(buf, l, &linesize, MNTTAB_TYPE_TMPFS);
#endif /* MNTTAB_TYPE_TMPFS */
#ifdef MNTTAB_TYPE_UFS
ops_show1(buf, &l, MNTTAB_TYPE_UFS);
ops_show1(buf, l, &linesize, MNTTAB_TYPE_UFS);
#endif /* MNTTAB_TYPE_UFS */
#ifdef MNTTAB_TYPE_UMAPFS
ops_show1(buf, &l, MNTTAB_TYPE_UMAPFS);
ops_show1(buf, l, &linesize, MNTTAB_TYPE_UMAPFS);
#endif /* MNTTAB_TYPE_UMAPFS */
#ifdef MNTTAB_TYPE_UNIONFS
ops_show1(buf, &l, MNTTAB_TYPE_UNIONFS);
ops_show1(buf, l, &linesize, MNTTAB_TYPE_UNIONFS);
#endif /* MNTTAB_TYPE_UNIONFS */
#ifdef MNTTAB_TYPE_XFS
ops_show1(buf, &l, MNTTAB_TYPE_XFS);
ops_show1(buf, l, &linesize, MNTTAB_TYPE_XFS);
#endif /* MNTTAB_TYPE_XFS */
/* terminate with a period, newline, and NULL */
@ -257,7 +257,7 @@ ops_showfstypes(char *buf)
buf[strlen(buf) - 4] = '\0';
else
buf[strlen(buf) - 2] = '\0';
strcat(buf, ".\n");
xstrlcat(buf, ".\n", l);
}
@ -289,11 +289,11 @@ reverse_option(const char *opt)
/* check if string starts with 'no' and chop it */
if (NSTREQ(opt, "no", 2)) {
strcpy(buf, &opt[2]);
xstrlcpy(buf, &opt[2], sizeof(buf));
} else {
/* finally return a string prepended with 'no' */
strcpy(buf, "no");
strcat(buf, opt);
xstrlcpy(buf, "no", sizeof(buf));
xstrlcat(buf, opt, sizeof(buf));
}
return buf;
}
@ -315,7 +315,7 @@ merge_opts(const char *opts1, const char *opts2)
char *eq; /* pointer to whatever follows '=' within temp */
char oneopt[80]; /* one option w/o value if any */
char *revoneopt; /* reverse of oneopt */
int len = strlen(opts1) + strlen(opts2) + 2; /* space for "," and NULL */
size_t len = strlen(opts1) + strlen(opts2) + 2; /* space for "," and NULL */
char *s1 = strdup(opts1); /* copy of opts1 to munge */
/* initialization */
@ -327,31 +327,30 @@ merge_opts(const char *opts1, const char *opts2)
tmpstr;
tmpstr = strtok(NULL, ",")) {
/* copy option to temp buffer */
strncpy(oneopt, tmpstr, 80);
oneopt[79] = '\0';
xstrlcpy(oneopt, tmpstr, 80);
/* if option has a value such as rsize=1024, chop the value part */
if ((eq = haseq(oneopt)))
*eq = '\0';
/* find reverse option of oneopt */
revoneopt = reverse_option(oneopt);
/* if option orits reverse exist in opts2, ignore it */
if (hasmntopt(&mnt2, oneopt) || hasmntopt(&mnt2, revoneopt))
if (amu_hasmntopt(&mnt2, oneopt) || amu_hasmntopt(&mnt2, revoneopt))
continue;
/* add option to returned string */
if (newstr && newstr[0]) {
strcat(newstr, ",");
strcat(newstr, tmpstr);
if (newstr[0]) {
xstrlcat(newstr, ",", len);
xstrlcat(newstr, tmpstr, len);
} else {
strcpy(newstr, tmpstr);
xstrlcpy(newstr, tmpstr, len);
}
}
/* finally, append opts2 itself */
if (newstr && newstr[0]) {
strcat(newstr, ",");
strcat(newstr, opts2);
if (newstr[0]) {
xstrlcat(newstr, ",", len);
xstrlcat(newstr, opts2, len);
} else {
strcpy(newstr, opts2);
xstrlcpy(newstr, opts2, len);
}
XFREE(s1);
@ -360,10 +359,22 @@ merge_opts(const char *opts1, const char *opts2)
am_ops *
ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map)
ops_search(char *type)
{
am_ops **vp;
am_ops *rop = 0;
for (vp = vops; (rop = *vp); vp++)
if (STREQ(rop->fs_type, type))
break;
return rop;
}
am_ops *
ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map)
{
am_ops *rop = 0;
char *link_dir;
/*
* First crack the global opts and the local opts
@ -377,9 +388,7 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map
/*
* Next find the correct filesystem type
*/
for (vp = vops; (rop = *vp); vp++)
if (STREQ(rop->fs_type, fo->opt_type))
break;
rop = ops_search(fo->opt_type);
if (!rop) {
plog(XLOG_USER, "fs type \"%s\" not recognized", fo->opt_type);
rop = &amfs_error_ops;
@ -433,18 +442,34 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map
}
}
/*
* Initialize opt_mount_type to "nfs", if it's not initialized already
*/
if (!fo->opt_mount_type)
fo->opt_mount_type = "nfs";
/* Normalize the sublink and make it absolute */
link_dir = fo->opt_sublink;
if (link_dir && link_dir[0] && link_dir[0] != '/') {
link_dir = str3cat((char *) 0, fo->opt_fs, "/", link_dir);
normalize_slash(link_dir);
XFREE(fo->opt_sublink);
fo->opt_sublink = link_dir;
}
/*
* Check the filesystem is happy
*/
if (fo->fs_mtab)
XFREE(fo->fs_mtab);
if ((fo->fs_mtab = (*rop->fs_match) (fo)))
fo->fs_mtab = rop->fs_match(fo);
if (fo->fs_mtab)
return rop;
/*
* Return error file system
*/
fo->fs_mtab = (*amfs_error_ops.fs_match) (fo);
fo->fs_mtab = amfs_error_ops.fs_match(fo);
return &amfs_error_ops;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amd.h,v 1.8.2.8 2004/01/21 04:04:58 ib42 Exp $
* File: am-utils/amd/amd.h
*
*/
@ -50,33 +49,160 @@
* MACROS:
*/
/*
* Define a default debug mtab path for systems
* that support mtab on file.
*/
#ifdef MOUNT_TABLE_ON_FILE
# define DEBUG_MNTTAB_FILE "/tmp/mnttab"
#endif /* MOUNT_TABLE_ON_FILE */
/* options for amd.conf */
#define CFM_BROWSABLE_DIRS 0x0001
#define CFM_MOUNT_TYPE_AUTOFS 0x0002
#define CFM_SELECTORS_IN_DEFAULTS 0x0004
#define CFM_NORMALIZE_HOSTNAMES 0x0008
#define CFM_PROCESS_LOCK 0x0010
#define CFM_PRINT_PID 0x0020
#define CFM_RESTART_EXISTING_MOUNTS 0x0040
#define CFM_SHOW_STATFS_ENTRIES 0x0080
#define CFM_FULLY_QUALIFIED_HOSTS 0x0100
#define CFM_BROWSABLE_DIRS_FULL 0x0200 /* allow '/' in readdir() */
#define CFM_UNMOUNT_ON_EXIT 0x0400 /* when amd finishing */
#define CFM_NFS_INSECURE_PORT 0x0800
#define CFM_BROWSABLE_DIRS 0x00000001
#define CFM_MOUNT_TYPE_AUTOFS 0x00000002 /* use kernel autofs support */
#define CFM_SELECTORS_IN_DEFAULTS 0x00000004
#define CFM_NORMALIZE_HOSTNAMES 0x00000008
#define CFM_PROCESS_LOCK 0x00000010
#define CFM_PRINT_PID 0x00000020
#define CFM_RESTART_EXISTING_MOUNTS 0x00000040
#define CFM_SHOW_STATFS_ENTRIES 0x00000080
#define CFM_FULLY_QUALIFIED_HOSTS 0x00000100
#define CFM_BROWSABLE_DIRS_FULL 0x00000200 /* allow '/' in readdir() */
#define CFM_UNMOUNT_ON_EXIT 0x00000400 /* when amd finishing */
#define CFM_USE_TCPWRAPPERS 0x00000800
#define CFM_AUTOFS_USE_LOFS 0x00001000
#define CFM_NFS_INSECURE_PORT 0x00002000
#define CFM_DOMAIN_STRIP 0x00004000
#define CFM_NORMALIZE_SLASHES 0x00008000 /* normalize slashes? */
#define CFM_FORCED_UNMOUNTS 0x00010000 /* forced unmounts? */
#define CFM_TRUNCATE_LOG 0x00020000 /* truncate log file? */
#if 0
/* XXX: reserved to sync up with am-utils-6.2 */
#define CFM_SUN_MAP_SYNTAX 0x00040000 /* Sun map syntax? */
#endif
#define CFM_NFS_ANY_INTERFACE 0x00080000 /* all interfaces are acceptable */
/* defaults global flags: plock, tcpwrappers, and autofs/lofs */
#define CFM_DEFAULT_FLAGS (CFM_PROCESS_LOCK|CFM_USE_TCPWRAPPERS|CFM_AUTOFS_USE_LOFS|CFM_DOMAIN_STRIP|CFM_NORMALIZE_SLASHES)
/*
* macro definitions for automounter vfs/vnode operations.
*/
#define VLOOK_CREATE 0x1
#define VLOOK_DELETE 0x2
#define VLOOK_LOOKUP 0x3
/*
* macro definitions for automounter vfs capabilities
*/
#define FS_DIRECTORY 0x0001 /* This looks like a dir, not a link */
#define FS_MBACKGROUND 0x0002 /* Should background this mount */
#define FS_NOTIMEOUT 0x0004 /* Don't bother with timeouts */
#define FS_MKMNT 0x0008 /* Need to make the mount point */
#define FS_UBACKGROUND 0x0010 /* Unmount in background */
#define FS_BACKGROUND (FS_MBACKGROUND|FS_UBACKGROUND)
#define FS_DISCARD 0x0020 /* Discard immediately on last reference */
#define FS_AMQINFO 0x0040 /* Amq is interested in this fs type */
#define FS_AUTOFS 0x0080 /* This filesystem can be an autofs f/s */
#define FS_DIRECT 0x0100 /* Direct mount */
#define FS_ON_AUTOFS 0x0200 /* This filesystem can be mounted directly
onto an autofs mountpoint */
/*
* macros for struct am_node (map of auto-mount points).
*/
#define AMF_NOTIMEOUT 0x0001 /* This node never times out */
#define AMF_ROOT 0x0002 /* This is a root node */
#define AMF_AUTOFS 0x0004 /* This node is part of an autofs filesystem */
#define AMF_REMOUNT 0x0008 /* This node needs to be remounted */
#define AMF_SOFTLOOKUP 0x0010 /* This node returns EIO if server is down */
/*
* macros for struct mntfs (list of mounted filesystems)
*/
#define MFF_MOUNTED 0x0001 /* Node is mounted */
#define MFF_MOUNTING 0x0002 /* Mount is in progress */
#define MFF_UNMOUNTING 0x0004 /* Unmount is in progress */
#define MFF_RESTART 0x0008 /* Restarted node */
#define MFF_MKMNT 0x0010 /* Delete this node's am_mount */
#define MFF_ERROR 0x0020 /* This node failed to mount */
#define MFF_LOGDOWN 0x0040 /* Logged that this mount is down */
#define MFF_RSTKEEP 0x0080 /* Don't timeout this filesystem - restarted */
#define MFF_WANTTIMO 0x0100 /* Need a timeout call when not busy */
#define MFF_NFSLINK 0x0200 /* nfsl type, and deemed a link */
#define MFF_IS_AUTOFS 0x0400 /* this filesystem is of type autofs */
#define MFF_NFS_SCALEDOWN 0x0800 /* the mount failed, retry with v2/UDP */
#define MFF_ON_AUTOFS 0x1000 /* autofs has a lofs/link to this f/s */
#define MFF_WEBNFS 0x2000 /* use public filehandle */
/*
* macros for struct fserver.
*/
#define FSF_VALID 0x0001 /* Valid information available */
#define FSF_DOWN 0x0002 /* This fileserver is thought to be down */
#define FSF_ERROR 0x0004 /* Permanent error has occurred */
#define FSF_WANT 0x0008 /* Want a wakeup call */
#define FSF_PINGING 0x0010 /* Already doing pings */
#define FSF_WEBNFS 0x0020 /* Don't try to contact portmapper */
#define FSF_PING_UNINIT 0x0040 /* ping values have not been initilized */
#define FSF_FORCE_UNMOUNT 0x0080 /* force umount of this fserver */
#define FSRV_ERROR(fs) ((fs) && (((fs)->fs_flags & FSF_ERROR) == FSF_ERROR))
#define FSRV_ISDOWN(fs) ((fs) && (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_DOWN|FSF_VALID)))
#define FSRV_ISUP(fs) (!(fs) || (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_VALID)))
/* some systems (SunOS 4.x) neglect to define the mount null message */
#ifndef MOUNTPROC_NULL
# define MOUNTPROC_NULL ((u_long)(0))
#endif /* not MOUNTPROC_NULL */
/*
* Error to return if remote host is not available.
* Try, in order, "host down", "host unreachable", "invalid argument".
*/
#ifdef EHOSTDOWN
# define AM_ERRNO_HOST_DOWN EHOSTDOWN
#else /* not EHOSTDOWN */
# ifdef EHOSTUNREACH
# define AM_ERRNO_HOST_DOWN EHOSTUNREACH
# else /* not EHOSTUNREACH */
# define AM_ERRNO_HOST_DOWN EINVAL
# endif /* not EHOSTUNREACH */
#endif /* not EHOSTDOWN */
/* Hash table size */
#define NKVHASH (1 << 2) /* Power of two */
/* Max entries to return in one call */
#define MAX_READDIR_ENTRIES 16
/*
* default amfs_auto retrans - 1/10th seconds
*/
#define AMFS_AUTO_RETRANS(x) ((ALLOWED_MOUNT_TIME*10+5*gopt.amfs_auto_timeo[(x)])/gopt.amfs_auto_timeo[(x)] * 2)
/*
* The following values can be tuned...
*/
#define AM_TTL (300) /* Default cache period (5 min) */
#define AM_TTL_W (120) /* Default unmount interval (2 min) */
#define AM_PINGER 30 /* NFS ping interval for live systems */
#define AMFS_AUTO_TIMEO 8 /* Default amfs_auto timeout - .8s */
#define AMFS_EXEC_MAP_TIMEOUT 10 /* default 10sec exec map timeout */
/* interval between forced retries of a mount */
#define RETRY_INTERVAL 2
#define ereturn(x) { *error_return = x; return 0; }
#ifndef ROOT_MAP
# define ROOT_MAP "\"root\""
#endif /* not ROOT_MAP */
#define ereturn(x) do { *error_return = x; return 0; } while (0)
#define NEVER (time_t) 0
#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
# define AMD_SERVICE_NAME "amd" /* for tcpwrappers */
#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
/*
* TYPEDEFS:
@ -84,6 +210,16 @@
typedef struct cf_map cf_map_t;
typedef struct kv kv;
typedef struct am_node am_node;
typedef struct mntfs mntfs;
typedef struct am_opts am_opts;
typedef struct am_ops am_ops;
typedef struct am_stats am_stats;
typedef struct fserver fserver;
typedef voidp wchan_t;
typedef voidp opaque_t;
/*
* Cache map operations
*/
@ -93,6 +229,28 @@ typedef int mtime_fn(mnt_map *, char *, time_t *);
typedef int isup_fn(mnt_map *, char *);
typedef int reload_fn(mnt_map *, char *, add_fn *);
typedef int search_fn(mnt_map *, char *, char *, char **, time_t *);
typedef int task_fun(opaque_t);
typedef void cb_fun(int, int, opaque_t);
typedef void fwd_fun(voidp, int, struct sockaddr_in *,
struct sockaddr_in *, opaque_t, int);
typedef int key_fun(char *, opaque_t);
typedef void callout_fun(opaque_t);
/*
* automounter vfs/vnode operations.
*/
typedef char *(*vfs_match) (am_opts *);
typedef int (*vfs_init) (mntfs *);
typedef int (*vmount_fs) (am_node *, mntfs *);
typedef int (*vumount_fs) (am_node *, mntfs *);
typedef am_node *(*vlookup_child) (am_node *, char *, int *, int);
typedef am_node *(*vmount_child) (am_node *, int *);
typedef int (*vreaddir) (am_node *, nfscookie, nfsdirlist *, nfsentry *, u_int);
typedef am_node *(*vreadlink) (am_node *, int *);
typedef void (*vmounted) (mntfs *);
typedef void (*vumounted) (mntfs *);
typedef fserver *(*vffserver) (mntfs *);
typedef wchan_t (*vget_wchan) (mntfs *);
@ -104,6 +262,7 @@ typedef int search_fn(mnt_map *, char *, char *, char **, time_t *);
struct amu_global_options {
char *arch; /* name of current architecture */
char *auto_dir; /* automounter temp dir */
int auto_attrcache; /* attribute cache timeout for auto dirs */
char *cluster; /* cluster name */
char *karch; /* kernel architecture */
char *logfile; /* amd log file */
@ -113,16 +272,33 @@ struct amu_global_options {
char *op_sys_vendor; /* name of OS vendor ${vendor} */
char *pid_file; /* PID file */
char *sub_domain; /* local domain */
char *localhost_address; /* localhost address (NULL means use 127.0.0.1) */
char *map_defaults; /* global map /default options */
char *map_options; /* global map options */
int map_reload_interval; /* map reload interval */
char *map_type; /* global map type */
char *search_path; /* search path for maps */
char *mount_type; /* mount type for map */
char *debug_mtab_file; /* path for the mtab file during debug mode */
u_int flags; /* various CFM_* flags */
int amfs_auto_retrans; /* NFS retransmit counter */
int amfs_auto_timeo; /* NFS retry interval */
#define AMU_TYPE_NONE -1 /* for amfs_auto_{timeo,retrans,toplvl} */
#define AMU_TYPE_UDP 0 /* for amfs_auto_{timeo,retrans,toplvl} */
#define AMU_TYPE_TCP 1 /* for amfs_auto_{timeo,retrans,toplvl} */
/*
* Note: toplvl is only UDP, but we want to separate it from regular
* NFS mounts which Amd makes, because the toplvl mount is a localhost
* mount for which different timeo/retrans parameters may be desired.
*/
#define AMU_TYPE_TOPLVL 2 /* for amfs_auto_{timeo,retrans,toplvl} */
#define AMU_TYPE_MAX 3 /* for amfs_auto_{timeo,retrans,toplvl} */
int amfs_auto_retrans[AMU_TYPE_MAX]; /* NFS retransmit counter */
int amfs_auto_timeo[AMU_TYPE_MAX]; /* NFS retry interval */
int am_timeo; /* cache duration */
int am_timeo_w; /* dismount interval */
int portmap_program; /* amd RPC program number */
u_long portmap_program; /* amd RPC program number */
u_short preferred_amq_port; /* preferred amq service RPC port number (0 means "any") */
#ifdef HAVE_MAP_HESIOD
char *hesiod_base; /* Hesiod rhs */
#endif /* HAVE_MAP_HESIOD */
@ -131,12 +307,14 @@ struct amu_global_options {
char *ldap_hostports; /* LDAP host ports */
long ldap_cache_seconds; /* LDAP internal cache - keep seconds */
long ldap_cache_maxmem; /* LDAP internal cache - max memory (bytes) */
long ldap_proto_version; /* LDAP protocol version */
#endif /* HAVE_MAP_LDAP */
#ifdef HAVE_MAP_NIS
char *nis_domain; /* YP domain name */
#endif /* HAVE_MAP_NIS */
char *nfs_proto; /* NFS protocol (NULL, udp, tcp) */
int nfs_vers; /* NFS version (0, 2, 3, 4) */
u_int exec_map_timeout; /* timeout (seconds) for executable maps */
};
/* if you add anything here, update conf.c:reset_cf_map() */
@ -144,10 +322,12 @@ struct cf_map {
char *cfm_dir; /* /home, /u, /src */
char *cfm_name; /* amd.home, /etc/amd.home ... */
char *cfm_type; /* file, hesiod, ndbm, nis ... */
char *cfm_defaults; /* map /defaults options in amd.conf */
char *cfm_opts; /* -cache:=all, etc. */
char *cfm_search_path; /* /etc/local:/etc/amdmaps:/misc/yp */
char *cfm_tag; /* optional map tag for amd -T */
u_int cfm_flags; /* browsable_dirs? mount_type? */
struct cf_map *cfm_next; /* pointer to next in list (if any) */
};
/*
@ -176,52 +356,173 @@ struct mnt_map {
search_fn *search; /* Function to be used for searching */
mtime_fn *mtime; /* Modify time function */
kv *kvhash[NKVHASH]; /* Cached data */
/* options available via amd conf file */
char *cf_map_type; /* file, hesiod, ndbm, nis, etc. */
char *cf_search_path; /* /etc/local:/etc/amdmaps:/misc/yp */
cf_map_t *cfm; /* pointer to per-map amd.conf opts, if any */
void *map_data; /* Map data black box */
};
/*
* Mounting a file system may take a significant period of time. The
* problem is that if this is done in the main process thread then the
* entire automounter could be blocked, possibly hanging lots of processes
* on the system. Instead we use a continuation scheme to allow mounts to
* be attempted in a sub-process. When the sub-process exits we pick up the
* exit status (by convention a UN*X error number) and continue in a
* notifier. The notifier gets handed a data structure and can then
* determine whether the mount was successful or not. If not, it updates
* the data structure and tries again until there are no more ways to try
* the mount, or some other permanent error occurs. In the mean time no RPC
* reply is sent, even after the mount is successful. We rely on the RPC
* retry mechanism to resend the lookup request which can then be handled.
* Options
*/
struct continuation {
char **ivec; /* Current mount info */
am_node *mp; /* Node we are trying to mount */
char *key; /* Map key */
char *info; /* Info string */
char **xivec; /* Saved strsplit vector */
char *auto_opts; /* Automount options */
am_opts fs_opts; /* Filesystem options */
char *def_opts; /* Default automount options */
int retry; /* Try again? */
int tried; /* Have we tried any yet? */
time_t start; /* Time we started this mount */
int callout; /* Callout identifier */
struct am_opts {
char *fs_glob; /* Smashed copy of global options */
char *fs_local; /* Expanded copy of local options */
char *fs_mtab; /* Mount table entry */
/* Other options ... */
char *opt_dev;
char *opt_delay;
char *opt_dir;
char *opt_fs;
char *opt_group;
char *opt_mount;
char *opt_opts;
char *opt_remopts;
char *opt_pref;
char *opt_cache;
char *opt_rfs;
char *opt_rhost;
char *opt_sublink;
char *opt_type;
char *opt_mount_type; /* "nfs" or "autofs" */
char *opt_unmount;
char *opt_umount; /* an "alias" for opt_unmount (type:=program) */
char *opt_user;
char *opt_maptype; /* map type: file, nis, hesiod, etc. */
char *opt_cachedir; /* cache directory */
char *opt_addopts; /* options to add to opt_opts */
};
struct am_ops {
char *fs_type; /* type of filesystems e.g. "nfsx" */
vfs_match fs_match; /* fxn: match */
vfs_init fs_init; /* fxn: initialization */
vmount_fs mount_fs; /* fxn: mount my own vnode */
vumount_fs umount_fs; /* fxn: unmount my own vnode */
vlookup_child lookup_child; /* fxn: lookup path-name */
vmount_child mount_child; /* fxn: mount path-name */
vreaddir readdir; /* fxn: read directory */
vreadlink readlink; /* fxn: read link */
vmounted mounted; /* fxn: after-mount extra actions */
vumounted umounted; /* fxn: after-umount extra actions */
vffserver ffserver; /* fxn: find a file server */
vget_wchan get_wchan; /* fxn: get the waiting channel */
int nfs_fs_flags; /* filesystem flags FS_* for nfs mounts */
#ifdef HAVE_FS_AUTOFS
int autofs_fs_flags;/* filesystem flags FS_* for autofs mounts */
#endif /* HAVE_FS_AUTOFS */
};
/*
* List of mounted filesystems
*/
struct mntfs {
qelem mf_q; /* List of mounted filesystems */
am_ops *mf_ops; /* Operations on this mountpoint */
am_opts *mf_fo; /* File opts */
char *mf_mount; /* "/a/kiska/home/kiska" */
char *mf_info; /* Mount info */
char *mf_auto; /* Automount opts */
char *mf_mopts; /* FS mount opts */
char *mf_remopts; /* Remote FS mount opts */
char *mf_loopdev; /* loop device name for /dev/loop mounts */
fserver *mf_server; /* File server */
int mf_fsflags; /* Flags FS_* copied from mf_ops->*_fs_flags */
int mf_flags; /* Flags MFF_* */
int mf_error; /* Error code from background mount */
int mf_refc; /* Number of references to this node */
int mf_cid; /* Callout id */
void (*mf_prfree) (opaque_t); /* Free private space */
opaque_t mf_private; /* Private - per-fs data */
};
/*
* List of fileservers
*/
struct fserver {
qelem fs_q; /* List of fileservers */
int fs_refc; /* Number of references to this server */
char *fs_host; /* Normalized hostname of server */
struct sockaddr_in *fs_ip; /* Network address of server */
int fs_cid; /* Callout id */
int fs_pinger; /* Ping (keepalive) interval */
int fs_flags; /* Flags */
char *fs_type; /* File server type */
u_long fs_version; /* NFS version of server (2, 3, etc.)*/
char *fs_proto; /* NFS protocol of server (tcp, udp, etc.) */
opaque_t fs_private; /* Private data */
void (*fs_prfree) (opaque_t); /* Free private data */
};
/*
* Per-mountpoint statistics
*/
struct am_stats {
time_t s_mtime; /* Mount time */
u_short s_uid; /* Uid of mounter */
int s_getattr; /* Count of getattrs */
int s_lookup; /* Count of lookups */
int s_readdir; /* Count of readdirs */
int s_readlink; /* Count of readlinks */
int s_statfs; /* Count of statfs */
};
/*
* System statistics
*/
struct amd_stats {
int d_drops; /* Dropped requests */
int d_stale; /* Stale NFS handles */
int d_mok; /* Successful mounts */
int d_merr; /* Failed mounts */
int d_uerr; /* Failed unmounts */
};
extern struct amd_stats amd_stats;
/*
* Map of auto-mount points.
*/
struct am_node {
int am_mapno; /* Map number */
mntfs *am_mnt; /* Mounted filesystem */
mntfs **am_mfarray; /* Filesystem sources to try to mount */
char *am_name; /* "kiska": name of this node */
char *am_path; /* "/home/kiska": path of this node's mount point */
char *am_link; /* "/a/kiska/home/kiska/this/that": link to sub-dir */
am_node *am_parent; /* Parent of this node */
am_node *am_ysib; /* Younger sibling of this node */
am_node *am_osib; /* Older sibling of this node */
am_node *am_child; /* First child of this node */
nfsattrstat am_attr; /* File attributes */
#define am_fattr am_attr.ns_u.ns_attr_u
int am_flags; /* Boolean flags AMF_* */
int am_error; /* Specific mount error */
time_t am_ttl; /* Time to live */
int am_timeo_w; /* Dismount wait interval */
int am_timeo; /* Cache timeout interval */
u_int am_gen; /* Generation number */
char *am_pref; /* Mount info prefix */
am_stats am_stats; /* Statistics gathering */
SVCXPRT *am_transp; /* Info for quick reply */
dev_t am_dev; /* Device number */
dev_t am_rdev; /* Remote/real device number */
#ifdef HAVE_FS_AUTOFS
autofs_fh_t *am_autofs_fh;
time_t am_autofs_ttl; /* Time to expire autofs nodes */
#endif /* HAVE_FS_AUTOFS */
};
/*
* EXTERNALS:
*/
/* Amq server global functions */
/*
* Amq server global functions
*/
extern amq_mount_info_list *amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp);
extern amq_mount_stats *amqproc_stats_1_svc(voidp argp, struct svc_req *rqstp);
extern amq_mount_tree_list *amqproc_export_1_svc(voidp argp, struct svc_req *rqstp);
extern amq_mount_tree_p *amqproc_mnttree_1_svc(voidp argp, struct svc_req *rqstp);
extern amq_string *amqproc_getvers_1_svc(voidp argp, struct svc_req *rqstp);
extern amq_string *amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp);
extern int *amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp);
extern int *amqproc_mount_1_svc(voidp argp, struct svc_req *rqstp);
extern int *amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp);
@ -229,44 +530,134 @@ extern voidp amqproc_null_1_svc(voidp argp, struct svc_req *rqstp);
extern voidp amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp);
/* other external definitions */
extern am_nfs_fh *root_fh(char *dir);
extern am_nfs_fh *get_root_nfs_fh(char *dir);
extern am_node *find_ap(char *);
extern am_node *find_ap2(char *, am_node *);
extern am_node *get_ap_child(am_node *, char *);
extern bool_t xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead);
extern fserver *find_nfs_srvr(mntfs *mf);
extern int auto_fmount(am_node *mp);
extern int auto_fumount(am_node *mp);
extern int mount_nfs_fh(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *mf);
extern int process_last_regular_map(void);
extern int mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf);
extern int process_all_regular_maps(void);
extern cf_map_t *find_cf_map(const char *name);
extern int set_conf_kv(const char *section, const char *k, const char *v);
extern int try_mount(voidp mvp);
extern int mount_node(opaque_t arg);
extern int unmount_mp(am_node *mp);
extern int yyparse (void);
extern nfsentry *make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable);
extern void amfs_auto_cont(int rc, int term, voidp closure);
extern void amfs_auto_mkcacheref(mntfs *mf);
extern void amfs_auto_retry(int rc, int term, voidp closure);
extern void assign_error_mntfs(am_node *mp);
extern void flush_srvr_nfs_cache(void);
extern void free_continuation(struct continuation *cp);
extern void mf_mounted(mntfs *mf);
extern void quick_reply(am_node *mp, int error);
extern void root_newmap(const char *, const char *, const char *, const cf_map_t *);
/* amd global variables */
extern void amfs_mkcacheref(mntfs *mf);
extern int amfs_mount(am_node *mp, mntfs *mf, char *opts);
extern void assign_error_mntfs(am_node *mp);
extern am_node *next_nonerror_node(am_node *xp);
extern void flush_srvr_nfs_cache(fserver *fs);
extern void am_mounted(am_node *);
extern void mf_mounted(mntfs *mf, bool_t call_free_opts);
extern void am_unmounted(am_node *);
extern am_node *get_exported_ap(int index);
extern am_node *get_first_exported_ap(int *index);
extern am_node *get_next_exported_ap(int *index);
extern am_node *path_to_exported_ap(char *path);
extern am_node *exported_ap_alloc(void);
extern am_node *find_mf(mntfs *);
extern am_node *next_map(int *);
extern am_ops *ops_match(am_opts *, char *, char *, char *, char *, char *);
extern am_ops *ops_search(char *);
extern fserver *dup_srvr(fserver *);
extern void srvrlog(fserver *, char *);
extern int get_mountd_port(fserver *, u_short *, wchan_t);
extern void flush_nfs_fhandle_cache(fserver *);
extern mntfs *dup_mntfs(mntfs *);
extern mntfs *find_mntfs(am_ops *, am_opts *, char *, char *, char *, char *, char *);
extern mntfs *locate_mntfs(am_ops *, am_opts *, char *, char *, char *, char *, char *);
extern mntfs *new_mntfs(void);
extern mntfs *realloc_mntfs(mntfs *, am_ops *, am_opts *, char *, char *, char *, char *, char *);
extern void flush_mntfs(void);
extern void free_mntfs(voidp);
extern void amq_program_1(struct svc_req *rqstp, SVCXPRT *transp);
extern int background(void);
extern void deslashify(char *);
extern void do_task_notify(void);
extern int eval_fs_opts(am_opts *, char *, char *, char *, char *, char *);
extern void forcibly_timeout_mp(am_node *);
extern void free_map(am_node *);
extern void free_opts(am_opts *);
extern void free_srvr(fserver *);
extern int fwd_init(void);
extern int fwd_packet(int, char *, int, struct sockaddr_in *, struct sockaddr_in *, opaque_t, fwd_fun *);
extern void fwd_reply(void);
extern void get_args(int argc, char *argv[]);
extern wchan_t get_mntfs_wchan(mntfs *mf);
extern void host_normalize(char **);
extern void init_map(am_node *, char *);
extern void ins_que(qelem *, qelem *);
extern void insert_am(am_node *, am_node *);
extern int make_nfs_auth(void);
extern void make_root_node(void);
extern void map_flush_srvr(fserver *);
extern void mapc_add_kv(mnt_map *, char *, char *);
extern mnt_map *mapc_find(char *, char *, const char *);
extern void mapc_free(opaque_t);
extern int mapc_keyiter(mnt_map *, key_fun, opaque_t);
extern void mapc_reload(void);
extern int mapc_search(mnt_map *, char *, char **);
extern void mapc_showtypes(char *buf, size_t l);
extern int mapc_type_exists(const char *type);
extern void mk_fattr(nfsfattr *, nfsftype);
extern int mount_auto_node(char *, opaque_t);
extern int mount_automounter(int);
extern int mount_exported(void);
extern void mp_to_fh(am_node *, am_nfs_fh *);
extern void new_ttl(am_node *);
extern void nfs_quick_reply(am_node *mp, int error);
extern void normalize_slash(char *);
extern void ops_showamfstypes(char *buf, size_t l);
extern void ops_showfstypes(char *outbuf, size_t l);
extern void rem_que(qelem *);
extern void reschedule_timeout_mp(void);
extern void restart(void);
extern void restart_automounter_nodes(void);
extern int root_keyiter(key_fun *, opaque_t);
extern void root_newmap(const char *, const char *, const char *, const cf_map_t *);
extern void run_task(task_fun *, opaque_t, cb_fun *, opaque_t);
extern void sched_task(cb_fun *, opaque_t, wchan_t);
extern int softclock(void);
extern int timeout(u_int, void (*fn)(opaque_t), opaque_t);
extern void timeout_mp(opaque_t);
extern void untimeout(int);
extern void umount_exported(void);
extern int valid_key(char *);
extern void wakeup(wchan_t);
extern void wakeup_srvr(fserver *);
extern void wakeup_task(int, int, wchan_t);
#define SIZEOF_PID_FSNAME (16 + MAXHOSTNAMELEN)
extern char pid_fsname[SIZEOF_PID_FSNAME]; /* "kiska.southseas.nz:(pid%d)" */
#define SIZEOF_HOSTD (2 * MAXHOSTNAMELEN + 1)
extern char hostd[SIZEOF_HOSTD]; /* Host+domain */
#define SIZEOF_OPTS 256 /* used for char opts[] and preopts[] */
/*
* Global variables.
*/
extern FILE *yyin;
extern SVCXPRT *nfs_program_2_transp; /* For quick_reply() */
extern SVCXPRT *current_transp; /* For nfs_quick_reply() */
extern char *conf_tag;
extern char *opt_gid;
extern char *opt_uid;
extern int NumChild;
#define SIZEOF_UID_STR 12
#define SIZEOF_GID_STR 12
extern char *opt_gid, gid_str[SIZEOF_GID_STR];
extern char *opt_uid, uid_str[SIZEOF_UID_STR];
extern int NumChildren;
extern int fwd_sock;
extern int select_intr_valid;
extern int immediate_abort; /* Should close-down unmounts be retried */
extern int usage;
extern int use_conf_file; /* use amd configuration file */
extern int task_notify_todo; /* Task notifier needs running */
extern jmp_buf select_intr;
extern qelem mfhead;
extern struct am_opts fs_static; /* copy of the options to play with */
extern struct amu_global_options gopt; /* where global options are stored */
extern time_t do_mapc_reload; /* Flush & reload mount map cache */
extern time_t next_softclock; /* Time to call softclock() */
#ifdef HAVE_SIGACTION
extern sigset_t masked_sigs;
@ -274,16 +665,88 @@ extern sigset_t masked_sigs;
#if defined(HAVE_AMU_FS_LINK) || defined(HAVE_AMU_FS_LINKX)
extern char *amfs_link_match(am_opts *fo);
extern int amfs_link_fumount(mntfs *mf);
#endif /* defined(HAVE_AMU_FS_LINK) || defined(HAVE_AMU_FS_LINKX) */
#ifdef HAVE_AMU_FS_NFSL
extern char *nfs_match(am_opts *fo);
#endif /* HAVE_AMU_FS_NFSL */
#ifdef HAVE_FS_AUTOFS
extern int amd_use_autofs;
#if defined(HAVE_FS_NFS3) && !defined(HAVE_XDR_MOUNTRES3)
extern bool_t xdr_mountres3(XDR *xdrs, mountres3 *objp);
#endif /* defined(HAVE_FS_NFS3) && !defined(HAVE_XDR_MOUNTRES3) */
extern int autofs_get_fh(am_node *mp);
extern void autofs_release_fh(am_node *mp);
extern void autofs_get_mp(am_node *mp);
extern void autofs_release_mp(am_node *mp);
extern void autofs_add_fdset(fd_set *readfds);
extern int autofs_handle_fdset(fd_set *readfds, int nsel);
extern void autofs_mounted(am_node *mp);
extern void autofs_mount_succeeded(am_node *mp);
extern void autofs_mount_failed(am_node *mp);
extern int autofs_umount_succeeded(am_node *mp);
extern int autofs_umount_failed(am_node *mp);
extern int autofs_mount_fs(am_node *mp, mntfs *mf);
extern int autofs_umount_fs(am_node *mp, mntfs *mf);
extern void autofs_get_opts(char *opts, size_t l, autofs_fh_t *fh);
extern int autofs_compute_mount_flags(mntent_t *);
extern void autofs_timeout_mp(am_node *);
extern int create_autofs_service(void);
extern int destroy_autofs_service(void);
#endif /* HAVE_FS_AUTOFS */
/**************************************************************************/
/*** Generic file-system types, implemented as part of the native O/S. ***/
/**************************************************************************/
/*
* Loopback File System
* Many systems can't support this, and in any case most of the
* functionality is available with Symlink FS.
*/
#ifdef HAVE_FS_LOFS
extern am_ops lofs_ops;
extern int mount_lofs(char *mntdir, char *fs_name, char *opts, int on_autofs);
#endif /* HAVE_FS_LOFS */
/*
* CD-ROM File System (CD-ROM)
* (HSFS: High Sierra F/S on some machines)
* Many systems can't support this, and in any case most of the
* functionality is available with program FS.
*/
#ifdef HAVE_FS_CDFS
extern am_ops cdfs_ops;
#endif /* HAVE_FS_CDFS */
/*
* PC File System (MS-DOS)
* Many systems can't support this, and in any case most of the
* functionality is available with program FS.
*/
#ifdef HAVE_FS_PCFS
extern am_ops pcfs_ops;
#endif /* HAVE_FS_PCFS */
/*
* Caching File System (Solaris)
*/
#ifdef HAVE_FS_CACHEFS
extern am_ops cachefs_ops;
#endif /* HAVE_FS_CACHEFS */
/*
* Network File System
* Good, slow, NFS V.2.
*/
#ifdef HAVE_FS_NFS
extern am_ops nfs_ops; /* NFS */
extern fserver *find_nfs_srvr (mntfs *);
extern qelem nfs_srvr_list;
#endif /* HAVE_FS_NFS */
/*
* Un*x File System
* Normal local disk file system.
*/
#ifdef HAVE_FS_UFS
extern am_ops ufs_ops; /* Un*x file system */
#endif /* HAVE_FS_UFS */
/* Unix file system (irix) */
#ifdef HAVE_FS_XFS
@ -295,4 +758,110 @@ extern am_ops xfs_ops; /* Un*x file system */
extern am_ops efs_ops; /* Un*x file system */
#endif /* HAVE_FS_EFS */
/**************************************************************************/
/*** Automounter file-system types, implemented by amd. ***/
/**************************************************************************/
/*
* Root AMD File System
*/
extern am_ops amfs_root_ops; /* Root file system */
/*
* Generic amfs helper methods
*/
extern am_node *amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op);
extern am_node *amfs_generic_mount_child(am_node *ap, int *error_return);
extern int amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count);
extern int amfs_generic_umount(am_node *mp, mntfs *mf);
extern void amfs_generic_mounted(mntfs *mf);
extern char *amfs_generic_match(am_opts *fo);
extern fserver *amfs_generic_find_srvr(mntfs *);
/*
* Automount File System
*/
#ifdef HAVE_AMU_FS_AUTO
extern am_ops amfs_auto_ops; /* Automount file system (this!) */
#endif /* HAVE_AMU_FS_AUTO */
/*
* Toplvl Automount File System
*/
#ifdef HAVE_AMU_FS_TOPLVL
extern am_ops amfs_toplvl_ops; /* Toplvl Automount file system */
extern int amfs_toplvl_mount(am_node *mp, mntfs *mf);
extern int amfs_toplvl_umount(am_node *mp, mntfs *mf);
#endif /* HAVE_AMU_FS_TOPLVL */
/*
* Direct Automount File System
*/
#ifdef HAVE_AMU_FS_DIRECT
extern am_ops amfs_direct_ops; /* Direct Automount file system (this too) */
#endif /* HAVE_AMU_FS_DIRECT */
/*
* Error File System
*/
#ifdef HAVE_AMU_FS_ERROR
extern am_ops amfs_error_ops; /* Error file system */
extern am_node *amfs_error_lookup_child(am_node *mp, char *fname, int *error_return, int op);
extern am_node *amfs_error_mount_child(am_node *ap, int *error_return);
extern int amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count);
#endif /* HAVE_AMU_FS_ERROR */
/*
* NFS mounts with local existence check.
*/
#ifdef HAVE_AMU_FS_NFSL
extern am_ops amfs_nfsl_ops; /* NFSL */
#endif /* HAVE_AMU_FS_NFSL */
/*
* Multi-nfs mounts.
*/
#ifdef HAVE_AMU_FS_NFSX
extern am_ops amfs_nfsx_ops; /* NFSX */
#endif /* HAVE_AMU_FS_NFSX */
/*
* NFS host - a whole tree.
*/
#ifdef HAVE_AMU_FS_HOST
extern am_ops amfs_host_ops; /* NFS host */
#endif /* HAVE_AMU_FS_HOST */
/*
* Program File System
* This is useful for things like RVD.
*/
#ifdef HAVE_AMU_FS_PROGRAM
extern am_ops amfs_program_ops; /* Program File System */
#endif /* HAVE_AMU_FS_PROGRAM */
/*
* Symbolic-link file system.
* A "filesystem" which is just a symbol link.
*/
#ifdef HAVE_AMU_FS_LINK
extern am_ops amfs_link_ops; /* Symlink FS */
#endif /* HAVE_AMU_FS_LINK */
/*
* Symbolic-link file system, which also checks that the target of
* the symlink exists.
* A "filesystem" which is just a symbol link.
*/
#ifdef HAVE_AMU_FS_LINKX
extern am_ops amfs_linkx_ops; /* Symlink FS with existence check */
#endif /* HAVE_AMU_FS_LINKX */
/*
* Union file system
*/
#ifdef HAVE_AMU_FS_UNION
extern am_ops amfs_union_ops; /* Union FS */
#endif /* HAVE_AMU_FS_UNION */
#endif /* not _AMD_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_direct.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/amfs_direct.c
*
*/
@ -63,19 +62,22 @@ static am_node *amfs_direct_readlink(am_node *mp, int *error_return);
am_ops amfs_direct_ops =
{
"direct",
amfs_auto_match,
amfs_generic_match,
0, /* amfs_direct_init */
amfs_toplvl_mount,
0,
amfs_toplvl_umount,
0,
amfs_error_lookuppn,
amfs_generic_lookup_child,
amfs_generic_mount_child,
amfs_error_readdir,
amfs_direct_readlink,
amfs_toplvl_mounted,
0, /* amfs_auto_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO
amfs_generic_mounted,
0, /* amfs_direct_umounted */
amfs_generic_find_srvr,
0, /* amfs_direct_get_wchan */
FS_DIRECT | FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO,
#ifdef HAVE_FS_AUTOFS
AUTOFS_DIRECT_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
@ -92,8 +94,10 @@ amfs_direct_readlink(am_node *mp, int *error_return)
xp = next_nonerror_node(mp->am_child);
if (!xp) {
if (!mp->am_mnt->mf_private)
amfs_auto_mkcacheref(mp->am_mnt); /* XXX */
xp = amfs_auto_lookuppn(mp, mp->am_path + 1, &rc, VLOOK_CREATE);
amfs_mkcacheref(mp->am_mnt); /* XXX */
xp = amfs_generic_lookup_child(mp, mp->am_path + 1, &rc, VLOOK_CREATE);
if (xp && rc < 0)
xp = amfs_generic_mount_child(xp, &rc);
}
if (xp) {
new_ttl(xp); /* (7/12/89) from Rein Tollevik */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_error.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/amfs_error.c
*
*/
@ -57,9 +56,8 @@
#include <amd.h>
static char *amfs_error_match(am_opts *fo);
static int amfs_error_fmount(mntfs *mf);
static int amfs_error_fumount(mntfs *mf);
static void amfs_error_umounted(am_node *mp);
static int amfs_error_mount(am_node *am, mntfs *mf);
static int amfs_error_umount(am_node *am, mntfs *mf);
/*
@ -70,17 +68,20 @@ am_ops amfs_error_ops =
"error",
amfs_error_match,
0, /* amfs_error_init */
amfs_auto_fmount,
amfs_error_fmount,
amfs_auto_fumount,
amfs_error_fumount,
amfs_error_lookuppn,
amfs_error_mount,
amfs_error_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_error_readdir,
0, /* amfs_error_readlink */
0, /* amfs_error_mounted */
amfs_error_umounted,
find_amfs_auto_srvr,
FS_DISCARD
0, /* amfs_error_umounted */
amfs_generic_find_srvr,
0, /* amfs_error_get_wchan */
FS_DISCARD, /* nfs_fs_flags */
#ifdef HAVE_FS_AUTOFS
AUTOFS_ERROR_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
@ -96,14 +97,14 @@ amfs_error_match(am_opts *fo)
static int
amfs_error_fmount(mntfs *mf)
amfs_error_mount(am_node *am, mntfs *mf)
{
return ENOENT;
}
static int
amfs_error_fumount(mntfs *mf)
amfs_error_umount(am_node *am, mntfs *mf)
{
/*
* Always succeed
@ -118,7 +119,20 @@ amfs_error_fumount(mntfs *mf)
* If we do then just give an error.
*/
am_node *
amfs_error_lookuppn(am_node *mp, char *fname, int *error_return, int op)
amfs_error_lookup_child(am_node *mp, char *fname, int *error_return, int op)
{
*error_return = ESTALE;
return 0;
}
/*
* EFS interface to RPC lookup() routine.
* Should never get here in the automounter.
* If we do then just give an error.
*/
am_node *
amfs_error_mount_child(am_node *ap, int *error_return)
{
*error_return = ESTALE;
return 0;
@ -131,20 +145,7 @@ amfs_error_lookuppn(am_node *mp, char *fname, int *error_return, int op)
* If we do then just give an error.
*/
int
amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count)
amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count)
{
return ESTALE;
}
/*
* umounted() callback for EFS.
*
* This prevents core-dumps on callbacks to error file-systems from
* nfsx_fumount.
*/
static void
amfs_error_umounted(am_node *mp)
{
/* nothing to do */
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_host.c,v 1.4.2.7 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/amfs_host.c
*
*/
@ -57,10 +56,10 @@
#include <amd.h>
static char *amfs_host_match(am_opts *fo);
static int amfs_host_fmount(mntfs *mf);
static int amfs_host_fumount(mntfs *mf);
static int amfs_host_init(mntfs *mf);
static void amfs_host_umounted(am_node *mp);
static int amfs_host_mount(am_node *am, mntfs *mf);
static int amfs_host_umount(am_node *am, mntfs *mf);
static void amfs_host_umounted(mntfs *mf);
/*
* Ops structure
@ -70,17 +69,20 @@ am_ops amfs_host_ops =
"host",
amfs_host_match,
amfs_host_init,
amfs_auto_fmount,
amfs_host_fmount,
amfs_auto_fumount,
amfs_host_fumount,
amfs_error_lookuppn,
amfs_host_mount,
amfs_host_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_error_readdir,
0, /* amfs_host_readlink */
0, /* amfs_host_mounted */
amfs_host_umounted,
find_nfs_srvr,
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO
0, /* amfs_host_get_wchan */
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO,
#ifdef HAVE_FS_AUTOFS
AUTOFS_HOST_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
@ -95,21 +97,21 @@ am_ops amfs_host_ops =
* allows the entire PC disk to be mounted.
*/
static void
make_mntpt(char *mntpt, const exports ex, const mntfs *mf)
make_mntpt(char *mntpt, size_t l, const exports ex, const char *mf_mount)
{
if (ex->ex_dir[0] == '/') {
if (ex->ex_dir[1] == 0)
strcpy(mntpt, (mf)->mf_mount);
xstrlcpy(mntpt, mf_mount, l);
else
sprintf(mntpt, "%s%s", mf->mf_mount, ex->ex_dir);
xsnprintf(mntpt, l, "%s%s", mf_mount, ex->ex_dir);
} else if (ex->ex_dir[0] >= 'a' &&
ex->ex_dir[0] <= 'z' &&
ex->ex_dir[1] == ':' &&
ex->ex_dir[2] == '/' &&
ex->ex_dir[3] == 0)
sprintf(mntpt, "%s/%c%%", mf->mf_mount, ex->ex_dir[0]);
xsnprintf(mntpt, l, "%s/%c%%", mf_mount, ex->ex_dir[0]);
else
sprintf(mntpt, "%s/%s", mf->mf_mount, ex->ex_dir);
xsnprintf(mntpt, l, "%s/%s", mf_mount, ex->ex_dir);
}
@ -134,8 +136,7 @@ amfs_host_match(am_opts *fo)
static int
amfs_host_init(mntfs *mf)
{
fserver *fs;
u_short port;
u_short mountd_port;
if (strchr(mf->mf_info, ':') == 0)
return ENOENT;
@ -152,41 +153,39 @@ amfs_host_init(mntfs *mf)
*/
/*
* First, we find the fileserver for this mntfs and then call
* nfs_srvr_port with our mntfs passed as the wait channel.
* nfs_srvr_port will check some things and then schedule
* get_mountd_port with our mntfs passed as the wait channel.
* get_mountd_port will check some things and then schedule
* it so that when the fileserver is ready, a wakeup is done
* on this mntfs. amfs_auto_cont() is already sleeping on this mntfs
* so as soon as that wakeup happens amfs_auto_cont() is called and
* on this mntfs. amfs_cont() is already sleeping on this mntfs
* so as soon as that wakeup happens amfs_cont() is called and
* this mount is retried.
*/
if ((fs = mf->mf_server))
if (mf->mf_server)
/*
* We don't really care if there's an error returned.
* Since this is just to help speed things along, the
* error will get handled properly elsewhere.
*/
(void) nfs_srvr_port(fs, &port, (voidp) mf);
get_mountd_port(mf->mf_server, &mountd_port, get_mntfs_wchan(mf));
return 0;
}
static int
do_mount(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *mf)
do_mount(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf)
{
struct stat stb;
#ifdef DEBUG
dlog("amfs_host: mounting fs %s on %s\n", fs_name, dir);
#endif /* DEBUG */
dlog("amfs_host: mounting fs %s on %s\n", fs_name, mntdir);
(void) mkdirs(dir, 0555);
if (stat(dir, &stb) < 0 || (stb.st_mode & S_IFMT) != S_IFDIR) {
plog(XLOG_ERROR, "No mount point for %s - skipping", dir);
(void) mkdirs(mntdir, 0555);
if (stat(mntdir, &stb) < 0 || (stb.st_mode & S_IFMT) != S_IFDIR) {
plog(XLOG_ERROR, "No mount point for %s - skipping", mntdir);
return ENOENT;
}
return mount_nfs_fh(fhp, dir, fs_name, opts, mf);
return mount_nfs_fh(fhp, mntdir, fs_name, mf);
}
@ -208,6 +207,10 @@ fetch_fhandle(CLIENT *client, char *dir, am_nfs_handle_t *fhp, u_long nfs_versio
{
struct timeval tv;
enum clnt_stat clnt_stat;
struct fhstatus res;
#ifdef HAVE_FS_NFS3
struct am_mountres3 res3;
#endif /* HAVE_FS_NFS3 */
/*
* Pick a number, any number...
@ -215,9 +218,7 @@ fetch_fhandle(CLIENT *client, char *dir, am_nfs_handle_t *fhp, u_long nfs_versio
tv.tv_sec = 20;
tv.tv_usec = 0;
#ifdef DEBUG
dlog("Fetching fhandle for %s", dir);
#endif /* DEBUG */
/*
* Call the mount daemon on the remote host to
@ -227,25 +228,28 @@ fetch_fhandle(CLIENT *client, char *dir, am_nfs_handle_t *fhp, u_long nfs_versio
plog(XLOG_INFO, "fetch_fhandle: NFS version %d", (int) nfs_version);
#ifdef HAVE_FS_NFS3
if (nfs_version == NFS_VERSION3) {
memset((char *) &fhp->v3, 0, sizeof(fhp->v3));
memset((char *) &res3, 0, sizeof(res3));
clnt_stat = clnt_call(client,
MOUNTPROC_MNT,
(XDRPROC_T_TYPE) xdr_dirpath,
(SVC_IN_ARG_TYPE) &dir,
(XDRPROC_T_TYPE) xdr_mountres3,
(SVC_IN_ARG_TYPE) &fhp->v3,
(XDRPROC_T_TYPE) xdr_am_mountres3,
(SVC_IN_ARG_TYPE) &res3,
tv);
if (clnt_stat != RPC_SUCCESS) {
plog(XLOG_ERROR, "mountd rpc failed: %s", clnt_sperrno(clnt_stat));
return EIO;
}
/* Check the status of the filehandle */
if ((errno = fhp->v3.fhs_status)) {
#ifdef DEBUG
if ((errno = res3.fhs_status)) {
dlog("fhandle fetch for mount version 3 failed: %m");
#endif /* DEBUG */
return errno;
}
memset((voidp) &fhp->v3, 0, sizeof(am_nfs_fh3));
fhp->v3.am_fh3_length = res3.mountres3_u.mountinfo.fhandle.fhandle3_len;
memmove(fhp->v3.am_fh3_data,
res3.mountres3_u.mountinfo.fhandle.fhandle3_val,
fhp->v3.am_fh3_length);
} else { /* not NFS_VERSION3 mount */
#endif /* HAVE_FS_NFS3 */
clnt_stat = clnt_call(client,
@ -253,20 +257,19 @@ fetch_fhandle(CLIENT *client, char *dir, am_nfs_handle_t *fhp, u_long nfs_versio
(XDRPROC_T_TYPE) xdr_dirpath,
(SVC_IN_ARG_TYPE) &dir,
(XDRPROC_T_TYPE) xdr_fhstatus,
(SVC_IN_ARG_TYPE) &fhp->v2,
(SVC_IN_ARG_TYPE) &res,
tv);
if (clnt_stat != RPC_SUCCESS) {
plog(XLOG_ERROR, "mountd rpc failed: %s", clnt_sperrno(clnt_stat));
return EIO;
}
/* Check status of filehandle */
if (fhp->v2.fhs_status) {
errno = fhp->v2.fhs_status;
#ifdef DEBUG
if (res.fhs_status) {
errno = res.fhs_status;
dlog("fhandle fetch for mount version 1 failed: %m");
#endif /* DEBUG */
return errno;
}
memmove(&fhp->v2, &res.fhs_fh, NFS_FHSIZE);
#ifdef HAVE_FS_NFS3
} /* end of "if (nfs_version == NFS_VERSION3)" statement */
#endif /* HAVE_FS_NFS3 */
@ -291,11 +294,8 @@ already_mounted(mntlist *mlist, char *dir)
}
/*
* Mount the export tree from a host
*/
static int
amfs_host_fmount(mntfs *mf)
amfs_host_mount(am_node *am, mntfs *mf)
{
struct timeval tv2;
CLIENT *client;
@ -316,6 +316,14 @@ amfs_host_fmount(mntfs *mf)
struct timeval tv;
u_long mnt_version;
/*
* WebNFS servers don't necessarily run mountd.
*/
if (mf->mf_flags & MFF_WEBNFS) {
plog(XLOG_ERROR, "amfs_host_mount: cannot support WebNFS");
return EIO;
}
/*
* Read the mount list
*/
@ -334,10 +342,10 @@ amfs_host_fmount(mntfs *mf)
*/
host = mf->mf_server->fs_host;
sin = *mf->mf_server->fs_ip;
plog(XLOG_INFO, "amfs_host_fmount: NFS version %d", (int) mf->mf_server->fs_version);
plog(XLOG_INFO, "amfs_host_mount: NFS version %d", (int) mf->mf_server->fs_version);
#ifdef HAVE_FS_NFS3
if (mf->mf_server->fs_version == NFS_VERSION3)
mnt_version = MOUNTVERS3;
mnt_version = AM_MOUNTVERS3;
else
#endif /* HAVE_FS_NFS3 */
mnt_version = MOUNTVERS;
@ -374,9 +382,7 @@ amfs_host_fmount(mntfs *mf)
}
client->cl_auth = nfs_auth;
#ifdef DEBUG
dlog("Fetching export list from %s", host);
#endif /* DEBUG */
/*
* Fetch the export list
@ -392,7 +398,7 @@ amfs_host_fmount(mntfs *mf)
tv2);
if (clnt_stat != RPC_SUCCESS) {
const char *msg = clnt_sperrno(clnt_stat);
plog(XLOG_ERROR, "host_fmount rpc failed: %s", msg);
plog(XLOG_ERROR, "host_mount rpc failed: %s", msg);
/* clnt_perror(client, "rpc"); */
error = EIO;
goto out;
@ -412,7 +418,7 @@ amfs_host_fmount(mntfs *mf)
*/
ep = (exports *) xmalloc(n_export * sizeof(exports));
for (j = 0, ex = exlist; ex; ex = ex->ex_next) {
make_mntpt(mntpt, ex, mf);
make_mntpt(mntpt, sizeof(mntpt), ex, mf->mf_mount);
if (already_mounted(mlist, mntpt))
/* we have at least one mounted f/s, so don't fail the mount */
ok = TRUE;
@ -442,9 +448,7 @@ amfs_host_fmount(mntfs *mf)
for (j = k = 0; j < n_export; j++) {
/* Check and avoid a duplicated export entry */
if (j > k && ep[k] && STREQ(ep[j]->ex_dir, ep[k]->ex_dir)) {
#ifdef DEBUG
dlog("avoiding dup fhandle requested for %s", ep[j]->ex_dir);
#endif /* DEBUG */
ep[j] = 0;
} else {
k = j;
@ -461,9 +465,9 @@ amfs_host_fmount(mntfs *mf)
* error code 0 at the end. If they all fail then return
* the last error code.
*/
strncpy(fs_name, mf->mf_info, sizeof(fs_name));
xstrlcpy(fs_name, mf->mf_info, MAXPATHLEN);
if ((rfs_dir = strchr(fs_name, ':')) == (char *) 0) {
plog(XLOG_FATAL, "amfs_host_fmount: mf_info has no colon");
plog(XLOG_FATAL, "amfs_host_mount: mf_info has no colon");
error = EINVAL;
goto out;
}
@ -471,9 +475,15 @@ amfs_host_fmount(mntfs *mf)
for (j = 0; j < n_export; j++) {
ex = ep[j];
if (ex) {
strcpy(rfs_dir, ex->ex_dir);
make_mntpt(mntpt, ex, mf);
if (do_mount(&fp[j], mntpt, fs_name, mf->mf_mopts, mf) == 0)
/*
* Note: the sizeof space left in rfs_dir is what's left in fs_name
* after strchr() above returned a pointer _inside_ fs_name. The
* calculation below also takes into account that rfs_dir was
* incremented by the ++ above.
*/
xstrlcpy(rfs_dir, ex->ex_dir, sizeof(fs_name) - (rfs_dir - fs_name));
make_mntpt(mntpt, sizeof(mntpt), ex, mf->mf_mount);
if (do_mount(&fp[j], mntpt, fs_name, mf) == 0)
ok = TRUE;
}
}
@ -522,9 +532,10 @@ directory_prefix(char *pref, char *dir)
* Unmount a mount tree
*/
static int
amfs_host_fumount(mntfs *mf)
amfs_host_umount(am_node *am, mntfs *mf)
{
mntlist *ml, *mprev;
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
int xerror = 0;
/*
@ -559,18 +570,24 @@ amfs_host_fumount(mntfs *mf)
char *dir = ml->mnt->mnt_dir;
if (directory_prefix(mf->mf_mount, dir)) {
int error;
#ifdef DEBUG
dlog("amfs_host: unmounts %s", dir);
#endif /* DEBUG */
/*
* Unmount "dir"
*/
error = UMOUNT_FS(dir, mnttab_file_name);
error = UMOUNT_FS(dir, mnttab_file_name, unmount_flags);
/*
* Keep track of errors
*/
if (error) {
if (!xerror)
/*
* If we have not already set xerror and error is not ENOENT,
* then set xerror equal to error and log it.
* 'xerror' is the return value for this function.
*
* We do not want to pass ENOENT as an error because if the
* directory does not exists our work is done anyway.
*/
if (!xerror && error != ENOENT)
xerror = error;
if (error != EBUSY) {
errno = error;
@ -591,7 +608,7 @@ amfs_host_fumount(mntfs *mf)
* Try to remount, except when we are shutting down.
*/
if (xerror && amd_state != Finishing) {
xerror = amfs_host_fmount(mf);
xerror = amfs_host_mount(am, mf);
if (!xerror) {
/*
* Don't log this - it's usually too verbose
@ -611,9 +628,8 @@ amfs_host_fumount(mntfs *mf)
* mountd protocol is badly broken anyway.
*/
static void
amfs_host_umounted(am_node *mp)
amfs_host_umounted(mntfs *mf)
{
mntfs *mf = mp->am_mnt;
char *host;
CLIENT *client;
enum clnt_stat clnt_stat;
@ -625,6 +641,14 @@ amfs_host_umounted(am_node *mp)
if (mf->mf_error || mf->mf_refc > 1 || !mf->mf_server)
return;
/*
* WebNFS servers shouldn't ever get here.
*/
if (mf->mf_flags & MFF_WEBNFS) {
plog(XLOG_ERROR, "amfs_host_umounted: cannot support WebNFS");
return;
}
/*
* Take a copy of the server hostname, address, and NFS version
* to mount version conversion.
@ -634,7 +658,7 @@ amfs_host_umounted(am_node *mp)
plog(XLOG_INFO, "amfs_host_umounted: NFS version %d", (int) mf->mf_server->fs_version);
#ifdef HAVE_FS_NFS3
if (mf->mf_server->fs_version == NFS_VERSION3)
mnt_version = MOUNTVERS3;
mnt_version = AM_MOUNTVERS3;
else
#endif /* HAVE_FS_NFS3 */
mnt_version = MOUNTVERS;
@ -661,9 +685,7 @@ amfs_host_umounted(am_node *mp)
}
client->cl_auth = nfs_auth;
#ifdef DEBUG
dlog("Unmounting all from %s", host);
#endif /* DEBUG */
clnt_stat = clnt_call(client,
MOUNTPROC_UMNTALL,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_link.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/amfs_link.c
*
*/
@ -52,6 +51,9 @@
#include <am_defs.h>
#include <amd.h>
/* forward declarations */
static int amfs_link_mount(am_node *mp, mntfs *mf);
static int amfs_link_umount(am_node *mp, mntfs *mf);
/*
* Ops structures
@ -61,17 +63,20 @@ am_ops amfs_link_ops =
"link",
amfs_link_match,
0, /* amfs_link_init */
amfs_auto_fmount,
amfs_link_fmount,
amfs_auto_fumount,
amfs_link_fumount,
amfs_error_lookuppn,
amfs_link_mount,
amfs_link_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_error_readdir,
0, /* amfs_link_readlink */
0, /* amfs_link_mounted */
0, /* amfs_link_umounted */
find_amfs_auto_srvr,
0
amfs_generic_find_srvr,
0, /* nfs_fs_flags */
0, /* amfs_link_get_wchan */
#ifdef HAVE_FS_AUTOFS
AUTOFS_LINK_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
@ -88,54 +93,41 @@ amfs_link_match(am_opts *fo)
}
/*
* Bug report (14/12/89) from Jay Plett <jay@princeton.edu>
* If an automount point has the same name as an existing
* link type mount Amd hits a race condition and either hangs
* or causes a symlink loop.
* If the link target points to another mount point, then we could
* end up with an unpleasant situation, where the link f/s simply
* "assumes" the mntfs of that mount point.
*
* If fs begins with a '/' change the opt_fs & opt_sublink
* fields so that the fs option doesn't end up pointing at
* an existing symlink.
* For example, if the link points to /usr, and /usr is a real ufs
* filesystem, then the link f/s will use the inherited ufs mntfs,
* and the end result will be that it will become unmountable.
*
* If sublink is nil then set sublink to fs
* else set sublink to fs / sublink
* To prevent this, we use a hack: we prepend a dot ('.') to opt_fs if
* its original value was an absolute path, so that it will never match
* any other mntfs.
*
* Finally set fs to ".".
* XXX: a less hacky solution should be used...
*/
if (*fo->opt_fs == '/') {
char *fullpath;
char *link = fo->opt_sublink;
if (link) {
if (*link == '/')
fullpath = strdup(link);
else
fullpath = str3cat((char *) 0, fo->opt_fs, "/", link);
} else {
fullpath = strdup(fo->opt_fs);
}
if (fo->opt_sublink)
XFREE(fo->opt_sublink);
fo->opt_sublink = fullpath;
fo->opt_fs = str3cat(fo->opt_fs, ".", fullpath, "");
if (fo->opt_fs[0] == '/') {
char *link_hack = str3cat(NULL, ".", fo->opt_fs, "");
if (!fo->opt_sublink)
fo->opt_sublink = strdup(fo->opt_fs);
XFREE(fo->opt_fs);
fo->opt_fs = link_hack;
}
return strdup(fo->opt_fs);
}
int
amfs_link_fmount(mntfs *mf)
static int
amfs_link_mount(am_node *mp, mntfs *mf)
{
/*
* Wow - this is hard to implement! :-)
*/
return 0;
}
int
amfs_link_fumount(mntfs *mf)
static int
amfs_link_umount(am_node *mp, mntfs *mf)
{
return 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_linkx.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/amfs_linkx.c
*
*/
@ -53,7 +52,8 @@
#include <amd.h>
/* forward declarations */
static int amfs_linkx_mount(am_node *mp);
static int amfs_linkx_mount(am_node *mp, mntfs *mf);
static int amfs_linkx_umount(am_node *mp, mntfs *mf);
/*
* linkx operations
@ -64,21 +64,24 @@ struct am_ops amfs_linkx_ops =
amfs_link_match,
0, /* amfs_linkx_init */
amfs_linkx_mount,
0,
amfs_auto_fumount,
amfs_link_fumount,
amfs_error_lookuppn,
amfs_linkx_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_error_readdir,
0, /* amfs_linkx_readlink */
0, /* amfs_linkx_mounted */
0, /* amfs_linkx_umounted */
find_amfs_auto_srvr,
FS_MBACKGROUND
amfs_generic_find_srvr,
0, /* amfs_linkx_get_wchan */
FS_MBACKGROUND,
#ifdef HAVE_FS_AUTOFS
AUTOFS_LINKX_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
static int
amfs_linkx_mount(am_node *mp)
amfs_linkx_mount(am_node *mp, mntfs *mf)
{
/*
* Check for existence of target.
@ -89,7 +92,7 @@ amfs_linkx_mount(am_node *mp)
if (mp->am_link)
ln = mp->am_link;
else /* should never occur */
ln = mp->am_mnt->mf_mount;
ln = mf->mf_mount;
/*
* Use lstat, not stat, since we don't
@ -101,3 +104,10 @@ amfs_linkx_mount(am_node *mp)
return 0;
}
static int
amfs_linkx_umount(am_node *mp, mntfs *mf)
{
return 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_nfsl.c,v 1.4.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/amfs_nfsl.c
*
*/
@ -60,9 +59,9 @@
/* forward declarations */
static char *amfs_nfsl_match(am_opts *fo);
static int amfs_nfsl_init(mntfs *mf);
static int amfs_nfsl_fmount(mntfs *mf);
static int amfs_nfsl_fumount(mntfs *mf);
static void amfs_nfsl_umounted(am_node *mp);
static int amfs_nfsl_mount(am_node *mp, mntfs *mf);
static int amfs_nfsl_umount(am_node *mp, mntfs *mf);
static void amfs_nfsl_umounted(mntfs *mf);
static fserver *amfs_nfsl_ffserver(mntfs *mf);
/*
@ -70,20 +69,23 @@ static fserver *amfs_nfsl_ffserver(mntfs *mf);
*/
am_ops amfs_nfsl_ops =
{
"nfsl", /* name of file system */
amfs_nfsl_match, /* match */
amfs_nfsl_init, /* initialize */
amfs_auto_fmount, /* mount vnode */
amfs_nfsl_fmount, /* mount vfs */
amfs_auto_fumount, /* unmount vnode */
amfs_nfsl_fumount, /* unmount VFS */
amfs_error_lookuppn, /* lookup path-name */
amfs_error_readdir, /* read directory */
0, /* read link */
0, /* after-mount extra actions */
amfs_nfsl_umounted, /* after-umount extra actions */
amfs_nfsl_ffserver, /* find a file server */
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO /* flags */
"nfsl",
amfs_nfsl_match,
amfs_nfsl_init,
amfs_nfsl_mount,
amfs_nfsl_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_error_readdir,
0, /* amfs_nfsl_readlink */
0, /* amfs_nfsl_mounted */
amfs_nfsl_umounted,
amfs_nfsl_ffserver,
0, /* amfs_nfsl_get_wchan */
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
#ifdef HAVE_FS_AUTOFS
AUTOFS_NFSL_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
@ -94,10 +96,16 @@ am_ops amfs_nfsl_ops =
static char *
amfs_nfsl_match(am_opts *fo)
{
char *cp = fo->opt_fs;
char *cp;
char *ho = fo->opt_rhost;
char *retval;
struct stat stb;
if (fo->opt_sublink)
cp = fo->opt_sublink;
else
cp = fo->opt_fs;
if (!cp || !ho) {
plog(XLOG_USER, "amfs_nfsl: host $fs and $rhost must be specified");
return NULL;
@ -105,20 +113,20 @@ amfs_nfsl_match(am_opts *fo)
/*
* If this host is not the same as $rhost, or if link does not exist,
* perform nfs_match(), same as for type:=nfs.
* If link value exists (or same host), then perform amfs_link_match(),
* same as for linkx.
* call nfs_ops.fs_match().
* If link value exists (or same host), call amfs_link_ops.fs_match().
*/
if (!STRCEQ(ho, am_get_hostname())) {
plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not local host, using type:=nfs", ho);
return nfs_match(fo);
retval = nfs_ops.fs_match(fo);
} else if (lstat(cp, &stb) < 0) {
plog(XLOG_INFO, "amfs_nfsl: \"%s\" does not exist, using type:=nfs", cp);
return nfs_match(fo);
retval = nfs_ops.fs_match(fo);
} else {
plog(XLOG_INFO, "amfs_nfsl: \"%s\" exists, using type:=link", cp);
return amfs_link_match(fo);
retval = amfs_link_ops.fs_match(fo);
}
return retval;
}
@ -129,15 +137,15 @@ amfs_nfsl_match(am_opts *fo)
static int
amfs_nfsl_init(mntfs *mf)
{
/*
* If a link, do nothing (same as type:=link).
* If non-link, do nfs_init (same as type:=nfs).
*/
int ret = 0;
if (mf->mf_flags & MFF_NFSLINK) {
return 0;
if (amfs_link_ops.fs_init)
ret = amfs_link_ops.fs_init(mf);
} else {
return nfs_init(mf);
if (nfs_ops.fs_init)
ret = nfs_ops.fs_init(mf);
}
return ret;
}
@ -146,17 +154,17 @@ amfs_nfsl_init(mntfs *mf)
* Returns: 0 if OK, non-zero (errno) if failed.
*/
static int
amfs_nfsl_fmount(mntfs *mf)
amfs_nfsl_mount(am_node *mp, mntfs *mf)
{
/*
* If a link, do run amfs_link_fmount() (same as type:=link)
* If non-link, do nfs_fmount (same as type:=nfs).
*/
int ret = 0;
if (mf->mf_flags & MFF_NFSLINK) {
return amfs_link_fmount(mf);
if (amfs_link_ops.mount_fs)
ret = amfs_link_ops.mount_fs(mp, mf);
} else {
return nfs_fmount(mf);
if (nfs_ops.mount_fs)
ret = nfs_ops.mount_fs(mp, mf);
}
return ret;
}
@ -165,17 +173,17 @@ amfs_nfsl_fmount(mntfs *mf)
* Returns: 0 if OK, non-zero (errno) if failed.
*/
static int
amfs_nfsl_fumount(mntfs *mf)
amfs_nfsl_umount(am_node *mp, mntfs *mf)
{
/*
* If a link, do run amfs_link_fumount() (same as type:=link)
* If non-link, do nfs_fumount (same as type:=nfs).
*/
int ret = 0;
if (mf->mf_flags & MFF_NFSLINK) {
return amfs_link_fumount(mf);
if (amfs_link_ops.umount_fs)
ret = amfs_link_ops.umount_fs(mp, mf);
} else {
return nfs_fumount(mf);
if (nfs_ops.umount_fs)
ret = nfs_ops.umount_fs(mp, mf);
}
return ret;
}
@ -186,27 +194,14 @@ amfs_nfsl_fumount(mntfs *mf)
* See amfs_auto_umounted(), host_umounted(), nfs_umounted().
*/
static void
amfs_nfsl_umounted(am_node *mp)
amfs_nfsl_umounted(mntfs *mf)
{
mntfs *mf = mp->am_mnt;
/*
* If a link, do nothing (same as type:=link)
* If non-link, do nfs_fumount (same as type:=nfs).
*/
if (mf->mf_flags & MFF_NFSLINK) {
return;
if (amfs_link_ops.umounted)
amfs_link_ops.umounted(mf);
} else {
nfs_umounted(mp);
/*
* MUST remove mount point directories, because if they remain
* behind, the next nfsl access will think they are a link
* type file system, and not NFS! (when it performs link target
* existence test)
*/
if (mf->mf_flags & MFF_MKMNT)
rmdirs(mf->mf_mount);
return;
if (nfs_ops.umounted)
nfs_ops.umounted(mf);
}
}
@ -218,20 +213,26 @@ amfs_nfsl_umounted(am_node *mp)
static fserver *
amfs_nfsl_ffserver(mntfs *mf)
{
char *cp = mf->mf_fo->opt_fs;
char *cp;
char *ho = mf->mf_fo->opt_rhost;
struct stat stb;
if (mf->mf_fo->opt_sublink)
cp = mf->mf_fo->opt_sublink;
else
cp = mf->mf_fo->opt_fs;
/*
* If this host is not the same as $rhost, or if link does not exist,
* perform find_nfs_srvr(), same as for type:=nfs.
* If link value exists (or same host), then perform
* find_amfs_auto_srvr(), same as for linkx.
* call amfs_link_ops.ffserver().
* If link value exists (or same host), then call ops_nfs.ffserver().
*/
if (!STRCEQ(ho, am_get_hostname()) || lstat(cp, &stb) < 0) {
return find_nfs_srvr(mf);
return nfs_ops.ffserver(mf);
} else {
mf->mf_flags |= MFF_NFSLINK;
return find_amfs_auto_srvr(mf);
/* remove the FS_MKMNT flag, we don't want amd touching the mountpoint */
mf->mf_fsflags &= ~FS_MKMNT;
return amfs_link_ops.ffserver(mf);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_nfsx.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/amfs_nfsx.c
*
*/
@ -67,13 +66,13 @@ struct amfs_nfsx {
int nx_c; /* Number of elements in nx_v */
amfs_nfsx_mnt *nx_v; /* Underlying mounts */
amfs_nfsx_mnt *nx_try;
am_node *nx_mp;
};
/* forward definitions */
static char *amfs_nfsx_match(am_opts *fo);
static int amfs_nfsx_fmount (mntfs *);
static int amfs_nfsx_fmount(mntfs *mf);
static int amfs_nfsx_fumount(mntfs *mf);
static int amfs_nfsx_mount(am_node *am, mntfs *mf);
static int amfs_nfsx_umount(am_node *am, mntfs *mf);
static int amfs_nfsx_init(mntfs *mf);
/*
@ -84,17 +83,20 @@ am_ops amfs_nfsx_ops =
"nfsx",
amfs_nfsx_match,
amfs_nfsx_init,
amfs_auto_fmount,
amfs_nfsx_fmount,
amfs_auto_fumount,
amfs_nfsx_fumount,
amfs_error_lookuppn,
amfs_nfsx_mount,
amfs_nfsx_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_error_readdir,
0, /* amfs_nfsx_readlink */
0, /* amfs_nfsx_mounted */
0, /* amfs_nfsx_umounted */
find_nfs_srvr, /* XXX */
/* FS_UBACKGROUND| */ FS_AMQINFO
0, /* amfs_nfsx_get_wchan */
/* FS_UBACKGROUND| */ FS_AMQINFO, /* nfs_fs_flags */
#ifdef HAVE_FS_AUTOFS
AUTOFS_NFSX_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
@ -118,7 +120,7 @@ amfs_nfsx_match(am_opts *fo)
/* set default sublink */
if (fo->opt_sublink == 0) {
ptr = strchr(fo->opt_rfs, ',');
if (ptr && ptr != (fo->opt_rfs + 1))
if (ptr && ptr > (fo->opt_rfs + 1))
fo->opt_sublink = strnsave(fo->opt_rfs + 1, ptr - fo->opt_rfs - 1);
}
@ -148,17 +150,15 @@ amfs_nfsx_match(am_opts *fo)
* Determine magic cookie to put in mtab
*/
xmtab = str3cat((char *) 0, fo->opt_rhost, ":", fo->opt_rfs);
#ifdef DEBUG
dlog("NFSX: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
fo->opt_rhost, fo->opt_rfs, fo->opt_fs);
#endif /* DEBUG */
return xmtab;
}
static void
amfs_nfsx_prfree(voidp vp)
amfs_nfsx_prfree(opaque_t vp)
{
struct amfs_nfsx *nx = (struct amfs_nfsx *) vp;
int i;
@ -201,7 +201,7 @@ amfs_nfsx_init(mntfs *mf)
error = EINVAL;
goto errexit;
}
pref = host +1;
pref = host + 1;
host = info;
/*
@ -212,14 +212,16 @@ amfs_nfsx_init(mntfs *mf)
/*
* Count array size
*/
for (i = 0; ivec[i]; i++) ;
for (i = 0; ivec[i]; i++)
/* nothing */;
nx = ALLOC(struct amfs_nfsx);
mf->mf_private = (voidp) nx;
mf->mf_private = (opaque_t) nx;
mf->mf_prfree = amfs_nfsx_prfree;
nx->nx_c = i - 1; /* i-1 because we don't want the prefix */
nx->nx_v = (amfs_nfsx_mnt *) xmalloc(nx->nx_c * sizeof(amfs_nfsx_mnt));
nx->nx_mp = 0;
{
char *mp = 0;
char *xinfo = 0;
@ -243,11 +245,11 @@ amfs_nfsx_init(mntfs *mf)
normalize_slash(xinfo);
if (pref[1] != '\0')
deslashify(xinfo);
#ifdef DEBUG
dlog("amfs_nfsx: init mount for %s on %s", xinfo, mp);
#endif /* DEBUG */
nx->nx_v[i].n_error = -1;
nx->nx_v[i].n_mnt = find_mntfs(&nfs_ops, mf->mf_fo, mp, xinfo, "", mf->mf_mopts, mf->mf_remopts);
/* propagate the on_autofs flag */
nx->nx_v[i].n_mnt->mf_flags |= mf->mf_flags & MFF_ON_AUTOFS;
}
if (rfs)
XFREE(rfs);
@ -274,7 +276,9 @@ amfs_nfsx_init(mntfs *mf)
for (i = 0; i < nx->nx_c; i++) {
amfs_nfsx_mnt *n = &nx->nx_v[i];
mntfs *m = n->n_mnt;
int error = (*m->mf_ops->fs_init) (m);
int error = 0;
if (m->mf_ops->fs_init && !(mf->mf_flags & MFF_RESTART))
error = m->mf_ops->fs_init(m);
/*
* if you just "return error" here, you will have made a failure
* in any submounts to fail the whole group. There was old unused code
@ -287,7 +291,7 @@ amfs_nfsx_init(mntfs *mf)
glob_error = -1;
if (!asked_for_wakeup) {
asked_for_wakeup = 1;
sched_task(wakeup_task, (voidp) mf, (voidp) m);
sched_task(wakeup_task, (opaque_t) mf, get_mntfs_wchan(m));
}
}
}
@ -297,10 +301,11 @@ amfs_nfsx_init(mntfs *mf)
static void
amfs_nfsx_cont(int rc, int term, voidp closure)
amfs_nfsx_cont(int rc, int term, opaque_t arg)
{
mntfs *mf = (mntfs *) closure;
mntfs *mf = (mntfs *) arg;
struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private;
am_node *mp = nx->nx_mp;
amfs_nfsx_mnt *n = nx->nx_try;
n->n_mnt->mf_flags &= ~(MFF_ERROR | MFF_MOUNTING);
@ -309,7 +314,7 @@ amfs_nfsx_cont(int rc, int term, voidp closure)
/*
* Wakeup anything waiting for this mount
*/
wakeup((voidp) n->n_mnt);
wakeup(get_mntfs_wchan(n->n_mnt));
if (rc || term) {
if (term) {
@ -334,52 +339,41 @@ amfs_nfsx_cont(int rc, int term, voidp closure)
/*
* The mount worked.
*/
mf_mounted(n->n_mnt);
mf_mounted(n->n_mnt, FALSE); /* FALSE => don't free the n_mnt->am_opts */
n->n_error = 0;
}
/*
* Do the remaining bits
*/
if (amfs_nfsx_fmount(mf) >= 0) {
wakeup((voidp) mf);
mf->mf_flags &= ~MFF_MOUNTING;
mf_mounted(mf);
}
if (amfs_nfsx_mount(mp, mf) >= 0)
wakeup(get_mntfs_wchan(mf));
}
static int
try_amfs_nfsx_mount(voidp mv)
try_amfs_nfsx_mount(opaque_t mv)
{
mntfs *mf = (mntfs *) mv;
struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private;
am_node *mp = nx->nx_mp;
int error;
mf->mf_flags |= MFF_MOUNTING;
error = (*mf->mf_ops->fmount_fs) (mf);
mf->mf_flags &= ~MFF_MOUNTING;
error = mf->mf_ops->mount_fs(mp, mf);
return error;
}
static int
amfs_nfsx_remount(mntfs *mf, int fg)
amfs_nfsx_remount(am_node *am, mntfs *mf, int fg)
{
struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private;
amfs_nfsx_mnt *n;
int glob_error = -1;
for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) {
mntfs *m = n->n_mnt;
if (n->n_error < 0) {
if (!(m->mf_flags & MFF_MKMNT) && m->mf_ops->fs_flags & FS_MKMNT) {
int error = mkdirs(m->mf_mount, 0555);
if (!error)
m->mf_flags |= MFF_MKMNT;
}
}
}
/* Save the am_node pointer for later use */
nx->nx_mp = am;
/*
* Iterate through the mntfs's and mount each filesystem
@ -387,40 +381,38 @@ amfs_nfsx_remount(mntfs *mf, int fg)
*/
for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) {
mntfs *m = n->n_mnt;
if (m->mf_flags & MFF_MOUNTING)
break;
if (m->mf_flags & MFF_MOUNTED) {
mf_mounted(m, FALSE); /* FALSE => don't free the m->am_opts */
n->n_error = glob_error = 0;
continue;
}
if (n->n_error < 0) {
/*
* Check fmount entry pt. exists
* and then mount...
*/
if (!m->mf_ops->fmount_fs) {
n->n_error = EINVAL;
} else {
#ifdef DEBUG
dlog("calling underlying fmount on %s", m->mf_mount);
#endif /* DEBUG */
if (!fg && foreground && (m->mf_ops->fs_flags & FS_MBACKGROUND)) {
m->mf_flags |= MFF_MOUNTING; /* XXX */
#ifdef DEBUG
dlog("backgrounding mount of \"%s\"", m->mf_info);
#endif /* DEBUG */
nx->nx_try = n;
run_task(try_amfs_nfsx_mount, (voidp) m, amfs_nfsx_cont, (voidp) mf);
n->n_error = -1;
return -1;
} else {
#ifdef DEBUG
dlog("foreground mount of \"%s\" ...", mf->mf_info);
#endif /* DEBUG */
n->n_error = (*m->mf_ops->fmount_fs) (m);
}
/* Create the mountpoint, if and as required */
if (!(m->mf_flags & MFF_MKMNT) && m->mf_fsflags & FS_MKMNT) {
if (!mkdirs(m->mf_mount, 0555))
m->mf_flags |= MFF_MKMNT;
}
#ifdef DEBUG
if (n->n_error > 0) {
errno = n->n_error; /* XXX */
dlog("underlying fmount of %s failed: %m", m->mf_mount);
dlog("calling underlying mount on %s", m->mf_mount);
if (!fg && foreground && (m->mf_fsflags & FS_MBACKGROUND)) {
m->mf_flags |= MFF_MOUNTING;
dlog("backgrounding mount of \"%s\"", m->mf_info);
nx->nx_try = n;
run_task(try_amfs_nfsx_mount, (opaque_t) m, amfs_nfsx_cont, (opaque_t) mf);
n->n_error = -1;
return -1;
} else {
dlog("foreground mount of \"%s\" ...", mf->mf_info);
n->n_error = m->mf_ops->mount_fs(am, m);
}
#endif /* DEBUG */
if (n->n_error > 0)
dlog("underlying fmount of %s failed: %s", m->mf_mount, strerror(n->n_error));
if (n->n_error == 0) {
glob_error = 0;
@ -435,9 +427,9 @@ amfs_nfsx_remount(mntfs *mf, int fg)
static int
amfs_nfsx_fmount(mntfs *mf)
amfs_nfsx_mount(am_node *am, mntfs *mf)
{
return amfs_nfsx_remount(mf, FALSE);
return amfs_nfsx_remount(am, mf, FALSE);
}
@ -447,7 +439,7 @@ amfs_nfsx_fmount(mntfs *mf)
* and so may hang under extremely rare conditions.
*/
static int
amfs_nfsx_fumount(mntfs *mf)
amfs_nfsx_umount(am_node *am, mntfs *mf)
{
struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private;
amfs_nfsx_mnt *n;
@ -469,10 +461,8 @@ amfs_nfsx_fumount(mntfs *mf)
* which had been successfully unmounted.
*/
if (n->n_error == 0) {
#ifdef DEBUG
dlog("calling underlying fumount on %s", m->mf_mount);
#endif /* DEBUG */
n->n_error = (*m->mf_ops->fumount_fs) (m);
n->n_error = m->mf_ops->umount_fs(am, m);
if (n->n_error) {
glob_error = n->n_error;
n->n_error = 0;
@ -490,7 +480,7 @@ amfs_nfsx_fumount(mntfs *mf)
* whole lot...
*/
if (glob_error) {
glob_error = amfs_nfsx_remount(mf, TRUE);
glob_error = amfs_nfsx_remount(am, mf, TRUE);
if (glob_error) {
errno = glob_error; /* XXX */
plog(XLOG_USER, "amfs_nfsx: remount of %s failed: %m", mf->mf_mount);
@ -502,22 +492,12 @@ amfs_nfsx_fumount(mntfs *mf)
*/
for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) {
mntfs *m = n->n_mnt;
am_node am;
/*
* XXX: all the umounted handler needs is a
* mntfs pointer, so pass an am_node with the right
* pointer in it.
*/
memset((voidp) &am, 0, sizeof(am));
am.am_mnt = m;
#ifdef DEBUG
dlog("calling underlying umounted on %s", m->mf_mount);
#endif /* DEBUG */
(*m->mf_ops->umounted) (&am);
if (m->mf_ops->umounted)
m->mf_ops->umounted(m);
if (n->n_error < 0) {
if (m->mf_ops->fs_flags & FS_MKMNT) {
if (m->mf_fsflags & FS_MKMNT) {
(void) rmdirs(m->mf_mount);
m->mf_flags &= ~MFF_MKMNT;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_program.c,v 1.6.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/amfs_program.c
*
*/
@ -54,8 +53,8 @@
/* forward definitions */
static char *amfs_program_match(am_opts *fo);
static int amfs_program_fmount(mntfs *mf);
static int amfs_program_fumount(mntfs *mf);
static int amfs_program_mount(am_node *am, mntfs *mf);
static int amfs_program_umount(am_node *am, mntfs *mf);
static int amfs_program_init(mntfs *mf);
/*
@ -66,17 +65,20 @@ am_ops amfs_program_ops =
"program",
amfs_program_match,
amfs_program_init,
amfs_auto_fmount,
amfs_program_fmount,
amfs_auto_fumount,
amfs_program_fumount,
amfs_error_lookuppn,
amfs_program_mount,
amfs_program_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_error_readdir,
0, /* amfs_program_readlink */
0, /* amfs_program_mounted */
0, /* amfs_program_umounted */
find_amfs_auto_srvr,
FS_BACKGROUND | FS_AMQINFO
amfs_generic_find_srvr,
0, /* amfs_program_get_wchan */
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
#ifdef HAVE_FS_AUTOFS
AUTOFS_PROGRAM_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
@ -88,10 +90,19 @@ amfs_program_match(am_opts *fo)
{
char *prog;
if (!fo->opt_mount || !fo->opt_unmount) {
plog(XLOG_ERROR, "program: both mount and unmount must be specified");
if (fo->opt_unmount && fo->opt_umount) {
plog(XLOG_ERROR, "program: cannot specify both unmount and umount options");
return 0;
}
if (!fo->opt_mount) {
plog(XLOG_ERROR, "program: must specify mount command");
return 0;
}
if (!fo->opt_unmount && !fo->opt_umount) {
fo->opt_unmount = str3cat(NULL, UNMOUNT_PROGRAM, " umount ", fo->opt_fs);
plog(XLOG_INFO, "program: un/umount not specified; using default \"%s\"",
fo->opt_unmount);
}
prog = strchr(fo->opt_mount, ' ');
return strdup(prog ? prog + 1 : fo->opt_mount);
@ -101,13 +112,16 @@ amfs_program_match(am_opts *fo)
static int
amfs_program_init(mntfs *mf)
{
/*
* Save unmount command
*/
if (mf->mf_refc == 1) {
mf->mf_private = (voidp) strdup(mf->mf_fo->opt_unmount);
mf->mf_prfree = (void (*)(voidp)) free;
}
/* check if already saved value */
if (mf->mf_private != NULL)
return 0;
/* save unmount (or umount) command */
if (mf->mf_fo->opt_unmount != NULL)
mf->mf_private = (opaque_t) strdup(mf->mf_fo->opt_unmount);
else
mf->mf_private = (opaque_t) strdup(mf->mf_fo->opt_umount);
mf->mf_prfree = (void (*)(opaque_t)) free;
return 0;
}
@ -142,8 +156,7 @@ amfs_program_exec(char *info)
/*
* Try the exec
*/
#ifdef DEBUG
amuDebug(D_FULL) {
if (amuDebug(D_FULL)) {
char **cp = xivec;
plog(XLOG_DEBUG, "executing (un)mount command...");
while (*cp) {
@ -151,7 +164,6 @@ amfs_program_exec(char *info)
cp++;
}
}
#endif /* DEBUG */
if (xivec[0] == 0 || xivec[1] == 0) {
errno = EINVAL;
@ -180,14 +192,14 @@ amfs_program_exec(char *info)
static int
amfs_program_fmount(mntfs *mf)
amfs_program_mount(am_node *am, mntfs *mf)
{
return amfs_program_exec(mf->mf_fo->opt_mount);
}
static int
amfs_program_fumount(mntfs *mf)
amfs_program_umount(am_node *am, mntfs *mf)
{
return amfs_program_exec((char *) mf->mf_private);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_root.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/amfs_root.c
*
*/
@ -55,7 +54,7 @@
/****************************************************************************
*** FORWARD DEFINITIONS ***
****************************************************************************/
static int amfs_root_mount(am_node *mp);
static int amfs_root_mount(am_node *mp, mntfs *mf);
/****************************************************************************
*** OPS STRUCTURES ***
@ -66,16 +65,19 @@ am_ops amfs_root_ops =
0, /* amfs_root_match */
0, /* amfs_root_init */
amfs_root_mount,
0,
amfs_auto_umount,
0,
amfs_auto_lookuppn,
amfs_auto_readdir,
amfs_generic_umount,
amfs_generic_lookup_child,
amfs_generic_mount_child,
amfs_generic_readdir,
0, /* amfs_root_readlink */
0, /* amfs_root_mounted */
0, /* amfs_root_umounted */
find_amfs_auto_srvr,
FS_NOTIMEOUT | FS_AMQINFO | FS_DIRECTORY
amfs_generic_find_srvr,
0, /* amfs_root_get_wchan */
FS_NOTIMEOUT | FS_AMQINFO | FS_DIRECTORY, /* nfs_fs_flags */
#ifdef HAVE_FS_AUTOFS
AUTOFS_ROOT_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
@ -87,12 +89,10 @@ am_ops amfs_root_ops =
* Mount the root...
*/
static int
amfs_root_mount(am_node *mp)
amfs_root_mount(am_node *mp, mntfs *mf)
{
mntfs *mf = mp->am_mnt;
mf->mf_mount = strealloc(mf->mf_mount, pid_fsname);
mf->mf_private = (voidp) mapc_find(mf->mf_info, "", NULL);
mf->mf_private = (opaque_t) mapc_find(mf->mf_info, "", NULL);
mf->mf_prfree = mapc_free;
return 0;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_toplvl.c,v 1.7.2.5 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/amfs_toplvl.c
*
*/
@ -55,7 +54,7 @@
/****************************************************************************
*** FORWARD DEFINITIONS ***
****************************************************************************/
static int amfs_toplvl_init(mntfs *mf);
/****************************************************************************
*** OPS STRUCTURES ***
@ -63,19 +62,23 @@
am_ops amfs_toplvl_ops =
{
"toplvl",
amfs_auto_match,
0, /* amfs_auto_init */
amfs_generic_match,
amfs_toplvl_init, /* amfs_toplvl_init */
amfs_toplvl_mount,
0,
amfs_toplvl_umount,
0,
amfs_auto_lookuppn,
amfs_auto_readdir, /* browsable version of readdir() */
amfs_generic_lookup_child,
amfs_generic_mount_child,
amfs_generic_readdir,
0, /* amfs_toplvl_readlink */
amfs_toplvl_mounted,
amfs_generic_mounted,
0, /* amfs_toplvl_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO | FS_DIRECTORY
amfs_generic_find_srvr,
0, /* amfs_toplvl_get_wchan */
FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND |
FS_AMQINFO | FS_DIRECTORY, /* nfs_fs_flags */
#ifdef HAVE_FS_AUTOFS
AUTOFS_TOPLVL_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
@ -83,166 +86,79 @@ am_ops amfs_toplvl_ops =
*** FUNCTIONS ***
****************************************************************************/
static void
set_auto_attrcache_timeout(char *preopts, char *opts, size_t l)
{
#ifdef MNTTAB_OPT_NOAC
/*
* Don't cache attributes - they are changing under the kernel's feet.
* For example, IRIX5.2 will dispense with nfs lookup calls and hand stale
* filehandles to getattr unless we disable attribute caching on the
* automount points.
*/
if (gopt.auto_attrcache == 0) {
xsnprintf(preopts, l, ",%s", MNTTAB_OPT_NOAC);
xstrlcat(opts, preopts, l);
}
#endif /* MNTTAB_OPT_NOAC */
/*
* XXX: note that setting these to 0 in the past resulted in an error on
* some systems, which is why it's better to use "noac" if possible. For
* now, we're setting everything possible, but if this will cause trouble,
* then we'll have to condition the remainder of this on OPT_NOAC.
*/
#ifdef MNTTAB_OPT_ACTIMEO
xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTIMEO, gopt.auto_attrcache);
xstrlcat(opts, preopts, l);
#else /* MNTTAB_OPT_ACTIMEO */
# ifdef MNTTAB_OPT_ACDIRMIN
xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTDIRMIN, gopt.auto_attrcache);
xstrlcat(opts, preopts, l);
# endif /* MNTTAB_OPT_ACDIRMIN */
# ifdef MNTTAB_OPT_ACDIRMAX
xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTDIRMAX, gopt.auto_attrcache);
xstrlcat(opts, preopts, l);
# endif /* MNTTAB_OPT_ACDIRMAX */
# ifdef MNTTAB_OPT_ACREGMIN
xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTREGMIN, gopt.auto_attrcache);
xstrlcat(opts, preopts, l);
# endif /* MNTTAB_OPT_ACREGMIN */
# ifdef MNTTAB_OPT_ACREGMAX
xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTREGMAX, gopt.auto_attrcache);
xstrlcat(opts, preopts, l);
# endif /* MNTTAB_OPT_ACREGMAX */
#endif /* MNTTAB_OPT_ACTIMEO */
}
/*
* Mount an automounter directory.
* The automounter is connected into the system
* as a user-level NFS server. mount_amfs_toplvl constructs
* the necessary NFS parameters to be given to the
* kernel so that it will talk back to us.
* Initialize a top-level mount. In our case, if the user asked for
* forced_unmounts, and the OS supports it, then we try forced/lazy unmounts
* on any previous toplvl mounts. This is useful if a previous Amd died and
* left behind toplvl mount points (this Amd will clean them up).
*
* NOTE: automounter mounts in themselves are using NFS Version 2.
* WARNING: Don't use forced/lazy unmounts if you have another valid Amd
* running, because this code WILL force those valid toplvl mount points to
* be detached as well!
*/
static int
mount_amfs_toplvl(char *dir, char *opts)
amfs_toplvl_init(mntfs *mf)
{
char fs_hostname[MAXHOSTNAMELEN + MAXPATHLEN + 1];
int retry, error, genflags;
mntent_t mnt;
nfs_args_t nfs_args;
am_nfs_fh *fhp;
am_nfs_handle_t anh;
MTYPE_TYPE type = MOUNT_TYPE_NFS;
#ifndef HAVE_TRANSPORT_TYPE_TLI
u_short port;
struct sockaddr_in sin;
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
int error = 0;
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
mnt.mnt_fsname = pid_fsname;
mnt.mnt_opts = opts;
/*
* Make sure that amd's top-level NFS mounts are hidden by default
* from df.
* If they don't appear to support the either the "ignore" mnttab
* option entry, or the "auto" one, set the mount type to "nfs".
*/
mnt.mnt_type = HIDE_MOUNT_TYPE;
retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
if (retry <= 0)
retry = 2; /* XXX */
/*
* SET MOUNT ARGS
*/
/*
* get fhandle of remote path for automount point
*/
fhp = root_fh(dir);
if (!fhp) {
plog(XLOG_FATAL, "Can't find root file handle for %s", dir);
return EINVAL;
#if defined(MNT2_GEN_OPT_FORCE) || defined(MNT2_GEN_OPT_DETACH)
if (gopt.flags & CFM_FORCED_UNMOUNTS) {
plog(XLOG_INFO, "amfs_toplvl_init: trying forced/lazy unmount of %s",
mf->mf_mount);
error = umount2_fs(mf->mf_mount, AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH);
if (error)
plog(XLOG_INFO, "amfs_toplvl_init: forced/lazy unmount failed: %m");
else
dlog("amfs_toplvl_init: forced/lazy unmount succeeded");
}
#ifndef HAVE_TRANSPORT_TYPE_TLI
/*
* Create sockaddr to point to the local machine. 127.0.0.1
* is not used since that will not work in HP-UX clusters and
* this is no more expensive.
*/
memset((voidp) &sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr = myipaddr;
port = hasmntval(&mnt, MNTTAB_OPT_PORT);
if (port) {
sin.sin_port = htons(port);
} else {
plog(XLOG_ERROR, "no port number specified for %s", dir);
return EINVAL;
}
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/*
* Make a ``hostname'' string for the kernel
*/
sprintf(fs_hostname, "pid%ld@%s:%s",
(long) (foreground ? am_mypid : getppid()),
am_get_hostname(),
dir);
/*
* Most kernels have a name length restriction (64 bytes)...
*/
if (strlen(fs_hostname) >= MAXHOSTNAMELEN)
strcpy(fs_hostname + MAXHOSTNAMELEN - 3, "..");
#ifdef HOSTNAMESZ
/*
* ... and some of these restrictions are 32 bytes (HOSTNAMESZ)
* If you need to get the definition for HOSTNAMESZ found, you may
* add the proper header file to the conf/nfs_prot/nfs_prot_*.h file.
*/
if (strlen(fs_hostname) >= HOSTNAMESZ)
strcpy(fs_hostname + HOSTNAMESZ - 3, "..");
#endif /* HOSTNAMESZ */
/*
* Finally we can compute the mount genflags set above,
* and add any automounter specific flags.
*/
genflags = compute_mount_flags(&mnt);
genflags |= compute_automounter_mount_flags(&mnt);
/* setup the many fields and flags within nfs_args */
memmove(&anh.v2.fhs_fh, fhp, sizeof(*fhp));
#ifdef HAVE_TRANSPORT_TYPE_TLI
compute_nfs_args(&nfs_args,
&mnt,
genflags,
nfsncp,
NULL, /* remote host IP addr is set below */
NFS_VERSION, /* version 2 */
"udp",
&anh,
fs_hostname,
pid_fsname);
/*
* IMPORTANT: set the correct IP address AFTERWARDS. It cannot
* be done using the normal mechanism of compute_nfs_args(), because
* that one will allocate a new address and use NFS_SA_DREF() to copy
* parts to it, while assuming that the ip_addr passed is always
* a "struct sockaddr_in". That assumption is incorrect on TLI systems,
* because they define a special macro HOST_SELF which is DIFFERENT
* than localhost (127.0.0.1)!
*/
nfs_args.addr = &nfsxprt->xp_ltaddr;
#else /* not HAVE_TRANSPORT_TYPE_TLI */
compute_nfs_args(&nfs_args,
&mnt,
genflags,
&sin,
NFS_VERSION, /* version 2 */
"udp",
&anh,
fs_hostname,
pid_fsname);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/*************************************************************************
* NOTE: while compute_nfs_args() works ok for regular NFS mounts *
* the toplvl one is not, and so some options must be corrected by hand *
* more carefully, *after* compute_nfs_args() runs. *
*************************************************************************/
compute_automounter_nfs_args(&nfs_args, &mnt);
/* This is it! Here we try to mount amd on its mount points */
#ifdef DEBUG
amuDebug(D_TRACE) {
print_nfs_args(&nfs_args, 0);
plog(XLOG_DEBUG, "Generic mount flags 0x%x", genflags);
}
#endif /* DEBUG */
error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type,
0, NULL, mnttab_file_name);
#ifdef HAVE_TRANSPORT_TYPE_TLI
free_knetconfig(nfs_args.knconf);
/*
* local automounter mounts do not allocate a special address, so
* no need to XFREE(nfs_args.addr) under TLI.
*/
#endif /* HAVE_TRANSPORT_TYPE_TLI */
#endif /* MNT2_GEN_OPT_FORCE || MNT2_GEN_OPT_DETACH */
return error;
}
@ -251,13 +167,11 @@ mount_amfs_toplvl(char *dir, char *opts)
* Mount the top-level
*/
int
amfs_toplvl_mount(am_node *mp)
amfs_toplvl_mount(am_node *mp, mntfs *mf)
{
mntfs *mf = mp->am_mnt;
struct stat stb;
char opts[256], preopts[256];
char opts[SIZEOF_OPTS], preopts[SIZEOF_OPTS], toplvl_opts[40];
int error;
char *mnttype;
/*
* Mounting the automounter.
@ -271,16 +185,6 @@ amfs_toplvl_mount(am_node *mp)
plog(XLOG_WARNING, "%s is not a directory", mp->am_path);
return ENOTDIR;
}
if (mf->mf_ops == &amfs_toplvl_ops)
mnttype = "indirect";
else if (mf->mf_ops == &amfs_direct_ops)
mnttype = "direct";
#ifdef HAVE_AMU_FS_UNION
else if (mf->mf_ops == &amfs_union_ops)
mnttype = "union";
#endif /* HAVE_AMU_FS_UNION */
else
mnttype = "auto";
/*
* Construct some mount options:
@ -288,49 +192,71 @@ amfs_toplvl_mount(am_node *mp)
* Tack on magic map=<mapname> option in mtab to emulate
* SunOS automounter behavior.
*/
preopts[0] = '\0';
#ifdef HAVE_FS_AUTOFS
if (mf->mf_flags & MFF_IS_AUTOFS) {
autofs_get_opts(opts, sizeof(opts), mp->am_autofs_fh);
} else
#endif /* HAVE_FS_AUTOFS */
{
preopts[0] = '\0';
#ifdef MNTTAB_OPT_INTR
strcat(preopts, MNTTAB_OPT_INTR);
strcat(preopts, ",");
xstrlcat(preopts, MNTTAB_OPT_INTR, sizeof(preopts));
xstrlcat(preopts, ",", sizeof(preopts));
#endif /* MNTTAB_OPT_INTR */
#ifdef MNTTAB_OPT_IGNORE
strcat(preopts, MNTTAB_OPT_IGNORE);
strcat(preopts, ",");
xstrlcat(preopts, MNTTAB_OPT_IGNORE, sizeof(preopts));
xstrlcat(preopts, ",", sizeof(preopts));
#endif /* MNTTAB_OPT_IGNORE */
sprintf(opts, "%s%s,%s=%d,%s=%d,%s=%d,%s,map=%s",
preopts,
MNTTAB_OPT_RW,
MNTTAB_OPT_PORT, nfs_port,
MNTTAB_OPT_TIMEO, gopt.amfs_auto_timeo,
MNTTAB_OPT_RETRANS, gopt.amfs_auto_retrans,
mnttype, mf->mf_info);
/* write most of the initial options + preopts */
xsnprintf(opts, sizeof(opts), "%s%s,%s=%d,%s,map=%s",
preopts,
MNTTAB_OPT_RW,
MNTTAB_OPT_PORT, nfs_port,
mf->mf_ops->fs_type, mf->mf_info);
/* process toplvl timeo/retrans options, if any */
if (gopt.amfs_auto_timeo[AMU_TYPE_TOPLVL] > 0) {
xsnprintf(toplvl_opts, sizeof(toplvl_opts), ",%s=%d",
MNTTAB_OPT_TIMEO, gopt.amfs_auto_timeo[AMU_TYPE_TOPLVL]);
xstrlcat(opts, toplvl_opts, sizeof(opts));
}
if (gopt.amfs_auto_retrans[AMU_TYPE_TOPLVL] > 0) {
xsnprintf(toplvl_opts, sizeof(toplvl_opts), ",%s=%d",
MNTTAB_OPT_RETRANS, gopt.amfs_auto_retrans[AMU_TYPE_TOPLVL]);
xstrlcat(opts, toplvl_opts, sizeof(opts));
}
#ifdef MNTTAB_OPT_NOAC
if (gopt.auto_attrcache == 0) {
xstrlcat(opts, ",", sizeof(opts));
xstrlcat(opts, MNTTAB_OPT_NOAC, sizeof(opts));
} else
#endif /* MNTTAB_OPT_NOAC */
set_auto_attrcache_timeout(preopts, opts, sizeof(preopts));
}
/* now do the mount */
error = mount_amfs_toplvl(mf->mf_mount, opts);
error = amfs_mount(mp, mf, opts);
if (error) {
errno = error;
plog(XLOG_FATAL, "amfs_toplvl_mount: mount_amfs_toplvl failed: %m");
plog(XLOG_FATAL, "amfs_toplvl_mount: amfs_mount failed: %m");
return error;
}
return 0;
}
void
amfs_toplvl_mounted(mntfs *mf)
{
amfs_auto_mkcacheref(mf);
}
/*
* Unmount a top-level automount node
*/
int
amfs_toplvl_umount(am_node *mp)
amfs_toplvl_umount(am_node *mp, mntfs *mf)
{
int error;
struct stat stb;
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
int error;
int count = 0; /* how many times did we try to unmount? */
again:
/*
@ -345,15 +271,48 @@ amfs_toplvl_umount(am_node *mp)
* actually fixed the problem - so simulate an ls -ld here.
*/
if (lstat(mp->am_path, &stb) < 0) {
#ifdef DEBUG
error = errno;
dlog("lstat(%s): %m", mp->am_path);
#endif /* DEBUG */
goto out;
}
error = UMOUNT_FS(mp->am_path, mnttab_file_name);
if ((stb.st_mode & S_IFMT) != S_IFDIR) {
plog(XLOG_ERROR, "amfs_toplvl_umount: %s is not a directory, aborting.", mp->am_path);
error = ENOTDIR;
goto out;
}
error = UMOUNT_FS(mp->am_path, mnttab_file_name, unmount_flags);
if (error == EBUSY) {
#ifdef HAVE_FS_AUTOFS
/*
* autofs mounts are "in place", so it is possible
* that we can't just unmount our mount points and go away.
* If that's the case, just give up.
*/
if (mf->mf_flags & MFF_IS_AUTOFS)
return error;
#endif /* HAVE_FS_AUTOFS */
plog(XLOG_WARNING, "amfs_toplvl_unmount retrying %s in 1s", mp->am_path);
sleep(1); /* XXX */
count++;
sleep(1);
/*
* If user wants forced/lazy unmount semantics, then set those flags,
* but only after we've tried normal lstat/umount a few times --
* otherwise forced unmounts may hang this very same Amd (by preventing
* it from achieving a clean unmount).
*/
if (gopt.flags & CFM_FORCED_UNMOUNTS) {
if (count == 5) { /* after 5 seconds, try MNT_FORCE */
dlog("enabling forced unmounts for toplvl node %s", mp->am_path);
unmount_flags |= AMU_UMOUNT_FORCE;
}
if (count == 10) { /* after 10 seconds, try MNT_DETACH */
dlog("enabling detached unmounts for toplvl node %s", mp->am_path);
unmount_flags |= AMU_UMOUNT_DETACH;
}
}
goto again;
}
out:
return error;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_union.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/amfs_union.c
*
*/
@ -55,6 +54,7 @@
/****************************************************************************
*** FORWARD DEFINITIONS ***
****************************************************************************/
static int create_amfs_union_node(char *dir, opaque_t arg);
static void amfs_union_mounted(mntfs *mf);
@ -64,19 +64,22 @@ static void amfs_union_mounted(mntfs *mf);
am_ops amfs_union_ops =
{
"union",
amfs_auto_match,
0, /* amfs_auto_init */
amfs_generic_match,
0, /* amfs_union_init */
amfs_toplvl_mount,
0,
amfs_toplvl_umount,
0,
amfs_auto_lookuppn,
amfs_auto_readdir,
0, /* amfs_toplvl_readlink */
amfs_generic_lookup_child,
amfs_generic_mount_child,
amfs_generic_readdir,
0, /* amfs_union_readlink */
amfs_union_mounted,
0, /* amfs_toplvl_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO | FS_DIRECTORY
0, /* amfs_union_umounted */
amfs_generic_find_srvr,
0, /* amfs_union_get_wchan */
FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO | FS_DIRECTORY,
#ifdef HAVE_FS_AUTOFS
AUTOFS_UNION_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
@ -85,11 +88,14 @@ am_ops amfs_union_ops =
* XXX: this function may not be used anywhere...
*/
static int
create_amfs_union_node(char *dir, voidp arg)
create_amfs_union_node(char *dir, opaque_t arg)
{
if (!STREQ(dir, "/defaults")) {
int error = 0;
(void) amfs_toplvl_ops.lookuppn(arg, dir, &error, VLOOK_CREATE);
am_node *am;
am = amfs_generic_lookup_child(arg, dir, &error, VLOOK_CREATE);
if (am && error < 0)
am = amfs_generic_mount_child(am, &error);
if (error > 0) {
errno = error; /* XXX */
plog(XLOG_ERROR, "unionfs: could not mount %s: %m", dir);
@ -103,20 +109,22 @@ create_amfs_union_node(char *dir, voidp arg)
static void
amfs_union_mounted(mntfs *mf)
{
int i;
int index;
am_node *mp;
amfs_auto_mkcacheref(mf);
amfs_mkcacheref(mf);
/*
* Having made the union mount point,
* populate all the entries...
*/
for (i = 0; i <= last_used_map; i++) {
am_node *mp = exported_ap[i];
if (mp && mp->am_mnt == mf) {
for (mp = get_first_exported_ap(&index);
mp;
mp = get_next_exported_ap(&index)) {
if (mp->am_mnt == mf) {
/* return value from create_amfs_union_node is ignored by mapc_keyiter */
(void) mapc_keyiter((mnt_map *) mp->am_mnt->mf_private,
(void (*)(char *, voidp)) create_amfs_union_node,
create_amfs_union_node,
mp);
break;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amq_svc.c,v 1.4.2.5 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/amq_svc.c
*
*/
@ -51,6 +50,65 @@
/* typedefs */
typedef char *(*amqsvcproc_t)(voidp, struct svc_req *);
#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
# ifdef NEED_LIBWRAP_SEVERITY_VARIABLES
/*
* Some systems that define libwrap already define these two variables
* in libwrap, while others don't: so I need to know precisely iff
* to define these two severity variables.
*/
int allow_severity=0, deny_severity=0;
# endif /* NEED_LIBWRAP_SEVERITY_VARIABLES */
/*
* check if remote amq is authorized to access this amd.
* Returns: 1=allowed, 0=denied.
*/
static int
amqsvc_is_client_allowed(const struct sockaddr_in *addr, char *remote)
{
struct hostent *h;
char *name = NULL, **ad;
int ret = 0; /* default is 0==denied */
/* Check IP address */
if (hosts_ctl(AMD_SERVICE_NAME, "", remote, "")) {
ret = 1;
goto out;
}
/* Get address */
if (!(h = gethostbyaddr((const char *)&(addr->sin_addr),
sizeof(addr->sin_addr),
AF_INET)))
goto out;
if (!(name = strdup(h->h_name)))
goto out;
/* Paranoia check */
if (!(h = gethostbyname(name)))
goto out;
for (ad = h->h_addr_list; *ad; ad++)
if (!memcmp(*ad, &(addr->sin_addr), h->h_length))
break;
if (!*ad)
goto out;
if (hosts_ctl(AMD_SERVICE_NAME, "", h->h_name, "")) {
return 1;
goto out;
}
/* Check aliases */
for (ad = h->h_aliases; *ad; ad++)
if (hosts_ctl(AMD_SERVICE_NAME, "", *ad, "")) {
return 1;
goto out;
}
out:
if (name)
XFREE(name);
return ret;
}
#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
void
amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
@ -64,6 +122,21 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
xdrproc_t xdr_argument, xdr_result;
amqsvcproc_t local;
#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
if (gopt.flags & CFM_USE_TCPWRAPPERS) {
struct sockaddr_in *remote_addr = svc_getcaller(rqstp->rq_xprt);
char *remote_hostname = inet_ntoa(remote_addr->sin_addr);
if (!amqsvc_is_client_allowed(remote_addr, remote_hostname)) {
plog(XLOG_WARNING, "Amd denied remote amq service to %s", remote_hostname);
svcerr_auth(transp, AUTH_FAILED);
return;
} else {
dlog("Amd allowed remote amq service to %s", remote_hostname);
}
}
#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
switch (rqstp->rq_proc) {
case AMQPROC_NULL:
@ -120,6 +193,12 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
local = (amqsvcproc_t) amqproc_getpid_1_svc;
break;
case AMQPROC_PAWD:
xdr_argument = (xdrproc_t) xdr_amq_string;
xdr_result = (xdrproc_t) xdr_amq_string;
local = (amqsvcproc_t) amqproc_pawd_1_svc;
break;
default:
svcerr_noproc(transp);
return;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: autil.c,v 1.4.2.6 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/autil.c
*
*/
@ -52,100 +51,49 @@
#include <am_defs.h>
#include <amd.h>
int NumChild = 0; /* number of children of primary amd */
int NumChildren = 0; /* number of children of primary amd */
static char invalid_keys[] = "\"'!;@ \t\n";
/****************************************************************************
*** MACROS ***
****************************************************************************/
#ifdef HAVE_TRANSPORT_TYPE_TLI
# define PARENT_USLEEP_TIME 100000 /* 0.1 seconds */
#endif /* HAVE_TRANSPORT_TYPE_TLI */
/****************************************************************************
*** FORWARD DEFINITIONS ***
****************************************************************************/
static void domain_strip(char *otherdom, char *localdom);
static int dofork(void);
/****************************************************************************
*** FUNCTIONS ***
****************************************************************************/
/*
* Copy s into p, reallocating p if necessary
*/
char *
strealloc(char *p, char *s)
{
int len = strlen(s) + 1;
size_t len = strlen(s) + 1;
p = (char *) xrealloc((voidp) p, len);
strcpy(p, s);
xstrlcpy(p, s, len);
#ifdef DEBUG_MEM
# if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY)
malloc_verify();
# endif /* not defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY) */
#endif /* DEBUG_MEM */
return p;
}
char **
strsplit(char *s, int ch, int qc)
{
char **ivec;
int ic = 0;
int done = 0;
ivec = (char **) xmalloc((ic + 1) * sizeof(char *));
while (!done) {
char *v;
/*
* skip to split char
*/
while (*s && (ch == ' ' ? (isascii(*s) && isspace((int)*s)) : *s == ch))
*s++ = '\0';
/*
* End of string?
*/
if (!*s)
break;
/*
* remember start of string
*/
v = s;
/*
* skip to split char
*/
while (*s && !(ch == ' ' ? (isascii(*s) && isspace((int)*s)) : *s == ch)) {
if (*s++ == qc) {
/*
* Skip past string.
*/
s++;
while (*s && *s != qc)
s++;
if (*s == qc)
s++;
}
}
if (!*s)
done = 1;
*s++ = '\0';
/*
* save string in new ivec slot
*/
ivec[ic++] = v;
ivec = (char **) xrealloc((voidp) ivec, (ic + 1) * sizeof(char *));
#ifdef DEBUG
amuDebug(D_STR)
plog(XLOG_DEBUG, "strsplit saved \"%s\"", v);
#endif /* DEBUG */
}
#ifdef DEBUG
amuDebug(D_STR)
plog(XLOG_DEBUG, "strsplit saved a total of %d strings", ic);
#endif /* DEBUG */
ivec[ic] = 0;
return ivec;
}
/*
* Strip off the trailing part of a domain
* to produce a short-form domain relative
@ -170,7 +118,8 @@ domain_strip(char *otherdom, char *localdom)
/*
* Normalize a host name
* Normalize a host name: replace cnames with real names, and decide if to
* strip domain name or not.
*/
void
host_normalize(char **chp)
@ -182,20 +131,18 @@ host_normalize(char **chp)
*/
if (gopt.flags & CFM_NORMALIZE_HOSTNAMES) {
struct hostent *hp;
clock_valid = 0;
hp = gethostbyname(*chp);
if (hp && hp->h_addrtype == AF_INET) {
#ifdef DEBUG
dlog("Hostname %s normalized to %s", *chp, hp->h_name);
#endif /* DEBUG */
*chp = strealloc(*chp, (char *) hp->h_name);
}
}
domain_strip(*chp, hostd);
if (gopt.flags & CFM_DOMAIN_STRIP) {
domain_strip(*chp, hostd);
}
}
/*
* Keys are not allowed to contain " ' ! or ; to avoid
* problems with macro expansions.
@ -226,14 +173,20 @@ forcibly_timeout_mp(am_node *mp)
} else {
plog(XLOG_INFO, "\"%s\" forcibly timed out", mp->am_path);
mp->am_flags &= ~AMF_NOTIMEOUT;
mp->am_ttl = clocktime();
mp->am_ttl = clocktime(NULL);
/*
* Force mtime update of parent dir, to prevent DNLC/dcache from caching
* the old entry, which could result in ESTALE errors, bad symlinks, and
* more.
*/
clocktime(&mp->am_parent->am_fattr.na_mtime);
reschedule_timeout_mp();
}
}
void
mf_mounted(mntfs *mf)
mf_mounted(mntfs *mf, bool_t call_free_opts)
{
int quoted;
int wasmounted = mf->mf_flags & MFF_MOUNTED;
@ -250,10 +203,33 @@ mf_mounted(mntfs *mf)
/*
* Do mounted callback
*/
if (mf->mf_ops->mounted) {
(*mf->mf_ops->mounted) (mf);
if (mf->mf_ops->mounted)
mf->mf_ops->mounted(mf);
/*
* Be careful when calling free_ops and XFREE here. Some pseudo file
* systems like nfsx call this function (mf_mounted), even though it
* would be called by the lower-level amd file system functions. nfsx
* needs to call this function because of the other actions it takes.
* So we pass a boolean from the caller (yes, not so clean workaround)
* to determine if we should free or not. If we're not freeing (often
* because we're called from a callback function), then just to be sure,
* we'll zero out the am_opts structure and set the pointer to NULL.
* The parent mntfs node owns this memory and is going to free it with a
* call to mf_mounted(mntfs,TRUE) (see comment in the am_mounted code).
*/
if (call_free_opts) {
free_opts(mf->mf_fo); /* this free is needed to prevent leaks */
XFREE(mf->mf_fo); /* (also this one) */
} else {
memset(mf->mf_fo, 0, sizeof(am_opts));
mf->mf_fo = NULL;
}
mf->mf_fo = 0;
}
if (mf->mf_flags & MFF_RESTART) {
mf->mf_flags &= ~MFF_RESTART;
dlog("Restarted filesystem %s, flags 0x%x", mf->mf_mount, mf->mf_flags);
}
/*
@ -272,40 +248,61 @@ mf_mounted(mntfs *mf)
void
am_mounted(am_node *mp)
{
int notimeout = 0; /* assume normal timeouts initially */
mntfs *mf = mp->am_mnt;
mf_mounted(mf);
/*
* This is the parent mntfs which does the mf->mf_fo (am_opts type), and
* we're passing TRUE here to tell mf_mounted to actually free the
* am_opts. See a related comment in mf_mounted().
*/
mf_mounted(mf, TRUE);
#ifdef HAVE_FS_AUTOFS
if (mf->mf_flags & MFF_IS_AUTOFS)
autofs_mounted(mp);
#endif /* HAVE_FS_AUTOFS */
/*
* Patch up path for direct mounts
*/
if (mp->am_parent && mp->am_parent->am_mnt->mf_ops == &amfs_direct_ops)
if (mp->am_parent && mp->am_parent->am_mnt->mf_fsflags & FS_DIRECT)
mp->am_path = str3cat(mp->am_path, mp->am_parent->am_path, "/", ".");
/*
* Check whether this mount should be cached permanently
* Check whether this mount should be cached permanently or not,
* and handle user-requested timeouts.
*/
if (mf->mf_ops->fs_flags & FS_NOTIMEOUT) {
/* first check if file system was set to never timeout */
if (mf->mf_fsflags & FS_NOTIMEOUT)
notimeout = 1;
/* next, alter that decision by map flags */
if (mf->mf_mopts) {
mntent_t mnt;
mnt.mnt_opts = mf->mf_mopts;
if (mf->mf_mopts && hasmntopt(&mnt, "unmount"))
mp->am_flags &= ~AMF_NOTIMEOUT;
/* umount option: user wants to unmount this entry */
if (amu_hasmntopt(&mnt, "unmount") || amu_hasmntopt(&mnt, "umount"))
notimeout = 0;
/* noumount option: user does NOT want to unmount this entry */
if (amu_hasmntopt(&mnt, "nounmount") || amu_hasmntopt(&mnt, "noumount"))
notimeout = 1;
/* utimeout=N option: user wants to unmount this option AND set timeout */
if ((mp->am_timeo = hasmntval(&mnt, "utimeout")) == 0)
mp->am_timeo = gopt.am_timeo; /* otherwise use default timeout */
else
mp->am_flags |= AMF_NOTIMEOUT;
} else if (mf->mf_mount[1] == '\0' && mf->mf_mount[0] == '/') {
notimeout = 0;
/* special case: don't try to unmount "/" (it can never succeed) */
if (mf->mf_mount[0] == '/' && mf->mf_mount[1] == '\0')
notimeout = 1;
}
/* finally set actual flags */
if (notimeout) {
mp->am_flags |= AMF_NOTIMEOUT;
plog(XLOG_INFO, "%s set to never timeout", mp->am_path);
} else {
mntent_t mnt;
if (mf->mf_mopts) {
mnt.mnt_opts = mf->mf_mopts;
if (hasmntopt(&mnt, "nounmount"))
mp->am_flags |= AMF_NOTIMEOUT;
if (hasmntopt(&mnt, "unmount"))
mp->am_flags &= ~AMF_NOTIMEOUT;
if ((mp->am_timeo = hasmntval(&mnt, "utimeout")) == 0)
mp->am_timeo = gopt.am_timeo;
}
mp->am_flags &= ~AMF_NOTIMEOUT;
plog(XLOG_INFO, "%s set to timeout in %d seconds", mp->am_path, mp->am_timeo);
}
/*
@ -313,25 +310,38 @@ am_mounted(am_node *mp)
* compute the length of the returned string.
*/
if (mp->am_fattr.na_type == NFLNK)
mp->am_fattr.na_size = strlen(mp->am_link ? mp->am_link : mp->am_mnt->mf_mount);
mp->am_fattr.na_size = strlen(mp->am_link ? mp->am_link : mf->mf_mount);
/*
* Record mount time
* Record mount time, and update am_stats at the same time.
*/
mp->am_fattr.na_mtime.nt_seconds = mp->am_stats.s_mtime = clocktime();
mp->am_stats.s_mtime = clocktime(&mp->am_fattr.na_mtime);
new_ttl(mp);
/*
* Update mtime of parent node
* Update mtime of parent node (copying "struct nfstime" in '=' below)
*/
if (mp->am_parent && mp->am_parent->am_mnt)
mp->am_parent->am_fattr.na_mtime.nt_seconds = mp->am_stats.s_mtime;
mp->am_parent->am_fattr.na_mtime = mp->am_fattr.na_mtime;
/*
* Now, if we can, do a reply to our NFS client here
* This is ugly, but essentially unavoidable
* Sublinks must be treated separately as type==link
* when the base type is different.
*/
if (mp->am_link && mf->mf_ops != &amfs_link_ops)
amfs_link_ops.mount_fs(mp, mf);
/*
* Now, if we can, do a reply to our client here
* to speed things up.
*/
quick_reply(mp, 0);
#ifdef HAVE_FS_AUTOFS
if (mp->am_flags & AMF_AUTOFS)
autofs_mount_succeeded(mp);
else
#endif /* HAVE_FS_AUTOFS */
nfs_quick_reply(mp, 0);
/*
* Update stats
@ -340,21 +350,303 @@ am_mounted(am_node *mp)
}
int
mount_node(am_node *mp)
/*
* Replace mount point with a reference to an error filesystem.
* The mount point (struct mntfs) is NOT discarded,
* the caller must do it if it wants to _before_ calling this function.
*/
void
assign_error_mntfs(am_node *mp)
{
mntfs *mf = mp->am_mnt;
int error = 0;
int error;
dlog("assign_error_mntfs");
/*
* Save the old error code
*/
error = mp->am_error;
if (error <= 0)
error = mp->am_mnt->mf_error;
/*
* Allocate a new error reference
*/
mp->am_mnt = new_mntfs();
/*
* Put back the error code
*/
mp->am_mnt->mf_error = error;
mp->am_mnt->mf_flags |= MFF_ERROR;
/*
* Zero the error in the mount point
*/
mp->am_error = 0;
}
mf->mf_flags |= MFF_MOUNTING;
error = (*mf->mf_ops->mount_fs) (mp);
mf = mp->am_mnt;
if (error >= 0)
mf->mf_flags &= ~MFF_MOUNTING;
if (!error && !(mf->mf_ops->fs_flags & FS_MBACKGROUND)) {
/* ...but see ifs_mount */
am_mounted(mp);
/*
* Build a new map cache for this node, or re-use
* an existing cache for the same map.
*/
void
amfs_mkcacheref(mntfs *mf)
{
char *cache;
if (mf->mf_fo && mf->mf_fo->opt_cache)
cache = mf->mf_fo->opt_cache;
else
cache = "none";
mf->mf_private = (opaque_t) mapc_find(mf->mf_info,
cache,
(mf->mf_fo ? mf->mf_fo->opt_maptype : NULL));
mf->mf_prfree = mapc_free;
}
/*
* Locate next node in sibling list which is mounted
* and is not an error node.
*/
am_node *
next_nonerror_node(am_node *xp)
{
mntfs *mf;
/*
* Bug report (7/12/89) from Rein Tollevik <rein@ifi.uio.no>
* Fixes a race condition when mounting direct automounts.
* Also fixes a problem when doing a readdir on a directory
* containing hung automounts.
*/
while (xp &&
(!(mf = xp->am_mnt) || /* No mounted filesystem */
mf->mf_error != 0 || /* There was a mntfs error */
xp->am_error != 0 || /* There was a mount error */
!(mf->mf_flags & MFF_MOUNTED) || /* The fs is not mounted */
(mf->mf_server->fs_flags & FSF_DOWN)) /* The fs may be down */
)
xp = xp->am_osib;
return xp;
}
/*
* Mount an automounter directory.
* The automounter is connected into the system
* as a user-level NFS server. amfs_mount constructs
* the necessary NFS parameters to be given to the
* kernel so that it will talk back to us.
*
* NOTE: automounter mounts in themselves are using NFS Version 2 (UDP).
*
* NEW: on certain systems, mounting can be done using the
* kernel-level automount (autofs) support. In that case,
* we don't need NFS at all here.
*/
int
amfs_mount(am_node *mp, mntfs *mf, char *opts)
{
char fs_hostname[MAXHOSTNAMELEN + MAXPATHLEN + 1];
int retry, error = 0, genflags;
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
char *dir = mf->mf_mount;
mntent_t mnt;
MTYPE_TYPE type;
int forced_unmount = 0; /* are we using forced unmounts? */
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
mnt.mnt_fsname = pid_fsname;
mnt.mnt_opts = opts;
#ifdef HAVE_FS_AUTOFS
if (mf->mf_flags & MFF_IS_AUTOFS) {
type = MOUNT_TYPE_AUTOFS;
/*
* Make sure that amd's top-level autofs mounts are hidden by default
* from df.
* XXX: It works ok on Linux, might not work on other systems.
*/
mnt.mnt_type = "autofs";
} else
#endif /* HAVE_FS_AUTOFS */
{
type = MOUNT_TYPE_NFS;
/*
* Make sure that amd's top-level NFS mounts are hidden by default
* from df.
* If they don't appear to support the either the "ignore" mnttab
* option entry, or the "auto" one, set the mount type to "nfs".
*/
mnt.mnt_type = HIDE_MOUNT_TYPE;
}
retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
if (retry <= 0)
retry = 2; /* XXX: default to 2 retries */
/*
* SET MOUNT ARGS
*/
/*
* Make a ``hostname'' string for the kernel
*/
xsnprintf(fs_hostname, sizeof(fs_hostname), "pid%ld@%s:%s",
get_server_pid(), am_get_hostname(), dir);
/*
* Most kernels have a name length restriction (64 bytes)...
*/
if (strlen(fs_hostname) >= MAXHOSTNAMELEN)
xstrlcpy(fs_hostname + MAXHOSTNAMELEN - 3, "..",
sizeof(fs_hostname) - MAXHOSTNAMELEN + 3);
#ifdef HOSTNAMESZ
/*
* ... and some of these restrictions are 32 bytes (HOSTNAMESZ)
* If you need to get the definition for HOSTNAMESZ found, you may
* add the proper header file to the conf/nfs_prot/nfs_prot_*.h file.
*/
if (strlen(fs_hostname) >= HOSTNAMESZ)
xstrlcpy(fs_hostname + HOSTNAMESZ - 3, "..",
sizeof(fs_hostname) - HOSTNAMESZ + 3);
#endif /* HOSTNAMESZ */
/*
* Finally we can compute the mount genflags set above,
* and add any automounter specific flags.
*/
genflags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
if (on_autofs)
genflags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */
genflags |= compute_automounter_mount_flags(&mnt);
again:
if (!(mf->mf_flags & MFF_IS_AUTOFS)) {
nfs_args_t nfs_args;
am_nfs_fh *fhp;
am_nfs_handle_t anh;
#ifndef HAVE_TRANSPORT_TYPE_TLI
u_short port;
struct sockaddr_in sin;
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/*
* get fhandle of remote path for automount point
*/
fhp = get_root_nfs_fh(dir);
if (!fhp) {
plog(XLOG_FATAL, "Can't find root file handle for %s", dir);
return EINVAL;
}
#ifndef HAVE_TRANSPORT_TYPE_TLI
/*
* Create sockaddr to point to the local machine.
*/
memset((voidp) &sin, 0, sizeof(sin));
/* as per POSIX, sin_len need not be set (used internally by kernel) */
sin.sin_family = AF_INET;
sin.sin_addr = myipaddr;
port = hasmntval(&mnt, MNTTAB_OPT_PORT);
if (port) {
sin.sin_port = htons(port);
} else {
plog(XLOG_ERROR, "no port number specified for %s", dir);
return EINVAL;
}
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/* setup the many fields and flags within nfs_args */
memmove(&anh.v2, fhp, sizeof(*fhp));
#ifdef HAVE_TRANSPORT_TYPE_TLI
compute_nfs_args(&nfs_args,
&mnt,
genflags,
nfsncp,
NULL, /* remote host IP addr is set below */
NFS_VERSION, /* version 2 */
"udp",
&anh,
fs_hostname,
pid_fsname);
/*
* IMPORTANT: set the correct IP address AFTERWARDS. It cannot
* be done using the normal mechanism of compute_nfs_args(), because
* that one will allocate a new address and use NFS_SA_DREF() to copy
* parts to it, while assuming that the ip_addr passed is always
* a "struct sockaddr_in". That assumption is incorrect on TLI systems,
* because they define a special macro HOST_SELF which is DIFFERENT
* than localhost (127.0.0.1)!
*/
nfs_args.addr = &nfsxprt->xp_ltaddr;
#else /* not HAVE_TRANSPORT_TYPE_TLI */
compute_nfs_args(&nfs_args,
&mnt,
genflags,
NULL,
&sin,
NFS_VERSION, /* version 2 */
"udp",
&anh,
fs_hostname,
pid_fsname);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/*************************************************************************
* NOTE: while compute_nfs_args() works ok for regular NFS mounts *
* the toplvl one is not quite regular, and so some options must be *
* corrected by hand more carefully, *after* compute_nfs_args() runs. *
*************************************************************************/
compute_automounter_nfs_args(&nfs_args, &mnt);
if (amuDebug(D_TRACE)) {
print_nfs_args(&nfs_args, 0);
plog(XLOG_DEBUG, "Generic mount flags 0x%x", genflags);
}
/* This is it! Here we try to mount amd on its mount points */
error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args,
retry, type, 0, NULL, mnttab_file_name, on_autofs);
#ifdef HAVE_TRANSPORT_TYPE_TLI
free_knetconfig(nfs_args.knconf);
/*
* local automounter mounts do not allocate a special address, so
* no need to XFREE(nfs_args.addr) under TLI.
*/
#endif /* HAVE_TRANSPORT_TYPE_TLI */
#ifdef HAVE_FS_AUTOFS
} else {
/* This is it! Here we try to mount amd on its mount points */
error = mount_fs(&mnt, genflags, (caddr_t) mp->am_autofs_fh,
retry, type, 0, NULL, mnttab_file_name, on_autofs);
#endif /* HAVE_FS_AUTOFS */
}
if (error == 0 || forced_unmount)
return error;
/*
* If user wants forced/lazy unmount semantics, then try it iff the
* current mount failed with EIO or ESTALE.
*/
if (gopt.flags & CFM_FORCED_UNMOUNTS) {
switch (errno) {
case ESTALE:
case EIO:
forced_unmount = errno;
plog(XLOG_WARNING, "Mount %s failed (%m); force unmount.", mp->am_path);
if ((error = UMOUNT_FS(mp->am_path, mnttab_file_name,
AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH)) < 0) {
plog(XLOG_WARNING, "Forced umount %s failed: %m.", mp->am_path);
errno = forced_unmount;
} else
goto again;
default:
break;
}
}
return error;
@ -373,15 +665,79 @@ am_unmounted(am_node *mp)
* Do unmounted callback
*/
if (mf->mf_ops->umounted)
(*mf->mf_ops->umounted) (mp);
mf->mf_ops->umounted(mf);
/*
* This is ugly, but essentially unavoidable.
* Sublinks must be treated separately as type==link
* when the base type is different.
*/
if (mp->am_link && mf->mf_ops != &amfs_link_ops)
amfs_link_ops.umount_fs(mp, mf);
#ifdef HAVE_FS_AUTOFS
if (mf->mf_flags & MFF_IS_AUTOFS)
autofs_release_fh(mp);
if (mp->am_flags & AMF_AUTOFS)
autofs_umount_succeeded(mp);
#endif /* HAVE_FS_AUTOFS */
/*
* Clean up any directories that were made
*
* If we remove the mount point of a pending mount, any queued access
* to it will fail. So don't do it in that case.
* Also don't do it if the refcount is > 1.
*/
if (mf->mf_flags & MFF_MKMNT &&
mf->mf_refc == 1 &&
!(mp->am_flags & AMF_REMOUNT)) {
plog(XLOG_INFO, "removing mountpoint directory '%s'", mf->mf_mount);
rmdirs(mf->mf_mount);
mf->mf_flags &= ~MFF_MKMNT;
}
/*
* If this is a pseudo-directory then adjust the link count
* in the parent
*/
if (mp->am_parent && mp->am_fattr.na_type == NFDIR)
--mp->am_parent->am_fattr.na_nlink;
/*
* Update mtime of parent node
*/
if (mp->am_parent && mp->am_parent->am_mnt)
mp->am_parent->am_fattr.na_mtime.nt_seconds = clocktime();
clocktime(&mp->am_parent->am_fattr.na_mtime);
free_map(mp);
if (mp->am_parent && (mp->am_flags & AMF_REMOUNT)) {
char *fname = strdup(mp->am_name);
am_node *mp_parent = mp->am_parent;
mntfs *mf_parent = mp_parent->am_mnt;
int error = 0;
free_map(mp);
plog(XLOG_INFO, "am_unmounted: remounting %s", fname);
mp = mf_parent->mf_ops->lookup_child(mp_parent, fname, &error, VLOOK_CREATE);
if (mp && error < 0)
mp = mf_parent->mf_ops->mount_child(mp, &error);
if (error > 0) {
errno = error;
plog(XLOG_ERROR, "am_unmounted: could not remount %s: %m", fname);
}
XFREE(fname);
} else
/*
* We have a race here.
* If this node has a pending mount and amd is going down (unmounting
* everything in the process), then we could potentially free it here
* while a struct continuation still has a reference to it. So when
* amfs_cont is called, it blows up.
* We avoid the race by refusing to free any nodes that have
* pending mounts (defined as having a non-NULL am_mfarray).
*/
if (!mp->am_mfarray)
free_map(mp);
}
@ -406,7 +762,7 @@ dofork(void)
am_set_mypid();
foreground = 0;
} else { /* parent process, has one more child */
NumChild++;
NumChildren++;
}
return pid;
@ -419,10 +775,9 @@ background(void)
int pid = dofork();
if (pid == 0) {
#ifdef DEBUG
dlog("backgrounded");
#endif /* DEBUG */
foreground = 0;
}
} else
dlog("forked process %d", pid);
return pid;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: clock.c,v 1.4.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/clock.c
*
*/
@ -59,14 +58,13 @@
#include <am_defs.h>
#include <amd.h>
int timeout(u_int secs, void (*fn) (voidp), voidp closure);
void reschedule_timeouts(time_t now, time_t then);
typedef struct callout callout;
struct callout {
callout *c_next; /* List of callouts */
void (*c_fn) (voidp); /* Function to call */
voidp c_closure; /* Closure to pass to call */
callout_fun *c_fn; /* Function to call */
opaque_t c_arg; /* Argument to pass to call */
time_t c_time; /* Time of call */
int c_id; /* Unique identifier */
};
@ -87,7 +85,7 @@ time_t next_softclock; /* Time of next call to softclock() */
/*
* Global assumption: valid id's are non-zero.
*/
#define CID_ALLOC(struct ) (++callout_id)
#define CID_ALLOC() (++callout_id)
#define CID_UNDEF (0)
@ -121,22 +119,22 @@ free_callout(callout *cp)
/*
* Schedule a callout.
*
* (*fn)(closure) will be called at clocktime() + secs
* (*fn)(fn_arg) will be called at clocktime(NULL) + secs
*/
int
timeout(u_int secs, void (*fn) (voidp), voidp closure)
timeout(u_int secs, callout_fun *fn, opaque_t fn_arg)
{
callout *cp, *cp2;
time_t t = clocktime() + secs;
time_t t = clocktime(NULL) + secs;
/*
* Allocate and fill in a new callout structure
*/
callout *cpnew = alloc_callout();
cpnew->c_closure = closure;
cpnew->c_arg = fn_arg;
cpnew->c_fn = fn;
cpnew->c_time = t;
cpnew->c_id = CID_ALLOC(struct );
cpnew->c_id = CID_ALLOC();
if (t < next_softclock)
next_softclock = t;
@ -189,10 +187,8 @@ reschedule_timeouts(time_t now, time_t then)
for (cp = callouts.c_next; cp; cp = cp->c_next) {
if (cp->c_time >= now && cp->c_time <= then) {
plog(XLOG_WARNING, "job %d rescheduled to run immediately", cp->c_id);
#ifdef DEBUG
dlog("rescheduling job %d back %ld seconds",
cp->c_id, (long) (cp->c_time - now));
#endif /* DEBUG */
next_softclock = cp->c_time = now;
}
}
@ -212,14 +208,14 @@ softclock(void)
if (task_notify_todo)
do_task_notify();
now = clocktime();
now = clocktime(NULL);
/*
* While there are more callouts waiting...
*/
while ((cp = callouts.c_next) && cp->c_time <= now) {
/*
* Extract first from list, save fn & closure and
* Extract first from list, save fn & fn_arg and
* unlink callout from list and free.
* Finally call function.
*
@ -228,12 +224,12 @@ softclock(void)
* function will call timeout()
* and try to allocate a callout
*/
void (*fn) (voidp) = cp->c_fn;
voidp closure = cp->c_closure;
callout_fun *fn = cp->c_fn;
opaque_t fn_arg = cp->c_arg;
callouts.c_next = cp->c_next;
free_callout(cp);
(*fn) (closure);
(*fn) (fn_arg);
}
} while (task_notify_todo);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: conf.c,v 1.7.2.8 2004/01/21 04:04:58 ib42 Exp $
* File: am-utils/amd/conf.c
*
*/
@ -76,12 +75,18 @@ struct _func_map {
* FORWARD DECLARATIONS:
*/
static int gopt_arch(const char *val);
static int gopt_auto_attrcache(const char *val);
static int gopt_auto_dir(const char *val);
static int gopt_autofs_use_lofs(const char *val);
static int gopt_browsable_dirs(const char *val);
static int gopt_cache_duration(const char *val);
static int gopt_cluster(const char *val);
static int gopt_debug_mtab_file(const char *val);
static int gopt_debug_options(const char *val);
static int gopt_dismount_interval(const char *val);
static int gopt_domain_strip(const char *val);
static int gopt_exec_map_timeout(const char *val);
static int gopt_forced_unmounts(const char *val);
static int gopt_full_os(const char *val);
static int gopt_fully_qualified_hosts(const char *val);
static int gopt_hesiod_base(const char *val);
@ -90,21 +95,34 @@ static int gopt_ldap_base(const char *val);
static int gopt_ldap_cache_maxmem(const char *val);
static int gopt_ldap_cache_seconds(const char *val);
static int gopt_ldap_hostports(const char *val);
static int gopt_ldap_proto_version(const char *val);
static int gopt_local_domain(const char *val);
static int gopt_localhost_address(const char *val);
static int gopt_log_file(const char *val);
static int gopt_log_options(const char *val);
static int gopt_map_defaults(const char *val);
static int gopt_map_options(const char *val);
static int gopt_map_reload_interval(const char *val);
static int gopt_map_type(const char *val);
static int gopt_mount_type(const char *val);
static int gopt_pid_file(const char *val);
static int gopt_portmap_program(const char *val);
static int gopt_preferred_amq_port(const char *val);
static int gopt_nfs_allow_any_interface(const char *val);
static int gopt_nfs_allow_insecure_port(const char *val);
static int gopt_nfs_proto(const char *val);
static int gopt_nfs_retransmit_counter(const char *val);
static int gopt_nfs_retransmit_counter_udp(const char *val);
static int gopt_nfs_retransmit_counter_tcp(const char *val);
static int gopt_nfs_retransmit_counter_toplvl(const char *val);
static int gopt_nfs_retry_interval(const char *val);
static int gopt_nfs_retry_interval_udp(const char *val);
static int gopt_nfs_retry_interval_tcp(const char *val);
static int gopt_nfs_retry_interval_toplvl(const char *val);
static int gopt_nfs_vers(const char *val);
static int gopt_nis_domain(const char *val);
static int gopt_normalize_hostnames(const char *val);
static int gopt_normalize_slashes(const char *val);
static int gopt_os(const char *val);
static int gopt_osver(const char *val);
static int gopt_plock(const char *val);
@ -114,33 +132,43 @@ static int gopt_restart_mounts(const char *val);
static int gopt_search_path(const char *val);
static int gopt_selectors_in_defaults(const char *val);
static int gopt_show_statfs_entries(const char *val);
static int gopt_truncate_log(const char *val);
static int gopt_unmount_on_exit(const char *val);
static int gopt_use_tcpwrappers(const char *val);
static int gopt_vendor(const char *val);
static int process_global_option(const char *key, const char *val);
static int process_regular_map(cf_map_t *cfm);
static int process_one_regular_map(const cf_map_t *cfm);
static int process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm);
static int ropt_browsable_dirs(const char *val, cf_map_t *cfm);
static int ropt_map_name(const char *val, cf_map_t *cfm);
static int ropt_map_defaults(const char *val, cf_map_t *cfm);
static int ropt_map_options(const char *val, cf_map_t *cfm);
static int ropt_map_type(const char *val, cf_map_t *cfm);
static int ropt_mount_type(const char *val, cf_map_t *cfm);
static int ropt_search_path(const char *val, cf_map_t *cfm);
static int ropt_tag(const char *val, cf_map_t *cfm);
static void reset_cf_map(cf_map_t *cfm);
static void init_cf_map(cf_map_t *cfm);
/*
* STATIC VARIABLES:
*/
static cf_map_t cur_map;
static cf_map_t *head_map, *cur_map;
static struct _func_map glob_functable[] = {
{"arch", gopt_arch},
{"auto_attrcache", gopt_auto_attrcache},
{"auto_dir", gopt_auto_dir},
{"autofs_use_lofs", gopt_autofs_use_lofs},
{"browsable_dirs", gopt_browsable_dirs},
{"cache_duration", gopt_cache_duration},
{"cluster", gopt_cluster},
{"debug_mtab_file", gopt_debug_mtab_file},
{"debug_options", gopt_debug_options},
{"dismount_interval", gopt_dismount_interval},
{"domain_strip", gopt_domain_strip},
{"exec_map_timeout", gopt_exec_map_timeout},
{"forced_unmounts", gopt_forced_unmounts},
{"fully_qualified_hosts", gopt_fully_qualified_hosts},
{"full_os", gopt_full_os},
{"hesiod_base", gopt_hesiod_base},
@ -149,21 +177,34 @@ static struct _func_map glob_functable[] = {
{"ldap_cache_maxmem", gopt_ldap_cache_maxmem},
{"ldap_cache_seconds", gopt_ldap_cache_seconds},
{"ldap_hostports", gopt_ldap_hostports},
{"ldap_proto_version", gopt_ldap_proto_version},
{"local_domain", gopt_local_domain},
{"localhost_address", gopt_localhost_address},
{"log_file", gopt_log_file},
{"log_options", gopt_log_options},
{"map_defaults", gopt_map_defaults},
{"map_options", gopt_map_options},
{"map_reload_interval", gopt_map_reload_interval},
{"map_type", gopt_map_type},
{"mount_type", gopt_mount_type},
{"pid_file", gopt_pid_file},
{"portmap_program", gopt_portmap_program},
{"preferred_amq_port", gopt_preferred_amq_port},
{"nfs_allow_any_interface", gopt_nfs_allow_any_interface},
{"nfs_allow_insecure_port", gopt_nfs_allow_insecure_port},
{"nfs_proto", gopt_nfs_proto},
{"nfs_retransmit_counter", gopt_nfs_retransmit_counter},
{"nfs_retransmit_counter_udp", gopt_nfs_retransmit_counter_udp},
{"nfs_retransmit_counter_tcp", gopt_nfs_retransmit_counter_tcp},
{"nfs_retransmit_counter_toplvl", gopt_nfs_retransmit_counter_toplvl},
{"nfs_retry_interval", gopt_nfs_retry_interval},
{"nfs_retry_interval_udp", gopt_nfs_retry_interval_udp},
{"nfs_retry_interval_tcp", gopt_nfs_retry_interval_tcp},
{"nfs_retry_interval_toplvl", gopt_nfs_retry_interval_toplvl},
{"nfs_vers", gopt_nfs_vers},
{"nis_domain", gopt_nis_domain},
{"normalize_hostnames", gopt_normalize_hostnames},
{"normalize_slashes", gopt_normalize_slashes},
{"os", gopt_os},
{"osver", gopt_osver},
{"plock", gopt_plock},
@ -174,61 +215,43 @@ static struct _func_map glob_functable[] = {
{"selectors_on_default", gopt_selectors_in_defaults},
{"selectors_in_defaults", gopt_selectors_in_defaults},
{"show_statfs_entries", gopt_show_statfs_entries},
{"truncate_log", gopt_truncate_log},
{"unmount_on_exit", gopt_unmount_on_exit},
{"use_tcpwrappers", gopt_use_tcpwrappers},
{"vendor", gopt_vendor},
{NULL, NULL}
};
/*
* Reset a map.
* Initialize a map from [global] defaults.
*/
static void
reset_cf_map(cf_map_t *cfm)
init_cf_map(cf_map_t *cfm)
{
if (!cfm)
return;
if (cfm->cfm_dir) {
XFREE(cfm->cfm_dir);
cfm->cfm_dir = NULL;
}
if (cfm->cfm_name) {
XFREE(cfm->cfm_name);
cfm->cfm_name = NULL;
}
if (cfm->cfm_tag) {
XFREE(cfm->cfm_tag);
cfm->cfm_tag = NULL;
}
/*
* reset/initialize a regular map's flags and other variables from the
* Initialize a regular map's flags and other variables from the
* global ones, so that they are applied to all maps. Of course, each map
* can then override the flags individually.
*
* NOTES:
* (1): Will only work for maps that appear after [global].
* (2): Also be careful not to free() a global option.
* (3): I'm doing direct char* pointer comparison, and not strcmp(). This
* is correct!
* (2): I'm assigning pointers directly from the global map.
*/
/* initialize map_type from [global] */
if (cfm->cfm_type && cfm->cfm_type != gopt.map_type)
XFREE(cfm->cfm_type);
cfm->cfm_type = gopt.map_type;
/* initialize map_defaults from [global] */
cfm->cfm_defaults = gopt.map_defaults;
/* initialize map_opts from [global] */
if (cfm->cfm_opts && cfm->cfm_opts != gopt.map_options)
XFREE(cfm->cfm_opts);
cfm->cfm_opts = gopt.map_options;
/* initialize search_path from [global] */
if (cfm->cfm_search_path && cfm->cfm_search_path != gopt.search_path)
XFREE(cfm->cfm_search_path);
cfm->cfm_search_path = gopt.search_path;
/*
@ -242,7 +265,7 @@ reset_cf_map(cf_map_t *cfm)
/*
* Process configuration file options.
* Process configuration file options (called from YACC parser).
* Return 0 if OK, 1 otherwise.
*/
int
@ -251,50 +274,67 @@ set_conf_kv(const char *section, const char *key, const char *val)
int ret;
#ifdef DEBUG_CONF
fprintf(stderr,"set_conf_kv: section=%s, key=%s, val=%s\n",
fprintf(stderr, "set_conf_kv: section=%s, key=%s, val=%s\n",
section, key, val);
#endif /* DEBUG_CONF */
/*
* If global section, process them one at a time.
* If global section, process kv pairs one at a time.
*/
if (STREQ(section, "global")) {
/*
* Check if a regular map was configured before "global",
* and process it as needed.
* and warn about it.
*/
if (cur_map.cfm_dir) {
fprintf(stderr,"processing regular map \"%s\" before global one.\n",
section);
ret = process_regular_map(&cur_map); /* will reset map */
if (ret != 0)
return ret;
if (cur_map && cur_map->cfm_dir) {
static short printed_this_error;
if (!printed_this_error) {
fprintf(stderr, "found regular map \"%s\" before global one.\n",
cur_map->cfm_dir);
printed_this_error = 1;
}
}
/* process the global option first */
ret = process_global_option(key, val);
/* reset default options for regular maps from just updated globals */
if (ret == 0)
reset_cf_map(&cur_map);
/* return status from the processing of the global option */
return ret;
}
/*
* otherwise save options and process a single map all at once.
* Otherwise we found a non-global option: store it after some testing.
*/
/* check if we found a new map, so process one already collected */
if (cur_map.cfm_dir && !STREQ(cur_map.cfm_dir, section)) {
ret = process_regular_map(&cur_map); /* will reset map */
if (ret != 0)
return ret;
/* initialize (static) global list head and current map pointer */
if (!head_map && !cur_map) {
cur_map = CALLOC(cf_map_t);
if (!cur_map) {
perror("calloc");
exit(1);
}
/* initialize first head map from global defaults */
init_cf_map(cur_map);
head_map = cur_map;
}
/* check if we found a new map, then allocate and initialize it */
if (cur_map->cfm_dir && !STREQ(cur_map->cfm_dir, section)) {
/* allocate new map struct */
cf_map_t *tmp_map = CALLOC(cf_map_t);
if (!tmp_map) {
perror("calloc");
exit(1);
}
/* initialize it from global defaults */
init_cf_map(tmp_map);
/* append it to end of linked list */
cur_map->cfm_next = tmp_map;
cur_map = tmp_map;
}
/* now process a single entry of a regular map */
return process_regular_option(section, key, val, &cur_map);
return process_regular_option(section, key, val, cur_map);
}
@ -331,6 +371,18 @@ gopt_arch(const char *val)
}
static int
gopt_auto_attrcache(const char *val)
{
gopt.auto_attrcache = atoi(val);
if (gopt.auto_attrcache < 0) {
fprintf(stderr, "conf: bad attrcache value: \"%s\"\n", val);
return 1;
}
return 0;
}
static int
gopt_auto_dir(const char *val)
{
@ -339,6 +391,22 @@ gopt_auto_dir(const char *val)
}
static int
gopt_autofs_use_lofs(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_AUTOFS_USE_LOFS;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_AUTOFS_USE_LOFS;
return 0;
}
fprintf(stderr, "conf: unknown value to autofs_use_lofs \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_browsable_dirs(const char *val)
{
@ -376,11 +444,19 @@ gopt_cluster(const char *val)
}
static int
gopt_debug_mtab_file(const char *val)
{
gopt.debug_mtab_file = strdup((char*)val);
return 0;
}
static int
gopt_debug_options(const char *val)
{
#ifdef DEBUG
usage += debug_option(strdup((char *)val));
usage += debug_option((char *)val);
return 0;
#else /* not DEBUG */
fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n",
@ -400,6 +476,74 @@ gopt_dismount_interval(const char *val)
}
static int
gopt_domain_strip(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_DOMAIN_STRIP;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_DOMAIN_STRIP;
return 0;
}
fprintf(stderr, "conf: unknown value to domain_strip \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_exec_map_timeout(const char *val)
{
gopt.exec_map_timeout = atoi(val);
if (gopt.exec_map_timeout <= 0)
gopt.exec_map_timeout = AMFS_EXEC_MAP_TIMEOUT; /* default exec map timeout */
return 0;
}
static int
gopt_forced_unmounts(const char *val)
{
if (STREQ(val, "yes")) {
#if !defined(MNT2_GEN_OPT_DETACH) && !defined(MNT2_GEN_OPT_FORCE)
fprintf(stderr, "conf: forced_unmounts unsupported on this system.\n");
return 1;
#else /* defined(MNT2_GEN_OPT_DETACH) || defined(MNT2_GEN_OPT_FORCE) */
# ifdef __linux__
/*
* HACK ALERT: Linux has had MNT_FORCE since 2.2, but it hasn't gotten
* stable until 2.4. And it had MNT_DETACH since 2.4, but it hasn't
* gotten stable since 2.6. So alert users if they're trying to use a
* feature that may not work well on their older kernel.
*/
{
struct utsname un;
if (uname(&un) >= 0) {
# ifdef MNT2_GEN_OPT_FORCE
if (strcmp(un.release, "2.4.0") < 0)
fprintf(stderr, "warning: forced-unmounts (MNT_FORCE) may not work well before 2.4.0\n");
# endif /* MNT2_GEN_OPT_FORCE */
# ifdef MNT2_GEN_OPT_DETACH
if (strcmp(un.release, "2.6.0") < 0)
fprintf(stderr, "warning: lazy-unmounts (MNT_DETACH) may not work well before 2.6.0\n");
# endif /* MNT2_GEN_OPT_DETACH */
}
}
# endif /* __linux__ */
gopt.flags |= CFM_FORCED_UNMOUNTS;
return 0;
#endif /* defined(MNT2_GEN_OPT_DETACH) || defined(MNT2_GEN_OPT_FORCE) */
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_FORCED_UNMOUNTS;
return 0;
}
fprintf(stderr, "conf: unknown value to unmount_on_exit \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_full_os(const char *val)
{
@ -461,6 +605,14 @@ gopt_local_domain(const char *val)
}
static int
gopt_localhost_address(const char *val)
{
gopt.localhost_address = strdup((char *)val);
return 0;
}
static int
gopt_ldap_base(const char *val)
{
@ -526,6 +678,44 @@ gopt_ldap_hostports(const char *val)
}
static int
gopt_ldap_proto_version(const char *val)
{
#ifdef HAVE_MAP_LDAP
char *end;
gopt.ldap_proto_version = strtol((char *)val, &end, 10);
if (end == val) {
fprintf(stderr, "conf: bad ldap_proto_version option: %s\n",val);
return 1;
}
if (gopt.ldap_proto_version < 0 || gopt.ldap_proto_version > LDAP_VERSION_MAX) {
fprintf(stderr, "conf: bad ldap_proto_version option value: %s\n",val);
return 1;
}
switch (gopt.ldap_proto_version) {
/* XXX: what about LDAP_VERSION1? */
case LDAP_VERSION2:
#ifdef LDAP_VERSION3
case LDAP_VERSION3:
#endif /* LDAP_VERSION3 */
#ifdef LDAP_VERSION4
case LDAP_VERSION4:
#endif /* LDAP_VERSION4 */
break;
default:
fprintf(stderr, "conf: unsupported ldap_proto_version option value: %s\n",val);
return 1;
}
return 0;
#else /* not HAVE_MAP_LDAP */
fprintf(stderr, "conf: ldap_proto_version option ignored. No LDAP support available.\n");
return 1;
#endif /* not HAVE_MAP_LDAP */
}
static int
gopt_log_file(const char *val)
{
@ -537,7 +727,15 @@ gopt_log_file(const char *val)
static int
gopt_log_options(const char *val)
{
usage += switch_option(strdup((char *)val));
usage += switch_option((char *)val);
return 0;
}
static int
gopt_map_defaults(const char *val)
{
gopt.map_defaults = strdup((char *)val);
return 0;
}
@ -550,6 +748,16 @@ gopt_map_options(const char *val)
}
static int
gopt_map_reload_interval(const char *val)
{
gopt.map_reload_interval = atoi(val);
if (gopt.map_reload_interval <= 0)
gopt.map_reload_interval = ONE_HOUR;
return 0;
}
static int
gopt_map_type(const char *val)
{
@ -567,9 +775,14 @@ static int
gopt_mount_type(const char *val)
{
if (STREQ(val, "autofs")) {
fprintf(stderr, "conf: no autofs support available, turning it off\n");
gopt.flags &= ~CFM_MOUNT_TYPE_AUTOFS;
#ifdef HAVE_FS_AUTOFS
gopt.flags |= CFM_MOUNT_TYPE_AUTOFS;
amd_use_autofs++;
return 0;
#else /* not HAVE_FS_AUTOFS */
fprintf(stderr, "conf: no autofs support available\n");
return 1;
#endif /* not HAVE_FS_AUTOFS */
} else if (STREQ(val, "nfs")) {
gopt.flags &= ~CFM_MOUNT_TYPE_AUTOFS;
return 0;
@ -583,7 +796,7 @@ gopt_mount_type(const char *val)
static int
gopt_portmap_program(const char *val)
{
gopt.portmap_program = atoi(val);
gopt.portmap_program = atol(val);
/*
* allow alternate program numbers to be no more than 10 offset from
* official amd program number (300019).
@ -601,6 +814,35 @@ gopt_portmap_program(const char *val)
}
static int
gopt_preferred_amq_port(const char *val)
{
gopt.preferred_amq_port = atoi(val);
/*
* No need to check value: preferred_amq_port is an unsigned short and 0
* is a valid number, meaning "any port".
*/
return 0; /* all is OK */
}
static int
gopt_nfs_allow_any_interface(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_NFS_ANY_INTERFACE;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_NFS_ANY_INTERFACE;
return 0;
}
fprintf(stderr, "conf: unknown value to nfs_allow_insecure_port \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_nfs_allow_insecure_port(const char *val)
{
@ -632,7 +874,34 @@ gopt_nfs_proto(const char *val)
static int
gopt_nfs_retransmit_counter(const char *val)
{
gopt.amfs_auto_retrans = atoi(val);
int i;
for (i=0; i<AMU_TYPE_MAX; ++i)
gopt.amfs_auto_retrans[i] = atoi(val);
return 0;
}
static int
gopt_nfs_retransmit_counter_udp(const char *val)
{
gopt.amfs_auto_retrans[AMU_TYPE_UDP] = atoi(val);
return 0;
}
static int
gopt_nfs_retransmit_counter_tcp(const char *val)
{
gopt.amfs_auto_retrans[AMU_TYPE_TCP] = atoi(val);
return 0;
}
static int
gopt_nfs_retransmit_counter_toplvl(const char *val)
{
gopt.amfs_auto_retrans[AMU_TYPE_TOPLVL] = atoi(val);
return 0;
}
@ -640,7 +909,34 @@ gopt_nfs_retransmit_counter(const char *val)
static int
gopt_nfs_retry_interval(const char *val)
{
gopt.amfs_auto_timeo = atoi(val);
int i;
for (i=0; i<AMU_TYPE_MAX; ++i)
gopt.amfs_auto_timeo[i] = atoi(val);
return 0;
}
static int
gopt_nfs_retry_interval_udp(const char *val)
{
gopt.amfs_auto_timeo[AMU_TYPE_UDP] = atoi(val);
return 0;
}
static int
gopt_nfs_retry_interval_tcp(const char *val)
{
gopt.amfs_auto_timeo[AMU_TYPE_TCP] = atoi(val);
return 0;
}
static int
gopt_nfs_retry_interval_toplvl(const char *val)
{
gopt.amfs_auto_timeo[AMU_TYPE_TOPLVL] = atoi(val);
return 0;
}
@ -688,6 +984,22 @@ gopt_normalize_hostnames(const char *val)
}
static int
gopt_normalize_slashes(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_NORMALIZE_SLASHES;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_NORMALIZE_SLASHES;
return 0;
}
fprintf(stderr, "conf: unknown value to normalize_slashes \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_os(const char *val)
{
@ -740,7 +1052,9 @@ static int
gopt_print_version(const char *val)
{
if (STREQ(val, "yes")) {
fputs(get_version_string(), stderr);
char *vers = get_version_string();
fputs(vers, stderr);
XFREE(vers);
return 0;
} else if (STREQ(val, "no")) {
return 0;
@ -807,6 +1121,22 @@ gopt_show_statfs_entries(const char *val)
}
static int
gopt_truncate_log(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_TRUNCATE_LOG;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_TRUNCATE_LOG;
return 0;
}
fprintf(stderr, "conf: unknown value to truncate_log \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_unmount_on_exit(const char *val)
{
@ -823,6 +1153,27 @@ gopt_unmount_on_exit(const char *val)
}
static int
gopt_use_tcpwrappers(const char *val)
{
#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
if (STREQ(val, "yes")) {
gopt.flags |= CFM_USE_TCPWRAPPERS;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_USE_TCPWRAPPERS;
return 0;
}
#else /* not defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
fprintf(stderr, "conf: no tcpd/libwrap support available\n");
return 1;
#endif /* not defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
fprintf(stderr, "conf: unknown value to use_tcpwrappers \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_vendor(const char *val)
{
@ -857,6 +1208,9 @@ process_regular_option(const char *section, const char *key, const char *val, cf
if (STREQ(key, "map_name"))
return ropt_map_name(val, cfm);
if (STREQ(key, "map_defaults"))
return ropt_map_defaults(val, cfm);
if (STREQ(key, "map_options"))
return ropt_map_options(val, cfm);
@ -905,6 +1259,14 @@ ropt_map_name(const char *val, cf_map_t *cfm)
}
static int
ropt_map_defaults(const char *val, cf_map_t *cfm)
{
cfm->cfm_defaults = strdup((char *)val);
return 0;
}
static int
ropt_map_options(const char *val, cf_map_t *cfm)
{
@ -930,9 +1292,14 @@ static int
ropt_mount_type(const char *val, cf_map_t *cfm)
{
if (STREQ(val, "autofs")) {
fprintf(stderr, "conf: no autofs support available, turning it off\n");
cfm->cfm_flags &= ~CFM_MOUNT_TYPE_AUTOFS;
#ifdef HAVE_FS_AUTOFS
cfm->cfm_flags |= CFM_MOUNT_TYPE_AUTOFS;
amd_use_autofs++;
return 0;
#else /* not HAVE_FS_AUTOFS */
fprintf(stderr, "conf: no autofs support available\n");
return 1;
#endif /* not HAVE_FS_AUTOFS */
} else if (STREQ(val, "nfs")) {
cfm->cfm_flags &= ~CFM_MOUNT_TYPE_AUTOFS;
return 0;
@ -963,9 +1330,8 @@ ropt_tag(const char *val, cf_map_t *cfm)
* Process one collected map.
*/
static int
process_regular_map(cf_map_t *cfm)
process_one_regular_map(const cf_map_t *cfm)
{
if (!cfm->cfm_name) {
fprintf(stderr, "conf: map_name must be defined for map \"%s\"\n", cfm->cfm_dir);
return 1;
@ -989,22 +1355,52 @@ process_regular_map(cf_map_t *cfm)
fprintf(stderr, "skipping map %s...\n", cfm->cfm_dir);
}
reset_cf_map(cfm);
return 0;
}
/*
* Process last map in conf file (if any)
* Process all regular maps in conf file (if any)
*/
int
process_last_regular_map(void)
process_all_regular_maps(void)
{
cf_map_t *tmp_map = head_map;
/*
* If the amd.conf file only has a [global] section (pretty useless
* IMHO), do not try to process a map that does not exist.
* IMHO), there's nothing to process
*/
if (!cur_map.cfm_dir)
if (!tmp_map)
return 0;
return process_regular_map(&cur_map);
while (tmp_map) {
if (process_one_regular_map(tmp_map) != 0)
return 1;
tmp_map = tmp_map->cfm_next;
}
return 0;
}
/*
* Find a cf_map_t for a given map name.
* Return NULL if not found.
*/
cf_map_t *
find_cf_map(const char *name)
{
cf_map_t *tmp_map = head_map;
if (!tmp_map || !name)
return NULL;
while (tmp_map) {
if (STREQ(tmp_map->cfm_dir,name)) {
return tmp_map;
}
tmp_map = tmp_map->cfm_next;
}
return NULL;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -37,7 +37,7 @@
* SUCH DAMAGE.
*
*
* $Id: conf_parse.y,v 1.4.2.5 2004/05/12 15:54:31 ezk Exp $
* File: am-utils/amd/conf_parse.y
*
*/

View File

@ -1,6 +1,6 @@
%{
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -38,7 +38,7 @@
* SUCH DAMAGE.
*
*
* $Id: conf_tok.l,v 1.3.2.5 2004/05/12 15:54:31 ezk Exp $
* File: am-utils/amd/conf_tok.l
*
*/

423
contrib/amd/amd/info_exec.c Normal file
View File

@ -0,0 +1,423 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgment:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* File: am-utils/amd/info_exec.c
*
*/
/*
* Get info from executable map
*
* Original from Erik Kline, 2004.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
#define MAX_LINE_LEN 1500
/* forward declarations */
int exec_init(mnt_map *m, char *map, time_t *tp);
int exec_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp);
/*
* a timed fgets()
*/
static char *
fgets_timed(char *s, int size, int rdfd, int secs)
{
fd_set fds;
struct timeval timeo;
time_t start, now;
int rval=0, i=0;
if (!s || size < 0 || rdfd < 0)
return 0;
s[0] = 0;
if (size == 0)
return s;
start = clocktime(NULL);
while (s[i] != '\n' && i < size-1) {
s[i+1] = 0; /* places the requisite trailing '\0' */
/* ready for reading */
rval = read(rdfd, (void *)(s+i), 1);
if (rval == 1) {
if (s[i] == 0) {
rval = 0;
break;
}
i++;
continue;
} else if (rval == 0) {
break;
} else if (rval < 0 && errno != EAGAIN && errno != EINTR) {
plog(XLOG_WARNING, "fgets_timed read error: %m");
break;
}
timeo.tv_usec = 0;
now = clocktime(NULL) - start;
if (secs <= 0)
timeo.tv_sec = 0;
else if (now < secs)
timeo.tv_sec = secs - now;
else {
/* timed out (now>=secs) */
plog(XLOG_WARNING, "executable map read timed out (> %d secs)", secs);
rval = -1;
break;
}
FD_ZERO(&fds);
FD_SET(rdfd, &fds);
rval = select(rdfd+1, &fds, 0, 0, &timeo);
if (rval < 0) {
/* error selecting */
plog(XLOG_WARNING, "fgets_timed select error: %m");
if (errno == EINTR)
continue;
rval = -1;
break;
} else if (rval == 0) {
/* timed out */
plog(XLOG_WARNING, "executable map read timed out (> %d secs)", secs);
rval = -1;
break;
}
}
if (rval > 0)
return s;
close(rdfd);
return (rval == 0 ? s : 0);
}
static int
read_line(char *buf, int size, int fd)
{
int done = 0;
while (fgets_timed(buf, size, fd, gopt.exec_map_timeout)) {
int len = strlen(buf);
done += len;
if (len > 1 && buf[len - 2] == '\\' &&
buf[len - 1] == '\n') {
buf += len - 2;
size -= len - 2;
*buf = '\n';
buf[1] = '\0';
} else {
return done;
}
}
return done;
}
/*
* Try to locate a value in a query answer
*/
static int
exec_parse_qanswer(int fd, char *map, char *key, char **pval, time_t *tp)
{
char qanswer[MAX_LINE_LEN], *dc = 0;
int chuck = 0;
int line_no = 0;
while (read_line(qanswer, sizeof(qanswer), fd)) {
char *cp;
char *hash;
int len = strlen(qanswer);
line_no++;
/*
* Make sure we got the whole line
*/
if (qanswer[len - 1] != '\n') {
plog(XLOG_WARNING, "line %d in \"%s\" is too long", line_no, map);
chuck = 1;
} else {
qanswer[len - 1] = '\0';
}
/*
* Strip comments
*/
hash = strchr(qanswer, '#');
if (hash)
*hash = '\0';
/*
* Find beginning of value (query answer)
*/
for (cp = qanswer; *cp && !isascii((int)*cp) && !isspace((int)*cp); cp++)
;;
/* Ignore blank lines */
if (!*cp)
goto again;
/*
* Return a copy of the data
*/
dc = strdup(cp);
*pval = dc;
dlog("%s returns %s", key, dc);
close(fd);
return 0;
again:
/*
* If the last read didn't get a whole line then
* throw away the remainder before continuing...
*/
if (chuck) {
while (fgets_timed(qanswer, sizeof(qanswer), fd, gopt.exec_map_timeout) &&
!strchr(qanswer, '\n')) ;
chuck = 0;
}
}
return ENOENT;
}
static int
set_nonblock(int fd)
{
int val;
if (fd < 0)
return 0;
if ((val = fcntl(fd, F_GETFL, 0)) < 0) {
plog(XLOG_WARNING, "set_nonblock fcntl F_GETFL error: %m");
return 0;
}
val |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, val) < 0) {
plog(XLOG_WARNING, "set_nonblock fcntl F_SETFL error: %m");
return 0;
}
return 1;
}
static int
exec_map_open(char *emap, char *key)
{
pid_t p1, p2;
int pdes[2], nullfd, i;
char *argv[3];
if (!emap)
return 0;
argv[0] = emap;
argv[1] = key;
argv[2] = NULL;
if ((nullfd = open("/dev/null", O_WRONLY|O_NOCTTY)) < 0)
return -1;
if (pipe(pdes) < 0) {
close(nullfd);
return -1;
}
switch ((p1 = vfork())) {
case -1:
/* parent: fork error */
close(nullfd);
close(pdes[0]);
close(pdes[1]);
return -1;
case 0:
/* child #1 */
p2 = vfork();
switch (p2) {
case -1:
/* child #1: fork error */
exit(errno);
case 0:
/* child #2: init will reap our status */
if (pdes[1] != STDOUT_FILENO) {
dup2(pdes[1], STDOUT_FILENO);
close(pdes[1]);
}
if (nullfd != STDERR_FILENO) {
dup2(nullfd, STDERR_FILENO);
close(nullfd);
}
for (i=0; i<FD_SETSIZE; i++)
if (i != STDOUT_FILENO && i != STDERR_FILENO)
close(i);
/* make the write descriptor non-blocking */
if (!set_nonblock(STDOUT_FILENO)) {
close(STDOUT_FILENO);
exit(-1);
}
execve(emap, argv, NULL);
exit(errno); /* in case execve failed */
}
/* child #1 */
exit(0);
}
/* parent */
close(nullfd);
close(pdes[1]);
/* anti-zombie insurance */
while (waitpid(p1,0,0) < 0)
if (errno != EINTR)
exit(errno);
/* make the read descriptor non-blocking */
if (!set_nonblock(pdes[0])) {
close(pdes[0]);
return -1;
}
return pdes[0];
}
/*
* Check for various permissions on executable map without trying to
* fork a new executable-map process.
*
* return: >0 (errno) if failed
* 0 if ok
*/
static int
exec_check_perm(char *map)
{
struct stat sb;
/* sanity and permission checks */
if (!map) {
dlog("exec_check_permission got a NULL map");
return EINVAL;
}
if (stat(map, &sb)) {
plog(XLOG_ERROR, "map \"%s\" stat failure: %m", map);
return errno;
}
if (!S_ISREG(sb.st_mode)) {
plog(XLOG_ERROR, "map \"%s\" should be regular file", map);
return EINVAL;
}
if (sb.st_uid != 0) {
plog(XLOG_ERROR, "map \"%s\" owned by uid %u (must be 0)", map, (u_int) sb.st_uid);
return EACCES;
}
if (!(sb.st_mode & S_IXUSR)) {
plog(XLOG_ERROR, "map \"%s\" should be executable", map);
return EACCES;
}
if (sb.st_mode & (S_ISUID|S_ISGID)) {
plog(XLOG_ERROR, "map \"%s\" should not be setuid/setgid", map);
return EACCES;
}
if (sb.st_mode & S_IWOTH) {
plog(XLOG_ERROR, "map \"%s\" should not be world writeable", map);
return EACCES;
}
return 0; /* all is well */
}
int
exec_init(mnt_map *m, char *map, time_t *tp)
{
/*
* Basically just test that the executable map can be found
* and has proper permissions.
*/
return exec_check_perm(map);
}
int
exec_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
{
int mapfd, ret;
if ((ret = exec_check_perm(map)) != 0) {
return ret;
}
if (!key)
return 0;
if (logfp)
fflush(logfp);
dlog("exec_search \"%s\", key: \"%s\"", map, key);
mapfd = exec_map_open(map, key);
if (mapfd >= 0) {
if (tp)
*tp = clocktime(NULL);
return exec_parse_qanswer(mapfd, map, key, pval, tp);
}
return errno;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: info_file.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/info_file.c
*
*/
@ -55,10 +54,9 @@
#define MAX_LINE_LEN 1500
/* forward declarations */
int file_init(mnt_map *m, char *map, time_t *tp);
int file_init_or_mtime(mnt_map *m, char *map, time_t *tp);
int file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *));
int file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp);
int file_mtime(mnt_map *m, char *map, time_t *tp);
static int
@ -87,7 +85,7 @@ read_line(char *buf, int size, FILE *fp)
return done;
}
}
} while (size > 0 && !feof(fp));
} while (size > 0 && !feof(fp) && !ferror(fp));
return done;
}
@ -97,7 +95,12 @@ read_line(char *buf, int size, FILE *fp)
* Try to locate a key in a file
*/
static int
search_or_reload_file(FILE *fp, char *map, char *key, char **val, mnt_map *m, void (*fn) (mnt_map *m, char *, char *))
file_search_or_reload(FILE *fp,
char *map,
char *key,
char **val,
mnt_map *m,
void (*fn) (mnt_map *m, char *, char *))
{
char key_val[MAX_LINE_LEN];
int chuck = 0;
@ -161,9 +164,7 @@ search_or_reload_file(FILE *fp, char *map, char *key, char **val, mnt_map *m, vo
(*fn) (m, strdup(kp), dc);
} else {
*val = dc;
#ifdef DEBUG
dlog("%s returns %s", key, dc);
#endif /* DEBUG */
}
if (!fn)
return 0;
@ -196,7 +197,7 @@ file_open(char *map, time_t *tp)
if (mapf && tp) {
struct stat stb;
if (fstat(fileno(mapf), &stb) < 0)
*tp = clocktime();
*tp = clocktime(NULL);
else
*tp = stb.st_mtime;
}
@ -205,7 +206,7 @@ file_open(char *map, time_t *tp)
int
file_init(mnt_map *m, char *map, time_t *tp)
file_init_or_mtime(mnt_map *m, char *map, time_t *tp)
{
FILE *mapf = file_open(map, tp);
@ -223,7 +224,7 @@ file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
FILE *mapf = file_open(map, (time_t *) 0);
if (mapf) {
int error = search_or_reload_file(mapf, map, 0, 0, m, fn);
int error = file_search_or_reload(mapf, map, 0, 0, m, fn);
(void) fclose(mapf);
return error;
}
@ -243,23 +244,10 @@ file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
*tp = t;
error = -1;
} else {
error = search_or_reload_file(mapf, map, key, pval, 0, 0);
error = file_search_or_reload(mapf, map, key, pval, 0, 0);
}
(void) fclose(mapf);
return error;
}
return errno;
}
int
file_mtime(mnt_map *m, char *map, time_t *tp)
{
FILE *mapf = file_open(map, tp);
if (mapf) {
(void) fclose(mapf);
return 0;
}
return errno;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: info_hesiod.c,v 1.6.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/info_hesiod.c
*
*/
@ -75,13 +74,11 @@ int hesiod_isup(mnt_map *m, char *map);
int
amu_hesiod_init(mnt_map *m, char *map, time_t *tp)
{
#ifdef DEBUG
dlog("amu_hesiod_init(%s)", map);
#endif /* DEBUG */
*tp = 0;
#ifdef HAVE_HESIOD_INIT
if(!hesiod_context && hesiod_init(&hesiod_context) != 0)
if (!hesiod_context && hesiod_init(&hesiod_context) != 0)
return ENOENT;
#endif /* HAVE_HESIOD_INIT */
@ -102,22 +99,21 @@ hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
int error;
#endif /* not HAVE_HESIOD_INIT */
#ifdef DEBUG
dlog("hesiod_search(m=%lx, map=%s, key=%s, pval=%lx tp=%lx)",
(unsigned long) m, map, key, (unsigned long) pval, (unsigned long) tp);
#endif /* DEBUG */
sprintf(hes_key, "%s.%s", key, map + HES_PREFLEN);
if (key[0] == '.')
return ENOENT;
xsnprintf(hes_key, sizeof(hes_key), "%s.%s", key, map + HES_PREFLEN);
/*
* Call the resolver
*/
#ifdef DEBUG
dlog("Hesiod base is: %s\n", gopt.hesiod_base);
dlog("hesiod_search: hes_resolve(%s, %s)", hes_key, gopt.hesiod_base);
if (debug_flags & D_INFO)
if (amuDebug(D_INFO))
_res.options |= RES_DEBUG;
#endif /* DEBUG */
#ifdef HAVE_HESIOD_INIT
/* new style hesiod */
@ -144,9 +140,7 @@ hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
/*
* Otherwise reflect the hesiod error into a Un*x error
*/
# ifdef DEBUG
dlog("hesiod_search: Error: %d", hes_error());
# endif /* DEBUG */
switch (hes_error()) {
case HES_ER_NOTFOUND:
error = ENOENT;
@ -161,9 +155,7 @@ hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
error = EINVAL;
break;
}
# ifdef DEBUG
dlog("hesiod_search: Returning: %d", error);
# endif /* DEBUG */
return error;
#endif /* not HAVE_HESIOD_INIT */
}
@ -183,9 +175,7 @@ hesiod_isup(mnt_map *m, char *map)
static int last_status = 1; /* assume up by default */
error = hesiod_search(m, map, "/defaults", &val, &mtime);
#ifdef DEBUG
dlog("hesiod_isup(%s): %s", map, strerror(error));
#endif /* DEBUG */
if (error != 0 && error != ENOENT) {
plog(XLOG_ERROR,
"hesiod_isup: error getting `/defaults' entry in map %s: %m", map);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: info_ldap.c,v 1.9.2.9 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/info_ldap.c
*
*/
@ -48,6 +47,20 @@
* LDAP Home Page: http://www.umich.edu/~rsug/ldap/
*/
/*
* WARNING: as of Linux Fedora Core 5 (which comes with openldap-2.3.9), the
* ldap.h headers deprecate several functions used in this file, such as
* ldap_unbind. You get compile errors about missing extern definitions.
* Those externs are still in <ldap.h>, but surrounded by an ifdef
* LDAP_DEPRECATED. I am turning on that ifdef here, under the assumption
* that the functions may be deprecated, but they still work for this
* (older?) version of the LDAP API. It gets am-utils to compile, but it is
* not clear if it will work perfectly.
*/
#ifndef LDAP_DEPRECATED
# define LDAP_DEPRECATED 1
#endif /* not LDAP_DEPRECATED */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
@ -109,7 +122,7 @@ struct he_ent {
* FORWARD DECLARATIONS:
*/
static int amu_ldap_rebind(ALD *a);
static int get_ldap_timestamp(LDAP *ld, char *map, time_t *ts);
static int get_ldap_timestamp(ALD *a, char *map, time_t *ts);
/*
@ -167,13 +180,54 @@ cr_free(CR *c)
}
/*
* Special ldap_unbind function to handle SIGPIPE.
* We first ignore SIGPIPE, in case a remote LDAP server was
* restarted, then we reinstall the handler.
*/
static int
amu_ldap_unbind(LDAP *ld)
{
int e;
#ifdef HAVE_SIGACTION
struct sigaction sa;
#else /* not HAVE_SIGACTION */
void (*handler)(int);
#endif /* not HAVE_SIGACTION */
dlog("amu_ldap_unbind()\n");
#ifdef HAVE_SIGACTION
sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;
sigemptyset(&(sa.sa_mask));
sigaddset(&(sa.sa_mask), SIGPIPE);
sigaction(SIGPIPE, &sa, &sa); /* set IGNORE, and get old action */
#else /* not HAVE_SIGACTION */
handler = signal(SIGPIPE, SIG_IGN);
#endif /* not HAVE_SIGACTION */
e = ldap_unbind(ld);
#ifdef HAVE_SIGACTION
sigemptyset(&(sa.sa_mask));
sigaddset(&(sa.sa_mask), SIGPIPE);
sigaction(SIGPIPE, &sa, NULL);
#else /* not HAVE_SIGACTION */
(void) signal(SIGPIPE, handler);
#endif /* not HAVE_SIGACTION */
return e;
}
static void
ald_free(ALD *a)
{
he_free(a->hostent);
cr_free(a->credentials);
if (a->ldap != NULL)
ldap_unbind(a->ldap);
amu_ldap_unbind(a->ldap);
XFREE(a);
}
@ -184,27 +238,29 @@ amu_ldap_init(mnt_map *m, char *map, time_t *ts)
ALD *aldh;
CR *creds;
dlog("-> amu_ldap_init: map <%s>\n", map);
/*
* XXX: by checking that map_type must be defined, aren't we
* excluding the possibility of automatic searches through all
* map types?
*/
if (!gopt.map_type || !STREQ(gopt.map_type, AMD_LDAP_TYPE)) {
return (ENOENT);
}
#ifdef DEBUG
else {
dlog("amu_ldap_init called with map_type <%s>\n",
(gopt.map_type ? gopt.map_type : "null"));
} else {
dlog("Map %s is ldap\n", map);
}
#endif /* DEBUG */
aldh = ALLOC(ALD);
creds = ALLOC(CR);
aldh->ldap = NULL ;
aldh->ldap = NULL;
aldh->hostent = string2he(gopt.ldap_hostports);
if (aldh->hostent == NULL) {
plog(XLOG_USER, "Unable to parse hostport %s for ldap map %s",
gopt.ldap_hostports ? gopt.ldap_hostports : "(null)", map);
XFREE(creds);
XFREE(aldh);
return (ENOENT);
}
creds->who = "";
@ -212,22 +268,17 @@ amu_ldap_init(mnt_map *m, char *map, time_t *ts)
creds->method = LDAP_AUTH_SIMPLE;
aldh->credentials = creds;
aldh->timestamp = 0;
#ifdef DEBUG
aldh->ldap = NULL;
dlog("Trying for %s:%d\n", aldh->hostent->host, aldh->hostent->port);
#endif /* DEBUG */
if (amu_ldap_rebind(aldh)) {
ald_free(aldh);
return (ENOENT);
}
m->map_data = (void *) aldh;
#ifdef DEBUG
dlog("Bound to %s:%d\n", aldh->hostent->host, aldh->hostent->port);
#endif /* DEBUG */
if (get_ldap_timestamp(aldh->ldap, map, ts))
if (get_ldap_timestamp(aldh, map, ts))
return (ENOENT);
#ifdef DEBUG
dlog("Got timestamp for map %s: %ld\n", map, *ts);
#endif /* DEBUG */
dlog("Got timestamp for map %s: %ld\n", map, (u_long) *ts);
return (0);
}
@ -239,16 +290,21 @@ amu_ldap_rebind(ALD *a)
LDAP *ld;
HE_ENT *h;
CR *c = a->credentials;
time_t now = clocktime();
time_t now = clocktime(NULL);
int try;
dlog("-> amu_ldap_rebind\n");
if (a->ldap != NULL) {
if ((a->timestamp - now) > AMD_LDAP_TTL) {
#ifdef DEBUG
dlog("Reestablishing ldap connection\n");
#endif /* DEBUG */
ldap_unbind(a->ldap);
dlog("Re-establishing ldap connection\n");
amu_ldap_unbind(a->ldap);
a->timestamp = now;
a->ldap = NULL;
} else {
/* Assume all is OK. If it wasn't we'll be back! */
dlog("amu_ldap_rebind: timestamp OK\n");
return (0);
}
}
@ -258,21 +314,34 @@ amu_ldap_rebind(ALD *a)
plog(XLOG_WARNING, "Unable to ldap_open to %s:%d\n", h->host, h->port);
break;
}
#if LDAP_VERSION_MAX > LDAP_VERSION2
/* handle LDAPv3 and heigher, if available and amd.conf-igured */
if (gopt.ldap_proto_version > LDAP_VERSION2) {
if (!ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &gopt.ldap_proto_version)) {
dlog("amu_ldap_rebind: LDAP protocol version set to %ld\n",
gopt.ldap_proto_version);
} else {
plog(XLOG_WARNING, "Unable to set ldap protocol version to %ld\n",
gopt.ldap_proto_version);
break;
}
}
#endif /* LDAP_VERSION_MAX > LDAP_VERSION2 */
if (ldap_bind_s(ld, c->who, c->pw, c->method) != LDAP_SUCCESS) {
plog(XLOG_WARNING, "Unable to ldap_bind to %s:%d as %s\n",
h->host, h->port, c->who);
break;
}
if (gopt.ldap_cache_seconds > 0) {
#ifdef HAVE_LDAP_ENABLE_CACHE
#if defined(HAVE_LDAP_ENABLE_CACHE) && defined(HAVE_EXTERN_LDAP_ENABLE_CACHE)
ldap_enable_cache(ld, gopt.ldap_cache_seconds, gopt.ldap_cache_maxmem);
#else /* HAVE_LDAP_ENABLE_CACHE */
plog(XLOG_WARNING, "ldap_enable_cache(%ld) does not exist on this system!\n", gopt.ldap_cache_seconds);
#endif /* HAVE_LDAP_ENABLE_CACHE */
a->ldap = ld;
a->timestamp = now;
return (0);
#else /* not defined(HAVE_LDAP_ENABLE_CACHE) && defined(HAVE_EXTERN_LDAP_ENABLE_CACHE) */
plog(XLOG_WARNING, "ldap_enable_cache(%ld) is not available on this system!\n", gopt.ldap_cache_seconds);
#endif /* not defined(HAVE_LDAP_ENABLE_CACHE) && defined(HAVE_EXTERN_LDAP_ENABLE_CACHE) */
}
a->ldap = ld;
a->timestamp = now;
return (0);
}
plog(XLOG_WARNING, "Exhausted list of ldap servers, looping.\n");
}
@ -283,115 +352,22 @@ amu_ldap_rebind(ALD *a)
static int
get_ldap_timestamp(LDAP *ld, char *map, time_t *ts)
get_ldap_timestamp(ALD *a, char *map, time_t *ts)
{
struct timeval tv;
char **vals, *end;
char filter[MAXPATHLEN];
int i, err = 0, nentries = 0;
LDAPMessage *res, *entry;
LDAPMessage *res = NULL, *entry;
dlog("-> get_ldap_timestamp: map <%s>\n", map);
tv.tv_sec = 3;
tv.tv_usec = 0;
sprintf(filter, AMD_LDAP_TSFILTER, map);
#ifdef DEBUG
xsnprintf(filter, sizeof(filter), AMD_LDAP_TSFILTER, map);
dlog("Getting timestamp for map %s\n", map);
dlog("Filter is: %s\n", filter);
dlog("Base is: %s\n", gopt.ldap_base);
#endif /* DEBUG */
for (i = 0; i < AMD_LDAP_RETRIES; i++) {
err = ldap_search_st(ld,
gopt.ldap_base,
LDAP_SCOPE_SUBTREE,
filter,
0,
0,
&tv,
&res);
if (err == LDAP_SUCCESS)
break;
#ifdef DEBUG
dlog("Timestamp search timed out, trying again...\n");
#endif /* DEBUG */
}
if (err != LDAP_SUCCESS) {
*ts = 0;
plog(XLOG_USER, "LDAP timestamp search failed: %s\n",
ldap_err2string(err));
return (ENOENT);
}
nentries = ldap_count_entries(ld, res);
if (nentries == 0) {
plog(XLOG_USER, "No timestamp entry for map %s\n", map);
*ts = 0;
ldap_msgfree(res);
return (ENOENT);
}
entry = ldap_first_entry(ld, res);
vals = ldap_get_values(ld, entry, AMD_LDAP_TSATTR);
if (ldap_count_values(vals) == 0) {
plog(XLOG_USER, "Missing timestamp value for map %s\n", map);
*ts = 0;
ldap_value_free(vals);
ldap_msgfree(res);
return (ENOENT);
}
#ifdef DEBUG
dlog("TS value is:%s:\n", vals[0]);
#endif /* DEBUG */
if (vals[0]) {
*ts = (time_t) strtol(vals[0], &end, 10);
if (end == vals[0]) {
plog(XLOG_USER, "Unable to decode ldap timestamp %s for map %s\n",
vals[0], map);
err = ENOENT;
}
if (!*ts > 0) {
plog(XLOG_USER, "Nonpositive timestamp %ld for map %s\n",
*ts, map);
err = ENOENT;
}
} else {
plog(XLOG_USER, "Empty timestamp value for map %s\n", map);
*ts = 0;
err = ENOENT;
}
ldap_value_free(vals);
ldap_msgfree(res);
#ifdef DEBUG
dlog("The timestamp for %s is %ld (err=%d)\n", map, *ts, err);
#endif /* DEBUG */
return (err);
}
int
amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts)
{
char **vals, filter[MAXPATHLEN];
struct timeval tv;
int i, err = 0, nvals = 0, nentries = 0;
LDAPMessage *entry, *res;
ALD *a = (ALD *) (m->map_data);
tv.tv_sec = 2;
tv.tv_usec = 0;
if (a == NULL) {
plog(XLOG_USER, "LDAP panic: no map data\n");
return (EIO);
}
if (amu_ldap_rebind(a)) /* Check that's the handle is still valid */
return (ENOENT);
sprintf(filter, AMD_LDAP_FILTER, map, key);
#ifdef DEBUG
dlog("Search with filter: %s\n", filter);
#endif /* DEBUG */
for (i = 0; i < AMD_LDAP_RETRIES; i++) {
err = ldap_search_st(a->ldap,
gopt.ldap_base,
@ -403,28 +379,153 @@ amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts)
&res);
if (err == LDAP_SUCCESS)
break;
if (res) {
ldap_msgfree(res);
res = NULL;
}
plog(XLOG_USER, "Timestamp LDAP search attempt %d failed: %s\n",
i + 1, ldap_err2string(err));
if (err != LDAP_TIMEOUT) {
dlog("get_ldap_timestamp: unbinding...\n");
amu_ldap_unbind(a->ldap);
a->ldap = NULL;
if (amu_ldap_rebind(a))
return (ENOENT);
}
dlog("Timestamp search failed, trying again...\n");
}
if (err != LDAP_SUCCESS) {
*ts = 0;
plog(XLOG_USER, "LDAP timestamp search failed: %s\n",
ldap_err2string(err));
if (res)
ldap_msgfree(res);
return (ENOENT);
}
nentries = ldap_count_entries(a->ldap, res);
if (nentries == 0) {
plog(XLOG_USER, "No timestamp entry for map %s\n", map);
*ts = 0;
ldap_msgfree(res);
return (ENOENT);
}
entry = ldap_first_entry(a->ldap, res);
vals = ldap_get_values(a->ldap, entry, AMD_LDAP_TSATTR);
if (ldap_count_values(vals) == 0) {
plog(XLOG_USER, "Missing timestamp value for map %s\n", map);
*ts = 0;
ldap_value_free(vals);
ldap_msgfree(res);
return (ENOENT);
}
dlog("TS value is:%s:\n", vals[0]);
if (vals[0]) {
*ts = (time_t) strtol(vals[0], &end, 10);
if (end == vals[0]) {
plog(XLOG_USER, "Unable to decode ldap timestamp %s for map %s\n",
vals[0], map);
err = ENOENT;
}
if (!*ts > 0) {
plog(XLOG_USER, "Nonpositive timestamp %ld for map %s\n",
(u_long) *ts, map);
err = ENOENT;
}
} else {
plog(XLOG_USER, "Empty timestamp value for map %s\n", map);
*ts = 0;
err = ENOENT;
}
ldap_value_free(vals);
ldap_msgfree(res);
dlog("The timestamp for %s is %ld (err=%d)\n", map, (u_long) *ts, err);
return (err);
}
int
amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts)
{
char **vals, filter[MAXPATHLEN], filter2[2 * MAXPATHLEN];
char *f1, *f2;
struct timeval tv;
int i, err = 0, nvals = 0, nentries = 0;
LDAPMessage *entry, *res = NULL;
ALD *a = (ALD *) (m->map_data);
dlog("-> amu_ldap_search: map <%s>, key <%s>\n", map, key);
tv.tv_sec = 2;
tv.tv_usec = 0;
if (a == NULL) {
plog(XLOG_USER, "LDAP panic: no map data\n");
return (EIO);
}
if (amu_ldap_rebind(a)) /* Check that's the handle is still valid */
return (ENOENT);
xsnprintf(filter, sizeof(filter), AMD_LDAP_FILTER, map, key);
/* "*" is special to ldap_search(); run through the filter escaping it. */
f1 = filter; f2 = filter2;
while (*f1) {
if (*f1 == '*') {
*f2++ = '\\'; *f2++ = '2'; *f2++ = 'a';
f1++;
} else {
*f2++ = *f1++;
}
}
*f2 = '\0';
dlog("Search with filter: <%s>\n", filter2);
for (i = 0; i < AMD_LDAP_RETRIES; i++) {
err = ldap_search_st(a->ldap,
gopt.ldap_base,
LDAP_SCOPE_SUBTREE,
filter2,
0,
0,
&tv,
&res);
if (err == LDAP_SUCCESS)
break;
if (res) {
ldap_msgfree(res);
res = NULL;
}
plog(XLOG_USER, "LDAP search attempt %d failed: %s\n",
i + 1, ldap_err2string(err));
if (err != LDAP_TIMEOUT) {
dlog("amu_ldap_search: unbinding...\n");
amu_ldap_unbind(a->ldap);
a->ldap = NULL;
if (amu_ldap_rebind(a))
return (ENOENT);
}
}
switch (err) {
case LDAP_SUCCESS:
break;
case LDAP_NO_SUCH_OBJECT:
#ifdef DEBUG
dlog("No object\n");
#endif /* DEBUG */
ldap_msgfree(res);
if (res)
ldap_msgfree(res);
return (ENOENT);
default:
plog(XLOG_USER, "LDAP search failed: %s\n",
ldap_err2string(err));
ldap_msgfree(res);
if (res)
ldap_msgfree(res);
return (EIO);
}
nentries = ldap_count_entries(a->ldap, res);
#ifdef DEBUG
dlog("Search found %d entries\n", nentries);
#endif /* DEBUG */
if (nentries == 0) {
ldap_msgfree(res);
return (ENOENT);
@ -438,9 +539,7 @@ amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts)
ldap_msgfree(res);
return (EIO);
}
#ifdef DEBUG
dlog("Map %s, %s => %s\n", map, key, vals[0]);
#endif /* DEBUG */
if (vals[0]) {
*pval = strdup(vals[0]);
err = 0;
@ -461,15 +560,13 @@ amu_ldap_mtime(mnt_map *m, char *map, time_t *ts)
ALD *aldh = (ALD *) (m->map_data);
if (aldh == NULL) {
#ifdef DEBUG
dlog("LDAP panic: unable to find map data\n");
#endif /* DEBUG */
return (ENOENT);
}
if (amu_ldap_rebind(aldh)) {
return (ENOENT);
}
if (get_ldap_timestamp(aldh->ldap, map, ts)) {
if (get_ldap_timestamp(aldh, map, ts)) {
return (ENOENT);
}
return (0);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: info_ndbm.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/info_ndbm.c
*
*/
@ -86,8 +85,8 @@ ndbm_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
#ifdef DBM_SUFFIX
char dbfilename[256];
strcpy(dbfilename, map);
strcat(dbfilename, DBM_SUFFIX);
xstrlcpy(dbfilename, map, sizeof(dbfilename));
xstrlcat(dbfilename, DBM_SUFFIX, sizeof(dbfilename));
error = stat(dbfilename, &stb);
#else /* not DBM_SUFFIX */
error = fstat(dbm_pagfno(db), &stb);
@ -117,14 +116,14 @@ ndbm_init(mnt_map *m, char *map, time_t *tp)
#ifdef DBM_SUFFIX
char dbfilename[256];
strcpy(dbfilename, map);
strcat(dbfilename, DBM_SUFFIX);
xstrlcpy(dbfilename, map, sizeof(dbfilename));
xstrlcat(dbfilename, DBM_SUFFIX, sizeof(dbfilename));
error = stat(dbfilename, &stb);
#else /* not DBM_SUFFIX */
error = fstat(dbm_pagfno(db), &stb);
#endif /* not DBM_SUFFIX */
if (error < 0)
*tp = clocktime();
*tp = clocktime(NULL);
else
*tp = stb.st_mtime;
dbm_close(db);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: info_nis.c,v 1.6.2.5 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/info_nis.c
*
*/
@ -107,9 +106,7 @@ determine_nis_domain(void)
}
if (!*default_domain) {
nis_not_running = 1;
#ifdef DEBUG
plog(XLOG_WARNING, "NIS domain name is not set. NIS ignored.");
#endif /* DEBUG */
return ENOENT;
}
gopt.nis_domain = strdup(default_domain);
@ -144,12 +141,8 @@ callback(int status, char *key, int kl, char *val, int vl, char *data)
/* check what went wrong */
int e = ypprot_err(status);
#ifdef DEBUG
plog(XLOG_ERROR, "yp enumeration of %s: %s, status=%d, e=%d",
ncdp->ncd_map, yperr_string(e), status, e);
#else /* not DEBUG */
plog(XLOG_ERROR, "yp enumeration of %s: %s", ncdp->ncd_map, yperr_string(e));
#endif /* not DEBUG */
}
return TRUE;
}
@ -350,9 +343,7 @@ nis_init(mnt_map *m, char *map, time_t *tp)
/* NIS server found */
has_yp_order = 1;
*tp = (time_t) order;
#ifdef DEBUG
dlog("NIS master for %s@%s has order %lu", map, gopt.nis_domain, (unsigned long) order);
#endif /* DEBUG */
break;
case YPERR_YPERR:
/* NIS+ server found ! */
@ -361,9 +352,7 @@ nis_init(mnt_map *m, char *map, time_t *tp)
if (yp_master(gopt.nis_domain, map, &master)) {
return ENOENT;
} else {
#ifdef DEBUG
dlog("NIS master for %s@%s is a NIS+ server", map, gopt.nis_domain);
#endif /* DEBUG */
/* Use fake timestamps */
*tp = time(NULL);
}
@ -442,11 +431,9 @@ am_yp_all(char *indomain, char *inmap, struct ypall_callback *incallback)
&outvallen);
XFREE(outkey_old);
} while (!i);
#ifdef DEBUG
if (i) {
dlog("yp_next() returned error: %s\n", yperr_string(i));
}
#endif /* DEBUG */
if (i == YPERR_NOMORE)
return 0;
return i;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: info_nisplus.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/info_nisplus.c
*
*/
@ -74,9 +73,7 @@ nisplus_callback(const nis_name key, const nis_object *value, voidp opaquedata)
char *vp = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
struct nis_callback_data *data = (struct nis_callback_data *) opaquedata;
#ifdef DEBUG
dlog("NISplus callback for <%s,%s>", kp, vp);
#endif /* DEBUG */
(*data->ncd_fn) (data->ncd_m, kp, vp);
@ -95,6 +92,7 @@ nisplus_reload(mnt_map *m, char *map, void (*fn) ())
nis_result *result;
char *org; /* if map does not have ".org_dir" then append it */
nis_name map_name;
size_t l;
org = strstr(map, NISPLUS_ORGDIR);
if (org == NULL)
@ -103,21 +101,20 @@ nisplus_reload(mnt_map *m, char *map, void (*fn) ())
org = "";
/* make some room for the NIS map_name */
map_name = xmalloc(strlen(map) + sizeof(NISPLUS_ORGDIR));
l = strlen(map) + sizeof(NISPLUS_ORGDIR);
map_name = xmalloc(l);
if (map_name == NULL) {
plog(XLOG_ERROR, "Unable to create map_name %s: %s",
map, strerror(ENOMEM));
return ENOMEM;
}
sprintf(map_name, "%s%s", map, org);
xsnprintf(map_name, l, "%s%s", map, org);
data.ncd_m = m;
data.ncd_map = map_name;
data.ncd_fn = fn;
#ifdef DEBUG
dlog("NISplus reload for %s", map);
#endif /* DEBUG */
result = nis_list(map_name,
EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH,
@ -145,10 +142,8 @@ nisplus_search_callback(const nis_name key, const nis_object *value, voidp opaqu
{
struct nisplus_search_callback_data *data = (struct nisplus_search_callback_data *) opaquedata;
#ifdef DEBUG
dlog("NISplus search callback for <%s>", ENTRY_VAL(value, 0));
dlog("NISplus search callback value <%s>", ENTRY_VAL(value, 1));
#endif /* DEBUG */
data->value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
return TRUE;
@ -166,6 +161,7 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
struct nisplus_search_callback_data data;
nis_name index;
char *org; /* if map does not have ".org_dir" then append it */
size_t l;
org = strstr(map, NISPLUS_ORGDIR);
if (org == NULL)
@ -174,14 +170,14 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
org = "";
/* make some room for the NIS index */
index = xmalloc(sizeof('[') /* for opening selection criteria */
+sizeof(NISPLUS_KEY)
+ strlen(key)
+ sizeof(']') /* for closing selection criteria */
+sizeof(',') /* + 1 for , separator */
+strlen(map)
+ sizeof(NISPLUS_ORGDIR)
);
l = sizeof('[') /* for opening selection criteria */
+ sizeof(NISPLUS_KEY)
+ strlen(key)
+ sizeof(']') /* for closing selection criteria */
+ sizeof(',') /* + 1 for , separator */
+ strlen(map)
+ sizeof(NISPLUS_ORGDIR);
index = xmalloc(l);
if (index == NULL) {
plog(XLOG_ERROR,
"Unable to create index %s: %s",
@ -189,14 +185,12 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
strerror(ENOMEM));
return ENOMEM;
}
sprintf(index, "[%s%s],%s%s", NISPLUS_KEY, key, map, org);
xsnprintf(index, l, "[%s%s],%s%s", NISPLUS_KEY, key, map, org);
data.key = key;
data.value = NULL;
#ifdef DEBUG
dlog("NISplus search for %s", index);
#endif /* DEBUG */
result = nis_list(index,
EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH,
@ -220,11 +214,9 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
if (data.value == NULL) {
nis_object *value = result->objects.objects_val;
#ifdef DEBUG
dlog("NISplus search found <nothing>");
dlog("NISplus search for %s: %s(%d)",
map, nis_sperrno(result->status), result->status);
#endif /* DEBUG */
if (value != NULL)
data.value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
@ -233,23 +225,17 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
if (*val) {
error = 0;
#ifdef DEBUG
dlog("NISplus search found %s", *val);
#endif /* DEBUG */
} else {
error = ENOENT;
#ifdef DEBUG
dlog("NISplus search found nothing");
#endif /* DEBUG */
}
*tp = 0;
break;
case NIS_NOSUCHNAME:
#ifdef DEBUG
dlog("NISplus search returned %d", result->status);
#endif /* DEBUG */
error = ENOENT;
break;
@ -271,6 +257,7 @@ nisplus_init(mnt_map *m, char *map, time_t *tp)
char *org; /* if map does not have ".org_dir" then append it */
nis_name map_name;
int error = 0;
size_t l;
org = strstr(map, NISPLUS_ORGDIR);
if (org == NULL)
@ -279,7 +266,8 @@ nisplus_init(mnt_map *m, char *map, time_t *tp)
org = "";
/* make some room for the NIS map_name */
map_name = xmalloc(strlen(map) + sizeof(NISPLUS_ORGDIR));
l = strlen(map) + sizeof(NISPLUS_ORGDIR);
map_name = xmalloc(l);
if (map_name == NULL) {
plog(XLOG_ERROR,
"Unable to create map_name %s: %s",
@ -287,7 +275,7 @@ nisplus_init(mnt_map *m, char *map, time_t *tp)
strerror(ENOMEM));
return ENOMEM;
}
sprintf(map_name, "%s%s", map, org);
xsnprintf(map_name, l, "%s%s", map, org);
result = nis_lookup(map_name, (EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH));
@ -300,10 +288,8 @@ nisplus_init(mnt_map *m, char *map, time_t *tp)
}
if (result->status != NIS_SUCCESS) {
#ifdef DEBUG
dlog("NISplus init <%s>: %s (%d)",
map, nis_sperrno(result->status), result->status);
#endif /* DEBUG */
error = ENOENT;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: info_passwd.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/info_passwd.c
*
*/
@ -151,11 +150,11 @@ passwd_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
do {
q = strrchr(p, '/');
if (q) {
strcat(rhost, q + 1);
strcat(rhost, ".");
xstrlcat(rhost, q + 1, sizeof(rhost));
xstrlcat(rhost, ".", sizeof(rhost));
*q = '\0';
} else {
strcat(rhost, p);
xstrlcat(rhost, p, sizeof(rhost));
}
} while (q);
@ -176,11 +175,9 @@ passwd_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
p++;
else
p = "type:=nfs;rfs:=/${var0}/${var1};rhost:=${var1};sublink:=${var2};fs:=${autodir}${var3}";
sprintf(val, "var0:=%s;var1:=%s;var2:=%s;var3:=%s;%s",
dir+1, rhost, user, pw->pw_dir, p);
#ifdef DEBUG
xsnprintf(val, sizeof(val), "var0:=%s;var1:=%s;var2:=%s;var3:=%s;%s",
dir+1, rhost, user, pw->pw_dir, p);
dlog("passwd_search: map=%s key=%s -> %s", map, key, val);
#endif /* DEBUG */
if (q)
*q = '.';
*pval = strdup(val);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: info_union.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/info_union.c
*
*/
@ -81,10 +80,12 @@ union_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
char *mapd = strdup(map + UNION_PREFLEN);
char **v = strsplit(mapd, ':', '\"');
char **p;
size_t l;
for (p = v; p[1]; p++) ;
*pval = xmalloc(strlen(*p) + 5);
sprintf(*pval, "fs:=%s", *p);
l = strlen(*p) + 5;
*pval = xmalloc(l);
xsnprintf(*pval, l, "fs:=%s", *p);
XFREE(mapd);
XFREE(v);
return 0;
@ -104,7 +105,7 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
(*fn) (m, strdup("/defaults"), strdup("type:=link;opts:=nounmount;sublink:=${key}"));
for (dir = v; *dir; dir++) {
int dlen;
size_t l;
struct dirent *dp;
DIR *dirp = opendir(*dir);
@ -112,11 +113,9 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
plog(XLOG_USER, "Cannot read directory %s: %m", *dir);
continue;
}
dlen = strlen(*dir);
l = strlen(*dir) + 5;
#ifdef DEBUG
dlog("Reading directory %s...", *dir);
#endif /* DEBUG */
while ((dp = readdir(dirp))) {
char *val, *dpname = &dp->d_name[0];
if (dpname[0] == '.' &&
@ -124,11 +123,9 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
(dpname[1] == '.' && dpname[2] == '\0')))
continue;
#ifdef DEBUG
dlog("... gives %s", dp->d_name);
#endif /* DEBUG */
val = xmalloc(dlen + 5);
sprintf(val, "fs:=%s", *dir);
val = xmalloc(l);
xsnprintf(val, l + 5, "fs:=%s", *dir);
(*fn) (m, strdup(dp->d_name), val);
}
closedir(dirp);
@ -138,9 +135,10 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
* Add wildcard entry
*/
{
char *val = xmalloc(strlen(dir[-1]) + 5);
size_t l = strlen(*(dir-1)) + 5;
char *val = xmalloc(l);
sprintf(val, "fs:=%s", dir[-1]);
xsnprintf(val, l, "fs:=%s", *(dir-1));
(*fn) (m, strdup("*"), val);
}
XFREE(mapd);

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: mapc.c,v 1.7.2.7 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/mapc.c
*
*/
@ -85,8 +84,6 @@
#define MREC_PART 1
#define MREC_NONE 0
#define MAX_CHAIN 2048
static struct opt_tab mapc_opt[] =
{
{"all", MAPC_ALL},
@ -201,12 +198,17 @@ extern int ndbm_search(mnt_map *, char *, char *, char **, time_t *);
extern int ndbm_mtime(mnt_map *, char *, time_t *);
#endif /* HAVE_MAP_NDBM */
/* EXECUTABLE MAPS */
#ifdef HAVE_MAP_EXEC
extern int exec_init(mnt_map *, char *, time_t *);
extern int exec_search(mnt_map *, char *, char *, char **, time_t *);
#endif /* HAVE_MAP_EXEC */
/* FILE MAPS */
#ifdef HAVE_MAP_FILE
extern int file_init(mnt_map *, char *, time_t *);
extern int file_init_or_mtime(mnt_map *, char *, time_t *);
extern int file_reload(mnt_map *, char *, add_fn *);
extern int file_search(mnt_map *, char *, char *, char **, time_t *);
extern int file_mtime(mnt_map *, char *, time_t *);
#endif /* HAVE_MAP_FILE */
@ -302,14 +304,25 @@ static map_type maptypes[] =
#ifdef HAVE_MAP_FILE
{
"file",
file_init,
file_init_or_mtime,
file_reload,
NULL, /* isup function */
file_search,
file_mtime,
file_init_or_mtime,
MAPC_ALL
},
#endif /* HAVE_MAP_FILE */
#ifdef HAVE_MAP_EXEC
{
"exec",
exec_init,
error_reload,
NULL, /* isup function */
exec_search,
error_mtime,
MAPC_INC
},
#endif /* HAVE_MAP_EXEC */
{
"error",
error_init,
@ -337,16 +350,27 @@ kvhash_of(char *key)
void
mapc_showtypes(char *buf)
mapc_showtypes(char *buf, size_t l)
{
map_type *mt;
char *sep = "";
map_type *mt=NULL, *lastmt;
int linesize = 0, i;
i = sizeof(maptypes) / sizeof(maptypes[0]);
lastmt = maptypes + i;
buf[0] = '\0';
for (mt = maptypes; mt < maptypes + sizeof(maptypes) / sizeof(maptypes[0]); mt++) {
strcat(buf, sep);
strcat(buf, mt->name);
sep = ", ";
for (mt = maptypes; mt < lastmt; mt++) {
xstrlcat(buf, mt->name, l);
if (mt == (lastmt-1))
break; /* if last one, don't do xstrlcat's that follows */
linesize += strlen(mt->name);
if (--i > 0) {
xstrlcat(buf, ", ", l);
linesize += 2;
}
if (linesize > 54) {
linesize = 0;
xstrlcat(buf, "\n\t\t ", l);
}
}
}
@ -386,9 +410,7 @@ mapc_add_kv(mnt_map *m, char *key, char *val)
regex_t re;
#endif /* HAVE_REGEXEC */
#ifdef DEBUG
dlog("add_kv: %s -> %s", key, val);
#endif /* DEBUG */
#ifdef HAVE_REGEXEC
if (MAPC_ISRE(m)) {
@ -398,7 +420,7 @@ mapc_add_kv(mnt_map *m, char *key, char *val)
/*
* Make sure the string is bound to the start and end
*/
sprintf(pattern, "^%s$", key);
xsnprintf(pattern, sizeof(pattern), "^%s$", key);
retval = regcomp(&re, pattern, REG_ICASE);
if (retval != 0) {
char errstr[256];
@ -492,11 +514,12 @@ mapc_find_wildcard(mnt_map *m)
* Do a map reload.
* Attempt to reload without losing current data by switching the hashes
* round.
* If reloading was needed and succeeded, return 1; else return 0.
*/
static void
static int
mapc_reload_map(mnt_map *m)
{
int error;
int error, ret = 0;
kv *maphash[NKVHASH], *tmphash[NKVHASH];
time_t t;
@ -512,11 +535,9 @@ mapc_reload_map(mnt_map *m)
if (m->reloads != 0 && do_mapc_reload != 0) {
if (t <= m->modify) {
plog(XLOG_INFO, "reload of map %s is not needed (in sync)", m->map_name);
#ifdef DEBUG
dlog("map %s last load time is %d, last modify time is %d",
m->map_name, (int) m->modify, (int) t);
#endif /* DEBUG */
return;
return ret;
}
}
@ -524,9 +545,7 @@ mapc_reload_map(mnt_map *m)
memcpy((voidp) maphash, (voidp) m->kvhash, sizeof(m->kvhash));
memset((voidp) m->kvhash, 0, sizeof(m->kvhash));
#ifdef DEBUG
dlog("calling map reload on %s", m->map_name);
#endif /* DEBUG */
error = (*m->reload) (m, m->map_name, mapc_add_kv);
if (error) {
if (m->reloads == 0)
@ -547,15 +566,15 @@ mapc_reload_map(mnt_map *m)
mapc_clear(m);
memcpy((voidp) m->kvhash, (voidp) tmphash, sizeof(m->kvhash));
m->modify = t;
ret = 1;
}
m->wildcard = 0;
#ifdef DEBUG
dlog("calling mapc_search for wildcard");
#endif /* DEBUG */
error = mapc_search(m, wildcard, &m->wildcard);
if (error)
m->wildcard = 0;
return ret;
}
@ -567,7 +586,7 @@ mapc_create(char *map, char *opt, const char *type)
{
mnt_map *m = ALLOC(struct mnt_map);
map_type *mt;
time_t modify;
time_t modify = 0;
int alloc = 0;
cmdoption(opt, mapc_opt, &alloc);
@ -603,9 +622,7 @@ mapc_create(char *map, char *opt, const char *type)
for (mt = maptypes;
mt < maptypes + sizeof(maptypes) / sizeof(maptypes[0]);
mt++) {
#ifdef DEBUG
dlog("trying to initialize map %s of type %s ...", map, mt->name);
#endif /* DEBUG */
if ((*mt->init) (m, map, &modify) == 0) {
break;
}
@ -652,9 +669,7 @@ mapc_create(char *map, char *opt, const char *type)
#endif /* HAVE_REGEXEC */
}
#ifdef DEBUG
dlog("Map for %s coming from maptype %s", map, mt->name);
#endif /* DEBUG */
m->alloc = alloc;
m->reload = mt->reload;
@ -667,6 +682,8 @@ mapc_create(char *map, char *opt, const char *type)
m->refc = 1;
m->wildcard = 0;
m->reloads = 0;
/* Unfortunately with current code structure, this cannot be initialized here */
m->cfm = NULL;
/*
* synchronize cache with reality
@ -732,7 +749,7 @@ mapc_find(char *map, char *opt, const char *maptype)
* add it to the list of maps
*/
ITER(m, mnt_map, &map_list_head)
if (STREQ(m->map_name, map))
if (STREQ(m->map_name, map))
return mapc_dup(m);
m = mapc_create(map, opt, maptype);
ins_que(&m->hdr, &map_list_head);
@ -745,9 +762,9 @@ mapc_find(char *map, char *opt, const char *maptype)
* Free a map.
*/
void
mapc_free(voidp v)
mapc_free(opaque_t arg)
{
mnt_map *m = v;
mnt_map *m = (mnt_map *) arg;
/*
* Decrement the reference count.
@ -883,12 +900,15 @@ mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse)
* For example:
* "src/gnu/gcc" -> "src / gnu / *" -> "src / *"
*/
strcpy(wildname, key);
xstrlcpy(wildname, key, sizeof(wildname));
while (error && (subp = strrchr(wildname, '/'))) {
strcpy(subp, "/*");
#ifdef DEBUG
/*
* sizeof space left in subp is sizeof wildname minus what's left
* after the strchr above returned a pointer inside wildname into
* subp.
*/
xstrlcpy(subp, "/*", sizeof(wildname) - (subp - wildname));
dlog("mapc recurses on %s", wildname);
#endif /* DEBUG */
error = mapc_meta_search(m, wildname, pval, MREC_PART);
if (error)
*subp = 0;
@ -917,25 +937,42 @@ mapc_search(mnt_map *m, char *key, char **pval)
static void
mapc_sync(mnt_map *m)
{
if (m->alloc != MAPC_ROOT) {
int need_mtime_update = 0;
/* do not clear map if map service is down */
if (m->isup) {
if (!((*m->isup)(m, m->map_name))) {
plog(XLOG_ERROR, "mapc_sync: map %s is down: not clearing map", m->map_name);
return;
}
if (m->alloc == MAPC_ROOT)
return; /* nothing to do */
/* do not clear map if map service is down */
if (m->isup) {
if (!((*m->isup)(m, m->map_name))) {
plog(XLOG_ERROR, "mapc_sync: map %s is down: not clearing map", m->map_name);
return;
}
}
if (m->alloc >= MAPC_ALL) {
/* mapc_reload_map() always works */
mapc_reload_map(m);
if (m->alloc >= MAPC_ALL) {
/* mapc_reload_map() always works */
need_mtime_update = mapc_reload_map(m);
} else {
mapc_clear(m);
/*
* Attempt to find the wildcard entry
*/
mapc_find_wildcard(m);
need_mtime_update = 1; /* because mapc_clear always works */
}
/*
* To be safe, update the mtime of the mnt_map's own node, so that the
* kernel will flush all of its cached entries.
*/
if (need_mtime_update && m->cfm) {
am_node *mp = find_ap(m->cfm->cfm_dir);
if (mp) {
clocktime(&mp->am_fattr.na_mtime);
} else {
mapc_clear(m);
/*
* Attempt to find the wildcard entry
*/
mapc_find_wildcard(m);
plog(XLOG_ERROR, "cannot find map %s to update its mtime",
m->cfm->cfm_dir);
}
}
}
@ -972,7 +1009,7 @@ mapc_reload(void)
static int
root_init(mnt_map *m, char *map, time_t *tp)
{
*tp = clocktime();
*tp = clocktime(NULL);
return STREQ(map, ROOT_MAP) ? 0 : ENOENT;
}
@ -1007,36 +1044,39 @@ root_newmap(const char *dir, const char *opts, const char *map, const cf_map_t *
if (cfm) {
if (map) {
sprintf(str, "cache:=mapdefault;type:=toplvl;fs:=\"%s\"",
get_full_path(map, cfm->cfm_search_path, cfm->cfm_type));
xsnprintf(str, sizeof(str),
"cache:=mapdefault;type:=toplvl;mount_type:=%s;fs:=\"%s\"",
cfm->cfm_flags & CFM_MOUNT_TYPE_AUTOFS ? "autofs" : "nfs",
get_full_path(map, cfm->cfm_search_path, cfm->cfm_type));
if (opts && opts[0] != '\0') {
strcat(str, ";");
strcat(str, opts);
xstrlcat(str, ";", sizeof(str));
xstrlcat(str, opts, sizeof(str));
}
if (cfm->cfm_flags & CFM_BROWSABLE_DIRS_FULL)
strcat(str, ";opts:=rw,fullybrowsable");
xstrlcat(str, ";opts:=rw,fullybrowsable", sizeof(str));
if (cfm->cfm_flags & CFM_BROWSABLE_DIRS)
strcat(str, ";opts:=rw,browsable");
xstrlcat(str, ";opts:=rw,browsable", sizeof(str));
if (cfm->cfm_type) {
strcat(str, ";maptype:=");
strcat(str, cfm->cfm_type);
xstrlcat(str, ";maptype:=", sizeof(str));
xstrlcat(str, cfm->cfm_type, sizeof(str));
}
} else {
strcpy(str, opts);
xstrlcpy(str, opts, sizeof(str));
}
} else {
if (map)
sprintf(str, "cache:=mapdefault;type:=toplvl;fs:=\"%s\";%s",
map, opts ? opts : "");
xsnprintf(str, sizeof(str),
"cache:=mapdefault;type:=toplvl;fs:=\"%s\";%s",
map, opts ? opts : "");
else
strcpy(str, opts);
xstrlcpy(str, opts, sizeof(str));
}
mapc_repl_kv(root_map, strdup((char *)dir), strdup(str));
}
int
mapc_keyiter(mnt_map *m, void (*fn) (char *, voidp), voidp arg)
mapc_keyiter(mnt_map *m, key_fun *fn, opaque_t arg)
{
int i;
int c = 0;
@ -1056,10 +1096,10 @@ mapc_keyiter(mnt_map *m, void (*fn) (char *, voidp), voidp arg)
/*
* Iterate on the root map and call (*fn)() on the key of all the nodes.
* Finally throw away the root map.
* Returns the number of entries in the root map.
*/
int
root_keyiter(void (*fn)(char *, voidp), voidp arg)
root_keyiter(key_fun *fn, opaque_t arg)
{
if (root_map) {
int c = mapc_keyiter(root_map, fn, arg);
@ -1070,132 +1110,6 @@ root_keyiter(void (*fn)(char *, voidp), voidp arg)
}
/*
* Was: NEW_TOPLVL_READDIR
* Search a chain for an entry with some name.
* -Erez Zadok <ezk@cs.columbia.edu>
*/
static int
key_already_in_chain(char *keyname, const nfsentry *chain)
{
const nfsentry *tmpchain = chain;
while (tmpchain) {
if (keyname && tmpchain->ne_name && STREQ(keyname, tmpchain->ne_name))
return 1;
tmpchain = tmpchain->ne_nextentry;
}
return 0;
}
/*
* Create a chain of entries which are not linked.
* -Erez Zadok <ezk@cs.columbia.edu>
*/
nfsentry *
make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable)
{
static u_int last_cookie = (u_int) 2; /* monotonically increasing */
static nfsentry chain[MAX_CHAIN];
static int max_entries = MAX_CHAIN;
char *key;
int num_entries = 0, preflen = 0, i;
nfsentry *retval = (nfsentry *) NULL;
mntfs *mf;
mnt_map *mmp;
if (!mp) {
plog(XLOG_DEBUG, "make_entry_chain: mp is (NULL)");
return retval;
}
mf = mp->am_mnt;
if (!mf) {
plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt is (NULL)");
return retval;
}
mmp = (mnt_map *) mf->mf_private;
if (!mmp) {
plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt->mf_private is (NULL)");
return retval;
}
if (mp->am_pref)
preflen = strlen(mp->am_pref);
/* iterate over keys */
for (i = 0; i < NKVHASH; i++) {
kv *k;
for (k = mmp->kvhash[i]; k ; k = k->next) {
/*
* Skip unwanted entries which are either not real entries or
* very difficult to interpret (wildcards...) This test needs
* lots of improvement. Any takers?
*/
key = k->key;
if (!key)
continue;
/* Skip '*' */
if (!fully_browsable && strchr(key, '*'))
continue;
/*
* If the map has a prefix-string then check if the key starts with
* this string, and if it does, skip over this prefix. If it has a
* prefix and it doesn't match the start of the key, skip it.
*/
if (preflen && (preflen <= (strlen(key)))) {
if (!NSTREQ(key, mp->am_pref, preflen))
continue;
key += preflen;
} else if (preflen) {
continue;
}
/* no more '/' are allowed, unless browsable_dirs=full was used */
if (!fully_browsable && strchr(key, '/'))
continue;
/* no duplicates allowed */
if (key_already_in_chain(key, current_chain))
continue;
/* fill in a cell and link the entry */
if (num_entries >= max_entries) {
/* out of space */
plog(XLOG_DEBUG, "make_entry_chain: no more space in chain");
if (num_entries > 0) {
chain[num_entries - 1].ne_nextentry = 0;
retval = &chain[0];
}
return retval;
}
/* we have space. put entry in next cell */
++last_cookie;
chain[num_entries].ne_fileid = (u_int) last_cookie;
*(u_int *) chain[num_entries].ne_cookie = (u_int) last_cookie;
chain[num_entries].ne_name = key;
if (num_entries < max_entries - 1) { /* link to next one */
chain[num_entries].ne_nextentry = &chain[num_entries + 1];
}
++num_entries;
} /* end of "while (k)" */
} /* end of "for (i ... NKVHASH ..." */
/* terminate chain */
if (num_entries > 0) {
chain[num_entries - 1].ne_nextentry = 0;
retval = &chain[0];
}
return retval;
}
/*
* Error map
*/
@ -1260,15 +1174,15 @@ get_full_path(const char *map, const char *path, const char *type)
return map;
/* now break path into components, and search in each */
strcpy(component, path);
xstrlcpy(component, path, sizeof(component));
str = strtok(component, ":");
do {
strcpy(full_path, str);
xstrlcpy(full_path, str, sizeof(full_path));
len = strlen(full_path);
if (full_path[len - 1] != '/') /* add trailing "/" if needed */
strcat(full_path, "/");
strcat(full_path, map);
xstrlcat(full_path, "/", sizeof(full_path));
xstrlcat(full_path, map, sizeof(full_path));
if (access(full_path, R_OK) == 0)
return full_path;
str = strtok(NULL, ":");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: mntfs.c,v 1.5.2.5 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/mntfs.c
*
*/
@ -71,12 +70,14 @@ static void
init_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)
{
mf->mf_ops = ops;
mf->mf_fsflags = ops->nfs_fs_flags;
mf->mf_fo = mo;
mf->mf_mount = strdup(mp);
mf->mf_info = strdup(info);
mf->mf_auto = strdup(auto_opts);
mf->mf_mopts = strdup(mopts);
mf->mf_remopts = strdup(remopts);
mf->mf_loopdev = NULL;
mf->mf_refc = 1;
mf->mf_flags = 0;
mf->mf_error = -1;
@ -104,17 +105,25 @@ alloc_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, cha
}
/* find a matching mntfs in our list */
mntfs *
find_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)
locate_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)
{
mntfs *mf;
#ifdef DEBUG
dlog("Locating mntfs reference to %s", mp);
#endif /* DEBUG */
dlog("Locating mntfs reference to (%s,%s)", mp, info);
ITER(mf, mntfs, &mfhead) {
if (STREQ(mf->mf_mount, mp)) {
/*
* For backwards compatibility purposes, we treat already-mounted
* filesystems differently and only require a match of their mount point,
* not of their server info. After all, there is little we can do if
* the user asks us to mount two different things onto the same mount: one
* will always cover the other one.
*/
if (STREQ(mf->mf_mount, mp) &&
((mf->mf_flags & MFF_MOUNTED && !(mf->mf_fsflags & FS_DIRECT))
|| (STREQ(mf->mf_info, info) && mf->mf_ops == ops))) {
/*
* Handle cases where error ops are involved
*/
@ -125,35 +134,32 @@ find_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char
*/
if (mf->mf_ops != &amfs_error_ops)
continue;
else
return dup_mntfs(mf);
} else { /* ops != &amfs_error_ops */
/*
* If the existing ops are amfs_error_ops
* then continue...
*/
if (mf->mf_ops == &amfs_error_ops)
continue;
return dup_mntfs(mf);
}
if ((mf->mf_flags & MFF_RESTART) && amd_state == Run) {
dlog("mf->mf_flags = %#x", mf->mf_flags);
mf->mf_fo = mo;
if ((mf->mf_flags & MFF_RESTART) && amd_state < Finishing) {
/*
* Restart a previously mounted filesystem.
*/
mntfs *mf2 = alloc_mntfs(&amfs_inherit_ops, mo, mp, info, auto_opts, mopts, remopts);
#ifdef DEBUG
dlog("Restarting filesystem %s", mf->mf_mount);
#endif /* DEBUG */
/*
* Remember who we are restarting
* If we are restarting an amd internal filesystem,
* we need to initialize it a bit.
*
* We know it's internal because it is marked as toplvl.
*/
mf2->mf_private = (voidp) dup_mntfs(mf);
mf2->mf_prfree = free_mntfs;
return mf2;
if (mf->mf_ops == &amfs_toplvl_ops) {
mf->mf_ops = ops;
mf->mf_info = strealloc(mf->mf_info, info);
ops->mounted(mf); /* XXX: not right, but will do for now */
}
return mf;
}
mf->mf_fo = mo;
if (!(mf->mf_flags & (MFF_MOUNTED | MFF_MOUNTING | MFF_UNMOUNTING))) {
fserver *fs;
mf->mf_flags &= ~MFF_ERROR;
@ -164,7 +170,7 @@ find_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char
mf->mf_info = strealloc(mf->mf_info, info);
if (mf->mf_private && mf->mf_prfree) {
(*mf->mf_prfree) (mf->mf_private);
mf->mf_prfree(mf->mf_private);
mf->mf_private = 0;
}
@ -177,6 +183,18 @@ find_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char
} /* end of "if (STREQ(mf-> ..." */
} /* end of ITER */
return 0;
}
/* find a matching mntfs in our list, create a new one if none is found */
mntfs *
find_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)
{
mntfs *mf = locate_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
if (mf)
return mf;
return alloc_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
}
@ -189,7 +207,7 @@ new_mntfs(void)
static void
uninit_mntfs(mntfs *mf, int rmd)
uninit_mntfs(mntfs *mf)
{
if (mf->mf_auto)
XFREE(mf->mf_auto);
@ -202,12 +220,6 @@ uninit_mntfs(mntfs *mf, int rmd)
if (mf->mf_private && mf->mf_prfree)
(*mf->mf_prfree) (mf->mf_private);
/*
* Clean up any directories that were made
*/
if (rmd && (mf->mf_flags & MFF_MKMNT))
rmdirs(mf->mf_mount);
/* free mf_mount _AFTER_ removing the directories */
if (mf->mf_mount)
XFREE(mf->mf_mount);
@ -237,7 +249,7 @@ discard_mntfs(voidp v)
/*
* Free memory
*/
uninit_mntfs(mf, TRUE);
uninit_mntfs(mf);
XFREE(mf);
--mntfs_allocated;
@ -260,17 +272,27 @@ flush_mntfs(void)
void
free_mntfs(voidp v)
free_mntfs(opaque_t arg)
{
mntfs *mf = v;
mntfs *mf = (mntfs *) arg;
dlog("free_mntfs <%s> type %s mf_refc %d flags %x",
mf->mf_mount, mf->mf_ops->fs_type, mf->mf_refc, mf->mf_flags);
/*
* We shouldn't ever be called to free something that has
* a non-positive refcount. Something is badly wrong if
* we have been! Ignore the request for now...
*/
if(mf->mf_refc <= 0) {
plog(XLOG_ERROR, "IGNORING free_mntfs for <%s>: refc %d, flags %x",
if (mf->mf_refc <= 0) {
plog(XLOG_ERROR, "IGNORING free_mntfs for <%s>: refc %d, flags %x (bug?)",
mf->mf_mount, mf->mf_refc, mf->mf_flags);
return;
}
/* don't discard last reference of a restarted/kept mntfs */
if (mf->mf_refc == 1 && mf->mf_flags & MFF_RSTKEEP) {
plog(XLOG_ERROR, "IGNORING free_mntfs for <%s>: refc %d, flags %x (restarted)",
mf->mf_mount, mf->mf_refc, mf->mf_flags);
return;
}
@ -292,15 +314,12 @@ free_mntfs(voidp v)
mf->mf_ops->fs_type, mf->mf_mount);
}
if (mf->mf_ops->fs_flags & FS_DISCARD) {
#ifdef DEBUG
if (mf->mf_fsflags & FS_DISCARD) {
dlog("Immediately discarding mntfs for %s", mf->mf_mount);
#endif /* DEBUG */
discard_mntfs(mf);
} else {
#ifdef DEBUG
if (mf->mf_flags & MFF_RESTART) {
dlog("Discarding remount hook for %s", mf->mf_mount);
} else {
@ -309,7 +328,6 @@ free_mntfs(voidp v)
}
if (mf->mf_flags & (MFF_MOUNTED | MFF_MOUNTING | MFF_UNMOUNTING))
dlog("mntfs reference for %s still active", mf->mf_mount);
#endif /* DEBUG */
mf->mf_cid = timeout(ALLOWED_MOUNT_TIME, discard_mntfs, (voidp) mf);
}
}
@ -322,7 +340,7 @@ realloc_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *a
mntfs *mf2;
if (mf->mf_refc == 1 &&
mf->mf_ops == &amfs_inherit_ops &&
mf->mf_flags & MFF_RESTART &&
STREQ(mf->mf_mount, mp)) {
/*
* If we are inheriting then just return
@ -344,23 +362,5 @@ realloc_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *a
mf2 = find_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
free_mntfs(mf);
#if 0
/*
* XXX: EZK IS THIS RIGHT???
* The next "if" statement is what supposedly fixes bgmount() in
* that it will actually use the ops structure of the next mount
* entry, if the previous one failed.
*/
if (mf2 &&
ops &&
mf2->mf_ops != ops &&
mf2->mf_ops != &amfs_inherit_ops &&
mf2->mf_ops != &amfs_toplvl_ops &&
mf2->mf_ops != &amfs_error_ops) {
plog(XLOG_WARNING, "realloc_mntfs: copy fallback ops \"%s\" over \"%s\"",
ops->fs_type, mf2->mf_ops->fs_type);
mf2->mf_ops = ops;
}
#endif
return mf2;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: nfs_start.c,v 1.5.2.7 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/nfs_start.c
*
*/
@ -52,8 +51,8 @@
# define SELECT_MAXWAIT 16
#endif /* not SELECT_MAXWAIT */
SVCXPRT *nfsxprt;
u_short nfs_port;
SVCXPRT *nfsxprt = NULL;
u_short nfs_port = 0;
#ifndef HAVE_SIGACTION
# define MASKED_SIGS (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGCHLD)|sigmask(SIGHUP))
@ -92,7 +91,9 @@ checkup(void)
}
}
#endif /* DEBUG */
#else /* not DEBUG */
#define checkup()
#endif /* not DEBUG */
static int
@ -120,10 +121,6 @@ do_select(int smask, int fds, fd_set *fdp, struct timeval *tvp)
errno = EINTR;
} else {
select_intr_valid = 1;
/*
* Invalidate the current clock value
*/
clock_valid = 0;
/*
* Allow interrupts. If a signal
* occurs, then it will cause a longjmp
@ -151,9 +148,9 @@ do_select(int smask, int fds, fd_set *fdp, struct timeval *tvp)
/*
* Perhaps reload the cache?
*/
if (do_mapc_reload < clocktime()) {
if (do_mapc_reload < clocktime(NULL)) {
mapc_reload();
do_mapc_reload = clocktime() + ONE_HOUR;
do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval;
}
return nsel;
}
@ -168,26 +165,17 @@ rpc_pending_now(void)
{
struct timeval tvv;
int nsel;
#ifdef FD_SET
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(fwd_sock, &readfds);
#else /* not FD_SET */
int readfds = (1 << fwd_sock);
#endif /* not FD_SET */
tvv.tv_sec = tvv.tv_usec = 0;
nsel = select(FD_SETSIZE, &readfds, (fd_set *) 0, (fd_set *) 0, &tvv);
if (nsel < 1)
return (0);
#ifdef FD_SET
if (FD_ISSET(fwd_sock, &readfds))
return (1);
#else /* not FD_SET */
if (readfds & (1 << fwd_sock))
return (1);
#endif /* not FD_SET */
return (0);
}
@ -203,7 +191,7 @@ run_rpc(void)
int smask = sigblock(MASKED_SIGS);
#endif /* not HAVE_SIGACTION */
next_softclock = clocktime();
next_softclock = clocktime(NULL);
amd_state = Run;
@ -216,31 +204,27 @@ run_rpc(void)
struct timeval tvv;
int nsel;
time_t now;
fd_set readfds;
#ifdef HAVE_SVC_GETREQSET
fd_set readfds;
memmove(&readfds, &svc_fdset, sizeof(svc_fdset));
FD_SET(fwd_sock, &readfds);
#else /* not HAVE_SVC_GETREQSET */
# ifdef FD_SET
fd_set readfds;
FD_ZERO(&readfds);
# ifdef HAVE_FD_SET_FDS_BITS
readfds.fds_bits[0] = svc_fds;
FD_SET(fwd_sock, &readfds);
# else /* not FD_SET */
int readfds = svc_fds | (1 << fwd_sock);
# endif /* not FD_SET */
# else /* not HAVE_FD_SET_FDS_BITS */
readfds = svc_fds;
# endif /* not HAVE_FD_SET_FDS_BITS */
#endif /* not HAVE_SVC_GETREQSET */
FD_SET(fwd_sock, &readfds);
#ifdef DEBUG
checkup();
#endif /* DEBUG */
/*
* If the full timeout code is not called,
* then recompute the time delta manually.
*/
now = clocktime();
now = clocktime(NULL);
if (next_softclock <= now) {
if (amd_state == Finishing)
@ -251,29 +235,30 @@ run_rpc(void)
}
tvv.tv_usec = 0;
if (amd_state == Finishing && last_used_map < 0) {
if (amd_state == Finishing && get_exported_ap(0) == NULL) {
flush_mntfs();
amd_state = Quit;
break;
}
#ifdef HAVE_FS_AUTOFS
autofs_add_fdset(&readfds);
#endif /* HAVE_FS_AUTOFS */
if (tvv.tv_sec <= 0)
tvv.tv_sec = SELECT_MAXWAIT;
#ifdef DEBUG
if (tvv.tv_sec) {
dlog("Select waits for %ds", (int) tvv.tv_sec);
} else {
dlog("Select waits for Godot");
}
#endif /* DEBUG */
nsel = do_select(smask, FD_SETSIZE, &readfds, &tvv);
switch (nsel) {
case -1:
if (errno == EINTR) {
#ifdef DEBUG
dlog("select interrupted");
#endif /* DEBUG */
continue;
}
plog(XLOG_ERROR, "select: %m");
@ -284,22 +269,22 @@ run_rpc(void)
default:
/*
* Read all pending NFS responses at once to avoid having responses.
* Read all pending NFS responses at once to avoid having responses
* queue up as a consequence of retransmissions.
*/
#ifdef FD_SET
if (FD_ISSET(fwd_sock, &readfds)) {
FD_CLR(fwd_sock, &readfds);
#else /* not FD_SET */
if (readfds & (1 << fwd_sock)) {
readfds &= ~(1 << fwd_sock);
#endif /* not FD_SET */
--nsel;
do {
fwd_reply();
} while (rpc_pending_now() > 0);
}
#ifdef HAVE_FS_AUTOFS
if (nsel)
nsel = autofs_handle_fdset(&readfds, nsel);
#endif /* HAVE_FS_AUTOFS */
if (nsel) {
/*
* Anything left must be a normal
@ -308,11 +293,11 @@ run_rpc(void)
#ifdef HAVE_SVC_GETREQSET
svc_getreqset(&readfds);
#else /* not HAVE_SVC_GETREQSET */
# ifdef FD_SET
# ifdef HAVE_FD_SET_FDS_BITS
svc_getreq(readfds.fds_bits[0]);
# else /* not FD_SET */
# else /* not HAVE_FD_SET_FDS_BITS */
svc_getreq(readfds);
# endif /* not FD_SET */
# endif /* not HAVE_FD_SET_FDS_BITS */
#endif /* not HAVE_SVC_GETREQSET */
}
break;
@ -344,26 +329,16 @@ mount_automounter(int ppid)
int nmount, ret;
int soNFS;
int udp_soAMQ, tcp_soAMQ;
#ifdef HAVE_TRANSPORT_TYPE_TLI
struct netconfig *udp_amqncp, *tcp_amqncp;
#endif /* HAVE_TRANSPORT_TYPE_TLI */
/*
* Create the nfs service for amd
* This must be done first, because it attempts to bind
* to various UDP ports and we don't want anything else
* potentially taking over those ports before we get a chance
* to reserve them.
*/
#ifdef HAVE_TRANSPORT_TYPE_TLI
ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
if (ret != 0)
return ret;
ret = create_amq_service(&udp_soAMQ, &udp_amqp, &udp_amqncp, &tcp_soAMQ, &tcp_amqp, &tcp_amqncp);
#else /* not HAVE_TRANSPORT_TYPE_TLI */
ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
if (ret != 0)
return ret;
ret = create_amq_service(&udp_soAMQ, &udp_amqp, &tcp_soAMQ, &tcp_amqp);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
if (ret != 0)
return ret;
if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS)
restart_automounter_nodes();
/*
* Start RPC forwarding
@ -384,6 +359,46 @@ mount_automounter(int ppid)
if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS)
restart();
/*
* Create the nfs service for amd
* If nfs_port is already initialized, it means we
* already created the service during restart_automounter_nodes().
*/
if (nfs_port == 0) {
ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
if (ret != 0)
return ret;
}
xsnprintf(pid_fsname, sizeof(pid_fsname), "%s:(pid%ld,port%u)",
am_get_hostname(), (long) am_mypid, nfs_port);
/* security: if user sets -D amq, don't even create listening socket */
if (!amuDebug(D_AMQ)) {
ret = create_amq_service(&udp_soAMQ,
&udp_amqp,
&udp_amqncp,
&tcp_soAMQ,
&tcp_amqp,
&tcp_amqncp,
gopt.preferred_amq_port);
if (ret != 0)
return ret;
}
#ifdef HAVE_FS_AUTOFS
if (amd_use_autofs) {
/*
* Create the autofs service for amd.
*/
ret = create_autofs_service();
/* if autofs service fails it is OK if using a test amd */
if (ret != 0) {
plog(XLOG_WARNING, "autofs service registration failed, turning off autofs support");
amd_use_autofs = 0;
}
}
#endif /* HAVE_FS_AUTOFS */
/*
* Mount the top-level auto-mountpoints
*/
@ -401,41 +416,26 @@ mount_automounter(int ppid)
return 0;
}
#ifdef DEBUG
amuDebug(D_AMQ) {
#endif /* DEBUG */
if (!amuDebug(D_AMQ)) {
/*
* Complete registration of amq (first TCP service then UDP)
*/
unregister_amq();
#ifdef HAVE_TRANSPORT_TYPE_TLI
ret = svc_reg(tcp_amqp, get_amd_program_number(), AMQ_VERSION,
amq_program_1, tcp_amqncp);
#else /* not HAVE_TRANSPORT_TYPE_TLI */
ret = svc_register(tcp_amqp, get_amd_program_number(), AMQ_VERSION,
amq_program_1, IPPROTO_TCP);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
ret = amu_svc_register(tcp_amqp, get_amd_program_number(), AMQ_VERSION,
amq_program_1, IPPROTO_TCP, tcp_amqncp);
if (ret != 1) {
plog(XLOG_FATAL, "unable to register (AMQ_PROGRAM=%d, AMQ_VERSION, tcp)", get_amd_program_number());
return 3;
}
#ifdef HAVE_TRANSPORT_TYPE_TLI
ret = svc_reg(udp_amqp, get_amd_program_number(), AMQ_VERSION,
amq_program_1, udp_amqncp);
#else /* not HAVE_TRANSPORT_TYPE_TLI */
ret = svc_register(udp_amqp, get_amd_program_number(), AMQ_VERSION,
amq_program_1, IPPROTO_UDP);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
ret = amu_svc_register(udp_amqp, get_amd_program_number(), AMQ_VERSION,
amq_program_1, IPPROTO_UDP, udp_amqncp);
if (ret != 1) {
plog(XLOG_FATAL, "unable to register (AMQ_PROGRAM=%d, AMQ_VERSION, udp)", get_amd_program_number());
return 4;
}
#ifdef DEBUG
}
#endif /* DEBUG */
/*
* Start timeout_mp rolling

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: nfs_subr.c,v 1.6.2.6 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/nfs_subr.c
*
*/
@ -57,19 +56,45 @@
# define nfs_error(e) ((nfsstat)(e))
#endif /* nfs_error */
/*
* File Handle structure
*
* This is interpreted by indexing the exported array
* by fhh_id (for old-style filehandles), or by retrieving
* the node name from fhh_path (for new-style filehandles).
*
* The whole structure is mapped onto a standard fhandle_t
* when transmitted.
*/
struct am_fh {
u_int fhh_gen; /* generation number */
union {
struct {
int fhh_type; /* old or new am_fh */
pid_t fhh_pid; /* process id */
int fhh_id; /* map id */
} s;
char fhh_path[NFS_FHSIZE-sizeof(u_int)]; /* path to am_node */
} u;
};
/* forward declarations */
/* converting am-filehandles to mount-points */
static am_node *fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop);
static am_node *fh_to_mp(am_nfs_fh *fhp);
static void count_map_entries(const am_node *mp, u_int *out_blocks, u_int *out_bfree, u_int *out_bavail);
static char *
do_readlink(am_node *mp, int *error_return, nfsattrstat **attrpp)
do_readlink(am_node *mp, int *error_return)
{
char *ln;
/*
* If there is a readlink method, then use
* that, otherwise if a link exists use
* that, otherwise use the mount point.
* If there is a readlink method then use it,
* otherwise if a link exists use that,
* otherwise use the mount point.
*/
if (mp->am_mnt->mf_ops->readlink) {
int retry = 0;
@ -86,8 +111,6 @@ do_readlink(am_node *mp, int *error_return, nfsattrstat **attrpp)
} else {
ln = mp->am_mnt->mf_mount;
}
if (attrpp)
*attrpp = &mp->am_attr;
return ln;
}
@ -108,46 +131,38 @@ nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
static nfsattrstat res;
am_node *mp;
int retry;
time_t now = clocktime();
time_t now = clocktime(NULL);
#ifdef DEBUG
amuDebug(D_TRACE)
if (amuDebug(D_TRACE))
plog(XLOG_DEBUG, "getattr:");
#endif /* DEBUG */
mp = fh_to_mp2(argp, &retry);
mp = fh_to_mp3(argp, &retry, VLOOK_CREATE);
if (mp == 0) {
#ifdef DEBUG
amuDebug(D_TRACE)
if (amuDebug(D_TRACE))
plog(XLOG_DEBUG, "\tretry=%d", retry);
#endif /* DEBUG */
if (retry < 0) {
amd_stats.d_drops++;
return 0;
}
res.ns_status = nfs_error(retry);
} else {
nfsattrstat *attrp = &mp->am_attr;
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "\tstat(%s), size = %d, mtime=%ld",
mp->am_path,
(int) attrp->ns_u.ns_attr_u.na_size,
(long) attrp->ns_u.ns_attr_u.na_mtime.nt_seconds);
#endif /* DEBUG */
/* Delay unmount of what was looked up */
if (mp->am_timeo_w < 4 * gopt.am_timeo_w)
mp->am_timeo_w += gopt.am_timeo_w;
mp->am_ttl = now + mp->am_timeo_w;
mp->am_stats.s_getattr++;
return attrp;
return &res;
}
res = mp->am_attr;
if (amuDebug(D_TRACE))
plog(XLOG_DEBUG, "\tstat(%s), size = %d, mtime=%ld.%ld",
mp->am_path,
(int) res.ns_u.ns_attr_u.na_size,
(long) res.ns_u.ns_attr_u.na_mtime.nt_seconds,
(long) res.ns_u.ns_attr_u.na_mtime.nt_useconds);
/* Delay unmount of what was looked up */
if (mp->am_timeo_w < 4 * gopt.am_timeo_w)
mp->am_timeo_w += gopt.am_timeo_w;
mp->am_ttl = now + mp->am_timeo_w;
mp->am_stats.s_getattr++;
return &res;
}
@ -184,18 +199,16 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
uid_t uid;
gid_t gid;
#ifdef DEBUG
amuDebug(D_TRACE)
if (amuDebug(D_TRACE))
plog(XLOG_DEBUG, "lookup:");
#endif /* DEBUG */
/* finally, find the effective uid/gid from RPC request */
if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0)
plog(XLOG_ERROR, "cannot get uid/gid from RPC credentials");
sprintf(opt_uid, "%d", (int) uid);
sprintf(opt_gid, "%d", (int) gid);
xsnprintf(opt_uid, sizeof(uid_str), "%d", (int) uid);
xsnprintf(opt_gid, sizeof(gid_str), "%d", (int) gid);
mp = fh_to_mp2(&argp->da_fhandle, &retry);
mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_CREATE);
if (mp == 0) {
if (retry < 0) {
amd_stats.d_drops++;
@ -205,11 +218,11 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
} else {
int error;
am_node *ap;
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "\tlookuppn(%s, %s)", mp->am_path, argp->da_name);
#endif /* DEBUG */
ap = (*mp->am_mnt->mf_ops->lookuppn) (mp, argp->da_name, &error, VLOOK_CREATE);
if (amuDebug(D_TRACE))
plog(XLOG_DEBUG, "\tlookup(%s, %s)", mp->am_path, argp->da_name);
ap = mp->am_mnt->mf_ops->lookup_child(mp, argp->da_name, &error, VLOOK_CREATE);
if (ap && error < 0)
ap = mp->am_mnt->mf_ops->mount_child(ap, &error);
if (ap == 0) {
if (error < 0) {
amd_stats.d_drops++;
@ -237,7 +250,7 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
void
quick_reply(am_node *mp, int error)
nfs_quick_reply(am_node *mp, int error)
{
SVCXPRT *transp = mp->am_transp;
nfsdiropres res;
@ -271,11 +284,8 @@ quick_reply(am_node *mp, int error)
/*
* Free up transp. It's only used for one reply.
*/
XFREE(transp);
mp->am_transp = NULL;
#ifdef DEBUG
XFREE(mp->am_transp);
dlog("Quick reply sent for %s", mp->am_mnt->mf_mount);
#endif /* DEBUG */
}
}
@ -287,12 +297,10 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
am_node *mp;
int retry;
#ifdef DEBUG
amuDebug(D_TRACE)
if (amuDebug(D_TRACE))
plog(XLOG_DEBUG, "readlink:");
#endif /* DEBUG */
mp = fh_to_mp2(argp, &retry);
mp = fh_to_mp3(argp, &retry, VLOOK_CREATE);
if (mp == 0) {
readlink_retry:
if (retry < 0) {
@ -301,15 +309,12 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
}
res.rlr_status = nfs_error(retry);
} else {
char *ln = do_readlink(mp, &retry, (nfsattrstat **) 0);
char *ln = do_readlink(mp, &retry);
if (ln == 0)
goto readlink_retry;
res.rlr_status = NFS_OK;
#ifdef DEBUG
amuDebug(D_TRACE)
if (ln)
plog(XLOG_DEBUG, "\treadlink(%s) = %s", mp->am_path, ln);
#endif /* DEBUG */
if (amuDebug(D_TRACE) && ln)
plog(XLOG_DEBUG, "\treadlink(%s) = %s", mp->am_path, ln);
res.rlr_u.rlr_data_u = ln;
mp->am_stats.s_readlink++;
}
@ -388,12 +393,10 @@ unlink_or_rmdir(nfsdiropargs *argp, struct svc_req *rqstp, int unlinkp)
goto out;
}
#ifdef DEBUG
amuDebug(D_TRACE)
if (amuDebug(D_TRACE))
plog(XLOG_DEBUG, "\tremove(%s, %s)", mp->am_path, argp->da_name);
#endif /* DEBUG */
mp = (*mp->am_mnt->mf_ops->lookuppn) (mp, argp->da_name, &retry, VLOOK_DELETE);
mp = mp->am_mnt->mf_ops->lookup_child(mp, argp->da_name, &retry, VLOOK_DELETE);
if (mp == 0) {
/*
* Ignore retries...
@ -503,12 +506,10 @@ nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
am_node *mp;
int retry;
#ifdef DEBUG
amuDebug(D_TRACE)
if (amuDebug(D_TRACE))
plog(XLOG_DEBUG, "readdir:");
#endif /* DEBUG */
mp = fh_to_mp2(&argp->rda_fhandle, &retry);
mp = fh_to_mp3(&argp->rda_fhandle, &retry, VLOOK_CREATE);
if (mp == 0) {
if (retry < 0) {
amd_stats.d_drops++;
@ -516,10 +517,8 @@ nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
}
res.rdr_status = nfs_error(retry);
} else {
#ifdef DEBUG
amuDebug(D_TRACE)
if (amuDebug(D_TRACE))
plog(XLOG_DEBUG, "\treaddir(%s)", mp->am_path);
#endif /* DEBUG */
res.rdr_status = nfs_error((*mp->am_mnt->mf_ops->readdir)
(mp, argp->rda_cookie,
&res.rdr_u.rdr_reply_u, e_res, argp->rda_count));
@ -538,12 +537,10 @@ nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
int retry;
mntent_t mnt;
#ifdef DEBUG
amuDebug(D_TRACE)
if (amuDebug(D_TRACE))
plog(XLOG_DEBUG, "statfs:");
#endif /* DEBUG */
mp = fh_to_mp2(argp, &retry);
mp = fh_to_mp3(argp, &retry, VLOOK_CREATE);
if (mp == 0) {
if (retry < 0) {
amd_stats.d_drops++;
@ -552,10 +549,8 @@ nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
res.sfr_status = nfs_error(retry);
} else {
nfsstatfsokres *fp;
#ifdef DEBUG
amuDebug(D_TRACE)
if (amuDebug(D_TRACE))
plog(XLOG_DEBUG, "\tstat_fs(%s)", mp->am_path);
#endif /* DEBUG */
/*
* just return faked up file system information
@ -569,7 +564,7 @@ nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
if ((gopt.flags & CFM_SHOW_STATFS_ENTRIES) &&
mp->am_mnt && mp->am_mnt->mf_mopts) {
mnt.mnt_opts = mp->am_mnt->mf_mopts;
if (hasmntopt(&mnt, "browsable")) {
if (amu_hasmntopt(&mnt, "browsable")) {
count_map_entries(mp,
&fp->sfrok_blocks,
&fp->sfrok_bfree,
@ -629,3 +624,205 @@ count_map_entries(const am_node *mp, u_int *out_blocks, u_int *out_bfree, u_int
*out_bfree = bfree;
*out_bavail = bavail;
}
/*
* Convert from file handle to automount node.
*/
static am_node *
fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop)
{
struct am_fh *fp = (struct am_fh *) fhp;
am_node *ap = 0;
if (fp->u.s.fhh_type != 0) {
/* New filehandle type */
int len = sizeof(*fhp) - sizeof(fp->fhh_gen);
char *path = xmalloc(len+1);
/*
* Because fhp is treated as a filehandle we use memcpy
* instead of xstrlcpy.
*/
memcpy(path, (char *) fp->u.fhh_path, len);
path[len] = '\0';
/* dlog("fh_to_mp3: new filehandle: %s", path); */
ap = path_to_exported_ap(path);
XFREE(path);
} else {
/* dlog("fh_to_mp3: old filehandle: %d", fp->u.s.fhh_id); */
/*
* Check process id matches
* If it doesn't then it is probably
* from an old kernel-cached filehandle
* which is now out of date.
*/
if (fp->u.s.fhh_pid != get_server_pid()) {
dlog("fh_to_mp3: wrong pid %ld != my pid %ld",
(long) fp->u.s.fhh_pid, get_server_pid());
goto drop;
}
/*
* Get hold of the supposed mount node
*/
ap = get_exported_ap(fp->u.s.fhh_id);
}
/*
* Check the generation number in the node
* matches the one from the kernel. If not
* then the old node has been timed out and
* a new one allocated.
*/
if (ap != NULL && ap->am_gen != fp->fhh_gen)
ap = 0;
/*
* If it doesn't exists then drop the request
*/
if (!ap)
goto drop;
#if 0
/*
* If the node is hung then locate a new node
* for it. This implements the replicated filesystem
* retries.
*/
if (ap->am_mnt && FSRV_ISDOWN(ap->am_mnt->mf_server) && ap->am_parent) {
int error;
am_node *orig_ap = ap;
dlog("fh_to_mp3: %s (%s) is hung: lookup alternative file server",
orig_ap->am_path, orig_ap->am_mnt->mf_info);
/*
* Update modify time of parent node.
* With any luck the kernel will re-stat
* the child node and get new information.
*/
clocktime(&orig_ap->am_fattr.na_mtime);
/*
* Call the parent's lookup routine for an object
* with the same name. This may return -1 in error
* if a mount is in progress. In any case, if no
* mount node is returned the error code is propagated
* to the caller.
*/
if (vop == VLOOK_CREATE) {
ap = orig_ap->am_parent->am_mnt->mf_ops->lookup_child(orig_ap->am_parent, orig_ap->am_name, &error, vop);
if (ap && error < 0)
ap = orig_ap->am_parent->am_mnt->mf_ops->mount_child(ap, &error);
} else {
ap = 0;
error = ESTALE;
}
if (ap == 0) {
if (error < 0 && amd_state == Finishing)
error = ENOENT;
*rp = error;
return 0;
}
/*
* Update last access to original node. This
* avoids timing it out and so sending ESTALE
* back to the kernel.
* XXX - Not sure we need this anymore (jsp, 90/10/6).
*/
new_ttl(orig_ap);
}
#endif
/*
* Disallow references to objects being unmounted, unless
* they are automount points.
*/
if (ap->am_mnt && (ap->am_mnt->mf_flags & MFF_UNMOUNTING) &&
!(ap->am_flags & AMF_ROOT)) {
if (amd_state == Finishing)
*rp = ENOENT;
else
*rp = -1;
return 0;
}
new_ttl(ap);
drop:
if (!ap || !ap->am_mnt) {
/*
* If we are shutting down then it is likely
* that this node has disappeared because of
* a fast timeout. To avoid things thrashing
* just pretend it doesn't exist at all. If
* ESTALE is returned, some NFS clients just
* keep retrying (stupid or what - if it's
* stale now, what's it going to be in 5 minutes?)
*/
if (amd_state == Finishing)
*rp = ENOENT;
else
*rp = ESTALE;
amd_stats.d_stale++;
}
return ap;
}
static am_node *
fh_to_mp(am_nfs_fh *fhp)
{
int dummy;
return fh_to_mp3(fhp, &dummy, VLOOK_CREATE);
}
/*
* Convert from automount node to file handle.
*/
void
mp_to_fh(am_node *mp, am_nfs_fh *fhp)
{
u_int pathlen;
struct am_fh *fp = (struct am_fh *) fhp;
memset((char *) fhp, 0, sizeof(am_nfs_fh));
/* Store the generation number */
fp->fhh_gen = mp->am_gen;
pathlen = strlen(mp->am_path);
if (pathlen <= sizeof(*fhp) - sizeof(fp->fhh_gen)) {
/* dlog("mp_to_fh: new filehandle: %s", mp->am_path); */
/*
* Because fhp is treated as a filehandle we use memcpy instead of
* xstrlcpy.
*/
memcpy(fp->u.fhh_path, mp->am_path, pathlen); /* making a filehandle */
} else {
/*
* Take the process id
*/
fp->u.s.fhh_pid = get_server_pid();
/*
* ... the map number
*/
fp->u.s.fhh_id = mp->am_mapno;
/*
* ... and the generation number (previously stored)
* to make a "unique" triple that will never
* be reallocated except across reboots (which doesn't matter)
* or if we are unlucky enough to be given the same
* pid as a previous amd (very unlikely).
*/
/* dlog("mp_to_fh: old filehandle: %d", fp->u.s.fhh_id); */
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_TEMPLATE.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/ops_TEMPLATE.c
*
*/
@ -62,16 +61,14 @@
/* forward declarations */
static char *foofs_match(am_opts *fo);
static int foofs_init(mntfs *mf);
static int foofs_mount(am_node *mp);
static int foofs_fmount(mntfs *mf);
static int foofs_umount(am_node *mp);
static int foofs_fumount(mntfs *mf);
static int foofs_mount(am_node *mp, mntfs *mf);
static int foofs_umount(am_node *mp, mntfs *mf);
static am_node *foofs_lookuppn(am_node *mp, char *fname, int *error_return, int op);
static int foofs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count);
static int foofs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count);
static am_node *foofs_readlink(am_node *mp, int *error_return);
static void foofs_mounted(mntfs *mf);
static void foofs_umounted(am_node *mp);
fserver *foofs_ffserver(mntfs *mf);
static void foofs_mounted(am_node *am, mntfs *mf);
static void foofs_umounted(am_node *mp, mntfs *mf);
static fserver *foofs_ffserver(mntfs *mf);
/*
@ -84,16 +81,19 @@ am_ops foofs_ops =
foofs_match, /* match */
foofs_init, /* initialize */
foofs_mount, /* mount vnode */
foofs_fmount, /* mount vfs */
foofs_umount, /* unmount vnode */
foofs_fumount, /* unmount VFS */
foofs_lookuppn, /* lookup path-name */
foofs_lookup_child, /* lookup path-name */
foofs_mount_child, /* mount path-name */
foofs_readdir, /* read directory */
foofs_readlink, /* read link */
foofs_mounted, /* after-mount extra actions */
foofs_umounted, /* after-umount extra actions */
foofs_ffserver, /* find a file server */
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO /* flags */
foofs_get_wchan, /* return the waiting channel */
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
#ifdef HAVE_FS_AUTOFS
AUTOFS_TEMPLATE_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
@ -220,7 +220,7 @@ foofs_lookuppn(am_node *mp, char *fname, int *error_return, int op)
* If OK, fills in ep with chain of directory entries.
*/
static int
foofs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count)
foofs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count)
{
int error = 0;
@ -284,10 +284,22 @@ foofs_umounted(am_node *mp)
* Find a file server.
* Returns: fserver of found server, or NULL if not found.
*/
fserver *
static fserver *
foofs_ffserver(mntfs *mf)
{
plog(XLOG_INFO, "entering foofs_ffserver...");
return NULL;
}
/*
* Normally just return mf. Only inherit needs to do special tricks.
*/
static wchan_t *
foofs_get_wchan(mntfs *mf)
{
plog(XLOG_INFO, "entering foofs_get_wchan...");
return mf;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_cachefs.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/ops_cachefs.c
*
*/
@ -55,8 +54,8 @@
/* forward declarations */
static char *cachefs_match(am_opts *fo);
static int cachefs_init(mntfs *mf);
static int cachefs_fmount(mntfs *mf);
static int cachefs_fumount(mntfs *mf);
static int cachefs_mount(am_node *am, mntfs *mf);
static int cachefs_umount(am_node *am, mntfs *mf);
/*
@ -67,17 +66,20 @@ am_ops cachefs_ops =
"cachefs",
cachefs_match,
cachefs_init,
amfs_auto_fmount,
cachefs_fmount,
amfs_auto_fumount,
cachefs_fumount,
amfs_error_lookuppn,
cachefs_mount,
cachefs_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_error_readdir,
0, /* cachefs_readlink */
0, /* post-mount actions */
0, /* post-umount actions */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
0, /* cachefs_mounted */
0, /* cachefs_umounted */
amfs_generic_find_srvr,
0, /* cachefs_get_wchan */
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
#ifdef HAVE_FS_AUTOFS
AUTOFS_CACHEFS_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
@ -94,9 +96,7 @@ cachefs_match(am_opts *fo)
return NULL;
}
#ifdef DEBUG
dlog("CACHEFS: using cache directory \"%s\"", fo->opt_cachedir);
#endif /* DEBUG */
/* determine magic cookie to put in mtab */
return strdup(fo->opt_cachedir);
@ -113,7 +113,7 @@ cachefs_init(mntfs *mf)
/*
* Save cache directory name
*/
if (mf->mf_refc == 1) {
if (!mf->mf_private) {
mf->mf_private = (voidp) strdup(mf->mf_fo->opt_cachedir);
mf->mf_prfree = (void (*)(voidp)) free;
}
@ -128,7 +128,8 @@ cachefs_init(mntfs *mf)
* cachedir is the cache directory ($cachedir)
*/
static int
mount_cachefs(char *mntpt, char *backdir, char *cachedir, char *opts)
mount_cachefs(char *mntdir, char *backdir, char *cachedir,
char *opts, int on_autofs)
{
cachefs_args_t ca;
mntent_t mnt;
@ -142,12 +143,16 @@ mount_cachefs(char *mntpt, char *backdir, char *cachedir, char *opts)
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = mntpt;
mnt.mnt_dir = mntdir;
mnt.mnt_fsname = backdir;
mnt.mnt_type = MNTTAB_TYPE_CACHEFS;
mnt.mnt_opts = opts;
flags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
if (on_autofs)
flags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */
/* Fill in cachefs mount arguments */
@ -170,8 +175,13 @@ mount_cachefs(char *mntpt, char *backdir, char *cachedir, char *opts)
/* CFS fscdir name */
memset(ca.cfs_cacheid, 0, sizeof(ca.cfs_cacheid));
/* append cacheid and mountpoint */
sprintf(ca.cfs_cacheid, "%s:%s", ca.cfs_fsid, mntpt);
/*
* Append cacheid and mountpoint.
* sizeof(cfs_cacheid) should be C_MAX_MOUNT_FSCDIRNAME as per
* <sys/fs/cachefs_fs.h> (checked on Solaris 8).
*/
xsnprintf(ca.cfs_cacheid, sizeof(ca.cfs_cacheid),
"%s:%s", ca.cfs_fsid, mntdir);
/* convert '/' to '_' (Solaris does that...) */
cp = ca.cfs_cacheid;
while ((cp = strpbrk(cp, "/")) != NULL)
@ -192,19 +202,21 @@ mount_cachefs(char *mntpt, char *backdir, char *cachedir, char *opts)
/*
* Call generic mount routine
*/
return mount_fs(&mnt, flags, (caddr_t) &ca, 0, type, 0, NULL, mnttab_file_name);
return mount_fs(&mnt, flags, (caddr_t) &ca, 0, type, 0, NULL, mnttab_file_name, on_autofs);
}
static int
cachefs_fmount(mntfs *mf)
cachefs_mount(am_node *am, mntfs *mf)
{
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
int error;
error = mount_cachefs(mf->mf_mount,
mf->mf_fo->opt_rfs,
mf->mf_fo->opt_cachedir,
mf->mf_mopts);
mf->mf_mopts,
on_autofs);
if (error) {
errno = error;
/* according to Solaris, if errno==ESRCH, "options to not match" */
@ -220,11 +232,12 @@ cachefs_fmount(mntfs *mf)
static int
cachefs_fumount(mntfs *mf)
cachefs_umount(am_node *am, mntfs *mf)
{
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
int error;
error = UMOUNT_FS(mf->mf_mount, mnttab_file_name);
error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
/*
* In the case of cachefs, we must fsck the cache directory. Otherwise,
@ -239,7 +252,7 @@ cachefs_fumount(mntfs *mf)
cachedir = (char *) mf->mf_private;
plog(XLOG_INFO, "running fsck on cache directory \"%s\"", cachedir);
sprintf(cmd, "fsck -F cachefs %s", cachedir);
xsnprintf(cmd, sizeof(cmd), "fsck -F cachefs %s", cachedir);
system(cmd);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_cdfs.c,v 1.4.2.5 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/ops_cdfs.c
*
*/
@ -54,8 +53,8 @@
/* forward declarations */
static char *cdfs_match(am_opts *fo);
static int cdfs_fmount(mntfs *mf);
static int cdfs_fumount(mntfs *mf);
static int cdfs_mount(am_node *am, mntfs *mf);
static int cdfs_umount(am_node *am, mntfs *mf);
/*
* Ops structure
@ -65,17 +64,20 @@ am_ops cdfs_ops =
"cdfs",
cdfs_match,
0, /* cdfs_init */
amfs_auto_fmount,
cdfs_fmount,
amfs_auto_fumount,
cdfs_fumount,
amfs_error_lookuppn,
cdfs_mount,
cdfs_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_error_readdir,
0, /* cdfs_readlink */
0, /* cdfs_mounted */
0, /* cdfs_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO
amfs_generic_find_srvr,
0, /* cdfs_get_wchan */
FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
#ifdef HAVE_FS_AUTOFS
AUTOFS_CDFS_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
@ -89,10 +91,8 @@ cdfs_match(am_opts *fo)
plog(XLOG_USER, "cdfs: no source device specified");
return 0;
}
#ifdef DEBUG
dlog("CDFS: mounting device \"%s\" on \"%s\"",
fo->opt_dev, fo->opt_fs);
#endif /* DEBUG */
/*
* Determine magic cookie to put in mtab
@ -102,11 +102,11 @@ cdfs_match(am_opts *fo)
static int
mount_cdfs(char *dir, char *fs_name, char *opts)
mount_cdfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
{
cdfs_args_t cdfs_args;
mntent_t mnt;
int genflags, cdfs_flags;
int genflags, cdfs_flags, retval;
/*
* Figure out the name of the file system type.
@ -120,13 +120,13 @@ mount_cdfs(char *dir, char *fs_name, char *opts)
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
mnt.mnt_dir = mntdir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_CDFS;
mnt.mnt_opts = opts;
#if defined(MNT2_CDFS_OPT_DEFPERM) && defined(MNTTAB_OPT_DEFPERM)
if (hasmntopt(&mnt, MNTTAB_OPT_DEFPERM))
if (amu_hasmntopt(&mnt, MNTTAB_OPT_DEFPERM))
# ifdef MNT2_CDFS_OPT_DEFPERM
cdfs_flags |= MNT2_CDFS_OPT_DEFPERM;
# else /* not MNT2_CDFS_OPT_DEFPERM */
@ -135,34 +135,38 @@ mount_cdfs(char *dir, char *fs_name, char *opts)
#endif /* defined(MNT2_CDFS_OPT_DEFPERM) && defined(MNTTAB_OPT_DEFPERM) */
#if defined(MNT2_CDFS_OPT_NODEFPERM) && defined(MNTTAB_OPT_NODEFPERM)
if (hasmntopt(&mnt, MNTTAB_OPT_NODEFPERM))
if (amu_hasmntopt(&mnt, MNTTAB_OPT_NODEFPERM))
cdfs_flags |= MNT2_CDFS_OPT_NODEFPERM;
#endif /* MNTTAB_OPT_NODEFPERM */
#if defined(MNT2_CDFS_OPT_NOVERSION) && defined(MNTTAB_OPT_NOVERSION)
if (hasmntopt(&mnt, MNTTAB_OPT_NOVERSION))
if (amu_hasmntopt(&mnt, MNTTAB_OPT_NOVERSION))
cdfs_flags |= MNT2_CDFS_OPT_NOVERSION;
#endif /* defined(MNT2_CDFS_OPT_NOVERSION) && defined(MNTTAB_OPT_NOVERSION) */
#if defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP)
if (hasmntopt(&mnt, MNTTAB_OPT_RRIP))
if (amu_hasmntopt(&mnt, MNTTAB_OPT_RRIP))
cdfs_flags |= MNT2_CDFS_OPT_RRIP;
#endif /* defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP) */
#if defined(MNT2_CDFS_OPT_NORRIP) && defined(MNTTAB_OPT_NORRIP)
if (hasmntopt(&mnt, MNTTAB_OPT_NORRIP))
if (amu_hasmntopt(&mnt, MNTTAB_OPT_NORRIP))
cdfs_flags |= MNT2_CDFS_OPT_NORRIP;
#endif /* defined(MNT2_CDFS_OPT_NORRIP) && defined(MNTTAB_OPT_NORRIP) */
#if defined(MNT2_CDFS_OPT_GENS) && defined(MNTTAB_OPT_GENS)
if (hasmntopt(&mnt, MNTTAB_OPT_GENS))
if (amu_hasmntopt(&mnt, MNTTAB_OPT_GENS))
cdfs_flags |= MNT2_CDFS_OPT_GENS;
#endif /* defined(MNT2_CDFS_OPT_GENS) && defined(MNTTAB_OPT_GENS) */
#if defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT)
if (hasmntopt(&mnt, MNTTAB_OPT_EXTATT))
if (amu_hasmntopt(&mnt, MNTTAB_OPT_EXTATT))
cdfs_flags |= MNT2_CDFS_OPT_EXTATT;
#endif /* defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT) */
genflags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
if (on_autofs)
genflags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */
#ifdef HAVE_CDFS_ARGS_T_FLAGS
cdfs_args.flags = cdfs_flags;
@ -176,10 +180,6 @@ mount_cdfs(char *dir, char *fs_name, char *opts)
cdfs_args.iso_pgthresh = hasmntval(&mnt, MNTTAB_OPT_PGTHRESH);
#endif /* HAVE_CDFS_ARGS_T_ISO_PGTHRESH */
#ifdef HAVE_CDFS_ARGS_T_FSPEC
cdfs_args.fspec = fs_name;
#endif /* HAVE_CDFS_ARGS_T_FSPEC */
#ifdef HAVE_CDFS_ARGS_T_NORRIP
/* XXX: need to provide norrip mount opt */
cdfs_args.norrip = 0; /* use Rock-Ridge Protocol extensions */
@ -190,19 +190,26 @@ mount_cdfs(char *dir, char *fs_name, char *opts)
cdfs_args.ssector = 0; /* use 1st session on disk */
#endif /* HAVE_CDFS_ARGS_T_SSECTOR */
#ifdef HAVE_CDFS_ARGS_T_FSPEC
cdfs_args.fspec = fs_name;
#endif /* HAVE_CDFS_ARGS_T_FSPEC */
/*
* Call generic mount routine
*/
return mount_fs(&mnt, genflags, (caddr_t) &cdfs_args, 0, type, 0, NULL, mnttab_file_name);
retval = mount_fs(&mnt, genflags, (caddr_t) &cdfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
return retval;
}
static int
cdfs_fmount(mntfs *mf)
cdfs_mount(am_node *am, mntfs *mf)
{
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
int error;
error = mount_cdfs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
error = mount_cdfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_cdfs: %m");
@ -213,7 +220,9 @@ cdfs_fmount(mntfs *mf)
static int
cdfs_fumount(mntfs *mf)
cdfs_umount(am_node *am, mntfs *mf)
{
return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_efs.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/ops_efs.c
*
*/
@ -54,8 +53,8 @@
/* forward declarations */
static char *efs_match(am_opts *fo);
static int efs_fmount(mntfs *mf);
static int efs_fumount(mntfs *mf);
static int efs_mount(am_node *am, mntfs *mf);
static int efs_umount(am_node *am, mntfs *mf);
/*
* Ops structure
@ -65,17 +64,20 @@ am_ops efs_ops =
"efs",
efs_match,
0, /* efs_init */
amfs_auto_fmount,
efs_fmount,
amfs_auto_fumount,
efs_fumount,
amfs_error_lookuppn,
efs_mount,
efs_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_error_readdir,
0, /* efs_readlink */
0, /* efs_mounted */
0, /* efs_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
amfs_generic_find_srvr,
0, /* efs_get_wchan */
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
#ifdef HAVE_FS_AUTOFS
AUTOFS_EFS_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
@ -91,9 +93,7 @@ efs_match(am_opts *fo)
return 0;
}
#ifdef DEBUG
dlog("EFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
#endif /* DEBUG */
/*
* Determine magic cookie to put in mtab
@ -103,7 +103,7 @@ efs_match(am_opts *fo)
static int
mount_efs(char *dir, char *fs_name, char *opts)
mount_efs(char *mntdir, char *fs_name, char *opts, int on_autofs)
{
efs_args_t efs_args;
mntent_t mnt;
@ -120,12 +120,16 @@ mount_efs(char *dir, char *fs_name, char *opts)
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
mnt.mnt_dir = mntdir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_EFS;
mnt.mnt_opts = opts;
flags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
if (on_autofs)
flags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */
#ifdef HAVE_EFS_ARGS_T_FLAGS
efs_args.flags = 0; /* XXX: fix this to correct flags */
@ -137,16 +141,17 @@ mount_efs(char *dir, char *fs_name, char *opts)
/*
* Call generic mount routine
*/
return mount_fs(&mnt, flags, (caddr_t) &efs_args, 0, type, 0, NULL, mnttab_file_name);
return mount_fs(&mnt, flags, (caddr_t) &efs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
}
static int
efs_fmount(mntfs *mf)
efs_mount(am_node *am, mntfs *mf)
{
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
int error;
error = mount_efs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
error = mount_efs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_efs: %m");
@ -158,7 +163,10 @@ efs_fmount(mntfs *mf)
static int
efs_fumount(mntfs *mf)
efs_umount(am_node *am, mntfs *mf)
{
return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_lofs.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/ops_lofs.c
*
*/
@ -54,10 +53,8 @@
/* forward definitions */
static char *lofs_match(am_opts *fo);
static int lofs_fmount(mntfs *mf);
static int lofs_fumount(mntfs *mf);
static int mount_lofs(char *dir, char *fs_name, char *opts);
static int lofs_mount(am_node *am, mntfs *mf);
static int lofs_umount(am_node *am, mntfs *mf);
/*
* Ops structure
@ -67,17 +64,20 @@ am_ops lofs_ops =
"lofs",
lofs_match,
0, /* lofs_init */
amfs_auto_fmount,
lofs_fmount,
amfs_auto_fumount,
lofs_fumount,
amfs_error_lookuppn,
lofs_mount,
lofs_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_error_readdir,
0, /* lofs_readlink */
0, /* lofs_mounted */
0, /* lofs_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
amfs_generic_find_srvr,
0, /* lofs_get_wchan */
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
#ifdef HAVE_FS_AUTOFS
AUTOFS_LOFS_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
@ -91,10 +91,8 @@ lofs_match(am_opts *fo)
plog(XLOG_USER, "lofs: no source filesystem specified");
return 0;
}
#ifdef DEBUG
dlog("LOFS: mounting fs \"%s\" on \"%s\"",
fo->opt_rfs, fo->opt_fs);
#endif /* DEBUG */
/*
* Determine magic cookie to put in mtab
@ -103,8 +101,8 @@ lofs_match(am_opts *fo)
}
static int
mount_lofs(char *dir, char *fs_name, char *opts)
int
mount_lofs(char *mntdir, char *fs_name, char *opts, int on_autofs)
{
mntent_t mnt;
int flags;
@ -118,26 +116,31 @@ mount_lofs(char *dir, char *fs_name, char *opts)
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
mnt.mnt_dir = mntdir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_LOFS;
mnt.mnt_opts = opts;
flags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
if (on_autofs)
flags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */
/*
* Call generic mount routine
*/
return mount_fs(&mnt, flags, NULL, 0, type, 0, NULL, mnttab_file_name);
return mount_fs(&mnt, flags, NULL, 0, type, 0, NULL, mnttab_file_name, on_autofs);
}
static int
lofs_fmount(mntfs *mf)
lofs_mount(am_node *am, mntfs *mf)
{
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
int error;
error = mount_lofs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
error = mount_lofs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_lofs: %m");
@ -148,7 +151,9 @@ lofs_fmount(mntfs *mf)
static int
lofs_fumount(mntfs *mf)
lofs_umount(am_node *am, mntfs *mf)
{
return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_mfs.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/ops_mfs.c
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_nfs.c,v 1.6.2.6 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/ops_nfs.c
*
*/
@ -64,7 +63,7 @@
*/
#define FH_TTL (5 * 60) /* five minutes */
#define FH_TTL_ERROR (30) /* 30 seconds */
#define FHID_ALLOC(struct) (++fh_id)
#define FHID_ALLOC() (++fh_id)
/*
* The NFS layer maintains a cache of file handles.
@ -92,19 +91,26 @@
typedef struct fh_cache fh_cache;
struct fh_cache {
qelem fh_q; /* List header */
voidp fh_wchan; /* Wait channel */
wchan_t fh_wchan; /* Wait channel */
int fh_error; /* Valid data? */
int fh_id; /* Unique id */
int fh_cid; /* Callout id */
u_long fh_nfs_version; /* highest NFS version on host */
am_nfs_handle_t fh_nfs_handle; /* Handle on filesystem */
int fh_status; /* Status of last rpc */
struct sockaddr_in fh_sin; /* Address of mountd */
fserver *fh_fs; /* Server holding filesystem */
char *fh_path; /* Filesystem on host */
};
/* forward definitions */
static int call_mountd(fh_cache *fp, u_long proc, fwd_fun f, voidp wchan);
static int nfs_init(mntfs *mf);
static char *nfs_match(am_opts *fo);
static int nfs_mount(am_node *am, mntfs *mf);
static int nfs_umount(am_node *am, mntfs *mf);
static void nfs_umounted(mntfs *mf);
static int call_mountd(fh_cache *fp, u_long proc, fwd_fun f, wchan_t wchan);
static int webnfs_lookup(fh_cache *fp, fwd_fun f, wchan_t wchan);
static int fh_id = 0;
/* globals */
@ -119,25 +125,28 @@ am_ops nfs_ops =
"nfs",
nfs_match,
nfs_init,
amfs_auto_fmount,
nfs_fmount,
amfs_auto_fumount,
nfs_fumount,
amfs_error_lookuppn,
nfs_mount,
nfs_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_error_readdir,
0, /* nfs_readlink */
0, /* nfs_mounted */
nfs_umounted,
find_nfs_srvr,
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO
0, /* nfs_get_wchan */
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
#ifdef HAVE_FS_AUTOFS
AUTOFS_NFS_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
static fh_cache *
find_nfs_fhandle_cache(voidp idv, int done)
find_nfs_fhandle_cache(opaque_t arg, int done)
{
fh_cache *fp, *fp2 = 0;
int id = (long) idv; /* for 64-bit archs */
int id = (long) arg; /* for 64-bit archs */
ITER(fp, fh_cache, &fh_head) {
if (fp->fh_id == id) {
@ -146,13 +155,11 @@ find_nfs_fhandle_cache(voidp idv, int done)
}
}
#ifdef DEBUG
if (fp2) {
dlog("fh cache gives fp %#lx, fs %s", (unsigned long) fp2, fp2->fh_path);
} else {
dlog("fh cache search failed");
}
#endif /* DEBUG */
if (fp2 && !done) {
fp2->fh_error = ETIMEDOUT;
@ -164,14 +171,18 @@ find_nfs_fhandle_cache(voidp idv, int done)
/*
* Called when a filehandle appears
* Called when a filehandle appears via the mount protocol
*/
static void
got_nfs_fh(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, voidp idv, int done)
got_nfs_fh_mount(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, opaque_t arg, int done)
{
fh_cache *fp;
struct fhstatus res;
#ifdef HAVE_FS_NFS3
struct am_mountres3 res3;
#endif /* HAVE_FS_NFS3 */
fp = find_nfs_fhandle_cache(idv, done);
fp = find_nfs_fhandle_cache(arg, done);
if (!fp)
return;
@ -180,28 +191,109 @@ got_nfs_fh(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, v
* NFS protocol version.
*/
#ifdef HAVE_FS_NFS3
if (fp->fh_nfs_version == NFS_VERSION3)
fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &fp->fh_nfs_handle.v3,
(XDRPROC_T_TYPE) xdr_mountres3);
else
if (fp->fh_nfs_version == NFS_VERSION3) {
memset(&res3, 0, sizeof(res3));
fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res3,
(XDRPROC_T_TYPE) xdr_am_mountres3);
fp->fh_status = unx_error(res3.fhs_status);
memset(&fp->fh_nfs_handle.v3, 0, sizeof(am_nfs_fh3));
fp->fh_nfs_handle.v3.am_fh3_length = res3.mountres3_u.mountinfo.fhandle.fhandle3_len;
memmove(fp->fh_nfs_handle.v3.am_fh3_data,
res3.mountres3_u.mountinfo.fhandle.fhandle3_val,
fp->fh_nfs_handle.v3.am_fh3_length);
} else {
#endif /* HAVE_FS_NFS3 */
fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &fp->fh_nfs_handle.v2,
memset(&res, 0, sizeof(res));
fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res,
(XDRPROC_T_TYPE) xdr_fhstatus);
fp->fh_status = unx_error(res.fhs_status);
memmove(&fp->fh_nfs_handle.v2, &res.fhs_fh, NFS_FHSIZE);
#ifdef HAVE_FS_NFS3
}
#endif /* HAVE_FS_NFS3 */
if (!fp->fh_error) {
#ifdef DEBUG
dlog("got filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
#endif /* DEBUG */
} else {
plog(XLOG_USER, "filehandle denied for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
/*
* Wakeup anything sleeping on this filehandle
* Force the error to be EACCES. It's debatable whether it should be
* ENOENT instead, but the server really doesn't give us any clues, and
* EACCES is more in line with the "filehandle denied" message.
*/
if (fp->fh_wchan) {
#ifdef DEBUG
dlog("Calling wakeup on %#lx", (unsigned long) fp->fh_wchan);
#endif /* DEBUG */
wakeup(fp->fh_wchan);
}
fp->fh_error = EACCES;
}
/*
* Wakeup anything sleeping on this filehandle
*/
if (fp->fh_wchan) {
dlog("Calling wakeup on %#lx", (unsigned long) fp->fh_wchan);
wakeup(fp->fh_wchan);
}
}
/*
* Called when a filehandle appears via WebNFS
*/
static void
got_nfs_fh_webnfs(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, opaque_t arg, int done)
{
fh_cache *fp;
nfsdiropres res;
#ifdef HAVE_FS_NFS3
am_LOOKUP3res res3;
#endif /* HAVE_FS_NFS3 */
fp = find_nfs_fhandle_cache(arg, done);
if (!fp)
return;
/*
* retrieve the correct RPC reply for the file handle, based on the
* NFS protocol version.
*/
#ifdef HAVE_FS_NFS3
if (fp->fh_nfs_version == NFS_VERSION3) {
memset(&res3, 0, sizeof(res3));
fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res3,
(XDRPROC_T_TYPE) xdr_am_LOOKUP3res);
fp->fh_status = unx_error(res3.status);
memset(&fp->fh_nfs_handle.v3, 0, sizeof(am_nfs_fh3));
fp->fh_nfs_handle.v3.am_fh3_length = res3.res_u.ok.object.am_fh3_length;
memmove(fp->fh_nfs_handle.v3.am_fh3_data,
res3.res_u.ok.object.am_fh3_data,
fp->fh_nfs_handle.v3.am_fh3_length);
} else {
#endif /* HAVE_FS_NFS3 */
memset(&res, 0, sizeof(res));
fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res,
(XDRPROC_T_TYPE) xdr_diropres);
fp->fh_status = unx_error(res.dr_status);
memmove(&fp->fh_nfs_handle.v2, &res.dr_u.dr_drok_u.drok_fhandle, NFS_FHSIZE);
#ifdef HAVE_FS_NFS3
}
#endif /* HAVE_FS_NFS3 */
if (!fp->fh_error) {
dlog("got filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
} else {
plog(XLOG_USER, "filehandle denied for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
/*
* Force the error to be EACCES. It's debatable whether it should be
* ENOENT instead, but the server really doesn't give us any clues, and
* EACCES is more in line with the "filehandle denied" message.
*/
fp->fh_error = EACCES;
}
/*
* Wakeup anything sleeping on this filehandle
*/
if (fp->fh_wchan) {
dlog("Calling wakeup on %#lx", (unsigned long) fp->fh_wchan);
wakeup(fp->fh_wchan);
}
}
@ -212,8 +304,12 @@ flush_nfs_fhandle_cache(fserver *fs)
fh_cache *fp;
ITER(fp, fh_cache, &fh_head) {
if (fp->fh_fs == fs || fs == 0) {
fp->fh_sin.sin_port = (u_short) 0;
if (fp->fh_fs == fs || fs == NULL) {
/*
* Only invalidate port info for non-WebNFS servers
*/
if (!(fp->fh_fs->fs_flags & FSF_WEBNFS))
fp->fh_sin.sin_port = (u_short) 0;
fp->fh_error = -1;
}
}
@ -221,15 +317,13 @@ flush_nfs_fhandle_cache(fserver *fs)
static void
discard_fh(voidp v)
discard_fh(opaque_t arg)
{
fh_cache *fp = v;
fh_cache *fp = (fh_cache *) arg;
rem_que(&fp->fh_q);
if (fp->fh_fs) {
#ifdef DEBUG
dlog("Discarding filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
#endif /* DEBUG */
free_srvr(fp->fh_fs);
}
if (fp->fh_path)
@ -242,88 +336,92 @@ discard_fh(voidp v)
* Determine the file handle for a node
*/
static int
prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, voidp wchan)
prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, mntfs *mf)
{
fh_cache *fp, *fp_save = 0;
int error;
int reuse_id = FALSE;
#ifdef DEBUG
dlog("Searching cache for %s:%s", fs->fs_host, path);
#endif /* DEBUG */
/*
* First search the cache
*/
ITER(fp, fh_cache, &fh_head) {
if (fs == fp->fh_fs && STREQ(path, fp->fh_path)) {
switch (fp->fh_error) {
case 0:
plog(XLOG_INFO, "prime_nfs_fhandle_cache: NFS version %d", (int) fp->fh_nfs_version);
#ifdef HAVE_FS_NFS3
if (fp->fh_nfs_version == NFS_VERSION3)
error = fp->fh_error = unx_error(fp->fh_nfs_handle.v3.fhs_status);
else
#endif /* HAVE_FS_NFS3 */
error = fp->fh_error = unx_error(fp->fh_nfs_handle.v2.fhs_status);
if (error == 0) {
if (fhbuf) {
#ifdef HAVE_FS_NFS3
if (fp->fh_nfs_version == NFS_VERSION3)
memmove((voidp) &(fhbuf->v3), (voidp) &(fp->fh_nfs_handle.v3),
sizeof(fp->fh_nfs_handle.v3));
else
#endif /* HAVE_FS_NFS3 */
memmove((voidp) &(fhbuf->v2), (voidp) &(fp->fh_nfs_handle.v2),
sizeof(fp->fh_nfs_handle.v2));
}
if (fp->fh_cid)
untimeout(fp->fh_cid);
fp->fh_cid = timeout(FH_TTL, discard_fh, (voidp) fp);
} else if (error == EACCES) {
/*
* Now decode the file handle return code.
*/
plog(XLOG_INFO, "Filehandle denied for \"%s:%s\"",
fs->fs_host, path);
} else {
errno = error; /* XXX */
plog(XLOG_INFO, "Filehandle error for \"%s:%s\": %m",
fs->fs_host, path);
if (fs != fp->fh_fs || !STREQ(path, fp->fh_path))
continue; /* skip to next ITER item */
/* else we got a match */
switch (fp->fh_error) {
case 0:
plog(XLOG_INFO, "prime_nfs_fhandle_cache: NFS version %d", (int) fp->fh_nfs_version);
error = fp->fh_error = fp->fh_status;
if (error == 0) {
if (mf->mf_flags & MFF_NFS_SCALEDOWN) {
fp_save = fp;
/* XXX: why reuse the ID? */
reuse_id = TRUE;
break;
}
if (fhbuf) {
#ifdef HAVE_FS_NFS3
if (fp->fh_nfs_version == NFS_VERSION3) {
memmove((voidp) &(fhbuf->v3), (voidp) &(fp->fh_nfs_handle.v3),
sizeof(fp->fh_nfs_handle.v3));
} else
#endif /* HAVE_FS_NFS3 */
{
memmove((voidp) &(fhbuf->v2), (voidp) &(fp->fh_nfs_handle.v2),
sizeof(fp->fh_nfs_handle.v2));
}
}
if (fp->fh_cid)
untimeout(fp->fh_cid);
fp->fh_cid = timeout(FH_TTL, discard_fh, (opaque_t) fp);
} else if (error == EACCES) {
/*
* The error was returned from the remote mount daemon.
* Policy: this error will be cached for now...
* Now decode the file handle return code.
*/
return error;
case -1:
/*
* Still thinking about it, but we can re-use.
*/
fp_save = fp;
reuse_id = TRUE;
break;
default:
/*
* Return the error.
* Policy: make sure we recompute if required again
* in case this was caused by a network failure.
* This can thrash mountd's though... If you find
* your mountd going slowly then:
* 1. Add a fork() loop to main.
* 2. Remove the call to innetgr() and don't use
* netgroups, especially if you don't use YP.
*/
error = fp->fh_error;
fp->fh_error = -1;
return error;
plog(XLOG_INFO, "Filehandle denied for \"%s:%s\"",
fs->fs_host, path);
} else {
errno = error; /* XXX */
plog(XLOG_INFO, "Filehandle error for \"%s:%s\": %m",
fs->fs_host, path);
}
/*
* The error was returned from the remote mount daemon.
* Policy: this error will be cached for now...
*/
return error;
case -1:
/*
* Still thinking about it, but we can re-use.
*/
fp_save = fp;
reuse_id = TRUE;
break;
}
}
default:
/*
* Return the error.
* Policy: make sure we recompute if required again
* in case this was caused by a network failure.
* This can thrash mountd's though... If you find
* your mountd going slowly then:
* 1. Add a fork() loop to main.
* 2. Remove the call to innetgr() and don't use
* netgroups, especially if you don't use YP.
*/
error = fp->fh_error;
fp->fh_error = -1;
return error;
} /* end of switch statement */
} /* end of ITER loop */
/*
* Not in cache
@ -342,13 +440,13 @@ prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, voidp w
ins_que(&fp->fh_q, &fh_head);
}
if (!reuse_id)
fp->fh_id = FHID_ALLOC(struct );
fp->fh_wchan = wchan;
fp->fh_id = FHID_ALLOC();
fp->fh_wchan = get_mntfs_wchan(mf);
fp->fh_error = -1;
fp->fh_cid = timeout(FH_TTL, discard_fh, (voidp) fp);
fp->fh_cid = timeout(FH_TTL, discard_fh, (opaque_t) fp);
/*
* if fs->fs_ip is null, remote server is probably down.
* If fs->fs_ip is null, remote server is probably down.
*/
if (!fs->fs_ip) {
/* Mark the fileserver down and invalid again */
@ -359,18 +457,25 @@ prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, voidp w
}
/*
* If the address has changed then don't try to re-use the
* port information
* Either fp has been freshly allocated or the address has changed.
* Initialize address and nfs version. Don't try to re-use the port
* information unless using WebNFS where the port is fixed either by
* the spec or the "port" mount option.
*/
if (fp->fh_sin.sin_addr.s_addr != fs->fs_ip->sin_addr.s_addr) {
fp->fh_sin = *fs->fs_ip;
fp->fh_sin.sin_port = 0;
if (!(mf->mf_flags & MFF_WEBNFS))
fp->fh_sin.sin_port = 0;
fp->fh_nfs_version = fs->fs_version;
}
fp->fh_fs = dup_srvr(fs);
fp->fh_path = strdup(path);
error = call_mountd(fp, MOUNTPROC_MNT, got_nfs_fh, wchan);
if (mf->mf_flags & MFF_WEBNFS)
error = webnfs_lookup(fp, got_nfs_fh_webnfs, get_mntfs_wchan(mf));
else
error = call_mountd(fp, MOUNTPROC_MNT, got_nfs_fh_mount, get_mntfs_wchan(mf));
if (error) {
/*
* Local error - cache for a short period
@ -378,7 +483,7 @@ prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, voidp w
*/
untimeout(fp->fh_cid);
fp->fh_cid = timeout(error < 0 ? 2 * ALLOWED_MOUNT_TIME : FH_TTL_ERROR,
discard_fh, (voidp) fp);
discard_fh, (opaque_t) fp);
fp->fh_error = error;
} else {
error = fp->fh_error;
@ -419,11 +524,11 @@ make_nfs_auth(void)
static int
call_mountd(fh_cache *fp, u_long proc, fwd_fun f, voidp wchan)
call_mountd(fh_cache *fp, u_long proc, fwd_fun fun, wchan_t wchan)
{
struct rpc_msg mnt_msg;
int len;
char iobuf[8192];
char iobuf[UDPMSGSIZE];
int error;
u_long mnt_version;
@ -434,17 +539,17 @@ call_mountd(fh_cache *fp, u_long proc, fwd_fun f, voidp wchan)
}
if (fp->fh_sin.sin_port == 0) {
u_short port;
error = nfs_srvr_port(fp->fh_fs, &port, wchan);
u_short mountd_port;
error = get_mountd_port(fp->fh_fs, &mountd_port, wchan);
if (error)
return error;
fp->fh_sin.sin_port = port;
fp->fh_sin.sin_port = mountd_port;
}
/* find the right version of the mount protocol */
#ifdef HAVE_FS_NFS3
if (fp->fh_nfs_version == NFS_VERSION3)
mnt_version = MOUNTVERS3;
mnt_version = AM_MOUNTVERS3;
else
#endif /* HAVE_FS_NFS3 */
mnt_version = MOUNTVERS;
@ -462,40 +567,128 @@ call_mountd(fh_cache *fp, u_long proc, fwd_fun f, voidp wchan)
if (len > 0) {
error = fwd_packet(MK_RPC_XID(RPC_XID_MOUNTD, fp->fh_id),
(voidp) iobuf,
iobuf,
len,
&fp->fh_sin,
&fp->fh_sin,
(voidp) ((long) fp->fh_id), /* for 64-bit archs */
f);
(opaque_t) ((long) fp->fh_id), /* cast to long needed for 64-bit archs */
fun);
} else {
error = -len;
}
/*
* It may be the case that we're sending to the wrong MOUNTD port. This
* occurs if mountd is restarted on the server after the port has been
* looked up and stored in the filehandle cache somewhere. The correct
* solution, if we're going to cache port numbers is to catch the ICMP
* port unreachable reply from the server and cause the portmap request
* to be redone. The quick solution here is to invalidate the MOUNTD
* port.
*/
/*
* It may be the case that we're sending to the wrong MOUNTD port. This
* occurs if mountd is restarted on the server after the port has been
* looked up and stored in the filehandle cache somewhere. The correct
* solution, if we're going to cache port numbers is to catch the ICMP
* port unreachable reply from the server and cause the portmap request
* to be redone. The quick solution here is to invalidate the MOUNTD
* port.
*/
fp->fh_sin.sin_port = 0;
return error;
}
static int
webnfs_lookup(fh_cache *fp, fwd_fun fun, wchan_t wchan)
{
struct rpc_msg wnfs_msg;
int len;
char iobuf[UDPMSGSIZE];
int error;
u_long proc;
XDRPROC_T_TYPE xdr_fn;
voidp argp;
nfsdiropargs args;
#ifdef HAVE_FS_NFS3
am_LOOKUP3args args3;
#endif
char *wnfs_path;
size_t l;
if (!nfs_auth) {
error = make_nfs_auth();
if (error)
return error;
}
if (fp->fh_sin.sin_port == 0) {
/* FIXME: wrong, don't discard sin_port in the first place for WebNFS. */
plog(XLOG_WARNING, "webnfs_lookup: port == 0 for nfs on %s, fixed",
fp->fh_fs->fs_host);
fp->fh_sin.sin_port = htons(NFS_PORT);
}
/*
* Use native path like the rest of amd (cf. RFC 2054, 6.1).
*/
l = strlen(fp->fh_path) + 2;
wnfs_path = (char *) xmalloc(l);
wnfs_path[0] = 0x80;
xstrlcpy(wnfs_path + 1, fp->fh_path, l - 1);
/* find the right program and lookup procedure */
#ifdef HAVE_FS_NFS3
if (fp->fh_nfs_version == NFS_VERSION3) {
proc = AM_NFSPROC3_LOOKUP;
xdr_fn = (XDRPROC_T_TYPE) xdr_am_LOOKUP3args;
argp = &args3;
/* WebNFS public file handle */
args3.what.dir.am_fh3_length = 0;
args3.what.name = wnfs_path;
} else {
#endif /* HAVE_FS_NFS3 */
proc = NFSPROC_LOOKUP;
xdr_fn = (XDRPROC_T_TYPE) xdr_diropargs;
argp = &args;
/* WebNFS public file handle */
memset(&args.da_fhandle, 0, NFS_FHSIZE);
args.da_name = wnfs_path;
#ifdef HAVE_FS_NFS3
}
#endif /* HAVE_FS_NFS3 */
plog(XLOG_INFO, "webnfs_lookup: NFS version %d", (int) fp->fh_nfs_version);
rpc_msg_init(&wnfs_msg, NFS_PROGRAM, fp->fh_nfs_version, proc);
len = make_rpc_packet(iobuf,
sizeof(iobuf),
proc,
&wnfs_msg,
argp,
(XDRPROC_T_TYPE) xdr_fn,
nfs_auth);
if (len > 0) {
error = fwd_packet(MK_RPC_XID(RPC_XID_WEBNFS, fp->fh_id),
iobuf,
len,
&fp->fh_sin,
&fp->fh_sin,
(opaque_t) ((long) fp->fh_id), /* cast to long needed for 64-bit archs */
fun);
} else {
error = -len;
}
XFREE(wnfs_path);
return error;
}
/*
* NFS needs the local filesystem, remote filesystem
* remote hostname.
* Local filesystem defaults to remote and vice-versa.
*/
char *
static char *
nfs_match(am_opts *fo)
{
char *xmtab;
size_t l;
if (fo->opt_fs && !fo->opt_rfs)
fo->opt_rfs = fo->opt_fs;
@ -511,12 +704,11 @@ nfs_match(am_opts *fo)
/*
* Determine magic cookie to put in mtab
*/
xmtab = (char *) xmalloc(strlen(fo->opt_rhost) + strlen(fo->opt_rfs) + 2);
sprintf(xmtab, "%s:%s", fo->opt_rhost, fo->opt_rfs);
#ifdef DEBUG
l = strlen(fo->opt_rhost) + strlen(fo->opt_rfs) + 2;
xmtab = (char *) xmalloc(l);
xsnprintf(xmtab, l, "%s:%s", fo->opt_rhost, fo->opt_rfs);
dlog("NFS: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
fo->opt_rhost, fo->opt_rfs, fo->opt_fs);
#endif /* DEBUG */
return xmtab;
}
@ -525,24 +717,36 @@ nfs_match(am_opts *fo)
/*
* Initialize am structure for nfs
*/
int
static int
nfs_init(mntfs *mf)
{
int error;
am_nfs_handle_t fhs;
char *colon;
if (mf->mf_private)
return 0;
if (mf->mf_private) {
if (mf->mf_flags & MFF_NFS_SCALEDOWN) {
fserver *fs;
/* tell remote mountd that we're done with this filehandle */
mf->mf_ops->umounted(mf);
mf->mf_prfree(mf->mf_private);
fs = mf->mf_ops->ffserver(mf);
free_srvr(mf->mf_server);
mf->mf_server = fs;
} else
return 0;
}
colon = strchr(mf->mf_info, ':');
if (colon == 0)
return ENOENT;
error = prime_nfs_fhandle_cache(colon + 1, mf->mf_server, &fhs, (voidp) mf);
error = prime_nfs_fhandle_cache(colon + 1, mf->mf_server, &fhs, mf);
if (!error) {
mf->mf_private = (voidp) ALLOC(am_nfs_handle_t);
mf->mf_prfree = (void (*)(voidp)) free;
mf->mf_private = (opaque_t) ALLOC(am_nfs_handle_t);
mf->mf_prfree = (void (*)(opaque_t)) free;
memmove(mf->mf_private, (voidp) &fhs, sizeof(fhs));
}
return error;
@ -550,18 +754,20 @@ nfs_init(mntfs *mf)
int
mount_nfs_fh(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *mf)
mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf)
{
MTYPE_TYPE type;
char *colon;
char *xopts;
char *xopts=NULL, transp_timeo_opts[40], transp_retrans_opts[40];
char host[MAXHOSTNAMELEN + MAXPATHLEN + 2];
fserver *fs = mf->mf_server;
u_long nfs_version = fs->fs_version;
char *nfs_proto = fs->fs_proto; /* "tcp" or "udp" */
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
int error;
int genflags;
int retry;
int proto = AMU_TYPE_NONE;
mntent_t mnt;
nfs_args_t nfs_args;
@ -575,26 +781,48 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *
#ifdef MOUNT_TABLE_ON_FILE
*colon = '\0';
#endif /* MOUNT_TABLE_ON_FILE */
strncpy(host, fs_name, sizeof(host));
xstrlcpy(host, fs_name, sizeof(host));
#ifdef MOUNT_TABLE_ON_FILE
*colon = ':';
#endif /* MOUNT_TABLE_ON_FILE */
#ifdef MAXHOSTNAMELEN
/* most kernels have a name length restriction */
if (strlen(host) >= MAXHOSTNAMELEN)
strcpy(host + MAXHOSTNAMELEN - 3, "..");
xstrlcpy(host + MAXHOSTNAMELEN - 3, "..",
sizeof(host) - MAXHOSTNAMELEN + 3);
#endif /* MAXHOSTNAMELEN */
/*
* Create option=VAL for udp/tcp specific timeouts and retrans values, but
* only if these options were specified.
*/
transp_timeo_opts[0] = transp_retrans_opts[0] = '\0'; /* initialize */
if (STREQ(nfs_proto, "udp"))
proto = AMU_TYPE_UDP;
else if (STREQ(nfs_proto, "tcp"))
proto = AMU_TYPE_TCP;
if (proto != AMU_TYPE_NONE) {
if (gopt.amfs_auto_timeo[proto] > 0)
xsnprintf(transp_timeo_opts, sizeof(transp_timeo_opts), "%s=%d,",
MNTTAB_OPT_TIMEO, gopt.amfs_auto_timeo[proto]);
if (gopt.amfs_auto_retrans[proto] > 0)
xsnprintf(transp_retrans_opts, sizeof(transp_retrans_opts), "%s=%d,",
MNTTAB_OPT_RETRANS, gopt.amfs_auto_retrans[proto]);
}
if (mf->mf_remopts && *mf->mf_remopts &&
!islocalnet(fs->fs_ip->sin_addr.s_addr)) {
plog(XLOG_INFO, "Using remopts=\"%s\"", mf->mf_remopts);
xopts = strdup(mf->mf_remopts);
/* use transp_opts first, so map-specific opts will override */
xopts = str3cat(xopts, transp_timeo_opts, transp_retrans_opts, mf->mf_remopts);
} else {
xopts = strdup(opts);
/* use transp_opts first, so map-specific opts will override */
xopts = str3cat(xopts, transp_timeo_opts, transp_retrans_opts, mf->mf_mopts);
}
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
mnt.mnt_dir = mntdir;
mnt.mnt_fsname = fs_name;
mnt.mnt_opts = xopts;
@ -626,18 +854,19 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *
}
#endif /* HAVE_FS_NFS3 */
plog(XLOG_INFO, "mount_nfs_fh: NFS version %d", (int) nfs_version);
#if defined(HAVE_FS_NFS3) || defined(HAVE_TRANSPORT_TYPE_TLI)
plog(XLOG_INFO, "mount_nfs_fh: using NFS transport %s", nfs_proto);
#endif /* defined(HAVE_FS_NFS3) || defined(HAVE_TRANSPORT_TYPE_TLI) */
retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
if (retry <= 0)
retry = 1; /* XXX */
genflags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
if (on_autofs)
genflags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */
/* setup the many fields and flags within nfs_args */
#ifdef HAVE_TRANSPORT_TYPE_TLI
compute_nfs_args(&nfs_args,
&mnt,
genflags,
@ -648,27 +877,14 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *
fhp,
host,
fs_name);
#else /* not HAVE_TRANSPORT_TYPE_TLI */
compute_nfs_args(&nfs_args,
&mnt,
genflags,
fs->fs_ip,
nfs_version,
nfs_proto,
fhp,
host,
fs_name);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/* finally call the mounting function */
#ifdef DEBUG
amuDebug(D_TRACE) {
if (amuDebug(D_TRACE)) {
print_nfs_args(&nfs_args, nfs_version);
plog(XLOG_DEBUG, "Generic mount flags 0x%x used for NFS mount", genflags);
}
#endif /* DEBUG */
error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type,
nfs_version, nfs_proto, mnttab_file_name);
nfs_version, nfs_proto, mnttab_file_name, on_autofs);
XFREE(xopts);
#ifdef HAVE_TRANSPORT_TYPE_TLI
@ -682,39 +898,62 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *
static int
mount_nfs(char *dir, char *fs_name, char *opts, mntfs *mf)
nfs_mount(am_node *am, mntfs *mf)
{
int error = 0;
mntent_t mnt;
if (!mf->mf_private) {
plog(XLOG_ERROR, "Missing filehandle for %s", fs_name);
plog(XLOG_ERROR, "Missing filehandle for %s", mf->mf_info);
return EINVAL;
}
return mount_nfs_fh((am_nfs_handle_t *) mf->mf_private, dir, fs_name, opts, mf);
}
mnt.mnt_opts = mf->mf_mopts;
if (amu_hasmntopt(&mnt, "softlookup") ||
(amu_hasmntopt(&mnt, "soft") && !amu_hasmntopt(&mnt, "nosoftlookup")))
am->am_flags |= AMF_SOFTLOOKUP;
error = mount_nfs_fh((am_nfs_handle_t *) mf->mf_private,
mf->mf_mount,
mf->mf_info,
mf);
int
nfs_fmount(mntfs *mf)
{
int error = 0;
error = mount_nfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, mf);
#ifdef DEBUG
if (error) {
errno = error;
dlog("mount_nfs: %m");
}
#endif /* DEBUG */
return error;
}
int
nfs_fumount(mntfs *mf)
static int
nfs_umount(am_node *am, mntfs *mf)
{
int error = UMOUNT_FS(mf->mf_mount, mnttab_file_name);
int unmount_flags, new_unmount_flags, error;
unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
#if defined(HAVE_UMOUNT2) && (defined(MNT2_GEN_OPT_FORCE) || defined(MNT2_GEN_OPT_DETACH))
/*
* If the attempt to unmount failed with EBUSY, and this fserver was
* marked for forced unmounts, then use forced/lazy unmounts.
*/
if (error == EBUSY &&
gopt.flags & CFM_FORCED_UNMOUNTS &&
mf->mf_server->fs_flags & FSF_FORCE_UNMOUNT) {
plog(XLOG_INFO, "EZK: nfs_umount: trying forced/lazy unmounts");
/*
* XXX: turning off the FSF_FORCE_UNMOUNT may not be perfectly
* incorrect. Multiple nodes may need to be timed out and restarted for
* a single hung fserver.
*/
mf->mf_server->fs_flags &= ~FSF_FORCE_UNMOUNT;
new_unmount_flags = unmount_flags | AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH;
error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, new_unmount_flags);
}
#endif /* HAVE_UMOUNT2 && (MNT2_GEN_OPT_FORCE || MNT2_GEN_OPT_DETACH) */
/*
* Here is some code to unmount 'restarted' file systems.
@ -743,12 +982,14 @@ nfs_fumount(mntfs *mf)
if (NSTREQ(mf->mf_mount, new_mf->mf_mount, len) &&
new_mf->mf_mount[len] == '/') {
UMOUNT_FS(new_mf->mf_mount, mnttab_file_name);
new_unmount_flags =
(new_mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
UMOUNT_FS(new_mf->mf_mount, mnttab_file_name, new_unmount_flags);
didsome = 1;
}
}
if (didsome)
error = UMOUNT_FS(mf->mf_mount, mnttab_file_name);
error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
}
if (error)
return error;
@ -757,38 +998,35 @@ nfs_fumount(mntfs *mf)
}
void
nfs_umounted(am_node *mp)
static void
nfs_umounted(mntfs *mf)
{
/*
* Don't bother to inform remote mountd that we are finished. Until a
* full track of filehandles is maintained the mountd unmount callback
* cannot be done correctly anyway...
*/
mntfs *mf = mp->am_mnt;
fserver *fs;
char *colon, *path;
if (mf->mf_error || mf->mf_refc > 1)
return;
fs = mf->mf_server;
/*
* No need to inform mountd when WebNFS is in use.
*/
if (mf->mf_flags & MFF_WEBNFS)
return;
/*
* Call the mount daemon on the server to announce that we are not using
* the fs any more.
*
* This is *wrong*. The mountd should be called when the fhandle is
* XXX: This is *wrong*. The mountd should be called when the fhandle is
* flushed from the cache, and a reference held to the cached entry while
* the fs is mounted...
*/
fs = mf->mf_server;
colon = path = strchr(mf->mf_info, ':');
if (fs && colon) {
fh_cache f;
#ifdef DEBUG
dlog("calling mountd for %s", mf->mf_info);
#endif /* DEBUG */
*path++ = '\0';
f.fh_path = path;
f.fh_sin = *fs->fs_ip;
@ -797,8 +1035,8 @@ nfs_umounted(am_node *mp)
f.fh_fs = fs;
f.fh_id = 0;
f.fh_error = 0;
prime_nfs_fhandle_cache(colon + 1, mf->mf_server, (am_nfs_handle_t *) 0, (voidp) mf);
call_mountd(&f, MOUNTPROC_UMNT, (fwd_fun) 0, (voidp) 0);
prime_nfs_fhandle_cache(colon + 1, mf->mf_server, (am_nfs_handle_t *) 0, mf);
call_mountd(&f, MOUNTPROC_UMNT, (fwd_fun *) 0, (wchan_t) 0);
*colon = ':';
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_nfs3.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/ops_nfs3.c
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_nullfs.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/ops_nullfs.c
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_tfs.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/ops_tfs.c
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_tmpfs.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/ops_tmpfs.c
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_ufs.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/ops_ufs.c
*
*/
@ -54,8 +53,8 @@
/* forward declarations */
static char *ufs_match(am_opts *fo);
static int ufs_fmount(mntfs *mf);
static int ufs_fumount(mntfs *mf);
static int ufs_mount(am_node *am, mntfs *mf);
static int ufs_umount(am_node *am, mntfs *mf);
/*
* Ops structure
@ -65,17 +64,20 @@ am_ops ufs_ops =
"ufs",
ufs_match,
0, /* ufs_init */
amfs_auto_fmount,
ufs_fmount,
amfs_auto_fumount,
ufs_fumount,
amfs_error_lookuppn,
ufs_mount,
ufs_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_error_readdir,
0, /* ufs_readlink */
0, /* ufs_mounted */
0, /* ufs_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
amfs_generic_find_srvr,
0, /* ufs_get_wchan */
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
#ifdef HAVE_FS_AUTOFS
AUTOFS_UFS_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
@ -91,9 +93,7 @@ ufs_match(am_opts *fo)
return 0;
}
#ifdef DEBUG
dlog("UFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
#endif /* DEBUG */
/*
* Determine magic cookie to put in mtab
@ -103,7 +103,7 @@ ufs_match(am_opts *fo)
static int
mount_ufs(char *dir, char *fs_name, char *opts)
mount_ufs(char *mntdir, char *fs_name, char *opts, int on_autofs)
{
ufs_args_t ufs_args;
mntent_t mnt;
@ -120,12 +120,16 @@ mount_ufs(char *dir, char *fs_name, char *opts)
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
mnt.mnt_dir = mntdir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_UFS;
mnt.mnt_opts = opts;
genflags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
if (on_autofs)
genflags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */
#ifdef HAVE_UFS_ARGS_T_FLAGS
ufs_args.flags = genflags; /* XXX: is this correct? */
@ -146,16 +150,17 @@ mount_ufs(char *dir, char *fs_name, char *opts)
/*
* Call generic mount routine
*/
return mount_fs(&mnt, genflags, (caddr_t) &ufs_args, 0, type, 0, NULL, mnttab_file_name);
return mount_fs(&mnt, genflags, (caddr_t) &ufs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
}
static int
ufs_fmount(mntfs *mf)
ufs_mount(am_node *am, mntfs *mf)
{
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
int error;
error = mount_ufs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
error = mount_ufs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_ufs: %m");
@ -167,7 +172,9 @@ ufs_fmount(mntfs *mf)
static int
ufs_fumount(mntfs *mf)
ufs_umount(am_node *am, mntfs *mf)
{
return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_umapfs.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/ops_umapfs.c
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_unionfs.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/ops_unionfs.c
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_xfs.c,v 1.3.2.6 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/ops_xfs.c
*
*/
@ -54,8 +53,8 @@
/* forward declarations */
static char *xfs_match(am_opts *fo);
static int xfs_fmount(mntfs *mf);
static int xfs_fumount(mntfs *mf);
static int xfs_mount(am_node *am, mntfs *mf);
static int xfs_umount(am_node *am, mntfs *mf);
/*
* Ops structure
@ -65,17 +64,20 @@ am_ops xfs_ops =
"xfs",
xfs_match,
0, /* xfs_init */
amfs_auto_fmount,
xfs_fmount,
amfs_auto_fumount,
xfs_fumount,
amfs_error_lookuppn,
xfs_mount,
xfs_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_error_readdir,
0, /* xfs_readlink */
0, /* xfs_mounted */
0, /* xfs_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
amfs_generic_find_srvr,
0, /* xfs_get_wchan */
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
#ifdef HAVE_FS_AUTOFS
AUTOFS_XFS_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
};
@ -91,9 +93,7 @@ xfs_match(am_opts *fo)
return 0;
}
#ifdef DEBUG
dlog("XFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
#endif /* DEBUG */
/*
* Determine magic cookie to put in mtab
@ -103,7 +103,7 @@ xfs_match(am_opts *fo)
static int
mount_xfs(char *dir, char *fs_name, char *opts)
mount_xfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
{
xfs_args_t xfs_args;
mntent_t mnt;
@ -120,12 +120,16 @@ mount_xfs(char *dir, char *fs_name, char *opts)
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
mnt.mnt_dir = mntdir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_XFS;
mnt.mnt_opts = opts;
flags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
if (on_autofs)
flags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */
#ifdef HAVE_XFS_ARGS_T_FLAGS
xfs_args.flags = 0; /* XXX: fix this to correct flags */
@ -137,16 +141,17 @@ mount_xfs(char *dir, char *fs_name, char *opts)
/*
* Call generic mount routine
*/
return mount_fs(&mnt, flags, (caddr_t) &xfs_args, 0, type, 0, NULL, mnttab_file_name);
return mount_fs(&mnt, flags, (caddr_t) &xfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
}
static int
xfs_fmount(mntfs *mf)
xfs_mount(am_node *am, mntfs *mf)
{
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
int error;
error = mount_xfs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
error = mount_xfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_xfs: %m");
@ -158,7 +163,9 @@ xfs_fmount(mntfs *mf)
static int
xfs_fumount(mntfs *mf)
xfs_umount(am_node *am, mntfs *mf)
{
return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: opts.c,v 1.8.2.7 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/opts.c
*
*/
@ -94,11 +93,13 @@ struct functable {
* FORWARD DEFINITION:
*/
static int f_in_network(char *);
static int f_xhost(char *);
static int f_netgrp(char *);
static int f_netgrpd(char *);
static int f_exists(char *);
static int f_false(char *);
static int f_true(char *);
static inline char *expand_options(char *key);
/*
* STATICS:
@ -112,7 +113,7 @@ static char *opt_key = nullstr;
static char *opt_keyd = nullstr;
static char *opt_map = nullstr;
static char *opt_path = nullstr;
static char uid_str[12], gid_str[12];
char uid_str[SIZEOF_UID_STR], gid_str[SIZEOF_GID_STR];
char *opt_uid = uid_str;
char *opt_gid = gid_str;
static char *vars[8];
@ -121,11 +122,11 @@ static char *literal_dollar = "$"; /* ${dollar}: a literal '$' in maps */
/*
* GLOBALS
*/
struct am_opts fs_static; /* copy of the options to play with */
static struct am_opts fs_static; /* copy of the options to play with */
/*
* Options in something corresponding to frequency of use so that
* Options in some order corresponding to frequency of use so that
* first-match algorithm is sped up.
*/
static struct opt opt_fields[] = {
@ -191,6 +192,8 @@ static struct opt opt_fields[] = {
&fs_static.opt_mount, 0, 0, FALSE },
{ S("unmount"),
&fs_static.opt_unmount, 0, 0, FALSE },
{ S("umount"),
&fs_static.opt_umount, 0, 0, FALSE },
{ S("cache"),
&fs_static.opt_cache, 0, 0, FALSE },
{ S("user"),
@ -201,7 +204,6 @@ static struct opt opt_fields[] = {
0, &opt_dkey, 0, FALSE },
{ S("key."),
0, &opt_keyd, 0, FALSE },
/* XXX: should maptype really be a variable? I think selector. -Erez */
{ S("maptype"),
&fs_static.opt_maptype, 0, 0, FALSE },
{ S("cachedir"),
@ -212,6 +214,8 @@ static struct opt opt_fields[] = {
0, &opt_uid, 0, FALSE },
{ S("gid"),
0, &opt_gid, 0, FALSE },
{ S("mount_type"),
&fs_static.opt_mount_type, 0, 0, FALSE },
{ S("dollar"),
&literal_dollar, 0, 0, FALSE },
{ S("var0"),
@ -235,6 +239,7 @@ static struct opt opt_fields[] = {
static struct functable functable[] = {
{ "in_network", f_in_network },
{ "xhost", f_xhost },
{ "netgrp", f_netgrp },
{ "netgrpd", f_netgrpd },
{ "exists", f_exists },
@ -265,6 +270,7 @@ static opt_apply expansions[] =
{&fs_static.opt_remopts, "${opts}"},
{&fs_static.opt_mount, 0},
{&fs_static.opt_unmount, 0},
{&fs_static.opt_umount, 0},
{&fs_static.opt_cachedir, 0},
{&fs_static.opt_addopts, 0},
{0, 0},
@ -286,6 +292,7 @@ static opt_apply to_free[] =
{&fs_static.opt_remopts, 0},
{&fs_static.opt_mount, 0},
{&fs_static.opt_unmount, 0},
{&fs_static.opt_umount, 0},
{&fs_static.opt_cachedir, 0},
{&fs_static.opt_addopts, 0},
{&vars[0], 0},
@ -302,6 +309,7 @@ static opt_apply to_free[] =
/*
* expand backslash escape sequences
* (escaped slash is handled separately in normalize_slash)
*/
static char
backslash(char **p)
@ -457,33 +465,99 @@ functable_lookup(char *key)
}
/*
* Fill in the global structure fs_static by
* cracking the string opts. opts may be
* scribbled on at will. Does NOT evaluate options.
* Returns 0 on error, 1 if no syntax errors were discovered.
*/
static int
eval_opts(char *opts, char *mapkey)
split_opts(char *opts, char *mapkey)
{
/*
* Fill in the global structure fs_static by
* cracking the string opts. opts may be
* scribbled on at will.
*/
char *o = opts;
char *f;
/*
* For each user-specified option
*/
while (*(f = opt(&o))) {
for (f = opt(&o); *f; f = opt(&o)) {
struct opt *op;
enum vs_opt vs_opt = VarAss;
char *eq = strchr(f, '=');
char *opt = NULL;
if (!eq)
continue;
if (*(eq-1) == '!' ||
eq[1] == '=' ||
eq[1] == '!') { /* != or == or =! */
continue; /* we don't care about selectors */
}
if (*(eq-1) == ':') { /* := */
*(eq-1) = '\0';
} else {
/* old style assignment */
eq[0] = '\0';
}
opt = eq + 1;
/*
* For each recognized option
*/
for (op = opt_fields; op->name; op++) {
/*
* Check whether they match
*/
if (FSTREQ(op->name, f)) {
if (op->sel_p) {
plog(XLOG_USER, "key %s: Can't assign to a selector (%s)",
mapkey, op->name);
return 0;
}
*op->optp = opt; /* actual assignment into fs_static */
break; /* break out of for loop */
} /* end of "if (FSTREQ(op->name, f))" statement */
} /* end of "for (op = opt_fields..." statement */
if (!op->name)
plog(XLOG_USER, "key %s: Unrecognized key/option \"%s\"", mapkey, f);
}
return 1;
}
/*
* Just evaluate selectors, which were split by split_opts.
* Returns 0 on error or no match, 1 if matched.
*/
static int
eval_selectors(char *opts, char *mapkey)
{
char *o, *old_o;
char *f;
int ret = 0;
o = old_o = strdup(opts);
/*
* For each user-specified option
*/
for (f = opt(&o); *f; f = opt(&o)) {
struct opt *op;
enum vs_opt vs_opt;
char *eq = strchr(f, '=');
char *fx;
IntFuncPtr func;
char *opt = NULL;
char *arg;
if (!eq || eq[1] == '\0' || eq == f) {
if (!eq) {
/*
* No value, is it a function call?
*/
char *arg = strchr(f, '(');
arg = strchr(f, '(');
if (!arg || arg[1] == '\0' || arg == f) {
/*
@ -502,43 +576,54 @@ eval_opts(char *opts, char *mapkey)
}
*fx = '\0';
if (f[0] == '!') {
vs_opt = SelNE;
f++;
} else {
vs_opt = SelEQ;
}
/*
* look up f in functable and pass it arg.
* func must return 0 on failure, and 1 on success.
*/
if ((func = functable_lookup(f))) {
if (!(*func) (arg)) {
return (0);
}
continue;
} else if (NSTREQ(f, "!", 1) && (func = functable_lookup(&f[1]))) {
/* then this is a negated prefixed function such as "!exists" */
plog(XLOG_INFO, "executing negated function %s", &f[1]);
if ((*func) (arg)) {
return (0);
}
int funok;
/* this allocates memory, don't forget to free */
arg = expand_options(arg);
funok = func(arg);
XFREE(arg);
if (vs_opt == SelNE)
funok = !funok;
if (!funok)
goto out;
continue;
} else {
plog(XLOG_USER, "key %s: unknown function \"%s\"", mapkey, f);
return (0);
goto out;
}
} else {
if (eq[1] == '\0' || eq == f) {
/* misformed selector */
plog(XLOG_USER, "key %s: Bad selector \"%s\"", mapkey, f);
continue;
}
}
/*
* Check what type of operation is happening
* !=, =! is SelNE
* == is SelEQ
* := is VarAss
* =, := is VarAss
*/
if (eq[-1] == '!') { /* != */
if (*(eq-1) == '!') { /* != */
vs_opt = SelNE;
eq[-1] = '\0';
opt = eq + 1;
} else if (eq[-1] == ':') { /* := */
vs_opt = VarAss;
eq[-1] = '\0';
*(eq-1) = '\0';
opt = eq + 1;
} else if (*(eq-1) == ':') { /* := */
continue;
} else if (eq[1] == '=') { /* == */
vs_opt = SelEQ;
eq[0] = '\0';
@ -547,6 +632,9 @@ eval_opts(char *opts, char *mapkey)
vs_opt = SelNE;
eq[0] = '\0';
opt = eq + 2;
} else {
/* old style assignment */
continue;
}
/*
@ -557,48 +645,47 @@ eval_opts(char *opts, char *mapkey)
* Check whether they match
*/
if (FSTREQ(op->name, f)) {
int selok;
switch (vs_opt) {
case SelEQ:
case SelNE:
if ((selok = (op->sel_p != NULL))) {
if (op->case_insensitive) {
selok = (STRCEQ(*op->sel_p, opt) == (vs_opt == SelNE));
} else {
selok = (STREQ(*op->sel_p, opt) == (vs_opt == SelNE));
}
}
if (selok) {
opt = expand_options(opt);
if (op->sel_p != NULL) {
int selok;
if (op->case_insensitive) {
selok = STRCEQ(*op->sel_p, opt);
} else {
selok = STREQ(*op->sel_p, opt);
}
if (vs_opt == SelNE)
selok = !selok;
if (!selok) {
plog(XLOG_MAP, "key %s: map selector %s (=%s) did not %smatch %s",
mapkey,
op->name,
*op->sel_p,
vs_opt == SelNE ? "mis" : "",
opt);
return 0;
XFREE(opt);
goto out;
}
/* check if to apply a function */
if (op->fxn_p &&
((*op->fxn_p)(opt) == (vs_opt == SelNE))) {
XFREE(opt);
}
/* check if to apply a function */
if (op->fxn_p) {
int funok;
funok = op->fxn_p(opt);
if (vs_opt == SelNE)
funok = !funok;
if (!funok) {
plog(XLOG_MAP, "key %s: map function %s did not %smatch %s",
mapkey,
op->name,
vs_opt == SelNE ? "mis" : "",
opt);
return 0;
XFREE(opt);
goto out;
}
break;
case VarAss:
if (op->sel_p) {
plog(XLOG_USER, "key %s: Can't assign to a selector (%s)",
mapkey, op->name);
return 0;
}
*op->optp = opt;
break;
} /* end of "switch (vs_opt)" statement */
XFREE(opt);
}
break; /* break out of for loop */
}
}
@ -607,7 +694,12 @@ eval_opts(char *opts, char *mapkey)
plog(XLOG_USER, "key %s: Unrecognized key/option \"%s\"", mapkey, f);
}
return 1;
/* all is ok */
ret = 1;
out:
free(old_o);
return ret;
}
@ -695,9 +787,9 @@ strip_selectors(char *opts, char *mapkey)
* == is SelEQ
* := is VarAss
*/
if (eq[-1] == '!') { /* != */
if (*(eq-1) == '!') { /* != */
vs_opt = SelNE;
} else if (eq[-1] == ':') { /* := */
} else if (*(eq-1) == ':') { /* := */
vs_opt = VarAss;
} else if (eq[1] == '=') { /* == */
vs_opt = SelEQ;
@ -715,9 +807,7 @@ strip_selectors(char *opts, char *mapkey)
case VarAss:
/* found the first assignment, return the string starting with it */
#ifdef DEBUG
dlog("found first assignment past selectors \"%s\"", o);
#endif /* DEBUG */
return oo;
}
}
@ -738,27 +828,86 @@ f_in_network(char *arg)
int status;
if (!arg)
return FALSE;
return 0;
status = is_network_member(arg);
#ifdef DEBUG
plog(XLOG_USER, "%s is %son a local network",
arg, (status ? "" : "not "));
#endif /* DEBUG */
dlog("%s is %son a local network", arg, (status ? "" : "not "));
return status;
}
/*
* Test if arg is any of this host's names or aliases (CNAMES).
* Note: this function compares against the fully expanded host name (hostd).
* XXX: maybe we also need to compare against the stripped host name?
*/
static int
f_xhost(char *arg)
{
struct hostent *hp;
char **cp;
if (!arg)
return 0;
/* simple test: does it match main host name? */
if (STREQ(arg, opt_hostd))
return 1;
/* now find all of the names of "arg" and compare against opt_hostd */
hp = gethostbyname(arg);
if (hp == NULL) {
#ifdef HAVE_HSTRERROR
plog(XLOG_ERROR, "gethostbyname xhost(%s): %s", arg, hstrerror(h_errno));
#else /* not HAVE_HSTRERROR */
plog(XLOG_ERROR, "gethostbyname xhost(%s): h_errno %d", arg, h_errno);
#endif /* not HAVE_HSTRERROR */
return 0;
}
/* check primary name */
if (hp->h_name) {
dlog("xhost: compare %s==%s", hp->h_name, opt_hostd);
if (STREQ(hp->h_name, opt_hostd)) {
plog(XLOG_INFO, "xhost(%s): matched h_name %s", arg, hp->h_name);
return 1;
}
}
/* check all aliases, if any */
if (hp->h_aliases == NULL) {
dlog("gethostbyname(%s) has no aliases", arg);
return 0;
}
cp = hp->h_aliases;
while (*cp) {
dlog("xhost: compare alias %s==%s", *cp, opt_hostd);
if (STREQ(*cp, opt_hostd)) {
plog(XLOG_INFO, "xhost(%s): matched alias %s", arg, *cp);
return 1;
}
cp++;
}
/* nothing matched */
return 0;
}
/* test if this host (short hostname form) is in netgroup (arg) */
static int
f_netgrp(char *arg)
{
int status;
char *ptr, *nhost;
status = innetgr(arg, opt_host, NULL, NULL);
#ifdef DEBUG
plog(XLOG_USER, "netgrp = %s status = %d host = %s", arg, status, opt_host);
#endif /* DEBUG */
if ((ptr = strchr(arg, ',')) != NULL) {
*ptr = '\0';
nhost = ptr + 1;
} else {
nhost = opt_host;
}
status = innetgr(arg, nhost, NULL, NULL);
dlog("netgrp = %s status = %d host = %s", arg, status, nhost);
if (ptr)
*ptr = ',';
return status;
}
@ -768,11 +917,18 @@ static int
f_netgrpd(char *arg)
{
int status;
char *ptr, *nhost;
status = innetgr(arg, opt_hostd, NULL, NULL);
#ifdef DEBUG
plog(XLOG_USER, "netgrp = %s status = %d hostd = %s", arg, status, opt_hostd);
#endif /* DEBUG */
if ((ptr = strchr(arg, ',')) != NULL) {
*ptr = '\0';
nhost = ptr + 1;
} else {
nhost = opt_hostd;
}
status = innetgr(arg, nhost, NULL, NULL);
dlog("netgrp = %s status = %d hostd = %s", arg, status, nhost);
if (ptr)
*ptr = ',';
return status;
}
@ -814,7 +970,6 @@ free_op(opt_apply *p, int b)
{
if (*p->opt) {
XFREE(*p->opt);
*p->opt = 0;
}
}
@ -825,9 +980,12 @@ free_op(opt_apply *p, int b)
void
normalize_slash(char *p)
{
char *f = strchr(p, '/');
char *f0 = f;
char *f, *f0;
if (!(gopt.flags & CFM_NORMALIZE_SLASHES))
return;
f0 = f = strchr(p, '/');
if (f) {
char *t = f;
do {
@ -849,6 +1007,9 @@ normalize_slash(char *p)
/* assert(*f != '/'); */
/* keep copying up to next / */
while (*f && *f != '/') {
/* support escaped slashes '\/' */
if (f[0] == '\\' && f[1] == '/')
f++; /* skip backslash */
*t++ = *f++;
}
@ -863,22 +1024,20 @@ normalize_slash(char *p)
/*
* Macro-expand an option. Note that this does not
* handle recursive expansions. They will go badly wrong.
* If sel is true then old expand selectors, otherwise
* If sel_p is true then old expand selectors, otherwise
* don't expand selectors.
*/
static void
expand_op(opt_apply *p, int sel_p)
static char *
expand_op(char *opt, int sel_p)
{
static const char expand_error[] = "No space to expand \"%s\"";
#define EXPAND_ERROR "No space to expand \"%s\""
char expbuf[MAXPATHLEN + 1];
char nbuf[NLEN + 1];
char *ep = expbuf;
char *cp = *p->opt;
char *cp = opt;
char *dp;
struct opt *op;
#ifdef DEBUG
char *cp_orig = *p->opt;
#endif /* DEBUG */
char *cp_orig = opt;
while ((dp = strchr(cp, '$'))) {
char ch;
@ -888,12 +1047,18 @@ expand_op(opt_apply *p, int sel_p)
{
int len = dp - cp;
if (BUFSPACE(ep, len)) {
strncpy(ep, cp, len);
ep += len;
} else {
plog(XLOG_ERROR, expand_error, *p->opt);
goto out;
if (len > 0) {
if (BUFSPACE(ep, len)) {
/*
* We use strncpy (not xstrlcpy) because 'ep' relies on its
* semantics. BUFSPACE guarantees that ep can hold len.
*/
strncpy(ep, cp, len);
ep += len;
} else {
plog(XLOG_ERROR, EXPAND_ERROR, opt);
goto out;
}
}
}
@ -903,7 +1068,7 @@ expand_op(opt_apply *p, int sel_p)
if (BUFSPACE(ep, 1)) {
*ep++ = '$';
} else {
plog(XLOG_ERROR, expand_error, *p->opt);
plog(XLOG_ERROR, EXPAND_ERROR, opt);
goto out;
}
} else if (ch == '{') {
@ -924,7 +1089,7 @@ expand_op(opt_apply *p, int sel_p)
/*
* Just give up
*/
plog(XLOG_USER, "No closing '}' in \"%s\"", *p->opt);
plog(XLOG_USER, "No closing '}' in \"%s\"", opt);
goto out;
}
len = br_p - cp;
@ -939,7 +1104,7 @@ expand_op(opt_apply *p, int sel_p)
todo = E_File;
cp++;
--len;
} else if (br_p[-1] == '/') {
} else if (*(br_p-1) == '/') {
/*
* Take all but the last component
*/
@ -952,7 +1117,7 @@ expand_op(opt_apply *p, int sel_p)
todo = E_Domain;
cp++;
--len;
} else if (br_p[-1] == '.') {
} else if (*(br_p-1) == '.') {
/*
* Take host name
*/
@ -976,6 +1141,11 @@ expand_op(opt_apply *p, int sel_p)
/*
* Put the string into another buffer so
* we can do comparisons.
*
* We use strncpy here (not xstrlcpy) because the dest is meant
* to be truncated and we don't want to log it as an error. The
* use of the BUFSPACE macro above guarantees the safe use of
* strncpy with nbuf.
*/
strncpy(nbuf, cp, len);
nbuf[len] = '\0';
@ -1003,12 +1173,12 @@ expand_op(opt_apply *p, int sel_p)
/*
* Copy the string across unexpanded
*/
sprintf(xbuf, "${%s%s%s}",
todo == E_File ? "/" :
todo == E_Domain ? "." : "",
nbuf,
todo == E_Dir ? "/" :
todo == E_Host ? "." : "");
xsnprintf(xbuf, sizeof(xbuf), "${%s%s%s}",
todo == E_File ? "/" :
todo == E_Domain ? "." : "",
nbuf,
todo == E_Dir ? "/" :
todo == E_Host ? "." : "");
val = xbuf;
/*
* Make sure expansion doesn't
@ -1067,11 +1237,11 @@ expand_op(opt_apply *p, int sel_p)
break;
}
if (BUFSPACE(ep, vlen)) {
strcpy(ep, vptr);
if (BUFSPACE(ep, vlen+1)) {
xstrlcpy(ep, vptr, vlen+1);
ep += vlen;
} else {
plog(XLOG_ERROR, expand_error, *p->opt);
plog(XLOG_ERROR, EXPAND_ERROR, opt);
goto out;
}
}
@ -1096,17 +1266,15 @@ expand_op(opt_apply *p, int sel_p)
if (env) {
int vlen = strlen(env);
if (BUFSPACE(ep, vlen)) {
strcpy(ep, env);
if (BUFSPACE(ep, vlen+1)) {
xstrlcpy(ep, env, vlen+1);
ep += vlen;
} else {
plog(XLOG_ERROR, expand_error, *p->opt);
plog(XLOG_ERROR, EXPAND_ERROR, opt);
goto out;
}
#ifdef DEBUG
amuDebug(D_STR)
if (amuDebug(D_STR))
plog(XLOG_DEBUG, "Environment gave \"%s\" -> \"%s\"", nbuf, env);
#endif /* DEBUG */
} else {
plog(XLOG_USER, "Unknown sequence \"${%s}\"", nbuf);
}
@ -1115,7 +1283,7 @@ expand_op(opt_apply *p, int sel_p)
/*
* Error, error
*/
plog(XLOG_USER, "Unknown $ sequence in \"%s\"", *p->opt);
plog(XLOG_USER, "Unknown $ sequence in \"%s\"", opt);
}
}
@ -1123,33 +1291,33 @@ expand_op(opt_apply *p, int sel_p)
/*
* Handle common case - no expansion
*/
if (cp == *p->opt) {
*p->opt = strdup(cp);
if (cp == opt) {
opt = strdup(cp);
} else {
/*
* Finish off the expansion
*/
if (BUFSPACE(ep, strlen(cp))) {
strcpy(ep, cp);
/* ep += strlen(ep); */
int vlen = strlen(cp);
if (BUFSPACE(ep, vlen+1)) {
xstrlcpy(ep, cp, vlen+1);
/* ep += vlen; */
} else {
plog(XLOG_ERROR, expand_error, *p->opt);
plog(XLOG_ERROR, EXPAND_ERROR, opt);
}
/*
* Save the expansion
*/
*p->opt = strdup(expbuf);
opt = strdup(expbuf);
}
normalize_slash(*p->opt);
normalize_slash(opt);
#ifdef DEBUG
amuDebug(D_STR) {
if (amuDebug(D_STR)) {
plog(XLOG_DEBUG, "Expansion of \"%s\"...", cp_orig);
plog(XLOG_DEBUG, "... is \"%s\"", *p->opt);
plog(XLOG_DEBUG, "......... is \"%s\"", opt);
}
#endif /* DEBUG */
return opt;
}
@ -1160,15 +1328,15 @@ static void
expand_opts(opt_apply *p, int sel_p)
{
if (*p->opt) {
expand_op(p, sel_p);
*p->opt = expand_op(*p->opt, sel_p);
} else if (p->val) {
/*
* Do double expansion, remembering
* to free the string from the first
* expansion...
*/
char *s = *p->opt = expand_key(p->val);
expand_op(p, sel_p);
char *s = expand_op(p->val, TRUE);
*p->opt = expand_op(s, sel_p);
XFREE(s);
}
}
@ -1206,18 +1374,22 @@ free_opts(am_opts *fo)
/*
* Expand lookup key
* Expand selectors (variables that cannot be assigned to or overridden)
*/
char *
expand_key(char *key)
expand_selectors(char *key)
{
opt_apply oa;
return expand_op(key, TRUE);
}
oa.opt = &key;
oa.val = 0;
expand_opts(&oa, TRUE);
return key;
/*
* Expand options (i.e. non-selectors, see above for definition)
*/
static inline char *
expand_options(char *key)
{
return expand_op(key, FALSE);
}
@ -1225,10 +1397,14 @@ expand_key(char *key)
* Remove trailing /'s from a string
* unless the string is a single / (Steven Glassman)
* or unless it is two slashes // (Kevin D. Bond)
* or unless amd.conf says not to touch slashes.
*/
void
deslashify(char *s)
{
if (!(gopt.flags & CFM_NORMALIZE_SLASHES))
return;
if (s && *s) {
char *sl = s + strlen(s);
@ -1276,24 +1452,27 @@ eval_fs_opts(am_opts *fo, char *opts, char *g_opts, char *path, char *key, char
/*
* Expand global options
*/
fs_static.fs_glob = expand_key(g_opts);
fs_static.fs_glob = expand_selectors(g_opts);
/*
* Expand local options
*/
fs_static.fs_local = expand_key(opts);
fs_static.fs_local = expand_selectors(opts);
/*
* Expand default (global) options
*/
if (!eval_opts(fs_static.fs_glob, key))
ok = FALSE;
/*
* Expand local options
*/
if (ok && !eval_opts(fs_static.fs_local, key))
ok = FALSE;
/* break global options into fs_static fields */
if ((ok = split_opts(fs_static.fs_glob, key))) {
dlog("global split_opts ok");
/*
* evaluate local selectors
*/
if ((ok = eval_selectors(fs_static.fs_local, key))) {
dlog("local eval_selectors ok");
/* if the local selectors matched, then do the local overrides */
ok = split_opts(fs_static.fs_local, key);
if (ok)
dlog("local split_opts ok");
}
}
/*
* Normalize remote host name.

498
contrib/amd/amd/readdir.c Normal file
View File

@ -0,0 +1,498 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgment:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* File: am-utils/amd/readdir.c
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/****************************************************************************
*** MACROS ***
****************************************************************************/
#define DOT_DOT_COOKIE (u_int) 1
#define MAX_CHAIN 2048
/****************************************************************************
*** FORWARD DEFINITIONS ***
****************************************************************************/
static int key_already_in_chain(char *keyname, const nfsentry *chain);
static nfsentry *make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable);
static int amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count, int fully_browsable);
/****************************************************************************
*** FUNCTIONS ***
****************************************************************************/
/*
* Was: NEW_TOPLVL_READDIR
* Search a chain for an entry with some name.
* -Erez Zadok <ezk@cs.columbia.edu>
*/
static int
key_already_in_chain(char *keyname, const nfsentry *chain)
{
const nfsentry *tmpchain = chain;
while (tmpchain) {
if (keyname && tmpchain->ne_name && STREQ(keyname, tmpchain->ne_name))
return 1;
tmpchain = tmpchain->ne_nextentry;
}
return 0;
}
/*
* Create a chain of entries which are not linked.
* -Erez Zadok <ezk@cs.columbia.edu>
*/
static nfsentry *
make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable)
{
static u_int last_cookie = (u_int) 2; /* monotonically increasing */
static nfsentry chain[MAX_CHAIN];
static int max_entries = MAX_CHAIN;
char *key;
int num_entries = 0, i;
u_int preflen = 0;
nfsentry *retval = (nfsentry *) NULL;
mntfs *mf;
mnt_map *mmp;
if (!mp) {
plog(XLOG_DEBUG, "make_entry_chain: mp is (NULL)");
return retval;
}
mf = mp->am_mnt;
if (!mf) {
plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt is (NULL)");
return retval;
}
mmp = (mnt_map *) mf->mf_private;
if (!mmp) {
plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt->mf_private is (NULL)");
return retval;
}
if (mp->am_pref)
preflen = strlen(mp->am_pref);
/* iterate over keys */
for (i = 0; i < NKVHASH; i++) {
kv *k;
for (k = mmp->kvhash[i]; k ; k = k->next) {
/*
* Skip unwanted entries which are either not real entries or
* very difficult to interpret (wildcards...) This test needs
* lots of improvement. Any takers?
*/
key = k->key;
if (!key)
continue;
/* Skip '/defaults' */
if (STREQ(key, "/defaults"))
continue;
/* Skip '*' */
if (!fully_browsable && strchr(key, '*'))
continue;
/*
* If the map has a prefix-string then check if the key starts with
* this string, and if it does, skip over this prefix. If it has a
* prefix and it doesn't match the start of the key, skip it.
*/
if (preflen) {
if (preflen > strlen(key))
continue;
if (!NSTREQ(key, mp->am_pref, preflen))
continue;
key += preflen;
}
/* no more '/' are allowed, unless browsable_dirs=full was used */
if (!fully_browsable && strchr(key, '/'))
continue;
/* no duplicates allowed */
if (key_already_in_chain(key, current_chain))
continue;
/* fill in a cell and link the entry */
if (num_entries >= max_entries) {
/* out of space */
plog(XLOG_DEBUG, "make_entry_chain: no more space in chain");
if (num_entries > 0) {
chain[num_entries - 1].ne_nextentry = 0;
retval = &chain[0];
}
return retval;
}
/* we have space. put entry in next cell */
++last_cookie;
chain[num_entries].ne_fileid = (u_int) last_cookie;
*(u_int *) chain[num_entries].ne_cookie = (u_int) last_cookie;
chain[num_entries].ne_name = key;
if (num_entries < max_entries - 1) { /* link to next one */
chain[num_entries].ne_nextentry = &chain[num_entries + 1];
}
++num_entries;
} /* end of "while (k)" */
} /* end of "for (i ... NKVHASH ..." */
/* terminate chain */
if (num_entries > 0) {
chain[num_entries - 1].ne_nextentry = 0;
retval = &chain[0];
}
return retval;
}
/* This one is called only if map is browsable */
static int
amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count, int fully_browsable)
{
u_int gen = *(u_int *) cookie;
int chain_length, i;
static nfsentry *te, *te_next;
static int j;
dp->dl_eof = FALSE; /* assume readdir not done */
if (amuDebug(D_READDIR))
plog(XLOG_DEBUG, "amfs_readdir_browsable gen=%u, count=%d",
gen, count);
if (gen == 0) {
/*
* In the default instance (which is used to start a search) we return
* "." and "..".
*
* This assumes that the count is big enough to allow both "." and ".."
* to be returned in a single packet. If it isn't (which would be
* fairly unbelievable) then tough.
*/
dlog("amfs_readdir_browsable: default search");
/*
* Check for enough room. This is extremely approximate but is more
* than enough space. Really need 2 times:
* 4byte fileid
* 4byte cookie
* 4byte name length
* 4byte name
* plus the dirlist structure */
if (count < (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp))))
return EINVAL;
/*
* compute # of entries to send in this chain.
* heuristics: 128 bytes per entry.
* This is too much probably, but it seems to work better because
* of the re-entrant nature of nfs_readdir, and esp. on systems
* like OpenBSD 2.2.
*/
chain_length = count / 128;
/* reset static state counters */
te = te_next = NULL;
dp->dl_entries = ep;
/* construct "." */
ep[0].ne_fileid = mp->am_gen;
ep[0].ne_name = ".";
ep[0].ne_nextentry = &ep[1];
*(u_int *) ep[0].ne_cookie = 0;
/* construct ".." */
if (mp->am_parent)
ep[1].ne_fileid = mp->am_parent->am_gen;
else
ep[1].ne_fileid = mp->am_gen;
ep[1].ne_name = "..";
ep[1].ne_nextentry = 0;
*(u_int *) ep[1].ne_cookie = DOT_DOT_COOKIE;
/*
* If map is browsable, call a function make_entry_chain() to construct
* a linked list of unmounted keys, and return it. Then link the chain
* to the regular list. Get the chain only once, but return
* chunks of it each time.
*/
te = make_entry_chain(mp, dp->dl_entries, fully_browsable);
if (!te)
return 0;
if (amuDebug(D_READDIR)) {
nfsentry *ne;
for (j = 0, ne = te; ne; ne = ne->ne_nextentry)
plog(XLOG_DEBUG, "gen1 key %4d \"%s\"", j++, ne->ne_name);
}
/* return only "chain_length" entries */
te_next = te;
for (i=1; i<chain_length; ++i) {
te_next = te_next->ne_nextentry;
if (!te_next)
break;
}
if (te_next) {
nfsentry *te_saved = te_next->ne_nextentry;
te_next->ne_nextentry = NULL; /* terminate "te" chain */
te_next = te_saved; /* save rest of "te" for next iteration */
dp->dl_eof = FALSE; /* tell readdir there's more */
} else {
dp->dl_eof = TRUE; /* tell readdir that's it */
}
ep[1].ne_nextentry = te; /* append this chunk of "te" chain */
if (amuDebug(D_READDIR)) {
nfsentry *ne;
for (j = 0, ne = te; ne; ne = ne->ne_nextentry)
plog(XLOG_DEBUG, "gen2 key %4d \"%s\"", j++, ne->ne_name);
for (j = 0, ne = ep; ne; ne = ne->ne_nextentry)
plog(XLOG_DEBUG, "gen2+ key %4d \"%s\" fi=%d ck=%d",
j++, ne->ne_name, ne->ne_fileid, *(u_int *)ne->ne_cookie);
plog(XLOG_DEBUG, "EOF is %d", dp->dl_eof);
}
return 0;
} /* end of "if (gen == 0)" statement */
dlog("amfs_readdir_browsable: real child");
if (gen == DOT_DOT_COOKIE) {
dlog("amfs_readdir_browsable: End of readdir in %s", mp->am_path);
dp->dl_eof = TRUE;
dp->dl_entries = 0;
return 0;
}
/*
* If browsable directories, then continue serving readdir() with another
* chunk of entries, starting from where we left off (when gen was equal
* to 0). Once again, assume last chunk served to readdir.
*/
dp->dl_eof = TRUE;
dp->dl_entries = ep;
te = te_next; /* reset 'te' from last saved te_next */
if (!te) { /* another indicator of end of readdir */
dp->dl_entries = 0;
return 0;
}
/*
* compute # of entries to send in this chain.
* heuristics: 128 bytes per entry.
*/
chain_length = count / 128;
/* return only "chain_length" entries */
for (i = 1; i < chain_length; ++i) {
te_next = te_next->ne_nextentry;
if (!te_next)
break;
}
if (te_next) {
nfsentry *te_saved = te_next->ne_nextentry;
te_next->ne_nextentry = NULL; /* terminate "te" chain */
te_next = te_saved; /* save rest of "te" for next iteration */
dp->dl_eof = FALSE; /* tell readdir there's more */
}
ep = te; /* send next chunk of "te" chain */
dp->dl_entries = ep;
if (amuDebug(D_READDIR)) {
nfsentry *ne;
plog(XLOG_DEBUG, "dl_entries=%p, te_next=%p, dl_eof=%d",
dp->dl_entries, te_next, dp->dl_eof);
for (ne = te; ne; ne = ne->ne_nextentry)
plog(XLOG_DEBUG, "gen3 key %4d \"%s\"", j++, ne->ne_name);
}
return 0;
}
/*
* This readdir function which call a special version of it that allows
* browsing if browsable_dirs=yes was set on the map.
*/
int
amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count)
{
u_int gen = *(u_int *) cookie;
am_node *xp;
mntent_t mnt;
dp->dl_eof = FALSE; /* assume readdir not done */
/* check if map is browsable */
if (mp->am_mnt && mp->am_mnt->mf_mopts) {
mnt.mnt_opts = mp->am_mnt->mf_mopts;
if (amu_hasmntopt(&mnt, "fullybrowsable"))
return amfs_readdir_browsable(mp, cookie, dp, ep, count, TRUE);
if (amu_hasmntopt(&mnt, "browsable"))
return amfs_readdir_browsable(mp, cookie, dp, ep, count, FALSE);
}
/* when gen is 0, we start reading from the beginning of the directory */
if (gen == 0) {
/*
* In the default instance (which is used to start a search) we return
* "." and "..".
*
* This assumes that the count is big enough to allow both "." and ".."
* to be returned in a single packet. If it isn't (which would be
* fairly unbelievable) then tough.
*/
dlog("amfs_generic_readdir: default search");
/*
* Check for enough room. This is extremely approximate but is more
* than enough space. Really need 2 times:
* 4byte fileid
* 4byte cookie
* 4byte name length
* 4byte name
* plus the dirlist structure */
if (count < (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp))))
return EINVAL;
xp = next_nonerror_node(mp->am_child);
dp->dl_entries = ep;
/* construct "." */
ep[0].ne_fileid = mp->am_gen;
ep[0].ne_name = ".";
ep[0].ne_nextentry = &ep[1];
*(u_int *) ep[0].ne_cookie = 0;
/* construct ".." */
if (mp->am_parent)
ep[1].ne_fileid = mp->am_parent->am_gen;
else
ep[1].ne_fileid = mp->am_gen;
ep[1].ne_name = "..";
ep[1].ne_nextentry = 0;
*(u_int *) ep[1].ne_cookie = (xp ? xp->am_gen : DOT_DOT_COOKIE);
if (!xp)
dp->dl_eof = TRUE; /* by default assume readdir done */
if (amuDebug(D_READDIR)) {
nfsentry *ne;
int j;
for (j = 0, ne = ep; ne; ne = ne->ne_nextentry)
plog(XLOG_DEBUG, "gen1 key %4d \"%s\" fi=%d ck=%d",
j++, ne->ne_name, ne->ne_fileid, *(u_int *)ne->ne_cookie);
}
return 0;
}
dlog("amfs_generic_readdir: real child");
if (gen == DOT_DOT_COOKIE) {
dlog("amfs_generic_readdir: End of readdir in %s", mp->am_path);
dp->dl_eof = TRUE;
dp->dl_entries = 0;
if (amuDebug(D_READDIR))
plog(XLOG_DEBUG, "end of readdir eof=TRUE, dl_entries=0\n");
return 0;
}
/* non-browsable directories code */
xp = mp->am_child;
while (xp && xp->am_gen != gen)
xp = xp->am_osib;
if (xp) {
int nbytes = count / 2; /* conservative */
int todo = MAX_READDIR_ENTRIES;
dp->dl_entries = ep;
do {
am_node *xp_next = next_nonerror_node(xp->am_osib);
if (xp_next) {
*(u_int *) ep->ne_cookie = xp_next->am_gen;
} else {
*(u_int *) ep->ne_cookie = DOT_DOT_COOKIE;
dp->dl_eof = TRUE;
}
ep->ne_fileid = xp->am_gen;
ep->ne_name = xp->am_name;
nbytes -= sizeof(*ep) + 1;
if (xp->am_name)
nbytes -= strlen(xp->am_name);
xp = xp_next;
if (nbytes > 0 && !dp->dl_eof && todo > 1) {
ep->ne_nextentry = ep + 1;
ep++;
--todo;
} else {
todo = 0;
}
} while (todo > 0);
ep->ne_nextentry = 0;
if (amuDebug(D_READDIR)) {
nfsentry *ne;
int j;
for (j=0,ne=ep; ne; ne=ne->ne_nextentry)
plog(XLOG_DEBUG, "gen2 key %4d \"%s\" fi=%d ck=%d",
j++, ne->ne_name, ne->ne_fileid, *(u_int *)ne->ne_cookie);
}
return 0;
}
return ESTALE;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: restart.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/restart.c
*
*/
@ -49,14 +48,81 @@
#include <amd.h>
static void
restart_fake_mntfs(mntent_t *me, am_ops *fs_ops)
{
mntfs *mf;
am_opts mo;
char *cp;
/*
* Partially fake up an opts structure
*/
memset(&mo, 0, sizeof(mo));
mo.opt_rhost = 0;
mo.opt_rfs = 0;
cp = strchr(me->mnt_fsname, ':');
if (cp) {
*cp = '\0';
mo.opt_rhost = strdup(me->mnt_fsname);
mo.opt_rfs = strdup(cp + 1);
*cp = ':';
} else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) {
/*
* Hacky workaround for mnttab NFS entries that only list the server
*/
plog(XLOG_WARNING, "NFS server entry assumed to be %s:/", me->mnt_fsname);
mo.opt_rhost = strdup(me->mnt_fsname);
mo.opt_rfs = strdup("/");
me->mnt_fsname = str3cat(me->mnt_fsname, mo.opt_rhost, ":", "/");
}
mo.opt_fs = me->mnt_dir;
mo.opt_opts = me->mnt_opts;
/*
* Make a new mounted filesystem
*/
mf = find_mntfs(fs_ops, &mo, me->mnt_dir,
me->mnt_fsname, "", me->mnt_opts, "");
if (mf->mf_refc == 1) {
mf->mf_flags |= MFF_RESTART | MFF_MOUNTED;
mf->mf_error = 0; /* Already mounted correctly */
mf->mf_fo = 0;
/*
* Only timeout non-NFS entries
*/
if (!STREQ(me->mnt_type, MNTTAB_TYPE_NFS))
mf->mf_flags |= MFF_RSTKEEP;
if (fs_ops->fs_init) {
/*
* Don't care whether this worked since
* it is checked again when the fs is
* inherited.
*/
(void) (*fs_ops->fs_init) (mf);
}
plog(XLOG_INFO, "%s restarted fstype %s on %s, flags 0x%x",
me->mnt_fsname, fs_ops->fs_type, me->mnt_dir, mf->mf_flags);
} else {
/* Something strange happened - two mounts at the same place! */
free_mntfs(mf);
}
/*
* Clean up mo
*/
if (mo.opt_rhost)
XFREE(mo.opt_rhost);
if (mo.opt_rfs)
XFREE(mo.opt_rfs);
}
/*
* Handle an amd restart.
*
* Scan through the mount list finding all "interesting" mount points.
* Next hack up partial data structures and add the mounted file
* system to the list of known filesystems. This will leave a
* dangling reference to that filesystems, so when the filesystem is
* finally inherited, an extra "free" must be done on it.
* system to the list of known filesystems.
*
* This module relies on internal details of other components. If
* you change something else make *sure* restart() still works.
@ -64,26 +130,19 @@
void
restart(void)
{
/*
* Read the existing mount table
*/
mntlist *ml, *mlp;
/*
* For each entry, find nfs, ufs or auto mounts
* and create a partial am_node to represent it.
* Read the existing mount table. For each entry, find nfs, ufs or auto
* mounts and create a partial am_node to represent it.
*/
for (mlp = ml = read_mtab("restart", mnttab_file_name);
mlp;
mlp = mlp->mnext) {
mntent_t *me = mlp->mnt;
am_ops *fs_ops = 0;
if (STREQ(me->mnt_type, MNTTAB_TYPE_UFS)) {
/*
* UFS entry
*/
fs_ops = &ufs_ops;
} else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) {
if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) {
/*
* NFS entry, or possibly an Amd entry...
* The mnt_fsname for daemon mount points is
@ -92,113 +151,21 @@ restart(void)
* host:daemon(pidXXX)
*/
char *colon = strchr(me->mnt_fsname, ':');
if (colon && strstr(colon, "(pid")) {
plog(XLOG_WARNING, "%s is an existing automount point", me->mnt_dir);
fs_ops = &amfs_link_ops;
} else {
fs_ops = &nfs_ops;
}
#ifdef MNTTAB_TYPE_NFS3
} else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS3)) {
fs_ops = &nfs_ops;
#endif /* MNTTAB_TYPE_NFS3 */
#ifdef MNTTAB_TYPE_LOFS
} else if (STREQ(me->mnt_type, MNTTAB_TYPE_LOFS)) {
fs_ops = &lofs_ops;
#endif /* MNTTAB_TYPE_LOFS */
#ifdef MNTTAB_TYPE_CDFS
} else if (STREQ(me->mnt_type, MNTTAB_TYPE_CDFS)) {
fs_ops = &cdfs_ops;
#endif /* MNTTAB_TYPE_CDFS */
#ifdef MNTTAB_TYPE_PCFS
} else if (STREQ(me->mnt_type, MNTTAB_TYPE_PCFS)) {
fs_ops = &pcfs_ops;
#endif /* MNTTAB_TYPE_PCFS */
#ifdef MNTTAB_TYPE_MFS
} else if (STREQ(me->mnt_type, MNTTAB_TYPE_MFS)) {
/*
* MFS entry. Fake with a symlink.
*/
fs_ops = &amfs_link_ops;
#endif /* MNTTAB_TYPE_MFS */
} else {
/*
* Catch everything else with symlinks to
* avoid recursive mounts. This is debatable...
*/
fs_ops = &amfs_link_ops;
if (colon && strstr(colon, "(pid"))
continue;
}
/* Search for the correct filesystem ops */
fs_ops = ops_search(me->mnt_type);
/*
* If we found something to do
* Catch everything else with symlinks to
* avoid recursive mounts. This is debatable...
*/
if (fs_ops) {
mntfs *mf;
am_opts mo;
char *cp;
cp = strchr(me->mnt_fsname, ':');
if (!fs_ops)
fs_ops = &amfs_link_ops;
/*
* Partially fake up an opts structure
*/
mo.opt_rhost = 0;
mo.opt_rfs = 0;
if (cp) {
*cp = '\0';
mo.opt_rhost = strdup(me->mnt_fsname);
mo.opt_rfs = strdup(cp + 1);
*cp = ':';
} else if (fs_ops->ffserver == find_nfs_srvr) {
/*
* Prototype 4.4 BSD used to end up here -
* might as well keep the workaround for now
*/
plog(XLOG_WARNING, "NFS server entry assumed to be %s:/", me->mnt_fsname);
mo.opt_rhost = strdup(me->mnt_fsname);
mo.opt_rfs = strdup("/");
me->mnt_fsname = str3cat(me->mnt_fsname, mo.opt_rhost, ":", "/");
}
mo.opt_fs = me->mnt_dir;
mo.opt_opts = me->mnt_opts;
/*
* Make a new mounted filesystem
*/
mf = find_mntfs(fs_ops, &mo, me->mnt_dir,
me->mnt_fsname, "", me->mnt_opts, "");
if (mf->mf_refc == 1) {
mf->mf_flags |= MFF_RESTART | MFF_MOUNTED;
mf->mf_error = 0; /* Already mounted correctly */
mf->mf_fo = 0;
/*
* If the restarted type is a link then
* don't time out.
*/
if (fs_ops == &amfs_link_ops || fs_ops == &ufs_ops)
mf->mf_flags |= MFF_RSTKEEP;
if (fs_ops->fs_init) {
/*
* Don't care whether this worked since
* it is checked again when the fs is
* inherited.
*/
(void) (*fs_ops->fs_init) (mf);
}
plog(XLOG_INFO, "%s restarted fstype %s on %s",
me->mnt_fsname, fs_ops->fs_type, me->mnt_dir);
} else {
/* Something strange happened - two mounts at the same place! */
free_mntfs(mf);
}
/*
* Clean up mo
*/
if (mo.opt_rhost)
XFREE(mo.opt_rhost);
if (mo.opt_rfs)
XFREE(mo.opt_rfs);
}
restart_fake_mntfs(me, fs_ops);
}
/*
@ -206,3 +173,116 @@ restart(void)
*/
free_mntlist(ml);
}
/*
* Handle an amd restart for amd's own mount points.
*
* Scan through the mount list finding all daemon mount points
* (determined by the presence of a pid inside the mount info).
* Next hack up partial data structures and add the mounted file
* system to the list of known filesystems.
*
* This module relies on internal details of other components. If
* you change something else make *sure* restart() still works.
*/
void
restart_automounter_nodes(void)
{
mntlist *ml, *mlp;
/* reasonably sized list of restarted nfs ports */
u_short old_ports[256];
memset((voidp) &old_ports, 0, sizeof(u_short) * 256);
/*
* Read the existing mount table. For each entry, find nfs, ufs or auto
* mounts and create a partial am_node to represent it.
*/
for (mlp = ml = read_mtab("restart", mnttab_file_name);
mlp;
mlp = mlp->mnext) {
mntent_t *me = mlp->mnt;
am_ops *fs_ops = 0;
char *colon;
long pid;
u_short port;
int err;
if (!STREQ(me->mnt_type, MNTTAB_TYPE_NFS))
continue; /* to next mlp */
/*
* NFS entry, or possibly an Amd entry...
* The mnt_fsname for daemon mount points is
* host:(pidXXX)
* or (seen on Solaris)
* host:daemon(pidXXX)
*/
colon = strchr(me->mnt_fsname, ':');
if (!colon || !strstr(colon, "(pid"))
continue;
/* if got here, then we matched an existing Amd mount point */
err = 1;
plog(XLOG_WARNING, "%s is an existing automount point", me->mnt_dir);
/* Is the old automounter still alive? */
if (sscanf(colon, "%*[^(](pid%ld%*[,)]", &pid) != 1) {
plog(XLOG_WARNING, "Can't parse pid in %s", me->mnt_fsname);
goto give_up;
}
if (kill(pid, 0) != -1 || errno != ESRCH) {
plog(XLOG_WARNING, "Automounter (pid: %ld) still alive", pid);
goto give_up;
}
/*
* Do we have a map for this mount point? Who cares, we'll restart
* anyway -- getting ESTALE is way better than hanging.
*/
/* Can we restart it? Only if it tells us what port it was using... */
if (sscanf(colon, "%*[^,],port%hu)", &port) != 1) {
plog(XLOG_WARNING, "No port specified for %s", me->mnt_fsname);
goto give_up;
}
/* Maybe we already own that port... */
if (port != nfs_port) {
int i;
for (i = 0; i < 256; i++) {
if (old_ports[i] == port ||
old_ports[i] == 0)
break;
}
if (i == 256) {
plog(XLOG_WARNING, "Too many open ports (256)");
goto give_up;
}
if (old_ports[i] == 0) {
int soNFS;
SVCXPRT *nfsxprt;
if (create_nfs_service(&soNFS, &port, &nfsxprt, nfs_program_2) != 0) {
plog(XLOG_WARNING, "Can't bind to port %u", port);
goto give_up;
}
old_ports[i] = nfs_port = port;
}
}
err = 0;
give_up:
if (err) {
plog(XLOG_WARNING, "Can't restart %s, leaving it alone", me->mnt_dir);
fs_ops = &amfs_link_ops;
} else {
fs_ops = &amfs_toplvl_ops;
}
restart_fake_mntfs(me, fs_ops);
} /* end of "for (mlp" */
/* free the mount list */
free_mntlist(ml);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: rpc_fwd.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/rpc_fwd.c
*
*/
@ -58,7 +57,7 @@
* is no need to convert to and from network byte ordering.
*/
#define XID_ALLOC(struct ) (xid++)
#define XID_ALLOC() (xid++)
#define MAX_PACKET_SIZE 8192 /* Maximum UDP packet size */
/*
@ -75,7 +74,7 @@ struct rpc_forward {
time_t rf_ttl; /* Time to live */
u_int rf_xid; /* Packet id */
u_int rf_oldid; /* Original packet id */
fwd_fun rf_fwd; /* Forwarding function */
fwd_fun *rf_fwd; /* Forwarding function */
voidp rf_ptr;
struct sockaddr_in rf_sin;
};
@ -94,7 +93,7 @@ static u_int xid;
static rpc_forward *
fwd_alloc(void)
{
time_t now = clocktime();
time_t now = clocktime(NULL);
rpc_forward *p = 0, *p2;
/*
@ -117,9 +116,7 @@ fwd_alloc(void)
* Call forwarding function to say that
* this message was junked.
*/
#ifdef DEBUG
dlog("Re-using packet forwarding slot - id %#x", p->rf_xid);
#endif /* DEBUG */
if (p->rf_fwd)
(*p->rf_fwd) (0, 0, 0, &p->rf_sin, p->rf_ptr, FALSE);
rem_que(&p->rf_q);
@ -228,7 +225,7 @@ fwd_locate(u_int id)
* different address.
*/
int
fwd_packet(int type_id, voidp pkt, int len, struct sockaddr_in *fwdto, struct sockaddr_in *replyto, voidp i, fwd_fun cb)
fwd_packet(int type_id, char *pkt, int len, struct sockaddr_in *fwdto, struct sockaddr_in *replyto, opaque_t cb_arg, fwd_fun cb)
{
rpc_forward *p;
u_int *pkt_int;
@ -247,36 +244,33 @@ fwd_packet(int type_id, voidp pkt, int len, struct sockaddr_in *fwdto, struct so
* Otherwise make sure the type_id is
* fully qualified by allocating an id here.
*/
#ifdef DEBUG
switch (type_id & RPC_XID_MASK) {
case RPC_XID_PORTMAP:
dlog("Sending PORTMAP request");
dlog("Sending PORTMAP request %#x", type_id);
break;
case RPC_XID_MOUNTD:
dlog("Sending MOUNTD request %#x", type_id);
break;
case RPC_XID_NFSPING:
dlog("Sending NFS ping");
dlog("Sending NFS ping %#x", type_id);
break;
case RPC_XID_WEBNFS:
dlog("Sending WebNFS lookup %#x", type_id);
break;
default:
dlog("UNKNOWN RPC XID");
dlog("UNKNOWN RPC XID %#x", type_id);
break;
}
#endif /* DEBUG */
if (type_id & ~RPC_XID_MASK) {
p = fwd_locate(type_id);
if (p) {
#ifdef DEBUG
dlog("Discarding earlier rpc fwd handle");
#endif /* DEBUG */
fwd_free(p);
}
} else {
#ifdef DEBUG
dlog("Allocating a new xid...");
#endif /* DEBUG */
type_id = MK_RPC_XID(type_id, XID_ALLOC(struct ));
type_id = MK_RPC_XID(type_id, XID_ALLOC());
}
p = fwd_alloc();
@ -290,12 +284,13 @@ fwd_packet(int type_id, voidp pkt, int len, struct sockaddr_in *fwdto, struct so
/*
* Get the original packet id
*/
p->rf_oldid = *pkt_int;
p->rf_oldid = ntohl(*pkt_int);
/*
* Replace with newly allocated id
*/
p->rf_xid = *pkt_int = type_id;
p->rf_xid = type_id;
*pkt_int = htonl(type_id);
/*
* The sendto may fail if, for example, the route
@ -307,9 +302,9 @@ fwd_packet(int type_id, voidp pkt, int len, struct sockaddr_in *fwdto, struct so
{
char dq[20];
if (p && fwdto)
dlog("Sending packet id %#x to %s.%d",
dlog("Sending packet id %#x to %s:%d",
p->rf_xid,
inet_dquad(dq, fwdto->sin_addr.s_addr),
inet_dquad(dq, sizeof(dq), fwdto->sin_addr.s_addr),
ntohs(fwdto->sin_port));
}
#endif /* DEBUG */
@ -349,7 +344,7 @@ fwd_packet(int type_id, voidp pkt, int len, struct sockaddr_in *fwdto, struct so
p->rf_sin = *replyto;
else
memset((voidp) &p->rf_sin, 0, sizeof(p->rf_sin));
p->rf_ptr = i;
p->rf_ptr = cb_arg;
return error;
}
@ -364,6 +359,7 @@ fwd_reply(void)
int len;
u_int pkt[MAX_PACKET_SIZE / sizeof(u_int) + 1];
u_int *pkt_int;
u_int pkt_xid;
int rc;
rpc_forward *p;
struct sockaddr_in src_addr;
@ -396,6 +392,12 @@ fwd_reply(void)
rc = ud.udata.len;
else {
plog(XLOG_ERROR,"fwd_reply failed: t_errno=%d, errno=%d, flags=%d",t_errno,errno, flags);
/*
* Clear error indication, otherwise the error condition persists and
* amd gets into an infinite loop.
*/
if (t_errno == TLOOK)
t_rcvuderr(fwd_sock, NULL);
}
#else /* not HAVE_TRANSPORT_TYPE_TLI */
rc = recvfrom(fwd_sock,
@ -428,29 +430,29 @@ fwd_reply(void)
* Find packet reference
*/
pkt_int = (u_int *) pkt;
pkt_xid = ntohl(*pkt_int);
#ifdef DEBUG
switch (*pkt_int & RPC_XID_MASK) {
switch (pkt_xid & RPC_XID_MASK) {
case RPC_XID_PORTMAP:
dlog("Receiving PORTMAP reply");
dlog("Receiving PORTMAP reply %#x", pkt_xid);
break;
case RPC_XID_MOUNTD:
dlog("Receiving MOUNTD reply %#x", *pkt_int);
dlog("Receiving MOUNTD reply %#x", pkt_xid);
break;
case RPC_XID_NFSPING:
dlog("Receiving NFS ping %#x", *pkt_int);
dlog("Receiving NFS ping %#x", pkt_xid);
break;
case RPC_XID_WEBNFS:
dlog("Receiving WebNFS lookup %#x", pkt_xid);
break;
default:
dlog("UNKNOWN RPC XID");
dlog("UNKNOWN RPC XID %#x", pkt_xid);
break;
}
#endif /* DEBUG */
p = fwd_locate(*pkt_int);
p = fwd_locate(pkt_xid);
if (!p) {
#ifdef DEBUG
dlog("Can't forward reply id %#x", *pkt_int);
#endif /* DEBUG */
dlog("Can't forward reply id %#x", pkt_xid);
goto out;
}
@ -459,7 +461,7 @@ fwd_reply(void)
* Put the original message id back
* into the packet.
*/
*pkt_int = p->rf_oldid;
*pkt_int = htonl(p->rf_oldid);
/*
* Call forwarding function

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: sched.c,v 1.4.2.5 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/sched.c
*
*/
@ -56,12 +55,12 @@
typedef struct pjob pjob;
struct pjob {
qelem hdr; /* Linked list */
int pid; /* Process ID of job */
cb_fun cb_fun; /* Callback function */
voidp cb_closure; /* Closure for callback */
qelem hdr; /* Linked list */
int pid; /* Process ID of job */
cb_fun *cb_fun; /* Callback function */
opaque_t cb_arg; /* Argument for callback */
int w; /* everyone these days uses int, not a "union wait" */
voidp wchan; /* Wait channel */
wchan_t wchan; /* Wait channel */
};
/* globals */
@ -94,12 +93,12 @@ rem_que(qelem *elem)
static pjob *
sched_job(cb_fun cf, voidp ca)
sched_job(cb_fun *cf, opaque_t ca)
{
pjob *p = ALLOC(struct pjob);
p->cb_fun = cf;
p->cb_closure = ca;
p->cb_arg = ca;
/*
* Now place on wait queue
@ -115,7 +114,7 @@ sched_job(cb_fun cf, voidp ca)
* cf: Continuation function (ca is its arguments)
*/
void
run_task(task_fun tf, voidp ta, cb_fun cf, voidp ca)
run_task(task_fun *tf, opaque_t ta, cb_fun *cf, opaque_t ca)
{
pjob *p = sched_job(cf, ca);
#ifdef HAVE_SIGACTION
@ -124,7 +123,7 @@ run_task(task_fun tf, voidp ta, cb_fun cf, voidp ca)
int mask;
#endif /* not HAVE_SIGACTION */
p->wchan = (voidp) p;
p->wchan = (wchan_t) p;
#ifdef HAVE_SIGACTION
sigemptyset(&new); /* initialize signal set we wish to block */
@ -143,7 +142,7 @@ run_task(task_fun tf, voidp ta, cb_fun cf, voidp ca)
return;
}
/* child code runs here, parent have returned to caller */
/* child code runs here, parent has returned to caller */
exit((*tf) (ta));
/* firewall... */
@ -155,19 +154,17 @@ run_task(task_fun tf, voidp ta, cb_fun cf, voidp ca)
* Schedule a task to be run when woken up
*/
void
sched_task(cb_fun cf, voidp ca, voidp wchan)
sched_task(cb_fun *cf, opaque_t ca, wchan_t wchan)
{
/*
* Allocate a new task
*/
pjob *p = sched_job(cf, ca);
#ifdef DEBUG
dlog("SLEEP on %#lx", (unsigned long) wchan);
#endif /* DEBUG */
dlog("SLEEP on %p", wchan);
p->wchan = wchan;
p->pid = 0;
memset((voidp) &p->w, 0, sizeof(p->w));
p->w = 0; /* was memset (when ->w was union) */
}
@ -181,7 +178,7 @@ wakeupjob(pjob *p)
void
wakeup(voidp wchan)
wakeup(wchan_t wchan)
{
pjob *p, *p2;
@ -189,7 +186,7 @@ wakeup(voidp wchan)
return;
/*
* Can't user ITER() here because
* Can't use ITER() here because
* wakeupjob() juggles the list.
*/
for (p = AM_FIRST(pjob, &proc_wait_list);
@ -203,9 +200,20 @@ wakeup(voidp wchan)
void
wakeup_task(int rc, int term, voidp cl)
wakeup_task(int rc, int term, wchan_t wchan)
{
wakeup(cl);
wakeup(wchan);
}
wchan_t
get_mntfs_wchan(mntfs *mf)
{
if (mf &&
mf->mf_ops &&
mf->mf_ops->get_wchan)
return mf->mf_ops->get_wchan(mf);
return mf;
}
@ -236,9 +244,9 @@ do_task_notify(void)
*/
if (p->cb_fun) {
/* these two trigraphs will ensure compatibility with strict POSIX.1 */
(*p->cb_fun) (WIFEXITED(p->w) ? WEXITSTATUS(p->w) : 0,
WIFSIGNALED(p->w) ? WTERMSIG(p->w) : 0,
p->cb_closure);
p->cb_fun(WIFEXITED(p->w) ? WEXITSTATUS(p->w) : 0,
WIFSIGNALED(p->w) ? WTERMSIG(p->w) : 0,
p->cb_arg);
}
XFREE(p);
}
@ -261,11 +269,9 @@ sigchld(int sig)
if (WIFSIGNALED(w))
plog(XLOG_ERROR, "Process %d exited with signal %d",
pid, WTERMSIG(w));
#ifdef DEBUG
else
dlog("Process %d exited with status %d",
pid, WEXITSTATUS(w));
#endif /* DEBUG */
for (p = AM_FIRST(pjob, &proc_wait_list);
p2 = NEXT(pjob, p), p != HEAD(pjob, &proc_wait_list);
@ -277,18 +283,16 @@ sigchld(int sig)
}
} /* end of for loop */
#ifdef DEBUG
if (!p)
if (p == HEAD(pjob, &proc_wait_list))
dlog("can't locate task block for pid %d", pid);
#endif /* DEBUG */
/*
* Must count down children inside the while loop, otherwise we won't
* count them all, and NumChild (and later backoff) will be set
* count them all, and NumChildren (and later backoff) will be set
* incorrectly. SH/RUNIT 940519.
*/
if (--NumChild < 0)
NumChild = 0;
if (--NumChildren < 0)
NumChildren = 0;
} /* end of "while wait..." loop */
#ifdef REINSTALL_SIGNAL_HANDLER

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: srvr_amfs_auto.c,v 1.3.2.6 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/srvr_amfs_auto.c
*
*/
@ -53,9 +52,9 @@
#include <amd.h>
/* globals */
qelem amfs_auto_srvr_list = {&amfs_auto_srvr_list, &amfs_auto_srvr_list};
/* statics */
static qelem amfs_auto_srvr_list = {&amfs_auto_srvr_list, &amfs_auto_srvr_list};
static fserver *localhost;
@ -63,7 +62,7 @@ static fserver *localhost;
* Find an nfs server for the local host
*/
fserver *
find_amfs_auto_srvr(mntfs *mf)
amfs_generic_find_srvr(mntfs *mf)
{
fserver *fs = localhost;
@ -73,8 +72,8 @@ find_amfs_auto_srvr(mntfs *mf)
fs->fs_host = strdup("localhost");
fs->fs_ip = 0;
fs->fs_cid = 0;
fs->fs_pinger = 0;
fs->fs_flags = FSF_VALID;
fs->fs_pinger = AM_PINGER;
fs->fs_flags = FSF_VALID | FSF_PING_UNINIT;
fs->fs_type = "local";
fs->fs_private = 0;
fs->fs_prfree = 0;
@ -119,9 +118,7 @@ timeout_srvr(voidp v)
* we are free to remove this node
*/
if (fs->fs_refc == 0) {
#ifdef DEBUG
dlog("Deleting file server %s", fs->fs_host);
#endif /* DEBUG */
if (fs->fs_flags & FSF_WANT)
wakeup_srvr(fs);
@ -167,11 +164,9 @@ free_srvr(fserver *fs)
* removed in AM_TTL seconds if no
* other mntfs is referencing it.
*/
int ttl = (fs->fs_flags & (FSF_DOWN | FSF_ERROR)) ? 19 : AM_TTL;
int ttl = (FSRV_ERROR(fs) || FSRV_ISDOWN(fs)) ? 19 : AM_TTL;
#ifdef DEBUG
dlog("Last hard reference to file server %s - will timeout in %ds", fs->fs_host, ttl);
#endif /* DEBUG */
if (fs->fs_cid) {
untimeout(fs->fs_cid);
/*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amq.h,v 1.14.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amq/amq.h
*
*/
@ -59,5 +58,6 @@ extern amq_mount_info_list *amqproc_getmntfs_1(voidp argp, CLIENT *rqstp);
extern int *amqproc_mount_1(voidp argp, CLIENT *rqstp);
extern amq_string *amqproc_getvers_1(voidp argp, CLIENT *rqstp);
extern int *amqproc_getpid_1(voidp argp, CLIENT *rqstp);
extern amq_string *amqproc_pawd_1(amq_string *argp, CLIENT *rqstp);
#endif /* not _AMQ_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amq_clnt.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amq/amq_clnt.c
*
*/
@ -76,7 +75,7 @@ amqproc_mnttree_1(amq_string *argp, CLIENT *clnt)
memset((char *) &res, 0, sizeof(res));
if (clnt_call(clnt, AMQPROC_MNTTREE,
(XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) argp,
(XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (SVC_IN_ARG_TYPE) & res,
(XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (SVC_IN_ARG_TYPE) &res,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
@ -109,7 +108,7 @@ amqproc_stats_1(voidp argp, CLIENT *clnt)
if (clnt_call(clnt, AMQPROC_STATS,
(XDRPROC_T_TYPE) xdr_void, argp,
(XDRPROC_T_TYPE) xdr_amq_mount_stats,
(SVC_IN_ARG_TYPE) & res,
(SVC_IN_ARG_TYPE) &res,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
@ -126,7 +125,7 @@ amqproc_export_1(voidp argp, CLIENT *clnt)
if (clnt_call(clnt, AMQPROC_EXPORT,
(XDRPROC_T_TYPE) xdr_void, argp,
(XDRPROC_T_TYPE) xdr_amq_mount_tree_list,
(SVC_IN_ARG_TYPE) & res, TIMEOUT) != RPC_SUCCESS) {
(SVC_IN_ARG_TYPE) &res, TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
return (&res);
@ -141,7 +140,7 @@ amqproc_setopt_1(amq_setopt *argp, CLIENT *clnt)
memset((char *) &res, 0, sizeof(res));
if (clnt_call(clnt, AMQPROC_SETOPT, (XDRPROC_T_TYPE) xdr_amq_setopt,
(SVC_IN_ARG_TYPE) argp, (XDRPROC_T_TYPE) xdr_int,
(SVC_IN_ARG_TYPE) & res, TIMEOUT) != RPC_SUCCESS) {
(SVC_IN_ARG_TYPE) &res, TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
return (&res);
@ -156,7 +155,7 @@ amqproc_getmntfs_1(voidp argp, CLIENT *clnt)
memset((char *) &res, 0, sizeof(res));
if (clnt_call(clnt, AMQPROC_GETMNTFS, (XDRPROC_T_TYPE) xdr_void, argp,
(XDRPROC_T_TYPE) xdr_amq_mount_info_list,
(SVC_IN_ARG_TYPE) & res, TIMEOUT) != RPC_SUCCESS) {
(SVC_IN_ARG_TYPE) &res, TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
return (&res);
@ -170,7 +169,7 @@ amqproc_mount_1(voidp argp, CLIENT *clnt)
memset((char *) &res, 0, sizeof(res));
if (clnt_call(clnt, AMQPROC_MOUNT, (XDRPROC_T_TYPE) xdr_amq_string, argp,
(XDRPROC_T_TYPE) xdr_int, (SVC_IN_ARG_TYPE) & res,
(XDRPROC_T_TYPE) xdr_int, (SVC_IN_ARG_TYPE) &res,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
@ -185,7 +184,7 @@ amqproc_getvers_1(voidp argp, CLIENT *clnt)
memset((char *) &res, 0, sizeof(res));
if (clnt_call(clnt, AMQPROC_GETVERS, (XDRPROC_T_TYPE) xdr_void, argp,
(XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) & res,
(XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) &res,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
@ -200,7 +199,23 @@ amqproc_getpid_1(voidp argp, CLIENT *clnt)
memset((char *) &res, 0, sizeof(res));
if (clnt_call(clnt, AMQPROC_GETPID, (XDRPROC_T_TYPE) xdr_void, argp,
(XDRPROC_T_TYPE) xdr_int, (SVC_IN_ARG_TYPE) & res,
(XDRPROC_T_TYPE) xdr_int, (SVC_IN_ARG_TYPE) &res,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
return (&res);
}
amq_string *
amqproc_pawd_1(amq_string *argp, CLIENT *clnt)
{
static amq_string res;
memset((char *) &res, 0, sizeof(res));
if (clnt_call(clnt, AMQPROC_PAWD,
(XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) argp,
(XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) &res,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amq_xdr.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amq/amq_xdr.c
*
*/
@ -107,11 +106,17 @@ xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp)
return (FALSE);
}
if (!xdr_pointer(xdrs, (char **) &objp->mt_next, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
if (!xdr_pointer(xdrs,
(char **) ((voidp) &objp->mt_next),
sizeof(amq_mount_tree),
(XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
return (FALSE);
}
if (!xdr_pointer(xdrs, (char **) &objp->mt_child, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
if (!xdr_pointer(xdrs,
(char **) ((voidp) &objp->mt_child),
sizeof(amq_mount_tree),
(XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
return (FALSE);
}
@ -122,7 +127,10 @@ xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp)
bool_t
xdr_amq_mount_tree_p(XDR *xdrs, amq_mount_tree_p *objp)
{
if (!xdr_pointer(xdrs, (char **) objp, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
if (!xdr_pointer(xdrs,
(char **) objp,
sizeof(amq_mount_tree),
(XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
return (FALSE);
}
return (TRUE);
@ -169,7 +177,7 @@ bool_t
xdr_amq_mount_info_list(XDR *xdrs, amq_mount_info_list *objp)
{
if (!xdr_array(xdrs,
(char **) &objp->amq_mount_info_list_val,
(char **) ((voidp) &objp->amq_mount_info_list_val),
(u_int *) &objp->amq_mount_info_list_len,
~0,
sizeof(amq_mount_info),
@ -184,7 +192,7 @@ bool_t
xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp)
{
if (!xdr_array(xdrs,
(char **) &objp->amq_mount_tree_list_val,
(char **) ((voidp) &objp->amq_mount_tree_list_val),
(u_int *) &objp->amq_mount_tree_list_len,
~0,
sizeof(amq_mount_tree_p),

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: pawd.c,v 1.6.2.4 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amq/pawd.c
*
*/
@ -58,48 +57,11 @@
#include <am_defs.h>
#include <amq.h>
/* statics */
static char *localhost="localhost";
static char newdir[MAXPATHLEN];
static char *localhost = "localhost";
static char transform[MAXPATHLEN];
static int
find_mt(amq_mount_tree *mt, char *dir)
{
while (mt) {
if (STREQ(mt->mt_type, "link") ||
STREQ(mt->mt_type, "nfs") ||
STREQ(mt->mt_type, "nfsl")) {
int len = strlen(mt->mt_mountpoint);
if (NSTREQ(mt->mt_mountpoint, dir, len) &&
((dir[len] == '\0') || (dir[len] == '/'))) {
char tmp_buf[MAXPATHLEN];
strcpy(tmp_buf, mt->mt_directory);
strcat(tmp_buf, &dir[len]);
strcpy(newdir, tmp_buf);
return 1;
}
}
if (find_mt(mt->mt_next,dir))
return 1;
mt = mt->mt_child;
}
return 0;
}
static int
find_mlp(amq_mount_tree_list *mlp, char *dir)
{
int i;
for (i = 0; i < mlp->amq_mount_tree_list_len; i++) {
if (find_mt(mlp->amq_mount_tree_list_val[i], dir))
return 1;
}
return 0;
}
#ifdef HAVE_CNODEID
static char *
@ -160,7 +122,8 @@ hack_name(char *dir)
fprintf(stderr, "partition %s, username %s\n", partition, username);
#endif /* DEBUG */
sprintf(hesiod_lookup, "%s.homes-remote", username);
xsnprintf(hesiod_lookup, sizeof(hesiod_lookup),
"%s.homes-remote", username);
hes = hes_resolve(hesiod_lookup, "amd");
if (!hes)
return NULL;
@ -184,9 +147,10 @@ hack_name(char *dir)
#ifdef DEBUG
fprintf(stderr, "A match, munging....\n");
#endif /* DEBUG */
strcpy(transform, "/home/");
strcat(transform, username);
if (*ch) strcat(transform, ch);
xstrlcpy(transform, "/home/", sizeof(transform));
xstrlcat(transform, username, sizeof(transform));
if (*ch)
xstrlcat(transform, ch, sizeof(transform));
#ifdef DEBUG
fprintf(stderr, "Munged to <%s>\n", transform);
#endif /* DEBUG */
@ -216,8 +180,9 @@ transform_dir(char *dir)
int s = RPC_ANYSOCK;
CLIENT *clnt;
struct hostent *hp;
amq_mount_tree_list *mlp;
struct timeval tmo = {10, 0};
char *dummystr;
amq_string *spp;
#ifdef DISK_HOME_HACK
if (ch = hack_name(dir))
@ -230,31 +195,37 @@ transform_dir(char *dir)
server = localhost;
#endif /* not HAVE_CNODEID */
if ((hp = gethostbyname(server)) == 0)
if ((hp = gethostbyname(server)) == NULL)
return dir;
memset(&server_addr, 0, sizeof(server_addr));
/* as per POSIX, sin_len need not be set (used internally by kernel) */
server_addr.sin_family = AF_INET;
server_addr.sin_addr = *(struct in_addr *) hp->h_addr;
clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, tmo, &s);
if (clnt == 0)
if (clnt == NULL)
clnt = clnttcp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, &s, 0, 0);
if (clnt == NULL)
return dir;
strcpy(transform,dir);
while ( (mlp = amqproc_export_1((voidp)0, clnt)) &&
find_mlp(mlp,transform) ) {
strcpy(transform,newdir);
xstrlcpy(transform, dir, sizeof(transform));
dummystr = transform;
spp = amqproc_pawd_1((amq_string *) &dummystr, clnt);
if (spp && *spp && **spp) {
xstrlcpy(transform, *spp, sizeof(transform));
XFREE(*spp);
}
clnt_destroy(clnt);
return transform;
}
/* getawd() is a substitute for getwd() which transforms the path */
static char *
getawd(char *path)
getawd(char *path, size_t l)
{
#ifdef HAVE_GETCWD
char *wd = getcwd(path, MAXPATHLEN+1);
char *wd = getcwd(path, MAXPATHLEN);
#else /* not HAVE_GETCWD */
char *wd = getwd(path);
#endif /* not HAVE_GETCWD */
@ -262,7 +233,7 @@ getawd(char *path)
if (wd == NULL) {
return NULL;
}
strcpy(path, transform_dir(wd));
xstrlcpy(path, transform_dir(wd), l);
return path;
}
@ -273,7 +244,7 @@ main(int argc, char *argv[])
char tmp_buf[MAXPATHLEN], *wd;
if (argc == 1) {
wd = getawd(tmp_buf);
wd = getawd(tmp_buf, sizeof(tmp_buf));
if (wd == NULL) {
fprintf(stderr, "pawd: %s\n", tmp_buf);
exit(1);

View File

@ -25,6 +25,8 @@
*/
#define UNMOUNT_TRAP(mnt) @am_utils_unmount_call@(@am_utils_unmount_args@)
/* End of replaced UNMOUNT_TRAP macro definition */
/* umount(8) executable path, for type:=program */
#define UNMOUNT_PROGRAM "@UNMOUNT_PROGRAM@"
/*
* The next line is a literal inclusion of a file which includes a

View File

@ -23,7 +23,7 @@ if [ ! -f m4/macros/HEADER ]; then
fi
# remove any remaining autom4te.cache directory
rm -fr autom4te.cache
rm -fr autom4te.cache autom4te-*.cache
# generate acinclude.m4 file
echo "AMU: prepare acinclude.m4..."

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: checkmount_bsd44.c,v 1.3.2.4 2004/01/06 03:15:19 ezk Exp $
* File: am-utils/conf/checkmount/checkmount_bsd44.c
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: mtab_bsd.c,v 1.3.2.5 2004/01/06 03:15:19 ezk Exp $
* File: am-utils/conf/mtab/mtab_bsd.c
*
*/

View File

@ -3,3 +3,4 @@
(dst)->addr = (struct sockaddr *) (src); \
(dst)->addrlen = sizeof(*src); \
}
#define NFS_ARGS_T_ADDR_IS_POINTER 1

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: transp_sockets.c,v 1.6.2.11 2004/01/06 03:15:20 ezk Exp $
* File: am-utils/conf/transp/transp_sockets.c
*
* Socket specific utilities.
* -Erez Zadok <ezk@cs.columbia.edu>
@ -55,18 +54,67 @@
* find the IP address that can be used to connect to the local host
*/
void
amu_get_myaddress(struct in_addr *iap)
amu_get_myaddress(struct in_addr *iap, const char *preferred_localhost)
{
struct hostent *hp;
char dq[20];
#ifdef DEBUG_off
#error this code is old and probably not useful any longer.
#error Erez, Jan 21, 2004.
struct sockaddr_in sin;
/*
* Most modern systems should use 127.0.0.1 as the localhost address over
* which you can do NFS mounts. In the past we found that some NFS
* clients may not allow mounts from localhost. So we used
* get_myaddress() and that seemed to work. Alas, on some other systems,
* get_myaddress() may return one of the interface addresses at random,
* and thus use a less efficient IP address than 127.0.0.1. The solution
* is to hard-code 127.0.0.1, but still check if get_myaddress() returns a
* different value and warn about it.
*/
memset((char *) &sin, 0, sizeof(sin));
get_myaddress(&sin);
iap->s_addr = sin.sin_addr.s_addr;
if (sin.sin_addr.s_addr != htonl(INADDR_LOOPBACK))
dlog("amu_get_myaddress: myaddress conflict (0x%x vs. 0x%lx)",
sin.sin_addr.s_addr, (u_long) htonl(INADDR_LOOPBACK));
#endif /* DEBUG_off */
if (preferred_localhost == NULL)
goto out;
/* if specified preferred locahost, then try to use it */
hp = gethostbyname(preferred_localhost);
if (hp == NULL) {
/* XXX: if hstrerror()/h_errno aren't portable, then need to port the next statement */
plog(XLOG_ERROR, "Unable to resolve localhost_address \"%s\" (%s): using default",
preferred_localhost, hstrerror(h_errno));
goto out;
}
if (hp->h_addr_list == NULL) {
plog(XLOG_ERROR, "localhost_address \"%s\" has no IP addresses: using default",
preferred_localhost);
goto out;
}
if (hp->h_addr_list[1] != NULL) {
plog(XLOG_ERROR, "localhost_address \"%s\" has more than one IP addresses: using first",
preferred_localhost);
goto out;
}
memmove((voidp) &iap->s_addr, (voidp) hp->h_addr_list[0], sizeof(iap->s_addr));
plog(XLOG_INFO, "localhost_address \"%s\" requested, using %s",
preferred_localhost, inet_dquad(dq, sizeof(dq), iap->s_addr));
return;
out:
iap->s_addr = htonl(INADDR_LOOPBACK);
}
/*
* How to bind to reserved ports.
* Note: if *pp is non-null and is greater than 0, then *pp will not be modified.
*/
int
bind_resv_port(int so, u_short *pp)
@ -78,16 +126,21 @@ bind_resv_port(int so, u_short *pp)
memset((voidp) &sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
port = IPPORT_RESERVED;
do {
--port;
sin.sin_port = htons(port);
if (pp && *pp > 0) {
sin.sin_port = htons(*pp);
rc = bind(so, (struct sockaddr *) &sin, sizeof(sin));
} while (rc < 0 && (int) port > IPPORT_RESERVED / 2);
} else {
port = IPPORT_RESERVED;
if (pp && rc == 0)
*pp = port;
do {
--port;
sin.sin_port = htons(port);
rc = bind(so, (struct sockaddr *) &sin, sizeof(sin));
} while (rc < 0 && (int) port > IPPORT_RESERVED / 2);
if (pp && rc == 0)
*pp = port;
}
return rc;
}
@ -161,9 +214,7 @@ get_mount_client(char *unused_host, struct sockaddr_in *sin, struct timeval *tv,
*sock = RPC_ANYSOCK;
return NULL;
}
#ifdef DEBUG
dlog("get_mount_client: Using udp, port %d", sin->sin_port);
#endif /* DEBUG */
return client;
}
@ -175,7 +226,19 @@ struct sockaddr_in *
amu_svc_getcaller(SVCXPRT *xprt)
{
/* glibc 2.2 returns a sockaddr_storage ??? */
return (struct sockaddr_in *)svc_getcaller(xprt);
return (struct sockaddr_in *) svc_getcaller(xprt);
}
/*
* register an RPC server
*/
int
amu_svc_register(SVCXPRT *xprt, u_long prognum, u_long versnum,
void (*dispatch)(struct svc_req *rqstp, SVCXPRT *transp),
u_long protocol, struct netconfig *dummy)
{
return svc_register(xprt, prognum, versnum, dispatch, protocol);
}
@ -188,21 +251,28 @@ create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*
*soNFSp = socket(AF_INET, SOCK_DGRAM, 0);
if (*soNFSp < 0 || bind_resv_port(*soNFSp, NULL) < 0) {
if (*soNFSp < 0 || bind_resv_port(*soNFSp, nfs_portp) < 0) {
plog(XLOG_FATAL, "Can't create privileged nfs port (socket)");
if (*soNFSp >= 0)
close(*soNFSp);
return 1;
}
if ((*nfs_xprtp = svcudp_create(*soNFSp)) == NULL) {
plog(XLOG_FATAL, "cannot create rpc/udp service");
close(*soNFSp);
return 2;
}
if ((*nfs_portp = (*nfs_xprtp)->xp_port) >= IPPORT_RESERVED) {
plog(XLOG_FATAL, "Can't create privileged nfs port");
svc_destroy(*nfs_xprtp);
close(*soNFSp);
return 1;
}
if (!svc_register(*nfs_xprtp, NFS_PROGRAM, NFS_VERSION, dispatch_fxn, 0)) {
plog(XLOG_FATAL, "unable to register (%ld, %ld, 0)",
(u_long) NFS_PROGRAM, (u_long) NFS_VERSION);
svc_destroy(*nfs_xprtp);
close(*soNFSp);
return 3;
}
@ -214,7 +284,13 @@ create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*
* Create the amq service for amd (both TCP and UDP)
*/
int
create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp)
create_amq_service(int *udp_soAMQp,
SVCXPRT **udp_amqpp,
struct netconfig **dummy1,
int *tcp_soAMQp,
SVCXPRT **tcp_amqpp,
struct netconfig **dummy2,
u_short preferred_amq_port)
{
/* first create TCP service */
if (tcp_soAMQp) {
@ -224,11 +300,25 @@ create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, int *tcp_soAMQp, SVCXPR
return 1;
}
/* next, bind to a specific (TCP) port if asked for */
if (preferred_amq_port > 0) {
/*
* Note: if &preferred_amq_port is non-null and is greater than 0,
* then the pointer will not be modified. We don't want it to be
* modified because it was passed down to create_amq_service as a
* non-pointer (a variable on the stack, not to be modified!)
*/
if (bind_resv_port(*tcp_soAMQp, &preferred_amq_port) < 0) {
plog(XLOG_FATAL, "can't bind amq service to requested TCP port %d: %m)", preferred_amq_port);
return 1;
}
}
/* now create RPC service handle for amq */
if (tcp_amqpp &&
(*tcp_amqpp = svctcp_create(*tcp_soAMQp, AMQ_SIZE, AMQ_SIZE)) == NULL) {
plog(XLOG_FATAL, "cannot create tcp service for amq: soAMQp=%d", *tcp_soAMQp);
return 2;
return 1;
}
#ifdef SVCSET_CONNMAXREC
@ -240,7 +330,7 @@ create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, int *tcp_soAMQp, SVCXPR
# ifndef RPC_MAXDATASIZE
# define RPC_MAXDATASIZE 9000
# endif /* not RPC_MAXDATASIZE */
{
if (tcp_amqpp) {
int maxrec = RPC_MAXDATASIZE;
SVC_CONTROL(*tcp_amqpp, SVCSET_CONNMAXREC, &maxrec);
}
@ -252,14 +342,26 @@ create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, int *tcp_soAMQp, SVCXPR
*udp_soAMQp = socket(AF_INET, SOCK_DGRAM, 0);
if (*udp_soAMQp < 0) {
plog(XLOG_FATAL, "cannot create udp socket for amq service: %m");
return 3;
return 1;
}
/* next, bind to a specific (UDP) port if asked for */
if (preferred_amq_port > 0) {
/*
* Note: see comment about using &preferred_amq_port above in this
* function.
*/
if (bind_resv_port(*udp_soAMQp, &preferred_amq_port) < 0) {
plog(XLOG_FATAL, "can't bind amq service to requested UDP port %d: %m)", preferred_amq_port);
return 1;
}
}
/* now create RPC service handle for amq */
if (udp_amqpp &&
(*udp_amqpp = svcudp_bufcreate(*udp_soAMQp, AMQ_SIZE, AMQ_SIZE)) == NULL) {
plog(XLOG_FATAL, "cannot create udp service for amq: soAMQp=%d", *udp_soAMQp);
return 4;
return 1;
}
}
@ -268,34 +370,47 @@ create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, int *tcp_soAMQp, SVCXPR
/*
* Ping the portmapper on a remote system by calling the nullproc
* Check if the portmapper is running and reachable: 0==down, 1==up
*/
enum clnt_stat
pmap_ping(struct sockaddr_in *address)
int check_pmap_up(char *host, struct sockaddr_in* sin)
{
CLIENT *client;
enum clnt_stat clnt_stat = RPC_TIMEDOUT; /* assume failure */
int socket = RPC_ANYSOCK;
struct timeval timeout;
timeout.tv_sec = 3;
timeout.tv_sec = 2;
timeout.tv_usec = 0;
address->sin_port = htons(PMAPPORT);
client = clntudp_create(address, PMAPPROG, PMAPVERS, timeout, &socket);
if (client != (CLIENT *) NULL) {
clnt_stat = clnt_call(client,
PMAPPROC_NULL,
(XDRPROC_T_TYPE) xdr_void,
NULL,
(XDRPROC_T_TYPE) xdr_void,
NULL,
timeout);
clnt_destroy(client);
}
close(socket);
address->sin_port = 0;
sin->sin_port = htons(PMAPPORT);
client = clntudp_create(sin, PMAPPROG, PMAPVERS, timeout, &socket);
return clnt_stat;
if (client == (CLIENT *) NULL) {
plog(XLOG_ERROR,
"check_pmap_up: cannot create connection to contact portmapper on host \"%s\"%s",
host, clnt_spcreateerror(""));
return 0;
}
timeout.tv_sec = 6;
/* Ping the portmapper on a remote system by calling the nullproc */
clnt_stat = clnt_call(client,
PMAPPROC_NULL,
(XDRPROC_T_TYPE) xdr_void,
NULL,
(XDRPROC_T_TYPE) xdr_void,
NULL,
timeout);
clnt_destroy(client);
close(socket);
sin->sin_port = 0;
if (clnt_stat == RPC_TIMEDOUT) {
plog(XLOG_ERROR,
"check_pmap_up: failed to contact portmapper on host \"%s\": %s",
host, clnt_sperrno(clnt_stat));
return 0;
}
return 1;
}
@ -310,6 +425,7 @@ get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const c
enum clnt_stat clnt_stat;
struct timeval tv;
int sock;
char *errstr;
/*
* If not set or set wrong, then try from NFS_VERS_MAX on down. If
@ -319,23 +435,15 @@ get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const c
nfs_version = NFS_VERS_MAX;
again = 1;
}
tv.tv_sec = 3; /* retry every 3 seconds, but also timeout */
tv.tv_sec = 2; /* retry every 2 seconds, but also timeout */
tv.tv_usec = 0;
/*
* First check if remote portmapper is up (verify if remote host is up).
*/
clnt_stat = pmap_ping(sin);
if (clnt_stat == RPC_TIMEDOUT) {
plog(XLOG_ERROR, "get_nfs_version: failed to contact portmapper on host \"%s\": %s", host, clnt_sperrno(clnt_stat));
return 0;
}
#ifdef HAVE_FS_NFS3
try_again:
#endif /* HAVE_FS_NFS3 */
sock = RPC_ANYSOCK;
errstr = NULL;
if (STREQ(proto, "tcp"))
clnt = clnttcp_create(sin, NFS_PROGRAM, nfs_version, &sock, 0, 0);
else if (STREQ(proto, "udp"))
@ -343,45 +451,90 @@ get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const c
else
clnt = NULL;
if (clnt == NULL) {
if (clnt != NULL) {
/* Try three times (6/2=3) to verify the CLIENT handle. */
tv.tv_sec = 6;
clnt_stat = clnt_call(clnt,
NFSPROC_NULL,
(XDRPROC_T_TYPE) xdr_void,
0,
(XDRPROC_T_TYPE) xdr_void,
0,
tv);
if (clnt_stat != RPC_SUCCESS)
errstr = clnt_sperrno(clnt_stat);
close(sock);
clnt_destroy(clnt);
} else {
#ifdef HAVE_CLNT_SPCREATEERROR
plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s: %s",
(int) nfs_version, proto, host, clnt_spcreateerror(""));
errstr = clnt_spcreateerror("");
#else /* not HAVE_CLNT_SPCREATEERROR */
plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s",
(int) nfs_version, proto, host);
errstr = "";
#endif /* not HAVE_CLNT_SPCREATEERROR */
return 0;
}
/* Try a couple times to verify the CLIENT handle. */
tv.tv_sec = 6;
clnt_stat = clnt_call(clnt,
NFSPROC_NULL,
(XDRPROC_T_TYPE) xdr_void,
0,
(XDRPROC_T_TYPE) xdr_void,
0,
tv);
close(sock);
clnt_destroy(clnt);
if (clnt_stat != RPC_SUCCESS) {
if (errstr) {
plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s%s",
(int) nfs_version, proto, host, errstr);
if (again) {
#ifdef HAVE_FS_NFS3
if (nfs_version == NFS_VERSION3) {
plog(XLOG_INFO, "get_nfs_version trying a lower version");
nfs_version = NFS_VERSION;
again = 0;
plog(XLOG_INFO, "get_nfs_version trying a lower version: NFS(%d,%s)", (int) nfs_version, proto);
}
goto try_again;
#endif /* HAVE_FS_NFS3 */
}
plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s",
(int) nfs_version, proto, host);
return 0;
}
plog(XLOG_INFO, "get_nfs_version: returning (%d,%s) on host %s",
plog(XLOG_INFO, "get_nfs_version: returning NFS(%d,%s) on host %s",
(int) nfs_version, proto, host);
return nfs_version;
}
#if defined(HAVE_FS_AUTOFS) && defined(AUTOFS_PROG)
/*
* Register the autofs service for amd
*/
int
register_autofs_service(char *autofs_conftype, void (*autofs_dispatch)(struct svc_req *rqstp, SVCXPRT *transp))
{
int autofs_socket;
SVCXPRT *autofs_xprt = NULL;
autofs_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (autofs_socket < 0 || bind_resv_port(autofs_socket, NULL) < 0) {
plog(XLOG_FATAL, "Can't create privileged autofs port (socket)");
return 1;
}
if ((autofs_xprt = svcudp_create(autofs_socket)) == NULL) {
plog(XLOG_FATAL, "Can't create autofs rpc/udp service");
return 2;
}
if (autofs_xprt->xp_port >= IPPORT_RESERVED) {
plog(XLOG_FATAL, "Can't create privileged autofs port");
return 1;
}
if (!svc_register(autofs_xprt, AUTOFS_PROG, AUTOFS_VERS, autofs_dispatch, 0)) {
plog(XLOG_FATAL, "unable to register (%ld, %ld, 0)",
(u_long) AUTOFS_PROG, (u_long) AUTOFS_VERS);
return 3;
}
return 0; /* all is well */
}
int
unregister_autofs_service(char *autofs_conftype)
{
svc_unregister(AUTOFS_PROG, AUTOFS_VERS);
return 0;
}
#endif /* HAVE_FS_AUTOFS && AUTOFS_PROG */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: umount_bsd44.c,v 1.3.2.4 2004/01/06 03:15:20 ezk Exp $
* File: am-utils/conf/umount/umount_bsd44.c
*
*/
@ -54,12 +53,12 @@
int
umount_fs(char *fs_name, const char *mnttabname)
umount_fs(char *mntdir, const char *mnttabname, u_int unmount_flags)
{
int error;
eintr:
error = unmount(fs_name, 0);
error = unmount(mntdir, 0);
if (error < 0)
error = errno;
@ -67,23 +66,55 @@ umount_fs(char *fs_name, const char *mnttabname)
case EINVAL:
case ENOTBLK:
case ENOENT:
plog(XLOG_WARNING, "unmount: %s is not mounted", fs_name);
plog(XLOG_WARNING, "unmount: %s is not mounted", mntdir);
error = 0; /* Not really an error */
break;
case EINTR:
#ifdef DEBUG
/* not sure why this happens, but it does. ask kirk one day... */
dlog("%s: unmount: %m", fs_name);
#endif /* DEBUG */
dlog("%s: unmount: %m", mntdir);
goto eintr;
#ifdef DEBUG
#ifdef MNT2_GEN_OPT_FORCE
case EBUSY:
case EIO:
case ESTALE:
/* caller determines if forced unmounts should be used */
if (unmount_flags & AMU_UMOUNT_FORCE) {
error = umount2_fs(mntdir, unmount_flags);
if (error < 0)
error = errno;
else
return error;
}
/* fallthrough */
#endif /* MNT2_GEN_OPT_FORCE */
default:
dlog("%s: unmount: %m", fs_name);
dlog("%s: unmount: %m", mntdir);
break;
#endif /* DEBUG */
}
return error;
}
#ifdef MNT2_GEN_OPT_FORCE
/* force unmount, no questions asked, without touching mnttab file */
int
umount2_fs(const char *mntdir, u_int unmount_flags)
{
int error = 0;
if (unmount_flags & AMU_UMOUNT_FORCE) {
plog(XLOG_INFO, "umount2_fs: trying unmount/forced on %s", mntdir);
error = unmount(mntdir, MNT2_GEN_OPT_FORCE);
if (error < 0 && (errno == EINVAL || errno == ENOENT))
error = 0; /* ignore EINVAL/ENOENT */
if (error < 0)
plog(XLOG_WARNING, "%s: unmount/force: %m", mntdir);
else
dlog("%s: unmount/force: OK", mntdir);
}
return error;
}
#endif /* MNT2_GEN_OPT_FORCE */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,4 @@
@set UPDATED 28 August 2003
@set EDITION 6.0.9
@set VERSION 6.0.9
@set UPDATED 20 April 2006
@set UPDATED-MONTH April 2006
@set EDITION 6.1.5
@set VERSION 6.1.5

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: fsi_analyze.c,v 1.3.2.5 2004/01/06 03:15:23 ezk Exp $
* File: am-utils/fsinfo/fsi_analyze.c
*
*/
@ -112,10 +111,11 @@ domain_strip(char *otherdom, char *localdom)
static char *
compute_hostpath(char *hn)
{
char *p = strdup(hn);
char *p = xmalloc(MAXPATHLEN);
char *d;
char path[MAXPATHLEN];
xstrlcpy(p, hn, MAXPATHLEN);
domain_strip(p, hostname);
path[0] = '\0';
@ -123,16 +123,16 @@ compute_hostpath(char *hn)
d = strrchr(p, '.');
if (d) {
*d = 0;
strcat(path, d + 1);
strcat(path, "/");
xstrlcat(path, d + 1, sizeof(path));
xstrlcat(path, "/", sizeof(path));
} else {
strcat(path, p);
xstrlcat(path, p, sizeof(path));
}
} while (d);
fsi_log("hostpath of '%s' is '%s'", hn, path);
strcpy(p, path);
xstrlcpy(p, path, MAXPATHLEN);
return p;
}
@ -221,7 +221,7 @@ analyze_dkmount_tree(qelem *q, fsi_mount *parent, disk_fs *dk)
fsi_log("Mount %s:", mp->m_name);
if (parent) {
char n[MAXPATHLEN];
sprintf(n, "%s/%s", parent->m_name, mp->m_name);
xsnprintf(n, sizeof(n), "%s/%s", parent->m_name, mp->m_name);
if (*mp->m_name == '/')
lerror(mp->m_ioloc, "sub-directory %s of %s starts with '/'", mp->m_name, parent->m_name);
else if (STREQ(mp->m_name, "default"))
@ -281,10 +281,10 @@ analyze_dkmounts(disk_fs *dk, qelem *q)
/*
* Now see if a default mount point is required
*/
if (STREQ(mp2->m_name, "default")) {
if (mp2 && STREQ(mp2->m_name, "default")) {
if (ISSET(mp2->m_mask, DM_VOLNAME)) {
char nbuf[1024];
compute_automount_point(nbuf, dk->d_host, mp2->m_volname);
compute_automount_point(nbuf, sizeof(nbuf), dk->d_host, mp2->m_volname);
XFREE(mp2->m_name);
mp2->m_name = strdup(nbuf);
fsi_log("%s:%s has default mount on %s", dk->d_host->h_hostname, dk->d_dev, mp2->m_name);
@ -516,7 +516,8 @@ analyze_mounts(host *hp)
ITER(dd, dict_data, &de->de_q) {
fsi_mount *mp = (fsi_mount *) dd->dd_data;
if (STREQ(mp->m_dk->d_host->h_hostname, fp->f_from)) {
if (fp->f_from &&
STREQ(mp->m_dk->d_host->h_hostname, fp->f_from)) {
mp2 = mp;
break;
}
@ -542,7 +543,8 @@ analyze_mounts(host *hp)
lerror(fp->f_ioloc, "volname %s unknown", fp->f_volname);
} else if (matched) {
fixup_required_mount_info(fp, de);
if (de)
fixup_required_mount_info(fp, de);
req = ~fp->f_mask & FM_REQUIRED;
if (req) {
show_required(fp->f_ioloc, req, fp->f_volname, hp->h_hostname,
@ -631,7 +633,7 @@ analyze_automount_tree(qelem *q, char *pref, int lvl)
if (lvl > 0 || ap->a_mount)
if (ap->a_name[1] && strchr(ap->a_name + 1, '/'))
lerror(ap->a_ioloc, "not allowed '/' in a directory name");
sprintf(nname, "%s/%s", pref, ap->a_name);
xsnprintf(nname, sizeof(nname), "%s/%s", pref, ap->a_name);
XFREE(ap->a_name);
ap->a_name = strdup(nname[1] == '/' ? nname + 1 : nname);
fsi_log("automount point %s:", ap->a_name);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,12 +36,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: fsi_data.h,v 1.3.2.4 2004/01/06 03:15:23 ezk Exp $
* File: am-utils/fsinfo/fsi_data.h
*
*/
#ifndef _FSI_DATA_H
#define _FSI_DATA_H
typedef struct auto_tree auto_tree;
typedef struct automount automount;
typedef struct dict dict;
@ -233,3 +235,4 @@ struct ioloc {
int i_line;
char *i_file;
};
#endif /* not _FSI_DATA_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: fsi_dict.c,v 1.3.2.4 2004/01/06 03:15:23 ezk Exp $
* File: am-utils/fsinfo/fsi_dict.c
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: fsi_gram.y,v 1.4.2.4 2004/01/06 03:15:23 ezk Exp $
* File: am-utils/fsinfo/fsi_gram.y
*
*/
@ -50,22 +49,6 @@
#include <fsi_data.h>
#include <fsinfo.h>
/* AIX requires this to be the first thing in the file. */
#ifndef __GNUC__
# if HAVE_ALLOCA_H
# include <alloca.h>
# else /* not HAVE_ALLOCA_H */
# ifdef _AIX
#pragma alloca
# else /* not _AIX */
# ifndef alloca
/* predefined by HP cc +Olibcalls */
voidp alloca();
# endif /* not alloca */
# endif /* not _AIX */
# endif /* not HAVE_ALLOCA_H */
#endif /* not __GNUC__ */
extern qelem *list_of_hosts, *list_of_automounts;
%}

View File

@ -1,6 +1,6 @@
%{
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -38,7 +38,7 @@
* SUCH DAMAGE.
*
*
* $Id: fsi_lex.l,v 1.4.2.6 2004/05/12 15:54:31 ezk Exp $
* File: am-utils/fsinfo/fsi_lex.l
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -33,9 +33,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: fsi_util.c,v 1.3.2.6 2004/01/06 03:15:23 ezk Exp $
* File: am-utils/fsinfo/fsi_util.c
*
*/
@ -77,7 +76,7 @@ show_total(void)
if (total_mmm < 0)
fputc('*', stdout);
sprintf(n, "%d", total_shown);
xsnprintf(n, sizeof(n), "%d", total_shown);
len = strlen(n);
if (col_output(len))
fputc(' ', stdout);
@ -276,7 +275,7 @@ pref_open(char *pref, char *hn, void (*hdr) (FILE *, char *), char *arg)
char p[MAXPATHLEN];
FILE *ef;
sprintf(p, "%s%s", pref, hn);
xsnprintf(p, sizeof(p), "%s%s", pref, hn);
fsi_log("Writing %s info for %s to %s", pref, hn, p);
ef = fopen(p, "w");
if (ef) {
@ -301,20 +300,9 @@ pref_close(FILE *fp)
* Determine where Amd would automount the host/volname pair
*/
void
compute_automount_point(char *buf, host *hp, char *vn)
compute_automount_point(char *buf, size_t l, host *hp, char *vn)
{
sprintf(buf, "%s/%s%s", autodir, hp->h_lochost, vn);
}
char *
xcalloc(int i, int s)
{
char *p = (char *) calloc(i, (unsigned) s);
if (!p)
fatal("Out of memory");
return p;
xsnprintf(buf, l, "%s/%s%s", autodir, hp->h_lochost, vn);
}
@ -463,7 +451,7 @@ set_ether_if(ether_if *ep, int k, char *v)
case EF_INADDR:{
ep->e_inaddr.s_addr = inet_addr(v);
if (ep->e_inaddr.s_addr == (u_long) - 1)
if ((int) ep->e_inaddr.s_addr == (int) INADDR_NONE)
yyerror("malformed IP dotted quad: %s", v);
XFREE(v);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -37,7 +37,7 @@
* SUCH DAMAGE.
*
*
* $Id: fsinfo.h,v 1.4.2.7 2004/05/12 15:54:31 ezk Exp $
* File: am-utils/fsinfo/fsinfo.h
*
*/
@ -80,7 +80,7 @@ extern fsi_mount *new_mount(void);
extern qelem *new_que(void);
extern void analyze_automounts(qelem *);
extern void analyze_hosts(qelem *);
extern void compute_automount_point(char *, host *, char *);
extern void compute_automount_point(char *, size_t, host *, char *);
extern void dict_add(dict *, char *, char *);
extern void error(char *fmt, ...)
__attribute__((__format__(__printf__, 1, 2)));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: wr_atab.c,v 1.3.2.4 2004/01/06 03:15:23 ezk Exp $
* File: am-utils/fsinfo/wr_atab.c
*
*/
@ -54,7 +53,7 @@
* Write a sequence of automount mount map entries
*/
static int
write_amount_info(FILE *af, automount *ap, int sk)
write_amount_info(FILE *af, automount *ap, u_int sk)
{
int errors = 0;
@ -135,7 +134,8 @@ write_amount_info(FILE *af, automount *ap, int sk)
*/
if (mp->m_dk->d_host->h_lochost) {
char amountpt[1024];
compute_automount_point(amountpt, mp->m_dk->d_host, mp->m_exported->m_volname);
compute_automount_point(amountpt, sizeof(amountpt),
mp->m_dk->d_host, mp->m_exported->m_volname);
if (!STREQ(mp->m_dk->d_mountpt, amountpt)) {
/*
* ap->a_volname is the name of the aliased volume
@ -221,12 +221,12 @@ write_amount_info(FILE *af, automount *ap, int sk)
char sublink[1024];
sublink[0] = '\0';
if (exp_namelen < namelen) {
strcat(sublink, mp->m_name + exp_namelen + 1);
xstrlcat(sublink, mp->m_name + exp_namelen + 1, sizeof(sublink));
if (mvolnlen < volnlen)
strcat(sublink, "/");
xstrlcat(sublink, "/", sizeof(sublink));
}
if (mvolnlen < volnlen)
strcat(sublink, ap->a_volname + mvolnlen + 1);
xstrlcat(sublink, ap->a_volname + mvolnlen + 1, sizeof(sublink));
fprintf(af, ";sublink:=%s", sublink);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: wr_bparam.c,v 1.3.2.4 2004/01/06 03:15:23 ezk Exp $
* File: am-utils/fsinfo/wr_bparam.c
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: wr_dumpset.c,v 1.3.2.4 2004/01/06 03:15:23 ezk Exp $
* File: am-utils/fsinfo/wr_dumpset.c
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: wr_exportfs.c,v 1.3.2.4 2004/01/06 03:15:23 ezk Exp $
* File: am-utils/fsinfo/wr_exportfs.c
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: wr_fstab.c,v 1.3.2.5 2004/01/06 03:15:23 ezk Exp $
* File: am-utils/fsinfo/wr_fstab.c
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: nfs_prot_svc.c,v 1.4.2.5 2004/01/06 03:15:23 ezk Exp $
* File: am-utils/hlfsd/nfs_prot_svc.c
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: stubs.c,v 1.5.2.7 2004/01/06 03:15:23 ezk Exp $
* File: am-utils/hlfsd/stubs.c
*
* HLFSD was written at Columbia University Computer Science Department, by
* Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@cs.columbia.edu>
@ -127,8 +126,18 @@ nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
res.ns_status = NFSERR_STALE;
return &res;
}
if (eq_fh(argp, &root)) {
#if 0
/*
* XXX: increment mtime of parent directory, causes NFS clients to
* invalidate their cache for that directory.
* Some NFS clients may need this code.
*/
if (uid != rootfattr.na_uid) {
clocktime(&rootfattr.na_mtime);
rootfattr.na_uid = uid;
}
#endif
res.ns_status = NFS_OK;
res.ns_u.ns_attr_u = rootfattr;
} else if (eq_fh(argp, &slink)) {
@ -144,7 +153,7 @@ nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
* so we must update the nt_seconds field every time.
*/
if (uid != slinkfattr.na_uid) {
slinkfattr.na_mtime.nt_seconds++;
clocktime(&slinkfattr.na_mtime);
slinkfattr.na_uid = uid;
}
#endif /* not MNT2_NFS_OPT_SYMTTL */
@ -161,10 +170,8 @@ nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
res.ns_status = NFS_OK;
un_fattr.na_fileid = uid;
res.ns_u.ns_attr_u = un_fattr;
#ifdef DEBUG
dlog("nfs_getattr: successful search for uid=%ld, gid=%ld",
(long) uid, (long) gid);
#endif /* DEBUG */
} else { /* not found */
res.ns_status = NFSERR_STALE;
}
@ -219,12 +226,22 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
res.dr_status = NFSERR_NOENT;
return &res;
}
if (eq_fh(&argp->da_fhandle, &root)) {
if (argp->da_name[0] == '.' &&
(argp->da_name[1] == '\0' ||
(argp->da_name[1] == '.' &&
argp->da_name[2] == '\0'))) {
#if 0
/*
* XXX: increment mtime of parent directory, causes NFS clients to
* invalidate their cache for that directory.
* Some NFS clients may need this code.
*/
if (uid != rootfattr.na_uid) {
clocktime(&rootfattr.na_mtime);
rootfattr.na_uid = uid;
}
#endif
res.dr_u.dr_drok_u.drok_fhandle = root;
res.dr_u.dr_drok_u.drok_attributes = rootfattr;
res.dr_status = NFS_OK;
@ -243,7 +260,7 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
* so we must update the nt_seconds field every time.
*/
if (uid != slinkfattr.na_uid) {
slinkfattr.na_mtime.nt_seconds++;
clocktime(&slinkfattr.na_mtime);
slinkfattr.na_uid = uid;
}
#endif /* not MNT2_NFS_OPT_SYMTTL */
@ -267,15 +284,13 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
res.dr_u.dr_drok_u.drok_attributes = un_fattr;
memset((char *) &un_fhandle, 0, sizeof(am_nfs_fh));
*(u_int *) un_fhandle.fh_data = (u_int) untab[idx].uid;
strncpy((char *) &un_fhandle.fh_data[sizeof(int)],
untab[idx].username,
sizeof(am_nfs_fh) - sizeof(int));
xstrlcpy((char *) &un_fhandle.fh_data[sizeof(int)],
untab[idx].username,
sizeof(am_nfs_fh) - sizeof(int));
res.dr_u.dr_drok_u.drok_fhandle = un_fhandle;
res.dr_status = NFS_OK;
#ifdef DEBUG
dlog("nfs_lookup: successful lookup for uid=%ld, gid=%ld: username=%s",
(long) uid, (long) gid, untab[idx].username);
#endif /* DEBUG */
return &res;
}
} /* end of "if (eq_fh(argp->dir.data, root.data)) {" */
@ -302,7 +317,7 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
if (getcreds(rqstp, &userid, &groupid, nfsxprt) < 0)
return (nfsreadlinkres *) NULL;
gettimeofday((struct timeval *) &slinkfattr.na_atime, (struct timezone *) 0);
clocktime(&slinkfattr.na_atime);
res.rlr_status = NFS_OK;
if (groupid == hlfs_gid) {
@ -340,7 +355,7 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
last_uid = userid;
}
/* I don't think will pass this if -D nofork */
/* I don't think it will pass this if -D fork */
if (serverpid == getpid())
return &res;
@ -359,15 +374,13 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
else
retval = 0;
#ifdef DEBUG
/*
* If asked for -D nofork, then must return the value,
* If asked for -D fork, then must return the value,
* NOT exit, or else the main hlfsd server exits.
* Bug where is that status information being collected?
* Bug: where is that status information being collected?
*/
amuDebugNo(D_FORK)
if (amuDebug(D_FORK))
return &res;
#endif /* DEBUG */
exit(retval);
}
@ -476,7 +489,7 @@ nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
if (eq_fh(&argp->rda_fhandle, &slink)) {
res.rdr_status = NFSERR_NOTDIR;
} else if (eq_fh(&argp->rda_fhandle, &root)) {
gettimeofday((struct timeval *) &rootfattr.na_atime, (struct timezone *) 0);
clocktime(&rootfattr.na_atime);
res.rdr_status = NFS_OK;
switch (argp->rda_cookie[0]) {

View File

@ -1,5 +1,47 @@
/*
* am_compat.h:
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgment:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* File: am-utils/include/am_compat.h
*
*/
/*
*
* This file contains compatibility functions and macros, all of which
* should be auto-discovered, but for one reason or another (mostly
@ -59,6 +101,10 @@
# define MNTTAB_OPT_PGTHRESH "pgthresh"
#endif /* defined(MNT2_NFS_OPT_PGTHRESH) && !defined(MNTTAB_OPT_PGTHRESH) */
#if defined(MNT2_NFS_OPT_PRIVATE) && !defined(MNTTAB_OPT_PRIVATE)
# define MNTTAB_OPT_PRIVATE "private"
#endif /* defined(MNT2_NFS_OPT_PRIVATE) && !defined(MNTTAB_OPT_PRIVATE) */
#if defined(MNT2_NFS_OPT_RETRANS) && !defined(MNTTAB_OPT_RETRANS)
# define MNTTAB_OPT_RETRANS "retrans"
#endif /* defined(MNT2_NFS_OPT_RETRANS) && !defined(MNTTAB_OPT_RETRANS) */
@ -94,6 +140,10 @@
# define MNTTAB_OPT_NOLOCK "nolock"
#endif /* defined(MNT2_NFS_OPT_NONLM) && !defined(MNTTAB_OPT_NOLOCK) */
#if defined(MNT2_NFS_OPT_XLATECOOKIE) && !defined(MNTTAB_OPT_XLATECOOKIE)
# define MNTTAB_OPT_XLATECOOKIE "xlatecookie"
#endif /* defined(MNT2_NFS_OPT_XLATECOOKIE) && !defined(MNTTAB_OPT_XLATECOOKIE) */
/*
* Complete MNTTAB_OPT_* options based on MNT2_CDFS_OPT_* mount options.
*/
@ -130,6 +180,19 @@
# define MNTTAB_OPT_EXTATT "extatt"
#endif /* defined(MNT2_CDFS_OPT_EXTATT) && !defined(MNTTAB_OPT_EXTATT) */
/*
* Complete MNTTAB_OPT_* options based on MNT2_PCFS_OPT_* mount options.
*/
#if defined(MNT2_PCFS_OPT_LONGNAME) && !defined(MNTTAB_OPT_LONGNAME)
# define MNTTAB_OPT_LONGNAME "longnames"
#endif /* defined(MNT2_PCFS_OPT_LONGNAME) && !defined(MNTTAB_OPT_LONGNAME) */
#if defined(MNT2_PCFS_OPT_NOWIN95) && !defined(MNTTAB_OPT_NOWIN95)
# define MNTTAB_OPT_NOWIN95 "nowin95"
#endif /* defined(MNT2_PCFS_OPT_NOWIN95) && !defined(MNTTAB_OPT_NOWIN95) */
#if defined(MNT2_PCFS_OPT_SHORTNAME) && !defined(MNTTAB_OPT_SHORTNAME)
# define MNTTAB_OPT_SHORTNAME "shortnames"
#endif /* defined(MNT2_PCFS_OPT_SHORTNAME) && !defined(MNTTAB_OPT_SHORTNAME) */
/*
* Complete MNTTAB_OPT_* options based on MNT2_GEN_OPT_* mount options.
*/
@ -189,6 +252,10 @@
# define MNTTAB_OPT_PORT "port"
#endif /* not MNTTAB_OPT_PORT */
#ifndef MNTTAB_OPT_PUBLIC
# define MNTTAB_OPT_PUBLIC "public"
#endif /* not MNTTAB_OPT_PUBLIC */
#ifndef MNTTAB_OPT_RETRANS
# define MNTTAB_OPT_RETRANS "retrans"
#endif /* not MNTTAB_OPT_RETRANS */
@ -217,6 +284,19 @@
# define MNTTAB_OPT_WSIZE "wsize"
#endif /* not MNTTAB_OPT_WSIZE */
/* next four are useful for pcfs mounts */
#ifndef MNTTAB_OPT_USER
# define MNTTAB_OPT_USER "user"
#endif /* not MNTTAB_OPT_USER */
#ifndef MNTTAB_OPT_GROUP
# define MNTTAB_OPT_GROUP "group"
#endif /* not MNTTAB_OPT_GROUP */
#ifndef MNTTAB_OPT_MASK
# define MNTTAB_OPT_MASK "mask"
#endif /* not MNTTAB_OPT_MASK */
#ifndef MNTTAB_OPT_DIRMASK
# define MNTTAB_OPT_DIRMASK "dirmask"
#endif /* not MNTTAB_OPT_DIRMASK */
/*
* Incomplete filesystem definitions (sunos4, irix6, solaris2)
@ -268,6 +348,10 @@ struct hsfs_args {
# define xfs_args_t u_int
#endif /* defined(HAVE_FS_XFS) && !defined(xfs_args_t) */
#if defined(HAVE_FS_AUTOFS) && defined(MOUNT_TYPE_AUTOFS) && !defined(MNTTYPE_AUTOFS)
# define MNTTYPE_AUTOFS "autofs"
#endif /* defined(HAVE_FS_AUTOFS) && defined(MOUNT_TYPE_AUTOFS) && !defined(MNTTYPE_AUTOFS) */
/*
* If NFS3, then make sure that "proto" and "vers" mnttab options
* are available.
@ -281,4 +365,29 @@ struct hsfs_args {
# endif /* not MNTTAB_OPT_PROTO */
#endif /* not HAVE_FS_NFS3 */
/*
* If loop device (header file) exists, define mount table option
*/
#if defined(HAVE_LOOP_DEVICE) && !defined(MNTTAB_OPT_LOOP)
# define MNTTAB_OPT_LOOP "loop"
#endif /* defined(HAVE_LOOP_DEVICE) && !defined(MNTTAB_OPT_LOOP) */
/*
* Define a dummy struct netconfig for non-TLI systems
*/
#if !defined(HAVE_NETCONFIG_H) && !defined(HAVE_SYS_NETCONFIG_H)
struct netconfig {
int dummy;
};
#endif /* not HAVE_NETCONFIG_H and not HAVE_SYS_NETCONFIG_H */
/* some OSs don't define INADDR_NONE and assume it's unsigned -1 */
#ifndef INADDR_NONE
# define INADDR_NONE 0xffffffffU
#endif /* INADDR_NONE */
/* some OSs don't define INADDR_LOOPBACK */
#ifndef INADDR_LOOPBACK
# define INADDR_LOOPBACK 0x7f000001
#endif /* not INADDR_LOOPBACK */
#endif /* not _AM_COMPAT_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: am_utils.h,v 1.11.2.13 2004/01/06 03:15:24 ezk Exp $
* File: am-utils/include/am_utils.h
*
*/
@ -50,6 +49,8 @@
#define _AM_UTILS_H
#include "aux_conf.h"
/**************************************************************************/
/*** MACROS ***/
/**************************************************************************/
@ -111,16 +112,9 @@
#define XLOG_DEFSTR "all,nomap,nostats" /* Default log options */
#define XLOG_ALL (XLOG_FATAL|XLOG_ERROR|XLOG_USER|XLOG_WARNING|XLOG_INFO|XLOG_MAP|XLOG_STATS)
#define clocktime() (clock_valid ? clock_valid : time(&clock_valid))
#ifndef ROOT_MAP
# define ROOT_MAP "\"root\""
#endif /* not ROOT_MAP */
#define NO_SUBNET "notknown" /* default subnet name for no subnet */
#define NEXP_AP (1022) /* gdmr: was 254 */
#define NEXP_AP_MARGIN (128)
#define MAX_READDIR_ENTRIES 16
#define NO_SUBNET "notknown" /* default subnet name for no subnet */
#define NEXP_AP (1022) /* gdmr: was 254 */
#define NEXP_AP_MARGIN (128) /* ???? not used */
/*
* Linked list macros
@ -135,82 +129,30 @@
/* allocate anything of type ty */
#define ALLOC(ty) ((ty *) xmalloc(sizeof(ty)))
#define CALLOC(ty) ((ty *) xcalloc(1, sizeof(ty)))
#define CALLOC(ty) ((ty *) xzalloc(sizeof(ty)))
/* simply allocate b bytes */
#define SALLOC(b) xmalloc((b))
/* converting am-filehandles to mount-points */
#define fh_to_mp2(fhp, rp) fh_to_mp3(fhp, rp, VLOOK_CREATE)
/*
* Systems which have the mount table in a file need to read it before
* they can perform an unmount() system call.
*/
#define UMOUNT_FS(dir, mtb_name) umount_fs(dir, mtb_name)
/* imported via $srcdir/conf/umount/umount_*.c */
extern int umount_fs(char *fs_name, const char *mnttabname);
#define UMOUNT_FS(dir, mtb_name, unmount_flags) umount_fs(dir, mtb_name, unmount_flags)
/* next two are imported via $srcdir/conf/umount/umount_*.c */
extern int umount_fs(char *mntdir, const char *mnttabname, u_int unmount_flags);
#ifdef MNT2_GEN_OPT_FORCE
extern int umount2_fs(const char *mntdir, u_int unmount_flags);
#endif /* MNT2_GEN_OPT_FORCE */
/*
* macros for automounter vfs/vnode operations.
*/
#define VLOOK_CREATE 0x1
#define VLOOK_DELETE 0x2
#define FS_DIRECTORY 0x0001 /* This looks like a dir, not a link */
#define FS_MBACKGROUND 0x0002 /* Should background this mount */
#define FS_NOTIMEOUT 0x0004 /* Don't bother with timeouts */
#define FS_MKMNT 0x0008 /* Need to make the mount point */
#define FS_UBACKGROUND 0x0010 /* Unmount in background */
#define FS_BACKGROUND (FS_MBACKGROUND|FS_UBACKGROUND)
#define FS_DISCARD 0x0020 /* Discard immediately on last reference */
#define FS_AMQINFO 0x0040 /* Amq is interested in this fs type */
/*
* macros for struct fserver.
*/
#define FSF_VALID 0x0001 /* Valid information available */
#define FSF_DOWN 0x0002 /* This fileserver is thought to be down */
#define FSF_ERROR 0x0004 /* Permanent error has occurred */
#define FSF_WANT 0x0008 /* Want a wakeup call */
#define FSF_PINGING 0x0010 /* Already doing pings */
#define FSRV_ISDOWN(fs) (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_DOWN|FSF_VALID))
#define FSRV_ISUP(fs) (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_VALID))
/*
* macros for struct mntfs (list of mounted filesystems)
*/
#define MFF_MOUNTED 0x0001 /* Node is mounted */
#define MFF_MOUNTING 0x0002 /* Mount is in progress */
#define MFF_UNMOUNTING 0x0004 /* Unmount is in progress */
#define MFF_RESTART 0x0008 /* Restarted node */
#define MFF_MKMNT 0x0010 /* Delete this node's am_mount */
#define MFF_ERROR 0x0020 /* This node failed to mount */
#define MFF_LOGDOWN 0x0040 /* Logged that this mount is down */
#define MFF_RSTKEEP 0x0080 /* Don't timeout this filesystem - restarted */
#define MFF_WANTTIMO 0x0100 /* Need a timeout call when not busy */
#ifdef HAVE_AMU_FS_NFSL
# define MFF_NFSLINK 0x0200 /* nfsl type, and deemed a link */
#endif /* HAVE_AMU_FS_NFSL */
/*
* macros for struct am_node (map of auto-mount points).
*/
#define AMF_NOTIMEOUT 0x0001 /* This node never times out */
#define AMF_ROOT 0x0002 /* This is a root node */
#define AMF_AUTOFS 0x0004 /* This node is of type autofs -- not yet supported */
/* unmount-related flags (special handling of autofs, forced/lazy, etc.) */
#define AMU_UMOUNT_FORCE 0x1
#define AMU_UMOUNT_DETACH 0x2
#define AMU_UMOUNT_AUTOFS 0x4
/*
* The following values can be tuned...
*/
#define ALLOWED_MOUNT_TIME 40 /* 40s for a mount */
#define AM_TTL (5 * 60) /* Default cache period */
#define AM_TTL_W (2 * 60) /* Default unmount interval */
#define AM_PINGER 30 /* NFS ping interval for live systems */
#define AMFS_AUTO_TIMEO 8 /* Default amfs_auto timeout - .8s */
/*
* default amfs_auto retrans - 1/10th seconds
*/
#define AMFS_AUTO_RETRANS ((ALLOWED_MOUNT_TIME*10+5*gopt.amfs_auto_timeo)/gopt.amfs_auto_timeo * 2)
/*
* RPC-related macros.
@ -218,6 +160,7 @@ extern int umount_fs(char *fs_name, const char *mnttabname);
#define RPC_XID_PORTMAP 0
#define RPC_XID_MOUNTD 1
#define RPC_XID_NFSPING 2
#define RPC_XID_WEBNFS 3
#define RPC_XID_MASK (0x0f) /* 16 id's for now */
#define MK_RPC_XID(type_id, uniq) ((type_id) | ((uniq) << 4))
@ -228,20 +171,6 @@ extern int umount_fs(char *fs_name, const char *mnttabname);
*/
#define AMD_COMPAT 5000000 /* 5.0 */
/*
* Error to return if remote host is not available.
* Try, in order, "host down", "host unreachable", "invalid argument".
*/
#ifdef EHOSTDOWN
# define AM_ERRNO_HOST_DOWN EHOSTDOWN
# else /* not EHOSTDOWN */
# ifdef EHOSTUNREACH
# define AM_ERRNO_HOST_DOWN EHOSTUNREACH
# else /* not EHOSTUNREACH */
# define AM_ERRNO_HOST_DOWN EINVAL
# endif /* not EHOSTUNREACH */
#endif /* not EHOSTDOWN */
/**************************************************************************/
/*** STRUCTURES AND TYPEDEFS ***/
@ -249,13 +178,8 @@ extern int umount_fs(char *fs_name, const char *mnttabname);
/* some typedefs must come first */
typedef char *amq_string;
typedef struct mntfs mntfs;
typedef struct am_opts am_opts;
typedef struct am_ops am_ops;
typedef struct am_node am_node;
typedef struct _qelem qelem;
typedef struct mntlist mntlist;
typedef struct fserver fserver;
/*
* Linked list
@ -285,120 +209,6 @@ typedef enum {
Done
} serv_state;
/*
* Options
*/
struct am_opts {
char *fs_glob; /* Smashed copy of global options */
char *fs_local; /* Expanded copy of local options */
char *fs_mtab; /* Mount table entry */
/* Other options ... */
char *opt_dev;
char *opt_delay;
char *opt_dir;
char *opt_fs;
char *opt_group;
char *opt_mount;
char *opt_opts;
char *opt_remopts;
char *opt_pref;
char *opt_cache;
char *opt_rfs;
char *opt_rhost;
char *opt_sublink;
char *opt_type;
char *opt_unmount;
char *opt_user;
char *opt_maptype; /* map type: file, nis, hesiod, etc. */
char *opt_cachedir; /* cache directory */
char *opt_addopts; /* options to add to opt_opts */
};
/*
* List of mounted filesystems
*/
struct mntfs {
qelem mf_q; /* List of mounted filesystems */
am_ops *mf_ops; /* Operations on this mountpoint */
am_opts *mf_fo; /* File opts */
char *mf_mount; /* "/a/kiska/home/kiska" */
char *mf_info; /* Mount info */
char *mf_auto; /* Automount opts */
char *mf_mopts; /* FS mount opts */
char *mf_remopts; /* Remote FS mount opts */
fserver *mf_server; /* File server */
int mf_flags; /* Flags MFF_* */
int mf_error; /* Error code from background mount */
int mf_refc; /* Number of references to this node */
int mf_cid; /* Callout id */
void (*mf_prfree) (voidp); /* Free private space */
voidp mf_private; /* Private - per-fs data */
};
/*
* File Handle
*
* This is interpreted by indexing the exported array
* by fhh_id.
*
* The whole structure is mapped onto a standard fhandle_t
* when transmitted.
*/
struct am_fh {
int fhh_pid; /* process id */
int fhh_id; /* map id */
int fhh_gen; /* generation number */
};
/*
* Multi-protocol NFS file handle
*/
union am_nfs_handle {
/* placeholder for V4 file handle */
#ifdef HAVE_FS_NFS3
struct mountres3 v3; /* NFS version 3 handle */
#endif /* HAVE_FS_NFS3 */
struct fhstatus v2; /* NFS version 2 handle */
};
typedef union am_nfs_handle am_nfs_handle_t;
/*
* automounter vfs/vnode operations.
*/
typedef char *(*vfs_match) (am_opts *);
typedef int (*vfs_init) (mntfs *);
typedef int (*vmount_fs) (am_node *);
typedef int (*vfmount_fs) (mntfs *);
typedef int (*vumount_fs) (am_node *);
typedef int (*vfumount_fs) (mntfs *);
typedef am_node *(*vlookuppn) (am_node *, char *, int *, int);
typedef int (*vreaddir) (am_node *, nfscookie, nfsdirlist *, nfsentry *, int);
typedef am_node *(*vreadlink) (am_node *, int *);
typedef void (*vmounted) (mntfs *);
typedef void (*vumounted) (am_node *);
typedef fserver *(*vffserver) (mntfs *);
struct am_ops {
char *fs_type; /* type of filesystems "nfsx" */
vfs_match fs_match; /* fxn: match */
vfs_init fs_init; /* fxn: initialization */
vmount_fs mount_fs; /* fxn: mount vnode */
vfmount_fs fmount_fs; /* fxn: mount VFS */
vumount_fs umount_fs; /* fxn: unmount vnode */
vfumount_fs fumount_fs; /* fxn: unmount VFS */
vlookuppn lookuppn; /* fxn: lookup path-name */
vreaddir readdir; /* fxn: read directory */
vreadlink readlink; /* fxn: read link */
vmounted mounted; /* fxn: after-mount extra actions */
vumounted umounted; /* fxn: after-umount extra actions */
vffserver ffserver; /* fxn: find a file server */
int fs_flags; /* filesystem flags FS_* */
};
typedef int (*task_fun) (voidp);
typedef void (*cb_fun) (int, int, voidp);
typedef void (*fwd_fun) P((voidp, int, struct sockaddr_in *,
struct sockaddr_in *, voidp, int));
/*
* List of mount table entries
@ -413,76 +223,6 @@ struct mntlist {
*/
typedef struct mnt_map mnt_map;
/*
* Per-mountpoint statistics
*/
struct am_stats {
time_t s_mtime; /* Mount time */
u_short s_uid; /* Uid of mounter */
int s_getattr; /* Count of getattrs */
int s_lookup; /* Count of lookups */
int s_readdir; /* Count of readdirs */
int s_readlink; /* Count of readlinks */
int s_statfs; /* Count of statfs */
};
typedef struct am_stats am_stats;
/*
* System statistics
*/
struct amd_stats {
int d_drops; /* Dropped requests */
int d_stale; /* Stale NFS handles */
int d_mok; /* Successful mounts */
int d_merr; /* Failed mounts */
int d_uerr; /* Failed unmounts */
};
extern struct amd_stats amd_stats;
/*
* List of fileservers
*/
struct fserver {
qelem fs_q; /* List of fileservers */
int fs_refc; /* Number of references to this node */
char *fs_host; /* Normalized hostname of server */
struct sockaddr_in *fs_ip; /* Network address of server */
int fs_cid; /* Callout id */
int fs_pinger; /* Ping (keepalive) interval */
int fs_flags; /* Flags */
char *fs_type; /* File server type */
u_long fs_version; /* NFS version of server (2, 3, etc.)*/
char *fs_proto; /* NFS protocol of server (tcp, udp, etc.) */
voidp fs_private; /* Private data */
void (*fs_prfree) (voidp); /* Free private data */
};
/*
* Map of auto-mount points.
*/
struct am_node {
int am_mapno; /* Map number */
mntfs *am_mnt; /* Mounted filesystem */
char *am_name; /* "kiska": name of this node */
char *am_path; /* "/home/kiska": path of this node's mount point */
char *am_link; /* "/a/kiska/home/kiska/this/that": link to sub-dir */
am_node *am_parent; /* Parent of this node */
am_node *am_ysib; /* Younger sibling of this node */
am_node *am_osib; /* Older sibling of this node */
am_node *am_child; /* First child of this node */
nfsattrstat am_attr; /* File attributes */
#define am_fattr am_attr.ns_u.ns_attr_u
int am_flags; /* Boolean flags AMF_* */
int am_error; /* Specific mount error */
time_t am_ttl; /* Time to live */
int am_timeo_w; /* Wait interval */
int am_timeo; /* Timeout interval */
u_int am_gen; /* Generation number */
char *am_pref; /* Mount info prefix */
am_stats am_stats; /* Statistics gathering */
SVCXPRT *am_transp; /* Info for quick reply */
};
/**************************************************************************/
/*** EXTERNALS ***/
@ -496,8 +236,6 @@ extern char *cpu; /* "CPU type" */
extern char *endian; /* "big" */
extern char *hostdomain; /* "southseas.nz" */
extern char copyright[]; /* Copyright info */
extern char hostd[]; /* "kiska.southseas.nz" */
extern char pid_fsname[]; /* kiska.southseas.nz:(pid%d) */
extern char version[]; /* Version info */
/*
@ -506,8 +244,6 @@ extern char version[]; /* Version info */
extern AUTH *nfs_auth; /* Dummy authorization for remote servers */
extern FILE *logfp; /* Log file */
extern SVCXPRT *nfsxprt;
extern am_node **exported_ap; /* List of nodes */
extern am_node *root_node; /* Node for "root" */
extern char *PrimNetName; /* Name of primary connected network */
extern char *PrimNetNum; /* Name of primary connected network */
extern char *SubsNetName; /* Name of subsidiary connected network */
@ -520,20 +256,13 @@ extern const char *am_get_hostname(void);
extern pid_t am_set_mypid(void);
extern pid_t am_mypid;
extern int first_free_map; /* First free node */
extern int foreground; /* Foreground process */
extern int immediate_abort; /* Should close-down unmounts be retried */
extern int last_used_map; /* Last map being used for mounts */
extern int orig_umask; /* umask() on startup */
extern int task_notify_todo; /* Task notifier needs running */
extern int xlog_level; /* Logging level */
extern int xlog_level_init;
extern serv_state amd_state; /* Should we go now */
extern struct in_addr myipaddr; /* (An) IP address of this host */
extern struct opt_tab xlog_opt[];
extern time_t clock_valid; /* Clock needs recalculating */
extern time_t do_mapc_reload; /* Flush & reload mount map cache */
extern time_t next_softclock; /* Time to call softclock() */
extern u_short nfs_port; /* Our NFS service port */
/*
@ -541,134 +270,92 @@ extern u_short nfs_port; /* Our NFS service port */
*/
extern CLIENT *get_mount_client(char *unused_host, struct sockaddr_in *sin, struct timeval *tv, int *sock, u_long mnt_version);
extern RETSIGTYPE sigchld(int);
extern am_node *efs_lookuppn(am_node *, char *, int *, int);
extern am_node *exported_ap_alloc(void);
extern am_node *fh_to_mp(am_nfs_fh *);
extern am_node *fh_to_mp3(am_nfs_fh *, int *, int);
extern am_node *find_mf(mntfs *);
extern am_node *next_map(int *);
extern am_node *root_ap(char *, int);
extern am_ops *ops_match(am_opts *, char *, char *, char *, char *, char *);
extern bool_t xdr_amq_string(XDR *xdrs, amq_string *objp);
extern bool_t xdr_dirpath(XDR *xdrs, dirpath *objp);
extern char **strsplit(char *, int, int);
extern char *expand_key(char *);
extern char *expand_selectors(char *);
extern char *get_version_string(void);
extern char *inet_dquad(char *, u_long);
extern char *inet_dquad(char *, size_t, u_long);
extern char *print_wires(void);
extern char *str3cat(char *, char *, char *, char *);
extern char *strealloc(char *, char *);
extern char *strip_selectors(char *, char *);
extern char *strnsave(const char *, int);
extern fserver *dup_srvr(fserver *);
extern int amu_close(int fd);
extern int background(void);
extern int bind_resv_port(int, u_short *);
extern int cmdoption(char *, struct opt_tab *, int *);
extern int compute_automounter_mount_flags(mntent_t *);
extern int compute_mount_flags(mntent_t *);
extern int efs_readdir(am_node *, nfscookie, nfsdirlist *, nfsentry *, int);
extern int eval_fs_opts(am_opts *, char *, char *, char *, char *, char *);
extern int fwd_init(void);
extern int fwd_packet(int, voidp, int, struct sockaddr_in *, struct sockaddr_in *, voidp, fwd_fun);
extern int get_amd_program_number(void);
extern int getcreds(struct svc_req *, uid_t *, gid_t *, SVCXPRT *);
extern int hasmntval(mntent_t *, char *);
extern unsigned int hasmntvalerr(mntent_t *, char *, int *);
extern char *hasmntstr(mntent_t *, char *);
extern char *hasmnteq(mntent_t *, char *);
extern char *haseq(char *);
extern int is_network_member(const char *net);
extern int is_interface_local(u_long);
extern int islocalnet(u_long);
extern int make_nfs_auth(void);
extern int make_rpc_packet(char *, int, u_long, struct rpc_msg *, voidp, XDRPROC_T_TYPE, AUTH *);
extern int mapc_keyiter(mnt_map *, void(*)(char *, voidp), voidp);
extern int mapc_search(mnt_map *, char *, char **);
extern int mapc_type_exists(const char *type);
extern int mkdirs(char *, int);
extern int mount_auto_node(char *, voidp);
extern int mount_automounter(int);
extern int mount_exported(void);
extern int mount_fs(mntent_t *, int, caddr_t, int, MTYPE_TYPE, u_long, const char *, const char *);
extern int mount_node(am_node *);
extern int nfs_srvr_port(fserver *, u_short *, voidp);
extern int mount_fs(mntent_t *, int, caddr_t, int, MTYPE_TYPE, u_long, const char *, const char *, int);
extern void nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp);
extern int pickup_rpc_reply(voidp, int, voidp, XDRPROC_T_TYPE);
extern int root_keyiter(void(*)(char *, voidp), voidp);
extern int softclock(void);
extern int switch_option(char *);
extern int switch_to_logfile(char *logfile, int orig_umask);
extern int timeout(u_int, void (*fn)(voidp), voidp);
extern int valid_key(char *);
extern mnt_map *mapc_find(char *, char *, const char *);
extern mntfs *dup_mntfs(mntfs *);
extern mntfs *find_mntfs(am_ops *, am_opts *, char *, char *, char *, char *, char *);
extern mntfs *new_mntfs(void);
extern mntfs *realloc_mntfs(mntfs *, am_ops *, am_opts *, char *, char *, char *, char *, char *);
extern int switch_to_logfile(char *logfile, int orig_umask, int truncate_log);
extern mntlist *read_mtab(char *, const char *);
#ifndef HAVE_TRANSPORT_TYPE_TLI
extern struct sockaddr_in *amu_svc_getcaller(SVCXPRT *xprt);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
extern time_t time(time_t *);
extern void am_mounted(am_node *);
extern void am_unmounted(am_node *);
extern void amq_program_1(struct svc_req *rqstp, SVCXPRT *transp);
extern void amu_get_myaddress(struct in_addr *iap);
extern void amu_get_myaddress(struct in_addr *iap, const char *preferred_localhost);
extern void amu_release_controlling_tty(void);
extern void compute_automounter_nfs_args(nfs_args_t *nap, mntent_t *mntp);
extern void deslashify(char *);
extern void discard_mntlist(mntlist *mp);
extern void do_task_notify(void);
extern void flush_mntfs(void);
extern void flush_nfs_fhandle_cache(fserver *);
extern void forcibly_timeout_mp(am_node *);
extern void free_map(am_node *);
extern void free_mntfs(voidp);
extern void free_mntlist(mntlist *);
extern void free_opts(am_opts *);
extern void free_srvr(fserver *);
extern void fwd_reply(void);
extern void get_args(int argc, char *argv[]);
extern void getwire(char **name1, char **number1);
extern void going_down(int);
extern void host_normalize(char **);
extern void init_map(am_node *, char *);
extern void ins_que(qelem *, qelem *);
extern void insert_am(am_node *, am_node *);
extern void make_root_node(void);
extern void map_flush_srvr(fserver *);
extern void mapc_add_kv(mnt_map *, char *, char *);
extern void mapc_free(voidp);
extern void mapc_reload(void);
extern void mapc_showtypes(char *buf);
extern void mk_fattr(am_node *, nfsftype);
extern void mnt_free(mntent_t *);
extern void mp_to_fh(am_node *, am_nfs_fh *);
extern void new_ttl(am_node *);
extern void nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp);
extern void normalize_slash(char *);
extern void ops_showamfstypes(char *buf);
extern void ops_showfstypes(char *outbuf);
extern void plog(int, const char *,...)
__attribute__ ((__format__ (__printf__, 2, 3)));
extern void rem_que(qelem *);
extern void reschedule_timeout_mp(void);
extern void restart(void);
extern void rmdirs(char *);
extern void rpc_msg_init(struct rpc_msg *, u_long, u_long, u_long);
extern void run_task(task_fun, voidp, cb_fun, voidp);
extern void sched_task(cb_fun, voidp, voidp);
extern void set_amd_program_number(int program);
extern void show_opts(int ch, struct opt_tab *);
extern void show_rcs_info(const char *, char *);
extern void srvrlog(fserver *, char *);
extern void timeout_mp(voidp);
extern void umount_exported(void);
extern void unregister_amq(void);
extern void untimeout(int);
extern void wakeup(voidp);
extern void wakeup_srvr(fserver *);
extern void wakeup_task(int, int, voidp);
extern voidp xmalloc(int);
extern voidp xrealloc(voidp, int);
extern voidp xzalloc(int);
extern int check_pmap_up(char *host, struct sockaddr_in* sin);
extern u_long get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto);
extern long get_server_pid(void);
extern void setup_sighandler(int signum, void (*handler)(int));
extern time_t clocktime(nfstime *nt);
#if defined(DEBUG) && (defined(HAVE_C99_VARARGS_MACROS) || defined(HAVE_GCC_VARARGS_MACROS))
# ifdef HAVE_C99_VARARGS_MACROS
#define xsnprintf(str,size,fmt,...) _xsnprintf(__FILE__,__LINE__,(str),(size),(fmt),__VA_ARGS__)
# endif /* HAVE_C99_VARARGS_MACROS */
# ifdef HAVE_GCC_VARARGS_MACROS
#define xsnprintf(str,size,fmt,args...) _xsnprintf(__FILE__,__LINE__,(str),(size),(fmt),args)
# endif /* HAVE_GCC_VARARGS_MACROS */
extern int _xsnprintf(const char *filename, int lineno, char *str, size_t size, const char *format, ...);
#define xvsnprintf(str,size,fmt,ap) _xvsnprintf(__FILE__,__LINE__,(str),(size),(fmt),(ap))
extern int _xvsnprintf(const char *filename, int lineno, char *str, size_t size, const char *format, va_list ap);
#else /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
extern int xsnprintf(char *str, size_t size, const char *format, ...);
extern int xvsnprintf(char *str, size_t size, const char *format, va_list ap);
#endif /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
#ifdef DEBUG
extern void _xstrlcat(const char *filename, int lineno, char *dst, const char *src, size_t len);
# define xstrlcat(d,s,l) _xstrlcat(__FILE__,__LINE__,(d),(s),(l))
extern void _xstrlcpy(const char *filename, int lineno, char *dst, const char *src, size_t len);
# define xstrlcpy(d,s,l) _xstrlcpy(__FILE__,__LINE__,(d),(s),(l))
#else /* not DEBUG */
extern void xstrlcat(char *dst, const char *src, size_t len);
extern void xstrlcpy(char *dst, const char *src, size_t len);
#endif /* not DEBUG */
#ifdef MOUNT_TABLE_ON_FILE
extern void rewrite_mtab(mntlist *, const char *);
@ -680,83 +367,30 @@ extern void write_mntent(mntent_t *, const char *);
extern int syslogging;
#endif /* defined(HAVE_SYSLOG_H) || defined(HAVE_SYS_SYSLOG_H) */
extern void compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct netconfig *nfsncp, struct sockaddr_in *ip_addr, u_long nfs_version, char *nfs_proto, am_nfs_handle_t *fhp, char *host_name, char *fs_name);
extern int create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, struct netconfig **udp_amqncpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp, struct netconfig **tcp_amqncpp, u_short preferred_amq_port);
extern int create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp));
extern int amu_svc_register(SVCXPRT *, u_long, u_long, void (*)(struct svc_req *, SVCXPRT *), u_long, struct netconfig *);
#ifdef HAVE_TRANSPORT_TYPE_TLI
extern void compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct netconfig *nfsncp, struct sockaddr_in *ip_addr, u_long nfs_version, char *nfs_proto, am_nfs_handle_t *fhp, char *host_name, char *fs_name);
extern int create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, struct netconfig **udp_amqncpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp, struct netconfig **tcp_amqncpp);
extern int create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp));
extern int get_knetconfig(struct knetconfig **kncpp, struct netconfig *in_ncp, char *nc_protoname);
extern struct netconfig *nfsncp;
extern void free_knetconfig(struct knetconfig *kncp);
#else /* not HAVE_TRANSPORT_TYPE_TLI */
#endif /* HAVE_TRANSPORT_TYPE_TLI */
extern void compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct sockaddr_in *ip_addr, u_long nfs_version, char *nfs_proto, am_nfs_handle_t *fhp, char *host_name, char *fs_name);
extern enum clnt_stat pmap_ping(struct sockaddr_in *address);
extern int create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp);
extern int create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp));
#ifdef HAVE_FS_AUTOFS
extern int register_autofs_service(char *autofs_conftype, void (*autofs_dispatch)(struct svc_req *rqstp, SVCXPRT *xprt));
extern int unregister_autofs_service(char *autofs_conftype);
#endif /* HAVE_FS_AUTOFS */
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
#ifndef HAVE_STRUCT_FHSTATUS_FHS_FH
# define fhs_fh fhstatus_u.fhs_fhandle
#endif /* not HAVE_STRUCT_FHSTATUS_FHS_FH */
/**************************************************************************/
/*** Generic file-system types, implemented as part of the native O/S. ***/
/**************************************************************************/
/*
* Loopback File System
* Many systems can't support this, and in any case most of the
* functionality is available with Symlink FS.
*/
#ifdef HAVE_FS_LOFS
extern am_ops lofs_ops;
#endif /* HAVE_FS_LOFS */
/*
* CD-ROM File System (CD-ROM)
* (HSFS: High Sierra F/S on some machines)
* Many systems can't support this, and in any case most of the
* functionality is available with program FS.
*/
#ifdef HAVE_FS_CDFS
extern am_ops cdfs_ops;
#endif /* HAVE_FS_CDFS */
/*
* PC File System (MS-DOS)
* Many systems can't support this, and in any case most of the
* functionality is available with program FS.
*/
#ifdef HAVE_FS_PCFS
extern am_ops pcfs_ops;
#endif /* HAVE_FS_PCFS */
/*
* Caching File System (Solaris)
*/
#ifdef HAVE_FS_CACHEFS
extern am_ops cachefs_ops;
#endif /* HAVE_FS_CACHEFS */
/*
* Network File System
* Good, slow, NFS V.2.
*/
#ifdef HAVE_FS_NFS
extern am_ops nfs_ops; /* NFS */
extern fserver *find_nfs_srvr (mntfs *);
extern int nfs_fmount(mntfs *mf);
extern int nfs_fumount(mntfs *mf);
extern int nfs_init(mntfs *mf);
extern qelem nfs_srvr_list;
extern void nfs_umounted(am_node *mp);
#endif /* HAVE_FS_NFS */
/*
* Network File System: the new generation
* NFS V.3
@ -767,124 +401,6 @@ extern void nfs_umounted(am_node *mp);
# endif /* not NFS_VERSION3 */
#endif /* HAVE_FS_NFS3 */
/*
* Un*x File System
* Normal local disk file system.
*/
#ifdef HAVE_FS_UFS
extern am_ops ufs_ops; /* Un*x file system */
#endif /* HAVE_FS_UFS */
/**************************************************************************/
/*** Automounter file-system types, implemented by amd. ***/
/**************************************************************************/
/*
* Automount File System
*/
#ifdef HAVE_AMU_FS_AUTO
extern am_ops amfs_auto_ops; /* Automount file system (this!) */
extern am_ops amfs_toplvl_ops; /* Top-level automount file system */
extern am_ops amfs_root_ops; /* Root file system */
extern qelem amfs_auto_srvr_list;
extern am_node *amfs_auto_lookuppn(am_node *mp, char *fname, int *error_return, int op);
extern am_node *next_nonerror_node(am_node *xp);
extern char *amfs_auto_match(am_opts *fo);
extern fserver *find_amfs_auto_srvr(mntfs *);
extern int amfs_auto_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count);
extern int amfs_auto_umount(am_node *mp);
extern int amfs_auto_fmount(am_node *mp);
extern int amfs_auto_fumount(am_node *mp);
#endif /* HAVE_AMU_FS_AUTO */
/*
* Toplvl Automount File System
*/
#ifdef HAVE_AMU_FS_TOPLVL
extern am_ops amfs_toplvl_ops; /* Toplvl Automount file system */
extern int amfs_toplvl_mount(am_node *mp);
extern int amfs_toplvl_umount(am_node *mp);
extern void amfs_toplvl_mounted(mntfs *mf);
#endif /* HAVE_AMU_FS_TOPLVL */
/*
* Direct Automount File System
*/
#ifdef HAVE_AMU_FS_DIRECT
extern am_ops amfs_direct_ops; /* Direct Automount file system (this too) */
#endif /* HAVE_AMU_FS_DIRECT */
/*
* Error File System
*/
#ifdef HAVE_AMU_FS_ERROR
extern am_ops amfs_error_ops; /* Error file system */
extern am_node *amfs_error_lookuppn(am_node *mp, char *fname, int *error_return, int op);
extern int amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count);
#endif /* HAVE_AMU_FS_ERROR */
/*
* Inheritance File System
*/
#ifdef HAVE_AMU_FS_INHERIT
extern am_ops amfs_inherit_ops; /* Inheritance file system */
#endif /* HAVE_AMU_FS_INHERIT */
/*
* NFS mounts with local existence check.
*/
#ifdef HAVE_AMU_FS_NFSL
extern am_ops amfs_nfsl_ops; /* NFSL */
#endif /* HAVE_AMU_FS_NFSL */
/*
* Multi-nfs mounts.
*/
#ifdef HAVE_AMU_FS_NFSX
extern am_ops amfs_nfsx_ops; /* NFSX */
#endif /* HAVE_AMU_FS_NFSX */
/*
* NFS host - a whole tree.
*/
#ifdef HAVE_AMU_FS_HOST
extern am_ops amfs_host_ops; /* NFS host */
#endif /* HAVE_AMU_FS_HOST */
/*
* Program File System
* This is useful for things like RVD.
*/
#ifdef HAVE_AMU_FS_PROGRAM
extern am_ops amfs_program_ops; /* Program File System */
#endif /* HAVE_AMU_FS_PROGRAM */
/*
* Symbolic-link file system.
* A "filesystem" which is just a symbol link.
*/
#ifdef HAVE_AMU_FS_LINK
extern am_ops amfs_link_ops; /* Symlink FS */
extern int amfs_link_fmount(mntfs *mf);
#endif /* HAVE_AMU_FS_LINK */
/*
* Symbolic-link file system, which also checks that the target of
* the symlink exists.
* A "filesystem" which is just a symbol link.
*/
#ifdef HAVE_AMU_FS_LINKX
extern am_ops amfs_linkx_ops; /* Symlink FS with existence check */
#endif /* HAVE_AMU_FS_LINKX */
/*
* Union file system
*/
#ifdef HAVE_AMU_FS_UNION
extern am_ops amfs_union_ops; /* Union FS */
#endif /* HAVE_AMU_FS_UNION */
/**************************************************************************/
/*** DEBUGGING ***/
@ -893,42 +409,39 @@ extern am_ops amfs_union_ops; /* Union FS */
/*
* DEBUGGING:
*/
#ifdef DEBUG
# define D_ALL (~0)
# define D_DAEMON 0x0001 /* Enter daemon mode */
# define D_ALL (~(D_MTAB|D_HRTIME|D_XDRTRACE|D_DAEMON|D_FORK|D_AMQ))
# define D_DAEMON 0x0001 /* Don't enter daemon mode */
# define D_TRACE 0x0002 /* Do protocol trace */
# define D_FULL 0x0004 /* Do full trace */
# define D_MTAB 0x0008 /* Use local mtab */
# define D_AMQ 0x0010 /* Register amq program */
# define D_AMQ 0x0010 /* Don't register amq program */
# define D_STR 0x0020 /* Debug string munging */
# ifdef DEBUG_MEM
# define D_MEM 0x0040 /* Trace memory allocations */
# endif /* DEBUG_MEM */
# define D_FORK 0x0080 /* Fork server */
# ifdef DEBUG_MEM
# define D_MEM 0x0040 /* Trace memory allocations */
# else /* not DEBUG_MEM */
# define D_MEM 0x0000 /* Dummy */
# endif /* not DEBUG_MEM */
# define D_FORK 0x0080 /* Don't fork server */
/* info service specific debugging (hesiod, nis, etc) */
# define D_INFO 0x0100
# define D_HRTIME 0x0200 /* Print high resolution time stamps */
# define D_XDRTRACE 0x0400 /* Trace xdr routines */
# define D_READDIR 0x0800 /* show browsable_dir progress */
# define D_READDIR 0x0800 /* Show browsable_dir progress */
/*
* Normally, don't enter daemon mode, don't register amq, and don't trace xdr
* Test mode is test mode: don't daemonize, don't register amq, don't fork,
* don't touch system mtab, etc.
*/
# ifdef DEBUG_MEM
# define D_TEST (~(D_DAEMON|D_MEM|D_STR|D_XDRTRACE))
# else /* not DEBUG_MEM */
# define D_TEST (~(D_DAEMON|D_STR|D_XDRTRACE))
# endif /* not DEBUG_MEM */
# define D_TEST (~(D_MEM|D_STR|D_XDRTRACE))
# define amuDebug(x) if (debug_flags & (x))
# define dlog amuDebug(D_FULL) dplog
# define amuDebugNo(x) if (!(debug_flags & (x)))
# define amuDebug(x) (debug_flags & (x))
# define dlog if (amuDebug(D_FULL)) dplog
/* debugging mount-table file to use */
# ifndef DEBUG_MNTTAB
# define DEBUG_MNTTAB "./mnttab"
# endif /* not DEBUG_MNTTAB */
/* my favorite debugging tool -Erez */
#define EZKDBG plog(XLOG_INFO,"EZK:%s:%s:%d\n",__FILE__,__FUNCTION__,__LINE__)
# ifdef DEBUG_MEM
/*
@ -949,18 +462,25 @@ extern void malloc_verify(void);
/* functions that depend solely on debugging */
extern void print_nfs_args(const nfs_args_t *nap, u_long nfs_version);
extern int debug_option (char *opt);
extern void dplog(const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 1, 2)));
#else /* not DEBUG */
/*
* if not debugging, then simple perform free, and don't bother
* resetting the pointer.
* If not debugging, then also reset the pointer.
* It's safer -- and besides, free() should do that anyway.
*/
# define XFREE(x) free(x)
# define XFREE(x) do { free((voidp)x); x = NULL;} while (0)
#define amuDebug(x) if (0)
#define dlog if (0) dplog
#define amuDebugNo(x) if (0)
#define amuDebug(x) (0)
#ifdef __GNUC__
#define dlog(fmt...)
#else /* not __GNUC__ */
/* this define means that we CCP leaves code behind the (list,of,args) */
#define dlog
#endif /* not __GNUC__ */
#define print_nfs_args(nap, nfs_version)
#define debug_option(x) (1)
@ -969,8 +489,6 @@ extern int debug_option (char *opt);
extern int debug_flags; /* Debug options */
extern struct opt_tab dbg_opt[];
extern void dplog(const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 1, 2)));
/**************************************************************************/
/*** MISC (stuff left to autoconfiscate) ***/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,12 +36,147 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: am_xdr_func.h,v 1.3.2.6 2004/01/06 03:15:24 ezk Exp $
* File: am-utils/include/am_xdr_func.h
*
*/
#ifdef HAVE_FS_NFS3
#define AM_FHSIZE3 64 /* size in bytes of a file handle (v3) */
#define AM_MOUNTVERS3 ((unsigned long)(3))
/* NFSv3 handle */
struct am_nfs_fh3 {
u_int am_fh3_length;
char am_fh3_data[AM_FHSIZE3];
};
typedef struct am_nfs_fh3 am_nfs_fh3;
#define AM_NFSPROC3_LOOKUP ((u_long) 3)
enum am_nfsstat3 {
AM_NFS3_OK = 0,
AM_NFS3ERR_PERM = 1,
AM_NFS3ERR_NOENT = 2,
AM_NFS3ERR_IO = 5,
AM_NFS3ERR_NXIO = 6,
AM_NFS3ERR_ACCES = 13,
AM_NFS3ERR_EXIST = 17,
AM_NFS3ERR_XDEV = 18,
AM_NFS3ERR_NODEV = 19,
AM_NFS3ERR_NOTDIR = 20,
AM_NFS3ERR_ISDIR = 21,
AM_NFS3ERR_INVAL = 22,
AM_NFS3ERR_FBIG = 27,
AM_NFS3ERR_NOSPC = 28,
AM_NFS3ERR_ROFS = 30,
AM_NFS3ERR_MLINK = 31,
AM_NFS3ERR_NAMETOOLONG = 63,
AM_NFS3ERR_NOTEMPTY = 66,
AM_NFS3ERR_DQUOT = 69,
AM_NFS3ERR_STALE = 70,
AM_NFS3ERR_REMOTE = 71,
AM_NFS3ERR_BADHANDLE = 10001,
AM_NFS3ERR_NOT_SYNC = 10002,
AM_NFS3ERR_BAD_COOKIE = 10003,
AM_NFS3ERR_NOTSUPP = 10004,
AM_NFS3ERR_TOOSMALL = 10005,
AM_NFS3ERR_SERVERFAULT = 10006,
AM_NFS3ERR_BADTYPE = 10007,
AM_NFS3ERR_JUKEBOX = 10008
};
typedef enum am_nfsstat3 am_nfsstat3;
typedef struct {
u_int fhandle3_len;
char *fhandle3_val;
} am_fhandle3;
enum am_mountstat3 {
AM_MNT3_OK = 0,
AM_MNT3ERR_PERM = 1,
AM_MNT3ERR_NOENT = 2,
AM_MNT3ERR_IO = 5,
AM_MNT3ERR_ACCES = 13,
AM_MNT3ERR_NOTDIR = 20,
AM_MNT3ERR_INVAL = 22,
AM_MNT3ERR_NAMETOOLONG = 63,
AM_MNT3ERR_NOTSUPP = 10004,
AM_MNT3ERR_SERVERFAULT = 10006
};
typedef enum am_mountstat3 am_mountstat3;
struct am_mountres3_ok {
am_fhandle3 fhandle;
struct {
u_int auth_flavors_len;
int *auth_flavors_val;
} auth_flavors;
};
typedef struct am_mountres3_ok am_mountres3_ok;
struct am_mountres3 {
am_mountstat3 fhs_status;
union {
am_mountres3_ok mountinfo;
} mountres3_u;
};
typedef struct am_mountres3 am_mountres3;
typedef char *am_filename3;
struct am_diropargs3 {
am_nfs_fh3 dir;
am_filename3 name;
};
typedef struct am_diropargs3 am_diropargs3;
struct am_LOOKUP3args {
am_diropargs3 what;
};
typedef struct am_LOOKUP3args am_LOOKUP3args;
struct am_LOOKUP3resok {
am_nfs_fh3 object;
#if 0
post_op_attr obj_attributes;
post_op_attr dir_attributes;
#endif
};
typedef struct am_LOOKUP3resok am_LOOKUP3resok;
struct am_LOOKUP3resfail {
#if 0
post_op_attr dir_attributes;
#else
char dummy; /* cannot have an empty declaration */
#endif
};
typedef struct am_LOOKUP3resfail am_LOOKUP3resfail;
struct am_LOOKUP3res {
am_nfsstat3 status;
union {
am_LOOKUP3resok ok;
am_LOOKUP3resfail fail;
} res_u;
};
typedef struct am_LOOKUP3res am_LOOKUP3res;
#endif /* HAVE_FS_NFS3 */
/*
* Multi-protocol NFS file handle
*/
union am_nfs_handle {
/* placeholder for V4 file handle */
#ifdef HAVE_FS_NFS3
am_nfs_fh3 v3; /* NFS version 3 handle */
#endif /* HAVE_FS_NFS3 */
am_nfs_fh v2; /* NFS version 2 handle */
};
typedef union am_nfs_handle am_nfs_handle_t;
/*
* Definitions of all possible xdr functions that are otherwise
* not defined elsewhere.
@ -110,17 +245,6 @@ bool_t xdr_mountbody(XDR *xdrs, mountbody *objp);
#ifndef HAVE_XDR_MOUNTLIST
bool_t xdr_mountlist(XDR *xdrs, mountlist *objp);
#endif /* not HAVE_XDR_MOUNTLIST */
/*
* NFS3 XDR FUNCTIONS:
*/
#if defined(HAVE_FS_NFS3) && !defined(HAVE_XDR_MOUNTRES3)
bool_t xdr_fhandle3(XDR *xdrs, fhandle3 *objp);
bool_t xdr_mountstat3(XDR *xdrs, mountstat3 *objp);
bool_t xdr_mountres3_ok(XDR *xdrs, mountres3_ok *objp);
bool_t xdr_mountres3(XDR *xdrs, mountres3 *objp);
#endif /* defined(HAVE_FS_NFS3) && !defined(HAVE_XDR_MOUNTRES3) */
#ifndef HAVE_XDR_NAME
bool_t xdr_name(XDR *xdrs, name *objp);
#endif /* not HAVE_XDR_NAME */
@ -182,4 +306,22 @@ bool_t xdr_symlinkargs(XDR *xdrs, nfssymlinkargs *objp);
bool_t xdr_writeargs(XDR *xdrs, nfswriteargs *objp);
#endif /* not HAVE_XDR_WRITEARGS */
/*
* NFS3 XDR FUNCTIONS:
*/
#ifdef HAVE_FS_NFS3
bool_t xdr_am_fhandle3(XDR *xdrs, am_fhandle3 *objp);
bool_t xdr_am_mountstat3(XDR *xdrs, am_mountstat3 *objp);
bool_t xdr_am_mountres3_ok(XDR *xdrs, am_mountres3_ok *objp);
bool_t xdr_am_mountres3(XDR *xdrs, am_mountres3 *objp);
bool_t xdr_am_diropargs3(XDR *xdrs, am_diropargs3 *objp);
bool_t xdr_am_filename3(XDR *xdrs, am_filename3 *objp);
bool_t xdr_am_LOOKUP3args(XDR *xdrs, am_LOOKUP3args *objp);
bool_t xdr_am_LOOKUP3res(XDR *xdrs, am_LOOKUP3res *objp);
bool_t xdr_am_LOOKUP3resfail(XDR *xdrs, am_LOOKUP3resfail *objp);
bool_t xdr_am_LOOKUP3resok(XDR *xdrs, am_LOOKUP3resok *objp);
bool_t xdr_am_nfsstat3(XDR *xdrs, am_nfsstat3 *objp);
bool_t xdr_am_nfs_fh3(XDR *xdrs, am_nfs_fh3 *objp);
#endif /* HAVE_FS_NFS3 */
#endif /* not _AM_XDR_FUNC_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@ -36,9 +36,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amq_defs.h,v 1.4.2.4 2004/01/06 03:15:24 ezk Exp $
* File: am-utils/include/amq_defs.h
*
*/
@ -51,7 +50,7 @@
#ifndef AMQ_SIZE
# define AMQ_SIZE 16384
#endif /* not AMQ_SIZE */
#define AMQ_STRLEN 2048
#define AMQ_STRLEN 16384
#define AMQ_PROGRAM ((u_long)300019)
#define AMQ_VERSION ((u_long)1)
#define AMQPROC_NULL ((u_long)0)
@ -64,6 +63,7 @@
#define AMQPROC_MOUNT ((u_long)7)
#define AMQPROC_GETVERS ((u_long)8)
#define AMQPROC_GETPID ((u_long)9)
#define AMQPROC_PAWD ((u_long)10)
/*
* TYPEDEFS

View File

@ -1,3 +1,47 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgment:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* File: am-utils/include/mount_headers1.h
*
*/
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif /* HAVE_SYS_TYPES_H */
@ -131,17 +175,12 @@
#ifdef HAVE_UFS_UFS_MOUNT_H
# include <ufs/ufs_mount.h>
#endif /* HAVE_UFS_UFS_MOUNT_H */
#ifdef HAVE_UFS_UFS_UFSMOUNT_H
# ifndef MAXQUOTAS
# define MAXQUOTAS 2
# endif /* not MAXQUOTAS */
struct netexport { int this_is_SO_wrong; }; /* for bsdi-2.1 */
/* netbsd-1.4 does't protect <ufs/ufs/ufsmount.h> */
# ifndef _UFS_UFS_UFSMOUNT_H
# include <ufs/ufs/ufsmount.h>
# define _UFS_UFS_UFSMOUNT_H
# endif /* not _UFS_UFS_UFSMOUNT_H */
#endif /* HAVE_UFS_UFS_UFSMOUNT_H */
#ifdef HAVE_UFS_UFS_UFSMOUNT_H_off
# error do not include this file here because on *bsd it
# error causes errors with other header files. Instead, add it to the
# error specific conf/nfs_prot_*.h file.
# include <ufs/ufs/ufsmount.h>
#endif /* HAVE_UFS_UFS_UFSMOUNT_H_off */
#ifdef HAVE_CDFS_CDFS_MOUNT_H
# include <cdfs/cdfs_mount.h>
@ -153,6 +192,16 @@ struct netexport { int this_is_SO_wrong; }; /* for bsdi-2.1 */
# include <isofs/cd9660/cd9660_mount.h>
#endif /* HAVE_ISOFS_CD9660_CD9660_MOUNT_H */
#ifdef HAVE_SYS_FS_PC_FS_H
# include <sys/fs/pc_fs.h>
#endif /* HAVE_SYS_FS_PC_FS_H */
#ifdef HAVE_MSDOSFS_MSDOSFSMOUNT_H
# include <msdosfs/msdosfsmount.h>
#endif /* HAVE_MSDOSFS_MSDOSFSMOUNT_H */
#ifdef HAVE_FS_MSDOSFS_MSDOSFSMOUNT_H
# include <fs/msdosfs/msdosfsmount.h>
#endif /* HAVE_FS_MSDOSFS_MSDOSFSMOUNT_H */
#ifdef HAVE_RPC_RPC_H
# include <rpc/rpc.h>
#endif /* HAVE_RPC_RPC_H */

View File

@ -1,3 +1,47 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgment:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* File: am-utils/include/mount_headers2.h
*
*/
#ifdef HAVE_RPCSVC_MOUNT_H
# include <rpcsvc/mount.h>
@ -20,10 +64,24 @@
#endif /* HAVE_SYS_FS_NFS_CLNT_H */
#ifdef HAVE_LINUX_NFS_MOUNT_H
# define _LINUX_NFS_H
# define _LINUX_NFS2_H
# define _LINUX_NFS3_H
# define _LINUX_NFS_FS_H
# define _LINUX_IN_H
# ifndef _LINUX_NFS_H
# define _LINUX_NFS_H
# endif /* not _LINUX_NFS_H */
# ifndef _LINUX_NFS2_H
# define _LINUX_NFS2_H
# endif /* not _LINUX_NFS2_H */
# ifndef _LINUX_NFS3_H
# define _LINUX_NFS3_H
# endif /* not _LINUX_NFS3_H */
# ifndef _LINUX_NFS_FS_H
# define _LINUX_NFS_FS_H
# endif /* not _LINUX_NFS_FS_H */
# ifndef _LINUX_IN_H
# define _LINUX_IN_H
# endif /* not _LINUX_IN_H */
# ifndef __KERNEL__
# define __KERNEL__
# endif /* __KERNEL__ */
# include <linux/nfs_mount.h>
# undef __KERNEL__
#endif /* HAVE_LINUX_NFS_MOUNT_H */

View File

@ -28,31 +28,31 @@ A directory (X.500 and LDAPv3) schema for Berkely automounter
.fi
.in 3
This memo describes a directory (LDAP or X.500) schema for storing
amd (Berkely-style automounter) mount info maps. The schema is currently
beeing supported by the (beta version of the) am-utils version 6 package
[AMUTILS].
amd (Berkely-style automounter) mount info maps. The schema is currently
beeing supported by the (beta version of the) am-utils version 6 package
[AMUTILS].
.ti 0
2. Overview and Rationale
Directory services such as X.500 [X500] or LDAP [RFC2251] are a natural
choice of repository for amd mount map databases. All Object Identifiers
in this document are prefixed by amdSchema-id to be assigned later. The
relation between this schema and the automount schema elements in [HOWARD]
choice of repository for amd mount map databases. All Object Identifiers
in this document are prefixed by amdSchema-id to be assigned later. The
relation between this schema and the automount schema elements in [HOWARD]
are mostly superficial. The model for the elements in [HOWARD] was the SUN
automounter which has quite a different syntax for mount maps. Furthermore
the intended usage of this schema differs from that of [HOWARD] in many
automounter which has quite a different syntax for mount maps. Furthermore
the intended usage of this schema differs from that of [HOWARD] in many
respects.
.ti 0
3. DSA requirements
Directory servers implementing this schema SHOULD maintain the
modifyTimestamp operational attribute. If not the amdMapCacheTtl
Directory servers implementing this schema SHOULD maintain the
modifyTimestamp operational attribute. If not the amdMapCacheTtl
attribute SHOULD be set to 0 indicating to clients that caching of
map entries SHOULD be turned off. Clients wishing to use the amdMap
schema MAY use the modifyTimestamp information to set the ttl for
internal caching schemes. A value of 0 for the amdMapCacheTtl must
map entries SHOULD be turned off. Clients wishing to use the amdMap
schema MAY use the modifyTimestamp information to set the ttl for
internal caching schemes. A value of 0 for the amdMapCacheTtl must
result in clients turning off any local caching.
.ti 0
@ -70,11 +70,11 @@ in BNF using definitions from [RFC2252]:
amdlocationselection = amdlocation |
amdlocationselection whsp amdlocation
amdlocation = amdlocationinfo |
"-" amdlocationinfo |
"-"
amdlocationinfo = seloropt |
amdlocationinfo ";" seloropt |
";"
@ -87,7 +87,7 @@ in BNF using definitions from [RFC2252]:
optass = keystring \":=\" printablestring
X.500 servers or LDAPv3 servers (supporting the binary attribute
X.500 servers or LDAPv3 servers (supporting the binary attribute
option) may use the following syntax definition:
AmdLocationList ::= SEQUENCE OF {
@ -103,21 +103,21 @@ option) may use the following syntax definition:
not [2] NULL
}
}
AmdLocationInfo ::= SET OF {
CHOICE {
selection [0] AmdSelection
option [1] AmdOption
}
}
AmdSelection ::= CHOICE {
eq [0] AttributeAndValue
ne [1] AttributeAndValue
}
AmdOption ::= AttributeAndValue
AttributeAndValue ::= SEQUENCE {
attribute IA5String
value IA5String
@ -127,7 +127,7 @@ option) may use the following syntax definition:
5. Attribute types
The following attribute types are defined in this document:
amdMapName
amdMapCacheTtl
amdMapEntry
@ -136,21 +136,21 @@ The following attribute types are defined in this document:
amdSchema-a OBJECT IDENTIFIER ::= { amdSchema-id 1 }
amdMapName
amdMapName
ATTRIBUTE ::= {
WITH SYNTAX IA5String
EQUALITY MATCHING RULE caseIgoreExactMatch
--ID { amdSchema-a 1 }
DESCRIPTION
DESCRIPTION
"This attribute is the symbolic and in the naming
context unique name of an amd map. This corresponds
in the case of a flat file database to the name of
the file or the mount-point of the map."
}
amdMapCacheTtl
ATTRIBUTE ::= {
amdMapCacheTtl
ATTRIBUTE ::= {
WITH SYNTAX Integer
EQUALITY MATCHING RULE integerExactMatch
--ID { amdSchema-a 2 }
@ -213,7 +213,7 @@ The following attribute types are defined in this document:
using the syntax described above."
}
.ti 0
.ti 0
6. Object classes
The following object classes are defined in this document:
@ -251,13 +251,13 @@ defined as follows:
.ti 0
7. Examples
.ti 0
8. Security Considerations
Due to the security problems posed by NFS care should be taken not to
advertise exported filesystems. Therefore it is often desirable to limit
advertise exported filesystems. Therefore it is often desirable to limit
access to entries carrying amd mount map information to those systems
to which the corresponding filesystems have been exported.
@ -282,13 +282,13 @@ to which the corresponding filesystems have been exported.
Names", RFC 2253, December 1997.
[HOWARD]
Luke Howard, "An Approach for Using LDAP as a Network
Luke Howard, "An Approach for Using LDAP as a Network
Information Service", draft-howard-nis-schema-??.txt, Internet
draft.
[X500]
[X500]
ITU something or other.
.in 3

Some files were not shown because too many files have changed in this diff Show More