Virgin import of AMD (am-utils) v6.0a16

This commit is contained in:
obrien 1998-08-23 22:07:21 +00:00
commit 663d5a0f32
153 changed files with 63365 additions and 0 deletions

190
contrib/amd/AUTHORS Normal file
View File

@ -0,0 +1,190 @@
# -*- text -*-
PRIMARY AUTHORS AND MAJOR CONTRIBUTORS TO AM_UTILS:
Original authors of amd were the Berkeley team and especially Jan-Simon
Pendry. Since then many people have contributed patches.
This file lists the ones who contributed major code changes, in no
particular order, and I thank them all. This is of course not to diminish
the smaller contributes of the many others. Thank you all.
* Erez Zadok <ezk@cs.columbia.edu>
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.
There is a mailing list dedicated to developers of am-utils. To subscribe
to it, send mail to majordomo@majordomo.cs.columbia.edu, with the body of
the message having the single line "subscribe amd-dev".
* Randall S. Winchester <rsw@glue.umd.edu>
May 7, 1997: contributed a special version of upl102 that included NFS V.3
support. Some of the code was contributed by Christos Zoulas
<christos@deshaw.com>. I (Erez) ported these changes to am-utils.
September 12, 1997: lots of small prototype cleanups and fixes to numerous
files.
January 27, 1998: support pid files in the amd.conf file. Provide base name
for hesiod zone files. Always use /etc/amd.conf if exists.
* Hannes Reinecke <hare@MathI.UNI-Heidelberg.DE>
Back in 1995, contributed code for linux. A new parser for file system
specific options that only exist under linux.
* Leif Johansson <leifj@matematik.su.se>
June 22, 1997: minor patch to ensure that systems without an RE library work.
June 23, 1997: mount options should be properly comma limited.
July 10, 1997: info_ldap.c and prototype changes to all map _init and _mtime
functions. Contributed scripts/amd2ldif.pl.
August 4, 1997: info_ldap.c fixes and adding two new amd.conf ldap
variables: ldap_cache_seconds and ldap_cache_maxmem.
* Andreas Stolcke <stolcke@speech.sri.com>
June 22, 1997: patches to ensure that proto= and vers= options work
properly in mount tables and can be overridden. Later on, more code
contribued to optimize the best combination of proto/vers.
July 4, 1997: patches to get NFS V.3 working under irix5.
September 9, 1997: initialize all fields of mntent_t structures to 0.
October 2, 1997: don't log an RPC timeout as an error but only as an info
message.
December 19, 1997: detected an FMR (Free Memory Read) in amd/mntfs.c,
uninit_mntfs().
* Danny Braniss <danny@cs.huji.ac.il>
July, 6 1997: contributed patches to hesiod on bsdi3.
* Tom Schmidt <tschmidt@micron.com>
July 10, 1997: Recommdation to include libgdbm if libc has no dbm_open.
Patches for netgrp(host) command. Mods to aux/config.guess to recognize
sun3.
January 19, 1998: print correct -l option depending if system supports
syslog and/or syslog facilities.
January 29, 1998: fix for 0.0.0.0 loopback on SunOS 3.X which defines
IFF_ROUTE instead of IFF_LOOPBACK.
* Daniel S. Riley <dsr@mail.lns.cornell.edu>
July 11, 1997: fixes to DU-4.0 to support string POSIX.1 signals, and struct
sockaddr with sa_len field.
July 13, 1997: Move amd.conf parsing to before switch_option() on log/debug
options. Minor type wrt "ro" option in libamu/mount_fs.c. Added more
fillers of mnttab options, for acdirmax, acdirmin, acregmax, acregmin, noac,
grpid, nosuid, and actimo.
* Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
July 23, 1997: Got lots of patches from the Debian Linux folks, who fixed
several generic bugs, and one serious one for Linux. The latter involved
using connected sockets for NFS mounts on kernels 1.3.10 and older. Roman's
work is baed on amd-upl102, and work from Ian Murdock <imurdock@debian.org>
and Dominik Kubla <dominik@debian.org>.
* Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
August 6, 1997: assorted fixes to support hesiod-1.3, solaris 2.4 (which I
already fixed but did not release yet), and support for $LDFLAGS at
configure/compile time.
February 24, 1998: lots of patches for ultrix 4.3 port.
February 28, 1998: lots of documentation fixes!
* Jason Thorpe <thorpej@nas.nasa.gov>
August 25, 1997: make amd work when talking to NIS+ servers in NIS
compatibility mode. Fix originally came from Matthieu Herrb
<matthieu@laas.fr>.
* Chris Metcalf <metcalf@catfish.lcs.mit.edu>
August 29, 1997: patch to make amd use FQHN for NFS/RPC authentication,
useful esp. for cross-domain NFS mounts.
September 2, 1997: if plock() succeeded, don't display errno string.
* Enami Tsugutomo <enami@cv.sony.co.jp>
September 4, 1997: don't ping remote servers with NFS V.3 always, but V.2,
regardless of client's NFS version. (conf/transp/transp_sockets.c)
* Dan Riley <dsr@mail.lns.cornell.edu>
September 19, 1997: make sure that amd works with more secure portmappers
that do not allow forwarding of RPC messages to other services.
* Wolfgang Rupprecht <wolfgang@wsrcc.com>
August 10, 1997: netbsd and other bsd systems have a mask flag for
pcfs_args (msdos mount).
* Christos Zoulas <christos@deshaw.com>
September 25, 1997: fix to initialize uid/gid fields of pcfs_args_t on
netbsd.
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.
* Bill Paul <wpaul@ctr.columbia.edu>
November 5, 1997: NFS v.3 support for AIX 4.2.1, which does *not* include
headers for this. Bill had to guess at the right structures, field names,
sizes, alignment, etc.
* Stefan Vogel <vogel@physik-rzu.unizh.ch>
November 14, 1997: typo in the subscription instructions to amd-dev.
* Guntram Wolski <gwolsk@sei.com>
November 15, 1997: pointed out mismatching documentation for the -o option.
* Michael Hucka <hucka@eecs.umich.edu>
January 11, 1997: pointed out reversed definition of NFS mount options vers
and proto.
* Albert Chin <china@pprd.abbott.com>
January 12, 1998: minor bug in output of amd -H.
* Thomas Richter <richter@chemie.fu-berlin.de>
January 13, 1998: use case insensitive comparisons for variables that need
it (such as all hostname related ones, and more).
* Fred Korz <korz@smarts.com>
January 30, 1998: minor typo fixed to tftp example in am-utils.texi.
* Donald Buczek <buczek@MPIMG-Berlin-Dahlem.MPG.DE>
March 6, 1998: correctly inherit existing NFS V.3 mounts upon restart.
March 17, 1998: compare log file name and syslog string with correct length.
March 20, 1998: do not close stdout in case it gets reused elsewhere and to
allow startup script to redirect it. Set a temporary secure umask(0022)
before writing log file and restore it afterwards.
* Matthew Crosby <mcrosby@ms.com>
April 20, 1998: allow arbitrary number of interfaces in wire listing.

73
contrib/amd/BUGS Normal file
View File

@ -0,0 +1,73 @@
# -*- text -*-
LIST OF KNOWN BUGS IN AM-UTILS OR OPERATING SYSTEMS
(1) mips-sgi-irix*
[1A] known to have flakey NFS V.3 and TCP. Amd tends to hang or spin
infinitely after a few hours or days of use. Users must install recommended
patches from vendor. Patches help, but not all the time. Otherwise avoid
using NFS V.3 and TCP on these systems, by setting
/defaults opts:=vers=2,proto=udp
[1B] yp_all() leaks a file descriptor. Eventually amd runs out of file
descriptors and hangs. Am-utils circumvents this by using its own version
of yp_all which uses udp and iterats over NIS maps. The latter isn't as
reliable as yp_all() which uses TCP, but it is better than hanging.
(2) alpha-unknown-linux-gnu (RedHat Linux 4.2)
hasmntopt(mnt, opt) can goes into an infinite loop if opt is any substring
of mnt->mnt_opts. Redhat 5.0 does not have this libc bug. Here is an
example program:
#include <stdio.h>
#include <mntent.h>
main()
{
struct mntent mnt;
char *cp;
mnt.mnt_opts = "intr,rw,port=1023,timeo=8,foo=br,retrans=110,indirect,map=/usr/local/AMD/etc/amd.proj,boo";
cp = hasmntopt(&mnt, "ro");
printf("cp = %s\n", cp);
exit(0);
}
(3) mips-dec-ultrix4.3
Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> reports
[3A] At least the gcc 2.7.0 fixincludes-mangled <sys/utsname.h> needs a
forward declaration of struct utsname to avoid lots of gcc warnings:
RCS file: RCS/utsname.h,v
retrieving revision 1.1
diff -u -r1.1 utsname.h
--- utsname.h 1995/06/19 13:07:01 1.1
+++ utsname.h 1998/01/27 12:34:26
@@ -59,6 +59,7 @@
#ifdef KERNEL
#include "../h/limits.h"
#else /* user mode */
+struct utsname;
extern int uname _PARAMS((struct utsname *));
#endif
#define __SYS_NMLN 32
[3B] It autoconfigures and compiles cleanly, but currently hangs after a
couple of hours without leaving any traces in the syslog output.
(4) powerpc-ibm-aix4.2.1.0
[4A] "Randall S. Winchester" <rsw@Glue.umd.edu> reports that for amd to
start, you need to kill and restart rpc.mountd and possibly also make sure
that nfsd is running. Normally these are not required.
[4B] "Stefan Vogel" <vogel@physik.unizh.ch> reports that if your amq
executable dump core unexpectedly, then it may be a bug in gcc 2.7.x.
Upgrade to gcc 2.8.x or use IBM's xlC compiler.

37
contrib/amd/COPYING Normal file
View File

@ -0,0 +1,37 @@
Copyright (c) 1997-1998 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.
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, as well as the Trustees of
Columbia University.
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.

3039
contrib/amd/ChangeLog Normal file

File diff suppressed because it is too large Load Diff

113
contrib/amd/INSTALL Normal file
View File

@ -0,0 +1,113 @@
# -*- text -*-
am-utils 6.0 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' means verified broken.
SYSTEM AUTOCONF COMPILE RUN SHLIB
========================= ======== ========= ======= =====
alpha-dec-osf2.1 ezk ezk ezk
alpha-dec-osf4.0 ezk ezk dsr[3]
alphaev5-unknown-linux-gnu ezk ezk finkel ezk
hppa1.0-hp-hpux11.00 ezk ezk ezk
hppa1.1-hp-hpux10.10 ezk ezk ezk -ezk (!rpcsvc.so)
hppa1.1-hp-hpux10.20 ezk ezk ezk -ezk (!rpcsvc.so)
hppa1.1-hp-hpux9.01 ezk[4] ezk[4] nrh/ezk
hppa1.1-hp-hpux9.05 ezk[4] ezk[4] nrh/ezk
hppa1.1-hp-hpux9.07 ezk[4] ezk[4] nrh/ezk
i386-pc-bsdi2.1 ezk ezk ezk
i386-pc-bsdi3.0 ezk ezk ezk
i386-pc-bsdi3.1 ezk ezk ezk
i386-pc-solaris2.5.1 ezk ezk ezk ezk
i386-pc-solaris2.6 ezk ezk ezk ezk
i386-unknown-freebsd2.1.0 ezk ezk ezk
i386-unknown-freebsd2.2.1 ezk ezk ezk ezk
i386-unknown-freebsd3.0 ezk ezk ezk ezk
i386-unknown-netbsd1.2.1 ezk ezk ezk ezk
i386-unknown-netbsd1.3 ezk ezk ezk ezk
i386-unknown-netbsd1.3.1 ezk ezk ezk ezk
i386-unknown-openbsd2.1 ezk ezk ezk ezk
i486-ncr-sysv4.3.03 ezk ezk
i486-pc-linux-gnulibc1 ezk ezk ezk ezk
i586-pc-linux-gnulibc1 ezk ezk ezk ezk
i686-pc-linux-gnu ezk ezk ezk ezk
m68k-hp-hpux9.00 ezk[4] ezk[4] nrh/ezk
m68k-next-nextstep3 ezk ezk ezk
m68k-sun-sunos4.1.1 ezk ezk
mips-dec-ultrix4.3 ro ro ro
mips-sgi-irix5.2
mips-sgi-irix5.3 ezk ezk ezk
mips-sgi-irix6.2 ezk[1] ezk[1] ezk[1]
mips-sgi-irix6.4 ezk ezk ezk ezk (!gcc)
powerpc-ibm-aix4.1.5.0 ezk ezk wpaul
powerpc-ibm-aix4.2.1.0 ezk ezk ezk
rs6000-ibm-aix3.2 ezk ezk ezk
rs6000-ibm-aix3.2.5 ezk ezk ezk
rs6000-ibm-aix4.1.4.0 ezk ezk
sparc-sun-solaris2.3 ezk ezk ezk
sparc-sun-solaris2.4 ezk ezk ezk ezk
sparc-sun-solaris2.5 ezk ezk ezk ezk
sparc-sun-solaris2.5.1 ezk ezk ezk ezk
sparc-sun-solaris2.6 ezk ezk[2] ezk ezk
sparc-sun-sunos4.1.1 ezk ezk ezk ezk
sparc-sun-sunos4.1.3 ezk ezk ezk ezk
sparc-sun-sunos4.1.3C ezk ezk ezk ezk
sparc-sun-sunos4.1.3_U1 ezk ezk ezk ezk
sparc-sun-sunos4.1.4 ezk ezk ezk ezk
sparc-unknown-linux-gnulibc1 ezk ezk ezk ezk
sparc-unknown-netbsd1.2E ezk ezk ezk
EMAIL ID LEGEND:
bking: Bevis R W King <B.King@ee.surrey.ac.uk>
dsr: Dan Riley <dsr@mail.lns.cornell.edu>
ezk: Erez Zadok <ezk@cs.columbia.edu>
nrh: Nick Hall <nrh@dcs.ed.ac.uk>
stolke: Andreas Stolcke <stolcke@speech.sri.com>
wpaul: Bill Paul <wpaul@ctr.columbia.edu>
finkel: Raphael Finkel <raphael@cs.uky.edu>
ro: Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
FOOTNOTES:
[1] If compiling with cc on Irix 6, then use
CC="cc -32 -Wl,-woff,84" ./buildall
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] If compiling on Solaris 2.6, you need to add -D_LARGEFILE64_SOURCE to
CFLAGS to enable the 64bit file offset interface:
make CFLAGS="-O2 -g -D_LARGEFILE64_SOURCE"
If you're using the standard configure script, it will add this flag for you
automatically.
[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.

43
contrib/amd/MIRRORS Normal file
View File

@ -0,0 +1,43 @@
# -*- text -*-
AM-UTILS-6.0 MIRRORS
Note: in case of any problems accessing the individual FTP sites, please
contact their respective maintainers. If you wish to be added to the
official mirror list, please send mail to amd-dev@cs.columbia.edu with the
full URL, maintainer's email, and geographical location.
U.S.A:
New York (Primary Site):
ftp://shekel.mcl.cs.columbia.edu/pub/am-utils
Maintainer: ezk@cs.columbia.edu
Maryland:
ftp://ftp.cs.umn.edu/pub/AMD
Maintainer: dokas@cs.umn.edu
Virginia (Newport News):
* ftp://www.ferginc.com/pub/unix/am-utils
Maintainer: Branson.Matheson@FergInc.com
Europe:
Germany:
ftp://ftp.fu-berlin.de/pub/unix/network/am-utils
Maintainer: ftp-adm@ftp.fu-berlin.de
Sweden:
ftp://ftp.sunet.se/pub/unix/admin/am-utils
Maintainer: archive@ftp.sunet.se
Sweden:
ftp://ftp.matematik.su.se/pub/mirrors/shekel.mcl.cs.columbia.edu/pub/am-utils
Maintainer: lifj@matematik.su.se
UK:
ftp://sunsite.org.uk/packages/am-utils
Maintainer: lmjm@icparc.ic.ac.uk
Asia:
Japan:
ftp://ftp.u-aizu.ac.jp/pub/net/amd/am-utils
Maintainer: ftp-admin@u-aizu.ac.jp
Australia:
Melbourne:
ftp://ftp.sage-au.org.au/pub/network/filesystem/am-utils
Maintainer: mirror@ftp.sage-au.org.au

628
contrib/amd/NEWS Normal file
View File

@ -0,0 +1,628 @@
*** Notes specific to am-utils version 6.0a16:
- new ports:
hppa1.0-hp-hpux11.00 (works, not NFS V.3 due to missing headers)
mips-dec-ultrix4.3 (working, unverified)
- new minor ports:
i386-pc-bsdi3.1
i386-unknown-netbsd1.3.1
alpha-dec-osf2.1
- new options addopt:=ARG will "smartly" add and override options specified
in opts:=
- new amd.conf options:
pid_file: specifies the file to store the PID
hesiod_base: specifies the base for the Hesiod service
unmount_on_exit: if 'yes' will attempt to unmount all file systems
when amd exits.
- amd.conf file is parsed after all other command line options. If no
options specified at all, then use /etc/amd.conf by default.
- some variables' values are now compared case-insensitive as per specs,
such as host names, domain names, and more.
- NIS service uses a new isup() function to detect if the service is up
before using it. Used to ensure amd doesn't clear the existing maps before
reloading them, unless the remote info service is working.
- new cdfs mount options: rrip, noversion, defperm, nodefperm (OSF)
- support efs/xfs separately on irix
- new -D info trace option to turn on info specific debugging, such as
RES_DEBUG for hesiod services.
- document updates and fixes
- new file MIRRORS lists official mirror sites (also in am-utils home page)
- new file BUGS lists known amd/OS bugs
- source restructuring: rename all Amd file-systems' sources to amfs_ARG.c
such that it matches the type:=ARG as well. Free names afs/dfs for Andrew
F/S and Distributed F/S.
- checkpoint config.guess several times during the long configure, so that
if it is aborted midway, the bulk of the features discovered will be re-read
from the config.cache file.
- more systems support shared libraries (libtool 1.2)
- using automake 1.3 + more fixes
- bugs fixed:
use dynamic buffer for list of interfaces, not fixed size
output of amd -H duplicated if >2 interfaces
-D mem for hlfsd not on by default (so it will daemonize)
linux looks for ext2fs before ufs
CDFS looks for 'isofs' mount type as well
compile on Solaris 2.6 with /opt/SUNWspro/bin/cc
various additional fixes which gcc 2.8.x reported
print syslog help string based on what's supported
correctly ignore loopback interface on SunOS 3.x
don't use -lucb for strcasecmp
hlfsd's dump file securely written in /usr/tmp/hlfsd.dump.XXXXXX
inherit NFS V.3 mounts correctly
write pid file securely
*** Notes specific to am-utils version 6.0a15:
- new ports:
alpha-unknown-linux-gnu: works
i386-unknown-netbsd1.3: fully working
*-sun-sunos3: compiles, not tested
- updated ports:
m68k-next-nextstep3: cleaner compile, works.
- new file system type nfsl (NFS Link). Uses nfs if file system is remote,
and link if it is local (based on if $rhost equals the host name).
- support for Solaris cachefs. Requires setting fs, rfs, and a new variable
cachedir. See documentation for explanation, examples, and caveats.
- support negated selector functions such as !exists(/foo/bar)
- wire, network, netnumber, in_network() selectors now match against all
locally attached networks (by either name or number), not just the first two
interfaces.
- new program pawd (and man page for it) --- Print Automounter Working
Directory, to print the proper pathname of the cwd or any other pathname,
adjusted for automounter paths, while avoiding mount points.
- two new switches to amq: -U will force using UDP only; -T will force using
only TCP to communicate with amd. If neither (or both) are specified, amq
will try TCP first, and if that failed, will try UDP.
- support syslog facilities, using "amd -l syslog:facility". Old behavior
when using only -l syslog is to use the LOG_DAEMON facility.
- you may specify browsable_dirs=full, to get a listing of all entries
(other than /default), including those with '*' wildcard and '/'
characters.
- amd -D trace now also includes as much of struct nfs_args as can be
displayed. Useful in figuring out what the kernel really gets during a
mount(2), as opposed to what the /etc/mnttab file says. -D trace also
traces the xdr_* functions.
- support for versions of shared libamu version. upped version from 0.0.0
to 1.0.0. each am-utils release that will change the library will also
update its version.
- amd/ops_TEMPLATE.c: a new template file for those brave enough to try and
implement a new amd file system. Includes comments and other info useful
for developers.
- if localconfig.h exists in the current directory during the run of
configure, it is included in all am-utils sources. This allows courageous
developers to make certain modifications during compilations, and especially
turn off undesired features (not very recommended).
- documentation types and updates for all new features, ports, etc.
- bugs fixed:
support NFS mount options grpid and maxgrps
nextstep: set NFS success code to 0 (NFS_OK), not 1 (EPERM)
bsdi2: set NFS success code to 0 (NFS_OK), not 1 (EPERM)
set NFS V.3 mount table names to "nfs" if vers/proto exist
use mkstemp() if possible (more secure)
ctl-amd looks for amd.conf in ${prefix}/etc after /etc
hpux: use "ignore" mount table type
openbsd2.2: turn off "noconn" mount option, so only connected used
fixed memory leak in hlfsd (don't setpwent after endpwent)
all NFS3 systems should have proto/vers mount/amd options
DEBUG_MEM compiles and prints something more useful
uninit_mntfs(): free() mf_private *after* it is used
browsable_readdir: fewer bytes sent back to kernel for each chunk
mount_toplvl: don't free() an automatic variable!
amd should chdir() to / before daemonzing (for core dumps etc)
cdfs should be called 'cdfs' not whatever the mnttab type is
amd -v: don't print "FS:" list twice when >=2 net interfaces
*** Notes specific to am-utils version 6.0a14:
- updated ports:
powerpc-ibm-aix4.2.1.0: NFS V.3 works
- minor new ports:
sparc-sun-sunos4.1.3C
m68k-sun-sunos4.1.1 (sun3)
mips-sgi-irix5.2
- new option to amd, -O ARG, will override the operating systems *name* with
ARG. Corrected documentation for amd -o ARG --- it overrides the operating
system *version* and not the name as the docs incorrectly stated.
- logging now behave more like syslog: will not print repeated strings, but
rather a count such as "last message repeated N times". (N will not exceed
100.)
- restructured the code which deals with the numerous possible fields and
flags that are set in struct nfs_args. That code was moved to libamu as
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
set correct nfs_prot headers for Solaris 2.5
removed stale code from lostaltmail.in
lostaltmail will look for conf file in multiple locations
assorted documentation corrections
amq does not print "get_secure_amd_client" if run as root
*** Notes specific to am-utils version 6.0a13:
- new in_network(ARG) nomadic selector, true if ARG is the name (or number)
of any of this host's network interfaces.
- removed variables primnetname, primnetnum, subsnetname, and subsnetnum.
(Kept "wire" and its alias "network", and "netnumber".)
- include am-utils.dvi and am-utils.ps in distribution.
- hlfsd supports new option -P ARG, for reading password map off of file
ARG. Allows you to use the hlfs redirector using paths other than user's
home directories.
- use a replacement yp_all for some systems (irix) known to have a broken
one which leaks a file descriptor each time called.
- if remote NFS server is down or does not support portmap, downgrade
machine to NFS V.2 and retry again later.
- bugs:
don't redefine yywrap on systems using a modified flex
use correct "ignore" mnttab/mount option on hpux for df(1)
use nfs_args' fsname field (hpux) to avoid syncer/mount(1) problems
don't add ops_ufs.o twice to Makefile's $(OBJS)
don't fail if autofs listener fails to initialize
hlfsd should test if run as root after usage() and getopt
- minor code cleanups for netbsd
- html docs now in http://www.cs.columbia.edu/~ezk/am-utils/
- added README file in binaries ftp directory
*** Notes specific to am-utils version 6.0a12:
- minor or updated/broken ports fixed:
hppa1.1-hp-hpux10.10: compiles, untested (probably works).
hppa1.1-hp-hpux9.05: compiles, untested (probably works).
hppa1.1-hp-hpux9.07: compiles, untested (probably works).
m68k-hp-hpux9.00: compiles, untested (probably works).
rs6000-ibm-aix4.1.4.0: compiles, untested.
sparc-sun-solaris2.6: works w/ NFS V.3.
sparc-sun-sunos4.1.4: compiles, untested (probably works).
- new ports:
powerpc-ibm-aix4.2.1.0: compiles w/ NFS V.3, untested.
- wire-test also checks for combinations of NFS protocol/version from the
client to a remote (or local) host.
- conf/mtab/mtab_file.c: use flock() to lock the file, and fcntl() if
flock() is not available. (Used to prefer fcntl() over flock().)
- bug fixes:
tli get_nfs_version() gets into an infinite loop
tli get_nfs_version() should time out faster
sockets get_nfs_version() should work w/ secure portmappers
ESTALE returned for NFS mounts for SunOS 4.x fixed
do not exceed HOSTNAMESZ for nfs_args.hostname (get ENAMETOOLONG)
properly initialize some mntent_t fields (fsck, freq, mnt_time)
properly initialize some pcfs_args fields (mask, uid, gid)
properly initialize some cdfs_args fields (ssector)
*** Notes specific to am-utils version 6.0a11:
- bug fixes:
amd could not NFS mount v.2 servers from v.3 clients
hlfsd will only use first occurrence of home dir for same uid
*** Notes specific to am-utils version 6.0a10:
- MAJOR DOCUMENTATION UPDATE! (first time in 6 years)
- new ports:
m68k-next-nextstep3: configures, compiles, not tested.
- preliminary autofs support. See README.autofs for details.
- new amd.conf [global] yes/no keywords:
show_statfs_entries: shows number of entries for df(1)
fully_qualified_hosts: use FQHN for NFS/RPC authentication
- detect down remote hosts faster
- log output of "amd -v" at startup
- removed $osver override for solaris: now it is 2.5.1, not 5.5.1
- buildall will use gmake first if available
- bugs fixed:
amd core dumped when remote host was down
allow up to 1024 entries back from readdir()
amd.conf works even if only [global] option defined
avoid using bad memcmp() implementations
fixed meaning of plock [global] option (was reversed)
hlfsd infinite loop unless compiled with --enable-debug
NIS code works with NIS+ servers in NIS compatibility mode
reset tag fields in amd.conf so they don't carry to other entries
*** Notes specific to am-utils version 6.0a9:
- new ports:
sparc-sun-solaris2.4:
configures/compiles, and runs (no NFS V3)
i386-unknown-openbsd2.1:
configures/compiles, runs (NFS V3)
- updated ports:
i486-ncr-sysv4.3.03: configures/compiles, not tested
- Multiple amd support: new amd.conf [global] key "portmap_program" can be
used to specify an alternate RPC program number for amd to un/register.
Allowed numbers range from 300019 to 300029. A matching new option for amq:
-P prognum, will use an alternate program number to contact.
- man pages:
amd.conf.5 new
mk-amd-map.8 new
amd.8 updated
amq.8 updated
(other man pages required minor updates)
- shared libraries support expanded. Using GNU libtool-1.0. You can build
a shared version of libamu, and link with it accordingly, by specifying
--enable-shared to configure. Default is --enable-static --disable-shared,
and you can mix and match. See "INSTALL" file for listing of systems on
which shared libraries seem to build and work fine.
- new option: amq -p, will return the PID of the running amd (local or
remote). Uses a new RPC message. Useful especially in "ctl-amd stop".
- new configure script options --enable-ldflags, for specifying -L flags.
The older --enable-libs is to be used only for -l options.
- two new LDAP map options for amd.conf: ldap_cache_seconds and
ldap_cache_maxmem.
- new script, am-eject from Debian linux's version of amd-upl102.
- additional passwd map support using var[0-3], from Debian folks.
- hesiod code cleanup. works for hesiod 1.3 as well as 3.0.
- removed defunct -h option from amd.
- started using automake-1.2. This fixed several bugs that caused some
versions of yacc/lex and non-GNU make to fail.
- bug fixes:
amd/hlfsd mounts should be hidden from df(1)
use "noconn" option for nfs mounts (multi-homed hosts)
don't use connected sockets on linux before 1.3.10 (from Debian)
better checks for [gn]dbm
forbid excessive retries after timeouts (from Debian)
readdir(): don't skip over map entries with prefix, and include it
more assorted linux fixes from Debian folks
lofs mount on svr4 was broken
find default value of $karch from uname() not $arch
hlfsd failed to mount itself on some little-endians
*** Notes specific to am-utils version 6.0a8:
- new ports:
i386-unknown-netbsd1.2.1: configures/compiles (with NFS V.3), works,
but some OS stability problems exist.
- updated ports:
hppa1.1-hp-hpux9.01:
now tested and working
rs6000-ibm-aix3.2 and rs6000-ibm-aix3.2.5:
now tested and working
- fixed browsable directories (readdir) code.
- better methods to find amd/hlfsd pid to kill in ctl-{amd,hlfsd}
- "ignore/auto" mount types fixed for irix, sunos, and others, so "df" does not
show amd mounts by default (but GNU df -a does).
- each time amd is built, a new "build" version is incremented. See amd -v.
- man page for fsinfo added
- empty fillers for new file (bsd44) systems: nullfs, unionfs, umapfs.
- when amd is not running, or portmapper is down, make amq timeout faster (5
sec) than system default, usually 4-5 minutes.
- bug fixes:
hlfsd mount got "protocol not supported"
first regular map in amd.conf didn't inherit global options
make "bad" versions of lex still work with amd/conf_parse.l
check for 'nodev' option, not 'nondev'
typo in "ro" option, and fillers to ac{reg,dir}{min,max} and others
amd.conf parsing done before switching default log/debug options
allow doubly-quoted values in amd.conf
hesiod-reload code cleanup
- assorted code cleanup
*** Notes specific to am-utils version 6.0a7:
- new ports:
i386-unknown-freebsd3.0:
fully functional with NFS V.3
sparc-sun-solaris2.3:
fully functional (should work for 2.4)
sparc-unknown-netbsd1.2E:
configures/compiles (with NFS V.3), untested
- updated ports:
i386-pc-bsdi3.0:
NFS V.3 works
look for hesiod in libc
mips-sgi-irix5.3:
fully functional with NFS V.3
- LDAP support! New [global] amd.conf options ldap_base and ldap_hostports.
Also includes a new script amd2ldif to convert amd maps into plain text LDAP
object files.
- the following amd.conf variables: browsable_dirs, map_options, map_type,
mount_type, and search_path --- can now be specified in [global] as well as
the map entry itself. That way you can declare them only once in [global],
and override them as needed per map.
- option "cluster" added to [global] (HPUX clusters ala "amd -C").
- assorted info_hesiod map fixes and cleanup. removed HESIOD_RELOAD code.
- added netgrp(name) function to amd map syntax to see if current host is in
the <name> netgroup.
- removed unused option "amd -m".
- filled in "tasks" file with todo items.
- filled "COPYING" file with legal stuff.
- cleanup: all global variables are now in one big structure (struct
amu_global_options) that's easy to identify and enhance. Also migrated
several flags that used be an integer each into one unsigned integer that's
used as a bit-flag.
- big fixes:
xdr_mountres3 should compile only if has NFS V3
lex/yacc macros show full pathname (to tell if correct one runs)
misc fixes/cleanup
*** Notes specific to am-utils version 6.0a6:
- amd configuration file!
See scripts/amd.conf-sample for help and some explanation. This new conf
file allows for the following new features:
default selectors can be turned on/off globally.
browsable_dirs/readdir() support can be turned on per map.
search paths for file type maps.
can force the map type to file, nis, ndbm, etc. rather than default
to looking at all of them.
tag each map for "amd -T tag", useful for grouping maps.
can override $os and others (so if you don't like "sunos5" default
naming, set os=sos5 and it will work with your old maps).
and more goodies...
- enable-default-selectors: No longer turned on by the configure script or
optionally compiled. Code made dynamic and can be turned on or off from the
amd.conf file. This code is off by default, and must be turned on by
amd.conf's [global] section.
- new ports:
mips-sgi-irix5.3: configure/compile, not tested
i486-ncr-sysv4.3.03: configure/compile, not tested
- updated ports:
alpha-dec-osf4.0: major code redone
sparc-sun-sunos4.1.3: fixed and working
mips-sgi-irix6.2: tested with gcc and "cc -32 -Wl,-woff,84"
mips-sgi-irix6.4: tested with gcc and "cc -32 -Wl,-woff,84"
- better NFS3 port, including more support for proto= and vers=, and
automatic determination of proto/vers combination.
- conf/nfs_prot/nfs_prot_*.h: all of the NFS protocol header files had to be
redone, because of the osf4 port. OSF used very different names for these,
and they conflicted with am-utils'. The only solution was to more or less
conform to OSF4's naming, and change all the others.
- ctl-amd script:
improved to look for amd.conf in $prefix/etc and /etc
better methods for finding the pid of amd to kill
- autoconf support for LDAP. amd/info_ldap.c needs to be written.
- wire-test also reports the local IP address. Some systems have multiple,
buggy version of get_myaddress(), esp. SunOS and Irix. Note that Solaris
x86 has a buggy htonl().
- amd -H prints usage.
- bugs fixed:
minor TLI problem in fwd_socket
mount options properly comma delimited
LIBS is set only to the right set of libraries to include
selectors-on-default code ignored last selector ent in /defaults
assorted code cleanups
*** Notes specific to am-utils version 6.0a5:
- NFS Version 3 support!!!
Works on Solaris 2.5.1.
Minimal testing done on Irix 6.
Compiles cleanly on DU-4.0 but no tests performed.
Will fall back to V2 mounts when V3 is not available. Will also use TCP if
possible, UDP otherwise.
- Ports to new platforms:
alpha-dec-osf4.0 (not tested)
i386-pc-bsdi3.0 (tested and working)
i386-unknown-freebsd2.2.1 (tested and working)
sparc-unknown-linux-gnu (tested and working)
- New scripts added:
amd2sun: convert amd maps to Sun automount maps
ctl-amd: script to start/stop/restart amd
ctl-hlfsd: script to start/stop/restart hlfsd
expn: expand mail alias (used by hlfsd)
lostaltmail: redeliver "lost" mail redirected by hlfsd
lostaltmail.conf-sample: sample conf file for lostaltmail
wait4amd: run a command once amd is up on a host
wait4amd2die: wait for an amd process to die before returning
- "amd -v" now includes more info and "amq -v" lists all of it.
- new parser for linux specific mount options.
- Main bugs fixed:
"new toplvl readdir" bug caused amd to dump core
handler for SIGCHLD didn't check for all possible children
hlfsd leaking file descriptors when home file system was full
cdfs/pcfs mounts should not timeout by default
hesiod domain names should be compared in case-insensitive manner
several printfs in amq were missing \n
*** Notes specific to am-utils version 6.0a4:
- amd services both TCP and UDP amq requests. This will help because of the
limited UDP message size.
- "amq -M" code is disabled by default because it is insecure. It is
rarely used. Users who wish to use it should run
"configure --enable-amq-mount".
*** Notes specific to am-utils version 6.0a3:
- New tested ports (configures, compiles, and runs):
i386-unknown-freebsd2.2
- New ports (configures and compiles correctly, not tested):
rs6000-ibm-aix3.2.5
rs6000-ibm-aix4.1.5.0
- More am-utils programs ported to all existing platforms: hlfsd, fsinfo,
mk-amd-map, and fixmount.
- Shared libraries: a new configure option --enable-shared will build a
shared libamu.so, link applications with it, and use it. Reduces binary
sizes by 20-30%. This is the first step towards loadable modules, as many
changes had to be done to be able to compile and use PIC code. This is code
that obviously needs to be generalized to be able to build shared libraries
on many other platforms. It was only tested on Solaris 5.5.1.
- the file INSTALL contains the latest compatibility table of which
platforms am-utils configures, compiles and runs on.
- Trimmed down the size of the configure script. Some tests that are not
used anywhere were removed.
*** Notes specific to am-utils version 6.0a2:
- New ports (configures and compiles correctly, not tested):
i386-pc-bsdi2.1
hppa1.1-hp-hpux9.01
hppa1.1-hp-hpux10.20
- new configure options:
--enable-cppflags[=ARG]
configure/compile with ARG (-I) preprocessor flags
--enable-libs[=ARG]
configure/compile with ARG (-L/-l) library flags
- filesystem, 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.
- moved all fixed headers to include/am_defs. Left only #define/#undef
entries in aux/acconfig.h.
- make more sense of systems that have full, partial, or no NFS protocol
headers.
- minor fixes for NetBSD (untested platform).
- hesiod map fixed.
- buildall -D: new option to run even stricter developer options.
- lots of other bugs fixed (see ChangeLog).
*** Notes specific to am-utils version 6.0a1:
I have it configure and build correctly for the following systems:
i386-pc-solaris2.5.1
i386-unknown-freebsd2.1.0
mips-sgi-irix6.2
sparc-sun-solaris2.5.1
sparc-sun-sunos4.1.3
Amq, wire-test, and "amd -v" work on all of the above. A real running amd
was only tested and confirmed working on
i386-pc-solaris2.5.1
sparc-sun-solaris2.5.1
Many things are still missing: options, features, etc. But for now, let's
concentrate on getting the basic functionality working on the more popular
systems.

105
contrib/amd/README Normal file
View File

@ -0,0 +1,105 @@
# -*- text -*-
This is an alpha version of amd. "Buyers" beware!!!
See the file NEWS for news on this and previous releases.
*** General Notes to alpha testers:
[A] an an alpha testers, I expect you to be able to find certain things on
your own (especially look at the sources to figure out how things work).
[B] if you intend to modify any files, first find out if the file you want
to modify gets autogenerated from some other place. If so, modify it at the
source.
You can adjust some of the configuration of am-utils after it has been
auto-configured by putting whatever definitions you wish in a file called
localconfig.h, located in the top build directory (the same one where
config.h is created for you).
[C] there are several ways you can build am-utils:
(1) run the buildall script as follows:
./buildall
This would build all the applications inside a special directory relative to
the root of the source tree, called A.<cpu-company-system>, where the <>
part is filled in by GNU's config.guess script. This is the preferred
method, for it will separate the build from the sources, and allow you to
run buildall for multiple architectures concurrently.
You can run "buildall -h" to see what options it takes.
(2) run the configure script such as:
./configure
and then run
make
This would configure amd in the directory you've run the configure script
in, and the built it there. Run "make install" to install all the necessary
files.
Note that this is good for building only one version of amd on one
architecture! Don't try this for multiple architectures. If you must, then
after doing one such build, run "make distclean" and then reconfigure for
another architecture.
(3) run the configure script for build in a different location. Let's say
that /src/am-utils-6.0 is where you unpacked the sources. So you could
mkdir /src/build/sunos5
cd /src/build/sunos5
/src/am-utils-6.0/configure --srcdir=/src/am-utils-6.0
make
This is a manual method that will let you build in any directory outside the
am-utils source tree. It requires that your "make" program understand
VPATH. This can be used multiple times to build am-utils concurrently in
multiple (but different) directories. In fact, the buildall script
described above.
(4) If you need to configure am-utils with extra libraries and/or headers,
for example to add hesiod support, do so as follows:
configure --enable-libs="-lhesiod -lresolv" \
--enable-ldflags="-L/usr/local/hesiod/lib" \
--enable-cppflags="-I/usr/local/hesiod/include"
[D] If you modify any of the *.[chyl] sources in the directories amd, amq,
hlfsd, lib, etc, all you need to do to get a new version of am-utils is run
make.
If you modify any of the files in the aux/ or conf/ directories, then you
must rebuild the configure script, Makefile.in files, aclocal.m4, etc. The
best way to do so is to run
./aux/mkconf
or
./buildall -K
To be a developer and be able to run mkconf, you must have autoconf-2.12,
GNU make-3.75 or later, and automake-1.2 (plus my fixes to it) installed on
your system. You may find my version of automake-1.2 where you ftp'ed this
version of am-utils. You may also need GNU libtool 1.0.
After you've remade the basic configuration files you must rerun the
buildall script to rerun configure and then remake the binaries.
Modifying M4 macros may not be very intuitive to anyone that has not done so
before. Let me know if you are having any problems with them. I fully
expect, at least initially, to have to be the sole developers of the M4
macros and let others concentrate on C sources.
[E] Report all bugs to amd-dev@majordomo.cs.columbia.edu. Avoid reporting
to my personal email address. It is important to involve the whole list in
bug fixes etc.
Good luck.
Erez Zadok,
Maintainer, am-utils.

177
contrib/amd/TODO Normal file
View File

@ -0,0 +1,177 @@
# -*- text -*-
Make a tasks file that people can pick jobs off of.
take a look at am_compat.h and fix everything there...
fix all $Id bla bla bla $ on every file.
add my own copyright 1997 etc.
NOT NEEDED: convert DEBUG symbol to ENABLE_DEBUG
NOT NEEDED: convert DEBUG_MEM symbol to ENABLE_DEBUG_MEM
Use these two somewhere:
AC_DEFINE(AM_UTILS_NAME_PACKAGE, "am-utils")
AC_DEFINE(AM_UTILS_VERSION, "6.0a1)
check all "dnl XXX: in configure.in
check for: INLINE, Const->const, P_void, VOIDP
rename DEBUG_MTAB to DEBUG_MNTTAB
rename UPDATE_MTAB to MOUNT_TABLE_ON_FILE
rename HAS_NIS_MAPS to HAVE_MAP_NIS
rename HAS_TFS to HAVE_FS_TFS
rename SIG_HNDL_TYP to RETSIGTYPE
remove HOST_EXEC #define from everywhere. add to am_ops.c a static flag
initialized_vops, which if not true, should set the host_ops vector field to
0 or host_umounted. This way let the feature be turned on if -h option to
amd is given.
nuke all code that is ifdef'd SUNOS4_COMPAT
rename NEED_MNTOPT_PARSER to HAVE_HASMNTOPT and cleanup the code. also take
the supplied code in amd/mount_fs.c and include it as the library function
libamd/hasmntopt.c
TLI code needs to be fixed.
a way to include a site-specific configuration file IFF it exists from
directory local/<${target}.h>
replace #include WAIT with nothing (HAVE_SYS_WAIT_H?)
replace SYS5_SIGNALS with HAVE_SYS_WAIT_H (which is on only if it sys/wait.h
exists and is using the newer "int" for type, not "union wait". The macro
AC_HEADER_SYS_WAIT turns on HAVE_SYS_WAIT_H iff wait*() functions are
posix.1 compliant. Make sure you don't remove SYS5_SIGNALS ifdef's that are
not related to wait*() syscalls.
add username, hostname, and date at which time amd was compiled.
No more need for MOUNT_HELPER_SOURCE.
any code which is included by NEED_UMOUNT_FS, should be on iff
MOUNT_TABLE_ON_FILE is on.
replace NFS_FH_FIELD with references fo ".fh" in calls to
NFS_FH_DREF(src, dst) macro
For *EVERY* M4 Macro with case/esac, check that the $host_os case entries
are correct.
I'm not using amd's regexp code. Instead, use generic system code. If the
system has posix style regexp functions, then change amd/map.c to use
correct new prototype.
use HAVE_SVC_GETREQSET instead of RPC_4.
replace all "jsp" in *.[hc] $Id$ with ezk.
use MNTTAB_FILE_NAME instead of MOUNTED
use MOUNT_TABLE_ON_FILE instead of READ_MTAB_FROM_FILE
no more HAS_EMPTY_AUTOMOUNTS, which was used if a df(1) divide by zero bug
was invoked. Instead, change nfs_statfs() code to always return non-zero
values. Then nuke HAS_EMPTY_AUTOMOUNTS.
REGEXP: use whatever regular expressionlibrary you have on the system,
including regexp.h if available, and using regcomp/regexec. Amd was written
with BSD regexps in mind, not Sys V, so if I use any of those, I have to
watch for correct usage. Otherwise, I can include the older include/re.h
and amd/re.c. Replace HAS_REGEXP with HAVE_REGEXEC.
The regex code in amd/mapc.c has changed a lot. It probably has bugs. Must
test and debug it!!!
# string name of filesystem in /etc/mnttab file
Use MNTTAB_TYPE_FOO instead of MTAB_TYPE_FOO.
# string name of mount option in /etc/mnttab file
Use MNTTAB_OPT_FOO instead of MNTOPT_FOO.
# string (or integer?) name of filesystem type in mount(2) syscall
Use MOUNT_TYPE_FOO instead of MNTTYPE_FOO or MOUNT_FOO.
# hex/number of FS mount option in nfs_args passed to mount(2) syscall
Use MNT2_NFS_OPT_FOO instead NFSMNT_FOO.
# hex/number of generic FS mount option directly passed to mount(2) syscall
Use MNT2_GEN_OPT_FOO instead of MS_FOO or M_FOO.
update AMD_COMPAT to 6.0 in include/am_utils.h
convert all mem* functions b* functions (memset to bzero, etc.) or vice
verse.
put my name/copyright on every src file
change all struct mnttab/mntent to "mntent_t"
cleanup lib/resvport.c (TLI vs. Sockets). TLI code is #defin'ed
HAVE_T_OPEN.
[
setting MTAB_LOCK_FILE (mtab_svr4.c) should be an amd run-time configuration
option.
change all UMOUNT_FS macros to umount_fs() fxn calls.
remove getnetbyaddr() from lib/getnetbyaddr.c and then link w/ -lsocket
take care of various (hlfsd et al) scripts in Makefile.am files.
rename HOSTNAMESZ to MAXHOSTNAMELEN
turn on all the NEW_TOPLVL_READDIR code (for "ls" to work in an amd point)
change all NEW_DEFAULTS to ENABLE_DEFAULT_SELECTOTS (which is now on by
default)
remove refereces to mnt_freq and mnt_passno in mntent_t since it's not in
use any more.
remove all the (lint?) comments /*ARGSUSED */
change HAS_FOOFS to HAVE_AM_FS_FOO (for example HAS_NFSX -> HAVE_AM_FS_FOO),
but change HAS_UNION_FS to HAVE_AM_FS_UNION.
some code uses #ifdef M_NEWTYPE to tell if mount(2)'s type field is "char *"
or int. Use MTYPE_TYPE declaration instead (not ifdef macro!)
change DEBUG_MTAB to DEBUG_MNTTAB
deal with the changes in values of $os, $arch, and $osver!
replace SYS5_SIGNALS with REINSTATE_SIGNAL_HANDLER
figure out how to auto-conf HAS_HESIOD_RELOAD (amd/info_hesiod.c). For now
I've used the macro HAVE_HS_ZONE_TRANSFER.
******************************************************************************
PERL SCRIPT TO FIX OLD AMD MAPS:
- fix '=' to ':='
- fix sos5 -> solaris2, etc.
******************************************************************************
USE AS IS:
- SVC_IN_ARG_TYPE (change from SVC_IN_ARGS_TYPE, with an 'S')
- NFS_FH_TYPE
- MTYPE_TYPE
- MOUNT_TYPE_* NO!!!
******************************************************************************
NEW FEATURES:
- autofs
- cachefs
- dbm/gdbm/db file maps
- add amd option -O (override) to override $os, $osver, $arch, $karch, etc.
******************************************************************************
DONE:
HAS_TFS is gone and all of it's code too.
major code cleanup, removed if 0 code and if notdef

441
contrib/amd/amd/am_ops.c Normal file
View File

@ -0,0 +1,441 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: am_ops.c,v 5.2.2.1 1992/02/09 15:08:17 jsp beta $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/*
* The order of these entries matters, since lookups in this table are done
* on a first-match basis. The entries below are a mixture of native
* filesystems supported by the OS (HAVE_FS_FOO), and some meta-filesystems
* supported by amd (HAVE_AM_FS_FOO). The order is set here in expected
* match-hit such that more popular filesystems are listed first (nfs is the
* most popular, followed by a symlink F/S)
*/
static am_ops *vops[] =
{
#ifdef HAVE_FS_NFS
&nfs_ops, /* network F/S (version 2) */
#endif /* HAVE_FS_NFS */
#ifdef HAVE_AM_FS_LINK
&amfs_link_ops, /* symlink F/S */
#endif /* HAVE_AM_FS_LINK */
/*
* Other amd-supported meta-filesystems.
*/
#ifdef HAVE_AM_FS_NFSX
&amfs_nfsx_ops, /* multiple-nfs F/S */
#endif /* HAVE_AM_FS_NFSX */
#ifdef HAVE_AM_FS_NFSL
&amfs_nfsl_ops, /* NFS with local link existence check */
#endif /* HAVE_AM_FS_NFSL */
#ifdef HAVE_AM_FS_HOST
&amfs_host_ops, /* multiple exported nfs F/S */
#endif /* HAVE_AM_FS_HOST */
#ifdef HAVE_AM_FS_LINKX
&amfs_linkx_ops, /* symlink F/S with link target verify */
#endif /* HAVE_AM_FS_LINKX */
#ifdef HAVE_AM_FS_PROGRAM
&amfs_program_ops, /* program F/S */
#endif /* HAVE_AM_FS_PROGRAM */
#ifdef HAVE_AM_FS_UNION
&amfs_union_ops, /* union F/S */
#endif /* HAVE_AM_FS_UNION */
#ifdef HAVE_AM_FS_INHERIT
&amfs_inherit_ops, /* inheritance F/S */
#endif /* HAVE_AM_FS_INHERIT */
/*
* A few more native filesystems.
*/
#ifdef HAVE_FS_UFS
&ufs_ops, /* Unix F/S */
#endif /* HAVE_FS_UFS */
#ifdef HAVE_FS_XFS
&xfs_ops, /* Unix (irix) F/S */
#endif /* HAVE_FS_XFS */
#ifdef HAVE_FS_EFS
&efs_ops, /* Unix (irix) F/S */
#endif /* HAVE_FS_EFS */
#ifdef HAVE_FS_LOFS
&lofs_ops, /* loopback F/S */
#endif /* HAVE_FS_LOFS */
#ifdef HAVE_FS_CDFS
&cdfs_ops, /* CDROM/HSFS/ISO9960 F/S */
#endif /* HAVE_FS_CDFS */
#ifdef HAVE_FS_PCFS
&pcfs_ops, /* Floppy/MSDOS F/S */
#endif /* HAVE_FS_PCFS */
#ifdef HAVE_FS_CACHEFS
&cachefs_ops, /* caching F/S */
#endif /* HAVE_FS_CACHEFS */
#ifdef HAVE_FS_NULLFS
/* FILL IN */ /* null (loopback) F/S */
#endif /* HAVE_FS_NULLFS */
#ifdef HAVE_FS_UNIONFS
/* FILL IN */ /* union (bsd44) F/S */
#endif /* HAVE_FS_UNIONFS */
#ifdef HAVE_FS_UMAPFS
/* FILL IN */ /* uid/gid mapping F/S */
#endif /* HAVE_FS_UMAPFS */
/*
* These 5 should be last, in the order:
* (1) amfs_auto
* (2) amfs_direct
* (3) amfs_toplvl
* (4) autofs
* (5) amfs_error
*/
#ifdef HAVE_AM_FS_AUTO
&amfs_auto_ops, /* Automounter F/S */
#endif /* HAVE_AM_FS_AUTO */
#ifdef HAVE_AM_FS_DIRECT
&amfs_direct_ops, /* direct-mount F/S */
#endif /* HAVE_AM_FS_DIRECT */
#ifdef HAVE_AM_FS_TOPLVL
&amfs_toplvl_ops, /* top-level mount F/S */
#endif /* HAVE_AM_FS_TOPLVL */
#ifdef HAVE_FS_AUTOFS
&autofs_ops, /* autofs mount F/S */
#endif /* HAVE_FS_AUTOFS */
#ifdef HAVE_AM_FS_ERROR
&amfs_error_ops, /* error F/S */
#endif /* HAVE_AM_FS_ERROR */
0
};
void
ops_showamfstypes(char *buf)
{
struct am_ops **ap;
int l = 0;
buf[0] = '\0';
for (ap = vops; *ap; ap++) {
strcat(buf, (*ap)->fs_type);
if (ap[1])
strcat(buf, ", ");
l += strlen((*ap)->fs_type) + 2;
if (l > 60) {
l = 0;
strcat(buf, "\n ");
}
}
}
static void
ops_show1(char *buf, int *lp, const char *name)
{
strcat(buf, name);
strcat(buf, ", ");
*lp += strlen(name) + 2;
if (*lp > 60) {
strcat(buf, "\t\n");
*lp = 0;
}
}
void
ops_showfstypes(char *buf)
{
int l = 0;
buf[0] = '\0';
#ifdef MNTTAB_TYPE_AUTOFS
ops_show1(buf, &l, MNTTAB_TYPE_AUTOFS);
#endif /* MNTTAB_TYPE_AUTOFS */
#ifdef MNTTAB_TYPE_CACHEFS
ops_show1(buf, &l, MNTTAB_TYPE_CACHEFS);
#endif /* MNTTAB_TYPE_CACHEFS */
#ifdef MNTTAB_TYPE_CDFS
ops_show1(buf, &l, MNTTAB_TYPE_CDFS);
#endif /* MNTTAB_TYPE_CDFS */
#ifdef MNTTAB_TYPE_CFS
ops_show1(buf, &l, MNTTAB_TYPE_CFS);
#endif /* MNTTAB_TYPE_CFS */
#ifdef MNTTAB_TYPE_LOFS
ops_show1(buf, &l, MNTTAB_TYPE_LOFS);
#endif /* MNTTAB_TYPE_LOFS */
#ifdef MNTTAB_TYPE_EFS
ops_show1(buf, &l, MNTTAB_TYPE_EFS);
#endif /* MNTTAB_TYPE_EFS */
#ifdef MNTTAB_TYPE_MFS
ops_show1(buf, &l, MNTTAB_TYPE_MFS);
#endif /* MNTTAB_TYPE_MFS */
#ifdef MNTTAB_TYPE_NFS
ops_show1(buf, &l, MNTTAB_TYPE_NFS);
#endif /* MNTTAB_TYPE_NFS */
#ifdef MNTTAB_TYPE_NFS3
ops_show1(buf, &l, "nfs3"); /* always hard-code as nfs3 */
#endif /* MNTTAB_TYPE_NFS3 */
#ifdef MNTTAB_TYPE_NULLFS
ops_show1(buf, &l, MNTTAB_TYPE_NULLFS);
#endif /* MNTTAB_TYPE_NULLFS */
#ifdef MNTTAB_TYPE_PCFS
ops_show1(buf, &l, MNTTAB_TYPE_PCFS);
#endif /* MNTTAB_TYPE_PCFS */
#ifdef MNTTAB_TYPE_TFS
ops_show1(buf, &l, MNTTAB_TYPE_TFS);
#endif /* MNTTAB_TYPE_TFS */
#ifdef MNTTAB_TYPE_TMPFS
ops_show1(buf, &l, MNTTAB_TYPE_TMPFS);
#endif /* MNTTAB_TYPE_TMPFS */
#ifdef MNTTAB_TYPE_UFS
ops_show1(buf, &l, MNTTAB_TYPE_UFS);
#endif /* MNTTAB_TYPE_UFS */
#ifdef MNTTAB_TYPE_UMAPFS
ops_show1(buf, &l, MNTTAB_TYPE_UMAPFS);
#endif /* MNTTAB_TYPE_UMAPFS */
#ifdef MNTTAB_TYPE_UNIONFS
ops_show1(buf, &l, MNTTAB_TYPE_UNIONFS);
#endif /* MNTTAB_TYPE_UNIONFS */
#ifdef MNTTAB_TYPE_XFS
ops_show1(buf, &l, MNTTAB_TYPE_XFS);
#endif /* MNTTAB_TYPE_XFS */
/* terminate with a period, newline, and NULL */
if (buf[strlen(buf)-1] == '\n')
buf[strlen(buf) - 4] = '\0';
else
buf[strlen(buf) - 2] = '\0';
strcat(buf, ".\n");
}
/*
* return string option which is the reverse of opt.
* nosuid -> suid
* quota -> noquota
* ro -> rw
* etc.
* may return pointer to static buffer or subpointer within opt.
*/
static char *
reverse_option(const char *opt)
{
static char buf[80];
/* sanity check */
if (!opt)
return NULL;
/* check special cases */
/* XXX: if this gets too long, rewrite the code more flexibly */
if (STREQ(opt, "ro")) return "rw";
if (STREQ(opt, "rw")) return "ro";
if (STREQ(opt, "bg")) return "fg";
if (STREQ(opt, "fg")) return "bg";
if (STREQ(opt, "soft")) return "hard";
if (STREQ(opt, "hard")) return "soft";
/* check if string starts with 'no' and chop it */
if (NSTREQ(opt, "no", 2)) {
strcpy(buf, &opt[2]);
} else {
/* finally return a string prepended with 'no' */
strcpy(buf, "no");
strcat(buf, opt);
}
return buf;
}
/*
* start with an empty string. for each opts1 option that is not
* in opts2, add it to the string (make sure the reverse of it
* isn't in either). finally add opts2. return new string.
* Both opts1 and opts2 must not be null!
* Caller must eventually free the string being returned.
*/
static char *
merge_opts(char *opts1, char *opts2)
{
mntent_t mnt2; /* place holder for opts2 */
char *newstr; /* new string to return (malloc'ed) */
char *tmpstr; /* temp */
char *eq; /* pointer to '=' 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 */
char *s1 = strdup(opts1); /* copy of opts1 to munge */
/* initialization */
mnt2.mnt_opts = opts2;
newstr = xmalloc(len);
newstr[0] = '\0';
for (tmpstr = strtok(s1, ",");
tmpstr;
tmpstr = strtok(NULL, ",")) {
/* copy option to temp buffer */
strncpy(oneopt, tmpstr, 80);
oneopt[79] = '\0';
/* if option has a value such as rsize=1024, chop the value part */
if ((eq = strchr(oneopt, '=')))
eq[1] = '\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))
continue;
/* add option to returned string */
if (newstr && newstr[0]) {
strcat(newstr, ",");
strcat(newstr, tmpstr);
} else {
strcpy(newstr, tmpstr);
}
}
/* finally, append opts2 itself */
if (newstr && newstr[0]) {
strcat(newstr, ",");
strcat(newstr, opts2);
} else {
strcpy(newstr, opts2);
}
XFREE(s1);
return newstr;
}
am_ops *
ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map)
{
am_ops **vp;
am_ops *rop = 0;
/*
* First crack the global opts and the local opts
*/
if (!eval_fs_opts(fo, key, g_key, path, keym, map)) {
rop = &amfs_error_ops;
} else if (fo->opt_type == 0) {
plog(XLOG_USER, "No fs type specified (key = \"%s\", map = \"%s\")", keym, map);
rop = &amfs_error_ops;
} else {
/*
* Next find the correct filesystem type
*/
for (vp = vops; (rop = *vp); vp++)
if (STREQ(rop->fs_type, fo->opt_type))
break;
if (!rop) {
plog(XLOG_USER, "fs type \"%s\" not recognized", fo->opt_type);
rop = &amfs_error_ops;
}
}
/*
* Make sure we have a default mount option.
* Otherwise skip past any leading '-'.
*/
if (fo->opt_opts == 0)
fo->opt_opts = strdup("rw,defaults");
else if (*fo->opt_opts == '-') {
/*
* We cannot simply do fo->opt_opts++ here since the opts
* module will try to free the pointer fo->opt_opts later.
* So just reallocate the thing -- stolcke 11/11/94
*/
char *old = fo->opt_opts;
fo->opt_opts = strdup(old + 1);
XFREE(old);
}
/*
* If addopts option was used, then append it to the
* current options.
*/
if (fo->opt_addopts) {
char *mergedstr;
mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts);
plog(XLOG_USER, "merge opts \"%s\" add \"%s\" => \"%s\"",
fo->opt_opts, fo->opt_addopts, mergedstr);
XFREE(fo->opt_opts);
fo->opt_opts = mergedstr;
}
/*
* Check the filesystem is happy
*/
if (fo->fs_mtab)
XFREE(fo->fs_mtab);
if ((fo->fs_mtab = (*rop->fs_match) (fo)))
return rop;
/*
* Return error file system
*/
fo->fs_mtab = (*amfs_error_ops.fs_match) (fo);
return &amfs_error_ops;
}

352
contrib/amd/amd/amd.8 Normal file
View File

@ -0,0 +1,352 @@
.\"
.\" Copyright (c) 1997-1998 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.
.\" 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.
.\"
.\" %W% (Berkeley) %G%
.\"
.\" $Id: amd.8,v 5.2.2.1 1992/02/09 15:11:11 jsp beta $
.\"
.TH AMD 8 "3 November 1989"
.SH NAME
amd \- automatically mount file systems
.SH SYNOPSIS
.B amd
.B \-H
.br
.B amd
[
.BI \-F " conf_file"
]
.br
.B amd
[
.B \-nprvHS
] [
.BI \-a " mount_point"
] [
.BI \-c " duration"
] [
.BI \-d " domain"
] [
.BI \-k " kernel-arch"
] [
.BI \-l " logfile"
] [
.BI \-o " op_sys_ver"
] [
.BI \-t " interval.interval"
] [
.BI \-w " interval"
] [
.BI \-x " log-option"
] [
.BI \-y " YP-domain"
] [
.BI \-C " cluster-name"
] [
.BI \-D " option"
] [
.BI \-F " conf_file"
] [
.BI \-O " op_sys_name"
] [
.BI \-T " tag"
]
[
.I directory
.I mapname
.RI [ " \-map-options " ]
] .\|.\|.
.SH DESCRIPTION
.B Amd
is a daemon that automatically mounts filesystems
whenever a file or directory
within that filesystem is accessed.
Filesystems are automatically unmounted when they
appear to have become quiescent.
.LP
.B Amd
operates by attaching itself as an
.SM NFS
server to each of the specified
.IB directories .
Lookups within the specified directories
are handled by
.BR amd ,
which uses the map defined by
.I mapname
to determine how to resolve the lookup.
Generally, this will be a host name, some filesystem information
and some mount options for the given filesystem.
.LP
In the first form depicted above,
.B amd
will print a short help string. In the second form, if no options are
specified, or the
.B -F
is used,
.B amd
will read configuration parameters from the file
.I conf_file
which defaults to
.BR /etc/amd.conf .
The last form is described below.
.SH OPTIONS
.\"*******************************************************"
.TP
.BI \-a " temporary-directory"
Specify an alternative location for the real mount points.
The default is
.BR /a .
.TP
.BI \-c " duration"
Specify a
.IR duration ,
in seconds, that a looked up name remains
cached when not in use. The default is 5 minutes.
.TP
.BI \-d " domain"
Specify the local domain name. If this option is not
given the domain name is determined from the hostname.
.TP
.BI \-k " kernel-arch"
Specifies the kernel architecture. This is used solely
to set the ${karch} selector.
.TP
.BI \-l " logfile"
Specify a logfile in which to record mount and unmount events.
If
.I logfile
is the string
.B syslog
then the log messages will be sent to the system log daemon by
.IR syslog (3).
The default syslog facility used is LOG_DAEMON. If you
wish to change it, append its name to the log file name, delimited by a
single colon. For example, if
.I logfile
is the string
.B syslog:local7
then
.B Amd
will log messages via
.IR syslog (3)
using the LOG_LOCAL7 facility (if it exists on the system).
.TP
.B \-n
Normalize hostnames.
The name refereed to by ${rhost} is normalized relative to the
host database before being used. The effect is to translate
aliases into ``official'' names.
.TP
.BI \-o " op_sys_ver"
Override the compiled-in version number of the operating system. Useful
when the built in version is not desired for backward compatibility reasons.
For example, if the build in version is ``2.5.1'', you can override it to
``5.5.1'', and use older maps that were written with the latter in mind.
.TP
.B \-p
Print PID.
Outputs the process-id of
.B amd
to standard output where it can be saved into a file.
.TP
.B \-r
Restart existing mounts.
.B Amd
will scan the mount file table to determine which filesystems
are currently mounted. Whenever one of these would have
been auto-mounted,
.B amd
.I inherits
it.
.TP
.BI \-t " interval.interval"
Specify the
.IR interval ,
in tenths of a second, between NFS/RPC/UDP retries.
The default is 0.8 seconds.
The second values alters the restransmit counter.
Useful defaults are supplied if either or both
values are missing.
.TP
.B \-v
Version. Displays version and configuration information on standard error.
.TP
.BI \-w " interval"
Specify an
.IR interval ,
in seconds, between attempts to dismount
filesystems that have exceeded their cached times.
The default is 2 minutes.
.TP
.BI \-x " options"
Specify run-time logging options. The options are a comma separated
list chosen from: fatal, error, user, warn, info, map, stats, all.
.TP
.BI \-y " domain"
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 \-C " cluster-name"
Specify an alternative HP-UX cluster name to use.
.TP
.BI \-D " option"
Select from a variety of debug options. Prefixing an
option with the strings
.B no
reverses the effect of that option. Options are cumulative.
The most useful option is
.BR all .
Since
.I \-D
is only used for debugging other options are not documented here:
the current supported set of options is listed by the \-v option
and a fuller description is available in the program source.
.TP
.BI \-F " conf_file"
Specify an amd configuration file to use. See
.BR amd.conf (5)
for description of this file's format. This configuration file is used to
specify any options in lieu of typing many of them on the command line. The
.I amd.conf
file includes directives for every command line option amd has, and many
more that are only available via the configuration file facility. The
configuration file specified by this option is processed after all other
options had been processed, regardless of the actual location of this option
on the command line.
.TP
.B \-H
Print help and usage string.
.TP
.BI \-O " op_sys_name"
Override the compiled-in name of the operating system. Useful when the
built in name is not desired for backward compatibility reasons. For
example, if the build in name is ``sunos5'', you can override it to
``sos5'', and use older maps which were written with the latter in mind.
.TP
.B \-S
Do not lock the running executable pages of amd into memory. To improve
amd's performance, systems that support the
.BR plock (3)
call, could lock the amd process into memory. This way there is less chance
the operating system will schedule, page out, and swap the amd process as
needed. This tends improves amd's performance, at the cost of reserving the
memory used by the amd process (making it unavailable for other processes).
If this behavior is not desired, use the
.B \-S
option.
.TP
.BI \-T " tag"
Specify a tag to use with
.BR amd.conf (5).
All map entries tagged with
.I tag
will be processed. Map entries that are not tagged are always processed.
Map entries that are tagged with a tag other than
.I tag
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
Symbolic links on an NFS filesystem can be incredibly inefficient.
In most implementations of NFS, their interpolations are not cached
by the kernel and each time a symlink is encountered during a
.I lookuppn
translation it costs an RPC call to the NFS server.
It would appear that a large improvement in real-time
performance could be gained by adding a cache somewhere.
Replacing symlinks with a suitable incarnation of the auto-mounter
results in a large real-time speedup, but also causes a large
number of process context switches.
.LP
A weird imagination is most useful to gain full advantage of all
the features.
.SH "SEE ALSO"
.BR amd.conf (5),
.BR amq (8),
.BR domainname (1),
.BR hostname (1),
.BR automount (8),
.BR mount (8),
.BR umount (8),
.BR mtab (5),
.BR syslog (3).
.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.
.P
Other authors and contributors to am-utils are listed in the
.B AUTHORS
file distributed with am-utils.

535
contrib/amd/amd/amd.c Normal file
View File

@ -0,0 +1,535 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amd.c,v 5.2.2.1 1992/02/09 15:08:15 jsp beta $
*
*/
/*
* Automounter
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
struct amu_global_options gopt; /* where global options are stored */
char pid_fsname[16 + MAXHOSTNAMELEN]; /* "kiska.southseas.nz:(pid%d)" */
char *progname; /* "amd" */
char *hostdomain = "unknown.domain";
char hostname[MAXHOSTNAMELEN] = "localhost"; /* Hostname */
char hostd[2 * MAXHOSTNAMELEN]; /* Host+domain */
char *endian = ARCH_ENDIAN; /* Big or Little endian */
char *cpu = HOST_CPU; /* CPU type */
char *PrimNetName; /* name of primary network */
char *PrimNetNum; /* number of primary network */
int foreground = 1; /* This is the top-level server */
int immediate_abort; /* Should close-down unmounts be retried */
int orig_umask;
int select_intr_valid;
jmp_buf select_intr;
pid_t mypid; /* Current process id */
serv_state amd_state;
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_SIGACTION
sigset_t masked_sigs;
#endif /* HAVE_SIGACTION */
/*
* Signal handler:
* SIGINT - tells amd to do a full shutdown, including unmounting all
* filesystem.
* SIGTERM - tells amd to shutdown now. Just unmounts the automount nodes.
*/
static RETSIGTYPE
sigterm(int sig)
{
#ifdef REINSTALL_SIGNAL_HANDLER
signal(sig, sigterm);
#endif /* REINSTALL_SIGNAL_HANDLER */
switch (sig) {
case SIGINT:
immediate_abort = 15;
break;
case SIGTERM:
immediate_abort = -1;
/* fall through... */
default:
plog(XLOG_WARNING, "WARNING: automounter going down on signal %d", sig);
break;
}
if (select_intr_valid)
longjmp(select_intr, sig);
}
/*
* Hook for cache reload.
* When a SIGHUP arrives it schedules a call to mapc_reload
*/
static RETSIGTYPE
sighup(int sig)
{
#ifdef REINSTALL_SIGNAL_HANDLER
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
*/
if (amd_state == Run)
do_mapc_reload = 0;
}
static RETSIGTYPE
parent_exit(int sig)
{
exit(0);
}
static int
daemon_mode(void)
{
int bgpid;
#ifdef HAVE_SIGACTION
struct sigaction sa, osa;
sa.sa_handler = parent_exit;
sa.sa_flags = 0;
sigemptyset(&(sa.sa_mask));
sigaddset(&(sa.sa_mask), SIGQUIT);
sigaction(SIGQUIT, &sa, &osa);
#else /* not HAVE_SIGACTION */
signal(SIGQUIT, parent_exit);
#endif /* not HAVE_SIGACTION */
bgpid = background();
if (bgpid != 0) {
/*
* Now wait for the automount points to
* complete.
*/
for (;;)
pause();
/* should never reache here */
}
#ifdef HAVE_SIGACTION
sigaction(SIGQUIT, &osa, NULL);
#else /* not HAVE_SIGACTION */
signal(SIGQUIT, SIG_DFL);
#endif /* not HAVE_SIGACTION */
/*
* Record our pid to make it easier to kill the correct amd.
*/
if (gopt.flags & CFM_PRINT_PID) {
if (STREQ(gopt.pid_file, "/dev/stdout")) {
printf("%ld\n", (long) mypid);
fflush(stdout);
/* do not fclose stdout */
} else {
FILE *f;
mode_t prev_umask = umask(0022); /* set secure temporary umask */
f = fopen(gopt.pid_file, "w");
if (f) {
fprintf(f, "%ld\n", (long) mypid);
(void) fclose(f);
} else {
fprintf(stderr, "cannot open %s (errno=%d)\n", gopt.pid_file, errno);
}
umask(prev_umask); /* restore umask */
}
}
/*
* Pretend we are in the foreground again
*/
foreground = 1;
/*
* Dissociate from the controlling terminal
*/
amu_release_controlling_tty();
return getppid();
}
/*
* Initialize global options structure.
*/
static void
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) */
memset(&gopt, 0, sizeof(struct amu_global_options));
/* name of current architecture */
gopt.arch = HOST_ARCH;
/* automounter temp dir */
gopt.auto_dir = "/a";
/* cluster name */
gopt.cluster = NULL;
/*
* kernel architecture: this you must get from uname() if possible.
*/
#if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
if (uname(&un) >= 0)
gopt.karch = un.machine;
else
#endif /* defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME) */
gopt.karch = HOST_ARCH;
/* amd log file */
gopt.logfile = NULL;
/* operating system name */
gopt.op_sys = HOST_OS_NAME;
/* OS version */
gopt.op_sys_ver = HOST_OS_VERSION;
/* pid file */
gopt.pid_file = "/dev/stdout";
/* local domain */
gopt.sub_domain = NULL;
/* NFS retransmit counter */
gopt.amfs_auto_retrans = -1;
/* NFS retry interval */
gopt.amfs_auto_timeo = -1;
/* cache duration */
gopt.am_timeo = AM_TTL;
/* dismount interval */
gopt.am_timeo_w = AM_TTL_W;
/*
* various CFM_* flags.
* by default, only the "plock" option is on (if available).
*/
gopt.flags = CFM_PROCESS_LOCK;
#ifdef HAVE_MAP_HESIOD
/* Hesiod rhs zone */
gopt.hesiod_base = "automount";
#endif /* HAVE_MAP_HESIOD */
#ifdef HAVE_MAP_LDAP
/* LDAP base */
gopt.ldap_base = NULL;
/* LDAP host ports */
gopt.ldap_hostports = NULL;
/* LDAP cache */
gopt.ldap_cache_seconds = 0;
gopt.ldap_cache_maxmem = 131072;
#endif /* HAVE_MAP_LDAP */
#ifdef HAVE_MAP_NIS
/* YP domain name */
gopt.nis_domain = NULL;
#endif /* HAVE_MAP_NIS */
}
int
main(int argc, char *argv[])
{
char *domdot, *verstr;
int ppid = 0;
int error;
#ifdef HAVE_SIGACTION
struct sigaction sa;
#endif /* HAVE_SIGACTION */
/*
* Make sure some built-in assumptions are true before we start
*/
assert(sizeof(nfscookie) >= sizeof(u_int));
assert(sizeof(int) >= 4);
/*
* Set processing status.
*/
amd_state = Start;
/*
* Determine program name
*/
if (argv[0]) {
progname = strrchr(argv[0], '/');
if (progname && progname[1])
progname++;
else
progname = argv[0];
}
if (!progname)
progname = "amd";
/*
* Initialise process id. This is kept
* cached since it is used for generating
* and using file handles.
*/
mypid = getpid();
/*
* Get local machine name
*/
if (gethostname(hostname, sizeof(hostname)) < 0) {
plog(XLOG_FATAL, "gethostname: %m");
going_down(1);
}
/*
* Check it makes sense
*/
if (!*hostname) {
plog(XLOG_FATAL, "host name is not set");
going_down(1);
}
/*
* Initialize global options structure.
*/
init_global_options();
/*
* Partially initialise hostd[]. This
* is completed in get_args().
*/
if ((domdot = strchr(hostname, '.'))) {
/*
* Hostname already contains domainname.
* Split out hostname and domainname
* components
*/
*domdot++ = '\0';
hostdomain = domdot;
}
strcpy(hostd, hostname);
/*
* Trap interrupts for shutdowns.
*/
#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 */
/*
* Trap Terminate so that we can shutdown gracefully (some chance)
*/
#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
*/
sigemptyset(&masked_sigs);
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 */
/*
* Fix-up any umask problems. Most systems default
* to 002 which is not too convenient for our purposes
*/
orig_umask = umask(0);
/*
* Figure out primary network name
*/
getwire(&PrimNetName, &PrimNetNum);
/*
* Determine command-line arguments
*/
get_args(argc, argv);
/*
* Log version information.
*/
verstr = strtok(get_version_string(), "\n");
plog(XLOG_INFO, "AM-UTILS VERSION INFORMATION:");
while (verstr) {
plog(XLOG_INFO, verstr);
verstr = strtok(NULL, "\n");
}
/*
* Get our own IP address so that we
* can mount the automounter.
*/
amu_get_myaddress(&myipaddr);
plog(XLOG_INFO, "My ip addr is 0x%x", htonl(myipaddr.s_addr));
/* avoid hanging on other NFS servers if started elsewhere */
if (chdir("/") < 0)
plog(XLOG_INFO, "cannot chdir to /: %m");
/*
* Now check we are root.
*/
if (geteuid() != 0) {
plog(XLOG_FATAL, "Must be root to mount filesystems (euid = %d)", geteuid());
going_down(1);
}
/*
* Lock process text and data segment in memory.
*/
#ifdef HAVE_PLOCK
if (gopt.flags & CFM_PROCESS_LOCK) {
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
* to circumvent any default bindings that may
* be done in the C library.
*/
if (gopt.nis_domain && yp_bind(gopt.nis_domain)) {
plog(XLOG_FATAL, "Can't bind to NIS domain \"%s\"", gopt.nis_domain);
going_down(1);
}
#endif /* HAVE_MAP_NIS */
#ifdef DEBUG
amuDebug(D_DAEMON)
#endif /* DEBUG */
ppid = daemon_mode();
sprintf(pid_fsname, "%s:(pid%ld)", hostname, (long) mypid);
do_mapc_reload = clocktime() + ONE_HOUR;
/*
* Register automounter with system.
*/
error = mount_automounter(ppid);
if (error && ppid)
kill(SIGALRM, ppid);
going_down(error);
abort();
return 1; /* should never get here */
}

303
contrib/amd/amd/amd.h Normal file
View File

@ -0,0 +1,303 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amd.h,v 1.1 1996/01/13 23:23:39 ezk Exp ezk $
*
*/
#ifndef _AMD_H
#define _AMD_H
/*
* MACROS:
*/
/* options for amd.conf */
#define CFM_BROWSABLE_DIRS 0x0001
#define CFM_MOUNT_TYPE_AUTOFS 0x0002
#define CFM_ENABLE_DEFAULT_SELECTORS 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 */
/* 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 */
/* Hash table size */
#define NKVHASH (1 << 2) /* Power of two */
/* interval between forced retries of a mount */
#define RETRY_INTERVAL 2
#define ereturn(x) { *error_return = x; return 0; }
/*
* TYPEDEFS:
*/
typedef struct cf_map cf_map_t;
typedef struct kv kv;
/*
* Cache map operations
*/
typedef void add_fn(mnt_map *, char *, char *);
typedef int init_fn(mnt_map *, char *, time_t *);
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 *);
/*
* STRUCTURES:
*/
/* global amd options that are manipulated by conf.c */
struct amu_global_options {
char *arch; /* name of current architecture */
char *auto_dir; /* automounter temp dir */
char *cluster; /* cluster name */
char *karch; /* kernel architecture */
char *logfile; /* amd log file */
char *op_sys; /* operating system name */
char *op_sys_ver; /* OS version */
char *pid_file; /* PID file */
char *sub_domain; /* local domain */
char *map_options; /* global map options */
char *map_type; /* global map type */
char *search_path; /* search path for maps */
char *mount_type; /* mount type for map */
u_int flags; /* various CFM_* flags */
int amfs_auto_retrans; /* NFS retransmit counter */
int amfs_auto_timeo; /* NFS retry interval */
int am_timeo; /* cache duration */
int am_timeo_w; /* dismount interval */
int portmap_program; /* amd RPC program number */
#ifdef HAVE_MAP_HESIOD
char *hesiod_base; /* Hesiod rhs */
#endif /* HAVE_MAP_HESIOD */
#ifdef HAVE_MAP_LDAP
char *ldap_base; /* LDAP base */
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) */
#endif /* HAVE_MAP_LDAP */
#ifdef HAVE_MAP_NIS
char *nis_domain; /* YP domain name */
#endif /* HAVE_MAP_NIS */
};
/* if you add anything here, update conf.c:reset_cf_map() */
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_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? */
};
/*
* Key-value pair
*/
struct kv {
kv *next;
char *key;
#ifdef HAVE_REGEXEC
regex_t re; /* store the regexp from regcomp() */
#endif /* HAVE_REGEXEC */
char *val;
};
struct mnt_map {
qelem hdr;
int refc; /* Reference count */
short flags; /* Allocation flags */
short alloc; /* Allocation mode */
time_t modify; /* Modify time of map */
char *map_name; /* Name of this map */
char *wildcard; /* Wildcard value */
reload_fn *reload; /* Function to be used for reloads */
isup_fn *isup; /* Is service up or not? (1=up, 0=down) */
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 */
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 succesful.
* We rely on the RPC retry mechanism to resend the lookup request which
* can then be handled.
*/
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 */
};
/*
* EXTERNALS:
*/
/* 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 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);
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_node * autofs_lookuppn(am_node *mp, char *fname, int *error_return, int op);
extern am_node *find_ap(char *);
extern am_node *find_ap2(char *, am_node *);
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 set_conf_kv(const char *section, const char *k, const char *v);
extern int try_mount(voidp mvp);
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 FILE *yyin;
extern SVCXPRT *nfs_program_2_transp; /* For quick_reply() */
extern char *conf_tag;
extern int NumChild;
extern int fwd_sock;
extern int select_intr_valid;
extern int usage;
extern int use_conf_file; /* use amd configuration file */
extern jmp_buf select_intr;
extern qelem mfhead;
extern struct amu_global_options gopt; /* where global options are stored */
#ifdef HAVE_SIGACTION
extern sigset_t masked_sigs;
#endif /* HAVE_SIGACTION */
#if defined(HAVE_AM_FS_LINK) || defined(HAVE_AM_FS_LINKX)
extern char *amfs_link_match(am_opts *fo);
extern int amfs_link_fumount(mntfs *mf);
#endif /* defined(HAVE_AM_FS_LINK) || defined(HAVE_AM_FS_LINKX) */
#ifdef HAVE_AM_FS_NFSL
extern char *nfs_match(am_opts *fo);
#endif /* HAVE_AM_FS_NFSL */
#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) */
#ifdef HAVE_FS_AUTOFS
extern SVCXPRT *autofsxprt;
extern u_short autofs_port;
extern int autofs_mount(am_node *mp);
extern int autofs_umount(am_node *mp);
extern int create_autofs_service(int *soAUTOFSp, u_short *autofs_portp, SVCXPRT **autofs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp));
extern int svc_create_local_service(void (*dispatch) (), u_long prognum, u_long versnum, char *nettype, char *servname);
extern void autofs_mounted(mntfs *mf);
extern void autofs_program_1(struct svc_req *rqstp, SVCXPRT *transp);
#endif /* HAVE_FS_AUTOFS */
/* Unix file system (irix) */
#ifdef HAVE_FS_XFS
extern am_ops xfs_ops; /* Un*x file system */
#endif /* HAVE_FS_XFS */
/* Unix file system (irix) */
#ifdef HAVE_FS_EFS
extern am_ops efs_ops; /* Un*x file system */
#endif /* HAVE_FS_EFS */
#endif /* not _AMD_H */

1595
contrib/amd/amd/amfs_auto.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_direct.c,v 1.1 1997-1998/06/30 19:22:30 ezk Exp ezk $
*
*/
/*
* Direct file system
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/****************************************************************************
*** FORWARD DEFINITIONS ***
****************************************************************************/
static am_node *amfs_direct_readlink(am_node *mp, int *error_return);
/****************************************************************************
*** OPS STRUCTURES ***
****************************************************************************/
am_ops amfs_direct_ops =
{
"direct",
amfs_auto_match,
0, /* amfs_direct_init */
amfs_toplvl_mount,
0,
amfs_toplvl_umount,
0,
amfs_error_lookuppn,
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
};
/****************************************************************************
*** FUNCTIONS ***
****************************************************************************/
static am_node *
amfs_direct_readlink(am_node *mp, int *error_return)
{
am_node *xp;
int rc = 0;
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);
}
if (xp) {
new_ttl(xp); /* (7/12/89) from Rein Tollevik */
return xp;
}
if (amd_state == Finishing)
rc = ENOENT;
*error_return = rc;
return 0;
}

View File

@ -0,0 +1,150 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_error.c,v 5.2.2.1 1992/02/09 15:08:21 jsp beta $
*
*/
/*
* Error file system.
* This is used as a last resort catchall if
* nothing else worked. EFS just returns lots
* of error codes, except for unmount which
* always works of course.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#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);
/*
* Ops structure
*/
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_readdir,
0, /* amfs_error_readlink */
0, /* amfs_error_mounted */
amfs_error_umounted,
find_amfs_auto_srvr,
FS_DISCARD
};
/*
* EFS file system always matches
*/
static char *
amfs_error_match(am_opts *fo)
{
return strdup("(error-hook)");
}
static int
amfs_error_fmount(mntfs *mf)
{
return ENOENT;
}
static int
amfs_error_fumount(mntfs *mf)
{
/*
* Always succeed
*/
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_lookuppn(am_node *mp, char *fname, int *error_return, int op)
{
*error_return = ESTALE;
return 0;
}
/*
* EFS interface to RPC readdir() routine.
* Should never get here in the automounter.
* If we do then just give an error.
*/
int
amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, 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 */
}

686
contrib/amd/amd/amfs_host.c Normal file
View File

@ -0,0 +1,686 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_host.c,v 5.2.2.2 1992/05/31 16:36:08 jsp Exp $
*
*/
/*
* NFS host file system.
* Mounts all exported filesystems from a given host.
* This has now degenerated into a mess but will not
* be rewritten. Amd 6 will support the abstractions
* needed to make this work correctly.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#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);
/*
* Ops structure
*/
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_error_readdir,
0, /* amfs_host_readlink */
0, /* amfs_host_mounted */
amfs_host_umounted,
find_nfs_srvr,
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO
};
/*
* Determine the mount point:
*
* The next change we put in to better handle PCs. This is a bit
* disgusting, so you'd better sit down. We change the make_mntpt function
* to look for exported file systems without a leading '/'. If they don't
* have a leading '/', we add one. If the export is 'a:' through 'z:'
* (without a leading slash), we change it to 'a%' (or b% or z%). This
* allows the entire PC disk to be mounted.
*/
static void
make_mntpt(char *mntpt, const exports ex, const mntfs *mf)
{
if (ex->ex_dir[0] == '/') {
if (ex->ex_dir[1] == 0)
strcpy(mntpt, (mf)->mf_mount);
else
sprintf(mntpt, "%s%s", mf->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]);
else
sprintf(mntpt, "%s/%s", mf->mf_mount, ex->ex_dir);
}
/*
* Execute needs the same as NFS plus a helper command
*/
static char *
amfs_host_match(am_opts *fo)
{
extern am_ops nfs_ops;
/*
* Make sure rfs is specified to keep nfs_match happy...
*/
if (!fo->opt_rfs)
fo->opt_rfs = "/";
return (*nfs_ops.fs_match) (fo);
}
static int
amfs_host_init(mntfs *mf)
{
fserver *fs;
u_short port;
if (strchr(mf->mf_info, ':') == 0)
return ENOENT;
/*
* This is primarily to schedule a wakeup so that as soon
* as our fileserver is ready, we can continue setting up
* the host filesystem. If we don't do this, the standard
* amfs_auto code will set up a fileserver structure, but it will
* have to wait for another nfs request from the client to come
* in before finishing. Our way is faster since we don't have
* to wait for the client to resend its request (which could
* take a second or two).
*/
/*
* 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
* 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
* this mount is retried.
*/
if ((fs = 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);
return 0;
}
static int
do_mount(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *mf)
{
struct stat stb;
#ifdef DEBUG
dlog("amfs_host: mounting fs %s on %s\n", fs_name, dir);
#endif /* DEBUG */
(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);
return ENOENT;
}
return mount_nfs_fh(fhp, dir, fs_name, opts, mf);
}
static int
sortfun(const voidp x, const voidp y)
{
exports *a = (exports *) x;
exports *b = (exports *) y;
return strcmp((*a)->ex_dir, (*b)->ex_dir);
}
/*
* Get filehandle
*/
static int
fetch_fhandle(CLIENT * client, char *dir, am_nfs_handle_t *fhp, u_long nfs_version)
{
struct timeval tv;
enum clnt_stat clnt_stat;
/*
* Pick a number, any number...
*/
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
* get the filehandle. Use NFS version specific call.
*/
plog(XLOG_INFO, "fetch_fhandle: NFS version %d", nfs_version);
#ifdef HAVE_FS_NFS3
if (nfs_version == NFS_VERSION3) {
memset((char *) &fhp->v3, 0, sizeof(fhp->v3));
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,
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
dlog("fhandle fetch for mount version 3 failed: %m");
#endif /* DEBUG */
return errno;
}
} else { /* not NFS_VERSION3 mount */
#endif /* HAVE_FS_NFS3 */
clnt_stat = clnt_call(client,
MOUNTPROC_MNT,
(XDRPROC_T_TYPE) xdr_dirpath,
(SVC_IN_ARG_TYPE) &dir,
(XDRPROC_T_TYPE) xdr_fhstatus,
(SVC_IN_ARG_TYPE) &fhp->v2,
tv);
if (clnt_stat != RPC_SUCCESS) {
char *msg = clnt_sperrno(clnt_stat);
plog(XLOG_ERROR, "mountd rpc failed: %s", msg);
return EIO;
}
/* Check status of filehandle */
if (fhp->v2.fhs_status) {
errno = fhp->v2.fhs_status;
#ifdef DEBUG
dlog("fhandle fetch for mount version 1 failed: %m");
#endif /* DEBUG */
return errno;
}
#ifdef HAVE_FS_NFS3
} /* end of "if (nfs_version == NFS_VERSION3)" statement */
#endif /* HAVE_FS_NFS3 */
/* all is well */
return 0;
}
/*
* Scan mount table to see if something already mounted
*/
static int
already_mounted(mntlist *mlist, char *dir)
{
mntlist *ml;
for (ml = mlist; ml; ml = ml->mnext)
if (STREQ(ml->mnt->mnt_dir, dir))
return 1;
return 0;
}
/*
* Mount the export tree from a host
*/
static int
amfs_host_fmount(mntfs *mf)
{
struct timeval tv2;
CLIENT *client;
enum clnt_stat clnt_stat;
int n_export;
int j, k;
exports exlist = 0, ex;
exports *ep = 0;
am_nfs_handle_t *fp = 0;
char *host;
int error = 0;
struct sockaddr_in sin;
int sock = RPC_ANYSOCK;
int ok = FALSE;
mntlist *mlist;
char fs_name[MAXPATHLEN], *rfs_dir;
char mntpt[MAXPATHLEN];
struct timeval tv;
u_long mnt_version;
/*
* Read the mount list
*/
mlist = read_mtab(mf->mf_mount, mnttab_file_name);
#ifdef MOUNT_TABLE_ON_FILE
/*
* Unlock the mount list
*/
unlock_mntlist();
#endif /* MOUNT_TABLE_ON_FILE */
/*
* Take a copy of the server hostname, address, and nfs version
* to mount version conversion.
*/
host = mf->mf_server->fs_host;
sin = *mf->mf_server->fs_ip;
plog(XLOG_INFO, "amfs_host_fmount: NFS version %d", mf->mf_server->fs_version);
#ifdef HAVE_FS_NFS3
if (mf->mf_server->fs_version == NFS_VERSION3)
mnt_version = MOUNTVERS3;
else
#endif /* HAVE_FS_NFS3 */
mnt_version = MOUNTVERS;
/*
* The original 10 second per try timeout is WAY too large, especially
* if we're only waiting 10 or 20 seconds max for the response.
* That would mean we'd try only once in 10 seconds, and we could
* lose the transmitt or receive packet, and never try again.
* A 2-second per try timeout here is much more reasonable.
* 09/28/92 Mike Mitchell, mcm@unx.sas.com
*/
tv.tv_sec = 2;
tv.tv_usec = 0;
/*
* Create a client attached to mountd
*/
client = get_mount_client(host, &sin, &tv, &sock, mnt_version);
if (client == NULL) {
#ifdef HAVE_CLNT_SPCREATEERROR
plog(XLOG_ERROR, "get_mount_client failed for %s: %s",
host, clnt_spcreateerror(""));
#else /* not HAVE_CLNT_SPCREATEERROR */
plog(XLOG_ERROR, "get_mount_client failed for %s", host);
#endif /* not HAVE_CLNT_SPCREATEERROR */
error = EIO;
goto out;
}
if (!nfs_auth) {
error = make_nfs_auth();
if (error)
goto out;
}
client->cl_auth = nfs_auth;
#ifdef DEBUG
dlog("Fetching export list from %s", host);
#endif /* DEBUG */
/*
* Fetch the export list
*/
tv2.tv_sec = 10;
tv2.tv_usec = 0;
clnt_stat = clnt_call(client,
MOUNTPROC_EXPORT,
(XDRPROC_T_TYPE) xdr_void,
0,
(XDRPROC_T_TYPE) xdr_exports,
(SVC_IN_ARG_TYPE) & exlist,
tv2);
if (clnt_stat != RPC_SUCCESS) {
char *msg = clnt_sperrno(clnt_stat);
plog(XLOG_ERROR, "host_fmount rpc failed: %s", msg);
/* clnt_perror(client, "rpc"); */
error = EIO;
goto out;
}
/*
* Figure out how many exports were returned
*/
for (n_export = 0, ex = exlist; ex; ex = ex->ex_next) {
/* printf("export %s\n", ex->ex_dir); */
n_export++;
}
/*
* Allocate an array of pointers into the list
* so that they can be sorted. If the filesystem
* is already mounted then ignore it.
*/
ep = (exports *) xmalloc(n_export * sizeof(exports));
for (j = 0, ex = exlist; ex; ex = ex->ex_next) {
make_mntpt(mntpt, ex, mf);
if (!already_mounted(mlist, mntpt))
ep[j++] = ex;
}
n_export = j;
/*
* Sort into order.
* This way the mounts are done in order down the tree,
* instead of any random order returned by the mount
* daemon (the protocol doesn't specify...).
*/
qsort(ep, n_export, sizeof(exports), sortfun);
/*
* Allocate an array of filehandles
*/
fp = (am_nfs_handle_t *) xmalloc(n_export * sizeof(am_nfs_handle_t));
/*
* Try to obtain filehandles for each directory.
* If a fetch fails then just zero out the array
* reference but discard the error.
*/
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;
error = fetch_fhandle(client, ep[j]->ex_dir, &fp[j],
mf->mf_server->fs_version);
if (error)
ep[j] = 0;
}
}
/*
* Mount each filesystem for which we have a filehandle.
* If any of the mounts succeed then mark "ok" and return
* 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));
if ((rfs_dir = strchr(fs_name, ':')) == (char *) 0) {
plog(XLOG_FATAL, "amfs_host_fmount: mf_info has no colon");
error = EINVAL;
goto out;
}
++rfs_dir;
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)
ok = TRUE;
}
}
/*
* Clean up and exit
*/
out:
discard_mntlist(mlist);
if (ep)
XFREE(ep);
if (fp)
XFREE(fp);
if (sock != RPC_ANYSOCK)
(void) amu_close(sock);
if (client)
clnt_destroy(client);
if (exlist)
xdr_pri_free((XDRPROC_T_TYPE) xdr_exports, (caddr_t) &exlist);
if (ok)
return 0;
return error;
}
/*
* Return true if pref is a directory prefix of dir.
*
* XXX TODO:
* Does not work if pref is "/".
*/
static int
directory_prefix(char *pref, char *dir)
{
int len = strlen(pref);
if (!NSTREQ(pref, dir, len))
return FALSE;
if (dir[len] == '/' || dir[len] == '\0')
return TRUE;
return FALSE;
}
/*
* Unmount a mount tree
*/
static int
amfs_host_fumount(mntfs *mf)
{
mntlist *ml, *mprev;
int xerror = 0;
/*
* Read the mount list
*/
mntlist *mlist = read_mtab(mf->mf_mount, mnttab_file_name);
#ifdef MOUNT_TABLE_ON_FILE
/*
* Unlock the mount list
*/
unlock_mntlist();
#endif /* MOUNT_TABLE_ON_FILE */
/*
* Reverse list...
*/
ml = mlist;
mprev = 0;
while (ml) {
mntlist *ml2 = ml->mnext;
ml->mnext = mprev;
mprev = ml;
ml = ml2;
}
mlist = mprev;
/*
* Unmount all filesystems...
*/
for (ml = mlist; ml && !xerror; ml = ml->mnext) {
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);
/*
* Keep track of errors
*/
if (error) {
if (!xerror)
xerror = error;
if (error != EBUSY) {
errno = error;
plog(XLOG_ERROR, "Tree unmount of %s failed: %m", ml->mnt->mnt_dir);
}
} else {
(void) rmdirs(dir);
}
}
}
/*
* Throw away mount list
*/
discard_mntlist(mlist);
/*
* Try to remount, except when we are shutting down.
*/
if (xerror && amd_state != Finishing) {
xerror = amfs_host_fmount(mf);
if (!xerror) {
/*
* Don't log this - it's usually too verbose
plog(XLOG_INFO, "Remounted host %s", mf->mf_info);
*/
xerror = EBUSY;
}
}
return xerror;
}
/*
* Tell mountd we're done.
* This is not quite right, because we may still
* have other filesystems mounted, but the existing
* mountd protocol is badly broken anyway.
*/
static void
amfs_host_umounted(am_node *mp)
{
mntfs *mf = mp->am_mnt;
char *host;
CLIENT *client;
enum clnt_stat clnt_stat;
struct sockaddr_in sin;
int sock = RPC_ANYSOCK;
struct timeval tv;
u_long mnt_version;
if (mf->mf_error || mf->mf_refc > 1 || !mf->mf_server)
return;
/*
* Take a copy of the server hostname, address, and NFS version
* to mount version conversion.
*/
host = mf->mf_server->fs_host;
sin = *mf->mf_server->fs_ip;
plog(XLOG_INFO, "amfs_host_umounted: NFS version %d", mf->mf_server->fs_version);
#ifdef HAVE_FS_NFS3
if (mf->mf_server->fs_version == NFS_VERSION3)
mnt_version = MOUNTVERS3;
else
#endif /* HAVE_FS_NFS3 */
mnt_version = MOUNTVERS;
/*
* Create a client attached to mountd
*/
tv.tv_sec = 10;
tv.tv_usec = 0;
client = get_mount_client(host, &sin, &tv, &sock, mnt_version);
if (client == NULL) {
#ifdef HAVE_CLNT_SPCREATEERROR
plog(XLOG_ERROR, "get_mount_client failed for %s: %s",
host, clnt_spcreateerror(""));
#else /* not HAVE_CLNT_SPCREATEERROR */
plog(XLOG_ERROR, "get_mount_client failed for %s", host);
#endif /* not HAVE_CLNT_SPCREATEERROR */
goto out;
}
if (!nfs_auth) {
if (make_nfs_auth())
goto out;
}
client->cl_auth = nfs_auth;
#ifdef DEBUG
dlog("Unmounting all from %s", host);
#endif /* DEBUG */
clnt_stat = clnt_call(client,
MOUNTPROC_UMNTALL,
(XDRPROC_T_TYPE) xdr_void,
0,
(XDRPROC_T_TYPE) xdr_void,
0,
tv);
if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_SYSTEMERROR) {
/* RPC_SYSTEMERROR seems to be returned for no good reason ... */
char *msg = clnt_sperrno(clnt_stat);
plog(XLOG_ERROR, "unmount all from %s rpc failed: %s", host, msg, clnt_stat);
goto out;
}
out:
if (sock != RPC_ANYSOCK)
(void) amu_close(sock);
if (client)
clnt_destroy(client);
}

View File

@ -0,0 +1,200 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_inherit.c,v 5.2.2.1 1992/02/09 15:08:26 jsp beta $
*
*/
/*
* Inheritance file system.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/*
* This implements a filesystem restart.
*
* This is a *gross* hack - it knows far too
* much about the way other parts of the
* system work. See restart.c too.
*/
static char *amfs_inherit_match(am_opts *fo);
static int amfs_inherit_fmount(mntfs *mf);
static int amfs_inherit_fumount(mntfs *mf);
static int amfs_inherit_init(mntfs *mf);
static int amfs_inherit_mount(am_node *mp);
/*
* Ops structure
*/
am_ops amfs_inherit_ops =
{
"inherit",
amfs_inherit_match,
amfs_inherit_init,
amfs_inherit_mount,
amfs_inherit_fmount,
amfs_auto_fumount,
amfs_inherit_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* amfs_inherit_readlink */
0, /* amfs_inherit_mounted */
0, /* amfs_inherit_umounted */
find_amfs_auto_srvr,
FS_DISCARD
};
/*
* This should never be called.
*/
static char *
amfs_inherit_match(am_opts *fo)
{
plog(XLOG_FATAL, "amfs_inherit_match called!");
return 0;
}
static int
amfs_inherit_init(mntfs *mf)
{
mntfs *mf_link = (mntfs *) mf->mf_private;
if (mf_link == 0) {
plog(XLOG_ERROR, "Remount collision on %s?", mf->mf_mount);
plog(XLOG_FATAL, "Attempting to init not-a-filesystem");
return EINVAL;
}
if (mf_link->mf_ops->fs_init)
return (*mf_link->mf_ops->fs_init) (mf_link);
return 0;
}
/*
* Take the linked mount point and
* propogate.
*/
static mntfs *
amfs_inherit_inherit(mntfs *mf)
{
mntfs *mf_link = (mntfs *) mf->mf_private;
if (mf_link == 0) {
plog(XLOG_FATAL, "Attempting to inherit not-a-filesystem");
return 0; /* XXX */
}
mf_link->mf_fo = mf->mf_fo;
/*
* Discard the old map.
* Don't call am_unmounted since this
* node was never really mounted in the
* first place.
*/
mf->mf_private = 0;
free_mntfs(mf);
/*
* Free the dangling reference
* to the mount link.
*/
free_mntfs(mf_link);
/*
* Get a hold of the other entry
*/
mf_link->mf_flags &= ~MFF_RESTART;
/* Say what happened */
plog(XLOG_INFO, "restarting %s on %s", mf_link->mf_info, mf_link->mf_mount);
return mf_link;
}
static int
amfs_inherit_mount(am_node *mp)
{
mntfs *newmf = amfs_inherit_inherit(mp->am_mnt);
if (newmf) {
mp->am_mnt = newmf;
/*
* XXX - must do the am_mounted call here
*/
if (newmf->mf_ops->fs_flags & FS_MBACKGROUND)
am_mounted(mp);
new_ttl(mp);
return 0;
}
return EINVAL;
}
static int
amfs_inherit_fmount(mntfs *mf)
{
am_node *mp = find_mf(mf);
if (mp)
return amfs_inherit_mount(mp);
return amfs_inherit_inherit(mf) ? 0 : EINVAL;
}
static int
amfs_inherit_fumount(mntfs *mf)
{
/*
* Always succeed
*/
return 0;
}

141
contrib/amd/amd/amfs_link.c Normal file
View File

@ -0,0 +1,141 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_link.c,v 5.2.2.1 1992/02/09 15:09:04 jsp beta $
*
*/
/*
* Symbol-link file system
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/*
* Ops structures
*/
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_error_readdir,
0, /* amfs_link_readlink */
0, /* amfs_link_mounted */
0, /* amfs_link_umounted */
find_amfs_auto_srvr,
0
};
/*
* SFS needs a link.
*/
char *
amfs_link_match(am_opts *fo)
{
if (!fo->opt_fs) {
plog(XLOG_USER, "link: no fs specified");
return 0;
}
/*
* 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 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.
*
* If sublink is nil then set sublink to fs
* else set sublink to fs / sublink
*
* Finally set fs to ".".
*/
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, "");
}
return strdup(fo->opt_fs);
}
int
amfs_link_fmount(mntfs *mf)
{
/*
* Wow - this is hard to implement! :-)
*/
return 0;
}
int
amfs_link_fumount(mntfs *mf)
{
return 0;
}

View File

@ -0,0 +1,104 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_linkx.c,v 5.2.2.1 1992/02/09 15:09:04 jsp beta $
*
*/
/*
* Symbol-link file system, with test that the target of the link exists.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* forward declarations */
static int amfs_linkx_mount(am_node *mp);
/*
* linkx operations
*/
struct am_ops amfs_linkx_ops =
{
"linkx",
amfs_link_match,
0, /* amfs_linkx_init */
amfs_linkx_mount,
0,
amfs_auto_fumount,
amfs_link_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* amfs_linkx_readlink */
0, /* amfs_linkx_mounted */
0, /* amfs_linkx_umounted */
find_amfs_auto_srvr,
FS_MBACKGROUND
};
static int
amfs_linkx_mount(am_node *mp)
{
/*
* Check for existence of target.
*/
struct stat stb;
char *ln;
if (mp->am_link)
ln = mp->am_link;
else /* should never occur */
ln = mp->am_mnt->mf_mount;
/*
* Use lstat, not stat, since we don't
* want to know if the ultimate target of
* a symlink chain exists, just the first.
*/
if (lstat(ln, &stb) < 0)
return errno;
return 0;
}

237
contrib/amd/amd/amfs_nfsl.c Normal file
View File

@ -0,0 +1,237 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_nfsl.c,v 5.2.2.3 1992/08/02 10:42:21 jsp Exp $
*
*/
/*
* NFSL: Network file system with local existence check. If the local
* path denoted by $rfs exists, it behaves as type:=link.
*
* Example:
* pkg type:=nfsl;rhost:=jonny;rfs:=/n/johnny/src/pkg;fs:=${rfs}
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* 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 fserver *amfs_nfsl_ffserver(mntfs *mf);
/*
* NFS-Link operations
*/
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 */
};
/*
* Check that f/s has all needed fields.
* Returns: matched string if found, NULL otherwise.
*/
static char *
amfs_nfsl_match(am_opts *fo)
{
char *cp = fo->opt_fs;
char *ho = fo->opt_rhost;
struct stat stb;
if (!cp || !ho) {
plog(XLOG_USER, "amfs_nfsl: nost $fs and $rhost must be specified");
return NULL;
}
/*
* 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.
*/
if (!STRCEQ(ho, hostname)) {
plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not local host, using type:=nfs", ho);
return nfs_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);
} else {
plog(XLOG_INFO, "amfs_nfsl: \"%s\" exists, using type:=link", cp);
return amfs_link_match(fo);
}
}
/*
* Initialize.
* Returns: 0 if OK, non-zero (errno) if failed.
*/
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).
*/
if (mf->mf_flags & MFF_NFSLINK) {
return 0;
} else {
return nfs_init(mf);
}
}
/*
* Mount vfs.
* Returns: 0 if OK, non-zero (errno) if failed.
*/
static int
amfs_nfsl_fmount(mntfs *mf)
{
/*
* If a link, do run amfs_link_fmount() (same as type:=link)
* If non-link, do nfs_fmount (same as type:=nfs).
*/
if (mf->mf_flags & MFF_NFSLINK) {
return amfs_link_fmount(mf);
} else {
return nfs_fmount(mf);
}
}
/*
* Unmount VFS.
* Returns: 0 if OK, non-zero (errno) if failed.
*/
static int
amfs_nfsl_fumount(mntfs *mf)
{
/*
* If a link, do run amfs_link_fumount() (same as type:=link)
* If non-link, do nfs_fumount (same as type:=nfs).
*/
if (mf->mf_flags & MFF_NFSLINK) {
return amfs_link_fumount(mf);
} else {
return nfs_fumount(mf);
}
}
/*
* Async unmount callback function.
* After the base umount() succeeds, we may want to take extra actions,
* such as informing remote mount daemons that we've unmounted them.
* See amfs_auto_umounted(), host_umounted(), nfs_umounted().
*/
static void
amfs_nfsl_umounted(am_node *mp)
{
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;
} 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;
}
}
/*
* Find a file server.
* Returns: fserver of found server, or NULL if not found.
*/
static fserver *
amfs_nfsl_ffserver(mntfs *mf)
{
char *cp = mf->mf_fo->opt_fs;
char *ho = mf->mf_fo->opt_rhost;
struct stat stb;
/*
* 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.
*/
if (!STREQ(ho, hostname) || lstat(cp, &stb) < 0) {
return find_nfs_srvr(mf);
} else {
mf->mf_flags |= MFF_NFSLINK;
return find_amfs_auto_srvr(mf);
}
}

532
contrib/amd/amd/amfs_nfsx.c Normal file
View File

@ -0,0 +1,532 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_linxx.c,v 5.2.2.3 1992/05/31 16:13:07 jsp Exp $
*
*/
/*
* NFS hierarchical mounts
*
* TODO: Re-implement.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/*
* The rfs field contains a list of mounts to be done from
* the remote host.
*/
typedef struct amfs_nfsx_mnt {
mntfs *n_mnt;
int n_error;
} amfs_nfsx_mnt;
struct amfs_nfsx {
int nx_c; /* Number of elements in nx_v */
amfs_nfsx_mnt *nx_v; /* Underlying mounts */
amfs_nfsx_mnt *nx_try;
};
/* 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_init(mntfs *mf);
/*
* Ops structure
*/
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_error_readdir,
0, /* amfs_nfsx_readlink */
0, /* amfs_nfsx_mounted */
0, /* amfs_nfsx_umounted */
find_nfs_srvr, /* XXX */
/* FS_UBACKGROUND| */ FS_AMQINFO
};
static char *
amfs_nfsx_match(am_opts *fo)
{
char *xmtab;
char *ptr;
int len;
if (!fo->opt_rfs) {
plog(XLOG_USER, "amfs_nfsx: no remote filesystem specified");
return FALSE;
}
if (!fo->opt_rhost) {
plog(XLOG_USER, "amfs_nfsx: no remote host specified");
return FALSE;
}
/* set default sublink */
if (fo->opt_sublink == 0) {
ptr = strchr(fo->opt_rfs, ',');
if (ptr && ptr != (fo->opt_rfs + 1))
fo->opt_sublink = strnsave(fo->opt_rfs + 1, ptr - fo->opt_rfs - 1);
}
/*
* Remove trailing ",..." from ${fs}
* After deslashifying, overwrite the end of ${fs} with "/"
* to make sure it is unique.
*/
if ((ptr = strchr(fo->opt_fs, ',')))
*ptr = '\0';
deslashify(fo->opt_fs);
/*
* Bump string length to allow trailing /
*/
len = strlen(fo->opt_fs);
fo->opt_fs = xrealloc(fo->opt_fs, len + 1 + 1);
ptr = fo->opt_fs + len;
/*
* Make unique...
*/
*ptr++ = '/';
*ptr = '\0';
/*
* Determine magic cookie to put in mtab
*/
xmtab = str3cat((char *) 0, fo->opt_rhost, ":", fo->opt_rfs);
#ifdef DEBUG
dlog("NFS: 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)
{
struct amfs_nfsx *nx = (struct amfs_nfsx *) vp;
int i;
for (i = 0; i < nx->nx_c; i++) {
mntfs *m = nx->nx_v[i].n_mnt;
if (m)
free_mntfs(m);
}
XFREE(nx->nx_v);
XFREE(nx);
}
static int
amfs_nfsx_init(mntfs *mf)
{
/*
* mf_info has the form:
* host:/prefix/path,sub,sub,sub
*/
int i;
int glob_error;
struct amfs_nfsx *nx;
int asked_for_wakeup = 0;
nx = (struct amfs_nfsx *) mf->mf_private;
if (nx == 0) {
char **ivec;
char *info = 0;
char *host;
char *pref;
int error = 0;
info = strdup(mf->mf_info);
host = strchr(info, ':');
if (!host) {
error = EINVAL;
goto errexit;
}
pref = host +1;
host = info;
/*
* Split the prefix off from the suffices
*/
ivec = strsplit(pref, ',', '\'');
/*
* Count array size
*/
for (i = 0; ivec[i]; i++) ;
nx = ALLOC(struct amfs_nfsx);
mf->mf_private = (voidp) 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));
{
char *mp = 0;
char *xinfo = 0;
char *fs = mf->mf_fo->opt_fs;
char *rfs = 0;
for (i = 0; i < nx->nx_c; i++) {
char *path = ivec[i + 1];
rfs = str3cat(rfs, pref, "/", path);
/*
* Determine the mount point.
* If this is the root, then don't remove
* the trailing slash to avoid mntfs name clashes.
*/
mp = str3cat(mp, fs, "/", rfs);
normalize_slash(mp);
deslashify(mp);
/*
* Determine the mount info
*/
xinfo = str3cat(xinfo, host, *path == '/' ? "" : "/", path);
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);
}
if (rfs)
XFREE(rfs);
if (mp)
XFREE(mp);
if (xinfo)
XFREE(xinfo);
}
XFREE(ivec);
errexit:
if (info)
XFREE(info);
if (error)
return error;
}
/*
* Iterate through the mntfs's and call
* the underlying init routine on each
*/
glob_error = 0;
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);
/*
* 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
* here before.
*/
if (error > 0)
n->n_error = error;
else if (error < 0) {
glob_error = -1;
if (!asked_for_wakeup) {
asked_for_wakeup = 1;
sched_task(wakeup_task, (voidp) mf, (voidp) m);
}
}
}
return glob_error;
}
static void
amfs_nfsx_cont(int rc, int term, voidp closure)
{
mntfs *mf = (mntfs *) closure;
struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private;
amfs_nfsx_mnt *n = nx->nx_try;
n->n_mnt->mf_flags &= ~(MFF_ERROR | MFF_MOUNTING);
mf->mf_flags &= ~MFF_ERROR;
/*
* Wakeup anything waiting for this mount
*/
wakeup((voidp) n->n_mnt);
if (rc || term) {
if (term) {
/*
* Not sure what to do for an error code.
*/
plog(XLOG_ERROR, "mount for %s got signal %d", n->n_mnt->mf_mount, term);
n->n_error = EIO;
} else {
/*
* Check for exit status
*/
errno = rc; /* XXX */
plog(XLOG_ERROR, "%s: mount (amfs_nfsx_cont): %m", n->n_mnt->mf_mount);
n->n_error = rc;
}
free_mntfs(n->n_mnt);
n->n_mnt = new_mntfs();
n->n_mnt->mf_error = n->n_error;
n->n_mnt->mf_flags |= MFF_ERROR;
} else {
/*
* The mount worked.
*/
mf_mounted(n->n_mnt);
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);
}
}
static int
try_amfs_nfsx_mount(voidp mv)
{
mntfs *mf = (mntfs *) mv;
int error;
mf->mf_flags |= MFF_MOUNTING;
error = (*mf->mf_ops->fmount_fs) (mf);
mf->mf_flags &= ~MFF_MOUNTING;
return error;
}
static int
amfs_nfsx_remount(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;
}
}
}
/*
* Iterate through the mntfs's and mount each filesystem
* which is not yet mounted.
*/
for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) {
mntfs *m = n->n_mnt;
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);
}
}
#ifdef DEBUG
if (n->n_error > 0) {
errno = n->n_error; /* XXX */
dlog("underlying fmount of %s failed: %m", m->mf_mount);
}
#endif /* DEBUG */
if (n->n_error == 0) {
glob_error = 0;
} else if (glob_error < 0) {
glob_error = n->n_error;
}
}
}
return glob_error < 0 ? 0 : glob_error;
}
static int
amfs_nfsx_fmount(mntfs *mf)
{
return amfs_nfsx_remount(mf, FALSE);
}
/*
* Unmount an NFS hierarchy.
* Note that this is called in the foreground
* and so may hang under extremely rare conditions.
*/
static int
amfs_nfsx_fumount(mntfs *mf)
{
struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private;
amfs_nfsx_mnt *n;
int glob_error = 0;
/*
* Iterate in reverse through the mntfs's and unmount each filesystem
* which is mounted.
*/
for (n = nx->nx_v + nx->nx_c - 1; n >= nx->nx_v; --n) {
mntfs *m = n->n_mnt;
/*
* If this node has not been messed with
* and there has been no error so far
* then try and unmount.
* If an error had occured then zero
* the error code so that the remount
* only tries to unmount those nodes
* 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);
if (n->n_error) {
glob_error = n->n_error;
n->n_error = 0;
} else {
/*
* Make sure remount gets this node
*/
n->n_error = -1;
}
}
}
/*
* If any unmounts failed then remount the
* whole lot...
*/
if (glob_error) {
glob_error = amfs_nfsx_remount(mf, TRUE);
if (glob_error) {
errno = glob_error; /* XXX */
plog(XLOG_USER, "amfs_nfsx: remount of %s failed: %m", mf->mf_mount);
}
glob_error = EBUSY;
} else {
/*
* Remove all the mount points
*/
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 (n->n_error < 0) {
if (m->mf_ops->fs_flags & FS_MKMNT) {
(void) rmdirs(m->mf_mount);
m->mf_flags &= ~MFF_MKMNT;
}
}
free_mntfs(m);
n->n_mnt = 0;
n->n_error = -1;
}
}
return glob_error;
}

View File

@ -0,0 +1,191 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_program.c,v 5.2.2.1 1992/02/09 15:08:56 jsp beta $
*
*/
/*
* Program file system
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* 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_init(mntfs *mf);
/*
* Ops structure
*/
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_error_readdir,
0, /* amfs_program_readlink */
0, /* amfs_program_mounted */
0, /* amfs_program_umounted */
find_amfs_auto_srvr,
FS_BACKGROUND | FS_AMQINFO
};
/*
* Execute needs a mount and unmount command.
*/
static char *
amfs_program_match(am_opts *fo)
{
char *prog;
if (!fo->opt_mount || !fo->opt_unmount) {
plog(XLOG_USER, "program: no mount/unmount specified");
return 0;
}
prog = strchr(fo->opt_mount, ' ');
return strdup(prog ? prog + 1 : fo->opt_mount);
}
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;
}
return 0;
}
static int
amfs_program_exec(char *info)
{
char **xivec;
int error;
/*
* Split copy of command info string
*/
info = strdup(info);
if (info == 0)
return ENOBUFS;
xivec = strsplit(info, ' ', '\'');
/*
* Put stdout to stderr
*/
(void) fclose(stdout);
(void) dup(fileno(logfp));
if (fileno(logfp) != fileno(stderr)) {
(void) fclose(stderr);
(void) dup(fileno(logfp));
}
/*
* Try the exec
*/
#ifdef DEBUG
amuDebug(D_FULL) {
char **cp = xivec;
plog(XLOG_DEBUG, "executing (un)mount command...");
while (*cp) {
plog(XLOG_DEBUG, "arg[%d] = '%s'", cp - xivec, *cp);
cp++;
}
}
#endif /* DEBUG */
if (xivec[0] == 0 || xivec[1] == 0) {
errno = EINVAL;
plog(XLOG_USER, "1st/2nd args missing to (un)mount program");
} else {
(void) execv(xivec[0], xivec + 1);
}
/*
* Save error number
*/
error = errno;
plog(XLOG_ERROR, "exec failed: %m");
/*
* Free allocate memory
*/
XFREE(info);
XFREE(xivec);
/*
* Return error
*/
return error;
}
static int
amfs_program_fmount(mntfs *mf)
{
return amfs_program_exec(mf->mf_fo->opt_mount);
}
static int
amfs_program_fumount(mntfs *mf)
{
return amfs_program_exec((char *) mf->mf_private);
}

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_root.c,v 1.1 1997-1998/06/30 19:22:30 ezk Exp ezk $
*
*/
/*
* Root file system
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/****************************************************************************
*** FORWARD DEFINITIONS ***
****************************************************************************/
static int amfs_root_mount(am_node *mp);
/****************************************************************************
*** OPS STRUCTURES ***
****************************************************************************/
am_ops amfs_root_ops =
{
"root",
0, /* amfs_root_match */
0, /* amfs_root_init */
amfs_root_mount,
0,
amfs_auto_umount,
0,
amfs_auto_lookuppn,
amfs_auto_readdir,
0, /* amfs_root_readlink */
0, /* amfs_root_mounted */
0, /* amfs_root_umounted */
find_amfs_auto_srvr,
FS_NOTIMEOUT | FS_AMQINFO | FS_DIRECTORY
};
/****************************************************************************
*** FUNCTIONS ***
****************************************************************************/
/*
* Mount the root...
*/
static int
amfs_root_mount(am_node *mp)
{
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_prfree = mapc_free;
return 0;
}

View File

@ -0,0 +1,355 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_toplvl.c,v 1.1 1997-1998/06/30 19:22:30 ezk Exp ezk $
*
*/
/*
* Top-level file system
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/****************************************************************************
*** FORWARD DEFINITIONS ***
****************************************************************************/
/****************************************************************************
*** OPS STRUCTURES ***
****************************************************************************/
am_ops amfs_toplvl_ops =
{
"toplvl",
amfs_auto_match,
0, /* amfs_auto_init */
amfs_toplvl_mount,
0,
amfs_toplvl_umount,
0,
amfs_auto_lookuppn,
amfs_auto_readdir, /* browsable version of readdir() */
0, /* amfs_toplvl_readlink */
amfs_toplvl_mounted,
0, /* amfs_toplvl_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO | FS_DIRECTORY
};
/****************************************************************************
*** FUNCTIONS ***
****************************************************************************/
/*
* 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.
*
* NOTE: automounter mounts in themselves are using NFS Version 2.
*/
static int
mount_amfs_toplvl(char *dir, char *opts)
{
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 */
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;
}
#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 ? mypid : getppid()),
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.
*/
genflags = compute_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);
#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 */
return error;
}
/*
* Mount the top-level
*/
int
amfs_toplvl_mount(am_node *mp)
{
mntfs *mf = mp->am_mnt;
struct stat stb;
char opts[256], preopts[256];
int error;
char *mnttype;
/*
* Mounting the automounter.
* Make sure the mount directory exists, construct
* the mount options and call the mount_amfs_toplvl routine.
*/
if (stat(mp->am_path, &stb) < 0) {
return errno;
} else if ((stb.st_mode & S_IFMT) != S_IFDIR) {
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_AM_FS_UNION
else if (mf->mf_ops == &amfs_union_ops)
mnttype = "union";
#endif /* HAVE_AM_FS_UNION */
else
mnttype = "auto";
/*
* Construct some mount options:
*
* Tack on magic map=<mapname> option in mtab to emulate
* SunOS automounter behavior.
*/
preopts[0] = '\0';
#ifdef MNTTAB_OPT_INTR
strcat(preopts, MNTTAB_OPT_INTR);
strcat(preopts, ",");
#endif /* MNTTAB_OPT_INTR */
#ifdef MNTTAB_OPT_IGNORE
strcat(preopts, MNTTAB_OPT_IGNORE);
strcat(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);
/* now do the mount */
error = mount_amfs_toplvl(mf->mf_mount, opts);
if (error) {
errno = error;
plog(XLOG_FATAL, "mount_amfs_toplvl: %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)
{
int error;
struct stat stb;
again:
/*
* The lstat is needed if this mount is type=direct.
* When that happens, the kernel cache gets confused
* between the underlying type (dir) and the mounted
* type (link) and so needs to be re-synced before
* the unmount. This is all because the unmount system
* call follows links and so can't actually unmount
* a link (stupid!). It was noted that doing an ls -ld
* of the mount point to see why things were not working
* actually fixed the problem - so simulate an ls -ld here.
*/
if (lstat(mp->am_path, &stb) < 0) {
#ifdef DEBUG
dlog("lstat(%s): %m", mp->am_path);
#endif /* DEBUG */
}
error = UMOUNT_FS(mp->am_path, mnttab_file_name);
if (error == EBUSY) {
plog(XLOG_WARNING, "amfs_toplvl_unmount retrying %s in 1s", mp->am_path);
sleep(1); /* XXX */
goto again;
}
return error;
}

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_union.c,v 1.1 1997-1998/06/30 19:22:30 ezk Exp ezk $
*
*/
/*
* Union automounter file system
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/****************************************************************************
*** FORWARD DEFINITIONS ***
****************************************************************************/
static void amfs_union_mounted(mntfs *mf);
/****************************************************************************
*** OPS STRUCTURES ***
****************************************************************************/
am_ops amfs_union_ops =
{
"union",
amfs_auto_match,
0, /* amfs_auto_init */
amfs_toplvl_mount,
0,
amfs_toplvl_umount,
0,
amfs_auto_lookuppn,
amfs_auto_readdir,
0, /* amfs_toplvl_readlink */
amfs_union_mounted,
0, /* amfs_toplvl_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO | FS_DIRECTORY
};
/*
* Create a reference to a union'ed entry
* XXX: this function may not be used anywhere...
*/
static int
create_amfs_union_node(char *dir, voidp arg)
{
if (!STREQ(dir, "/defaults")) {
int error = 0;
(void) amfs_toplvl_ops.lookuppn(arg, dir, &error, VLOOK_CREATE);
if (error > 0) {
errno = error; /* XXX */
plog(XLOG_ERROR, "Could not mount %s: %m", dir);
}
return error;
}
return 0;
}
static void
amfs_union_mounted(mntfs *mf)
{
int i;
amfs_auto_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) {
/* 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,
mp);
break;
}
}
}

501
contrib/amd/amd/amq_subr.c Normal file
View File

@ -0,0 +1,501 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amq_subr.c,v 5.2.2.1 1992/02/09 15:08:18 jsp beta $
*
*/
/*
* Auxilliary routines for amq tool
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* forward definitions */
bool_t xdr_amq_mount_tree_node(XDR *xdrs, amq_mount_tree *objp);
bool_t xdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp);
voidp
amqproc_null_1_svc(voidp argp, struct svc_req *rqstp)
{
static char res;
return (voidp) &res;
}
/*
* Return a sub-tree of mounts
*/
amq_mount_tree_p *
amqproc_mnttree_1_svc(voidp argp, struct svc_req *rqstp)
{
static am_node *mp;
mp = find_ap(*(char **) argp);
return (amq_mount_tree_p *) &mp;
}
/*
* Unmount a single node
*/
voidp
amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp)
{
static char res;
am_node *mp = find_ap(*(char **) argp);
if (mp)
forcibly_timeout_mp(mp);
return (voidp) &res;
}
/*
* Return global statistics
*/
amq_mount_stats *
amqproc_stats_1_svc(voidp argp, struct svc_req *rqstp)
{
return (amq_mount_stats *) &amd_stats;
}
/*
* Return the entire tree of mount nodes
*/
amq_mount_tree_list *
amqproc_export_1_svc(voidp argp, struct svc_req *rqstp)
{
static amq_mount_tree_list aml;
aml.amq_mount_tree_list_val = (amq_mount_tree_p *) &exported_ap[0];
aml.amq_mount_tree_list_len = 1; /* XXX */
return &aml;
}
int *
amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp)
{
static int rc;
amq_setopt *opt = (amq_setopt *) argp;
rc = 0;
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))
rc = EINVAL;
} else {
rc = EACCES;
}
break;
case AMOPT_XLOG:
if (switch_option(opt->as_str))
rc = EINVAL;
break;
case AMOPT_FLUSHMAPC:
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();
}
break;
}
return &rc;
}
amq_mount_info_list *
amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp)
{
return (amq_mount_info_list *) &mfhead; /* XXX */
}
#ifdef ENABLE_AMQ_MOUNT
/*
* This is code that is vulnerable to IP spoofing attacks. Unless you
* absolutely need it, I suggest you do not enable it
* (using configure --enable-amq-mount)
*/
static int
ok_security(struct svc_req *rqstp)
{
struct sockaddr_in *sin = (struct sockaddr_in *) NULL;
if ((sin = amu_svc_getcaller(rqstp->rq_xprt)) == NULL) {
plog(XLOG_ERROR, "amu_svc_getcaller returned NULL");
return(0); /* assume security is therefore not OK */
}
if (ntohs(sin->sin_port) >= 1024 ||
!(sin->sin_addr.s_addr == htonl(0x7f000001) ||
sin->sin_addr.s_addr == myipaddr.s_addr)) {
char dq[20];
plog(XLOG_INFO, "AMQ request from %s.%d DENIED",
inet_dquad(dq, sin->sin_addr.s_addr),
ntohs(sin->sin_port));
return (0);
}
return (1);
}
int *
amqproc_mount_1_svc(voidp argp, struct svc_req *rqstp)
{
static int rc;
char *s = *(amq_string *) argp;
char *cp;
plog(XLOG_INFO, "amq requested mount of %s", s);
/*
* Minimalist security check.
*/
if (!ok_security(rqstp)) {
rc = EACCES;
return &rc;
}
/*
* Find end of key
*/
for (cp = (char *) s; *cp && (!isascii(*cp) || !isspace(*cp)); cp++) ;
if (!*cp) {
plog(XLOG_INFO, "amqproc_mount: Invalid arguments");
rc = EINVAL;
return &rc;
}
*cp++ = '\0';
/*
* Find start of value
*/
while (*cp && isascii(*cp) && isspace(*cp))
cp++;
root_newmap(s, cp, (char *) 0, NULL);
rc = mount_auto_node(s, (voidp) root_node);
if (rc < 0)
return 0;
return &rc;
}
#else /* not ENABLE_AMQ_MOUNT */
int *
amqproc_mount_1_svc(voidp argp, struct svc_req *rqstp)
{
static int rc;
char *s = *(amq_string *) argp;
plog(XLOG_ERROR, "amq requested mount of %s, but code is disabled", s);
rc = EINVAL;
return &rc;
}
#endif /* not ENABLE_AMQ_MOUNT */
amq_string *
amqproc_getvers_1_svc(voidp argp, struct svc_req *rqstp)
{
static amq_string res;
res = get_version_string();
return &res;
}
/* get PID of remote amd */
int *
amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp)
{
static int res;
res = getpid();
return &res;
}
/*
* XDR routines.
*/
bool_t
xdr_amq_setopt(XDR *xdrs, amq_setopt *objp)
{
if (!xdr_enum(xdrs, (enum_t *) & objp->as_opt)) {
return (FALSE);
}
if (!xdr_string(xdrs, &objp->as_str, AMQ_STRLEN)) {
return (FALSE);
}
return (TRUE);
}
/*
* More XDR routines - Should be used for OUTPUT ONLY.
*/
bool_t
xdr_amq_mount_tree_node(XDR *xdrs, amq_mount_tree *objp)
{
am_node *mp = (am_node *) objp;
if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_info)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &mp->am_path)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, mp->am_link ? &mp->am_link : &mp->am_mnt->mf_mount)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_ops->fs_type)) {
return (FALSE);
}
if (!xdr_long(xdrs, (long *) &mp->am_stats.s_mtime)) {
return (FALSE);
}
if (!xdr_u_short(xdrs, &mp->am_stats.s_uid)) {
return (FALSE);
}
if (!xdr_int(xdrs, &mp->am_stats.s_getattr)) {
return (FALSE);
}
if (!xdr_int(xdrs, &mp->am_stats.s_lookup)) {
return (FALSE);
}
if (!xdr_int(xdrs, &mp->am_stats.s_readdir)) {
return (FALSE);
}
if (!xdr_int(xdrs, &mp->am_stats.s_readlink)) {
return (FALSE);
}
if (!xdr_int(xdrs, &mp->am_stats.s_statfs)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp)
{
am_node *mp = (am_node *) 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)) {
return (FALSE);
}
if (!xdr_pointer(xdrs, (char **) &mp->am_child, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp)
{
am_node *mp = (am_node *) objp;
am_node *mnil = 0;
if (!xdr_amq_mount_tree_node(xdrs, objp)) {
return (FALSE);
}
if (!xdr_pointer(xdrs, (char **) &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)) {
return (FALSE);
}
return (TRUE);
}
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)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_amq_mount_stats(XDR *xdrs, amq_mount_stats *objp)
{
if (!xdr_int(xdrs, &objp->as_drops)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->as_stale)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->as_mok)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->as_merr)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->as_uerr)) {
return (FALSE);
}
return (TRUE);
}
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,
(u_int *) &objp->amq_mount_tree_list_len,
~0,
sizeof(amq_mount_tree_p),
(XDRPROC_T_TYPE) xdr_amq_mount_tree_p)) {
return (FALSE);
}
return (TRUE);
}
/*
* Compute length of list
*/
bool_t
xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead)
{
mntfs *mf;
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))
continue;
len++;
}
xdr_u_int(xdrs, &len);
/*
* Send individual data items
*/
for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) {
int up;
if (!(mf->mf_ops->fs_flags & FS_AMQINFO))
continue;
if (!xdr_amq_string(xdrs, &mf->mf_ops->fs_type)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &mf->mf_mount)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &mf->mf_info)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &mf->mf_server->fs_host)) {
return (FALSE);
}
if (!xdr_int(xdrs, &mf->mf_error)) {
return (FALSE);
}
if (!xdr_int(xdrs, &mf->mf_refc)) {
return (FALSE);
}
if (mf->mf_server->fs_flags & FSF_ERROR)
up = 0;
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;
}
if (!xdr_int(xdrs, &up)) {
return (FALSE);
}
}
return (TRUE);
}
bool_t
xdr_pri_free(XDRPROC_T_TYPE xdr_args, caddr_t args_ptr)
{
XDR xdr;
xdr.x_op = XDR_FREE;
return ((*xdr_args) (&xdr, (caddr_t *) args_ptr));
}

157
contrib/amd/amd/amq_svc.c Normal file
View File

@ -0,0 +1,157 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amq_svc.c,v 5.2.2.1 1992/02/09 15:09:26 jsp beta $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* typedefs */
typedef char *(*amqsvcproc_t)(voidp, struct svc_req *);
void
amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
{
union {
amq_string amqproc_mnttree_1_arg;
amq_string amqproc_umnt_1_arg;
amq_setopt amqproc_setopt_1_arg;
amq_string amqproc_mount_1_arg;
} argument;
char *result;
xdrproc_t xdr_argument, xdr_result;
amqsvcproc_t local;
switch (rqstp->rq_proc) {
case AMQPROC_NULL:
xdr_argument = (xdrproc_t) xdr_void;
xdr_result = (xdrproc_t) xdr_void;
local = (amqsvcproc_t) amqproc_null_1_svc;
break;
case AMQPROC_MNTTREE:
xdr_argument = (xdrproc_t) xdr_amq_string;
xdr_result = (xdrproc_t) xdr_amq_mount_tree_p;
local = (amqsvcproc_t) amqproc_mnttree_1_svc;
break;
case AMQPROC_UMNT:
xdr_argument = (xdrproc_t) xdr_amq_string;
xdr_result = (xdrproc_t) xdr_void;
local = (amqsvcproc_t) amqproc_umnt_1_svc;
break;
case AMQPROC_STATS:
xdr_argument = (xdrproc_t) xdr_void;
xdr_result = (xdrproc_t) xdr_amq_mount_stats;
local = (amqsvcproc_t) amqproc_stats_1_svc;
break;
case AMQPROC_EXPORT:
xdr_argument = (xdrproc_t) xdr_void;
xdr_result = (xdrproc_t) xdr_amq_mount_tree_list;
local = (amqsvcproc_t) amqproc_export_1_svc;
break;
case AMQPROC_SETOPT:
xdr_argument = (xdrproc_t) xdr_amq_setopt;
xdr_result = (xdrproc_t) xdr_int;
local = (amqsvcproc_t) amqproc_setopt_1_svc;
break;
case AMQPROC_GETMNTFS:
xdr_argument = (xdrproc_t) xdr_void;
xdr_result = (xdrproc_t) xdr_amq_mount_info_qelem;
local = (amqsvcproc_t) amqproc_getmntfs_1_svc;
break;
case AMQPROC_MOUNT:
xdr_argument = (xdrproc_t) xdr_amq_string;
xdr_result = (xdrproc_t) xdr_int;
local = (amqsvcproc_t) amqproc_mount_1_svc;
break;
case AMQPROC_GETVERS:
xdr_argument = (xdrproc_t) xdr_void;
xdr_result = (xdrproc_t) xdr_amq_string;
local = (amqsvcproc_t) amqproc_getvers_1_svc;
break;
case AMQPROC_GETPID:
xdr_argument = (xdrproc_t) xdr_void;
xdr_result = (xdrproc_t) xdr_int;
local = (amqsvcproc_t) amqproc_getpid_1_svc;
break;
default:
svcerr_noproc(transp);
return;
}
memset((char *) &argument, 0, sizeof(argument));
if (!svc_getargs(transp,
(XDRPROC_T_TYPE) xdr_argument,
(SVC_IN_ARG_TYPE) & argument)) {
svcerr_decode(transp);
return;
}
result = (*local) (&argument, rqstp);
if (result != NULL && !svc_sendreply(transp,
(XDRPROC_T_TYPE) xdr_result,
result)) {
svcerr_systemerr(transp);
}
if (!svc_freeargs(transp,
(XDRPROC_T_TYPE) xdr_argument,
(SVC_IN_ARG_TYPE) & argument)) {
plog(XLOG_FATAL, "unable to free rpc arguments in amqprog_1");
going_down(1);
}
}

418
contrib/amd/amd/autil.c Normal file
View File

@ -0,0 +1,418 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: autil.c,v 5.2.2.2 1992/03/07 17:52:06 jsp Exp $
*
*/
/*
* utilities specified to amd, taken out of the older amd/util.c.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
int NumChild = 0; /* number of children of primary amd */
static char invalid_keys[] = "\"'!;@ \t\n";
#ifdef HAVE_TRANSPORT_TYPE_TLI
# define PARENT_USLEEP_TIME 100000 /* 0.1 seconds */
#endif /* HAVE_TRANSPORT_TYPE_TLI */
char *
strealloc(char *p, char *s)
{
int len = strlen(s) + 1;
p = (char *) xrealloc((voidp) p, len);
strcpy(p, s);
#ifdef DEBUG_MEM
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
* to the local host domain.
* Note that this has no effect if the domain
* names do not have the same number of
* components. If that restriction proves
* to be a problem then the loop needs recoding
* to skip from right to left and do partial
* matches along the way -- ie more expensive.
*/
static void
domain_strip(char *otherdom, char *localdom)
{
char *p1, *p2;
if ((p1 = strchr(otherdom, '.')) &&
(p2 = strchr(localdom, '.')) &&
STREQ(p1 + 1, p2 + 1))
*p1 = '\0';
}
/*
* Normalize a host name
*/
void
host_normalize(char **chp)
{
/*
* Normalize hosts is used to resolve host name aliases
* and replace them with the standard-form name.
* Invoked with "-n" command line option.
*/
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);
}
/*
* Keys are not allowed to contain " ' ! or ; to avoid
* problems with macro expansions.
*/
int
valid_key(char *key)
{
while (*key)
if (strchr(invalid_keys, *key++))
return FALSE;
return TRUE;
}
void
forcibly_timeout_mp(am_node *mp)
{
mntfs *mf = mp->am_mnt;
/*
* Arrange to timeout this node
*/
if (mf && ((mp->am_flags & AMF_ROOT) ||
(mf->mf_flags & (MFF_MOUNTING | MFF_UNMOUNTING)))) {
if (!(mf->mf_flags & MFF_UNMOUNTING))
plog(XLOG_WARNING, "ignoring timeout request for active node %s", mp->am_path);
} else {
plog(XLOG_INFO, "\"%s\" forcibly timed out", mp->am_path);
mp->am_flags &= ~AMF_NOTIMEOUT;
mp->am_ttl = clocktime();
reschedule_timeout_mp();
}
}
void
mf_mounted(mntfs *mf)
{
int quoted;
int wasmounted = mf->mf_flags & MFF_MOUNTED;
if (!wasmounted) {
/*
* If this is a freshly mounted
* filesystem then update the
* mntfs structure...
*/
mf->mf_flags |= MFF_MOUNTED;
mf->mf_error = 0;
/*
* Do mounted callback
*/
if (mf->mf_ops->mounted) {
(*mf->mf_ops->mounted) (mf);
}
mf->mf_fo = 0;
}
/*
* Log message
*/
quoted = strchr(mf->mf_info, ' ') != 0;
plog(XLOG_INFO, "%s%s%s %s fstype %s on %s",
quoted ? "\"" : "",
mf->mf_info,
quoted ? "\"" : "",
wasmounted ? "referenced" : "mounted",
mf->mf_ops->fs_type, mf->mf_mount);
}
void
am_mounted(am_node *mp)
{
mntfs *mf = mp->am_mnt;
mf_mounted(mf);
/*
* Patch up path for direct mounts
*/
if (mp->am_parent && mp->am_parent->am_mnt->mf_ops == &amfs_direct_ops)
mp->am_path = str3cat(mp->am_path, mp->am_parent->am_path, "/", ".");
/*
* Check whether this mount should be cached permanently
*/
if (mf->mf_ops->fs_flags & FS_NOTIMEOUT) {
mp->am_flags |= AMF_NOTIMEOUT;
} else if (mf->mf_mount[1] == '\0' && mf->mf_mount[0] == '/') {
mp->am_flags |= AMF_NOTIMEOUT;
} else {
mntent_t mnt;
if (mf->mf_mopts) {
mnt.mnt_opts = mf->mf_mopts;
if (hasmntopt(&mnt, "nounmount"))
mp->am_flags |= AMF_NOTIMEOUT;
if ((mp->am_timeo = hasmntval(&mnt, "utimeout")) == 0)
mp->am_timeo = gopt.am_timeo;
}
}
/*
* If this node is a symlink then
* 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);
/*
* Record mount time
*/
mp->am_fattr.na_mtime.nt_seconds = mp->am_stats.s_mtime = clocktime();
new_ttl(mp);
/*
* Update mtime of parent node
*/
if (mp->am_parent && mp->am_parent->am_mnt)
mp->am_parent->am_fattr.na_mtime.nt_seconds = mp->am_stats.s_mtime;
/*
* Now, if we can, do a reply to our NFS client here
* to speed things up.
*/
quick_reply(mp, 0);
/*
* Update stats
*/
amd_stats.d_mok++;
}
int
mount_node(am_node *mp)
{
mntfs *mf = mp->am_mnt;
int 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);
}
return error;
}
void
am_unmounted(am_node *mp)
{
mntfs *mf = mp->am_mnt;
if (!foreground) /* firewall - should never happen */
return;
/*
* Do unmounted callback
*/
if (mf->mf_ops->umounted)
(*mf->mf_ops->umounted) (mp);
/*
* Update mtime of parent node
*/
if (mp->am_parent && mp->am_parent->am_mnt)
mp->am_parent->am_fattr.na_mtime.nt_seconds = clocktime();
free_map(mp);
}
/*
* Fork the automounter
*
* TODO: Need a better strategy for handling errors
*/
static int
dofork(void)
{
int pid;
top:
pid = fork();
if (pid < 0) { /* fork error, retry in 1 second */
sleep(1);
goto top;
}
if (pid == 0) { /* child process (foreground==false) */
mypid = getpid();
foreground = 0;
} else { /* parent process, has one more child */
NumChild++;
}
return pid;
}
int
background(void)
{
int pid = dofork();
if (pid == 0) {
#ifdef DEBUG
dlog("backgrounded");
#endif /* DEBUG */
foreground = 0;
}
return pid;
}

247
contrib/amd/amd/clock.c Normal file
View File

@ -0,0 +1,247 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: clock.c,v 5.2.2.1 1992/02/09 15:08:20 jsp beta $
*
*/
/*
* Callouts.
*
* Modelled on kernel object of the same name.
* See usual references.
*
* Use of a heap-based mechanism was rejected:
* 1. more complex implementation needed.
* 2. not obvious that a list is too slow for Amd.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#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 */
time_t c_time; /* Time of call */
int c_id; /* Unique identifier */
};
static callout callouts; /* List of pending callouts */
static callout *free_callouts; /* Cache of free callouts */
static int nfree_callouts; /* Number on free list */
static int callout_id; /* Next free callout identifier */
time_t next_softclock; /* Time of next call to softclock() */
/*
* Number of callout slots we keep on the free list
*/
#define CALLOUT_FREE_SLOP 10
/*
* Global assumption: valid id's are non-zero.
*/
#define CID_ALLOC(struct ) (++callout_id)
#define CID_UNDEF (0)
static callout *
alloc_callout(void)
{
callout *cp = free_callouts;
if (cp) {
--nfree_callouts;
free_callouts = free_callouts->c_next;
return cp;
}
return ALLOC(struct callout);
}
static void
free_callout(callout *cp)
{
if (nfree_callouts > CALLOUT_FREE_SLOP) {
XFREE(cp);
} else {
cp->c_next = free_callouts;
free_callouts = cp;
nfree_callouts++;
}
}
/*
* Schedule a callout.
*
* (*fn)(closure) will be called at clocktime() + secs
*/
int
timeout(u_int secs, void (*fn) (voidp), voidp closure)
{
callout *cp, *cp2;
time_t t = clocktime() + secs;
/*
* Allocate and fill in a new callout structure
*/
callout *cpnew = alloc_callout();
cpnew->c_closure = closure;
cpnew->c_fn = fn;
cpnew->c_time = t;
cpnew->c_id = CID_ALLOC(struct );
if (t < next_softclock)
next_softclock = t;
/*
* Find the correct place in the list
*/
for (cp = &callouts; (cp2 = cp->c_next); cp = cp2)
if (cp2->c_time >= t)
break;
/*
* And link it in
*/
cp->c_next = cpnew;
cpnew->c_next = cp2;
/*
* Return callout identifier
*/
return cpnew->c_id;
}
/*
* De-schedule a callout
*/
void
untimeout(int id)
{
callout *cp, *cp2;
for (cp = &callouts; (cp2 = cp->c_next); cp = cp2) {
if (cp2->c_id == id) {
cp->c_next = cp2->c_next;
free_callout(cp2);
break;
}
}
}
/*
* Reschedule after clock changed
*/
void
reschedule_timeouts(time_t now, time_t then)
{
callout *cp;
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 %d seconds", cp->c_id, cp->c_time - now);
#endif /* DEBUG */
next_softclock = cp->c_time = now;
}
}
}
/*
* Clock handler
*/
int
softclock(void)
{
time_t now;
callout *cp;
do {
if (task_notify_todo)
do_task_notify();
now = clocktime();
/*
* While there are more callouts waiting...
*/
while ((cp = callouts.c_next) && cp->c_time <= now) {
/*
* Extract first from list, save fn & closure and
* unlink callout from list and free.
* Finally call function.
*
* The free is done first because
* it is quite common that the
* function will call timeout()
* and try to allocate a callout
*/
void (*fn) (voidp) = cp->c_fn;
voidp closure = cp->c_closure;
callouts.c_next = cp->c_next;
free_callout(cp);
(*fn) (closure);
}
} while (task_notify_todo);
/*
* Return number of seconds to next event,
* or 0 if there is no event.
*/
if ((cp = callouts.c_next))
return cp->c_time - now;
return 0;
}

939
contrib/amd/amd/conf.c Normal file
View File

@ -0,0 +1,939 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: conf.c,v 5.2.2.1 1992/02/09 15:08:23 jsp beta $
*
*/
/*
* Functions to handle the configuration file.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/*
* MACROS:
*/
/* Turn on to show some info about maps being configured */
/* #define DEBUG_CONF */
/*
* TYPEDEFS:
*/
typedef int (*OptFuncPtr)(const char *);
/*
* STRUCTURES:
*/
struct _func_map {
char *name;
OptFuncPtr func;
};
/*
* FORWARD DECLARATIONS:
*/
static int gopt_arch(const char *val);
static int gopt_auto_dir(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_options(const char *val);
static int gopt_dismount_interval(const char *val);
static int gopt_fully_qualified_hosts(const char *val);
static int gopt_hesiod_base(const char *val);
static int gopt_karch(const char *val);
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_local_domain(const char *val);
static int gopt_log_file(const char *val);
static int gopt_log_options(const char *val);
static int gopt_map_options(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_nfs_retransmit_counter(const char *val);
static int gopt_nfs_retry_interval(const char *val);
static int gopt_nis_domain(const char *val);
static int gopt_normalize_hostnames(const char *val);
static int gopt_os(const char *val);
static int gopt_osver(const char *val);
static int gopt_plock(const char *val);
static int gopt_print_pid(const char *val);
static int gopt_print_version(const char *val);
static int gopt_restart_mounts(const char *val);
static int gopt_search_path(const char *val);
static int gopt_selectors_on_default(const char *val);
static int gopt_show_statfs_entries(const char *val);
static int gopt_unmount_on_exit(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_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_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 VARIABLES:
*/
static cf_map_t cur_map;
static struct _func_map glob_functable[] = {
{"arch", gopt_arch},
{"auto_dir", gopt_auto_dir},
{"browsable_dirs", gopt_browsable_dirs},
{"cache_duration", gopt_cache_duration},
{"cluster", gopt_cluster},
{"debug_options", gopt_debug_options},
{"dismount_interval", gopt_dismount_interval},
{"fully_qualified_hosts", gopt_fully_qualified_hosts},
{"hesiod_base", gopt_hesiod_base},
{"karch", gopt_karch},
{"ldap_base", gopt_ldap_base},
{"ldap_cache_maxmem", gopt_ldap_cache_maxmem},
{"ldap_cache_seconds", gopt_ldap_cache_seconds},
{"ldap_hostports", gopt_ldap_hostports},
{"local_domain", gopt_local_domain},
{"log_file", gopt_log_file},
{"log_options", gopt_log_options},
{"map_options", gopt_map_options},
{"map_type", gopt_map_type},
{"mount_type", gopt_mount_type},
{"pid_file", gopt_pid_file},
{"portmap_program", gopt_portmap_program},
{"nfs_retransmit_counter", gopt_nfs_retransmit_counter},
{"nfs_retry_interval", gopt_nfs_retry_interval},
{"nis_domain", gopt_nis_domain},
{"normalize_hostnames", gopt_normalize_hostnames},
{"os", gopt_os},
{"osver", gopt_osver},
{"plock", gopt_plock},
{"print_pid", gopt_print_pid},
{"print_version", gopt_print_version},
{"restart_mounts", gopt_restart_mounts},
{"search_path", gopt_search_path},
{"selectors_on_default", gopt_selectors_on_default},
{"show_statfs_entries", gopt_show_statfs_entries},
{"unmount_on_exit", gopt_unmount_on_exit},
{NULL, NULL}
};
/*
* Reset a map.
*/
static void
reset_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
* 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!
*/
/* 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_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;
/*
* Initialize flags that are common both to [global] and a local map.
*/
cfm->cfm_flags = gopt.flags & (CFM_BROWSABLE_DIRS |
CFM_BROWSABLE_DIRS_FULL |
CFM_MOUNT_TYPE_AUTOFS |
CFM_ENABLE_DEFAULT_SELECTORS);
}
/*
* Process configuration file options.
* Return 0 if OK, 1 otherwise.
*/
int
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",
section, key, val);
#endif /* DEBUG_CONF */
/*
* If global section, process them one at a time.
*/
if (STREQ(section, "global")) {
/*
* Check if a regular map was configured before "global",
* and process it as needed.
*/
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;
}
/* 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.
*/
/* 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;
}
/* now process a single entry of a regular map */
return process_regular_option(section, key, val, &cur_map);
}
/*
* Process global section of configuration file options.
* Return 0 upon success, 1 otherwise.
*/
static int
process_global_option(const char *key, const char *val)
{
struct _func_map *gfp;
/* ensure that val is valid */
if (!val || val[0] == '\0')
return 1;
/*
* search for global function.
*/
for (gfp = glob_functable; gfp->name; gfp++)
if (FSTREQ(gfp->name, key))
return (gfp->func)(val);
fprintf(stderr, "conf: unknown global key: \"%s\"\n", key);
return 1; /* failed to match any command */
}
static int
gopt_arch(const char *val)
{
gopt.arch = strdup((char *)val);
return 0;
}
static int
gopt_auto_dir(const char *val)
{
gopt.auto_dir = strdup((char *)val);
return 0;
}
static int
gopt_browsable_dirs(const char *val)
{
if (STREQ(val, "full")) {
gopt.flags |= CFM_BROWSABLE_DIRS_FULL;
return 0;
} else if (STREQ(val, "yes")) {
gopt.flags |= CFM_BROWSABLE_DIRS;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_BROWSABLE_DIRS;
return 0;
}
fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_cache_duration(const char *val)
{
gopt.am_timeo = atoi(val);
if (gopt.am_timeo <= 0)
gopt.am_timeo = AM_TTL;
return 0;
}
static int
gopt_cluster(const char *val)
{
gopt.cluster = strdup((char *)val);
return 0;
}
static int
gopt_debug_options(const char *val)
{
#ifdef DEBUG
usage += debug_option(strdup((char *)val));
return 0;
#else /* not DEBUG */
fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n",
progname);
return 1;
#endif /* not DEBUG */
}
static int
gopt_dismount_interval(const char *val)
{
gopt.am_timeo_w = atoi(val);
if (gopt.am_timeo_w <= 0)
gopt.am_timeo_w = AM_TTL_W;
return 0;
}
static int
gopt_fully_qualified_hosts(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_FULLY_QUALIFIED_HOSTS;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_FULLY_QUALIFIED_HOSTS;
return 0;
}
fprintf(stderr, "conf: unknown value to fully_qualified_hosts \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_hesiod_base(const char *val)
{
#ifdef HAVE_MAP_HESIOD
gopt.hesiod_base = strdup((char *)val);
return 0;
#else /* not HAVE_MAP_HESIOD */
fprintf(stderr, "conf: hesiod_base option ignored. No Hesiod support available.\n");
return 1;
#endif /* not HAVE_MAP_HESIOD */
}
static int
gopt_karch(const char *val)
{
gopt.karch = strdup((char *)val);
return 0;
}
static int
gopt_pid_file(const char *val)
{
gopt.pid_file = strdup((char *)val);
return 0;
}
static int
gopt_local_domain(const char *val)
{
gopt.sub_domain = strdup((char *)val);
return 0;
}
static int
gopt_ldap_base(const char *val)
{
#ifdef HAVE_MAP_LDAP
gopt.ldap_base = strdup((char *)val);
return 0;
#else /* not HAVE_MAP_LDAP */
fprintf(stderr, "conf: ldap_base option ignored. No LDAP support available.\n");
return 1;
#endif /* not HAVE_MAP_LDAP */
}
static int
gopt_ldap_cache_seconds(const char *val)
{
#ifdef HAVE_MAP_LDAP
char *end;
gopt.ldap_cache_seconds = strtol((char *)val, &end, 10);
if (end == val) {
fprintf(stderr, "conf: bad LDAP cache (seconds) option: %s\n",val);
return 1;
}
return 0;
#else /* not HAVE_MAP_LDAP */
fprintf(stderr, "conf: ldap_cache option ignored. No LDAP support available.\n");
return 1;
#endif /* not HAVE_MAP_LDAP */
}
static int
gopt_ldap_cache_maxmem(const char *val)
{
#ifdef HAVE_MAP_LDAP
char *end;
gopt.ldap_cache_maxmem = strtol((char *)val, &end, 10);
if (end == val) {
fprintf(stderr, "conf: bad LDAP cache (maxmem) option: %s\n",val);
return 1;
}
return 0;
#else /* not HAVE_MAP_LDAP */
fprintf(stderr, "conf: ldap_cache option ignored. No LDAP support available.\n");
return 1;
#endif /* not HAVE_MAP_LDAP */
}
static int
gopt_ldap_hostports(const char *val)
{
#ifdef HAVE_MAP_LDAP
gopt.ldap_hostports = strdup((char *)val);
return 0;
#else /* not HAVE_MAP_LDAP */
fprintf(stderr, "conf: ldap_hostports option ignored. No LDAP support available.\n");
return 1;
#endif /* not HAVE_MAP_LDAP */
}
static int
gopt_log_file(const char *val)
{
gopt.logfile = strdup((char *)val);
return 0;
}
static int
gopt_log_options(const char *val)
{
usage += switch_option(strdup((char *)val));
return 0;
}
static int
gopt_map_options(const char *val)
{
gopt.map_options = strdup((char *)val);
return 0;
}
static int
gopt_map_type(const char *val)
{
gopt.map_type = strdup((char *)val);
return 0;
}
static int
gopt_mount_type(const char *val)
{
if (STREQ(val, "autofs")) {
#ifdef HAVE_FS_AUTOFS
gopt.flags |= CFM_MOUNT_TYPE_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;
}
fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_portmap_program(const char *val)
{
gopt.portmap_program = atoi(val);
/*
* allow alternate program numbers to be no more than 10 offset from
* official amd program number (300019).
*/
if (gopt.portmap_program < AMQ_PROGRAM ||
gopt.portmap_program > AMQ_PROGRAM + 10) {
gopt.portmap_program = AMQ_PROGRAM;
set_amd_program_number(gopt.portmap_program);
fprintf(stderr, "conf: illegal amd program numver \"%s\"\n", val);
return 1;
}
set_amd_program_number(gopt.portmap_program);
return 0; /* all is OK */
}
static int
gopt_nfs_retransmit_counter(const char *val)
{
gopt.amfs_auto_retrans = atoi(val);
return 0;
}
static int
gopt_nfs_retry_interval(const char *val)
{
gopt.amfs_auto_timeo = atoi(val);
return 0;
}
static int
gopt_nis_domain(const char *val)
{
#ifdef HAVE_MAP_NIS
gopt.nis_domain = strdup((char *)val);
return 0;
#else /* not HAVE_MAP_NIS */
fprintf(stderr, "conf: nis_domain option ignored. No NIS support available.\n");
return 1;
#endif /* not HAVE_MAP_NIS */
}
static int
gopt_normalize_hostnames(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_NORMALIZE_HOSTNAMES;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_NORMALIZE_HOSTNAMES;
return 0;
}
fprintf(stderr, "conf: unknown value to normalize_hostnames \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_os(const char *val)
{
gopt.op_sys = strdup((char *)val);
return 0;
}
static int
gopt_osver(const char *val)
{
gopt.op_sys_ver = strdup((char *)val);
return 0;
}
static int
gopt_plock(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_PROCESS_LOCK;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_PROCESS_LOCK;
return 0;
}
fprintf(stderr, "conf: unknown value to plock \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_print_pid(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_PRINT_PID;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_PRINT_PID;
return 0;
}
fprintf(stderr, "conf: unknown value to print_pid \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_print_version(const char *val)
{
if (STREQ(val, "yes")) {
fputs(get_version_string(), stderr);
return 0;
} else if (STREQ(val, "no")) {
return 0;
}
fprintf(stderr, "conf: unknown value to print_version \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_restart_mounts(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_RESTART_EXISTING_MOUNTS;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_RESTART_EXISTING_MOUNTS;
return 0;
}
fprintf(stderr, "conf: unknown value to restart_mounts \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_search_path(const char *val)
{
gopt.search_path = strdup((char *)val);
return 0;
}
static int
gopt_selectors_on_default(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_ENABLE_DEFAULT_SELECTORS;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_ENABLE_DEFAULT_SELECTORS;
return 0;
}
fprintf(stderr, "conf: unknown value to enable_default_selectors \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_show_statfs_entries(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_SHOW_STATFS_ENTRIES;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_SHOW_STATFS_ENTRIES;
return 0;
}
fprintf(stderr, "conf: unknown value to show_statfs_entries \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_unmount_on_exit(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_UNMOUNT_ON_EXIT;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_UNMOUNT_ON_EXIT;
return 0;
}
fprintf(stderr, "conf: unknown value to unmount_on_exit \"%s\"\n", val);
return 1; /* unknown value */
}
/*
* Collect one entry for a regular map
*/
static int
process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm)
{
/* ensure that val is valid */
if (!section || section[0] == '\0' ||
!key || key[0] == '\0' ||
!val || val[0] == '\0' ||
!cfm) {
fprintf(stderr, "conf: process_regular_option: null entries\n");
return 1;
}
/* check if initializing a new map */
if (!cfm->cfm_dir)
cfm->cfm_dir = strdup((char *)section);
/* check for each possible field */
if (STREQ(key, "browsable_dirs"))
return ropt_browsable_dirs(val, cfm);
if (STREQ(key, "map_name"))
return ropt_map_name(val, cfm);
if (STREQ(key, "map_options"))
return ropt_map_options(val, cfm);
if (STREQ(key, "map_type"))
return ropt_map_type(val, cfm);
if (STREQ(key, "mount_type"))
return ropt_mount_type(val, cfm);
if (STREQ(key, "search_path"))
return ropt_search_path(val, cfm);
if (STREQ(key, "tag"))
return ropt_tag(val, cfm);
fprintf(stderr, "conf: unknown regular key \"%s\" for section \"%s\"\n",
key, section);
return 1; /* failed to match any command */
}
static int
ropt_browsable_dirs(const char *val, cf_map_t *cfm)
{
if (STREQ(val, "full")) {
cfm->cfm_flags |= CFM_BROWSABLE_DIRS_FULL;
return 0;
} else if (STREQ(val, "yes")) {
cfm->cfm_flags |= CFM_BROWSABLE_DIRS;
return 0;
} else if (STREQ(val, "no")) {
cfm->cfm_flags &= ~CFM_BROWSABLE_DIRS;
return 0;
}
fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val);
return 1; /* unknown value */
}
static int
ropt_map_name(const char *val, cf_map_t *cfm)
{
cfm->cfm_name = strdup((char *)val);
return 0;
}
static int
ropt_map_options(const char *val, cf_map_t *cfm)
{
cfm->cfm_opts = strdup((char *)val);
return 0;
}
static int
ropt_map_type(const char *val, cf_map_t *cfm)
{
cfm->cfm_type = strdup((char *)val);
return 0;
}
static int
ropt_mount_type(const char *val, cf_map_t *cfm)
{
if (STREQ(val, "autofs")) {
#ifdef HAVE_FS_AUTOFS
cfm->cfm_flags |= CFM_MOUNT_TYPE_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;
}
fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val);
return 1; /* unknown value */
}
static int
ropt_search_path(const char *val, cf_map_t *cfm)
{
cfm->cfm_search_path = strdup((char *)val);
return 0;
}
static int
ropt_tag(const char *val, cf_map_t *cfm)
{
cfm->cfm_tag = strdup((char *)val);
return 0;
}
/*
* Process one collected map.
*/
static int
process_regular_map(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;
}
/*
* If map has no tag defined, process the map.
* If no conf_tag was set in amd -T, process all untagged entries.
* If a tag is defined, then process it only if it matches the map tag.
*/
if (!cfm->cfm_tag ||
(conf_tag && STREQ(cfm->cfm_tag, conf_tag))) {
#ifdef DEBUG_CONF
fprintf(stderr, "processing map %s (flags=0x%x)...\n",
cfm->cfm_dir, cfm->cfm_flags);
#endif /* DEBUG_CONF */
root_newmap(cfm->cfm_dir,
cfm->cfm_opts ? cfm->cfm_opts : "",
cfm->cfm_name,
cfm);
} else {
fprintf(stderr, "skipping map %s...\n", cfm->cfm_dir);
}
reset_cf_map(cfm);
return 0;
}
/*
* Process last map in conf file (if any)
*/
int
process_last_regular_map(void)
{
/*
* If the amd.conf file only has a [global] section (pretty useless
* IMHO), do not try to process a map that does not exist.
*/
if (!cur_map.cfm_dir)
return 0;
return process_regular_map(&cur_map);
}

View File

@ -0,0 +1,159 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: conf_parse.y,v 5.2.2.1 1992/02/09 15:09:35 jsp beta $
*
*/
%{
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
extern char *yytext;
extern int yylineno;
extern int yylex(void);
static int yyerror(const char *s);
static int retval;
static char *header_section = NULL; /* start with no header section */
#define YYDEBUG 1
#define PARSE_DEBUG 0
#if PARSE_DEBUG
# define dprintf(f,s) fprintf(stderr, (f), yylineno, (s))
# define amu_return(v)
#else
# define dprintf(f,s)
# define amu_return(v) return((v))
#endif /* PARSE_DEBUG */
%}
%union {
char *strtype;
}
%token LEFT_BRACKET RIGHT_BRACKET EQUAL
%token NEWLINE
%token <strtype> NONWS_STRING
%token <strtype> NONWSEQ_STRING
%token <strtype> QUOTED_NONWSEQ_STRING
%start file
%%
/****************************************************************************/
file : { yydebug = PARSE_DEBUG; } newlines map_sections
| { yydebug = PARSE_DEBUG; } map_sections
;
newlines : NEWLINE
| NEWLINE newlines
;
map_sections : map_section
| map_section map_sections
;
map_section : sec_header kv_pairs
;
sec_header : LEFT_BRACKET NONWS_STRING RIGHT_BRACKET NEWLINE
{
if (yydebug)
fprintf(stderr, "sec_header1 = \"%s\"\n", $2);
header_section = $2;
}
;
kv_pairs : kv_pair
| kv_pair kv_pairs
;
kv_pair : NONWS_STRING EQUAL NONWS_STRING NEWLINE
{
if (yydebug)
fprintf(stderr,"parse1: key=\"%s\", val=\"%s\"\n", $1, $3);
retval = set_conf_kv(header_section, $1, $3);
if (retval != 0) {
yyerror("syntax error");
YYABORT;
}
}
| NONWS_STRING EQUAL NONWSEQ_STRING NEWLINE
{
if (yydebug)
fprintf(stderr,"parse2: key=\"%s\", val=\"%s\"\n", $1, $3);
retval = set_conf_kv(header_section, $1, $3);
if (retval != 0) {
yyerror("syntax error");
YYABORT;
}
}
| NONWS_STRING EQUAL QUOTED_NONWSEQ_STRING NEWLINE
{
if (yydebug)
fprintf(stderr,"parse3: key=\"%s\", val=\"%s\"\n", $1, $3);
retval = set_conf_kv(header_section, $1, $3);
if (retval != 0) {
yyerror("syntax error");
YYABORT;
}
}
| NEWLINE
;
/****************************************************************************/
%%
static int
yyerror(const char *s)
{
fprintf(stderr, "AMDCONF: %s on line %d (section %s)\n",
s, yylineno,
(header_section ? header_section : "null"));
exit(1);
return 1; /* to full compilers that insist on a return statement */
}

186
contrib/amd/amd/conf_tok.l Normal file
View File

@ -0,0 +1,186 @@
%{
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: conf_tok.l,v 5.2.2.1 1992/02/09 15:09:36 jsp beta $
*
*/
/*
* Lexical analyzer for AMD configuration parser.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
/*
* Some systems include a definition for the macro ECHO in <sys/ioctl.h>,
* and their (bad) version of lex defines it too at the very beginning of
* the generated lex.yy.c file (before it can be easily undefined),
* resulting in a conflict. So undefine it here before needed.
* Luckily, it does not appear that this macro is actually used in the rest
* of the generated lex.yy.c file.
*/
#ifdef ECHO
# undef ECHO
#endif /* ECHO */
#include <am_defs.h>
#include <amd.h>
#include <conf_parse.h>
/* and once again undefine this, just in case */
#ifdef ECHO
# undef ECHO
#endif /* ECHO */
/*
* There are some things that need to be defined only if useing GNU flex.
* These must not be defined if using standard lex
*/
#ifdef FLEX_SCANNER
# ifndef ECHO
# define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
# endif /* not ECHO */
int yylineno = 0;
#endif /* FLEX_SCANNER */
int yylex(void);
/*
* some systems such as DU-4.x have a different GNU flex in /usr/bin
* which automatically generates yywrap macros and symbols. So I must
* distinguish between them and when yywrap is actually needed.
*/
#ifndef yywrap
int yywrap(void);
#endif /* not yywrap */
#define TOK_DEBUG 0
#if TOK_DEBUG
# define dprintf(f,s) fprintf(stderr, (f), yylineno, (s))
# define amu_return(v)
#else
# define dprintf(f,s)
# define amu_return(v) return((v))
#endif /* TOK_DEBUG */
/* no need to use yyunput() or yywrap() */
#define YY_NO_UNPUT
#define YY_SKIP_YYWRAP
%}
DIGIT [0-9]
ALPHA [A-Za-z]
ALPHANUM [A-Za-z0-9]
SYMBOL [A-Za-z0-9_-]
PATH [A-Za-z0-9_-/]
NONWSCHAR [^ \t\n\[\]=]
NONWSEQCHAR [^ \t\n\[\]]
NONNL [^\n]
NONQUOTE [^\"]
%%
\n {
yylineno++;
amu_return(NEWLINE);
}
\[ {
dprintf("%8d: Left bracket \"%s\"\n", yytext);
yylval.strtype = strdup((char *)yytext);
amu_return(LEFT_BRACKET);
}
\] {
dprintf("%8d: Right bracket \"%s\"\n", yytext);
yylval.strtype = strdup((char *)yytext);
amu_return(RIGHT_BRACKET);
}
= {
dprintf("%8d: Equal \"%s\"\n", yytext);
yylval.strtype = strdup((char *)yytext);
amu_return(EQUAL);
}
[ \t]* {
dprintf("%8d: Whitespace \"%s\"\n", yytext);
}
"#"[^\n]*\n {
/* a comment line includes the terminating \n */
yylineno++;
yytext[strlen((char *)yytext)-1] = '\0';
dprintf("%8d: Comment \"%s\"\n", yytext);
}
{NONWSCHAR}{NONWSCHAR}* {
dprintf("%8d: Non-WS string \"%s\"\n", yytext);
yylval.strtype = strdup((char *)yytext);
amu_return(NONWS_STRING);
}
\"{NONQUOTE}{NONQUOTE}*\" {
dprintf("%8d: QUOTED-Non-WS-EQ string \"%s\"\n", yytext);
/* must strip quotes */
yytext[strlen((char *)yytext)-1] = '\0';
yylval.strtype = strdup((char *)&yytext[1]);
amu_return(QUOTED_NONWSEQ_STRING);
}
{NONWSEQCHAR}{NONWSEQCHAR}* {
dprintf("%8d: Non-WS-EQ string \"%s\"\n", yytext);
yylval.strtype = strdup((char *)yytext);
amu_return(NONWSEQ_STRING);
}
%%
/*
* some systems such as DU-4.x have a different GNU flex in /usr/bin
* which automatically generates yywrap macros and symbols. So I must
* distinguish between them and when yywrap is actually needed.
*/
#ifndef yywrap
int yywrap(void)
{
return 1;
}
#endif /* not yywrap */

389
contrib/amd/amd/get_args.c Normal file
View File

@ -0,0 +1,389 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: get_args.c,v 5.2.2.1 1992/02/09 15:08:23 jsp beta $
*
*/
/*
* Argument decode
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* include auto-generated version file */
#include <build_version.h>
char *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 */
#ifdef DEBUG
int debug_flags = D_AMQ /* Register AMQ */
| D_DAEMON; /* Enter daemon mode */
#endif /* DEBUG */
/*
* Return the version string (dynamic buffer)
*/
char *
get_version_string(void)
{
static char *vers = NULL;
char tmpbuf[1024];
char *wire_buf;
int wire_buf_len = 0;
/* first get dynamic string listing all known networks */
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-1998 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",
HOST_OS, gopt.op_sys, gopt.op_sys_ver, HOST_VENDOR);
strcat(vers, tmpbuf);
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);
/* append list of networks if available */
if (wire_buf) {
strcat(vers, wire_buf);
XFREE(wire_buf);
}
return vers;
}
void
get_args(int argc, char *argv[])
{
int opt_ch;
FILE *fp = stdin;
/* if no arguments were passed, try to use /etc/amd.conf file */
if (argc <= 1)
use_conf_file = 1;
while ((opt_ch = getopt(argc, argv, "nprvSa:c:d:k:l:o:t:w:x:y:C:D:F:T:O:H")) != EOF)
switch (opt_ch) {
case 'a':
if (*optarg != '/') {
fprintf(stderr, "%s: -a option must begin with a '/'\n",
progname);
exit(1);
}
gopt.auto_dir = optarg;
break;
case 'c':
gopt.am_timeo = atoi(optarg);
if (gopt.am_timeo <= 0)
gopt.am_timeo = AM_TTL;
break;
case 'd':
gopt.sub_domain = optarg;
break;
case 'k':
gopt.karch = optarg;
break;
case 'l':
gopt.logfile = optarg;
break;
case 'n':
gopt.flags |= CFM_NORMALIZE_HOSTNAMES;
break;
case 'o':
gopt.op_sys_ver = optarg;
break;
case 'p':
gopt.flags |= CFM_PRINT_PID;
break;
case 'r':
gopt.flags |= CFM_RESTART_EXISTING_MOUNTS;
break;
case 't':
/* timeo.retrans */
{
char *dot = strchr(optarg, '.');
if (dot)
*dot = '\0';
if (*optarg) {
gopt.amfs_auto_timeo = atoi(optarg);
}
if (dot) {
gopt.amfs_auto_retrans = atoi(dot + 1);
*dot = '.';
}
}
break;
case 'v':
fputs(get_version_string(), stderr);
exit(0);
break;
case 'w':
gopt.am_timeo_w = atoi(optarg);
if (gopt.am_timeo_w <= 0)
gopt.am_timeo_w = AM_TTL_W;
break;
case 'x':
usage += switch_option(optarg);
break;
case 'y':
#ifdef HAVE_MAP_NIS
gopt.nis_domain = optarg;
#else /* not HAVE_MAP_NIS */
plog(XLOG_USER, "-y: option ignored. No NIS support available.");
#endif /* not HAVE_MAP_NIS */
break;
case 'C':
gopt.cluster = optarg;
break;
case 'D':
#ifdef DEBUG
usage += debug_option(optarg);
#else /* not DEBUG */
fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n", progname);
#endif /* not DEBUG */
break;
case 'F':
conf_file = optarg;
use_conf_file = 1;
break;
case 'H':
goto show_usage;
break;
case 'O':
gopt.op_sys = optarg;
break;
case 'S':
gopt.flags &= ~CFM_PROCESS_LOCK; /* turn process locking off */
break;
case 'T':
conf_tag = optarg;
break;
default:
usage = 1;
break;
}
/*
* amd.conf file: if not command-line arguments were used, or if -F was
* 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 (!fp) {
char buf[128];
sprintf(buf, "Amd configuration file (%s)", conf_file);
perror(buf);
exit(1);
}
yyin = fp;
yyparse();
fclose(fp);
if (process_last_regular_map() != 0)
exit(1);
}
/* make sure there are some default options defined */
if (xlog_level_init == ~0) {
switch_option("");
}
#ifdef DEBUG
usage += switch_option("debug");
#endif /* DEBUG */
/* log information regarding amd.conf file */
if (use_conf_file && conf_file)
plog(XLOG_INFO, "using configuration file %s", conf_file);
#ifdef HAVE_MAP_LDAP
/* ensure that if ldap_base is specified, that also ldap_hostports is */
if (gopt.ldap_hostports && !gopt.ldap_base) {
fprintf(stderr, "must specify both ldap_hostports and ldap_base\n");
exit(1);
}
#endif /* HAVE_MAP_LDAP */
if (usage)
goto show_usage;
while (optind <= argc - 2) {
char *dir = argv[optind++];
char *map = argv[optind++];
char *opts = "";
if (argv[optind] && *argv[optind] == '-')
opts = &argv[optind++][1];
root_newmap(dir, opts, map, NULL);
}
if (optind == argc) {
/*
* Append domain name to hostname.
* sub_domain overrides hostdomain
* if given.
*/
if (gopt.sub_domain)
hostdomain = gopt.sub_domain;
if (*hostdomain == '.')
hostdomain++;
strcat(hostd, ".");
strcat(hostd, hostdomain);
#ifdef MOUNT_TABLE_ON_FILE
# ifdef DEBUG
if (debug_flags & D_MTAB)
mnttab_file_name = DEBUG_MNTTAB;
else
# endif /* DEBUG */
mnttab_file_name = MNTTAB_FILE_NAME;
#else /* not MOUNT_TABLE_ON_FILE */
# ifdef DEBUG
if (debug_flags & D_MTAB)
dlog("-D mtab option ignored");
# endif /* DEBUG */
#endif /* not MOUNT_TABLE_ON_FILE */
if (switch_to_logfile(gopt.logfile) != 0)
plog(XLOG_USER, "Cannot switch logfile");
/*
* If the kernel architecture was not specified
* then use the machine architecture.
*/
if (gopt.karch == 0)
gopt.karch = gopt.arch;
if (gopt.cluster == 0)
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;
}
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]", 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");
exit(1);
}

265
contrib/amd/amd/info_file.c Normal file
View File

@ -0,0 +1,265 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: info_file.c,v 5.2.2.1 1992/02/09 15:08:28 jsp beta $
*
*/
/*
* Get info from file
*/
#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 file_init(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
read_line(char *buf, int size, FILE * fp)
{
int done = 0;
do {
while (fgets(buf, size, fp)) {
int len = strlen(buf);
done += len;
if (len > 1 && buf[len - 2] == '\\' &&
buf[len - 1] == '\n') {
int ch;
buf += len - 2;
size -= len - 2;
*buf = '\n';
buf[1] = '\0';
/*
* Skip leading white space on next line
*/
while ((ch = getc(fp)) != EOF &&
isascii(ch) && isspace(ch)) ;
(void) ungetc(ch, fp);
} else {
return done;
}
}
} while (size > 0 && !feof(fp));
return done;
}
/*
* 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 *))
{
char key_val[MAX_LINE_LEN];
int chuck = 0;
int line_no = 0;
while (read_line(key_val, sizeof(key_val), fp)) {
char *kp;
char *cp;
char *hash;
int len = strlen(key_val);
line_no++;
/*
* Make sure we got the whole line
*/
if (key_val[len - 1] != '\n') {
plog(XLOG_WARNING, "line %d in \"%s\" is too long", line_no, map);
chuck = 1;
} else {
key_val[len - 1] = '\0';
}
/*
* Strip comments
*/
hash = strchr(key_val, '#');
if (hash)
*hash = '\0';
/*
* Find start of key
*/
for (kp = key_val; *kp && isascii(*kp) && isspace((int)*kp); kp++) ;
/*
* Ignore blank lines
*/
if (!*kp)
goto again;
/*
* Find end of key
*/
for (cp = kp; *cp && (!isascii(*cp) || !isspace((int)*cp)); cp++) ;
/*
* Check whether key matches
*/
if (*cp)
*cp++ = '\0';
if (fn || (*key == *kp && STREQ(key, kp))) {
while (*cp && isascii(*cp) && isspace((int)*cp))
cp++;
if (*cp) {
/*
* Return a copy of the data
*/
char *dc = strdup(cp);
if (fn) {
(*fn) (m, strdup(kp), dc);
} else {
*val = dc;
#ifdef DEBUG
dlog("%s returns %s", key, dc);
#endif /* DEBUG */
}
if (!fn)
return 0;
} else {
plog(XLOG_USER, "%s: line %d has no value field", map, line_no);
}
}
again:
/*
* If the last read didn't get a whole line then
* throw away the remainder before continuing...
*/
if (chuck) {
while (fgets(key_val, sizeof(key_val), fp) &&
!strchr(key_val, '\n')) ;
chuck = 0;
}
}
return fn ? 0 : ENOENT;
}
static FILE *
file_open(char *map, time_t *tp)
{
FILE *mapf = fopen(map, "r");
if (mapf && tp) {
struct stat stb;
if (fstat(fileno(mapf), &stb) < 0)
*tp = clocktime();
else
*tp = stb.st_mtime;
}
return mapf;
}
int
file_init(mnt_map *m, char *map, time_t *tp)
{
FILE *mapf = file_open(map, tp);
if (mapf) {
fclose(mapf);
return 0;
}
return errno;
}
int
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);
(void) fclose(mapf);
return error;
}
return errno;
}
int
file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
{
time_t t;
FILE *mapf = file_open(map, &t);
if (mapf) {
int error;
if (*tp < t) {
*tp = t;
error = -1;
} else {
error = search_or_reload_file(mapf, map, key, pval, 0, 0);
}
(void) fclose(mapf);
return error;
}
return errno;
}
int
file_mtime(mnt_map *m, char *map, time_t *tp)
{
FILE *mapf = file_open(map, tp);
if (mapf) {
(void) fclose(mapf);
return 0;
}
return errno;
}

View File

@ -0,0 +1,163 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: info_hesiod.c,v 1.1 1997-1998/07/11 08:34:52 danny Exp danny $
*
*/
/*
* Get info from Hesiod
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
#define HES_PREFIX "hesiod."
#define HES_PREFLEN 7
#ifdef HAVE_HESIOD_INIT
/* bsdi3 does not define this extern in any header file */
extern char **hesiod_resolve(void *context, const char *name, const char *type);
static voidp hesiod_context;
#endif /* HAVE_HESIOD_INIT */
/*
* No easy way to probe the server - check the map name begins with "hesiod."
* Note: this name includes 'amu_' so as to not conflict with libhesiod's
* hesiod_init() function.
*/
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)
return ENOENT;
#endif /* HAVE_HESIOD_INIT */
return NSTREQ(map, HES_PREFIX, HES_PREFLEN) ? 0 : ENOENT;
}
/*
* Do a Hesiod nameserver call.
* Modify time is ignored by Hesiod - XXX
*/
int
hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
{
char hes_key[MAXPATHLEN];
char **rvec;
#ifndef HAVE_HESIOD_INIT
int error;
#endif /* not HAVE_HESIOD_INIT */
#ifdef DEBUG
dlog("hesiod_search(m=%x, map=%s, key=%s, pval=%x tp=%x)", m, map, key, pval, tp);
#endif /* DEBUG */
sprintf(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)
_res.options |= RES_DEBUG;
#endif /* DEBUG */
#ifdef HAVE_HESIOD_INIT
/* new style hesiod */
rvec = hesiod_resolve(hesiod_context, hes_key, gopt.hesiod_base);
#else /* not HAVE_HESIOD_INIT */
rvec = hes_resolve(hes_key, gopt.hesiod_base);
#endif /* not HAVE_HESIOD_INIT */
/*
* If a reply was forthcoming then return
* it (and free subsequent replies)
*/
if (rvec && *rvec) {
*pval = *rvec;
while (*++rvec)
XFREE(*rvec);
return 0;
}
#ifdef HAVE_HESIOD_INIT
/* new style hesiod */
return errno;
#else /* not HAVE_HESIOD_INIT */
/*
* 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;
break;
case HES_ER_CONFIG:
error = EIO;
break;
case HES_ER_NET:
error = ETIMEDOUT;
break;
default:
error = EINVAL;
break;
}
# ifdef DEBUG
dlog("hesiod_search: Returning: %d", error);
# endif /* DEBUG */
return error;
#endif /* not HAVE_HESIOD_INIT */
}

465
contrib/amd/amd/info_ldap.c Normal file
View File

@ -0,0 +1,465 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: info_ldap.c,v 5.2.2.1 1992/02/09 15:08:29 jsp beta $
*
*/
/*
* Get info from LDAP (Lightweight Directory Access Protocol)
* LDAP Home Page: http://www.umich.edu/~rsug/ldap/
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/*
* MACROS:
*/
#define AMD_LDAP_TYPE "ldap"
/* Time to live for an LDAP cached in an mnt_map */
#define AMD_LDAP_TTL 3600
#define AMD_LDAP_RETRIES 5
#define AMD_LDAP_HOST "ldap"
#ifndef LDAP_PORT
# define LDAP_PORT 389
#endif /* LDAP_PORT */
/* How timestamps are searched */
#define AMD_LDAP_TSFILTER "(&(objectClass=amdmapTimestamp)(amdmapName=%s))"
/* How maps are searched */
#define AMD_LDAP_FILTER "(&(objectClass=amdmap)(amdmapName=%s)(amdmapKey=%s))"
/* How timestamps are stored */
#define AMD_LDAP_TSATTR "amdmaptimestamp"
/* How maps are stored */
#define AMD_LDAP_ATTR "amdmapvalue"
/*
* TYPEDEFS:
*/
typedef struct ald_ent ALD;
typedef struct cr_ent CR;
typedef struct he_ent HE;
/*
* STRUCTURES:
*/
struct ald_ent {
LDAP *ldap;
HE *hostent;
CR *credentials;
time_t timestamp;
};
struct cr_ent {
char *who;
char *pw;
int method;
};
struct he_ent {
char *host;
int port;
struct he_ent *next;
};
/*
* FORWARD DECLARATIONS:
*/
static int amu_ldap_rebind(ALD *a);
static int get_ldap_timestamp(LDAP *ld, char *map, time_t *ts);
/*
* FUNCTIONS:
*/
static void
he_free(HE *h)
{
XFREE(h->host);
if (h->next != NULL)
he_free(h->next);
XFREE(h);
}
static HE *
string2he(char *s)
{
char *c, *p;
HE *new, *old = NULL;
if (s == NULL)
return (NULL);
for (p = s; p; p = strchr(p, ',')) {
if (old != NULL) {
new = (HE *) xmalloc(sizeof(HE));
old->next = new;
old = new;
} else {
old = (HE *) xmalloc(sizeof(HE));
old->next = NULL;
}
c = strchr(p, ':');
if (c) { /* Host and port */
*c++ = '\0';
old->host = strdup(p);
old->port = atoi(c);
} else
old->host = strdup(p);
}
return (old);
}
static void
cr_free(CR *c)
{
XFREE(c->who);
XFREE(c->pw);
XFREE(c);
}
static void
ald_free(ALD *a)
{
he_free(a->hostent);
cr_free(a->credentials);
if (a->ldap != NULL)
ldap_unbind(a->ldap);
XFREE(a);
}
int
amu_ldap_init(mnt_map *m, char *map, time_t *ts)
{
ALD *aldh;
CR *creds;
if (!STREQ(gopt.map_type, AMD_LDAP_TYPE)) {
return (ENOENT);
}
#ifdef DEBUG
else {
dlog("Map %s is ldap\n", map);
}
#endif /* DEBUG */
aldh = (ALD *) xmalloc(sizeof(ALD));
creds = (CR *) xmalloc(sizeof(CR));
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, map);
return (ENOENT);
}
creds->who = "";
creds->pw = "";
creds->method = LDAP_AUTH_SIMPLE;
aldh->credentials = creds;
aldh->timestamp = 0;
#ifdef DEBUG
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))
return (ENOENT);
#ifdef DEBUG
dlog("Got timestamp for map %s: %d\n", map, *ts);
#endif /* DEBUG */
return (0);
}
static int
amu_ldap_rebind(ALD *a)
{
LDAP *ld;
HE *h;
CR *c = a->credentials;
time_t now = clocktime();
if (a->ldap != NULL) {
if ((a->timestamp - now) > AMD_LDAP_TTL) {
#ifdef DEBUG
dlog("Reestablishing ldap connection\n");
#endif /* DEBUG */
ldap_unbind(a->ldap);
a->timestamp = now;
} else
return (0);
}
while (TRUE) {
for (h = a->hostent; h != NULL; h = h->next) {
if ((ld = ldap_open(h->host, h->port)) == NULL) {
plog(XLOG_WARNING, "Unable to ldap_open to %s:%d\n", h->host, h->port);
break;
}
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) {
ldap_enable_cache(ld, gopt.ldap_cache_seconds, gopt.ldap_cache_maxmem);
a->ldap = ld;
a->timestamp = now;
return (0);
}
}
plog(XLOG_WARNING, "Exausted list of ldap servers, looping.\n");
}
plog(XLOG_USER, "Unable to (re)bind to any ldap hosts\n");
return (ENOENT);
}
static int
get_ldap_timestamp(LDAP * ld, char *map, time_t *ts)
{
struct timeval tv;
char **vals, *end;
char filter[MAXPATHLEN];
int i, err, nentries = 0;
LDAPMessage *res, *entry;
tv.tv_sec = 3;
tv.tv_usec = 0;
sprintf(filter, AMD_LDAP_TSFILTER, map);
#ifdef DEBUG
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;
dlog("Timestamp search timed out, trying again...\n");
}
if (err != LDAP_SUCCESS) {
*ts = 0;
plog(XLOG_USER, "LDAP timestamp search failed: %s\n",
ldap_err2string(ld->ld_errno));
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);
ldap_msgfree(entry);
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 %d 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);
ldap_msgfree(entry);
#ifdef DEBUG
dlog("The timestamp for %s is %d (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, 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,
LDAP_SCOPE_SUBTREE,
filter,
0,
0,
&tv,
&res);
if (err == LDAP_SUCCESS)
break;
}
switch (err) {
case LDAP_SUCCESS:
break;
case LDAP_NO_SUCH_OBJECT:
#ifdef DEBUG
dlog("No object\n");
#endif /* DEBUG */
ldap_msgfree(res);
return (ENOENT);
default:
plog(XLOG_USER, "LDAP search failed: %s\n",
ldap_err2string(a->ldap->ld_errno));
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);
}
entry = ldap_first_entry(a->ldap, res);
vals = ldap_get_values(a->ldap, entry, AMD_LDAP_ATTR);
nvals = ldap_count_values(vals);
if (nvals == 0) {
plog(XLOG_USER, "Missing value for %s in map %s\n", key, map);
ldap_value_free(vals);
ldap_msgfree(res);
ldap_msgfree(entry);
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;
} else {
plog(XLOG_USER, "Empty value for %s in map %s\n", key, map);
err = ENOENT;
}
ldap_msgfree(res);
ldap_msgfree(entry);
ldap_value_free(vals);
return (err);
}
int
amu_ldap_mtime(mnt_map *m, char *map, time_t *ts)
{
ALD *aldh = (ALD *) (m->map_data);
if (aldh == NULL) {
dlog("LDAP panic: unable to find map data\n");
return (ENOENT);
}
if (amu_ldap_rebind(aldh)) {
return (ENOENT);
}
if (get_ldap_timestamp(aldh->ldap, map, ts)) {
return (ENOENT);
}
return (0);
}

141
contrib/amd/amd/info_ndbm.c Normal file
View File

@ -0,0 +1,141 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: info_ndbm.c,v 5.2.2.1 1992/02/09 15:08:31 jsp beta $
*
*/
/*
* Get info from NDBM map
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* forward declarations */
int ndbm_init(mnt_map *m, char *map, time_t *tp);
int ndbm_mtime(mnt_map *m, char *map, time_t *tp);
int ndbm_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp);
static int
search_ndbm(DBM *db, char *key, char **val)
{
datum k, v;
k.dptr = key;
k.dsize = strlen(key) + 1;
v = dbm_fetch(db, k);
if (v.dptr) {
*val = strdup(v.dptr);
return 0;
}
return ENOENT;
}
int
ndbm_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
{
DBM *db;
db = dbm_open(map, O_RDONLY, 0);
if (db) {
struct stat stb;
int error;
#ifdef DBM_SUFFIX
char dbfilename[256];
strcpy(dbfilename, map);
strcat(dbfilename, DBM_SUFFIX);
error = stat(dbfilename, &stb);
#else /* not DBM_SUFFIX */
error = fstat(dbm_pagfno(db), &stb);
#endif /* not DBM_SUFFIX */
if (!error && *tp < stb.st_mtime) {
*tp = stb.st_mtime;
error = -1;
} else {
error = search_ndbm(db, key, pval);
}
(void) dbm_close(db);
return error;
}
return errno;
}
int
ndbm_init(mnt_map *m, char *map, time_t *tp)
{
DBM *db;
db = dbm_open(map, O_RDONLY, 0);
if (db) {
struct stat stb;
int error;
#ifdef DBM_SUFFIX
char dbfilename[256];
strcpy(dbfilename, map);
strcat(dbfilename, DBM_SUFFIX);
error = stat(dbfilename, &stb);
#else /* not DBM_SUFFIX */
error = fstat(dbm_pagfno(db), &stb);
#endif /* not DBM_SUFFIX */
if (error < 0)
*tp = clocktime();
else
*tp = stb.st_mtime;
dbm_close(db);
return 0;
}
return errno;
}
int
ndbm_mtime(mnt_map *m, char *map, time_t *tp)
{
return ndbm_init(m,map, tp);
}

401
contrib/amd/amd/info_nis.c Normal file
View File

@ -0,0 +1,401 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: info_nis.c,v 5.2.2.1 1992/02/09 15:08:32 jsp beta $
*
*/
/*
* Get info from NIS map
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/*
* NIS+ servers in NIS compat mode don't have yp_order()
*/
static int has_yp_order = FALSE;
/* forward declarations */
int nis_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *));
int nis_search(mnt_map *m, char *map, char *key, char **val, time_t *tp);
int nis_init(mnt_map *m, char *map, time_t *tp);
int nis_mtime(mnt_map *m, char *map, time_t *tp);
/* typedefs */
typedef void (*nis_callback_fxn_t)(mnt_map *, char *, char *);
#ifndef DEFINED_YPALL_CALLBACK_FXN_T
typedef int (*ypall_callback_fxn_t)();
#endif /* DEFINED_YPALL_CALLBACK_FXN_T */
struct nis_callback_data {
mnt_map *ncd_m;
char *ncd_map;
nis_callback_fxn_t ncd_fn;
};
/* Map to the right version of yp_all */
#ifdef HAVE_BAD_YP_ALL
# define yp_all am_yp_all
static int am_yp_all(char *indomain, char *inmap, struct ypall_callback *incallback);
#endif /* HAVE_BAD_YP_ALL */
/*
* Figure out the nis domain name
*/
static int
determine_nis_domain(void)
{
static int nis_not_running = 0;
char default_domain[YPMAXDOMAIN];
if (nis_not_running)
return ENOENT;
if (getdomainname(default_domain, sizeof(default_domain)) < 0) {
nis_not_running = 1;
plog(XLOG_ERROR, "getdomainname: %m");
return EIO;
}
if (!*default_domain) {
nis_not_running = 1;
plog(XLOG_WARNING, "NIS domain name is not set. NIS ignored.");
return ENOENT;
}
gopt.nis_domain = strdup(default_domain);
return 0;
}
/*
* Callback from yp_all
*/
static int
callback(int status, char *key, int kl, char *val, int vl, char *data)
{
struct nis_callback_data *ncdp = (struct nis_callback_data *) data;
if (status == YP_TRUE) {
/*
* Add to list of maps
*/
char *kp = strnsave(key, kl);
char *vp = strnsave(val, vl);
(*ncdp->ncd_fn) (ncdp->ncd_m, kp, vp);
/*
* We want more ...
*/
return FALSE;
} else {
/*
* NOMORE means end of map - otherwise log error
*/
if (status != YP_NOMORE) {
/*
* 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;
}
}
int
nis_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
{
int error;
struct nis_callback_data data;
struct ypall_callback cbinfo;
if (!gopt.nis_domain) {
error = determine_nis_domain();
if (error)
return error;
}
data.ncd_m = m;
data.ncd_map = map;
data.ncd_fn = fn;
cbinfo.data = (voidp) &data;
cbinfo.foreach = (ypall_callback_fxn_t) callback;
/*
* If you are using NIS and your yp_all function is "broken", you have to
* get it fixed. The bug in yp_all() is that it does not close a TCP
* connection to ypserv, and this ypserv runs out of open file descriptors,
* getting into an infinite loop, thus all YP clients eventually unbind
* and hang too.
*/
error = yp_all(gopt.nis_domain, map, &cbinfo);
if (error)
plog(XLOG_ERROR, "error grabbing nis map of %s: %s", map, yperr_string(ypprot_err(error)));
return error;
}
/*
* Check if NIS is up, so we can determine if to clear the map or not.
* Test it by checking the yp order.
* Returns: 0 if NIS is down, 1 if it is up.
*/
int
nis_isup(mnt_map *m, char *map)
{
YP_ORDER_OUTORDER_TYPE order;
int error;
static int last_status = 1; /* assume up by default */
if (has_yp_order) {
error = yp_order(gopt.nis_domain, map, &order);
if (error != 0) {
plog(XLOG_ERROR,
"nis_isup: error getting the order of map of %s: %s",
map, yperr_string(ypprot_err(error)));
last_status = 0;
return 0; /* NIS is down */
}
}
if (last_status == 0) { /* if was down before */
time_t dummy;
plog(XLOG_INFO, "nis_isup: NIS came back up for map %s", map);
/* XXX: do we really need to reinitialize nis? */
error = nis_init(m, map, &dummy);
if (!error)
last_status = 1;
}
return 1; /* NIS is up */
}
/*
* Try to locate a key using NIS.
*/
int
nis_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
{
int outlen;
int res;
YP_ORDER_OUTORDER_TYPE order;
/*
* Make sure domain initialised
*/
if (!gopt.nis_domain) {
int error = determine_nis_domain();
if (error)
return error;
}
if (has_yp_order) {
/*
* Check if map has changed
*/
if (yp_order(gopt.nis_domain, map, &order))
return EIO;
if ((time_t) order > *tp) {
*tp = (time_t) order;
return -1;
}
} else {
/*
* NIS+ server without yp_order
* Check if timeout has expired to invalidate the cache
*/
order = time(NULL);
if ((time_t)order - *tp > gopt.am_timeo) {
*tp = (time_t)order;
return(-1);
}
}
/*
* Lookup key
*/
res = yp_match(gopt.nis_domain, map, key, strlen(key), val, &outlen);
/*
* Do something interesting with the return code
*/
switch (res) {
case 0:
return 0;
case YPERR_KEY:
return ENOENT;
default:
plog(XLOG_ERROR, "%s: %s", map, yperr_string(res));
return EIO;
}
}
int
nis_init(mnt_map *m, char *map, time_t *tp)
{
YP_ORDER_OUTORDER_TYPE order;
int yp_order_result;
char *master;
if (!gopt.nis_domain) {
int error = determine_nis_domain();
if (error)
return error;
}
/*
* To see if the map exists, try to find
* a master for it.
*/
yp_order_result = yp_order(gopt.nis_domain, map, &order);
switch (yp_order_result) {
case 0:
has_yp_order = TRUE;
*tp = (time_t) order;
#ifdef DEBUG
dlog("NIS master for %s@%s has order %d", map, gopt.nis_domain, order);
#endif /* DEBUG */
break;
case YPERR_YPERR:
/* NIS+ server found ! */
has_yp_order = FALSE;
/* try yp_master() instead */
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);
}
break;
default:
return ENOENT;
}
return 0;
}
int
nis_mtime(mnt_map *m, char *map, time_t *tp)
{
return nis_init(m, map, tp);
}
#ifdef HAVE_BAD_YP_ALL
/*
* If you are using NIS and your yp_all function is "broken", use an
* alternate code which avoids a bug in yp_all(). The bug in yp_all() is
* that it does not close a TCP connection to ypserv, and this ypserv runs
* out of open filedescriptors, getting into an infinite loop, thus all YP
* clients enevtually unbind and hang too.
*
* Systems known to be plagued with this bug:
* earlier SunOS 4.x
* all irix systems (at this time, up to 6.4 was checked)
*
* -Erez Zadok <ezk@cs.columbia.edu>
* -James Tanis <jtt@cs.columbia.edu> */
static int
am_yp_all(char *indomain, char *inmap, struct ypall_callback *incallback)
{
int i, j;
char *outkey, *outval;
int outkeylen, outvallen;
char *outkey_old;
int outkeylen_old;
plog(XLOG_INFO, "NIS map %s reloading using am_yp_all", inmap);
i = yp_first(indomain, inmap, &outkey, &outkeylen, &outval, &outvallen);
if (i) {
plog(XLOG_ERROR, "yp_first() returned error: %s\n", yperr_string(i));
}
do {
j = (incallback->foreach)(YP_TRUE,
outkey,
outkeylen,
outval,
outvallen,
incallback->data);
if (j != FALSE) /* terminate loop */
break;
outkey_old = outkey;
outkeylen_old = outkeylen;
i = yp_next(indomain,
inmap,
outkey_old,
outkeylen_old,
&outkey,
&outkeylen,
&outval,
&outvallen);
} 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;
}
#endif /* HAVE_BAD_YP_ALL */

View File

@ -0,0 +1,321 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: info_nisplus.c,v 5.2.2.1 1992/02/09 15:08:32 jsp beta $
*
*/
/*
* Get info from NIS+ (version 3) map
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
#define NISPLUS_KEY "key="
#define NISPLUS_ORGDIR ".org_dir"
struct nis_callback_data {
mnt_map *ncd_m;
char *ncd_map;
void (*ncd_fn)();
};
struct nisplus_search_callback_data {
nis_name key;
char *value;
};
static int
nisplus_callback(const nis_name key, const nis_object *value, voidp opaquedata)
{
char *kp = strnsave(ENTRY_VAL(value, 0), ENTRY_LEN(value, 0));
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);
/*
* We want more ...
*/
return FALSE;
}
int
nisplus_reload(mnt_map *m, char *map, void (*fn) ())
{
int error = 0;
struct nis_callback_data data;
nis_result *result;
char *org; /* if map does not have ".org_dir" then append it */
nis_name map_name;
org = strstr(map, NISPLUS_ORGDIR);
if (org == NULL)
org = NISPLUS_ORGDIR;
else
org = "";
/* make some room for the NIS map_name */
map_name = xmalloc(strlen(map) + sizeof(NISPLUS_ORGDIR));
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);
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,
(int (*)()) nisplus_callback,
&data);
/* free off the NIS map_name */
XFREE(map_name);
if (result->status != NIS_SUCCESS && result->status != NIS_CBRESULTS)
error = 1;
if (error)
plog(XLOG_ERROR, "error grabbing nisplus map of %s: %s",
map,
nis_sperrno(result->status));
nis_freeresult(result);
return error;
}
static int
nisplus_search_callback(const nis_name key, const nis_object *value, voidp opaquedata)
{
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;
}
/*
* Try to locate a key using NIS+.
*/
int
nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
{
nis_result *result;
int error = 0;
struct nisplus_search_callback_data data;
nis_name index;
char *org; /* if map does not have ".org_dir" then append it */
org = strstr(map, NISPLUS_ORGDIR);
if (org == NULL)
org = NISPLUS_ORGDIR;
else
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)
);
if (index == NULL) {
plog(XLOG_ERROR,
"Unable to create index %s: %s",
map,
strerror(ENOMEM));
return ENOMEM;
}
sprintf(index, "[%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,
(int (*)()) nisplus_search_callback,
&data);
/* free off the NIS index */
XFREE(index);
if (result == NULL) {
plog(XLOG_ERROR, "%s: %s", map, strerror(ENOMEM));
return ENOMEM;
}
/*
* Do something interesting with the return code
*/
switch (result->status) {
case NIS_SUCCESS:
case NIS_CBRESULTS:
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));
}
*val = data.value;
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;
default:
plog(XLOG_ERROR, "%s: %s", map, nis_sperrno(result->status));
error = EIO;
break;
}
nis_freeresult(result);
return error;
}
int
nisplus_init(mnt_map *m, char *map, time_t *tp)
{
nis_result *result;
char *org; /* if map does not have ".org_dir" then append it */
nis_name map_name;
int error = 0;
org = strstr(map, NISPLUS_ORGDIR);
if (org == NULL)
org = NISPLUS_ORGDIR;
else
org = "";
/* make some room for the NIS map_name */
map_name = xmalloc(strlen(map) + sizeof(NISPLUS_ORGDIR));
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);
result = nis_lookup(map_name, (EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH));
/* free off the NIS map_name */
XFREE(map_name);
if (result == NULL) {
plog(XLOG_ERROR, "NISplus init <%s>: %s", map, strerror(ENOMEM));
return ENOMEM;
}
if (result->status != NIS_SUCCESS) {
#ifdef DEBUG
dlog("NISplus init <%s>: %s (%d)",
map, nis_sperrno(result->status), result->status);
#endif /* DEBUG */
error = ENOENT;
}
*tp = 0; /* no time */
nis_freeresult(result);
return error;
}
int
nisplus_mtime(mnt_map *m, char *map, time_t *tp)
{
return nisplus_init(m,map, tp);
}

View File

@ -0,0 +1,195 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: info_passwd.c,v 5.2.2.1 1992/02/09 15:08:33 jsp beta $
*
*/
/*
* Get info from password "file"
*
* This is experimental and probably doesn't do what you expect.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
#define PASSWD_MAP "/etc/passwd"
/* forward declarations */
int passwd_init(mnt_map *m, char *map, time_t *tp);
int passwd_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp);
/*
* Nothing to probe - check the map name is PASSWD_MAP.
*/
int
passwd_init(mnt_map *m, char *map, time_t *tp)
{
*tp = 0;
/*
* Recognize the old format "PASSWD_MAP"
* Uses default return string
* "type:=nfs;rfs:=/${var0}/${var1};rhost:=${var1};sublink:=${var2};fs:=${autodir}${var3}"
*/
if (STREQ(map, PASSWD_MAP))
return 0;
/*
* Recognize the new format "PASSWD_MAP:pval-format"
*/
if (!NSTREQ(map, PASSWD_MAP, sizeof(PASSWD_MAP) - 1))
return ENOENT;
if (map[sizeof(PASSWD_MAP)-1] != ':')
return ENOENT;
return 0;
}
/*
* Grab the entry via the getpwname routine
* Modify time is ignored by passwd - XXX
*/
int
passwd_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
{
char *dir = 0;
struct passwd *pw;
if (STREQ(key, "/defaults")) {
*pval = strdup("type:=nfs");
return 0;
}
pw = getpwnam(key);
if (pw) {
/*
* We chop the home directory up as follows:
* /anydir/dom1/dom2/dom3/user
*
* and return
* rfs:=/anydir/dom3;rhost:=dom3.dom2.dom1;sublink:=user
* and now have
* var0:=pw-prefix:=anydir
* var1:=pw-rhost:=dom3.dom2.dom1
* var2:=pw-user:=user
* var3:=pw-home:=/anydir/dom1/dom2/dom3/user
*
* This allows cross-domain entries in your passwd file.
* ... but forget about security!
*/
char *user;
char *p, *q;
char val[MAXPATHLEN];
char rhost[MAXHOSTNAMELEN];
dir = strdup(pw->pw_dir);
/*
* Find user name. If no / then Invalid...
*/
user = strrchr(dir, '/');
if (!user)
goto enoent;
*user++ = '\0';
/*
* Find start of host "path". If no / then Invalid...
*/
p = strchr(dir + 1, '/');
if (!p)
goto enoent;
*p++ = '\0';
/*
* At this point, p is dom1/dom2/dom3
* Copy, backwards, into rhost replacing
* / with .
*/
rhost[0] = '\0';
do {
q = strrchr(p, '/');
if (q) {
strcat(rhost, q + 1);
strcat(rhost, ".");
*q = '\0';
} else {
strcat(rhost, p);
}
} while (q);
/*
* Sanity check
*/
if (*rhost == '\0' || *user == '\0' || *dir == '\0')
goto enoent;
/*
* Make up return string
*/
q = strchr(rhost, '.');
if (q)
*q = '\0';
p = strchr(map, ':');
if (p)
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
dlog("passwd_search: map=%s key=%s -> %s", map, key, val);
#endif /* DEBUG */
if (q)
*q = '.';
*pval = strdup(val);
return 0;
}
enoent:
if (dir)
XFREE(dir);
return ENOENT;
}

View File

@ -0,0 +1,149 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: info_union.c,v 5.2.2.1 1992/02/09 15:08:34 jsp beta $
*
*/
/*
* Get info from the system namespace
*
* NOTE: Cannot handle reads back through the automounter.
* THIS WILL CAUSE A DEADLOCK!
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
#define UNION_PREFIX "union:"
#define UNION_PREFLEN 6
/* forward declarations */
int union_init(mnt_map *m, char *map, time_t *tp);
int union_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp);
int union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *));
/*
* No way to probe - check the map name begins with "union:"
*/
int
union_init(mnt_map *m, char *map, time_t *tp)
{
*tp = 0;
return NSTREQ(map, UNION_PREFIX, UNION_PREFLEN) ? 0 : ENOENT;
}
int
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;
for (p = v; p[1]; p++) ;
*pval = xmalloc(strlen(*p) + 5);
sprintf(*pval, "fs:=%s", *p);
XFREE(mapd);
XFREE(v);
return 0;
}
int
union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
{
char *mapd = strdup(map + UNION_PREFLEN);
char **v = strsplit(mapd, ':', '\"');
char **dir;
/*
* Add fake /defaults entry
*/
(*fn) (m, strdup("/defaults"), strdup("type:=link;opts:=nounmount;sublink:=${key}"));
for (dir = v; *dir; dir++) {
int dlen;
struct dirent *dp;
DIR *dirp = opendir(*dir);
if (!dirp) {
plog(XLOG_USER, "Cannot read directory %s: %m", *dir);
continue;
}
dlen = strlen(*dir);
#ifdef DEBUG
dlog("Reading directory %s...", *dir);
#endif /* DEBUG */
while ((dp = readdir(dirp))) {
char *val, *dpname = &dp->d_name[0];
if (dpname[0] == '.' &&
(dpname[1] == '\0' ||
(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);
(*fn) (m, strdup(dp->d_name), val);
}
closedir(dirp);
}
/*
* Add wildcard entry
*/
{
char *val = xmalloc(strlen(dir[-1]) + 5);
sprintf(val, "fs:=%s", dir[-1]);
(*fn) (m, strdup("*"), val);
}
XFREE(mapd);
XFREE(v);
return 0;
}

1112
contrib/amd/amd/map.c Normal file

File diff suppressed because it is too large Load Diff

1205
contrib/amd/amd/mapc.c Normal file

File diff suppressed because it is too large Load Diff

335
contrib/amd/amd/mntfs.c Normal file
View File

@ -0,0 +1,335 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: mntfs.c,v 5.2.2.2 1992/08/02 10:42:21 jsp Exp $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
qelem mfhead = {&mfhead, &mfhead};
int mntfs_allocated;
mntfs *
dup_mntfs(mntfs *mf)
{
if (mf->mf_refc == 0) {
if (mf->mf_cid)
untimeout(mf->mf_cid);
mf->mf_cid = 0;
}
mf->mf_refc++;
return mf;
}
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_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_refc = 1;
mf->mf_flags = 0;
mf->mf_error = -1;
mf->mf_cid = 0;
mf->mf_private = 0;
mf->mf_prfree = 0;
if (ops->ffserver)
mf->mf_server = (*ops->ffserver) (mf);
else
mf->mf_server = 0;
}
static mntfs *
alloc_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)
{
mntfs *mf = ALLOC(struct mntfs);
init_mntfs(mf, ops, mo, mp, info, auto_opts, mopts, remopts);
ins_que(&mf->mf_q, &mfhead);
mntfs_allocated++;
return mf;
}
mntfs *
find_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 */
ITER(mf, mntfs, &mfhead) {
if (STREQ(mf->mf_mount, mp)) {
/*
* Handle cases where error ops are involved
*/
if (ops == &amfs_error_ops) {
/*
* If the existing ops are not amfs_error_ops
* then continue...
*/
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;
}
if ((mf->mf_flags & MFF_RESTART) && amd_state == Run) {
/*
* 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
*/
mf2->mf_private = (voidp) dup_mntfs(mf);
mf2->mf_prfree = free_mntfs;
return mf2;
}
mf->mf_fo = mo;
if (!(mf->mf_flags & (MFF_MOUNTED | MFF_MOUNTING | MFF_UNMOUNTING))) {
fserver *fs;
mf->mf_flags &= ~MFF_ERROR;
mf->mf_error = -1;
mf->mf_auto = strealloc(mf->mf_auto, auto_opts);
mf->mf_mopts = strealloc(mf->mf_mopts, mopts);
mf->mf_remopts = strealloc(mf->mf_remopts, remopts);
mf->mf_info = strealloc(mf->mf_info, info);
if (mf->mf_private && mf->mf_prfree) {
(*mf->mf_prfree) (mf->mf_private);
mf->mf_private = 0;
}
fs = ops->ffserver ? (*ops->ffserver) (mf) : (fserver *) NULL;
if (mf->mf_server)
free_srvr(mf->mf_server);
mf->mf_server = fs;
}
return dup_mntfs(mf);
}
}
return alloc_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
}
mntfs *
new_mntfs(void)
{
return alloc_mntfs(&amfs_error_ops, (am_opts *) 0, "//nil//", ".", "", "", "");
}
static void
uninit_mntfs(mntfs *mf, int rmd)
{
if (mf->mf_auto)
XFREE(mf->mf_auto);
if (mf->mf_mopts)
XFREE(mf->mf_mopts);
if (mf->mf_remopts)
XFREE(mf->mf_remopts);
if (mf->mf_info)
XFREE(mf->mf_info);
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);
/*
* Clean up the file server
*/
if (mf->mf_server)
free_srvr(mf->mf_server);
/*
* Don't do a callback on this mount
*/
if (mf->mf_cid) {
untimeout(mf->mf_cid);
mf->mf_cid = 0;
}
}
static void
discard_mntfs(voidp v)
{
mntfs *mf = v;
rem_que(&mf->mf_q);
/*
* Free memory
*/
uninit_mntfs(mf, TRUE);
XFREE(mf);
--mntfs_allocated;
}
void
flush_mntfs(void)
{
mntfs *mf;
mf = AM_FIRST(mntfs, &mfhead);
while (mf != HEAD(mntfs, &mfhead)) {
mntfs *mf2 = mf;
mf = NEXT(mntfs, mf);
if (mf2->mf_refc == 0 && mf2->mf_cid)
discard_mntfs(mf2);
}
}
void
free_mntfs(voidp v)
{
mntfs *mf = v;
if (--mf->mf_refc == 0) {
if (mf->mf_flags & MFF_MOUNTED) {
int quoted;
mf->mf_flags &= ~MFF_MOUNTED;
/*
* Record for posterity
*/
quoted = strchr(mf->mf_info, ' ') != 0; /* cheap */
plog(XLOG_INFO, "%s%s%s %sed fstype %s from %s",
quoted ? "\"" : "",
mf->mf_info,
quoted ? "\"" : "",
mf->mf_error ? "discard" : "unmount",
mf->mf_ops->fs_type, mf->mf_mount);
}
if (mf->mf_ops->fs_flags & FS_DISCARD) {
#ifdef DEBUG
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 {
dlog("Discarding last mntfs reference to %s fstype %s",
mf->mf_mount, mf->mf_ops->fs_type);
}
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);
}
}
}
mntfs *
realloc_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)
{
mntfs *mf2;
if (mf->mf_refc == 1 && mf->mf_ops == &amfs_inherit_ops && STREQ(mf->mf_mount, mp)) {
/*
* If we are inheriting then just return
* the same node...
*/
return mf;
}
/*
* Re-use the existing mntfs if it is mounted.
* This traps a race in nfsx.
*/
if (mf->mf_ops != &amfs_error_ops &&
(mf->mf_flags & MFF_MOUNTED) &&
!FSRV_ISDOWN(mf->mf_server)) {
mf->mf_fo = mo;
return mf;
}
mf2 = find_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
free_mntfs(mf);
return mf2;
}

View File

@ -0,0 +1,250 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: nfs_prot_svc.c,v 5.2.2.1 1992/02/09 15:09:30 jsp beta $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* external definitions */
extern voidp nfsproc_null_2_svc(voidp, struct svc_req *);
extern nfsattrstat * nfsproc_getattr_2_svc(am_nfs_fh *, struct svc_req *);
extern nfsattrstat * nfsproc_setattr_2_svc(nfssattrargs *, struct svc_req *);
extern voidp nfsproc_root_2_svc(voidp, struct svc_req *);
extern nfsdiropres * nfsproc_lookup_2_svc(nfsdiropargs *, struct svc_req *);
extern nfsreadlinkres * nfsproc_readlink_2_svc(am_nfs_fh *, struct svc_req *);
extern nfsreadres * nfsproc_read_2_svc(nfsreadargs *, struct svc_req *);
extern voidp nfsproc_writecache_2_svc(voidp, struct svc_req *);
extern nfsattrstat * nfsproc_write_2_svc(nfswriteargs *, struct svc_req *);
extern nfsdiropres * nfsproc_create_2_svc(nfscreateargs *, struct svc_req *);
extern nfsstat * nfsproc_remove_2_svc(nfsdiropargs *, struct svc_req *);
extern nfsstat * nfsproc_rename_2_svc(nfsrenameargs *, struct svc_req *);
extern nfsstat * nfsproc_link_2_svc(nfslinkargs *, struct svc_req *);
extern nfsstat * nfsproc_symlink_2_svc(nfssymlinkargs *, struct svc_req *);
extern nfsdiropres * nfsproc_mkdir_2_svc(nfscreateargs *, struct svc_req *);
extern nfsstat * nfsproc_rmdir_2_svc(nfsdiropargs *, struct svc_req *);
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;
/* typedefs */
typedef char *(*nfssvcproc_t)(voidp, struct svc_req *);
void
nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
{
union {
am_nfs_fh nfsproc_getattr_2_arg;
nfssattrargs nfsproc_setattr_2_arg;
nfsdiropargs nfsproc_lookup_2_arg;
am_nfs_fh nfsproc_readlink_2_arg;
nfsreadargs nfsproc_read_2_arg;
nfswriteargs nfsproc_write_2_arg;
nfscreateargs nfsproc_create_2_arg;
nfsdiropargs nfsproc_remove_2_arg;
nfsrenameargs nfsproc_rename_2_arg;
nfslinkargs nfsproc_link_2_arg;
nfssymlinkargs nfsproc_symlink_2_arg;
nfscreateargs nfsproc_mkdir_2_arg;
nfsdiropargs fsproc_rmdir_2_arg;
nfsreaddirargs nfsproc_readdir_2_arg;
am_nfs_fh nfsproc_statfs_2_arg;
} argument;
char *result;
xdrproc_t xdr_argument, xdr_result;
nfssvcproc_t local;
nfs_program_2_transp = NULL;
switch (rqstp->rq_proc) {
case NFSPROC_NULL:
xdr_argument = (xdrproc_t) xdr_void;
xdr_result = (xdrproc_t) xdr_void;
local = (nfssvcproc_t) nfsproc_null_2_svc;
break;
case NFSPROC_GETATTR:
xdr_argument = (xdrproc_t) xdr_nfs_fh;
xdr_result = (xdrproc_t) xdr_attrstat;
local = (nfssvcproc_t) nfsproc_getattr_2_svc;
break;
case NFSPROC_SETATTR:
xdr_argument = (xdrproc_t) xdr_sattrargs;
xdr_result = (xdrproc_t) xdr_attrstat;
local = (nfssvcproc_t) nfsproc_setattr_2_svc;
break;
case NFSPROC_ROOT:
xdr_argument = (xdrproc_t) xdr_void;
xdr_result = (xdrproc_t) xdr_void;
local = (nfssvcproc_t) nfsproc_root_2_svc;
break;
case NFSPROC_LOOKUP:
xdr_argument = (xdrproc_t) xdr_diropargs;
xdr_result = (xdrproc_t) xdr_diropres;
local = (nfssvcproc_t) nfsproc_lookup_2_svc;
/*
* Cheap way to pass transp down to amfs_auto_lookuppn so it can
* be stored in the am_node structure and later used for
* quick_reply().
*/
nfs_program_2_transp = transp;
break;
case NFSPROC_READLINK:
xdr_argument = (xdrproc_t) xdr_nfs_fh;
xdr_result = (xdrproc_t) xdr_readlinkres;
local = (nfssvcproc_t) nfsproc_readlink_2_svc;
break;
case NFSPROC_READ:
xdr_argument = (xdrproc_t) xdr_readargs;
xdr_result = (xdrproc_t) xdr_readres;
local = (nfssvcproc_t) nfsproc_read_2_svc;
break;
case NFSPROC_WRITECACHE:
xdr_argument = (xdrproc_t) xdr_void;
xdr_result = (xdrproc_t) xdr_void;
local = (nfssvcproc_t) nfsproc_writecache_2_svc;
break;
case NFSPROC_WRITE:
xdr_argument = (xdrproc_t) xdr_writeargs;
xdr_result = (xdrproc_t) xdr_attrstat;
local = (nfssvcproc_t) nfsproc_write_2_svc;
break;
case NFSPROC_CREATE:
xdr_argument = (xdrproc_t) xdr_createargs;
xdr_result = (xdrproc_t) xdr_diropres;
local = (nfssvcproc_t) nfsproc_create_2_svc;
break;
case NFSPROC_REMOVE:
xdr_argument = (xdrproc_t) xdr_diropargs;
xdr_result = (xdrproc_t) xdr_nfsstat;
local = (nfssvcproc_t) nfsproc_remove_2_svc;
break;
case NFSPROC_RENAME:
xdr_argument = (xdrproc_t) xdr_renameargs;
xdr_result = (xdrproc_t) xdr_nfsstat;
local = (nfssvcproc_t) nfsproc_rename_2_svc;
break;
case NFSPROC_LINK:
xdr_argument = (xdrproc_t) xdr_linkargs;
xdr_result = (xdrproc_t) xdr_nfsstat;
local = (nfssvcproc_t) nfsproc_link_2_svc;
break;
case NFSPROC_SYMLINK:
xdr_argument = (xdrproc_t) xdr_symlinkargs;
xdr_result = (xdrproc_t) xdr_nfsstat;
local = (nfssvcproc_t) nfsproc_symlink_2_svc;
break;
case NFSPROC_MKDIR:
xdr_argument = (xdrproc_t) xdr_createargs;
xdr_result = (xdrproc_t) xdr_diropres;
local = (nfssvcproc_t) nfsproc_mkdir_2_svc;
break;
case NFSPROC_RMDIR:
xdr_argument = (xdrproc_t) xdr_diropargs;
xdr_result = (xdrproc_t) xdr_nfsstat;
local = (nfssvcproc_t) nfsproc_rmdir_2_svc;
break;
case NFSPROC_READDIR:
xdr_argument = (xdrproc_t) xdr_readdirargs;
xdr_result = (xdrproc_t) xdr_readdirres;
local = (nfssvcproc_t) nfsproc_readdir_2_svc;
break;
case NFSPROC_STATFS:
xdr_argument = (xdrproc_t) xdr_nfs_fh;
xdr_result = (xdrproc_t) xdr_statfsres;
local = (nfssvcproc_t) nfsproc_statfs_2_svc;
break;
default:
svcerr_noproc(transp);
return;
}
memset((char *) &argument, 0, sizeof(argument));
if (!svc_getargs(transp,
(XDRPROC_T_TYPE) xdr_argument,
(SVC_IN_ARG_TYPE) &argument)) {
plog(XLOG_ERROR,
"NFS xdr decode failed for %d %d %d",
rqstp->rq_prog, rqstp->rq_vers, rqstp->rq_proc);
svcerr_decode(transp);
return;
}
result = (*local) (&argument, rqstp);
nfs_program_2_transp = NULL;
if (result != NULL && !svc_sendreply(transp,
(XDRPROC_T_TYPE) xdr_result,
result)) {
svcerr_systemerr(transp);
}
if (!svc_freeargs(transp,
(XDRPROC_T_TYPE) xdr_argument,
(SVC_IN_ARG_TYPE) & argument)) {
plog(XLOG_FATAL, "unable to free rpc arguments in nfs_program_2");
going_down(1);
}
}

472
contrib/amd/amd/nfs_start.c Normal file
View File

@ -0,0 +1,472 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: nfs_start.c,v 5.2.2.1 1992/02/09 15:08:51 jsp beta $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
#ifndef SELECT_MAXWAIT
# define SELECT_MAXWAIT 16
#endif /* not SELECT_MAXWAIT */
SVCXPRT *nfsxprt;
u_short nfs_port;
#ifdef HAVE_FS_AUTOFS
SVCXPRT *autofsxprt = NULL;
u_short autofs_port = 0;
#endif /* HAVE_FS_AUTOFS */
#ifndef HAVE_SIGACTION
# define MASKED_SIGS (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGCHLD)|sigmask(SIGHUP))
#endif /* not HAVE_SIGACTION */
#ifdef DEBUG
/*
* Check that we are not burning resources
*/
static void
checkup(void)
{
static int max_fd = 0;
static char *max_mem = 0;
int next_fd = dup(0);
caddr_t next_mem = sbrk(0);
close(next_fd);
if (max_fd < next_fd) {
dlog("%d new fds allocated; total is %d",
next_fd - max_fd, next_fd);
max_fd = next_fd;
}
if (max_mem < next_mem) {
#ifdef HAVE_GETPAGESIZE
dlog("%#x bytes of memory allocated; total is %#x (%ld pages)",
next_mem - max_mem, next_mem,
((long) next_mem + getpagesize() - 1) / getpagesize());
#else /* not HAVE_GETPAGESIZE */
dlog("%#x bytes of memory allocated; total is %#x",
next_mem - max_mem, next_mem);
#endif /* not HAVE_GETPAGESIZE */
max_mem = next_mem;
}
}
#endif /* DEBUG */
static int
#ifdef HAVE_SIGACTION
do_select(sigset_t smask, int fds, fd_set *fdp, struct timeval *tvp)
#else /* not HAVE_SIGACTION */
do_select(int smask, int fds, fd_set *fdp, struct timeval *tvp)
#endif /* not HAVE_SIGACTION */
{
int sig;
int nsel;
if ((sig = setjmp(select_intr))) {
select_intr_valid = 0;
/* Got a signal */
switch (sig) {
case SIGINT:
case SIGTERM:
amd_state = Finishing;
reschedule_timeout_mp();
break;
}
nsel = -1;
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
* up above.
*/
#ifdef HAVE_SIGACTION
sigprocmask(SIG_SETMASK, &smask, NULL);
#else /* not HAVE_SIGACTION */
(void) sigsetmask(smask);
#endif /* not HAVE_SIGACTION */
/*
* Wait for input
*/
nsel = select(fds, fdp, (fd_set *) 0, (fd_set *) 0,
tvp->tv_sec ? tvp : (struct timeval *) 0);
}
#ifdef HAVE_SIGACTION
sigprocmask(SIG_BLOCK, &masked_sigs, NULL);
#else /* not HAVE_SIGACTION */
(void) sigblock(MASKED_SIGS);
#endif /* not HAVE_SIGACTION */
/*
* Perhaps reload the cache?
*/
if (do_mapc_reload < clocktime()) {
mapc_reload();
do_mapc_reload = clocktime() + ONE_HOUR;
}
return nsel;
}
/*
* Determine whether anything is left in
* the RPC input queue.
*/
static int
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);
}
static serv_state
run_rpc(void)
{
#ifdef HAVE_SIGACTION
sigset_t smask;
sigprocmask(SIG_BLOCK, &masked_sigs, &smask);
#else /* not HAVE_SIGACTION */
int smask = sigblock(MASKED_SIGS);
#endif /* not HAVE_SIGACTION */
next_softclock = clocktime();
amd_state = Run;
/*
* Keep on trucking while we are in Run mode. This state
* is switched to Quit after all the file systems have
* been unmounted.
*/
while ((int) amd_state <= (int) Finishing) {
struct timeval tvv;
int nsel;
time_t now;
#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);
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 */
#endif /* not HAVE_SVC_GETREQSET */
#ifdef DEBUG
checkup();
#endif /* DEBUG */
/*
* If the full timeout code is not called,
* then recompute the time delta manually.
*/
now = clocktime();
if (next_softclock <= now) {
if (amd_state == Finishing)
umount_exported();
tvv.tv_sec = softclock();
} else {
tvv.tv_sec = next_softclock - now;
}
tvv.tv_usec = 0;
if (amd_state == Finishing && last_used_map < 0) {
flush_mntfs();
amd_state = Quit;
break;
}
if (tvv.tv_sec <= 0)
tvv.tv_sec = SELECT_MAXWAIT;
#ifdef DEBUG
if (tvv.tv_sec) {
dlog("Select waits for %ds", 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;
}
perror("select");
break;
case 0:
break;
default:
/*
* 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);
}
if (nsel) {
/*
* Anything left must be a normal
* RPC request.
*/
#ifdef HAVE_SVC_GETREQSET
svc_getreqset(&readfds);
#else /* not HAVE_SVC_GETREQSET */
# ifdef FD_SET
svc_getreq(readfds.fds_bits[0]);
# else /* not FD_SET */
svc_getreq(readfds);
# endif /* not FD_SET */
#endif /* not HAVE_SVC_GETREQSET */
}
break;
}
}
#ifdef HAVE_SIGACTION
sigprocmask(SIG_SETMASK, &smask, NULL);
#else /* not HAVE_SIGACTION */
(void) sigsetmask(smask);
#endif /* not HAVE_SIGACTION */
if (amd_state == Quit)
amd_state = Done;
return amd_state;
}
int
mount_automounter(int ppid)
{
/*
* Old code replaced by rpc-trash patch.
* Erez Zadok <ezk@cs.columbia.edu>
int so = socket(AF_INET, SOCK_DGRAM, 0);
*/
SVCXPRT *udp_amqp = NULL, *tcp_amqp = NULL;
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 */
#ifdef HAVE_FS_AUTOFS
int soAUTOFS;
#endif /* HAVE_FS_AUTOFS */
/*
* Create the nfs service for amd
*/
#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;
#ifdef HAVE_FS_AUTOFS
/*
* Create the autofs service for amd.
*/
plog(XLOG_INFO, "creating autofs service listener");
ret = create_autofs_service(&soAUTOFS, &autofs_port, &autofsxprt, autofs_program_1);
/* if autofs service fails it is OK if using a test amd */
if (ret != 0 && gopt.portmap_program == AMQ_PROGRAM)
return ret;
#endif /* HAVE_FS_AUTOFS */
/*
* Start RPC forwarding
*/
if (fwd_init() != 0)
return 3;
/*
* Construct the root automount node
*/
make_root_node();
/*
* Pick up the pieces from a previous run
* This is likely to (indirectly) need the rpc_fwd package
* so it *must* come after the call to fwd_init().
*/
if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS)
restart();
/*
* Mount the top-level auto-mountpoints
*/
nmount = mount_exported();
/*
* Now safe to tell parent that we are up and running
*/
if (ppid)
kill(ppid, SIGQUIT);
if (nmount == 0) {
plog(XLOG_FATAL, "No work to do - quitting");
amd_state = Done;
return 0;
}
#ifdef DEBUG
amuDebug(D_AMQ) {
#endif /* DEBUG */
/*
* 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 */
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 */
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
*/
reschedule_timeout_mp();
/*
* Start the server
*/
if (run_rpc() != Done) {
plog(XLOG_FATAL, "run_rpc failed");
amd_state = Done;
}
return 0;
}

610
contrib/amd/amd/nfs_subr.c Normal file
View File

@ -0,0 +1,610 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: nfs_subr.c,v 5.2.2.1 1992/02/09 15:08:53 jsp beta $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/*
* Convert from UN*X to NFS error code.
* Some systems like linux define their own (see
* conf/mount/mount_linux.h).
*/
#ifndef nfs_error
# define nfs_error(e) ((nfsstat)(e))
#endif /* nfs_error */
/* forward declarations */
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)
{
char *ln;
/*
* If there is a readlink method, then use
* that, otherwise if a link exists use
* that, otherwise use the mount point.
*/
if (mp->am_mnt->mf_ops->readlink) {
int retry = 0;
mp = (*mp->am_mnt->mf_ops->readlink) (mp, &retry);
if (mp == 0) {
*error_return = retry;
return 0;
}
/* reschedule_timeout_mp(); */
}
if (mp->am_link) {
ln = mp->am_link;
} else {
ln = mp->am_mnt->mf_mount;
}
if (attrpp)
*attrpp = &mp->am_attr;
return ln;
}
voidp
nfsproc_null_2_svc(voidp argp, struct svc_req *rqstp)
{
static char res;
return (voidp) &res;
}
nfsattrstat *
nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
{
static nfsattrstat res;
am_node *mp;
int retry;
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "getattr:");
#endif /* DEBUG */
mp = fh_to_mp2(argp, &retry);
if (mp == 0) {
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "\tretry=%d", retry);
#endif /* DEBUG */
if (retry < 0)
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", mp->am_path,
attrp->ns_u.ns_attr_u.na_size);
#endif /* DEBUG */
mp->am_stats.s_getattr++;
return attrp;
}
#ifndef MNT2_NFS_OPT_SYMTTL
/*
* This code is needed to defeat Solaris 2.4's (and newer) symlink values
* cache. It forces the last-modifed time of the symlink to be current.
* It is not needed if the O/S has an nfs flag to turn off the
* symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez.
*/
if (++res.ns_u.ns_attr_u.na_mtime.nt_useconds == 0)
++res.ns_u.ns_attr_u.na_mtime.nt_seconds;
#endif /* not MNT2_NFS_OPT_SYMTTL */
return &res;
}
nfsattrstat *
nfsproc_setattr_2_svc(nfssattrargs *argp, struct svc_req *rqstp)
{
static nfsattrstat res;
if (!fh_to_mp(&argp->sag_fhandle))
res.ns_status = nfs_error(ESTALE);
else
res.ns_status = nfs_error(EROFS);
return &res;
}
voidp
nfsproc_root_2_svc(voidp argp, struct svc_req *rqstp)
{
static char res;
return (voidp) &res;
}
nfsdiropres *
nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
{
static nfsdiropres res;
am_node *mp;
int retry;
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "lookup:");
#endif /* DEBUG */
mp = fh_to_mp2(&argp->da_fhandle, &retry);
if (mp == 0) {
if (retry < 0)
return 0;
res.dr_status = nfs_error(retry);
} 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 (ap == 0) {
if (error < 0) {
#ifdef DEBUG
dlog("Not sending RPC reply");
#endif /* DEBUG */
amd_stats.d_drops++;
return 0;
}
res.dr_status = nfs_error(error);
} else {
mp_to_fh(ap, &res.dr_u.dr_drok_u.drok_fhandle);
res.dr_u.dr_drok_u.drok_attributes = ap->am_fattr;
res.dr_status = NFS_OK;
}
mp->am_stats.s_lookup++;
/* reschedule_timeout_mp(); */
}
return &res;
}
void
quick_reply(am_node *mp, int error)
{
SVCXPRT *transp = mp->am_transp;
nfsdiropres res;
xdrproc_t xdr_result = (xdrproc_t) xdr_diropres;
/*
* If there's a transp structure then we can reply to the client's
* nfs lookup request.
*/
if (transp) {
if (error == 0) {
/*
* Construct a valid reply to a lookup request. Same
* code as in nfsproc_lookup_2_svc() above.
*/
mp_to_fh(mp, &res.dr_u.dr_drok_u.drok_fhandle);
res.dr_u.dr_drok_u.drok_attributes = mp->am_fattr;
res.dr_status = NFS_OK;
} else
/*
* Return the error that was passed to us.
*/
res.dr_status = nfs_error(error);
/*
* Send off our reply
*/
if (!svc_sendreply(transp, (XDRPROC_T_TYPE) xdr_result, (SVC_IN_ARG_TYPE) & res))
svcerr_systemerr(transp);
/*
* Free up transp. It's only used for one reply.
*/
XFREE(transp);
mp->am_transp = NULL;
#ifdef DEBUG
dlog("Quick reply sent for %s", mp->am_mnt->mf_mount);
#endif /* DEBUG */
}
}
nfsreadlinkres *
nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
{
static nfsreadlinkres res;
am_node *mp;
int retry;
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "readlink:");
#endif /* DEBUG */
mp = fh_to_mp2(argp, &retry);
if (mp == 0) {
readlink_retry:
if (retry < 0)
return 0;
res.rlr_status = nfs_error(retry);
} else {
char *ln = do_readlink(mp, &retry, (nfsattrstat **) 0);
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 */
res.rlr_u.rlr_data_u = ln;
mp->am_stats.s_readlink++;
}
return &res;
}
nfsreadres *
nfsproc_read_2_svc(nfsreadargs *argp, struct svc_req *rqstp)
{
static nfsreadres res;
memset((char *) &res, 0, sizeof(res));
res.rr_status = nfs_error(EACCES);
return &res;
}
voidp
nfsproc_writecache_2_svc(voidp argp, struct svc_req *rqstp)
{
static char res;
return (voidp) &res;
}
nfsattrstat *
nfsproc_write_2_svc(nfswriteargs *argp, struct svc_req *rqstp)
{
static nfsattrstat res;
if (!fh_to_mp(&argp->wra_fhandle))
res.ns_status = nfs_error(ESTALE);
else
res.ns_status = nfs_error(EROFS);
return &res;
}
nfsdiropres *
nfsproc_create_2_svc(nfscreateargs *argp, struct svc_req *rqstp)
{
static nfsdiropres res;
if (!fh_to_mp(&argp->ca_where.da_fhandle))
res.dr_status = nfs_error(ESTALE);
else
res.dr_status = nfs_error(EROFS);
return &res;
}
static nfsstat *
unlink_or_rmdir(nfsdiropargs *argp, struct svc_req *rqstp, int unlinkp)
{
static nfsstat res;
int retry;
am_node *mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_DELETE);
if (mp == 0) {
if (retry < 0)
return 0;
res = nfs_error(retry);
goto out;
}
if (mp->am_fattr.na_type != NFDIR) {
res = nfs_error(ENOTDIR);
goto out;
}
#ifdef DEBUG
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);
if (mp == 0) {
/*
* Ignore retries...
*/
if (retry < 0)
retry = 0;
/*
* Usual NFS workaround...
*/
else if (retry == ENOENT)
retry = 0;
res = nfs_error(retry);
} else {
forcibly_timeout_mp(mp);
res = NFS_OK;
}
out:
return &res;
}
nfsstat *
nfsproc_remove_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
{
return unlink_or_rmdir(argp, rqstp, TRUE);
}
nfsstat *
nfsproc_rename_2_svc(nfsrenameargs *argp, struct svc_req *rqstp)
{
static nfsstat res;
if (!fh_to_mp(&argp->rna_from.da_fhandle) || !fh_to_mp(&argp->rna_to.da_fhandle))
res = nfs_error(ESTALE);
/*
* If the kernel is doing clever things with referenced files
* then let it pretend...
*/
else if (NSTREQ(argp->rna_to.da_name, ".nfs", 4))
res = NFS_OK;
/*
* otherwise a failure
*/
else
res = nfs_error(EROFS);
return &res;
}
nfsstat *
nfsproc_link_2_svc(nfslinkargs *argp, struct svc_req *rqstp)
{
static nfsstat res;
if (!fh_to_mp(&argp->la_fhandle) || !fh_to_mp(&argp->la_to.da_fhandle))
res = nfs_error(ESTALE);
else
res = nfs_error(EROFS);
return &res;
}
nfsstat *
nfsproc_symlink_2_svc(nfssymlinkargs *argp, struct svc_req *rqstp)
{
static nfsstat res;
if (!fh_to_mp(&argp->sla_from.da_fhandle))
res = nfs_error(ESTALE);
else
res = nfs_error(EROFS);
return &res;
}
nfsdiropres *
nfsproc_mkdir_2_svc(nfscreateargs *argp, struct svc_req *rqstp)
{
static nfsdiropres res;
if (!fh_to_mp(&argp->ca_where.da_fhandle))
res.dr_status = nfs_error(ESTALE);
else
res.dr_status = nfs_error(EROFS);
return &res;
}
nfsstat *
nfsproc_rmdir_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
{
return unlink_or_rmdir(argp, rqstp, FALSE);
}
nfsreaddirres *
nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
{
static nfsreaddirres res;
static nfsentry e_res[MAX_READDIR_ENTRIES];
am_node *mp;
int retry;
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "readdir:");
#endif /* DEBUG */
mp = fh_to_mp2(&argp->rda_fhandle, &retry);
if (mp == 0) {
if (retry < 0)
return 0;
res.rdr_status = nfs_error(retry);
} else {
#ifdef DEBUG
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));
mp->am_stats.s_readdir++;
}
return &res;
}
nfsstatfsres *
nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
{
static nfsstatfsres res;
am_node *mp;
int retry;
mntent_t mnt;
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "statfs:");
#endif /* DEBUG */
mp = fh_to_mp2(argp, &retry);
if (mp == 0) {
if (retry < 0)
return 0;
res.sfr_status = nfs_error(retry);
} else {
nfsstatfsokres *fp;
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "\tstat_fs(%s)", mp->am_path);
#endif /* DEBUG */
/*
* just return faked up file system information
*/
fp = &res.sfr_u.sfr_reply_u;
fp->sfrok_tsize = 1024;
fp->sfrok_bsize = 1024;
/* check if map is browsable and show_statfs_entries=yes */
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")) {
count_map_entries(mp,
&fp->sfrok_blocks,
&fp->sfrok_bfree,
&fp->sfrok_bavail);
}
} else {
fp->sfrok_blocks = 0; /* set to 1 if you don't want empty automounts */
fp->sfrok_bfree = 0;
fp->sfrok_bavail = 0;
}
res.sfr_status = NFS_OK;
mp->am_stats.s_statfs++;
}
return &res;
}
/*
* count how many total entries there are in a map, and how many
* of them are in use.
*/
static void
count_map_entries(const am_node *mp, u_int *out_blocks, u_int *out_bfree, u_int *out_bavail)
{
u_int blocks, bfree, bavail, i;
mntfs *mf;
mnt_map *mmp;
kv *k;
blocks = bfree = bavail = 0;
if (!mp)
goto out;
mf = mp->am_mnt;
if (!mf)
goto out;
mmp = (mnt_map *) mf->mf_private;
if (!mmp)
goto out;
/* iterate over keys */
for (i = 0; i < NKVHASH; i++) {
for (k = mmp->kvhash[i]; k ; k = k->next) {
if (!k->key)
continue;
blocks++;
/*
* XXX: Need to count how many are actively in use and recompute
* bfree and bavail based on it.
*/
}
}
out:
*out_blocks = blocks;
*out_bfree = bfree;
*out_bavail = bavail;
}

View File

@ -0,0 +1,293 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: ops_TEMPLATE.c,v 5.2.2.3 1992/08/02 10:42:21 jsp Exp $
*
*/
/*
* An empty template for an amd pseudo filesystem "foofs".
*/
/*
* NOTE: if this is an Amd file system, prepend "amfs_" to all foofs symbols
* and renamed the file name to amfs_foofs.c. If it is a native file system
* (such as pcfs, isofs, or ffs), then you can keep the names as is, and
* just rename the file to ops_foofs.c.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* 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 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 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);
/*
* Foofs operations.
* Define only those you need, others set to 0 (NULL)
*/
am_ops foofs_ops =
{
"foofs", /* name of file system */
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_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 */
};
/*
* Check that f/s has all needed fields.
* Returns: matched string if found, NULL otherwise.
*/
static char *
foofs_match(am_opts *fo)
{
char *cp = "fill this with a way to find the match";
plog(XLOG_INFO, "entering foofs_match...");
if (cp)
return cp; /* OK */
return NULL; /* not OK */
}
/*
* Initialize.
* Returns: 0 if OK, non-zero (errno) if failed.
*/
static int
foofs_init(mntfs *mf)
{
int error = 0;
plog(XLOG_INFO, "entering foofs_init...");
error = EPERM; /* XXX: fixme */
return error;
}
/*
* Mount vnode.
* Returns: 0 if OK, non-zero (errno) if failed.
*/
static int
foofs_mount(am_node *mp)
{
int error = 0;
plog(XLOG_INFO, "entering foofs_mount...");
error = EPERM; /* XXX: fixme */
return error;
}
/*
* Mount vfs.
* Returns: 0 if OK, non-zero (errno) if failed.
*/
static int
foofs_fmount(mntfs *mf)
{
int error = 0;
plog(XLOG_INFO, "entering foofs_fmount...");
error = EPERM; /* XXX: fixme */
return error;
}
/*
* Unmount vnode.
* Returns: 0 if OK, non-zero (errno) if failed.
*/
static int
foofs_umount(am_node *mp)
{
int error = 0;
plog(XLOG_INFO, "entering foofs_umount...");
error = EPERM; /* XXX: fixme */
return error;
}
/*
* Unmount VFS.
* Returns: 0 if OK, non-zero (errno) if failed.
*/
static int
foofs_fumount(mntfs *mf)
{
int error = 0;
plog(XLOG_INFO, "entering foofs_fumount...");
error = EPERM; /* XXX: fixme */
return error;
}
/*
* Lookup path-name.
* Returns: the am_node that was found, or NULL if failed.
* If failed, also fills in errno in error_return.
*/
static am_node *
foofs_lookuppn(am_node *mp, char *fname, int *error_return, int op)
{
int error = 0;
plog(XLOG_INFO, "entering foofs_lookuppn...");
error = EPERM; /* XXX: fixme */
*error_return = error;
return NULL;
}
/*
* Read directory.
* Returns: 0 if OK, non-zero (errno) if failed.
* 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)
{
int error = 0;
plog(XLOG_INFO, "entering foofs_readdir...");
error = EPERM; /* XXX: fixme */
return error;
}
/*
* Read link.
* Returns: am_node found, or NULL if not found.
* If failed, fills in errno in error_return.
*/
static am_node *
foofs_readlink(am_node *mp, int *error_return)
{
int error = 0;
plog(XLOG_INFO, "entering foofs_readlink...");
error = EPERM; /* XXX: fixme */
*error_return = error;
return NULL;
}
/*
* Async mount callback function.
* After the base mount went OK, sometimes
* there are additional actions that are needed. See union_mounted() and
* toplvl_mounted().
*/
static void
foofs_mounted(mntfs *mf)
{
plog(XLOG_INFO, "entering foofs_mounted...");
return;
}
/*
* Async unmount callback function.
* After the base umount() succeeds, we may want to take extra actions,
* such as informing remote mount daemons that we've unmounted them.
* See amfs_auto_umounted(), host_umounted(), nfs_umounted().
*/
static void
foofs_umounted(am_node *mp)
{
plog(XLOG_INFO, "entering foofs_umounted...");
return;
}
/*
* Find a file server.
* Returns: fserver of found server, or NULL if not found.
*/
fserver *
foofs_ffserver(mntfs *mf)
{
plog(XLOG_INFO, "entering foofs_ffserver...");
return NULL;
}

1275
contrib/amd/amd/ops_autofs.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,247 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: ops_cachefs.c,v 5.2.2.3 1992/08/02 10:42:21 jsp Exp $
*
*/
/*
* Caching filesystem (Solaris 2.x)
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* 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);
/*
* Ops structure
*/
am_ops cachefs_ops =
{
"cachefs",
cachefs_match,
cachefs_init,
amfs_auto_fmount,
cachefs_fmount,
amfs_auto_fumount,
cachefs_fumount,
amfs_error_lookuppn,
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
};
/*
* Check that f/s has all needed fields.
* Returns: matched string if found, NULL otherwise.
*/
static char *
cachefs_match(am_opts *fo)
{
/* sanity check */
if (!fo->opt_rfs || !fo->opt_fs || !fo->opt_cachedir) {
plog(XLOG_USER, "cachefs: must specify cachedir, rfs, and fs");
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);
}
/*
* Initialize.
* Returns: 0 if OK, non-zero (errno) if failed.
*/
static int
cachefs_init(mntfs *mf)
{
/*
* Save cache directory name
*/
if (mf->mf_refc == 1) {
mf->mf_private = (voidp) strdup(mf->mf_fo->opt_cachedir);
mf->mf_prfree = (void (*)(voidp)) free;
}
return 0;
}
/*
* mntpt is the mount point ($fs) [XXX: was 'dir']
* backdir is the mounted pathname ($rfs) [XXX: was 'fs_name']
* cachedir is the cache directory ($cachedir)
*/
static int
mount_cachefs(char *mntpt, char *backdir, char *cachedir, char *opts)
{
cachefs_args_t ca;
mntent_t mnt;
int flags;
char *cp;
MTYPE_TYPE type = MOUNT_TYPE_CACHEFS; /* F/S mount type */
memset((voidp) &ca, 0, sizeof(ca)); /* Paranoid */
/*
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = mntpt;
mnt.mnt_fsname = backdir;
mnt.mnt_type = MNTTAB_TYPE_CACHEFS;
mnt.mnt_opts = opts;
flags = compute_mount_flags(&mnt);
/* Fill in cachefs mount arguments */
/*
* XXX: Caveats
* (1) cache directory is NOT checked for sanity beforehand, nor is it
* purged. Maybe it should be purged first?
* (2) cache directory is NOT locked. Should we?
*/
/* mount flags */
ca.cfs_options.opt_flags = CFS_WRITE_AROUND | CFS_ACCESS_BACKFS;
/* cache population size */
ca.cfs_options.opt_popsize = DEF_POP_SIZE; /* default: 64K */
/* filegrp size */
ca.cfs_options.opt_fgsize = DEF_FILEGRP_SIZE; /* default: 256 */
/* CFS ID for file system (must be unique) */
ca.cfs_fsid = cachedir;
/* 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);
/* convert '/' to '_' (Solaris does that...) */
cp = ca.cfs_cacheid;
while ((cp = strpbrk(cp, "/")) != NULL)
*cp = '_';
/* path for this cache dir */
ca.cfs_cachedir = cachedir;
/* back filesystem dir */
ca.cfs_backfs = backdir;
/* same as nfs values (XXX: need to handle these options) */
ca.cfs_acregmin = 0;
ca.cfs_acregmax = 0;
ca.cfs_acdirmin = 0;
ca.cfs_acdirmax = 0;
/*
* Call generic mount routine
*/
return mount_fs(&mnt, flags, (caddr_t) &ca, 0, type, 0, NULL, mnttab_file_name);
}
static int
cachefs_fmount(mntfs *mf)
{
int error;
error = mount_cachefs(mf->mf_mount,
mf->mf_fo->opt_rfs,
mf->mf_fo->opt_cachedir,
mf->mf_mopts);
if (error) {
errno = error;
/* according to Solaris, if errno==ESRCH, "options to not match" */
if (error == ESRCH)
plog(XLOG_ERROR, "mount_cachefs: options to no match: %m");
else
plog(XLOG_ERROR, "mount_cachefs: %m");
return error;
}
return 0;
}
static int
cachefs_fumount(mntfs *mf)
{
int error;
error = UMOUNT_FS(mf->mf_mount, mnttab_file_name);
/*
* In the case of cachefs, we must fsck the cache directory. Otherwise,
* it will remain inconsistent, and the next cachefs mount will fail
* with the error "no space left on device" (ENOSPC).
*
* XXX: this is hacky! use fork/exec/wait instead...
*/
if (!error) {
char *cachedir = NULL;
char cmd[128];
cachedir = (char *) mf->mf_private;
plog(XLOG_INFO, "running fsck on cache directory \"%s\"", cachedir);
sprintf(cmd, "fsck -F cachefs %s", cachedir);
system(cmd);
}
return error;
}

206
contrib/amd/amd/ops_cdfs.c Normal file
View File

@ -0,0 +1,206 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: ops_cdfs.c,v 5.2.2.1 1992/02/09 15:09:08 jsp beta $
*
*/
/*
* High Sierra (CD-ROM) file system
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* forward declarations */
static char *cdfs_match(am_opts *fo);
static int cdfs_fmount(mntfs *mf);
static int cdfs_fumount(mntfs *mf);
/*
* Ops structure
*/
am_ops cdfs_ops =
{
"cdfs",
cdfs_match,
0, /* cdfs_init */
amfs_auto_fmount,
cdfs_fmount,
amfs_auto_fumount,
cdfs_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* cdfs_readlink */
0, /* cdfs_mounted */
0, /* cdfs_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO
};
/*
* CDFS needs remote filesystem.
*/
static char *
cdfs_match(am_opts *fo)
{
if (!fo->opt_dev) {
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
*/
return strdup(fo->opt_dev);
}
static int
mount_cdfs(char *dir, char *fs_name, char *opts)
{
cdfs_args_t cdfs_args;
mntent_t mnt;
int genflags, cdfs_flags;
/*
* Figure out the name of the file system type.
*/
MTYPE_TYPE type = MOUNT_TYPE_CDFS;
memset((voidp) &cdfs_args, 0, sizeof(cdfs_args)); /* Paranoid */
cdfs_flags = 0;
/*
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
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))
# ifdef MNT2_CDFS_OPT_DEFPERM
cdfs_flags |= MNT2_CDFS_OPT_DEFPERM;
# else /* not MNT2_CDFS_OPT_DEFPERM */
cdfs_flags &= ~MNT2_CDFS_OPT_NODEFPERM;
# endif /* not MNT2_CDFS_OPT_DEFPERM */
#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))
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))
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))
cdfs_flags |= MNT2_CDFS_OPT_RRIP;
#endif /* defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP) */
genflags = compute_mount_flags(&mnt);
#ifdef HAVE_FIELD_CDFS_ARGS_T_FLAGS
cdfs_args.flags = cdfs_flags;
#endif /* HAVE_FIELD_CDFS_ARGS_T_FLAGS */
#ifdef HAVE_FIELD_CDFS_ARGS_T_ISO_FLAGS
cdfs_args.iso_flags = genflags | cdfs_flags;
#endif /* HAVE_FIELD_CDFS_ARGS_T_ISO_FLAGS */
#ifdef HAVE_FIELD_CDFS_ARGS_T_ISO_PGTHRESH
cdfs_args.iso_pgthresh = hasmntval(&mnt, MNTTAB_OPT_PGTHRESH);
#endif /* HAVE_FIELD_CDFS_ARGS_T_ISO_PGTHRESH */
#ifdef HAVE_FIELD_CDFS_ARGS_T_FSPEC
cdfs_args.fspec = fs_name;
#endif /* HAVE_FIELD_CDFS_ARGS_T_FSPEC */
#ifdef HAVE_FIELD_CDFS_ARGS_T_NORRIP
/* XXX: need to provide norrip mount opt */
cdfs_args.norrip = 0; /* use Rock-Ridge Protocol extensions */
#endif /* HAVE_FIELD_CDFS_ARGS_T_NORRIP */
#ifdef HAVE_FIELD_CDFS_ARGS_T_SSECTOR
/* XXX: need to provide ssector mount option */
cdfs_args.ssector = 0; /* use 1st session on disk */
#endif /* HAVE_FIELD_CDFS_ARGS_T_SSECTOR */
/*
* Call generic mount routine
*/
return mount_fs(&mnt, genflags, (caddr_t) &cdfs_args, 0, type, 0, NULL, mnttab_file_name);
}
static int
cdfs_fmount(mntfs *mf)
{
int error;
error = mount_cdfs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_cdfs: %m");
return error;
}
return 0;
}
static int
cdfs_fumount(mntfs *mf)
{
return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
}

164
contrib/amd/amd/ops_efs.c Normal file
View File

@ -0,0 +1,164 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: ops_efs.c,v 5.2.2.1 1992/02/09 15:09:08 jsp beta $
*
*/
/*
* Irix UN*X file system: EFS (Extent File System)
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* forward declarations */
static char *efs_match(am_opts *fo);
static int efs_fmount(mntfs *mf);
static int efs_fumount(mntfs *mf);
/*
* Ops structure
*/
am_ops efs_ops =
{
"efs",
efs_match,
0, /* efs_init */
amfs_auto_fmount,
efs_fmount,
amfs_auto_fumount,
efs_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* efs_readlink */
0, /* efs_mounted */
0, /* efs_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
};
/*
* EFS needs local filesystem and device.
*/
static char *
efs_match(am_opts *fo)
{
if (!fo->opt_dev) {
plog(XLOG_USER, "efs: no device specified");
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
*/
return strdup(fo->opt_dev);
}
static int
mount_efs(char *dir, char *fs_name, char *opts)
{
efs_args_t efs_args;
mntent_t mnt;
int flags;
/*
* Figure out the name of the file system type.
*/
MTYPE_TYPE type = MOUNT_TYPE_EFS;
memset((voidp) &efs_args, 0, sizeof(efs_args)); /* Paranoid */
/*
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_EFS;
mnt.mnt_opts = opts;
flags = compute_mount_flags(&mnt);
#ifdef HAVE_FIELD_EFS_ARGS_T_FLAGS
efs_args.flags = 0; /* XXX: fix this to correct flags */
#endif /* HAVE_FIELD_EFS_ARGS_T_FLAGS */
#ifdef HAVE_FIELD_EFS_ARGS_T_FSPEC
efs_args.fspec = fs_name;
#endif /* HAVE_FIELD_EFS_ARGS_T_FSPEC */
/*
* Call generic mount routine
*/
return mount_fs(&mnt, flags, (caddr_t) &efs_args, 0, type, 0, NULL, mnttab_file_name);
}
static int
efs_fmount(mntfs *mf)
{
int error;
error = mount_efs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_efs: %m");
return error;
}
return 0;
}
static int
efs_fumount(mntfs *mf)
{
return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
}

154
contrib/amd/amd/ops_lofs.c Normal file
View File

@ -0,0 +1,154 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: ops_lofs.c,v 5.2.2.1 1992/02/09 15:09:08 jsp beta $
*
*/
/*
* Loopback file system
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* 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);
/*
* Ops structure
*/
am_ops lofs_ops =
{
"lofs",
lofs_match,
0, /* lofs_init */
amfs_auto_fmount,
lofs_fmount,
amfs_auto_fumount,
lofs_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* lofs_readlink */
0, /* lofs_mounted */
0, /* lofs_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
};
/*
* LOFS needs remote filesystem.
*/
static char *
lofs_match(am_opts *fo)
{
if (!fo->opt_rfs) {
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
*/
return strdup(fo->opt_rfs);
}
static int
mount_lofs(char *dir, char *fs_name, char *opts)
{
mntent_t mnt;
int flags;
/*
* Figure out the name of the file system type.
*/
MTYPE_TYPE type = MOUNT_TYPE_LOFS;
/*
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_LOFS;
mnt.mnt_opts = opts;
flags = compute_mount_flags(&mnt);
/*
* Call generic mount routine
*/
return mount_fs(&mnt, flags, NULL, 0, type, 0, NULL, mnttab_file_name);
}
static int
lofs_fmount(mntfs *mf)
{
int error;
error = mount_lofs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_lofs: %m");
return error;
}
return 0;
}
static int
lofs_fumount(mntfs *mf)
{
return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
}

55
contrib/amd/amd/ops_mfs.c Normal file
View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: ops_mfs.c,v 5.2.2.3 1992/08/02 10:42:21 jsp Exp $
*
*/
/*
* Memory file system (RAM filesystem)
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* FEEL FREE TO INPLEMENT THIS... :-) */

799
contrib/amd/amd/ops_nfs.c Normal file
View File

@ -0,0 +1,799 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: ops_nfs.c,v 5.2.2.3 1992/08/02 10:42:21 jsp Exp $
*
*/
/*
* Network file system
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/*
* Convert from nfsstat to UN*X error code
*/
#define unx_error(e) ((int)(e))
/*
* FH_TTL is the time a file handle will remain in the cache since
* last being used. If the file handle becomes invalid, then it
* will be flushed anyway.
*/
#define FH_TTL (5 * 60) /* five minutes */
#define FH_TTL_ERROR (30) /* 30 seconds */
#define FHID_ALLOC(struct) (++fh_id)
/*
* The NFS layer maintains a cache of file handles.
* This is *fundamental* to the implementation and
* also allows quick remounting when a filesystem
* is accessed soon after timing out.
*
* The NFS server layer knows to flush this cache
* when a server goes down so avoiding stale handles.
*
* Each cache entry keeps a hard reference to
* the corresponding server. This ensures that
* the server keepalive information is maintained.
*
* The copy of the sockaddr_in here is taken so
* that the port can be twiddled to talk to mountd
* instead of portmap or the NFS server as used
* elsewhere.
* The port# is flushed if a server goes down.
* The IP address is never flushed - we assume
* that the address of a mounted machine never
* changes. If it does, then you have other
* problems...
*/
typedef struct fh_cache fh_cache;
struct fh_cache {
qelem fh_q; /* List header */
voidp 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 */
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 fh_id = 0;
/* globals */
AUTH *nfs_auth;
qelem fh_head = {&fh_head, &fh_head};
/*
* Network file system operations
*/
am_ops nfs_ops =
{
"nfs",
nfs_match,
nfs_init,
amfs_auto_fmount,
nfs_fmount,
amfs_auto_fumount,
nfs_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* nfs_readlink */
0, /* nfs_mounted */
nfs_umounted,
find_nfs_srvr,
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO
};
static fh_cache *
find_nfs_fhandle_cache(voidp idv, int done)
{
fh_cache *fp, *fp2 = 0;
int id = (long) idv; /* for 64-bit archs */
ITER(fp, fh_cache, &fh_head) {
if (fp->fh_id == id) {
fp2 = fp;
break;
}
}
#ifdef DEBUG
if (fp2) {
dlog("fh cache gives fp %#x, fs %s", fp2, fp2->fh_path);
} else {
dlog("fh cache search failed");
}
#endif /* DEBUG */
if (fp2 && !done) {
fp2->fh_error = ETIMEDOUT;
return 0;
}
return fp2;
}
/*
* Called when a filehandle appears
*/
static void
got_nfs_fh(voidp pkt, int len, struct sockaddr_in * sa, struct sockaddr_in * ia, voidp idv, int done)
{
fh_cache *fp;
fp = find_nfs_fhandle_cache(idv, 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)
fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &fp->fh_nfs_handle.v3,
(XDRPROC_T_TYPE) xdr_mountres3);
else
#endif /* HAVE_FS_NFS3 */
fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &fp->fh_nfs_handle.v2,
(XDRPROC_T_TYPE) xdr_fhstatus);
if (!fp->fh_error) {
#ifdef DEBUG
dlog("got filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
#endif /* DEBUG */
/*
* Wakeup anything sleeping on this filehandle
*/
if (fp->fh_wchan) {
#ifdef DEBUG
dlog("Calling wakeup on %#x", fp->fh_wchan);
#endif /* DEBUG */
wakeup(fp->fh_wchan);
}
}
}
void
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;
fp->fh_error = -1;
}
}
}
static void
discard_fh(voidp v)
{
fh_cache *fp = v;
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)
XFREE(fp->fh_path);
XFREE(fp);
}
/*
* Determine the file handle for a node
*/
static int
prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, voidp wchan)
{
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", 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);
}
/*
* 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;
}
break;
}
}
/*
* Not in cache
*/
if (fp_save) {
fp = fp_save;
/*
* Re-use existing slot
*/
untimeout(fp->fh_cid);
free_srvr(fp->fh_fs);
XFREE(fp->fh_path);
} else {
fp = ALLOC(struct fh_cache);
memset((voidp) fp, 0, sizeof(struct fh_cache));
ins_que(&fp->fh_q, &fh_head);
}
if (!reuse_id)
fp->fh_id = FHID_ALLOC(struct );
fp->fh_wchan = wchan;
fp->fh_error = -1;
fp->fh_cid = timeout(FH_TTL, discard_fh, (voidp) fp);
/*
* if fs->fs_ip is null, remote server is probably down.
*/
if (!fs->fs_ip) {
/* Mark the fileserver down and invalid again */
fs->fs_flags &= ~FSF_VALID;
fs->fs_flags |= FSF_DOWN;
error = AM_ERRNO_HOST_DOWN;
return error;
}
/*
* If the address has changed then don't try to re-use the
* port information
*/
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;
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 (error) {
/*
* Local error - cache for a short period
* just to prevent thrashing.
*/
untimeout(fp->fh_cid);
fp->fh_cid = timeout(error < 0 ? 2 * ALLOWED_MOUNT_TIME : FH_TTL_ERROR,
discard_fh, (voidp) fp);
fp->fh_error = error;
} else {
error = fp->fh_error;
}
return error;
}
int
make_nfs_auth(void)
{
AUTH_CREATE_GIDLIST_TYPE group_wheel = 0;
/* Some NFS mounts (particularly cross-domain) require FQDNs to succeed */
#ifdef HAVE_TRANSPORT_TYPE_TLI
if (gopt.flags & CFM_FULLY_QUALIFIED_HOSTS) {
plog(XLOG_INFO, "Using NFS auth for fqhn \"%s\"", hostd);
nfs_auth = authsys_create(hostd, 0, 0, 1, &group_wheel);
} else {
nfs_auth = authsys_create_default();
}
#else /* not HAVE_TRANSPORT_TYPE_TLI */
if (gopt.flags & CFM_FULLY_QUALIFIED_HOSTS) {
plog(XLOG_INFO, "Using NFS auth for fqhn \"%s\"", hostd);
nfs_auth = authunix_create(hostd, 0, 0, 1, &group_wheel);
} else {
nfs_auth = authunix_create_default();
}
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
if (!nfs_auth)
return ENOBUFS;
return 0;
}
static int
call_mountd(fh_cache *fp, u_long proc, fwd_fun f, voidp wchan)
{
struct rpc_msg mnt_msg;
int len;
char iobuf[8192];
int error;
u_long mnt_version;
if (!nfs_auth) {
error = make_nfs_auth();
if (error)
return error;
}
if (fp->fh_sin.sin_port == 0) {
u_short port;
error = nfs_srvr_port(fp->fh_fs, &port, wchan);
if (error)
return error;
fp->fh_sin.sin_port = port;
}
/* find the right version of the mount protocol */
#ifdef HAVE_FS_NFS3
if (fp->fh_nfs_version == NFS_VERSION3)
mnt_version = MOUNTVERS3;
else
#endif /* HAVE_FS_NFS3 */
mnt_version = MOUNTVERS;
plog(XLOG_INFO, "call_mountd: NFS version %d, mount version %d",
fp->fh_nfs_version, mnt_version);
rpc_msg_init(&mnt_msg, MOUNTPROG, mnt_version, MOUNTPROC_NULL);
len = make_rpc_packet(iobuf,
sizeof(iobuf),
proc,
&mnt_msg,
(voidp) &fp->fh_path,
(XDRPROC_T_TYPE) xdr_nfspath,
nfs_auth);
if (len > 0) {
error = fwd_packet(MK_RPC_XID(RPC_XID_MOUNTD, fp->fh_id),
(voidp) iobuf,
len,
&fp->fh_sin,
&fp->fh_sin,
(voidp) ((long) fp->fh_id), /* for 64-bit archs */
f);
} 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.
*/
fp->fh_sin.sin_port = 0;
return error;
}
/*
* NFS needs the local filesystem, remote filesystem
* remote hostname.
* Local filesystem defaults to remote and vice-versa.
*/
char *
nfs_match(am_opts *fo)
{
char *xmtab;
if (fo->opt_fs && !fo->opt_rfs)
fo->opt_rfs = fo->opt_fs;
if (!fo->opt_rfs) {
plog(XLOG_USER, "nfs: no remote filesystem specified");
return NULL;
}
if (!fo->opt_rhost) {
plog(XLOG_USER, "nfs: no remote host specified");
return NULL;
}
/*
* 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
dlog("NFS: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
fo->opt_rhost, fo->opt_rfs, fo->opt_fs);
#endif /* DEBUG */
return xmtab;
}
/*
* Initialize am structure for nfs
*/
int
nfs_init(mntfs *mf)
{
int error;
am_nfs_handle_t fhs;
char *colon;
if (mf->mf_private)
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);
if (!error) {
mf->mf_private = (voidp) ALLOC(am_nfs_handle_t);
mf->mf_prfree = (void (*)(voidp)) free;
memmove(mf->mf_private, (voidp) &fhs, sizeof(fhs));
}
return error;
}
int
mount_nfs_fh(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *mf)
{
MTYPE_TYPE type;
char *colon;
char *xopts;
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 error;
int genflags;
int retry;
mntent_t mnt;
nfs_args_t nfs_args;
/*
* Extract HOST name to give to kernel.
* Some systems like osf1/aix3/bsd44 variants may need old code
* for NFS_ARGS_NEEDS_PATH.
*/
if (!(colon = strchr(fs_name, ':')))
return ENOENT;
#ifdef MOUNT_TABLE_ON_FILE
*colon = '\0';
#endif /* MOUNT_TABLE_ON_FILE */
strncpy(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, "..");
#endif /* MAXHOSTNAMELEN */
if (mf->mf_remopts && *mf->mf_remopts && !islocalnet(fs->fs_ip->sin_addr.s_addr))
xopts = strdup(mf->mf_remopts);
else
xopts = strdup(opts);
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
mnt.mnt_fsname = fs_name;
mnt.mnt_opts = xopts;
/*
* Set mount types accordingly
*/
#ifndef HAVE_FS_NFS3
type = MOUNT_TYPE_NFS;
mnt.mnt_type = MNTTAB_TYPE_NFS;
#else /* HAVE_FS_NFS3 */
if (nfs_version == NFS_VERSION3) {
type = MOUNT_TYPE_NFS3;
/*
* Systems that include the mount table "vers" option generally do not
* set the mnttab entry to "nfs3", but to "nfs" and then they set
* "vers=3". Setting it to "nfs3" works, but it may break some things
* like "df -t nfs" and the "quota" program (esp. on Solaris and Irix).
* So on those systems, set it to "nfs".
* Note: MNTTAB_OPT_VERS is always set for NFS3 (see am_compat.h).
*/
# if defined(MNTTAB_OPT_VERS) && defined(MOUNT_TABLE_ON_FILE)
mnt.mnt_type = MNTTAB_TYPE_NFS;
# else /* defined(MNTTAB_OPT_VERS) && defined(MOUNT_TABLE_ON_FILE) */
mnt.mnt_type = MNTTAB_TYPE_NFS3;
# endif /* defined(MNTTAB_OPT_VERS) && defined(MOUNT_TABLE_ON_FILE) */
} else {
type = MOUNT_TYPE_NFS;
mnt.mnt_type = MNTTAB_TYPE_NFS;
}
#endif /* HAVE_FS_NFS3 */
plog(XLOG_INFO, "mount_nfs_fh: NFS version %d", 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);
/* setup the many fields and flags within nfs_args */
#ifdef HAVE_TRANSPORT_TYPE_TLI
compute_nfs_args(&nfs_args,
&mnt,
genflags,
NULL, /* struct netconfig *nfsncp */
fs->fs_ip,
nfs_version,
nfs_proto,
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)
print_nfs_args(&nfs_args, nfs_version);
#endif /* DEBUG */
error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type,
nfs_version, nfs_proto, mnttab_file_name);
XFREE(xopts);
#ifdef HAVE_TRANSPORT_TYPE_TLI
free_knetconfig(nfs_args.knconf);
if (nfs_args.addr)
XFREE(nfs_args.addr); /* allocated in compute_nfs_args() */
#endif /* HAVE_TRANSPORT_TYPE_TLI */
return error;
}
static int
mount_nfs(char *dir, char *fs_name, char *opts, mntfs *mf)
{
if (!mf->mf_private) {
plog(XLOG_ERROR, "Missing filehandle for %s", fs_name);
return EINVAL;
}
return mount_nfs_fh((am_nfs_handle_t *) mf->mf_private, dir, fs_name, opts, 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)
{
int error = UMOUNT_FS(mf->mf_mount, mnttab_file_name);
/*
* Here is some code to unmount 'restarted' file systems.
* The restarted file systems are marked as 'nfs', not
* 'host', so we only have the map information for the
* the top-level mount. The unmount will fail (EBUSY)
* if there are anything else from the NFS server mounted
* below the mount-point. This code checks to see if there
* is anything mounted with the same prefix as the
* file system to be unmounted ("/a/b/c" when unmounting "/a/b").
* If there is, and it is a 'restarted' file system, we unmount
* it.
* Added by Mike Mitchell, mcm@unx.sas.com, 09/08/93
*/
if (error == EBUSY) {
mntfs *new_mf;
int len = strlen(mf->mf_mount);
int didsome = 0;
ITER(new_mf, mntfs, &mfhead) {
if (new_mf->mf_ops != mf->mf_ops ||
new_mf->mf_refc > 1 ||
mf == new_mf ||
((new_mf->mf_flags & (MFF_MOUNTED | MFF_UNMOUNTING | MFF_RESTART)) == (MFF_MOUNTED | MFF_RESTART)))
continue;
if (NSTREQ(mf->mf_mount, new_mf->mf_mount, len) &&
new_mf->mf_mount[len] == '/') {
UMOUNT_FS(new_mf->mf_mount, mnttab_file_name);
didsome = 1;
}
}
if (didsome)
error = UMOUNT_FS(mf->mf_mount, mnttab_file_name);
}
if (error)
return error;
return 0;
}
void
nfs_umounted(am_node *mp)
{
/*
* 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;
/*
* 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
* flushed from the cache, and a reference held to the cached entry while
* the fs is mounted...
*/
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;
f.fh_sin.sin_port = (u_short) 0;
f.fh_nfs_version = fs->fs_version;
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);
*colon = ':';
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: ops_nfs3.c,v 5.2.2.3 1992/08/02 10:42:21 jsp Exp $
*
*/
/*
* Network file system version 3.0
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* FEEL FREE TO INPLEMENT THIS... :-) */

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: ops_nullfs.c,v 5.2.2.3 1992/08/02 10:42:21 jsp Exp $
*
*/
/*
* The null filesystem in BSD-4.4 is similar to the loopback one.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* FEEL FREE TO INPLEMENT THIS... :-) */

179
contrib/amd/amd/ops_pcfs.c Normal file
View File

@ -0,0 +1,179 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: ops_pcfs.c,v 5.2.2.1 1992/02/09 15:09:08 jsp beta $
*
*/
/*
* PC (MS-DOS) file system
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* forward definitions */
static char *pcfs_match(am_opts *fo);
static int pcfs_fmount(mntfs *mf);
static int pcfs_fumount(mntfs *mf);
/*
* Ops structure
*/
am_ops pcfs_ops =
{
"pcfs",
pcfs_match,
0, /* pcfs_init */
amfs_auto_fmount,
pcfs_fmount,
amfs_auto_fumount,
pcfs_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* pcfs_readlink */
0, /* pcfs_mounted */
0, /* pcfs_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO
};
/*
* PCFS needs remote filesystem.
*/
static char *
pcfs_match(am_opts *fo)
{
if (!fo->opt_dev) {
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
*/
return strdup(fo->opt_dev);
}
static int
mount_pcfs(char *dir, char *fs_name, char *opts)
{
pcfs_args_t pcfs_args;
mntent_t mnt;
int flags;
/*
* Figure out the name of the file system type.
*/
MTYPE_TYPE type = MOUNT_TYPE_PCFS;
memset((voidp) &pcfs_args, 0, sizeof(pcfs_args)); /* Paranoid */
/*
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_PCFS;
mnt.mnt_opts = opts;
flags = compute_mount_flags(&mnt);
#ifdef HAVE_FIELD_PCFS_ARGS_T_FSPEC
pcfs_args.fspec = fs_name;
#endif /* HAVE_FIELD_PCFS_ARGS_T_FSPEC */
#ifdef HAVE_FIELD_PCFS_ARGS_T_MASK
pcfs_args.mask = 0777; /* this may be the msdos file modes */
#endif /* HAVE_FIELD_PCFS_ARGS_T_MASK */
#ifdef HAVE_FIELD_PCFS_ARGS_T_UID
pcfs_args.uid = 0; /* root */
#endif /* HAVE_FIELD_PCFS_ARGS_T_UID */
#ifdef HAVE_FIELD_PCFS_ARGS_T_GID
pcfs_args.gid = 0; /* wheel */
#endif /* HAVE_FIELD_PCFS_ARGS_T_GID */
#ifdef HAVE_FIELD_PCFS_ARGS_T_SECONDSWEST
pcfs_args.secondswest = 0; /* XXX: fill in correct values */
#endif /* HAVE_FIELD_PCFS_ARGS_T_SECONDSWEST */
#ifdef HAVE_FIELD_PCFS_ARGS_T_DSTTIME
pcfs_args.dsttime = 0; /* XXX: fill in correct values */
#endif /* HAVE_FIELD_PCFS_ARGS_T_DSTTIME */
/*
* Call generic mount routine
*/
return mount_fs(&mnt, flags, (caddr_t) & pcfs_args, 0, type, 0, NULL, mnttab_file_name);
}
static int
pcfs_fmount(mntfs *mf)
{
int error;
error = mount_pcfs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_pcfs: %m");
return error;
}
return 0;
}
static int
pcfs_fumount(mntfs *mf)
{
return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
}

55
contrib/amd/amd/ops_tfs.c Normal file
View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: ops_tfs.c,v 5.2.2.3 1992/08/02 10:42:21 jsp Exp $
*
*/
/*
* Translucent file system
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* FEEL FREE TO INPLEMENT THIS... :-) */

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: ops_tmpfs.c,v 5.2.2.3 1992/08/02 10:42:21 jsp Exp $
*
*/
/*
* TMPFS file system (combines RAM-fs and swap-fs)
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* FEEL FREE TO INPLEMENT THIS... :-) */

173
contrib/amd/amd/ops_ufs.c Normal file
View File

@ -0,0 +1,173 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: ops_ufs.c,v 5.2.2.1 1992/02/09 15:09:08 jsp beta $
*
*/
/*
* UN*X file system
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* forward declarations */
static char *ufs_match(am_opts *fo);
static int ufs_fmount(mntfs *mf);
static int ufs_fumount(mntfs *mf);
/*
* Ops structure
*/
am_ops ufs_ops =
{
"ufs",
ufs_match,
0, /* ufs_init */
amfs_auto_fmount,
ufs_fmount,
amfs_auto_fumount,
ufs_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* ufs_readlink */
0, /* ufs_mounted */
0, /* ufs_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
};
/*
* UFS needs local filesystem and device.
*/
static char *
ufs_match(am_opts *fo)
{
if (!fo->opt_dev) {
plog(XLOG_USER, "ufs: no device specified");
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
*/
return strdup(fo->opt_dev);
}
static int
mount_ufs(char *dir, char *fs_name, char *opts)
{
ufs_args_t ufs_args;
mntent_t mnt;
int genflags;
/*
* Figure out the name of the file system type.
*/
MTYPE_TYPE type = MOUNT_TYPE_UFS;
memset((voidp) &ufs_args, 0, sizeof(ufs_args)); /* Paranoid */
/*
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_UFS;
mnt.mnt_opts = opts;
genflags = compute_mount_flags(&mnt);
#ifdef HAVE_FIELD_UFS_ARGS_T_FLAGS
ufs_args.flags = genflags; /* XXX: is this correct? */
#endif /* HAVE_FIELD_UFS_ARGS_T_FLAGS */
#ifdef HAVE_FIELD_UFS_ARGS_T_UFS_FLAGS
ufs_args.ufs_flags = genflags; /* XXX: is this correct? */
#endif /* HAVE_FIELD_UFS_ARGS_T_UFS_FLAGS */
#ifdef HAVE_FIELD_UFS_ARGS_T_FSPEC
ufs_args.fspec = fs_name;
#endif /* HAVE_FIELD_UFS_ARGS_T_FSPEC */
#ifdef HAVE_FIELD_UFS_ARGS_T_UFS_PGTHRESH
ufs_args.ufs_pgthresh = hasmntval(&mnt, MNTTAB_OPT_PGTHRESH);
#endif /* HAVE_FIELD_UFS_ARGS_T_UFS_PGTHRESH */
/*
* Call generic mount routine
*/
return mount_fs(&mnt, genflags, (caddr_t) &ufs_args, 0, type, 0, NULL, mnttab_file_name);
}
static int
ufs_fmount(mntfs *mf)
{
int error;
error = mount_ufs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_ufs: %m");
return error;
}
return 0;
}
static int
ufs_fumount(mntfs *mf)
{
return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: ops_umapfs.c,v 5.2.2.3 1992/08/02 10:42:21 jsp Exp $
*
*/
/*
* uid/gid mapping filesystem.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* FEEL FREE TO INPLEMENT THIS... :-) */

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: ops_unionfs.c,v 5.2.2.3 1992/08/02 10:42:21 jsp Exp $
*
*/
/*
* Union filesystem (ala BSD-4.4)
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* FEEL FREE TO INPLEMENT THIS... :-) */

164
contrib/amd/amd/ops_xfs.c Normal file
View File

@ -0,0 +1,164 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: ops_xfs.c,v 5.2.2.1 1992/02/09 15:09:08 jsp beta $
*
*/
/*
* Irix UN*X file system: XFS (Extended File System)
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* forward declarations */
static char * xfs_match(am_opts *fo);
static int xfs_fmount(mntfs *mf);
static int xfs_fumount(mntfs *mf);
/*
* Ops structure
*/
am_ops xfs_ops =
{
"xfs",
xfs_match,
0, /* xfs_init */
amfs_auto_fmount,
xfs_fmount,
amfs_auto_fumount,
xfs_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* xfs_readlink */
0, /* xfs_mounted */
0, /* xfs_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
};
/*
* XFS needs local filesystem and device.
*/
static char *
xfs_match(am_opts *fo)
{
if (!fo->opt_dev) {
plog(XLOG_USER, "xfs: no device specified");
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
*/
return strdup(fo->opt_dev);
}
static int
mount_xfs(char *dir, char *fs_name, char *opts)
{
xfs_args_t xfs_args;
mntent_t mnt;
int flags;
/*
* Figure out the name of the file system type.
*/
MTYPE_TYPE type = MOUNT_TYPE_XFS;
memset((voidp) &xfs_args, 0, sizeof(xfs_args)); /* Paranoid */
/*
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_XFS;
mnt.mnt_opts = opts;
flags = compute_mount_flags(&mnt);
#ifdef HAVE_FIELD_XFS_ARGS_T_FLAGS
xfs_args.flags = 0; /* XXX: fix this to correct flags */
#endif /* HAVE_FIELD_XFS_ARGS_T_FLAGS */
#ifdef HAVE_FIELD_XFS_ARGS_T_FSPEC
xfs_args.fspec = fs_name;
#endif /* HAVE_FIELD_XFS_ARGS_T_FSPEC */
/*
* Call generic mount routine
*/
return mount_fs(&mnt, flags, (caddr_t) &xfs_args, 0, type, 0, NULL, mnttab_file_name);
}
static int
xfs_fmount(mntfs *mf)
{
int error;
error = mount_xfs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_xfs: %m");
return error;
}
return 0;
}
static int
xfs_fumount(mntfs *mf)
{
return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
}

1304
contrib/amd/amd/opts.c Normal file

File diff suppressed because it is too large Load Diff

208
contrib/amd/amd/restart.c Normal file
View File

@ -0,0 +1,208 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: restart.c,v 5.2.2.2 1992/08/02 10:42:21 jsp Exp $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/*
* 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.
*
* This module relies on internal details of other components. If
* you change something else make *sure* restart() still works.
*/
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.
*/
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)) {
/*
* NFS entry, or possibly an Amd entry...
* The mnt_fsname for daemon mount points is
* host:(pidXXX)
* or (seen on Solaris)
* 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 we found something to do
*/
if (fs_ops) {
mntfs *mf;
am_opts mo;
char *cp;
cp = strchr(me->mnt_fsname, ':');
/*
* 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);
}
}
/*
* Free the mount list
*/
free_mntlist(ml);
}

476
contrib/amd/amd/rpc_fwd.c Normal file
View File

@ -0,0 +1,476 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: rpc_fwd.c,v 5.2.2.1 1992/02/09 15:09:01 jsp beta $
*
*/
/*
* RPC packet forwarding
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/*
* Note that the ID field in the external packet is only
* ever treated as a 32 bit opaque data object, so there
* is no need to convert to and from network byte ordering.
*/
#define XID_ALLOC(struct ) (xid++)
#define MAX_PACKET_SIZE 8192 /* Maximum UDP packet size */
/*
* Each pending reply has an rpc_forward structure
* associated with it. These have a 15 second lifespan.
* If a new structure is required, then an expired
* one will be re-allocated if available, otherwise a fresh
* one is allocated. Whenever a reply is received the
* structure is discarded.
*/
typedef struct rpc_forward rpc_forward;
struct rpc_forward {
qelem rf_q; /* Linked list */
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 */
voidp rf_ptr;
struct sockaddr_in rf_sin;
};
/*
* Head of list of pending replies
*/
qelem rpc_head = {&rpc_head, &rpc_head};
int fwd_sock;
static u_int xid;
/*
* Allocate a rely structure
*/
static rpc_forward *
fwd_alloc(void)
{
time_t now = clocktime();
rpc_forward *p = 0, *p2;
/*
* First search for an existing expired one.
*/
ITER(p2, rpc_forward, &rpc_head) {
if (p2->rf_ttl <= now) {
p = p2;
break;
}
}
/*
* If one couldn't be found then allocate
* a new structure and link it at the
* head of the list.
*/
if (p) {
/*
* 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);
} else {
p = ALLOC(struct rpc_forward);
}
ins_que(&p->rf_q, &rpc_head);
/*
* Set the time to live field
* Timeout in 43 seconds
*/
p->rf_ttl = now + 43;
return p;
}
/*
* Free an allocated reply structure.
* First unlink it from the list, then
* discard it.
*/
static void
fwd_free(rpc_forward *p)
{
rem_que(&p->rf_q);
XFREE(p);
}
/*
* Initialize the RPC forwarder
*/
int
fwd_init(void)
{
#ifdef FIONBIO
int on = 1;
#endif /* FIONBIO */
#ifdef HAVE_TRANSPORT_TYPE_TLI
/*
* Create ping TLI socket (/dev/tcp and /dev/ticlts did not work)
* (HPUX-11 does not like using O_NDELAY in flags)
*/
fwd_sock = t_open("/dev/udp", O_RDWR|O_NONBLOCK, 0);
if (fwd_sock < 0) {
plog(XLOG_ERROR, "unable to create RPC forwarding TLI socket: %s",
t_errlist[t_errno]);
return errno;
}
#else /* not HAVE_TRANSPORT_TYPE_TLI */
/*
* Create ping socket
*/
fwd_sock = socket(AF_INET, SOCK_DGRAM, 0);
if (fwd_sock < 0) {
plog(XLOG_ERROR, "unable to create RPC forwarding socket: %m");
return errno;
}
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/*
* Some things we talk to require a priv port - so make one here
*/
if (bind_resv_port(fwd_sock, (u_short *) 0) < 0)
plog(XLOG_ERROR, "can't bind privileged port");
if (fcntl(fwd_sock, F_SETFL, FNDELAY) < 0
#ifdef FIONBIO
&& ioctl(fwd_sock, FIONBIO, &on) < 0
#endif /* FIONBIO */
) {
plog(XLOG_ERROR, "Can't set non-block on forwarding socket: %m");
return errno;
}
return 0;
}
/*
* Locate a packet in the forwarding list
*/
static rpc_forward *
fwd_locate(u_int id)
{
rpc_forward *p;
ITER(p, rpc_forward, &rpc_head) {
if (p->rf_xid == id)
return p;
}
return 0;
}
/*
* This is called to forward a packet to another
* RPC server. The message id is changed and noted
* so that when a reply appears we can tie it up
* correctly. Just matching the reply's source address
* would not work because it might come from a
* 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)
{
rpc_forward *p;
u_int *pkt_int;
int error;
#ifdef HAVE_TRANSPORT_TYPE_TLI
struct t_unitdata ud;
#endif /* HAVE_TRANSPORT_TYPE_TLI */
if ((int) amd_state >= (int) Finishing)
return ENOENT;
/*
* See if the type_id is fully specified.
* If so, then discard any old entries
* for this id.
* 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");
break;
case RPC_XID_MOUNTD:
dlog("Sending MOUNTD request %#x", type_id);
break;
case RPC_XID_NFSPING:
dlog("Sending NFS ping");
break;
default:
dlog("UNKNOWN RPC XID");
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 ));
}
p = fwd_alloc();
if (!p)
return ENOBUFS;
error = 0;
pkt_int = (u_int *) pkt;
/*
* Get the original packet id
*/
p->rf_oldid = *pkt_int;
/*
* Replace with newly allocated id
*/
p->rf_xid = *pkt_int = type_id;
/*
* The sendto may fail if, for example, the route
* to a remote host is lost because an intermediate
* gateway has gone down. Important to fill in the
* rest of "p" otherwise nasty things happen later...
*/
#ifdef DEBUG
{
char dq[20];
if (p && fwdto)
dlog("Sending packet id %#x to %s.%d",
p->rf_xid,
inet_dquad(dq, fwdto->sin_addr.s_addr),
ntohs(fwdto->sin_port));
}
#endif /* DEBUG */
/* if NULL, remote server probably down */
if (!fwdto) {
error = AM_ERRNO_HOST_DOWN;
goto out;
}
#ifdef HAVE_TRANSPORT_TYPE_TLI
ud.addr.buf = (char *) fwdto;
if (fwdto) /* if NULL, set sizes to zero */
ud.addr.maxlen = ud.addr.len = sizeof(struct sockaddr_in);
else
ud.addr.maxlen = ud.addr.len = 0;
ud.opt.buf = (char *) NULL;
ud.opt.maxlen = ud.opt.len = 0;
ud.udata.buf = pkt;
ud.udata.maxlen = ud.udata.len = len;
if (t_sndudata(fwd_sock, &ud) < 0) {
plog(XLOG_ERROR,"fwd_packet failed: t_errno=%d, errno=%d",t_errno,errno);
error = errno;
}
#else /* not HAVE_TRANSPORT_TYPE_TLI */
if (sendto(fwd_sock, (char *) pkt, len, 0,
(struct sockaddr *) fwdto, sizeof(*fwdto)) < 0)
error = errno;
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/*
* Save callback function and return address
*/
out:
p->rf_fwd = cb;
if (replyto)
p->rf_sin = *replyto;
else
memset((voidp) &p->rf_sin, 0, sizeof(p->rf_sin));
p->rf_ptr = i;
return error;
}
/*
* Called when some data arrives on the forwarding socket
*/
void
fwd_reply(void)
{
int len;
u_int pkt[MAX_PACKET_SIZE / sizeof(u_int) + 1];
u_int *pkt_int;
int rc;
rpc_forward *p;
struct sockaddr_in src_addr;
RECVFROM_FROMLEN_TYPE src_addr_len;
#ifdef HAVE_TRANSPORT_TYPE_TLI
struct t_unitdata ud;
int flags = 0;
#endif /* HAVE_TRANSPORT_TYPE_TLI */
/*
* Determine the length of the packet
*/
len = MAX_PACKET_SIZE;
/*
* Read the packet and check for validity
*/
again:
src_addr_len = sizeof(src_addr);
#ifdef HAVE_TRANSPORT_TYPE_TLI
ud.addr.buf = (char *) &src_addr;
ud.addr.maxlen = ud.addr.len = src_addr_len;
ud.opt.buf = (char *) NULL;
ud.opt.maxlen = ud.opt.len = 0;
ud.udata.buf = (char *) pkt;
ud.udata.maxlen = ud.udata.len = len;
/* XXX: use flags accordingly such as if T_MORE set */
rc = t_rcvudata(fwd_sock, &ud, &flags);
if (rc == 0) /* success, reset rc to length */
rc = ud.udata.len;
else {
plog(XLOG_ERROR,"fwd_reply failed: t_errno=%d, errno=%d, flags=%d",t_errno,errno, flags);
}
#else /* not HAVE_TRANSPORT_TYPE_TLI */
rc = recvfrom(fwd_sock,
(char *) pkt,
len,
0,
(struct sockaddr *) &src_addr,
&src_addr_len);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/*
* XXX: in svr4, if the T_MORE bit of flags is set, what do
* we then do? -Erez
*/
if (rc < 0 || src_addr_len != sizeof(src_addr) ||
src_addr.sin_family != AF_INET) {
if (rc < 0 && errno == EINTR)
goto again;
plog(XLOG_ERROR, "Error reading RPC reply: %m");
goto out;
}
/*
* Do no more work if finishing soon
*/
if ((int) amd_state >= (int) Finishing)
goto out;
/*
* Find packet reference
*/
pkt_int = (u_int *) pkt;
#ifdef DEBUG
switch (*pkt_int & RPC_XID_MASK) {
case RPC_XID_PORTMAP:
dlog("Receiving PORTMAP reply");
break;
case RPC_XID_MOUNTD:
dlog("Receiving MOUNTD reply %#x", *pkt_int);
break;
case RPC_XID_NFSPING:
dlog("Receiving NFS ping %#x", *pkt_int);
break;
default:
dlog("UNKNOWN RPC XID");
break;
}
#endif /* DEBUG */
p = fwd_locate(*pkt_int);
if (!p) {
#ifdef DEBUG
dlog("Can't forward reply id %#x", *pkt_int);
#endif /* DEBUG */
goto out;
}
if (p->rf_fwd) {
/*
* Put the original message id back
* into the packet.
*/
*pkt_int = p->rf_oldid;
/*
* Call forwarding function
*/
(*p->rf_fwd) ((voidp) pkt, rc, &src_addr, &p->rf_sin, p->rf_ptr, TRUE);
}
/*
* Free forwarding info
*/
fwd_free(p);
out:;
}

300
contrib/amd/amd/sched.c Normal file
View File

@ -0,0 +1,300 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: sched.c,v 5.2.2.1 1992/02/09 15:09:02 jsp beta $
*
*/
/*
* Process scheduler
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
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 */
int w; /* everyone these days uses int, not a "union wait" */
voidp wchan; /* Wait channel */
};
/* globals */
qelem proc_list_head = {&proc_list_head, &proc_list_head};
qelem proc_wait_list = {&proc_wait_list, &proc_wait_list};
int task_notify_todo;
void
ins_que(qelem *elem, qelem *pred)
{
qelem *p = pred->q_forw;
elem->q_back = pred;
elem->q_forw = p;
pred->q_forw = elem;
p->q_back = elem;
}
void
rem_que(qelem *elem)
{
qelem *p = elem->q_forw;
qelem *p2 = elem->q_back;
p2->q_forw = p;
p->q_back = p2;
}
static pjob *
sched_job(cb_fun cf, voidp ca)
{
pjob *p = ALLOC(struct pjob);
p->cb_fun = cf;
p->cb_closure = ca;
/*
* Now place on wait queue
*/
ins_que(&p->hdr, &proc_wait_list);
return p;
}
/*
* tf: The task to execute (ta is its arguments)
* cf: Continuation function (ca is its arguments)
*/
void
run_task(task_fun tf, voidp ta, cb_fun cf, voidp ca)
{
pjob *p = sched_job(cf, ca);
#ifdef HAVE_SIGACTION
sigset_t new, mask;
#else /* not HAVE_SIGACTION */
int mask;
#endif /* not HAVE_SIGACTION */
p->wchan = (voidp) p;
#ifdef HAVE_SIGACTION
sigemptyset(&new); /* initialise signal set we wish to block */
sigaddset(&new, SIGCHLD); /* only block on SIGCHLD */
sigprocmask(SIG_BLOCK, &new, &mask);
#else /* not HAVE_SIGACTION */
mask = sigblock(sigmask(SIGCHLD));
#endif /* not HAVE_SIGACTION */
if ((p->pid = background())) {
#ifdef HAVE_SIGACTION
sigprocmask(SIG_SETMASK, &mask, NULL);
#else /* not HAVE_SIGACTION */
sigsetmask(mask);
#endif /* not HAVE_SIGACTION */
return;
}
/* child code runs here, parent have returned to caller */
exit((*tf) (ta));
/* firewall... */
abort();
}
/*
* Schedule a task to be run when woken up
*/
void
sched_task(cb_fun cf, voidp ca, voidp wchan)
{
/*
* Allocate a new task
*/
pjob *p = sched_job(cf, ca);
#ifdef DEBUG
dlog("SLEEP on %#x", wchan);
#endif /* DEBUG */
p->wchan = wchan;
p->pid = 0;
memset((voidp) &p->w, 0, sizeof(p->w));
}
static void
wakeupjob(pjob *p)
{
rem_que(&p->hdr);
ins_que(&p->hdr, &proc_list_head);
task_notify_todo++;
}
void
wakeup(voidp wchan)
{
pjob *p, *p2;
if (!foreground)
return;
/*
* Can't user ITER() here because
* wakeupjob() juggles the list.
*/
for (p = AM_FIRST(pjob, &proc_wait_list);
p2 = NEXT(pjob, p), p != HEAD(pjob, &proc_wait_list);
p = p2) {
if (p->wchan == wchan) {
wakeupjob(p);
}
}
}
void
wakeup_task(int rc, int term, voidp cl)
{
wakeup(cl);
}
/*
* Run any pending tasks.
* This must be called with SIGCHLD disabled
*/
void
do_task_notify(void)
{
/*
* Keep taking the first item off the list and processing it.
*
* Done this way because the the callback can, quite reasonably,
* queue a new task, so no local reference into the list can be
* held here.
*/
while (AM_FIRST(pjob, &proc_list_head) != HEAD(pjob, &proc_list_head)) {
pjob *p = AM_FIRST(pjob, &proc_list_head);
rem_que(&p->hdr);
/*
* This job has completed
*/
--task_notify_todo;
/*
* Do callback if it exists
*/
if (p->cb_fun) {
/* these two trigraphs will ensure compatibity with strict POSIX.1 */
(*p->cb_fun) (WIFEXITED(p->w) ? WEXITSTATUS(p->w) : 0,
WIFSIGNALED(p->w) ? WTERMSIG(p->w) : 0,
p->cb_closure);
}
XFREE(p);
}
}
RETSIGTYPE
sigchld(int sig)
{
int w; /* everyone these days uses int, not a "union wait" */
int pid;
#ifdef HAVE_WAITPID
while ((pid = waitpid((pid_t) -1, &w, WNOHANG)) > 0) {
#else /* not HAVE_WAITPID */
while ((pid = wait3( &w, WNOHANG, (struct rusage *) 0)) > 0) {
#endif /* not HAVE_WAITPID */
pjob *p, *p2;
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);
p = p2) {
if (p->pid == pid) {
p->w = w;
wakeupjob(p);
break;
}
} /* end of for loop */
#ifdef DEBUG
if (!p)
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
* incorrectly. SH/RUNIT 940519.
*/
if (--NumChild < 0)
NumChild = 0;
} /* end of "while wait..." loop */
#ifdef REINSTALL_SIGNAL_HANDLER
signal(sig, sigchld);
#endif /* REINSTALL_SIGNAL_HANDLER */
if (select_intr_valid)
longjmp(select_intr, sig);
}

View File

@ -0,0 +1,214 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: srvr_amfs_auto.c,v 5.2.2.1 1992/02/09 15:09:05 jsp beta $
*
*/
/*
* Automount FS server ("localhost") modeling
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* globals */
qelem amfs_auto_srvr_list = {&amfs_auto_srvr_list, &amfs_auto_srvr_list};
/* statics */
static fserver *localhost;
/*
* Find an nfs server for the local host
*/
fserver *
find_amfs_auto_srvr(mntfs *mf)
{
fserver *fs = localhost;
if (!fs) {
fs = ALLOC(struct fserver);
fs->fs_refc = 0;
fs->fs_host = strdup("localhost");
fs->fs_ip = 0;
fs->fs_cid = 0;
fs->fs_pinger = 0;
fs->fs_flags = FSF_VALID;
fs->fs_type = "local";
fs->fs_private = 0;
fs->fs_prfree = 0;
ins_que(&fs->fs_q, &amfs_auto_srvr_list);
srvrlog(fs, "starts up");
localhost = fs;
}
fs->fs_refc++;
return fs;
}
/*****************************************************************************
*** GENERIC ROUTINES FOLLOW
*****************************************************************************/
/*
* Wakeup anything waiting for this server
*/
void
wakeup_srvr(fserver *fs)
{
fs->fs_flags &= ~FSF_WANT;
wakeup((voidp) fs);
}
/*
* Called when final ttl of server has expired
*/
static void
timeout_srvr(voidp v)
{
fserver *fs = v;
/*
* If the reference count is still zero then
* 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);
/*
* Remove from queue.
*/
rem_que(&fs->fs_q);
/*
* (Possibly) call the private free routine.
*/
if (fs->fs_private && fs->fs_prfree)
(*fs->fs_prfree) (fs->fs_private);
/*
* Free the net address
*/
if (fs->fs_ip)
XFREE(fs->fs_ip);
/*
* Free the host name.
*/
XFREE(fs->fs_host);
/*
* Discard the fserver object.
*/
XFREE(fs);
}
}
/*
* Free a file server
*/
void
free_srvr(fserver *fs)
{
if (--fs->fs_refc == 0) {
/*
* The reference count is now zero,
* so arrange for this node to be
* removed in AM_TTL seconds if no
* other mntfs is referencing it.
*/
int ttl = (fs->fs_flags & (FSF_DOWN | FSF_ERROR)) ? 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);
/*
* Turn off pinging - XXX
*/
fs->fs_flags &= ~FSF_PINGING;
}
/*
* Keep structure lying around for a while
*/
fs->fs_cid = timeout(ttl, timeout_srvr, (voidp) fs);
/*
* Mark the fileserver down and invalid again
*/
fs->fs_flags &= ~FSF_VALID;
fs->fs_flags |= FSF_DOWN;
}
}
/*
* Make a duplicate fserver reference
*/
fserver *
dup_srvr(fserver *fs)
{
fs->fs_refc++;
return fs;
}
/*
* Log state change
*/
void srvrlog(fserver *fs, char *state)
{
plog(XLOG_INFO, "file server %s type %s %s", fs->fs_host, fs->fs_type, state);
}

851
contrib/amd/amd/srvr_nfs.c Normal file
View File

@ -0,0 +1,851 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: srvr_nfs.c,v 5.2.2.1 1992/02/09 15:09:06 jsp beta $
*
*/
/*
* NFS server modeling
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/*
* Number of pings allowed to fail before host is declared down
* - three-fifths of the allowed mount time...
*/
#define MAX_ALLOWED_PINGS (3 + /* for luck ... */ 1)
/*
* How often to ping when starting a new server
*/
#define FAST_NFS_PING 3
#if (FAST_NFS_PING * MAX_ALLOWED_PINGS) >= ALLOWED_MOUNT_TIME
# error: sanity check failed in srvr_nfs.c
/*
* you cannot do things this way...
* sufficient fast pings must be given the chance to fail
* within the allowed mount time
*/
#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 */
char np_mountd_inval; /* Port *may* be invalid */
int np_ping; /* Number of failed ping attempts */
time_t np_ttl; /* Time when server is thought dead */
int np_xid; /* RPC transaction id for pings */
int np_error; /* Error during portmap request */
} nfs_private;
/* globals */
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];
#if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3)
/* protocols we know about, in order of preference */
static char *protocols[] = { "tcp", "udp", NULL };
#endif /* defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
/* forward definitions */
static void nfs_keepalive(voidp);
/*
* Flush any cached data
*/
void
flush_srvr_nfs_cache(void)
{
fserver *fs = 0;
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;
}
}
}
/*
* Startup the NFS ping for a particular version.
*/
static void
start_ping(u_long nfs_version)
{
XDR ping_xdr;
struct rpc_msg ping_msg;
/*
* Non nfs mounts like /afs/glue.umd.edu have ended up here.
*/
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", 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);
/*
* Create the NFS ping message
*/
if (!xdr_callmsg(&ping_xdr, &ping_msg)) {
plog(XLOG_ERROR, "Couldn't create ping RPC message");
going_down(3);
}
/*
* Find out how long it is
*/
ping_len = xdr_getpos(&ping_xdr);
/*
* Destroy the XDR endpoint - we don't need it anymore
*/
xdr_destroy(&ping_xdr);
}
/*
* Called when a portmap reply arrives
*/
static void
got_portmap(voidp pkt, int len, struct sockaddr_in * sa, struct sockaddr_in * ia, voidp idv, int done)
{
fserver *fs2 = (fserver *) idv;
fserver *fs = 0;
/*
* Find which fileserver we are talking about
*/
ITER(fs, fserver, &nfs_srvr_list)
if (fs == fs2)
break;
if (fs == fs2) {
u_long port = 0; /* XXX - should be short but protocol is naff */
int error = done ? pickup_rpc_reply(pkt, len, (voidp) &port, (XDRPROC_T_TYPE) xdr_u_long) : -1;
nfs_private *np = (nfs_private *) fs->fs_private;
if (!error && port) {
#ifdef DEBUG
dlog("got port (%d) for mountd on %s", port, fs->fs_host);
#endif /* DEBUG */
/*
* Grab the port number. Portmap sends back
* an u_long in native ordering, so it
* needs converting to a u_short in
* network ordering.
*/
np->np_mountd = htons((u_short) port);
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, port);
#endif /* DEBUG */
/*
* Almost certainly no mountd running on remote host
*/
np->np_error = error ? error : ETIMEDOUT;
}
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 */
}
}
/*
* Obtain portmap information
*/
static int
call_portmap(fserver *fs, AUTH * auth, u_long prog, u_long vers, u_long prot)
{
struct rpc_msg pmap_msg;
int len;
char iobuf[UDPMSGSIZE];
int error;
struct pmap pmap;
rpc_msg_init(&pmap_msg, PMAPPROG, PMAPVERS, PMAPPROC_NULL);
pmap.pm_prog = prog;
pmap.pm_vers = vers;
pmap.pm_prot = prot;
pmap.pm_port = 0;
len = make_rpc_packet(iobuf,
sizeof(iobuf),
PMAPPROC_GETPORT,
&pmap_msg,
(voidp) &pmap,
(XDRPROC_T_TYPE) xdr_pmap,
auth);
if (len > 0) {
struct sockaddr_in sin;
memset((voidp) &sin, 0, sizeof(sin));
sin = *fs->fs_ip;
sin.sin_port = htons(PMAPPORT);
error = fwd_packet(RPC_XID_PORTMAP, (voidp) iobuf, len,
&sin, &sin, (voidp) fs, got_portmap);
} else {
error = -len;
}
return error;
}
static void
recompute_portmap(fserver *fs)
{
int error;
u_long mnt_version;
if (nfs_auth)
error = 0;
else
error = make_nfs_auth();
if (error) {
nfs_private *np = (nfs_private *) fs->fs_private;
np->np_error = error;
return;
}
if (fs->fs_version == 0)
plog(XLOG_WARNING, "recompute_portmap: nfs_version = 0 fixed");
plog(XLOG_INFO, "recompute_portmap: NFS version %d", fs->fs_version);
#ifdef HAVE_FS_NFS3
if (fs->fs_version == NFS_VERSION3)
mnt_version = MOUNTVERS3;
else
#endif /* HAVE_FS_NFS3 */
mnt_version = MOUNTVERS;
plog(XLOG_INFO, "Using MOUNT version: %d", mnt_version);
call_portmap(fs, nfs_auth, MOUNTPROG, mnt_version, (u_long) IPPROTO_UDP);
}
/*
* 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)
{
int xid = (long) idv; /* for 64-bit archs */
fserver *fs;
#ifdef DEBUG
int found_map = 0;
#endif /* DEBUG */
if (!done)
return;
/*
* For each node...
*/
ITER(fs, fserver, &nfs_srvr_list) {
nfs_private *np = (nfs_private *) fs->fs_private;
if (np->np_xid == xid && (fs->fs_flags & FSF_PINGING)) {
/*
* Reset the ping counter.
* Update the keepalive timer.
* Log what happened.
*/
if (fs->fs_flags & FSF_DOWN) {
fs->fs_flags &= ~FSF_DOWN;
if (fs->fs_flags & FSF_VALID) {
srvrlog(fs, "is up");
} 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");
fs->fs_flags |= FSF_VALID;
}
}
/*
* Adjust ping interval
*/
untimeout(fs->fs_cid);
fs->fs_cid = timeout(fs->fs_pinger, nfs_keepalive, (voidp) fs);
/*
* Update ttl for this server
*/
np->np_ttl = clocktime() +
(MAX_ALLOWED_PINGS - 1) * FAST_NFS_PING + fs->fs_pinger - 1;
/*
* New RPC xid...
*/
np->np_xid = NPXID_ALLOC(struct );
/*
* Failed pings is zero...
*/
np->np_ping = 0;
/*
* Recompute portmap information if not known
*/
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 */
}
/*
* Called when no ping-reply received
*/
static void
nfs_timed_out(voidp v)
{
fserver *fs = v;
nfs_private *np = (nfs_private *) fs->fs_private;
/*
* Another ping has failed
*/
np->np_ping++;
/*
* Not known to be up any longer
*/
if (FSRV_ISUP(fs)) {
fs->fs_flags &= ~FSF_VALID;
if (np->np_ping > 1)
srvrlog(fs, "not responding");
}
/*
* If ttl has expired then guess that it is dead
*/
if (np->np_ttl < clocktime()) {
int oflags = fs->fs_flags;
if ((fs->fs_flags & FSF_DOWN) == 0) {
/*
* Server was up, but is now down.
*/
srvrlog(fs, "is down");
fs->fs_flags |= FSF_DOWN | FSF_VALID;
/*
* Since the server is down, the portmap
* information may now be wrong, so it
* must be flushed from the local cache
*/
flush_nfs_fhandle_cache(fs);
np->np_error = -1;
} 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))
wakeup_srvr(fs);
} 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 */
}
/*
* Run keepalive again
*/
nfs_keepalive(fs);
}
/*
* Keep track of whether a server is alive
*/
static void
nfs_keepalive(voidp v)
{
fserver *fs = v;
int error;
nfs_private *np = (nfs_private *) fs->fs_private;
int fstimeo = -1;
/*
* Send an NFS ping to this node
*/
if (ping_len == 0)
start_ping(fs->fs_version);
/*
* Queue the packet...
*/
error = fwd_packet(MK_RPC_XID(RPC_XID_NFSPING, np->np_xid),
(voidp) ping_buf,
ping_len,
fs->fs_ip,
(struct sockaddr_in *) 0,
(voidp) ((long) np->np_xid), /* for 64-bit archs */
nfs_pinged);
/*
* See if a hard error occured
*/
switch (error) {
case ENETDOWN:
case ENETUNREACH:
case EHOSTDOWN:
case EHOSTUNREACH:
np->np_ping = MAX_ALLOWED_PINGS; /* immediately down */
np->np_ttl = (time_t) 0;
/*
* This causes an immediate call to nfs_timed_out
* whenever the server was thought to be up.
* See +++ below.
*/
fstimeo = 0;
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.
*/
switch (fs->fs_flags & (FSF_DOWN | FSF_VALID)) {
case FSF_VALID: /* Up */
if (fstimeo < 0) /* +++ see above */
fstimeo = FAST_NFS_PING;
break;
case FSF_VALID | FSF_DOWN: /* Down */
fstimeo = fs->fs_pinger;
break;
default: /* Unknown */
fstimeo = FAST_NFS_PING;
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 occured, 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;
}
static void
start_nfs_pings(fserver *fs, int pingval)
{
if (!(fs->fs_flags & FSF_PINGING)) {
fs->fs_flags |= FSF_PINGING;
if (fs->fs_cid)
untimeout(fs->fs_cid);
if (pingval < 0) {
srvrlog(fs, "wired up");
fs->fs_flags |= FSF_VALID;
fs->fs_flags &= ~FSF_DOWN;
} else {
nfs_keepalive(fs);
}
} else {
#ifdef DEBUG
dlog("Already running pings to %s", fs->fs_host);
#endif /* DEBUG */
}
}
/*
* Find an nfs server for a host.
*/
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;
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 */
/*
* Get ping interval from mount options.
* Current only used to decide whether pings
* are required or not. < 0 = no pings.
*/
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.
*/
#ifdef MNTTAB_OPT_VERS
nfs_version = hasmntval(&mnt, MNTTAB_OPT_VERS);
#endif /* MNTTAB_OPT_VERS */
#ifdef MNTTAB_OPT_PROTO
{
char *proto_opt = hasmntopt(&mnt, MNTTAB_OPT_PROTO);
if (proto_opt) {
char **p;
proto_opt += sizeof(MNTTAB_OPT_PROTO) - 1; /* skip the "proto" */
for (p = protocols; *p; p ++)
if (proto_opt[0] == '=' &&
NSTREQ(&proto_opt[1], *p, strlen(*p))) {
nfs_proto = *p;
break;
}
if (*p == NULL)
plog(XLOG_WARNING, "ignoring unknown protocol option for %s:%s",
host, rfsname);
}
}
#endif /* MNTTAB_OPT_PROTO */
/*
* lookup host address and canonical name
*/
hp = gethostbyname(host);
/*
* New code from Bob Harris <harris@basil-rathbone.mit.edu>
* Use canonical name to keep track of file server
* information. This way aliases do not generate
* multiple NFS pingers. (Except when we're normalizing
* hosts.)
*/
if (hp && !(gopt.flags & CFM_NORMALIZE_HOSTNAMES))
host = (char *) hp->h_name;
if (hp) {
switch (hp->h_addrtype) {
case AF_INET:
ip = ALLOC(struct sockaddr_in);
memset((voidp) ip, 0, sizeof(*ip));
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;
}
} else {
plog(XLOG_USER, "Unknown host: %s", host);
ip = 0;
}
/*
* Get the NFS Version, and verify server is up. Probably no
* longer need to start server down below.
*/
if (ip) {
#ifdef HAVE_FS_NFS3
/*
* 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;
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;
}
}
nfs_version = best_nfs_version;
}
if (!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
* use those.
*/
nfs_version = NFS_VERSION;
nfs_proto = "udp";
}
#else /* not HAVE_FS_NFS3 */
nfs_version = NFS_VERSION;
#endif /* not HAVE_FS_NFS3 */
}
if (!nfs_proto)
nfs_proto = "udp";
plog(XLOG_INFO, "Using NFS version %d, protocol %s on host %s",
nfs_version, nfs_proto, host);
/*
* Try to find an existing fs server stucture for this host.
* Note that differing versions or protocols have their own structures.
* XXX: Need to fix the ping mechanism to actually use the NFS protocol
* chosen here (right now it always uses datagram sockets).
*/
ITER(fs, fserver, &nfs_srvr_list) {
if (STREQ(host, fs->fs_host) &&
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.
*/
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_error = -1;
np->np_ping = 0;
/*
* Initially the server will be deemed dead
* after MAX_ALLOWED_PINGS of the fast variety
* have failed.
*/
np->np_ttl = MAX_ALLOWED_PINGS * FAST_NFS_PING + clocktime() - 1;
}
/*
* 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);
return fs;
}
}
/*
* Get here if we can't find an entry
*/
/*
* Allocate a new server
*/
fs = ALLOC(struct fserver);
fs->fs_refc = 1;
fs->fs_host = strdup(hp ? hp->h_name : "unknown_hostname");
if (gopt.flags & CFM_NORMALIZE_HOSTNAMES)
host_normalize(&fs->fs_host);
fs->fs_ip = ip;
fs->fs_cid = 0;
if (ip) {
fs->fs_flags = FSF_DOWN; /* Starts off down */
} else {
fs->fs_flags = FSF_ERROR | FSF_VALID;
mf->mf_flags |= MFF_ERROR;
mf->mf_error = ENOENT;
}
fs->fs_version = nfs_version;
fs->fs_proto = nfs_proto;
fs->fs_type = MNTTAB_TYPE_NFS;
fs->fs_pinger = AM_PINGER;
np = ALLOC(struct nfs_private);
memset((voidp) np, 0, sizeof(*np));
np->np_mountd_inval = TRUE;
np->np_xid = NPXID_ALLOC(struct );
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;
fs->fs_private = (voidp) np;
fs->fs_prfree = (void (*)(voidp)) free;
if (!(fs->fs_flags & FSF_ERROR)) {
/*
* Start of keepalive timer
*/
start_nfs_pings(fs, pingval);
}
/*
* Add to list of servers
*/
ins_que(&fs->fs_q, &nfs_srvr_list);
return fs;
}

214
contrib/amd/amq/amq.8 Normal file
View File

@ -0,0 +1,214 @@
.\"
.\" Copyright (c) 1997-1998 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.
.\"
.\" %W% (Berkeley) %G%
.\"
.\" $Id: amq.8,v 5.2.2.1 1992/02/09 15:11:15 jsp beta $
.\"
.TH AMQ 8 "25 April 1989"
.SH NAME
amq \- automounter query tool
.SH SYNOPSIS
.B amq
[
.BI \-fmpsuvTU
] [
.BI \-h " hostname"
] [
.BI \-l " log_file"
] [
.BI \-x " log_options"
] [
.BI \-D " debug_options"
] [
.BI \-M " mountmap entry"
] [
.BI \-P " program_number"
] [
.I directory
] .\|.\|.
.SH DESCRIPTION
.B Amq
provides a simple way of determining the current state of
.B amd
program.
Communication is by
.SM RPC.
Three modes of operation are supported by the current protocol. By default
a list of mount points and auto-mounted filesystems is output. An
alternative host can be specified using the
.I \-h
option.
.LP
If
.I directory
names are given, as output by default, then per-filesystem
information is displayed.
.SH OPTIONS
.TP
.B \-f
Ask the automounter to flush the internal caches.
.TP
.BI \-h " hostname"
Specify an alternate host to query. By default the local host is used. In
an
.SM HP-UX
cluster, the root server is queried by default, since that is the system on
which the automounter is normally run.
.TP
.BI \-l " log_file"
Tell amd to use
.I log_file
as the log file name. For security reasons, this must be the same log file
which amd used when started. This option is therefore only useful to
refresh amd's open file handle on the log file, so that it can be rotated
and compressed via daily cron jobs.
.TP
.B \-m
Ask the automounter to provide a list of mounted filesystems, including the
number of references to each filesystem and any error which occurred while
mounting.
.TP
.B \-p
Return the process ID of the remote or locally running amd. Useful when you
need to send a signal to the local amd process, and would rather not have to
search through the process table. This option is used in the
.I ctl-amd
script.
.TP
.B \-s
Ask the automounter to provide system-wide mount statistics.
.TP
.B \-u
Ask the automounter to unmount the filesystems named in
.I directory
instead of providing
information about them. Unmounts are requested, not forced. They merely
cause the mounted filesystem to timeout, which will be picked up by
.BR amd 's
main scheduler thus causing the normal timeout action to be taken.
.TP
.B \-v
Ask the automounter for its version information. This is a subset of the
information output by
.BR amd 's
.I -v
option.
.TP
.BI \-x " log_options"
Ask the automounter to use the logging options specified in
.I log_options
from now on.
.TP
.BI \-D " log_options"
Ask the automounter to use the debugging options specified in
.I debug_options
from now on.
.TP
.BI \-M " map_ent"
Pass a mount map entry to
.B amd
and wait for it to be evaluated, possible causing a mount. This option is
highly insecure. By default, amd and amq do not support it. You have to
configure am-utils with
.I \-\-enable\-amq\-mount
to enable this option.
.TP
.BI \-P " program_number"
Contact an alternate running amd that had registered itself on a different
RPC
.I program_number
and apply all other operations to that instance of the automounter. This is
useful when you run multiple copies of amd, and need to manage each
one separately. If not specified, amq will use the default program number
for amd, 300019. For security reasons, the only alternate program numbers
amd can use range from 300019 to 300029, inclusive.
.TP
.B \-T
Contact
.B amd
using the TCP transport only. Normally
.B amq
will try TCP, and if that failed, will try UDP.
.TP
.B \-U
Contact
.B amd
using UDP (connectionless) transport only. Normally
.B amq
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.
.SH "SEE ALSO"
.BR amd (8),
.BR ctl-amd (8),
.BR amd.conf (5).
.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.
.P
Other authors and contributors to am-utils are listed in the
.B AUTHORS
file distributed with am-utils.

938
contrib/amd/amq/amq.c Normal file
View File

@ -0,0 +1,938 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amq.c,v 5.2.2.1 1992/02/09 15:09:16 jsp beta $
*
*/
/*
* Automounter query tool
*/
#ifndef lint
char copyright[] = "\
@(#)Copyright (c) 1997-1998 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 6.0 1997-1998/01/01 15:09:16 ezk $";
static char sccsid[] = "%W% (Berkeley) %G%";
#endif /* __GNUC__ < 2 */
#endif /* not lint */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amq.h>
/* locals */
char *progname;
static int flush_flag;
static int minfo_flag;
static int getpid_flag;
static int unmount_flag;
static int stats_flag;
static int getvers_flag;
static int amd_program_number = AMQ_PROGRAM;
static int use_tcp_flag, use_udp_flag;
static char *debug_opts;
static char *amq_logfile;
static char *mount_map;
static char *xlog_optstr;
static char localhost[] = "localhost";
static char *def_server = localhost;
/* externals */
extern int optind;
extern char *optarg;
/* forward decalrations */
#ifdef HAVE_TRANSPORT_TYPE_TLI
static CLIENT *get_secure_amd_client(char *host, struct timeval *tv, int *sock);
static int amq_bind_resv_port(int td, u_short *pp);
#else /* not HAVE_TRANSPORT_TYPE_TLI */
static int privsock(int ty);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/* dummy variables */
char hostname[MAXHOSTNAMELEN];
int orig_umask, foreground, debug_flags;
pid_t mypid;
serv_state amd_state;
/* structures */
enum show_opt {
Full, Stats, Calc, Short, ShowDone
};
/*
* If (e) is Calc then just calculate the sizes
* Otherwise display the mount node on stdout
*/
static void
show_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid)
{
switch (e) {
case Calc:
{
int mw = strlen(mt->mt_mountinfo);
int dw = strlen(mt->mt_directory);
int tw = strlen(mt->mt_type);
if (mw > *mwid)
*mwid = mw;
if (dw > *dwid)
*dwid = dw;
if (tw > *twid)
*twid = tw;
}
break;
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",
*dwid, *dwid,
*mt->mt_directory ? mt->mt_directory : "/", /* XXX */
*twid, *twid,
mt->mt_type,
*mwid, *mwid,
mt->mt_mountinfo,
mt->mt_mountpoint,
mt->mt_mountuid,
mt->mt_getattr,
mt->mt_lookup,
mt->mt_readdir,
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_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",
*dwid, *dwid,
*mt->mt_directory ? mt->mt_directory : "/", /* XXX */
mt->mt_mountuid,
mt->mt_getattr,
mt->mt_lookup,
mt->mt_readdir,
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_hour, tp->tm_min, tp->tm_sec);
}
break;
case Short:
{
printf("%-*.*s %-*.*s %-*.*s %s\n",
*dwid, *dwid,
*mt->mt_directory ? mt->mt_directory : "/",
*twid, *twid,
mt->mt_type,
*mwid, *mwid,
mt->mt_mountinfo,
mt->mt_mountpoint);
}
break;
default:
break;
}
}
/*
* Display a mount tree.
*/
static void
show_mt(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *pwid)
{
while (mt) {
show_mti(mt, e, mwid, dwid, pwid);
show_mt(mt->mt_next, e, mwid, dwid, pwid);
mt = mt->mt_child;
}
}
static void
show_mi(amq_mount_info_list *ml, enum show_opt e, int *mwid, int *dwid, int *twid)
{
int i;
switch (e) {
case Calc:
{
for (i = 0; i < ml->amq_mount_info_list_len; i++) {
amq_mount_info *mi = &ml->amq_mount_info_list_val[i];
int mw = strlen(mi->mi_mountinfo);
int dw = strlen(mi->mi_mountpt);
int tw = strlen(mi->mi_type);
if (mw > *mwid)
*mwid = mw;
if (dw > *dwid)
*dwid = dw;
if (tw > *twid)
*twid = tw;
}
}
break;
case Full:
{
for (i = 0; i < ml->amq_mount_info_list_len; i++) {
amq_mount_info *mi = &ml->amq_mount_info_list_val[i];
printf("%-*.*s %-*.*s %-*.*s %-3d %s is %s",
*mwid, *mwid, mi->mi_mountinfo,
*dwid, *dwid, mi->mi_mountpt,
*twid, *twid, mi->mi_type,
mi->mi_refc, mi->mi_fserver,
mi->mi_up > 0 ? "up" :
mi->mi_up < 0 ? "starting" : "down");
if (mi->mi_error > 0) {
extern int sys_nerr;
if (mi->mi_error < sys_nerr)
printf(" (%s)", sys_errlist[mi->mi_error]);
else
printf(" (Error %d)", mi->mi_error);
} else if (mi->mi_error < 0) {
fputs(" (in progress)", stdout);
}
fputc('\n', stdout);
}
}
break;
default:
break;
}
}
/*
* Display general mount statistics
*/
static void
show_ms(amq_mount_stats *ms)
{
printf("\
requests stale mount mount unmount\n\
deferred fhandles ok failed failed\n\
%-9d %-9d %-9d %-9d %-9d\n",
ms->as_drops, ms->as_stale, ms->as_mok, ms->as_merr, ms->as_uerr);
}
#if defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT)
static char *
cluster_server(void)
{
struct cct_entry *cp;
if (cnodeid() == 0) {
/*
* Not clustered
*/
return def_server;
}
while (cp = getccent())
if (cp->cnode_type == 'r')
return cp->cnode_name;
return def_server;
}
#endif /* defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) */
/*
* MAIN
*/
int
main(int argc, char *argv[])
{
int opt_ch;
int errs = 0;
char *server;
struct sockaddr_in server_addr;
int s; /* to pass the Amd security check, we must use a priv port */
CLIENT *clnt = NULL;
struct hostent *hp;
int nodefault = 0;
struct timeval tv;
#ifndef HAVE_TRANSPORT_TYPE_TLI
enum clnt_stat cs;
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/*
* Compute program name
*/
if (argv[0]) {
progname = strrchr(argv[0], '/');
if (progname && progname[1])
progname++;
else
progname = argv[0];
}
if (!progname)
progname = "amq";
/*
* Parse arguments
*/
while ((opt_ch = getopt(argc, argv, "fh:l:msuvx:D:M:pP:TU")) != EOF)
switch (opt_ch) {
case 'f':
flush_flag = 1;
nodefault = 1;
break;
case 'h':
def_server = optarg;
break;
case 'l':
amq_logfile = optarg;
nodefault = 1;
break;
case 'm':
minfo_flag = 1;
nodefault = 1;
break;
case 'p':
getpid_flag = 1;
nodefault = 1;
break;
case 's':
stats_flag = 1;
nodefault = 1;
break;
case 'u':
unmount_flag = 1;
nodefault = 1;
break;
case 'v':
getvers_flag = 1;
nodefault = 1;
break;
case 'x':
xlog_optstr = optarg;
nodefault = 1;
break;
case 'D':
debug_opts = optarg;
nodefault = 1;
break;
case 'M':
mount_map = optarg;
nodefault = 1;
break;
case 'P':
amd_program_number = atoi(optarg);
break;
case 'T':
use_tcp_flag = 1;
break;
case 'U':
use_udp_flag = 1;
break;
default:
errs = 1;
break;
}
if (optind == argc) {
if (unmount_flag)
errs = 1;
}
if (errs) {
show_usage:
fprintf(stderr, "\
Usage: %s [-h host] [[-f] [-m] [-p] [-v] [-s]] | [[-u] directory ...]]\n\
\t[-l logfile|\"syslog\"] [-x log_flags] [-D dbg_opts] [-M mapent]\n\
\t[-P prognum] [-T] [-U]\n", progname);
exit(1);
}
/* set use_udp and use_tcp flags both to on if none are defined */
if (!use_tcp_flag && !use_udp_flag)
use_tcp_flag = use_udp_flag = 1;
#if defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT)
/*
* Figure out root server of cluster
*/
if (def_server == localhost)
server = cluster_server();
else
#endif /* defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) */
server = def_server;
/*
* Get address of server
*/
if ((hp = gethostbyname(server)) == 0 && !STREQ(server, localhost)) {
fprintf(stderr, "%s: Can't get address of %s\n", progname, server);
exit(1);
}
memset(&server_addr, 0, sizeof server_addr);
server_addr.sin_family = AF_INET;
if (hp) {
memmove((voidp) &server_addr.sin_addr, (voidp) hp->h_addr,
sizeof(server_addr.sin_addr));
} else {
/* fake "localhost" */
server_addr.sin_addr.s_addr = htonl(0x7f000001);
}
/*
* Create RPC endpoint
*/
tv.tv_sec = 5; /* 5 seconds for timeout or per retry */
tv.tv_usec = 0;
#ifdef HAVE_TRANSPORT_TYPE_TLI
clnt = get_secure_amd_client(server, &tv, &s);
if (!clnt && use_tcp_flag) /* try tcp first */
clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "tcp");
if (!clnt && use_udp_flag) { /* try udp next */
clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "udp");
/* if ok, set timeout (valid for connectionless transports only) */
if (clnt)
clnt_control(clnt, CLSET_RETRY_TIMEOUT, (char *) &tv);
}
#else /* not HAVE_TRANSPORT_TYPE_TLI */
/* first check if remote portmapper is up */
cs = pmap_ping(&server_addr);
if (cs == RPC_TIMEDOUT) {
fprintf(stderr, "%s: failed to contact portmapper on host \"%s\". %s\n",
progname, server, clnt_sperrno(cs));
exit(1);
}
/* portmapper exists: get remote amd info from it */
if (!clnt && use_tcp_flag) { /* try tcp first */
s = RPC_ANYSOCK;
clnt = clnttcp_create(&server_addr, amd_program_number,
AMQ_VERSION, &s, 0, 0);
}
if (!clnt && use_udp_flag) { /* try udp next */
/* XXX: do we need to close(s) ? */
s = privsock(SOCK_DGRAM);
clnt = clntudp_create(&server_addr, amd_program_number,
AMQ_VERSION, tv, &s);
}
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
if (!clnt) {
fprintf(stderr, "%s: ", progname);
clnt_pcreateerror(server);
exit(1);
}
/*
* Control debugging
*/
if (debug_opts) {
int *rc;
amq_setopt opt;
opt.as_opt = AMOPT_DEBUG;
opt.as_str = debug_opts;
rc = amqproc_setopt_1(&opt, clnt);
if (rc && *rc < 0) {
fprintf(stderr, "%s: daemon not compiled for debug\n", progname);
errs = 1;
} else if (!rc || *rc > 0) {
fprintf(stderr, "%s: debug setting for \"%s\" failed\n", progname, debug_opts);
errs = 1;
}
}
/*
* Control logging
*/
if (xlog_optstr) {
int *rc;
amq_setopt opt;
opt.as_opt = AMOPT_XLOG;
opt.as_str = xlog_optstr;
rc = amqproc_setopt_1(&opt, clnt);
if (!rc || *rc) {
fprintf(stderr, "%s: setting log level to \"%s\" failed\n", progname, xlog_optstr);
errs = 1;
}
}
/*
* Control log file
*/
if (amq_logfile) {
int *rc;
amq_setopt opt;
opt.as_opt = AMOPT_LOGFILE;
opt.as_str = amq_logfile;
rc = amqproc_setopt_1(&opt, clnt);
if (!rc || *rc) {
fprintf(stderr, "%s: setting logfile to \"%s\" failed\n", progname, amq_logfile);
errs = 1;
}
}
/*
* Flush map cache
*/
if (flush_flag) {
int *rc;
amq_setopt opt;
opt.as_opt = AMOPT_FLUSHMAPC;
opt.as_str = "";
rc = amqproc_setopt_1(&opt, clnt);
if (!rc || *rc) {
fprintf(stderr, "%s: amd on %s cannot flush the map cache\n", progname, server);
errs = 1;
}
}
/*
* Mount info
*/
if (minfo_flag) {
int dummy;
amq_mount_info_list *ml = amqproc_getmntfs_1(&dummy, clnt);
if (ml) {
int mwid = 0, dwid = 0, twid = 0;
show_mi(ml, Calc, &mwid, &dwid, &twid);
mwid++;
dwid++;
twid++;
show_mi(ml, Full, &mwid, &dwid, &twid);
} else {
fprintf(stderr, "%s: amd on %s cannot provide mount info\n", progname, server);
}
}
/*
* Mount map
*/
if (mount_map) {
int *rc;
do {
rc = amqproc_mount_1(&mount_map, clnt);
} while (rc && *rc < 0);
if (!rc || *rc > 0) {
if (rc)
errno = *rc;
else
errno = ETIMEDOUT;
fprintf(stderr, "%s: could not start new ", progname);
perror("autmount point");
}
}
/*
* Get Version
*/
if (getvers_flag) {
amq_string *spp = amqproc_getvers_1((voidp) 0, clnt);
if (spp && *spp) {
fputs(*spp, stdout);
XFREE(*spp);
} else {
fprintf(stderr, "%s: failed to get version information\n", progname);
errs = 1;
}
}
/*
* Get PID of amd
*/
if (getpid_flag) {
int *ip = amqproc_getpid_1((voidp) 0, clnt);
if (ip && *ip) {
printf("%d\n", *ip);
} else {
fprintf(stderr, "%s: failed to get PID of amd\n", progname);
errs = 1;
}
}
/*
* Apply required operation to all remaining arguments
*/
if (optind < argc) {
do {
char *fs = argv[optind++];
if (unmount_flag) {
/*
* Unmount request
*/
amqproc_umnt_1(&fs, clnt);
} else {
/*
* Stats request
*/
amq_mount_tree_p *mtp = amqproc_mnttree_1(&fs, clnt);
if (mtp) {
amq_mount_tree *mt = *mtp;
if (mt) {
int mwid = 0, dwid = 0, twid = 0;
show_mt(mt, Calc, &mwid, &dwid, &twid);
mwid++;
dwid++, twid++;
printf("%-*.*s Uid Getattr Lookup RdDir RdLnk Statfs Mounted@\n",
dwid, dwid, "What");
show_mt(mt, Stats, &mwid, &dwid, &twid);
} else {
fprintf(stderr, "%s: %s not automounted\n", progname, fs);
}
xdr_pri_free((XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (caddr_t) mtp);
} else {
fprintf(stderr, "%s: ", progname);
clnt_perror(clnt, server);
errs = 1;
}
}
} while (optind < argc);
} else if (unmount_flag) {
goto show_usage;
} else if (stats_flag) {
amq_mount_stats *ms = amqproc_stats_1((voidp) 0, clnt);
if (ms) {
show_ms(ms);
} else {
fprintf(stderr, "%s: ", progname);
clnt_perror(clnt, server);
errs = 1;
}
} else if (!nodefault) {
amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt);
if (mlp) {
enum show_opt e = Calc;
int mwid = 0, dwid = 0, pwid = 0;
while (e != ShowDone) {
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);
}
mwid++;
dwid++, pwid++;
if (e == Calc)
e = Short;
else if (e == Short)
e = ShowDone;
}
} else {
fprintf(stderr, "%s: ", progname);
clnt_perror(clnt, server);
errs = 1;
}
}
exit(errs);
return errs; /* should never reache here */
}
#ifdef HAVE_TRANSPORT_TYPE_TLI
/*
* How to bind to reserved ports.
* TLI handle (socket) and port version.
*/
/* defined here so that it does not have to resolve it with libamu.a */
static int
amq_bind_resv_port(int td, u_short *pp)
{
int rc = -1, port;
struct t_bind *treq, *tret;
struct sockaddr_in *sin;
treq = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR);
if (!treq) {
plog(XLOG_ERROR, "t_alloc 1");
return -1;
}
tret = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR);
if (!tret) {
t_free((char *) treq, T_BIND);
plog(XLOG_ERROR, "t_alloc 2");
return -1;
}
memset((char *) treq->addr.buf, 0, treq->addr.len);
sin = (struct sockaddr_in *) treq->addr.buf;
sin->sin_family = AF_INET;
treq->qlen = 0;
treq->addr.len = treq->addr.maxlen;
errno = EADDRINUSE;
port = IPPORT_RESERVED;
do {
--port;
sin->sin_port = htons(port);
rc = t_bind(td, treq, tret);
if (rc < 0) {
} else {
if (memcmp(treq->addr.buf, tret->addr.buf, tret->addr.len) == 0)
break;
else
t_unbind(td);
}
} while ((rc < 0 || errno == EADDRINUSE) && (int) port > IPPORT_RESERVED / 2);
if (pp) {
if (rc == 0)
*pp = port;
else
plog(XLOG_ERROR, "could not t_bind to any reserved port");
}
t_free((char *) tret, T_BIND);
t_free((char *) treq, T_BIND);
return rc;
}
/*
* Create a secure rpc client attached to the amd daemon.
*/
static CLIENT *
get_secure_amd_client(char *host, struct timeval *tv, int *sock)
{
CLIENT *client;
struct netbuf nb;
struct netconfig *nc, *pm_nc;
struct sockaddr_in sin;
nb.maxlen = sizeof(sin);
nb.buf = (char *) &sin;
/*
* Ensure that remote portmapper is alive
* (must use connectionless netconfig).
*/
if ((pm_nc = getnetconfigent(NC_UDP)) != NULL) {
enum clnt_stat cs;
cs = rpcb_rmtcall(pm_nc,
host,
amd_program_number,
AMQ_VERSION,
AMQPROC_NULL,
(XDRPROC_T_TYPE) xdr_void,
NULL,
(XDRPROC_T_TYPE) xdr_void,
NULL,
*tv,
NULL);
if (cs == RPC_TIMEDOUT) {
fprintf(stderr, "%s: failed to contact portmapper on host \"%s\". %s\n",
progname, host, clnt_sperrno(cs));
exit(1);
}
}
/*
* First transport type to try: TCP
*/
if (use_tcp_flag) {
/* Find amd address on TCP */
nc = getnetconfigent(NC_TCP);
if (!nc) {
fprintf(stderr, "getnetconfig for tcp failed: %s\n", nc_sperror());
goto tryudp;
}
if (!rpcb_getaddr(amd_program_number, AMQ_VERSION, nc, &nb, host)) {
/*
* don't pring error messages here, since amd might legitimately
* serve udp only
*/
goto tryudp;
}
/* Create priviledged TCP socket */
*sock = t_open(nc->nc_device, O_RDWR, 0);
if (*sock < 0) {
fprintf(stderr, "t_open %s: %m\n", nc->nc_device);
goto tryudp;
}
if (amq_bind_resv_port(*sock, (u_short *) 0) < 0)
goto tryudp;
client = clnt_vc_create(*sock, &nb, amd_program_number, AMQ_VERSION, 0, 0);
if (!client) {
fprintf(stderr, "clnt_vc_create failed");
t_close(*sock);
goto tryudp;
}
/* tcp succeeded */
return client;
}
tryudp:
/*
* TCP failed so try UDP
*/
if (use_udp_flag) {
/* find amd address on UDP */
nc = getnetconfigent(NC_UDP);
if (!nc) {
fprintf(stderr, "getnetconfig for udp failed: %s\n", nc_sperror());
return NULL;
}
if (!rpcb_getaddr(amd_program_number, AMQ_VERSION, nc, &nb, host)) {
fprintf(stderr, "%s\n",
clnt_spcreateerror("couldn't get amd address on udp"));
return NULL;
}
/* create priviledged UDP socket */
*sock = t_open(nc->nc_device, O_RDWR, 0);
if (*sock < 0) {
fprintf(stderr, "t_open %s: %m\n", nc->nc_device);
return NULL; /* neither tcp not udp succeeded */
}
if (amq_bind_resv_port(*sock, (u_short *) 0) < 0)
return NULL;
client = clnt_dg_create(*sock, &nb, amd_program_number, AMQ_VERSION, 0, 0);
if (!client) {
fprintf(stderr, "clnt_dg_create failed\n");
t_close(*sock);
return NULL; /* neither tcp not udp succeeded */
}
if (clnt_control(client, CLSET_RETRY_TIMEOUT, (char *) tv) == FALSE) {
fprintf(stderr, "clnt_control CLSET_RETRY_TIMEOUT for udp failed\n");
clnt_destroy(client);
return NULL; /* neither tcp not udp succeeded */
}
/* udp succeeded */
return client;
}
/* should never get here */
return NULL;
}
#else /* not HAVE_TRANSPORT_TYPE_TLI */
/*
* inetresport creates a datagram socket and attempts to bind it to a
* secure port.
* returns: The bound socket, or -1 to indicate an error.
*/
static int
inetresport(int ty)
{
int alport;
struct sockaddr_in addr;
int fd;
/* Use internet address family */
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
if ((fd = socket(AF_INET, ty, 0)) < 0)
return -1;
for (alport = IPPORT_RESERVED - 1; alport > IPPORT_RESERVED / 2 + 1; alport--) {
addr.sin_port = htons((u_short) alport);
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) >= 0)
return fd;
if (errno != EADDRINUSE) {
close(fd);
return -1;
}
}
close(fd);
errno = EAGAIN;
return -1;
}
/*
* Privsock() calls inetresport() to attempt to bind a socket to a secure
* port. If inetresport() fails, privsock returns a magic socket number which
* indicates to RPC that it should make its own socket.
* returns: A privileged socket # or RPC_ANYSOCK.
*/
static int
privsock(int ty)
{
int sock = inetresport(ty);
if (sock < 0) {
errno = 0;
/* Couldn't get a secure port, let RPC make an insecure one */
sock = RPC_ANYSOCK;
}
return sock;
}
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

63
contrib/amd/amq/amq.h Normal file
View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amq.h,v 1.1 1996/01/13 23:23:39 ezk Exp ezk $
*
*/
#ifndef _AMQ_H
#define _AMQ_H
/*
* external definitions for building amq
*/
extern voidp amqproc_null_1(voidp argp, CLIENT *rqstp);
extern amq_mount_tree_p *amqproc_mnttree_1(amq_string *argp, CLIENT *rqstp);
extern voidp amqproc_umnt_1(amq_string *argp, CLIENT *rqstp);
extern amq_mount_stats *amqproc_stats_1(voidp argp, CLIENT *rqstp);
extern amq_mount_tree_list *amqproc_export_1(voidp argp, CLIENT *rqstp);
extern int *amqproc_setopt_1(amq_setopt *argp, CLIENT *rqstp);
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);
#endif /* not _AMQ_H */

208
contrib/amd/amq/amq_clnt.c Normal file
View File

@ -0,0 +1,208 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amq_clnt.c,v 5.2.2.1 1992/02/09 15:09:24 jsp beta $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amq.h>
static struct timeval TIMEOUT = {ALLOWED_MOUNT_TIME, 0};
voidp
amqproc_null_1(voidp argp, CLIENT *clnt)
{
static char res;
memset((char *) &res, 0, sizeof(res));
if (clnt_call(clnt, AMQPROC_NULL,
(XDRPROC_T_TYPE) xdr_void, argp,
(XDRPROC_T_TYPE) xdr_void, &res, TIMEOUT)
!= RPC_SUCCESS) {
return (NULL);
}
return ((voidp) &res);
}
amq_mount_tree_p *
amqproc_mnttree_1(amq_string *argp, CLIENT *clnt)
{
static amq_mount_tree_p res;
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,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
return (&res);
}
voidp
amqproc_umnt_1(amq_string *argp, CLIENT *clnt)
{
static char res;
memset((char *) &res, 0, sizeof(res));
if (clnt_call(clnt, AMQPROC_UMNT,
(XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) argp,
(XDRPROC_T_TYPE) xdr_void, &res,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
return ((voidp) &res);
}
amq_mount_stats *
amqproc_stats_1(voidp argp, CLIENT *clnt)
{
static amq_mount_stats res;
memset((char *) &res, 0, sizeof(res));
if (clnt_call(clnt, AMQPROC_STATS,
(XDRPROC_T_TYPE) xdr_void, argp,
(XDRPROC_T_TYPE) xdr_amq_mount_stats,
(SVC_IN_ARG_TYPE) & res,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
return (&res);
}
amq_mount_tree_list *
amqproc_export_1(voidp argp, CLIENT *clnt)
{
static amq_mount_tree_list res;
memset((char *) &res, 0, sizeof(res));
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) {
return (NULL);
}
return (&res);
}
int *
amqproc_setopt_1(amq_setopt *argp, CLIENT *clnt)
{
static int res;
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) {
return (NULL);
}
return (&res);
}
amq_mount_info_list *
amqproc_getmntfs_1(voidp argp, CLIENT *clnt)
{
static amq_mount_info_list res;
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) {
return (NULL);
}
return (&res);
}
int *
amqproc_mount_1(voidp argp, CLIENT *clnt)
{
static int res;
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,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
return (&res);
}
amq_string *
amqproc_getvers_1(voidp argp, CLIENT *clnt)
{
static amq_string res;
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,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
return (&res);
}
int *
amqproc_getpid_1(voidp argp, CLIENT *clnt)
{
static int res;
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,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
return (&res);
}

259
contrib/amd/amq/amq_xdr.c Normal file
View File

@ -0,0 +1,259 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: amq_xdr.c,v 5.2.2.1 1992/02/09 15:09:23 jsp beta $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amq.h>
bool_t
xdr_time_type(XDR *xdrs, time_type *objp)
{
if (!xdr_long(xdrs, (long *) objp)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp)
{
if (!xdr_amq_string(xdrs, &objp->mt_mountinfo)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &objp->mt_directory)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &objp->mt_mountpoint)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &objp->mt_type)) {
return (FALSE);
}
if (!xdr_time_type(xdrs, &objp->mt_mounttime)) {
return (FALSE);
}
if (!xdr_u_short(xdrs, &objp->mt_mountuid)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->mt_getattr)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->mt_lookup)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->mt_readdir)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->mt_readlink)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->mt_statfs)) {
return (FALSE);
}
if (!xdr_pointer(xdrs, (char **) &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)) {
return (FALSE);
}
return (TRUE);
}
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)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_amq_mount_info(XDR *xdrs, amq_mount_info *objp)
{
if (!xdr_amq_string(xdrs, &objp->mi_type)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &objp->mi_mountpt)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &objp->mi_mountinfo)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &objp->mi_fserver)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->mi_error)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->mi_refc)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->mi_up)) {
return (FALSE);
}
return (TRUE);
}
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,
(u_int *) &objp->amq_mount_info_list_len,
~0,
sizeof(amq_mount_info),
(XDRPROC_T_TYPE) xdr_amq_mount_info)) {
return (FALSE);
}
return (TRUE);
}
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,
(u_int *) &objp->amq_mount_tree_list_len,
~0,
sizeof(amq_mount_tree_p),
(XDRPROC_T_TYPE) xdr_amq_mount_tree_p)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_amq_mount_stats(XDR *xdrs, amq_mount_stats *objp)
{
if (!xdr_int(xdrs, &objp->as_drops)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->as_stale)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->as_mok)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->as_merr)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->as_uerr)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_amq_opt(XDR *xdrs, amq_opt *objp)
{
if (!xdr_enum(xdrs, (enum_t *) objp)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_amq_setopt(XDR *xdrs, amq_setopt *objp)
{
if (!xdr_amq_opt(xdrs, &objp->as_opt)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &objp->as_str)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_pri_free(XDRPROC_T_TYPE xdr_args, caddr_t args_ptr)
{
XDR xdr;
xdr.x_op = XDR_FREE;
return ((*xdr_args) (&xdr, (caddr_t *) args_ptr));
}

72
contrib/amd/amq/pawd.1 Normal file
View File

@ -0,0 +1,72 @@
.\"
.\" Copyright (c) 1997-1998 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.
.\"
.\" %W% (Berkeley) %G%
.\"
.\" $Id: pawd.1,v 5.2.2.1 1992/02/09 15:11:15 jsp beta $
.\"
.TH PAWD 1 "6 Jan 1998"
.SH NAME
pawd \- print automounter working directory
.SH SYNOPSIS
.B pawd
[
.I path ...
]
.SH DESCRIPTION
.LP
.B pawd
is used to print the current working directory, adjusted to reflect proper
paths that can be reused to go through the automounter for the shortest
possible path. In particular, the path printed back does not include any
of
.BR Amd 's
local mount points. Using them is unsafe, because
.B Amd
may unmount managed file systems from the mount points, and thus including
them in paths may not always find the files within.
.P
Without any arguments,
.B pawd
will print the automounter adjusted current working directory. With any
number of arguments, it will print the adjusted path of each one of the
arguments.
.SH "SEE ALSO"
.BR amd (8),
.BR amq (8),
.BR pwd (1).

296
contrib/amd/amq/pawd.c Normal file
View File

@ -0,0 +1,296 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: pawd.c,v 5.2.2.1 1992/02/09 15:09:16 jsp beta $
*
*/
/*
* pawd is similar to pwd, except that it returns more "natural" versions of
* pathnames for directories automounted with the amd automounter. If any
* arguments are given, the "more natural" form of the given pathnames are
* printed.
*
* Paul Anderson (paul@ed.lfcs)
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amq.h>
/* dummy variables */
char *progname;
char hostname[MAXHOSTNAMELEN];
int orig_umask, foreground, debug_flags;
pid_t mypid;
serv_state amd_state;
/* statics */
static char *localhost="localhost";
static char newdir[MAXPATHLEN];
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")) {
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 *
cluster_server(void)
{
# ifdef HAVE_EXTERN_GETCCENT
struct cct_entry *cp;
# endif /* HAVE_EXTERN_GETCCENT */
if (cnodeid() == 0)
return localhost;
# ifdef HAVE_EXTERN_GETCCENT
while ((cp = getccent()))
if (cp->cnode_type == 'r')
return cp->cnode_name;
# endif /* HAVE_EXTERN_GETCCENT */
return localhost;
}
#endif /* HAVE_CNODEID */
/* DISK_HOME_HACK added by gdmr */
#ifdef DISK_HOME_HACK
static char *
hack_name(char *dir)
{
char partition[MAXPATHLEN];
char username[MAXPATHLEN];
char hesiod_lookup[MAXPATHLEN];
char *to, *ch, *hes_name, *dot;
char **hes;
#ifdef DEBUG
fprintf(stderr, "hack_name(%s)\n", dir);
#endif /* DEBUG */
if (dir[0] == '/' && dir[1] == 'a' && dir[2] == '/') {
/* Could be /a/server/disk/home/partition/user... */
ch = dir + 3;
while (*ch && *ch != '/') ch++; /* Skip server */
if (!NSTREQ(ch, "/disk/home/", 11))
return NULL; /* Nope */
/* Looking promising, next should be the partition name */
ch += 11;
to = partition;
while (*ch && *ch != '/') *to++ = *ch++;
to = '\0';
if (!(*ch))
return NULL; /* Off the end */
/* Now the username */
ch++;
to = username;
while (*ch && *ch != '/') *to++ = *ch++;
to = '\0';
#ifdef DEBUG
fprintf(stderr, "partition %s, username %s\n", partition, username);
#endif /* DEBUG */
sprintf(hesiod_lookup, "%s.homes-remote", username);
hes = hes_resolve(hesiod_lookup, "amd");
if (!hes)
return NULL;
#ifdef DEBUG
fprintf(stderr, "hesiod -> <%s>\n", *hes);
#endif /* DEBUG */
hes_name = strstr(*hes, "/homes/remote/");
if (!hes_name) return NULL;
hes_name += 14;
#ifdef DEBUG
fprintf(stderr, "hesiod -> <%s>\n", hes_name);
#endif /* DEBUG */
dot = hes_name;
while (*dot && *dot != '.') dot++;
*dot = '\0';
#ifdef DEBUG
fprintf(stderr, "hesiod -> <%s>\n", hes_name);
#endif /* DEBUG */
if (strcmp(partition, hes_name)) return NULL;
#ifdef DEBUG
fprintf(stderr, "A match, munging....\n");
#endif /* DEBUG */
strcpy(transform, "/home/");
strcat(transform, username);
if (*ch) strcat(transform, ch);
#ifdef DEBUG
fprintf(stderr, "Munged to <%s>\n", transform);
#endif /* DEBUG */
return transform;
}
return NULL;
}
#endif /* DISK_HOME_HACK */
/*
* The routine transform_dir(path) transforms pathnames of directories
* mounted with the amd automounter to produce a more "natural" version.
* The automount table is obtained from the local amd via the rpc interface
* and reverse lookups are repeatedly performed on the directory name
* substituting the name of the automount link for the value of the link
* whenever it occurs as a prefix of the directory name.
*/
static char *
transform_dir(char *dir)
{
#ifdef DISK_HOME_HACK
char *ch;
#endif /* DISK_HOME_HACK */
char *server;
struct sockaddr_in server_addr;
int s = RPC_ANYSOCK;
CLIENT *clnt;
struct hostent *hp;
amq_mount_tree_list *mlp;
struct timeval tmo = {10, 0};
#ifdef DISK_HOME_HACK
if (ch = hack_name(dir))
return ch;
#endif /* DISK_HOME_HACK */
#ifdef HAVE_CNODEID
server = cluster_server();
#else /* not HAVE_CNODEID */
server = localhost;
#endif /* not HAVE_CNODEID */
if ((hp = gethostbyname(server)) == 0)
return dir;
memset(&server_addr, 0, sizeof(server_addr));
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)
return dir;
strcpy(transform,dir);
while ( (mlp = amqproc_export_1((voidp)0, clnt)) &&
find_mlp(mlp,transform) ) {
strcpy(transform,newdir);
}
return transform;
}
/* getawd() is a substitute for getwd() which transforms the path */
static char *
getawd(char *path)
{
#ifdef HAVE_GETCWD
char *wd = getcwd(path, MAXPATHLEN+1);
#else /* not HAVE_GETCWD */
char *wd = getwd(path);
#endif /* not HAVE_GETCWD */
if (wd == NULL) {
return NULL;
}
strcpy(path, transform_dir(wd));
return path;
}
int
main(int argc, char *argv[])
{
char tmp_buf[MAXPATHLEN], *wd;
if (argc == 1) {
wd = getawd(tmp_buf);
if (wd == NULL) {
fprintf(stderr, "pawd: %s\n", tmp_buf);
exit(1);
} else {
fprintf(stdout, "%s\n", wd);
}
} else {
while (--argc) {
wd = transform_dir(*++argv);
fprintf(stdout, "%s\n", wd);
}
}
exit(0);
}

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: checkmount_bsd44.c,v 5.2.2.2 1992/05/31 16:35:45 jsp Exp $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
extern int is_same_host(char *name1, char *name2, struct in_addr addr2);
int fixmount_check_mount(char *host, struct in_addr hostaddr, char *path);
int
fixmount_check_mount(char *host, struct in_addr hostaddr, char *path)
{
struct statfs *mntbufp, *mntp;
int nloc, i;
char *colon;
/* read mount table from kernel */
nloc = getmntinfo(&mntbufp, MNT_NOWAIT);
if (nloc <= 0) {
perror("getmntinfo");
exit(1);
}
mntp = mntbufp;
for (i=0; i<nloc; ++i) {
if ((colon = strchr(mntp->f_mntfromname, ':'))) {
*colon = '\0';
if (STREQ(colon + 1, path) &&
is_same_host(mntp->f_mntfromname, host, hostaddr))
return 1;
}
}
return 0;
}

View File

@ -0,0 +1,2 @@
/* $srcdir/conf/fh_dref/fh_dref_freebsd22.h */
#define NFS_FH_DREF(dst, src) (dst) = (u_char *) (src)

View File

@ -0,0 +1,2 @@
/* $srcdir/conf/hn_dref/hn_dref_default.h */
#define NFS_HN_DREF(dst, src) (dst) = (src)

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: mount_freebsd3.c,v 5.2.2.1 1992/02/09 15:10:08 jsp beta $
*
*/
/*
* FreeBSD 3.x (as of snapshot 3.0-980311-SNAP) Mount helper
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amu.h>
/*
* Map from conventional mount arguments
* to FreeBSD 3.0 style arguments.
*/
int
mount_freebsd3(MTYPE_TYPE type, const char *dir, int flags, voidp data)
{
char const *namelist[] = INITMOUNTNAMES;
return mount(namelist[type],
dir,
flags,
data);
}

View File

@ -0,0 +1,145 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: mtab_bsd.c,v 5.2.2.2 1992/11/12 23:29:14 jsp Exp $
*
*/
/*
* BSD 4.4 systems don't write their mount tables on a file. Instead, they
* use a (better) system where the kernel keeps this state, and you access
* the mount tables via a known interface.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amu.h>
static mntent_t *
mnt_dup(struct statfs *mp)
{
mntent_t *new_mp = ALLOC(mntent_t);
char *ty;
new_mp->mnt_fsname = strdup(mp->f_mntfromname);
new_mp->mnt_dir = strdup(mp->f_mntonname);
#ifdef HAVE_FIELD_STRUCT_STATFS_F_FSTYPENAME
ty = mp->f_fstypename;
#else /* not HAVE_FIELD_STRUCT_STATFS_F_FSTYPENAME */
switch (mp->f_type) {
# if defined(MOUNT_UFS) && defined(MNTTAB_TYPE_UFS)
case MOUNT_UFS:
ty = MNTTAB_TYPE_UFS;
break;
# endif /* defined(MOUNT_UFS) && defined(MNTTAB_TYPE_UFS) */
# if defined(MOUNT_NFS) && defined(MNTTAB_TYPE_NFS)
case MOUNT_NFS:
ty = MNTTAB_TYPE_NFS;
break;
# endif /* defined(MOUNT_NFS) && defined(MNTTAB_TYPE_NFS) */
# if defined(MOUNT_MFS) && defined(MNTTAB_TYPE_MFS)
case MOUNT_MFS:
ty = MNTTAB_TYPE_MFS;
break;
# endif /* defined(MOUNT_MFS) && defined(MNTTAB_TYPE_MFS) */
default:
ty = "unknown";
break;
}
#endif /* not HAVE_FIELD_STRUCT_STATFS_F_FSTYPENAME */
new_mp->mnt_type = strdup(ty);
new_mp->mnt_opts = strdup("unset");
new_mp->mnt_freq = 0;
new_mp->mnt_passno = 0;
return new_mp;
}
/*
* Read a mount table into memory
*/
mntlist *
read_mtab(char *fs, const char *mnttabname)
{
mntlist **mpp, *mhp;
struct statfs *mntbufp, *mntp;
int nloc = getmntinfo(&mntbufp, MNT_NOWAIT);
if (nloc == 0) {
plog(XLOG_ERROR, "Can't read mount table");
return 0;
}
mpp = &mhp;
for (mntp = mntbufp; mntp < mntbufp + nloc; mntp++) {
/*
* Allocate a new slot
*/
*mpp = ALLOC(struct mntlist);
/*
* Copy the data returned by getmntent
*/
(*mpp)->mnt = mnt_dup(mntp);
/*
* Move to next pointer
*/
mpp = &(*mpp)->mnext;
}
/*
* Terminate the list
*/
*mpp = 0;
return mhp;
}

View File

@ -0,0 +1,146 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: nfs_prot_freebsd2.h,v 1.1 1996/01/13 23:23:39 ezk Exp ezk $
*
*/
#ifndef _AMU_NFS_PROT_H
#define _AMU_NFS_PROT_H
#ifdef HAVE_RPCSVC_NFS_PROT_H
# include <rpcsvc/nfs_prot.h>
#endif /* HAVE_RPCSVC_NFS_PROT_H */
/*
* MACROS:
*/
#define dr_drok_u diropres
#define ca_where where
#define da_fhandle dir
#define da_name name
#define dl_entries entries
#define dl_eof eof
#define dr_status status
#define dr_u diropres_u
#define drok_attributes attributes
#define drok_fhandle file
#define fh_data data
#define la_fhandle from
#define la_to to
#define na_atime atime
#define na_ctime ctime
#define na_fileid fileid
#define na_fsid fsid
#define na_mode mode
#define na_mtime mtime
#define na_nlink nlink
#define na_size size
#define na_type type
#define ne_cookie cookie
#define ne_fileid fileid
#define ne_name name
#define ne_nextentry nextentry
#define ns_attr_u attributes
#define ns_status status
#define ns_u attrstat_u
#define nt_seconds seconds
#define nt_useconds useconds
#define rda_cookie cookie
#define rda_count count
#define rda_fhandle dir
#define rdr_reply_u reply
#define rdr_status status
#define rdr_u readdirres_u
#define rlr_data_u data
#define rlr_status status
#define rlr_u readlinkres_u
#define rna_from from
#define rna_to to
#define rr_status status
#define sag_fhandle file
#define sfr_reply_u reply
#define sfr_status status
#define sfr_u statfsres_u
#define sfrok_bavail bavail
#define sfrok_bfree bfree
#define sfrok_blocks blocks
#define sfrok_bsize bsize
#define sfrok_tsize tsize
#define sla_from from
#define wra_fhandle file
/*
* TYPEDEFS:
*/
typedef attrstat nfsattrstat;
typedef createargs nfscreateargs;
typedef dirlist nfsdirlist;
typedef diropargs nfsdiropargs;
typedef diropres nfsdiropres;
typedef entry nfsentry;
typedef fattr nfsfattr;
typedef ftype nfsftype;
typedef linkargs nfslinkargs;
typedef readargs nfsreadargs;
typedef readdirargs nfsreaddirargs;
typedef readdirres nfsreaddirres;
typedef readlinkres nfsreadlinkres;
typedef readres nfsreadres;
typedef renameargs nfsrenameargs;
typedef sattrargs nfssattrargs;
typedef statfsokres nfsstatfsokres;
typedef statfsres nfsstatfsres;
typedef symlinkargs nfssymlinkargs;
typedef writeargs nfswriteargs;
/*
* FreeBSD 2.2.x has NFS V3, but it does not define enough macros
* in the headers to automatically detect it.
* So fake it in the meant time.
*/
#if 0
#define MOUNT_NFS3 MOUNT_NFS
#endif
#endif /* not _AMU_NFS_PROT_H */

View File

@ -0,0 +1,211 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: nfs_prot_freebsd3.h,v 1.1 1996/01/13 23:23:39 ezk Exp ezk $
*
*/
#ifndef _AMU_NFS_PROT_H
#define _AMU_NFS_PROT_H
#ifdef HAVE_RPCSVC_NFS_PROT_H
# include <rpcsvc/nfs_prot.h>
#endif /* HAVE_RPCSVC_NFS_PROT_H */
#ifdef HAVE_NFS_RPCV2_H
# include <nfs/rpcv2.h>
#endif /* HAVE_NFS_RPCV2_H */
#ifdef HAVE_NFS_NFS_H
# include <nfs/nfs.h>
#endif /* HAVE_NFS_NFS_H */
/*
* MACROS:
*/
#define dr_drok_u diropres
#define ca_where where
#define da_fhandle dir
#define da_name name
#define dl_entries entries
#define dl_eof eof
#define dr_status status
#define dr_u diropres_u
#define drok_attributes attributes
#define drok_fhandle file
#define fh_data data
#define la_fhandle from
#define la_to to
#define na_atime atime
#define na_ctime ctime
#define na_fileid fileid
#define na_fsid fsid
#define na_mode mode
#define na_mtime mtime
#define na_nlink nlink
#define na_size size
#define na_type type
#define ne_cookie cookie
#define ne_fileid fileid
#define ne_name name
#define ne_nextentry nextentry
#define ns_attr_u attributes
#define ns_status status
#define ns_u attrstat_u
#define nt_seconds seconds
#define nt_useconds useconds
#define rda_cookie cookie
#define rda_count count
#define rda_fhandle dir
#define rdr_reply_u reply
#define rdr_status status
#define rdr_u readdirres_u
#define rlr_data_u data
#define rlr_status status
#define rlr_u readlinkres_u
#define rna_from from
#define rna_to to
#define rr_status status
#define sag_fhandle file
#define sfr_reply_u reply
#define sfr_status status
#define sfr_u statfsres_u
#define sfrok_bavail bavail
#define sfrok_bfree bfree
#define sfrok_blocks blocks
#define sfrok_bsize bsize
#define sfrok_tsize tsize
#define sla_from from
#define wra_fhandle file
/*
* TYPEDEFS:
*/
typedef attrstat nfsattrstat;
typedef createargs nfscreateargs;
typedef dirlist nfsdirlist;
typedef diropargs nfsdiropargs;
typedef diropres nfsdiropres;
typedef entry nfsentry;
typedef fattr nfsfattr;
typedef ftype nfsftype;
typedef linkargs nfslinkargs;
typedef readargs nfsreadargs;
typedef readdirargs nfsreaddirargs;
typedef readdirres nfsreaddirres;
typedef readlinkres nfsreadlinkres;
typedef readres nfsreadres;
typedef renameargs nfsrenameargs;
typedef sattrargs nfssattrargs;
typedef statfsokres nfsstatfsokres;
typedef statfsres nfsstatfsres;
typedef symlinkargs nfssymlinkargs;
typedef writeargs nfswriteargs;
/*
*
* FreeBSD 3.0 has NFS V3, but you need to regenrate the rpcsc header files
* as follows:
* cd /usr/local/rpcsvc
* rpcgen -DWANT_NFS3 mount.x
* rpcgen -DWANT_NFS3 nfs_prot.x
* But that's not expected of everyone, plus there are additional things
* needed so I define everything that's neede for NFS V3 here.
*/
#ifdef NFSMNT_NFSV3
# define MOUNT_NFS3 MOUNT_NFS
# define MNTOPT_NFS3 "nfs"
#define FHSIZE3 64 /* size in bytes of a file handle (v3) */
#define NFS3_FHSIZE 64
#define MOUNTVERS3 ((unsigned long)(3))
#define NFS_V3 ((unsigned long)(3))
typedef struct {
u_int fhandle3_len;
char *fhandle3_val;
} fhandle3;
enum mountstat3 {
MNT3_OK = 0,
MNT3ERR_PERM = 1,
MNT3ERR_NOENT = 2,
MNT3ERR_IO = 5,
MNT3ERR_ACCES = 13,
MNT3ERR_NOTDIR = 20,
MNT3ERR_INVAL = 22,
MNT3ERR_NAMETOOLONG = 63,
MNT3ERR_NOTSUPP = 10004,
MNT3ERR_SERVERFAULT = 10006
};
typedef enum mountstat3 mountstat3;
struct mountres3_ok {
fhandle3 fhandle;
struct {
u_int auth_flavors_len;
int *auth_flavors_val;
} auth_flavors;
};
typedef struct mountres3_ok mountres3_ok;
struct mountres3 {
mountstat3 fhs_status;
union {
mountres3_ok mountinfo;
} mountres3_u;
};
typedef struct mountres3 mountres3;
struct nfs_fh3 {
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 nfs_fh3;
#endif /* NFSMNT_NFSV3 */
#endif /* not _AMU_NFS_PROT_H */

View File

@ -0,0 +1,5 @@
/* $srcdir/conf/sa_dref/sa_dref_bsd44.h */
#define NFS_SA_DREF(dst, src) { \
(dst)->addr = (struct sockaddr *) (src); \
(dst)->addrlen = sizeof(*src); \
}

View File

@ -0,0 +1,399 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: transp_sockets.c,v 5.2.2.2 1992/07/18 18:57:03 jsp Exp jsp $
*
* Socket specific utilities.
* -Erez Zadok <ezk@cs.columbia.edu>
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amu.h>
/*
* find the IP address that can be used to connect to the local host
*/
void
amu_get_myaddress(struct in_addr *iap)
{
struct sockaddr_in sin;
memset((char *) &sin, 0, sizeof(sin));
get_myaddress(&sin);
iap->s_addr = sin.sin_addr.s_addr;
}
/*
* How to bind to reserved ports.
*/
int
bind_resv_port(int so, u_short *pp)
{
struct sockaddr_in sin;
int rc;
u_short port;
memset((voidp) &sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
port = IPPORT_RESERVED;
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;
}
/*
* close a descriptor, Sockets style
*/
int
amu_close(int fd)
{
return close(fd);
}
/*
* Create an rpc client attached to the mount daemon.
*/
CLIENT *
get_mount_client(char *unused_host, struct sockaddr_in *sin, struct timeval *tv, int *sock, u_long mnt_version)
{
CLIENT *client;
/*
* First try a TCP socket
*/
if ((*sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) > 0) {
/*
* Bind to a privileged port
*/
if (bind_resv_port(*sock, (u_short *) 0) < 0)
plog(XLOG_ERROR, "can't bind privileged port");
/*
* Find mountd port to connect to.
* Connect to mountd.
* Create a tcp client.
*/
if ((sin->sin_port = htons(pmap_getport(sin, MOUNTPROG, mnt_version, IPPROTO_TCP))) != 0) {
if (connect(*sock, (struct sockaddr *) sin, sizeof(*sin)) >= 0
&& ((client = clnttcp_create(sin, MOUNTPROG, mnt_version, sock, 0, 0)) != NULL))
return client;
}
/*
* Failed so close socket
*/
(void) close(*sock);
} /* tcp socket opened */
/* TCP failed so try UDP */
if ((*sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
plog(XLOG_ERROR, "Can't create socket to connect to mountd: %m");
*sock = RPC_ANYSOCK;
return NULL;
}
/*
* Bind to a privileged port
*/
if (bind_resv_port(*sock, (u_short *) 0) < 0)
plog(XLOG_ERROR, "can't bind privileged port");
/*
* Zero out the port - make sure we recompute
*/
sin->sin_port = 0;
/*
* Make a UDP client
*/
if ((client = clntudp_create(sin, MOUNTPROG, mnt_version, *tv, sock)) == NULL) {
(void) close(*sock);
*sock = RPC_ANYSOCK;
return NULL;
}
#ifdef DEBUG
dlog("get_mount_client: Using udp, port %d", sin->sin_port);
#endif /* DEBUG */
return client;
}
/*
* find the address of the caller of an RPC procedure.
*/
struct sockaddr_in *
amu_svc_getcaller(SVCXPRT *xprt)
{
return svc_getcaller(xprt);
}
/*
* Bind NFS to a reserved port.
*/
static int
bindnfs_port(int so, u_short *nfs_portp)
{
u_short port;
int error = bind_resv_port(so, &port);
if (error == 0)
*nfs_portp = port;
return error;
}
/*
* Create the nfs service for amd
*/
int
create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp))
{
*soNFSp = socket(AF_INET, SOCK_DGRAM, 0);
if (*soNFSp < 0 || bindnfs_port(*soNFSp, nfs_portp) < 0) {
plog(XLOG_FATAL, "Can't create privileged nfs port");
return 1;
}
if ((*nfs_xprtp = svcudp_create(*soNFSp)) == NULL) {
plog(XLOG_FATAL, "cannot create rpc/udp service");
return 2;
}
if (!svc_register(*nfs_xprtp, NFS_PROGRAM, NFS_VERSION, dispatch_fxn, 0)) {
plog(XLOG_FATAL, "unable to register (NFS_PROGRAM, NFS_VERSION, 0)");
return 3;
}
return 0; /* all is well */
}
/*
* 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)
{
/* first create TCP service */
if (tcp_soAMQp) {
*tcp_soAMQp = socket(AF_INET, SOCK_STREAM, 0);
if (*tcp_soAMQp < 0) {
plog(XLOG_FATAL, "cannot create tcp socket for amq service: %m");
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;
}
}
/* next create UDP service */
if (udp_soAMQp) {
*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;
}
/* 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 0; /* all is well */
}
/*
* Ping the portmapper on a remote system by calling the nullproc
*/
enum clnt_stat
pmap_ping(struct sockaddr_in *address)
{
CLIENT *client;
enum clnt_stat clnt_stat = RPC_TIMEDOUT; /* assume failure */
int socket = RPC_ANYSOCK;
struct timeval timeout;
timeout.tv_sec = 3;
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;
return clnt_stat;
}
/*
* Find the best NFS version for a host and protocol.
*/
u_long
get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto)
{
CLIENT *clnt;
int again = 0;
enum clnt_stat clnt_stat;
struct timeval tv;
int sock;
/*
* If not set or set wrong, then try from NFS_VERS_MAX on down. If
* set, then try from nfs_version on down.
*/
if (nfs_version <= 0 || nfs_version > NFS_VERS_MAX) {
nfs_version = NFS_VERS_MAX;
again = 1;
}
tv.tv_sec = 3; /* retry every 3 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;
if (STREQ(proto, "tcp"))
clnt = clnttcp_create(sin, NFS_PROGRAM, nfs_version, &sock, 0, 0);
else if (STREQ(proto, "udp"))
clnt = clntudp_create(sin, NFS_PROGRAM, nfs_version, tv, &sock);
else
clnt = NULL;
if (clnt == NULL) {
#ifdef HAVE_CLNT_SPCREATEERROR
plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s :%s",
nfs_version, proto, host, clnt_spcreateerror(""));
#else /* not HAVE_CLNT_SPCREATEERROR */
plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s",
nfs_version, proto, host);
#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 (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;
}
goto try_again;
#endif /* HAVE_FS_NFS3 */
}
plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s",
nfs_version, proto, host);
return 0;
}
plog(XLOG_INFO, "get_nfs_version: returning (%d,%s) on host %s",
nfs_version, proto, host);
return nfs_version;
}
/*
* AUTOFS FUNCTIONS FOR SOCKETS:
*/
#ifdef HAVE_FS_AUTOFS
/*
* Create the nfs service for amd
*/
int
create_autofs_service(int *soAUTOFSp, u_short *autofs_portp, SVCXPRT **autofs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp))
{
/* NOT IMPLEMENTED! */
return -1;
}
#endif /* HAVE_FS_AUTOFS */

View File

@ -0,0 +1,2 @@
/* $srcdir/conf/trap/trap_default.h */
#define MOUNT_TRAP(type, mnt, flags, mnt_data) mount(type, mnt->mnt_dir, flags, mnt_data)

View File

@ -0,0 +1,3 @@
/* $srcdir/conf/trap/trap_freebsd3.h */
extern int mount_freebsd3(MTYPE_TYPE type, const char *dir, int flags, voidp data);
#define MOUNT_TRAP(type, mnt, flags, mnt_data) mount_freebsd3(type, mnt->mnt_dir, flags, mnt_data)

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: umount_bsd44.c,v 5.2.2.2 1993/01/27 07:32:45 jsp Exp $
*
*/
/*
* Unmounting filesystems under BSD 4.4.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amu.h>
int
umount_fs(char *fs_name, const char *mnttabname)
{
int error;
eintr:
error = unmount(fs_name, 0);
if (error < 0)
error = errno;
switch (error) {
case EINVAL:
case ENOTBLK:
case ENOENT:
plog(XLOG_WARNING, "unmount: %s is not mounted", fs_name);
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 */
goto eintr;
#ifdef DEBUG
default:
dlog("%s: unmount: %m", fs_name);
break;
#endif /* DEBUG */
}
return error;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
@set UPDATED 22 April 1998
@set EDITION 6.0a16
@set VERSION 6.0a16

4935
contrib/amd/doc/texinfo.tex Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
@set UPDATED 22 April 1998
@set EDITION 6.0a16
@set VERSION 6.0a16

View File

@ -0,0 +1,159 @@
.\"
.\" Copyright (c) 1997-1998 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.
.\"
.\" %W% (Berkeley) %G%
.\"
.\" $Id: fixmount.8,v 5.2.2.1 1992/02/09 15:11:15 jsp beta $
.\"
.TH FIXMOUNT 8L "26 Feb 1993"
.SH NAME
fixmount \- fix remote mount entries
.SH SYNOPSIS
.B fixmount
[
.B \-adervq
]
[
.B \-h
.I name
]
.I host
\&...
.SH DESCRIPTION
.IX "fixmount command" "" "\fLfixmount\fP \(em fix remote mount entries"
.LP
.B fixmount
is a variant of
.BR showmount (8)
that can delete bogus mount entries in remote
.BR mountd (8C)
daemons.
The actions specified by the options are performed for each
.I host
in turn.
.SH OPTIONS
.TP
.B \-a \-d \-e
These options work as in
.BR showmount (8)
except that only entries pertaining to the local host are printed.
.TP
.B \-r
Removes those remote mount entries on
.I host
that do not correspond to current mounts, i.e., which are left-over
from a crash or are the result of improper mount protocol.
The actuality of mounts is verified using the entries in
.BR /etc/mtab .
.TP
.B \-v
Verify remote mounts. Similar to
.B \-r
except that only a notification message is printed for each bogus entry
found. The remote mount table is not changed.
.TP
.B \-A
Issues a command to the remote mountd declaring that ALL of its filesystems
have been unmounted. This should be used with caution, as it removes all
remote mount entries pertaining to the local system, whether or not any
filesystems are still mounted locally.
.TP
.B \-q
Be quiet.
Suppresses error messages due to timeouts and "Program not registered",
i.e., due to remote hosts not supporting RPC or not running mountd.
.TP
.BI \-h \ name
Pretend the local hostname is
.IR name .
This is useful after the local hostname has been changed and rmtab entries
using the old name remain on a remote machine.
Unfortunately, most mountd's won't be able to successfully handle removal
of such entries, so this option is useful in combination with
.B \-v
only.
.br
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).
.SH BUGS
No attempt is made to verify the information in
.B /etc/mtab
itself.
.PP
Since swap file mounts are not recorded in
.BR /etc/mtab ,
a heuristic specific to SunOS is used to determine whether such a mount
is actual (replacing the string "swap" with "root" and verifying the resulting
path).
.PP
Symbolic links on the server will cause the path in the remote entry to differ
from the one in
.BR /etc/mtab .
To catch those cases, a filesystem is also deemed mounted if its
.I local
mount point is identical to the remote entry.
I.e., on a SunOS diskless client,
.B server:/export/share/sunos.4.1.1
is actually
.BR /usr/share .
Since the local mount point is
.B /usr/share
as well this will be handled correctly.
.PP
There is no way to clear a stale entry in a remote mountd after the
local hostname (or whatever reverse name resolution returns for it)
has been changed. To take care of these cases,
the remote /etc/rmtab file has to be edited and mountd restarted.
.PP
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.

View File

@ -0,0 +1,612 @@
/*
* Copyright (c) 1997-1998 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: fixmount.c,v 5.2.2.2 1992/05/31 16:35:45 jsp Exp $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#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
#define DODUMP 0x1
#define DOEXPORTS 0x2
#define DOREMOVE 0x4
#define DOVERIFY 0x8
#define DOREMALL 0x10
extern int fixmount_check_mount(char *host, struct in_addr hostaddr, char *path);
static char dir_path[NFS_MAXPATHLEN];
static char localhost[] = "localhost";
static char thishost[MAXHOSTNAMELEN] = "";
static exports mntexports;
static int quiet = 0;
static int type = 0;
static jmp_buf before_rpc;
static mountlist mntdump;
static struct in_addr thisaddr;
static CLIENT *clnt_create_timeout(char *, struct timeval *);
RETSIGTYPE create_timeout(int);
int is_same_host(char *, char *, struct in_addr);
int main(int, char *[]);
int remove_all(CLIENT *, char *);
int remove_mount(CLIENT *, char *, mountlist, int);
void fix_rmtab(CLIENT *, char *, mountlist, int, int);
void print_dump(mountlist);
void usage(void);
/* dummy variables */
char *progname;
char hostname[MAXHOSTNAMELEN];
int orig_umask, foreground, debug_flags;
pid_t mypid;
serv_state amd_state;
void
usage(void)
{
fprintf(stderr, "usage: fixmount [-adervAqf] [-h hostname] host ...\n");
exit(1);
}
/*
* Check hostname against other name and its IP address
*/
int
is_same_host(char *name1, char *name2, struct in_addr addr2)
{
if (strcasecmp(name1, name2) == 0) {
return 1;
} else if (addr2.s_addr == INADDR_NONE) {
return 0;
} else {
static char lasthost[MAXHOSTNAMELEN] = "";
static struct in_addr addr1;
struct hostent *he;
/*
* To save nameserver lookups, and because this function
* is typically called repeatedly on the same names,
* cache the last lookup result and reuse it if possible.
*/
if (strcasecmp(name1, lasthost) == 0) {
return (addr1.s_addr == addr2.s_addr);
} else if (!(he = gethostbyname(name1))) {
return 0;
} else {
strncpy(lasthost, name1, sizeof(lasthost) - 1);
memcpy(&addr1, he->h_addr, sizeof(addr1));
return (addr1.s_addr == addr2.s_addr);
}
}
}
/*
* Print the binary tree in inorder so that output is sorted.
*/
void
print_dump(mountlist mp)
{
if (mp == NULL)
return;
if (is_same_host(mp->ml_hostname, thishost, thisaddr)) {
switch (type) {
case ALL:
printf("%s:%s\n", mp->ml_hostname, mp->ml_directory);
break;
case DIRS:
printf("%s\n", mp->ml_directory);
break;
default:
printf("%s\n", mp->ml_hostname);
break;
};
}
if (mp->ml_next)
print_dump(mp->ml_next);
}
/*
* remove entry from remote rmtab
*/
int
remove_mount(CLIENT *client, char *host, mountlist ml, int fixit)
{
enum clnt_stat estat;
struct timeval tv;
char *pathp = dir_path;
strncpy(dir_path, ml->ml_directory, sizeof(dir_path));
if (!fixit) {
printf("%s: bogus mount %s:%s\n", host, ml->ml_hostname, ml->ml_directory);
fflush(stdout);
} else {
printf("%s: removing %s:%s\n", host, ml->ml_hostname, ml->ml_directory);
fflush(stdout);
tv.tv_sec = CALL_TIMEOUT;
tv.tv_usec = 0;
if ((estat = clnt_call(client,
MOUNTPROC_UMNT,
(XDRPROC_T_TYPE) xdr_dirpath,
(char *) &pathp,
(XDRPROC_T_TYPE) xdr_void,
(char *) 0,
tv)) != RPC_SUCCESS) {
fprintf(stderr, "%s:%s MOUNTPROC_UMNT: ",
host, ml->ml_directory);
clnt_perrno(estat);
fflush(stderr);
return -1;
}
}
return 0;
}
/*
* fix mount list on remote host
*/
void
fix_rmtab(CLIENT *client, char *host, mountlist mp, int fixit, int force)
{
mountlist p;
struct hostent *he;
struct in_addr hostaddr;
/*
* Obtain remote address for comparisons
*/
if ((he = gethostbyname(host))) {
memcpy(&hostaddr, he->h_addr, sizeof(hostaddr));
} else {
hostaddr.s_addr = INADDR_NONE;
}
for (p = mp; p; p = p->ml_next) {
if (is_same_host(p->ml_hostname, thishost, thisaddr)) {
if (force || !fixmount_check_mount(host, hostaddr, p->ml_directory))
remove_mount(client, host, p, fixit);
}
}
}
/*
* remove all entries from remote rmtab
*/
int
remove_all(CLIENT *client, char *host)
{
enum clnt_stat estat;
struct timeval tv;
printf("%s: removing ALL\n", host);
fflush(stdout);
tv.tv_sec = CALL_TIMEOUT;
tv.tv_usec = 0;
if ((estat = clnt_call(client,
MOUNTPROC_UMNTALL,
(XDRPROC_T_TYPE) xdr_void,
(char *) 0,
(XDRPROC_T_TYPE) xdr_void,
(char *) 0,
tv)) != RPC_SUCCESS) {
/*
* RPC_SYSTEMERROR is returned even if all went well
*/
if (estat != RPC_SYSTEMERROR) {
fprintf(stderr, "%s MOUNTPROC_UMNTALL: ", host);
clnt_perrno(estat);
fflush(stderr);
return -1;
}
}
return 0;
}
/*
* This command queries the NFS mount daemon for it's mount list and/or
* it's exports list and prints them out.
* See "NFS: Network File System Protocol Specification, RFC1094, Appendix A"
* for detailed information on the protocol.
*/
int
main(int argc, char *argv[])
{
AUTH *auth;
CLIENT *client;
char *host;
enum clnt_stat estat;
exports exp;
extern char *optarg;
extern int optind;
groups grp;
int ch;
int force = 0;
int morethanone;
register int rpcs = 0;
struct timeval tv;
while ((ch = getopt(argc, argv, "adervAqfh:")) != EOF)
switch ((char) ch) {
case 'a':
if (type == 0) {
type = ALL;
rpcs |= DODUMP;
} else
usage();
break;
case 'd':
if (type == 0) {
type = DIRS;
rpcs |= DODUMP;
} else
usage();
break;
case 'e':
rpcs |= DOEXPORTS;
break;
case 'r':
rpcs |= DOREMOVE;
break;
case 'A':
rpcs |= DOREMALL;
break;
case 'v':
rpcs |= DOVERIFY;
break;
case 'q':
quiet = 1;
break;
case 'f':
force = 1;
break;
case 'h':
strncpy(thishost, optarg, sizeof(thishost));
thishost[sizeof(thishost) - 1] = '\0';
break;
case '?':
default:
usage();
}
if (optind == argc)
usage();
if (rpcs == 0)
rpcs = DODUMP;
if (!*thishost) {
struct hostent *he;
if (gethostname(thishost, sizeof(thishost)) < 0) {
perror("gethostname");
exit(1);
}
/*
* We need the hostname as it appears to the other side's
* mountd, so get our own hostname by reverse address
* resolution.
*/
if (!(he = gethostbyname(thishost))) {
fprintf(stderr, "gethostbyname failed on %s\n",
thishost);
exit(1);
}
memcpy(&thisaddr, he->h_addr, sizeof(thisaddr));
if (!(he = gethostbyaddr((char *) &thisaddr, sizeof(thisaddr),
he->h_addrtype))) {
fprintf(stderr, "gethostbyaddr failed on %s\n",
inet_ntoa(thisaddr));
exit(1);
}
strncpy(thishost, he->h_name, sizeof(thishost));
thishost[sizeof(thishost) - 1] = '\0';
} else {
thisaddr.s_addr = INADDR_NONE;
}
if (!(auth = authunix_create_default())) {
fprintf(stderr, "couldn't create authentication handle\n");
exit(1);
}
morethanone = (optind + 1 < argc);
for (; optind < argc; optind++) {
host = argv[optind];
tv.tv_sec = CREATE_TIMEOUT;
tv.tv_usec = 0;
if (!(client = clnt_create_timeout(host, &tv)))
continue;
client->cl_auth = auth;
tv.tv_sec = CALL_TIMEOUT;
tv.tv_usec = 0;
if (rpcs & (DODUMP | DOREMOVE | DOVERIFY))
if ((estat = clnt_call(client,
MOUNTPROC_DUMP,
(XDRPROC_T_TYPE) xdr_void,
(char *) 0,
(XDRPROC_T_TYPE) xdr_mountlist,
(char *) &mntdump,
tv)) != RPC_SUCCESS) {
fprintf(stderr, "%s: MOUNTPROC_DUMP: ", host);
clnt_perrno(estat);
fflush(stderr);
mntdump = NULL;
goto next;
}
if (rpcs & DOEXPORTS)
if ((estat = clnt_call(client,
MOUNTPROC_EXPORT,
(XDRPROC_T_TYPE) xdr_void,
(char *) 0,
(XDRPROC_T_TYPE) xdr_exports,
(char *) &mntexports,
tv)) != RPC_SUCCESS) {
fprintf(stderr, "%s: MOUNTPROC_EXPORT: ", host);
clnt_perrno(estat);
fflush(stderr);
mntexports = NULL;
goto next;
}
/* Now just print out the results */
if ((rpcs & (DODUMP | DOEXPORTS)) &&
morethanone) {
printf(">>> %s <<<\n", host);
fflush(stdout);
}
if (rpcs & DODUMP) {
print_dump(mntdump);
}
if (rpcs & DOEXPORTS) {
exp = mntexports;
while (exp) {
printf("%-35s", exp->ex_dir);
grp = exp->ex_groups;
if (grp == NULL) {
printf("Everyone\n");
} else {
while (grp) {
printf("%s ", grp->gr_name);
grp = grp->gr_next;
}
printf("\n");
}
exp = exp->ex_next;
}
}
if (rpcs & DOVERIFY)
fix_rmtab(client, host, mntdump, 0, force);
if (rpcs & DOREMOVE)
fix_rmtab(client, host, mntdump, 1, force);
if (rpcs & DOREMALL)
remove_all(client, host);
next:
if (mntdump)
(void) clnt_freeres(client,
(XDRPROC_T_TYPE) xdr_mountlist,
(char *) &mntdump);
if (mntexports)
(void) clnt_freeres(client,
(XDRPROC_T_TYPE) xdr_exports,
(char *) &mntexports);
clnt_destroy(client);
}
exit(0);
return 0; /* should never reach here */
}
RETSIGTYPE
create_timeout(int sig)
{
signal(SIGALRM, SIG_DFL);
longjmp(before_rpc, 1);
}
#ifndef HAVE_TRANSPORT_TYPE_TLI
/*
* inetresport creates a datagram socket and attempts to bind it to a
* secure port.
* returns: The bound socket, or -1 to indicate an error.
*/
static int
inetresport(int ty)
{
int alport;
struct sockaddr_in addr;
int fd;
/* Use internet address family */
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
if ((fd = socket(AF_INET, ty, 0)) < 0)
return -1;
for (alport = IPPORT_RESERVED - 1; alport > IPPORT_RESERVED / 2 + 1; alport--) {
addr.sin_port = htons((u_short) alport);
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) >= 0)
return fd;
if (errno != EADDRINUSE) {
close(fd);
return -1;
}
}
close(fd);
errno = EAGAIN;
return -1;
}
/*
* Privsock() calls inetresport() to attempt to bind a socket to a secure
* port. If inetresport() fails, privsock returns a magic socket number which
* indicates to RPC that it should make its own socket.
* returns: A privileged socket # or RPC_ANYSOCK.
*/
static int
privsock(int ty)
{
int sock = inetresport(ty);
if (sock < 0) {
errno = 0;
/* Couldn't get a secure port, let RPC make an insecure one */
sock = RPC_ANYSOCK;
}
return sock;
}
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
static CLIENT *
clnt_create_timeout(char *host, struct timeval *tvp)
{
CLIENT *clnt;
struct sockaddr_in host_addr;
struct hostent *hp;
#ifndef HAVE_TRANSPORT_TYPE_TLI
int s;
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
if (setjmp(before_rpc)) {
if (!quiet) {
fprintf(stderr, "%s: ", host);
clnt_perrno(RPC_TIMEDOUT);
fprintf(stderr, "\n");
fflush(stderr);
}
return NULL;
}
signal(SIGALRM, create_timeout);
ualarm(tvp->tv_sec * 1000000 + tvp->tv_usec, 0);
/*
* Get address of host
*/
if ((hp = gethostbyname(host)) == 0 && !STREQ(host, localhost)) {
fprintf(stderr, "can't get address of %s\n", host);
return NULL;
}
memset(&host_addr, 0, sizeof host_addr);
host_addr.sin_family = AF_INET;
if (hp) {
memmove((voidp) &host_addr.sin_addr, (voidp) hp->h_addr,
sizeof(host_addr.sin_addr));
} else {
/* fake "localhost" */
host_addr.sin_addr.s_addr = htonl(0x7f000001);
}
#ifdef HAVE_TRANSPORT_TYPE_TLI
/* try TCP first (in case return data is large), then UDP */
clnt = clnt_create(host, MOUNTPROG, MOUNTVERS, "tcp");
if (!clnt)
clnt = clnt_create(host, MOUNTPROG, MOUNTVERS, "udp");
#else /* not HAVE_TRANSPORT_TYPE_TLI */
s = RPC_ANYSOCK;
clnt = clnttcp_create(&host_addr, MOUNTPROG, MOUNTVERS, &s, 0, 0);
if (!clnt) {
/* XXX: do we need to close(s) ? */
s = privsock(SOCK_DGRAM);
clnt = clntudp_create(&host_addr, MOUNTPROG, MOUNTVERS, *tvp, &s);
}
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
if (!clnt) {
ualarm(0, 0);
if (!quiet) {
clnt_pcreateerror(host);
fflush(stderr);
}
return NULL;
}
ualarm(0, 0);
return clnt;
}

View File

@ -0,0 +1,670 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: fsi_analyze.c,v 5.2.2.1 1992/02/09 15:09:41 jsp beta $
*
*/
/*
* Analyze filesystem declarations
*
* Note: most of this is magic!
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <fsi_data.h>
#include <fsinfo.h>
char *disk_fs_strings[] =
{
"fstype", "opts", "dumpset", "passno", "freq", "mount", "log", 0,
};
char *mount_strings[] =
{
"volname", "exportfs", 0,
};
char *fsmount_strings[] =
{
"as", "volname", "fstype", "opts", "from", 0,
};
char *host_strings[] =
{
"host", "netif", "config", "arch", "cluster", "os", 0,
};
char *ether_if_strings[] =
{
"inaddr", "netmask", "hwaddr", 0,
};
/*
* Strip off the trailing part of a domain
* to produce a short-form domain relative
* to the local host domain.
* Note that this has no effect if the domain
* names do not have the same number of
* components. If that restriction proves
* to be a problem then the loop needs recoding
* to skip from right to left and do partial
* matches along the way -- ie more expensive.
*/
void
domain_strip(char *otherdom, char *localdom)
{
char *p1, *p2;
if ((p1 = strchr(otherdom, '.')) &&
(p2 = strchr(localdom, '.')) &&
STREQ(p1 + 1, p2 + 1))
*p1 = '\0';
}
/*
* Take a little-endian domain name and
* transform into a big-endian Un*x pathname.
* For example: kiska.doc.ic -> ic/doc/kiska
*/
static char *
compute_hostpath(char *hn)
{
char *p = strdup(hn);
char *d;
char path[MAXPATHLEN];
domain_strip(p, hostname);
path[0] = '\0';
do {
d = strrchr(p, '.');
if (d) {
*d = 0;
strcat(path, d + 1);
strcat(path, "/");
} else {
strcat(path, p);
}
} while (d);
log("hostpath of '%s' is '%s'", hn, path);
strcpy(p, path);
return p;
}
static dict_ent *
find_volname(char *nn)
{
dict_ent *de;
char *p = strdup(nn);
char *q;
do {
log("Searching for volname %s", p);
de = dict_locate(dict_of_volnames, p);
q = strrchr(p, '/');
if (q)
*q = '\0';
} while (!de && q);
XFREE(p);
return de;
}
static void
show_required(ioloc *l, int mask, char *info, char *hostname, char *strings[])
{
int i;
log("mask left for %s:%s is %#x", hostname, info, mask);
for (i = 0; strings[i]; i++)
if (ISSET(mask, i))
lerror(l, "%s:%s needs field \"%s\"", hostname, info, strings[i]);
}
/*
* Check and fill in "exportfs" details.
* Make sure the m_exported field references
* the most local node with an "exportfs" entry.
*/
static int
check_exportfs(qelem *q, fsi_mount *e)
{
fsi_mount *mp;
int errors = 0;
ITER(mp, fsi_mount, q) {
if (ISSET(mp->m_mask, DM_EXPORTFS)) {
if (e)
lwarning(mp->m_ioloc, "%s has duplicate exportfs data", mp->m_name);
mp->m_exported = mp;
if (!ISSET(mp->m_mask, DM_VOLNAME))
set_mount(mp, DM_VOLNAME, strdup(mp->m_name));
} else {
mp->m_exported = e;
}
/*
* Recursively descend the mount tree
*/
if (mp->m_mount)
errors += check_exportfs(mp->m_mount, mp->m_exported);
/*
* If a volume name has been specified, but this node and none
* of its parents has been exported, report an error.
*/
if (ISSET(mp->m_mask, DM_VOLNAME) && !mp->m_exported) {
lerror(mp->m_ioloc, "%s has a volname but no exportfs data", mp->m_name);
errors++;
}
}
return errors;
}
static int
analyze_dkmount_tree(qelem *q, fsi_mount *parent, disk_fs *dk)
{
fsi_mount *mp;
int errors = 0;
ITER(mp, fsi_mount, q) {
log("Mount %s:", mp->m_name);
if (parent) {
char n[MAXPATHLEN];
sprintf(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"))
lwarning(mp->m_ioloc, "sub-directory of %s is named \"default\"", parent->m_name);
log("Changing name %s to %s", mp->m_name, n);
XFREE(mp->m_name);
mp->m_name = strdup(n);
}
mp->m_name_len = strlen(mp->m_name);
mp->m_parent = parent;
mp->m_dk = dk;
if (mp->m_mount)
analyze_dkmount_tree(mp->m_mount, mp, dk);
}
return errors;
}
/*
* The mount tree is a singleton list
* containing the top-level mount
* point for a disk.
*/
static int
analyze_dkmounts(disk_fs *dk, qelem *q)
{
int errors = 0;
fsi_mount *mp, *mp2 = 0;
int i = 0;
/*
* First scan the list of subdirs to make
* sure there is only one - and remember it
*/
if (q) {
ITER(mp, fsi_mount, q) {
mp2 = mp;
i++;
}
}
/*
* Check...
*/
if (i < 1) {
lerror(dk->d_ioloc, "%s:%s has no mount point", dk->d_host->h_hostname, dk->d_dev);
return 1;
}
if (i > 1) {
lerror(dk->d_ioloc, "%s:%s has more than one mount point", dk->d_host->h_hostname, dk->d_dev);
errors++;
}
/*
* Now see if a default mount point is required
*/
if (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);
XFREE(mp2->m_name);
mp2->m_name = strdup(nbuf);
log("%s:%s has default mount on %s", dk->d_host->h_hostname, dk->d_dev, mp2->m_name);
} else {
lerror(dk->d_ioloc, "no volname given for %s:%s", dk->d_host->h_hostname, dk->d_dev);
errors++;
}
}
/*
* Fill in the disk mount point
*/
if (!errors && mp2 && mp2->m_name)
dk->d_mountpt = strdup(mp2->m_name);
else
dk->d_mountpt = strdup("error");
/*
* Analyze the mount tree
*/
errors += analyze_dkmount_tree(q, 0, dk);
/*
* Analyze the export tree
*/
errors += check_exportfs(q, 0);
return errors;
}
static void
fixup_required_disk_info(disk_fs *dp)
{
/*
* "fstype"
*/
if (ISSET(dp->d_mask, DF_FSTYPE)) {
if (STREQ(dp->d_fstype, "swap")) {
/*
* Fixup for a swap device
*/
if (!ISSET(dp->d_mask, DF_PASSNO)) {
dp->d_passno = 0;
BITSET(dp->d_mask, DF_PASSNO);
} else if (dp->d_freq != 0) {
lwarning(dp->d_ioloc,
"Pass number for %s:%s is non-zero",
dp->d_host->h_hostname, dp->d_dev);
}
/*
* "freq"
*/
if (!ISSET(dp->d_mask, DF_FREQ)) {
dp->d_freq = 0;
BITSET(dp->d_mask, DF_FREQ);
} else if (dp->d_freq != 0) {
lwarning(dp->d_ioloc,
"dump frequency for %s:%s is non-zero",
dp->d_host->h_hostname, dp->d_dev);
}
/*
* "opts"
*/
if (!ISSET(dp->d_mask, DF_OPTS))
set_disk_fs(dp, DF_OPTS, strdup("swap"));
/*
* "mount"
*/
if (!ISSET(dp->d_mask, DF_MOUNT)) {
qelem *q = new_que();
fsi_mount *m = new_mount();
m->m_name = strdup("swap");
m->m_mount = new_que();
ins_que(&m->m_q, q->q_back);
dp->d_mount = q;
BITSET(dp->d_mask, DF_MOUNT);
} else {
lerror(dp->d_ioloc, "%s: mount field specified for swap partition", dp->d_host->h_hostname);
}
} else if (STREQ(dp->d_fstype, "export")) {
/*
* "passno"
*/
if (!ISSET(dp->d_mask, DF_PASSNO)) {
dp->d_passno = 0;
BITSET(dp->d_mask, DF_PASSNO);
} else if (dp->d_passno != 0) {
lwarning(dp->d_ioloc,
"pass number for %s:%s is non-zero",
dp->d_host->h_hostname, dp->d_dev);
}
/*
* "freq"
*/
if (!ISSET(dp->d_mask, DF_FREQ)) {
dp->d_freq = 0;
BITSET(dp->d_mask, DF_FREQ);
} else if (dp->d_freq != 0) {
lwarning(dp->d_ioloc,
"dump frequency for %s:%s is non-zero",
dp->d_host->h_hostname, dp->d_dev);
}
/*
* "opts"
*/
if (!ISSET(dp->d_mask, DF_OPTS))
set_disk_fs(dp, DF_OPTS, strdup("rw,defaults"));
}
}
}
static void
fixup_required_mount_info(fsmount *fp, dict_ent *de)
{
if (!ISSET(fp->f_mask, FM_FROM)) {
if (de->de_count != 1) {
lerror(fp->f_ioloc, "ambiguous mount: %s is a replicated filesystem", fp->f_volname);
} else {
dict_data *dd;
fsi_mount *mp = 0;
dd = AM_FIRST(dict_data, &de->de_q);
mp = (fsi_mount *) dd->dd_data;
if (!mp)
abort();
fp->f_ref = mp;
set_fsmount(fp, FM_FROM, mp->m_dk->d_host->h_hostname);
log("set: %s comes from %s", fp->f_volname, fp->f_from);
}
}
if (!ISSET(fp->f_mask, FM_FSTYPE)) {
set_fsmount(fp, FM_FSTYPE, strdup("nfs"));
log("set: fstype is %s", fp->f_fstype);
}
if (!ISSET(fp->f_mask, FM_OPTS)) {
set_fsmount(fp, FM_OPTS, strdup("rw,nosuid,grpid,defaults"));
log("set: opts are %s", fp->f_opts);
}
if (!ISSET(fp->f_mask, FM_LOCALNAME)) {
if (fp->f_ref) {
set_fsmount(fp, FM_LOCALNAME, strdup(fp->f_volname));
log("set: localname is %s", fp->f_localname);
} else {
lerror(fp->f_ioloc, "cannot determine localname since volname %s is not uniquely defined", fp->f_volname);
}
}
}
/*
* For each disk on a host
* analyze the mount information
* and fill in any derivable
* details.
*/
static void
analyze_drives(host *hp)
{
qelem *q = hp->h_disk_fs;
disk_fs *dp;
ITER(dp, disk_fs, q) {
int req;
log("Disk %s:", dp->d_dev);
dp->d_host = hp;
fixup_required_disk_info(dp);
req = ~dp->d_mask & DF_REQUIRED;
if (req)
show_required(dp->d_ioloc, req, dp->d_dev, hp->h_hostname, disk_fs_strings);
analyze_dkmounts(dp, dp->d_mount);
}
}
/*
* Check that all static mounts make sense and
* that the source volumes exist.
*/
static void
analyze_mounts(host *hp)
{
qelem *q = hp->h_mount;
fsmount *fp;
int netbootp = 0;
ITER(fp, fsmount, q) {
char *p;
char *nn = strdup(fp->f_volname);
int req;
dict_ent *de = (dict_ent *) NULL;
int found = 0;
int matched = 0;
if (ISSET(fp->f_mask, FM_DIRECT)) {
found = 1;
matched = 1;
} else
do {
p = 0;
de = find_volname(nn);
log("Mount: %s (trying %s)", fp->f_volname, nn);
if (de) {
found = 1;
/*
* Check that the from field is really exporting
* the filesystem requested.
* LBL: If fake mount, then don't care about
* consistency check.
*/
if (ISSET(fp->f_mask, FM_FROM) && !ISSET(fp->f_mask, FM_DIRECT)) {
dict_data *dd;
fsi_mount *mp2 = 0;
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)) {
mp2 = mp;
break;
}
}
if (mp2) {
fp->f_ref = mp2;
matched = 1;
break;
}
} else {
matched = 1;
break;
}
}
p = strrchr(nn, '/');
if (p)
*p = 0;
} while (de && p);
XFREE(nn);
if (!found) {
lerror(fp->f_ioloc, "volname %s unknown", fp->f_volname);
} else if (matched) {
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,
fsmount_strings);
} else if (STREQ(fp->f_localname, "/")) {
hp->h_netroot = fp;
netbootp |= FM_NETROOT;
} else if (STREQ(fp->f_localname, "swap")) {
hp->h_netswap = fp;
netbootp |= FM_NETSWAP;
}
} else {
lerror(fp->f_ioloc, "volname %s not exported from %s", fp->f_volname,
fp->f_from ? fp->f_from : "anywhere");
}
}
if (netbootp && (netbootp != FM_NETBOOT))
lerror(hp->h_ioloc, "network booting requires both root and swap areas");
}
void
analyze_hosts(qelem *q)
{
host *hp;
show_area_being_processed("analyze hosts", 5);
/*
* Check all drives
*/
ITER(hp, host, q) {
log("disks on host %s", hp->h_hostname);
show_new("ana-host");
hp->h_hostpath = compute_hostpath(hp->h_hostname);
if (hp->h_disk_fs)
analyze_drives(hp);
}
show_area_being_processed("analyze mounts", 5);
/*
* Check static mounts
*/
ITER(hp, host, q) {
log("mounts on host %s", hp->h_hostname);
show_new("ana-mount");
if (hp->h_mount)
analyze_mounts(hp);
}
}
/*
* Check an automount request
*/
static void
analyze_automount(automount *ap)
{
dict_ent *de = find_volname(ap->a_volname);
if (de) {
ap->a_mounted = de;
} else {
if (STREQ(ap->a_volname, ap->a_name))
lerror(ap->a_ioloc, "unknown volname %s automounted", ap->a_volname);
else
lerror(ap->a_ioloc, "unknown volname %s automounted on %s", ap->a_volname, ap->a_name);
}
}
static void
analyze_automount_tree(qelem *q, char *pref, int lvl)
{
automount *ap;
ITER(ap, automount, q) {
char nname[1024];
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);
XFREE(ap->a_name);
ap->a_name = strdup(nname[1] == '/' ? nname + 1 : nname);
log("automount point %s:", ap->a_name);
show_new("ana-automount");
if (ap->a_mount) {
analyze_automount_tree(ap->a_mount, ap->a_name, lvl + 1);
} else if (ap->a_hardwiredfs) {
log("\thardwired from %s to %s", ap->a_volname, ap->a_hardwiredfs);
} else if (ap->a_volname) {
log("\tautomount from %s", ap->a_volname);
analyze_automount(ap);
} else if (ap->a_symlink) {
log("\tsymlink to %s", ap->a_symlink);
} else {
ap->a_volname = strdup(ap->a_name);
log("\timplicit automount from %s", ap->a_volname);
analyze_automount(ap);
}
}
}
void
analyze_automounts(qelem *q)
{
auto_tree *tp;
show_area_being_processed("analyze automount", 5);
/*
* q is a list of automounts
*/
ITER(tp, auto_tree, q)
analyze_automount_tree(tp->t_mount, "", 0);
}

View File

@ -0,0 +1,236 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: fsi_data.h,v 5.2.2.1 1992/02/09 15:09:53 jsp beta $
*
*/
typedef struct auto_tree auto_tree;
typedef struct automount automount;
typedef struct dict dict;
typedef struct dict_data dict_data;
typedef struct dict_ent dict_ent;
typedef struct disk_fs disk_fs;
typedef struct ether_if ether_if;
typedef struct fsmount fsmount;
typedef struct host host;
typedef struct ioloc ioloc;
typedef struct fsi_mount fsi_mount;
/*
* Automount tree
*/
struct automount {
qelem a_q;
ioloc *a_ioloc;
char *a_name; /* Automount key */
char *a_volname; /* Equivalent volume to be referenced */
char *a_symlink; /* Symlink representation */
char *a_opts; /* opts for mounting */
char *a_hardwiredfs; /* hack to bypass bogus fs definitions */
qelem *a_mount; /* Tree representation */
dict_ent *a_mounted;
};
/*
* List of automount trees
*/
struct auto_tree {
qelem t_q;
ioloc *t_ioloc;
char *t_defaults;
qelem *t_mount;
};
/*
* A host
*/
struct host {
qelem q;
int h_mask;
ioloc *h_ioloc;
fsmount *h_netroot, *h_netswap;
#define HF_HOST 0
char *h_hostname; /* The full name of the host */
char *h_lochost; /* The name of the host with local domains *
* * * stripped */
char *h_hostpath; /* The filesystem path to the host (cf * * *
* compute_hostpath) */
#define HF_ETHER 1
qelem *h_ether;
#define HF_CONFIG 2
qelem *h_config;
#define HF_ARCH 3
char *h_arch;
#define HF_CLUSTER 4
char *h_cluster;
#define HF_OS 5
char *h_os;
qelem *h_disk_fs;
qelem *h_mount;
};
/*
* An ethernet interface
*/
struct ether_if {
qelem e_q;
int e_mask;
ioloc *e_ioloc;
char *e_if;
#define EF_INADDR 0
struct in_addr e_inaddr;
#define EF_NETMASK 1
u_long e_netmask;
#define EF_HWADDR 2
char *e_hwaddr;
};
/*
* Disk filesystem structure.
*
* If the DF_* numbers are changed
* disk_fs_strings in analyze.c will
* need updating.
*/
struct disk_fs {
qelem d_q;
int d_mask;
ioloc *d_ioloc;
host *d_host;
char *d_mountpt;
char *d_dev;
#define DF_FSTYPE 0
char *d_fstype;
#define DF_OPTS 1
char *d_opts;
#define DF_DUMPSET 2
char *d_dumpset;
#define DF_PASSNO 3
int d_passno;
#define DF_FREQ 4
int d_freq;
#define DF_MOUNT 5
qelem *d_mount;
#define DF_LOG 6
char *d_log;
};
#define DF_REQUIRED ((1<<DF_FSTYPE)|(1<<DF_OPTS)|(1<<DF_PASSNO)|(1<<DF_MOUNT))
/*
* A mount tree
*/
struct fsi_mount {
qelem m_q;
ioloc *m_ioloc;
int m_mask;
#define DM_VOLNAME 0
char *m_volname;
#define DM_EXPORTFS 1
char *m_exportfs;
#define DM_SEL 2
char *m_sel;
char *m_name;
int m_name_len;
fsi_mount *m_parent;
disk_fs *m_dk;
fsi_mount *m_exported;
qelem *m_mount;
};
/*
* Additional filesystem mounts
*
* If the FM_* numbers are changed
* disk_fs_strings in analyze.c will
* need updating.
*/
struct fsmount {
qelem f_q;
fsi_mount *f_ref;
ioloc *f_ioloc;
int f_mask;
#define FM_LOCALNAME 0
char *f_localname;
#define FM_VOLNAME 1
char *f_volname;
#define FM_FSTYPE 2
char *f_fstype;
#define FM_OPTS 3
char *f_opts;
#define FM_FROM 4
char *f_from;
#define FM_DIRECT 5
};
#define FM_REQUIRED ((1<<FM_VOLNAME)|(1<<FM_FSTYPE)|(1<<FM_OPTS)|(1<<FM_FROM)|(1<<FM_LOCALNAME))
#define FM_NETROOT 0x01
#define FM_NETSWAP 0x02
#define FM_NETBOOT (FM_NETROOT|FM_NETSWAP)
#define DICTHASH 5
struct dict_ent {
dict_ent *de_next;
char *de_key;
int de_count;
qelem de_q;
};
/*
* Dictionaries ...
*/
struct dict_data {
qelem dd_q;
char *dd_data;
};
struct dict {
dict_ent *de[DICTHASH];
};
/*
* Source text location for error reports
*/
struct ioloc {
int i_line;
char *i_file;
};

View File

@ -0,0 +1,138 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: fsi_dict.c,v 5.2.2.1 1992/02/09 15:09:43 jsp beta $
*
*/
/*
* Dictionary support
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <fsi_data.h>
#include <fsinfo.h>
static int
dict_hash(char *k)
{
u_int h;
for (h = 0; *k; h += *k++) ;
return h % DICTHASH;
}
dict *
new_dict(void)
{
dict *dp = CALLOC(struct dict);
return dp;
}
static void
dict_add_data(dict_ent *de, char *v)
{
dict_data *dd = CALLOC(struct dict_data);
dd->dd_data = v;
ins_que(&dd->dd_q, de->de_q.q_back);
de->de_count++;
}
static dict_ent *
new_dict_ent(char *k)
{
dict_ent *de = CALLOC(struct dict_ent);
de->de_key = k;
init_que(&de->de_q);
return de;
}
dict_ent *
dict_locate(dict *dp, char *k)
{
dict_ent *de = dp->de[dict_hash(k)];
while (de && !STREQ(de->de_key, k))
de = de->de_next;
return de;
}
void
dict_add(dict *dp, char *k, char *v)
{
dict_ent *de = dict_locate(dp, k);
if (!de) {
dict_ent **dep = &dp->de[dict_hash(k)];
de = new_dict_ent(k);
de->de_next = *dep;
*dep = de;
}
dict_add_data(de, v);
}
int
dict_iter(dict *dp, int (*fn) (qelem *))
{
int i;
int errors = 0;
for (i = 0; i < DICTHASH; i++) {
dict_ent *de = dp->de[i];
while (de) {
errors += (*fn) (&de->de_q);
de = de->de_next;
}
}
return errors;
}

View File

@ -0,0 +1,419 @@
/*
* Copyright (c) 1997-1998 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.
* 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 acknowledgement:
* 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.
*
* %W% (Berkeley) %G%
*
* $Id: fsi_gram.y,v 5.2.2.1 1992/02/09 15:09:35 jsp beta $
*
*/
%{
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <fsi_data.h>
#include <fsinfo.h>
extern qelem *list_of_hosts, *list_of_automounts;
%}
%union {
auto_tree *a;
disk_fs *d;
ether_if *e;
host *h;
qelem *q;
char *s;
fsi_mount *m;
fsmount *f;
}
%token tARCH
%token tAS
%token tAUTOMOUNT
%token tCLUSTER
%token tCONFIG
%token tDUMPSET
%token tEQ
%token tNFSEQ
%token tEXPORTFS
%token tFREQ
%token tFROM
%token tFS
%token tFSTYPE
%token tHWADDR
%token tINADDR
%token tHOST
%token tLOCALHOST
%token tLOG
%token tMOUNT
%token tNETMASK
%token tNETIF
%token tVOLNAME
%token tOPTS
%token tOS
%token tPASSNO
%token tDIRECT
%token tSEL
%token <s> tSTR
%start list_of_hosts
%type <a> automount
%type <q> automount_tree
%type <e> ether_attr
%type <m> dir_tree_info
%type <d> filesystem fs_info_list
%type <h> host host_attr host_attr_list
%type <q> list_of_hosts list_of_filesystems list_of_mounts dir_tree
%type <f> localinfo_list
%type <s> opt_auto_opts
%%
list_of_hosts :
/* empty */
{ $$ = new_que(); }
| list_of_hosts host
{ if ($2) ins_que((qelem *) $2, list_of_hosts->q_back);
$$ = $1; }
| list_of_hosts automount
{ if ($2) ins_que((qelem *) $2, list_of_automounts->q_back);
$$ = $1; }
;
/*
* A new host:
*
* host foo.domain
*/
host :
tHOST host_attr list_of_filesystems list_of_mounts
{ $$ = $2; $$->h_disk_fs = $3; $$->h_mount = $4; }
| error tHOST host_attr list_of_filesystems list_of_mounts
{ $$ = $3; $$->h_disk_fs = $4; $$->h_mount = $5; }
;
host_attr :
tSTR
{ $$ = new_host(); set_host($$, HF_HOST, $1); }
| '{' host_attr_list '}' tSTR
{ $$ = $2; set_host($$, HF_HOST, $4); }
;
host_attr_list :
/* empty */
{ $$ = new_host(); }
| host_attr_list tNETIF tSTR '{' ether_attr '}'
{ if ($5) {
$5->e_if = $3;
$$ = $1; set_host($$, HF_ETHER, (char *) $5); }
}
| host_attr_list tCONFIG tSTR
{ $$ = $1; set_host($$, HF_CONFIG, $3); }
| host_attr_list tARCH '=' tSTR
{ $$ = $1; set_host($$, HF_ARCH, $4); }
| host_attr_list tOS '=' tSTR
{ $$ = $1; set_host($$, HF_OS, $4); }
| host_attr_list tCLUSTER '=' tSTR
{ $$ = $1; set_host($$, HF_CLUSTER, $4); }
| host_attr_list error '=' tSTR
{ yyerror("unknown host attribute"); }
;
ether_attr :
/* empty */
{ $$ = new_ether_if(); }
| ether_attr tINADDR '=' tSTR
{ $$ = $1; set_ether_if($$, EF_INADDR, $4); }
| ether_attr tNETMASK '=' tSTR
{ $$ = $1; set_ether_if($$, EF_NETMASK, $4); }
| ether_attr tHWADDR '=' tSTR
{ $$ = $1; set_ether_if($$, EF_HWADDR, $4); }
;
/*
* A new automount tree:
*
* automount /mountpoint { ... }
*/
automount :
tAUTOMOUNT opt_auto_opts automount_tree
{ if ($3) {
$$ = new_auto_tree($2, $3);
} else {
$$ = 0;
}
}
| tAUTOMOUNT error
{ $$ = 0; }
;
opt_auto_opts :
/* empty */
{ $$ = strdup(""); }
| tOPTS tSTR
{ $$ = $2; }
;
list_of_filesystems :
/* empty */
{ $$ = 0; }
| list_of_filesystems filesystem
{ if ($2) {
if ($1)
$$ = $1;
else
$$ = new_que();
ins_que(&$2->d_q, $$->q_back);
} else {
$$ = $1;
}
}
;
/*
* A new filesystem:
*
* fs /dev/whatever { ... }
*/
filesystem :
tFS tSTR '{' fs_info_list '}'
{ $4->d_dev = $2; $$ = $4; }
| tFS error '}'
{ $$ = (disk_fs *) 0; }
;
/*
* Per-filesystem information:
*
* fstype - the type of the filesystem (4.2, nfs, swap, export)
* opts - the mount options ("rw,grpid")
* passno - fsck pass number
* freq - dump frequency
* dumpset - tape set for filesystem dumps
* mount - where to mount this filesystem
* log - log device
*/
fs_info_list :
/* empty */
{ $$ = new_disk_fs(); }
| fs_info_list tFSTYPE '=' tSTR
{ $$ = $1; set_disk_fs($$, DF_FSTYPE, $4); }
| fs_info_list tOPTS '=' tSTR
{ $$ = $1; set_disk_fs($$, DF_OPTS, $4); }
| fs_info_list tPASSNO '=' tSTR
{ $$ = $1; set_disk_fs($$, DF_PASSNO, $4); }
| fs_info_list tFREQ '=' tSTR
{ $$ = $1; set_disk_fs($$, DF_FREQ, $4); }
| fs_info_list tMOUNT dir_tree
{ $$ = $1; set_disk_fs($$, DF_MOUNT, (char *) $3); }
| fs_info_list tDUMPSET '=' tSTR
{ $$ = $1; set_disk_fs($$, DF_DUMPSET, $4); }
| fs_info_list tLOG '=' tSTR
{ $$ = $1; set_disk_fs($$, DF_LOG, $4); }
| fs_info_list error '=' tSTR
{ yyerror("unknown filesystem attribute"); }
;
/*
* An automount tree:
*
* name = "volname" name is a reference to volname
* name -> "string" name is a link to "string"
* name nfsalias "string" name is a link to "string", string parsed as NFS
* pathname.
* name { ... } name is an automount tree
*/
automount_tree :
/* empty */
{ $$ = 0; }
| automount_tree tSTR opt_auto_opts '=' tSTR
{ automount *a = new_automount($2);
a->a_volname = $5;
a->a_opts = $3;
if ($1)
$$ = $1;
else
$$ = new_que();
ins_que(&a->a_q, $$->q_back);
}
| automount_tree tSTR opt_auto_opts tNFSEQ tSTR
{ automount *a = new_automount($2);
a->a_hardwiredfs = $5;
a->a_opts = $3;
if ($1)
$$ = $1;
else
$$ = new_que();
ins_que(&a->a_q, $$->q_back);
}
| automount_tree tSTR tEQ tSTR
{ automount *a = new_automount($2);
a->a_symlink = $4;
if ($1)
$$ = $1;
else
$$ = new_que();
ins_que(&a->a_q, $$->q_back);
}
| automount_tree tSTR opt_auto_opts '{' automount_tree '}'
{ automount *a = new_automount($2);
a->a_mount = $5;
a->a_opts = $3;
if ($1)
$$ = $1;
else
$$ = new_que();
ins_que(&a->a_q, $$->q_back);
}
;
dir_tree :
/* empty */
{ $$ = 0; }
| dir_tree tSTR '{' dir_tree_info dir_tree '}'
{ $4->m_mount = $5;
$4->m_name = $2;
if ($2[0] != '/' && $2[1] && strchr($2+1, '/'))
yyerror("not allowed '/' in a directory name");
if ($1)
$$ = $1;
else
$$ = new_que();
ins_que(&$4->m_q, $$->q_back);
}
;
dir_tree_info :
/* empty */
{ $$ = new_mount(); }
| dir_tree_info tEXPORTFS tSTR
{ $$ = $1; set_mount($$, DM_EXPORTFS, $3); }
| dir_tree_info tVOLNAME tSTR
{ $$ = $1; set_mount($$, DM_VOLNAME, $3); }
| dir_tree_info tSEL tSTR
{ $$ = $1; set_mount($$, DM_SEL, $3); }
| dir_tree_info error '=' tSTR
{ yyerror("unknown directory attribute"); }
;
/*
* Additional mounts on a host
*
* mount "volname" ...
*/
list_of_mounts :
/* empty */
{ $$ = 0; }
| list_of_mounts tMOUNT tSTR localinfo_list
{ set_fsmount($4, FM_VOLNAME, $3);
if ($1)
$$ = $1;
else
$$ = new_que();
ins_que(&$4->f_q, $$->q_back);
}
;
/*
* Mount info:
*
* from "hostname" - obtain the object from the named host
* as "string" - where to mount, if different from the volname
* opts "string" - mount options
* fstype "type" - type of filesystem mount, if not nfs
* direct - mount entry, no need to create ad-hoc hosts file
*/
localinfo_list :
/* empty */
{ $$ = new_fsmount(); }
| localinfo_list tDIRECT
{ $$ = $1; set_fsmount($$, FM_DIRECT, ""); }
| localinfo_list tAS tSTR
{ $$ = $1; set_fsmount($$, FM_LOCALNAME, $3); }
| localinfo_list tFROM tSTR
{ $$ = $1; set_fsmount($$, FM_FROM, $3); }
| localinfo_list tFSTYPE tSTR
{ $$ = $1; set_fsmount($$, FM_FSTYPE, $3); }
| localinfo_list tOPTS tSTR
{ $$ = $1; set_fsmount($$, FM_OPTS, $3); }
| localinfo_list error '=' tSTR
{ yyerror("unknown mount attribute"); }
;

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