mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Virgin import of AMD (am-utils) v6.1.5
Sponsored by: Juniper Networks
This commit is contained in:
parent
a64b8e0693
commit
ad8bcc147f
157 changed files with 23030 additions and 11104 deletions
|
|
@ -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.
|
||||
|
|
|
|||
115
contrib/amd/BUGS
115
contrib/amd/BUGS
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
69
contrib/amd/FAQ
Normal 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>
|
||||
|
|
@ -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
|
||||
|
|
|
|||
708
contrib/amd/NEWS
708
contrib/amd/NEWS
|
|
@ -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.
|
||||
|
|
|
|||
129
contrib/amd/README.attrcache
Normal file
129
contrib/amd/README.attrcache
Normal 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.
|
||||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
.\"
|
||||
.\" %W% (Berkeley) %G%
|
||||
.\"
|
||||
.\" $Id: amd.8,v 1.4.2.5 2004/01/06 03:15:16 ezk Exp $
|
||||
.\" $Id: amd.8,v 1.14.2.1 2006/01/02 18:48:23 ezk Exp $
|
||||
.\"
|
||||
.TH AMD 8 "3 November 1989"
|
||||
.SH NAME
|
||||
|
|
@ -76,6 +76,8 @@ amd \- automatically mount file systems
|
|||
] [
|
||||
.BI \-y " YP-domain"
|
||||
] [
|
||||
.BI \-A " arch"
|
||||
] [
|
||||
.BI \-C " cluster-name"
|
||||
] [
|
||||
.BI \-D " option"
|
||||
|
|
@ -243,6 +245,11 @@ Specify an alternative NIS domain from which to fetch the NIS maps.
|
|||
The default is the system domain name. This option is ignored if NIS
|
||||
support is not available.
|
||||
|
||||
.TP
|
||||
.BI \-A " arch"
|
||||
Specifies the OS architecture. This is used solely to set the ${arch}
|
||||
selector.
|
||||
|
||||
.TP
|
||||
.BI \-C " cluster-name"
|
||||
Specify an alternative HP-UX cluster name to use.
|
||||
|
|
@ -310,14 +317,12 @@ Map entries that are tagged with a tag other than
|
|||
will not be processed.
|
||||
|
||||
.SH FILES
|
||||
.PD 0
|
||||
.TP 5
|
||||
.B /a
|
||||
directory under which filesystems are dynamically mounted
|
||||
.TP 5
|
||||
.B /etc/amd.conf
|
||||
default configuration file
|
||||
.PD
|
||||
.SH CAVEATS
|
||||
Some care may be required when creating a mount map.
|
||||
.LP
|
||||
|
|
@ -345,12 +350,21 @@ the features.
|
|||
.BR mtab (5),
|
||||
.BR syslog (3).
|
||||
.LP
|
||||
``am-utils''
|
||||
.BR info (1)
|
||||
entry.
|
||||
.LP
|
||||
.I "Linux NFS and Automounter Administration"
|
||||
by Erez Zadok, ISBN 0-7821-2739-8, (Sybex, 2001).
|
||||
.LP
|
||||
.I http://www.am-utils.org
|
||||
.LP
|
||||
.I "Amd \- The 4.4 BSD Automounter"
|
||||
.SH AUTHORS
|
||||
Jan-Simon Pendry <jsp@doc.ic.ac.uk>, Department of Computing, Imperial College, London, UK.
|
||||
.P
|
||||
Erez Zadok <ezk@cs.columbia.edu>, Department of Computer Science, Columbia
|
||||
University, New York, USA.
|
||||
Erez Zadok <ezk@cs.sunysb.edu>, Computer Science Department, Stony Brook
|
||||
University, Stony Brook, New York, USA.
|
||||
.P
|
||||
Other authors and contributors to am-utils are listed in the
|
||||
.B AUTHORS
|
||||
|
|
|
|||
|
|
@ -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: amd.c,v 1.8.2.6 2004/01/06 03:15:16 ezk Exp $
|
||||
* File: am-utils/amd/amd.c
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -54,9 +53,10 @@
|
|||
|
||||
struct amu_global_options gopt; /* where global options are stored */
|
||||
|
||||
char pid_fsname[16 + MAXHOSTNAMELEN]; /* "kiska.southseas.nz:(pid%d)" */
|
||||
char pid_fsname[SIZEOF_PID_FSNAME]; /* "kiska.southseas.nz:(pid%d)" */
|
||||
char *hostdomain = "unknown.domain";
|
||||
char hostd[2 * MAXHOSTNAMELEN + 1]; /* Host+domain */
|
||||
#define SIZEOF_HOSTD (2 * MAXHOSTNAMELEN + 1) /* Host+domain */
|
||||
char hostd[SIZEOF_HOSTD]; /* Host+domain */
|
||||
char *endian = ARCH_ENDIAN; /* Big or Little endian */
|
||||
char *cpu = HOST_CPU; /* CPU type */
|
||||
char *PrimNetName; /* name of primary network */
|
||||
|
|
@ -71,6 +71,10 @@ struct amd_stats amd_stats; /* Server statistics */
|
|||
struct in_addr myipaddr; /* (An) IP address of this host */
|
||||
time_t do_mapc_reload = 0; /* mapc_reload() call required? */
|
||||
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
int amd_use_autofs = 0;
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
sigset_t masked_sigs;
|
||||
#endif /* HAVE_SIGACTION */
|
||||
|
|
@ -118,10 +122,8 @@ sighup(int sig)
|
|||
signal(sig, sighup);
|
||||
#endif /* REINSTALL_SIGNAL_HANDLER */
|
||||
|
||||
#ifdef DEBUG
|
||||
if (sig != SIGHUP)
|
||||
dlog("spurious call to sighup");
|
||||
#endif /* DEBUG */
|
||||
/*
|
||||
* Force a reload by zero'ing the timer
|
||||
*/
|
||||
|
|
@ -133,7 +135,26 @@ sighup(int sig)
|
|||
static RETSIGTYPE
|
||||
parent_exit(int sig)
|
||||
{
|
||||
exit(0);
|
||||
/*
|
||||
* This signal handler is called during Amd initialization. The parent
|
||||
* forks a child to do all the hard automounting work, and waits for a
|
||||
* SIGQUIT signal from the child. When the parent gets the signal it's
|
||||
* supposed to call this handler and exit(3), thus completing the
|
||||
* daemonizing process. Alas, on some systems, especially Linux 2.4/2.6
|
||||
* with Glibc, exit(3) doesn't always terminate the parent process.
|
||||
* Worse, the parent process now refuses to accept any more SIGQUIT
|
||||
* signals -- they are blocked. What's really annoying is that this
|
||||
* doesn't happen all the time, suggesting a race condition somewhere.
|
||||
* (This happens even if I change the logic to use another signal.) I
|
||||
* traced this to something which exit(3) does in addition to exiting the
|
||||
* process, probably some atexit() stuff or other side-effects related to
|
||||
* signal handling. Either way, since at this stage the parent process
|
||||
* just needs to terminate, I'm simply calling _exit(2). Note also that
|
||||
* the OpenGroup doesn't list exit(3) as a recommended "Base Interface"
|
||||
* but they do list _exit(2) as one. This fix seems to work reliably all
|
||||
* the time. -Erez (2/27/2005)
|
||||
*/
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -145,6 +166,7 @@ daemon_mode(void)
|
|||
#ifdef HAVE_SIGACTION
|
||||
struct sigaction sa, osa;
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = parent_exit;
|
||||
sa.sa_flags = 0;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
|
|
@ -217,6 +239,7 @@ init_global_options(void)
|
|||
#if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
|
||||
static struct utsname un;
|
||||
#endif /* defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME) */
|
||||
int i;
|
||||
|
||||
memset(&gopt, 0, sizeof(struct amu_global_options));
|
||||
|
||||
|
|
@ -226,9 +249,15 @@ init_global_options(void)
|
|||
/* automounter temp dir */
|
||||
gopt.auto_dir = "/a";
|
||||
|
||||
/* toplevel attribute cache timeout */
|
||||
gopt.auto_attrcache = 0;
|
||||
|
||||
/* cluster name */
|
||||
gopt.cluster = NULL;
|
||||
|
||||
/* executable map timeout */
|
||||
gopt.exec_map_timeout = AMFS_EXEC_MAP_TIMEOUT;
|
||||
|
||||
/*
|
||||
* kernel architecture: this you must get from uname() if possible.
|
||||
*/
|
||||
|
|
@ -260,11 +289,11 @@ init_global_options(void)
|
|||
/* local domain */
|
||||
gopt.sub_domain = NULL;
|
||||
|
||||
/* NFS retransmit counter */
|
||||
gopt.amfs_auto_retrans = -1;
|
||||
|
||||
/* NFS retry interval */
|
||||
gopt.amfs_auto_timeo = -1;
|
||||
/* reset NFS (and toplvl) retransmit counter and retry interval */
|
||||
for (i=0; i<AMU_TYPE_MAX; ++i) {
|
||||
gopt.amfs_auto_retrans[i] = -1; /* -1 means "never set before" */
|
||||
gopt.amfs_auto_timeo[i] = -1; /* -1 means "never set before" */
|
||||
}
|
||||
|
||||
/* cache duration */
|
||||
gopt.am_timeo = AM_TTL;
|
||||
|
|
@ -272,11 +301,13 @@ init_global_options(void)
|
|||
/* dismount interval */
|
||||
gopt.am_timeo_w = AM_TTL_W;
|
||||
|
||||
/* map reload intervl */
|
||||
gopt.map_reload_interval = ONE_HOUR;
|
||||
|
||||
/*
|
||||
* various CFM_* flags.
|
||||
* by default, only the "plock" option is on (if available).
|
||||
* various CFM_* flags that are on by default.
|
||||
*/
|
||||
gopt.flags = CFM_PROCESS_LOCK;
|
||||
gopt.flags = CFM_DEFAULT_FLAGS;
|
||||
|
||||
#ifdef HAVE_MAP_HESIOD
|
||||
/* Hesiod rhs zone */
|
||||
|
|
@ -293,6 +324,9 @@ init_global_options(void)
|
|||
/* LDAP cache */
|
||||
gopt.ldap_cache_seconds = 0;
|
||||
gopt.ldap_cache_maxmem = 131072;
|
||||
|
||||
/* LDAP protocol version */
|
||||
gopt.ldap_proto_version = 2;
|
||||
#endif /* HAVE_MAP_LDAP */
|
||||
|
||||
#ifdef HAVE_MAP_NIS
|
||||
|
|
@ -302,17 +336,58 @@ init_global_options(void)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Lock process text and data segment in memory (after forking the daemon)
|
||||
*/
|
||||
static void
|
||||
do_memory_locking(void)
|
||||
{
|
||||
#if defined(HAVE_PLOCK) || defined(HAVE_MLOCKALL)
|
||||
int locked_ok = 0;
|
||||
#else /* not HAVE_PLOCK and not HAVE_MLOCKALL */
|
||||
plog(XLOG_WARNING, "Process memory locking not supported by the OS");
|
||||
#endif /* not HAVE_PLOCK and not HAVE_MLOCKALL */
|
||||
#ifdef HAVE_PLOCK
|
||||
# ifdef _AIX
|
||||
/*
|
||||
* On AIX you must lower the stack size using ulimit() before calling
|
||||
* plock. Otherwise plock will reserve a lot of memory space based on
|
||||
* your maximum stack size limit. Since it is not easily possible to
|
||||
* tell what should the limit be, I print a warning before calling
|
||||
* plock(). See the manual pages for ulimit(1,3,4) on your AIX system.
|
||||
*/
|
||||
plog(XLOG_WARNING, "AIX: may need to lower stack size using ulimit(3) before calling plock");
|
||||
# endif /* _AIX */
|
||||
if (!locked_ok && plock(PROCLOCK) != 0)
|
||||
plog(XLOG_WARNING, "Couldn't lock process pages in memory using plock(): %m");
|
||||
else
|
||||
locked_ok = 1;
|
||||
#endif /* HAVE_PLOCK */
|
||||
#ifdef HAVE_MLOCKALL
|
||||
if (!locked_ok && mlockall(MCL_CURRENT|MCL_FUTURE) != 0)
|
||||
plog(XLOG_WARNING, "Couldn't lock process pages in memory using mlockall(): %m");
|
||||
else
|
||||
locked_ok = 1;
|
||||
#endif /* HAVE_MLOCKALL */
|
||||
#if defined(HAVE_PLOCK) || defined(HAVE_MLOCKALL)
|
||||
if (locked_ok)
|
||||
plog(XLOG_INFO, "Locked process pages in memory");
|
||||
#endif /* HAVE_PLOCK || HAVE_MLOCKALL */
|
||||
|
||||
#if defined(HAVE_MADVISE) && defined(MADV_PROTECT)
|
||||
madvise(0, 0, MADV_PROTECT); /* may be redundant of the above worked out */
|
||||
#endif /* defined(HAVE_MADVISE) && defined(MADV_PROTECT) */
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char *domdot, *verstr;
|
||||
char *domdot, *verstr, *vertmp;
|
||||
int ppid = 0;
|
||||
int error;
|
||||
char *progname = NULL; /* "amd" */
|
||||
char hostname[MAXHOSTNAMELEN + 1] = "localhost"; /* Hostname */
|
||||
#ifdef HAVE_SIGACTION
|
||||
struct sigaction sa;
|
||||
#endif /* HAVE_SIGACTION */
|
||||
|
||||
/*
|
||||
* Make sure some built-in assumptions are true before we start
|
||||
|
|
@ -363,11 +438,6 @@ main(int argc, char *argv[])
|
|||
going_down(1);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* initialize debugging flags (Register AMQ, Enter daemon mode) */
|
||||
debug_flags = D_AMQ | D_DAEMON;
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* Initialize global options structure.
|
||||
*/
|
||||
|
|
@ -386,73 +456,31 @@ main(int argc, char *argv[])
|
|||
*domdot++ = '\0';
|
||||
hostdomain = domdot;
|
||||
}
|
||||
strcpy(hostd, hostname);
|
||||
xstrlcpy(hostd, hostname, sizeof(hostd));
|
||||
am_set_hostname(hostname);
|
||||
|
||||
/*
|
||||
* Trap interrupts for shutdowns.
|
||||
* Setup signal handlers
|
||||
*/
|
||||
#ifdef HAVE_SIGACTION
|
||||
sa.sa_handler = sigterm;
|
||||
sa.sa_flags = 0;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
sigaddset(&(sa.sa_mask), SIGINT);
|
||||
sigaddset(&(sa.sa_mask), SIGTERM);
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
#else /* not HAVE_SIGACTION */
|
||||
(void) signal(SIGINT, sigterm);
|
||||
#endif /* not HAVE_SIGACTION */
|
||||
|
||||
/* SIGINT: trap interrupts for shutdowns */
|
||||
setup_sighandler(SIGINT, sigterm);
|
||||
/* SIGTERM: trap terminate so we can shutdown cleanly (some chance) */
|
||||
setup_sighandler(SIGTERM, sigterm);
|
||||
/* SIGHUP: hangups tell us to reload the cache */
|
||||
setup_sighandler(SIGHUP, sighup);
|
||||
/*
|
||||
* Trap Terminate so that we can shutdown gracefully (some chance)
|
||||
* SIGCHLD: trap Death-of-a-child. These allow us to pick up the exit
|
||||
* status of backgrounded mounts. See "sched.c".
|
||||
*/
|
||||
setup_sighandler(SIGCHLD, sigchld);
|
||||
#ifdef HAVE_SIGACTION
|
||||
sa.sa_handler = sigterm;
|
||||
sa.sa_flags = 0;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
sigaddset(&(sa.sa_mask), SIGTERM);
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
#else /* not HAVE_SIGACTION */
|
||||
(void) signal(SIGTERM, sigterm);
|
||||
#endif /* not HAVE_SIGACTION */
|
||||
|
||||
/*
|
||||
* Hangups tell us to reload the cache
|
||||
*/
|
||||
#ifdef HAVE_SIGACTION
|
||||
sa.sa_handler = sighup;
|
||||
sa.sa_flags = 0;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
sigaddset(&(sa.sa_mask), SIGHUP);
|
||||
sigaction(SIGHUP, &sa, NULL);
|
||||
#else /* not HAVE_SIGACTION */
|
||||
(void) signal(SIGHUP, sighup);
|
||||
#endif /* not HAVE_SIGACTION */
|
||||
|
||||
/*
|
||||
* Trap Death-of-a-child. These allow us to
|
||||
* pick up the exit status of backgrounded mounts.
|
||||
* See "sched.c".
|
||||
*/
|
||||
#ifdef HAVE_SIGACTION
|
||||
sa.sa_handler = sigchld;
|
||||
sa.sa_flags = 0;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
sigaddset(&(sa.sa_mask), SIGCHLD);
|
||||
sigaction(SIGCHLD, &sa, NULL);
|
||||
|
||||
/*
|
||||
* construct global "masked_sigs" used in nfs_start.c
|
||||
*/
|
||||
/* construct global "masked_sigs" used in nfs_start.c */
|
||||
sigemptyset(&masked_sigs);
|
||||
sigaddset(&masked_sigs, SIGINT);
|
||||
sigaddset(&masked_sigs, SIGTERM);
|
||||
sigaddset(&masked_sigs, SIGHUP);
|
||||
sigaddset(&masked_sigs, SIGCHLD);
|
||||
sigaddset(&masked_sigs, SIGTERM);
|
||||
sigaddset(&masked_sigs, SIGINT);
|
||||
#else /* not HAVE_SIGACTION */
|
||||
(void) signal(SIGCHLD, sigchld);
|
||||
#endif /* not HAVE_SIGACTION */
|
||||
#endif /* HAVE_SIGACTION */
|
||||
|
||||
/*
|
||||
* Fix-up any umask problems. Most systems default
|
||||
|
|
@ -473,18 +501,21 @@ main(int argc, char *argv[])
|
|||
/*
|
||||
* Log version information.
|
||||
*/
|
||||
verstr = strtok(get_version_string(), "\n");
|
||||
vertmp = get_version_string();
|
||||
verstr = strtok(vertmp, "\n");
|
||||
plog(XLOG_INFO, "AM-UTILS VERSION INFORMATION:");
|
||||
while (verstr) {
|
||||
plog(XLOG_INFO, "%s", verstr);
|
||||
verstr = strtok(NULL, "\n");
|
||||
}
|
||||
XFREE(vertmp);
|
||||
|
||||
/*
|
||||
* Get our own IP address so that we
|
||||
* can mount the automounter.
|
||||
* Get our own IP address so that we can mount the automounter. We pass
|
||||
* localhost_address which could be used as the default localhost
|
||||
* name/address in amu_get_myaddress().
|
||||
*/
|
||||
amu_get_myaddress(&myipaddr);
|
||||
amu_get_myaddress(&myipaddr, gopt.localhost_address);
|
||||
plog(XLOG_INFO, "My ip addr is %s", inet_ntoa(myipaddr));
|
||||
|
||||
/* avoid hanging on other NFS servers if started elsewhere */
|
||||
|
|
@ -499,29 +530,6 @@ main(int argc, char *argv[])
|
|||
going_down(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock process text and data segment in memory.
|
||||
*/
|
||||
#ifdef HAVE_PLOCK
|
||||
if (gopt.flags & CFM_PROCESS_LOCK) {
|
||||
# ifdef _AIX
|
||||
/*
|
||||
* On AIX you must lower the stack size using ulimit() before calling
|
||||
* plock. Otherwise plock will reserve a lot of memory space based on
|
||||
* your maximum stack size limit. Since it is not easily possible to
|
||||
* tell what should the limit be, I print a warning before calling
|
||||
* plock(). See the manual pages for ulimit(1,3,4) on your AIX system.
|
||||
*/
|
||||
plog(XLOG_WARNING, "AIX: may need to lower stack size using ulimit(3) before calling plock");
|
||||
# endif /* _AIX */
|
||||
if (plock(PROCLOCK) != 0) {
|
||||
plog(XLOG_WARNING, "Couldn't lock process text and data segment in memory: %m");
|
||||
} else {
|
||||
plog(XLOG_INFO, "Locked process text and data segment in memory");
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_PLOCK */
|
||||
|
||||
#ifdef HAVE_MAP_NIS
|
||||
/*
|
||||
* If the domain was specified then bind it here
|
||||
|
|
@ -534,14 +542,17 @@ main(int argc, char *argv[])
|
|||
}
|
||||
#endif /* HAVE_MAP_NIS */
|
||||
|
||||
#ifdef DEBUG
|
||||
amuDebug(D_DAEMON)
|
||||
#endif /* DEBUG */
|
||||
if (!amuDebug(D_DAEMON))
|
||||
ppid = daemon_mode();
|
||||
|
||||
sprintf(pid_fsname, "%s:(pid%ld)", am_get_hostname(), (long) am_mypid);
|
||||
/*
|
||||
* Lock process text and data segment in memory.
|
||||
*/
|
||||
if (gopt.flags & CFM_PROCESS_LOCK) {
|
||||
do_memory_locking();
|
||||
}
|
||||
|
||||
do_mapc_reload = clocktime() + ONE_HOUR;
|
||||
do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval;
|
||||
|
||||
/*
|
||||
* Register automounter with system.
|
||||
|
|
@ -549,6 +560,16 @@ main(int argc, char *argv[])
|
|||
error = mount_automounter(ppid);
|
||||
if (error && ppid)
|
||||
kill(ppid, SIGALRM);
|
||||
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
/*
|
||||
* XXX this should be part of going_down(), but I can't move it there
|
||||
* because it would be calling non-library code from the library... ugh
|
||||
*/
|
||||
if (amd_use_autofs)
|
||||
destroy_autofs_service();
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
going_down(error);
|
||||
|
||||
abort();
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
|||
1262
contrib/amd/amd/amfs_generic.c
Normal file
1262
contrib/amd/amd/amfs_generic.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 @@ again:
|
|||
* 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_subr.c,v 1.6.2.6 2004/01/19 00:25:55 ezk Exp $
|
||||
* File: am-utils/amd/amq_subr.c
|
||||
*
|
||||
*/
|
||||
/*
|
||||
|
|
@ -111,8 +110,10 @@ amq_mount_tree_list *
|
|||
amqproc_export_1_svc(voidp argp, struct svc_req *rqstp)
|
||||
{
|
||||
static amq_mount_tree_list aml;
|
||||
static am_node *mp;
|
||||
|
||||
aml.amq_mount_tree_list_val = (amq_mount_tree_p *) &exported_ap[0];
|
||||
mp = get_exported_ap(0);
|
||||
aml.amq_mount_tree_list_val = (amq_mount_tree_p *) ((void *) &mp);
|
||||
aml.amq_mount_tree_list_len = 1; /* XXX */
|
||||
|
||||
return &aml;
|
||||
|
|
@ -130,16 +131,14 @@ amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp)
|
|||
switch (opt->as_opt) {
|
||||
|
||||
case AMOPT_DEBUG:
|
||||
#ifdef DEBUG
|
||||
if (debug_option(opt->as_str))
|
||||
#endif /* DEBUG */
|
||||
rc = EINVAL;
|
||||
break;
|
||||
|
||||
case AMOPT_LOGFILE:
|
||||
if (gopt.logfile && opt->as_str
|
||||
&& STREQ(gopt.logfile, opt->as_str)) {
|
||||
if (switch_to_logfile(opt->as_str, orig_umask))
|
||||
if (switch_to_logfile(opt->as_str, orig_umask, 0))
|
||||
rc = EINVAL;
|
||||
} else {
|
||||
rc = EACCES;
|
||||
|
|
@ -155,8 +154,8 @@ amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp)
|
|||
if (amd_state == Run) {
|
||||
plog(XLOG_INFO, "amq says flush cache");
|
||||
do_mapc_reload = 0;
|
||||
flush_nfs_fhandle_cache((fserver *) 0);
|
||||
flush_srvr_nfs_cache();
|
||||
flush_nfs_fhandle_cache((fserver *) NULL);
|
||||
flush_srvr_nfs_cache((fserver *) NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -168,7 +167,7 @@ amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp)
|
|||
amq_mount_info_list *
|
||||
amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp)
|
||||
{
|
||||
return (amq_mount_info_list *) ((void *)&mfhead); /* XXX */
|
||||
return (amq_mount_info_list *) ((void *)&mfhead); /* XXX */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -193,6 +192,64 @@ amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process PAWD string of remote pawd tool.
|
||||
*
|
||||
* We repeat the resolution of the string until the resolved string resolves
|
||||
* to itself. This ensures that we follow path resolutions through all
|
||||
* possible Amd mount points until we reach some sort of convergence. To
|
||||
* prevent possible infinite loops, we break out of this loop if the strings
|
||||
* do not converge after MAX_PAWD_TRIES times.
|
||||
*/
|
||||
amq_string *
|
||||
amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp)
|
||||
{
|
||||
static amq_string res;
|
||||
#define MAX_PAWD_TRIES 10
|
||||
int index, len, maxagain = MAX_PAWD_TRIES;
|
||||
am_node *mp;
|
||||
char *mountpoint;
|
||||
char *dir = *(char **) argp;
|
||||
static char tmp_buf[MAXPATHLEN];
|
||||
char prev_buf[MAXPATHLEN];
|
||||
|
||||
tmp_buf[0] = prev_buf[0] = '\0'; /* default is empty string: no match */
|
||||
do {
|
||||
for (mp = get_first_exported_ap(&index);
|
||||
mp;
|
||||
mp = get_next_exported_ap(&index)) {
|
||||
if (STREQ(mp->am_mnt->mf_ops->fs_type, "toplvl"))
|
||||
continue;
|
||||
if (STREQ(mp->am_mnt->mf_ops->fs_type, "auto"))
|
||||
continue;
|
||||
mountpoint = (mp->am_link ? mp->am_link : mp->am_mnt->mf_mount);
|
||||
len = strlen(mountpoint);
|
||||
if (len == 0)
|
||||
continue;
|
||||
if (!NSTREQ(mountpoint, dir, len))
|
||||
continue;
|
||||
if (dir[len] != '\0' && dir[len] != '/')
|
||||
continue;
|
||||
xstrlcpy(tmp_buf, mp->am_path, sizeof(tmp_buf));
|
||||
xstrlcat(tmp_buf, &dir[len], sizeof(tmp_buf));
|
||||
break;
|
||||
} /* end of "for" loop */
|
||||
/* once tmp_buf and prev_buf are equal, break out of "do" loop */
|
||||
if (STREQ(tmp_buf, prev_buf))
|
||||
break;
|
||||
else
|
||||
xstrlcpy(prev_buf, tmp_buf, sizeof(prev_buf));
|
||||
} while (--maxagain);
|
||||
/* check if we couldn't resolve the string after MAX_PAWD_TRIES times */
|
||||
if (maxagain <= 0)
|
||||
plog(XLOG_WARNING, "path \"%s\" did not resolve after %d tries",
|
||||
tmp_buf, MAX_PAWD_TRIES);
|
||||
|
||||
res = tmp_buf;
|
||||
return &res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* XDR routines.
|
||||
*/
|
||||
|
|
@ -201,7 +258,7 @@ amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp)
|
|||
bool_t
|
||||
xdr_amq_setopt(XDR *xdrs, amq_setopt *objp)
|
||||
{
|
||||
if (!xdr_enum(xdrs, (enum_t *) & objp->as_opt)) {
|
||||
if (!xdr_enum(xdrs, (enum_t *) ((voidp) &objp->as_opt))) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_string(xdrs, &objp->as_str, AMQ_STRLEN)) {
|
||||
|
|
@ -266,10 +323,16 @@ xdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp)
|
|||
if (!xdr_amq_mount_tree_node(xdrs, objp)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_pointer(xdrs, (char **) &mp->am_osib, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
|
||||
if (!xdr_pointer(xdrs,
|
||||
(char **) ((voidp) &mp->am_osib),
|
||||
sizeof(amq_mount_tree),
|
||||
(XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_pointer(xdrs, (char **) &mp->am_child, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
|
||||
if (!xdr_pointer(xdrs,
|
||||
(char **) ((voidp) &mp->am_child),
|
||||
sizeof(amq_mount_tree),
|
||||
(XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
|
|
@ -280,15 +343,21 @@ bool_t
|
|||
xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp)
|
||||
{
|
||||
am_node *mp = (am_node *) objp;
|
||||
am_node *mnil = 0;
|
||||
am_node *mnil = NULL;
|
||||
|
||||
if (!xdr_amq_mount_tree_node(xdrs, objp)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_pointer(xdrs, (char **) ((void *)&mnil), sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
|
||||
if (!xdr_pointer(xdrs,
|
||||
(char **) ((voidp) &mnil),
|
||||
sizeof(amq_mount_tree),
|
||||
(XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_pointer(xdrs, (char **) &mp->am_child, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
|
||||
if (!xdr_pointer(xdrs,
|
||||
(char **) ((voidp) &mp->am_child),
|
||||
sizeof(amq_mount_tree),
|
||||
(XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
|
|
@ -332,7 +401,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),
|
||||
|
|
@ -354,7 +423,7 @@ xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead)
|
|||
u_int len = 0;
|
||||
|
||||
for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) {
|
||||
if (!(mf->mf_ops->fs_flags & FS_AMQINFO))
|
||||
if (!(mf->mf_fsflags & FS_AMQINFO))
|
||||
continue;
|
||||
len++;
|
||||
}
|
||||
|
|
@ -365,7 +434,7 @@ xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead)
|
|||
*/
|
||||
for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) {
|
||||
int up;
|
||||
if (!(mf->mf_ops->fs_flags & FS_AMQINFO))
|
||||
if (!(mf->mf_fsflags & FS_AMQINFO))
|
||||
continue;
|
||||
|
||||
if (!xdr_amq_string(xdrs, &mf->mf_ops->fs_type)) {
|
||||
|
|
@ -386,20 +455,12 @@ xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead)
|
|||
if (!xdr_int(xdrs, &mf->mf_refc)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (mf->mf_server->fs_flags & FSF_ERROR)
|
||||
if (FSRV_ERROR(mf->mf_server) || FSRV_ISDOWN(mf->mf_server))
|
||||
up = 0;
|
||||
else if (FSRV_ISUP(mf->mf_server))
|
||||
up = 1;
|
||||
else
|
||||
switch (mf->mf_server->fs_flags & (FSF_DOWN | FSF_VALID)) {
|
||||
case FSF_DOWN | FSF_VALID:
|
||||
up = 0;
|
||||
break;
|
||||
case FSF_VALID:
|
||||
up = 1;
|
||||
break;
|
||||
default:
|
||||
up = -1;
|
||||
break;
|
||||
}
|
||||
up = -1;
|
||||
if (!xdr_int(xdrs, &up)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 @@ top:
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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: get_args.c,v 1.7.2.6 2004/01/06 03:15:16 ezk Exp $
|
||||
* File: am-utils/amd/get_args.c
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -55,17 +54,12 @@
|
|||
/* include auto-generated version file */
|
||||
#include <build_version.h>
|
||||
|
||||
char *conf_file = "/etc/amd.conf"; /* default amd configuration file */
|
||||
char *amu_conf_file = "/etc/amd.conf"; /* default amd configuration file */
|
||||
char *conf_tag = NULL; /* default conf file tags to use */
|
||||
int usage = 0;
|
||||
int use_conf_file = 0; /* default don't use amd.conf file */
|
||||
char *mnttab_file_name = NULL; /* symbol must be available always */
|
||||
#if 0
|
||||
#ifdef DEBUG
|
||||
int debug_flags = D_AMQ /* Register AMQ */
|
||||
| D_DAEMON; /* Enter daemon mode */
|
||||
#endif /* DEBUG */
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Return the version string (dynamic buffer)
|
||||
|
|
@ -73,48 +67,61 @@ int debug_flags = D_AMQ /* Register AMQ */
|
|||
char *
|
||||
get_version_string(void)
|
||||
{
|
||||
static char *vers = NULL;
|
||||
char *vers = NULL;
|
||||
char tmpbuf[1024];
|
||||
char *wire_buf;
|
||||
int wire_buf_len = 0;
|
||||
size_t len; /* max allocated length (to avoid buf overflow) */
|
||||
|
||||
/* first get dynamic string listing all known networks */
|
||||
/*
|
||||
* First get dynamic string listing all known networks.
|
||||
* This could be a long list, if host has lots of interfaces.
|
||||
*/
|
||||
wire_buf = print_wires();
|
||||
if (wire_buf)
|
||||
wire_buf_len = strlen(wire_buf);
|
||||
|
||||
vers = xmalloc(2048 + wire_buf_len);
|
||||
sprintf(vers, "%s\n%s\n%s\n%s\n",
|
||||
"Copyright (c) 1997-2004 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.");
|
||||
sprintf(tmpbuf, "%s version %s (build %d).\n",
|
||||
PACKAGE, VERSION, AMU_BUILD_VERSION);
|
||||
strcat(vers, tmpbuf);
|
||||
sprintf(tmpbuf, "Built by %s@%s on date %s.\n",
|
||||
USER_NAME, HOST_NAME, CONFIG_DATE);
|
||||
strcat(vers, tmpbuf);
|
||||
sprintf(tmpbuf, "cpu=%s (%s-endian), arch=%s, karch=%s.\n",
|
||||
cpu, endian, gopt.arch, gopt.karch);
|
||||
strcat(vers, tmpbuf);
|
||||
sprintf(tmpbuf, "full_os=%s, os=%s, osver=%s, vendor=%s.\n",
|
||||
gopt.op_sys_full, gopt.op_sys, gopt.op_sys_ver, gopt.op_sys_vendor);
|
||||
strcat(vers, tmpbuf);
|
||||
len = 2048 + wire_buf_len;
|
||||
vers = xmalloc(len);
|
||||
xsnprintf(vers, len, "%s\n%s\n%s\n%s\n",
|
||||
"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.");
|
||||
xsnprintf(tmpbuf, sizeof(tmpbuf), "%s version %s (build %d).\n",
|
||||
PACKAGE_NAME, PACKAGE_VERSION, AMU_BUILD_VERSION);
|
||||
strlcat(vers, tmpbuf, len);
|
||||
xsnprintf(tmpbuf, sizeof(tmpbuf), "Report bugs to %s.\n", PACKAGE_BUGREPORT);
|
||||
strlcat(vers, tmpbuf, len);
|
||||
xsnprintf(tmpbuf, sizeof(tmpbuf), "Configured by %s@%s on date %s.\n",
|
||||
USER_NAME, HOST_NAME, CONFIG_DATE);
|
||||
strlcat(vers, tmpbuf, len);
|
||||
xsnprintf(tmpbuf, sizeof(tmpbuf), "Built by %s@%s on date %s.\n",
|
||||
BUILD_USER, BUILD_HOST, BUILD_DATE);
|
||||
strlcat(vers, tmpbuf, len);
|
||||
xsnprintf(tmpbuf, sizeof(tmpbuf), "cpu=%s (%s-endian), arch=%s, karch=%s.\n",
|
||||
cpu, endian, gopt.arch, gopt.karch);
|
||||
strlcat(vers, tmpbuf, len);
|
||||
xsnprintf(tmpbuf, sizeof(tmpbuf), "full_os=%s, os=%s, osver=%s, vendor=%s, distro=%s.\n",
|
||||
gopt.op_sys_full, gopt.op_sys, gopt.op_sys_ver, gopt.op_sys_vendor, DISTRO_NAME);
|
||||
strlcat(vers, tmpbuf, len);
|
||||
xsnprintf(tmpbuf, sizeof(tmpbuf), "domain=%s, host=%s, hostd=%s.\n",
|
||||
hostdomain, am_get_hostname(), hostd);
|
||||
strlcat(vers, tmpbuf, len);
|
||||
|
||||
strcat(vers, "Map support for: ");
|
||||
mapc_showtypes(tmpbuf);
|
||||
strcat(vers, tmpbuf);
|
||||
strcat(vers, ".\nAMFS: ");
|
||||
ops_showamfstypes(tmpbuf);
|
||||
strcat(vers, tmpbuf);
|
||||
strcat(vers, ".\nFS: ");
|
||||
ops_showfstypes(tmpbuf);
|
||||
strcat(vers, tmpbuf);
|
||||
strlcat(vers, "Map support for: ", len);
|
||||
mapc_showtypes(tmpbuf, sizeof(tmpbuf));
|
||||
strlcat(vers, tmpbuf, len);
|
||||
strlcat(vers, ".\nAMFS: ", len);
|
||||
ops_showamfstypes(tmpbuf, sizeof(tmpbuf));
|
||||
strlcat(vers, tmpbuf, len);
|
||||
strlcat(vers, ", inherit.\nFS: ", len); /* hack: "show" that we support type:=inherit */
|
||||
ops_showfstypes(tmpbuf, sizeof(tmpbuf));
|
||||
strlcat(vers, tmpbuf, len);
|
||||
|
||||
/* append list of networks if available */
|
||||
if (wire_buf) {
|
||||
strcat(vers, wire_buf);
|
||||
strlcat(vers, wire_buf, len);
|
||||
XFREE(wire_buf);
|
||||
}
|
||||
|
||||
|
|
@ -122,13 +129,48 @@ get_version_string(void)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
show_usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-nprvHS] [-a mount_point] [-c cache_time] [-d domain]\n\
|
||||
\t[-k kernel_arch] [-l logfile%s\n\
|
||||
\t[-t timeout.retrans] [-w wait_timeout] [-A arch] [-C cluster_name]\n\
|
||||
\t[-o op_sys_ver] [-O op_sys_name]\n\
|
||||
\t[-F conf_file] [-T conf_tag]", am_get_progname(),
|
||||
#ifdef HAVE_SYSLOG
|
||||
# ifdef LOG_DAEMON
|
||||
"|\"syslog[:facility]\"]"
|
||||
# else /* not LOG_DAEMON */
|
||||
"|\"syslog\"]"
|
||||
# endif /* not LOG_DAEMON */
|
||||
#else /* not HAVE_SYSLOG */
|
||||
"]"
|
||||
#endif /* not HAVE_SYSLOG */
|
||||
);
|
||||
|
||||
#ifdef HAVE_MAP_NIS
|
||||
fputs(" [-y nis-domain]\n", stderr);
|
||||
#else /* not HAVE_MAP_NIS */
|
||||
fputc('\n', stderr);
|
||||
#endif /* HAVE_MAP_NIS */
|
||||
|
||||
show_opts('x', xlog_opt);
|
||||
#ifdef DEBUG
|
||||
show_opts('D', dbg_opt);
|
||||
#endif /* DEBUG */
|
||||
fprintf(stderr, "\t[directory mapname [-map_options]] ...\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
get_args(int argc, char *argv[])
|
||||
{
|
||||
int opt_ch;
|
||||
int opt_ch, i;
|
||||
FILE *fp = stdin;
|
||||
char getopt_arguments[] = "+nprvSa:c:d:k:l:o:t:w:x:y:C:D:F:T:O:H";
|
||||
char getopt_arguments[] = "+nprvSa:c:d:k:l:o:t:w:x:y:C:D:F:T:O:HA:";
|
||||
char *getopt_args;
|
||||
int print_version = 0; /* 1 means we should print version info */
|
||||
|
||||
#ifdef HAVE_GNU_GETOPT
|
||||
getopt_args = getopt_arguments;
|
||||
|
|
@ -187,24 +229,30 @@ get_args(int argc, char *argv[])
|
|||
break;
|
||||
|
||||
case 't':
|
||||
/* timeo.retrans */
|
||||
/* timeo.retrans (also affects toplvl mounts) */
|
||||
{
|
||||
char *dot = strchr(optarg, '.');
|
||||
int i;
|
||||
if (dot)
|
||||
*dot = '\0';
|
||||
if (*optarg) {
|
||||
gopt.amfs_auto_timeo = atoi(optarg);
|
||||
for (i=0; i<AMU_TYPE_MAX; ++i)
|
||||
gopt.amfs_auto_timeo[i] = atoi(optarg);
|
||||
}
|
||||
if (dot) {
|
||||
gopt.amfs_auto_retrans = atoi(dot + 1);
|
||||
for (i=0; i<AMU_TYPE_MAX; ++i)
|
||||
gopt.amfs_auto_retrans[i] = atoi(dot + 1);
|
||||
*dot = '.';
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
fputs(get_version_string(), stderr);
|
||||
exit(0);
|
||||
/*
|
||||
* defer to print version info after every variable had been
|
||||
* initialized.
|
||||
*/
|
||||
print_version++;
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
|
|
@ -225,6 +273,10 @@ get_args(int argc, char *argv[])
|
|||
#endif /* not HAVE_MAP_NIS */
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
gopt.arch = optarg;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
gopt.cluster = optarg;
|
||||
break;
|
||||
|
|
@ -239,12 +291,13 @@ get_args(int argc, char *argv[])
|
|||
break;
|
||||
|
||||
case 'F':
|
||||
conf_file = optarg;
|
||||
amu_conf_file = optarg;
|
||||
use_conf_file = 1;
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
goto show_usage;
|
||||
show_usage();
|
||||
exit(1);
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
|
|
@ -269,18 +322,19 @@ get_args(int argc, char *argv[])
|
|||
* specified, then use that amd.conf file. If the file cannot be opened,
|
||||
* abort amd. If it can be found, open it, parse it, and then close it.
|
||||
*/
|
||||
if (use_conf_file && conf_file) {
|
||||
fp = fopen(conf_file, "r");
|
||||
if (use_conf_file && amu_conf_file) {
|
||||
fp = fopen(amu_conf_file, "r");
|
||||
if (!fp) {
|
||||
char buf[128];
|
||||
sprintf(buf, "Amd configuration file (%s)", conf_file);
|
||||
xsnprintf(buf, sizeof(buf), "Amd configuration file (%s)",
|
||||
amu_conf_file);
|
||||
perror(buf);
|
||||
exit(1);
|
||||
}
|
||||
yyin = fp;
|
||||
yyparse();
|
||||
fclose(fp);
|
||||
if (process_last_regular_map() != 0)
|
||||
if (process_all_regular_maps() != 0)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -293,8 +347,8 @@ get_args(int argc, char *argv[])
|
|||
#endif /* DEBUG */
|
||||
|
||||
/* log information regarding amd.conf file */
|
||||
if (use_conf_file && conf_file)
|
||||
plog(XLOG_INFO, "using configuration file %s", conf_file);
|
||||
if (use_conf_file && amu_conf_file)
|
||||
plog(XLOG_INFO, "using configuration file %s", amu_conf_file);
|
||||
|
||||
#ifdef HAVE_MAP_LDAP
|
||||
/* ensure that if ldap_base is specified, that also ldap_hostports is */
|
||||
|
|
@ -304,8 +358,10 @@ get_args(int argc, char *argv[])
|
|||
}
|
||||
#endif /* HAVE_MAP_LDAP */
|
||||
|
||||
if (usage)
|
||||
goto show_usage;
|
||||
if (usage) {
|
||||
show_usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (optind <= argc - 2) {
|
||||
char *dir = argv[optind++];
|
||||
|
|
@ -327,76 +383,55 @@ get_args(int argc, char *argv[])
|
|||
hostdomain = gopt.sub_domain;
|
||||
if (*hostdomain == '.')
|
||||
hostdomain++;
|
||||
strcat(hostd, ".");
|
||||
strcat(hostd, hostdomain);
|
||||
xstrlcat(hostd, ".", sizeof(hostd));
|
||||
xstrlcat(hostd, hostdomain, sizeof(hostd));
|
||||
|
||||
#ifdef MOUNT_TABLE_ON_FILE
|
||||
# ifdef DEBUG
|
||||
if (debug_flags & D_MTAB)
|
||||
mnttab_file_name = DEBUG_MNTTAB;
|
||||
if (amuDebug(D_MTAB))
|
||||
if (gopt.debug_mtab_file)
|
||||
mnttab_file_name = gopt.debug_mtab_file; /* user supplied debug mtab path */
|
||||
else
|
||||
mnttab_file_name = DEBUG_MNTTAB_FILE; /* default debug mtab path */
|
||||
else
|
||||
# endif /* DEBUG */
|
||||
mnttab_file_name = MNTTAB_FILE_NAME;
|
||||
#else /* not MOUNT_TABLE_ON_FILE */
|
||||
# ifdef DEBUG
|
||||
if (debug_flags & D_MTAB)
|
||||
if (amuDebug(D_MTAB))
|
||||
dlog("-D mtab option ignored");
|
||||
# endif /* DEBUG */
|
||||
# ifdef MNTTAB_FILE_NAME
|
||||
mnttab_file_name = MNTTAB_FILE_NAME;
|
||||
# endif /* MNTTAB_FILE_NAME */
|
||||
#endif /* not MOUNT_TABLE_ON_FILE */
|
||||
|
||||
if (switch_to_logfile(gopt.logfile, orig_umask) != 0)
|
||||
plog(XLOG_USER, "Cannot switch logfile");
|
||||
|
||||
/*
|
||||
* If the kernel architecture was not specified
|
||||
* then use the machine architecture.
|
||||
*/
|
||||
if (gopt.karch == 0)
|
||||
if (gopt.karch == NULL)
|
||||
gopt.karch = gopt.arch;
|
||||
|
||||
if (gopt.cluster == 0)
|
||||
if (gopt.cluster == NULL)
|
||||
gopt.cluster = hostdomain;
|
||||
|
||||
if (gopt.amfs_auto_timeo <= 0)
|
||||
gopt.amfs_auto_timeo = AMFS_AUTO_TIMEO;
|
||||
if (gopt.amfs_auto_retrans <= 0)
|
||||
gopt.amfs_auto_retrans = AMFS_AUTO_RETRANS;
|
||||
if (gopt.amfs_auto_retrans <= 0)
|
||||
gopt.amfs_auto_retrans = 3; /* XXX */
|
||||
return;
|
||||
/* sanity checking, normalize values just in case (toplvl too) */
|
||||
for (i=0; i<AMU_TYPE_MAX; ++i) {
|
||||
if (gopt.amfs_auto_timeo[i] == 0)
|
||||
gopt.amfs_auto_timeo[i] = AMFS_AUTO_TIMEO;
|
||||
if (gopt.amfs_auto_retrans[i] == 0)
|
||||
gopt.amfs_auto_retrans[i] = AMFS_AUTO_RETRANS(i);
|
||||
if (gopt.amfs_auto_retrans[i] == 0)
|
||||
gopt.amfs_auto_retrans[i] = 3; /* under very unusual circumstances, could be zero */
|
||||
}
|
||||
}
|
||||
|
||||
show_usage:
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-nprvHS] [-a mount_point] [-c cache_time] [-d domain]\n\
|
||||
\t[-k kernel_arch] [-l logfile%s\n\
|
||||
\t[-t timeout.retrans] [-w wait_timeout] [-C cluster_name]\n\
|
||||
\t[-o op_sys_ver] [-O op_sys_name]\n\
|
||||
\t[-F conf_file] [-T conf_tag]", am_get_progname(),
|
||||
#ifdef HAVE_SYSLOG
|
||||
# ifdef LOG_DAEMON
|
||||
"|\"syslog[:facility]\"]"
|
||||
# else /* not LOG_DAEMON */
|
||||
"|\"syslog\"]"
|
||||
# endif /* not LOG_DAEMON */
|
||||
#else /* not HAVE_SYSLOG */
|
||||
"]"
|
||||
#endif /* not HAVE_SYSLOG */
|
||||
);
|
||||
/* finally print version string and exit, if asked for */
|
||||
if (print_version) {
|
||||
fputs(get_version_string(), stderr);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#ifdef HAVE_MAP_NIS
|
||||
fputs(" [-y nis-domain]\n", stderr);
|
||||
#else /* not HAVE_MAP_NIS */
|
||||
fputc('\n', stderr);
|
||||
#endif /* HAVE_MAP_NIS */
|
||||
if (switch_to_logfile(gopt.logfile, orig_umask,
|
||||
(gopt.flags & CFM_TRUNCATE_LOG)) != 0)
|
||||
plog(XLOG_USER, "Cannot switch logfile");
|
||||
|
||||
show_opts('x', xlog_opt);
|
||||
#ifdef DEBUG
|
||||
show_opts('D', dbg_opt);
|
||||
#endif /* DEBUG */
|
||||
fprintf(stderr, "\t[directory mapname [-map_options]] ...\n");
|
||||
exit(1);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
423
contrib/amd/amd/info_exec.c
Normal file
423
contrib/amd/amd/info_exec.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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, ":");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.5.2.6 2004/01/21 04:04:58 ib42 Exp $
|
||||
* File: am-utils/amd/nfs_prot_svc.c
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -69,7 +68,7 @@ extern nfsreaddirres *nfsproc_readdir_2_svc(nfsreaddirargs *, struct svc_req *);
|
|||
extern nfsstatfsres *nfsproc_statfs_2_svc(am_nfs_fh *, struct svc_req *);
|
||||
|
||||
/* global variables */
|
||||
SVCXPRT *nfs_program_2_transp;
|
||||
SVCXPRT *current_transp;
|
||||
|
||||
/* typedefs */
|
||||
typedef char *(*nfssvcproc_t)(voidp, struct svc_req *);
|
||||
|
|
@ -98,30 +97,60 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
|
|||
char *result;
|
||||
xdrproc_t xdr_argument, xdr_result;
|
||||
nfssvcproc_t local;
|
||||
|
||||
#ifdef HAVE_TRANSPORT_TYPE_TLI
|
||||
/*
|
||||
* On TLI systems we don't use an INET network type, but a "ticlts" (see
|
||||
* /etc/netconfig and conf/transp_tli.c:create_nfs_service). This means
|
||||
* that packets could only come from the loopback interface, and we don't
|
||||
* need to check them and filter possibly spoofed packets. Therefore we
|
||||
* only need to check if the UID caller is correct.
|
||||
*/
|
||||
# ifdef HAVE___RPC_GET_LOCAL_UID
|
||||
uid_t u;
|
||||
/* extern definition for an internal libnsl function */
|
||||
extern int __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid);
|
||||
if (__rpc_get_local_uid(transp, &u) >= 0 && u != 0) {
|
||||
plog(XLOG_WARNING, "ignoring request from UID %ld, must be 0", (long) u);
|
||||
return;
|
||||
}
|
||||
# else /* not HAVE___RPC_GET_LOCAL_UID */
|
||||
dlog("cannot verify local uid for rpc request");
|
||||
# endif /* HAVE___RPC_GET_LOCAL_UID */
|
||||
#else /* not HAVE_TRANPORT_TYPE_TLI */
|
||||
struct sockaddr_in *sinp;
|
||||
char dq[20], dq2[28];
|
||||
|
||||
sinp = amu_svc_getcaller(rqstp->rq_xprt);
|
||||
#ifdef MNT2_NFS_OPT_RESVPORT
|
||||
# ifdef MNT2_NFS_OPT_RESVPORT
|
||||
/* Verify that the request comes from a reserved port */
|
||||
if (ntohs(sinp->sin_port) >= IPPORT_RESERVED) &&
|
||||
if (sinp &&
|
||||
ntohs(sinp->sin_port) >= IPPORT_RESERVED &&
|
||||
!(gopt.flags & CFM_NFS_INSECURE_PORT)) {
|
||||
plog(XLOG_WARNING, "ignoring request from %s:%u, port not reserved",
|
||||
inet_dquad(dq, sinp->sin_addr.s_addr),
|
||||
inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
|
||||
ntohs(sinp->sin_port));
|
||||
return;
|
||||
}
|
||||
#endif /* MNT2_NFS_OPT_RESVPORT */
|
||||
# endif /* MNT2_NFS_OPT_RESVPORT */
|
||||
/* if the address does not match, ignore the request */
|
||||
if (sinp->sin_addr.s_addr && sinp->sin_addr.s_addr != myipaddr.s_addr) {
|
||||
plog(XLOG_WARNING, "ignoring request from %s:%u, expected %s",
|
||||
inet_dquad(dq, sinp->sin_addr.s_addr),
|
||||
ntohs(sinp->sin_port),
|
||||
inet_dquad(dq2, myipaddr.s_addr));
|
||||
return;
|
||||
if (sinp && (sinp->sin_addr.s_addr != myipaddr.s_addr)) {
|
||||
if (gopt.flags & CFM_NFS_ANY_INTERFACE) {
|
||||
if (!is_interface_local(sinp->sin_addr.s_addr)) {
|
||||
plog(XLOG_WARNING, "ignoring request from %s:%u, not a local interface",
|
||||
inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
|
||||
ntohs(sinp->sin_port));
|
||||
}
|
||||
} else {
|
||||
plog(XLOG_WARNING, "ignoring request from %s:%u, expected %s",
|
||||
inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
|
||||
ntohs(sinp->sin_port),
|
||||
inet_dquad(dq2, sizeof(dq2), myipaddr.s_addr));
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* not HAVE_TRANPORT_TYPE_TLI */
|
||||
|
||||
nfs_program_2_transp = NULL;
|
||||
current_transp = NULL;
|
||||
|
||||
switch (rqstp->rq_proc) {
|
||||
|
||||
|
|
@ -158,7 +187,7 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
|
|||
* be stored in the am_node structure and later used for
|
||||
* quick_reply().
|
||||
*/
|
||||
nfs_program_2_transp = transp;
|
||||
current_transp = transp;
|
||||
break;
|
||||
|
||||
case NFSPROC_READLINK:
|
||||
|
|
@ -256,7 +285,7 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
|
|||
}
|
||||
result = (*local) (&argument, rqstp);
|
||||
|
||||
nfs_program_2_transp = NULL;
|
||||
current_transp = NULL;
|
||||
|
||||
if (result != NULL && !svc_sendreply(transp,
|
||||
(XDRPROC_T_TYPE) xdr_result,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 @@ out:
|
|||
*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); */
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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 = ':';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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_pcfs.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
|
||||
* File: am-utils/amd/ops_pcfs.c
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -54,8 +53,8 @@
|
|||
|
||||
/* forward definitions */
|
||||
static char *pcfs_match(am_opts *fo);
|
||||
static int pcfs_fmount(mntfs *mf);
|
||||
static int pcfs_fumount(mntfs *mf);
|
||||
static int pcfs_mount(am_node *am, mntfs *mf);
|
||||
static int pcfs_umount(am_node *am, mntfs *mf);
|
||||
|
||||
/*
|
||||
* Ops structure
|
||||
|
|
@ -65,17 +64,20 @@ am_ops pcfs_ops =
|
|||
"pcfs",
|
||||
pcfs_match,
|
||||
0, /* pcfs_init */
|
||||
amfs_auto_fmount,
|
||||
pcfs_fmount,
|
||||
amfs_auto_fumount,
|
||||
pcfs_fumount,
|
||||
amfs_error_lookuppn,
|
||||
pcfs_mount,
|
||||
pcfs_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* pcfs_readlink */
|
||||
0, /* pcfs_mounted */
|
||||
0, /* pcfs_umounted */
|
||||
find_amfs_auto_srvr,
|
||||
FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO
|
||||
amfs_generic_find_srvr,
|
||||
0, /* pcfs_get_wchan */
|
||||
FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_PCFS_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -90,9 +92,7 @@ pcfs_match(am_opts *fo)
|
|||
plog(XLOG_USER, "pcfs: no source device specified");
|
||||
return 0;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
dlog("PCFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* Determine magic cookie to put in mtab
|
||||
|
|
@ -102,11 +102,17 @@ pcfs_match(am_opts *fo)
|
|||
|
||||
|
||||
static int
|
||||
mount_pcfs(char *dir, char *fs_name, char *opts)
|
||||
mount_pcfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
|
||||
{
|
||||
pcfs_args_t pcfs_args;
|
||||
mntent_t mnt;
|
||||
int flags;
|
||||
#if defined(HAVE_PCFS_ARGS_T_MASK) || defined(HAVE_PCFS_ARGS_T_DIRMASK)
|
||||
int mask;
|
||||
#endif /* defined(HAVE_PCFS_ARGS_T_MASK) || defined(HAVE_PCFS_ARGS_T_DIRMASK) */
|
||||
#if defined(HAVE_PCFS_ARGS_T_UID) || defined(HAVE_PCFS_ARGS_T_UID)
|
||||
char *str;
|
||||
#endif /* defined(HAVE_PCFS_ARGS_T_UID) || defined(HAVE_PCFS_ARGS_T_UID) */
|
||||
|
||||
/*
|
||||
* Figure out the name of the file system type.
|
||||
|
|
@ -119,12 +125,18 @@ mount_pcfs(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_PCFS;
|
||||
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 */
|
||||
if (amuDebug(D_TRACE))
|
||||
plog(XLOG_DEBUG, "mount_pcfs: flags=0x%x", (u_int) flags);
|
||||
|
||||
#ifdef HAVE_PCFS_ARGS_T_FSPEC
|
||||
pcfs_args.fspec = fs_name;
|
||||
|
|
@ -132,14 +144,46 @@ mount_pcfs(char *dir, char *fs_name, char *opts)
|
|||
|
||||
#ifdef HAVE_PCFS_ARGS_T_MASK
|
||||
pcfs_args.mask = 0777; /* this may be the msdos file modes */
|
||||
if ((mask = hasmntval(&mnt, MNTTAB_OPT_MASK)) > 0)
|
||||
pcfs_args.mask = mask;
|
||||
if (amuDebug(D_TRACE))
|
||||
plog(XLOG_DEBUG, "mount_pcfs: mask=%o (octal)", (u_int) pcfs_args.mask);
|
||||
#endif /* HAVE_PCFS_ARGS_T_MASK */
|
||||
|
||||
#ifdef HAVE_PCFS_ARGS_T_DIRMASK
|
||||
pcfs_args.dirmask = 0777; /* this may be the msdos dir modes */
|
||||
if ((mask = hasmntval(&mnt, MNTTAB_OPT_DIRMASK)) > 0)
|
||||
pcfs_args.dirmask = mask;
|
||||
if (amuDebug(D_TRACE))
|
||||
plog(XLOG_DEBUG, "mount_pcfs: dirmask=%o (octal)", (u_int) pcfs_args.dirmask);
|
||||
#endif /* HAVE_PCFS_ARGS_T_DIRMASK */
|
||||
|
||||
#ifdef HAVE_PCFS_ARGS_T_UID
|
||||
pcfs_args.uid = 0; /* root */
|
||||
pcfs_args.uid = 0; /* default to root */
|
||||
if ((str = hasmntstr(&mnt, MNTTAB_OPT_USER)) != NULL) {
|
||||
struct passwd *pw;
|
||||
if ((pw = getpwnam(str)) != NULL)
|
||||
pcfs_args.uid = pw->pw_uid;
|
||||
else /* maybe used passed a UID number, not user name */
|
||||
pcfs_args.uid = atoi(str); /* atoi returns '0' if it failed */
|
||||
XFREE(str);
|
||||
}
|
||||
if (amuDebug(D_TRACE))
|
||||
plog(XLOG_DEBUG, "mount_pcfs: uid=%d", (int) pcfs_args.uid);
|
||||
#endif /* HAVE_PCFS_ARGS_T_UID */
|
||||
|
||||
#ifdef HAVE_PCFS_ARGS_T_GID
|
||||
pcfs_args.gid = 0; /* wheel */
|
||||
pcfs_args.gid = 0; /* default to wheel/root group */
|
||||
if ((str = hasmntstr(&mnt, MNTTAB_OPT_GROUP)) != NULL) {
|
||||
struct group *gr;
|
||||
if ((gr = getgrnam(str)) != NULL)
|
||||
pcfs_args.gid = gr->gr_gid;
|
||||
else /* maybe used passed a GID number, not group name */
|
||||
pcfs_args.gid = atoi(str); /* atoi returns '0' if it failed */
|
||||
XFREE(str);
|
||||
}
|
||||
if (amuDebug(D_TRACE))
|
||||
plog(XLOG_DEBUG, "mount_pcfs: gid=%d", (int) pcfs_args.gid);
|
||||
#endif /* HAVE_PCFS_ARGS_T_GID */
|
||||
|
||||
#ifdef HAVE_PCFS_ARGS_T_SECONDSWEST
|
||||
|
|
@ -152,16 +196,17 @@ mount_pcfs(char *dir, char *fs_name, char *opts)
|
|||
/*
|
||||
* Call generic mount routine
|
||||
*/
|
||||
return mount_fs(&mnt, flags, (caddr_t) & pcfs_args, 0, type, 0, NULL, mnttab_file_name);
|
||||
return mount_fs(&mnt, flags, (caddr_t) & pcfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
pcfs_fmount(mntfs *mf)
|
||||
pcfs_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
|
||||
int error;
|
||||
|
||||
error = mount_pcfs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
|
||||
error = mount_pcfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
|
||||
if (error) {
|
||||
errno = error;
|
||||
plog(XLOG_ERROR, "mount_pcfs: %m");
|
||||
|
|
@ -173,7 +218,9 @@ pcfs_fmount(mntfs *mf)
|
|||
|
||||
|
||||
static int
|
||||
pcfs_fumount(mntfs *mf)
|
||||
pcfs_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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 @@ out:
|
|||
/*
|
||||
* 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
498
contrib/amd/amd/readdir.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 @@ out:
|
|||
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 @@ again:
|
|||
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 @@ again:
|
|||
* 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 @@ again:
|
|||
* Put the original message id back
|
||||
* into the packet.
|
||||
*/
|
||||
*pkt_int = p->rf_oldid;
|
||||
*pkt_int = htonl(p->rf_oldid);
|
||||
|
||||
/*
|
||||
* Call forwarding function
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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: srvr_nfs.c,v 1.7.2.11 2004/01/06 03:15:16 ezk Exp $
|
||||
* File: am-utils/amd/srvr_nfs.c
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -72,8 +71,6 @@
|
|||
*/
|
||||
#endif /* (FAST_NFS_PING * MAX_ALLOWED_PINGS) >= ALLOWED_MOUNT_TIME */
|
||||
|
||||
#define NPXID_ALLOC(struct ) (++np_xid)
|
||||
|
||||
/* structures and typedefs */
|
||||
typedef struct nfs_private {
|
||||
u_short np_mountd; /* Mount daemon port number */
|
||||
|
|
@ -88,9 +85,16 @@ typedef struct nfs_private {
|
|||
qelem nfs_srvr_list = {&nfs_srvr_list, &nfs_srvr_list};
|
||||
|
||||
/* statics */
|
||||
static int np_xid; /* For NFS pings */
|
||||
static int ping_len;
|
||||
static char ping_buf[sizeof(struct rpc_msg) + 32];
|
||||
static int global_xid; /* For NFS pings */
|
||||
#define XID_ALLOC() (++global_xid)
|
||||
|
||||
#ifdef HAVE_FS_NFS3
|
||||
# define NUM_NFS_VERS 2
|
||||
#else /* not HAVE_FS_NFS3 */
|
||||
# define NUM_NFS_VERS 1
|
||||
#endif /* not HAVE_FS_NFS3 */
|
||||
static int ping_len[NUM_NFS_VERS];
|
||||
static char ping_buf[NUM_NFS_VERS][sizeof(struct rpc_msg) + 32];
|
||||
|
||||
#if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3)
|
||||
/*
|
||||
|
|
@ -99,6 +103,8 @@ static char ping_buf[sizeof(struct rpc_msg) + 32];
|
|||
* Note that Solaris 8 and newer NetBSD systems are switching to UDP first,
|
||||
* so this order may have to be adjusted for Amd in the future once more
|
||||
* vendors make that change. -Erez 11/24/2000
|
||||
*
|
||||
* Or we might simply make this is a platform-specific order. -Ion 09/13/2003
|
||||
*/
|
||||
static char *protocols[] = { "tcp", "udp", NULL };
|
||||
#endif /* defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
|
||||
|
|
@ -107,20 +113,21 @@ static char *protocols[] = { "tcp", "udp", NULL };
|
|||
static void nfs_keepalive(voidp);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Flush any cached data
|
||||
* Flush cached data for an fserver (or for all, if fs==NULL)
|
||||
*/
|
||||
void
|
||||
flush_srvr_nfs_cache(void)
|
||||
flush_srvr_nfs_cache(fserver *fs)
|
||||
{
|
||||
fserver *fs = 0;
|
||||
fserver *fs2 = NULL;
|
||||
|
||||
ITER(fs, fserver, &nfs_srvr_list) {
|
||||
nfs_private *np = (nfs_private *) fs->fs_private;
|
||||
if (np) {
|
||||
np->np_mountd_inval = TRUE;
|
||||
np->np_error = -1;
|
||||
ITER(fs2, fserver, &nfs_srvr_list) {
|
||||
if (fs == NULL || fs == fs2) {
|
||||
nfs_private *np = (nfs_private *) fs2->fs_private;
|
||||
if (np) {
|
||||
np->np_mountd_inval = TRUE;
|
||||
np->np_error = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -130,7 +137,7 @@ flush_srvr_nfs_cache(void)
|
|||
* Startup the NFS ping for a particular version.
|
||||
*/
|
||||
static void
|
||||
start_ping(u_long nfs_version)
|
||||
create_ping_payload(u_long nfs_version)
|
||||
{
|
||||
XDR ping_xdr;
|
||||
struct rpc_msg ping_msg;
|
||||
|
|
@ -140,16 +147,16 @@ start_ping(u_long nfs_version)
|
|||
*/
|
||||
if (nfs_version == 0) {
|
||||
nfs_version = NFS_VERSION;
|
||||
plog(XLOG_WARNING, "start_ping: nfs_version = 0 fixed");
|
||||
}
|
||||
plog(XLOG_INFO, "start_ping: nfs_version: %d", (int) nfs_version);
|
||||
plog(XLOG_WARNING, "create_ping_payload: nfs_version = 0, changed to 2");
|
||||
} else
|
||||
plog(XLOG_INFO, "create_ping_payload: nfs_version: %d", (int) nfs_version);
|
||||
|
||||
rpc_msg_init(&ping_msg, NFS_PROGRAM, nfs_version, NFSPROC_NULL);
|
||||
|
||||
/*
|
||||
* Create an XDR endpoint
|
||||
*/
|
||||
xdrmem_create(&ping_xdr, ping_buf, sizeof(ping_buf), XDR_ENCODE);
|
||||
xdrmem_create(&ping_xdr, ping_buf[nfs_version - NFS_VERSION], sizeof(ping_buf[0]), XDR_ENCODE);
|
||||
|
||||
/*
|
||||
* Create the NFS ping message
|
||||
|
|
@ -161,7 +168,7 @@ start_ping(u_long nfs_version)
|
|||
/*
|
||||
* Find out how long it is
|
||||
*/
|
||||
ping_len = xdr_getpos(&ping_xdr);
|
||||
ping_len[nfs_version - NFS_VERSION] = xdr_getpos(&ping_xdr);
|
||||
|
||||
/*
|
||||
* Destroy the XDR endpoint - we don't need it anymore
|
||||
|
|
@ -183,7 +190,7 @@ got_portmap(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia,
|
|||
* Find which fileserver we are talking about
|
||||
*/
|
||||
ITER(fs, fserver, &nfs_srvr_list)
|
||||
if (fs == fs2)
|
||||
if (fs == fs2)
|
||||
break;
|
||||
|
||||
if (fs == fs2) {
|
||||
|
|
@ -192,9 +199,7 @@ got_portmap(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia,
|
|||
nfs_private *np = (nfs_private *) fs->fs_private;
|
||||
|
||||
if (!error && port) {
|
||||
#ifdef DEBUG
|
||||
dlog("got port (%d) for mountd on %s", (int) port, fs->fs_host);
|
||||
#endif /* DEBUG */
|
||||
/*
|
||||
* Grab the port number. Portmap sends back
|
||||
* an u_long in native ordering, so it
|
||||
|
|
@ -205,10 +210,8 @@ got_portmap(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia,
|
|||
np->np_mountd_inval = FALSE;
|
||||
np->np_error = 0;
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
dlog("Error fetching port for mountd on %s", fs->fs_host);
|
||||
dlog("\t error=%d, port=%d", error, (int) port);
|
||||
#endif /* DEBUG */
|
||||
/*
|
||||
* Almost certainly no mountd running on remote host
|
||||
*/
|
||||
|
|
@ -218,13 +221,9 @@ got_portmap(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia,
|
|||
if (fs->fs_flags & FSF_WANT)
|
||||
wakeup_srvr(fs);
|
||||
} else if (done) {
|
||||
#ifdef DEBUG
|
||||
dlog("Got portmap for old port request");
|
||||
#endif /* DEBUG */
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
dlog("portmap request timed out");
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -258,7 +257,7 @@ call_portmap(fserver *fs, AUTH *auth, u_long prog, u_long vers, u_long prot)
|
|||
memset((voidp) &sin, 0, sizeof(sin));
|
||||
sin = *fs->fs_ip;
|
||||
sin.sin_port = htons(PMAPPORT);
|
||||
error = fwd_packet(RPC_XID_PORTMAP, (voidp) iobuf, len,
|
||||
error = fwd_packet(RPC_XID_PORTMAP, iobuf, len,
|
||||
&sin, &sin, (voidp) fs, got_portmap);
|
||||
} else {
|
||||
error = -len;
|
||||
|
|
@ -274,6 +273,12 @@ recompute_portmap(fserver *fs)
|
|||
int error;
|
||||
u_long mnt_version;
|
||||
|
||||
/*
|
||||
* No portmap calls for pure WebNFS servers.
|
||||
*/
|
||||
if (fs->fs_flags & FSF_WEBNFS)
|
||||
return;
|
||||
|
||||
if (nfs_auth)
|
||||
error = 0;
|
||||
else
|
||||
|
|
@ -288,10 +293,11 @@ recompute_portmap(fserver *fs)
|
|||
if (fs->fs_version == 0)
|
||||
plog(XLOG_WARNING, "recompute_portmap: nfs_version = 0 fixed");
|
||||
|
||||
plog(XLOG_INFO, "recompute_portmap: NFS version %d", (int) fs->fs_version);
|
||||
plog(XLOG_INFO, "recompute_portmap: NFS version %d on %s",
|
||||
(int) fs->fs_version, fs->fs_host);
|
||||
#ifdef HAVE_FS_NFS3
|
||||
if (fs->fs_version == NFS_VERSION3)
|
||||
mnt_version = MOUNTVERS3;
|
||||
mnt_version = AM_MOUNTVERS3;
|
||||
else
|
||||
#endif /* HAVE_FS_NFS3 */
|
||||
mnt_version = MOUNTVERS;
|
||||
|
|
@ -301,19 +307,61 @@ recompute_portmap(fserver *fs)
|
|||
}
|
||||
|
||||
|
||||
int
|
||||
get_mountd_port(fserver *fs, u_short *port, wchan_t wchan)
|
||||
{
|
||||
int error = -1;
|
||||
if (FSRV_ISDOWN(fs))
|
||||
return EWOULDBLOCK;
|
||||
|
||||
if (FSRV_ISUP(fs)) {
|
||||
nfs_private *np = (nfs_private *) fs->fs_private;
|
||||
if (np->np_error == 0) {
|
||||
*port = np->np_mountd;
|
||||
error = 0;
|
||||
} else {
|
||||
error = np->np_error;
|
||||
}
|
||||
/*
|
||||
* Now go get the port mapping again in case it changed.
|
||||
* Note that it is used even if (np_mountd_inval)
|
||||
* is True. The flag is used simply as an
|
||||
* indication that the mountd may be invalid, not
|
||||
* that it is known to be invalid.
|
||||
*/
|
||||
if (np->np_mountd_inval)
|
||||
recompute_portmap(fs);
|
||||
else
|
||||
np->np_mountd_inval = TRUE;
|
||||
}
|
||||
if (error < 0 && wchan && !(fs->fs_flags & FSF_WANT)) {
|
||||
/*
|
||||
* If a wait channel is supplied, and no
|
||||
* error has yet occurred, then arrange
|
||||
* that a wakeup is done on the wait channel,
|
||||
* whenever a wakeup is done on this fs node.
|
||||
* Wakeup's are done on the fs node whenever
|
||||
* it changes state - thus causing control to
|
||||
* come back here and new, better things to happen.
|
||||
*/
|
||||
fs->fs_flags |= FSF_WANT;
|
||||
sched_task(wakeup_task, wchan, (wchan_t) fs);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This is called when we get a reply to an RPC ping.
|
||||
* The value of id was taken from the nfs_private
|
||||
* structure when the ping was transmitted.
|
||||
*/
|
||||
static void
|
||||
nfs_pinged(voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp, voidp idv, int done)
|
||||
nfs_keepalive_callback(voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp, voidp idv, int done)
|
||||
{
|
||||
int xid = (long) idv; /* for 64-bit archs */
|
||||
int xid = (long) idv; /* cast needed for 64-bit archs */
|
||||
fserver *fs;
|
||||
#ifdef DEBUG
|
||||
int found_map = 0;
|
||||
#endif /* DEBUG */
|
||||
|
||||
if (!done)
|
||||
return;
|
||||
|
|
@ -336,19 +384,15 @@ nfs_pinged(voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp,
|
|||
} else {
|
||||
if (np->np_ping > 1)
|
||||
srvrlog(fs, "ok");
|
||||
#ifdef DEBUG
|
||||
else
|
||||
srvrlog(fs, "starts up");
|
||||
#endif /* DEBUG */
|
||||
fs->fs_flags |= FSF_VALID;
|
||||
}
|
||||
|
||||
map_flush_srvr(fs);
|
||||
} else {
|
||||
if (fs->fs_flags & FSF_VALID) {
|
||||
#ifdef DEBUG
|
||||
dlog("file server %s type nfs is still up", fs->fs_host);
|
||||
#endif /* DEBUG */
|
||||
} else {
|
||||
if (np->np_ping > 1)
|
||||
srvrlog(fs, "ok");
|
||||
|
|
@ -365,13 +409,13 @@ nfs_pinged(voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp,
|
|||
/*
|
||||
* Update ttl for this server
|
||||
*/
|
||||
np->np_ttl = clocktime() +
|
||||
np->np_ttl = clocktime(NULL) +
|
||||
(MAX_ALLOWED_PINGS - 1) * FAST_NFS_PING + fs->fs_pinger - 1;
|
||||
|
||||
/*
|
||||
* New RPC xid...
|
||||
*/
|
||||
np->np_xid = NPXID_ALLOC(struct );
|
||||
np->np_xid = XID_ALLOC();
|
||||
|
||||
/*
|
||||
* Failed pings is zero...
|
||||
|
|
@ -384,17 +428,53 @@ nfs_pinged(voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp,
|
|||
if (np->np_mountd_inval)
|
||||
recompute_portmap(fs);
|
||||
|
||||
#ifdef DEBUG
|
||||
found_map++;
|
||||
#endif /* DEBUG */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (found_map == 0)
|
||||
dlog("Spurious ping packet");
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
check_fs_addr_change(fserver *fs)
|
||||
{
|
||||
struct hostent *hp = NULL;
|
||||
struct in_addr ia;
|
||||
char *old_ipaddr, *new_ipaddr;
|
||||
|
||||
hp = gethostbyname(fs->fs_host);
|
||||
if (!hp ||
|
||||
hp->h_addrtype != AF_INET ||
|
||||
!STREQ((char *) hp->h_name, fs->fs_host) ||
|
||||
memcmp((voidp) &fs->fs_ip->sin_addr,
|
||||
(voidp) hp->h_addr,
|
||||
sizeof(fs->fs_ip->sin_addr)) == 0)
|
||||
return;
|
||||
/* if got here: downed server changed IP address */
|
||||
old_ipaddr = strdup(inet_ntoa(fs->fs_ip->sin_addr));
|
||||
memmove((voidp) &ia, (voidp) hp->h_addr, sizeof(struct in_addr));
|
||||
new_ipaddr = inet_ntoa(ia); /* ntoa uses static buf */
|
||||
plog(XLOG_WARNING, "EZK: down fileserver %s changed ip: %s -> %s",
|
||||
fs->fs_host, old_ipaddr, new_ipaddr);
|
||||
XFREE(old_ipaddr);
|
||||
/* copy new IP addr */
|
||||
memmove((voidp) &fs->fs_ip->sin_addr,
|
||||
(voidp) hp->h_addr,
|
||||
sizeof(fs->fs_ip->sin_addr));
|
||||
/* XXX: do we need to un/set these flags? */
|
||||
fs->fs_flags &= ~FSF_DOWN;
|
||||
fs->fs_flags |= FSF_VALID | FSF_WANT;
|
||||
map_flush_srvr(fs); /* XXX: a race with flush_srvr_nfs_cache? */
|
||||
flush_srvr_nfs_cache(fs);
|
||||
fs->fs_flags |= FSF_FORCE_UNMOUNT;
|
||||
|
||||
#if 0
|
||||
flush_nfs_fhandle_cache(fs); /* done in caller: nfs_keepalive_timeout */
|
||||
/* XXX: need to purge nfs_private so that somehow it will get re-initialized? */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -402,7 +482,7 @@ nfs_pinged(voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp,
|
|||
* Called when no ping-reply received
|
||||
*/
|
||||
static void
|
||||
nfs_timed_out(voidp v)
|
||||
nfs_keepalive_timeout(voidp v)
|
||||
{
|
||||
fserver *fs = v;
|
||||
nfs_private *np = (nfs_private *) fs->fs_private;
|
||||
|
|
@ -423,11 +503,9 @@ nfs_timed_out(voidp v)
|
|||
/*
|
||||
* If ttl has expired then guess that it is dead
|
||||
*/
|
||||
if (np->np_ttl < clocktime()) {
|
||||
if (np->np_ttl < clocktime(NULL)) {
|
||||
int oflags = fs->fs_flags;
|
||||
#ifdef DEBUG
|
||||
dlog("ttl has expired");
|
||||
#endif /* DEBUG */
|
||||
if ((fs->fs_flags & FSF_DOWN) == 0) {
|
||||
/*
|
||||
* Server was up, but is now down.
|
||||
|
|
@ -441,14 +519,13 @@ nfs_timed_out(voidp v)
|
|||
*/
|
||||
flush_nfs_fhandle_cache(fs);
|
||||
np->np_error = -1;
|
||||
check_fs_addr_change(fs); /* check if IP addr of fserver changed */
|
||||
} else {
|
||||
/*
|
||||
* Known to be down
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
if ((fs->fs_flags & FSF_VALID) == 0)
|
||||
srvrlog(fs, "starts down");
|
||||
#endif /* DEBUG */
|
||||
fs->fs_flags |= FSF_VALID;
|
||||
}
|
||||
if (oflags != fs->fs_flags && (fs->fs_flags & FSF_WANT))
|
||||
|
|
@ -458,17 +535,15 @@ nfs_timed_out(voidp v)
|
|||
*/
|
||||
np->np_ping = 0;
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
if (np->np_ping > 1)
|
||||
dlog("%d pings to %s failed - at most %d allowed", np->np_ping, fs->fs_host, MAX_ALLOWED_PINGS);
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
/*
|
||||
* New RPC xid, so any late responses to the previous ping
|
||||
* get ignored...
|
||||
*/
|
||||
np->np_xid = NPXID_ALLOC(struct );
|
||||
np->np_xid = XID_ALLOC();
|
||||
|
||||
/*
|
||||
* Run keepalive again
|
||||
|
|
@ -492,19 +567,19 @@ nfs_keepalive(voidp v)
|
|||
* Send an NFS ping to this node
|
||||
*/
|
||||
|
||||
if (ping_len == 0)
|
||||
start_ping(fs->fs_version);
|
||||
if (ping_len[fs->fs_version - NFS_VERSION] == 0)
|
||||
create_ping_payload(fs->fs_version);
|
||||
|
||||
/*
|
||||
* Queue the packet...
|
||||
*/
|
||||
error = fwd_packet(MK_RPC_XID(RPC_XID_NFSPING, np->np_xid),
|
||||
(voidp) ping_buf,
|
||||
ping_len,
|
||||
ping_buf[fs->fs_version - NFS_VERSION],
|
||||
ping_len[fs->fs_version - NFS_VERSION],
|
||||
fs->fs_ip,
|
||||
(struct sockaddr_in *) 0,
|
||||
(voidp) ((long) np->np_xid), /* for 64-bit archs */
|
||||
nfs_pinged);
|
||||
(voidp) ((long) np->np_xid), /* cast needed for 64-bit archs */
|
||||
nfs_keepalive_callback);
|
||||
|
||||
/*
|
||||
* See if a hard error occurred
|
||||
|
|
@ -517,7 +592,7 @@ nfs_keepalive(voidp v)
|
|||
np->np_ping = MAX_ALLOWED_PINGS; /* immediately down */
|
||||
np->np_ttl = (time_t) 0;
|
||||
/*
|
||||
* This causes an immediate call to nfs_timed_out
|
||||
* This causes an immediate call to nfs_keepalive_timeout
|
||||
* whenever the server was thought to be up.
|
||||
* See +++ below.
|
||||
*/
|
||||
|
|
@ -525,15 +600,13 @@ nfs_keepalive(voidp v)
|
|||
break;
|
||||
|
||||
case 0:
|
||||
#ifdef DEBUG
|
||||
dlog("Sent NFS ping to %s", fs->fs_host);
|
||||
#endif /* DEBUG */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Back off the ping interval if we are not getting replies and
|
||||
* the remote system is know to be down.
|
||||
* the remote system is known to be down.
|
||||
*/
|
||||
switch (fs->fs_flags & (FSF_DOWN | FSF_VALID)) {
|
||||
case FSF_VALID: /* Up */
|
||||
|
|
@ -550,73 +623,41 @@ nfs_keepalive(voidp v)
|
|||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
dlog("NFS timeout in %d seconds", fstimeo);
|
||||
#endif /* DEBUG */
|
||||
|
||||
fs->fs_cid = timeout(fstimeo, nfs_timed_out, (voidp) fs);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_srvr_port(fserver *fs, u_short *port, voidp wchan)
|
||||
{
|
||||
int error = -1;
|
||||
if ((fs->fs_flags & FSF_VALID) == FSF_VALID) {
|
||||
if ((fs->fs_flags & FSF_DOWN) == 0) {
|
||||
nfs_private *np = (nfs_private *) fs->fs_private;
|
||||
if (np->np_error == 0) {
|
||||
*port = np->np_mountd;
|
||||
error = 0;
|
||||
} else {
|
||||
error = np->np_error;
|
||||
}
|
||||
/*
|
||||
* Now go get the port mapping again in case it changed.
|
||||
* Note that it is used even if (np_mountd_inval)
|
||||
* is True. The flag is used simply as an
|
||||
* indication that the mountd may be invalid, not
|
||||
* that it is known to be invalid.
|
||||
*/
|
||||
if (np->np_mountd_inval)
|
||||
recompute_portmap(fs);
|
||||
else
|
||||
np->np_mountd_inval = TRUE;
|
||||
} else {
|
||||
error = EWOULDBLOCK;
|
||||
}
|
||||
}
|
||||
if (error < 0 && wchan && !(fs->fs_flags & FSF_WANT)) {
|
||||
/*
|
||||
* If a wait channel is supplied, and no
|
||||
* error has yet occurred, then arrange
|
||||
* that a wakeup is done on the wait channel,
|
||||
* whenever a wakeup is done on this fs node.
|
||||
* Wakeup's are done on the fs node whenever
|
||||
* it changes state - thus causing control to
|
||||
* come back here and new, better things to happen.
|
||||
*/
|
||||
fs->fs_flags |= FSF_WANT;
|
||||
sched_task(wakeup_task, wchan, (voidp) fs);
|
||||
}
|
||||
return error;
|
||||
fs->fs_cid = timeout(fstimeo, nfs_keepalive_timeout, (voidp) fs);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
start_nfs_pings(fserver *fs, int pingval)
|
||||
{
|
||||
if (fs->fs_flags & FSF_PINGING) {
|
||||
#ifdef DEBUG
|
||||
dlog("Already running pings to %s", fs->fs_host);
|
||||
#endif /* DEBUG */
|
||||
if (pingval == 0) /* could be because ping mnt option not found */
|
||||
pingval = AM_PINGER;
|
||||
/* if pings haven't been initalized, then init them for first time */
|
||||
if (fs->fs_flags & FSF_PING_UNINIT) {
|
||||
fs->fs_flags &= ~FSF_PING_UNINIT;
|
||||
plog(XLOG_INFO, "initializing %s's pinger to %d sec", fs->fs_host, pingval);
|
||||
goto do_pings;
|
||||
}
|
||||
|
||||
if ((fs->fs_flags & FSF_PINGING) && fs->fs_pinger == pingval) {
|
||||
dlog("already running pings to %s", fs->fs_host);
|
||||
return;
|
||||
}
|
||||
|
||||
/* if got here, then we need to update the ping value */
|
||||
plog(XLOG_INFO, "changing %s's ping value from %d%s to %d%s",
|
||||
fs->fs_host,
|
||||
fs->fs_pinger, (fs->fs_pinger < 0 ? " (off)" : ""),
|
||||
pingval, (pingval < 0 ? " (off)" : ""));
|
||||
do_pings:
|
||||
fs->fs_pinger = pingval;
|
||||
|
||||
if (fs->fs_cid)
|
||||
untimeout(fs->fs_cid);
|
||||
if (pingval < 0) {
|
||||
srvrlog(fs, "wired up");
|
||||
srvrlog(fs, "wired up (pings disabled)");
|
||||
fs->fs_flags |= FSF_VALID;
|
||||
fs->fs_flags &= ~FSF_DOWN;
|
||||
} else {
|
||||
|
|
@ -633,17 +674,18 @@ fserver *
|
|||
find_nfs_srvr(mntfs *mf)
|
||||
{
|
||||
char *host = mf->mf_fo->opt_rhost;
|
||||
char *nfs_proto = NULL;
|
||||
fserver *fs;
|
||||
int pingval;
|
||||
mntent_t mnt;
|
||||
nfs_private *np;
|
||||
struct hostent *hp = 0;
|
||||
struct sockaddr_in *ip;
|
||||
struct hostent *hp = NULL;
|
||||
struct sockaddr_in *ip = NULL;
|
||||
u_long nfs_version = 0; /* default is no version specified */
|
||||
#ifdef MNTTAB_OPT_PROTO
|
||||
char *rfsname = mf->mf_fo->opt_rfs;
|
||||
#endif /* MNTTAB_OPT_PROTO */
|
||||
u_long best_nfs_version = 0;
|
||||
char *nfs_proto = NULL; /* no IP protocol either */
|
||||
int nfs_port = 0;
|
||||
int nfs_port_opt = 0;
|
||||
int fserver_is_down = 0;
|
||||
|
||||
/*
|
||||
* Get ping interval from mount options.
|
||||
|
|
@ -653,49 +695,60 @@ find_nfs_srvr(mntfs *mf)
|
|||
mnt.mnt_opts = mf->mf_mopts;
|
||||
pingval = hasmntval(&mnt, "ping");
|
||||
|
||||
/*
|
||||
* Get the NFS version from the mount options. This is used
|
||||
* to decide the highest NFS version to try.
|
||||
*/
|
||||
if (mf->mf_flags & MFF_NFS_SCALEDOWN) {
|
||||
/*
|
||||
* the server granted us a filehandle, but we were unable to mount it.
|
||||
* therefore, scale down to NFSv2/UDP and try again.
|
||||
*/
|
||||
nfs_version = NFS_VERSION;
|
||||
nfs_proto = "udp";
|
||||
plog(XLOG_WARNING, "find_nfs_srvr: NFS mount failed, trying again with NFSv2/UDP");
|
||||
mf->mf_flags &= ~MFF_NFS_SCALEDOWN;
|
||||
} else {
|
||||
/*
|
||||
* Get the NFS version from the mount options. This is used
|
||||
* to decide the highest NFS version to try.
|
||||
*/
|
||||
#ifdef MNTTAB_OPT_VERS
|
||||
nfs_version = hasmntval(&mnt, MNTTAB_OPT_VERS);
|
||||
nfs_version = hasmntval(&mnt, MNTTAB_OPT_VERS);
|
||||
#endif /* MNTTAB_OPT_VERS */
|
||||
|
||||
#ifdef MNTTAB_OPT_PROTO
|
||||
{
|
||||
char *proto_opt = hasmnteq(&mnt, MNTTAB_OPT_PROTO);
|
||||
if (proto_opt) {
|
||||
char **p;
|
||||
for (p = protocols; *p; p ++)
|
||||
if (NSTREQ(proto_opt, *p, strlen(*p))) {
|
||||
nfs_proto = *p;
|
||||
break;
|
||||
}
|
||||
if (*p == NULL)
|
||||
plog(XLOG_WARNING, "ignoring unknown protocol option for %s:%s",
|
||||
host, rfsname);
|
||||
{
|
||||
char *proto_opt = hasmnteq(&mnt, MNTTAB_OPT_PROTO);
|
||||
if (proto_opt) {
|
||||
char **p;
|
||||
for (p = protocols; *p; p++)
|
||||
if (NSTREQ(proto_opt, *p, strlen(*p))) {
|
||||
nfs_proto = *p;
|
||||
break;
|
||||
}
|
||||
if (*p == NULL)
|
||||
plog(XLOG_WARNING, "ignoring unknown protocol option for %s:%s",
|
||||
host, mf->mf_fo->opt_rfs);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* MNTTAB_OPT_PROTO */
|
||||
|
||||
#ifdef HAVE_NFS_NFSV2_H
|
||||
/* allow overriding if nfsv2 option is specified in mount options */
|
||||
if (hasmntopt(&mnt, "nfsv2")) {
|
||||
nfs_version = (u_long) 2; /* nullify any ``vers=X'' statements */
|
||||
nfs_proto = "udp"; /* nullify any ``proto=tcp'' statements */
|
||||
plog(XLOG_WARNING, "found compatiblity option \"nfsv2\": set options vers=2,proto=udp for host %s", host);
|
||||
}
|
||||
/* allow overriding if nfsv2 option is specified in mount options */
|
||||
if (amu_hasmntopt(&mnt, "nfsv2")) {
|
||||
nfs_version = NFS_VERSION;/* nullify any ``vers=X'' statements */
|
||||
nfs_proto = "udp"; /* nullify any ``proto=tcp'' statements */
|
||||
plog(XLOG_WARNING, "found compatibility option \"nfsv2\": set options vers=2,proto=udp for host %s", host);
|
||||
}
|
||||
#endif /* HAVE_NFS_NFSV2_H */
|
||||
|
||||
/* check if we globally overridden the NFS version/protocol */
|
||||
if (gopt.nfs_vers) {
|
||||
nfs_version = gopt.nfs_vers;
|
||||
plog(XLOG_INFO, "find_nfs_srvr: force NFS version to %d",
|
||||
(int) nfs_version);
|
||||
}
|
||||
if (gopt.nfs_proto) {
|
||||
nfs_proto = gopt.nfs_proto;
|
||||
plog(XLOG_INFO, "find_nfs_srvr: force NFS protocol transport to %s", nfs_proto);
|
||||
/* check if we've globally overridden the NFS version/protocol */
|
||||
if (gopt.nfs_vers) {
|
||||
nfs_version = gopt.nfs_vers;
|
||||
plog(XLOG_INFO, "find_nfs_srvr: force NFS version to %d",
|
||||
(int) nfs_version);
|
||||
}
|
||||
if (gopt.nfs_proto) {
|
||||
nfs_proto = gopt.nfs_proto;
|
||||
plog(XLOG_INFO, "find_nfs_srvr: force NFS protocol transport to %s", nfs_proto);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -718,72 +771,148 @@ find_nfs_srvr(mntfs *mf)
|
|||
case AF_INET:
|
||||
ip = ALLOC(struct sockaddr_in);
|
||||
memset((voidp) ip, 0, sizeof(*ip));
|
||||
/* as per POSIX, sin_len need not be set (used internally by kernel) */
|
||||
ip->sin_family = AF_INET;
|
||||
memmove((voidp) &ip->sin_addr, (voidp) hp->h_addr, sizeof(ip->sin_addr));
|
||||
|
||||
ip->sin_port = htons(NFS_PORT);
|
||||
break;
|
||||
|
||||
default:
|
||||
ip = 0;
|
||||
break;
|
||||
plog(XLOG_USER, "No IP address for host %s", host);
|
||||
goto no_dns;
|
||||
}
|
||||
} else {
|
||||
plog(XLOG_USER, "Unknown host: %s", host);
|
||||
ip = 0;
|
||||
goto no_dns;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the NFS Version, and verify server is up. Probably no
|
||||
* longer need to start server down below.
|
||||
* This may not be the best way to do things, but it really doesn't make
|
||||
* sense to query a file server which is marked as 'down' for any
|
||||
* version/proto combination.
|
||||
*/
|
||||
if (ip) {
|
||||
ITER(fs, fserver, &nfs_srvr_list) {
|
||||
if (FSRV_ISDOWN(fs) &&
|
||||
STREQ(host, fs->fs_host)) {
|
||||
plog(XLOG_WARNING, "fileserver %s is already hung - not running NFS proto/version discovery", host);
|
||||
fs->fs_refc++;
|
||||
if (ip)
|
||||
XFREE(ip);
|
||||
return fs;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the NFS Version, and verify server is up.
|
||||
* If the client only supports NFSv2, hardcode it but still try to
|
||||
* contact the remote portmapper to see if the service is running.
|
||||
*/
|
||||
#ifndef HAVE_FS_NFS3
|
||||
nfs_version = NFS_VERSION;
|
||||
nfs_proto = "udp";
|
||||
plog(XLOG_INFO, "The client supports only NFS(2,udp)");
|
||||
#endif /* not HAVE_FS_NFS3 */
|
||||
|
||||
|
||||
if (amu_hasmntopt(&mnt, MNTTAB_OPT_PUBLIC)) {
|
||||
/*
|
||||
* Use WebNFS to obtain file handles.
|
||||
*/
|
||||
mf->mf_flags |= MFF_WEBNFS;
|
||||
plog(XLOG_INFO, "%s option used, NOT contacting the portmapper on %s",
|
||||
MNTTAB_OPT_PUBLIC, host);
|
||||
/*
|
||||
* Prefer NFSv3/tcp if the client supports it (cf. RFC 2054, 7).
|
||||
*/
|
||||
if (!nfs_version) {
|
||||
#ifdef HAVE_FS_NFS3
|
||||
nfs_version = NFS_VERSION3;
|
||||
#else /* not HAVE_FS_NFS3 */
|
||||
nfs_version = NFS_VERSION;
|
||||
#endif /* not HAVE_FS_NFS3 */
|
||||
plog(XLOG_INFO, "No NFS version specified, will use NFSv%d",
|
||||
(int) nfs_version);
|
||||
}
|
||||
if (!nfs_proto) {
|
||||
#if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3)
|
||||
nfs_proto = "tcp";
|
||||
#else /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
|
||||
nfs_proto = "udp";
|
||||
#endif /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
|
||||
plog(XLOG_INFO, "No NFS protocol transport specified, will use %s",
|
||||
nfs_proto);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Find the best combination of NFS version and protocol.
|
||||
* When given a choice, use the highest available version,
|
||||
* and use TCP over UDP if available.
|
||||
*/
|
||||
if (nfs_proto)
|
||||
nfs_version = get_nfs_version(host, ip, nfs_version, nfs_proto);
|
||||
else {
|
||||
int best_nfs_version = 0;
|
||||
int proto_nfs_version;
|
||||
char **p;
|
||||
if (check_pmap_up(host, ip)) {
|
||||
if (nfs_proto) {
|
||||
best_nfs_version = get_nfs_version(host, ip, nfs_version, nfs_proto);
|
||||
nfs_port = ip->sin_port;
|
||||
}
|
||||
#ifdef MNTTAB_OPT_PROTO
|
||||
else {
|
||||
u_int proto_nfs_version;
|
||||
char **p;
|
||||
|
||||
for (p = protocols; *p; p++) {
|
||||
proto_nfs_version = get_nfs_version(host, ip, nfs_version, *p);
|
||||
for (p = protocols; *p; p++) {
|
||||
proto_nfs_version = get_nfs_version(host, ip, nfs_version, *p);
|
||||
|
||||
if (proto_nfs_version > best_nfs_version) {
|
||||
best_nfs_version = proto_nfs_version;
|
||||
nfs_proto = *p;
|
||||
if (proto_nfs_version > best_nfs_version) {
|
||||
best_nfs_version = proto_nfs_version;
|
||||
nfs_proto = *p;
|
||||
nfs_port = ip->sin_port;
|
||||
}
|
||||
}
|
||||
}
|
||||
nfs_version = best_nfs_version;
|
||||
#endif /* MNTTAB_OPT_PROTO */
|
||||
} else {
|
||||
plog(XLOG_INFO, "portmapper service not running on %s", host);
|
||||
}
|
||||
|
||||
if (!nfs_version) {
|
||||
/* use the portmapper results only nfs_version is not set yet */
|
||||
if (!best_nfs_version) {
|
||||
/*
|
||||
* If the NFS server is down or does not support the portmapper call
|
||||
* (such as certain Novell NFS servers) we mark it as version 2 and we
|
||||
* let the nfs code deal with the case that is down. If when the
|
||||
* server comes back up, it can support NFS V.3 and/or TCP, it will
|
||||
* let the nfs code deal with the case when it is down. If/when the
|
||||
* server comes back up and it can support NFSv3 and/or TCP, it will
|
||||
* use those.
|
||||
*/
|
||||
nfs_version = NFS_VERSION;
|
||||
nfs_proto = "udp";
|
||||
if (nfs_version == 0) {
|
||||
nfs_version = NFS_VERSION;
|
||||
nfs_proto = "udp";
|
||||
}
|
||||
plog(XLOG_INFO, "NFS service not running on %s", host);
|
||||
fserver_is_down = 1;
|
||||
} else {
|
||||
if (nfs_version == 0)
|
||||
nfs_version = best_nfs_version;
|
||||
plog(XLOG_INFO, "Using NFS version %d, protocol %s on host %s",
|
||||
(int) nfs_version, nfs_proto, host);
|
||||
}
|
||||
#else /* not HAVE_FS_NFS3 */
|
||||
nfs_version = NFS_VERSION;
|
||||
#endif /* not HAVE_FS_NFS3 */
|
||||
}
|
||||
|
||||
if (!nfs_proto)
|
||||
nfs_proto = "udp";
|
||||
/*
|
||||
* Determine the NFS port.
|
||||
*
|
||||
* A valid "port" mount option overrides anything else.
|
||||
* If the port has been determined from the portmapper, use that.
|
||||
* Default to NFS_PORT otherwise (cf. RFC 2054, 3).
|
||||
*/
|
||||
nfs_port_opt = hasmntval(&mnt, MNTTAB_OPT_PORT);
|
||||
if (nfs_port_opt > 0)
|
||||
nfs_port = htons(nfs_port_opt);
|
||||
if (!nfs_port)
|
||||
nfs_port = htons(NFS_PORT);
|
||||
|
||||
plog(XLOG_INFO, "Using NFS version %d, protocol %s on host %s",
|
||||
(int) nfs_version, nfs_proto, host);
|
||||
dlog("find_nfs_srvr: using port %d for nfs on %s",
|
||||
(int) ntohs(nfs_port), host);
|
||||
ip->sin_port = nfs_port;
|
||||
|
||||
no_dns:
|
||||
/*
|
||||
* Try to find an existing fs server structure for this host.
|
||||
* Note that differing versions or protocols have their own structures.
|
||||
|
|
@ -795,16 +924,46 @@ find_nfs_srvr(mntfs *mf)
|
|||
nfs_version == fs->fs_version &&
|
||||
STREQ(nfs_proto, fs->fs_proto)) {
|
||||
/*
|
||||
* following if statement from Mike Mitchell
|
||||
* <mcm@unx.sas.com>
|
||||
* Initialize the ping data if we aren't pinging
|
||||
* now. The np_ttl and np_ping fields are
|
||||
* especially important.
|
||||
* fill in the IP address -- this is only needed
|
||||
* if there is a chance an IP address will change
|
||||
* between mounts.
|
||||
* Mike Mitchell, mcm@unx.sas.com, 09/08/93
|
||||
*/
|
||||
if (hp && fs->fs_ip &&
|
||||
memcmp((voidp) &fs->fs_ip->sin_addr,
|
||||
(voidp) hp->h_addr,
|
||||
sizeof(fs->fs_ip->sin_addr)) != 0) {
|
||||
struct in_addr ia;
|
||||
char *old_ipaddr, *new_ipaddr;
|
||||
old_ipaddr = strdup(inet_ntoa(fs->fs_ip->sin_addr));
|
||||
memmove((voidp) &ia, (voidp) hp->h_addr, sizeof(struct in_addr));
|
||||
new_ipaddr = inet_ntoa(ia); /* ntoa uses static buf */
|
||||
plog(XLOG_WARNING, "fileserver %s changed ip: %s -> %s",
|
||||
fs->fs_host, old_ipaddr, new_ipaddr);
|
||||
XFREE(old_ipaddr);
|
||||
flush_nfs_fhandle_cache(fs);
|
||||
memmove((voidp) &fs->fs_ip->sin_addr, (voidp) hp->h_addr, sizeof(fs->fs_ip->sin_addr));
|
||||
}
|
||||
|
||||
/*
|
||||
* If the new file systems doesn't use WebNFS, the nfs pings may
|
||||
* try to contact the portmapper.
|
||||
*/
|
||||
if (!(mf->mf_flags & MFF_WEBNFS))
|
||||
fs->fs_flags &= ~FSF_WEBNFS;
|
||||
|
||||
/* check if pingval needs to be updated/set/reset */
|
||||
start_nfs_pings(fs, pingval);
|
||||
|
||||
/*
|
||||
* Following if statement from Mike Mitchell <mcm@unx.sas.com>
|
||||
* Initialize the ping data if we aren't pinging now. The np_ttl and
|
||||
* np_ping fields are especially important.
|
||||
*/
|
||||
if (!(fs->fs_flags & FSF_PINGING)) {
|
||||
np = (nfs_private *) fs->fs_private;
|
||||
np->np_mountd_inval = TRUE;
|
||||
np->np_xid = NPXID_ALLOC(struct );
|
||||
np->np_xid = XID_ALLOC();
|
||||
np->np_error = -1;
|
||||
np->np_ping = 0;
|
||||
/*
|
||||
|
|
@ -812,18 +971,12 @@ find_nfs_srvr(mntfs *mf)
|
|||
* after MAX_ALLOWED_PINGS of the fast variety
|
||||
* have failed.
|
||||
*/
|
||||
np->np_ttl = MAX_ALLOWED_PINGS * FAST_NFS_PING + clocktime() - 1;
|
||||
np->np_ttl = MAX_ALLOWED_PINGS * FAST_NFS_PING + clocktime(NULL) - 1;
|
||||
start_nfs_pings(fs, pingval);
|
||||
if (fserver_is_down)
|
||||
fs->fs_flags |= FSF_VALID | FSF_DOWN;
|
||||
}
|
||||
/*
|
||||
* fill in the IP address -- this is only needed
|
||||
* if there is a chance an IP address will change
|
||||
* between mounts.
|
||||
* Mike Mitchell, mcm@unx.sas.com, 09/08/93
|
||||
*/
|
||||
if (hp && fs->fs_ip)
|
||||
memmove((voidp) &fs->fs_ip->sin_addr, (voidp) hp->h_addr, sizeof(fs->fs_ip->sin_addr));
|
||||
|
||||
start_nfs_pings(fs, pingval);
|
||||
fs->fs_refc++;
|
||||
if (ip)
|
||||
XFREE(ip);
|
||||
|
|
@ -852,29 +1005,32 @@ find_nfs_srvr(mntfs *mf)
|
|||
mf->mf_flags |= MFF_ERROR;
|
||||
mf->mf_error = ENOENT;
|
||||
}
|
||||
if (mf->mf_flags & MFF_WEBNFS)
|
||||
fs->fs_flags |= FSF_WEBNFS;
|
||||
fs->fs_version = nfs_version;
|
||||
fs->fs_proto = nfs_proto;
|
||||
fs->fs_type = MNTTAB_TYPE_NFS;
|
||||
fs->fs_pinger = AM_PINGER;
|
||||
fs->fs_flags |= FSF_PING_UNINIT; /* pinger hasn't been initialized */
|
||||
np = ALLOC(struct nfs_private);
|
||||
memset((voidp) np, 0, sizeof(*np));
|
||||
np->np_mountd_inval = TRUE;
|
||||
np->np_xid = NPXID_ALLOC(struct );
|
||||
np->np_xid = XID_ALLOC();
|
||||
np->np_error = -1;
|
||||
|
||||
/*
|
||||
* Initially the server will be deemed dead after
|
||||
* MAX_ALLOWED_PINGS of the fast variety have failed.
|
||||
*/
|
||||
np->np_ttl = clocktime() + MAX_ALLOWED_PINGS * FAST_NFS_PING - 1;
|
||||
np->np_ttl = clocktime(NULL) + MAX_ALLOWED_PINGS * FAST_NFS_PING - 1;
|
||||
fs->fs_private = (voidp) np;
|
||||
fs->fs_prfree = (void (*)(voidp)) free;
|
||||
|
||||
if (!(fs->fs_flags & FSF_ERROR)) {
|
||||
/*
|
||||
* Start of keepalive timer
|
||||
*/
|
||||
if (!FSRV_ERROR(fs)) {
|
||||
/* start of keepalive timer, first updating pingval */
|
||||
start_nfs_pings(fs, pingval);
|
||||
if (fserver_is_down)
|
||||
fs->fs_flags |= FSF_VALID | FSF_DOWN;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
.\"
|
||||
.\" %W% (Berkeley) %G%
|
||||
.\"
|
||||
.\" $Id: amq.8,v 1.3.2.8 2004/01/06 03:15:16 ezk Exp $
|
||||
.\" $Id: amq.8,v 1.15.2.1 2006/01/02 18:48:24 ezk Exp $
|
||||
.\"
|
||||
.TH AMQ 8 "25 April 1989"
|
||||
.SH NAME
|
||||
|
|
@ -192,26 +192,70 @@ using UDP (connectionless) transport only. Normally
|
|||
will try TCP, and if that failed, will try UDP.
|
||||
|
||||
.SH FILES
|
||||
.PD 0
|
||||
.TP 20
|
||||
.B amq.x
|
||||
.SM RPC
|
||||
protocol description.
|
||||
|
||||
.SH CAVEATS
|
||||
.B Amq
|
||||
uses a Sun registered
|
||||
.SM RPC
|
||||
program number (300019 decimal) which may not
|
||||
be in the /etc/rpc database.
|
||||
.PP
|
||||
If the TCP wrappers library is available, and the
|
||||
.B use_tcpwrappers
|
||||
global
|
||||
.B amd.conf
|
||||
option is set to ``yes'', then
|
||||
.B amd
|
||||
will verify that the host running
|
||||
.B amq
|
||||
is authorized to connect. The
|
||||
.I amd
|
||||
service name must used in the
|
||||
.B /etc/hosts.allow
|
||||
and
|
||||
.B /etc/hosts.deny
|
||||
files. For example, to allow only localhost to connect to
|
||||
.B amd,
|
||||
add this line to
|
||||
.B /etc/hosts.allow:
|
||||
.PP
|
||||
.RS
|
||||
amd: localhost
|
||||
.RE
|
||||
.PP
|
||||
and this line to
|
||||
.B /etc/hosts.deny:
|
||||
.PP
|
||||
.RS
|
||||
amd: ALL
|
||||
.RE
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR amd (8),
|
||||
.BR ctl-amd (8),
|
||||
.BR amd.conf (5).
|
||||
.BR amd.conf (5),
|
||||
.BR hosts_access (5).
|
||||
.LP
|
||||
``am-utils''
|
||||
.BR info (1)
|
||||
entry.
|
||||
.LP
|
||||
.I "Linux NFS and Automounter Administration"
|
||||
by Erez Zadok, ISBN 0-7821-2739-8, (Sybex, 2001).
|
||||
.LP
|
||||
.I http://www.am-utils.org
|
||||
.LP
|
||||
.I "Amd \- The 4.4 BSD Automounter"
|
||||
|
||||
.SH AUTHORS
|
||||
Jan-Simon Pendry <jsp@doc.ic.ac.uk>, Department of Computing, Imperial College, London, UK.
|
||||
.P
|
||||
Erez Zadok <ezk@cs.columbia.edu>, Department of Computer Science, Columbia
|
||||
University, New York, USA.
|
||||
Erez Zadok <ezk@cs.sunysb.edu>, Computer Science Department, Stony Brook
|
||||
University, Stony Brook, New York, USA.
|
||||
.P
|
||||
Other authors and contributors to am-utils are listed in the
|
||||
.B AUTHORS
|
||||
|
|
|
|||
|
|
@ -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.c,v 1.7.2.9 2004/01/06 03:15:16 ezk Exp $
|
||||
* File: am-utils/amq/amq.c
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -46,19 +45,6 @@
|
|||
* Automounter query tool
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
char copyright[] = "\
|
||||
@(#)Copyright (c) 1997-2004 Erez Zadok\n\
|
||||
@(#)Copyright (c) 1990 Jan-Simon Pendry\n\
|
||||
@(#)Copyright (c) 1990 Imperial College of Science, Technology & Medicine\n\
|
||||
@(#)Copyright (c) 1990 The Regents of the University of California.\n\
|
||||
@(#)All rights reserved.\n";
|
||||
#if __GNUC__ < 2
|
||||
static char rcsid[] = "$Id: amq.c,v 1.7.2.9 2004/01/06 03:15:16 ezk Exp $";
|
||||
static char sccsid[] = "%W% (Berkeley) %G%";
|
||||
#endif /* __GNUC__ < 2 */
|
||||
#endif /* not lint */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
|
@ -115,8 +101,8 @@ show_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid)
|
|||
|
||||
case Full:
|
||||
{
|
||||
struct tm *tp = localtime((time_t *) &mt->mt_mounttime);
|
||||
printf("%-*.*s %-*.*s %-*.*s %s\n\t%-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%02d\n",
|
||||
struct tm *tp = localtime((time_t *) ((voidp) &mt->mt_mounttime));
|
||||
printf("%-*.*s %-*.*s %-*.*s %s\n\t%-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%04d %02d:%02d:%02d\n",
|
||||
*dwid, *dwid,
|
||||
*mt->mt_directory ? mt->mt_directory : "/", /* XXX */
|
||||
*twid, *twid,
|
||||
|
|
@ -132,16 +118,16 @@ show_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid)
|
|||
mt->mt_readlink,
|
||||
mt->mt_statfs,
|
||||
|
||||
tp->tm_year > 99 ? tp->tm_year - 100 : tp->tm_year,
|
||||
tp->tm_mon + 1, tp->tm_mday,
|
||||
tp->tm_year < 1900 ? tp->tm_year + 1900 : tp->tm_year,
|
||||
tp->tm_hour, tp->tm_min, tp->tm_sec);
|
||||
}
|
||||
break;
|
||||
|
||||
case Stats:
|
||||
{
|
||||
struct tm *tp = localtime((time_t *) &mt->mt_mounttime);
|
||||
printf("%-*.*s %-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%02d\n",
|
||||
struct tm *tp = localtime((time_t *) ((voidp) &mt->mt_mounttime));
|
||||
printf("%-*.*s %-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%04d\n",
|
||||
*dwid, *dwid,
|
||||
*mt->mt_directory ? mt->mt_directory : "/", /* XXX */
|
||||
|
||||
|
|
@ -152,8 +138,8 @@ show_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid)
|
|||
mt->mt_readlink,
|
||||
mt->mt_statfs,
|
||||
|
||||
tp->tm_year > 99 ? tp->tm_year - 100 : tp->tm_year,
|
||||
tp->tm_mon + 1, tp->tm_mday,
|
||||
tp->tm_year < 1900 ? tp->tm_year + 1900 : tp->tm_year,
|
||||
tp->tm_hour, tp->tm_min, tp->tm_sec);
|
||||
}
|
||||
break;
|
||||
|
|
@ -181,7 +167,7 @@ show_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid)
|
|||
* Display a pwd data
|
||||
*/
|
||||
static void
|
||||
show_pwd(amq_mount_tree *mt, char *path, int *flag)
|
||||
show_pwd(amq_mount_tree *mt, char *path, size_t l, int *flag)
|
||||
{
|
||||
int len;
|
||||
|
||||
|
|
@ -189,13 +175,13 @@ show_pwd(amq_mount_tree *mt, char *path, int *flag)
|
|||
len = strlen(mt->mt_mountpoint);
|
||||
if (NSTREQ(path, mt->mt_mountpoint, len) &&
|
||||
!STREQ(mt->mt_directory, mt->mt_mountpoint)) {
|
||||
char buf[MAXPATHLEN+1];
|
||||
strcpy(buf, mt->mt_directory);
|
||||
strcat(buf, &path[len]);
|
||||
strcpy(path, buf);
|
||||
char buf[MAXPATHLEN+1]; /* must be same size as 'path' */
|
||||
xstrlcpy(buf, mt->mt_directory, sizeof(buf));
|
||||
xstrlcat(buf, &path[len], sizeof(buf));
|
||||
xstrlcpy(path, buf, l);
|
||||
*flag = 1;
|
||||
}
|
||||
show_pwd(mt->mt_next, path, flag);
|
||||
show_pwd(mt->mt_next, path, l, flag);
|
||||
mt = mt->mt_child;
|
||||
}
|
||||
}
|
||||
|
|
@ -218,7 +204,7 @@ show_mt(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *pwid)
|
|||
static void
|
||||
show_mi(amq_mount_info_list *ml, enum show_opt e, int *mwid, int *dwid, int *twid)
|
||||
{
|
||||
int i;
|
||||
u_int i;
|
||||
|
||||
switch (e) {
|
||||
|
||||
|
|
@ -448,7 +434,8 @@ Usage: %s [-fmpsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\
|
|||
am_get_progname(), server);
|
||||
exit(1);
|
||||
}
|
||||
memset(&server_addr, 0, sizeof server_addr);
|
||||
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;
|
||||
if (hp) {
|
||||
memmove((voidp) &server_addr.sin_addr, (voidp) hp->h_addr,
|
||||
|
|
@ -554,7 +541,8 @@ Usage: %s [-fmpsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\
|
|||
char *wd = getcwd(path, MAXPATHLEN+1);
|
||||
amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt);
|
||||
amq_mount_tree_p mt;
|
||||
int i, flag;
|
||||
u_int i;
|
||||
int flag;
|
||||
|
||||
if (!wd) {
|
||||
perror("getcwd");
|
||||
|
|
@ -564,7 +552,7 @@ Usage: %s [-fmpsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\
|
|||
mt = mlp->amq_mount_tree_list_val[i];
|
||||
while (1) {
|
||||
flag = 0;
|
||||
show_pwd(mt, path, &flag);
|
||||
show_pwd(mt, path, sizeof(path), &flag);
|
||||
if (!flag) {
|
||||
printf("%s\n", path);
|
||||
break;
|
||||
|
|
@ -678,8 +666,9 @@ Usage: %s [-fmpsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\
|
|||
if (mlp) {
|
||||
enum show_opt e = Calc;
|
||||
int mwid = 0, dwid = 0, pwid = 0;
|
||||
|
||||
while (e != ShowDone) {
|
||||
int i;
|
||||
u_int i;
|
||||
for (i = 0; i < mlp->amq_mount_tree_list_len; i++) {
|
||||
show_mt(mlp->amq_mount_tree_list_val[i],
|
||||
e, &mwid, &dwid, &pwid);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
.\"
|
||||
.\" %W% (Berkeley) %G%
|
||||
.\"
|
||||
.\" $Id: pawd.1,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
|
||||
.\" $Id: pawd.1,v 1.9.2.1 2006/01/02 18:48:24 ezk Exp $
|
||||
.\"
|
||||
.TH PAWD 1 "6 Jan 1998"
|
||||
.SH NAME
|
||||
|
|
@ -70,3 +70,21 @@ arguments.
|
|||
.BR amd (8),
|
||||
.BR amq (8),
|
||||
.BR pwd (1).
|
||||
.LP
|
||||
``am-utils''
|
||||
.BR info (1)
|
||||
entry.
|
||||
.LP
|
||||
.I "Linux NFS and Automounter Administration"
|
||||
by Erez Zadok, ISBN 0-7821-2739-8, (Sybex, 2001).
|
||||
.LP
|
||||
.I http://www.am-utils.org
|
||||
.LP
|
||||
.I "Amd \- The 4.4 BSD Automounter"
|
||||
.SH AUTHORS
|
||||
Erez Zadok <ezk@cs.sunysb.edu>, Computer Science Department, Stony Brook
|
||||
University, Stony Brook, New York, USA.
|
||||
.P
|
||||
Other authors and contributors to am-utils are listed in the
|
||||
.B AUTHORS
|
||||
file distributed with am-utils.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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..."
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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_prot_freebsd2.h,v 1.3.2.4 2004/01/06 03:15:19 ezk Exp $
|
||||
* File: am-utils/conf/nfs_prot/nfs_prot_freebsd2.h
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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_prot_freebsd3.h,v 1.5.2.7 2004/01/06 03:15:19 ezk Exp $
|
||||
* File: am-utils/conf/nfs_prot/nfs_prot_freebsd3.h
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -55,6 +54,13 @@
|
|||
# include <nfs/nfs.h>
|
||||
#endif /* HAVE_NFS_NFS_H */
|
||||
#ifdef HAVE_UFS_UFS_UFSMOUNT_H
|
||||
# ifdef HAVE_UFS_UFS_EXTATTR_H
|
||||
/*
|
||||
* Define a dummy struct ufs_extattr_per_mount, which is used in struct
|
||||
* ufsmount in <ufs/ufs/ufsmount.h>.
|
||||
*/
|
||||
struct ufs_extattr_per_mount;
|
||||
# endif /* HAVE_UFS_UFS_EXTATTR_H */
|
||||
# include <ufs/ufs/ufsmount.h>
|
||||
#endif /* HAVE_UFS_UFS_UFSMOUNT_H */
|
||||
|
||||
|
|
@ -166,22 +172,16 @@ typedef writeargs nfswriteargs;
|
|||
# define MOUNT_NFS3 "nfs" /* is this right? */
|
||||
# define MNTOPT_NFS3 "nfs"
|
||||
|
||||
# ifndef HAVE_XDR_LOOKUP3RES
|
||||
/*
|
||||
* as of 3.0-RELEASE the nfs_fh3 that is defined in the system headers
|
||||
* (or the one generated by rpcgen) lacks the proper full definition,
|
||||
* listed below. A special macro (m4/macros/struct_nfs_fh3.m4) searches
|
||||
* for this special name before other names.
|
||||
* FreeBSD uses different field names than are defined on most other
|
||||
* systems.
|
||||
*/
|
||||
struct nfs_fh3_freebsd3 {
|
||||
u_int fh3_length;
|
||||
union nfs_fh3_u {
|
||||
struct nfs_fh3_i {
|
||||
fhandle_t fh3_i;
|
||||
} nfs_fh3_i;
|
||||
char data[NFS3_FHSIZE];
|
||||
} fh3_u;
|
||||
};
|
||||
typedef struct nfs_fh3_freebsd3 nfs_fh3_freebsd3;
|
||||
# define AMU_LOOKUP3RES_OK(x) ((x)->LOOKUP3res_u.resok)
|
||||
# define AMU_LOOKUP3RES_FAIL(x) ((x)->LOOKUP3res_u.resfail)
|
||||
# define AMU_LOOKUP3RES_FH_LEN(x) (AMU_LOOKUP3RES_OK(x).object.data.data_len)
|
||||
# define AMU_LOOKUP3RES_FH_DATA(x) (AMU_LOOKUP3RES_OK(x).object.data.data_val)
|
||||
# endif /* not HAVE_XDR_LOOKUP3RES */
|
||||
|
||||
#endif /* NFSMNT_NFSV3 */
|
||||
|
||||
|
|
|
|||
|
|
@ -3,3 +3,4 @@
|
|||
(dst)->addr = (struct sockaddr *) (src); \
|
||||
(dst)->addrlen = sizeof(*src); \
|
||||
}
|
||||
#define NFS_ARGS_T_ADDR_IS_POINTER 1
|
||||
|
|
|
|||
|
|
@ -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 @@ try_again:
|
|||
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 */
|
||||
|
|
|
|||
|
|
@ -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 @@ eintr:
|
|||
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
|
|
@ -1,3 +1,4 @@
|
|||
@set UPDATED 3 July 2001
|
||||
@set EDITION 6.0.7
|
||||
@set VERSION 6.0.7
|
||||
@set UPDATED 20 April 2006
|
||||
@set UPDATED-MONTH April 2006
|
||||
@set EDITION 6.1.5
|
||||
@set VERSION 6.1.5
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
.\"
|
||||
.\" %W% (Berkeley) %G%
|
||||
.\"
|
||||
.\" $Id: fixmount.8,v 1.3.2.6 2004/01/06 03:15:23 ezk Exp $
|
||||
.\" $Id: fixmount.8,v 1.12.2.1 2006/01/02 18:48:25 ezk Exp $
|
||||
.\"
|
||||
.TH FIXMOUNT 8 "26 Feb 1993"
|
||||
.SH NAME
|
||||
|
|
@ -111,19 +111,28 @@ only.
|
|||
This option also saves time as comparisons of remotely recorded and local
|
||||
hostnames by address are avoided.
|
||||
.SH FILES
|
||||
.PD 0
|
||||
.TP 20
|
||||
.B /etc/mtab
|
||||
List of current mounts.
|
||||
.TP
|
||||
.B /etc/rmtab
|
||||
Backup file for remote mount entries on NFS server.
|
||||
.PD
|
||||
.SH "SEE ALSO"
|
||||
.BR showmount (8),
|
||||
.BR mtab (5),
|
||||
.BR rmtab (5),
|
||||
.BR mountd (8C).
|
||||
.LP
|
||||
``am-utils''
|
||||
.BR info (1)
|
||||
entry.
|
||||
.LP
|
||||
.I "Linux NFS and Automounter Administration"
|
||||
by Erez Zadok, ISBN 0-7821-2739-8, (Sybex, 2001).
|
||||
.LP
|
||||
.I http://www.am-utils.org
|
||||
.LP
|
||||
.I "Amd \- The 4.4 BSD Automounter"
|
||||
.SH BUGS
|
||||
No attempt is made to verify the information in
|
||||
.B /etc/mtab
|
||||
|
|
@ -157,3 +166,12 @@ the remote /etc/rmtab file has to be edited and mountd restarted.
|
|||
The RPC timeouts for mountd calls can only be changed by recompiling.
|
||||
The defaults are 2 seconds for client handle creation and 5 seconds for
|
||||
RPC calls.
|
||||
.SH AUTHORS
|
||||
Andreas Stolcke <stolcke@icsi.berkeley.edu>.
|
||||
.P
|
||||
Erez Zadok <ezk@cs.sunysb.edu>, Computer Science Department, Stony Brook
|
||||
University, Stony Brook, New York, USA.
|
||||
.P
|
||||
Other authors and contributors to am-utils are listed in the
|
||||
.B AUTHORS
|
||||
file distributed with am-utils.
|
||||
|
|
|
|||
|
|
@ -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: fixmount.c,v 1.5.2.4 2004/01/06 03:15:23 ezk Exp $
|
||||
* File: am-utils/fixmount/fixmount.c
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -50,10 +49,6 @@
|
|||
#define CREATE_TIMEOUT 2 /* seconds */
|
||||
#define CALL_TIMEOUT 5 /* seconds */
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
# define INADDR_NONE 0xffffffff
|
||||
#endif /* not INADDR_NONE */
|
||||
|
||||
/* Constant defs */
|
||||
#define ALL 1
|
||||
#define DIRS 2
|
||||
|
|
@ -120,7 +115,7 @@ is_same_host(char *name1, char *name2, struct in_addr addr2)
|
|||
} else if (!(he = gethostbyname(name1))) {
|
||||
return 0;
|
||||
} else {
|
||||
strncpy(lasthost, name1, sizeof(lasthost) - 1);
|
||||
xstrlcpy(lasthost, name1, MAXHOSTNAMELEN);
|
||||
memcpy(&addr1, he->h_addr, sizeof(addr1));
|
||||
return (addr1.s_addr == addr2.s_addr);
|
||||
}
|
||||
|
|
@ -164,7 +159,7 @@ remove_mount(CLIENT *client, char *host, mountlist ml, int fixit)
|
|||
struct timeval tv;
|
||||
char *pathp = dir_path;
|
||||
|
||||
strncpy(dir_path, ml->ml_directory, sizeof(dir_path));
|
||||
xstrlcpy(dir_path, ml->ml_directory, sizeof(dir_path));
|
||||
|
||||
if (!fixit) {
|
||||
printf("%s: bogus mount %s:%s\n", host, ml->ml_hostname, ml->ml_directory);
|
||||
|
|
@ -326,8 +321,7 @@ main(int argc, char *argv[])
|
|||
break;
|
||||
|
||||
case 'h':
|
||||
strncpy(thishost, optarg, sizeof(thishost));
|
||||
thishost[sizeof(thishost) - 1] = '\0';
|
||||
xstrlcpy(thishost, optarg, sizeof(thishost));
|
||||
break;
|
||||
|
||||
case '?':
|
||||
|
|
@ -367,8 +361,7 @@ main(int argc, char *argv[])
|
|||
inet_ntoa(thisaddr));
|
||||
exit(1);
|
||||
}
|
||||
strncpy(thishost, he->h_name, sizeof(thishost));
|
||||
thishost[sizeof(thishost) - 1] = '\0';
|
||||
xstrlcpy(thishost, he->h_name, sizeof(thishost));
|
||||
} else {
|
||||
thisaddr.s_addr = INADDR_NONE;
|
||||
}
|
||||
|
|
@ -497,8 +490,10 @@ inetresport(int ty)
|
|||
struct sockaddr_in addr;
|
||||
int fd;
|
||||
|
||||
/* Use internet address family */
|
||||
addr.sin_family = AF_INET;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
/* as per POSIX, sin_len need not be set (used internally by kernel) */
|
||||
|
||||
addr.sin_family = AF_INET; /* use internet address family */
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
if ((fd = socket(AF_INET, ty, 0)) < 0)
|
||||
return -1;
|
||||
|
|
@ -568,7 +563,8 @@ clnt_create_timeout(char *host, struct timeval *tvp)
|
|||
fprintf(stderr, "can't get address of %s\n", host);
|
||||
return NULL;
|
||||
}
|
||||
memset(&host_addr, 0, sizeof host_addr);
|
||||
memset(&host_addr, 0, sizeof(host_addr));
|
||||
/* as per POSIX, sin_len need not be set (used internally by kernel) */
|
||||
host_addr.sin_family = AF_INET;
|
||||
if (hp) {
|
||||
memmove((voidp) &host_addr.sin_addr, (voidp) hp->h_addr,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
%}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue