Merge ^/head r358731 through r358831.
This commit is contained in:
commit
16b9056593
@ -2284,11 +2284,6 @@ _basic_bootstrap_tools+=sbin/sysctl bin/chflags
|
||||
# mkfifo is used by sys/conf/newvers.sh
|
||||
_basic_bootstrap_tools+=usr.bin/mkfifo
|
||||
|
||||
.if ${MK_AMD} != "no"
|
||||
# unifdef is only used by usr.sbin/amd/libamu/Makefile
|
||||
_basic_bootstrap_tools+=usr.bin/unifdef
|
||||
.endif
|
||||
|
||||
.if ${MK_BOOT} != "no"
|
||||
_basic_bootstrap_tools+=bin/dd
|
||||
# xz/unxz is used by EFI
|
||||
|
@ -273,6 +273,28 @@ OLD_DIRS+=usr/lib/clang/9.0.1/lib/freebsd
|
||||
OLD_DIRS+=usr/lib/clang/9.0.1/lib
|
||||
OLD_DIRS+=usr/lib/clang/9.0.1
|
||||
|
||||
# 20200309: amd(8) retired
|
||||
OLD_FILES+=etc/amd.map
|
||||
OLD_FILES+=etc/newsyslog.conf.d/amd.conf
|
||||
OLD_FILES+=etc/rc.d/amd
|
||||
OLD_FILES+=usr/bin/pawd
|
||||
OLD_FILES+=usr/sbin/amd
|
||||
OLD_FILES+=usr/sbin/amq
|
||||
OLD_FILES+=usr/sbin/fixmount
|
||||
OLD_FILES+=usr/sbin/fsinfo
|
||||
OLD_FILES+=usr/sbin/hlfsd
|
||||
OLD_FILES+=usr/sbin/mk-amd-map
|
||||
OLD_FILES+=usr/sbin/wire-test
|
||||
OLD_FILES+=usr/share/examples/etc/amd.map
|
||||
OLD_FILES+=usr/share/man/man1/pawd.1.gz
|
||||
OLD_FILES+=usr/share/man/man5/amd.conf.5.gz
|
||||
OLD_FILES+=usr/share/man/man8/amd.8.gz
|
||||
OLD_FILES+=usr/share/man/man8/amq.8.gz
|
||||
OLD_FILES+=usr/share/man/man8/fixmount.8.gz
|
||||
OLD_FILES+=usr/share/man/man8/fsinfo.8.gz
|
||||
OLD_FILES+=usr/share/man/man8/hlfsd.8.gz
|
||||
OLD_FILES+=usr/share/man/man8/mk-amd-map.8.gz
|
||||
OLD_FILES+=usr/share/man/man8/wire-test.8.gz
|
||||
# 20200301: bktr removed
|
||||
OLD_DIRS+=usr/include/dev/bktr
|
||||
OLD_FILES+=usr/include/dev/bktr/ioctl_bktr.h
|
||||
|
5
UPDATING
5
UPDATING
@ -32,6 +32,11 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW:
|
||||
information about prerequisites and upgrading, if you are not already
|
||||
using clang 3.5.0 or higher.
|
||||
|
||||
20200309:
|
||||
The amd(8) automount daemon has been removed from the source tree.
|
||||
As of FreeBSD 10.1 autofs(5) is the preferred tool for automounting.
|
||||
amd is still available in the sysutils/am-utils port.
|
||||
|
||||
20200301:
|
||||
Removed brooktree driver (bktr.4) from the tree.
|
||||
|
||||
|
@ -1,427 +0,0 @@
|
||||
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 AT cs.sunysb.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.
|
||||
|
||||
* Ion Badulescu <ion AT cs.columbia.edu>
|
||||
|
||||
Co-maintainer of am-utils since late 1999: Linux and Solaris autofs support,
|
||||
Linux NFSv3 support, major code reorganization, etc...
|
||||
|
||||
* Randall S. Winchester <rsw AT 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 AT 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.
|
||||
|
||||
August 8, 1998: add detection support for NFS V.3 for NetBSD 1.3F.
|
||||
|
||||
February 1, 1998: fixes for NetBSD to better detect its features.
|
||||
|
||||
September 4, 1999: assorted fixes for NetBSD 1.4+.
|
||||
|
||||
* Hannes Reinecke <hare AT 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 AT 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 AT 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 AT cs.huji.ac.il>
|
||||
|
||||
July, 6 1997: contributed patches to hesiod on bsdi3.
|
||||
|
||||
* Tom Schmidt <tschmidt AT 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.
|
||||
|
||||
May 30, 2000: correct logging types for addopts/mergeopts messages.
|
||||
|
||||
* Daniel S. Riley <dsr AT 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.
|
||||
|
||||
August 15, 1998: fix memory leak in processing of /defaults, and avoid
|
||||
accessing uninitialized memory in osf1.
|
||||
|
||||
* Roman Hodek <Roman.Hodek AT 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 AT debian.org>
|
||||
and Dominik Kubla <dominik AT debian.org>.
|
||||
|
||||
* Rainer Orth <ro AT 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!
|
||||
|
||||
January 8, 1999: texi fixes, and more Ultrix 4.3 fixes, among others.
|
||||
|
||||
January 11, 1999: hesiod_isup function. Fix format errors in dlog/plog.
|
||||
Remove obsolete or unnecessary files/macros. Don't report disabled file
|
||||
systems. More misc fixes.
|
||||
|
||||
February 3, 1998: don't start autofs listener unless autofs maps were in
|
||||
use.
|
||||
|
||||
December 10, 1999: assorted fixed and lots of fixes to support in-kernel
|
||||
mount tables in Solaris 8.
|
||||
|
||||
February 9, 2000: new debug options hrtime (hi-res timer) and xdrtrace. bug
|
||||
fixes.
|
||||
|
||||
* Jason Thorpe <thorpej AT 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 AT laas.fr>.
|
||||
|
||||
* Chris Metcalf <metcalf AT 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 AT 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 AT 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 AT wsrcc.com>
|
||||
|
||||
August 10, 1997: netbsd and other bsd systems have a mask flag for
|
||||
pcfs_args (msdos mount).
|
||||
|
||||
* Christos Zoulas <christos AT zoulas.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.
|
||||
|
||||
November 29, 2002: compile fixes for NetBSD, a couple of bug fixes (one
|
||||
already fixed by maintainers)
|
||||
|
||||
April 12, 2003: support new "unmount" option, useful to timeout removable
|
||||
local media mounts.
|
||||
|
||||
October 12, 2004: patch to support two new amd.conf options, domain_strip
|
||||
and auto_attrcache. Patch to cleanup NFS attribute-cache flag computation.
|
||||
Patch to fix an inconsistency in timeouts in the RPC code between socket and
|
||||
TLI implementations. Patch to print version string (amd -v) after all
|
||||
options had been initialized, so we can print domain, host, and hostd.
|
||||
Linux patch to use umount2(2) if umount(2) fails.
|
||||
|
||||
* Bill Paul <wpaul AT 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.
|
||||
|
||||
January 15, 1999: small ldap bug fixes.
|
||||
|
||||
* Stefan Vogel <vogel AT physik-rzu.unizh.ch>
|
||||
|
||||
November 14, 1997: typo in the subscription instructions to amd-dev.
|
||||
|
||||
* Guntram Wolski <gwolsk AT sei.com>
|
||||
|
||||
November 15, 1997: pointed out mismatching documentation for the -o option.
|
||||
|
||||
* Michael Hucka <hucka AT eecs.umich.edu>
|
||||
|
||||
January 11, 1997: pointed out reversed definition of NFS mount options vers
|
||||
and proto.
|
||||
|
||||
* Albert Chin <china AT pprd.abbott.com>
|
||||
|
||||
January 12, 1998: minor bug in output of amd -H.
|
||||
|
||||
June 23, 2005: assortment of small compile bugs on aix4, and solaris 5/6/7.
|
||||
|
||||
* Thomas Richter <richter AT chemie.fu-berlin.de>
|
||||
|
||||
January 13, 1998: use case insensitive comparisons for variables that need
|
||||
it (such as all hostname related ones, and more).
|
||||
|
||||
July 20, 1998: don't leak memory in the private version of yp_all (when
|
||||
vendor yp_all is bad).
|
||||
|
||||
* Fred Korz <korz AT smarts.com>
|
||||
|
||||
January 30, 1998: minor typo fixed to tftp example in am-utils.texi.
|
||||
|
||||
* Donald Buczek <buczek AT 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 AT ms.com>
|
||||
|
||||
April 20, 1998: allow arbitrary number of interfaces in wire listing.
|
||||
|
||||
* David O'Brien <obrien AT NUXI.com>
|
||||
|
||||
September 4, 1998: bug fix to avoid overrunning hostname buffer, and minor
|
||||
amd.conf man page typo correction.
|
||||
|
||||
September 22, 1999: use more secure vsnprintf in real_plog().
|
||||
|
||||
* Danny Rathjens <dkr AT cs.fiu.edu>
|
||||
|
||||
October 29, 1998: swap arguments to kill(2) in amd.c.
|
||||
|
||||
* Mike Mitchell <mcm AT unx.sas.com>
|
||||
|
||||
November 3, 1998: amd/nfs_subr.c (nfsproc_lookup_2_svc): try to avoid a race
|
||||
condition between unmounting and re-mounting an entry, by increasing the ttl
|
||||
of a looked up entry before unmounting it.
|
||||
|
||||
* Douglas K. Rand" <rand AT aero.und.edu>
|
||||
|
||||
December 3, 1998: case insensitive host name match for nfsl.
|
||||
|
||||
* David Wolfskill <dhw AT whistle.com>
|
||||
January 28, 1999: don't turn on/off noconn option if it was already in that
|
||||
state.
|
||||
|
||||
* Jeffrey C Honig <jch AT BSDI.COM>
|
||||
March 14, 1999: clean up more autogenerated files upon "make distclean".
|
||||
|
||||
March 15, 1999: avoid overly verbose NIS warning even on systems that don't
|
||||
run NIS. On BSD systems, wire.c uses getifaddrs(), sysctl(), IRS routines,
|
||||
and more fixes. Numerous IP packet security fixes.
|
||||
|
||||
March 16, 1999: documentation typos. new cdfs options. ufs structure
|
||||
detection for bsdi4.
|
||||
|
||||
September 17, 1999: fixes to expn.
|
||||
|
||||
* Paul Balyoz <pbalyoz AT sedona.ch.intel.com>
|
||||
March 26, 1999: ensure lostaltmail displays Y2K compliant dates.
|
||||
|
||||
* Jon Peatfield <J.S.Peatfield AT damtp.cam.ac.uk>
|
||||
March 30, 1999: turn off incomplete NFS V.3 support in HPUX 10.20.
|
||||
|
||||
September 22, 1999: safe reloading of maps without first clearing old
|
||||
copies, and using cached copies if map failed to reload.
|
||||
|
||||
* Peter Breitenlohner <peb AT mppmu.mpg.de>
|
||||
July 24, 1999: patch for linux 2.2.x to work with older libc5 systems, and
|
||||
nis_isup mis-logic fixes.
|
||||
December 13, 2001: report typos in scripts/amd.conf.5.
|
||||
|
||||
* Dale Talcott <aeh AT quest.cc.purdue.edu>
|
||||
July 26, 1999: added NFS3 support for AIX mounting.
|
||||
|
||||
* Christophe Kalt <Christophe-Kalt AT deshaw.com>
|
||||
July 14, 1999: add netgrpd() syntax function which uses FQHN.
|
||||
|
||||
* Andrew J. Korty <ajk AT purdue.edu>
|
||||
September 5, 1999: pawd works for type:=nfsl.
|
||||
|
||||
* Nick Williams <njw AT ms.com>
|
||||
September 1, 1999: bug fix for incorrect symlinks when two locations are
|
||||
requested simultaneously.
|
||||
|
||||
November 1, 1999: fixes to sync maps even if they are set to mapcache:=sync.
|
||||
|
||||
January 19, 2000: fix (and reduce the incidence of) stale file handles when
|
||||
doing rapid mounts and umounts in succession.
|
||||
|
||||
June 5, 2000: better handling of potential race-conditions during rapid
|
||||
u/mounts. Correctly update d_drops stats for amq -s.
|
||||
|
||||
* Johann Pfefferl <johann.pfefferl.jp AT germany.agfa.com>
|
||||
November 16, 1999: fix to ldap code so repeated calls to string2he don't
|
||||
corrupt the string passed.
|
||||
|
||||
* Amitha Perera <perera AT cs.rpi.edu>
|
||||
December 9, 1999: detect all wire() interfaces correctly.
|
||||
|
||||
* Steven Danz <sdanz AT awc.kc.noaa.gov>
|
||||
January 25, 2000: allow browsable auto maps.
|
||||
|
||||
* Wolfram Klaus <klaus AT physik.fu-berlin.de>.
|
||||
November 21, 2000: recognize proplist mnttab flag.
|
||||
|
||||
* Thomas Klausner <tk AT giga.or.at>
|
||||
November 21, 2000: lots of NetBSD fixes (many of which are generic).
|
||||
|
||||
April 18, 2003: patch to reference am-utils info pages in man page.
|
||||
|
||||
November 28, 2004: small fixes to typos in amd.conf(5) man page.
|
||||
|
||||
* Olaf Kirch <okir AT caldera.de>
|
||||
February 1, 2001: important Linux NFS error number mapping fixed
|
||||
|
||||
* Ahmon Dancy <dancy AT franz.com>
|
||||
February 9, 2001: Apple Rhapsody/Darwin/OS X port
|
||||
|
||||
* Sebastien Bahloul <sebastien.bahloul AT mangoosta.fr>
|
||||
July 3, 2001: LDAP fixes and updates to support new APIs
|
||||
|
||||
March 27, 2002: LDAP bug and port to HPUX-11.
|
||||
|
||||
* Philippe Troin <phil AT fifi.org>
|
||||
July 12, 2001: Proper handling of GNU getopt, support for optionally
|
||||
disabling LDAP/Hesiod, fixes for the dev/nodev option on Linux. Texi
|
||||
documentation fix.
|
||||
|
||||
November 28, 2001: Bug fix. Support "nolock" as an NFS option, not a
|
||||
generic mount option.
|
||||
|
||||
July 17, 2003: pref:=null core dump fix. libgdbm portability. tcpd/librap
|
||||
support. And a few other things for the 6.0 branch.
|
||||
|
||||
* Trond Myklebust <trond.myklebust AT fys.uio.no>
|
||||
January 10, 2002: Proper initialization of the timeo parameter on Linux, TCP
|
||||
_must_ have a timeout 2 orders of magnitude larger than UDP
|
||||
|
||||
* George Ross <gdmr AT dcs.ed.ac.uk>
|
||||
April 29, 2002: Rework of old code, support for wildcards in LDAP queries,
|
||||
and an FD leak fix. Amd -A support.
|
||||
|
||||
October 21, 2002: ldap_unbind fix for SIGPIPE, and support for LDAPv3
|
||||
protocol version parameter (with Tim Colles <timc AT inf.ed.ac.uk>).
|
||||
|
||||
* Matthias Scheler <tron AT zhadum.de>
|
||||
June 14, 2002: patch to use "xlatecookie" NFS mount option.
|
||||
|
||||
* Jun-ichiro itojun Hagino <itojun AT iijlab.net>.
|
||||
June 11, 2002: minor fixes to support NetBSD 1.6A.
|
||||
|
||||
* Sean Fagan <sef AT apple.com>
|
||||
March 14, 2003: detect and use the MNT2_GEN_OPT_AUTOMNTFS mount flag
|
||||
on OS X / Darwin.
|
||||
|
||||
* Hendrik Scholz <hscholz AT raisdorf.net>
|
||||
June 9, 2003: mk-amd-map should open temp db file using O_EXCL.
|
||||
|
||||
* Mark Davies <mark AT mcs.vuw.ac.nz>
|
||||
July 14, 2003: define "xlatecookie" mnttab option if not defined (for
|
||||
NetBSD). Support null hesiod entries if they start with a ".".
|
||||
|
||||
* Eric S. Raymond <esr AT thyrsus.com>
|
||||
December 9, 2003: fix unbalanced [] typo in fsinfo man page.
|
||||
|
||||
* Martin Blapp <mb AT imp.ch>
|
||||
July 6, 2004: recognize fields in pcfs_args_t in FreeBSD 5.
|
||||
|
||||
* Dan Nelson <dnelson AT allantgroup.com>
|
||||
August 2, 2004: pawd to recognize "host" type mounts.
|
||||
|
||||
* Hauke Fath <hauke AT Espresso.Rhein-Neckar.DE>
|
||||
August 3, 2004: pawd to recognize "linkx" type mounts.
|
||||
|
||||
* Michael van Elst <M.van.Elst AT science-computing.de>
|
||||
September 1, 2004: bug fix to avoid race condition in calls to mntctl on
|
||||
AIX.
|
||||
|
||||
* Jonathan Chen <jon+amd AT spock.org>
|
||||
October 22, 2004: patch/fix to move mlock/mlockall/plock code after the
|
||||
fork().
|
||||
June 29, 2005: core dump going off end of exported_ap[] array.
|
||||
September 29, 2005: patch/fix for pawd not to go into an infinite loop.
|
||||
October 25, 2005: patch/fix for pawd to repeatedly resolve path.
|
||||
|
||||
* David Rage <rage AT ucl.ac.uk>
|
||||
January 17, 2005: prevent Amd from logging 'Read-only filesystem' errors
|
||||
when the mount point has an ancestor (i.e. '/') that is mounted read-only.
|
||||
|
||||
* Kevin Layer <layer AT franz.com>
|
||||
January 28, 2005: basic instructions how to setup Amd on Mac OS-X.
|
||||
|
||||
* Dan Ottavio <dottavio AT ic.sunysb.edu>
|
||||
March 2, 2005: new global amd.conf option debug_mtab_file, to set the debug
|
||||
mtab file when using debug_options=mtab. Default has changed from "./mtab"
|
||||
to "/tmp/mtab" to avoid security problem. Bug fixed to ensure that Amd
|
||||
terminates properly even mtab file doesn't exist.
|
||||
|
||||
* Erik Kline <ekline at ekline dot com>
|
||||
January 3, 2005: implementation of executable maps for Amd.
|
||||
|
||||
* Jim Zajkowski <jim.zajkowski AT gmail.com>
|
||||
March 14, 2005: small patch to amd2ldif.
|
||||
|
||||
* Adam Morley <adam at gmi dot com>
|
||||
January 27, 2005: synchronize what amd2ldif does vs. what the ldap.schema
|
||||
expects.
|
||||
|
||||
* Graeme Wilford <G.Wilford AT surrey.ac.uk>
|
||||
July 4, 2005: buffer overflow in pawd.
|
||||
|
303
contrib/amd/BUGS
303
contrib/amd/BUGS
@ -1,303 +0,0 @@
|
||||
LIST OF KNOWN BUGS IN AM-UTILS OR OPERATING SYSTEMS
|
||||
|
||||
Note: report am-utils bugs via Bugzilla to https://bugzilla.am-utils.org/ or
|
||||
by email to the am-utils mailing list (see www.am-utils.org).
|
||||
|
||||
|
||||
(1) mips-sgi-irix*
|
||||
|
||||
[1A] known to have flaky 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 iterates over NIS maps. The latter isn't as
|
||||
reliable as yp_all() which uses TCP, but it is better than hanging.
|
||||
|
||||
(I have some reports that older version of hpux-9, with older libc, also
|
||||
leak file descriptors.)
|
||||
|
||||
[1C] SGI's MIPSpro C compiler on IRIX 6 has the unfortunate habit of
|
||||
creating code specificially for the machine it runs on. The ABI and ISA
|
||||
used depend very much on the OS version and compiler release used. This
|
||||
means that the resulting amd binary won't run on machines different from
|
||||
the build host, particularly older ones. Older versions of am-utils
|
||||
enforced the O32 ABI when compiling with cc to work around this, but this
|
||||
ABI is deprecated in favor of the N32 ABI now, so we use -n32 -mips3 to
|
||||
ensure that the binaries run on every host capable of running IRIX 6 at
|
||||
all. If this is not appropriate for you, configure with something like
|
||||
CC='cc -64' instead to get the desired ABI and ISA.
|
||||
|
||||
(2) alpha-unknown-linux-gnu (RedHat Linux 4.2)
|
||||
|
||||
hasmntopt(mnt, opt) can go 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);
|
||||
}
|
||||
|
||||
It is possible that sufficiently newer version of libc for RH4.2 fix this
|
||||
problem.
|
||||
|
||||
|
||||
(3) mips-dec-ultrix4.3
|
||||
|
||||
Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> reports
|
||||
|
||||
[3A] One needs the Kernel Config Files (UDTBIN430) subset installed to
|
||||
compile am-utils, otherwise essential header files (net/if.h, net/route.h,
|
||||
rpcsvc/mount.h, rpcsvc/yp_prot.h, rpcsvc/ypclnt.h, sys/proc.h) are
|
||||
missing.
|
||||
|
||||
[3B] It's probably impossible to build am-utils with DEC C on Ultrix V4.3.
|
||||
This compiler is pseudo-ANSI only. Maybe the new ANSI C compiler in V4.3A
|
||||
and beyond will do. I successfully used gcc 2.8.1.
|
||||
|
||||
[3C] You need to build against a recent libhesiod (I used 3.0.2) and
|
||||
libresolv/lib44bsd (I used BIND 4.9.5-P1). The resolver routines in
|
||||
libc seem to cause random memory corruption. It is necessary to specify
|
||||
LIBS=-l44bsd. lib44bsd is a helper library of libresolv used to supply
|
||||
functions like strdup which are missing on the host system. This isn't
|
||||
currently autoconfiscated.
|
||||
|
||||
[3D] You need to configure with CONFIG_SHELL=/bin/sh5 /bin/sh5 buildall;
|
||||
/bin/sh cannot handle the shell functions used in buildall and is both
|
||||
buggy and slow.
|
||||
|
||||
[3E] 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
|
||||
|
||||
|
||||
(4) powerpc-ibm-aix4.2.1.0
|
||||
|
||||
[4A] "Randall S. Winchester" <rsw AT 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 AT 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.
|
||||
|
||||
[C] Do not link amd with libnsl. It is buggy and causes amd to core dump
|
||||
in strlen inside strdup inside svc_register().
|
||||
|
||||
|
||||
(5) *-linux-rh51 (RedHat Linux 5.1)
|
||||
|
||||
There's a UDP file descriptor leak in libnsl in RedHat Linux 5.1. This
|
||||
library part of glibc2. Am-utils currently declares redhat 5.1 systems as
|
||||
having a "broken yp_all" and using an internal, slower, leak-free version.
|
||||
The leak is known to the glibc maintainers and a fix from them is due soon,
|
||||
but it is not yet in the glibc-2.0.7-19 RPM.
|
||||
|
||||
|
||||
(6) rs6000-ibm-aix4.1.x
|
||||
|
||||
A bug in libc results in an amq binary that doesn't work; amq -v dumps core
|
||||
in xdr_string. There is no known fix (source code or vendor patch) at this
|
||||
time. (Please let us know if you have a fix; see www.am-utils.org.)
|
||||
|
||||
|
||||
(7) *-aix4.3.2.0
|
||||
|
||||
The plock() function will pre-reserve all of the memory up to the maximum
|
||||
listed in the ulimit. If the ulimit is infinite, plock() will try to take
|
||||
all of the system's memory, and fail with ENOMEM (Not Enough Space).
|
||||
Normally ulimit may be set to a few gigs of max memory usage, but even that
|
||||
is too much; Amd doesn't need more than a few megs of resident memory size
|
||||
(depending on the particular usage, number of maps, etc.) Solution: lower
|
||||
your ulimit before starting amd. This can be done inside the ctl-amd
|
||||
script, but be careful not to limit it too low. Alternatively, don't use
|
||||
plock on aix-4.3: set it to plock=no in amd.conf (which is the default if
|
||||
you do nothing).
|
||||
|
||||
|
||||
(8) *-linux (systems using glibc 2.1, such as RedHat-6.x)
|
||||
|
||||
There's a UDP file descriptor leak in the NIS routines in glibc, especially
|
||||
those that do yp_bind. Until this is bug fixed, do not set nis_domain in
|
||||
amd.conf, but let the system pick up the default domain name as set by your
|
||||
system. That would avoid using the buggy yp_bind routines in libc.
|
||||
|
||||
|
||||
(9) *-linux (SuSE systems using unfsd)
|
||||
|
||||
The user-level nfsd (2.2beta44) on older SuSE Linux systems (and possibly
|
||||
others) dies with a SEGV when amd tries to contact it for access to a volume
|
||||
that does not exist, or one for which there is no permission to mount.
|
||||
|
||||
|
||||
(10) *-*-hpux11
|
||||
|
||||
If you're using NFSv3, you must install HP patches PHNE_20344 and
|
||||
PHNE_20371. If you don't, and you try to use amd with NFSv3 over TCP, your
|
||||
kernel will panic.
|
||||
|
||||
|
||||
(11) *-linux* (any system using a 2.2.18+ kernel)
|
||||
|
||||
The Linux kernels don't support Amd's direct mounts very well, leading to
|
||||
erratic behavior: shares that don't get remounted after the first timeout,
|
||||
inability to restart Amd because its mount points cannot be unmounted, etc.
|
||||
There are some kernel patches on the am-utils Web site, which solve these
|
||||
problems. See http://www.am-utils.org/patches/.
|
||||
|
||||
Later 2.4.x kernels completely disallow the hack amd was using for direct
|
||||
mounts, so another solution will have to be found.
|
||||
|
||||
Note: the above is for the old-style amd mount_type = nfs. The autofs mounts
|
||||
don't support direct mounts at all (due to lack of kernel support).
|
||||
|
||||
(12) *-aix5.1.0.0 and *-hpux9*
|
||||
|
||||
/bin/sh is broken and fails to run the configure script properly. You need
|
||||
to use /bin/ksh instead. The buildall script will do it for you; if for some
|
||||
reason you need to run configure directly, run it using 'ksh configure'
|
||||
instead of just 'configure'.
|
||||
|
||||
[12A] *-aix5.2.*
|
||||
|
||||
Apparently there is an NFS client side bug in vmount() which causes amd to
|
||||
hang when it starts (and tries to NFS-mount itself). According to IBM
|
||||
engineers, this has to do with partial support code for IPv6: the NFS kernel
|
||||
code doesn't appear to recognize the sin_family of the amd vmount(),
|
||||
although amd does the right thing. The bug doesn't appear to be in 5.1 or
|
||||
4.3.3. A fix from IBM is available, APAR number IY41417.
|
||||
|
||||
A binary built on 4.3.3 will not work on 5.2, because the kernel ABIs have
|
||||
changed.
|
||||
|
||||
[12C] *-aix*
|
||||
|
||||
It is important that you install bos.net.nfs.adt before configuring and
|
||||
building am-utils. If you don't, you will get compile-time or
|
||||
configure-time errors, especially when configure tries to find AIX's
|
||||
definition of struct nfs_args.
|
||||
|
||||
(13) *-linux and *-darwin6.0
|
||||
|
||||
Certain linux kernels (2.4.18+ are fine, 2.4.10- are probably bad, those in
|
||||
between have not been tested) have a bug which causes them to reconnect
|
||||
broken NFS/TCP connections using unprivileged ports (greater than 1024),
|
||||
unlike the initial connections which do originate from privileged
|
||||
ports. This can upset quite a few NFS servers and causes accesses to the
|
||||
mounted shares to fail with "Operation not permitted" (EPERM).
|
||||
|
||||
The darwin (MacOS X) kernel defaults to using unprivileged ports, but that
|
||||
can be changed by setting the resvport mount flag (which amd sets by
|
||||
default). Nonetheless, if a TCP connection breaks, under certain unclear
|
||||
circumstances the kernel might "forget" about that flag and start using
|
||||
unprivileged ports, causing the same EPERM error above.
|
||||
|
||||
(14) Solaris
|
||||
|
||||
The line "%option" in *.l files may cause Solaris /usr/ccs/bin/lex to abort
|
||||
with the error "missing translation value." This is a bug in Solaris lex.
|
||||
|
||||
Moreover, both Solaris yacc and lex produce code that does not pass strict
|
||||
compilation such as "gcc -Wall -Werror".
|
||||
|
||||
Use GNU Flex and Bison instead. You can download ready-made binaries from
|
||||
www.sunfreeware.com. Note, however, that sometimes the binaries on
|
||||
sunfreeware.com don't seem to work, often because they are built against an
|
||||
older revision of Solaris or build tools. In that case, build a fresh
|
||||
version of GNU flex and/or bison from the latest stable sources. See
|
||||
http://www.gnu.org/software/flex/ and http://www.gnu.org/software/bison/.
|
||||
|
||||
(15) Solaris 8 + patch 10899[34]-xx (18 <= xx < 25) or patch 11260[56]-xx
|
||||
|
||||
With this patch, Sun updated the autofs kernel module and automountd
|
||||
userspace daemon from version 3 to version 4. They also updated the
|
||||
/usr/include/rpcsvc/autofs_prot.x file, but forgot to regenerate the
|
||||
autofs_prot.h file. Thus, when amd is compiled, it uses the old header and
|
||||
thinks it should use autofs version 3, when in fact the kernel now supports
|
||||
(and expects) only version 4.
|
||||
|
||||
The workaround is to run 'rpcgen -C -h /usr/include/rpcsvc/autofs_prot.x >
|
||||
/usr/include/rpcsvc/autofs_prot.h' and completely reconfigure and rebuild
|
||||
am-utils (removing config.cache before running configure).
|
||||
|
||||
The problem is fixed in patch revisions 10899[34]-25 and up.
|
||||
|
||||
|
||||
(16) Linux kernel 2.4+ and lofs mounts
|
||||
|
||||
Lofs mounts are not supported by the linux kernel, at all, but since 2.4.0
|
||||
the kernel supports a similar type of mount called a bind mount. Its
|
||||
semantics are closer to those of a hardlink than to those of lofs, and one
|
||||
of the results is that bind mounts ignore any mount options paseed to them.
|
||||
|
||||
Amd uses bind mounts internally to emulate lofs mounts, which means that
|
||||
lofs mounts on linux will effectively ignore their mount parameters and
|
||||
inherit whatever options the original filesystem mounted upon had.
|
||||
|
||||
|
||||
(17) autoconf 2.57
|
||||
|
||||
If you see configure warnings of the following kind:
|
||||
|
||||
configure: WARNING: sys/proc.h: present but cannot be compiled
|
||||
configure: WARNING: sys/proc.h: check for missing prerequisite headers?
|
||||
configure: WARNING: sys/proc.h: proceeding with the preprocessor's result
|
||||
configure: WARNING: ## ------------------------------------ ##
|
||||
configure: WARNING: ## Report this to bug-autoconf@gnu.org. ##
|
||||
configure: WARNING: ## ------------------------------------ ##
|
||||
|
||||
please ignore them. They are not real errors, and neither
|
||||
bug-autoconf@gnu.org nor the am-utils maintainers are interested in hearing
|
||||
about them. Autoconf simply tries to do more than we need and attempts to
|
||||
compile each header in isolation, which fails for many system headers.
|
||||
That's ok, because we only need to know if a header file exists -- we know
|
||||
how to use it properly ourselves.
|
||||
|
||||
While autoconf does offer a way to specify other files to be included with
|
||||
the tested header, in order to avoid these warnings, using it would enlarge
|
||||
the resulting configure script by an order of magnitude, and for no real
|
||||
gain. Configure is big enough as it is, we don't need any more useless
|
||||
baggage in it.
|
||||
|
||||
(18) NetBSD 2.0.2, FreeBSD 5.4, OpenBSD 3.7, and quite possibly most other
|
||||
BSDs and other OSs (as of September 2005)
|
||||
|
||||
Some BSD kernels don't have a way to turn off the NFS attribute cache. They
|
||||
don't have a 'noac' mount flag, and setting various cache timeout fields in
|
||||
struct nfs_args doesn't turn off the attribute cache; instead, it sets the
|
||||
attribute cache timeout to some internal hard-coded default (usually
|
||||
anywhere from 5-30 seconds). If Amd cannot turn off the NFS attribute
|
||||
cache, under heavy Amd usage, users could get ESTALE errors from automounted
|
||||
symlinks, or find that those symlinks point to the wrong place. One
|
||||
workaround which would minimize this effect is to set auto_attrcache=1 in
|
||||
your amd.conf, but it doesn't eliminate the problem! The best solutions are
|
||||
(1) to use Amd in Autofs mode, if it's supported in your OS, and (2) talk to
|
||||
your OS vendor to support a true "noac" flag. See README.attrcache for more
|
||||
details.
|
||||
|
||||
Erez & the am-utils team.
|
@ -1,32 +0,0 @@
|
||||
Copyright (c) 1997-2014 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. 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.
|
13085
contrib/amd/ChangeLog
13085
contrib/amd/ChangeLog
File diff suppressed because it is too large
Load Diff
@ -1,69 +0,0 @@
|
||||
Am-utils Frequently Asked Questions
|
||||
|
||||
Note: we started this FAQ only on March 15, 2005; so it's not long or
|
||||
comprehensive, yet. Amd is much older than that, and so there's a lot of
|
||||
information that's already available in other forms. If this FAQ doesn't
|
||||
answer your questions, see information in the following sources:
|
||||
|
||||
1. The Am-utils book: http://www.am-utils.org/docs/amd-book/
|
||||
|
||||
2. The Am-utils user manual, which is part of the distribution and is also
|
||||
available from www.am-utils.org.
|
||||
|
||||
3. The www.am-utils.org Web site resources, especially the "am-utils" mailing
|
||||
list (and its archives).
|
||||
|
||||
4. In the am-utils distribution (always use the latest ones), see all of the
|
||||
various README files (README, README.autofs, README.ldap, README.osx, and
|
||||
README.y2k). The "BUGS" file also lists useful information about bugs
|
||||
and problems with specific OSs which affect Amd. All of these text files
|
||||
are also available from www.am-utils.org.
|
||||
|
||||
5. Some FAQ questions (including newbie questions) are available here:
|
||||
http://www.kernelcorp.com/resources_faqs.html
|
||||
|
||||
6. Some problems are known bugs but have not been fixed yet: this are
|
||||
listed in bugzilla in https://bugzilla.am-utils.org/
|
||||
|
||||
If you have additions to this FAQ, please let us know at
|
||||
the am-utils list (see www.am-utils.org).
|
||||
|
||||
Thank you,
|
||||
The Am-utils development team.
|
||||
|
||||
<FAQ>
|
||||
|
||||
*** Linux Questions
|
||||
|
||||
Q1. When I use Amd with Autofs and I restart Amd, how come it cannot remount
|
||||
the Autofs partitions?
|
||||
|
||||
A1. This is a limitation of the Linux Autofs kernel module (for both autofs
|
||||
v2. and v3). The Linux Autofs does not allow restarting automounted
|
||||
points. There's nothing Amd can do about this. In fact, the same
|
||||
problem exists if you use the userland "automount" daemon instead of
|
||||
Amd. Hopefully Autofs-v4 or the separate effort of Autofs-NG will
|
||||
address this serious problem.
|
||||
|
||||
Note that Amd itself can restart autofs automounted points just fine on
|
||||
OSs that support it, for example Solaris.
|
||||
|
||||
|
||||
Q2. When I use Amd, I get this console message frequently: "mount version
|
||||
older than kernel." Is it a problem?
|
||||
|
||||
A2. No, it's a harmless warning message that the Linux kernel prints for NFS
|
||||
mounts. The intent was to alert administrators that the kernel has
|
||||
supposedly a different version of the mount(2) code than a userland
|
||||
program used. This happens if you compile Amd against kernel headers
|
||||
that are different than the kernel you're running. If the message
|
||||
really bothers you, then one way to "fix" the problem is to recompile
|
||||
Amd against the same kernel headers as the running kernel.
|
||||
|
||||
Nevertheless, it is a relatively useless message because as far as we
|
||||
know, the NFS v2 and v3 mount codes have been in perfect sync between
|
||||
the userland and kernel sides, and were "standardized" for years
|
||||
already. This warning message caused more unnecessary worry among
|
||||
administrators than helping alert them to legitimate problems.
|
||||
|
||||
</FAQ>
|
@ -1,268 +0,0 @@
|
||||
$FreeBSD$
|
||||
*LSM.am-utils
|
||||
*Makefile.*
|
||||
*README.autofs
|
||||
*README.osx
|
||||
*ac*.m4
|
||||
*.old
|
||||
*acconfig.h
|
||||
*aux
|
||||
*autom4te.cache*
|
||||
*buildall
|
||||
*config*
|
||||
*depcomp
|
||||
*install-sh
|
||||
*lt*
|
||||
*missing
|
||||
*mkinstalldirs
|
||||
*stamp-h.in
|
||||
*amd/test1.sh
|
||||
*amd/Makefile.*
|
||||
*amq/Makefile.*
|
||||
*commit
|
||||
*cvs-server.txt
|
||||
*conf/checkmount/checkmount_aix.c
|
||||
*conf/checkmount/checkmount_default.c
|
||||
*conf/checkmount/checkmount_osf.c
|
||||
*conf/checkmount/checkmount_svr4.c
|
||||
*conf/checkmount/checkmount_ultrix.c
|
||||
*conf/fh_dref/fh_dref_aix3.h
|
||||
*conf/fh_dref/fh_dref_aix42.h
|
||||
*conf/fh_dref/fh_dref_bsd44.h
|
||||
*conf/fh_dref/fh_dref_default.h
|
||||
*conf/fh_dref/fh_dref_hpux.h
|
||||
*conf/fh_dref/fh_dref_irix.h
|
||||
*conf/fh_dref/fh_dref_isc3.h
|
||||
*conf/fh_dref/fh_dref_linux.h
|
||||
*conf/fh_dref/fh_dref_nextstep.h
|
||||
*conf/fh_dref/fh_dref_osf2.h
|
||||
*conf/fh_dref/fh_dref_osf4.h
|
||||
*conf/fh_dref/fh_dref_sunos3.h
|
||||
*conf/fh_dref/fh_dref_sunos4.h
|
||||
*conf/fh_dref/fh_dref_svr4.h
|
||||
*conf/hn_dref/hn_dref_default.h,
|
||||
*conf/hn_dref/hn_dref_isc3.h
|
||||
*conf/hn_dref/hn_dref_linux.h
|
||||
*conf/mount/mount_aix.c
|
||||
*conf/mount/mount_aix3.c
|
||||
*conf/mount/mount_bsdi3.c
|
||||
*conf/mount/mount_default.c
|
||||
*conf/mount/mount_freebsd3.c
|
||||
*conf/mount/mount_hpux.c
|
||||
*conf/mount/mount_irix5.c
|
||||
*conf/mount/mount_irix6.c
|
||||
*conf/mount/mount_isc3.c
|
||||
*conf/mount/mount_linux.c
|
||||
*conf/mount/mount_mach3.c
|
||||
*conf/mount/mount_stellix.c
|
||||
*conf/mount/mount_svr4.c
|
||||
*conf/mtab/mtab_aix.c
|
||||
*conf/mtab/mtab_file.c
|
||||
*conf/mtab/mtab_isc3.c
|
||||
*conf/mtab/mtab_linux.c
|
||||
*conf/mtab/mtab_mach3.c
|
||||
*conf/mtab/mtab_osf.c
|
||||
*conf/mtab/mtab_svr4.c
|
||||
*conf/mtab/mtab_ultrix.c
|
||||
*conf/nfs_prot/nfs_prot_aix3.h
|
||||
*conf/nfs_prot/nfs_prot_aix4.h
|
||||
*conf/nfs_prot/nfs_prot_aix4_2.h
|
||||
*conf/nfs_prot/nfs_prot_aix4_3.h
|
||||
*conf/nfs_prot/nfs_prot_aix5_1.h
|
||||
*conf/nfs_prot/nfs_prot_aix5_2.h
|
||||
*conf/nfs_prot/nfs_prot_bsdi2.h
|
||||
*conf/nfs_prot/nfs_prot_bsdi3.h
|
||||
*conf/nfs_prot/nfs_prot_darwin.h
|
||||
*conf/nfs_prot/nfs_prot_default.h
|
||||
*conf/nfs_prot/nfs_prot_hpux.h
|
||||
*conf/nfs_prot/nfs_prot_hpux11.h
|
||||
*conf/nfs_prot/nfs_prot_irix5.h
|
||||
*conf/nfs_prot/nfs_prot_irix6.h
|
||||
*conf/nfs_prot/nfs_prot_linux.h
|
||||
*conf/nfs_prot/nfs_prot_ncr2.h
|
||||
*conf/nfs_prot/nfs_prot_netbsd.h
|
||||
*conf/nfs_prot/nfs_prot_netbsd1_3.h
|
||||
*conf/nfs_prot/nfs_prot_netbsd1_4.h
|
||||
*conf/nfs_prot/nfs_prot_nextstep.h
|
||||
*conf/nfs_prot/nfs_prot_openbsd.h
|
||||
*conf/nfs_prot/nfs_prot_osf2.h
|
||||
*conf/nfs_prot/nfs_prot_osf4.h
|
||||
*conf/nfs_prot/nfs_prot_osf5.h
|
||||
*conf/nfs_prot/nfs_prot_osf5_1.h
|
||||
*conf/nfs_prot/nfs_prot_sunos3.h
|
||||
*conf/nfs_prot/nfs_prot_sunos4.h
|
||||
*conf/nfs_prot/nfs_prot_sunos5_3.h
|
||||
*conf/nfs_prot/nfs_prot_sunos5_4.h
|
||||
*conf/nfs_prot/nfs_prot_sunos5_5.h
|
||||
*conf/nfs_prot/nfs_prot_sunos5_6.h
|
||||
*conf/nfs_prot/nfs_prot_sunos5_7.h
|
||||
*conf/nfs_prot/nfs_prot_sunos5_8.h
|
||||
*conf/nfs_prot/nfs_prot_svr4.h
|
||||
*conf/nfs_prot/nfs_prot_ultrix.h
|
||||
*conf/autofs/autofs_linux.h
|
||||
*conf/autofs/autofs_linux.c
|
||||
*conf/autofs/autofs_solaris_v1.h
|
||||
*conf/autofs/autofs_solaris_v1.c
|
||||
*conf/autofs/autofs_solaris_v2_v3.h
|
||||
*conf/autofs/autofs_solaris_v2_v3.c
|
||||
*conf/sa_dref/sa_dref_386bsd.h
|
||||
*conf/sa_dref/sa_dref_aix3.h
|
||||
*conf/sa_dref/sa_dref_aoi.h
|
||||
*conf/sa_dref/sa_dref_default.h
|
||||
*conf/sa_dref/sa_dref_isc3.h
|
||||
*conf/sa_dref/sa_dref_linux.h
|
||||
*conf/sa_dref/sa_dref_svr4.h
|
||||
*conf/transp/transp_tli.c
|
||||
*conf/trap/trap_aix3.h
|
||||
*conf/trap/trap_aux.h
|
||||
*conf/trap/trap_dgux.h
|
||||
*conf/trap/trap_freebsd3.h
|
||||
*conf/trap/trap_hcx.h
|
||||
*conf/trap/trap_hpux.h
|
||||
*conf/trap/trap_hpux11.h
|
||||
*conf/trap/trap_irix.h
|
||||
*conf/trap/trap_isc3.h
|
||||
*conf/trap/trap_linux.h
|
||||
*conf/trap/trap_mach3.h
|
||||
*conf/trap/trap_news4.h
|
||||
*conf/trap/trap_rtu6.h
|
||||
*conf/trap/trap_stellix.h
|
||||
*conf/trap/trap_svr4.h
|
||||
*conf/trap/trap_ultrix.h
|
||||
*conf/umount/umount_aix.c
|
||||
*conf/umount/umount_default.c
|
||||
*conf/umount/umount_linux.c
|
||||
*conf/umount/umount_osf.c
|
||||
*doc/Makefile.am
|
||||
*doc/Makefile.in
|
||||
*doc/am-utils.dvi
|
||||
*doc/am-utils.info
|
||||
*doc/am-utils.info-1
|
||||
*doc/am-utils.info-2
|
||||
*doc/am-utils.info-3
|
||||
*doc/am-utils.info-4
|
||||
*doc/am-utils.info-5
|
||||
*doc/am-utils.info-6
|
||||
*doc/am-utils.info-7
|
||||
*doc/am-utils.ps
|
||||
*doc/hlfsd.ps
|
||||
*doc/mdate-sh
|
||||
*fixmount/Makefile.*
|
||||
*fsinfo/Makefile.*
|
||||
*hlfsd/Makefile.*
|
||||
*libamu/Makefile.*
|
||||
*libamu/alloca.c
|
||||
*libamu/clnt_sperrno.c
|
||||
*libamu/memcmp.c
|
||||
*libamu/strcasecmp.c
|
||||
*libamu/strdup.c
|
||||
*libamu/strstr.c
|
||||
*libamu/strlcat.c
|
||||
*libamu/strlcpy.c
|
||||
*libamu/ualarm.c
|
||||
*mk-amd-map/Makefile.*
|
||||
*wire-test/Makefile.*
|
||||
*m4/GNUmakefile
|
||||
*m4/amdgrep*
|
||||
*m4/amindent*
|
||||
*m4/autopat*
|
||||
*m4/chop-aclocal.pl*
|
||||
*m4/copy-if-newbig*
|
||||
*m4/mk-aclocal*
|
||||
*m4/mkconf*
|
||||
*m4/rmtspc*
|
||||
*m4/update_build_version*
|
||||
*m4/macros/HEADER
|
||||
*m4/macros/TRAILER
|
||||
*m4/macros/c_void_p.m4
|
||||
*m4/macros/cache_check_dynamic.m4
|
||||
*m4/macros/check_amu_fs.m4
|
||||
*m4/macros/check_checkmount_style.m4
|
||||
*m4/macros/check_extern.m4
|
||||
*m4/macros/check_fhandle.m4
|
||||
*m4/macros/check_field.m4
|
||||
*m4/macros/check_fs_headers.m4
|
||||
*m4/macros/check_fs_mntent.m4
|
||||
*m4/macros/check_gnu_getopt.m4
|
||||
*m4/macros/check_hide_mount_type.m4
|
||||
*m4/macros/check_lib2.m4
|
||||
*m4/macros/check_map_funcs.m4
|
||||
*m4/macros/check_mnt2_cdfs_opt.m4
|
||||
*m4/macros/check_mnt2_gen_opt.m4
|
||||
*m4/macros/check_mnt2_nfs_opt.m4
|
||||
*m4/macros/check_mnttab_file_name.m4
|
||||
*m4/macros/check_mnttab_location.m4
|
||||
*m4/macros/check_mnttab_opt.m4
|
||||
*m4/macros/check_mnttab_style.m4
|
||||
*m4/macros/check_mnttab_type.m4
|
||||
*m4/macros/check_mount_style.m4
|
||||
*m4/macros/check_mount_trap.m4
|
||||
*m4/macros/check_mount_type.m4
|
||||
*m4/macros/check_mtype_printf_type.m4
|
||||
*m4/macros/check_mtype_type.m4
|
||||
*m4/macros/check_network_transport_type.m4
|
||||
*m4/macros/check_nfs_fh_dref.m4
|
||||
*m4/macros/check_nfs_hn_dref.m4
|
||||
*m4/macros/check_nfs_prot_headers.m4
|
||||
*m4/macros/check_nfs_sa_dref.m4
|
||||
*m4/macros/check_nfs_socket_connection.m4
|
||||
*m4/macros/check_os_libs.m4
|
||||
*m4/macros/check_restartable_signal_handler.m4
|
||||
*m4/macros/check_umount_style.m4
|
||||
*m4/macros/check_unmount_args.m4
|
||||
*m4/macros/check_unmount_call.m4
|
||||
*m4/macros/expand_cpp_hex.m4
|
||||
*m4/macros/expand_cpp_int.m4
|
||||
*m4/macros/expand_cpp_string.m4
|
||||
*m4/macros/expand_run_string.m4
|
||||
*m4/macros/extern_optarg.m4
|
||||
*m4/macros/extern_sys_errlist.m4
|
||||
*m4/macros/field_mntent_t_mnt_time_string.m4
|
||||
*m4/macros/func_bad_memcmp.m4
|
||||
*m4/macros/func_bad_yp_all.m4
|
||||
*m4/macros/header_templates.m4
|
||||
*m4/macros/host_macros.m4
|
||||
*m4/macros/linux_headers.m4
|
||||
*m4/macros/localconfig.m4
|
||||
*m4/macros/mount_headers.m4
|
||||
*m4/macros/name_package.m4
|
||||
*m4/macros/name_version.m4
|
||||
*m4/macros/opt_amu_cflags.m4
|
||||
*m4/macros/opt_cppflags.m4
|
||||
*m4/macros/opt_debug.m4
|
||||
*m4/macros/opt_ldflags.m4
|
||||
*m4/macros/opt_libs.m4
|
||||
*m4/macros/os_cflags.m4
|
||||
*m4/macros/os_cppflags.m4
|
||||
*m4/macros/os_ldflags.m4
|
||||
*m4/macros/package_bugreport.m4
|
||||
*m4/macros/package_name.m4
|
||||
*m4/macros/package_version.m4
|
||||
*m4/macros/save_state.m4
|
||||
*m4/macros/struct_field_nfs_fh.m4
|
||||
*m4/macros/struct_mntent.m4
|
||||
*m4/macros/struct_mnttab.m4
|
||||
*m4/macros/struct_nfs_args.m4
|
||||
*m4/macros/struct_nfs_fh.m4
|
||||
*m4/macros/struct_nfs_fh3.m4
|
||||
*m4/macros/struct_nfs_gfs_mount.m4
|
||||
*m4/macros/try_compile_anyfs.m4
|
||||
*m4/macros/try_compile_nfs.m4
|
||||
*m4/macros/try_compile_rpc.m4
|
||||
*m4/macros/type_auth_create_gidlist.m4
|
||||
*m4/macros/type_cachefs_args.m4
|
||||
*m4/macros/type_cdfs_args.m4
|
||||
*m4/macros/type_efs_args.m4
|
||||
*m4/macros/type_lofs_args.m4
|
||||
*m4/macros/type_mfs_args.m4
|
||||
*m4/macros/type_pcfs_args.m4
|
||||
*m4/macros/type_recvfrom_fromlen.m4
|
||||
*m4/macros/type_rfs_args.m4
|
||||
*m4/macros/type_svc_in_arg.m4
|
||||
*m4/macros/type_time_t.m4
|
||||
*m4/macros/type_tmpfs_args.m4
|
||||
*m4/macros/type_ufs_args.m4
|
||||
*m4/macros/type_xdrproc_t.m4
|
||||
*m4/macros/type_xfs_args.m4
|
||||
*m4/macros/type_yp_order_outorder.m4
|
||||
*m4/macros/with_addon.m4
|
@ -1,103 +0,0 @@
|
||||
# ex:ts=8
|
||||
$FreeBSD$
|
||||
|
||||
AMD (am-utils) 6.1.5
|
||||
originals can be found at: ftp://ftp.am-utils.org/pub/am-utils/
|
||||
|
||||
For the import of AMD many files were pruned by:
|
||||
|
||||
tar -X FREEBSD-Xlist -xf am-utils-6.1.5.tar.gz
|
||||
|
||||
and `find . -name '.cvsignore' -delete`
|
||||
|
||||
Then imported by:
|
||||
|
||||
cvs import -m 'Virgin import of AMD (am-utils) v6.1.5' \
|
||||
src/contrib/amd COLUMBIA amd_6_1_5
|
||||
|
||||
After the import, a separate extraction of am-utils was GNU configured in
|
||||
the "normal" way. The resulting config.h file should be compared with
|
||||
src/usr.sbin/amd/include/config.h, and src/usr.sbin/amd/include/config.h
|
||||
updated as needed.
|
||||
|
||||
To make local changes to amd, simply patch and commit to the main
|
||||
branch (aka HEAD). Never make local changes on the vendor (COLUMBIA) branch.
|
||||
|
||||
Note, we don't trim anything in scripts/ as sysadmins may find the bits
|
||||
as a useful reference.
|
||||
|
||||
All local changes should be submitted to "am-utils@am-utils.org" or
|
||||
https://bugzilla.am-utils.org for inclusion in the next vendor release.
|
||||
|
||||
Local changes:
|
||||
|
||||
amd/amd.8
|
||||
- corrected formatting of SEE ALSO
|
||||
r1.17 Uniformly refer to a file system as "file system"
|
||||
r1.16 Add the am-utils homepage to SEE ALSO
|
||||
r1.15 s/BSD/.Bx/ where appropriate
|
||||
r1.14 Avoid using parenthesis enclosure macros
|
||||
r1.13 split punctuation characters + misc fixes
|
||||
r1.12 mdoc(7)NG
|
||||
r1.11 Catch a left over reference to "/a"
|
||||
r1.10 Document change to the default mount dir.
|
||||
r1.9 Mention "amd -H" in the synopsis
|
||||
r1.8 Fix miscellaneous mdoc macro argument limit infringements
|
||||
r1.7 Don't refer to non-existent automount(8)
|
||||
r1.6 Fix errors in .Xr usage
|
||||
r1.3 un-mandocafied, un4.4BSD'ed
|
||||
r1.2 sort cross references
|
||||
amd/amd.c
|
||||
r1.7 use /.amd_mnt as default for -a
|
||||
amq/amq.8
|
||||
r1.9 Uniformly refer to a file system as "file system".
|
||||
r1.8 s/BSD/.Bx/ where appropriate.
|
||||
r1.6 mdoc(7)NG.
|
||||
r1.5 Remove reference to non-existent manpage
|
||||
r1.4 Fix typos
|
||||
r1.3 un-mandocafied, un4.4BSD'ed
|
||||
amq/pawd.1
|
||||
r1.3 un-mandocafied, un4.4BSD'ed
|
||||
r1.2 sorting of references
|
||||
conf/nfs_prot/nfs_prot_freebsd3.h
|
||||
r1.11 Userland part of nfs client/server split and cleanup
|
||||
r1.6 restore the standard name nfs_fh3
|
||||
r1.3 Fully use our own generated files for NFSv3
|
||||
r1.2 rpcgen our own files for NFSv3 support
|
||||
fixmount/fixmount.8
|
||||
r1.8 Uniformly refer to a file system as "file system"
|
||||
r1.6 split punctuation characters + misc fixes.
|
||||
r1.5 mdoc(7)NG.
|
||||
r1.4 ".Mn mountd" -> ".Nm mountd"
|
||||
r1.3 un-mandocafied, un4.4BSD'ed
|
||||
r1.2 More sorting of references.
|
||||
fsinfo/fsinfo.8
|
||||
r1.9 add section number to .Xr directive
|
||||
r1.7 Uniformly refer to a file system as "file system"
|
||||
r1.6 split punctuation characters + misc fixes
|
||||
r1.5 mdoc(7)NG
|
||||
r1.3 describe all of the command line options
|
||||
r1.2 un-mandocafied, un4.4BSD'ed
|
||||
hlfsd/hlfsd.8
|
||||
- Fix a broken SEE ALSO section and some mdoc issues
|
||||
mk-amd-map/mk-amd-map.8
|
||||
r1.4 removed HISTORY info from the .Os call.
|
||||
r1.2 un-mandocafied, un4.4BSD'ed
|
||||
scripts/amd.conf.5
|
||||
r1.15 Bring man page back in shape
|
||||
r1.13 Uniformly refer to a file system as "file system"
|
||||
r1.12 Avoid using parenthesis enclosure macros
|
||||
r1.11 mdoc(7)NG
|
||||
r1.10 Fix miscellaneous mdoc macro argument limit infringements
|
||||
r1.8 Fix a bunch of broken cross-references
|
||||
r1.7 Bad reference of uname(2) -> uname(3)
|
||||
r1.6 Grammer fix and style nits.
|
||||
r1.5 xfer typo
|
||||
r1.4 un-mandocafied, un4.4BSD'ed
|
||||
r1.3 More sorting of references.
|
||||
wire-test/wire-test.8
|
||||
r1.2 un-mandocafied, un4.4BSD'ed
|
||||
|
||||
mbr@FreeBSD.org
|
||||
obrien@NUXI.com
|
||||
05-November-1999
|
@ -1,370 +0,0 @@
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. This file is offered as-is,
|
||||
without warranty of any kind.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
Briefly, the shell command `./configure && make && make install'
|
||||
should configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
instructions specific to this package. Some packages provide this
|
||||
`INSTALL' file but do not implement all of the features documented
|
||||
below. The lack of an optional feature in a given package is not
|
||||
necessarily a bug. More recommendations for GNU packages can be found
|
||||
in *note Makefile Conventions: (standards)Makefile Conventions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||
you want to change it or regenerate `configure' using a newer version
|
||||
of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system.
|
||||
|
||||
Running `configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package, generally using the just-built uninstalled binaries.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation. When installing into a prefix owned by root, it is
|
||||
recommended that the package be configured and built as a regular
|
||||
user, and only the `make install' phase executed with root
|
||||
privileges.
|
||||
|
||||
5. Optionally, type `make installcheck' to repeat any self-tests, but
|
||||
this time using the binaries in their final installed location.
|
||||
This target does not install anything. Running this target as a
|
||||
regular user, particularly if the prior `make install' required
|
||||
root privileges, verifies that the installation completed
|
||||
correctly.
|
||||
|
||||
6. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
7. Often, you can also type `make uninstall' to remove the installed
|
||||
files again. In practice, not all packages have tested that
|
||||
uninstallation works correctly, even though it is required by the
|
||||
GNU Coding Standards.
|
||||
|
||||
8. Some packages, particularly those that use Automake, provide `make
|
||||
distcheck', which can by used by developers to test that all other
|
||||
targets like `make install' and `make uninstall' work correctly.
|
||||
This target is generally not run by end users.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the `configure' script does not know about. Run `./configure --help'
|
||||
for details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'. This
|
||||
is known as a "VPATH" build.
|
||||
|
||||
With a non-GNU `make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use `make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
On MacOS X 10.5 and later systems, you can create libraries and
|
||||
executables that work on multiple system types--known as "fat" or
|
||||
"universal" binaries--by specifying multiple `-arch' options to the
|
||||
compiler but only a single `-arch' option to the preprocessor. Like
|
||||
this:
|
||||
|
||||
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CPP="gcc -E" CXXCPP="g++ -E"
|
||||
|
||||
This is not guaranteed to produce working output in all cases, you
|
||||
may have to build one architecture at a time and combine the results
|
||||
using the `lipo' tool if you have problems.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX', where PREFIX must be an
|
||||
absolute file name.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them. In general, the
|
||||
default for these options is expressed in terms of `${prefix}', so that
|
||||
specifying just `--prefix' will affect all of the other directory
|
||||
specifications that were not explicitly provided.
|
||||
|
||||
The most portable way to affect installation locations is to pass the
|
||||
correct locations to `configure'; however, many packages provide one or
|
||||
both of the following shortcuts of passing variable assignments to the
|
||||
`make install' command line to change installation locations without
|
||||
having to reconfigure or recompile.
|
||||
|
||||
The first method involves providing an override variable for each
|
||||
affected directory. For example, `make install
|
||||
prefix=/alternate/directory' will choose an alternate location for all
|
||||
directory configuration variables that were expressed in terms of
|
||||
`${prefix}'. Any directories that were specified during `configure',
|
||||
but not in terms of `${prefix}', must each be overridden at install
|
||||
time for the entire installation to be relocated. The approach of
|
||||
makefile variable overrides for each directory variable is required by
|
||||
the GNU Coding Standards, and ideally causes no recompilation.
|
||||
However, some platforms have known limitations with the semantics of
|
||||
shared libraries that end up requiring recompilation when using this
|
||||
method, particularly noticeable in packages that use GNU Libtool.
|
||||
|
||||
The second method involves providing the `DESTDIR' variable. For
|
||||
example, `make install DESTDIR=/alternate/directory' will prepend
|
||||
`/alternate/directory' before all installation names. The approach of
|
||||
`DESTDIR' overrides is not required by the GNU Coding Standards, and
|
||||
does not work on platforms that have drive letters. On the other hand,
|
||||
it does better at avoiding recompilation issues, and works well even
|
||||
when some directory options were not specified in terms of `${prefix}'
|
||||
at `configure' time.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Some packages offer the ability to configure how verbose the
|
||||
execution of `make' will be. For these packages, running `./configure
|
||||
--enable-silent-rules' sets the default to minimal output, which can be
|
||||
overridden with `make V=1'; while running `./configure
|
||||
--disable-silent-rules' sets the default to verbose, which can be
|
||||
overridden with `make V=0'.
|
||||
|
||||
Particular systems
|
||||
==================
|
||||
|
||||
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
|
||||
CC is not installed, it is recommended to use the following options in
|
||||
order to use an ANSI C compiler:
|
||||
|
||||
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
|
||||
|
||||
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||
|
||||
HP-UX `make' updates targets which have the same time stamps as
|
||||
their prerequisites, which makes it generally unusable when shipped
|
||||
generated files such as `configure' are involved. Use GNU `make'
|
||||
instead.
|
||||
|
||||
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
|
||||
a workaround. If GNU CC is not installed, it is therefore recommended
|
||||
to try
|
||||
|
||||
./configure CC="cc"
|
||||
|
||||
and if that doesn't work, try
|
||||
|
||||
./configure CC="cc -nodtk"
|
||||
|
||||
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
|
||||
directory contains several dysfunctional programs; working variants of
|
||||
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
|
||||
in your `PATH', put it _after_ `/usr/bin'.
|
||||
|
||||
On Haiku, software installed for all users goes in `/boot/common',
|
||||
not `/usr/local'. It is recommended to use the following options:
|
||||
|
||||
./configure --prefix=/boot/common
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out
|
||||
automatically, but needs to determine by the type of machine the package
|
||||
will run on. Usually, assuming the package is built to be run on the
|
||||
_same_ architectures, `configure' can figure that out, but if it prints
|
||||
a message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS
|
||||
KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share,
|
||||
you can create a site shell script called `config.site' that gives
|
||||
default values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||
an Autoconf limitation. Until the limitation is lifted, you can use
|
||||
this workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of all of the options to `configure', and exit.
|
||||
|
||||
`--help=short'
|
||||
`--help=recursive'
|
||||
Print a summary of the options unique to this package's
|
||||
`configure', and exit. The `short' variant lists options used
|
||||
only in the top level, while the `recursive' variant lists options
|
||||
also present in any nested packages.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`--prefix=DIR'
|
||||
Use DIR as the installation prefix. *note Installation Names::
|
||||
for more details, including other options available for fine-tuning
|
||||
the installation locations.
|
||||
|
||||
`--no-create'
|
||||
`-n'
|
||||
Run the configure checks, but stop before creating any output
|
||||
files.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
@ -1,106 +0,0 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
|
||||
<META NAME="Author" CONTENT="Erez Zadok">
|
||||
<TITLE>Am-Utils 6.x Mirror Sites</TITLE>
|
||||
</HEAD>
|
||||
<BODY BGCOLOR="#FFFFFF">
|
||||
|
||||
<CENTER>
|
||||
<H1> Am-Utils 6.x Software Mirror Sites</H1></CENTER>
|
||||
|
||||
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
|
||||
"am-utils-developers AT am-utils.org" with the
|
||||
full URL, maintainer's email, and geographical location.
|
||||
|
||||
<P>
|
||||
|
||||
<H2>North America</H2>
|
||||
<UL>
|
||||
|
||||
<LI> New York (Stony Brook, Primary Site)
|
||||
<UL>
|
||||
<LI> FTP: <A
|
||||
HREF="ftp://ftp.am-utils.org/pub/am-utils">ftp.am-utils.org</A>.
|
||||
Contact person in case of problems
|
||||
"am-utils-developers AT am-utils.org".
|
||||
</LI>
|
||||
</UL>
|
||||
|
||||
<LI> Minnesota
|
||||
<UL>
|
||||
<LI> FTP: <A
|
||||
HREF="ftp://ftp.cs.umn.edu/pub/am-utils">ftp.cs.umn.edu</A>.
|
||||
Maintainer <A HREF="mailto:dokas AT cs.umn.edu">dokas AT cs.umn.edu</A>.
|
||||
</LI>
|
||||
</UL>
|
||||
|
||||
<LI> Florida (University of Florida)
|
||||
<UL>
|
||||
<LI> FTP: <A HREF="ftp://ftp.cise.ufl.edu/pub/mirrors/am-utils">ftp.cise.ufl.edu</A>.
|
||||
Maintainer <A HREF="mailto:mirror AT cise.ufl.edu">mirror AT cise.ufl.edu</A>.
|
||||
</LI>
|
||||
</UL>
|
||||
|
||||
</UL>
|
||||
|
||||
<H2>Europe</H2>
|
||||
<UL>
|
||||
|
||||
<LI> Germany
|
||||
<UL>
|
||||
<LI> FTP: <A HREF="ftp://ftp.fu-berlin.de/unix/network/am-utils">ftp.fu-berlin.de</A>.
|
||||
Maintainer <A HREF="mailto:ftp-adm AT ftp.fu-berlin.de">ftp-adm AT ftp.fu-berlin.de</A>.
|
||||
</LI>
|
||||
<LI> FTP: <A HREF="ftp://ftp.tu-darmstadt.de/pub/networking/filesystems/am-utils/">ftp.tu-darmstadt.de</A>.
|
||||
Maintainer <A HREF="mailto:networking AT ftp.tu-darmstadt.de">networking AT ftp.tu-darmstadt.de</A>.
|
||||
</LI>
|
||||
</UL>
|
||||
|
||||
<LI> Sweden
|
||||
<UL>
|
||||
<LI> FTP: <A HREF="ftp://ftp.sunet.se/pub/unix/admin/am-utils">ftp.sunet.se</A>.
|
||||
Maintainer <A HREF="mailto:archive AT ftp.sunet.se">archive AT ftp.sunet.se</A>.
|
||||
</LI>
|
||||
</UL>
|
||||
|
||||
<LI> UK
|
||||
<UL>
|
||||
<LI> FTP: <A HREF="ftp://sunsite.org.uk/package/am-utils">sunsite.org.uk</A>.
|
||||
Maintainer <A HREF="mailto:lmjm AT icparc.ic.ac.uk">lmjm AT icparc.ic.ac.uk</A>.
|
||||
</LI>
|
||||
</UL>
|
||||
|
||||
</UL>
|
||||
|
||||
<H2>Asia</H2>
|
||||
<UL>
|
||||
|
||||
<LI> Japan
|
||||
<UL>
|
||||
<LI> FTP: <A HREF="ftp://ftp.u-aizu.ac.jp/pub/net/amd/am-utils">ftp.u-aizu.ac.jp</A>.
|
||||
Maintainer <A HREF="mailto:ftp-admin AT u-aizu.ac.jp">ftp-admin AT u-aizu.ac.jp</A>.
|
||||
</LI>
|
||||
|
||||
<LI> FTP: <A HREF="ftp://core.ring.gr.jp/pub/net/am-utils/">core.ring.gr.jp</A>.
|
||||
Maintainer <A HREF="mailto:ftpadmin AT ring.gr.jp">ftpadmin AT ring.gr.jp</A>.
|
||||
</LI>
|
||||
|
||||
<LI> FTP: <A HREF="ftp://ftp.ring.gr.jp/pub/net/am-utils/">ftp.ring.gr.jp</A>.
|
||||
Maintainer <A HREF="mailto:ftpadmin AT ring.gr.jp">ftpadmin AT ring.gr.jp</A>.
|
||||
</LI>
|
||||
</UL>
|
||||
</UL>
|
||||
|
||||
<HR>
|
||||
<I> Last updated: 2006-11-27</I>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
<!---
|
||||
<LI> FTP: <A HREF="X">X</A>.
|
||||
Maintainer <A HREF="mailto:X">X</A>.
|
||||
-->
|
@ -1,60 +0,0 @@
|
||||
AM-UTILS-6.x 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 am-utils-developers AT am-utils.org
|
||||
with the full URL, maintainer's email, and geographical location.
|
||||
|
||||
U.S.A:
|
||||
New York (Stony Brook, Primary Site):
|
||||
ftp://ftp.am-utils.org/pub/am-utils
|
||||
Maintainer: ezk AT am-utils.org
|
||||
Minnesota:
|
||||
ftp://ftp.cs.umn.edu/pub/am-utils
|
||||
Maintainer: dokas AT cs.umn.edu
|
||||
#Avoid for now: empty directory
|
||||
# Virginia (Newport News):
|
||||
# ftp://ftp.ferginc.com/pub/unix/am-utils
|
||||
# Maintainer: Branson.Matheson AT FergInc.com
|
||||
#server gone? (Jan 5, 2004)
|
||||
# Ohio (Kent State University):
|
||||
# ftp://info.mcs.kent.edu/pub/am-utils
|
||||
# Maintainer: root AT mcs.kent.edu
|
||||
Florida (University of Florida)
|
||||
ftp://ftp.cise.ufl.edu/pub/mirrors/am-utils
|
||||
Maintainer: mirror AT cise.ufl.edu
|
||||
|
||||
Europe:
|
||||
Germany:
|
||||
ftp://ftp.fu-berlin.de/unix/network/am-utils
|
||||
Maintainer: ftp-adm AT ftp.fu-berlin.de
|
||||
Germany:
|
||||
ftp://ftp.tu-darmstadt.de/pub/networking/filesystems/am-utils/
|
||||
Maintainer: networking AT ftp.tu-darmstadt.de
|
||||
Sweden:
|
||||
ftp://ftp.sunet.se/pub/unix/admin/am-utils
|
||||
Maintainer: archive AT ftp.sunet.se
|
||||
# not responding (Jan 5, 2004)
|
||||
# Sweden (Stockholm University, Math Depat):
|
||||
# ftp://mirror.matematik.su.se/pub/am-utils
|
||||
# Maintainer: leifj AT matematik.su.se
|
||||
UK:
|
||||
ftp://sunsite.org.uk/package/am-utils
|
||||
Maintainer: lmjm AT icparc.ic.ac.uk
|
||||
|
||||
Asia:
|
||||
Japan:
|
||||
ftp://ftp.u-aizu.ac.jp/pub/net/amd/am-utils
|
||||
Maintainer: ftp-admin AT u-aizu.ac.jp
|
||||
Japan:
|
||||
ftp://core.ring.gr.jp/pub/net/am-utils/
|
||||
Maintainer: ftpadmin AT ring.gr.jp
|
||||
Japan:
|
||||
ftp://ftp.ring.gr.jp/pub/net/am-utils/
|
||||
Maintainer: ftpadmin AT ring.gr.jp
|
||||
|
||||
# gone? (Jan 5, 2004)
|
||||
# Australia:
|
||||
# Melbourne:
|
||||
# ftp://ftp.sage-au.org.au/pub/network/filesystem/am-utils
|
||||
# Maintainer: mirror AT ftp.sage-au.org.au
|
1567
contrib/amd/NEWS
1567
contrib/amd/NEWS
File diff suppressed because it is too large
Load Diff
@ -1,104 +0,0 @@
|
||||
This is the official version of am-utils.
|
||||
|
||||
See the file NEWS for news on this and previous releases.
|
||||
|
||||
*** General Notes to alpha/beta testers:
|
||||
|
||||
[A] as alpha/beta 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 does precisely that, using the A.* subdirectories.
|
||||
|
||||
(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 m4/ or conf/ directories, or any *.in
|
||||
or *.am file, then you must rebuild the configure script, Makefile.in files,
|
||||
aclocal.m4, etc. The best way to do so is to run
|
||||
|
||||
./bootstrap
|
||||
or
|
||||
./buildall -K
|
||||
|
||||
To be a developer and be able to run "bootstrap", you must have
|
||||
autoconf-2.68, automake-1.11.1, and libtool 2.2.6b installed on your system (or
|
||||
later versions thereof). You no longer need to get my special version of
|
||||
automake. Contact me if you'd like to be a maintainer and get access to the
|
||||
CVS server.
|
||||
|
||||
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 via Bugzilla or the am-utils list (see
|
||||
www.am-utils.org). 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.
|
@ -1,129 +0,0 @@
|
||||
NFS Attribute Caching OS Problems and Amd
|
||||
Last updated September 18, 2005
|
||||
|
||||
* Summary:
|
||||
|
||||
Some OSs don't seem to have a way to turn off the NFS attribute cache, which
|
||||
breaks the Amd automounter so badly that it is not recommend using Amd on
|
||||
such OS for heavy use, not until this is fixed.
|
||||
|
||||
|
||||
* Details:
|
||||
|
||||
Amd is a user-level NFSv2 server that manages automounts of all other file
|
||||
systems. The kernel contacts Amd via RPCs, and Amd in turn performs the
|
||||
actual mounts, and then responds back to the kernel's RPCs. Every kernel
|
||||
caches attributes of files, in a cache called the Directory Name Lookup
|
||||
Cache (DNLC), or a Directory Cache (dcache).
|
||||
|
||||
Amd manages its namespace in the user level, but the kernel caches names
|
||||
itself. So the two must coordinate to ensure that both namespaces are in
|
||||
sync. If the kernel uses a cached entry from the DNLC, without consulting
|
||||
Amd, users may see corruption of the automounter namespace (symlinks
|
||||
pointing to the wrong places, ESTALE errors, and more). For example,
|
||||
suppose Amd timed out an entry and removed the entry from Amd's namespace.
|
||||
Amd has to tell the kernel to purge its corresponding DNLC entry too. The
|
||||
way Amd often does that is by incrementing the last modification time
|
||||
(mtime) of the parent directory. This is the most common method for kernels
|
||||
to check if their DNLC entries are stale: if the parent directory mtime is
|
||||
newer, the kernel will discard all cached entries for that directory, and
|
||||
will re-issue lookup methods. Those lookups will result in
|
||||
NFS_GETATTR/NFS_LOOKUP calls sent from the kernel down to Amd, and Amd can
|
||||
then properly inform the kernel of the new state of automounted entries.
|
||||
|
||||
In order to ensure that Amd is "in charge" of its namespace without
|
||||
interference from the kernel, Amd will try to turn off the NFS attribute
|
||||
cache. It does so by using the NFSMNT_NOAC flag, if it exists, or by
|
||||
setting various "cache timeout" fields in struct nfs_args to 0 (acregmin,
|
||||
acregmax, acdirmin, or acdirmax).
|
||||
|
||||
We have released a major new version of am-utils, version 6.1, in June 2005.
|
||||
Since then, a lot of people have experimented with Amd, in anticipation of
|
||||
migrating from the very old am-utils 6.0 to the new 6.1. For a couple of
|
||||
months since the release of 6.1, we have received reports of problems with
|
||||
Amd, especially under heavy use. Users reported getting ESTALE errors from
|
||||
time to time, or seeing automounted entries whose symlinks don't point to
|
||||
where it should be. After much debugging, we traced it to a few places in
|
||||
Amd where it wasn't updating the parent directory mtime as it should have;
|
||||
in some places where Amd was indeed updating the mtime, it was using a
|
||||
resolution of only 1 second, which was not fine enough under heavy load. We
|
||||
fixed this problem and switched to using a microsecond resolution mtime.
|
||||
|
||||
After fixing this in Amd, we went on to verify that things work for other
|
||||
OSs. When we got to test certain BSDs, we found out that they always cache
|
||||
directory entries, and there is no way to turn it off completely.
|
||||
Specifically, if we set the ac{reg,dir}{min,max} fields in struct nfs_args
|
||||
all to zero, the kernel seems to cache the entries for a default number of
|
||||
seconds (something like 5-30 seconds). On some OSs, setting these four
|
||||
fields to 0 turns off the attribute cache, but not on some BSDs. We were
|
||||
able to verify this using Amd and a script that exercises the interaction of
|
||||
the kernel's attrcache and Amd. (If you're interested, the script can be
|
||||
made available.)
|
||||
|
||||
We then experimented by setting the ac{reg,dir}{min,max} fields in struct
|
||||
nfs_args all to 1, the smallest non-zero value we could. When we ran the
|
||||
Amd exercising script, we found that the value of 1 reduced the race between
|
||||
the DNLC and Amd, and the script took a little longer to run before it
|
||||
detected an incoherency. That makes sense: the smaller the DNLC cache
|
||||
interval is, the shorter the window of vulnerability is. (BTW, the man
|
||||
pages on some OSs say that the ac{reg,dir}{min,max} fields use a 1 second
|
||||
resolution, but experimentation indicated it was in 0.1 second units.)
|
||||
|
||||
Clearly, setting the ac{reg,dir}{min,max} fields to 0 is worse than setting
|
||||
it to 1 on those OSs that don't have a way to turn off the attribute cache.
|
||||
So the current workaround I've implemented in am-utils is to create a
|
||||
configuration parameter called "broken_attrcache" which, if turned on, will
|
||||
set these nfs_args fields to 1 instead of 0. I wish I didn't have to create
|
||||
such ugly workaround features in Amd, but I've got no choice.
|
||||
|
||||
The near term solution is for every OS to support a true 'noac' flag, which
|
||||
can be added fairly easily. This'd make Amd work reliably.
|
||||
|
||||
The long term solution is to implement Autofs support for all OSs and to
|
||||
support it in Amd. Currently, Amd supports autofs on Solaris and Linux;
|
||||
FreeBSD is next. Still, we found that even with autofs support, many
|
||||
sysadmins still prefer to use the good 'ol non-autofs mode.
|
||||
|
||||
|
||||
* Confirmed Status
|
||||
|
||||
This is the confirmed status of various OSs' vulnerability to this attribute
|
||||
cache bug. We are slowly checking the status of other OSs. The status of
|
||||
any OS not listed is unknown as of the date at the top of this file.
|
||||
|
||||
** Not Vulnerable (support a proper "noac" flag):
|
||||
|
||||
Sun Solaris 8 and 9 (10 probably works fine)
|
||||
Linux: 2.6.11 kernel (2.4.latest probably works fine)
|
||||
FreeBSD 5.4 and 6.0-SNAP001 (older versions probably work fine)
|
||||
OpenBSD 3.7 (older versions probably work fine)
|
||||
|
||||
** Vulnerable (don't support a proper "noac" flag natively):
|
||||
|
||||
NetBSD 2.0.2 (older versions are also probably affected)
|
||||
|
||||
Note: NetBSD has promised to support a noac flag hopefully after 2.1.0 is
|
||||
released (maybe in 3.0 or 2.2). In the mean time, you can apply one of
|
||||
these two kernel patchs to support a 'noac' flag in NetBSD 2.x or 3.x:
|
||||
ftp://ftp.netbsd.org/pub/NetBSD/misc/christos/2x.nfs.noac.diff
|
||||
ftp://ftp.netbsd.org/pub/NetBSD/misc/christos/3x.nfs.noac.diff
|
||||
After applying this patch and rebuilding your kernel, reboot with the new
|
||||
kernel. Then copy the new nfs.h and nfsmount.h from /sys/nfs/ to
|
||||
/usr/include/nfs/, and finally rebuild am-utils from scratch.
|
||||
|
||||
** Testing
|
||||
|
||||
When you build am-utils, a script named scripts/test-attrcache is built,
|
||||
which can be used to test the NFS attribute cache behavior of the current
|
||||
OS. You can run this script as root as follows:
|
||||
|
||||
# make install
|
||||
# cd scripts
|
||||
# sh test-attrcache
|
||||
|
||||
If you run this script on an OS whose status is known (and not listed
|
||||
above), please report it to us via Bugzilla or the am-utils mailing list
|
||||
(see www.am-utils.org), so we can record it in this file.
|
||||
|
||||
Sincerely,
|
||||
Erez.
|
@ -1,57 +0,0 @@
|
||||
LDAP support for am-utils was originally done by Leif Johansson
|
||||
<leifj AT it.su.se>. He no longer maintains it.
|
||||
|
||||
The current LDAP support for am-utils is for LDAPv2 only. Reportedly,
|
||||
LDAPv3 mostly works. Volunteers and patches are welcome.
|
||||
|
||||
The IANA has assigned the following Private Enterprise Number to:
|
||||
|
||||
10180 Am-utils Organization Erez Zadok ezk AT am-utils.org
|
||||
|
||||
There are three files in this directory that relate to LDAP:
|
||||
|
||||
ldap.schema:
|
||||
|
||||
This is the most current schema.
|
||||
|
||||
ldap-id.txt:
|
||||
|
||||
This is an experimental schema for amd mount maps in LDAP. Since
|
||||
LDAP isn't maintained now, this code may not match with either the
|
||||
current ldap_info.c code or with Amd mount maps in general.
|
||||
|
||||
The schema is written in the form of an internet-draft but it has
|
||||
not been published as such. We need volunteers who know and use
|
||||
LDAP to clean it up and further its process of submission.
|
||||
|
||||
ldap-id.ms:
|
||||
|
||||
This is the NROFF source of the draft. To generate the text from
|
||||
it, run "nroff -ms ldap-id.ms > ldap-id.txt"
|
||||
|
||||
Erez.
|
||||
|
||||
------- Forwarded Message
|
||||
|
||||
From: "IANA Private Enterprise Number" <iana-pen AT icann.org>
|
||||
To: "Erez Zadok" <ezk AT cs.columbia.edu>
|
||||
Subject: RE: Application for Enterprise-number (10180)
|
||||
Date: Sun, 15 Jul 2001 14:43:45 -0700
|
||||
|
||||
Dear Erez,
|
||||
|
||||
The IANA has assigned the following Private Enterprise
|
||||
Number to:
|
||||
|
||||
10180 Am-utils Organization Erez Zadok ezk AT am-utils.org
|
||||
|
||||
Please notify the IANA if there is a change in your contact
|
||||
or company information.
|
||||
|
||||
Thank you,
|
||||
|
||||
Bill Huang
|
||||
IANA - Private Enterprise Numbers
|
||||
|
||||
------- End of Forwarded Message
|
||||
|
@ -1,26 +0,0 @@
|
||||
AM-UTILS YEAR-2000 COMPLIANCE
|
||||
|
||||
Most likely am-utils is y2k compliant.
|
||||
|
||||
I do not know for sure because I have not certified am-utils myself, nor do
|
||||
I have the time for it. I do not think that amd will be affected by y2k at
|
||||
all, because it does not do anything with dates other than print the date on
|
||||
the log file, in whatever format is provided by your os/libc --- especially
|
||||
the ctime(3) call.
|
||||
|
||||
However, on Friday, September 18th 1998, Matthew Crosby <mcrosby AT ms.com>
|
||||
reported that they evaluated 6.0a16 and found it to be compliant.
|
||||
|
||||
On March 26, 1999, Paul Balyoz <pbalyoz AT sedona.ch.intel.com> submitted a
|
||||
patch to lostaltmail which makes it print Y2K compliant dates. He used a
|
||||
code scanner and manually "eyeballed" the code and could not find any more
|
||||
problems. Paul's patch is included in am-utils-6.0.1s7 and newer versions.
|
||||
Paul also said that other 2-digit years used in am-utils are "harmless."
|
||||
|
||||
NOTE: NONE OF THE PERSONS MENTIONED HERE, AUTHOR INCLUDED, ARE WILLING TO
|
||||
CERTIFY AM-UTILS AS Y2K COMPLIANT. USE AT YOUR OWN RISK.
|
||||
|
||||
---
|
||||
Erez Zadok.
|
||||
Maintainer, am-utils package and am-utils list.
|
||||
WWW: http://www.am-utils.org
|
@ -1,484 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/am_ops.c
|
||||
*
|
||||
*/
|
||||
|
||||
#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_AMU_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_AMU_FS_LINK
|
||||
&amfs_link_ops, /* symlink F/S */
|
||||
#endif /* HAVE_AMU_FS_LINK */
|
||||
|
||||
/*
|
||||
* Other amd-supported meta-filesystems.
|
||||
*/
|
||||
#ifdef HAVE_AMU_FS_NFSX
|
||||
&amfs_nfsx_ops, /* multiple-nfs F/S */
|
||||
#endif /* HAVE_AMU_FS_NFSX */
|
||||
#ifdef HAVE_AMU_FS_NFSL
|
||||
&amfs_nfsl_ops, /* NFS with local link existence check */
|
||||
#endif /* HAVE_AMU_FS_NFSL */
|
||||
#ifdef HAVE_AMU_FS_HOST
|
||||
&amfs_host_ops, /* multiple exported nfs F/S */
|
||||
#endif /* HAVE_AMU_FS_HOST */
|
||||
#ifdef HAVE_AMU_FS_LINKX
|
||||
&amfs_linkx_ops, /* symlink F/S with link target verify */
|
||||
#endif /* HAVE_AMU_FS_LINKX */
|
||||
#ifdef HAVE_AMU_FS_PROGRAM
|
||||
&amfs_program_ops, /* program F/S */
|
||||
#endif /* HAVE_AMU_FS_PROGRAM */
|
||||
#ifdef HAVE_AMU_FS_UNION
|
||||
&amfs_union_ops, /* union F/S */
|
||||
#endif /* HAVE_AMU_FS_UNION */
|
||||
|
||||
/*
|
||||
* 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_EXT
|
||||
&ext2_ops, /* Unix (linux) F/S */
|
||||
&ext3_ops, /* Unix (linux) F/S */
|
||||
&ext4_ops, /* Unix (linux) F/S */
|
||||
#endif /* HAVE_FS_EXT */
|
||||
#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_TMPFS
|
||||
&tmpfs_ops, /* /tmp (in memory) F/S */
|
||||
#endif /* HAVE_FS_TMPFS */
|
||||
#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 */
|
||||
#ifdef HAVE_FS_UDF
|
||||
&udf_ops, /* UDF F/S */
|
||||
#endif /* HAVE_FS_UDF */
|
||||
#ifdef HAVE_FS_LUSTRE
|
||||
&lustre_ops, /* Lustre */
|
||||
#endif /* HAVE_FS_LUSTRE */
|
||||
|
||||
/*
|
||||
* These 4 should be last, in the order:
|
||||
* (1) amfs_auto
|
||||
* (2) amfs_direct
|
||||
* (3) amfs_toplvl
|
||||
* (4) amfs_error
|
||||
*/
|
||||
#ifdef HAVE_AMU_FS_AUTO
|
||||
&amfs_auto_ops, /* Automounter F/S */
|
||||
#endif /* HAVE_AMU_FS_AUTO */
|
||||
#ifdef HAVE_AMU_FS_DIRECT
|
||||
&amfs_direct_ops, /* direct-mount F/S */
|
||||
#endif /* HAVE_AMU_FS_DIRECT */
|
||||
#ifdef HAVE_AMU_FS_TOPLVL
|
||||
&amfs_toplvl_ops, /* top-level mount F/S */
|
||||
#endif /* HAVE_AMU_FS_TOPLVL */
|
||||
#ifdef HAVE_AMU_FS_ERROR
|
||||
&amfs_error_ops, /* error F/S */
|
||||
#endif /* HAVE_AMU_FS_ERROR */
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
ops_showamfstypes(char *buf, size_t l)
|
||||
{
|
||||
struct am_ops **ap;
|
||||
int linesize = 0;
|
||||
|
||||
buf[0] = '\0';
|
||||
for (ap = vops; *ap; ap++) {
|
||||
xstrlcat(buf, (*ap)->fs_type, l);
|
||||
if (ap[1])
|
||||
xstrlcat(buf, ", ", l);
|
||||
linesize += strlen((*ap)->fs_type) + 2;
|
||||
if (linesize > 62) {
|
||||
linesize = 0;
|
||||
xstrlcat(buf, "\n ", l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ops_show1(char *buf, size_t l, int *linesizep, const char *name)
|
||||
{
|
||||
xstrlcat(buf, name, l);
|
||||
xstrlcat(buf, ", ", l);
|
||||
*linesizep += strlen(name) + 2;
|
||||
if (*linesizep > 60) {
|
||||
xstrlcat(buf, "\t\n", l);
|
||||
*linesizep = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ops_showfstypes(char *buf, size_t l)
|
||||
{
|
||||
int linesize = 0;
|
||||
|
||||
buf[0] = '\0';
|
||||
|
||||
#ifdef MNTTAB_TYPE_AUTOFS
|
||||
ops_show1(buf, l, &linesize, MNTTAB_TYPE_AUTOFS);
|
||||
#endif /* MNTTAB_TYPE_AUTOFS */
|
||||
|
||||
#ifdef MNTTAB_TYPE_CACHEFS
|
||||
ops_show1(buf, l, &linesize, MNTTAB_TYPE_CACHEFS);
|
||||
#endif /* MNTTAB_TYPE_CACHEFS */
|
||||
|
||||
#ifdef MNTTAB_TYPE_CDFS
|
||||
ops_show1(buf, l, &linesize, MNTTAB_TYPE_CDFS);
|
||||
#endif /* MNTTAB_TYPE_CDFS */
|
||||
|
||||
#ifdef MNTTAB_TYPE_CFS
|
||||
ops_show1(buf, l, &linesize, MNTTAB_TYPE_CFS);
|
||||
#endif /* MNTTAB_TYPE_CFS */
|
||||
|
||||
#ifdef MNTTAB_TYPE_LOFS
|
||||
ops_show1(buf, l, &linesize, MNTTAB_TYPE_LOFS);
|
||||
#endif /* MNTTAB_TYPE_LOFS */
|
||||
|
||||
#ifdef MNTTAB_TYPE_EFS
|
||||
ops_show1(buf, l, &linesize, MNTTAB_TYPE_EFS);
|
||||
#endif /* MNTTAB_TYPE_EFS */
|
||||
|
||||
#ifdef MNTTAB_TYPE_MFS
|
||||
ops_show1(buf, l, &linesize, MNTTAB_TYPE_MFS);
|
||||
#endif /* MNTTAB_TYPE_MFS */
|
||||
|
||||
#ifdef MNTTAB_TYPE_NFS
|
||||
ops_show1(buf, l, &linesize, MNTTAB_TYPE_NFS);
|
||||
#endif /* MNTTAB_TYPE_NFS */
|
||||
|
||||
#ifdef MNTTAB_TYPE_NFS3
|
||||
ops_show1(buf, l, &linesize, "nfs3"); /* always hard-code as nfs3 */
|
||||
#endif /* MNTTAB_TYPE_NFS3 */
|
||||
|
||||
#ifdef MNTTAB_TYPE_NULLFS
|
||||
ops_show1(buf, l, &linesize, MNTTAB_TYPE_NULLFS);
|
||||
#endif /* MNTTAB_TYPE_NULLFS */
|
||||
|
||||
#ifdef MNTTAB_TYPE_PCFS
|
||||
ops_show1(buf, l, &linesize, MNTTAB_TYPE_PCFS);
|
||||
#endif /* MNTTAB_TYPE_PCFS */
|
||||
|
||||
#ifdef MNTTAB_TYPE_TFS
|
||||
ops_show1(buf, l, &linesize, MNTTAB_TYPE_TFS);
|
||||
#endif /* MNTTAB_TYPE_TFS */
|
||||
|
||||
#ifdef MNTTAB_TYPE_TMPFS
|
||||
ops_show1(buf, l, &linesize, MNTTAB_TYPE_TMPFS);
|
||||
#endif /* MNTTAB_TYPE_TMPFS */
|
||||
|
||||
#ifdef MNTTAB_TYPE_UFS
|
||||
ops_show1(buf, l, &linesize, MNTTAB_TYPE_UFS);
|
||||
#endif /* MNTTAB_TYPE_UFS */
|
||||
|
||||
#ifdef MNTTAB_TYPE_UMAPFS
|
||||
ops_show1(buf, l, &linesize, MNTTAB_TYPE_UMAPFS);
|
||||
#endif /* MNTTAB_TYPE_UMAPFS */
|
||||
|
||||
#ifdef MNTTAB_TYPE_UNIONFS
|
||||
ops_show1(buf, l, &linesize, MNTTAB_TYPE_UNIONFS);
|
||||
#endif /* MNTTAB_TYPE_UNIONFS */
|
||||
|
||||
#ifdef MNTTAB_TYPE_XFS
|
||||
ops_show1(buf, l, &linesize, 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';
|
||||
xstrlcat(buf, ".\n", l);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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)) {
|
||||
xstrlcpy(buf, &opt[2], sizeof(buf));
|
||||
} else {
|
||||
/* finally return a string prepended with 'no' */
|
||||
xstrlcpy(buf, "no", sizeof(buf));
|
||||
xstrlcat(buf, opt, sizeof(buf));
|
||||
}
|
||||
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(const char *opts1, const char *opts2)
|
||||
{
|
||||
mntent_t mnt2; /* place holder for opts2 */
|
||||
char *newstr; /* new string to return (malloc'ed) */
|
||||
char *tmpstr; /* temp */
|
||||
char *eq; /* pointer to whatever follows '=' within temp */
|
||||
char oneopt[80]; /* one option w/o value if any */
|
||||
char *revoneopt; /* reverse of oneopt */
|
||||
size_t len = strlen(opts1) + strlen(opts2) + 2; /* space for "," and NULL */
|
||||
char *s1 = xstrdup(opts1); /* copy of opts1 to munge */
|
||||
|
||||
/* initialization */
|
||||
mnt2.mnt_opts = (char *) opts2;
|
||||
newstr = xmalloc(len);
|
||||
newstr[0] = '\0';
|
||||
|
||||
for (tmpstr = strtok(s1, ",");
|
||||
tmpstr;
|
||||
tmpstr = strtok(NULL, ",")) {
|
||||
/* copy option to temp buffer */
|
||||
xstrlcpy(oneopt, tmpstr, sizeof(oneopt));
|
||||
/* if option has a value such as rsize=1024, chop the value part */
|
||||
if ((eq = strchr(oneopt, '=')))
|
||||
*eq = '\0';
|
||||
/* find reverse option of oneopt */
|
||||
revoneopt = reverse_option(oneopt);
|
||||
/* if option or its reverse exist in opts2, ignore it */
|
||||
if (amu_hasmntopt(&mnt2, oneopt) || amu_hasmntopt(&mnt2, revoneopt))
|
||||
continue;
|
||||
/* add option to returned string */
|
||||
if (newstr[0]) {
|
||||
xstrlcat(newstr, ",", len);
|
||||
xstrlcat(newstr, tmpstr, len);
|
||||
} else {
|
||||
xstrlcpy(newstr, tmpstr, len);
|
||||
}
|
||||
}
|
||||
|
||||
/* finally, append opts2 itself */
|
||||
if (newstr[0]) {
|
||||
xstrlcat(newstr, ",", len);
|
||||
xstrlcat(newstr, opts2, len);
|
||||
} else {
|
||||
xstrlcpy(newstr, opts2, len);
|
||||
}
|
||||
|
||||
XFREE(s1);
|
||||
return newstr;
|
||||
}
|
||||
|
||||
|
||||
am_ops *
|
||||
ops_search(char *type)
|
||||
{
|
||||
am_ops **vp;
|
||||
am_ops *rop = NULL;
|
||||
for (vp = vops; (rop = *vp); vp++)
|
||||
if (STREQ(rop->fs_type, type))
|
||||
break;
|
||||
return rop;
|
||||
}
|
||||
|
||||
|
||||
am_ops *
|
||||
ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map)
|
||||
{
|
||||
am_ops *rop = NULL;
|
||||
char *link_dir;
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
rop = ops_search(fo->opt_type);
|
||||
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 = xstrdup("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 = xstrdup(old + 1);
|
||||
XFREE(old);
|
||||
}
|
||||
|
||||
/*
|
||||
* If addopts option was used, then append it to the
|
||||
* current options and remote mount options.
|
||||
*/
|
||||
if (fo->opt_addopts) {
|
||||
if (STREQ(fo->opt_opts, fo->opt_remopts)) {
|
||||
/* optimize things for the common case where opts==remopts */
|
||||
char *mergedstr;
|
||||
mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts);
|
||||
plog(XLOG_INFO, "merge rem/opts \"%s\" add \"%s\" => \"%s\"",
|
||||
fo->opt_opts, fo->opt_addopts, mergedstr);
|
||||
XFREE(fo->opt_opts);
|
||||
XFREE(fo->opt_remopts);
|
||||
fo->opt_opts = mergedstr;
|
||||
fo->opt_remopts = xstrdup(mergedstr);
|
||||
} else {
|
||||
char *mergedstr, *remmergedstr;
|
||||
mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts);
|
||||
plog(XLOG_INFO, "merge opts \"%s\" add \"%s\" => \"%s\"",
|
||||
fo->opt_opts, fo->opt_addopts, mergedstr);
|
||||
XFREE(fo->opt_opts);
|
||||
fo->opt_opts = mergedstr;
|
||||
remmergedstr = merge_opts(fo->opt_remopts, fo->opt_addopts);
|
||||
plog(XLOG_INFO, "merge remopts \"%s\" add \"%s\" => \"%s\"",
|
||||
fo->opt_remopts, fo->opt_addopts, remmergedstr);
|
||||
XFREE(fo->opt_remopts);
|
||||
fo->opt_remopts = remmergedstr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize opt_mount_type to "nfs", if it's not initialized already
|
||||
*/
|
||||
if (!fo->opt_mount_type)
|
||||
fo->opt_mount_type = "nfs";
|
||||
|
||||
/* Normalize the sublink and make it absolute */
|
||||
link_dir = fo->opt_sublink;
|
||||
if (link_dir && link_dir[0] && link_dir[0] != '/') {
|
||||
link_dir = str3cat((char *) NULL, fo->opt_fs, "/", link_dir);
|
||||
normalize_slash(link_dir);
|
||||
XFREE(fo->opt_sublink);
|
||||
fo->opt_sublink = link_dir;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the filesystem is happy
|
||||
*/
|
||||
XFREE(fo->fs_mtab);
|
||||
|
||||
fo->fs_mtab = rop->fs_match(fo);
|
||||
if (fo->fs_mtab)
|
||||
return rop;
|
||||
|
||||
/*
|
||||
* Return error file system
|
||||
*/
|
||||
fo->fs_mtab = amfs_error_ops.fs_match(fo);
|
||||
return &amfs_error_ops;
|
||||
}
|
@ -1,412 +0,0 @@
|
||||
.\"
|
||||
.\" Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\"
|
||||
.\" File: am-utils/amd/amd.8
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd November 22, 2019
|
||||
.Dt AMD 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm amd
|
||||
.Nd automatically mount file systems
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Fl H
|
||||
.Nm
|
||||
.Op Fl F Ar conf_file
|
||||
.Nm
|
||||
.Op Fl nprvHS
|
||||
.Op Fl a Ar mount_point
|
||||
.Op Fl c Ar duration
|
||||
.Op Fl d Ar domain
|
||||
.Op Fl k Ar kernel-arch
|
||||
.Op Fl l Ar logfile
|
||||
.Op Fl o Ar op_sys_ver
|
||||
.Op Fl t Ar timeout.retransmit
|
||||
.Op Fl w Ar interval
|
||||
.Op Fl x Ar log-option
|
||||
.Op Fl y Ar YP-domain
|
||||
.Op Fl A Ar arch
|
||||
.Op Fl C Ar cluster-name
|
||||
.Op Fl D Ar option
|
||||
.Op Fl F Ar conf_file
|
||||
.Op Fl O Ar op_sys_name
|
||||
.Op Fl T Ar tag
|
||||
.Oo
|
||||
.Ar directory mapname
|
||||
.Op Fl map-options
|
||||
.Oc
|
||||
.Ar ...
|
||||
.Sh DESCRIPTION
|
||||
.Bf -symbolic
|
||||
The
|
||||
.Nm
|
||||
daemon in the
|
||||
.Fx
|
||||
base system is deprecated and will be removed before
|
||||
.Fx 13.0 .
|
||||
Users are advised to use
|
||||
.Xr autofs 5
|
||||
or the
|
||||
.Pa sysutils/am-utils
|
||||
port or package instead.
|
||||
.Ef
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility
|
||||
is a daemon that automatically mounts file systems
|
||||
whenever a file or directory
|
||||
within that file system is accessed.
|
||||
File systems are automatically unmounted when they
|
||||
appear to be quiescent.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility
|
||||
operates by attaching itself as an
|
||||
.Tn NFS
|
||||
server to each of the specified
|
||||
.Ar directories .
|
||||
Lookups within the specified directories
|
||||
are handled by
|
||||
.Nm ,
|
||||
which uses the map defined by
|
||||
.Ar mapname
|
||||
to determine how to resolve the lookup.
|
||||
Generally, this will be a host name, some file system information
|
||||
and some mount options for the given file system.
|
||||
.Pp
|
||||
In the first form depicted above,
|
||||
.Nm
|
||||
will print a short help string.
|
||||
In the second form, if no options are
|
||||
specified, or if the
|
||||
.Fl F
|
||||
is used,
|
||||
.Nm
|
||||
will read configuration parameters from the file
|
||||
.Ar conf_file
|
||||
which defaults to
|
||||
.Pa /etc/amd.conf .
|
||||
The last form is described below.
|
||||
.Sh OPTIONS
|
||||
.Bl -tag -width indent
|
||||
.It Fl a Ar temporary-directory
|
||||
Specify an alternative location for the real mount points.
|
||||
The default is
|
||||
.Pa /.amd_mnt .
|
||||
.It Fl c Ar duration
|
||||
Specify a
|
||||
.Ar duration ,
|
||||
in seconds, that a looked up name remains
|
||||
cached when not in use.
|
||||
The default is 5 minutes.
|
||||
.It Fl d Ar domain
|
||||
Specify the local domain name.
|
||||
If this option is not
|
||||
given the domain name is determined from the hostname.
|
||||
.It Fl k Ar kernel-arch
|
||||
Specifies the kernel architecture.
|
||||
This is used solely
|
||||
to set the ${karch} selector.
|
||||
.It Fl l Ar logfile
|
||||
Specify a logfile in which to record mount and unmount events.
|
||||
If
|
||||
.Ar logfile
|
||||
is the string
|
||||
.Dq Li syslog ,
|
||||
then the log messages will be sent to the system log daemon by
|
||||
.Xr syslog 3 .
|
||||
The default syslog facility used is
|
||||
.Dv LOG_DAEMON .
|
||||
If you
|
||||
wish to change it, append its name to the log file name, delimited by a
|
||||
single colon.
|
||||
For example, if
|
||||
.Ar logfile
|
||||
is the string
|
||||
.Dq Li syslog:local7
|
||||
then
|
||||
.Nm
|
||||
will log messages via
|
||||
.Xr syslog 3
|
||||
using the
|
||||
.Dv LOG_LOCAL7
|
||||
facility (if it exists on the system).
|
||||
.It Fl n
|
||||
Normalize hostnames.
|
||||
The name referred to by ${rhost} is normalized relative to the
|
||||
host database before being used.
|
||||
The effect is to translate
|
||||
aliases into
|
||||
.Dq official
|
||||
names.
|
||||
.It Fl o Ar 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
|
||||
.Dq Li 2.5.1 ,
|
||||
you can override it to
|
||||
.Dq Li 5.5.1 ,
|
||||
and use older maps that were written with the latter in mind.
|
||||
.It Fl p
|
||||
Print PID.
|
||||
Outputs the process ID of
|
||||
.Nm
|
||||
to standard output where it can be saved into a file.
|
||||
.It Fl r
|
||||
Restart existing mounts.
|
||||
The
|
||||
.Nm
|
||||
utility
|
||||
will scan the mount file table to determine which file systems
|
||||
are currently mounted.
|
||||
Whenever one of these would have
|
||||
been auto-mounted,
|
||||
.Nm
|
||||
.Em inherits
|
||||
it.
|
||||
.It Fl t Ar timeout.retransmit
|
||||
Specify the NFS
|
||||
.Ar timeout
|
||||
interval,
|
||||
in tenths of a second, between
|
||||
.Tn NFS/RPC
|
||||
retries (for UDP only).
|
||||
The default
|
||||
is 0.8 seconds.
|
||||
The second value alters the retransmit counter, which
|
||||
defaults to 11 retransmissions.
|
||||
Both of these values are used by the kernel
|
||||
to communicate with amd.
|
||||
Useful defaults are supplied if either or both
|
||||
values are missing.
|
||||
.Pp
|
||||
The
|
||||
.Xr amd 8
|
||||
utility
|
||||
relies on the kernel RPC retransmit mechanism to trigger mount retries.
|
||||
The values of these parameters change the overall retry interval.
|
||||
Too long
|
||||
an interval gives poor interactive response; too short an interval causes
|
||||
excessive retries.
|
||||
.It Fl v
|
||||
Version.
|
||||
Displays version and configuration information on standard error.
|
||||
.It Fl w Ar interval
|
||||
Specify an
|
||||
.Ar interval ,
|
||||
in seconds, between attempts to dismount
|
||||
file systems that have exceeded their cached times.
|
||||
The default is 2 minutes.
|
||||
.TP
|
||||
.It Fl x Ar options
|
||||
Specify run-time logging options. The options are a comma separated
|
||||
list chosen from:
|
||||
.Li fatal, error, user, warn, info, map, stats, defaults, all .
|
||||
Note that "fatal" and "error" are mandatory and cannot be turned off.
|
||||
.TP
|
||||
.It Fl y Ar domain
|
||||
Specify an alternative
|
||||
.Tn NIS
|
||||
domain from which to fetch the
|
||||
.Tn NIS
|
||||
maps.
|
||||
The default is the system domain name. This option is ignored if NIS
|
||||
support is not available.
|
||||
.It Fl A Ar arch
|
||||
Specifies the OS architecture.
|
||||
This is used solely to set the ${arch}
|
||||
selector.
|
||||
.It Fl C Ar cluster-name
|
||||
Specify an alternative HP-UX cluster name to use.
|
||||
.It Fl D Ar option
|
||||
Select from a variety of debug options.
|
||||
Prefixing an
|
||||
option with the string
|
||||
.Dq Li no
|
||||
reverses the effect of that option.
|
||||
Options are cumulative.
|
||||
The most useful option is
|
||||
.Dq Li all .
|
||||
.Pp
|
||||
Since
|
||||
.Fl D
|
||||
is only used for debugging other options are not documented here:
|
||||
the current supported set of options is listed by the
|
||||
.Fl v
|
||||
option
|
||||
and a fuller description is available in the program source.
|
||||
.It Fl F Ar conf_file
|
||||
Specify an
|
||||
.Nm
|
||||
configuration file to use.
|
||||
See
|
||||
.Xr 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
|
||||
.Xr amd.conf 5
|
||||
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.
|
||||
.It Fl H
|
||||
Print help and usage string.
|
||||
.It Fl O Ar 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
|
||||
.Dq Li sunos5 ,
|
||||
you can override it to
|
||||
.Dq Li sos5
|
||||
and use older maps which were written with the latter in mind.
|
||||
.It Fl S
|
||||
Do not lock the running executable pages of
|
||||
.Nm
|
||||
into memory.
|
||||
To improve
|
||||
.Nm Ns 's
|
||||
performance, systems that support the
|
||||
.Xr plock 3
|
||||
call, could lock the
|
||||
.Nm
|
||||
process into memory.
|
||||
This way there is less chance
|
||||
the operating system will schedule, page out, and swap the
|
||||
.Nm
|
||||
process as
|
||||
needed.
|
||||
This tends to improve
|
||||
.Nm Ns 's
|
||||
performance, at the cost of reserving the
|
||||
memory used by the
|
||||
.Nm
|
||||
process (making it unavailable for other processes).
|
||||
If this behavior is not desired, use the
|
||||
.Fl S
|
||||
option.
|
||||
.It Fl T Ar tag
|
||||
Specify a tag to use with
|
||||
.Xr amd.conf 5 .
|
||||
All map entries tagged with
|
||||
.Ar tag
|
||||
will be processed.
|
||||
Map entries that are not tagged are always processed.
|
||||
Map entries that are tagged with a tag other than
|
||||
.Ar tag
|
||||
will not be processed.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width ".Pa /etc/amd.conf"
|
||||
.It Pa /.amd_mnt
|
||||
directory under which file systems are dynamically mounted
|
||||
.It Pa /etc/amd.conf
|
||||
default configuration file
|
||||
.El
|
||||
.Sh CAVEATS
|
||||
Some care may be required when creating a mount map.
|
||||
.Pp
|
||||
Symbolic links on an
|
||||
.Tn NFS
|
||||
file system can be incredibly inefficient.
|
||||
In most implementations of
|
||||
.Tn NFS ,
|
||||
their interpolations are not cached
|
||||
by the kernel and each time a symbolic link is encountered during a
|
||||
.Em lookuppn
|
||||
translation it costs an
|
||||
.Tn RPC
|
||||
call to the
|
||||
.Tn 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.
|
||||
.Pp
|
||||
A weird imagination is most useful to gain full advantage of all
|
||||
the features.
|
||||
.Sh SEE ALSO
|
||||
.Xr domainname 1 ,
|
||||
.Xr hostname 1 ,
|
||||
.Xr syslog 3 ,
|
||||
.Xr amd.conf 5 ,
|
||||
.Xr mtab 5 ,
|
||||
.Xr amq 8 ,
|
||||
.Xr automount 8 ,
|
||||
.Xr mount 8 ,
|
||||
.Xr umount 8
|
||||
.Pp
|
||||
.Dq am-utils
|
||||
.Xr info 1
|
||||
entry.
|
||||
.Rs
|
||||
.%A Erez Zadok
|
||||
.%B "Linux NFS and Automounter Administration"
|
||||
.%O ISBN 0-7821-2739-8
|
||||
.%I Sybex
|
||||
.%D 2001
|
||||
.Re
|
||||
.Pp
|
||||
.Pa http://www.am-utils.org/
|
||||
.Rs
|
||||
.%T Amd \- The 4.4 BSD Automounter
|
||||
.Re
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility first appeared in
|
||||
.Bx 4.4 .
|
||||
.Sh AUTHORS
|
||||
.An Jan-Simon Pendry Aq jsp@doc.ic.ac.uk ,
|
||||
Department of Computing, Imperial College, London, UK.
|
||||
.Pp
|
||||
.An Erez Zadok Aq ezk@cs.sunysb.edu ,
|
||||
Computer Science Department, Stony Brook
|
||||
University, Stony Brook, New York, USA.
|
||||
.Pp
|
||||
Other authors and contributors to am-utils are listed in the
|
||||
.Pa AUTHORS
|
||||
file distributed with am-utils.
|
@ -1,584 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. 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.
|
||||
*
|
||||
*
|
||||
* $Id: amd.c,v 1.8.2.6 2004/01/06 03:15:16 ezk Exp $
|
||||
* File: am-utils/amd/amd.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* 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[SIZEOF_PID_FSNAME]; /* "kiska.southseas.nz:(pid%d)" */
|
||||
char *hostdomain = "unknown.domain";
|
||||
#define SIZEOF_HOSTD (2 * MAXHOSTNAMELEN + 1) /* Host+domain */
|
||||
char hostd[SIZEOF_HOSTD]; /* Host+domain */
|
||||
char *endian = ARCH_ENDIAN; /* Big or Little endian */
|
||||
char *cpu = HOST_CPU; /* CPU type */
|
||||
char *PrimNetName; /* name of primary network */
|
||||
char *PrimNetNum; /* number of primary network */
|
||||
|
||||
int immediate_abort; /* Should close-down unmounts be retried */
|
||||
int orig_umask = 022;
|
||||
int select_intr_valid;
|
||||
|
||||
jmp_buf select_intr;
|
||||
struct amd_stats amd_stats; /* Server statistics */
|
||||
struct in_addr myipaddr; /* (An) IP address of this host */
|
||||
time_t do_mapc_reload = 0; /* mapc_reload() call required? */
|
||||
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
int amd_use_autofs = 0;
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
sigset_t masked_sigs;
|
||||
#endif /* HAVE_SIGACTION */
|
||||
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
if (sig != SIGHUP)
|
||||
dlog("spurious call to sighup");
|
||||
/*
|
||||
* Force a reload by zero'ing the timer
|
||||
*/
|
||||
if (amd_state == Run)
|
||||
do_mapc_reload = 0;
|
||||
}
|
||||
|
||||
|
||||
static RETSIGTYPE
|
||||
parent_exit(int sig)
|
||||
{
|
||||
/*
|
||||
* This signal handler is called during Amd initialization. The parent
|
||||
* forks a child to do all the hard automounting work, and waits for a
|
||||
* SIGQUIT signal from the child. When the parent gets the signal it's
|
||||
* supposed to call this handler and exit(3), thus completing the
|
||||
* daemonizing process. Alas, on some systems, especially Linux 2.4/2.6
|
||||
* with Glibc, exit(3) doesn't always terminate the parent process.
|
||||
* Worse, the parent process now refuses to accept any more SIGQUIT
|
||||
* signals -- they are blocked. What's really annoying is that this
|
||||
* doesn't happen all the time, suggesting a race condition somewhere.
|
||||
* (This happens even if I change the logic to use another signal.) I
|
||||
* traced this to something which exit(3) does in addition to exiting the
|
||||
* process, probably some atexit() stuff or other side-effects related to
|
||||
* signal handling. Either way, since at this stage the parent process
|
||||
* just needs to terminate, I'm simply calling _exit(2). Note also that
|
||||
* the OpenGroup doesn't list exit(3) as a recommended "Base Interface"
|
||||
* but they do list _exit(2) as one. This fix seems to work reliably all
|
||||
* the time. -Erez (2/27/2005)
|
||||
*/
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
daemon_mode(void)
|
||||
{
|
||||
int bgpid;
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
struct sigaction sa, osa;
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = parent_exit;
|
||||
sa.sa_flags = 0;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
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 reach 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) am_mypid);
|
||||
/* flush stdout, just in case */
|
||||
fflush(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) am_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) */
|
||||
int i;
|
||||
|
||||
memset(&gopt, 0, sizeof(struct amu_global_options));
|
||||
|
||||
/* name of current architecture */
|
||||
gopt.arch = HOST_ARCH;
|
||||
|
||||
/* automounter temp dir */
|
||||
gopt.auto_dir = "/.amd_mnt";
|
||||
|
||||
/* toplevel attribute cache timeout */
|
||||
gopt.auto_attrcache = 0;
|
||||
|
||||
/* cluster name */
|
||||
gopt.cluster = NULL;
|
||||
|
||||
/* executable map timeout */
|
||||
gopt.exec_map_timeout = AMFS_EXEC_MAP_TIMEOUT;
|
||||
|
||||
/*
|
||||
* kernel architecture: this you must get from uname() if possible.
|
||||
*/
|
||||
#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;
|
||||
|
||||
/* full OS name and version */
|
||||
gopt.op_sys_full = HOST_OS;
|
||||
|
||||
/* OS version */
|
||||
gopt.op_sys_vendor = HOST_VENDOR;
|
||||
|
||||
/* pid file */
|
||||
gopt.pid_file = "/dev/stdout";
|
||||
|
||||
/* local domain */
|
||||
gopt.sub_domain = NULL;
|
||||
|
||||
/* reset NFS (and toplvl) retransmit counter and retry interval */
|
||||
for (i=0; i<AMU_TYPE_MAX; ++i) {
|
||||
gopt.amfs_auto_retrans[i] = -1; /* -1 means "never set before" */
|
||||
gopt.amfs_auto_timeo[i] = -1; /* -1 means "never set before" */
|
||||
}
|
||||
|
||||
/* cache duration */
|
||||
gopt.am_timeo = AM_TTL;
|
||||
|
||||
/* dismount interval */
|
||||
gopt.am_timeo_w = AM_TTL_W;
|
||||
|
||||
/* map reload intervl */
|
||||
gopt.map_reload_interval = ONE_HOUR;
|
||||
|
||||
/*
|
||||
* various CFM_* flags that are on by default.
|
||||
*/
|
||||
gopt.flags = CFM_DEFAULT_FLAGS;
|
||||
|
||||
#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;
|
||||
|
||||
/* LDAP protocol version */
|
||||
gopt.ldap_proto_version = 2;
|
||||
#endif /* HAVE_MAP_LDAP */
|
||||
|
||||
#ifdef HAVE_MAP_NIS
|
||||
/* YP domain name */
|
||||
gopt.nis_domain = NULL;
|
||||
#endif /* HAVE_MAP_NIS */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Lock process text and data segment in memory (after forking the daemon)
|
||||
*/
|
||||
static void
|
||||
do_memory_locking(void)
|
||||
{
|
||||
#if defined(HAVE_PLOCK) || defined(HAVE_MLOCKALL)
|
||||
int locked_ok = 0;
|
||||
#else /* not HAVE_PLOCK and not HAVE_MLOCKALL */
|
||||
plog(XLOG_WARNING, "Process memory locking not supported by the OS");
|
||||
#endif /* not HAVE_PLOCK and not HAVE_MLOCKALL */
|
||||
#ifdef HAVE_PLOCK
|
||||
# ifdef _AIX
|
||||
/*
|
||||
* On AIX you must lower the stack size using ulimit() before calling
|
||||
* plock. Otherwise plock will reserve a lot of memory space based on
|
||||
* your maximum stack size limit. Since it is not easily possible to
|
||||
* tell what should the limit be, I print a warning before calling
|
||||
* plock(). See the manual pages for ulimit(1,3,4) on your AIX system.
|
||||
*/
|
||||
plog(XLOG_WARNING, "AIX: may need to lower stack size using ulimit(3) before calling plock");
|
||||
# endif /* _AIX */
|
||||
if (!locked_ok && plock(PROCLOCK) != 0)
|
||||
plog(XLOG_WARNING, "Couldn't lock process pages in memory using plock(): %m");
|
||||
else
|
||||
locked_ok = 1;
|
||||
#endif /* HAVE_PLOCK */
|
||||
#ifdef HAVE_MLOCKALL
|
||||
if (!locked_ok && mlockall(MCL_CURRENT|MCL_FUTURE) != 0)
|
||||
plog(XLOG_WARNING, "Couldn't lock process pages in memory using mlockall(): %m");
|
||||
else
|
||||
locked_ok = 1;
|
||||
#endif /* HAVE_MLOCKALL */
|
||||
#if defined(HAVE_PLOCK) || defined(HAVE_MLOCKALL)
|
||||
if (locked_ok)
|
||||
plog(XLOG_INFO, "Locked process pages in memory");
|
||||
#endif /* HAVE_PLOCK || HAVE_MLOCKALL */
|
||||
|
||||
#if defined(HAVE_MADVISE) && defined(MADV_PROTECT)
|
||||
madvise(NULL, 0, MADV_PROTECT); /* may be redundant of the above worked out */
|
||||
#endif /* defined(HAVE_MADVISE) && defined(MADV_PROTECT) */
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char *domdot, *verstr, *vertmp;
|
||||
int ppid = 0;
|
||||
int error;
|
||||
char *progname = NULL; /* "amd" */
|
||||
char hostname[MAXHOSTNAMELEN + 1] = "localhost"; /* Hostname */
|
||||
|
||||
/*
|
||||
* 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";
|
||||
am_set_progname(progname);
|
||||
|
||||
plog(XLOG_WARNING, "built-in amd in FreeBSD is deprecated and will be removed before FreeBSD 13");
|
||||
|
||||
/*
|
||||
* Initialize process id. This is kept
|
||||
* cached since it is used for generating
|
||||
* and using file handles.
|
||||
*/
|
||||
am_set_mypid();
|
||||
|
||||
/*
|
||||
* Get local machine name
|
||||
*/
|
||||
if (gethostname(hostname, sizeof(hostname)) < 0) {
|
||||
plog(XLOG_FATAL, "gethostname: %m");
|
||||
going_down(1);
|
||||
return 1;
|
||||
}
|
||||
hostname[sizeof(hostname) - 1] = '\0';
|
||||
|
||||
/*
|
||||
* Check it makes sense
|
||||
*/
|
||||
if (!*hostname) {
|
||||
plog(XLOG_FATAL, "host name is not set");
|
||||
going_down(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize global options structure.
|
||||
*/
|
||||
init_global_options();
|
||||
|
||||
/*
|
||||
* Partially initialize 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;
|
||||
}
|
||||
xstrlcpy(hostd, hostname, sizeof(hostd));
|
||||
am_set_hostname(hostname);
|
||||
|
||||
/*
|
||||
* Setup signal handlers
|
||||
*/
|
||||
/* SIGINT: trap interrupts for shutdowns */
|
||||
setup_sighandler(SIGINT, sigterm);
|
||||
/* SIGTERM: trap terminate so we can shutdown cleanly (some chance) */
|
||||
setup_sighandler(SIGTERM, sigterm);
|
||||
/* SIGHUP: hangups tell us to reload the cache */
|
||||
setup_sighandler(SIGHUP, sighup);
|
||||
/*
|
||||
* SIGCHLD: trap Death-of-a-child. These allow us to pick up the exit
|
||||
* status of backgrounded mounts. See "sched.c".
|
||||
*/
|
||||
setup_sighandler(SIGCHLD, sigchld);
|
||||
#ifdef HAVE_SIGACTION
|
||||
/* construct global "masked_sigs" used in nfs_start.c */
|
||||
sigemptyset(&masked_sigs);
|
||||
sigaddset(&masked_sigs, SIGINT);
|
||||
sigaddset(&masked_sigs, SIGTERM);
|
||||
sigaddset(&masked_sigs, SIGHUP);
|
||||
sigaddset(&masked_sigs, SIGCHLD);
|
||||
#endif /* 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.
|
||||
* (Also initialize amd.conf parameters, maps, and more.)
|
||||
*/
|
||||
get_args(argc, argv);
|
||||
|
||||
/*
|
||||
* Log version information.
|
||||
*/
|
||||
vertmp = get_version_string();
|
||||
verstr = strtok(vertmp, "\n");
|
||||
plog(XLOG_INFO, "AM-UTILS VERSION INFORMATION:");
|
||||
while (verstr) {
|
||||
plog(XLOG_INFO, "%s", verstr);
|
||||
verstr = strtok(NULL, "\n");
|
||||
}
|
||||
XFREE(vertmp);
|
||||
|
||||
/*
|
||||
* Get our own IP address so that we can mount the automounter. We pass
|
||||
* localhost_address which could be used as the default localhost
|
||||
* name/address in amu_get_myaddress().
|
||||
*/
|
||||
amu_get_myaddress(&myipaddr, gopt.localhost_address);
|
||||
plog(XLOG_INFO, "My ip addr is %s", inet_ntoa(myipaddr));
|
||||
|
||||
/* avoid hanging on other NFS servers if started elsewhere */
|
||||
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 = %ld)", (long) geteuid());
|
||||
going_down(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#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);
|
||||
return 1;
|
||||
}
|
||||
#endif /* HAVE_MAP_NIS */
|
||||
|
||||
if (amuDebug(D_DAEMON))
|
||||
ppid = daemon_mode();
|
||||
|
||||
/*
|
||||
* Lock process text and data segment in memory.
|
||||
*/
|
||||
if (gopt.flags & CFM_PROCESS_LOCK) {
|
||||
do_memory_locking();
|
||||
}
|
||||
|
||||
do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval;
|
||||
|
||||
/*
|
||||
* Register automounter with system.
|
||||
*/
|
||||
error = mount_automounter(ppid);
|
||||
if (error && ppid)
|
||||
kill(ppid, SIGALRM);
|
||||
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
/*
|
||||
* XXX this should be part of going_down(), but I can't move it there
|
||||
* because it would be calling non-library code from the library... ugh
|
||||
*/
|
||||
if (amd_use_autofs)
|
||||
destroy_autofs_service();
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
going_down(error);
|
||||
|
||||
abort();
|
||||
return 1; /* should never get here */
|
||||
}
|
@ -1,923 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/amd.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _AMD_H
|
||||
#define _AMD_H
|
||||
|
||||
|
||||
/*
|
||||
* MACROS:
|
||||
*/
|
||||
|
||||
/*
|
||||
* Define a default debug mtab path for systems
|
||||
* that support mtab on file.
|
||||
*/
|
||||
#ifdef MOUNT_TABLE_ON_FILE
|
||||
# define DEBUG_MNTTAB_FILE "/tmp/mtab"
|
||||
#endif /* MOUNT_TABLE_ON_FILE */
|
||||
|
||||
/* Max line length that info services can handle */
|
||||
#define INFO_MAX_LINE_LEN 1500
|
||||
|
||||
/* options for amd.conf */
|
||||
#define CFM_BROWSABLE_DIRS 0x00000001
|
||||
#define CFM_MOUNT_TYPE_AUTOFS 0x00000002 /* use kernel autofs support */
|
||||
#define CFM_SELECTORS_IN_DEFAULTS 0x00000004
|
||||
#define CFM_NORMALIZE_HOSTNAMES 0x00000008
|
||||
#define CFM_PROCESS_LOCK 0x00000010
|
||||
#define CFM_PRINT_PID 0x00000020
|
||||
#define CFM_RESTART_EXISTING_MOUNTS 0x00000040
|
||||
#define CFM_SHOW_STATFS_ENTRIES 0x00000080
|
||||
#define CFM_FULLY_QUALIFIED_HOSTS 0x00000100
|
||||
#define CFM_BROWSABLE_DIRS_FULL 0x00000200 /* allow '/' in readdir() */
|
||||
#define CFM_UNMOUNT_ON_EXIT 0x00000400 /* when amd finishing */
|
||||
#define CFM_USE_TCPWRAPPERS 0x00000800
|
||||
#define CFM_AUTOFS_USE_LOFS 0x00001000
|
||||
#define CFM_NFS_INSECURE_PORT 0x00002000
|
||||
#define CFM_DOMAIN_STRIP 0x00004000
|
||||
#define CFM_NORMALIZE_SLASHES 0x00008000 /* normalize slashes? */
|
||||
#define CFM_FORCED_UNMOUNTS 0x00010000 /* forced unmounts? */
|
||||
#define CFM_TRUNCATE_LOG 0x00020000 /* truncate log file? */
|
||||
#define CFM_SUN_MAP_SYNTAX 0x00040000 /* Sun map syntax? */
|
||||
#define CFM_NFS_ANY_INTERFACE 0x00080000 /* all interfaces are acceptable */
|
||||
|
||||
/* defaults global flags: plock, tcpwrappers, and autofs/lofs */
|
||||
#define CFM_DEFAULT_FLAGS (CFM_PROCESS_LOCK|CFM_USE_TCPWRAPPERS|CFM_AUTOFS_USE_LOFS|CFM_DOMAIN_STRIP|CFM_NORMALIZE_SLASHES)
|
||||
|
||||
/*
|
||||
* macro definitions for automounter vfs/vnode operations.
|
||||
*/
|
||||
#define VLOOK_CREATE 0x1
|
||||
#define VLOOK_DELETE 0x2
|
||||
#define VLOOK_LOOKUP 0x3
|
||||
|
||||
/*
|
||||
* macro definitions for automounter vfs capabilities
|
||||
*/
|
||||
#define FS_DIRECTORY 0x0001 /* This looks like a dir, not a link */
|
||||
#define FS_MBACKGROUND 0x0002 /* Should background this mount */
|
||||
#define FS_NOTIMEOUT 0x0004 /* Don't bother with timeouts */
|
||||
#define FS_MKMNT 0x0008 /* Need to make the mount point */
|
||||
#define FS_UBACKGROUND 0x0010 /* Unmount in background */
|
||||
#define FS_BACKGROUND (FS_MBACKGROUND|FS_UBACKGROUND)
|
||||
#define FS_DISCARD 0x0020 /* Discard immediately on last reference */
|
||||
#define FS_AMQINFO 0x0040 /* Amq is interested in this fs type */
|
||||
#define FS_AUTOFS 0x0080 /* This filesystem can be an autofs f/s */
|
||||
#define FS_DIRECT 0x0100 /* Direct mount */
|
||||
#define FS_ON_AUTOFS 0x0200 /* This filesystem can be mounted directly
|
||||
onto an autofs mountpoint */
|
||||
|
||||
/*
|
||||
* macros for struct am_node (map of auto-mount points).
|
||||
*/
|
||||
#define AMF_NOTIMEOUT 0x0001 /* This node never times out */
|
||||
#define AMF_ROOT 0x0002 /* This is a root node */
|
||||
#define AMF_AUTOFS 0x0004 /* This node is part of an autofs filesystem */
|
||||
#define AMF_REMOUNT 0x0008 /* This node needs to be remounted */
|
||||
#define AMF_SOFTLOOKUP 0x0010 /* This node returns EIO if server is down */
|
||||
|
||||
/*
|
||||
* macros for struct mntfs (list of mounted filesystems)
|
||||
*/
|
||||
#define MFF_MOUNTED 0x0001 /* Node is mounted */
|
||||
#define MFF_MOUNTING 0x0002 /* Mount is in progress */
|
||||
#define MFF_UNMOUNTING 0x0004 /* Unmount is in progress */
|
||||
#define MFF_RESTART 0x0008 /* Restarted node */
|
||||
#define MFF_MKMNT 0x0010 /* Delete this node's am_mount */
|
||||
#define MFF_ERROR 0x0020 /* This node failed to mount */
|
||||
#define MFF_LOGDOWN 0x0040 /* Logged that this mount is down */
|
||||
#define MFF_RSTKEEP 0x0080 /* Don't timeout this filesystem - restarted */
|
||||
#define MFF_WANTTIMO 0x0100 /* Need a timeout call when not busy */
|
||||
#define MFF_NFSLINK 0x0200 /* nfsl type, and deemed a link */
|
||||
#define MFF_IS_AUTOFS 0x0400 /* this filesystem is of type autofs */
|
||||
#define MFF_NFS_SCALEDOWN 0x0800 /* the mount failed, retry with v2/UDP */
|
||||
#define MFF_ON_AUTOFS 0x1000 /* autofs has a lofs/link to this f/s */
|
||||
#define MFF_WEBNFS 0x2000 /* use public filehandle */
|
||||
|
||||
/*
|
||||
* macros for struct fserver.
|
||||
*/
|
||||
#define FSF_VALID 0x0001 /* Valid information available */
|
||||
#define FSF_DOWN 0x0002 /* This fileserver is thought to be down */
|
||||
#define FSF_ERROR 0x0004 /* Permanent error has occurred */
|
||||
#define FSF_WANT 0x0008 /* Want a wakeup call */
|
||||
#define FSF_PINGING 0x0010 /* Already doing pings */
|
||||
#define FSF_WEBNFS 0x0020 /* Don't try to contact portmapper */
|
||||
#define FSF_PING_UNINIT 0x0040 /* ping values have not been initilized */
|
||||
#define FSF_FORCE_UNMOUNT 0x0080 /* force umount of this fserver */
|
||||
#define FSRV_ERROR(fs) ((fs) && (((fs)->fs_flags & FSF_ERROR) == FSF_ERROR))
|
||||
#define FSRV_ISDOWN(fs) ((fs) && (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_DOWN|FSF_VALID)))
|
||||
#define FSRV_ISUP(fs) (!(fs) || (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_VALID)))
|
||||
|
||||
/* some systems (SunOS 4.x) neglect to define the mount null message */
|
||||
#ifndef MOUNTPROC_NULL
|
||||
# define MOUNTPROC_NULL ((u_long)(0))
|
||||
#endif /* not MOUNTPROC_NULL */
|
||||
|
||||
/*
|
||||
* Error to return if remote host is not available.
|
||||
* Try, in order, "host down", "host unreachable", "invalid argument".
|
||||
*/
|
||||
#ifdef EHOSTDOWN
|
||||
# define AM_ERRNO_HOST_DOWN EHOSTDOWN
|
||||
#else /* not EHOSTDOWN */
|
||||
# ifdef EHOSTUNREACH
|
||||
# define AM_ERRNO_HOST_DOWN EHOSTUNREACH
|
||||
# else /* not EHOSTUNREACH */
|
||||
# define AM_ERRNO_HOST_DOWN EINVAL
|
||||
# endif /* not EHOSTUNREACH */
|
||||
#endif /* not EHOSTDOWN */
|
||||
|
||||
/* Hash table size */
|
||||
#define NKVHASH (1 << 2) /* Power of two */
|
||||
|
||||
/* Max entries to return in one call */
|
||||
#define MAX_READDIR_ENTRIES 16
|
||||
|
||||
/*
|
||||
* default amfs_auto retrans - 1/10th seconds
|
||||
*/
|
||||
#define AMFS_AUTO_RETRANS(x) ((ALLOWED_MOUNT_TIME*10+5*gopt.amfs_auto_timeo[(x)])/gopt.amfs_auto_timeo[(x)] * 2)
|
||||
|
||||
/*
|
||||
* The following values can be tuned...
|
||||
*/
|
||||
#define AM_TTL (300) /* Default cache period (5 min) */
|
||||
#define AM_TTL_W (120) /* Default unmount interval (2 min) */
|
||||
#define AM_PINGER 30 /* NFS ping interval for live systems */
|
||||
#define AMFS_AUTO_TIMEO 8 /* Default amfs_auto timeout - .8s */
|
||||
#define AMFS_EXEC_MAP_TIMEOUT 10 /* default 10sec exec map timeout */
|
||||
|
||||
/* interval between forced retries of a mount */
|
||||
#define RETRY_INTERVAL 2
|
||||
|
||||
#ifndef ROOT_MAP
|
||||
# define ROOT_MAP "\"root\""
|
||||
#endif /* not ROOT_MAP */
|
||||
|
||||
#define ereturn(x) do { *error_return = x; return 0; } while (0)
|
||||
|
||||
#define NEVER (time_t) 0
|
||||
|
||||
#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
|
||||
# define AMD_SERVICE_NAME "amd" /* for tcpwrappers */
|
||||
#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
|
||||
|
||||
/*
|
||||
* TYPEDEFS:
|
||||
*/
|
||||
|
||||
typedef struct cf_map cf_map_t;
|
||||
typedef struct kv kv;
|
||||
typedef struct am_node am_node;
|
||||
typedef struct mntfs mntfs;
|
||||
typedef struct am_loc am_loc;
|
||||
typedef struct am_opts am_opts;
|
||||
typedef struct am_ops am_ops;
|
||||
typedef struct am_stats am_stats;
|
||||
typedef struct fserver fserver;
|
||||
|
||||
typedef voidp wchan_t;
|
||||
typedef voidp opaque_t;
|
||||
|
||||
/*
|
||||
* Cache map operations
|
||||
*/
|
||||
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 *);
|
||||
typedef int task_fun(opaque_t);
|
||||
typedef void cb_fun(int, int, opaque_t);
|
||||
typedef void fwd_fun(voidp, int, struct sockaddr_in *,
|
||||
struct sockaddr_in *, opaque_t, int);
|
||||
typedef int key_fun(char *, opaque_t);
|
||||
typedef void callout_fun(opaque_t);
|
||||
|
||||
/*
|
||||
* automounter vfs/vnode operations.
|
||||
*/
|
||||
typedef char *(*vfs_match) (am_opts *);
|
||||
typedef int (*vfs_init) (mntfs *);
|
||||
typedef int (*vmount_fs) (am_node *, mntfs *);
|
||||
typedef int (*vumount_fs) (am_node *, mntfs *);
|
||||
typedef am_node *(*vlookup_child) (am_node *, char *, int *, int);
|
||||
typedef am_node *(*vmount_child) (am_node *, int *);
|
||||
typedef int (*vreaddir) (am_node *, voidp, voidp, voidp, u_int);
|
||||
typedef am_node *(*vreadlink) (am_node *, int *);
|
||||
typedef void (*vmounted) (mntfs *);
|
||||
typedef void (*vumounted) (mntfs *);
|
||||
typedef fserver *(*vffserver) (mntfs *);
|
||||
typedef wchan_t (*vget_wchan) (mntfs *);
|
||||
|
||||
/*
|
||||
* NFS progran dispatcher
|
||||
*/
|
||||
typedef void (*dispatcher_t)(struct svc_req *rqstp, SVCXPRT *transp);
|
||||
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
int auto_attrcache; /* attribute cache timeout for auto dirs */
|
||||
char *cluster; /* cluster name */
|
||||
char *karch; /* kernel architecture */
|
||||
char *logfile; /* amd log file */
|
||||
char *op_sys; /* operating system name ${os} */
|
||||
char *op_sys_ver; /* OS version ${osver} */
|
||||
char *op_sys_full; /* full OS name ${full_os} */
|
||||
char *op_sys_vendor; /* name of OS vendor ${vendor} */
|
||||
char *pid_file; /* PID file */
|
||||
char *sub_domain; /* local domain */
|
||||
char *localhost_address; /* localhost address (NULL means use 127.0.0.1) */
|
||||
char *map_defaults; /* global map /default options */
|
||||
char *map_options; /* global map options */
|
||||
int map_reload_interval; /* map reload interval */
|
||||
char *map_type; /* global map type */
|
||||
char *search_path; /* search path for maps */
|
||||
char *mount_type; /* mount type for map */
|
||||
char *debug_mtab_file; /* path for the mtab file during debug mode */
|
||||
u_int flags; /* various CFM_* flags */
|
||||
|
||||
#define AMU_TYPE_NONE -1 /* for amfs_auto_{timeo,retrans,toplvl} */
|
||||
#define AMU_TYPE_UDP 0 /* for amfs_auto_{timeo,retrans,toplvl} */
|
||||
#define AMU_TYPE_TCP 1 /* for amfs_auto_{timeo,retrans,toplvl} */
|
||||
/*
|
||||
* Note: toplvl is only UDP, but we want to separate it from regular
|
||||
* NFS mounts which Amd makes, because the toplvl mount is a localhost
|
||||
* mount for which different timeo/retrans parameters may be desired.
|
||||
*/
|
||||
#define AMU_TYPE_TOPLVL 2 /* for amfs_auto_{timeo,retrans,toplvl} */
|
||||
#define AMU_TYPE_MAX 3 /* for amfs_auto_{timeo,retrans,toplvl} */
|
||||
int amfs_auto_retrans[AMU_TYPE_MAX]; /* NFS retransmit counter */
|
||||
int amfs_auto_timeo[AMU_TYPE_MAX]; /* NFS retry interval */
|
||||
|
||||
int am_timeo; /* cache duration */
|
||||
int am_timeo_w; /* dismount interval */
|
||||
u_long portmap_program; /* amd RPC program number */
|
||||
u_short preferred_amq_port; /* preferred amq service RPC port number (0 means "any") */
|
||||
#ifdef HAVE_MAP_HESIOD
|
||||
char *hesiod_base; /* Hesiod rhs */
|
||||
#endif /* HAVE_MAP_HESIOD */
|
||||
#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) */
|
||||
long ldap_proto_version; /* LDAP protocol version */
|
||||
#endif /* HAVE_MAP_LDAP */
|
||||
#ifdef HAVE_MAP_NIS
|
||||
char *nis_domain; /* YP domain name */
|
||||
#endif /* HAVE_MAP_NIS */
|
||||
char *nfs_proto; /* NFS protocol (NULL, udp, tcp) */
|
||||
int nfs_vers; /* NFS version (0, 2, 3, 4) */
|
||||
int nfs_vers_ping; /* NFS rpc ping version (0, 2, 3, 4) */
|
||||
u_int exec_map_timeout; /* timeout (seconds) for executable maps */
|
||||
};
|
||||
|
||||
/* if you add anything here, update conf.c:reset_cf_map() */
|
||||
struct cf_map {
|
||||
char *cfm_dir; /* /home, /u, /src */
|
||||
char *cfm_name; /* amd.home, /etc/amd.home ... */
|
||||
char *cfm_type; /* file, hesiod, ndbm, nis ... */
|
||||
char *cfm_defaults; /* map /defaults options in amd.conf */
|
||||
char *cfm_opts; /* -cache:=all, etc. */
|
||||
char *cfm_search_path; /* /etc/local:/etc/amdmaps:/misc/yp */
|
||||
char *cfm_tag; /* optional map tag for amd -T */
|
||||
u_int cfm_flags; /* browsable_dirs? mount_type? */
|
||||
struct cf_map *cfm_next; /* pointer to next in list (if any) */
|
||||
};
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
u_int reloads; /* Number of times map was reloaded */
|
||||
u_int nentries; /* Number of entries in the 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 */
|
||||
cf_map_t *cfm; /* pointer to per-map amd.conf opts, if any */
|
||||
void *map_data; /* Map data black box */
|
||||
};
|
||||
|
||||
/*
|
||||
* Options
|
||||
*/
|
||||
struct am_opts {
|
||||
char *fs_glob; /* Smashed copy of global options */
|
||||
char *fs_local; /* Expanded copy of local options */
|
||||
char *fs_mtab; /* Mount table entry */
|
||||
/* Other options ... */
|
||||
char *opt_dev;
|
||||
char *opt_delay;
|
||||
char *opt_dir;
|
||||
char *opt_fs;
|
||||
char *opt_group;
|
||||
char *opt_mount;
|
||||
char *opt_opts;
|
||||
char *opt_remopts;
|
||||
char *opt_pref;
|
||||
char *opt_cache;
|
||||
char *opt_rfs;
|
||||
char *opt_rhost;
|
||||
char *opt_sublink;
|
||||
char *opt_type;
|
||||
char *opt_mount_type; /* "nfs" or "autofs" */
|
||||
char *opt_unmount;
|
||||
char *opt_umount; /* an "alias" for opt_unmount (type:=program) */
|
||||
char *opt_user;
|
||||
char *opt_maptype; /* map type: file, nis, hesiod, etc. */
|
||||
char *opt_cachedir; /* cache directory */
|
||||
char *opt_addopts; /* options to add to opt_opts */
|
||||
};
|
||||
|
||||
struct am_ops {
|
||||
char *fs_type; /* type of filesystems e.g. "nfsx" */
|
||||
vfs_match fs_match; /* fxn: match */
|
||||
vfs_init fs_init; /* fxn: initialization */
|
||||
vmount_fs mount_fs; /* fxn: mount my own vnode */
|
||||
vumount_fs umount_fs; /* fxn: unmount my own vnode */
|
||||
vlookup_child lookup_child; /* fxn: lookup path-name */
|
||||
vmount_child mount_child; /* fxn: mount path-name */
|
||||
vreaddir readdir; /* fxn: read directory */
|
||||
vreadlink readlink; /* fxn: read link */
|
||||
vmounted mounted; /* fxn: after-mount extra actions */
|
||||
vumounted umounted; /* fxn: after-umount extra actions */
|
||||
vffserver ffserver; /* fxn: find a file server */
|
||||
vget_wchan get_wchan; /* fxn: get the waiting channel */
|
||||
int nfs_fs_flags; /* filesystem flags FS_* for nfs mounts */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
int autofs_fs_flags;/* filesystem flags FS_* for autofs mounts */
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
/*
|
||||
* List of mounted filesystems
|
||||
*/
|
||||
struct mntfs {
|
||||
qelem mf_q; /* List of mounted filesystems */
|
||||
am_ops *mf_ops; /* Operations on this mountpoint */
|
||||
am_opts *mf_fo; /* File opts */
|
||||
char *mf_mount; /* "/a/kiska/home/kiska" */
|
||||
char *mf_info; /* Mount info */
|
||||
char *mf_auto; /* Mount info */
|
||||
char *mf_mopts; /* FS mount opts */
|
||||
char *mf_remopts; /* Remote FS mount opts */
|
||||
char *mf_loopdev; /* loop device name for /dev/loop mounts */
|
||||
fserver *mf_server; /* File server */
|
||||
int mf_fsflags; /* Flags FS_* copied from mf_ops->*_fs_flags */
|
||||
int mf_flags; /* Flags MFF_* */
|
||||
int mf_error; /* Error code from background mount */
|
||||
int mf_refc; /* Number of references to this node */
|
||||
int mf_cid; /* Callout id */
|
||||
void (*mf_prfree) (opaque_t); /* Free private space */
|
||||
opaque_t mf_private; /* Private - per-fs data */
|
||||
};
|
||||
|
||||
/*
|
||||
* Locations: bindings between keys and mntfs
|
||||
*/
|
||||
struct am_loc {
|
||||
am_opts *al_fo;
|
||||
mntfs *al_mnt;
|
||||
int al_refc;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* List of fileservers
|
||||
*/
|
||||
struct fserver {
|
||||
qelem fs_q; /* List of fileservers */
|
||||
int fs_refc; /* Number of references to this server */
|
||||
char *fs_host; /* Normalized hostname of server */
|
||||
struct sockaddr_in *fs_ip; /* Network address of server */
|
||||
int fs_cid; /* Callout id */
|
||||
int fs_pinger; /* Ping (keepalive) interval */
|
||||
int fs_flags; /* Flags */
|
||||
char *fs_type; /* File server type */
|
||||
u_long fs_version; /* NFS version of server (2, 3, etc.)*/
|
||||
char *fs_proto; /* NFS protocol of server (tcp, udp, etc.) */
|
||||
opaque_t fs_private; /* Private data */
|
||||
void (*fs_prfree) (opaque_t); /* Free private data */
|
||||
};
|
||||
|
||||
/*
|
||||
* Per-mountpoint statistics
|
||||
*/
|
||||
struct am_stats {
|
||||
time_t s_mtime; /* Mount time */
|
||||
u_short s_uid; /* Uid of mounter */
|
||||
int s_getattr; /* Count of getattrs */
|
||||
int s_lookup; /* Count of lookups */
|
||||
int s_readdir; /* Count of readdirs */
|
||||
int s_readlink; /* Count of readlinks */
|
||||
int s_statfs; /* Count of statfs */
|
||||
int s_fsinfo; /* Count of fsinfo */
|
||||
int s_pathconf; /* Count of pathconf */
|
||||
};
|
||||
|
||||
/*
|
||||
* System statistics
|
||||
*/
|
||||
struct amd_stats {
|
||||
int d_drops; /* Dropped requests */
|
||||
int d_stale; /* Stale NFS handles */
|
||||
int d_mok; /* Successful mounts */
|
||||
int d_merr; /* Failed mounts */
|
||||
int d_uerr; /* Failed unmounts */
|
||||
};
|
||||
extern struct amd_stats amd_stats;
|
||||
|
||||
/*
|
||||
* Map of auto-mount points.
|
||||
*/
|
||||
struct am_node {
|
||||
int am_mapno; /* Map number */
|
||||
am_loc *am_al; /* Mounted filesystem */
|
||||
am_loc **am_alarray; /* Filesystem sources to try to mount */
|
||||
char *am_name; /* "kiska": name of this node */
|
||||
char *am_path; /* "/home/kiska": path of this node's mount point */
|
||||
char *am_link; /* "/a/kiska/home/kiska/this/that": link to sub-dir */
|
||||
am_node *am_parent; /* Parent of this node */
|
||||
am_node *am_ysib; /* Younger sibling of this node */
|
||||
am_node *am_osib; /* Older sibling of this node */
|
||||
am_node *am_child; /* First child of this node */
|
||||
nfsattrstat am_attr; /* File attributes */
|
||||
#define am_fattr am_attr.ns_u.ns_attr_u
|
||||
int am_flags; /* Boolean flags AMF_* */
|
||||
int am_error; /* Specific mount error */
|
||||
time_t am_ttl; /* Time to live */
|
||||
int am_timeo_w; /* Dismount wait interval */
|
||||
int am_timeo; /* Cache timeout interval */
|
||||
u_int am_gen; /* Generation number */
|
||||
char *am_pref; /* Mount info prefix */
|
||||
am_stats am_stats; /* Statistics gathering */
|
||||
SVCXPRT *am_transp; /* Info for quick reply */
|
||||
dev_t am_dev; /* Device number */
|
||||
dev_t am_rdev; /* Remote/real device number */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
autofs_fh_t *am_autofs_fh;
|
||||
time_t am_autofs_ttl; /* Time to expire autofs nodes */
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
int am_fd[2]; /* parent child pipe fd's for sync umount */
|
||||
};
|
||||
|
||||
/*
|
||||
* 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 amq_string *amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp);
|
||||
extern int *amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp);
|
||||
extern int *amqproc_mount_1_svc(voidp argp, struct svc_req *rqstp);
|
||||
extern int *amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp);
|
||||
extern voidp amqproc_null_1_svc(voidp argp, struct svc_req *rqstp);
|
||||
extern int *amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp);
|
||||
extern int *amqproc_sync_umnt_1_svc_parent(voidp argp, struct svc_req *rqstp);
|
||||
extern amq_sync_umnt *amqproc_sync_umnt_1_svc_child(voidp argp, struct svc_req *rqstp);
|
||||
extern amq_sync_umnt *amqproc_sync_umnt_1_svc_async(voidp argp, struct svc_req *rqstp);
|
||||
extern amq_map_info_list *amqproc_getmapinfo_1_svc(voidp argp, struct svc_req *rqstp);
|
||||
|
||||
/* other external definitions */
|
||||
extern am_nfs_handle_t *get_root_nfs_fh(char *dir, am_nfs_handle_t *nfh);
|
||||
extern am_node *find_ap(char *);
|
||||
extern am_node *get_ap_child(am_node *, char *);
|
||||
extern bool_t xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead);
|
||||
extern bool_t xdr_amq_map_info_qelem(XDR *xdrs, qelem *qhead);
|
||||
extern fserver *find_nfs_srvr(mntfs *mf);
|
||||
extern int mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf);
|
||||
extern int process_all_regular_maps(void);
|
||||
extern cf_map_t *find_cf_map(const char *name);
|
||||
extern int set_conf_kv(const char *section, const char *k, const char *v);
|
||||
extern int mount_node(opaque_t arg);
|
||||
extern int unmount_mp(am_node *mp);
|
||||
extern int conf_parse(void); /* "yyparse" renamed */
|
||||
extern FILE *conf_in; /* "yyin" renamed */
|
||||
|
||||
extern void amfs_mkcacheref(mntfs *mf);
|
||||
extern int amfs_mount(am_node *mp, mntfs *mf, char *opts);
|
||||
extern void assign_error_mntfs(am_node *mp);
|
||||
extern am_node *next_nonerror_node(am_node *xp);
|
||||
extern void flush_srvr_nfs_cache(fserver *fs);
|
||||
extern void am_mounted(am_node *);
|
||||
extern void mf_mounted(mntfs *mf, bool_t call_free_opts);
|
||||
extern void am_unmounted(am_node *);
|
||||
extern am_node *get_exported_ap(int index);
|
||||
extern am_node *get_first_exported_ap(int *index);
|
||||
extern am_node *get_next_exported_ap(int *index);
|
||||
extern am_node *path_to_exported_ap(char *path);
|
||||
extern am_node *exported_ap_alloc(void);
|
||||
extern am_node *find_mf(mntfs *);
|
||||
extern am_node *next_map(int *);
|
||||
extern am_ops *ops_match(am_opts *, char *, char *, char *, char *, char *);
|
||||
extern am_ops *ops_search(char *);
|
||||
extern fserver *dup_srvr(fserver *);
|
||||
extern void srvrlog(fserver *, char *);
|
||||
extern int get_mountd_port(fserver *, u_short *, wchan_t);
|
||||
extern void flush_nfs_fhandle_cache(fserver *);
|
||||
|
||||
extern mntfs *dup_mntfs(mntfs *);
|
||||
extern am_loc *dup_loc(am_loc *);
|
||||
extern mntfs *find_mntfs(am_ops *, am_opts *, char *, char *, char *, char *, char *);
|
||||
extern mntfs *locate_mntfs(am_ops *, am_opts *, char *, char *, char *, char *, char *);
|
||||
extern am_loc *new_loc(void);
|
||||
extern mntfs *new_mntfs(void);
|
||||
extern mntfs *realloc_mntfs(mntfs *, am_ops *, am_opts *, char *, char *, char *, char *, char *);
|
||||
extern void flush_mntfs(void);
|
||||
extern void free_mntfs(voidp);
|
||||
extern void free_loc(voidp);
|
||||
|
||||
|
||||
extern void amq_program_1(struct svc_req *rqstp, SVCXPRT *transp);
|
||||
extern int background(void);
|
||||
extern void deslashify(char *);
|
||||
extern void do_task_notify(void);
|
||||
extern int eval_fs_opts(am_opts *, char *, char *, char *, char *, char *);
|
||||
extern int file_read_line(char *, int, FILE *);
|
||||
extern void forcibly_timeout_mp(am_node *);
|
||||
extern void free_map(am_node *);
|
||||
extern void free_opts(am_opts *);
|
||||
extern am_opts *copy_opts(am_opts *);
|
||||
extern void free_srvr(fserver *);
|
||||
extern int fwd_init(void);
|
||||
extern int fwd_packet(int, char *, int, struct sockaddr_in *, struct sockaddr_in *, opaque_t, fwd_fun *);
|
||||
extern void fwd_reply(void);
|
||||
extern void get_args(int argc, char *argv[]);
|
||||
extern wchan_t get_mntfs_wchan(mntfs *mf);
|
||||
extern void host_normalize(char **);
|
||||
extern void init_map(am_node *, char *);
|
||||
extern void ins_que(qelem *, qelem *);
|
||||
extern void insert_am(am_node *, am_node *);
|
||||
extern int make_nfs_auth(void);
|
||||
extern void make_root_node(void);
|
||||
extern void map_flush_srvr(fserver *);
|
||||
extern void mapc_add_kv(mnt_map *, char *, char *);
|
||||
extern mnt_map *mapc_find(char *, char *, const char *, const char *);
|
||||
extern void mapc_free(opaque_t);
|
||||
extern int mapc_keyiter(mnt_map *, key_fun *, opaque_t);
|
||||
extern void mapc_reload(void);
|
||||
extern int mapc_search(mnt_map *, char *, char **);
|
||||
extern void mapc_showtypes(char *buf, size_t l);
|
||||
extern int mapc_type_exists(const char *type);
|
||||
extern void mk_fattr(nfsfattr *, nfsftype);
|
||||
extern int mount_auto_node(char *, opaque_t);
|
||||
extern int mount_automounter(int);
|
||||
extern int mount_exported(void);
|
||||
extern void mp_to_fh(am_node *, am_nfs_fh *);
|
||||
extern void mp_to_fh3(am_node *mp, am_nfs_fh3 *fhp);
|
||||
extern void new_ttl(am_node *);
|
||||
extern void nfs_quick_reply(am_node *mp, int error);
|
||||
extern void normalize_slash(char *);
|
||||
extern void notify_child(am_node *, au_etype, int, int);
|
||||
extern void ops_showamfstypes(char *buf, size_t l);
|
||||
extern void ops_showfstypes(char *outbuf, size_t l);
|
||||
extern void rem_que(qelem *);
|
||||
extern void reschedule_timeout_mp(void);
|
||||
extern void restart(void);
|
||||
extern void restart_automounter_nodes(void);
|
||||
extern int root_keyiter(key_fun *, opaque_t);
|
||||
extern void root_newmap(const char *, const char *, const char *, const cf_map_t *);
|
||||
extern void run_task(task_fun *, opaque_t, cb_fun *, opaque_t);
|
||||
extern void sched_task(cb_fun *, opaque_t, wchan_t);
|
||||
extern int softclock(void);
|
||||
extern int timeout(u_int, void (*fn)(opaque_t), opaque_t);
|
||||
extern void timeout_mp(opaque_t);
|
||||
extern void untimeout(int);
|
||||
extern void umount_exported(void);
|
||||
extern int valid_key(char *);
|
||||
extern void wakeup(wchan_t);
|
||||
extern void wakeup_srvr(fserver *);
|
||||
extern void wakeup_task(int, int, wchan_t);
|
||||
#define SIZEOF_PID_FSNAME (16 + MAXHOSTNAMELEN)
|
||||
extern char pid_fsname[SIZEOF_PID_FSNAME]; /* "kiska.southseas.nz:(pid%d)" */
|
||||
#define SIZEOF_HOSTD (2 * MAXHOSTNAMELEN + 1)
|
||||
extern char hostd[SIZEOF_HOSTD]; /* Host+domain */
|
||||
#define SIZEOF_OPTS 256 /* used for char opts[] and preopts[] */
|
||||
|
||||
/*
|
||||
* Global variables.
|
||||
*/
|
||||
extern SVCXPRT *current_transp; /* For nfs_quick_reply() */
|
||||
extern dispatcher_t nfs_dispatcher;
|
||||
extern char *conf_tag;
|
||||
#define SIZEOF_UID_STR 12
|
||||
#define SIZEOF_GID_STR 12
|
||||
extern char *opt_gid, gid_str[SIZEOF_GID_STR];
|
||||
extern char *opt_uid, uid_str[SIZEOF_UID_STR];
|
||||
extern int NumChildren;
|
||||
extern int fwd_sock;
|
||||
extern int select_intr_valid;
|
||||
extern int immediate_abort; /* Should close-down unmounts be retried */
|
||||
extern int usage;
|
||||
extern int use_conf_file; /* use amd configuration file */
|
||||
extern int task_notify_todo; /* Task notifier needs running */
|
||||
extern jmp_buf select_intr;
|
||||
extern qelem mfhead;
|
||||
extern struct amu_global_options gopt; /* where global options are stored */
|
||||
extern time_t do_mapc_reload; /* Flush & reload mount map cache */
|
||||
extern time_t next_softclock; /* Time to call softclock() */
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
extern sigset_t masked_sigs;
|
||||
#endif /* HAVE_SIGACTION */
|
||||
|
||||
#if defined(HAVE_AMU_FS_LINK) || defined(HAVE_AMU_FS_LINKX)
|
||||
extern char *amfs_link_match(am_opts *fo);
|
||||
#endif /* defined(HAVE_AMU_FS_LINK) || defined(HAVE_AMU_FS_LINKX) */
|
||||
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
extern int amd_use_autofs;
|
||||
|
||||
extern int autofs_get_fh(am_node *mp);
|
||||
extern void autofs_release_fh(am_node *mp);
|
||||
extern void autofs_get_mp(am_node *mp);
|
||||
extern void autofs_release_mp(am_node *mp);
|
||||
extern void autofs_add_fdset(fd_set *readfds);
|
||||
extern int autofs_handle_fdset(fd_set *readfds, int nsel);
|
||||
extern void autofs_mounted(am_node *mp);
|
||||
extern void autofs_mount_succeeded(am_node *mp);
|
||||
extern void autofs_mount_failed(am_node *mp);
|
||||
extern int autofs_umount_succeeded(am_node *mp);
|
||||
extern int autofs_umount_failed(am_node *mp);
|
||||
extern int autofs_mount_fs(am_node *mp, mntfs *mf);
|
||||
extern int autofs_umount_fs(am_node *mp, mntfs *mf);
|
||||
extern void autofs_get_opts(char *opts, size_t l, autofs_fh_t *fh);
|
||||
extern int autofs_compute_mount_flags(mntent_t *);
|
||||
extern void autofs_timeout_mp(am_node *);
|
||||
extern int create_autofs_service(void);
|
||||
extern int destroy_autofs_service(void);
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
/**************************************************************************/
|
||||
/*** Generic file-system types, implemented as part of the native O/S. ***/
|
||||
/**************************************************************************/
|
||||
|
||||
/*
|
||||
* Loopback File System
|
||||
* Many systems can't support this, and in any case most of the
|
||||
* functionality is available with Symlink FS.
|
||||
*/
|
||||
#ifdef HAVE_FS_LOFS
|
||||
extern am_ops lofs_ops;
|
||||
extern int mount_lofs(char *mntdir, char *fs_name, char *opts, int on_autofs);
|
||||
#endif /* HAVE_FS_LOFS */
|
||||
|
||||
/*
|
||||
* CD-ROM File System (CD-ROM)
|
||||
* (HSFS: High Sierra F/S on some machines)
|
||||
* Many systems can't support this, and in any case most of the
|
||||
* functionality is available with program FS.
|
||||
*/
|
||||
#ifdef HAVE_FS_CDFS
|
||||
extern am_ops cdfs_ops;
|
||||
#endif /* HAVE_FS_CDFS */
|
||||
|
||||
/*
|
||||
* PC File System (MS-DOS)
|
||||
* Many systems can't support this, and in any case most of the
|
||||
* functionality is available with program FS.
|
||||
*/
|
||||
#ifdef HAVE_FS_PCFS
|
||||
extern am_ops pcfs_ops;
|
||||
#endif /* HAVE_FS_PCFS */
|
||||
|
||||
/*
|
||||
* UDF File System
|
||||
* Many systems can't support this, and in any case most of the
|
||||
* functionality is available with program FS.
|
||||
*/
|
||||
#ifdef HAVE_FS_UDF
|
||||
extern am_ops udf_ops;
|
||||
#endif /* HAVE_FS_UDF */
|
||||
|
||||
#ifdef HAVE_FS_LUSTRE
|
||||
extern am_ops lustre_ops;
|
||||
#endif /* HAVE_FS_LUSTRE */
|
||||
|
||||
/*
|
||||
* Caching File System (Solaris)
|
||||
*/
|
||||
#ifdef HAVE_FS_CACHEFS
|
||||
extern am_ops cachefs_ops;
|
||||
#endif /* HAVE_FS_CACHEFS */
|
||||
|
||||
/*
|
||||
* In memory /tmp filesystem (Linux, NetBSD)
|
||||
*/
|
||||
#ifdef HAVE_FS_TMPFS
|
||||
extern am_ops tmpfs_ops;
|
||||
#endif /* HAVE_FS_TMPFS */
|
||||
/*
|
||||
* Network File System
|
||||
* Good, slow, NFS V.2.
|
||||
*/
|
||||
#ifdef HAVE_FS_NFS
|
||||
extern am_ops nfs_ops; /* NFS */
|
||||
extern fserver *find_nfs_srvr (mntfs *);
|
||||
extern qelem nfs_srvr_list;
|
||||
#endif /* HAVE_FS_NFS */
|
||||
|
||||
/*
|
||||
* Un*x File System
|
||||
* Normal local disk file system.
|
||||
*/
|
||||
#ifdef HAVE_FS_UFS
|
||||
extern am_ops ufs_ops; /* Un*x file system */
|
||||
#endif /* HAVE_FS_UFS */
|
||||
|
||||
/* Unix file system (irix) */
|
||||
#ifdef HAVE_FS_XFS
|
||||
extern am_ops xfs_ops; /* Un*x file system */
|
||||
#endif /* HAVE_FS_XFS */
|
||||
|
||||
/* Unix file system (ext*) */
|
||||
#ifdef HAVE_FS_EXT
|
||||
extern am_ops ext2_ops; /* Un*x file system */
|
||||
extern am_ops ext3_ops; /* Un*x file system */
|
||||
extern am_ops ext4_ops; /* Un*x file system */
|
||||
#endif /* HAVE_FS_EXT */
|
||||
|
||||
/* Unix file system (irix) */
|
||||
#ifdef HAVE_FS_EFS
|
||||
extern am_ops efs_ops; /* Un*x file system */
|
||||
#endif /* HAVE_FS_EFS */
|
||||
|
||||
/**************************************************************************/
|
||||
/*** Automounter file-system types, implemented by amd. ***/
|
||||
/**************************************************************************/
|
||||
|
||||
/*
|
||||
* Root AMD File System
|
||||
*/
|
||||
extern am_ops amfs_root_ops; /* Root file system */
|
||||
|
||||
/*
|
||||
* Generic amfs helper methods
|
||||
*/
|
||||
extern am_node *amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op);
|
||||
extern am_node *amfs_generic_mount_child(am_node *ap, int *error_return);
|
||||
extern int amfs_generic_readdir(am_node *mp, voidp cookie, voidp dp, voidp ep, u_int count);
|
||||
extern int amfs_generic_umount(am_node *mp, mntfs *mf);
|
||||
extern void amfs_generic_mounted(mntfs *mf);
|
||||
extern char *amfs_generic_match(am_opts *fo);
|
||||
extern fserver *amfs_generic_find_srvr(mntfs *);
|
||||
|
||||
/*
|
||||
* Automount File System
|
||||
*/
|
||||
#ifdef HAVE_AMU_FS_AUTO
|
||||
extern am_ops amfs_auto_ops; /* Automount file system (this!) */
|
||||
#endif /* HAVE_AMU_FS_AUTO */
|
||||
|
||||
/*
|
||||
* Toplvl Automount File System
|
||||
*/
|
||||
#ifdef HAVE_AMU_FS_TOPLVL
|
||||
extern am_ops amfs_toplvl_ops; /* Toplvl Automount file system */
|
||||
extern int amfs_toplvl_mount(am_node *mp, mntfs *mf);
|
||||
extern int amfs_toplvl_umount(am_node *mp, mntfs *mf);
|
||||
#endif /* HAVE_AMU_FS_TOPLVL */
|
||||
|
||||
/*
|
||||
* Direct Automount File System
|
||||
*/
|
||||
#ifdef HAVE_AMU_FS_DIRECT
|
||||
extern am_ops amfs_direct_ops; /* Direct Automount file system (this too) */
|
||||
#endif /* HAVE_AMU_FS_DIRECT */
|
||||
|
||||
/*
|
||||
* Error File System
|
||||
*/
|
||||
#ifdef HAVE_AMU_FS_ERROR
|
||||
extern am_ops amfs_error_ops; /* Error file system */
|
||||
extern am_node *amfs_error_lookup_child(am_node *mp, char *fname, int *error_return, int op);
|
||||
extern am_node *amfs_error_mount_child(am_node *ap, int *error_return);
|
||||
extern int amfs_error_readdir(am_node *mp, voidp cookie, voidp dp, voidp ep, u_int count);
|
||||
|
||||
#endif /* HAVE_AMU_FS_ERROR */
|
||||
|
||||
/*
|
||||
* NFS mounts with local existence check.
|
||||
*/
|
||||
#ifdef HAVE_AMU_FS_NFSL
|
||||
extern am_ops amfs_nfsl_ops; /* NFSL */
|
||||
#endif /* HAVE_AMU_FS_NFSL */
|
||||
|
||||
/*
|
||||
* Multi-nfs mounts.
|
||||
*/
|
||||
#ifdef HAVE_AMU_FS_NFSX
|
||||
extern am_ops amfs_nfsx_ops; /* NFSX */
|
||||
#endif /* HAVE_AMU_FS_NFSX */
|
||||
|
||||
/*
|
||||
* NFS host - a whole tree.
|
||||
*/
|
||||
#ifdef HAVE_AMU_FS_HOST
|
||||
extern am_ops amfs_host_ops; /* NFS host */
|
||||
#endif /* HAVE_AMU_FS_HOST */
|
||||
|
||||
/*
|
||||
* Program File System
|
||||
* This is useful for things like RVD.
|
||||
*/
|
||||
#ifdef HAVE_AMU_FS_PROGRAM
|
||||
extern am_ops amfs_program_ops; /* Program File System */
|
||||
#endif /* HAVE_AMU_FS_PROGRAM */
|
||||
|
||||
/*
|
||||
* Symbolic-link file system.
|
||||
* A "filesystem" which is just a symbol link.
|
||||
*/
|
||||
#ifdef HAVE_AMU_FS_LINK
|
||||
extern am_ops amfs_link_ops; /* Symlink FS */
|
||||
#endif /* HAVE_AMU_FS_LINK */
|
||||
|
||||
/*
|
||||
* Symbolic-link file system, which also checks that the target of
|
||||
* the symlink exists.
|
||||
* A "filesystem" which is just a symbol link.
|
||||
*/
|
||||
#ifdef HAVE_AMU_FS_LINKX
|
||||
extern am_ops amfs_linkx_ops; /* Symlink FS with existence check */
|
||||
#endif /* HAVE_AMU_FS_LINKX */
|
||||
|
||||
/*
|
||||
* Union file system
|
||||
*/
|
||||
#ifdef HAVE_AMU_FS_UNION
|
||||
extern am_ops amfs_union_ops; /* Union FS */
|
||||
#endif /* HAVE_AMU_FS_UNION */
|
||||
|
||||
#endif /* not _AMD_H */
|
@ -1,174 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/amfs_auto.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Automount file system
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
|
||||
/****************************************************************************
|
||||
*** MACROS ***
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*** STRUCTURES ***
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*** FORWARD DEFINITIONS ***
|
||||
****************************************************************************/
|
||||
static int amfs_auto_mount(am_node *mp, mntfs *mf);
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*** OPS STRUCTURES ***
|
||||
****************************************************************************/
|
||||
am_ops amfs_auto_ops =
|
||||
{
|
||||
"auto",
|
||||
amfs_generic_match,
|
||||
0, /* amfs_auto_init */
|
||||
amfs_auto_mount,
|
||||
amfs_generic_umount,
|
||||
amfs_generic_lookup_child,
|
||||
amfs_generic_mount_child,
|
||||
amfs_generic_readdir,
|
||||
0, /* amfs_auto_readlink */
|
||||
amfs_generic_mounted,
|
||||
0, /* amfs_auto_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* amfs_auto_get_wchan */
|
||||
FS_AMQINFO | FS_DIRECTORY,
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_AUTO_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*** FUNCTIONS ***
|
||||
****************************************************************************/
|
||||
/*
|
||||
* Mount a sub-mount
|
||||
*/
|
||||
static int
|
||||
amfs_auto_mount(am_node *mp, mntfs *mf)
|
||||
{
|
||||
if (mp->am_parent == NULL)
|
||||
return EINVAL;
|
||||
/*
|
||||
* Pseudo-directories are used to provide some structure
|
||||
* to the automounted directories instead
|
||||
* of putting them all in the top-level automount directory.
|
||||
*
|
||||
* Here, just increment the parent's link count.
|
||||
*/
|
||||
mp->am_parent->am_fattr.na_nlink++;
|
||||
|
||||
/*
|
||||
* Info field of . means use parent's info field.
|
||||
* Historical - not documented.
|
||||
*/
|
||||
if (mf->mf_info[0] == '.' && mf->mf_info[1] == '\0')
|
||||
mf->mf_info = strealloc(mf->mf_info, mp->am_parent->am_al->al_mnt->mf_info);
|
||||
|
||||
/*
|
||||
* Compute prefix:
|
||||
*
|
||||
* If there is an option prefix then use that else
|
||||
* If the parent had a prefix then use that with name
|
||||
* of this node appended else
|
||||
* Use the name of this node.
|
||||
*
|
||||
* That means if you want no prefix you must say so
|
||||
* in the map.
|
||||
*/
|
||||
if (mf->mf_fo->opt_pref) {
|
||||
/* allow pref:=null to set a real null prefix */
|
||||
if (STREQ(mf->mf_fo->opt_pref, "null")) {
|
||||
mp->am_pref = xstrdup("");
|
||||
} else {
|
||||
/*
|
||||
* the prefix specified as an option
|
||||
*/
|
||||
mp->am_pref = xstrdup(mf->mf_fo->opt_pref);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* else the parent's prefix
|
||||
* followed by the name
|
||||
* followed by /
|
||||
*/
|
||||
char *ppref = mp->am_parent->am_pref;
|
||||
if (ppref == 0)
|
||||
ppref = "";
|
||||
mp->am_pref = str3cat((char *) NULL, ppref, mp->am_name, "/");
|
||||
}
|
||||
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (mf->mf_flags & MFF_IS_AUTOFS) {
|
||||
char opts[SIZEOF_OPTS];
|
||||
int error;
|
||||
|
||||
autofs_get_opts(opts, sizeof(opts), mp->am_autofs_fh);
|
||||
|
||||
/* now do the mount */
|
||||
error = amfs_mount(mp, mf, opts);
|
||||
if (error) {
|
||||
errno = error;
|
||||
plog(XLOG_FATAL, "amfs_auto_mount: amfs_mount failed: %m");
|
||||
return error;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
/*
|
||||
* Attach a map cache
|
||||
*/
|
||||
amfs_mkcacheref(mf);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/amfs_direct.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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_generic_match,
|
||||
0, /* amfs_direct_init */
|
||||
amfs_toplvl_mount,
|
||||
amfs_toplvl_umount,
|
||||
amfs_generic_lookup_child,
|
||||
amfs_generic_mount_child,
|
||||
amfs_error_readdir,
|
||||
amfs_direct_readlink,
|
||||
amfs_generic_mounted,
|
||||
0, /* amfs_direct_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* amfs_direct_get_wchan */
|
||||
FS_DIRECT | FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO,
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_DIRECT_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*** 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_al->al_mnt->mf_private)
|
||||
amfs_mkcacheref(mp->am_al->al_mnt);
|
||||
xp = amfs_generic_lookup_child(mp, mp->am_path + 1, &rc, VLOOK_CREATE);
|
||||
if (xp && rc < 0)
|
||||
xp = amfs_generic_mount_child(xp, &rc);
|
||||
}
|
||||
if (xp) {
|
||||
new_ttl(xp); /* (7/12/89) from Rein Tollevik */
|
||||
return xp;
|
||||
}
|
||||
if (amd_state == Finishing)
|
||||
rc = ENOENT;
|
||||
*error_return = rc;
|
||||
return 0;
|
||||
}
|
@ -1,147 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/amfs_error.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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_mount(am_node *am, mntfs *mf);
|
||||
static int amfs_error_umount(am_node *am, mntfs *mf);
|
||||
|
||||
|
||||
/*
|
||||
* Ops structure
|
||||
*/
|
||||
am_ops amfs_error_ops =
|
||||
{
|
||||
"error",
|
||||
amfs_error_match,
|
||||
0, /* amfs_error_init */
|
||||
amfs_error_mount,
|
||||
amfs_error_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* amfs_error_readlink */
|
||||
0, /* amfs_error_mounted */
|
||||
0, /* amfs_error_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* amfs_error_get_wchan */
|
||||
FS_DISCARD, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_ERROR_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* EFS file system always matches
|
||||
*/
|
||||
static char *
|
||||
amfs_error_match(am_opts *fo)
|
||||
{
|
||||
return xstrdup("(error-hook)");
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
amfs_error_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
amfs_error_umount(am_node *am, 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_lookup_child(am_node *mp, char *fname, int *error_return, int op)
|
||||
{
|
||||
*error_return = ESTALE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* EFS interface to RPC lookup() routine.
|
||||
* Should never get here in the automounter.
|
||||
* If we do then just give an error.
|
||||
*/
|
||||
am_node *
|
||||
amfs_error_mount_child(am_node *ap, int *error_return)
|
||||
{
|
||||
*error_return = ESTALE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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, voidp cookie, voidp dp, voidp ep, u_int count)
|
||||
{
|
||||
return ESTALE;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,710 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/amfs_host.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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_init(mntfs *mf);
|
||||
static int amfs_host_mount(am_node *am, mntfs *mf);
|
||||
static int amfs_host_umount(am_node *am, mntfs *mf);
|
||||
static void amfs_host_umounted(mntfs *mf);
|
||||
|
||||
/*
|
||||
* Ops structure
|
||||
*/
|
||||
am_ops amfs_host_ops =
|
||||
{
|
||||
"host",
|
||||
amfs_host_match,
|
||||
amfs_host_init,
|
||||
amfs_host_mount,
|
||||
amfs_host_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* amfs_host_readlink */
|
||||
0, /* amfs_host_mounted */
|
||||
amfs_host_umounted,
|
||||
find_nfs_srvr,
|
||||
0, /* amfs_host_get_wchan */
|
||||
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO,
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_HOST_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 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, size_t l, const exports ex, const char *mf_mount)
|
||||
{
|
||||
if (ex->ex_dir[0] == '/') {
|
||||
if (ex->ex_dir[1] == 0)
|
||||
xstrlcpy(mntpt, mf_mount, l);
|
||||
else
|
||||
xsnprintf(mntpt, l, "%s%s", mf_mount, ex->ex_dir);
|
||||
} else if (ex->ex_dir[0] >= 'a' &&
|
||||
ex->ex_dir[0] <= 'z' &&
|
||||
ex->ex_dir[1] == ':' &&
|
||||
ex->ex_dir[2] == '/' &&
|
||||
ex->ex_dir[3] == 0)
|
||||
xsnprintf(mntpt, l, "%s/%c%%", mf_mount, ex->ex_dir[0]);
|
||||
else
|
||||
xsnprintf(mntpt, l, "%s/%s", 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)
|
||||
{
|
||||
u_short mountd_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
|
||||
* get_mountd_port with our mntfs passed as the wait channel.
|
||||
* get_mountd_port will check some things and then schedule
|
||||
* it so that when the fileserver is ready, a wakeup is done
|
||||
* on this mntfs. amfs_cont() is already sleeping on this mntfs
|
||||
* so as soon as that wakeup happens amfs_cont() is called and
|
||||
* this mount is retried.
|
||||
*/
|
||||
if (mf->mf_server)
|
||||
/*
|
||||
* We don't really care if there's an error returned.
|
||||
* Since this is just to help speed things along, the
|
||||
* error will get handled properly elsewhere.
|
||||
*/
|
||||
get_mountd_port(mf->mf_server, &mountd_port, get_mntfs_wchan(mf));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_mount(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf)
|
||||
{
|
||||
struct stat stb;
|
||||
|
||||
dlog("amfs_host: mounting fs %s on %s\n", fs_name, mntdir);
|
||||
|
||||
(void) mkdirs(mntdir, 0555);
|
||||
if (stat(mntdir, &stb) < 0 || (stb.st_mode & S_IFMT) != S_IFDIR) {
|
||||
plog(XLOG_ERROR, "No mount point for %s - skipping", mntdir);
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
return mount_nfs_fh(fhp, mntdir, fs_name, 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;
|
||||
struct fhstatus res;
|
||||
#ifdef HAVE_FS_NFS3
|
||||
struct am_mountres3 res3;
|
||||
#endif /* HAVE_FS_NFS3 */
|
||||
|
||||
/*
|
||||
* Pick a number, any number...
|
||||
*/
|
||||
tv.tv_sec = 20;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
dlog("Fetching fhandle for %s", dir);
|
||||
|
||||
/*
|
||||
* 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", (int) nfs_version);
|
||||
#ifdef HAVE_FS_NFS3
|
||||
if (nfs_version == NFS_VERSION3
|
||||
#ifdef HAVE_FS_NFS4
|
||||
#ifndef NO_FALLBACK
|
||||
|| nfs_version == NFS_VERSION4
|
||||
#endif /* NO_FALLBACK */
|
||||
#endif /* HAVE_FS_NFS4 */
|
||||
) {
|
||||
|
||||
memset((char *) &res3, 0, sizeof(res3));
|
||||
clnt_stat = clnt_call(client,
|
||||
MOUNTPROC_MNT,
|
||||
(XDRPROC_T_TYPE) xdr_dirpath,
|
||||
(SVC_IN_ARG_TYPE) &dir,
|
||||
(XDRPROC_T_TYPE) xdr_am_mountres3,
|
||||
(SVC_IN_ARG_TYPE) &res3,
|
||||
tv);
|
||||
if (clnt_stat != RPC_SUCCESS) {
|
||||
plog(XLOG_ERROR, "mountd rpc failed: %s", clnt_sperrno(clnt_stat));
|
||||
return EIO;
|
||||
}
|
||||
/* Check the status of the filehandle */
|
||||
if ((errno = res3.fhs_status)) {
|
||||
dlog("fhandle fetch for mount version 3 failed: %m");
|
||||
return errno;
|
||||
}
|
||||
memset((voidp) &fhp->v3, 0, sizeof(am_nfs_fh3));
|
||||
fhp->v3.am_fh3_length = res3.mountres3_u.mountinfo.fhandle.fhandle3_len;
|
||||
memmove(fhp->v3.am_fh3_data,
|
||||
res3.mountres3_u.mountinfo.fhandle.fhandle3_val,
|
||||
fhp->v3.am_fh3_length);
|
||||
} else { /* not NFS_VERSION3 mount */
|
||||
#endif /* HAVE_FS_NFS3 */
|
||||
clnt_stat = clnt_call(client,
|
||||
MOUNTPROC_MNT,
|
||||
(XDRPROC_T_TYPE) xdr_dirpath,
|
||||
(SVC_IN_ARG_TYPE) &dir,
|
||||
(XDRPROC_T_TYPE) xdr_fhstatus,
|
||||
(SVC_IN_ARG_TYPE) &res,
|
||||
tv);
|
||||
if (clnt_stat != RPC_SUCCESS) {
|
||||
plog(XLOG_ERROR, "mountd rpc failed: %s", clnt_sperrno(clnt_stat));
|
||||
return EIO;
|
||||
}
|
||||
/* Check status of filehandle */
|
||||
if (res.fhs_status) {
|
||||
errno = res.fhs_status;
|
||||
dlog("fhandle fetch for mount version 1 failed: %m");
|
||||
return errno;
|
||||
}
|
||||
memmove(&fhp->v2, &res.fhs_fh, NFS_FHSIZE);
|
||||
#ifdef HAVE_FS_NFS3
|
||||
} /* end of "if (nfs_version == NFS_VERSION3)" statement */
|
||||
#endif /* HAVE_FS_NFS3 */
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
amfs_host_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
struct timeval tv2;
|
||||
CLIENT *client;
|
||||
enum clnt_stat clnt_stat;
|
||||
int n_export;
|
||||
int j, k;
|
||||
exports exlist = 0, ex;
|
||||
exports *ep = NULL;
|
||||
am_nfs_handle_t *fp = NULL;
|
||||
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;
|
||||
|
||||
/*
|
||||
* WebNFS servers don't necessarily run mountd.
|
||||
*/
|
||||
if (mf->mf_flags & MFF_WEBNFS) {
|
||||
plog(XLOG_ERROR, "amfs_host_mount: cannot support WebNFS");
|
||||
return EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the mount list
|
||||
*/
|
||||
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_mount: NFS version %d", (int) mf->mf_server->fs_version);
|
||||
#ifdef HAVE_FS_NFS3
|
||||
if (mf->mf_server->fs_version == NFS_VERSION3)
|
||||
mnt_version = AM_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 transmit 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;
|
||||
|
||||
dlog("Fetching export list from %s", host);
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
const char *msg = clnt_sperrno(clnt_stat);
|
||||
plog(XLOG_ERROR, "host_mount 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) {
|
||||
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, sizeof(mntpt), ex, mf->mf_mount);
|
||||
if (already_mounted(mlist, mntpt))
|
||||
/* we have at least one mounted f/s, so don't fail the mount */
|
||||
ok = TRUE;
|
||||
else
|
||||
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)) {
|
||||
dlog("avoiding dup fhandle requested for %s", ep[j]->ex_dir);
|
||||
ep[j] = NULL;
|
||||
} else {
|
||||
k = j;
|
||||
error = fetch_fhandle(client, ep[j]->ex_dir, &fp[j],
|
||||
mf->mf_server->fs_version);
|
||||
if (error)
|
||||
ep[j] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
xstrlcpy(fs_name, mf->mf_info, sizeof(fs_name));
|
||||
if ((rfs_dir = strchr(fs_name, ':')) == (char *) NULL) {
|
||||
plog(XLOG_FATAL, "amfs_host_mount: mf_info has no colon");
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
++rfs_dir;
|
||||
for (j = 0; j < n_export; j++) {
|
||||
ex = ep[j];
|
||||
if (ex) {
|
||||
/*
|
||||
* Note: the sizeof space left in rfs_dir is what's left in fs_name
|
||||
* after strchr() above returned a pointer _inside_ fs_name. The
|
||||
* calculation below also takes into account that rfs_dir was
|
||||
* incremented by the ++ above.
|
||||
*/
|
||||
xstrlcpy(rfs_dir, ex->ex_dir, sizeof(fs_name) - (rfs_dir - fs_name));
|
||||
make_mntpt(mntpt, sizeof(mntpt), ex, mf->mf_mount);
|
||||
if (do_mount(&fp[j], mntpt, fs_name, mf) == 0)
|
||||
ok = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up and exit
|
||||
*/
|
||||
out:
|
||||
discard_mntlist(mlist);
|
||||
XFREE(ep);
|
||||
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_umount(am_node *am, mntfs *mf)
|
||||
{
|
||||
mntlist *ml, *mprev;
|
||||
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
|
||||
int xerror = 0;
|
||||
|
||||
/*
|
||||
* 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 = NULL;
|
||||
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;
|
||||
dlog("amfs_host: unmounts %s", dir);
|
||||
/*
|
||||
* Unmount "dir"
|
||||
*/
|
||||
error = UMOUNT_FS(dir, mnttab_file_name, unmount_flags);
|
||||
/*
|
||||
* Keep track of errors
|
||||
*/
|
||||
if (error) {
|
||||
/*
|
||||
* If we have not already set xerror and error is not ENOENT,
|
||||
* then set xerror equal to error and log it.
|
||||
* 'xerror' is the return value for this function.
|
||||
*
|
||||
* We do not want to pass ENOENT as an error because if the
|
||||
* directory does not exists our work is done anyway.
|
||||
*/
|
||||
if (!xerror && error != ENOENT)
|
||||
xerror = error;
|
||||
if (error != EBUSY) {
|
||||
errno = error;
|
||||
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_mount(am, 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(mntfs *mf)
|
||||
{
|
||||
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;
|
||||
|
||||
/*
|
||||
* WebNFS servers shouldn't ever get here.
|
||||
*/
|
||||
if (mf->mf_flags & MFF_WEBNFS) {
|
||||
plog(XLOG_ERROR, "amfs_host_umounted: cannot support WebNFS");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take a copy of the server hostname, address, and NFS version
|
||||
* to mount version conversion.
|
||||
*/
|
||||
host = mf->mf_server->fs_host;
|
||||
sin = *mf->mf_server->fs_ip;
|
||||
plog(XLOG_INFO, "amfs_host_umounted: NFS version %d", (int) mf->mf_server->fs_version);
|
||||
#ifdef HAVE_FS_NFS3
|
||||
if (mf->mf_server->fs_version == NFS_VERSION3)
|
||||
mnt_version = AM_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;
|
||||
|
||||
dlog("Unmounting all from %s", host);
|
||||
|
||||
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 ... */
|
||||
const char *msg = clnt_sperrno(clnt_stat);
|
||||
plog(XLOG_ERROR, "unmount all from %s rpc failed: %s", host, msg);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (sock != RPC_ANYSOCK)
|
||||
(void) amu_close(sock);
|
||||
if (client)
|
||||
clnt_destroy(client);
|
||||
}
|
@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/amfs_link.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Symbol-link file system
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
|
||||
/* forward declarations */
|
||||
static int amfs_link_mount(am_node *mp, mntfs *mf);
|
||||
static int amfs_link_umount(am_node *mp, mntfs *mf);
|
||||
|
||||
/*
|
||||
* Ops structures
|
||||
*/
|
||||
am_ops amfs_link_ops =
|
||||
{
|
||||
"link",
|
||||
amfs_link_match,
|
||||
0, /* amfs_link_init */
|
||||
amfs_link_mount,
|
||||
amfs_link_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* amfs_link_readlink */
|
||||
0, /* amfs_link_mounted */
|
||||
0, /* amfs_link_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* nfs_fs_flags */
|
||||
0, /* amfs_link_get_wchan */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_LINK_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* SFS needs a link.
|
||||
*/
|
||||
char *
|
||||
amfs_link_match(am_opts *fo)
|
||||
{
|
||||
|
||||
if (!fo->opt_fs) {
|
||||
plog(XLOG_USER, "link: no fs specified");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the link target points to another mount point, then we could
|
||||
* end up with an unpleasant situation, where the link f/s simply
|
||||
* "assumes" the mntfs of that mount point.
|
||||
*
|
||||
* For example, if the link points to /usr, and /usr is a real ufs
|
||||
* filesystem, then the link f/s will use the inherited ufs mntfs,
|
||||
* and the end result will be that it will become unmountable.
|
||||
*
|
||||
* To prevent this, we use a hack: we prepend a dot ('.') to opt_fs if
|
||||
* its original value was an absolute path, so that it will never match
|
||||
* any other mntfs.
|
||||
*
|
||||
* XXX: a less hacky solution should be used...
|
||||
*/
|
||||
if (fo->opt_fs[0] == '/') {
|
||||
char *link_hack = str3cat(NULL, ".", fo->opt_fs, "");
|
||||
if (fo->opt_sublink == NULL || fo->opt_sublink[0] == '\0')
|
||||
fo->opt_sublink = xstrdup(fo->opt_fs);
|
||||
XFREE(fo->opt_fs);
|
||||
fo->opt_fs = link_hack;
|
||||
}
|
||||
|
||||
return xstrdup(fo->opt_fs);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
amfs_link_mount(am_node *mp, mntfs *mf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
amfs_link_umount(am_node *mp, mntfs *mf)
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/amfs_linkx.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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, mntfs *mf);
|
||||
static int amfs_linkx_umount(am_node *mp, mntfs *mf);
|
||||
|
||||
/*
|
||||
* linkx operations
|
||||
*/
|
||||
struct am_ops amfs_linkx_ops =
|
||||
{
|
||||
"linkx",
|
||||
amfs_link_match,
|
||||
0, /* amfs_linkx_init */
|
||||
amfs_linkx_mount,
|
||||
amfs_linkx_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* amfs_linkx_readlink */
|
||||
0, /* amfs_linkx_mounted */
|
||||
0, /* amfs_linkx_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* amfs_linkx_get_wchan */
|
||||
FS_MBACKGROUND,
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_LINKX_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
amfs_linkx_mount(am_node *mp, mntfs *mf)
|
||||
{
|
||||
/*
|
||||
* Check for existence of target.
|
||||
*/
|
||||
struct stat stb;
|
||||
char *ln;
|
||||
|
||||
if (mp->am_link)
|
||||
ln = mp->am_link;
|
||||
else /* should never occur */
|
||||
ln = mf->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;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
amfs_linkx_umount(am_node *mp, mntfs *mf)
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -1,241 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/amfs_nfsl.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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_mount(am_node *mp, mntfs *mf);
|
||||
static int amfs_nfsl_umount(am_node *mp, mntfs *mf);
|
||||
static void amfs_nfsl_umounted(mntfs *mf);
|
||||
static fserver *amfs_nfsl_ffserver(mntfs *mf);
|
||||
|
||||
/*
|
||||
* NFS-Link operations
|
||||
*/
|
||||
am_ops amfs_nfsl_ops =
|
||||
{
|
||||
"nfsl",
|
||||
amfs_nfsl_match,
|
||||
amfs_nfsl_init,
|
||||
amfs_nfsl_mount,
|
||||
amfs_nfsl_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* amfs_nfsl_readlink */
|
||||
0, /* amfs_nfsl_mounted */
|
||||
amfs_nfsl_umounted,
|
||||
amfs_nfsl_ffserver,
|
||||
0, /* amfs_nfsl_get_wchan */
|
||||
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_NFSL_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
char *ho = fo->opt_rhost;
|
||||
char *retval;
|
||||
struct stat stb;
|
||||
|
||||
if (fo->opt_sublink && fo->opt_sublink[0])
|
||||
cp = fo->opt_sublink;
|
||||
else
|
||||
cp = fo->opt_fs;
|
||||
|
||||
if (!cp || !ho) {
|
||||
plog(XLOG_USER, "amfs_nfsl: host $fs and $rhost must be specified");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this host is not the same as $rhost, or if link does not exist,
|
||||
* call nfs_ops.fs_match().
|
||||
* If link value exists (or same host), call amfs_link_ops.fs_match().
|
||||
*/
|
||||
if (!STRCEQ(ho, am_get_hostname()) && !STRCEQ(ho, hostd)) {
|
||||
plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not the local host \"%s\", "
|
||||
"or \"%s\" using type:=nfs", ho, am_get_hostname(), hostd);
|
||||
retval = nfs_ops.fs_match(fo);
|
||||
} else if (lstat(cp, &stb) < 0) {
|
||||
plog(XLOG_INFO, "amfs_nfsl: \"%s\" does not exist, using type:=nfs", cp);
|
||||
retval = nfs_ops.fs_match(fo);
|
||||
} else {
|
||||
plog(XLOG_INFO, "amfs_nfsl: \"%s\" exists, using type:=link", cp);
|
||||
retval = amfs_link_ops.fs_match(fo);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize.
|
||||
* Returns: 0 if OK, non-zero (errno) if failed.
|
||||
*/
|
||||
static int
|
||||
amfs_nfsl_init(mntfs *mf)
|
||||
{
|
||||
int ret = 0;
|
||||
if (mf->mf_flags & MFF_NFSLINK) {
|
||||
if (amfs_link_ops.fs_init)
|
||||
ret = amfs_link_ops.fs_init(mf);
|
||||
} else {
|
||||
if (nfs_ops.fs_init)
|
||||
ret = nfs_ops.fs_init(mf);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Mount vfs.
|
||||
* Returns: 0 if OK, non-zero (errno) if failed.
|
||||
*/
|
||||
static int
|
||||
amfs_nfsl_mount(am_node *mp, mntfs *mf)
|
||||
{
|
||||
int ret = 0;
|
||||
if (mf->mf_flags & MFF_NFSLINK) {
|
||||
if (amfs_link_ops.mount_fs)
|
||||
ret = amfs_link_ops.mount_fs(mp, mf);
|
||||
} else {
|
||||
if (nfs_ops.mount_fs)
|
||||
ret = nfs_ops.mount_fs(mp, mf);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Unmount VFS.
|
||||
* Returns: 0 if OK, non-zero (errno) if failed.
|
||||
*/
|
||||
static int
|
||||
amfs_nfsl_umount(am_node *mp, mntfs *mf)
|
||||
{
|
||||
int ret = 0;
|
||||
if (mf->mf_flags & MFF_NFSLINK) {
|
||||
if (amfs_link_ops.umount_fs)
|
||||
ret = amfs_link_ops.umount_fs(mp, mf);
|
||||
} else {
|
||||
if (nfs_ops.umount_fs)
|
||||
ret = nfs_ops.umount_fs(mp, mf);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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(mntfs *mf)
|
||||
{
|
||||
if (mf->mf_flags & MFF_NFSLINK) {
|
||||
if (amfs_link_ops.umounted)
|
||||
amfs_link_ops.umounted(mf);
|
||||
} else {
|
||||
if (nfs_ops.umounted)
|
||||
nfs_ops.umounted(mf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Find a file server.
|
||||
* Returns: fserver of found server, or NULL if not found.
|
||||
*/
|
||||
static fserver *
|
||||
amfs_nfsl_ffserver(mntfs *mf)
|
||||
{
|
||||
char *cp, *ho;
|
||||
struct stat stb;
|
||||
|
||||
if (mf->mf_fo == NULL) {
|
||||
plog(XLOG_ERROR, "%s: NULL mf_fo", __func__);
|
||||
return NULL;
|
||||
}
|
||||
ho = mf->mf_fo->opt_rhost;
|
||||
|
||||
if (mf->mf_fo->opt_sublink && mf->mf_fo->opt_sublink[0])
|
||||
cp = mf->mf_fo->opt_sublink;
|
||||
else
|
||||
cp = mf->mf_fo->opt_fs;
|
||||
|
||||
/*
|
||||
* If this host is not the same as $rhost, or if link does not exist,
|
||||
* call amfs_link_ops.ffserver().
|
||||
* If link value exists (or same host), then call ops_nfs.ffserver().
|
||||
*/
|
||||
if ((!STRCEQ(ho, am_get_hostname()) &&
|
||||
!STRCEQ(ho, hostd)) || lstat(cp, &stb) < 0) {
|
||||
return nfs_ops.ffserver(mf);
|
||||
} else {
|
||||
mf->mf_flags |= MFF_NFSLINK;
|
||||
/* remove the FS_MKMNT flag, we don't want amd touching the mountpoint */
|
||||
mf->mf_fsflags &= ~FS_MKMNT;
|
||||
return amfs_link_ops.ffserver(mf);
|
||||
}
|
||||
}
|
@ -1,507 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/amfs_nfsx.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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;
|
||||
am_node *nx_mp;
|
||||
};
|
||||
|
||||
/* forward definitions */
|
||||
static char *amfs_nfsx_match(am_opts *fo);
|
||||
static int amfs_nfsx_mount(am_node *am, mntfs *mf);
|
||||
static int amfs_nfsx_umount(am_node *am, mntfs *mf);
|
||||
static int amfs_nfsx_init(mntfs *mf);
|
||||
|
||||
/*
|
||||
* Ops structure
|
||||
*/
|
||||
am_ops amfs_nfsx_ops =
|
||||
{
|
||||
"nfsx",
|
||||
amfs_nfsx_match,
|
||||
amfs_nfsx_init,
|
||||
amfs_nfsx_mount,
|
||||
amfs_nfsx_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* amfs_nfsx_readlink */
|
||||
0, /* amfs_nfsx_mounted */
|
||||
0, /* amfs_nfsx_umounted */
|
||||
find_nfs_srvr, /* XXX */
|
||||
0, /* amfs_nfsx_get_wchan */
|
||||
/* FS_UBACKGROUND| */ FS_AMQINFO, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_NFSX_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
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 == NULL || fo->opt_sublink[0] == '\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 *) NULL, fo->opt_rhost, ":", fo->opt_rfs);
|
||||
dlog("NFSX: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
|
||||
fo->opt_rhost, fo->opt_rfs, fo->opt_fs);
|
||||
|
||||
return xmtab;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
amfs_nfsx_prfree(opaque_t 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 = NULL;
|
||||
char *host;
|
||||
char *pref;
|
||||
int error = 0;
|
||||
|
||||
info = xstrdup(mf->mf_info);
|
||||
if (info == NULL)
|
||||
return errno;
|
||||
|
||||
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++)
|
||||
/* nothing */;
|
||||
|
||||
nx = ALLOC(struct amfs_nfsx);
|
||||
mf->mf_private = (opaque_t) nx;
|
||||
mf->mf_prfree = amfs_nfsx_prfree;
|
||||
|
||||
nx->nx_c = i - 1; /* i-1 because we don't want the prefix */
|
||||
nx->nx_v = (amfs_nfsx_mnt *) xmalloc(nx->nx_c * sizeof(amfs_nfsx_mnt));
|
||||
nx->nx_mp = NULL;
|
||||
{
|
||||
char *mp = NULL;
|
||||
char *xinfo = NULL;
|
||||
char *fs = mf->mf_fo->opt_fs;
|
||||
char *rfs = NULL;
|
||||
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);
|
||||
dlog("amfs_nfsx: init mount for %s on %s", xinfo, mp);
|
||||
nx->nx_v[i].n_error = -1;
|
||||
nx->nx_v[i].n_mnt = find_mntfs(&nfs_ops, mf->mf_fo, mp, xinfo, "", mf->mf_mopts, mf->mf_remopts);
|
||||
/* propagate the on_autofs flag */
|
||||
nx->nx_v[i].n_mnt->mf_flags |= mf->mf_flags & MFF_ON_AUTOFS;
|
||||
}
|
||||
XFREE(rfs);
|
||||
XFREE(mp);
|
||||
XFREE(xinfo);
|
||||
}
|
||||
|
||||
XFREE(ivec);
|
||||
errexit:
|
||||
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 = 0;
|
||||
if (m->mf_ops->fs_init && !(mf->mf_flags & MFF_RESTART))
|
||||
error = m->mf_ops->fs_init(m);
|
||||
/*
|
||||
* if you just "return error" here, you will have made a failure
|
||||
* in any submounts to fail the whole group. There was old unused code
|
||||
* 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, (opaque_t) mf, get_mntfs_wchan(m));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return glob_error;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
amfs_nfsx_cont(int rc, int term, opaque_t arg)
|
||||
{
|
||||
mntfs *mf = (mntfs *) arg;
|
||||
struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private;
|
||||
am_node *mp = nx->nx_mp;
|
||||
amfs_nfsx_mnt *n = nx->nx_try;
|
||||
|
||||
n->n_mnt->mf_flags &= ~(MFF_ERROR | MFF_MOUNTING);
|
||||
mf->mf_flags &= ~MFF_ERROR;
|
||||
|
||||
/*
|
||||
* Wakeup anything waiting for this mount
|
||||
*/
|
||||
wakeup(get_mntfs_wchan(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, FALSE); /* FALSE => don't free the n_mnt->am_opts */
|
||||
n->n_error = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the remaining bits
|
||||
*/
|
||||
if (amfs_nfsx_mount(mp, mf) >= 0)
|
||||
wakeup(get_mntfs_wchan(mf));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
try_amfs_nfsx_mount(opaque_t mv)
|
||||
{
|
||||
mntfs *mf = (mntfs *) mv;
|
||||
struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private;
|
||||
am_node *mp = nx->nx_mp;
|
||||
int error;
|
||||
|
||||
error = mf->mf_ops->mount_fs(mp, mf);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
amfs_nfsx_remount(am_node *am, mntfs *mf, int fg)
|
||||
{
|
||||
struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private;
|
||||
amfs_nfsx_mnt *n;
|
||||
int glob_error = -1;
|
||||
|
||||
/* Save the am_node pointer for later use */
|
||||
nx->nx_mp = am;
|
||||
|
||||
/*
|
||||
* 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 (m->mf_flags & MFF_MOUNTING)
|
||||
break;
|
||||
|
||||
if (m->mf_flags & MFF_MOUNTED) {
|
||||
mf_mounted(m, FALSE); /* FALSE => don't free the m->am_opts */
|
||||
n->n_error = glob_error = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n->n_error < 0) {
|
||||
/* Create the mountpoint, if and as required */
|
||||
if (!(m->mf_flags & MFF_MKMNT) && m->mf_fsflags & FS_MKMNT) {
|
||||
if (!mkdirs(m->mf_mount, 0555))
|
||||
m->mf_flags |= MFF_MKMNT;
|
||||
}
|
||||
|
||||
dlog("calling underlying mount on %s", m->mf_mount);
|
||||
if (!fg && foreground && (m->mf_fsflags & FS_MBACKGROUND)) {
|
||||
m->mf_flags |= MFF_MOUNTING;
|
||||
dlog("backgrounding mount of \"%s\"", m->mf_info);
|
||||
nx->nx_try = n;
|
||||
run_task(try_amfs_nfsx_mount, (opaque_t) m, amfs_nfsx_cont, (opaque_t) mf);
|
||||
n->n_error = -1;
|
||||
return -1;
|
||||
} else {
|
||||
dlog("foreground mount of \"%s\" ...", mf->mf_info);
|
||||
n->n_error = m->mf_ops->mount_fs(am, m);
|
||||
}
|
||||
|
||||
if (n->n_error > 0)
|
||||
dlog("underlying fmount of %s failed: %s", m->mf_mount, strerror(n->n_error));
|
||||
|
||||
if (n->n_error == 0) {
|
||||
glob_error = 0;
|
||||
} else if (glob_error < 0) {
|
||||
glob_error = n->n_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return glob_error < 0 ? 0 : glob_error;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
amfs_nfsx_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
return amfs_nfsx_remount(am, 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_umount(am_node *am, 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 occurred 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) {
|
||||
dlog("calling underlying fumount on %s", m->mf_mount);
|
||||
n->n_error = m->mf_ops->umount_fs(am, 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(am, 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;
|
||||
dlog("calling underlying umounted on %s", m->mf_mount);
|
||||
if (m->mf_ops->umounted)
|
||||
m->mf_ops->umounted(m);
|
||||
|
||||
if (n->n_error < 0) {
|
||||
if (m->mf_fsflags & FS_MKMNT) {
|
||||
(void) rmdirs(m->mf_mount);
|
||||
m->mf_flags &= ~MFF_MKMNT;
|
||||
}
|
||||
}
|
||||
free_mntfs(m);
|
||||
n->n_mnt = NULL;
|
||||
n->n_error = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return glob_error;
|
||||
}
|
@ -1,207 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/amfs_program.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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_mount(am_node *am, mntfs *mf);
|
||||
static int amfs_program_umount(am_node *am, mntfs *mf);
|
||||
static int amfs_program_init(mntfs *mf);
|
||||
|
||||
/*
|
||||
* Ops structure
|
||||
*/
|
||||
am_ops amfs_program_ops =
|
||||
{
|
||||
"program",
|
||||
amfs_program_match,
|
||||
amfs_program_init,
|
||||
amfs_program_mount,
|
||||
amfs_program_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* amfs_program_readlink */
|
||||
0, /* amfs_program_mounted */
|
||||
0, /* amfs_program_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* amfs_program_get_wchan */
|
||||
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_PROGRAM_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Execute needs a mount and unmount command.
|
||||
*/
|
||||
static char *
|
||||
amfs_program_match(am_opts *fo)
|
||||
{
|
||||
char *prog;
|
||||
|
||||
if (fo->opt_unmount && fo->opt_umount) {
|
||||
plog(XLOG_ERROR, "program: cannot specify both unmount and umount options");
|
||||
return 0;
|
||||
}
|
||||
if (!fo->opt_mount) {
|
||||
plog(XLOG_ERROR, "program: must specify mount command");
|
||||
return 0;
|
||||
}
|
||||
if (!fo->opt_unmount && !fo->opt_umount) {
|
||||
fo->opt_unmount = str3cat(NULL, UNMOUNT_PROGRAM, " umount ", fo->opt_fs);
|
||||
plog(XLOG_INFO, "program: un/umount not specified; using default \"%s\"",
|
||||
fo->opt_unmount);
|
||||
}
|
||||
prog = strchr(fo->opt_mount, ' ');
|
||||
|
||||
return xstrdup(prog ? prog + 1 : fo->opt_mount);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
amfs_program_init(mntfs *mf)
|
||||
{
|
||||
/* check if already saved value */
|
||||
if (mf->mf_private != NULL)
|
||||
return 0;
|
||||
|
||||
if (mf->mf_fo == NULL)
|
||||
return 0;
|
||||
|
||||
/* save unmount (or umount) command */
|
||||
if (mf->mf_fo->opt_unmount != NULL)
|
||||
mf->mf_private = (opaque_t) xstrdup(mf->mf_fo->opt_unmount);
|
||||
else
|
||||
mf->mf_private = (opaque_t) xstrdup(mf->mf_fo->opt_umount);
|
||||
mf->mf_prfree = (void (*)(opaque_t)) free;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
amfs_program_exec(char *info)
|
||||
{
|
||||
char **xivec;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Split copy of command info string
|
||||
*/
|
||||
info = xstrdup(info);
|
||||
xivec = strsplit(info, ' ', '\'');
|
||||
|
||||
/*
|
||||
* Put stdout to stderr
|
||||
*/
|
||||
(void) fclose(stdout);
|
||||
if (!logfp)
|
||||
logfp = stderr; /* initialize before possible first use */
|
||||
if (dup(fileno(logfp)) == -1)
|
||||
goto out;
|
||||
if (fileno(logfp) != fileno(stderr)) {
|
||||
(void) fclose(stderr);
|
||||
if (dup(fileno(logfp)) == -1)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try the exec
|
||||
*/
|
||||
if (amuDebug(D_FULL)) {
|
||||
char **cp = xivec;
|
||||
plog(XLOG_DEBUG, "executing (un)mount command...");
|
||||
while (*cp) {
|
||||
plog(XLOG_DEBUG, "arg[%ld] = '%s'", (long) (cp - xivec), *cp);
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
error = errno;
|
||||
plog(XLOG_ERROR, "exec failed: %m");
|
||||
errno = error;
|
||||
}
|
||||
|
||||
out:
|
||||
/*
|
||||
* Save error number
|
||||
*/
|
||||
error = errno;
|
||||
|
||||
/*
|
||||
* Free allocate memory
|
||||
*/
|
||||
XFREE(info);
|
||||
XFREE(xivec);
|
||||
|
||||
/*
|
||||
* Return error
|
||||
*/
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
amfs_program_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
return amfs_program_exec(mf->mf_fo->opt_mount);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
amfs_program_umount(am_node *am, mntfs *mf)
|
||||
{
|
||||
return amfs_program_exec((char *) mf->mf_private);
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/amfs_root.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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, mntfs *mf);
|
||||
|
||||
/****************************************************************************
|
||||
*** OPS STRUCTURES ***
|
||||
****************************************************************************/
|
||||
am_ops amfs_root_ops =
|
||||
{
|
||||
"root",
|
||||
0, /* amfs_root_match */
|
||||
0, /* amfs_root_init */
|
||||
amfs_root_mount,
|
||||
amfs_generic_umount,
|
||||
amfs_generic_lookup_child,
|
||||
amfs_generic_mount_child,
|
||||
amfs_generic_readdir,
|
||||
0, /* amfs_root_readlink */
|
||||
0, /* amfs_root_mounted */
|
||||
0, /* amfs_root_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* amfs_root_get_wchan */
|
||||
FS_NOTIMEOUT | FS_AMQINFO | FS_DIRECTORY, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_ROOT_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*** FUNCTIONS ***
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Mount the root...
|
||||
*/
|
||||
static int
|
||||
amfs_root_mount(am_node *mp, mntfs *mf)
|
||||
{
|
||||
mf->mf_mount = strealloc(mf->mf_mount, pid_fsname);
|
||||
mf->mf_private = (opaque_t) mapc_find(mf->mf_info, "", NULL, NULL);
|
||||
mf->mf_prfree = mapc_free;
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,319 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/amfs_toplvl.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Top-level 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_toplvl_init(mntfs *mf);
|
||||
|
||||
/****************************************************************************
|
||||
*** OPS STRUCTURES ***
|
||||
****************************************************************************/
|
||||
am_ops amfs_toplvl_ops =
|
||||
{
|
||||
"toplvl",
|
||||
amfs_generic_match,
|
||||
amfs_toplvl_init, /* amfs_toplvl_init */
|
||||
amfs_toplvl_mount,
|
||||
amfs_toplvl_umount,
|
||||
amfs_generic_lookup_child,
|
||||
amfs_generic_mount_child,
|
||||
amfs_generic_readdir,
|
||||
0, /* amfs_toplvl_readlink */
|
||||
amfs_generic_mounted,
|
||||
0, /* amfs_toplvl_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* amfs_toplvl_get_wchan */
|
||||
FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND |
|
||||
FS_AMQINFO | FS_DIRECTORY, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_TOPLVL_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*** FUNCTIONS ***
|
||||
****************************************************************************/
|
||||
|
||||
static void
|
||||
set_auto_attrcache_timeout(char *preopts, char *opts, size_t l)
|
||||
{
|
||||
|
||||
#ifdef MNTTAB_OPT_NOAC
|
||||
/*
|
||||
* Don't cache attributes - they are changing under the kernel's feet.
|
||||
* For example, IRIX5.2 will dispense with nfs lookup calls and hand stale
|
||||
* filehandles to getattr unless we disable attribute caching on the
|
||||
* automount points.
|
||||
*/
|
||||
if (gopt.auto_attrcache == 0) {
|
||||
xsnprintf(preopts, l, ",%s", MNTTAB_OPT_NOAC);
|
||||
xstrlcat(opts, preopts, l);
|
||||
}
|
||||
#endif /* MNTTAB_OPT_NOAC */
|
||||
|
||||
/*
|
||||
* XXX: note that setting these to 0 in the past resulted in an error on
|
||||
* some systems, which is why it's better to use "noac" if possible. For
|
||||
* now, we're setting everything possible, but if this will cause trouble,
|
||||
* then we'll have to condition the remainder of this on OPT_NOAC.
|
||||
*/
|
||||
#ifdef MNTTAB_OPT_ACTIMEO
|
||||
xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTIMEO, gopt.auto_attrcache);
|
||||
xstrlcat(opts, preopts, l);
|
||||
#else /* MNTTAB_OPT_ACTIMEO */
|
||||
# ifdef MNTTAB_OPT_ACDIRMIN
|
||||
xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTDIRMIN, gopt.auto_attrcache);
|
||||
xstrlcat(opts, preopts, l);
|
||||
# endif /* MNTTAB_OPT_ACDIRMIN */
|
||||
# ifdef MNTTAB_OPT_ACDIRMAX
|
||||
xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTDIRMAX, gopt.auto_attrcache);
|
||||
xstrlcat(opts, preopts, l);
|
||||
# endif /* MNTTAB_OPT_ACDIRMAX */
|
||||
# ifdef MNTTAB_OPT_ACREGMIN
|
||||
xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTREGMIN, gopt.auto_attrcache);
|
||||
xstrlcat(opts, preopts, l);
|
||||
# endif /* MNTTAB_OPT_ACREGMIN */
|
||||
# ifdef MNTTAB_OPT_ACREGMAX
|
||||
xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTREGMAX, gopt.auto_attrcache);
|
||||
xstrlcat(opts, preopts, l);
|
||||
# endif /* MNTTAB_OPT_ACREGMAX */
|
||||
#endif /* MNTTAB_OPT_ACTIMEO */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize a top-level mount. In our case, if the user asked for
|
||||
* forced_unmounts, and the OS supports it, then we try forced/lazy unmounts
|
||||
* on any previous toplvl mounts. This is useful if a previous Amd died and
|
||||
* left behind toplvl mount points (this Amd will clean them up).
|
||||
*
|
||||
* WARNING: Don't use forced/lazy unmounts if you have another valid Amd
|
||||
* running, because this code WILL force those valid toplvl mount points to
|
||||
* be detached as well!
|
||||
*/
|
||||
static int
|
||||
amfs_toplvl_init(mntfs *mf)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
#if (defined(MNT2_GEN_OPT_FORCE) || defined(MNT2_GEN_OPT_DETACH)) && (defined(HAVE_UVMOUNT) || defined(HAVE_UMOUNT2))
|
||||
if (gopt.flags & CFM_FORCED_UNMOUNTS) {
|
||||
plog(XLOG_INFO, "amfs_toplvl_init: trying forced/lazy unmount of %s",
|
||||
mf->mf_mount);
|
||||
error = umount2_fs(mf->mf_mount, AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH);
|
||||
if (error)
|
||||
plog(XLOG_INFO, "amfs_toplvl_init: forced/lazy unmount failed: %m");
|
||||
else
|
||||
dlog("amfs_toplvl_init: forced/lazy unmount succeeded");
|
||||
}
|
||||
#endif /* (MNT2_GEN_OPT_FORCE || MNT2_GEN_OPT_DETACH) && (HAVE_UVMOUNT || HAVE_UMOUNT2) */
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Mount the top-level
|
||||
*/
|
||||
int
|
||||
amfs_toplvl_mount(am_node *mp, mntfs *mf)
|
||||
{
|
||||
struct stat stb;
|
||||
char opts[SIZEOF_OPTS], preopts[SIZEOF_OPTS], toplvl_opts[40];
|
||||
int error;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct some mount options:
|
||||
*
|
||||
* Tack on magic map=<mapname> option in mtab to emulate
|
||||
* SunOS automounter behavior.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (mf->mf_flags & MFF_IS_AUTOFS) {
|
||||
autofs_get_opts(opts, sizeof(opts), mp->am_autofs_fh);
|
||||
} else
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
{
|
||||
preopts[0] = '\0';
|
||||
#ifdef MNTTAB_OPT_INTR
|
||||
xstrlcat(preopts, MNTTAB_OPT_INTR, sizeof(preopts));
|
||||
xstrlcat(preopts, ",", sizeof(preopts));
|
||||
#endif /* MNTTAB_OPT_INTR */
|
||||
#ifdef MNTTAB_OPT_IGNORE
|
||||
xstrlcat(preopts, MNTTAB_OPT_IGNORE, sizeof(preopts));
|
||||
xstrlcat(preopts, ",", sizeof(preopts));
|
||||
#endif /* MNTTAB_OPT_IGNORE */
|
||||
/* write most of the initial options + preopts */
|
||||
xsnprintf(opts, sizeof(opts), "%s%s,%s=%d,%s,map=%s",
|
||||
preopts,
|
||||
MNTTAB_OPT_RW,
|
||||
MNTTAB_OPT_PORT, nfs_port,
|
||||
mf->mf_ops->fs_type, mf->mf_info);
|
||||
|
||||
/* process toplvl timeo/retrans options, if any */
|
||||
if (gopt.amfs_auto_timeo[AMU_TYPE_TOPLVL] > 0) {
|
||||
xsnprintf(toplvl_opts, sizeof(toplvl_opts), ",%s=%d",
|
||||
MNTTAB_OPT_TIMEO, gopt.amfs_auto_timeo[AMU_TYPE_TOPLVL]);
|
||||
xstrlcat(opts, toplvl_opts, sizeof(opts));
|
||||
}
|
||||
if (gopt.amfs_auto_retrans[AMU_TYPE_TOPLVL] > 0) {
|
||||
xsnprintf(toplvl_opts, sizeof(toplvl_opts), ",%s=%d",
|
||||
MNTTAB_OPT_RETRANS, gopt.amfs_auto_retrans[AMU_TYPE_TOPLVL]);
|
||||
xstrlcat(opts, toplvl_opts, sizeof(opts));
|
||||
}
|
||||
|
||||
#ifdef MNTTAB_OPT_NOLOCK
|
||||
xstrlcat(opts, ",", sizeof(opts));
|
||||
xstrlcat(opts, MNTTAB_OPT_NOLOCK, sizeof(opts));
|
||||
#endif /* MNTTAB_OPT_NOLOCK */
|
||||
|
||||
#ifdef MNTTAB_OPT_NOAC
|
||||
if (gopt.auto_attrcache == 0) {
|
||||
xstrlcat(opts, ",", sizeof(opts));
|
||||
xstrlcat(opts, MNTTAB_OPT_NOAC, sizeof(opts));
|
||||
} else
|
||||
#endif /* MNTTAB_OPT_NOAC */
|
||||
set_auto_attrcache_timeout(preopts, opts, sizeof(preopts));
|
||||
}
|
||||
|
||||
/* now do the mount */
|
||||
error = amfs_mount(mp, mf, opts);
|
||||
if (error) {
|
||||
errno = error;
|
||||
plog(XLOG_FATAL, "amfs_toplvl_mount: amfs_mount failed: %m");
|
||||
return error;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Unmount a top-level automount node
|
||||
*/
|
||||
int
|
||||
amfs_toplvl_umount(am_node *mp, mntfs *mf)
|
||||
{
|
||||
struct stat stb;
|
||||
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
|
||||
int error;
|
||||
int count = 0; /* how many times did we try to unmount? */
|
||||
|
||||
again:
|
||||
/*
|
||||
* 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) {
|
||||
error = errno;
|
||||
dlog("lstat(%s): %m", mp->am_path);
|
||||
goto out;
|
||||
}
|
||||
if ((stb.st_mode & S_IFMT) != S_IFDIR) {
|
||||
plog(XLOG_ERROR, "amfs_toplvl_umount: %s is not a directory, aborting.", mp->am_path);
|
||||
error = ENOTDIR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = UMOUNT_FS(mp->am_path, mnttab_file_name, unmount_flags);
|
||||
if (error == EBUSY) {
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
/*
|
||||
* autofs mounts are "in place", so it is possible
|
||||
* that we can't just unmount our mount points and go away.
|
||||
* If that's the case, just give up.
|
||||
*/
|
||||
if (mf->mf_flags & MFF_IS_AUTOFS)
|
||||
return error;
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
plog(XLOG_WARNING, "amfs_toplvl_unmount retrying %s in 1s", mp->am_path);
|
||||
count++;
|
||||
sleep(1);
|
||||
/*
|
||||
* If user wants forced/lazy unmount semantics, then set those flags,
|
||||
* but only after we've tried normal lstat/umount a few times --
|
||||
* otherwise forced unmounts may hang this very same Amd (by preventing
|
||||
* it from achieving a clean unmount).
|
||||
*/
|
||||
if (gopt.flags & CFM_FORCED_UNMOUNTS) {
|
||||
if (count == 5) { /* after 5 seconds, try MNT_FORCE */
|
||||
dlog("enabling forced unmounts for toplvl node %s", mp->am_path);
|
||||
unmount_flags |= AMU_UMOUNT_FORCE;
|
||||
}
|
||||
if (count == 10) { /* after 10 seconds, try MNT_DETACH */
|
||||
dlog("enabling detached unmounts for toplvl node %s", mp->am_path);
|
||||
unmount_flags |= AMU_UMOUNT_DETACH;
|
||||
}
|
||||
}
|
||||
goto again;
|
||||
}
|
||||
out:
|
||||
return error;
|
||||
}
|
@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/amfs_union.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 int create_amfs_union_node(char *dir, opaque_t arg);
|
||||
static void amfs_union_mounted(mntfs *mf);
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*** OPS STRUCTURES ***
|
||||
****************************************************************************/
|
||||
am_ops amfs_union_ops =
|
||||
{
|
||||
"union",
|
||||
amfs_generic_match,
|
||||
0, /* amfs_union_init */
|
||||
amfs_toplvl_mount,
|
||||
amfs_toplvl_umount,
|
||||
amfs_generic_lookup_child,
|
||||
amfs_generic_mount_child,
|
||||
amfs_generic_readdir,
|
||||
0, /* amfs_union_readlink */
|
||||
amfs_union_mounted,
|
||||
0, /* amfs_union_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* amfs_union_get_wchan */
|
||||
FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO | FS_DIRECTORY,
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_UNION_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Create a reference to a union'ed entry
|
||||
* XXX: this function may not be used anywhere...
|
||||
*/
|
||||
static int
|
||||
create_amfs_union_node(char *dir, opaque_t arg)
|
||||
{
|
||||
if (!STREQ(dir, "/defaults")) {
|
||||
int error = 0;
|
||||
am_node *am;
|
||||
am = amfs_generic_lookup_child(arg, dir, &error, VLOOK_CREATE);
|
||||
if (am && error < 0)
|
||||
(void)amfs_generic_mount_child(am, &error);
|
||||
if (error > 0) {
|
||||
errno = error; /* XXX */
|
||||
plog(XLOG_ERROR, "unionfs: could not mount %s: %m", dir);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
amfs_union_mounted(mntfs *mf)
|
||||
{
|
||||
int index;
|
||||
am_node *mp;
|
||||
|
||||
amfs_mkcacheref(mf);
|
||||
|
||||
/*
|
||||
* Having made the union mount point,
|
||||
* populate all the entries...
|
||||
*/
|
||||
for (mp = get_first_exported_ap(&index);
|
||||
mp;
|
||||
mp = get_next_exported_ap(&index)) {
|
||||
if (mp->am_al->al_mnt == mf) {
|
||||
/* return value from create_amfs_union_node is ignored by mapc_keyiter */
|
||||
(void) mapc_keyiter((mnt_map *) mp->am_al->al_mnt->mf_private,
|
||||
create_amfs_union_node,
|
||||
mp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,596 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/amq_subr.c
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Auxiliary 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 *) ((void *)&mp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Unmount a single node
|
||||
*/
|
||||
int *
|
||||
amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp)
|
||||
{
|
||||
static int res = AMQ_UMNT_OK;
|
||||
am_node *mp = find_ap(*(char **) argp);
|
||||
|
||||
if (mp)
|
||||
forcibly_timeout_mp(mp);
|
||||
|
||||
return &res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Synchronously unmount a single node - parent side.
|
||||
*/
|
||||
int *
|
||||
amqproc_sync_umnt_1_svc_parent(voidp argp, struct svc_req *rqstp)
|
||||
{
|
||||
amqproc_umnt_1_svc(argp, rqstp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Synchronously unmount a single node - child side.
|
||||
*/
|
||||
amq_sync_umnt *
|
||||
amqproc_sync_umnt_1_svc_child(voidp argp, struct svc_req *rqstp)
|
||||
{
|
||||
static amq_sync_umnt rv;
|
||||
amq_sync_umnt buf;
|
||||
ssize_t n;
|
||||
|
||||
am_node *mp = find_ap(*(char **) argp);
|
||||
|
||||
memset(&rv, 0, sizeof(rv));
|
||||
rv.au_etype = AMQ_UMNT_READ;
|
||||
if (mp && mp->am_fd[0] >= 0) {
|
||||
n = read(mp->am_fd[0], &buf, sizeof(buf));
|
||||
if (n == sizeof(buf))
|
||||
rv = buf;
|
||||
}
|
||||
return &rv;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Synchronously unmount a single node - use if we can't fork (asynchronous).
|
||||
*/
|
||||
amq_sync_umnt *
|
||||
amqproc_sync_umnt_1_svc_async(voidp argp, struct svc_req *rqstp)
|
||||
{
|
||||
static amq_sync_umnt rv;
|
||||
|
||||
memset(&rv, 0, sizeof(rv));
|
||||
rv.au_etype = AMQ_UMNT_FORK;
|
||||
rv.au_errno = errno;
|
||||
|
||||
amqproc_umnt_1_svc(argp, rqstp);
|
||||
|
||||
return &rv;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return global statistics
|
||||
*/
|
||||
amq_mount_stats *
|
||||
amqproc_stats_1_svc(voidp argp, struct svc_req *rqstp)
|
||||
{
|
||||
return (amq_mount_stats *) ((void *)&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;
|
||||
static am_node *mp;
|
||||
|
||||
mp = get_exported_ap(0);
|
||||
aml.amq_mount_tree_list_val = (amq_mount_tree_p *) ((void *) &mp);
|
||||
aml.amq_mount_tree_list_len = 1; /* XXX */
|
||||
|
||||
return &aml;
|
||||
}
|
||||
|
||||
|
||||
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:
|
||||
if (debug_option(opt->as_str))
|
||||
rc = EINVAL;
|
||||
break;
|
||||
|
||||
case AMOPT_LOGFILE:
|
||||
if (gopt.logfile && opt->as_str
|
||||
&& STREQ(gopt.logfile, opt->as_str)) {
|
||||
if (switch_to_logfile(opt->as_str, orig_umask, 0))
|
||||
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 *) NULL);
|
||||
flush_srvr_nfs_cache((fserver *) NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return &rc;
|
||||
}
|
||||
|
||||
|
||||
amq_mount_info_list *
|
||||
amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp)
|
||||
{
|
||||
return (amq_mount_info_list *) ((void *)&mfhead); /* XXX */
|
||||
}
|
||||
|
||||
extern qelem map_list_head;
|
||||
amq_map_info_list *
|
||||
amqproc_getmapinfo_1_svc(voidp argp, struct svc_req *rqstp)
|
||||
{
|
||||
return (amq_map_info_list *) ((void *)&map_list_head); /* XXX */
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process PAWD string of remote pawd tool.
|
||||
*
|
||||
* We repeat the resolution of the string until the resolved string resolves
|
||||
* to itself. This ensures that we follow path resolutions through all
|
||||
* possible Amd mount points until we reach some sort of convergence. To
|
||||
* prevent possible infinite loops, we break out of this loop if the strings
|
||||
* do not converge after MAX_PAWD_TRIES times.
|
||||
*/
|
||||
amq_string *
|
||||
amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp)
|
||||
{
|
||||
static amq_string res;
|
||||
#define MAX_PAWD_TRIES 10
|
||||
int index, len, maxagain = MAX_PAWD_TRIES;
|
||||
am_node *mp;
|
||||
char *mountpoint;
|
||||
char *dir = *(char **) argp;
|
||||
static char tmp_buf[MAXPATHLEN];
|
||||
char prev_buf[MAXPATHLEN];
|
||||
|
||||
tmp_buf[0] = prev_buf[0] = '\0'; /* default is empty string: no match */
|
||||
do {
|
||||
for (mp = get_first_exported_ap(&index);
|
||||
mp;
|
||||
mp = get_next_exported_ap(&index)) {
|
||||
if (STREQ(mp->am_al->al_mnt->mf_ops->fs_type, "toplvl"))
|
||||
continue;
|
||||
if (STREQ(mp->am_al->al_mnt->mf_ops->fs_type, "auto"))
|
||||
continue;
|
||||
mountpoint = (mp->am_link ? mp->am_link : mp->am_al->al_mnt->mf_mount);
|
||||
len = strlen(mountpoint);
|
||||
if (len == 0)
|
||||
continue;
|
||||
if (!NSTREQ(mountpoint, dir, len))
|
||||
continue;
|
||||
if (dir[len] != '\0' && dir[len] != '/')
|
||||
continue;
|
||||
xstrlcpy(tmp_buf, mp->am_path, sizeof(tmp_buf));
|
||||
xstrlcat(tmp_buf, &dir[len], sizeof(tmp_buf));
|
||||
break;
|
||||
} /* end of "for" loop */
|
||||
/* once tmp_buf and prev_buf are equal, break out of "do" loop */
|
||||
if (STREQ(tmp_buf, prev_buf))
|
||||
break;
|
||||
else
|
||||
xstrlcpy(prev_buf, tmp_buf, sizeof(prev_buf));
|
||||
} while (--maxagain);
|
||||
/* check if we couldn't resolve the string after MAX_PAWD_TRIES times */
|
||||
if (maxagain <= 0)
|
||||
plog(XLOG_WARNING, "path \"%s\" did not resolve after %d tries",
|
||||
tmp_buf, MAX_PAWD_TRIES);
|
||||
|
||||
res = tmp_buf;
|
||||
return &res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* XDR routines.
|
||||
*/
|
||||
|
||||
|
||||
bool_t
|
||||
xdr_amq_setopt(XDR *xdrs, amq_setopt *objp)
|
||||
{
|
||||
if (!xdr_enum(xdrs, (enum_t *) ((voidp) &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;
|
||||
long mtime;
|
||||
|
||||
if (!xdr_amq_string(xdrs, &mp->am_al->al_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_al->al_mnt->mf_mount)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_amq_string(xdrs, &mp->am_al->al_mnt->mf_ops->fs_type)) {
|
||||
return (FALSE);
|
||||
}
|
||||
mtime = mp->am_stats.s_mtime;
|
||||
if (!xdr_long(xdrs, &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 **) ((voidp) &mp->am_osib),
|
||||
sizeof(amq_mount_tree),
|
||||
(XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_pointer(xdrs,
|
||||
(char **) ((voidp) &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 = NULL;
|
||||
|
||||
if (!xdr_amq_mount_tree_node(xdrs, objp)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_pointer(xdrs,
|
||||
(char **) ((voidp) &mnil),
|
||||
sizeof(amq_mount_tree),
|
||||
(XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_pointer(xdrs,
|
||||
(char **) ((voidp) &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 **) ((voidp) &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_info_qelem(XDR *xdrs, qelem *qhead)
|
||||
{
|
||||
mntfs *mf;
|
||||
u_int len = 0;
|
||||
|
||||
/*
|
||||
* Compute length of list
|
||||
*/
|
||||
for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) {
|
||||
if (!(mf->mf_fsflags & 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_fsflags & 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 (FSRV_ERROR(mf->mf_server) || FSRV_ISDOWN(mf->mf_server))
|
||||
up = 0;
|
||||
else if (FSRV_ISUP(mf->mf_server))
|
||||
up = 1;
|
||||
else
|
||||
up = -1;
|
||||
if (!xdr_int(xdrs, &up)) {
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
bool_t
|
||||
xdr_amq_map_info_qelem(XDR *xdrs, qelem *qhead)
|
||||
{
|
||||
mnt_map *m;
|
||||
u_int len = 0;
|
||||
int x;
|
||||
char *n;
|
||||
|
||||
/*
|
||||
* Compute length of list
|
||||
*/
|
||||
ITER(m, mnt_map, qhead) {
|
||||
len++;
|
||||
}
|
||||
|
||||
if (!xdr_u_int(xdrs, &len))
|
||||
return (FALSE);
|
||||
|
||||
/*
|
||||
* Send individual data items
|
||||
*/
|
||||
ITER(m, mnt_map, qhead) {
|
||||
if (!xdr_amq_string(xdrs, &m->map_name)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
n = m->wildcard ? m->wildcard : "";
|
||||
if (!xdr_amq_string(xdrs, &n)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (!xdr_long(xdrs, (long *) &m->modify)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
x = m->flags;
|
||||
if (!xdr_int(xdrs, &x)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
x = m->nentries;
|
||||
if (!xdr_int(xdrs, &x)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
x = m->reloads;
|
||||
if (!xdr_int(xdrs, &x)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (!xdr_int(xdrs, &m->refc)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (m->isup)
|
||||
x = (*m->isup)(m, m->map_name);
|
||||
else
|
||||
x = -1;
|
||||
if (!xdr_int(xdrs, &x)) {
|
||||
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));
|
||||
}
|
@ -1,310 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/amq_svc.c
|
||||
*
|
||||
*/
|
||||
|
||||
#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 *);
|
||||
|
||||
#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
|
||||
# ifdef NEED_LIBWRAP_SEVERITY_VARIABLES
|
||||
/*
|
||||
* Some systems that define libwrap already define these two variables
|
||||
* in libwrap, while others don't: so I need to know precisely iff
|
||||
* to define these two severity variables.
|
||||
*/
|
||||
int allow_severity=0, deny_severity=0, rfc931_timeout=0;
|
||||
# endif /* NEED_LIBWRAP_SEVERITY_VARIABLES */
|
||||
|
||||
/*
|
||||
* check if remote amq is authorized to access this amd.
|
||||
* Returns: 1=allowed, 0=denied.
|
||||
*/
|
||||
static int
|
||||
amqsvc_is_client_allowed(const struct sockaddr_in *addr)
|
||||
{
|
||||
struct request_info req;
|
||||
|
||||
request_init(&req, RQ_DAEMON, AMD_SERVICE_NAME, RQ_CLIENT_SIN, addr, 0);
|
||||
sock_methods(&req);
|
||||
|
||||
if (hosts_access(&req))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
|
||||
|
||||
|
||||
/*
|
||||
* Prepare the parent and child:
|
||||
* 1) Setup IPC pipe.
|
||||
* 2) Set signal masks.
|
||||
* 3) Fork by calling background() so that NumChildren is updated.
|
||||
*/
|
||||
static int
|
||||
amq_fork(opaque_t argp)
|
||||
{
|
||||
#ifdef HAVE_SIGACTION
|
||||
sigset_t new, mask;
|
||||
#else /* not HAVE_SIGACTION */
|
||||
int mask;
|
||||
#endif /* not HAVE_SIGACTION */
|
||||
am_node *mp;
|
||||
pid_t pid;
|
||||
|
||||
mp = find_ap(*(char **) argp);
|
||||
if (mp == NULL) {
|
||||
errno = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pipe(mp->am_fd) == -1) {
|
||||
mp->am_fd[0] = -1;
|
||||
mp->am_fd[1] = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
sigemptyset(&new); /* initialize signal set we wish to block */
|
||||
sigaddset(&new, SIGHUP);
|
||||
sigaddset(&new, SIGINT);
|
||||
sigaddset(&new, SIGQUIT);
|
||||
sigaddset(&new, SIGCHLD);
|
||||
sigprocmask(SIG_BLOCK, &new, &mask);
|
||||
#else /* not HAVE_SIGACTION */
|
||||
mask =
|
||||
sigmask(SIGHUP) |
|
||||
sigmask(SIGINT) |
|
||||
sigmask(SIGQUIT) |
|
||||
sigmask(SIGCHLD);
|
||||
mask = sigblock(mask);
|
||||
#endif /* not HAVE_SIGACTION */
|
||||
|
||||
switch ((pid = background())) {
|
||||
case -1: /* error */
|
||||
dlog("amq_fork failed");
|
||||
return -1;
|
||||
|
||||
case 0: /* child */
|
||||
close(mp->am_fd[1]); /* close output end of pipe */
|
||||
mp->am_fd[1] = -1;
|
||||
return 0;
|
||||
|
||||
default: /* parent */
|
||||
close(mp->am_fd[0]); /* close input end of pipe */
|
||||
mp->am_fd[0] = -1;
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||
#else /* not HAVE_SIGACTION */
|
||||
sigsetmask(mask);
|
||||
#endif /* not HAVE_SIGACTION */
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
} argument;
|
||||
char *result;
|
||||
xdrproc_t xdr_argument, xdr_result;
|
||||
amqsvcproc_t local;
|
||||
amqsvcproc_t child;
|
||||
amqsvcproc_t parent;
|
||||
pid_t pid;
|
||||
|
||||
#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
|
||||
if (gopt.flags & CFM_USE_TCPWRAPPERS) {
|
||||
struct sockaddr_in *remote_addr = svc_getcaller(rqstp->rq_xprt);
|
||||
char *remote_hostname = inet_ntoa(remote_addr->sin_addr);
|
||||
|
||||
if (!amqsvc_is_client_allowed(remote_addr)) {
|
||||
plog(XLOG_WARNING, "Amd denied remote amq service to %s", remote_hostname);
|
||||
svcerr_auth(transp, AUTH_FAILED);
|
||||
return;
|
||||
} else {
|
||||
dlog("Amd allowed remote amq service to %s", remote_hostname);
|
||||
}
|
||||
}
|
||||
#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
|
||||
|
||||
local = NULL;
|
||||
child = NULL;
|
||||
parent = NULL;
|
||||
|
||||
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_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;
|
||||
|
||||
case AMQPROC_PAWD:
|
||||
xdr_argument = (xdrproc_t) xdr_amq_string;
|
||||
xdr_result = (xdrproc_t) xdr_amq_string;
|
||||
local = (amqsvcproc_t) amqproc_pawd_1_svc;
|
||||
break;
|
||||
|
||||
case AMQPROC_SYNC_UMNT:
|
||||
xdr_argument = (xdrproc_t) xdr_amq_string;
|
||||
xdr_result = (xdrproc_t) xdr_amq_sync_umnt;
|
||||
parent = (amqsvcproc_t) amqproc_sync_umnt_1_svc_parent;
|
||||
child = (amqsvcproc_t) amqproc_sync_umnt_1_svc_child;
|
||||
/* used if fork fails */
|
||||
local = (amqsvcproc_t) amqproc_sync_umnt_1_svc_async;
|
||||
break;
|
||||
|
||||
case AMQPROC_GETMAPINFO:
|
||||
xdr_argument = (xdrproc_t) xdr_void;
|
||||
xdr_result = (xdrproc_t) xdr_amq_map_info_qelem;
|
||||
local = (amqsvcproc_t) amqproc_getmapinfo_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;
|
||||
}
|
||||
|
||||
pid = -1;
|
||||
result = NULL;
|
||||
|
||||
if (child) {
|
||||
switch ((pid = amq_fork(&argument))) {
|
||||
case -1: /* error */
|
||||
break;
|
||||
|
||||
case 0: /* child */
|
||||
result = (*child) (&argument, rqstp);
|
||||
local = NULL;
|
||||
break;
|
||||
|
||||
default: /* parent */
|
||||
result = (*parent) (&argument, rqstp);
|
||||
local = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (local)
|
||||
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);
|
||||
}
|
||||
|
||||
if (pid == 0)
|
||||
exit(0); /* the child is done! */
|
||||
}
|
@ -1,800 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/autil.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 NumChildren = 0; /* number of children of primary amd */
|
||||
static char invalid_keys[] = "\"'!;@ \t\n";
|
||||
|
||||
/****************************************************************************
|
||||
*** MACROS ***
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_TRANSPORT_TYPE_TLI
|
||||
# define PARENT_USLEEP_TIME 100000 /* 0.1 seconds */
|
||||
#endif /* HAVE_TRANSPORT_TYPE_TLI */
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*** FORWARD DEFINITIONS ***
|
||||
****************************************************************************/
|
||||
static void domain_strip(char *otherdom, char *localdom);
|
||||
static int dofork(void);
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*** FUNCTIONS ***
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copy s into p, reallocating p if necessary
|
||||
*/
|
||||
char *
|
||||
strealloc(char *p, char *s)
|
||||
{
|
||||
size_t len = strlen(s) + 1;
|
||||
|
||||
p = (char *) xrealloc((voidp) p, len);
|
||||
|
||||
xstrlcpy(p, s, len);
|
||||
#ifdef DEBUG_MEM
|
||||
# if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY)
|
||||
malloc_verify();
|
||||
# endif /* not defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY) */
|
||||
#endif /* DEBUG_MEM */
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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: replace cnames with real names, and decide if to
|
||||
* strip domain name or not.
|
||||
*/
|
||||
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;
|
||||
hp = gethostbyname(*chp);
|
||||
if (hp && hp->h_addrtype == AF_INET) {
|
||||
dlog("Hostname %s normalized to %s", *chp, hp->h_name);
|
||||
*chp = strealloc(*chp, (char *) hp->h_name);
|
||||
}
|
||||
}
|
||||
if (gopt.flags & CFM_DOMAIN_STRIP) {
|
||||
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_al->al_mnt;
|
||||
/*
|
||||
* Arrange to timeout this node
|
||||
*/
|
||||
if (mf && ((mp->am_flags & AMF_ROOT) ||
|
||||
(mf->mf_flags & (MFF_MOUNTING | MFF_UNMOUNTING)))) {
|
||||
/*
|
||||
* We aren't going to schedule a timeout, so we need to notify the
|
||||
* child here unless we are already unmounting, in which case that
|
||||
* process is responsible for notifying the child.
|
||||
*/
|
||||
if (mf->mf_flags & MFF_UNMOUNTING)
|
||||
plog(XLOG_WARNING, "node %s is currently being unmounted, ignoring timeout request", mp->am_path);
|
||||
else {
|
||||
plog(XLOG_WARNING, "ignoring timeout request for active node %s", mp->am_path);
|
||||
notify_child(mp, AMQ_UMNT_FAILED, EBUSY, 0);
|
||||
}
|
||||
} else {
|
||||
plog(XLOG_INFO, "\"%s\" forcibly timed out", mp->am_path);
|
||||
mp->am_flags &= ~AMF_NOTIMEOUT;
|
||||
mp->am_ttl = clocktime(NULL);
|
||||
/*
|
||||
* Force mtime update of parent dir, to prevent DNLC/dcache from caching
|
||||
* the old entry, which could result in ESTALE errors, bad symlinks, and
|
||||
* more.
|
||||
*/
|
||||
clocktime(&mp->am_parent->am_fattr.na_mtime);
|
||||
reschedule_timeout_mp();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mf_mounted(mntfs *mf, bool_t call_free_opts)
|
||||
{
|
||||
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);
|
||||
|
||||
/*
|
||||
* We used to free the mf_mo (options) here, however they're now stored
|
||||
* and managed with the mntfs and do not need to be free'd here (this ensures
|
||||
* that we use the same options to monitor/unmount the system as we used
|
||||
* to mount it).
|
||||
*/
|
||||
}
|
||||
|
||||
if (mf->mf_flags & MFF_RESTART) {
|
||||
mf->mf_flags &= ~MFF_RESTART;
|
||||
dlog("Restarted filesystem %s, flags 0x%x", mf->mf_mount, mf->mf_flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
int notimeout = 0; /* assume normal timeouts initially */
|
||||
mntfs *mf = mp->am_al->al_mnt;
|
||||
|
||||
/*
|
||||
* This is the parent mntfs which does the mf->mf_fo (am_opts type), and
|
||||
* we're passing TRUE here to tell mf_mounted to actually free the
|
||||
* am_opts. See a related comment in mf_mounted().
|
||||
*/
|
||||
mf_mounted(mf, TRUE);
|
||||
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (mf->mf_flags & MFF_IS_AUTOFS)
|
||||
autofs_mounted(mp);
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
/*
|
||||
* Patch up path for direct mounts
|
||||
*/
|
||||
if (mp->am_parent && mp->am_parent->am_al->al_mnt->mf_fsflags & FS_DIRECT)
|
||||
mp->am_path = str3cat(mp->am_path, mp->am_parent->am_path, "/", ".");
|
||||
|
||||
/*
|
||||
* Check whether this mount should be cached permanently or not,
|
||||
* and handle user-requested timeouts.
|
||||
*/
|
||||
/* first check if file system was set to never timeout */
|
||||
if (mf->mf_fsflags & FS_NOTIMEOUT)
|
||||
notimeout = 1;
|
||||
/* next, alter that decision by map flags */
|
||||
|
||||
if (mf->mf_mopts) {
|
||||
mntent_t mnt;
|
||||
mnt.mnt_opts = mf->mf_mopts;
|
||||
|
||||
/* umount option: user wants to unmount this entry */
|
||||
if (amu_hasmntopt(&mnt, "unmount") || amu_hasmntopt(&mnt, "umount"))
|
||||
notimeout = 0;
|
||||
/* noumount option: user does NOT want to unmount this entry */
|
||||
if (amu_hasmntopt(&mnt, "nounmount") || amu_hasmntopt(&mnt, "noumount"))
|
||||
notimeout = 1;
|
||||
/* utimeout=N option: user wants to unmount this option AND set timeout */
|
||||
if ((mp->am_timeo = hasmntval(&mnt, "utimeout")) == 0)
|
||||
mp->am_timeo = gopt.am_timeo; /* otherwise use default timeout */
|
||||
else
|
||||
notimeout = 0;
|
||||
/* special case: don't try to unmount "/" (it can never succeed) */
|
||||
if (mf->mf_mount[0] == '/' && mf->mf_mount[1] == '\0')
|
||||
notimeout = 1;
|
||||
}
|
||||
/* finally set actual flags */
|
||||
if (notimeout) {
|
||||
mp->am_flags |= AMF_NOTIMEOUT;
|
||||
plog(XLOG_INFO, "%s set to never timeout", mp->am_path);
|
||||
} else {
|
||||
mp->am_flags &= ~AMF_NOTIMEOUT;
|
||||
plog(XLOG_INFO, "%s set to timeout in %d seconds", mp->am_path, mp->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 : mf->mf_mount);
|
||||
|
||||
/*
|
||||
* Record mount time, and update am_stats at the same time.
|
||||
*/
|
||||
mp->am_stats.s_mtime = clocktime(&mp->am_fattr.na_mtime);
|
||||
new_ttl(mp);
|
||||
|
||||
/*
|
||||
* Update mtime of parent node (copying "struct nfstime" in '=' below)
|
||||
*/
|
||||
if (mp->am_parent && mp->am_parent->am_al->al_mnt)
|
||||
mp->am_parent->am_fattr.na_mtime = mp->am_fattr.na_mtime;
|
||||
|
||||
/*
|
||||
* This is ugly, but essentially unavoidable
|
||||
* Sublinks must be treated separately as type==link
|
||||
* when the base type is different.
|
||||
*/
|
||||
if (mp->am_link && mf->mf_ops != &amfs_link_ops)
|
||||
amfs_link_ops.mount_fs(mp, mf);
|
||||
|
||||
/*
|
||||
* Now, if we can, do a reply to our client here
|
||||
* to speed things up.
|
||||
*/
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (mp->am_flags & AMF_AUTOFS)
|
||||
autofs_mount_succeeded(mp);
|
||||
else
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
nfs_quick_reply(mp, 0);
|
||||
|
||||
/*
|
||||
* Update stats
|
||||
*/
|
||||
amd_stats.d_mok++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Replace mount point with a reference to an error filesystem.
|
||||
* The mount point (struct mntfs) is NOT discarded,
|
||||
* the caller must do it if it wants to _before_ calling this function.
|
||||
*/
|
||||
void
|
||||
assign_error_mntfs(am_node *mp)
|
||||
{
|
||||
int error;
|
||||
dlog("assign_error_mntfs");
|
||||
|
||||
if (mp->am_al == NULL) {
|
||||
plog(XLOG_ERROR, "%s: Can't assign error", __func__);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Save the old error code
|
||||
*/
|
||||
error = mp->am_error;
|
||||
if (error <= 0)
|
||||
error = mp->am_al->al_mnt->mf_error;
|
||||
/*
|
||||
* Allocate a new error reference
|
||||
*/
|
||||
free_loc(mp->am_al);
|
||||
mp->am_al = new_loc();
|
||||
/*
|
||||
* Put back the error code
|
||||
*/
|
||||
mp->am_al->al_mnt->mf_error = error;
|
||||
mp->am_al->al_mnt->mf_flags |= MFF_ERROR;
|
||||
/*
|
||||
* Zero the error in the mount point
|
||||
*/
|
||||
mp->am_error = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Build a new map cache for this node, or re-use
|
||||
* an existing cache for the same map.
|
||||
*/
|
||||
void
|
||||
amfs_mkcacheref(mntfs *mf)
|
||||
{
|
||||
char *cache;
|
||||
|
||||
if (mf->mf_fo && mf->mf_fo->opt_cache)
|
||||
cache = mf->mf_fo->opt_cache;
|
||||
else
|
||||
cache = "none";
|
||||
mf->mf_private = (opaque_t) mapc_find(mf->mf_info,
|
||||
cache,
|
||||
(mf->mf_fo ? mf->mf_fo->opt_maptype : NULL),
|
||||
mf->mf_mount);
|
||||
mf->mf_prfree = mapc_free;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Locate next node in sibling list which is mounted
|
||||
* and is not an error node.
|
||||
*/
|
||||
am_node *
|
||||
next_nonerror_node(am_node *xp)
|
||||
{
|
||||
mntfs *mf;
|
||||
|
||||
/*
|
||||
* Bug report (7/12/89) from Rein Tollevik <rein@ifi.uio.no>
|
||||
* Fixes a race condition when mounting direct automounts.
|
||||
* Also fixes a problem when doing a readdir on a directory
|
||||
* containing hung automounts.
|
||||
*/
|
||||
while (xp &&
|
||||
(!(mf = xp->am_al->al_mnt) || /* No mounted filesystem */
|
||||
mf->mf_error != 0 || /* There was a mntfs error */
|
||||
xp->am_error != 0 || /* There was a mount error */
|
||||
!(mf->mf_flags & MFF_MOUNTED) || /* The fs is not mounted */
|
||||
(mf->mf_server->fs_flags & FSF_DOWN)) /* The fs may be down */
|
||||
)
|
||||
xp = xp->am_osib;
|
||||
|
||||
return xp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Mount an automounter directory.
|
||||
* The automounter is connected into the system
|
||||
* as a user-level NFS server. amfs_mount constructs
|
||||
* the necessary NFS parameters to be given to the
|
||||
* kernel so that it will talk back to us.
|
||||
*
|
||||
* NOTE: automounter mounts in themselves are using NFS Version 2 (UDP).
|
||||
*
|
||||
* NEW: on certain systems, mounting can be done using the
|
||||
* kernel-level automount (autofs) support. In that case,
|
||||
* we don't need NFS at all here.
|
||||
*/
|
||||
int
|
||||
amfs_mount(am_node *mp, mntfs *mf, char *opts)
|
||||
{
|
||||
char fs_hostname[MAXHOSTNAMELEN + MAXPATHLEN + 1];
|
||||
int retry, error = 0, genflags;
|
||||
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
|
||||
char *dir = mf->mf_mount;
|
||||
mntent_t mnt;
|
||||
MTYPE_TYPE type;
|
||||
int forced_unmount = 0; /* are we using forced unmounts? */
|
||||
u_long nfs_version = get_nfs_dispatcher_version(nfs_dispatcher);
|
||||
|
||||
memset(&mnt, 0, sizeof(mnt));
|
||||
mnt.mnt_dir = dir;
|
||||
mnt.mnt_fsname = pid_fsname;
|
||||
mnt.mnt_opts = opts;
|
||||
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (mf->mf_flags & MFF_IS_AUTOFS) {
|
||||
type = MOUNT_TYPE_AUTOFS;
|
||||
/*
|
||||
* Make sure that amd's top-level autofs mounts are hidden by default
|
||||
* from df.
|
||||
* XXX: It works ok on Linux, might not work on other systems.
|
||||
*/
|
||||
mnt.mnt_type = "autofs";
|
||||
} else
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
{
|
||||
type = MOUNT_TYPE_NFS;
|
||||
/*
|
||||
* Make sure that amd's top-level NFS mounts are hidden by default
|
||||
* from df.
|
||||
* If they don't appear to support the either the "ignore" mnttab
|
||||
* option entry, or the "auto" one, set the mount type to "nfs".
|
||||
*/
|
||||
mnt.mnt_type = HIDE_MOUNT_TYPE;
|
||||
}
|
||||
|
||||
retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
|
||||
if (retry <= 0)
|
||||
retry = 2; /* XXX: default to 2 retries */
|
||||
|
||||
/*
|
||||
* SET MOUNT ARGS
|
||||
*/
|
||||
|
||||
/*
|
||||
* Make a ``hostname'' string for the kernel
|
||||
*/
|
||||
xsnprintf(fs_hostname, sizeof(fs_hostname), "pid%ld@%s:%s",
|
||||
get_server_pid(), am_get_hostname(), dir);
|
||||
/*
|
||||
* Most kernels have a name length restriction (64 bytes)...
|
||||
*/
|
||||
if (strlen(fs_hostname) >= MAXHOSTNAMELEN)
|
||||
xstrlcpy(fs_hostname + MAXHOSTNAMELEN - 3, "..",
|
||||
sizeof(fs_hostname) - MAXHOSTNAMELEN + 3);
|
||||
#ifdef HOSTNAMESZ
|
||||
/*
|
||||
* ... and some of these restrictions are 32 bytes (HOSTNAMESZ)
|
||||
* If you need to get the definition for HOSTNAMESZ found, you may
|
||||
* add the proper header file to the conf/nfs_prot/nfs_prot_*.h file.
|
||||
*/
|
||||
if (strlen(fs_hostname) >= HOSTNAMESZ)
|
||||
xstrlcpy(fs_hostname + HOSTNAMESZ - 3, "..",
|
||||
sizeof(fs_hostname) - HOSTNAMESZ + 3);
|
||||
#endif /* HOSTNAMESZ */
|
||||
|
||||
/*
|
||||
* Finally we can compute the mount genflags set above,
|
||||
* and add any automounter specific flags.
|
||||
*/
|
||||
genflags = compute_mount_flags(&mnt);
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (on_autofs)
|
||||
genflags |= autofs_compute_mount_flags(&mnt);
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
genflags |= compute_automounter_mount_flags(&mnt);
|
||||
|
||||
again:
|
||||
if (!(mf->mf_flags & MFF_IS_AUTOFS)) {
|
||||
nfs_args_t nfs_args;
|
||||
am_nfs_handle_t *fhp, anh;
|
||||
#ifndef HAVE_TRANSPORT_TYPE_TLI
|
||||
u_short port;
|
||||
struct sockaddr_in sin;
|
||||
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
|
||||
|
||||
/*
|
||||
* get fhandle of remote path for automount point
|
||||
*/
|
||||
fhp = get_root_nfs_fh(dir, &anh);
|
||||
if (!fhp) {
|
||||
plog(XLOG_FATAL, "Can't find root file handle for %s", dir);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
#ifndef HAVE_TRANSPORT_TYPE_TLI
|
||||
/*
|
||||
* Create sockaddr to point to the local machine.
|
||||
*/
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
/* as per POSIX, sin_len need not be set (used internally by kernel) */
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr = myipaddr;
|
||||
port = hasmntval(&mnt, MNTTAB_OPT_PORT);
|
||||
if (port) {
|
||||
sin.sin_port = htons(port);
|
||||
} else {
|
||||
plog(XLOG_ERROR, "no port number specified for %s", dir);
|
||||
return EINVAL;
|
||||
}
|
||||
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
|
||||
|
||||
/* setup the many fields and flags within nfs_args */
|
||||
#ifdef HAVE_TRANSPORT_TYPE_TLI
|
||||
compute_nfs_args(&nfs_args,
|
||||
&mnt,
|
||||
genflags,
|
||||
nfsncp,
|
||||
NULL, /* remote host IP addr is set below */
|
||||
nfs_version,
|
||||
"udp",
|
||||
fhp,
|
||||
fs_hostname,
|
||||
pid_fsname);
|
||||
/*
|
||||
* IMPORTANT: set the correct IP address AFTERWARDS. It cannot
|
||||
* be done using the normal mechanism of compute_nfs_args(), because
|
||||
* that one will allocate a new address and use NFS_SA_DREF() to copy
|
||||
* parts to it, while assuming that the ip_addr passed is always
|
||||
* a "struct sockaddr_in". That assumption is incorrect on TLI systems,
|
||||
* because they define a special macro HOST_SELF which is DIFFERENT
|
||||
* than localhost (127.0.0.1)!
|
||||
*/
|
||||
nfs_args.addr = &nfsxprt->xp_ltaddr;
|
||||
#else /* not HAVE_TRANSPORT_TYPE_TLI */
|
||||
compute_nfs_args(&nfs_args,
|
||||
&mnt,
|
||||
genflags,
|
||||
NULL,
|
||||
&sin,
|
||||
nfs_version,
|
||||
"udp",
|
||||
fhp,
|
||||
fs_hostname,
|
||||
pid_fsname);
|
||||
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
|
||||
|
||||
/*************************************************************************
|
||||
* NOTE: while compute_nfs_args() works ok for regular NFS mounts *
|
||||
* the toplvl one is not quite regular, and so some options must be *
|
||||
* corrected by hand more carefully, *after* compute_nfs_args() runs. *
|
||||
*************************************************************************/
|
||||
compute_automounter_nfs_args(&nfs_args, &mnt);
|
||||
|
||||
if (amuDebug(D_TRACE)) {
|
||||
print_nfs_args(&nfs_args, 0);
|
||||
plog(XLOG_DEBUG, "Generic mount flags 0x%x", genflags);
|
||||
}
|
||||
|
||||
/* This is it! Here we try to mount amd on its mount points */
|
||||
error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args,
|
||||
retry, type, 0, NULL, mnttab_file_name, on_autofs);
|
||||
|
||||
#ifdef HAVE_TRANSPORT_TYPE_TLI
|
||||
free_knetconfig(nfs_args.knconf);
|
||||
/*
|
||||
* local automounter mounts do not allocate a special address, so
|
||||
* no need to XFREE(nfs_args.addr) under TLI.
|
||||
*/
|
||||
#endif /* HAVE_TRANSPORT_TYPE_TLI */
|
||||
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
} else {
|
||||
/* This is it! Here we try to mount amd on its mount points */
|
||||
error = mount_fs(&mnt, genflags, (caddr_t) mp->am_autofs_fh,
|
||||
retry, type, 0, NULL, mnttab_file_name, on_autofs);
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
}
|
||||
if (error == 0 || forced_unmount)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* If user wants forced/lazy unmount semantics, then try it iff the
|
||||
* current mount failed with EIO or ESTALE.
|
||||
*/
|
||||
if (gopt.flags & CFM_FORCED_UNMOUNTS) {
|
||||
switch (errno) {
|
||||
case ESTALE:
|
||||
case EIO:
|
||||
forced_unmount = errno;
|
||||
plog(XLOG_WARNING, "Mount %s failed (%m); force unmount.", mp->am_path);
|
||||
if ((error = UMOUNT_FS(mp->am_path, mnttab_file_name,
|
||||
AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH)) < 0) {
|
||||
plog(XLOG_WARNING, "Forced umount %s failed: %m.", mp->am_path);
|
||||
errno = forced_unmount;
|
||||
} else
|
||||
goto again;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
am_unmounted(am_node *mp)
|
||||
{
|
||||
mntfs *mf = mp->am_al->al_mnt;
|
||||
|
||||
if (!foreground) { /* firewall - should never happen */
|
||||
/*
|
||||
* This is a coding error. Make sure we hear about it!
|
||||
*/
|
||||
plog(XLOG_FATAL, "am_unmounted: illegal use in background (%s)",
|
||||
mp->am_name);
|
||||
notify_child(mp, AMQ_UMNT_OK, 0, 0); /* XXX - be safe? */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do unmounted callback
|
||||
*/
|
||||
if (mf->mf_ops->umounted)
|
||||
mf->mf_ops->umounted(mf);
|
||||
|
||||
/*
|
||||
* This is ugly, but essentially unavoidable.
|
||||
* Sublinks must be treated separately as type==link
|
||||
* when the base type is different.
|
||||
*/
|
||||
if (mp->am_link && mf->mf_ops != &amfs_link_ops)
|
||||
amfs_link_ops.umount_fs(mp, mf);
|
||||
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (mf->mf_flags & MFF_IS_AUTOFS)
|
||||
autofs_release_fh(mp);
|
||||
if (mp->am_flags & AMF_AUTOFS)
|
||||
autofs_umount_succeeded(mp);
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
/*
|
||||
* Clean up any directories that were made
|
||||
*
|
||||
* If we remove the mount point of a pending mount, any queued access
|
||||
* to it will fail. So don't do it in that case.
|
||||
* Also don't do it if the refcount is > 1.
|
||||
*/
|
||||
if (mf->mf_flags & MFF_MKMNT &&
|
||||
mf->mf_refc == 1 &&
|
||||
!(mp->am_flags & AMF_REMOUNT)) {
|
||||
plog(XLOG_INFO, "removing mountpoint directory '%s'", mf->mf_mount);
|
||||
rmdirs(mf->mf_mount);
|
||||
mf->mf_flags &= ~MFF_MKMNT;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is a pseudo-directory then adjust the link count
|
||||
* in the parent
|
||||
*/
|
||||
if (mp->am_parent && mp->am_fattr.na_type == NFDIR)
|
||||
--mp->am_parent->am_fattr.na_nlink;
|
||||
|
||||
/*
|
||||
* Update mtime of parent node
|
||||
*/
|
||||
if (mp->am_parent && mp->am_parent->am_al->al_mnt)
|
||||
clocktime(&mp->am_parent->am_fattr.na_mtime);
|
||||
|
||||
if (mp->am_parent && (mp->am_flags & AMF_REMOUNT)) {
|
||||
char *fname = xstrdup(mp->am_name);
|
||||
am_node *mp_parent = mp->am_parent;
|
||||
mntfs *mf_parent = mp_parent->am_al->al_mnt;
|
||||
am_node fake_mp;
|
||||
int error = 0;
|
||||
|
||||
/*
|
||||
* We need to use notify_child() after free_map(), so save enough
|
||||
* to do that in fake_mp.
|
||||
*/
|
||||
fake_mp.am_fd[1] = mp->am_fd[1];
|
||||
mp->am_fd[1] = -1;
|
||||
|
||||
free_map(mp);
|
||||
plog(XLOG_INFO, "am_unmounted: remounting %s", fname);
|
||||
mp = mf_parent->mf_ops->lookup_child(mp_parent, fname, &error, VLOOK_CREATE);
|
||||
if (mp && error < 0)
|
||||
(void)mf_parent->mf_ops->mount_child(mp, &error);
|
||||
if (error > 0) {
|
||||
errno = error;
|
||||
plog(XLOG_ERROR, "am_unmounted: could not remount %s: %m", fname);
|
||||
notify_child(&fake_mp, AMQ_UMNT_OK, 0, 0);
|
||||
} else {
|
||||
notify_child(&fake_mp, AMQ_UMNT_FAILED, EBUSY, 0);
|
||||
}
|
||||
XFREE(fname);
|
||||
} else {
|
||||
/*
|
||||
* We have a race here.
|
||||
* If this node has a pending mount and amd is going down (unmounting
|
||||
* everything in the process), then we could potentially free it here
|
||||
* while a struct continuation still has a reference to it. So when
|
||||
* amfs_cont is called, it blows up.
|
||||
* We avoid the race by refusing to free any nodes that have
|
||||
* pending mounts (defined as having a non-NULL am_alarray).
|
||||
*/
|
||||
notify_child(mp, AMQ_UMNT_OK, 0, 0); /* do this regardless */
|
||||
if (!mp->am_alarray)
|
||||
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) */
|
||||
am_set_mypid();
|
||||
foreground = 0;
|
||||
} else { /* parent process, has one more child */
|
||||
NumChildren++;
|
||||
}
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
background(void)
|
||||
{
|
||||
int pid = dofork();
|
||||
|
||||
if (pid == 0) {
|
||||
dlog("backgrounded");
|
||||
foreground = 0;
|
||||
} else
|
||||
dlog("forked process %d", pid);
|
||||
return pid;
|
||||
}
|
@ -1,240 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/clock.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Callouts.
|
||||
*
|
||||
* Modeled 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>
|
||||
|
||||
void reschedule_timeouts(time_t now, time_t then);
|
||||
|
||||
typedef struct callout callout;
|
||||
struct callout {
|
||||
callout *c_next; /* List of callouts */
|
||||
callout_fun *c_fn; /* Function to call */
|
||||
opaque_t c_arg; /* Argument to pass to call */
|
||||
time_t c_time; /* Time of call */
|
||||
int c_id; /* Unique identifier */
|
||||
};
|
||||
|
||||
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() (++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)(fn_arg) will be called at clocktime(NULL) + secs
|
||||
*/
|
||||
int
|
||||
timeout(u_int secs, callout_fun *fn, opaque_t fn_arg)
|
||||
{
|
||||
callout *cp, *cp2;
|
||||
time_t t = clocktime(NULL) + secs;
|
||||
|
||||
/*
|
||||
* Allocate and fill in a new callout structure
|
||||
*/
|
||||
callout *cpnew = alloc_callout();
|
||||
cpnew->c_arg = fn_arg;
|
||||
cpnew->c_fn = fn;
|
||||
cpnew->c_time = t;
|
||||
cpnew->c_id = CID_ALLOC();
|
||||
|
||||
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);
|
||||
dlog("rescheduling job %d back %ld seconds",
|
||||
cp->c_id, (long) (cp->c_time - now));
|
||||
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(NULL);
|
||||
|
||||
/*
|
||||
* While there are more callouts waiting...
|
||||
*/
|
||||
while ((cp = callouts.c_next) && cp->c_time <= now) {
|
||||
/*
|
||||
* Extract first from list, save fn & fn_arg 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
|
||||
*/
|
||||
callout_fun *fn = cp->c_fn;
|
||||
opaque_t fn_arg = cp->c_arg;
|
||||
|
||||
callouts.c_next = cp->c_next;
|
||||
free_callout(cp);
|
||||
(*fn) (fn_arg);
|
||||
}
|
||||
|
||||
} 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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,154 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/conf_parse.y
|
||||
*
|
||||
*/
|
||||
|
||||
%{
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
|
||||
extern char *yytext;
|
||||
extern int ayylineno;
|
||||
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), ayylineno, (s))
|
||||
# define amu_return(v)
|
||||
#else /* not PARSE_DEBUG */
|
||||
# define dprintf(f,s)
|
||||
# define amu_return(v) return((v))
|
||||
#endif /* not 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, ayylineno,
|
||||
(header_section ? header_section : "null"));
|
||||
exit(1);
|
||||
return 1; /* to full compilers that insist on a return statement */
|
||||
}
|
@ -1,189 +0,0 @@
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/conf_tok.l
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 using GNU flex.
|
||||
* These must not be defined if using standard lex
|
||||
*/
|
||||
#ifdef FLEX_SCANNER
|
||||
# ifndef ECHO
|
||||
# define ECHO __IGNORE(fwrite( yytext, yyleng, 1, yyout ))
|
||||
# endif /* not ECHO */
|
||||
#endif /* FLEX_SCANNER */
|
||||
|
||||
int ayylineno = 0;
|
||||
|
||||
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.
|
||||
*/
|
||||
#if !defined(yywrap) || defined(yylex)
|
||||
int yywrap(void);
|
||||
#endif /* not yywrap or yylex */
|
||||
|
||||
#define TOK_DEBUG 0
|
||||
|
||||
#if TOK_DEBUG
|
||||
# define dprintf(f,s) fprintf(stderr, (f), ayylineno, (s))
|
||||
# define amu_return(v)
|
||||
#else /* not TOK_DEBUG */
|
||||
# define dprintf(f,s)
|
||||
# define amu_return(v) return((v))
|
||||
#endif /* not TOK_DEBUG */
|
||||
|
||||
/* no need to use yywrap() */
|
||||
#define YY_SKIP_YYWRAP
|
||||
|
||||
%}
|
||||
|
||||
/* This option causes Solaris lex to fail. Use flex. See BUGS file */
|
||||
/* no need to use yyunput() */
|
||||
%option nounput
|
||||
%option noinput
|
||||
|
||||
/* allocate more output slots so lex scanners don't run out of mem */
|
||||
%o 1024
|
||||
|
||||
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 {
|
||||
ayylineno++;
|
||||
amu_return(NEWLINE);
|
||||
}
|
||||
|
||||
\[ {
|
||||
dprintf("%8d: Left bracket \"%s\"\n", yytext);
|
||||
conf_lval.strtype = xstrdup(yytext);
|
||||
amu_return(LEFT_BRACKET);
|
||||
}
|
||||
|
||||
\] {
|
||||
dprintf("%8d: Right bracket \"%s\"\n", yytext);
|
||||
conf_lval.strtype = xstrdup(yytext);
|
||||
amu_return(RIGHT_BRACKET);
|
||||
}
|
||||
|
||||
= {
|
||||
dprintf("%8d: Equal \"%s\"\n", yytext);
|
||||
conf_lval.strtype = xstrdup(yytext);
|
||||
amu_return(EQUAL);
|
||||
}
|
||||
|
||||
[ \t]* {
|
||||
dprintf("%8d: Whitespace \"%s\"\n", yytext);
|
||||
}
|
||||
"#"[^\n]*\n {
|
||||
/* a comment line includes the terminating \n */
|
||||
ayylineno++;
|
||||
yytext[strlen((char *)yytext)-1] = '\0';
|
||||
dprintf("%8d: Comment \"%s\"\n", yytext);
|
||||
}
|
||||
|
||||
{NONWSCHAR}{NONWSCHAR}* {
|
||||
dprintf("%8d: Non-WS string \"%s\"\n", yytext);
|
||||
conf_lval.strtype = xstrdup(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';
|
||||
conf_lval.strtype = xstrdup(&yytext[1]);
|
||||
amu_return(QUOTED_NONWSEQ_STRING);
|
||||
}
|
||||
|
||||
{NONWSEQCHAR}{NONWSEQCHAR}* {
|
||||
dprintf("%8d: Non-WS-EQ string \"%s\"\n", yytext);
|
||||
conf_lval.strtype = xstrdup(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.
|
||||
*/
|
||||
#if !defined(yywrap) || defined(yylex)
|
||||
int yywrap(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif /* not yywrap or yylex */
|
@ -1,440 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/get_args.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 *amu_conf_file = "/etc/amd.conf"; /* default amd configuration file */
|
||||
char *conf_tag = NULL; /* default conf file tags to use */
|
||||
int usage = 0;
|
||||
int use_conf_file = 0; /* default don't use amd.conf file */
|
||||
char *mnttab_file_name = NULL; /* symbol must be available always */
|
||||
|
||||
|
||||
/*
|
||||
* Return the version string (dynamic buffer)
|
||||
*/
|
||||
char *
|
||||
get_version_string(void)
|
||||
{
|
||||
char *vers = NULL;
|
||||
char tmpbuf[1024];
|
||||
char *wire_buf;
|
||||
int wire_buf_len = 0;
|
||||
size_t len; /* max allocated length (to avoid buf overflow) */
|
||||
|
||||
/*
|
||||
* First get dynamic string listing all known networks.
|
||||
* This could be a long list, if host has lots of interfaces.
|
||||
*/
|
||||
wire_buf = print_wires();
|
||||
if (wire_buf)
|
||||
wire_buf_len = strlen(wire_buf);
|
||||
|
||||
len = 2048 + wire_buf_len;
|
||||
vers = xmalloc(len);
|
||||
xsnprintf(vers, len, "%s\n%s\n%s\n%s\n",
|
||||
"Copyright (c) 1997-2014 Erez Zadok",
|
||||
"Copyright (c) 1990 Jan-Simon Pendry",
|
||||
"Copyright (c) 1990 Imperial College of Science, Technology & Medicine",
|
||||
"Copyright (c) 1990 The Regents of the University of California.");
|
||||
xsnprintf(tmpbuf, sizeof(tmpbuf), "%s version %s (build %d).\n",
|
||||
PACKAGE_NAME, PACKAGE_VERSION, AMU_BUILD_VERSION);
|
||||
xstrlcat(vers, tmpbuf, len);
|
||||
xsnprintf(tmpbuf, sizeof(tmpbuf), "Report bugs to %s.\n", PACKAGE_BUGREPORT);
|
||||
xstrlcat(vers, tmpbuf, len);
|
||||
#if 0
|
||||
/*
|
||||
* XXX This block (between from the #if 0 to #endif was in the
|
||||
* XXX original was in the original merge however in the interest
|
||||
* XXX of reproduceable builds and the fact that this is redundant
|
||||
* XXX information, it is effectively removed.
|
||||
*/
|
||||
xsnprintf(tmpbuf, sizeof(tmpbuf), "Configured by %s@%s on date %s.\n",
|
||||
USER_NAME, HOST_NAME, CONFIG_DATE);
|
||||
xstrlcat(vers, tmpbuf, len);
|
||||
xsnprintf(tmpbuf, sizeof(tmpbuf), "Built by %s@%s on date %s.\n",
|
||||
BUILD_USER, BUILD_HOST, BUILD_DATE);
|
||||
xstrlcat(vers, tmpbuf, len);
|
||||
#endif
|
||||
xsnprintf(tmpbuf, sizeof(tmpbuf), "cpu=%s (%s-endian), arch=%s, karch=%s.\n",
|
||||
cpu, endian, gopt.arch, gopt.karch);
|
||||
xstrlcat(vers, tmpbuf, len);
|
||||
xsnprintf(tmpbuf, sizeof(tmpbuf), "full_os=%s, os=%s, osver=%s, vendor=%s, distro=%s.\n",
|
||||
gopt.op_sys_full, gopt.op_sys, gopt.op_sys_ver, gopt.op_sys_vendor, DISTRO_NAME);
|
||||
xstrlcat(vers, tmpbuf, len);
|
||||
xsnprintf(tmpbuf, sizeof(tmpbuf), "domain=%s, host=%s, hostd=%s.\n",
|
||||
hostdomain, am_get_hostname(), hostd);
|
||||
xstrlcat(vers, tmpbuf, len);
|
||||
|
||||
xstrlcat(vers, "Map support for: ", len);
|
||||
mapc_showtypes(tmpbuf, sizeof(tmpbuf));
|
||||
xstrlcat(vers, tmpbuf, len);
|
||||
xstrlcat(vers, ".\nAMFS: ", len);
|
||||
ops_showamfstypes(tmpbuf, sizeof(tmpbuf));
|
||||
xstrlcat(vers, tmpbuf, len);
|
||||
xstrlcat(vers, ", inherit.\nFS: ", len); /* hack: "show" that we support type:=inherit */
|
||||
ops_showfstypes(tmpbuf, sizeof(tmpbuf));
|
||||
xstrlcat(vers, tmpbuf, len);
|
||||
|
||||
/* append list of networks if available */
|
||||
if (wire_buf) {
|
||||
xstrlcat(vers, wire_buf, len);
|
||||
XFREE(wire_buf);
|
||||
}
|
||||
|
||||
return vers;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
show_usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-nprvHS] [-a mount_point] [-c cache_time] [-d domain]\n\
|
||||
\t[-k kernel_arch] [-l logfile%s\n\
|
||||
\t[-t timeout.retrans] [-w wait_timeout] [-A arch] [-C cluster_name]\n\
|
||||
\t[-o op_sys_ver] [-O op_sys_name]\n\
|
||||
\t[-F conf_file] [-T conf_tag]", am_get_progname(),
|
||||
#ifdef HAVE_SYSLOG
|
||||
# ifdef LOG_DAEMON
|
||||
"|\"syslog[:facility]\"]"
|
||||
# else /* not LOG_DAEMON */
|
||||
"|\"syslog\"]"
|
||||
# endif /* not LOG_DAEMON */
|
||||
#else /* not HAVE_SYSLOG */
|
||||
"]"
|
||||
#endif /* not HAVE_SYSLOG */
|
||||
);
|
||||
|
||||
#ifdef HAVE_MAP_NIS
|
||||
fputs(" [-y nis-domain]\n", stderr);
|
||||
#else /* not HAVE_MAP_NIS */
|
||||
fputc('\n', stderr);
|
||||
#endif /* HAVE_MAP_NIS */
|
||||
|
||||
show_opts('x', xlog_opt);
|
||||
#ifdef DEBUG
|
||||
show_opts('D', dbg_opt);
|
||||
#endif /* DEBUG */
|
||||
fprintf(stderr, "\t[directory mapname [-map_options]] ...\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
get_args(int argc, char *argv[])
|
||||
{
|
||||
int opt_ch, i;
|
||||
FILE *fp = stdin;
|
||||
char getopt_arguments[] = "+nprvSa:c:d:k:l:o:t:w:x:y:C:D:F:T:O:HA:";
|
||||
char *getopt_args;
|
||||
int print_version = 0; /* 1 means we should print version info */
|
||||
|
||||
#ifdef HAVE_GNU_GETOPT
|
||||
getopt_args = getopt_arguments;
|
||||
#else /* ! HAVE_GNU_GETOPT */
|
||||
getopt_args = &getopt_arguments[1];
|
||||
#endif /* HAVE_GNU_GETOPT */
|
||||
|
||||
/* 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, getopt_args)) != -1)
|
||||
switch (opt_ch) {
|
||||
|
||||
case 'a':
|
||||
if (*optarg != '/') {
|
||||
fprintf(stderr, "%s: -a option must begin with a '/'\n",
|
||||
am_get_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 (also affects toplvl mounts) */
|
||||
{
|
||||
char *dot = strchr(optarg, '.');
|
||||
int i;
|
||||
if (dot)
|
||||
*dot = '\0';
|
||||
if (*optarg) {
|
||||
for (i=0; i<AMU_TYPE_MAX; ++i)
|
||||
gopt.amfs_auto_timeo[i] = atoi(optarg);
|
||||
}
|
||||
if (dot) {
|
||||
for (i=0; i<AMU_TYPE_MAX; ++i)
|
||||
gopt.amfs_auto_retrans[i] = atoi(dot + 1);
|
||||
*dot = '.';
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
/*
|
||||
* defer to print version info after every variable had been
|
||||
* initialized.
|
||||
*/
|
||||
print_version++;
|
||||
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 'A':
|
||||
gopt.arch = optarg;
|
||||
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",
|
||||
am_get_progname());
|
||||
#endif /* not DEBUG */
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
amu_conf_file = optarg;
|
||||
use_conf_file = 1;
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
show_usage();
|
||||
exit(1);
|
||||
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 && amu_conf_file) {
|
||||
fp = fopen(amu_conf_file, "r");
|
||||
if (!fp) {
|
||||
char buf[128];
|
||||
xsnprintf(buf, sizeof(buf), "Amd configuration file (%s)",
|
||||
amu_conf_file);
|
||||
perror(buf);
|
||||
exit(1);
|
||||
}
|
||||
conf_in = fp;
|
||||
conf_parse();
|
||||
fclose(fp);
|
||||
if (process_all_regular_maps() != 0)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
usage += switch_option("debug");
|
||||
/* initialize debug options */
|
||||
if (!debug_flags)
|
||||
debug_flags = D_CONTROL; /* CONTROL = "daemon,amq,fork" */
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* log information regarding amd.conf file */
|
||||
if (use_conf_file && amu_conf_file)
|
||||
plog(XLOG_INFO, "using configuration file %s", amu_conf_file);
|
||||
|
||||
#ifdef HAVE_MAP_LDAP
|
||||
/* ensure that if ldap_base is specified, that also ldap_hostports is */
|
||||
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) {
|
||||
show_usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
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++;
|
||||
xstrlcat(hostd, ".", sizeof(hostd));
|
||||
xstrlcat(hostd, hostdomain, sizeof(hostd));
|
||||
|
||||
#ifdef MOUNT_TABLE_ON_FILE
|
||||
if (amuDebug(D_MTAB))
|
||||
if (gopt.debug_mtab_file)
|
||||
mnttab_file_name = gopt.debug_mtab_file; /* user supplied debug mtab path */
|
||||
else
|
||||
mnttab_file_name = DEBUG_MNTTAB_FILE; /* default debug mtab path */
|
||||
else
|
||||
mnttab_file_name = MNTTAB_FILE_NAME;
|
||||
#else /* not MOUNT_TABLE_ON_FILE */
|
||||
if (amuDebug(D_MTAB))
|
||||
dlog("-D mtab option ignored");
|
||||
# ifdef MNTTAB_FILE_NAME
|
||||
mnttab_file_name = MNTTAB_FILE_NAME;
|
||||
# endif /* MNTTAB_FILE_NAME */
|
||||
#endif /* not MOUNT_TABLE_ON_FILE */
|
||||
|
||||
/*
|
||||
* If the kernel architecture was not specified
|
||||
* then use the machine architecture.
|
||||
*/
|
||||
if (gopt.karch == NULL)
|
||||
gopt.karch = gopt.arch;
|
||||
|
||||
if (gopt.cluster == NULL)
|
||||
gopt.cluster = hostdomain;
|
||||
|
||||
/* sanity checking, normalize values just in case (toplvl too) */
|
||||
for (i=0; i<AMU_TYPE_MAX; ++i) {
|
||||
if (gopt.amfs_auto_timeo[i] == 0)
|
||||
gopt.amfs_auto_timeo[i] = AMFS_AUTO_TIMEO;
|
||||
if (gopt.amfs_auto_retrans[i] == 0)
|
||||
gopt.amfs_auto_retrans[i] = AMFS_AUTO_RETRANS(i);
|
||||
if (gopt.amfs_auto_retrans[i] == 0)
|
||||
gopt.amfs_auto_retrans[i] = 3; /* under very unusual circumstances, could be zero */
|
||||
}
|
||||
}
|
||||
|
||||
/* finally print version string and exit, if asked for */
|
||||
if (print_version) {
|
||||
fputs(get_version_string(), stderr);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (switch_to_logfile(gopt.logfile, orig_umask,
|
||||
(gopt.flags & CFM_TRUNCATE_LOG)) != 0)
|
||||
plog(XLOG_USER, "Cannot switch logfile");
|
||||
|
||||
return;
|
||||
}
|
@ -1,422 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/info_exec.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get info from executable map
|
||||
*
|
||||
* Original from Erik Kline, 2004.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
#include <sun_map.h>
|
||||
|
||||
|
||||
/* forward declarations */
|
||||
int exec_init(mnt_map *m, char *map, time_t *tp);
|
||||
int exec_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp);
|
||||
|
||||
|
||||
/*
|
||||
* a timed fgets()
|
||||
*/
|
||||
static char *
|
||||
fgets_timed(char *s, int size, int rdfd, int secs)
|
||||
{
|
||||
fd_set fds;
|
||||
struct timeval timeo;
|
||||
time_t start, now;
|
||||
int rval=0, i=0;
|
||||
|
||||
if (!s || size < 0 || rdfd < 0)
|
||||
return 0;
|
||||
|
||||
s[0] = '\0';
|
||||
if (size == 0)
|
||||
return s;
|
||||
|
||||
start = clocktime(NULL);
|
||||
while (s[i] != '\n' && i < size-1) {
|
||||
s[i+1] = '\0'; /* places the requisite trailing '\0' */
|
||||
|
||||
/* ready for reading */
|
||||
rval = read(rdfd, (void *)(s+i), 1);
|
||||
if (rval == 1) {
|
||||
if (s[i] == 0) {
|
||||
rval = 0;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
} else if (rval == 0) {
|
||||
break;
|
||||
} else if (rval < 0 && errno != EAGAIN && errno != EINTR) {
|
||||
plog(XLOG_WARNING, "fgets_timed read error: %m");
|
||||
break;
|
||||
}
|
||||
|
||||
timeo.tv_usec = 0;
|
||||
now = clocktime(NULL) - start;
|
||||
if (secs <= 0)
|
||||
timeo.tv_sec = 0;
|
||||
else if (now < secs)
|
||||
timeo.tv_sec = secs - now;
|
||||
else {
|
||||
/* timed out (now>=secs) */
|
||||
plog(XLOG_WARNING, "executable map read timed out (> %d secs)", secs);
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(rdfd, &fds);
|
||||
|
||||
rval = select(rdfd+1, &fds, NULL, NULL, &timeo);
|
||||
if (rval < 0) {
|
||||
/* error selecting */
|
||||
plog(XLOG_WARNING, "fgets_timed select error: %m");
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
rval = -1;
|
||||
break;
|
||||
} else if (rval == 0) {
|
||||
/* timed out */
|
||||
plog(XLOG_WARNING, "executable map read timed out (> %d secs)", secs);
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rval > 0)
|
||||
return s;
|
||||
|
||||
close(rdfd);
|
||||
return (rval == 0 ? s : 0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
read_line(char *buf, int size, int fd)
|
||||
{
|
||||
int done = 0;
|
||||
|
||||
while (fgets_timed(buf, size, fd, gopt.exec_map_timeout)) {
|
||||
int len = strlen(buf);
|
||||
done += len;
|
||||
if (len > 1 && buf[len - 2] == '\\' &&
|
||||
buf[len - 1] == '\n') {
|
||||
buf += len - 2;
|
||||
size -= len - 2;
|
||||
*buf = '\n';
|
||||
buf[1] = '\0';
|
||||
} else {
|
||||
return done;
|
||||
}
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Try to locate a value in a query answer
|
||||
*/
|
||||
static int
|
||||
exec_parse_qanswer(mnt_map *m, int fd, char *map, char *key, char **pval, time_t *tp)
|
||||
{
|
||||
char qanswer[INFO_MAX_LINE_LEN], *dc = NULL;
|
||||
int chuck = 0;
|
||||
int line_no = 0;
|
||||
|
||||
while (read_line(qanswer, sizeof(qanswer), fd)) {
|
||||
char *cp;
|
||||
char *hash;
|
||||
int len = strlen(qanswer);
|
||||
line_no++;
|
||||
|
||||
/*
|
||||
* Make sure we got the whole line
|
||||
*/
|
||||
if (qanswer[len - 1] != '\n') {
|
||||
plog(XLOG_WARNING, "line %d in \"%s\" is too long", line_no, map);
|
||||
chuck = 1;
|
||||
} else {
|
||||
qanswer[len - 1] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Strip comments
|
||||
*/
|
||||
hash = strchr(qanswer, '#');
|
||||
if (hash)
|
||||
*hash = '\0';
|
||||
|
||||
/*
|
||||
* Find beginning of value (query answer)
|
||||
*/
|
||||
for (cp = qanswer; *cp && !isascii((unsigned char)*cp) && !isspace((unsigned char)*cp); cp++)
|
||||
;;
|
||||
|
||||
/* Ignore blank lines */
|
||||
if (!*cp)
|
||||
goto again;
|
||||
|
||||
/*
|
||||
* Return a copy of the data
|
||||
*/
|
||||
if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX))
|
||||
dc = sun_entry2amd(key, cp);
|
||||
else
|
||||
dc = xstrdup(cp);
|
||||
*pval = dc;
|
||||
dlog("%s returns %s", key, dc);
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
|
||||
again:
|
||||
/*
|
||||
* If the last read didn't get a whole line then
|
||||
* throw away the remainder before continuing...
|
||||
*/
|
||||
if (chuck) {
|
||||
while (fgets_timed(qanswer, sizeof(qanswer), fd, gopt.exec_map_timeout) &&
|
||||
!strchr(qanswer, '\n')) ;
|
||||
chuck = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
set_nonblock(int fd)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
|
||||
if ((val = fcntl(fd, F_GETFL, 0)) < 0) {
|
||||
plog(XLOG_WARNING, "set_nonblock fcntl F_GETFL error: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
val |= O_NONBLOCK;
|
||||
if (fcntl(fd, F_SETFL, val) < 0) {
|
||||
plog(XLOG_WARNING, "set_nonblock fcntl F_SETFL error: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
exec_map_open(char *emap, char *key)
|
||||
{
|
||||
pid_t p1, p2;
|
||||
int pdes[2], nullfd, i;
|
||||
char *argv[3];
|
||||
|
||||
if (!emap)
|
||||
return 0;
|
||||
|
||||
argv[0] = emap;
|
||||
argv[1] = key;
|
||||
argv[2] = NULL;
|
||||
|
||||
if ((nullfd = open("/dev/null", O_WRONLY|O_NOCTTY)) < 0)
|
||||
return -1;
|
||||
|
||||
if (pipe(pdes) < 0) {
|
||||
close(nullfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch ((p1 = vfork())) {
|
||||
case -1:
|
||||
/* parent: fork error */
|
||||
close(nullfd);
|
||||
close(pdes[0]);
|
||||
close(pdes[1]);
|
||||
return -1;
|
||||
case 0:
|
||||
/* child #1 */
|
||||
p2 = vfork();
|
||||
switch (p2) {
|
||||
case -1:
|
||||
/* child #1: fork error */
|
||||
exit(errno);
|
||||
case 0:
|
||||
/* child #2: init will reap our status */
|
||||
if (pdes[1] != STDOUT_FILENO) {
|
||||
dup2(pdes[1], STDOUT_FILENO);
|
||||
close(pdes[1]);
|
||||
}
|
||||
|
||||
if (nullfd != STDERR_FILENO) {
|
||||
dup2(nullfd, STDERR_FILENO);
|
||||
close(nullfd);
|
||||
}
|
||||
|
||||
for (i=0; i<FD_SETSIZE; i++)
|
||||
if (i != STDOUT_FILENO && i != STDERR_FILENO)
|
||||
close(i);
|
||||
|
||||
/* make the write descriptor non-blocking */
|
||||
if (!set_nonblock(STDOUT_FILENO)) {
|
||||
close(STDOUT_FILENO);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
execve(emap, argv, NULL);
|
||||
exit(errno); /* in case execve failed */
|
||||
}
|
||||
|
||||
/* child #1 */
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* parent */
|
||||
close(nullfd);
|
||||
close(pdes[1]);
|
||||
|
||||
/* anti-zombie insurance */
|
||||
while (waitpid(p1, 0, 0) < 0)
|
||||
if (errno != EINTR)
|
||||
exit(errno);
|
||||
|
||||
/* make the read descriptor non-blocking */
|
||||
if (!set_nonblock(pdes[0])) {
|
||||
close(pdes[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return pdes[0];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check for various permissions on executable map without trying to
|
||||
* fork a new executable-map process.
|
||||
*
|
||||
* return: >0 (errno) if failed
|
||||
* 0 if ok
|
||||
*/
|
||||
static int
|
||||
exec_check_perm(char *map)
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
/* sanity and permission checks */
|
||||
if (!map) {
|
||||
dlog("exec_check_permission got a NULL map");
|
||||
return EINVAL;
|
||||
}
|
||||
if (stat(map, &sb)) {
|
||||
plog(XLOG_ERROR, "map \"%s\" stat failure: %m", map);
|
||||
return errno;
|
||||
}
|
||||
if (!S_ISREG(sb.st_mode)) {
|
||||
plog(XLOG_ERROR, "map \"%s\" should be regular file", map);
|
||||
return EINVAL;
|
||||
}
|
||||
if (sb.st_uid != 0) {
|
||||
plog(XLOG_ERROR, "map \"%s\" owned by uid %u (must be 0)", map, (u_int) sb.st_uid);
|
||||
return EACCES;
|
||||
}
|
||||
if (!(sb.st_mode & S_IXUSR)) {
|
||||
plog(XLOG_ERROR, "map \"%s\" should be executable", map);
|
||||
return EACCES;
|
||||
}
|
||||
if (sb.st_mode & (S_ISUID|S_ISGID)) {
|
||||
plog(XLOG_ERROR, "map \"%s\" should not be setuid/setgid", map);
|
||||
return EACCES;
|
||||
}
|
||||
if (sb.st_mode & S_IWOTH) {
|
||||
plog(XLOG_ERROR, "map \"%s\" should not be world writeable", map);
|
||||
return EACCES;
|
||||
}
|
||||
|
||||
return 0; /* all is well */
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
exec_init(mnt_map *m, char *map, time_t *tp)
|
||||
{
|
||||
/*
|
||||
* Basically just test that the executable map can be found
|
||||
* and has proper permissions.
|
||||
*/
|
||||
return exec_check_perm(map);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
exec_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
|
||||
{
|
||||
int mapfd, ret;
|
||||
|
||||
if ((ret = exec_check_perm(map)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!key)
|
||||
return 0;
|
||||
|
||||
if (logfp)
|
||||
fflush(logfp);
|
||||
dlog("exec_search \"%s\", key: \"%s\"", map, key);
|
||||
mapfd = exec_map_open(map, key);
|
||||
|
||||
if (mapfd >= 0) {
|
||||
if (tp)
|
||||
*tp = clocktime(NULL);
|
||||
|
||||
return exec_parse_qanswer(m, mapfd, map, key, pval, tp);
|
||||
}
|
||||
|
||||
return errno;
|
||||
}
|
@ -1,254 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/info_file.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get info from file
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
#include <sun_map.h>
|
||||
|
||||
|
||||
/* forward declarations */
|
||||
int file_init_or_mtime(mnt_map *m, char *map, time_t *tp);
|
||||
int file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *));
|
||||
int file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp);
|
||||
|
||||
|
||||
int
|
||||
file_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((unsigned char)ch) && isspace((unsigned char)ch)) ;
|
||||
(void) ungetc(ch, fp);
|
||||
} else {
|
||||
return done;
|
||||
}
|
||||
}
|
||||
} while (size > 0 && !feof(fp) && !ferror(fp));
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Try to locate a key in a file
|
||||
*/
|
||||
static int
|
||||
file_search_or_reload(mnt_map *m,
|
||||
FILE *fp,
|
||||
char *map,
|
||||
char *key,
|
||||
char **val,
|
||||
void (*fn) (mnt_map *m, char *, char *))
|
||||
{
|
||||
char key_val[INFO_MAX_LINE_LEN];
|
||||
int chuck = 0;
|
||||
int line_no = 0;
|
||||
|
||||
while (file_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((unsigned char)*kp) && isspace((unsigned char)*kp); kp++) ;
|
||||
|
||||
/*
|
||||
* Ignore blank lines
|
||||
*/
|
||||
if (!*kp)
|
||||
goto again;
|
||||
|
||||
/*
|
||||
* Find end of key
|
||||
*/
|
||||
for (cp = kp; *cp && (!isascii((unsigned char)*cp) || !isspace((unsigned char)*cp)); cp++) ;
|
||||
|
||||
/*
|
||||
* Check whether key matches
|
||||
*/
|
||||
if (*cp)
|
||||
*cp++ = '\0';
|
||||
|
||||
if (fn || (*key == *kp && STREQ(key, kp))) {
|
||||
while (*cp && isascii((unsigned char)*cp) && isspace((unsigned char)*cp))
|
||||
cp++;
|
||||
if (*cp) {
|
||||
/*
|
||||
* Return a copy of the data
|
||||
*/
|
||||
char *dc;
|
||||
/* if m->cfm == NULL, not using amd.conf file */
|
||||
if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX))
|
||||
dc = sun_entry2amd(kp, cp);
|
||||
else
|
||||
dc = xstrdup(cp);
|
||||
if (fn) {
|
||||
(*fn) (m, xstrdup(kp), dc);
|
||||
} else {
|
||||
*val = dc;
|
||||
dlog("%s returns %s", key, dc);
|
||||
}
|
||||
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(NULL);
|
||||
else
|
||||
*tp = stb.st_mtime;
|
||||
}
|
||||
return mapf;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
file_init_or_mtime(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 *) NULL);
|
||||
|
||||
if (mapf) {
|
||||
int error = file_search_or_reload(m, mapf, map, NULL, NULL, 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 = file_search_or_reload(m, mapf, map, key, pval, NULL);
|
||||
}
|
||||
(void) fclose(mapf);
|
||||
return error;
|
||||
}
|
||||
return errno;
|
||||
}
|
@ -1,191 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/info_hesiod.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get info from Hesiod
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
#include <sun_map.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);
|
||||
extern int hesiod_init(void **context);
|
||||
static voidp hesiod_context;
|
||||
#endif /* HAVE_HESIOD_INIT */
|
||||
|
||||
/* forward declarations */
|
||||
int amu_hesiod_init(mnt_map *m, char *map, time_t *tp);
|
||||
int hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp);
|
||||
int hesiod_isup(mnt_map *m, char *map);
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
dlog("amu_hesiod_init(%s)", map);
|
||||
*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 */
|
||||
|
||||
dlog("hesiod_search(m=%lx, map=%s, key=%s, pval=%lx tp=%lx)",
|
||||
(unsigned long) m, map, key, (unsigned long) pval, (unsigned long) tp);
|
||||
|
||||
if (key[0] == '.')
|
||||
return ENOENT;
|
||||
|
||||
xsnprintf(hes_key, sizeof(hes_key), "%s.%s", key, map + HES_PREFLEN);
|
||||
|
||||
/*
|
||||
* Call the resolver
|
||||
*/
|
||||
dlog("Hesiod base is: %s\n", gopt.hesiod_base);
|
||||
dlog("hesiod_search: hes_resolve(%s, %s)", hes_key, gopt.hesiod_base);
|
||||
if (amuDebug(D_INFO))
|
||||
_res.options |= RES_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) {
|
||||
if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX)) {
|
||||
*pval = sun_entry2amd(key, *rvec);
|
||||
XFREE(*rvec);
|
||||
} else
|
||||
*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
|
||||
*/
|
||||
dlog("hesiod_search: Error: %d", hes_error());
|
||||
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;
|
||||
}
|
||||
dlog("hesiod_search: Returning: %d", error);
|
||||
return error;
|
||||
#endif /* not HAVE_HESIOD_INIT */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check if Hesiod is up, so we can determine if to clear the map or not.
|
||||
* Test it by querying for /defaults.
|
||||
* Returns: 0 if Hesiod is down, 1 if it is up.
|
||||
*/
|
||||
int
|
||||
hesiod_isup(mnt_map *m, char *map)
|
||||
{
|
||||
int error;
|
||||
char *val;
|
||||
time_t mtime;
|
||||
static int last_status = 1; /* assume up by default */
|
||||
|
||||
error = hesiod_search(m, map, "/defaults", &val, &mtime);
|
||||
dlog("hesiod_isup(%s): %s", map, strerror(error));
|
||||
if (error != 0 && error != ENOENT) {
|
||||
plog(XLOG_ERROR,
|
||||
"hesiod_isup: error getting `/defaults' entry in map %s: %m", map);
|
||||
last_status = 0;
|
||||
return 0; /* Hesiod is down */
|
||||
}
|
||||
if (last_status == 0) { /* if was down before */
|
||||
plog(XLOG_INFO, "hesiod_isup: Hesiod came back up for map %s", map);
|
||||
last_status = 1;
|
||||
}
|
||||
return 1; /* Hesiod is up */
|
||||
}
|
@ -1,592 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/info_ldap.c
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Get info from LDAP (Lightweight Directory Access Protocol)
|
||||
* LDAP Home Page: http://www.umich.edu/~rsug/ldap/
|
||||
*/
|
||||
|
||||
/*
|
||||
* WARNING: as of Linux Fedora Core 5 (which comes with openldap-2.3.9), the
|
||||
* ldap.h headers deprecate several functions used in this file, such as
|
||||
* ldap_unbind. You get compile errors about missing extern definitions.
|
||||
* Those externs are still in <ldap.h>, but surrounded by an ifdef
|
||||
* LDAP_DEPRECATED. I am turning on that ifdef here, under the assumption
|
||||
* that the functions may be deprecated, but they still work for this
|
||||
* (older?) version of the LDAP API. It gets am-utils to compile, but it is
|
||||
* not clear if it will work perfectly.
|
||||
*/
|
||||
#ifndef LDAP_DEPRECATED
|
||||
# define LDAP_DEPRECATED 1
|
||||
#endif /* not LDAP_DEPRECATED */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
#include <sun_map.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_ENT;
|
||||
|
||||
/*
|
||||
* STRUCTURES:
|
||||
*/
|
||||
struct ald_ent {
|
||||
LDAP *ldap;
|
||||
HE_ENT *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;
|
||||
};
|
||||
|
||||
static ALD *ldap_connection;
|
||||
|
||||
/*
|
||||
* FORWARD DECLARATIONS:
|
||||
*/
|
||||
static int amu_ldap_rebind(ALD *a);
|
||||
static int get_ldap_timestamp(ALD *a, char *map, time_t *ts);
|
||||
|
||||
int amu_ldap_init(mnt_map *m, char *map, time_t *tsu);
|
||||
int amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts);
|
||||
int amu_ldap_mtime(mnt_map *m, char *map, time_t *ts);
|
||||
|
||||
/*
|
||||
* FUNCTIONS:
|
||||
*/
|
||||
|
||||
static void
|
||||
he_free(HE_ENT *h)
|
||||
{
|
||||
XFREE(h->host);
|
||||
if (h->next != NULL)
|
||||
he_free(h->next);
|
||||
XFREE(h);
|
||||
}
|
||||
|
||||
|
||||
static HE_ENT *
|
||||
string2he(char *s_orig)
|
||||
{
|
||||
char *c, *p;
|
||||
char *s;
|
||||
HE_ENT *first = NULL, *cur = NULL;
|
||||
|
||||
if (NULL == s_orig)
|
||||
return NULL;
|
||||
s = xstrdup(s_orig);
|
||||
for (p = strtok(s, ","); p; p = strtok(NULL, ",")) {
|
||||
if (cur != NULL) {
|
||||
cur->next = ALLOC(HE_ENT);
|
||||
cur = cur->next;
|
||||
} else
|
||||
first = cur = ALLOC(HE_ENT);
|
||||
|
||||
cur->next = NULL;
|
||||
c = strchr(p, ':');
|
||||
if (c) { /* Host and port */
|
||||
*c++ = '\0';
|
||||
cur->host = xstrdup(p);
|
||||
cur->port = atoi(c);
|
||||
} else {
|
||||
cur->host = xstrdup(p);
|
||||
cur->port = LDAP_PORT;
|
||||
}
|
||||
plog(XLOG_USER, "Adding ldap server %s:%d",
|
||||
cur->host, cur->port);
|
||||
}
|
||||
XFREE(s);
|
||||
return first;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cr_free(CR *c)
|
||||
{
|
||||
XFREE(c->who);
|
||||
XFREE(c->pw);
|
||||
XFREE(c);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Special ldap_unbind function to handle SIGPIPE.
|
||||
* We first ignore SIGPIPE, in case a remote LDAP server was
|
||||
* restarted, then we reinstall the handler.
|
||||
*/
|
||||
static int
|
||||
amu_ldap_unbind(LDAP *ld)
|
||||
{
|
||||
int e;
|
||||
#ifdef HAVE_SIGACTION
|
||||
struct sigaction sa;
|
||||
#else /* not HAVE_SIGACTION */
|
||||
void (*handler)(int);
|
||||
#endif /* not HAVE_SIGACTION */
|
||||
|
||||
dlog("amu_ldap_unbind()\n");
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sa.sa_flags = 0;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
sigaddset(&(sa.sa_mask), SIGPIPE);
|
||||
sigaction(SIGPIPE, &sa, &sa); /* set IGNORE, and get old action */
|
||||
#else /* not HAVE_SIGACTION */
|
||||
handler = signal(SIGPIPE, SIG_IGN);
|
||||
#endif /* not HAVE_SIGACTION */
|
||||
|
||||
e = ldap_unbind(ld);
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
sigaddset(&(sa.sa_mask), SIGPIPE);
|
||||
sigaction(SIGPIPE, &sa, NULL);
|
||||
#else /* not HAVE_SIGACTION */
|
||||
(void) signal(SIGPIPE, handler);
|
||||
#endif /* not HAVE_SIGACTION */
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ald_free(ALD *a)
|
||||
{
|
||||
he_free(a->hostent);
|
||||
cr_free(a->credentials);
|
||||
if (a->ldap != NULL)
|
||||
amu_ldap_unbind(a->ldap);
|
||||
XFREE(a);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
amu_ldap_init(mnt_map *m, char *map, time_t *ts)
|
||||
{
|
||||
ALD *aldh;
|
||||
CR *creds;
|
||||
|
||||
dlog("-> amu_ldap_init: map <%s>\n", map);
|
||||
|
||||
/*
|
||||
* XXX: by checking that map_type must be defined, aren't we
|
||||
* excluding the possibility of automatic searches through all
|
||||
* map types?
|
||||
*/
|
||||
if (!gopt.map_type || !STREQ(gopt.map_type, AMD_LDAP_TYPE)) {
|
||||
dlog("amu_ldap_init called with map_type <%s>\n",
|
||||
(gopt.map_type ? gopt.map_type : "null"));
|
||||
return ENOENT;
|
||||
} else {
|
||||
dlog("Map %s is ldap\n", map);
|
||||
}
|
||||
|
||||
#ifndef LDAP_CONNECTION_PER_MAP
|
||||
if (ldap_connection != NULL) {
|
||||
m->map_data = (void *) ldap_connection;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
aldh = ALLOC(ALD);
|
||||
creds = ALLOC(CR);
|
||||
aldh->ldap = NULL;
|
||||
aldh->hostent = string2he(gopt.ldap_hostports);
|
||||
if (aldh->hostent == NULL) {
|
||||
plog(XLOG_USER, "Unable to parse hostport %s for ldap map %s",
|
||||
gopt.ldap_hostports ? gopt.ldap_hostports : "(null)", map);
|
||||
XFREE(creds);
|
||||
XFREE(aldh);
|
||||
return (ENOENT);
|
||||
}
|
||||
creds->who = "";
|
||||
creds->pw = "";
|
||||
creds->method = LDAP_AUTH_SIMPLE;
|
||||
aldh->credentials = creds;
|
||||
aldh->timestamp = 0;
|
||||
aldh->ldap = NULL;
|
||||
dlog("Trying for %s:%d\n", aldh->hostent->host, aldh->hostent->port);
|
||||
if (amu_ldap_rebind(aldh)) {
|
||||
ald_free(aldh);
|
||||
return (ENOENT);
|
||||
}
|
||||
dlog("Bound to %s:%d\n", aldh->hostent->host, aldh->hostent->port);
|
||||
if (get_ldap_timestamp(aldh, map, ts)) {
|
||||
ald_free(aldh);
|
||||
return (ENOENT);
|
||||
}
|
||||
dlog("Got timestamp for map %s: %ld\n", map, (u_long) *ts);
|
||||
ldap_connection = aldh;
|
||||
m->map_data = (void *) ldap_connection;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
amu_ldap_rebind(ALD *a)
|
||||
{
|
||||
LDAP *ld;
|
||||
HE_ENT *h;
|
||||
CR *c = a->credentials;
|
||||
time_t now = clocktime(NULL);
|
||||
int try;
|
||||
|
||||
dlog("-> amu_ldap_rebind\n");
|
||||
|
||||
if (a->ldap != NULL) {
|
||||
if ((a->timestamp - now) > AMD_LDAP_TTL) {
|
||||
dlog("Re-establishing ldap connection\n");
|
||||
amu_ldap_unbind(a->ldap);
|
||||
a->timestamp = now;
|
||||
a->ldap = NULL;
|
||||
} else {
|
||||
/* Assume all is OK. If it wasn't we'll be back! */
|
||||
dlog("amu_ldap_rebind: timestamp OK\n");
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
for (try=0; try<10; try++) { /* XXX: try up to 10 times (makes sense?) */
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
#if LDAP_VERSION_MAX > LDAP_VERSION2
|
||||
/* handle LDAPv3 and heigher, if available and amd.conf-igured */
|
||||
if (gopt.ldap_proto_version > LDAP_VERSION2) {
|
||||
if (!ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &gopt.ldap_proto_version)) {
|
||||
dlog("amu_ldap_rebind: LDAP protocol version set to %ld\n",
|
||||
gopt.ldap_proto_version);
|
||||
} else {
|
||||
plog(XLOG_WARNING, "Unable to set ldap protocol version to %ld for "
|
||||
"%s:%d\n", gopt.ldap_proto_version, h->host, h->port);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif /* LDAP_VERSION_MAX > LDAP_VERSION2 */
|
||||
if (ldap_bind_s(ld, c->who, c->pw, c->method) != LDAP_SUCCESS) {
|
||||
plog(XLOG_WARNING, "Unable to ldap_bind to %s:%d as %s\n",
|
||||
h->host, h->port, c->who);
|
||||
continue;
|
||||
}
|
||||
if (gopt.ldap_cache_seconds > 0) {
|
||||
#if defined(HAVE_LDAP_ENABLE_CACHE) && defined(HAVE_EXTERN_LDAP_ENABLE_CACHE)
|
||||
ldap_enable_cache(ld, gopt.ldap_cache_seconds, gopt.ldap_cache_maxmem);
|
||||
#else /* not defined(HAVE_LDAP_ENABLE_CACHE) && defined(HAVE_EXTERN_LDAP_ENABLE_CACHE) */
|
||||
plog(XLOG_WARNING, "ldap_enable_cache(%ld) is not available on this system!\n", gopt.ldap_cache_seconds);
|
||||
#endif /* not defined(HAVE_LDAP_ENABLE_CACHE) && defined(HAVE_EXTERN_LDAP_ENABLE_CACHE) */
|
||||
}
|
||||
a->ldap = ld;
|
||||
a->timestamp = now;
|
||||
return (0);
|
||||
}
|
||||
plog(XLOG_WARNING, "Exhausted list of ldap servers, looping.\n");
|
||||
}
|
||||
|
||||
plog(XLOG_USER, "Unable to (re)bind to any ldap hosts\n");
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
get_ldap_timestamp(ALD *a, char *map, time_t *ts)
|
||||
{
|
||||
struct timeval tv;
|
||||
char **vals, *end;
|
||||
char filter[MAXPATHLEN];
|
||||
int i, err = 0, nentries = 0;
|
||||
LDAPMessage *res = NULL, *entry;
|
||||
|
||||
dlog("-> get_ldap_timestamp: map <%s>\n", map);
|
||||
|
||||
tv.tv_sec = 3;
|
||||
tv.tv_usec = 0;
|
||||
xsnprintf(filter, sizeof(filter), AMD_LDAP_TSFILTER, map);
|
||||
dlog("Getting timestamp for map %s\n", map);
|
||||
dlog("Filter is: %s\n", filter);
|
||||
dlog("Base is: %s\n", gopt.ldap_base);
|
||||
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;
|
||||
if (res) {
|
||||
ldap_msgfree(res);
|
||||
res = NULL;
|
||||
}
|
||||
plog(XLOG_USER, "Timestamp LDAP search attempt %d failed: %s\n",
|
||||
i + 1, ldap_err2string(err));
|
||||
if (err != LDAP_TIMEOUT) {
|
||||
dlog("get_ldap_timestamp: unbinding...\n");
|
||||
amu_ldap_unbind(a->ldap);
|
||||
a->ldap = NULL;
|
||||
if (amu_ldap_rebind(a))
|
||||
return (ENOENT);
|
||||
}
|
||||
dlog("Timestamp search failed, trying again...\n");
|
||||
}
|
||||
|
||||
if (err != LDAP_SUCCESS) {
|
||||
*ts = 0;
|
||||
plog(XLOG_USER, "LDAP timestamp search failed: %s\n",
|
||||
ldap_err2string(err));
|
||||
if (res)
|
||||
ldap_msgfree(res);
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
nentries = ldap_count_entries(a->ldap, res);
|
||||
if (nentries == 0) {
|
||||
plog(XLOG_USER, "No timestamp entry for map %s\n", map);
|
||||
*ts = 0;
|
||||
ldap_msgfree(res);
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
entry = ldap_first_entry(a->ldap, res);
|
||||
vals = ldap_get_values(a->ldap, entry, AMD_LDAP_TSATTR);
|
||||
if (ldap_count_values(vals) == 0) {
|
||||
plog(XLOG_USER, "Missing timestamp value for map %s\n", map);
|
||||
*ts = 0;
|
||||
ldap_value_free(vals);
|
||||
ldap_msgfree(res);
|
||||
return (ENOENT);
|
||||
}
|
||||
dlog("TS value is:%s:\n", vals[0]);
|
||||
|
||||
if (vals[0]) {
|
||||
*ts = (time_t) strtol(vals[0], &end, 10);
|
||||
if (end == vals[0]) {
|
||||
plog(XLOG_USER, "Unable to decode ldap timestamp %s for map %s\n",
|
||||
vals[0], map);
|
||||
err = ENOENT;
|
||||
}
|
||||
if (!*ts > 0) {
|
||||
plog(XLOG_USER, "Nonpositive timestamp %ld for map %s\n",
|
||||
(u_long) *ts, map);
|
||||
err = ENOENT;
|
||||
}
|
||||
} else {
|
||||
plog(XLOG_USER, "Empty timestamp value for map %s\n", map);
|
||||
*ts = 0;
|
||||
err = ENOENT;
|
||||
}
|
||||
|
||||
ldap_value_free(vals);
|
||||
ldap_msgfree(res);
|
||||
dlog("The timestamp for %s is %ld (err=%d)\n", map, (u_long) *ts, err);
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts)
|
||||
{
|
||||
char **vals, filter[MAXPATHLEN], filter2[2 * MAXPATHLEN];
|
||||
char *f1, *f2;
|
||||
struct timeval tv;
|
||||
int i, err = 0, nvals = 0, nentries = 0;
|
||||
LDAPMessage *entry, *res = NULL;
|
||||
ALD *a = (ALD *) (m->map_data);
|
||||
|
||||
dlog("-> amu_ldap_search: map <%s>, key <%s>\n", map, key);
|
||||
|
||||
tv.tv_sec = 2;
|
||||
tv.tv_usec = 0;
|
||||
if (a == NULL) {
|
||||
plog(XLOG_USER, "LDAP panic: no map data\n");
|
||||
return (EIO);
|
||||
}
|
||||
if (amu_ldap_rebind(a)) /* Check that's the handle is still valid */
|
||||
return (ENOENT);
|
||||
|
||||
xsnprintf(filter, sizeof(filter), AMD_LDAP_FILTER, map, key);
|
||||
/* "*" is special to ldap_search(); run through the filter escaping it. */
|
||||
f1 = filter; f2 = filter2;
|
||||
while (*f1) {
|
||||
if (*f1 == '*') {
|
||||
*f2++ = '\\'; *f2++ = '2'; *f2++ = 'a';
|
||||
f1++;
|
||||
} else {
|
||||
*f2++ = *f1++;
|
||||
}
|
||||
}
|
||||
*f2 = '\0';
|
||||
dlog("Search with filter: <%s>\n", filter2);
|
||||
for (i = 0; i < AMD_LDAP_RETRIES; i++) {
|
||||
err = ldap_search_st(a->ldap,
|
||||
gopt.ldap_base,
|
||||
LDAP_SCOPE_SUBTREE,
|
||||
filter2,
|
||||
0,
|
||||
0,
|
||||
&tv,
|
||||
&res);
|
||||
if (err == LDAP_SUCCESS)
|
||||
break;
|
||||
if (res) {
|
||||
ldap_msgfree(res);
|
||||
res = NULL;
|
||||
}
|
||||
plog(XLOG_USER, "LDAP search attempt %d failed: %s\n",
|
||||
i + 1, ldap_err2string(err));
|
||||
if (err != LDAP_TIMEOUT) {
|
||||
dlog("amu_ldap_search: unbinding...\n");
|
||||
amu_ldap_unbind(a->ldap);
|
||||
a->ldap = NULL;
|
||||
if (amu_ldap_rebind(a))
|
||||
return (ENOENT);
|
||||
}
|
||||
}
|
||||
|
||||
switch (err) {
|
||||
case LDAP_SUCCESS:
|
||||
break;
|
||||
case LDAP_NO_SUCH_OBJECT:
|
||||
dlog("No object\n");
|
||||
if (res)
|
||||
ldap_msgfree(res);
|
||||
return (ENOENT);
|
||||
default:
|
||||
plog(XLOG_USER, "LDAP search failed: %s\n",
|
||||
ldap_err2string(err));
|
||||
if (res)
|
||||
ldap_msgfree(res);
|
||||
return (EIO);
|
||||
}
|
||||
|
||||
nentries = ldap_count_entries(a->ldap, res);
|
||||
dlog("Search found %d entries\n", nentries);
|
||||
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);
|
||||
return (EIO);
|
||||
}
|
||||
dlog("Map %s, %s => %s\n", map, key, vals[0]);
|
||||
if (vals[0]) {
|
||||
if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX))
|
||||
*pval = sun_entry2amd(key, vals[0]);
|
||||
else
|
||||
*pval = xstrdup(vals[0]);
|
||||
err = 0;
|
||||
} else {
|
||||
plog(XLOG_USER, "Empty value for %s in map %s\n", key, map);
|
||||
err = ENOENT;
|
||||
}
|
||||
ldap_msgfree(res);
|
||||
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, map, ts)) {
|
||||
return (ENOENT);
|
||||
}
|
||||
return (0);
|
||||
}
|
@ -1,140 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/info_ndbm.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get info from NDBM map
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
#include <sun_map.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(mnt_map *m, 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) {
|
||||
if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX))
|
||||
*val = sun_entry2amd(key, v.dptr);
|
||||
else
|
||||
*val = xstrdup(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];
|
||||
|
||||
xstrlcpy(dbfilename, map, sizeof(dbfilename));
|
||||
xstrlcat(dbfilename, DBM_SUFFIX, sizeof(dbfilename));
|
||||
error = stat(dbfilename, &stb);
|
||||
#else /* not DBM_SUFFIX */
|
||||
error = fstat(dbm_pagfno(db), &stb);
|
||||
#endif /* not DBM_SUFFIX */
|
||||
if (!error && *tp < stb.st_mtime) {
|
||||
*tp = stb.st_mtime;
|
||||
error = -1;
|
||||
} else {
|
||||
error = search_ndbm(m, 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];
|
||||
|
||||
xstrlcpy(dbfilename, map, sizeof(dbfilename));
|
||||
xstrlcat(dbfilename, DBM_SUFFIX, sizeof(dbfilename));
|
||||
error = stat(dbfilename, &stb);
|
||||
#else /* not DBM_SUFFIX */
|
||||
error = fstat(dbm_pagfno(db), &stb);
|
||||
#endif /* not DBM_SUFFIX */
|
||||
if (error < 0)
|
||||
*tp = clocktime(NULL);
|
||||
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);
|
||||
}
|
@ -1,447 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/info_nis.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get info from NIS map
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
#include <sun_map.h>
|
||||
|
||||
|
||||
/*
|
||||
* NIS+ servers in NIS compat mode don't have yp_order()
|
||||
*
|
||||
* has_yp_order = 1 NIS server
|
||||
* = 0 NIS+ server
|
||||
* = -1 server is down
|
||||
*/
|
||||
static int has_yp_order = -1;
|
||||
|
||||
/* 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_isup(mnt_map *m, char *map);
|
||||
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 = xstrdup(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);
|
||||
|
||||
plog(XLOG_ERROR, "yp enumeration of %s: %s, status=%d, e=%d",
|
||||
ncdp->ncd_map, yperr_string(e), status, e);
|
||||
}
|
||||
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;
|
||||
|
||||
plog(XLOG_INFO, "NIS map %s reloading using yp_all", map);
|
||||
/*
|
||||
* 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;
|
||||
char *master;
|
||||
static int last_status = 1; /* assume up by default */
|
||||
|
||||
switch (has_yp_order) {
|
||||
case 1:
|
||||
/*
|
||||
* NIS server with yp_order
|
||||
*/
|
||||
error = yp_order(gopt.nis_domain, map, &order);
|
||||
if (error != 0) {
|
||||
plog(XLOG_ERROR,
|
||||
"nis_isup: error getting the order of map %s: %s",
|
||||
map, yperr_string(ypprot_err(error)));
|
||||
last_status = 0;
|
||||
return 0; /* NIS is down */
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
/*
|
||||
* NIS+ server without yp_order
|
||||
*/
|
||||
error = yp_master(gopt.nis_domain, map, &master);
|
||||
if (error != 0) {
|
||||
plog(XLOG_ERROR,
|
||||
"nis_isup: error getting the master of map %s: %s",
|
||||
map, yperr_string(ypprot_err(error)));
|
||||
last_status = 0;
|
||||
return 0; /* NIS+ is down */
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* server was down
|
||||
*/
|
||||
last_status = 0;
|
||||
}
|
||||
|
||||
if (last_status == 0) { /* reinitialize if was down before */
|
||||
time_t dummy;
|
||||
error = nis_init(m, map, &dummy);
|
||||
if (error)
|
||||
return 0; /* still down */
|
||||
plog(XLOG_INFO, "nis_isup: NIS came back up for map %s", map);
|
||||
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 **pval, time_t *tp)
|
||||
{
|
||||
int outlen;
|
||||
int res;
|
||||
YP_ORDER_OUTORDER_TYPE order;
|
||||
|
||||
/*
|
||||
* Make sure domain initialized
|
||||
*/
|
||||
if (!gopt.nis_domain) {
|
||||
int error = determine_nis_domain();
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
switch (has_yp_order) {
|
||||
case 1:
|
||||
/*
|
||||
* NIS server with 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;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* server was down
|
||||
*/
|
||||
if (nis_isup(m, map))
|
||||
return -1;
|
||||
return EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup key
|
||||
*/
|
||||
res = yp_match(gopt.nis_domain, map, key, strlen(key), pval, &outlen);
|
||||
if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX) && res == 0) {
|
||||
char *oldval = *pval;
|
||||
*pval = sun_entry2amd(key, oldval);
|
||||
/* We always need to free the output of the yp_match call. */
|
||||
XFREE(oldval);
|
||||
if (*pval == NULL)
|
||||
return -1; /* sun2amd parser error */
|
||||
}
|
||||
|
||||
/*
|
||||
* Do something interesting with the return code
|
||||
*/
|
||||
switch (res) {
|
||||
case 0:
|
||||
return 0;
|
||||
|
||||
case YPERR_KEY:
|
||||
return ENOENT;
|
||||
|
||||
default:
|
||||
plog(XLOG_ERROR, "nis_search: %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:
|
||||
/* NIS server found */
|
||||
has_yp_order = 1;
|
||||
*tp = (time_t) order;
|
||||
dlog("NIS master for %s@%s has order %lu", map, gopt.nis_domain, (unsigned long) order);
|
||||
break;
|
||||
case YPERR_YPERR:
|
||||
/* NIS+ server found ! */
|
||||
has_yp_order = 0;
|
||||
/* try yp_master() instead */
|
||||
if (yp_master(gopt.nis_domain, map, &master)) {
|
||||
return ENOENT;
|
||||
} else {
|
||||
dlog("NIS master for %s@%s is a NIS+ server", map, gopt.nis_domain);
|
||||
/* Use fake timestamps */
|
||||
*tp = time(NULL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* server is down */
|
||||
has_yp_order = -1;
|
||||
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 eventually 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;
|
||||
|
||||
/*
|
||||
* We have to manually free all char ** arguments to yp_first/yp_next
|
||||
* outval must be freed *before* calling yp_next again, outkey can be
|
||||
* freed as outkey_old *after* the call (this saves one call to
|
||||
* strnsave).
|
||||
*/
|
||||
XFREE(outval);
|
||||
outkey_old = outkey;
|
||||
outkeylen_old = outkeylen;
|
||||
i = yp_next(indomain,
|
||||
inmap,
|
||||
outkey_old,
|
||||
outkeylen_old,
|
||||
&outkey,
|
||||
&outkeylen,
|
||||
&outval,
|
||||
&outvallen);
|
||||
XFREE(outkey_old);
|
||||
} while (!i);
|
||||
if (i) {
|
||||
dlog("yp_next() returned error: %s\n", yperr_string(i));
|
||||
}
|
||||
if (i == YPERR_NOMORE)
|
||||
return 0;
|
||||
return i;
|
||||
}
|
||||
#endif /* HAVE_BAD_YP_ALL */
|
@ -1,309 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/info_nisplus.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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>
|
||||
#include <sun_map.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;
|
||||
|
||||
dlog("NISplus callback for <%s,%s>", kp, vp);
|
||||
|
||||
(*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;
|
||||
size_t l;
|
||||
|
||||
org = strstr(map, NISPLUS_ORGDIR);
|
||||
if (org == NULL)
|
||||
org = NISPLUS_ORGDIR;
|
||||
else
|
||||
org = "";
|
||||
|
||||
/* make some room for the NIS map_name */
|
||||
l = strlen(map) + sizeof(NISPLUS_ORGDIR);
|
||||
map_name = xmalloc(l);
|
||||
if (map_name == NULL) {
|
||||
plog(XLOG_ERROR, "Unable to create map_name %s: %s",
|
||||
map, strerror(ENOMEM));
|
||||
return ENOMEM;
|
||||
}
|
||||
xsnprintf(map_name, l, "%s%s", map, org);
|
||||
|
||||
data.ncd_m = m;
|
||||
data.ncd_map = map_name;
|
||||
data.ncd_fn = fn;
|
||||
|
||||
dlog("NISplus reload for %s", map);
|
||||
|
||||
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;
|
||||
|
||||
dlog("NISplus search callback for <%s>", ENTRY_VAL(value, 0));
|
||||
dlog("NISplus search callback value <%s>", ENTRY_VAL(value, 1));
|
||||
|
||||
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 */
|
||||
size_t l;
|
||||
|
||||
org = strstr(map, NISPLUS_ORGDIR);
|
||||
if (org == NULL)
|
||||
org = NISPLUS_ORGDIR;
|
||||
else
|
||||
org = "";
|
||||
|
||||
/* make some room for the NIS index */
|
||||
l = sizeof('[') /* for opening selection criteria */
|
||||
+ sizeof(NISPLUS_KEY)
|
||||
+ strlen(key)
|
||||
+ sizeof(']') /* for closing selection criteria */
|
||||
+ sizeof(',') /* + 1 for , separator */
|
||||
+ strlen(map)
|
||||
+ sizeof(NISPLUS_ORGDIR);
|
||||
index = xmalloc(l);
|
||||
if (index == NULL) {
|
||||
plog(XLOG_ERROR,
|
||||
"Unable to create index %s: %s",
|
||||
map,
|
||||
strerror(ENOMEM));
|
||||
return ENOMEM;
|
||||
}
|
||||
xsnprintf(index, l, "[%s%s],%s%s", NISPLUS_KEY, key, map, org);
|
||||
|
||||
data.key = key;
|
||||
data.value = NULL;
|
||||
|
||||
dlog("NISplus search for %s", index);
|
||||
|
||||
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, "nisplus_search: %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;
|
||||
dlog("NISplus search found <nothing>");
|
||||
dlog("NISplus search for %s: %s(%d)",
|
||||
map, nis_sperrno(result->status), result->status);
|
||||
|
||||
if (value != NULL)
|
||||
data.value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
|
||||
}
|
||||
|
||||
if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX)) {
|
||||
*val = sun_entry2amd(key, data.value);
|
||||
XFREE(data.value); /* strnsave malloc'ed it above */
|
||||
} else
|
||||
*val = data.value;
|
||||
|
||||
if (*val) {
|
||||
error = 0;
|
||||
dlog("NISplus search found %s", *val);
|
||||
} else {
|
||||
error = ENOENT;
|
||||
dlog("NISplus search found nothing");
|
||||
}
|
||||
|
||||
*tp = 0;
|
||||
break;
|
||||
|
||||
case NIS_NOSUCHNAME:
|
||||
dlog("NISplus search returned %d", result->status);
|
||||
error = ENOENT;
|
||||
break;
|
||||
|
||||
default:
|
||||
plog(XLOG_ERROR, "nisplus_search: %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;
|
||||
size_t l;
|
||||
|
||||
org = strstr(map, NISPLUS_ORGDIR);
|
||||
if (org == NULL)
|
||||
org = NISPLUS_ORGDIR;
|
||||
else
|
||||
org = "";
|
||||
|
||||
/* make some room for the NIS map_name */
|
||||
l = strlen(map) + sizeof(NISPLUS_ORGDIR);
|
||||
map_name = xmalloc(l);
|
||||
if (map_name == NULL) {
|
||||
plog(XLOG_ERROR,
|
||||
"Unable to create map_name %s: %s",
|
||||
map,
|
||||
strerror(ENOMEM));
|
||||
return ENOMEM;
|
||||
}
|
||||
xsnprintf(map_name, l, "%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) {
|
||||
dlog("NISplus init <%s>: %s (%d)",
|
||||
map, nis_sperrno(result->status), result->status);
|
||||
|
||||
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);
|
||||
}
|
@ -1,187 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/info_passwd.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 = NULL;
|
||||
struct passwd *pw;
|
||||
|
||||
if (STREQ(key, "/defaults")) {
|
||||
*pval = xstrdup("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 = xstrdup(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) {
|
||||
xstrlcat(rhost, q + 1, sizeof(rhost));
|
||||
xstrlcat(rhost, ".", sizeof(rhost));
|
||||
*q = '\0';
|
||||
} else {
|
||||
xstrlcat(rhost, p, sizeof(rhost));
|
||||
}
|
||||
} 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}";
|
||||
xsnprintf(val, sizeof(val), "var0:=%s;var1:=%s;var2:=%s;var3:=%s;%s",
|
||||
dir+1, rhost, user, pw->pw_dir, p);
|
||||
dlog("passwd_search: map=%s key=%s -> %s", map, key, val);
|
||||
if (q)
|
||||
*q = '.';
|
||||
*pval = xstrdup(val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
enoent:
|
||||
XFREE(dir);
|
||||
|
||||
return ENOENT;
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/info_sun.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get info from Sun automount-style /etc/auto_master, possibly following
|
||||
* into multiple info services (via /etc/nsswitch.conf).
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
#include <sun_map.h>
|
||||
|
||||
|
||||
/* XXX: just a placeholder. fill in */
|
@ -1,144 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/info_union.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 = xstrdup(map + UNION_PREFLEN);
|
||||
char **v = strsplit(mapd, ':', '\"');
|
||||
char **p;
|
||||
size_t l;
|
||||
|
||||
for (p = v; p[1]; p++) ;
|
||||
l = strlen(*p) + 5;
|
||||
*pval = xmalloc(l);
|
||||
xsnprintf(*pval, l, "fs:=%s", *p);
|
||||
XFREE(mapd);
|
||||
XFREE(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
|
||||
{
|
||||
static const char fseq[] = "fs:=";
|
||||
char *mapd = xstrdup(map + UNION_PREFLEN);
|
||||
char **v = strsplit(mapd, ':', '\"');
|
||||
char **dir;
|
||||
|
||||
/*
|
||||
* Add fake /defaults entry
|
||||
*/
|
||||
(*fn) (m, xstrdup("/defaults"), xstrdup("type:=link;opts:=nounmount;sublink:=${key}"));
|
||||
|
||||
for (dir = v; *dir; dir++) {
|
||||
size_t l;
|
||||
struct dirent *dp;
|
||||
|
||||
DIR *dirp = opendir(*dir);
|
||||
if (!dirp) {
|
||||
plog(XLOG_USER, "Cannot read directory %s: %m", *dir);
|
||||
continue;
|
||||
}
|
||||
l = strlen(*dir) + sizeof(fseq);
|
||||
|
||||
dlog("Reading directory %s...", *dir);
|
||||
while ((dp = readdir(dirp))) {
|
||||
char *val, *dpname = &dp->d_name[0];
|
||||
if (dpname[0] == '.' &&
|
||||
(dpname[1] == '\0' ||
|
||||
(dpname[1] == '.' && dpname[2] == '\0')))
|
||||
continue;
|
||||
|
||||
dlog("... gives %s", dp->d_name);
|
||||
val = xmalloc(l);
|
||||
xsnprintf(val, l, "%s%s", fseq, *dir);
|
||||
(*fn) (m, xstrdup(dp->d_name), val);
|
||||
}
|
||||
closedir(dirp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add wildcard entry
|
||||
*/
|
||||
{
|
||||
size_t l = strlen(*(dir-1)) + sizeof(fseq);
|
||||
char *val = xmalloc(l);
|
||||
|
||||
xsnprintf(val, l, "%s%s", fseq, *(dir-1));
|
||||
(*fn) (m, xstrdup("*"), val);
|
||||
}
|
||||
XFREE(mapd);
|
||||
XFREE(v);
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,410 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/mntfs.c
|
||||
*
|
||||
*/
|
||||
|
||||
#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;
|
||||
|
||||
|
||||
am_loc *
|
||||
dup_loc(am_loc *loc)
|
||||
{
|
||||
loc->al_refc++;
|
||||
if (loc->al_mnt) {
|
||||
dup_mntfs(loc->al_mnt);
|
||||
}
|
||||
return loc;
|
||||
}
|
||||
|
||||
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_fsflags = ops->nfs_fs_flags;
|
||||
mf->mf_fo = 0;
|
||||
if (mo)
|
||||
mf->mf_fo = copy_opts(mo);
|
||||
|
||||
mf->mf_mount = xstrdup(mp);
|
||||
mf->mf_info = xstrdup(info);
|
||||
mf->mf_auto = xstrdup(auto_opts);
|
||||
mf->mf_mopts = xstrdup(mopts);
|
||||
mf->mf_remopts = xstrdup(remopts);
|
||||
mf->mf_loopdev = NULL;
|
||||
mf->mf_refc = 1;
|
||||
mf->mf_flags = 0;
|
||||
mf->mf_error = -1;
|
||||
mf->mf_cid = 0;
|
||||
mf->mf_private = NULL;
|
||||
mf->mf_prfree = NULL;
|
||||
|
||||
if (ops->ffserver)
|
||||
mf->mf_server = (*ops->ffserver) (mf);
|
||||
else
|
||||
mf->mf_server = NULL;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* find a matching mntfs in our list */
|
||||
mntfs *
|
||||
locate_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)
|
||||
{
|
||||
mntfs *mf;
|
||||
|
||||
dlog("Locating mntfs reference to (%s,%s)", mp, info);
|
||||
|
||||
ITER(mf, mntfs, &mfhead) {
|
||||
/*
|
||||
* For backwards compatibility purposes, we treat already-mounted
|
||||
* filesystems differently and only require a match of their mount point,
|
||||
* not of their server info. After all, there is little we can do if
|
||||
* the user asks us to mount two different things onto the same mount: one
|
||||
* will always cover the other one.
|
||||
*/
|
||||
if (STREQ(mf->mf_mount, mp) &&
|
||||
((mf->mf_flags & MFF_MOUNTED && !(mf->mf_fsflags & FS_DIRECT))
|
||||
|| (STREQ(mf->mf_info, info) && mf->mf_ops == ops))) {
|
||||
/*
|
||||
* Handle cases where error ops are involved
|
||||
*/
|
||||
if (ops == &amfs_error_ops) {
|
||||
/*
|
||||
* If the existing ops are not amfs_error_ops
|
||||
* then continue...
|
||||
*/
|
||||
if (mf->mf_ops != &amfs_error_ops)
|
||||
continue;
|
||||
return dup_mntfs(mf);
|
||||
}
|
||||
|
||||
dlog("mf->mf_flags = %#x", mf->mf_flags);
|
||||
|
||||
if ((mf->mf_flags & MFF_RESTART) && amd_state < Finishing) {
|
||||
/*
|
||||
* Restart a previously mounted filesystem.
|
||||
*/
|
||||
dlog("Restarting filesystem %s", mf->mf_mount);
|
||||
|
||||
/*
|
||||
* If we are restarting an amd internal filesystem,
|
||||
* we need to initialize it a bit.
|
||||
*
|
||||
* We know it's internal because it is marked as toplvl.
|
||||
*/
|
||||
if (mf->mf_ops == &amfs_toplvl_ops) {
|
||||
mf->mf_ops = ops;
|
||||
mf->mf_info = strealloc(mf->mf_info, info);
|
||||
ops->mounted(mf); /* XXX: not right, but will do for now */
|
||||
}
|
||||
|
||||
return mf;
|
||||
}
|
||||
|
||||
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 = NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
} /* end of "if (STREQ(mf-> ..." */
|
||||
} /* end of ITER */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* find a matching mntfs in our list, create a new one if none is found */
|
||||
mntfs *
|
||||
find_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)
|
||||
{
|
||||
mntfs *mf = locate_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
|
||||
if (mf)
|
||||
return mf;
|
||||
|
||||
return alloc_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
|
||||
}
|
||||
|
||||
|
||||
mntfs *
|
||||
new_mntfs(void)
|
||||
{
|
||||
return alloc_mntfs(&amfs_error_ops, (am_opts *) NULL, "//nil//", ".", "", "", "");
|
||||
}
|
||||
|
||||
am_loc *
|
||||
new_loc(void)
|
||||
{
|
||||
am_loc *loc = CALLOC(struct am_loc);
|
||||
loc->al_fo = 0;
|
||||
loc->al_mnt = new_mntfs();
|
||||
loc->al_refc = 1;
|
||||
return loc;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
uninit_mntfs(mntfs *mf)
|
||||
{
|
||||
if (mf->mf_fo) {
|
||||
free_opts(mf->mf_fo);
|
||||
XFREE(mf->mf_fo);
|
||||
}
|
||||
XFREE(mf->mf_auto);
|
||||
XFREE(mf->mf_mopts);
|
||||
XFREE(mf->mf_remopts);
|
||||
XFREE(mf->mf_info);
|
||||
if (mf->mf_private && mf->mf_prfree)
|
||||
(*mf->mf_prfree) (mf->mf_private);
|
||||
|
||||
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);
|
||||
XFREE(mf);
|
||||
|
||||
--mntfs_allocated;
|
||||
}
|
||||
|
||||
static void
|
||||
discard_loc(voidp v)
|
||||
{
|
||||
am_loc *loc = v;
|
||||
if (loc->al_fo) {
|
||||
free_opts(loc->al_fo);
|
||||
XFREE(loc->al_fo);
|
||||
}
|
||||
XFREE(loc);
|
||||
}
|
||||
|
||||
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_loc(opaque_t arg)
|
||||
{
|
||||
am_loc *loc = (am_loc *) arg;
|
||||
dlog("free_loc %p", loc);
|
||||
|
||||
if (loc->al_refc <= 0) {
|
||||
plog(XLOG_ERROR, "IGNORING free_loc for 0x%p", loc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (loc->al_mnt)
|
||||
free_mntfs(loc->al_mnt);
|
||||
if (--loc->al_refc == 0) {
|
||||
discard_loc(loc);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
free_mntfs(opaque_t arg)
|
||||
{
|
||||
mntfs *mf = (mntfs *) arg;
|
||||
|
||||
dlog("free_mntfs <%s> type %s mf_refc %d flags %x",
|
||||
mf->mf_mount, mf->mf_ops->fs_type, mf->mf_refc, mf->mf_flags);
|
||||
|
||||
/*
|
||||
* We shouldn't ever be called to free something that has
|
||||
* a non-positive refcount. Something is badly wrong if
|
||||
* we have been! Ignore the request for now...
|
||||
*/
|
||||
if (mf->mf_refc <= 0) {
|
||||
plog(XLOG_ERROR, "IGNORING free_mntfs for <%s>: refc %d, flags %x (bug?)",
|
||||
mf->mf_mount, mf->mf_refc, mf->mf_flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/* don't discard last reference of a restarted/kept mntfs */
|
||||
if (mf->mf_refc == 1 && mf->mf_flags & MFF_RSTKEEP) {
|
||||
plog(XLOG_ERROR, "IGNORING free_mntfs for <%s>: refc %d, flags %x (restarted)",
|
||||
mf->mf_mount, mf->mf_refc, mf->mf_flags);
|
||||
return;
|
||||
}
|
||||
|
||||
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_fsflags & FS_DISCARD) {
|
||||
dlog("Immediately discarding mntfs for %s", mf->mf_mount);
|
||||
discard_mntfs(mf);
|
||||
|
||||
} else {
|
||||
|
||||
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);
|
||||
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_flags & MFF_RESTART &&
|
||||
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)) {
|
||||
return mf;
|
||||
}
|
||||
|
||||
mf2 = find_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
|
||||
free_mntfs(mf);
|
||||
return mf2;
|
||||
}
|
@ -1,488 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/nfs_prot_svc.c
|
||||
*
|
||||
*/
|
||||
|
||||
#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 *current_transp;
|
||||
dispatcher_t nfs_dispatcher = nfs_program_2;
|
||||
|
||||
/* 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;
|
||||
|
||||
#ifdef HAVE_TRANSPORT_TYPE_TLI
|
||||
/*
|
||||
* On TLI systems we don't use an INET network type, but a "ticlts" (see
|
||||
* /etc/netconfig and conf/transp_tli.c:create_nfs_service). This means
|
||||
* that packets could only come from the loopback interface, and we don't
|
||||
* need to check them and filter possibly spoofed packets. Therefore we
|
||||
* only need to check if the UID caller is correct.
|
||||
*/
|
||||
# ifdef HAVE___RPC_GET_LOCAL_UID
|
||||
uid_t u;
|
||||
/* extern definition for an internal libnsl function */
|
||||
extern int __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid);
|
||||
if (__rpc_get_local_uid(transp, &u) >= 0 && u != 0) {
|
||||
plog(XLOG_WARNING, "ignoring request from UID %ld, must be 0", (long) u);
|
||||
return;
|
||||
}
|
||||
# else /* not HAVE___RPC_GET_LOCAL_UID */
|
||||
dlog("cannot verify local uid for rpc request");
|
||||
# endif /* HAVE___RPC_GET_LOCAL_UID */
|
||||
#else /* not HAVE_TRANPORT_TYPE_TLI */
|
||||
struct sockaddr_in *sinp;
|
||||
char dq[20], dq2[28];
|
||||
sinp = amu_svc_getcaller(rqstp->rq_xprt);
|
||||
# ifdef MNT2_NFS_OPT_RESVPORT
|
||||
/* Verify that the request comes from a reserved port */
|
||||
if (sinp &&
|
||||
ntohs(sinp->sin_port) >= IPPORT_RESERVED &&
|
||||
!(gopt.flags & CFM_NFS_INSECURE_PORT)) {
|
||||
plog(XLOG_WARNING, "ignoring request from %s:%u, port not reserved",
|
||||
inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
|
||||
ntohs(sinp->sin_port));
|
||||
return;
|
||||
}
|
||||
# endif /* MNT2_NFS_OPT_RESVPORT */
|
||||
/* if the address does not match, ignore the request */
|
||||
if (sinp && (sinp->sin_addr.s_addr != myipaddr.s_addr)) {
|
||||
if (gopt.flags & CFM_NFS_ANY_INTERFACE) {
|
||||
if (!is_interface_local(sinp->sin_addr.s_addr)) {
|
||||
plog(XLOG_WARNING, "ignoring request from %s:%u, not a local interface",
|
||||
inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
|
||||
ntohs(sinp->sin_port));
|
||||
}
|
||||
} else {
|
||||
plog(XLOG_WARNING, "ignoring request from %s:%u, expected %s",
|
||||
inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
|
||||
ntohs(sinp->sin_port),
|
||||
inet_dquad(dq2, sizeof(dq2), myipaddr.s_addr));
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* not HAVE_TRANPORT_TYPE_TLI */
|
||||
|
||||
current_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().
|
||||
*/
|
||||
current_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",
|
||||
(int) rqstp->rq_prog, (int) rqstp->rq_vers, (int) rqstp->rq_proc);
|
||||
svcerr_decode(transp);
|
||||
return;
|
||||
}
|
||||
result = (*local) (&argument, rqstp);
|
||||
|
||||
current_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);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nfs_program_3(struct svc_req *rqstp, register SVCXPRT *transp)
|
||||
{
|
||||
union {
|
||||
am_GETATTR3args am_nfs3_getattr_3_arg;
|
||||
am_SETATTR3args am_nfs3_setattr_3_arg;
|
||||
am_LOOKUP3args am_nfs3_lookup_3_arg;
|
||||
am_ACCESS3args am_nfs3_access_3_arg;
|
||||
am_READLINK3args am_nfs3_readlink_3_arg;
|
||||
am_READ3args am_nfs3_read_3_arg;
|
||||
am_WRITE3args am_nfs3_write_3_arg;
|
||||
am_CREATE3args am_nfs3_create_3_arg;
|
||||
am_MKDIR3args am_nfs3_mkdir_3_arg;
|
||||
am_SYMLINK3args am_nfs3_symlink_3_arg;
|
||||
am_MKNOD3args am_nfs3_mknod_3_arg;
|
||||
am_REMOVE3args am_nfs3_remove_3_arg;
|
||||
am_RMDIR3args am_nfs3_rmdir_3_arg;
|
||||
am_RENAME3args am_nfs3_rename_3_arg;
|
||||
am_LINK3args am_nfs3_link_3_arg;
|
||||
am_READDIR3args am_nfs3_readdir_3_arg;
|
||||
am_READDIRPLUS3args am_nfs3_readdirplus_3_arg;
|
||||
am_FSSTAT3args am_nfs3_fsstat_3_arg;
|
||||
am_FSINFO3args am_nfs3_fsinfo_3_arg;
|
||||
am_PATHCONF3args am_nfs3_pathconf_3_arg;
|
||||
am_COMMIT3args am_nfs3_commit_3_arg;
|
||||
} argument;
|
||||
char *result;
|
||||
xdrproc_t _xdr_argument, _xdr_result;
|
||||
nfssvcproc_t local;
|
||||
|
||||
switch (rqstp->rq_proc) {
|
||||
case AM_NFS3_NULL:
|
||||
_xdr_argument = (xdrproc_t) xdr_void;
|
||||
_xdr_result = (xdrproc_t) xdr_void;
|
||||
local = (nfssvcproc_t) am_nfs3_null_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_GETATTR:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_GETATTR3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_GETATTR3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_getattr_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_SETATTR:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_SETATTR3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_SETATTR3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_setattr_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_LOOKUP:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_LOOKUP3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_LOOKUP3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_lookup_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_ACCESS:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_ACCESS3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_ACCESS3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_access_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_READLINK:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_READLINK3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_READLINK3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_readlink_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_READ:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_READ3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_READ3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_read_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_WRITE:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_WRITE3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_WRITE3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_write_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_CREATE:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_CREATE3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_CREATE3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_create_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_MKDIR:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_MKDIR3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_MKDIR3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_mkdir_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_SYMLINK:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_SYMLINK3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_SYMLINK3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_symlink_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_MKNOD:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_MKNOD3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_MKNOD3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_mknod_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_REMOVE:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_REMOVE3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_REMOVE3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_remove_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_RMDIR:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_RMDIR3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_RMDIR3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_rmdir_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_RENAME:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_RENAME3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_RENAME3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_rename_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_LINK:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_LINK3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_LINK3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_link_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_READDIR:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_READDIR3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_READDIR3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_readdir_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_READDIRPLUS:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_READDIRPLUS3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_READDIRPLUS3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_readdirplus_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_FSSTAT:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_FSSTAT3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_FSSTAT3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_fsstat_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_FSINFO:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_FSINFO3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_FSINFO3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_fsinfo_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_PATHCONF:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_PATHCONF3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_PATHCONF3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_pathconf_3_svc;
|
||||
break;
|
||||
|
||||
case AM_NFS3_COMMIT:
|
||||
_xdr_argument = (xdrproc_t) xdr_am_COMMIT3args;
|
||||
_xdr_result = (xdrproc_t) xdr_am_COMMIT3res;
|
||||
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_commit_3_svc;
|
||||
break;
|
||||
|
||||
default:
|
||||
svcerr_noproc (transp);
|
||||
return;
|
||||
}
|
||||
|
||||
memset ((char *)&argument, 0, sizeof (argument));
|
||||
|
||||
if (!svc_getargs(transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
|
||||
plog(XLOG_ERROR,
|
||||
"NFS xdr decode failed for %d %d %d",
|
||||
(int) rqstp->rq_prog, (int) rqstp->rq_vers, (int) rqstp->rq_proc);
|
||||
svcerr_decode(transp);
|
||||
return;
|
||||
}
|
||||
|
||||
result = (*local) (&argument, rqstp);
|
||||
if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) {
|
||||
svcerr_systemerr (transp);
|
||||
}
|
||||
|
||||
if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
|
||||
plog(XLOG_FATAL, "unable to free rpc arguments in nfs_program_3");
|
||||
going_down(1);
|
||||
}
|
||||
return;
|
||||
}
|
@ -1,457 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/nfs_start.c
|
||||
*
|
||||
*/
|
||||
|
||||
#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 = NULL;
|
||||
u_short nfs_port = 0;
|
||||
|
||||
#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 = NULL;
|
||||
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("%#lx bytes of memory allocated; total is %#lx (%ld pages)",
|
||||
(long) (next_mem - max_mem), (unsigned long) next_mem,
|
||||
((long) next_mem + getpagesize() - 1) / (long) getpagesize());
|
||||
#else /* not HAVE_GETPAGESIZE */
|
||||
dlog("%#lx bytes of memory allocated; total is %#lx",
|
||||
(long) (next_mem - max_mem), (unsigned long) next_mem);
|
||||
#endif /* not HAVE_GETPAGESIZE */
|
||||
max_mem = next_mem;
|
||||
|
||||
}
|
||||
}
|
||||
#else /* not DEBUG */
|
||||
#define checkup()
|
||||
#endif /* not 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;
|
||||
/*
|
||||
* 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 *) NULL, (fd_set *) NULL,
|
||||
tvp->tv_sec ? tvp : (struct timeval *) NULL);
|
||||
}
|
||||
|
||||
#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(NULL)) {
|
||||
mapc_reload();
|
||||
do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval;
|
||||
}
|
||||
return nsel;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Determine whether anything is left in
|
||||
* the RPC input queue.
|
||||
*/
|
||||
static int
|
||||
rpc_pending_now(void)
|
||||
{
|
||||
struct timeval tvv;
|
||||
int nsel;
|
||||
fd_set readfds;
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(fwd_sock, &readfds);
|
||||
|
||||
tvv.tv_sec = tvv.tv_usec = 0;
|
||||
nsel = select(FD_SETSIZE, &readfds, (fd_set *) NULL, (fd_set *) NULL, &tvv);
|
||||
if (nsel < 1)
|
||||
return (0);
|
||||
if (FD_ISSET(fwd_sock, &readfds))
|
||||
return (1);
|
||||
|
||||
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(NULL);
|
||||
|
||||
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;
|
||||
fd_set readfds;
|
||||
|
||||
#ifdef HAVE_SVC_GETREQSET
|
||||
memmove(&readfds, &svc_fdset, sizeof(svc_fdset));
|
||||
#else /* not HAVE_SVC_GETREQSET */
|
||||
FD_ZERO(&readfds);
|
||||
# ifdef HAVE_FD_SET_FDS_BITS
|
||||
readfds.fds_bits[0] = svc_fds;
|
||||
# else /* not HAVE_FD_SET_FDS_BITS */
|
||||
readfds = svc_fds;
|
||||
# endif /* not HAVE_FD_SET_FDS_BITS */
|
||||
#endif /* not HAVE_SVC_GETREQSET */
|
||||
FD_SET(fwd_sock, &readfds);
|
||||
|
||||
checkup();
|
||||
|
||||
/*
|
||||
* If the full timeout code is not called,
|
||||
* then recompute the time delta manually.
|
||||
*/
|
||||
now = clocktime(NULL);
|
||||
|
||||
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 && get_exported_ap(0) == NULL) {
|
||||
flush_mntfs();
|
||||
amd_state = Quit;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
autofs_add_fdset(&readfds);
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
if (tvv.tv_sec <= 0)
|
||||
tvv.tv_sec = SELECT_MAXWAIT;
|
||||
if (tvv.tv_sec) {
|
||||
dlog("Select waits for %ds", (int) tvv.tv_sec);
|
||||
} else {
|
||||
dlog("Select waits for Godot");
|
||||
}
|
||||
|
||||
nsel = do_select(smask, FD_SETSIZE, &readfds, &tvv);
|
||||
|
||||
switch (nsel) {
|
||||
case -1:
|
||||
if (errno == EINTR) {
|
||||
dlog("select interrupted");
|
||||
continue;
|
||||
}
|
||||
plog(XLOG_ERROR, "select: %m");
|
||||
break;
|
||||
|
||||
case 0:
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* Read all pending NFS responses at once to avoid having responses
|
||||
* queue up as a consequence of retransmissions.
|
||||
*/
|
||||
if (FD_ISSET(fwd_sock, &readfds)) {
|
||||
FD_CLR(fwd_sock, &readfds);
|
||||
--nsel;
|
||||
do {
|
||||
fwd_reply();
|
||||
} while (rpc_pending_now() > 0);
|
||||
}
|
||||
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (nsel)
|
||||
nsel = autofs_handle_fdset(&readfds, nsel);
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
if (nsel) {
|
||||
/*
|
||||
* Anything left must be a normal
|
||||
* RPC request.
|
||||
*/
|
||||
#ifdef HAVE_SVC_GETREQSET
|
||||
svc_getreqset(&readfds);
|
||||
#else /* not HAVE_SVC_GETREQSET */
|
||||
# ifdef HAVE_FD_SET_FDS_BITS
|
||||
svc_getreq(readfds.fds_bits[0]);
|
||||
# else /* not HAVE_FD_SET_FDS_BITS */
|
||||
svc_getreq(readfds);
|
||||
# endif /* not HAVE_FD_SET_FDS_BITS */
|
||||
#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;
|
||||
struct netconfig *udp_amqncp, *tcp_amqncp;
|
||||
|
||||
/*
|
||||
* This must be done first, because it attempts to bind
|
||||
* to various UDP ports and we don't want anything else
|
||||
* potentially taking over those ports before we get a chance
|
||||
* to reserve them.
|
||||
*/
|
||||
if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS)
|
||||
restart_automounter_nodes();
|
||||
|
||||
/*
|
||||
* 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();
|
||||
|
||||
/*
|
||||
* Create the nfs service for amd
|
||||
* If nfs_port is already initialized, it means we
|
||||
* already created the service during restart_automounter_nodes().
|
||||
*/
|
||||
if (nfs_port == 0) {
|
||||
ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_dispatcher,
|
||||
get_nfs_dispatcher_version(nfs_dispatcher));
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
xsnprintf(pid_fsname, sizeof(pid_fsname), "%s:(pid%ld,port%u)",
|
||||
am_get_hostname(), (long) am_mypid, nfs_port);
|
||||
|
||||
/* security: if user sets -D noamq, don't even create listening socket */
|
||||
if (amuDebug(D_AMQ)) {
|
||||
ret = create_amq_service(&udp_soAMQ,
|
||||
&udp_amqp,
|
||||
&udp_amqncp,
|
||||
&tcp_soAMQ,
|
||||
&tcp_amqp,
|
||||
&tcp_amqncp,
|
||||
gopt.preferred_amq_port);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (amd_use_autofs) {
|
||||
/*
|
||||
* Create the autofs service for amd.
|
||||
*/
|
||||
ret = create_autofs_service();
|
||||
/* if autofs service fails it is OK if using a test amd */
|
||||
if (ret != 0) {
|
||||
plog(XLOG_WARNING, "autofs service registration failed, turning off autofs support");
|
||||
amd_use_autofs = 0;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
/*
|
||||
* Mount the top-level auto-mountpoints
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
if (amuDebug(D_AMQ)) {
|
||||
/*
|
||||
* Complete registration of amq (first TCP service then UDP)
|
||||
*/
|
||||
int tcp_ok = 0, udp_ok = 0;
|
||||
|
||||
unregister_amq(); /* unregister leftover Amd, if any, just in case */
|
||||
|
||||
tcp_ok = amu_svc_register(tcp_amqp, get_amd_program_number(), AMQ_VERSION,
|
||||
amq_program_1, IPPROTO_TCP, tcp_amqncp);
|
||||
if (!tcp_ok)
|
||||
plog(XLOG_FATAL,
|
||||
"unable to register (AMQ_PROGRAM=%lu, AMQ_VERSION, tcp)",
|
||||
get_amd_program_number());
|
||||
|
||||
udp_ok = amu_svc_register(udp_amqp, get_amd_program_number(), AMQ_VERSION,
|
||||
amq_program_1, IPPROTO_UDP, udp_amqncp);
|
||||
if (!udp_ok)
|
||||
plog(XLOG_FATAL,
|
||||
"unable to register (AMQ_PROGRAM=%lu, AMQ_VERSION, udp)",
|
||||
get_amd_program_number());
|
||||
|
||||
/* return error only if both failed */
|
||||
if (!tcp_ok && !udp_ok) {
|
||||
amd_state = Done;
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,301 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_TEMPLATE.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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, mntfs *mf);
|
||||
static int foofs_umount(am_node *mp, mntfs *mf);
|
||||
static am_node *foofs_lookuppn(am_node *mp, char *fname, int *error_return, int op);
|
||||
static int foofs_readdir(am_node *mp, void cookie, voidp dp, voidp ep, u_int count);
|
||||
static am_node *foofs_readlink(am_node *mp, int *error_return);
|
||||
static void foofs_mounted(am_node *am, mntfs *mf);
|
||||
static void foofs_umounted(am_node *mp, mntfs *mf);
|
||||
static 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_umount, /* unmount vnode */
|
||||
foofs_lookup_child, /* lookup path-name */
|
||||
foofs_mount_child, /* mount path-name */
|
||||
foofs_readdir, /* read directory */
|
||||
foofs_readlink, /* read link */
|
||||
foofs_mounted, /* after-mount extra actions */
|
||||
foofs_umounted, /* after-umount extra actions */
|
||||
foofs_ffserver, /* find a file server */
|
||||
foofs_get_wchan, /* return the waiting channel */
|
||||
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_TEMPLATE_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 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, void cookie, voidp dp, voidp ep, u_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.
|
||||
*/
|
||||
static fserver *
|
||||
foofs_ffserver(mntfs *mf)
|
||||
{
|
||||
plog(XLOG_INFO, "entering foofs_ffserver...");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Normally just return mf. Only inherit needs to do special tricks.
|
||||
*/
|
||||
static wchan_t *
|
||||
foofs_get_wchan(mntfs *mf)
|
||||
{
|
||||
plog(XLOG_INFO, "entering foofs_get_wchan...");
|
||||
|
||||
return mf;
|
||||
}
|
@ -1,256 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_cachefs.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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_mount(am_node *am, mntfs *mf);
|
||||
static int cachefs_umount(am_node *am, mntfs *mf);
|
||||
|
||||
|
||||
/*
|
||||
* Ops structure
|
||||
*/
|
||||
am_ops cachefs_ops =
|
||||
{
|
||||
"cachefs",
|
||||
cachefs_match,
|
||||
cachefs_init,
|
||||
cachefs_mount,
|
||||
cachefs_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* cachefs_readlink */
|
||||
0, /* cachefs_mounted */
|
||||
0, /* cachefs_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* cachefs_get_wchan */
|
||||
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_CACHEFS_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
dlog("CACHEFS: using cache directory \"%s\"", fo->opt_cachedir);
|
||||
|
||||
/* determine magic cookie to put in mtab */
|
||||
return xstrdup(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_private) {
|
||||
mf->mf_private = (voidp) xstrdup(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 *mntdir, char *backdir, char *cachedir,
|
||||
char *opts, int on_autofs)
|
||||
{
|
||||
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 = mntdir;
|
||||
mnt.mnt_fsname = backdir;
|
||||
mnt.mnt_type = MNTTAB_TYPE_CACHEFS;
|
||||
mnt.mnt_opts = opts;
|
||||
|
||||
flags = compute_mount_flags(&mnt);
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (on_autofs)
|
||||
flags |= autofs_compute_mount_flags(&mnt);
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
/* Fill in cachefs mount arguments */
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* sizeof(cfs_cacheid) should be C_MAX_MOUNT_FSCDIRNAME as per
|
||||
* <sys/fs/cachefs_fs.h> (checked on Solaris 8).
|
||||
*/
|
||||
xsnprintf(ca.cfs_cacheid, sizeof(ca.cfs_cacheid),
|
||||
"%s:%s", ca.cfs_fsid, mntdir);
|
||||
/* convert '/' to '_' (Solaris does that...) */
|
||||
cp = ca.cfs_cacheid;
|
||||
while ((cp = strpbrk(cp, "/")) != NULL)
|
||||
*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, on_autofs);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cachefs_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
|
||||
int error;
|
||||
|
||||
error = mount_cachefs(mf->mf_mount,
|
||||
mf->mf_fo->opt_rfs,
|
||||
mf->mf_fo->opt_cachedir,
|
||||
mf->mf_mopts,
|
||||
on_autofs);
|
||||
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_umount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
|
||||
int error;
|
||||
|
||||
error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
xsnprintf(cmd, sizeof(cmd), "fsck -F cachefs %s", cachedir);
|
||||
system(cmd);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
@ -1,241 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_cdfs.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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_mount(am_node *am, mntfs *mf);
|
||||
static int cdfs_umount(am_node *am, mntfs *mf);
|
||||
|
||||
/*
|
||||
* Ops structure
|
||||
*/
|
||||
am_ops cdfs_ops =
|
||||
{
|
||||
"cdfs",
|
||||
cdfs_match,
|
||||
0, /* cdfs_init */
|
||||
cdfs_mount,
|
||||
cdfs_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* cdfs_readlink */
|
||||
0, /* cdfs_mounted */
|
||||
0, /* cdfs_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* cdfs_get_wchan */
|
||||
FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_CDFS_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
dlog("CDFS: mounting device \"%s\" on \"%s\"",
|
||||
fo->opt_dev, fo->opt_fs);
|
||||
|
||||
/*
|
||||
* Determine magic cookie to put in mtab
|
||||
*/
|
||||
return xstrdup(fo->opt_dev);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
mount_cdfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
|
||||
{
|
||||
cdfs_args_t cdfs_args;
|
||||
mntent_t mnt;
|
||||
int genflags, cdfs_flags, retval;
|
||||
|
||||
/*
|
||||
* 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 = mntdir;
|
||||
mnt.mnt_fsname = fs_name;
|
||||
mnt.mnt_type = MNTTAB_TYPE_CDFS;
|
||||
mnt.mnt_opts = opts;
|
||||
|
||||
#if defined(MNT2_CDFS_OPT_DEFPERM) && defined(MNTTAB_OPT_DEFPERM)
|
||||
if (amu_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 (amu_hasmntopt(&mnt, MNTTAB_OPT_NODEFPERM))
|
||||
cdfs_flags |= MNT2_CDFS_OPT_NODEFPERM;
|
||||
#endif /* MNTTAB_OPT_NODEFPERM */
|
||||
|
||||
#if defined(MNT2_CDFS_OPT_NOVERSION) && defined(MNTTAB_OPT_NOVERSION)
|
||||
if (amu_hasmntopt(&mnt, MNTTAB_OPT_NOVERSION))
|
||||
cdfs_flags |= MNT2_CDFS_OPT_NOVERSION;
|
||||
#endif /* defined(MNT2_CDFS_OPT_NOVERSION) && defined(MNTTAB_OPT_NOVERSION) */
|
||||
|
||||
#if defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP)
|
||||
if (amu_hasmntopt(&mnt, MNTTAB_OPT_RRIP))
|
||||
cdfs_flags |= MNT2_CDFS_OPT_RRIP;
|
||||
#endif /* defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP) */
|
||||
|
||||
#if defined(MNT2_CDFS_OPT_NORRIP) && defined(MNTTAB_OPT_NORRIP)
|
||||
if (amu_hasmntopt(&mnt, MNTTAB_OPT_NORRIP))
|
||||
cdfs_flags |= MNT2_CDFS_OPT_NORRIP;
|
||||
#endif /* defined(MNT2_CDFS_OPT_NORRIP) && defined(MNTTAB_OPT_NORRIP) */
|
||||
|
||||
#if defined(MNT2_CDFS_OPT_GENS) && defined(MNTTAB_OPT_GENS)
|
||||
if (amu_hasmntopt(&mnt, MNTTAB_OPT_GENS))
|
||||
cdfs_flags |= MNT2_CDFS_OPT_GENS;
|
||||
#endif /* defined(MNT2_CDFS_OPT_GENS) && defined(MNTTAB_OPT_GENS) */
|
||||
|
||||
#if defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT)
|
||||
if (amu_hasmntopt(&mnt, MNTTAB_OPT_EXTATT))
|
||||
cdfs_flags |= MNT2_CDFS_OPT_EXTATT;
|
||||
#endif /* defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT) */
|
||||
|
||||
#if defined(MNT2_CDFS_OPT_NOCASETRANS) && defined(MNTTAB_OPT_NOCASETRANS)
|
||||
if (amu_hasmntopt(&mnt, MNTTAB_OPT_NOCASETRANS))
|
||||
cdfs_flags |= MNT2_CDFS_OPT_NOCASETRANS;
|
||||
#endif /* defined(MNT2_CDFS_OPT_NOCASETRANS) && defined(MNTTAB_OPT_NOCASETRANS) */
|
||||
|
||||
#if defined(MNT2_CDFS_OPT_NOJOLIET) && defined(MNTTAB_OPT_NOJOLIET)
|
||||
if (amu_hasmntopt(&mnt, MNTTAB_OPT_NOJOLIET))
|
||||
cdfs_flags |= MNT2_CDFS_OPT_NOJOLIET;
|
||||
#endif /* defined(MNT2_CDFS_OPT_NOJOLIET) && defined(MNTTAB_OPT_NOJOLIET) */
|
||||
|
||||
#if defined(MNT2_CDFS_OPT_RRCASEINS) && defined(MNTTAB_OPT_RRCASEINS)
|
||||
if (amu_hasmntopt(&mnt, MNTTAB_OPT_RRCASEINS))
|
||||
cdfs_flags |= MNT2_CDFS_OPT_RRCASEINS;
|
||||
#endif /* defined(MNT2_CDFS_OPT_RRCASEINS) && defined(MNTTAB_OPT_RRCASEINS) */
|
||||
|
||||
genflags = compute_mount_flags(&mnt);
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (on_autofs)
|
||||
genflags |= autofs_compute_mount_flags(&mnt);
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
#ifdef HAVE_CDFS_ARGS_T_FLAGS
|
||||
cdfs_args.flags = cdfs_flags;
|
||||
#endif /* HAVE_CDFS_ARGS_T_FLAGS */
|
||||
|
||||
#ifdef HAVE_CDFS_ARGS_T_ISO_FLAGS
|
||||
cdfs_args.iso_flags = genflags | cdfs_flags;
|
||||
#endif /* HAVE_CDFS_ARGS_T_ISO_FLAGS */
|
||||
|
||||
#ifdef HAVE_CDFS_ARGS_T_ISO_PGTHRESH
|
||||
cdfs_args.iso_pgthresh = hasmntval(&mnt, MNTTAB_OPT_PGTHRESH);
|
||||
#endif /* HAVE_CDFS_ARGS_T_ISO_PGTHRESH */
|
||||
|
||||
#ifdef HAVE_CDFS_ARGS_T_NORRIP
|
||||
/* XXX: need to provide norrip mount opt */
|
||||
cdfs_args.norrip = 0; /* use Rock-Ridge Protocol extensions */
|
||||
#endif /* HAVE_CDFS_ARGS_T_NORRIP */
|
||||
|
||||
#ifdef HAVE_CDFS_ARGS_T_SSECTOR
|
||||
/* XXX: need to provide ssector mount option */
|
||||
cdfs_args.ssector = 0; /* use 1st session on disk */
|
||||
#endif /* HAVE_CDFS_ARGS_T_SSECTOR */
|
||||
|
||||
#ifdef HAVE_CDFS_ARGS_T_FSPEC
|
||||
cdfs_args.fspec = fs_name;
|
||||
#endif /* HAVE_CDFS_ARGS_T_FSPEC */
|
||||
|
||||
/*
|
||||
* Call generic mount routine
|
||||
*/
|
||||
retval = mount_fs(&mnt, genflags, (caddr_t) &cdfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cdfs_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
|
||||
int error;
|
||||
|
||||
error = mount_cdfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
|
||||
if (error) {
|
||||
errno = error;
|
||||
plog(XLOG_ERROR, "mount_cdfs: %m");
|
||||
return error;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cdfs_umount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
|
||||
|
||||
return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
|
||||
}
|
@ -1,171 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_efs.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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_mount(am_node *am, mntfs *mf);
|
||||
static int efs_umount(am_node *am, mntfs *mf);
|
||||
|
||||
/*
|
||||
* Ops structure
|
||||
*/
|
||||
am_ops efs_ops =
|
||||
{
|
||||
"efs",
|
||||
efs_match,
|
||||
0, /* efs_init */
|
||||
efs_mount,
|
||||
efs_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* efs_readlink */
|
||||
0, /* efs_mounted */
|
||||
0, /* efs_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* efs_get_wchan */
|
||||
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_EFS_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
dlog("EFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
|
||||
|
||||
/*
|
||||
* Determine magic cookie to put in mtab
|
||||
*/
|
||||
return xstrdup(fo->opt_dev);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
mount_efs(char *mntdir, char *fs_name, char *opts, int on_autofs)
|
||||
{
|
||||
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 = mntdir;
|
||||
mnt.mnt_fsname = fs_name;
|
||||
mnt.mnt_type = MNTTAB_TYPE_EFS;
|
||||
mnt.mnt_opts = opts;
|
||||
|
||||
flags = compute_mount_flags(&mnt);
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (on_autofs)
|
||||
flags |= autofs_compute_mount_flags(&mnt);
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
#ifdef HAVE_EFS_ARGS_T_FLAGS
|
||||
efs_args.flags = 0; /* XXX: fix this to correct flags */
|
||||
#endif /* HAVE_EFS_ARGS_T_FLAGS */
|
||||
#ifdef HAVE_EFS_ARGS_T_FSPEC
|
||||
efs_args.fspec = fs_name;
|
||||
#endif /* HAVE_EFS_ARGS_T_FSPEC */
|
||||
#if defined(HAVE_EFS_ARGS_T_VERSION) && defined(EFS_MNT_VERSION)
|
||||
efs_args.version = EFS_MNT_VERSION;
|
||||
#endif /* HAVE_EFS_ARGS_T_VERSION && EFS_MNT_VERSION */
|
||||
|
||||
/*
|
||||
* Call generic mount routine
|
||||
*/
|
||||
return mount_fs(&mnt, flags, (caddr_t) &efs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
efs_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
|
||||
int error;
|
||||
|
||||
error = mount_efs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
|
||||
if (error) {
|
||||
errno = error;
|
||||
plog(XLOG_ERROR, "mount_efs: %m");
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
efs_umount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
|
||||
|
||||
return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
|
||||
}
|
||||
|
@ -1,223 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_ext.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Irix UN*X file system: EXT (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 *ext_match(am_opts *fo);
|
||||
static int ext2_mount(am_node *am, mntfs *mf);
|
||||
static int ext3_mount(am_node *am, mntfs *mf);
|
||||
static int ext4_mount(am_node *am, mntfs *mf);
|
||||
static int ext_umount(am_node *am, mntfs *mf);
|
||||
|
||||
/*
|
||||
* Ops structure
|
||||
*/
|
||||
am_ops ext2_ops =
|
||||
{
|
||||
"ext2",
|
||||
ext_match,
|
||||
0, /* ext_init */
|
||||
ext2_mount,
|
||||
ext_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* ext_readlink */
|
||||
0, /* ext_mounted */
|
||||
0, /* ext_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* ext_get_wchan */
|
||||
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_EXT_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
am_ops ext3_ops =
|
||||
{
|
||||
"ext3",
|
||||
ext_match,
|
||||
0, /* ext_init */
|
||||
ext3_mount,
|
||||
ext_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* ext_readlink */
|
||||
0, /* ext_mounted */
|
||||
0, /* ext_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* ext_get_wchan */
|
||||
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_EXT_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
am_ops ext4_ops =
|
||||
{
|
||||
"ext4",
|
||||
ext_match,
|
||||
0, /* ext_init */
|
||||
ext4_mount,
|
||||
ext_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* ext_readlink */
|
||||
0, /* ext_mounted */
|
||||
0, /* ext_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* ext_get_wchan */
|
||||
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_EXT_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
/*
|
||||
* EXT needs local filesystem and device.
|
||||
*/
|
||||
static char *
|
||||
ext_match(am_opts *fo)
|
||||
{
|
||||
|
||||
if (!fo->opt_dev) {
|
||||
plog(XLOG_USER, "ext: no device specified");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dlog("EXT: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
|
||||
|
||||
/*
|
||||
* Determine magic cookie to put in mtab
|
||||
*/
|
||||
return xstrdup(fo->opt_dev);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
mount_ext(char *mntdir, char *fs_name, char *opts, int on_autofs, char *
|
||||
mount_type, const char *mnttab_type)
|
||||
{
|
||||
ext_args_t ext_args;
|
||||
mntent_t mnt;
|
||||
int flags;
|
||||
|
||||
/*
|
||||
* Figure out the name of the file system type.
|
||||
*/
|
||||
MTYPE_TYPE type = mount_type;
|
||||
|
||||
memset((voidp) &ext_args, 0, sizeof(ext_args)); /* Paranoid */
|
||||
|
||||
/*
|
||||
* Fill in the mount structure
|
||||
*/
|
||||
memset((voidp) &mnt, 0, sizeof(mnt));
|
||||
mnt.mnt_dir = mntdir;
|
||||
mnt.mnt_fsname = fs_name;
|
||||
mnt.mnt_type = mnttab_type;
|
||||
mnt.mnt_opts = opts;
|
||||
|
||||
flags = compute_mount_flags(&mnt);
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (on_autofs)
|
||||
flags |= autofs_compute_mount_flags(&mnt);
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
/*
|
||||
* Call generic mount routine
|
||||
*/
|
||||
return mount_fs(&mnt, flags, (caddr_t) &ext_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ext_mount(am_node *am, mntfs *mf, char *mount_type,
|
||||
const char *mnttab_type)
|
||||
{
|
||||
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
|
||||
int error;
|
||||
|
||||
error = mount_ext(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs,
|
||||
mount_type, mnttab_type);
|
||||
if (error) {
|
||||
errno = error;
|
||||
plog(XLOG_ERROR, "mount_ext: %m");
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ext2_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
return ext_mount(am, mf, MOUNT_TYPE_EXT2, MNTTAB_TYPE_EXT2);
|
||||
}
|
||||
|
||||
static int
|
||||
ext3_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
return ext_mount(am, mf, MOUNT_TYPE_EXT3, MNTTAB_TYPE_EXT3);
|
||||
}
|
||||
|
||||
static int
|
||||
ext4_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
return ext_mount(am, mf, MOUNT_TYPE_EXT4, MNTTAB_TYPE_EXT4);
|
||||
}
|
||||
|
||||
static int
|
||||
ext_umount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
|
||||
|
||||
return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_lofs.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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_mount(am_node *am, mntfs *mf);
|
||||
static int lofs_umount(am_node *am, mntfs *mf);
|
||||
|
||||
/*
|
||||
* Ops structure
|
||||
*/
|
||||
am_ops lofs_ops =
|
||||
{
|
||||
"lofs",
|
||||
lofs_match,
|
||||
0, /* lofs_init */
|
||||
lofs_mount,
|
||||
lofs_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* lofs_readlink */
|
||||
0, /* lofs_mounted */
|
||||
0, /* lofs_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* lofs_get_wchan */
|
||||
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_LOFS_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
dlog("LOFS: mounting fs \"%s\" on \"%s\"",
|
||||
fo->opt_rfs, fo->opt_fs);
|
||||
|
||||
/*
|
||||
* Determine magic cookie to put in mtab
|
||||
*/
|
||||
return xstrdup(fo->opt_rfs);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
mount_lofs(char *mntdir, char *fs_name, char *opts, int on_autofs)
|
||||
{
|
||||
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 = mntdir;
|
||||
mnt.mnt_fsname = fs_name;
|
||||
mnt.mnt_type = MNTTAB_TYPE_LOFS;
|
||||
mnt.mnt_opts = opts;
|
||||
|
||||
flags = compute_mount_flags(&mnt);
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (on_autofs)
|
||||
flags |= autofs_compute_mount_flags(&mnt);
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
/*
|
||||
* Call generic mount routine
|
||||
*/
|
||||
return mount_fs(&mnt, flags, NULL, 0, type, 0, NULL, mnttab_file_name, on_autofs);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
lofs_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
|
||||
int error;
|
||||
|
||||
error = mount_lofs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
|
||||
if (error) {
|
||||
errno = error;
|
||||
plog(XLOG_ERROR, "mount_lofs: %m");
|
||||
return error;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
lofs_umount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
|
||||
|
||||
return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
|
||||
}
|
@ -1,203 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Christos Zoulas
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_lustre.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Lustre file system
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#ifdef HAVE_FS_LUSTRE
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
|
||||
/* forward declarations */
|
||||
static char *lustre_match(am_opts *fo);
|
||||
static int lustre_mount(am_node *am, mntfs *mf);
|
||||
static int lustre_umount(am_node *am, mntfs *mf);
|
||||
|
||||
/*
|
||||
* Ops structure
|
||||
*/
|
||||
am_ops lustre_ops =
|
||||
{
|
||||
"lustre",
|
||||
lustre_match,
|
||||
0, /* lustre_init */
|
||||
lustre_mount,
|
||||
lustre_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* lustre_readlink */
|
||||
0, /* lustre_mounted */
|
||||
0, /* lustre_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* lustre_get_wchan */
|
||||
FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_LUSTRE_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Lustre needs remote filesystem and host.
|
||||
*/
|
||||
static char *
|
||||
lustre_match(am_opts *fo)
|
||||
{
|
||||
char *xmtab, *cp;
|
||||
size_t l;
|
||||
char *rhost, *ptr, *remhost;
|
||||
struct in_addr addr;
|
||||
|
||||
if (fo->opt_fs && !fo->opt_rfs)
|
||||
fo->opt_rfs = fo->opt_fs;
|
||||
if (!fo->opt_rfs) {
|
||||
plog(XLOG_USER, "lustre: no remote filesystem specified");
|
||||
return NULL;
|
||||
}
|
||||
if (!fo->opt_rhost) {
|
||||
plog(XLOG_USER, "lustre: no remote host specified");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine magic cookie to put in mtab
|
||||
*/
|
||||
rhost = xstrdup(fo->opt_rhost);
|
||||
remhost = NULL;
|
||||
for (ptr = strtok(rhost, ":"); ptr; ptr = strtok(NULL, ":")) {
|
||||
char *at = strchr(ptr, '@');
|
||||
if (at == NULL) {
|
||||
plog(XLOG_USER, "lustre: missing protocol in host `%s'", ptr);
|
||||
XFREE(rhost);
|
||||
return NULL;
|
||||
}
|
||||
*at = '\0';
|
||||
/*
|
||||
* Convert symbolic addresses to numbers that the kernel likes
|
||||
*/
|
||||
if (inet_aton(ptr, &addr) == 0) {
|
||||
struct hostent *hp;
|
||||
if ((hp = gethostbyname(ptr)) == NULL) {
|
||||
plog(XLOG_USER, "lustre: unknown host `%s'", ptr);
|
||||
XFREE(rhost);
|
||||
return NULL;
|
||||
}
|
||||
if (hp->h_length != sizeof(addr.s_addr)) {
|
||||
plog(XLOG_USER, "lustre: bad address length %zu != %d for %s",
|
||||
sizeof(addr), hp->h_length, ptr);
|
||||
XFREE(rhost);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(&addr.s_addr, hp->h_addr, sizeof(addr));
|
||||
}
|
||||
*at = '@';
|
||||
|
||||
cp = remhost;
|
||||
if (remhost)
|
||||
remhost = strvcat(cp, ":", inet_ntoa(addr), at, NULL);
|
||||
else
|
||||
remhost = strvcat(inet_ntoa(addr), at, NULL);
|
||||
XFREE(cp);
|
||||
}
|
||||
if (remhost == NULL) {
|
||||
plog(XLOG_USER, "lustre: empty host");
|
||||
XFREE(rhost);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XFREE(rhost);
|
||||
XFREE(fo->opt_rhost);
|
||||
fo->opt_rhost = remhost;
|
||||
|
||||
l = strlen(fo->opt_rhost) + strlen(fo->opt_rfs) + 2;
|
||||
xmtab = xmalloc(l);
|
||||
xsnprintf(xmtab, l, "%s:%s", fo->opt_rhost, fo->opt_rfs);
|
||||
dlog("lustre: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
|
||||
fo->opt_rhost, fo->opt_rfs, fo->opt_fs);
|
||||
|
||||
|
||||
return xmtab;
|
||||
}
|
||||
|
||||
static int
|
||||
lustre_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
mntent_t mnt;
|
||||
int genflags, error;
|
||||
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
|
||||
|
||||
/*
|
||||
* Figure out the name of the file system type.
|
||||
*/
|
||||
MTYPE_TYPE type = MOUNT_TYPE_LUSTRE;
|
||||
|
||||
/*
|
||||
* Fill in the mount structure
|
||||
*/
|
||||
memset(&mnt, 0, sizeof(mnt));
|
||||
mnt.mnt_dir = mf->mf_mount;
|
||||
mnt.mnt_fsname = mf->mf_info;
|
||||
mnt.mnt_type = MNTTAB_TYPE_LUSTRE;
|
||||
mnt.mnt_opts = mf->mf_mopts;
|
||||
|
||||
genflags = compute_mount_flags(&mnt);
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (on_autofs)
|
||||
genflags |= autofs_compute_mount_flags(&mnt);
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
/*
|
||||
* Call generic mount routine
|
||||
*/
|
||||
error = mount_fs(&mnt, genflags, NULL, 0, type, 0,
|
||||
NULL, mnttab_file_name, on_autofs);
|
||||
if (error) {
|
||||
errno = error;
|
||||
plog(XLOG_ERROR, "mount_lustre: %m");
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
lustre_umount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
|
||||
|
||||
return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
|
||||
}
|
||||
#endif
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_mfs.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 IMPLEMENT THIS... :-) */
|
File diff suppressed because it is too large
Load Diff
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_nfs3.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 IMPLEMENT THIS... :-) */
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_nfs4.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Network file system version 4.0
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
|
||||
/* FEEL FREE TO IMPLEMENT THIS... :-) */
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_nullfs.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 IMPLEMENT THIS... :-) */
|
@ -1,222 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_pcfs.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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_mount(am_node *am, mntfs *mf);
|
||||
static int pcfs_umount(am_node *am, mntfs *mf);
|
||||
|
||||
/*
|
||||
* Ops structure
|
||||
*/
|
||||
am_ops pcfs_ops =
|
||||
{
|
||||
"pcfs",
|
||||
pcfs_match,
|
||||
0, /* pcfs_init */
|
||||
pcfs_mount,
|
||||
pcfs_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* pcfs_readlink */
|
||||
0, /* pcfs_mounted */
|
||||
0, /* pcfs_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* pcfs_get_wchan */
|
||||
FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_PCFS_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
dlog("PCFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
|
||||
|
||||
/*
|
||||
* Determine magic cookie to put in mtab
|
||||
*/
|
||||
return xstrdup(fo->opt_dev);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
mount_pcfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
|
||||
{
|
||||
pcfs_args_t pcfs_args;
|
||||
mntent_t mnt;
|
||||
int flags;
|
||||
#if defined(HAVE_PCFS_ARGS_T_MASK) || defined(HAVE_PCFS_ARGS_T_DIRMASK)
|
||||
int mask;
|
||||
#endif /* defined(HAVE_PCFS_ARGS_T_MASK) || defined(HAVE_PCFS_ARGS_T_DIRMASK) */
|
||||
#if defined(HAVE_PCFS_ARGS_T_UID) || defined(HAVE_PCFS_ARGS_T_UID)
|
||||
char *str;
|
||||
#endif /* defined(HAVE_PCFS_ARGS_T_UID) || defined(HAVE_PCFS_ARGS_T_UID) */
|
||||
|
||||
/*
|
||||
* Figure out the name of the file system type.
|
||||
*/
|
||||
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 = mntdir;
|
||||
mnt.mnt_fsname = fs_name;
|
||||
mnt.mnt_type = MNTTAB_TYPE_PCFS;
|
||||
mnt.mnt_opts = opts;
|
||||
|
||||
flags = compute_mount_flags(&mnt);
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (on_autofs)
|
||||
flags |= autofs_compute_mount_flags(&mnt);
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
if (amuDebug(D_TRACE))
|
||||
plog(XLOG_DEBUG, "mount_pcfs: flags=0x%x", (u_int) flags);
|
||||
|
||||
#ifdef HAVE_PCFS_ARGS_T_FSPEC
|
||||
pcfs_args.fspec = fs_name;
|
||||
#endif /* HAVE_PCFS_ARGS_T_FSPEC */
|
||||
|
||||
#ifdef HAVE_PCFS_ARGS_T_MASK
|
||||
pcfs_args.mask = 0777; /* this may be the msdos file modes */
|
||||
if ((mask = hasmntval(&mnt, MNTTAB_OPT_MASK)) > 0)
|
||||
pcfs_args.mask = mask;
|
||||
if (amuDebug(D_TRACE))
|
||||
plog(XLOG_DEBUG, "mount_pcfs: mask=%o (octal)", (u_int) pcfs_args.mask);
|
||||
#endif /* HAVE_PCFS_ARGS_T_MASK */
|
||||
|
||||
#ifdef HAVE_PCFS_ARGS_T_DIRMASK
|
||||
pcfs_args.dirmask = 0777; /* this may be the msdos dir modes */
|
||||
if ((mask = hasmntval(&mnt, MNTTAB_OPT_DIRMASK)) > 0)
|
||||
pcfs_args.dirmask = mask;
|
||||
if (amuDebug(D_TRACE))
|
||||
plog(XLOG_DEBUG, "mount_pcfs: dirmask=%o (octal)", (u_int) pcfs_args.dirmask);
|
||||
#endif /* HAVE_PCFS_ARGS_T_DIRMASK */
|
||||
|
||||
#ifdef HAVE_PCFS_ARGS_T_UID
|
||||
pcfs_args.uid = 0; /* default to root */
|
||||
if ((str = hasmntstr(&mnt, MNTTAB_OPT_USER)) != NULL) {
|
||||
struct passwd *pw;
|
||||
if ((pw = getpwnam(str)) != NULL)
|
||||
pcfs_args.uid = pw->pw_uid;
|
||||
else /* maybe used passed a UID number, not user name */
|
||||
pcfs_args.uid = atoi(str); /* atoi returns '0' if it failed */
|
||||
XFREE(str);
|
||||
}
|
||||
if (amuDebug(D_TRACE))
|
||||
plog(XLOG_DEBUG, "mount_pcfs: uid=%d", (int) pcfs_args.uid);
|
||||
#endif /* HAVE_PCFS_ARGS_T_UID */
|
||||
|
||||
#ifdef HAVE_PCFS_ARGS_T_GID
|
||||
pcfs_args.gid = 0; /* default to wheel/root group */
|
||||
if ((str = hasmntstr(&mnt, MNTTAB_OPT_GROUP)) != NULL) {
|
||||
struct group *gr;
|
||||
if ((gr = getgrnam(str)) != NULL)
|
||||
pcfs_args.gid = gr->gr_gid;
|
||||
else /* maybe used passed a GID number, not group name */
|
||||
pcfs_args.gid = atoi(str); /* atoi returns '0' if it failed */
|
||||
XFREE(str);
|
||||
}
|
||||
if (amuDebug(D_TRACE))
|
||||
plog(XLOG_DEBUG, "mount_pcfs: gid=%d", (int) pcfs_args.gid);
|
||||
#endif /* HAVE_PCFS_ARGS_T_GID */
|
||||
|
||||
#ifdef HAVE_PCFS_ARGS_T_SECONDSWEST
|
||||
pcfs_args.secondswest = 0; /* XXX: fill in correct values */
|
||||
#endif /* HAVE_PCFS_ARGS_T_SECONDSWEST */
|
||||
#ifdef HAVE_PCFS_ARGS_T_DSTTIME
|
||||
pcfs_args.dsttime = 0; /* XXX: fill in correct values */
|
||||
#endif /* HAVE_PCFS_ARGS_T_DSTTIME */
|
||||
|
||||
/*
|
||||
* Call generic mount routine
|
||||
*/
|
||||
return mount_fs(&mnt, flags, (caddr_t) & pcfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
pcfs_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
|
||||
int error;
|
||||
|
||||
error = mount_pcfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
|
||||
if (error) {
|
||||
errno = error;
|
||||
plog(XLOG_ERROR, "mount_pcfs: %m");
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
pcfs_umount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
|
||||
|
||||
return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_tfs.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Translucent file system
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
|
||||
/* FEEL FREE TO IMPLEMENT THIS... :-) */
|
@ -1,192 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_tmpfs.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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>
|
||||
|
||||
/* forward declarations */
|
||||
static char *tmpfs_match(am_opts *fo);
|
||||
static int tmpfs_mount(am_node *am, mntfs *mf);
|
||||
static int tmpfs_umount(am_node *am, mntfs *mf);
|
||||
|
||||
/*
|
||||
* Ops structure
|
||||
*/
|
||||
am_ops tmpfs_ops =
|
||||
{
|
||||
"tmpfs",
|
||||
tmpfs_match,
|
||||
0, /* tmpfs_init */
|
||||
tmpfs_mount,
|
||||
tmpfs_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* tmpfs_readlink */
|
||||
0, /* tmpfs_mounted */
|
||||
0, /* tmpfs_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* tmpfs_get_wchan */
|
||||
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
|
||||
#if defined(HAVE_FS_AUTOFS) && defined(AUTOFS_TMPFS_FS_FLAGS)
|
||||
AUTOFS_TMPFS_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* EFS needs local filesystem and device.
|
||||
*/
|
||||
static char *
|
||||
tmpfs_match(am_opts *fo)
|
||||
{
|
||||
|
||||
if (!fo->opt_dev) {
|
||||
plog(XLOG_USER, "tmpfs: no device specified");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dlog("EFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
|
||||
|
||||
/*
|
||||
* Determine magic cookie to put in mtab
|
||||
*/
|
||||
return xstrdup(fo->opt_dev);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
mount_tmpfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
|
||||
{
|
||||
tmpfs_args_t tmpfs_args;
|
||||
mntent_t mnt;
|
||||
int flags;
|
||||
const char *p;
|
||||
|
||||
/*
|
||||
* Figure out the name of the file system type.
|
||||
*/
|
||||
MTYPE_TYPE type = MOUNT_TYPE_TMPFS;
|
||||
|
||||
p = NULL;
|
||||
memset((voidp) &tmpfs_args, 0, sizeof(tmpfs_args)); /* Paranoid */
|
||||
|
||||
/*
|
||||
* Fill in the mount structure
|
||||
*/
|
||||
memset((voidp) &mnt, 0, sizeof(mnt));
|
||||
mnt.mnt_dir = mntdir;
|
||||
mnt.mnt_fsname = fs_name;
|
||||
mnt.mnt_type = MNTTAB_TYPE_TMPFS;
|
||||
mnt.mnt_opts = opts;
|
||||
|
||||
flags = compute_mount_flags(&mnt);
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (on_autofs)
|
||||
flags |= autofs_compute_mount_flags(&mnt);
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
#if defined(HAVE_TMPFS_ARGS_T_TA_VERSION) && defined(TMPFS_ARGS_VERSION)
|
||||
tmpfs_args.ta_version = TMPFS_ARGS_VERSION;
|
||||
#endif /* HAVE_TMPFS_ARGS_T_TA_VERSION && TMPFS_ARGS_VERSION */
|
||||
#ifdef HAVE_TMPFS_ARGS_T_TA_NODES_MAX
|
||||
if ((p = amu_hasmntopt(&mnt, "nodes")) == NULL)
|
||||
p = "1000000";
|
||||
tmpfs_args.ta_nodes_max = atoi(p);
|
||||
#endif /* HAVE_TMPFS_ARGS_T_TA_SIZE_MAX */
|
||||
#ifdef HAVE_TMPFS_ARGS_T_TA_SIZE_MAX
|
||||
if ((p = amu_hasmntopt(&mnt, "size")) == NULL)
|
||||
p = "10000000";
|
||||
tmpfs_args.ta_size_max = atoi(p);
|
||||
#endif /* HAVE_TMPFS_ARGS_T_TA_SIZE_MAX */
|
||||
#ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_UID
|
||||
if ((p = amu_hasmntopt(&mnt, "uid")) == NULL)
|
||||
p = "0";
|
||||
tmpfs_args.ta_root_uid = atoi(p);
|
||||
#endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_UID */
|
||||
#ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_GID
|
||||
if ((p = amu_hasmntopt(&mnt, "gid")) == NULL)
|
||||
p = "0";
|
||||
tmpfs_args.ta_root_gid = atoi(p);
|
||||
#endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_GID */
|
||||
#ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_MODE
|
||||
if ((p = amu_hasmntopt(&mnt, "mode")) == NULL)
|
||||
p = "01777";
|
||||
tmpfs_args.ta_root_mode = strtol(p, NULL, 8);
|
||||
#endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_MODE */
|
||||
|
||||
/*
|
||||
* Call generic mount routine
|
||||
*/
|
||||
return mount_fs(&mnt, flags, (caddr_t) &tmpfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
tmpfs_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
|
||||
int error;
|
||||
|
||||
error = mount_tmpfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
|
||||
if (error) {
|
||||
errno = error;
|
||||
plog(XLOG_ERROR, "mount_tmpfs: %m");
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
tmpfs_umount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
|
||||
|
||||
return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
|
||||
}
|
||||
|
@ -1,272 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_udf.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* UDF file system
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
|
||||
/* forward definitions */
|
||||
static char *udf_match(am_opts *fo);
|
||||
static int udf_mount(am_node *am, mntfs *mf);
|
||||
static int udf_umount(am_node *am, mntfs *mf);
|
||||
|
||||
/*
|
||||
* Ops structure
|
||||
*/
|
||||
am_ops udf_ops =
|
||||
{
|
||||
"udf",
|
||||
udf_match,
|
||||
0, /* udf_init */
|
||||
udf_mount,
|
||||
udf_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* udf_readlink */
|
||||
0, /* udf_mounted */
|
||||
0, /* udf_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* udf_get_wchan */
|
||||
FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_UDF_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
#if defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_NOBODY_UID)
|
||||
static int
|
||||
a_num(const char *s, const char *id_type)
|
||||
{
|
||||
int id;
|
||||
char *ep;
|
||||
|
||||
id = strtol(s, &ep, 0);
|
||||
if (*ep || s == ep || id < 0) {
|
||||
plog(XLOG_ERROR, "mount_udf: unknown %s: %s", id_type, s);
|
||||
return 0;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_NOBODY_UID) */
|
||||
|
||||
#if defined(HAVE_UDF_ARGS_T_NOBODY_GID)
|
||||
static gid_t
|
||||
a_gid(const char *s, const char *id_type)
|
||||
{
|
||||
struct group *gr;
|
||||
|
||||
if ((gr = getgrnam(s)) != NULL)
|
||||
return gr->gr_gid;
|
||||
return a_num(s, id_type);
|
||||
}
|
||||
#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_GID) */
|
||||
|
||||
#if defined(HAVE_UDF_ARGS_T_NOBODY_UID)
|
||||
static uid_t
|
||||
a_uid(const char *s, const char *id_type)
|
||||
{
|
||||
struct passwd *pw;
|
||||
|
||||
if ((pw = getpwnam(s)) != NULL)
|
||||
return pw->pw_uid;
|
||||
return a_num(s, id_type);
|
||||
}
|
||||
#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_UID) */
|
||||
|
||||
/*
|
||||
* UDF needs remote filesystem.
|
||||
*/
|
||||
static char *
|
||||
udf_match(am_opts *fo)
|
||||
{
|
||||
|
||||
if (!fo->opt_dev) {
|
||||
plog(XLOG_USER, "udf: no source device specified");
|
||||
return 0;
|
||||
}
|
||||
dlog("UDF: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
|
||||
|
||||
/*
|
||||
* Determine magic cookie to put in mtab
|
||||
*/
|
||||
return xstrdup(fo->opt_dev);
|
||||
}
|
||||
|
||||
static int
|
||||
mount_udf(char *mntdir, char *fs_name, char *opts, int on_autofs)
|
||||
{
|
||||
udf_args_t udf_args;
|
||||
mntent_t mnt;
|
||||
int flags;
|
||||
char *str;
|
||||
#if defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID)
|
||||
uid_t uid_nobody;
|
||||
gid_t gid_nobody;
|
||||
#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID) */
|
||||
/*
|
||||
* Figure out the name of the file system type.
|
||||
*/
|
||||
MTYPE_TYPE type = MOUNT_TYPE_UDF;
|
||||
|
||||
#if defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID)
|
||||
uid_nobody = a_uid("nobody", "user");
|
||||
if (uid_nobody == 0) {
|
||||
plog(XLOG_ERROR, "mount_udf: invalid uid for nobody");
|
||||
return EPERM;
|
||||
}
|
||||
#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID) */
|
||||
|
||||
#if defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_ANON_GID)
|
||||
gid_nobody = a_gid("nobody", "group");
|
||||
if (gid_nobody == 0) {
|
||||
plog(XLOG_ERROR, "mount_udf: invalid gid for nobody");
|
||||
return EPERM;
|
||||
}
|
||||
#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_ANON_GID) */
|
||||
|
||||
str = NULL;
|
||||
memset((voidp) &udf_args, 0, sizeof(udf_args)); /* Paranoid */
|
||||
|
||||
/*
|
||||
* Fill in the mount structure
|
||||
*/
|
||||
memset((voidp)&mnt, 0, sizeof(mnt));
|
||||
mnt.mnt_dir = mntdir;
|
||||
mnt.mnt_fsname = fs_name;
|
||||
mnt.mnt_type = MNTTAB_TYPE_UDF;
|
||||
mnt.mnt_opts = opts;
|
||||
|
||||
flags = compute_mount_flags(&mnt);
|
||||
|
||||
#ifdef HAVE_UDF_ARGS_T_UDFMFLAGS
|
||||
# if defined(MNT2_UDF_OPT_CLOSESESSION) && defined(MNTTAB_OPT_CLOSESESSION)
|
||||
if (amu_hasmntopt(&mnt, MNTTAB_OPT_CLOSESESSION))
|
||||
udf_args.udfmflags |= MNT2_UDF_OPT_CLOSESESSION;
|
||||
# endif /* defined(MNT2_UDF_OPT_CLOSESESSION) && defined(MNTTAB_OPT_CLOSESESSION) */
|
||||
#endif /* HAVE_UDF_ARGS_T_UDFMFLAGS */
|
||||
|
||||
#ifdef HAVE_UDF_ARGS_T_NOBODY_UID
|
||||
udf_args.nobody_uid = uid_nobody;
|
||||
#endif /* HAVE_UDF_ARGS_T_NOBODY_UID */
|
||||
|
||||
#ifdef HAVE_UDF_ARGS_T_NOBODY_GID
|
||||
udf_args.nobody_gid = gid_nobody;
|
||||
#endif /* HAVE_UDF_ARGS_T_NOBODY_GID */
|
||||
|
||||
#ifdef HAVE_UDF_ARGS_T_ANON_UID
|
||||
udf_args.anon_uid = uid_nobody; /* default to nobody */
|
||||
if ((str = hasmntstr(&mnt, MNTTAB_OPT_USER)) != NULL) {
|
||||
udf_args.anon_uid = a_uid(str, MNTTAB_OPT_USER);
|
||||
XFREE(str);
|
||||
}
|
||||
#endif /* HAVE_UDF_ARGS_T_ANON_UID */
|
||||
|
||||
#ifdef HAVE_UDF_ARGS_T_ANON_GID
|
||||
udf_args.anon_gid = gid_nobody; /* default to nobody */
|
||||
if ((str = hasmntstr(&mnt, MNTTAB_OPT_GROUP)) != NULL) {
|
||||
udf_args.anon_gid = a_gid(str, MNTTAB_OPT_GROUP);
|
||||
XFREE(str);
|
||||
}
|
||||
#endif /* HAVE_UDF_ARGS_T_ANON_GID */
|
||||
|
||||
#ifdef HAVE_UDF_ARGS_T_GMTOFF
|
||||
udf_args.gmtoff = 0;
|
||||
if ((str = hasmntstr(&mnt, MNTTAB_OPT_GMTOFF)) != NULL) {
|
||||
udf_args.gmtoff = a_num(str, MNTTAB_OPT_GMTOFF);
|
||||
XFREE(str);
|
||||
}
|
||||
#endif /* HAVE_UDF_ARGS_T_GMTOFF */
|
||||
|
||||
#ifdef HAVE_UDF_ARGS_T_SESSIONNR
|
||||
udf_args.sessionnr = 0;
|
||||
if ((str = hasmntstr(&mnt, MNTTAB_OPT_SESSIONNR)) != NULL) {
|
||||
udf_args.sessionnr = a_num(str, MNTTAB_OPT_SESSIONNR);
|
||||
XFREE(str);
|
||||
}
|
||||
#endif /* HAVE_UDF_ARGS_T_SESSIONNR */
|
||||
|
||||
#ifdef HAVE_UDF_ARGS_T_VERSION
|
||||
# ifdef UDFMNT_VERSION
|
||||
udf_args.version = UDFMNT_VERSION;
|
||||
# endif /* UDFMNT_VERSION */
|
||||
#endif /* HAVE_UDF_ARGS_T_VERSION */
|
||||
|
||||
#ifdef HAVE_UDF_ARGS_T_FSPEC
|
||||
udf_args.fspec = fs_name;
|
||||
#endif /* HAVE_UFS_ARGS_T_FSPEC */
|
||||
|
||||
/*
|
||||
* Call generic mount routine
|
||||
*/
|
||||
return mount_fs(&mnt, flags, (caddr_t)&udf_args, 0, type, 0, NULL,
|
||||
mnttab_file_name, on_autofs);
|
||||
}
|
||||
|
||||
static int
|
||||
udf_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int on_autofs;
|
||||
int error;
|
||||
|
||||
on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
|
||||
error = mount_udf(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
|
||||
if (error) {
|
||||
errno = error;
|
||||
plog(XLOG_ERROR, "mount_udf: %m");
|
||||
return error;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
udf_umount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int unmount_flags;
|
||||
|
||||
unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
|
||||
return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
|
||||
}
|
@ -1,180 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_ufs.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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_mount(am_node *am, mntfs *mf);
|
||||
static int ufs_umount(am_node *am, mntfs *mf);
|
||||
|
||||
/*
|
||||
* Ops structure
|
||||
*/
|
||||
am_ops ufs_ops =
|
||||
{
|
||||
#ifndef __NetBSD__
|
||||
"ufs",
|
||||
#else
|
||||
"ffs",
|
||||
#endif
|
||||
ufs_match,
|
||||
0, /* ufs_init */
|
||||
ufs_mount,
|
||||
ufs_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* ufs_readlink */
|
||||
0, /* ufs_mounted */
|
||||
0, /* ufs_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* ufs_get_wchan */
|
||||
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_UFS_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
dlog("UFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
|
||||
|
||||
/*
|
||||
* Determine magic cookie to put in mtab
|
||||
*/
|
||||
return xstrdup(fo->opt_dev);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
mount_ufs(char *mntdir, char *fs_name, char *opts, int on_autofs)
|
||||
{
|
||||
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 = mntdir;
|
||||
mnt.mnt_fsname = fs_name;
|
||||
mnt.mnt_type = MNTTAB_TYPE_UFS;
|
||||
mnt.mnt_opts = opts;
|
||||
|
||||
genflags = compute_mount_flags(&mnt);
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (on_autofs)
|
||||
genflags |= autofs_compute_mount_flags(&mnt);
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
#ifdef HAVE_UFS_ARGS_T_FLAGS
|
||||
ufs_args.flags = genflags; /* XXX: is this correct? */
|
||||
#endif /* HAVE_UFS_ARGS_T_FLAGS */
|
||||
|
||||
#ifdef HAVE_UFS_ARGS_T_UFS_FLAGS
|
||||
ufs_args.ufs_flags = genflags;
|
||||
#endif /* HAVE_UFS_ARGS_T_UFS_FLAGS */
|
||||
|
||||
#ifdef HAVE_UFS_ARGS_T_FSPEC
|
||||
ufs_args.fspec = fs_name;
|
||||
#endif /* HAVE_UFS_ARGS_T_FSPEC */
|
||||
|
||||
#ifdef HAVE_UFS_ARGS_T_UFS_PGTHRESH
|
||||
ufs_args.ufs_pgthresh = hasmntval(&mnt, MNTTAB_OPT_PGTHRESH);
|
||||
#endif /* HAVE_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, on_autofs);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ufs_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
|
||||
int error;
|
||||
|
||||
error = mount_ufs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
|
||||
if (error) {
|
||||
errno = error;
|
||||
plog(XLOG_ERROR, "mount_ufs: %m");
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ufs_umount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
|
||||
|
||||
return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_umapfs.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 IMPLEMENT THIS... :-) */
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_unionfs.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 IMPLEMENT THIS... :-) */
|
@ -1,167 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/ops_xfs.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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_mount(am_node *am, mntfs *mf);
|
||||
static int xfs_umount(am_node *am, mntfs *mf);
|
||||
|
||||
/*
|
||||
* Ops structure
|
||||
*/
|
||||
am_ops xfs_ops =
|
||||
{
|
||||
"xfs",
|
||||
xfs_match,
|
||||
0, /* xfs_init */
|
||||
xfs_mount,
|
||||
xfs_umount,
|
||||
amfs_error_lookup_child,
|
||||
amfs_error_mount_child,
|
||||
amfs_error_readdir,
|
||||
0, /* xfs_readlink */
|
||||
0, /* xfs_mounted */
|
||||
0, /* xfs_umounted */
|
||||
amfs_generic_find_srvr,
|
||||
0, /* xfs_get_wchan */
|
||||
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
AUTOFS_XFS_FS_FLAGS,
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
dlog("XFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
|
||||
|
||||
/*
|
||||
* Determine magic cookie to put in mtab
|
||||
*/
|
||||
return xstrdup(fo->opt_dev);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
mount_xfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
|
||||
{
|
||||
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 = mntdir;
|
||||
mnt.mnt_fsname = fs_name;
|
||||
mnt.mnt_type = MNTTAB_TYPE_XFS;
|
||||
mnt.mnt_opts = opts;
|
||||
|
||||
flags = compute_mount_flags(&mnt);
|
||||
#ifdef HAVE_FS_AUTOFS
|
||||
if (on_autofs)
|
||||
flags |= autofs_compute_mount_flags(&mnt);
|
||||
#endif /* HAVE_FS_AUTOFS */
|
||||
|
||||
#ifdef HAVE_XFS_ARGS_T_FLAGS
|
||||
xfs_args.flags = 0; /* XXX: fix this to correct flags */
|
||||
#endif /* HAVE_XFS_ARGS_T_FLAGS */
|
||||
#ifdef HAVE_XFS_ARGS_T_FSPEC
|
||||
xfs_args.fspec = fs_name;
|
||||
#endif /* HAVE_XFS_ARGS_T_FSPEC */
|
||||
|
||||
/*
|
||||
* Call generic mount routine
|
||||
*/
|
||||
return mount_fs(&mnt, flags, (caddr_t) &xfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
xfs_mount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
|
||||
int error;
|
||||
|
||||
error = mount_xfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
|
||||
if (error) {
|
||||
errno = error;
|
||||
plog(XLOG_ERROR, "mount_xfs: %m");
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
xfs_umount(am_node *am, mntfs *mf)
|
||||
{
|
||||
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
|
||||
|
||||
return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,952 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/readdir.c
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*** MACROS ***
|
||||
****************************************************************************/
|
||||
#define DOT_DOT_COOKIE (u_int) 1
|
||||
#define MAX_CHAIN 2048
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*** FORWARD DEFINITIONS ***
|
||||
****************************************************************************/
|
||||
static int key_already_in_chain(char *keyname, const nfsentry *chain);
|
||||
static nfsentry *make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable);
|
||||
static int amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count, int fully_browsable);
|
||||
|
||||
static const u_int dotdotcookie = DOT_DOT_COOKIE;
|
||||
|
||||
/****************************************************************************
|
||||
*** FUNCTIONS ***
|
||||
****************************************************************************/
|
||||
/*
|
||||
* Was: NEW_TOPLVL_READDIR
|
||||
* Search a chain for an entry with some name.
|
||||
* -Erez Zadok <ezk@cs.columbia.edu>
|
||||
*/
|
||||
static int
|
||||
key_already_in_chain(char *keyname, const nfsentry *chain)
|
||||
{
|
||||
const nfsentry *tmpchain = chain;
|
||||
|
||||
while (tmpchain) {
|
||||
if (keyname && tmpchain->ne_name && STREQ(keyname, tmpchain->ne_name))
|
||||
return 1;
|
||||
tmpchain = tmpchain->ne_nextentry;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create a chain of entries which are not linked.
|
||||
* -Erez Zadok <ezk@cs.columbia.edu>
|
||||
*/
|
||||
static nfsentry *
|
||||
make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable)
|
||||
{
|
||||
static u_int last_cookie = (u_int) 2; /* monotonically increasing */
|
||||
static nfsentry chain[MAX_CHAIN];
|
||||
static int max_entries = MAX_CHAIN;
|
||||
char *key;
|
||||
int num_entries = 0, i;
|
||||
u_int preflen = 0;
|
||||
nfsentry *retval = (nfsentry *) NULL;
|
||||
mntfs *mf;
|
||||
mnt_map *mmp;
|
||||
|
||||
if (!mp) {
|
||||
plog(XLOG_DEBUG, "make_entry_chain: mp is (NULL)");
|
||||
return retval;
|
||||
}
|
||||
mf = mp->am_al->al_mnt;
|
||||
if (!mf) {
|
||||
plog(XLOG_DEBUG, "make_entry_chain: mp->am_al->al_mnt is (NULL)");
|
||||
return retval;
|
||||
}
|
||||
mmp = (mnt_map *) mf->mf_private;
|
||||
if (!mmp) {
|
||||
plog(XLOG_DEBUG, "make_entry_chain: mp->am_al->al_mnt->mf_private is (NULL)");
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (mp->am_pref)
|
||||
preflen = strlen(mp->am_pref);
|
||||
|
||||
/* iterate over keys */
|
||||
for (i = 0; i < NKVHASH; i++) {
|
||||
kv *k;
|
||||
for (k = mmp->kvhash[i]; k ; k = k->next) {
|
||||
|
||||
/*
|
||||
* Skip unwanted entries which are either not real entries or
|
||||
* very difficult to interpret (wildcards...) This test needs
|
||||
* lots of improvement. Any takers?
|
||||
*/
|
||||
key = k->key;
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
/* Skip '/defaults' */
|
||||
if (STREQ(key, "/defaults"))
|
||||
continue;
|
||||
|
||||
/* Skip '*' */
|
||||
if (!fully_browsable && strchr(key, '*'))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If the map has a prefix-string then check if the key starts with
|
||||
* this string, and if it does, skip over this prefix. If it has a
|
||||
* prefix and it doesn't match the start of the key, skip it.
|
||||
*/
|
||||
if (preflen) {
|
||||
if (preflen > strlen(key))
|
||||
continue;
|
||||
if (!NSTREQ(key, mp->am_pref, preflen))
|
||||
continue;
|
||||
key += preflen;
|
||||
}
|
||||
|
||||
/* no more '/' are allowed, unless browsable_dirs=full was used */
|
||||
if (!fully_browsable && strchr(key, '/'))
|
||||
continue;
|
||||
|
||||
/* no duplicates allowed */
|
||||
if (key_already_in_chain(key, current_chain))
|
||||
continue;
|
||||
|
||||
/* fill in a cell and link the entry */
|
||||
if (num_entries >= max_entries) {
|
||||
/* out of space */
|
||||
plog(XLOG_DEBUG, "make_entry_chain: no more space in chain");
|
||||
if (num_entries > 0) {
|
||||
chain[num_entries - 1].ne_nextentry = NULL;
|
||||
retval = &chain[0];
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* we have space. put entry in next cell */
|
||||
++last_cookie;
|
||||
chain[num_entries].ne_fileid = last_cookie;
|
||||
(void)memcpy(chain[num_entries].ne_cookie, &last_cookie,
|
||||
sizeof(last_cookie));
|
||||
chain[num_entries].ne_name = key;
|
||||
if (num_entries < max_entries - 1) { /* link to next one */
|
||||
chain[num_entries].ne_nextentry = &chain[num_entries + 1];
|
||||
}
|
||||
++num_entries;
|
||||
} /* end of "while (k)" */
|
||||
} /* end of "for (i ... NKVHASH ..." */
|
||||
|
||||
/* terminate chain */
|
||||
if (num_entries > 0) {
|
||||
chain[num_entries - 1].ne_nextentry = NULL;
|
||||
retval = &chain[0];
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This one is called only if map is browsable */
|
||||
static int
|
||||
amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count, int fully_browsable)
|
||||
{
|
||||
u_int gen = *(u_int *) (uintptr_t) cookie;
|
||||
int chain_length, i;
|
||||
static nfsentry *te, *te_next;
|
||||
static int j;
|
||||
|
||||
dp->dl_eof = FALSE; /* assume readdir not done */
|
||||
|
||||
if (amuDebug(D_READDIR))
|
||||
plog(XLOG_DEBUG, "amfs_readdir_browsable gen=%u, count=%d",
|
||||
gen, count);
|
||||
|
||||
if (gen == 0) {
|
||||
/*
|
||||
* In the default instance (which is used to start a search) we return
|
||||
* "." and "..".
|
||||
*
|
||||
* This assumes that the count is big enough to allow both "." and ".."
|
||||
* to be returned in a single packet. If it isn't (which would be
|
||||
* fairly unbelievable) then tough.
|
||||
*/
|
||||
dlog("%s: default search", __func__);
|
||||
/*
|
||||
* Check for enough room. This is extremely approximate but is more
|
||||
* than enough space. Really need 2 times:
|
||||
* 4byte fileid
|
||||
* 4byte cookie
|
||||
* 4byte name length
|
||||
* 4byte name
|
||||
* plus the dirlist structure */
|
||||
if (count < (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp))))
|
||||
return EINVAL;
|
||||
|
||||
/*
|
||||
* compute # of entries to send in this chain.
|
||||
* heuristics: 128 bytes per entry.
|
||||
* This is too much probably, but it seems to work better because
|
||||
* of the re-entrant nature of nfs_readdir, and esp. on systems
|
||||
* like OpenBSD 2.2.
|
||||
*/
|
||||
chain_length = count / 128;
|
||||
|
||||
/* reset static state counters */
|
||||
te = te_next = NULL;
|
||||
|
||||
dp->dl_entries = ep;
|
||||
|
||||
/* construct "." */
|
||||
ep[0].ne_fileid = mp->am_gen;
|
||||
ep[0].ne_name = ".";
|
||||
ep[0].ne_nextentry = &ep[1];
|
||||
(void)memset(ep[0].ne_cookie, 0, sizeof(u_int));
|
||||
|
||||
/* construct ".." */
|
||||
if (mp->am_parent)
|
||||
ep[1].ne_fileid = mp->am_parent->am_gen;
|
||||
else
|
||||
ep[1].ne_fileid = mp->am_gen;
|
||||
|
||||
ep[1].ne_name = "..";
|
||||
ep[1].ne_nextentry = NULL;
|
||||
(void)memcpy(ep[1].ne_cookie, &dotdotcookie, sizeof(dotdotcookie));
|
||||
|
||||
/*
|
||||
* If map is browsable, call a function make_entry_chain() to construct
|
||||
* a linked list of unmounted keys, and return it. Then link the chain
|
||||
* to the regular list. Get the chain only once, but return
|
||||
* chunks of it each time.
|
||||
*/
|
||||
te = make_entry_chain(mp, dp->dl_entries, fully_browsable);
|
||||
if (!te)
|
||||
return 0;
|
||||
if (amuDebug(D_READDIR)) {
|
||||
nfsentry *ne;
|
||||
for (j = 0, ne = te; ne; ne = ne->ne_nextentry)
|
||||
plog(XLOG_DEBUG, "gen1 key %4d \"%s\"", j++, ne->ne_name);
|
||||
}
|
||||
|
||||
/* return only "chain_length" entries */
|
||||
te_next = te;
|
||||
for (i=1; i<chain_length; ++i) {
|
||||
te_next = te_next->ne_nextentry;
|
||||
if (!te_next)
|
||||
break;
|
||||
}
|
||||
if (te_next) {
|
||||
nfsentry *te_saved = te_next->ne_nextentry;
|
||||
te_next->ne_nextentry = NULL; /* terminate "te" chain */
|
||||
te_next = te_saved; /* save rest of "te" for next iteration */
|
||||
dp->dl_eof = FALSE; /* tell readdir there's more */
|
||||
} else {
|
||||
dp->dl_eof = TRUE; /* tell readdir that's it */
|
||||
}
|
||||
ep[1].ne_nextentry = te; /* append this chunk of "te" chain */
|
||||
if (amuDebug(D_READDIR)) {
|
||||
nfsentry *ne;
|
||||
for (j = 0, ne = te; ne; ne = ne->ne_nextentry)
|
||||
plog(XLOG_DEBUG, "gen2 key %4d \"%s\"", j++, ne->ne_name);
|
||||
for (j = 0, ne = ep; ne; ne = ne->ne_nextentry) {
|
||||
u_int cookie;
|
||||
(void)memcpy(&cookie, ne->ne_cookie, sizeof(cookie));
|
||||
plog(XLOG_DEBUG, "gen2+ key %4d \"%s\" fi=%d ck=%d",
|
||||
j++, ne->ne_name, ne->ne_fileid, cookie);
|
||||
}
|
||||
plog(XLOG_DEBUG, "EOF is %d", dp->dl_eof);
|
||||
}
|
||||
return 0;
|
||||
} /* end of "if (gen == 0)" statement */
|
||||
|
||||
dlog("%s: real child", __func__);
|
||||
|
||||
if (gen == DOT_DOT_COOKIE) {
|
||||
dlog("%s: End of readdir in %s", __func__, mp->am_path);
|
||||
dp->dl_eof = TRUE;
|
||||
dp->dl_entries = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If browsable directories, then continue serving readdir() with another
|
||||
* chunk of entries, starting from where we left off (when gen was equal
|
||||
* to 0). Once again, assume last chunk served to readdir.
|
||||
*/
|
||||
dp->dl_eof = TRUE;
|
||||
dp->dl_entries = ep;
|
||||
|
||||
te = te_next; /* reset 'te' from last saved te_next */
|
||||
if (!te) { /* another indicator of end of readdir */
|
||||
dp->dl_entries = NULL;
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* compute # of entries to send in this chain.
|
||||
* heuristics: 128 bytes per entry.
|
||||
*/
|
||||
chain_length = count / 128;
|
||||
|
||||
/* return only "chain_length" entries */
|
||||
for (i = 1; i < chain_length; ++i) {
|
||||
te_next = te_next->ne_nextentry;
|
||||
if (!te_next)
|
||||
break;
|
||||
}
|
||||
if (te_next) {
|
||||
nfsentry *te_saved = te_next->ne_nextentry;
|
||||
te_next->ne_nextentry = NULL; /* terminate "te" chain */
|
||||
te_next = te_saved; /* save rest of "te" for next iteration */
|
||||
dp->dl_eof = FALSE; /* tell readdir there's more */
|
||||
}
|
||||
ep = te; /* send next chunk of "te" chain */
|
||||
dp->dl_entries = ep;
|
||||
if (amuDebug(D_READDIR)) {
|
||||
nfsentry *ne;
|
||||
plog(XLOG_DEBUG, "dl_entries=%p, te_next=%p, dl_eof=%d",
|
||||
dp->dl_entries, te_next, dp->dl_eof);
|
||||
for (ne = te; ne; ne = ne->ne_nextentry)
|
||||
plog(XLOG_DEBUG, "gen3 key %4d \"%s\"", j++, ne->ne_name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
amfs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count)
|
||||
{
|
||||
u_int gen = *(u_int *) (uintptr_t) cookie;
|
||||
am_node *xp;
|
||||
|
||||
dp->dl_eof = FALSE; /* assume readdir not done */
|
||||
|
||||
/* when gen is 0, we start reading from the beginning of the directory */
|
||||
if (gen == 0) {
|
||||
/*
|
||||
* In the default instance (which is used to start a search) we return
|
||||
* "." and "..".
|
||||
*
|
||||
* This assumes that the count is big enough to allow both "." and ".."
|
||||
* to be returned in a single packet. If it isn't (which would be
|
||||
* fairly unbelievable) then tough.
|
||||
*/
|
||||
dlog("%s: default search", __func__);
|
||||
/*
|
||||
* Check for enough room. This is extremely approximate but is more
|
||||
* than enough space. Really need 2 times:
|
||||
* 4byte fileid
|
||||
* 4byte cookie
|
||||
* 4byte name length
|
||||
* 4byte name
|
||||
* plus the dirlist structure */
|
||||
#define NEEDROOM (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp)))
|
||||
if (count < NEEDROOM) {
|
||||
dlog("%s: not enough room %u < %zu", __func__, count, NEEDROOM);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
xp = next_nonerror_node(mp->am_child);
|
||||
dp->dl_entries = ep;
|
||||
|
||||
/* construct "." */
|
||||
ep[0].ne_fileid = mp->am_gen;
|
||||
ep[0].ne_name = ".";
|
||||
ep[0].ne_nextentry = &ep[1];
|
||||
(void)memset(ep[0].ne_cookie, 0, sizeof(u_int));
|
||||
|
||||
/* construct ".." */
|
||||
if (mp->am_parent)
|
||||
ep[1].ne_fileid = mp->am_parent->am_gen;
|
||||
else
|
||||
ep[1].ne_fileid = mp->am_gen;
|
||||
ep[1].ne_name = "..";
|
||||
ep[1].ne_nextentry = NULL;
|
||||
(void)memcpy(ep[1].ne_cookie, (xp ? &xp->am_gen : &dotdotcookie),
|
||||
sizeof(dotdotcookie));
|
||||
|
||||
if (!xp)
|
||||
dp->dl_eof = TRUE; /* by default assume readdir done */
|
||||
|
||||
if (amuDebug(D_READDIR)) {
|
||||
nfsentry *ne;
|
||||
int j;
|
||||
for (j = 0, ne = ep; ne; ne = ne->ne_nextentry) {
|
||||
u_int cookie;
|
||||
(void)memcpy(&cookie, ne->ne_cookie, sizeof(cookie));
|
||||
plog(XLOG_DEBUG, "gen1 key %4d \"%s\" fi=%d ck=%d",
|
||||
j++, ne->ne_name, ne->ne_fileid, cookie);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
dlog("%s: real child", __func__);
|
||||
|
||||
if (gen == DOT_DOT_COOKIE) {
|
||||
dlog("%s: End of readdir in %s", __func__, mp->am_path);
|
||||
dp->dl_eof = TRUE;
|
||||
dp->dl_entries = NULL;
|
||||
if (amuDebug(D_READDIR))
|
||||
plog(XLOG_DEBUG, "end of readdir eof=TRUE, dl_entries=0\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* non-browsable directories code */
|
||||
xp = mp->am_child;
|
||||
while (xp && xp->am_gen != gen)
|
||||
xp = xp->am_osib;
|
||||
|
||||
if (xp) {
|
||||
int nbytes = count / 2; /* conservative */
|
||||
int todo = MAX_READDIR_ENTRIES;
|
||||
|
||||
dp->dl_entries = ep;
|
||||
do {
|
||||
am_node *xp_next = next_nonerror_node(xp->am_osib);
|
||||
|
||||
if (xp_next) {
|
||||
(void)memcpy(ep->ne_cookie, &xp_next->am_gen, sizeof(xp_next->am_gen));
|
||||
} else {
|
||||
(void)memcpy(ep->ne_cookie, &dotdotcookie, sizeof(dotdotcookie));
|
||||
dp->dl_eof = TRUE;
|
||||
}
|
||||
|
||||
ep->ne_fileid = xp->am_gen;
|
||||
ep->ne_name = xp->am_name;
|
||||
nbytes -= sizeof(*ep) + 1;
|
||||
if (xp->am_name)
|
||||
nbytes -= strlen(xp->am_name);
|
||||
|
||||
xp = xp_next;
|
||||
|
||||
if (nbytes > 0 && !dp->dl_eof && todo > 1) {
|
||||
ep->ne_nextentry = ep + 1;
|
||||
ep++;
|
||||
--todo;
|
||||
} else {
|
||||
todo = 0;
|
||||
}
|
||||
} while (todo > 0);
|
||||
|
||||
ep->ne_nextentry = NULL;
|
||||
|
||||
if (amuDebug(D_READDIR)) {
|
||||
nfsentry *ne;
|
||||
int j;
|
||||
for (j=0,ne=ep; ne; ne=ne->ne_nextentry) {
|
||||
u_int cookie;
|
||||
(void)memcpy(&cookie, ne->ne_cookie, sizeof(cookie));
|
||||
plog(XLOG_DEBUG, "gen2 key %4d \"%s\" fi=%d ck=%d",
|
||||
j++, ne->ne_name, ne->ne_fileid, cookie);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return ESTALE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search a chain for an entry with some name.
|
||||
*/
|
||||
static int
|
||||
key_already_in_chain3(char *keyname, const am_entry3 *chain)
|
||||
{
|
||||
const am_entry3 *tmpchain = chain;
|
||||
|
||||
while (tmpchain) {
|
||||
if (keyname && tmpchain->name && STREQ(keyname, tmpchain->name))
|
||||
return 1;
|
||||
tmpchain = tmpchain->nextentry;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a chain of entries which are not linked.
|
||||
*/
|
||||
static am_entry3 *
|
||||
make_entry_chain3(am_node *mp, const am_entry3 *current_chain, int fully_browsable)
|
||||
{
|
||||
static uint64 last_cookie = (uint64) 2; /* monotonically increasing */
|
||||
static am_entry3 chain[MAX_CHAIN];
|
||||
static int max_entries = MAX_CHAIN;
|
||||
char *key;
|
||||
int num_entries = 0, i;
|
||||
u_int preflen = 0;
|
||||
am_entry3 *retval = (am_entry3 *) NULL;
|
||||
mntfs *mf;
|
||||
mnt_map *mmp;
|
||||
|
||||
if (!mp) {
|
||||
plog(XLOG_DEBUG, "make_entry_chain3: mp is (NULL)");
|
||||
return retval;
|
||||
}
|
||||
mf = mp->am_al->al_mnt;
|
||||
if (!mf) {
|
||||
plog(XLOG_DEBUG, "make_entry_chain3: mp->am_al->al_mnt is (NULL)");
|
||||
return retval;
|
||||
}
|
||||
mmp = (mnt_map *) mf->mf_private;
|
||||
if (!mmp) {
|
||||
plog(XLOG_DEBUG, "make_entry_chain3: mp->am_al->al_mnt->mf_private is (NULL)");
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (mp->am_pref)
|
||||
preflen = strlen(mp->am_pref);
|
||||
|
||||
/* iterate over keys */
|
||||
for (i = 0; i < NKVHASH; i++) {
|
||||
kv *k;
|
||||
for (k = mmp->kvhash[i]; k ; k = k->next) {
|
||||
|
||||
/*
|
||||
* Skip unwanted entries which are either not real entries or
|
||||
* very difficult to interpret (wildcards...) This test needs
|
||||
* lots of improvement. Any takers?
|
||||
*/
|
||||
key = k->key;
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
/* Skip '/defaults' */
|
||||
if (STREQ(key, "/defaults"))
|
||||
continue;
|
||||
|
||||
/* Skip '*' */
|
||||
if (!fully_browsable && strchr(key, '*'))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If the map has a prefix-string then check if the key starts with
|
||||
* this string, and if it does, skip over this prefix. If it has a
|
||||
* prefix and it doesn't match the start of the key, skip it.
|
||||
*/
|
||||
if (preflen) {
|
||||
if (preflen > strlen(key))
|
||||
continue;
|
||||
if (!NSTREQ(key, mp->am_pref, preflen))
|
||||
continue;
|
||||
key += preflen;
|
||||
}
|
||||
|
||||
/* no more '/' are allowed, unless browsable_dirs=full was used */
|
||||
if (!fully_browsable && strchr(key, '/'))
|
||||
continue;
|
||||
|
||||
/* no duplicates allowed */
|
||||
if (key_already_in_chain3(key, current_chain))
|
||||
continue;
|
||||
|
||||
/* fill in a cell and link the entry */
|
||||
if (num_entries >= max_entries) {
|
||||
/* out of space */
|
||||
plog(XLOG_DEBUG, "make_entry_chain3: no more space in chain");
|
||||
if (num_entries > 0) {
|
||||
chain[num_entries - 1].nextentry = NULL;
|
||||
retval = &chain[0];
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* we have space. put entry in next cell */
|
||||
++last_cookie;
|
||||
chain[num_entries].fileid = last_cookie;
|
||||
chain[num_entries].cookie = last_cookie;
|
||||
chain[num_entries].name = key;
|
||||
if (num_entries < max_entries - 1) { /* link to next one */
|
||||
chain[num_entries].nextentry = &chain[num_entries + 1];
|
||||
}
|
||||
++num_entries;
|
||||
} /* end of "while (k)" */
|
||||
} /* end of "for (i ... NKVHASH ..." */
|
||||
|
||||
/* terminate chain */
|
||||
if (num_entries > 0) {
|
||||
chain[num_entries - 1].nextentry = NULL;
|
||||
retval = &chain[0];
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static size_t needroom3(void)
|
||||
{
|
||||
/*
|
||||
* Check for enough room. This is extremely approximate but should
|
||||
* be enough space. Really need 2 times:
|
||||
* (8byte fileid
|
||||
* 8byte cookie
|
||||
* 8byte name pointer
|
||||
* 8byte next entry addres) = sizeof(am_entry3)
|
||||
* 2byte name + 1byte terminator
|
||||
* plus the size of the am_dirlist3 structure */
|
||||
return ((2 * ((sizeof(am_entry3) + sizeof("..") + 1))) + sizeof(am_dirlist3));
|
||||
}
|
||||
|
||||
/* This one is called only if map is browsable */
|
||||
static int
|
||||
amfs_readdir3_browsable(am_node *mp, am_cookie3 cookie,
|
||||
am_dirlist3 *dp, am_entry3 *ep, u_int count,
|
||||
int fully_browsable)
|
||||
{
|
||||
uint64 gen = *(uint64 *) (uintptr_t) cookie;
|
||||
int chain_length, i;
|
||||
static am_entry3 *te, *te_next;
|
||||
static int j;
|
||||
|
||||
dp->eof = FALSE; /* assume readdir not done */
|
||||
|
||||
if (amuDebug(D_READDIR))
|
||||
plog(XLOG_DEBUG, "amfs_readdir3_browsable gen=%lu, count=%d", (long unsigned) gen, count);
|
||||
|
||||
if (gen == 0) {
|
||||
size_t needed = needroom3();
|
||||
/*
|
||||
* In the default instance (which is used to start a search) we return
|
||||
* "." and "..".
|
||||
*
|
||||
* This assumes that the count is big enough to allow both "." and ".."
|
||||
* to be returned in a single packet. If it isn't (which would be
|
||||
* fairly unbelievable) then tough.
|
||||
*/
|
||||
dlog("%s: default search", __func__);
|
||||
|
||||
if (count < needed) {
|
||||
dlog("%s: not enough room %u < %zu", __func__, count, needed);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* compute # of entries to send in this chain.
|
||||
* heuristics: 128 bytes per entry.
|
||||
* This is too much probably, but it seems to work better because
|
||||
* of the re-entrant nature of nfs_readdir, and esp. on systems
|
||||
* like OpenBSD 2.2.
|
||||
*/
|
||||
chain_length = count / 128;
|
||||
|
||||
/* reset static state counters */
|
||||
te = te_next = NULL;
|
||||
|
||||
dp->entries = ep;
|
||||
|
||||
/* construct "." */
|
||||
ep[0].fileid = mp->am_gen;
|
||||
ep[0].name = ".";
|
||||
ep[0].nextentry = &ep[1];
|
||||
ep[0].cookie = 0;
|
||||
|
||||
/* construct ".." */
|
||||
if (mp->am_parent)
|
||||
ep[1].fileid = mp->am_parent->am_gen;
|
||||
else
|
||||
ep[1].fileid = mp->am_gen;
|
||||
|
||||
ep[1].name = "..";
|
||||
ep[1].nextentry = NULL;
|
||||
ep[1].cookie = dotdotcookie;
|
||||
|
||||
/*
|
||||
* If map is browsable, call a function make_entry_chain() to construct
|
||||
* a linked list of unmounted keys, and return it. Then link the chain
|
||||
* to the regular list. Get the chain only once, but return
|
||||
* chunks of it each time.
|
||||
*/
|
||||
te = make_entry_chain3(mp, dp->entries, fully_browsable);
|
||||
if (!te)
|
||||
return 0;
|
||||
if (amuDebug(D_READDIR)) {
|
||||
am_entry3 *ne;
|
||||
for (j = 0, ne = te; ne; ne = ne->ne_nextentry)
|
||||
plog(XLOG_DEBUG, "gen1 key %4d \"%s\"", j++, ne->ne_name);
|
||||
}
|
||||
|
||||
/* return only "chain_length" entries */
|
||||
te_next = te;
|
||||
for (i=1; i<chain_length; ++i) {
|
||||
te_next = te_next->nextentry;
|
||||
if (!te_next)
|
||||
break;
|
||||
}
|
||||
if (te_next) {
|
||||
am_entry3 *te_saved = te_next->nextentry;
|
||||
te_next->nextentry = NULL; /* terminate "te" chain */
|
||||
te_next = te_saved; /* save rest of "te" for next iteration */
|
||||
dp->eof = FALSE; /* tell readdir there's more */
|
||||
} else {
|
||||
dp->eof = TRUE; /* tell readdir that's it */
|
||||
}
|
||||
ep[1].nextentry = te; /* append this chunk of "te" chain */
|
||||
if (amuDebug(D_READDIR)) {
|
||||
am_entry3 *ne;
|
||||
for (j = 0, ne = te; ne; ne = ne->ne_nextentry)
|
||||
plog(XLOG_DEBUG, "gen2 key %4d \"%s\"", j++, ne->name);
|
||||
for (j = 0, ne = ep; ne; ne = ne->ne_nextentry) {
|
||||
plog(XLOG_DEBUG, "gen2+ key %4d \"%s\" fi=%lu ck=%lu",
|
||||
j++, ne->name, (long unsigned) ne->fileid, (long unsigned) ne->cookie);
|
||||
}
|
||||
plog(XLOG_DEBUG, "EOF is %d", dp->eof);
|
||||
}
|
||||
return 0;
|
||||
} /* end of "if (gen == 0)" statement */
|
||||
|
||||
dlog("%s: real child", __func__);
|
||||
|
||||
if (gen == DOT_DOT_COOKIE) {
|
||||
dlog("%s: End of readdir in %s", __func__, mp->am_path);
|
||||
dp->eof = TRUE;
|
||||
dp->entries = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If browsable directories, then continue serving readdir() with another
|
||||
* chunk of entries, starting from where we left off (when gen was equal
|
||||
* to 0). Once again, assume last chunk served to readdir.
|
||||
*/
|
||||
dp->eof = TRUE;
|
||||
dp->entries = ep;
|
||||
|
||||
te = te_next; /* reset 'te' from last saved te_next */
|
||||
if (!te) { /* another indicator of end of readdir */
|
||||
dp->entries = NULL;
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* compute # of entries to send in this chain.
|
||||
* heuristics: 128 bytes per entry.
|
||||
*/
|
||||
chain_length = count / 128;
|
||||
|
||||
/* return only "chain_length" entries */
|
||||
for (i = 1; i < chain_length; ++i) {
|
||||
te_next = te_next->nextentry;
|
||||
if (!te_next)
|
||||
break;
|
||||
}
|
||||
if (te_next) {
|
||||
am_entry3 *te_saved = te_next->nextentry;
|
||||
te_next->nextentry = NULL; /* terminate "te" chain */
|
||||
te_next = te_saved; /* save rest of "te" for next iteration */
|
||||
dp->eof = FALSE; /* tell readdir there's more */
|
||||
}
|
||||
ep = te; /* send next chunk of "te" chain */
|
||||
dp->entries = ep;
|
||||
if (amuDebug(D_READDIR)) {
|
||||
am_entry3 *ne;
|
||||
plog(XLOG_DEBUG,
|
||||
"entries=%p, te_next=%p, eof=%d", dp->entries, te_next, dp->eof);
|
||||
for (ne = te; ne; ne = ne->nextentry)
|
||||
plog(XLOG_DEBUG, "gen3 key %4d \"%s\"", j++, ne->name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
amfs_readdir3(am_node *mp, am_cookie3 cookie,
|
||||
am_dirlist3 *dp, am_entry3 *ep, u_int count)
|
||||
{
|
||||
uint64 gen = *(uint64 *) (uintptr_t) cookie;
|
||||
am_node *xp;
|
||||
|
||||
if (amuDebug(D_READDIR))
|
||||
plog(XLOG_DEBUG, "amfs_readdir3 gen=%lu, count=%d", (long unsigned) gen, count);
|
||||
|
||||
dp->eof = FALSE; /* assume readdir not done */
|
||||
|
||||
/* when gen is 0, we start reading from the beginning of the directory */
|
||||
if (gen == 0) {
|
||||
size_t needed = needroom3();
|
||||
/*
|
||||
* In the default instance (which is used to start a search) we return
|
||||
* "." and "..".
|
||||
*
|
||||
* This assumes that the count is big enough to allow both "." and ".."
|
||||
* to be returned in a single packet. If it isn't (which would be
|
||||
* fairly unbelievable) then tough.
|
||||
*/
|
||||
dlog("%s: default search", __func__);
|
||||
|
||||
if (count < needed) {
|
||||
dlog("%s: not enough room %u < %zu", __func__, count, needed);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
xp = next_nonerror_node(mp->am_child);
|
||||
dp->entries = ep;
|
||||
|
||||
/* construct "." */
|
||||
ep[0].fileid = mp->am_gen;
|
||||
ep[0].name = ".";
|
||||
ep[0].cookie = 0;
|
||||
ep[0].nextentry = &ep[1];
|
||||
|
||||
/* construct ".." */
|
||||
if (mp->am_parent)
|
||||
ep[1].fileid = mp->am_parent->am_gen;
|
||||
else
|
||||
ep[1].fileid = mp->am_gen;
|
||||
ep[1].name = "..";
|
||||
ep[1].nextentry = NULL;
|
||||
ep[1].cookie = (xp ? xp->am_gen : dotdotcookie);
|
||||
|
||||
if (!xp)
|
||||
dp->eof = TRUE; /* by default assume readdir done */
|
||||
|
||||
if (amuDebug(D_READDIR)) {
|
||||
am_entry3 *ne;
|
||||
int j;
|
||||
for (j = 0, ne = ep; ne; ne = ne->nextentry) {
|
||||
plog(XLOG_DEBUG, "gen1 key %4d \"%s\" fi=%lu ck=%lu",
|
||||
j++, ne->name, (long unsigned) ne->fileid, (long unsigned) ne->cookie);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
dlog("%s: real child", __func__);
|
||||
|
||||
if (gen == (uint64) DOT_DOT_COOKIE) {
|
||||
dlog("%s: End of readdir in %s", __func__, mp->am_path);
|
||||
dp->eof = TRUE;
|
||||
dp->entries = NULL;
|
||||
if (amuDebug(D_READDIR))
|
||||
plog(XLOG_DEBUG, "end of readdir eof=TRUE, dl_entries=0\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* non-browsable directories code */
|
||||
xp = mp->am_child;
|
||||
while (xp && xp->am_gen != gen)
|
||||
xp = xp->am_osib;
|
||||
|
||||
if (xp) {
|
||||
int nbytes = count / 2; /* conservative */
|
||||
int todo = MAX_READDIR_ENTRIES;
|
||||
|
||||
dp->entries = ep;
|
||||
do {
|
||||
am_node *xp_next = next_nonerror_node(xp->am_osib);
|
||||
|
||||
if (xp_next) {
|
||||
ep->cookie = xp_next->am_gen;
|
||||
} else {
|
||||
ep->cookie = (uint64) dotdotcookie;
|
||||
dp->eof = TRUE;
|
||||
}
|
||||
|
||||
ep->fileid = xp->am_gen;
|
||||
ep->name = xp->am_name;
|
||||
nbytes -= sizeof(*ep) + 1;
|
||||
if (xp->am_name)
|
||||
nbytes -= strlen(xp->am_name);
|
||||
|
||||
xp = xp_next;
|
||||
|
||||
if (nbytes > 0 && !dp->dl_eof && todo > 1) {
|
||||
ep->nextentry = ep + 1;
|
||||
ep++;
|
||||
--todo;
|
||||
} else {
|
||||
todo = 0;
|
||||
}
|
||||
} while (todo > 0);
|
||||
|
||||
ep->nextentry = NULL;
|
||||
|
||||
if (amuDebug(D_READDIR)) {
|
||||
am_entry3 *ne;
|
||||
int j;
|
||||
for (j = 0, ne = ep; ne; ne = ne->nextentry) {
|
||||
plog(XLOG_DEBUG, "gen2 key %4d \"%s\" fi=%lu ck=%lu",
|
||||
j++, ne->name, (long unsigned) ne->fileid, (long unsigned) ne->cookie);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return ESTALE;
|
||||
}
|
||||
|
||||
/*
|
||||
* This readdir function which call a special version of it that allows
|
||||
* browsing if browsable_dirs=yes was set on the map.
|
||||
*/
|
||||
int
|
||||
amfs_generic_readdir(am_node *mp, voidp cookie, voidp dp, voidp ep, u_int count)
|
||||
{
|
||||
int browsable, full;
|
||||
|
||||
/* check if map is browsable */
|
||||
browsable = 0;
|
||||
if (mp->am_al->al_mnt && mp->am_al->al_mnt->mf_mopts) {
|
||||
mntent_t mnt;
|
||||
mnt.mnt_opts = mp->am_al->al_mnt->mf_mopts;
|
||||
if (amu_hasmntopt(&mnt, "fullybrowsable"))
|
||||
browsable = 2;
|
||||
else if (amu_hasmntopt(&mnt, "browsable"))
|
||||
browsable = 1;
|
||||
}
|
||||
full = (browsable == 2);
|
||||
|
||||
if (nfs_dispatcher == nfs_program_2) {
|
||||
if (browsable)
|
||||
return amfs_readdir_browsable(mp, cookie, dp, ep, count, full);
|
||||
else
|
||||
return amfs_readdir(mp, cookie, dp, ep, count);
|
||||
} else {
|
||||
if (browsable)
|
||||
return amfs_readdir3_browsable(mp, (am_cookie3) (uintptr_t) cookie, dp, ep, count, full);
|
||||
else
|
||||
return amfs_readdir3(mp, (am_cookie3) (uintptr_t) cookie, dp, ep, count);
|
||||
}
|
||||
}
|
@ -1,282 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/restart.c
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
|
||||
|
||||
static void
|
||||
restart_fake_mntfs(mntent_t *me, am_ops *fs_ops)
|
||||
{
|
||||
mntfs *mf;
|
||||
am_opts mo;
|
||||
char *cp;
|
||||
|
||||
/*
|
||||
* Partially fake up an opts structure
|
||||
*/
|
||||
memset(&mo, 0, sizeof(mo));
|
||||
mo.opt_rhost = NULL;
|
||||
mo.opt_rfs = NULL;
|
||||
cp = strchr(me->mnt_fsname, ':');
|
||||
if (cp) {
|
||||
*cp = '\0';
|
||||
mo.opt_rhost = xstrdup(me->mnt_fsname);
|
||||
mo.opt_rfs = xstrdup(cp + 1);
|
||||
*cp = ':';
|
||||
} else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) {
|
||||
/*
|
||||
* Hacky workaround for mnttab NFS entries that only list the server
|
||||
*/
|
||||
plog(XLOG_WARNING, "NFS server entry assumed to be %s:/", me->mnt_fsname);
|
||||
mo.opt_rhost = xstrdup(me->mnt_fsname);
|
||||
mo.opt_rfs = xstrdup("/");
|
||||
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 */
|
||||
/*
|
||||
* Only timeout non-NFS entries
|
||||
*/
|
||||
if (!STREQ(me->mnt_type, MNTTAB_TYPE_NFS))
|
||||
mf->mf_flags |= MFF_RSTKEEP;
|
||||
if (fs_ops->fs_init) {
|
||||
/*
|
||||
* Don't care whether this worked since
|
||||
* it is checked again when the fs is
|
||||
* inherited.
|
||||
*/
|
||||
(void) (*fs_ops->fs_init) (mf);
|
||||
}
|
||||
plog(XLOG_INFO, "%s restarted fstype %s on %s, flags 0x%x",
|
||||
me->mnt_fsname, fs_ops->fs_type, me->mnt_dir, mf->mf_flags);
|
||||
} else {
|
||||
/* Something strange happened - two mounts at the same place! */
|
||||
free_mntfs(mf);
|
||||
}
|
||||
/*
|
||||
* Clean up mo
|
||||
*/
|
||||
XFREE(mo.opt_rhost);
|
||||
XFREE(mo.opt_rfs);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Handle an amd restart.
|
||||
*
|
||||
* Scan through the mount list finding all "interesting" mount points.
|
||||
* Next hack up partial data structures and add the mounted file
|
||||
* system to the list of known filesystems.
|
||||
*
|
||||
* This module relies on internal details of other components. If
|
||||
* you change something else make *sure* restart() still works.
|
||||
*/
|
||||
void
|
||||
restart(void)
|
||||
{
|
||||
mntlist *ml, *mlp;
|
||||
|
||||
/*
|
||||
* Read the existing mount table. For each entry, find nfs, ufs or auto
|
||||
* mounts and create a partial am_node to represent it.
|
||||
*/
|
||||
for (mlp = ml = read_mtab("restart", mnttab_file_name);
|
||||
mlp;
|
||||
mlp = mlp->mnext) {
|
||||
mntent_t *me = mlp->mnt;
|
||||
am_ops *fs_ops = NULL;
|
||||
|
||||
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"))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Search for the correct filesystem ops */
|
||||
fs_ops = ops_search(me->mnt_type);
|
||||
|
||||
/*
|
||||
* Catch everything else with symlinks to
|
||||
* avoid recursive mounts. This is debatable...
|
||||
*/
|
||||
if (!fs_ops)
|
||||
fs_ops = &amfs_link_ops;
|
||||
|
||||
restart_fake_mntfs(me, fs_ops);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the mount list
|
||||
*/
|
||||
free_mntlist(ml);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Handle an amd restart for amd's own mount points.
|
||||
*
|
||||
* Scan through the mount list finding all daemon mount points
|
||||
* (determined by the presence of a pid inside the mount info).
|
||||
* Next hack up partial data structures and add the mounted file
|
||||
* system to the list of known filesystems.
|
||||
*
|
||||
* This module relies on internal details of other components. If
|
||||
* you change something else make *sure* restart() still works.
|
||||
*/
|
||||
void
|
||||
restart_automounter_nodes(void)
|
||||
{
|
||||
mntlist *ml, *mlp;
|
||||
/* reasonably sized list of restarted nfs ports */
|
||||
u_short old_ports[256];
|
||||
|
||||
memset((voidp) &old_ports, 0, sizeof(u_short) * 256);
|
||||
|
||||
/*
|
||||
* Read the existing mount table. For each entry, find nfs, ufs or auto
|
||||
* mounts and create a partial am_node to represent it.
|
||||
*/
|
||||
for (mlp = ml = read_mtab("restart", mnttab_file_name);
|
||||
mlp;
|
||||
mlp = mlp->mnext) {
|
||||
mntent_t *me = mlp->mnt;
|
||||
am_ops *fs_ops = NULL;
|
||||
char *colon;
|
||||
long pid;
|
||||
u_short port;
|
||||
int err;
|
||||
|
||||
if (!STREQ(me->mnt_type, MNTTAB_TYPE_NFS))
|
||||
continue; /* to next mlp */
|
||||
/*
|
||||
* NFS entry, or possibly an Amd entry...
|
||||
* The mnt_fsname for daemon mount points is
|
||||
* host:(pidXXX)
|
||||
* or (seen on Solaris)
|
||||
* host:daemon(pidXXX)
|
||||
*/
|
||||
colon = strchr(me->mnt_fsname, ':');
|
||||
if (!colon || !strstr(colon, "(pid"))
|
||||
continue;
|
||||
/* if got here, then we matched an existing Amd mount point */
|
||||
err = 1;
|
||||
|
||||
plog(XLOG_WARNING, "%s is an existing automount point", me->mnt_dir);
|
||||
|
||||
/* Is the old automounter still alive? */
|
||||
if (sscanf(colon, "%*[^(](pid%ld%*[,)]", &pid) != 1) {
|
||||
plog(XLOG_WARNING, "Can't parse pid in %s", me->mnt_fsname);
|
||||
goto give_up;
|
||||
}
|
||||
if (kill(pid, 0) != -1 || errno != ESRCH) {
|
||||
plog(XLOG_WARNING, "Automounter (pid: %ld) still alive", pid);
|
||||
goto give_up;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do we have a map for this mount point? Who cares, we'll restart
|
||||
* anyway -- getting ESTALE is way better than hanging.
|
||||
*/
|
||||
|
||||
/* Can we restart it? Only if it tells us what port it was using... */
|
||||
if (sscanf(colon, "%*[^,],port%hu)", &port) != 1) {
|
||||
plog(XLOG_WARNING, "No port specified for %s", me->mnt_fsname);
|
||||
goto give_up;
|
||||
}
|
||||
|
||||
/* Maybe we already own that port... */
|
||||
if (port != nfs_port) {
|
||||
int i;
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (old_ports[i] == port ||
|
||||
old_ports[i] == 0)
|
||||
break;
|
||||
}
|
||||
if (i == 256) {
|
||||
plog(XLOG_WARNING, "Too many open ports (256)");
|
||||
goto give_up;
|
||||
}
|
||||
|
||||
if (old_ports[i] == 0) {
|
||||
int soNFS;
|
||||
SVCXPRT *nfsxprt;
|
||||
if (create_nfs_service(&soNFS, &port, &nfsxprt, nfs_dispatcher,
|
||||
get_nfs_dispatcher_version(nfs_dispatcher)) != 0) {
|
||||
plog(XLOG_WARNING, "Can't bind to port %u", port);
|
||||
goto give_up;
|
||||
}
|
||||
old_ports[i] = nfs_port = port;
|
||||
}
|
||||
}
|
||||
err = 0;
|
||||
|
||||
give_up:
|
||||
if (err) {
|
||||
plog(XLOG_WARNING, "Can't restart %s, leaving it alone", me->mnt_dir);
|
||||
fs_ops = &amfs_link_ops;
|
||||
} else {
|
||||
fs_ops = &amfs_toplvl_ops;
|
||||
}
|
||||
|
||||
restart_fake_mntfs(me, fs_ops);
|
||||
} /* end of "for (mlp" */
|
||||
|
||||
/* free the mount list */
|
||||
free_mntlist(ml);
|
||||
}
|
@ -1,474 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/rpc_fwd.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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() (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(NULL);
|
||||
rpc_forward *p = NULL, *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.
|
||||
*/
|
||||
dlog("Re-using packet forwarding slot - id %#x", p->rf_xid);
|
||||
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 *) NULL) < 0)
|
||||
plog(XLOG_ERROR, "can't bind privileged port (rpc_fwd)");
|
||||
|
||||
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, char *pkt, int len, struct sockaddr_in *fwdto, struct sockaddr_in *replyto, opaque_t cb_arg, fwd_fun *cb)
|
||||
{
|
||||
rpc_forward *p;
|
||||
u_int *pkt_int;
|
||||
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.
|
||||
*/
|
||||
switch (type_id & RPC_XID_MASK) {
|
||||
case RPC_XID_PORTMAP:
|
||||
dlog("Sending PORTMAP request %#x", type_id);
|
||||
break;
|
||||
case RPC_XID_MOUNTD:
|
||||
dlog("Sending MOUNTD request %#x", type_id);
|
||||
break;
|
||||
case RPC_XID_NFSPING:
|
||||
dlog("Sending NFS ping %#x", type_id);
|
||||
break;
|
||||
case RPC_XID_WEBNFS:
|
||||
dlog("Sending WebNFS lookup %#x", type_id);
|
||||
break;
|
||||
default:
|
||||
dlog("UNKNOWN RPC XID %#x", type_id);
|
||||
break;
|
||||
}
|
||||
|
||||
if (type_id & ~RPC_XID_MASK) {
|
||||
p = fwd_locate(type_id);
|
||||
if (p) {
|
||||
dlog("Discarding earlier rpc fwd handle");
|
||||
fwd_free(p);
|
||||
}
|
||||
} else {
|
||||
dlog("Allocating a new xid...");
|
||||
type_id = MK_RPC_XID(type_id, XID_ALLOC());
|
||||
}
|
||||
|
||||
p = fwd_alloc();
|
||||
if (!p)
|
||||
return ENOBUFS;
|
||||
|
||||
error = 0;
|
||||
|
||||
pkt_int = (u_int *) pkt;
|
||||
|
||||
/*
|
||||
* Get the original packet id
|
||||
*/
|
||||
p->rf_oldid = ntohl(*pkt_int);
|
||||
|
||||
/*
|
||||
* Replace with newly allocated id
|
||||
*/
|
||||
p->rf_xid = type_id;
|
||||
*pkt_int = htonl(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, sizeof(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 = cb_arg;
|
||||
|
||||
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;
|
||||
u_int pkt_xid;
|
||||
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);
|
||||
/*
|
||||
* Clear error indication, otherwise the error condition persists and
|
||||
* amd gets into an infinite loop.
|
||||
*/
|
||||
if (t_errno == TLOOK)
|
||||
t_rcvuderr(fwd_sock, NULL);
|
||||
}
|
||||
#else /* not HAVE_TRANSPORT_TYPE_TLI */
|
||||
rc = recvfrom(fwd_sock,
|
||||
(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;
|
||||
pkt_xid = ntohl(*pkt_int);
|
||||
|
||||
switch (pkt_xid & RPC_XID_MASK) {
|
||||
case RPC_XID_PORTMAP:
|
||||
dlog("Receiving PORTMAP reply %#x", pkt_xid);
|
||||
break;
|
||||
case RPC_XID_MOUNTD:
|
||||
dlog("Receiving MOUNTD reply %#x", pkt_xid);
|
||||
break;
|
||||
case RPC_XID_NFSPING:
|
||||
dlog("Receiving NFS ping %#x", pkt_xid);
|
||||
break;
|
||||
case RPC_XID_WEBNFS:
|
||||
dlog("Receiving WebNFS lookup %#x", pkt_xid);
|
||||
break;
|
||||
default:
|
||||
dlog("UNKNOWN RPC XID %#x", pkt_xid);
|
||||
break;
|
||||
}
|
||||
|
||||
p = fwd_locate(pkt_xid);
|
||||
if (!p) {
|
||||
dlog("Can't forward reply id %#x", pkt_xid);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (p->rf_fwd) {
|
||||
/*
|
||||
* Put the original message id back
|
||||
* into the packet.
|
||||
*/
|
||||
*pkt_int = htonl(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:;
|
||||
}
|
@ -1,300 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/sched.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
opaque_t cb_arg; /* Argument for callback */
|
||||
int w; /* everyone these days uses int, not a "union wait" */
|
||||
wchan_t 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, opaque_t ca)
|
||||
{
|
||||
pjob *p = ALLOC(struct pjob);
|
||||
|
||||
p->cb_fun = cf;
|
||||
p->cb_arg = 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, opaque_t ta, cb_fun *cf, opaque_t 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 = (wchan_t) p;
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
sigemptyset(&new); /* initialize 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 has returned to caller */
|
||||
|
||||
exit((*tf) (ta));
|
||||
/* firewall... */
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Schedule a task to be run when woken up
|
||||
*/
|
||||
void
|
||||
sched_task(cb_fun *cf, opaque_t ca, wchan_t wchan)
|
||||
{
|
||||
/*
|
||||
* Allocate a new task
|
||||
*/
|
||||
pjob *p = sched_job(cf, ca);
|
||||
|
||||
dlog("SLEEP on %p", wchan);
|
||||
p->wchan = wchan;
|
||||
p->pid = 0;
|
||||
p->w = 0; /* was memset (when ->w was union) */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
wakeupjob(pjob *p)
|
||||
{
|
||||
rem_que(&p->hdr);
|
||||
ins_que(&p->hdr, &proc_list_head);
|
||||
task_notify_todo++;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
wakeup(wchan_t wchan)
|
||||
{
|
||||
pjob *p, *p2;
|
||||
|
||||
if (!foreground)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Can't use 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, wchan_t wchan)
|
||||
{
|
||||
wakeup(wchan);
|
||||
}
|
||||
|
||||
|
||||
wchan_t
|
||||
get_mntfs_wchan(mntfs *mf)
|
||||
{
|
||||
if (mf &&
|
||||
mf->mf_ops &&
|
||||
mf->mf_ops->get_wchan)
|
||||
return mf->mf_ops->get_wchan(mf);
|
||||
return mf;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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 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 compatibility with strict POSIX.1 */
|
||||
p->cb_fun(WIFEXITED(p->w) ? WEXITSTATUS(p->w) : 0,
|
||||
WIFSIGNALED(p->w) ? WTERMSIG(p->w) : 0,
|
||||
p->cb_arg);
|
||||
}
|
||||
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 *) NULL)) > 0) {
|
||||
#endif /* not HAVE_WAITPID */
|
||||
pjob *p, *p2;
|
||||
|
||||
if (WIFSIGNALED(w))
|
||||
plog(XLOG_ERROR, "Process %d exited with signal %d",
|
||||
pid, WTERMSIG(w));
|
||||
else
|
||||
dlog("Process %d exited with status %d",
|
||||
pid, WEXITSTATUS(w));
|
||||
|
||||
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 */
|
||||
|
||||
if (p == HEAD(pjob, &proc_wait_list))
|
||||
dlog("can't locate task block for pid %d", pid);
|
||||
|
||||
/*
|
||||
* Must count down children inside the while loop, otherwise we won't
|
||||
* count them all, and NumChildren (and later backoff) will be set
|
||||
* incorrectly. SH/RUNIT 940519.
|
||||
*/
|
||||
if (--NumChildren < 0)
|
||||
NumChildren = 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);
|
||||
}
|
@ -1,205 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/srvr_amfs_auto.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Automount FS server ("localhost") modeling
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
|
||||
/* globals */
|
||||
|
||||
/* statics */
|
||||
static qelem amfs_auto_srvr_list = {&amfs_auto_srvr_list, &amfs_auto_srvr_list};
|
||||
static fserver *localhost;
|
||||
|
||||
|
||||
/*
|
||||
* Find an nfs server for the local host
|
||||
*/
|
||||
fserver *
|
||||
amfs_generic_find_srvr(mntfs *mf)
|
||||
{
|
||||
fserver *fs = localhost;
|
||||
|
||||
if (!fs) {
|
||||
fs = ALLOC(struct fserver);
|
||||
fs->fs_refc = 0;
|
||||
fs->fs_host = xstrdup("localhost");
|
||||
fs->fs_ip = NULL;
|
||||
fs->fs_cid = 0;
|
||||
fs->fs_pinger = AM_PINGER;
|
||||
fs->fs_flags = FSF_VALID | FSF_PING_UNINIT;
|
||||
fs->fs_type = "local";
|
||||
fs->fs_private = NULL;
|
||||
fs->fs_prfree = NULL;
|
||||
|
||||
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) {
|
||||
dlog("Deleting file server %s", fs->fs_host);
|
||||
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
|
||||
*/
|
||||
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 = (FSRV_ERROR(fs) || FSRV_ISDOWN(fs)) ? 19 : AM_TTL;
|
||||
|
||||
dlog("Last hard reference to file server %s - will timeout in %ds", fs->fs_host, ttl);
|
||||
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, state %s", fs->fs_host, fs->fs_type, state);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,92 +0,0 @@
|
||||
.\"
|
||||
.\" Copyright (c) 1997-2014 Erez Zadok
|
||||
.\" Copyright (c) 2005 Daniel P. Ottavio
|
||||
.\" 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. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\"
|
||||
.\" File: am-utils/amd/sun2amd.8
|
||||
.\"
|
||||
.TH SUN2AMD 8L "14 August 2005"
|
||||
|
||||
.SH NAME
|
||||
sun2amd \- converts Sun automount maps to Amd maps
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B sun2amd
|
||||
[-hH] [-i infile] [-o outfile]
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B sun2amd
|
||||
is used to convert Sun style automount maps to Amd style automount
|
||||
maps. By default
|
||||
.B sun2amd
|
||||
reads from stdin and writes to stdout.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B -h
|
||||
Help
|
||||
.TP
|
||||
.B -i
|
||||
Read Sun map information from specified file.
|
||||
.TP
|
||||
.B -o
|
||||
Write Amd map information to specified file.
|
||||
|
||||
.SH EXAMPLE
|
||||
To convert a Sun automount file called auto_foo to an Amd file called
|
||||
auto.amd type:
|
||||
|
||||
.B sun2amd
|
||||
-i auto_foo -o auto.amd
|
||||
|
||||
.SH BUGS
|
||||
* Can not convert master maps yet.
|
||||
|
||||
* NFS is the only automount type currently supported.
|
||||
|
||||
total_bug_count = number_found + 1;
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR automount(8),
|
||||
.BR amd(8)
|
||||
|
||||
.I "Linux NFS and Automounter Administration"
|
||||
by Erez Zadok, ISBN 0-7821-2739-8, (Sybex, 2001).
|
||||
.LP
|
||||
.I http://www.am-utils.org
|
||||
.LP
|
||||
|
||||
.SH AUTHOR
|
||||
Daniel P. Ottavio
|
||||
.I <dottavio@ic.sunysb.edu>
|
@ -1,203 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 Erez Zadok
|
||||
* Copyright (c) 2005 Daniel P. Ottavio
|
||||
* 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/sun2amd.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Translate Sun-syntax maps to Amd maps
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
#include <sun_map.h>
|
||||
|
||||
|
||||
/* dummies to make the program compile and link */
|
||||
struct amu_global_options gopt;
|
||||
#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
|
||||
# ifdef NEED_LIBWRAP_SEVERITY_VARIABLES
|
||||
/*
|
||||
* Some systems that define libwrap already define these two variables
|
||||
* in libwrap, while others don't: so I need to know precisely iff
|
||||
* to define these two severity variables.
|
||||
*/
|
||||
int allow_severity=0, deny_severity=0, rfc931_timeout=0;
|
||||
# endif /* NEED_LIBWRAP_SEVERITY_VARIABLES */
|
||||
#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
|
||||
|
||||
|
||||
/*
|
||||
* Parse the stream sun_in, convert the map information to amd, write
|
||||
* the results to amd_out.
|
||||
*/
|
||||
static int
|
||||
sun2amd_convert(FILE *sun_in, FILE *amd_out)
|
||||
{
|
||||
char line_buff[INFO_MAX_LINE_LEN], *tmp, *key, *entry;
|
||||
int pos, line = 0, retval = 1;
|
||||
|
||||
/* just to be safe */
|
||||
memset(line_buff, 0, sizeof(line_buff));
|
||||
|
||||
/* Read the input line by line and do the conversion. */
|
||||
while ((pos = file_read_line(line_buff, sizeof(line_buff), sun_in))) {
|
||||
line++;
|
||||
line_buff[pos - 1] = '\0';
|
||||
|
||||
/* remove comments */
|
||||
if ((tmp = strchr(line_buff, '#')) != NULL) {
|
||||
*tmp = '\0';
|
||||
}
|
||||
|
||||
/* find start of key */
|
||||
key = line_buff;
|
||||
while (*key != '\0' && isspace((unsigned char)*key)) {
|
||||
key++;
|
||||
}
|
||||
|
||||
/* ignore blank lines */
|
||||
if (*key == '\0') {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* find the end of the key and NULL terminate */
|
||||
tmp = key;
|
||||
while (*tmp != '\0' && isspace((unsigned char)*tmp) == 0) {
|
||||
tmp++;
|
||||
}
|
||||
if (*tmp == '\0') {
|
||||
plog(XLOG_ERROR, "map line %d has no entry", line);
|
||||
goto err;
|
||||
}
|
||||
*tmp++ = '\0';
|
||||
if (*tmp == '\0') {
|
||||
plog(XLOG_ERROR, "map line %d has no entry", line);
|
||||
goto err;
|
||||
}
|
||||
entry = tmp;
|
||||
|
||||
/* convert the sun entry to an amd entry */
|
||||
if ((tmp = sun_entry2amd(key, entry)) == NULL) {
|
||||
plog(XLOG_ERROR, "parse error on line %d", line);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (fprintf(amd_out, "%s %s\n", key, tmp) < 0) {
|
||||
plog(XLOG_ERROR, "can't write to output stream: %s", strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* just to be safe */
|
||||
memset(line_buff, 0, sizeof(line_buff));
|
||||
}
|
||||
|
||||
/* success */
|
||||
retval = 0;
|
||||
|
||||
err:
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* wrapper open function
|
||||
*/
|
||||
static FILE *
|
||||
sun2amd_open(const char *path, const char *mode)
|
||||
{
|
||||
FILE *retval = NULL;
|
||||
|
||||
if ((retval = fopen(path,mode)) == NULL) {
|
||||
plog(XLOG_ERROR,"could not open file %s",path);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* echo the usage and exit
|
||||
*/
|
||||
static void
|
||||
sun2amd_usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage : sun2amd [-hH] [-i infile] [-o outfile]\n"
|
||||
"-h\thelp\n"
|
||||
"-i\tspecify an infile (defaults to stdin)\n"
|
||||
"-o\tspecify an outfile (defaults to stdout)\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
/* default in/out to stdin/stdout */
|
||||
FILE *sun_in = stdin, *amd_out = stdout;
|
||||
int opt, retval = 1;
|
||||
|
||||
while ((opt = getopt(argc, argv , "i:o:hH")) != -1) {
|
||||
switch (opt) {
|
||||
|
||||
case 'i':
|
||||
if ((sun_in = sun2amd_open(optarg,"r")) == NULL) {
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
if ((amd_out = sun2amd_open(optarg,"w")) == NULL) {
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case 'H':
|
||||
sun2amd_usage();
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
retval = sun2amd_convert(sun_in,amd_out);
|
||||
|
||||
err:
|
||||
exit(retval);
|
||||
}
|
@ -1,595 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 Erez Zadok
|
||||
* Copyright (c) 2005 Daniel P. Ottavio
|
||||
* 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/sun_map.c
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
#include <sun_map.h>
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Add a data pointer to the end of the list.
|
||||
*/
|
||||
void
|
||||
sun_list_add(struct sun_list *list, qelem *item)
|
||||
{
|
||||
if (list->last == NULL) {
|
||||
list->last = item;
|
||||
list->first = item;
|
||||
item->q_back = NULL;
|
||||
}
|
||||
else {
|
||||
list->last->q_forw = item;
|
||||
item->q_back = list->last;
|
||||
list->last = item;
|
||||
}
|
||||
|
||||
item->q_forw = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Sun2Amd conversion routines
|
||||
*/
|
||||
|
||||
/*
|
||||
* AMD entry keywords
|
||||
*/
|
||||
#define AMD_OPTS_KW "addopts:=" /* add entry options */
|
||||
#define AMD_RHOST_KW "rhost:=" /* remote host */
|
||||
#define AMD_RFS_KW "rfs:=" /* remote file system */
|
||||
#define AMD_FS_KW "fs:=" /* local file system */
|
||||
#define AMD_DEV_KW "dev:=" /* device */
|
||||
#define AMD_TYPE_NFS_KW "type:=nfs;" /* fs type nfs */
|
||||
#define AMD_TYPE_AUTO_KW "type:=auto;" /* fs type auto */
|
||||
#define AMD_TYPE_CDFS_KW "type:=cdfs;" /* fs type cd */
|
||||
#define AMD_MAP_FS_KW "fs:=${map};" /* set the mount map as current map */
|
||||
#define AMD_MAP_PREF_KW "pref:=${key}/" /* set the mount map as current map */
|
||||
|
||||
/*
|
||||
* A set of string Sun fstypes.
|
||||
*/
|
||||
#define SUN_NFS_TYPE "nfs"
|
||||
#define SUN_HSFS_TYPE "hsfs" /* CD fs */
|
||||
#define SUN_AUTOFS_TYPE "autofs"
|
||||
#define SUN_CACHEFS_TYPE "cachefs"
|
||||
|
||||
#define SUN_KEY_SUB "&" /* Sun key substitution */
|
||||
|
||||
/* a set a Sun variable substitutions for map entries */
|
||||
#define SUN_ARCH "$ARCH" /* host architecture */
|
||||
#define SUN_CPU "$CPU" /* processor type */
|
||||
#define SUN_HOST "$HOST" /* host name */
|
||||
#define SUN_OSNAME "$OSNAME" /* OS name */
|
||||
#define SUN_OSREL "$OSREL" /* OS release */
|
||||
#define SUN_OSVERS "$OSVERS" /* OS version */
|
||||
#define SUN_NATISA "$NATISA" /* native instruction set */
|
||||
|
||||
/* a set of Amd variable substitutions */
|
||||
#define AMD_ARCH "${arch}" /* host architecture */
|
||||
#define AMD_HOST "${host}" /* host name */
|
||||
#define AMD_OSNAME "${os}" /* OS name */
|
||||
#define AMD_OSVER "${osver}" /* OS version */
|
||||
|
||||
|
||||
/*
|
||||
* Return a copy of src that has all occurrences of 'str' replaced
|
||||
* with sub.
|
||||
*
|
||||
* param src - the original string
|
||||
* param str - string that is the replaced with str
|
||||
* param sub - string that replaces an occurrences of 'delim'
|
||||
*
|
||||
* return - new string with str substitutions, NULL on error
|
||||
*/
|
||||
static char *
|
||||
sun_strsub(const char *src, const char *str, const char *sub)
|
||||
{
|
||||
|
||||
char *retval = NULL, *str_start, *str_end, *src_end;
|
||||
size_t total_size, first_half, second_half, sub_size;
|
||||
|
||||
/* assign pointers to the start and end of str */
|
||||
if ((str_start = strstr(src, str)) == NULL) {
|
||||
return retval;
|
||||
}
|
||||
str_end = (strlen(str) - 1) + str_start;
|
||||
|
||||
/* assign to the end of the src. */
|
||||
src_end = (strlen(src) - 1) + (char*)src;
|
||||
|
||||
/* size from the beginning of src to the start of str */
|
||||
first_half = (size_t)(str_start - src);
|
||||
|
||||
/* size from the end of str to the end of src */
|
||||
second_half = (size_t)(src_end - str_end);
|
||||
|
||||
sub_size = strlen(sub);
|
||||
|
||||
total_size = (first_half + sub_size + second_half + 1);
|
||||
|
||||
retval = (char*)xmalloc(total_size);
|
||||
memset(retval, 0, total_size);
|
||||
|
||||
/*
|
||||
* Put together the string such that the first half is copied
|
||||
* followed the sub and second half.
|
||||
*
|
||||
* We use strncpy instead of xstrlcpy because we are intentionally
|
||||
* causing truncation and we don't want this to cause errors in the
|
||||
* log.
|
||||
*/
|
||||
(void)strncpy(retval, src, first_half);
|
||||
(void)strncat(retval, sub, sub_size);
|
||||
(void)strncat(retval, str_end + 1, second_half);
|
||||
|
||||
if (strstr(retval, str) != NULL) {
|
||||
/*
|
||||
* If there is another occurrences of str call this function
|
||||
* recursively.
|
||||
*/
|
||||
char* tmp;
|
||||
if ((tmp = sun_strsub(retval, str, sub)) != NULL) {
|
||||
XFREE(retval);
|
||||
retval = tmp;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return a new string that is a copy of str, all occurrences of a Sun
|
||||
* variable substitutions are replaced by there equivalent Amd
|
||||
* substitutions.
|
||||
*
|
||||
* param str - source string
|
||||
*
|
||||
* return - A new string with the expansions, NULL if str does not
|
||||
* exist in src or error.
|
||||
*/
|
||||
static char *
|
||||
sun_expand2amd(const char *str)
|
||||
{
|
||||
|
||||
char *retval = NULL, *tmp = NULL, *tmp2 = NULL;
|
||||
const char *pos;
|
||||
|
||||
/*
|
||||
* Iterator through the string looking for '$' chars. For each '$'
|
||||
* found try to replace it with Sun variable substitutions. If we
|
||||
* find a '$' that is not a substation each of the i.e $blah than
|
||||
* each of the replace attempt will fail and we'll move on to the
|
||||
* next char.
|
||||
*/
|
||||
tmp = xstrdup(str);
|
||||
for (pos = str; *pos != '\0'; pos++) {
|
||||
if (*pos != '$') {
|
||||
continue;
|
||||
}
|
||||
if (tmp2 != NULL) {
|
||||
XFREE(tmp);
|
||||
tmp = tmp2;
|
||||
}
|
||||
|
||||
/*
|
||||
* If a 'replace' does not return NULL than a variable was
|
||||
* successfully substituted.
|
||||
*/
|
||||
|
||||
/* architecture */
|
||||
if ((tmp2 = sun_strsub(tmp, SUN_ARCH, AMD_ARCH)) != NULL) {
|
||||
continue;
|
||||
}
|
||||
/* cpu - there is not POSIX uname for cpu so just use machine */
|
||||
if ((tmp2 = sun_strsub(tmp, SUN_CPU, AMD_ARCH)) != NULL) {
|
||||
continue;
|
||||
}
|
||||
/* hostname */
|
||||
if ((tmp2 = sun_strsub(tmp, SUN_HOST, AMD_HOST)) != NULL) {
|
||||
continue;
|
||||
}
|
||||
/* os name */
|
||||
if ((tmp2 = sun_strsub(tmp, SUN_OSNAME, AMD_OSNAME)) != NULL) {
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* os release - Amd doesn't hava a OS release var just usr os
|
||||
* version or now.
|
||||
*/
|
||||
if ((tmp2 = sun_strsub(tmp, SUN_OSREL, AMD_OSVER)) != NULL) {
|
||||
continue;
|
||||
}
|
||||
/* os version */
|
||||
if ((tmp2 = sun_strsub(tmp, SUN_OSVERS, AMD_OSVER)) != NULL) {
|
||||
continue;
|
||||
}
|
||||
/* native instruction set - there is no POSIX natisa so just use system */
|
||||
if ((tmp2 = sun_strsub(tmp, SUN_NATISA, AMD_ARCH)) != NULL) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (tmp2 == NULL) {
|
||||
retval = tmp;
|
||||
}
|
||||
else {
|
||||
retval = tmp2;
|
||||
XFREE(tmp);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This is a wrapper function for appending Amd entry information to a
|
||||
* buffer. Any Sun variable substitutions will be converted into Amd
|
||||
* equivalents.
|
||||
*
|
||||
* param dest - destination buffer
|
||||
* param deslen - destination buffer length
|
||||
* param key - entry key, this might be needed for key substitutions
|
||||
* param str - string to append
|
||||
*/
|
||||
static void
|
||||
sun_append_str(char *dest,
|
||||
size_t destlen,
|
||||
const char *key,
|
||||
const char *str)
|
||||
{
|
||||
char *sub = NULL, *sub2 = NULL, *out = NULL;
|
||||
|
||||
/* By default we are going to just write the original string. */
|
||||
out = (char*)str;
|
||||
|
||||
/*
|
||||
* Resolve variable substitutions in two steps; 1) replace any key
|
||||
* map substitutions with the entry key 2) expand any variable
|
||||
* substitutions i.e $HOST.
|
||||
*
|
||||
* Try to replace the key substitution '&'. If this function returns
|
||||
* with a new string, one or more key subs. where replaced with the
|
||||
* entry key.
|
||||
*/
|
||||
if ((sub = sun_strsub(str, SUN_KEY_SUB, "${key}")) != NULL) {
|
||||
out = sub;
|
||||
/*
|
||||
* Try to convert any variable substitutions. If this function
|
||||
* returns a new string one or more var subs where expanded.
|
||||
*/
|
||||
if ((sub2 = sun_expand2amd(sub)) != NULL) {
|
||||
out = sub2;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Try to convert any variable substitutions. If this function
|
||||
* returns a new string one or more var subs where expanded.
|
||||
*/
|
||||
else if (out != NULL && (sub = sun_expand2amd(out)) != NULL) {
|
||||
out = sub;
|
||||
}
|
||||
|
||||
if (out != NULL) {
|
||||
xstrlcat(dest, out, destlen);
|
||||
}
|
||||
XFREE(sub);
|
||||
XFREE(sub2);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert the list of Sun mount options to Amd mount options. The
|
||||
* result is concatenated to dest.
|
||||
*
|
||||
* param dest - destination buffer
|
||||
* param destlen - destination buffer length
|
||||
* param key - automount key
|
||||
* param opt_list - list of Sun mount options
|
||||
*/
|
||||
static void
|
||||
sun_opts2amd(char *dest,
|
||||
size_t destlen,
|
||||
const char *key,
|
||||
const struct sun_opt *opt_list)
|
||||
{
|
||||
const struct sun_opt *opt;
|
||||
|
||||
xstrlcat(dest, AMD_OPTS_KW, destlen);
|
||||
|
||||
/* Iterate through each option and append it to the buffer. */
|
||||
for(opt = opt_list; opt != NULL; opt = NEXT(struct sun_opt, opt)) {
|
||||
sun_append_str(dest, destlen, key, opt->str);
|
||||
/* If there are more options add some commas. */
|
||||
if (NEXT(struct sun_opt, opt) != NULL) {
|
||||
xstrlcat(dest, ",", destlen);
|
||||
}
|
||||
}
|
||||
xstrlcat(dest, ";", destlen);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert the list of Sun mount locations to a list of Amd mount
|
||||
* locations. The result is concatenated to dest.
|
||||
*
|
||||
* param dest - destination buffer
|
||||
* param destlen - destination buffer length
|
||||
* param key - automount key
|
||||
* param local_list - list of Sun mount locations
|
||||
*/
|
||||
static void
|
||||
sun_locations2amd(char *dest,
|
||||
size_t destlen,
|
||||
const char *key,
|
||||
const struct sun_location *local_list)
|
||||
{
|
||||
const struct sun_location *local;
|
||||
const struct sun_host *host;
|
||||
|
||||
for (local = local_list;
|
||||
local != NULL;
|
||||
local = NEXT(struct sun_location,local)) {
|
||||
/*
|
||||
* Check to see if the list of hosts is empty. Some mount types
|
||||
* i.e cd-rom may have mount location with no host.
|
||||
*/
|
||||
if (local->host_list != NULL) {
|
||||
/* Write each host that belongs to this location. */
|
||||
for (host = local->host_list;
|
||||
host != NULL;
|
||||
host = NEXT(struct sun_host, host)) {
|
||||
/* set fstype NFS */
|
||||
xstrlcat(dest, AMD_TYPE_NFS_KW, destlen);
|
||||
/* add rhost key word */
|
||||
xstrlcat(dest, AMD_RHOST_KW, destlen);
|
||||
/* add host name */
|
||||
sun_append_str(dest, destlen, key, host->name);
|
||||
xstrlcat(dest, ";", destlen);
|
||||
/* add remote fs key word */
|
||||
xstrlcat(dest, AMD_RFS_KW, destlen);
|
||||
/* add local path */
|
||||
sun_append_str(dest, destlen, key, local->path);
|
||||
if (NEXT(struct sun_host, host) != NULL) {
|
||||
xstrlcat(dest, ";", destlen);
|
||||
xstrlcat(dest, " ", destlen);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* no host location */
|
||||
xstrlcat(dest, AMD_FS_KW, destlen);
|
||||
sun_append_str(dest, destlen, key, local->path);
|
||||
}
|
||||
if (NEXT(struct sun_location, local) != NULL) {
|
||||
/* add a space to separate each location */
|
||||
xstrlcat(dest, " ", destlen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert a Sun HSFS mount point to an Amd. The result is
|
||||
* concatenated intp dest.
|
||||
*
|
||||
* param dest - destination buffer
|
||||
* param destlen - destination buffer length
|
||||
* param key - automount key
|
||||
* param s_entry - Sun entry
|
||||
*/
|
||||
static void
|
||||
sun_hsfs2amd(char *dest,
|
||||
size_t destlen,
|
||||
const char *key,
|
||||
const struct sun_entry *s_entry)
|
||||
{
|
||||
/* set fstype CDFS */
|
||||
xstrlcat(dest, AMD_TYPE_CDFS_KW, destlen);
|
||||
/* set the cdrom device */
|
||||
xstrlcat(dest, AMD_DEV_KW, destlen);
|
||||
/* XXX: For now just assume that there is only one device. */
|
||||
xstrlcat(dest, s_entry->location_list->path, destlen);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert a Sun NFS automount entry to an Amd. The result is concatenated
|
||||
* into dest.
|
||||
*
|
||||
* param dest - destination buffer
|
||||
* param destlen - destination buffer length
|
||||
* param key - automount key
|
||||
* param s_entry - Sun entry
|
||||
*/
|
||||
static void
|
||||
sun_nfs2amd(char *dest,
|
||||
size_t destlen,
|
||||
const char *key,
|
||||
const struct sun_entry *s_entry)
|
||||
{
|
||||
if (s_entry->location_list != NULL) {
|
||||
/* write out the list of mountpoint locations */
|
||||
sun_locations2amd(dest, destlen, key, s_entry->location_list);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert a Sun multi-mount point entry to an Amd. This is done
|
||||
* using the Amd type auto. Each auto entry is separated with a \n.
|
||||
*
|
||||
* param dest - destination buffer
|
||||
* param destlen - destination buffer length
|
||||
* param key - automount key
|
||||
* param s_entry - Sun entry
|
||||
*/
|
||||
static void
|
||||
sun_multi2amd(char *dest,
|
||||
size_t destlen,
|
||||
const char *key,
|
||||
const struct sun_entry *s_entry)
|
||||
{
|
||||
const struct sun_mountpt *mountpt;
|
||||
|
||||
/* We need to setup a auto fs Amd automount point. */
|
||||
xstrlcat(dest, AMD_TYPE_AUTO_KW, destlen);
|
||||
xstrlcat(dest, AMD_MAP_FS_KW, destlen);
|
||||
xstrlcat(dest, AMD_MAP_PREF_KW, destlen);
|
||||
|
||||
/* write the mountpts to dest */
|
||||
for (mountpt = s_entry->mountpt_list;
|
||||
mountpt != NULL;
|
||||
mountpt = NEXT(struct sun_mountpt, mountpt)) {
|
||||
xstrlcat(dest, "\n", destlen);
|
||||
/* write the key */
|
||||
xstrlcat(dest, key, destlen);
|
||||
/* write the mount path */
|
||||
sun_append_str(dest, destlen, key, mountpt->path);
|
||||
/* space */
|
||||
xstrlcat(dest, " ", destlen);
|
||||
/* Write all the host locations for this mount point. */
|
||||
sun_locations2amd(dest, destlen, key, mountpt->location_list);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert the sun_entry into an Amd equivalent string.
|
||||
*
|
||||
* param key - automount key
|
||||
* param s_entry - Sun style automap entry
|
||||
*
|
||||
* return - Amd entry on succes, NULL on error
|
||||
*/
|
||||
char *
|
||||
sun_entry2amd(const char *key, const char *s_entry_str)
|
||||
{
|
||||
char *retval = NULL;
|
||||
char line_buff[INFO_MAX_LINE_LEN];
|
||||
int ws;
|
||||
struct sun_entry *s_entry = NULL;
|
||||
|
||||
/* The key should not be NULL. */
|
||||
if (key == NULL) {
|
||||
plog(XLOG_ERROR,"Sun key value was null");
|
||||
goto err;
|
||||
}
|
||||
/* The Sun entry string should never be NULL. */
|
||||
if (s_entry_str == NULL) {
|
||||
plog(XLOG_ERROR,"Sun entry value was null");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Make sure there are no trailing white spaces or '\n'. */
|
||||
xstrlcpy(line_buff, s_entry_str, sizeof(line_buff));
|
||||
ws = strlen(line_buff) - 1;
|
||||
while (ws >= 0 && (isspace((unsigned char)line_buff[ws]) || line_buff[ws] == '\n')) {
|
||||
line_buff[ws--] = '\0';
|
||||
}
|
||||
|
||||
/* Parse the sun entry line. */
|
||||
s_entry = sun_map_parse_read(line_buff);
|
||||
if (s_entry == NULL) {
|
||||
plog(XLOG_ERROR,"could not parse Sun style map");
|
||||
goto err;
|
||||
}
|
||||
|
||||
memset(line_buff, 0, sizeof(line_buff));
|
||||
|
||||
if (s_entry->opt_list != NULL) {
|
||||
/* write the mount options to the buffer */
|
||||
sun_opts2amd(line_buff, sizeof(line_buff), key, s_entry->opt_list);
|
||||
}
|
||||
|
||||
/* Check if this is a multi-mount entry. */
|
||||
if (s_entry->mountpt_list != NULL) {
|
||||
/* multi-mount point */
|
||||
sun_multi2amd(line_buff, sizeof(line_buff), key, s_entry);
|
||||
retval = xstrdup(line_buff);
|
||||
}
|
||||
else {
|
||||
/* single mount point */
|
||||
if (s_entry->fstype != NULL) {
|
||||
if (NSTREQ(s_entry->fstype, SUN_NFS_TYPE, strlen(SUN_NFS_TYPE))) {
|
||||
/* NFS Type */
|
||||
sun_nfs2amd(line_buff, sizeof(line_buff), key, s_entry);
|
||||
retval = xstrdup(line_buff);
|
||||
}
|
||||
else if (NSTREQ(s_entry->fstype, SUN_HSFS_TYPE, strlen(SUN_HSFS_TYPE))) {
|
||||
/* HSFS Type (CD fs) */
|
||||
sun_hsfs2amd(line_buff, sizeof(line_buff), key, s_entry);
|
||||
retval = xstrdup(line_buff);
|
||||
}
|
||||
/*
|
||||
* XXX: The following fstypes are not yet supported.
|
||||
*/
|
||||
else if (NSTREQ(s_entry->fstype, SUN_AUTOFS_TYPE, strlen(SUN_AUTOFS_TYPE))) {
|
||||
/* AutoFS Type */
|
||||
plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.",
|
||||
s_entry->fstype);
|
||||
goto err;
|
||||
|
||||
}
|
||||
else if (NSTREQ(s_entry->fstype, SUN_CACHEFS_TYPE, strlen(SUN_CACHEFS_TYPE))) {
|
||||
/* CacheFS Type */
|
||||
plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.",
|
||||
s_entry->fstype);
|
||||
goto err;
|
||||
}
|
||||
else {
|
||||
plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.",
|
||||
s_entry->fstype);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else {
|
||||
plog(XLOG_INFO, "No SUN fstype specified defaulting to NFS.");
|
||||
sun_nfs2amd(line_buff, sizeof(line_buff), key, s_entry);
|
||||
retval = xstrdup(line_buff);
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
XFREE(s_entry);
|
||||
return retval;
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 Erez Zadok
|
||||
* Copyright (c) 2005 Daniel P. Ottavio
|
||||
* 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/sun_map.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SUN_MAP_H
|
||||
#define _SUN_MAP_H
|
||||
|
||||
/* host */
|
||||
struct sun_host {
|
||||
qelem head; /* link-list header */
|
||||
char *name; /* hostname */
|
||||
int weight; /* weight given to the host */
|
||||
};
|
||||
|
||||
/* location */
|
||||
struct sun_location {
|
||||
qelem head; /* link-list header */
|
||||
char *path; /* server path */
|
||||
struct sun_host *host_list; /* list of hosts */
|
||||
};
|
||||
|
||||
/* sun mount option */
|
||||
struct sun_opt {
|
||||
qelem head; /* link-list header */
|
||||
char *str; /* option string */
|
||||
};
|
||||
|
||||
/* mount point */
|
||||
struct sun_mountpt {
|
||||
qelem head; /* link-list header */
|
||||
char *path; /* optional mount point path */
|
||||
char *fstype; /* filesystem type */
|
||||
struct sun_opt *opt_list; /* list of option strings */
|
||||
struct sun_location *location_list; /* list of 'struct s2a_location' */
|
||||
};
|
||||
|
||||
/* automount entry */
|
||||
struct sun_entry {
|
||||
qelem head; /* link-list header */
|
||||
char *key; /* auto map key */
|
||||
char *fstype; /* filesystem type */
|
||||
struct sun_opt *opt_list; /* list of mount options */
|
||||
struct sun_location *location_list; /* list of mount locations */
|
||||
struct sun_mountpt *mountpt_list; /* list of mount points */
|
||||
};
|
||||
|
||||
/*
|
||||
* automount map file
|
||||
*
|
||||
* XXX: Only a place holder structure, not implemented yet.
|
||||
*/
|
||||
struct sun_map {
|
||||
qelem head; /* link-list header */
|
||||
char *path; /* directory path of the map file */
|
||||
char *mount_dir; /* top level mount point for this map */
|
||||
int lookup; /* lookup type i.e file, yp, program, etc. */
|
||||
int direct_bool; /* set true if this map is a direct map */
|
||||
struct sun_opt *opt_list; /* list of global map options */
|
||||
struct sun_opt *include_list; /* list of included map files */
|
||||
struct sun_entry *entry_list; /* list of 'struct s2a_entry' */
|
||||
};
|
||||
|
||||
/*
|
||||
* master map file
|
||||
*
|
||||
* XXX: Only a place holder structure, not implemented yet.
|
||||
*/
|
||||
struct sun_mmap {
|
||||
qelem head; /* link-list header */
|
||||
struct sun_opt *include_list; /* list of included master maps */
|
||||
struct sun_map *amap_list; /* list of 'struct s2a_amap' */
|
||||
};
|
||||
|
||||
struct sun_list {
|
||||
qelem *first;
|
||||
qelem *last;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* EXTERNS
|
||||
*/
|
||||
extern char *sun_entry2amd(const char *, const char *);
|
||||
extern struct sun_entry *sun_map_parse_read(const char *);
|
||||
extern void sun_list_add(struct sun_list *, qelem *);
|
||||
|
||||
#endif /* not _SUN_MAP_H */
|
@ -1,492 +0,0 @@
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1997-2014 Erez Zadok
|
||||
* Copyright (c) 2005 Daniel P. Ottavio
|
||||
* 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/sun_map_parse.y
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amd.h>
|
||||
#include <sun_map.h>
|
||||
|
||||
|
||||
#define SUN_FSTYPE_STR "fstype="
|
||||
|
||||
|
||||
extern int sun_map_lex(void);
|
||||
extern int sun_map_error(const char *);
|
||||
extern void sun_map_tok_setbuff(const char *);
|
||||
extern int sun_map_parse(void);
|
||||
|
||||
struct sun_entry *sun_map_parse_read(const char *);
|
||||
|
||||
static struct sun_list *sun_entry_list = NULL;
|
||||
static struct sun_list *sun_opt_list = NULL;
|
||||
static struct sun_list *sun_host_list = NULL;
|
||||
static struct sun_list *sun_location_list = NULL;
|
||||
static struct sun_list *mountpt_list = NULL;
|
||||
static char *tmpFsType = NULL;
|
||||
|
||||
|
||||
/*
|
||||
* Each get* function returns a pointer to the corresponding global
|
||||
* list structure. If the structure is NULL than a new instance is
|
||||
* returned.
|
||||
*/
|
||||
static struct sun_list *get_sun_opt_list(void);
|
||||
static struct sun_list *get_sun_host_list(void);
|
||||
static struct sun_list *get_sun_location_list(void);
|
||||
static struct sun_list *get_mountpt_list(void);
|
||||
static struct sun_list *get_sun_entry_list(void);
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
char strval[2048];
|
||||
}
|
||||
|
||||
%token NEWLINE COMMENT WSPACE
|
||||
%token <strval> WORD
|
||||
|
||||
%%
|
||||
|
||||
amap : file
|
||||
;
|
||||
|
||||
file : new_lines entries
|
||||
| entries
|
||||
;
|
||||
|
||||
entries : entry
|
||||
| entry new_lines
|
||||
| entry new_lines entries
|
||||
;
|
||||
|
||||
new_lines : NEWLINE
|
||||
| NEWLINE new_lines
|
||||
;
|
||||
|
||||
entry : locations {
|
||||
|
||||
struct sun_list *list;
|
||||
struct sun_entry *entry;
|
||||
|
||||
/* allocate an entry */
|
||||
entry = CALLOC(struct sun_entry);
|
||||
|
||||
/*
|
||||
* Assign the global location list to this entry and reset the
|
||||
* global pointer. Reseting the global pointer will create a new
|
||||
* list instance next time get_sun_location_list() is called.
|
||||
*/
|
||||
list = get_sun_location_list();
|
||||
entry->location_list = (struct sun_location *)list->first;
|
||||
sun_location_list = NULL;
|
||||
|
||||
/* Add this entry to the entry list. */
|
||||
sun_list_add(get_sun_entry_list(), (qelem *)entry);
|
||||
}
|
||||
|
||||
| '-' options WSPACE locations {
|
||||
|
||||
struct sun_list *list;
|
||||
struct sun_entry *entry;
|
||||
|
||||
entry = CALLOC(struct sun_entry);
|
||||
|
||||
/* An fstype may have been defined in the 'options'. */
|
||||
if (tmpFsType != NULL) {
|
||||
entry->fstype = tmpFsType;
|
||||
tmpFsType = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assign the global location list to this entry and reset the
|
||||
* global pointer. Reseting the global pointer will create a new
|
||||
* list instance next time get_sun_location_list() is called.
|
||||
*/
|
||||
list = get_sun_location_list();
|
||||
entry->location_list = (struct sun_location *)list->first;
|
||||
sun_location_list = NULL;
|
||||
|
||||
/*
|
||||
* Assign the global opt list to this entry and reset the global
|
||||
* pointer. Reseting the global pointer will create a new list
|
||||
* instance next time get_sun_opt_list() is called.
|
||||
*/
|
||||
list = get_sun_opt_list();
|
||||
entry->opt_list = (struct sun_opt *)list->first;
|
||||
sun_opt_list = NULL;
|
||||
|
||||
/* Add this entry to the entry list. */
|
||||
sun_list_add(get_sun_entry_list(), (qelem *)entry);
|
||||
}
|
||||
|
||||
| mountpoints {
|
||||
|
||||
struct sun_list *list;
|
||||
struct sun_entry *entry;
|
||||
|
||||
/* allocate an entry */
|
||||
entry = CALLOC(struct sun_entry);
|
||||
|
||||
/*
|
||||
* Assign the global mountpt list to this entry and reset the global
|
||||
* pointer. Reseting the global pointer will create a new list
|
||||
* instance next time get_mountpt_list() is called.
|
||||
*/
|
||||
list = get_mountpt_list();
|
||||
entry->mountpt_list = (struct sun_mountpt *)list->first;
|
||||
mountpt_list = NULL;
|
||||
|
||||
/* Add this entry to the entry list. */
|
||||
sun_list_add(get_sun_entry_list(), (qelem *)entry);
|
||||
}
|
||||
|
||||
| '-' options WSPACE mountpoints {
|
||||
|
||||
struct sun_list *list;
|
||||
struct sun_entry *entry;
|
||||
|
||||
/* allocate an entry */
|
||||
entry = CALLOC(struct sun_entry);
|
||||
|
||||
/* An fstype may have been defined in the 'options'. */
|
||||
if (tmpFsType != NULL) {
|
||||
entry->fstype = tmpFsType;
|
||||
tmpFsType = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assign the global mountpt list to this entry and reset the global
|
||||
* pointer. Reseting the global pointer will create a new list
|
||||
* instance next time get_mountpt_list() is called.
|
||||
*/
|
||||
list = get_mountpt_list();
|
||||
entry->mountpt_list = (struct sun_mountpt *)list->first;
|
||||
mountpt_list = NULL;
|
||||
|
||||
/*
|
||||
* Assign the global opt list to this entry and reset the global
|
||||
* pointer. Reseting the global pointer will create a new list
|
||||
* instance next time get_sun_opt_list() is called.
|
||||
*/
|
||||
list = get_sun_opt_list();
|
||||
entry->opt_list = (struct sun_opt *)list->first;
|
||||
sun_opt_list = NULL;
|
||||
|
||||
/* Add this entry to the entry list. */
|
||||
sun_list_add(get_sun_entry_list(), (qelem *)entry);
|
||||
}
|
||||
;
|
||||
|
||||
mountpoints : mountpoint
|
||||
| mountpoint WSPACE mountpoints
|
||||
;
|
||||
|
||||
mountpoint : WORD WSPACE location {
|
||||
|
||||
struct sun_list *list;
|
||||
struct sun_mountpt *mountpt;
|
||||
|
||||
/* allocate a mountpt */
|
||||
mountpt = CALLOC(struct sun_mountpt);
|
||||
|
||||
/*
|
||||
* Assign the global loaction list to this entry and reset the
|
||||
* global pointer. Reseting the global pointer will create a new
|
||||
* list instance next time get_sun_location_list() is called.
|
||||
*/
|
||||
list = get_sun_location_list();
|
||||
mountpt->location_list = (struct sun_location *)list->first;
|
||||
sun_location_list = NULL;
|
||||
|
||||
mountpt->path = xstrdup($1);
|
||||
|
||||
/* Add this mountpt to the mountpt list. */
|
||||
sun_list_add(get_mountpt_list(), (qelem *)mountpt);
|
||||
}
|
||||
|
||||
| WORD WSPACE '-' options WSPACE location {
|
||||
|
||||
struct sun_list *list;
|
||||
struct sun_mountpt *mountpt;
|
||||
|
||||
/* allocate a mountpt */
|
||||
mountpt = CALLOC(struct sun_mountpt);
|
||||
|
||||
/* An fstype may have been defined in the 'options'. */
|
||||
if (tmpFsType != NULL) {
|
||||
mountpt->fstype = tmpFsType;
|
||||
tmpFsType = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assign the global location list to this entry and reset the
|
||||
* global pointer. Reseting the global pointer will create a new
|
||||
* list instance next time get_sun_location_list() is called.
|
||||
*/
|
||||
list = get_sun_location_list();
|
||||
mountpt->location_list = (struct sun_location *)list->first;
|
||||
sun_location_list = NULL;
|
||||
|
||||
/*
|
||||
* Assign the global opt list to this entry and reset the global
|
||||
* pointer. Reseting the global pointer will create a new list
|
||||
* instance next time get_sun_opt_list() is called.
|
||||
*/
|
||||
list = get_sun_opt_list();
|
||||
mountpt->opt_list = (struct sun_opt *)list->first;
|
||||
sun_opt_list = NULL;
|
||||
|
||||
mountpt->path = xstrdup($1);
|
||||
|
||||
/* Add this mountpt to the mountpt list. */
|
||||
sun_list_add(get_mountpt_list(), (qelem *)mountpt);
|
||||
}
|
||||
;
|
||||
|
||||
locations : location
|
||||
| location WSPACE locations
|
||||
;
|
||||
|
||||
location : hosts ':' WORD {
|
||||
|
||||
struct sun_list *list;
|
||||
struct sun_location *location;
|
||||
|
||||
/* allocate a new location */
|
||||
location = CALLOC(struct sun_location);
|
||||
|
||||
/*
|
||||
* Assign the global opt list to this entry and reset the global
|
||||
* pointer. Reseting the global pointer will create a new list
|
||||
* instance next time get_sun_opt_list() is called.
|
||||
*/
|
||||
list = get_sun_host_list();
|
||||
location->host_list = (struct sun_host *)list->first;
|
||||
sun_host_list = NULL;
|
||||
|
||||
location->path = xstrdup($3);
|
||||
|
||||
/* Add this location to the location list. */
|
||||
sun_list_add(get_sun_location_list(), (qelem *)location);
|
||||
}
|
||||
|
||||
| ':' WORD {
|
||||
|
||||
struct sun_location *location;
|
||||
|
||||
/* allocate a new location */
|
||||
location = CALLOC(struct sun_location);
|
||||
|
||||
location->path = xstrdup($2);
|
||||
|
||||
/* Add this location to the location list. */
|
||||
sun_list_add(get_sun_location_list(), (qelem *)location);
|
||||
}
|
||||
;
|
||||
|
||||
hosts : host
|
||||
| host ',' hosts
|
||||
;
|
||||
|
||||
host : WORD {
|
||||
|
||||
/* allocate a new host */
|
||||
struct sun_host *host = CALLOC(struct sun_host);
|
||||
|
||||
host->name = xstrdup($1);
|
||||
|
||||
/* Add this host to the host list. */
|
||||
sun_list_add(get_sun_host_list(),(qelem *)host);
|
||||
}
|
||||
|
||||
| WORD weight {
|
||||
|
||||
/*
|
||||
* It is assumed that the host for this rule was allocated by the
|
||||
* 'weight' rule and assigned to be the last host item on the host
|
||||
* list.
|
||||
*/
|
||||
struct sun_host *host = (struct sun_host *)sun_host_list->last;
|
||||
|
||||
host->name = xstrdup($1);
|
||||
}
|
||||
;
|
||||
|
||||
weight : '(' WORD ')' {
|
||||
|
||||
int val;
|
||||
/* allocate a new host */
|
||||
struct sun_host *host = CALLOC(struct sun_host);
|
||||
|
||||
val = atoi($2);
|
||||
|
||||
host->weight = val;
|
||||
|
||||
/* Add this host to the host list. */
|
||||
sun_list_add(get_sun_host_list(), (qelem *)host);
|
||||
}
|
||||
;
|
||||
|
||||
options : option
|
||||
| option ',' options
|
||||
;
|
||||
|
||||
option : WORD {
|
||||
|
||||
char *type;
|
||||
|
||||
/* check if this is an fstype option */
|
||||
if ((type = strstr($1,SUN_FSTYPE_STR)) != NULL) {
|
||||
/* parse out the fs type from the Sun fstype keyword */
|
||||
if ((type = type + strlen(SUN_FSTYPE_STR)) != NULL) {
|
||||
/*
|
||||
* This global fstype str will be assigned to the current being
|
||||
* parsed later in the parsing.
|
||||
*/
|
||||
tmpFsType = xstrdup(type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* If it is not an fstype option allocate an opt struct and assign
|
||||
* the value.
|
||||
*/
|
||||
struct sun_opt *opt = CALLOC(struct sun_opt);
|
||||
opt->str = xstrdup($1);
|
||||
/* Add this opt to the opt list. */
|
||||
sun_list_add(get_sun_opt_list(), (qelem *)opt);
|
||||
}
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
/*
|
||||
* Parse 'map_data' which is assumed to be a Sun-syle map. If
|
||||
* successful a sun_entry is returned.
|
||||
*
|
||||
* The parser is designed to parse map entries with out the keys. For
|
||||
* example the entry:
|
||||
*
|
||||
* usr -ro pluto:/usr/local
|
||||
*
|
||||
* should be passed to the parser as:
|
||||
*
|
||||
* -ro pluto:/usr/local
|
||||
*
|
||||
* The reason for this is that the Amd info services already strip off
|
||||
* the key when they read map info.
|
||||
*/
|
||||
struct sun_entry *
|
||||
sun_map_parse_read(const char *map_data)
|
||||
{
|
||||
struct sun_entry *retval = NULL;
|
||||
|
||||
/* pass map_data to lex */
|
||||
sun_map_tok_setbuff(map_data);
|
||||
|
||||
/* call yacc */
|
||||
sun_map_parse();
|
||||
|
||||
if (sun_entry_list != NULL) {
|
||||
/* return the first Sun entry in the list */
|
||||
retval = (struct sun_entry*)sun_entry_list->first;
|
||||
sun_entry_list = NULL;
|
||||
}
|
||||
else {
|
||||
plog(XLOG_ERROR, "Sun map parser did not produce data structs.");
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static struct sun_list *
|
||||
get_sun_entry_list(void)
|
||||
{
|
||||
if (sun_entry_list == NULL) {
|
||||
sun_entry_list = CALLOC(struct sun_list);
|
||||
}
|
||||
return sun_entry_list;
|
||||
}
|
||||
|
||||
|
||||
static struct sun_list *
|
||||
get_mountpt_list(void)
|
||||
{
|
||||
if (mountpt_list == NULL) {
|
||||
mountpt_list = CALLOC(struct sun_list);
|
||||
}
|
||||
return mountpt_list;
|
||||
}
|
||||
|
||||
|
||||
static struct sun_list *
|
||||
get_sun_location_list(void)
|
||||
{
|
||||
if (sun_location_list == NULL) {
|
||||
sun_location_list = CALLOC(struct sun_list);
|
||||
}
|
||||
return sun_location_list;
|
||||
}
|
||||
|
||||
|
||||
static struct sun_list *
|
||||
get_sun_host_list(void)
|
||||
{
|
||||
if (sun_host_list == NULL) {
|
||||
sun_host_list = CALLOC(struct sun_list);
|
||||
}
|
||||
return sun_host_list;
|
||||
}
|
||||
|
||||
|
||||
static struct sun_list *
|
||||
get_sun_opt_list(void)
|
||||
{
|
||||
if (sun_opt_list == NULL) {
|
||||
sun_opt_list = CALLOC(struct sun_list);
|
||||
}
|
||||
return sun_opt_list;
|
||||
}
|
@ -1,233 +0,0 @@
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1997-2014 Erez Zadok
|
||||
* Copyright (c) 2005 Daniel P. Ottavio
|
||||
* 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amd/sun_map_tok.l
|
||||
*
|
||||
*/
|
||||
|
||||
#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 <sun_map_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 using GNU flex.
|
||||
* These must not be defined if using standard lex
|
||||
*/
|
||||
#ifdef FLEX_SCANNER
|
||||
# ifndef ECHO
|
||||
# define ECHO __IGNORE(fwrite( yytext, yyleng, 1, yyout ))
|
||||
# endif /* not ECHO */
|
||||
#endif /* FLEX_SCANNER */
|
||||
|
||||
int yylex(void);
|
||||
int sun_map_error(const char *);
|
||||
|
||||
/*
|
||||
* We need to configure lex to parse from a string
|
||||
* instead of a file. Each version of lex has it's
|
||||
* own way of doing this (sigh).
|
||||
*/
|
||||
|
||||
/* assign the buffer to parse */
|
||||
void sun_map_tok_setbuff(const char* buff);
|
||||
|
||||
/* buffer that contains the string to parse */
|
||||
const char *sun_map_tok_buff = NULL;
|
||||
|
||||
#ifdef FLEX_SCANNER
|
||||
/*
|
||||
* The flex scanner uses the YY_INPUT to parse the input.
|
||||
* We need to redefine it so that it can parse strings.
|
||||
* In addition to the above string buffer we need to have
|
||||
* a position pointer and a end pointer.
|
||||
*/
|
||||
|
||||
/* current position of the buffer */
|
||||
const char *sun_map_tok_pos = NULL;
|
||||
|
||||
/* size of the buffer */
|
||||
const char *sun_map_tok_end = NULL;
|
||||
|
||||
/* copies the current position + maxsize into buff */
|
||||
int sun_map_input(char *buff, int maxsize);
|
||||
|
||||
# undef YY_INPUT
|
||||
# define YY_INPUT(buff,result,maxsize) (result = sun_map_input(buff,maxsize))
|
||||
|
||||
#else
|
||||
/*
|
||||
* If this is not Flex than fall back to an AT&T style lex.
|
||||
* We can parse strings by redefining input and unput.
|
||||
*/
|
||||
#undef input
|
||||
#undef unput
|
||||
#define input() (*(char *)sun_map_tok_buff++)
|
||||
#define unput(c) (*(char *)--sun_map_tok_buff = c)
|
||||
|
||||
#endif /* FLEX_SCANNER */
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#if !defined(yywrap) || defined(yylex)
|
||||
int yywrap(void);
|
||||
#endif /* not yywrap or yylex */
|
||||
|
||||
/* no need to use yywrap() */
|
||||
#define YY_SKIP_YYWRAP
|
||||
|
||||
int sun_map_line = 1;
|
||||
int sun_map_tokpos = 1;
|
||||
|
||||
%}
|
||||
|
||||
/* This option causes Solaris lex to fail. Use flex. See BUGS file */
|
||||
/* no need to use yyunput() */
|
||||
%option nounput
|
||||
%option noinput
|
||||
|
||||
/* allocate more output slots so lex scanners don't run out of mem */
|
||||
%o 1024
|
||||
|
||||
WORD_REX [A-Za-z0-9_/&\.$=]+[A-Za-z0-9_/&\.$=-]*
|
||||
COMMENT_REX ^#.*\n
|
||||
WSPACE_REX [ \t]*
|
||||
NEWLINE_REX [ \t]*\n
|
||||
CONTINUE_REX "\\"\n
|
||||
|
||||
%%
|
||||
|
||||
{WORD_REX} {
|
||||
sun_map_tokpos += yyleng;
|
||||
xstrlcpy((char *)sun_map_lval.strval,(const char *)yytext,sizeof(sun_map_lval.strval));
|
||||
return WORD;
|
||||
}
|
||||
|
||||
{WSPACE_REX} {
|
||||
sun_map_tokpos += yyleng;
|
||||
return WSPACE;
|
||||
}
|
||||
|
||||
{NEWLINE_REX} {
|
||||
sun_map_tokpos = 0;
|
||||
sun_map_line++;
|
||||
return NEWLINE;
|
||||
}
|
||||
|
||||
{CONTINUE_REX} {
|
||||
sun_map_tokpos = 0;
|
||||
sun_map_line++;
|
||||
}
|
||||
|
||||
{COMMENT_REX} {
|
||||
sun_map_line++;
|
||||
}
|
||||
|
||||
. {
|
||||
return yytext[0];
|
||||
}
|
||||
|
||||
%%
|
||||
|
||||
|
||||
int
|
||||
sun_map_error(const char* s)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef FLEX_SCANNER
|
||||
void
|
||||
sun_map_tok_setbuff(const char* buff)
|
||||
{
|
||||
sun_map_tok_end = buff + strlen(buff);
|
||||
sun_map_tok_pos = buff;
|
||||
sun_map_tok_buff = buff;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sun_map_input(char *buff, int maxsize)
|
||||
{
|
||||
int size = MIN(maxsize, (sun_map_tok_end - sun_map_tok_pos));
|
||||
if (size > 0) {
|
||||
memcpy(buff,sun_map_tok_pos,size);
|
||||
sun_map_tok_pos += size;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
#else
|
||||
void
|
||||
sun_map_tok_setbuff(const char* buff)
|
||||
{
|
||||
sun_map_tok_buff = buff;
|
||||
}
|
||||
|
||||
#endif /* FLEX_SCANNER */
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#if !defined(yywrap) || defined(yylex)
|
||||
int yywrap(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif /* not yywrap or yylex */
|
@ -1,2 +0,0 @@
|
||||
#!/bin/sh
|
||||
./amd -v 2> /dev/null
|
@ -1,307 +0,0 @@
|
||||
.\"
|
||||
.\" Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\"
|
||||
.\" File: am-utils/amq/amq.8
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 31, 2016
|
||||
.Dt AMQ 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm amq
|
||||
.Nd automounter query tool
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl fimpqsvwHTU
|
||||
.Op Fl h Ar hostname
|
||||
.Op Fl l Ar log_file
|
||||
.Op Fl x Ar log_options
|
||||
.Op Fl D Ar debug_options
|
||||
.Op Fl P Ar program_number
|
||||
.Op Oo Fl u Oc Ar directory ...
|
||||
.Sh DESCRIPTION
|
||||
.Bf -symbolic
|
||||
This command is obsolete.
|
||||
Users are advised to use
|
||||
.Xr autofs 5
|
||||
instead.
|
||||
.Ef
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility
|
||||
provides a simple way of determining the current state of the
|
||||
.Xr amd 8
|
||||
program.
|
||||
Communication is by
|
||||
.Tn RPC .
|
||||
Three modes of operation are supported by the current protocol.
|
||||
By default
|
||||
a list of mount points and auto-mounted file systems is output.
|
||||
An
|
||||
alternative host can be specified using the
|
||||
.Fl h
|
||||
option.
|
||||
.Pp
|
||||
If
|
||||
.Ar directory
|
||||
names are given, as output by default, then per file system
|
||||
information is displayed.
|
||||
.Sh OPTIONS
|
||||
.Bl -tag -width indent
|
||||
.It Fl f
|
||||
Ask the automounter to flush the internal caches and reload all the maps.
|
||||
.It Fl h Ar hostname
|
||||
Specify an alternate host to query.
|
||||
By default the local host is used.
|
||||
In
|
||||
an
|
||||
.Tn HP-UX
|
||||
cluster, the root server is queried by default, since that is the system on
|
||||
which the automounter is normally run.
|
||||
.TP
|
||||
.It Fl i
|
||||
Print information about the mount maps.
|
||||
.TP
|
||||
.It Fl l Ar log_file
|
||||
Tell
|
||||
.Xr amd 8
|
||||
to use
|
||||
.Ar log_file
|
||||
as the log file name.
|
||||
For security reasons, this must be the same log file
|
||||
which
|
||||
.Xr amd 8
|
||||
used when started.
|
||||
This option is therefore only useful to
|
||||
refresh
|
||||
.Nm amd Ns 's
|
||||
open file handle on the log file, so that it can be rotated
|
||||
and compressed via daily cron jobs.
|
||||
.It Fl m
|
||||
Ask the automounter to provide a list of mounted file systems, including the
|
||||
number of references to each file system and any error which occurred while
|
||||
mounting.
|
||||
.It Fl p
|
||||
Return the process ID of the remote or locally running
|
||||
.Xr amd 8 .
|
||||
Useful when you
|
||||
need to send a signal to the local
|
||||
.Xr amd 8
|
||||
process, and would rather not have to
|
||||
search through the process table.
|
||||
This option is used in the
|
||||
.Pa ctl-amd
|
||||
script.
|
||||
.TP
|
||||
.It Fl q
|
||||
Suppress error messages produced when attempting synchronous unmounts
|
||||
with the
|
||||
.B \-u
|
||||
option.
|
||||
.TP
|
||||
.It Fl s
|
||||
Ask the automounter to provide system-wide mount statistics.
|
||||
.It Fl u
|
||||
Ask the automounter to unmount the file systems named in
|
||||
.Ar directory
|
||||
instead of providing
|
||||
information about them.
|
||||
Unmounts are requested, not forced.
|
||||
They merely
|
||||
cause the mounted file system to timeout, which will be picked up by
|
||||
.Nm amd Ns 's
|
||||
main scheduler thus causing the normal timeout action to be taken.
|
||||
If the
|
||||
.B \-u
|
||||
option is repeated,
|
||||
.B amq
|
||||
will attempt to unmount the file system synchronously by waiting until
|
||||
the timeout action is taken and returning an error if the unmount
|
||||
fails.
|
||||
Any error messages produced may be suppressed with the
|
||||
.B \-q
|
||||
option.
|
||||
.TP
|
||||
.It Fl v
|
||||
Ask the automounter for its version information. This is a subset of the
|
||||
information output by
|
||||
.Xr amd 8 Ns 's
|
||||
.Fl v
|
||||
option.
|
||||
.It Fl w
|
||||
Translate a full pathname as returned by
|
||||
.Xr getcwd 3
|
||||
into a short
|
||||
.Xr amd 8
|
||||
pathname that goes through its mount points.
|
||||
This option requires that
|
||||
.Xr amd 8
|
||||
is running.
|
||||
.It Fl x Ar log_options
|
||||
Ask the automounter to use the logging options specified in
|
||||
.Ar log_options
|
||||
from now on. Note that the "fatal" and "error" options cannot be turned
|
||||
off.
|
||||
.It Fl D Ar debug_options
|
||||
.BI \-D " debug_options"
|
||||
Ask the automounter to use the debugging options specified in
|
||||
.Ar debug_options
|
||||
from now on.
|
||||
.It Fl H
|
||||
Display short usage message.
|
||||
.It Fl P Ar program_number
|
||||
Contact an alternate running
|
||||
.Xr amd 8
|
||||
that had registered itself on a different
|
||||
.Tn RPC
|
||||
.Ar program_number
|
||||
and apply all other operations to that instance of the automounter.
|
||||
This is
|
||||
useful when you run multiple copies of
|
||||
.Xr amd 8 ,
|
||||
and need to manage each
|
||||
one separately.
|
||||
If not specified,
|
||||
.Nm
|
||||
will use the default program number for
|
||||
.Xr amd 8 ,
|
||||
300019.
|
||||
For security reasons, the only alternate program numbers
|
||||
.Xr amd 8
|
||||
can use range from 300019 to 300029, inclusive.
|
||||
.It Fl T
|
||||
Contact
|
||||
.Xr amd 8
|
||||
using the TCP transport only.
|
||||
Normally
|
||||
.Nm
|
||||
will try TCP, and if that failed, will try UDP.
|
||||
.It Fl U
|
||||
Contact
|
||||
.Xr amd 8
|
||||
using UDP (connectionless) transport only.
|
||||
Normally
|
||||
.Nm
|
||||
will try TCP, and if that failed, will try UDP.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width ".Pa amq.x" -compact
|
||||
.It Pa amq.x
|
||||
.Tn RPC
|
||||
protocol description.
|
||||
.El
|
||||
.Sh CAVEATS
|
||||
The
|
||||
.Nm
|
||||
utility
|
||||
uses a Sun registered
|
||||
.Tn RPC
|
||||
program number (300019 decimal) which may not
|
||||
be in the
|
||||
.Xr rpc 5
|
||||
database.
|
||||
.Pp
|
||||
If the TCP wrappers library is available, and the
|
||||
.Va use_tcpwrappers
|
||||
global
|
||||
.Xr amd.conf 5
|
||||
option is set to
|
||||
.Dq Li yes ,
|
||||
then
|
||||
.Xr amd 8
|
||||
will verify that the host running
|
||||
.Nm
|
||||
is authorized to connect.
|
||||
The
|
||||
.Dq Li amd
|
||||
service name must be used in the
|
||||
.Pa /etc/hosts.allow
|
||||
and
|
||||
.Pa /etc/hosts.deny
|
||||
files.
|
||||
For example, to allow only localhost to connect to
|
||||
.Xr amd 8 ,
|
||||
add this line to
|
||||
.Pa /etc/hosts.allow :
|
||||
.Pp
|
||||
.Dl "amd: localhost"
|
||||
.Pp
|
||||
and this line to
|
||||
.Pa /etc/hosts.deny :
|
||||
.Pp
|
||||
.RS
|
||||
.Dl "amd: ALL"
|
||||
.Sh SEE ALSO
|
||||
.Xr amd.conf 5 ,
|
||||
.Xr hosts_access 5 .
|
||||
.Xr amd 8 ,
|
||||
.\" .Xr ctl-amd 8 ,
|
||||
.Pp
|
||||
.Dq am-utils
|
||||
.Xr info 1
|
||||
entry.
|
||||
.Rs
|
||||
.%A Erez Zadok
|
||||
.%B "Linux NFS and Automounter Administration"
|
||||
.%O ISBN 0-7821-2739-8
|
||||
.%I Sybex
|
||||
.%D 2001
|
||||
.Re
|
||||
.Pp
|
||||
.Pa http://www.am-utils.org/
|
||||
.Rs
|
||||
.%T Amd \- The 4.4 BSD Automounter
|
||||
.Re
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility
|
||||
first appeared in
|
||||
.Bx 4.4 .
|
||||
.Sh AUTHORS
|
||||
.An Jan-Simon Pendry Aq jsp@doc.ic.ac.uk ,
|
||||
Department of Computing, Imperial College, London, UK.
|
||||
.Pp
|
||||
.An Erez Zadok Aq ezk@cs.sunysb.edu ,
|
||||
Computer Science Department, Stony Brook
|
||||
University, Stony Brook, New York, USA.
|
||||
.Pp
|
||||
Other authors and contributors to
|
||||
.Nm am-utils
|
||||
are listed in the
|
||||
.Pa AUTHORS
|
||||
file distributed with
|
||||
.Nm am-utils .
|
@ -1,851 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amq/amq.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Automounter query tool
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include <am_defs.h>
|
||||
#include <amq.h>
|
||||
|
||||
/* locals */
|
||||
static int flush_flag;
|
||||
static int getpid_flag;
|
||||
static int getpwd_flag;
|
||||
static int getvers_flag;
|
||||
static int minfo_flag;
|
||||
static int mapinfo_flag;
|
||||
static int quiet_flag;
|
||||
static int stats_flag;
|
||||
static int unmount_flag;
|
||||
static int use_tcp_flag;
|
||||
static int use_udp_flag;
|
||||
static u_long amd_program_number = AMQ_PROGRAM;
|
||||
static char *debug_opts;
|
||||
static char *amq_logfile;
|
||||
static char *xlog_optstr;
|
||||
static char localhost[] = "localhost";
|
||||
static char *def_server = localhost;
|
||||
|
||||
/* externals */
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
/* structures */
|
||||
enum show_opt {
|
||||
Full, Stats, Calc, Short, ShowDone
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
time_print(time_type tt)
|
||||
{
|
||||
time_t t = (time_t)(intptr_t)tt;
|
||||
struct tm *tp = localtime(&t);
|
||||
printf("%02d/%02d/%04d %02d:%02d:%02d",
|
||||
tp->tm_mon + 1, tp->tm_mday,
|
||||
tp->tm_year < 1900 ? tp->tm_year + 1900 : tp->tm_year,
|
||||
tp->tm_hour, tp->tm_min, tp->tm_sec);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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:
|
||||
{
|
||||
printf("%-*.*s %-*.*s %-*.*s %s\n\t%-5d %-7d %-6d %-7d %-7d %-6d",
|
||||
*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);
|
||||
time_print(mt->mt_mounttime);
|
||||
printf("\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case Stats:
|
||||
{
|
||||
printf("%-*.*s %-5d %-7d %-6d %-7d %-7d %-6d ",
|
||||
*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);
|
||||
time_print(mt->mt_mounttime);
|
||||
printf("\n");
|
||||
}
|
||||
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 pwd data
|
||||
*/
|
||||
static void
|
||||
show_pwd(amq_mount_tree *mt, char *path, size_t l, int *flag)
|
||||
{
|
||||
int len;
|
||||
|
||||
while (mt) {
|
||||
len = strlen(mt->mt_mountpoint);
|
||||
if (NSTREQ(path, mt->mt_mountpoint, len) &&
|
||||
!STREQ(mt->mt_directory, mt->mt_mountpoint)) {
|
||||
char buf[MAXPATHLEN+1]; /* must be same size as 'path' */
|
||||
xstrlcpy(buf, mt->mt_directory, sizeof(buf));
|
||||
xstrlcat(buf, &path[len], sizeof(buf));
|
||||
xstrlcpy(path, buf, l);
|
||||
*flag = 1;
|
||||
}
|
||||
show_pwd(mt->mt_next, path, l, flag);
|
||||
mt = mt->mt_child;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
u_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) {
|
||||
printf(" (%s)", strerror(mi->mi_error));
|
||||
} else if (mi->mi_error < 0) {
|
||||
fputs(" (in progress)", stdout);
|
||||
}
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
show_map(amq_map_info *mi)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
show_mapinfo(amq_map_info_list *ml, enum show_opt e, int *nwid, int *wwid)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
switch (e) {
|
||||
|
||||
case Calc:
|
||||
{
|
||||
for (i = 0; i < ml->amq_map_info_list_len; i++) {
|
||||
amq_map_info *mi = &ml->amq_map_info_list_val[i];
|
||||
int nw = strlen(mi->mi_name);
|
||||
int ww = strlen(mi->mi_wildcard ? mi->mi_wildcard : "(null");
|
||||
if (nw > *nwid)
|
||||
*nwid = nw;
|
||||
if (ww > *wwid)
|
||||
*wwid = ww;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Full:
|
||||
{
|
||||
printf("%-*.*s %-*.*s %-8.8s %-7.7s %-7.7s %-7.7s %-s Modified\n",
|
||||
*nwid, *nwid, "Name",
|
||||
*wwid, *wwid, "Wild",
|
||||
"Flags", "Refcnt", "Entries", "Reloads", "Stat");
|
||||
for (i = 0; i < ml->amq_map_info_list_len; i++) {
|
||||
amq_map_info *mi = &ml->amq_map_info_list_val[i];
|
||||
printf("%-*.*s %*.*s %-8x %-7d %-7d %-7d %s ",
|
||||
*nwid, *nwid, mi->mi_name,
|
||||
*wwid, *wwid, mi->mi_wildcard,
|
||||
mi->mi_flags, mi->mi_refc, mi->mi_nentries, mi->mi_reloads,
|
||||
mi->mi_up == -1 ? "root" : (mi->mi_up ? " up" : "down"));
|
||||
time_print(mi->mi_modify);
|
||||
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) */
|
||||
|
||||
|
||||
static void
|
||||
print_umnt_error(amq_sync_umnt *rv, const char *fs)
|
||||
{
|
||||
|
||||
switch (rv->au_etype) {
|
||||
case AMQ_UMNT_OK:
|
||||
break;
|
||||
case AMQ_UMNT_FAILED:
|
||||
printf("unmount failed: %s\n", strerror(rv->au_errno));
|
||||
break;
|
||||
case AMQ_UMNT_FORK:
|
||||
if (rv->au_errno == 0)
|
||||
printf("%s is not mounted\n", fs);
|
||||
else
|
||||
printf("falling back to asynchronous unmount: %s\n",
|
||||
strerror(rv->au_errno));
|
||||
break;
|
||||
case AMQ_UMNT_READ:
|
||||
printf("pipe read error: %s\n", strerror(rv->au_errno));
|
||||
break;
|
||||
case AMQ_UMNT_SERVER:
|
||||
printf("amd server down\n");
|
||||
break;
|
||||
case AMQ_UMNT_SIGNAL:
|
||||
printf("got signal: %d\n", rv->au_signal);
|
||||
break;
|
||||
/*
|
||||
* Omit default so the compiler can check for missing cases.
|
||||
*
|
||||
default:
|
||||
break;
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
amu_sync_umnt_to_retval(amq_sync_umnt *rv)
|
||||
{
|
||||
switch (rv->au_etype) {
|
||||
case AMQ_UMNT_FORK:
|
||||
if (rv->au_errno == 0) {
|
||||
/*
|
||||
* We allow this error so that things like:
|
||||
* amq -uu /l/cd0d && eject cd0
|
||||
* will work when /l/cd0d is not mounted.
|
||||
* XXX - We still print an error message.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
/*FALLTHROUGH*/
|
||||
default:
|
||||
return rv->au_etype;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
clnt_failed(CLIENT *clnt, char *server)
|
||||
{
|
||||
fprintf(stderr, "%s: ", am_get_progname());
|
||||
clnt_perror(clnt, server);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MAIN
|
||||
*/
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int opt_ch;
|
||||
int errs = 0;
|
||||
char *server;
|
||||
struct sockaddr_in server_addr;
|
||||
CLIENT *clnt = NULL;
|
||||
struct hostent *hp;
|
||||
int nodefault = 0;
|
||||
struct timeval tv;
|
||||
char *progname = NULL;
|
||||
|
||||
/*
|
||||
* Compute program name
|
||||
*/
|
||||
if (argv[0]) {
|
||||
progname = strrchr(argv[0], '/');
|
||||
if (progname && progname[1])
|
||||
progname++;
|
||||
else
|
||||
progname = argv[0];
|
||||
}
|
||||
if (!progname)
|
||||
progname = "amq";
|
||||
am_set_progname(progname);
|
||||
|
||||
/*
|
||||
* Parse arguments
|
||||
*/
|
||||
while ((opt_ch = getopt(argc, argv, "Hfh:il:mqsuvx:D:pP:TUw")) != -1)
|
||||
switch (opt_ch) {
|
||||
case 'H':
|
||||
goto show_usage;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
flush_flag = 1;
|
||||
nodefault = 1;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
def_server = optarg;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
mapinfo_flag = 1;
|
||||
nodefault = 1;
|
||||
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 'q':
|
||||
quiet_flag = 1;
|
||||
nodefault = 1;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
stats_flag = 1;
|
||||
nodefault = 1;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
unmount_flag++;
|
||||
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 'P':
|
||||
amd_program_number = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
use_tcp_flag = 1;
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
use_udp_flag = 1;
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
getpwd_flag = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
errs = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (optind == argc) {
|
||||
if (unmount_flag)
|
||||
errs = 1;
|
||||
}
|
||||
if (errs) {
|
||||
show_usage:
|
||||
fprintf(stderr, "\
|
||||
Usage: %s [-fimpqsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\
|
||||
\t[-x log_options] [-D debug_options]\n\
|
||||
\t[-P program_number] [[-u[u]] directory ...]\n",
|
||||
am_get_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",
|
||||
am_get_progname(), server);
|
||||
exit(1);
|
||||
}
|
||||
memset(&server_addr, 0, sizeof(server_addr));
|
||||
/* as per POSIX, sin_len need not be set (used internally by kernel) */
|
||||
server_addr.sin_family = AF_INET;
|
||||
if (hp) {
|
||||
memmove((voidp) &server_addr.sin_addr, (voidp) hp->h_addr,
|
||||
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;
|
||||
|
||||
if (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);
|
||||
}
|
||||
if (!clnt) {
|
||||
fprintf(stderr, "%s: ", am_get_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",
|
||||
am_get_progname());
|
||||
errs = 1;
|
||||
} else if (!rc || *rc > 0) {
|
||||
fprintf(stderr, "%s: debug setting for \"%s\" failed\n",
|
||||
am_get_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",
|
||||
am_get_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",
|
||||
am_get_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",
|
||||
am_get_progname(), server);
|
||||
errs = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* getpwd info
|
||||
*/
|
||||
if (getpwd_flag) {
|
||||
char path[MAXPATHLEN+1];
|
||||
char *wd;
|
||||
amq_mount_tree_list *mlp;
|
||||
amq_mount_tree_p mt;
|
||||
u_int i;
|
||||
int flag;
|
||||
|
||||
wd = getcwd(path, MAXPATHLEN+1);
|
||||
if (!wd) {
|
||||
fprintf(stderr, "%s: getcwd failed (%s)", am_get_progname(),
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
mlp = amqproc_export_1((voidp) 0, clnt);
|
||||
for (i = 0; mlp && i < mlp->amq_mount_tree_list_len; i++) {
|
||||
mt = mlp->amq_mount_tree_list_val[i];
|
||||
while (1) {
|
||||
flag = 0;
|
||||
show_pwd(mt, path, sizeof(path), &flag);
|
||||
if (!flag) {
|
||||
printf("%s\n", path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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",
|
||||
am_get_progname(), server);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Map
|
||||
*/
|
||||
if (mapinfo_flag) {
|
||||
int dummy;
|
||||
amq_map_info_list *ml = amqproc_getmapinfo_1(&dummy, clnt);
|
||||
if (ml) {
|
||||
int mwid = 0, wwid = 0;
|
||||
show_mapinfo(ml, Calc, &mwid, &wwid);
|
||||
mwid++;
|
||||
if (wwid)
|
||||
wwid++;
|
||||
show_mapinfo(ml, Full, &mwid, &wwid);
|
||||
} else {
|
||||
fprintf(stderr, "%s: amd on %s cannot provide map info\n",
|
||||
am_get_progname(), server);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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",
|
||||
am_get_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", am_get_progname());
|
||||
errs = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply required operation to all remaining arguments
|
||||
*/
|
||||
if (optind < argc) {
|
||||
do {
|
||||
char *fs = argv[optind++];
|
||||
if (unmount_flag > 1) {
|
||||
amq_sync_umnt *sup;
|
||||
/*
|
||||
* Synchronous unmount request
|
||||
*/
|
||||
sup = amqproc_sync_umnt_1(&fs, clnt);
|
||||
if (sup) {
|
||||
if (quiet_flag == 0)
|
||||
print_umnt_error(sup, fs);
|
||||
errs = amu_sync_umnt_to_retval(sup);
|
||||
} else {
|
||||
errs = clnt_failed(clnt, server);
|
||||
}
|
||||
} else 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", am_get_progname(), fs);
|
||||
}
|
||||
xdr_pri_free((XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (caddr_t) mtp);
|
||||
} else {
|
||||
errs = clnt_failed(clnt, server);
|
||||
}
|
||||
}
|
||||
} 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 {
|
||||
errs = clnt_failed(clnt, server);
|
||||
}
|
||||
|
||||
} 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) {
|
||||
u_int i;
|
||||
for (i = 0; i < mlp->amq_mount_tree_list_len; i++) {
|
||||
show_mt(mlp->amq_mount_tree_list_val[i],
|
||||
e, &mwid, &dwid, &pwid);
|
||||
}
|
||||
mwid++;
|
||||
dwid++, pwid++;
|
||||
if (e == Calc)
|
||||
e = Short;
|
||||
else if (e == Short)
|
||||
e = ShowDone;
|
||||
}
|
||||
|
||||
} else {
|
||||
errs = clnt_failed(clnt, server);
|
||||
}
|
||||
}
|
||||
exit(errs);
|
||||
return errs; /* should never reach here */
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amq/amq.h
|
||||
*
|
||||
*/
|
||||
|
||||
#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_sync_umnt *amqproc_sync_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 amq_map_info_list *amqproc_getmapinfo_1(voidp argp, CLIENT *rqstp);
|
||||
extern int *amqproc_mount_1(voidp argp, CLIENT *rqstp);
|
||||
extern amq_string *amqproc_getvers_1(voidp argp, CLIENT *rqstp);
|
||||
extern int *amqproc_getpid_1(voidp argp, CLIENT *rqstp);
|
||||
extern amq_string *amqproc_pawd_1(amq_string *argp, CLIENT *rqstp);
|
||||
|
||||
#endif /* not _AMQ_H */
|
@ -1,250 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amq/amq_clnt.c
|
||||
*
|
||||
*/
|
||||
|
||||
#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_sync_umnt *
|
||||
amqproc_sync_umnt_1(amq_string *argp, CLIENT *clnt)
|
||||
{
|
||||
static amq_sync_umnt res;
|
||||
enum clnt_stat rv;
|
||||
|
||||
memset((char *) &res, 0, sizeof(res));
|
||||
if ((rv = clnt_call(clnt, AMQPROC_SYNC_UMNT,
|
||||
(XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) argp,
|
||||
(XDRPROC_T_TYPE) xdr_amq_sync_umnt, (SVC_IN_ARG_TYPE) &res,
|
||||
TIMEOUT)) != RPC_SUCCESS) {
|
||||
return (NULL);
|
||||
}
|
||||
return &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);
|
||||
}
|
||||
|
||||
amq_map_info_list *
|
||||
amqproc_getmapinfo_1(voidp argp, CLIENT *clnt)
|
||||
{
|
||||
static amq_map_info_list res;
|
||||
|
||||
memset((char *) &res, 0, sizeof(res));
|
||||
if (clnt_call(clnt, AMQPROC_GETMAPINFO, (XDRPROC_T_TYPE) xdr_void, argp,
|
||||
(XDRPROC_T_TYPE) xdr_amq_map_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);
|
||||
}
|
||||
|
||||
|
||||
amq_string *
|
||||
amqproc_pawd_1(amq_string *argp, CLIENT *clnt)
|
||||
{
|
||||
static amq_string res;
|
||||
|
||||
memset((char *) &res, 0, sizeof(res));
|
||||
if (clnt_call(clnt, AMQPROC_PAWD,
|
||||
(XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) argp,
|
||||
(XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) &res,
|
||||
TIMEOUT) != RPC_SUCCESS) {
|
||||
return (NULL);
|
||||
}
|
||||
return (&res);
|
||||
}
|
@ -1,316 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amq/amq_xdr.c
|
||||
*
|
||||
*/
|
||||
|
||||
#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 **) ((voidp) &objp->mt_next),
|
||||
sizeof(amq_mount_tree),
|
||||
(XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (!xdr_pointer(xdrs,
|
||||
(char **) ((voidp) &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 **) ((voidp) &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_map_info(XDR *xdrs, amq_map_info *objp)
|
||||
{
|
||||
if (!xdr_amq_string(xdrs, &objp->mi_name)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (!xdr_amq_string(xdrs, &objp->mi_wildcard)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (!xdr_time_type(xdrs, &objp->mi_modify)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (!xdr_int(xdrs, &objp->mi_flags)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (!xdr_int(xdrs, &objp->mi_nentries)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (!xdr_int(xdrs, &objp->mi_reloads)) {
|
||||
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_map_info_list(XDR *xdrs, amq_map_info_list *objp)
|
||||
{
|
||||
if (!xdr_array(xdrs,
|
||||
(char **) ((voidp) &objp->amq_map_info_list_val),
|
||||
(u_int *) &objp->amq_map_info_list_len,
|
||||
~0,
|
||||
sizeof(amq_map_info),
|
||||
(XDRPROC_T_TYPE) xdr_amq_map_info)) {
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
|
||||
bool_t
|
||||
xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp)
|
||||
{
|
||||
if (!xdr_array(xdrs,
|
||||
(char **) ((voidp) &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));
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
.\"
|
||||
.\" Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\"
|
||||
.\" File: am-utils/amq/pawd.1
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 26, 2016
|
||||
.Dt PAWD 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm pawd
|
||||
.Nd print automounter working directory
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Ar path ...
|
||||
.Sh DESCRIPTION
|
||||
.Bf -symbolic
|
||||
This command is obsolete.
|
||||
Users are advised to use
|
||||
.Xr autofs 5
|
||||
instead.
|
||||
.Ef
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility
|
||||
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
|
||||
.Xr amd 8 Ns 's
|
||||
local mount points.
|
||||
Using them is unsafe, because
|
||||
.Xr amd 8
|
||||
may unmount managed file systems from the mount points, and thus including
|
||||
them in paths may not always find the files within.
|
||||
.Pp
|
||||
Without any arguments,
|
||||
.Nm
|
||||
will print the automounter adjusted current working directory.
|
||||
With any
|
||||
number of arguments, it will print the adjusted
|
||||
.Ar path
|
||||
of each one of the
|
||||
arguments.
|
||||
.Sh SEE ALSO
|
||||
.Xr pwd 1 ,
|
||||
.Xr amd 8 ,
|
||||
.Xr amq 8
|
||||
.Pp
|
||||
.Dq am-utils
|
||||
.Xr info 1
|
||||
entry.
|
||||
.Rs
|
||||
.%A Erez Zadok
|
||||
.%B "Linux NFS and Automounter Administration"
|
||||
.%O ISBN 0-7821-2739-8
|
||||
.%I Sybex
|
||||
.%D 2001
|
||||
.Re
|
||||
.Pp
|
||||
.Pa http://www.am-utils.org/
|
||||
.Rs
|
||||
.%T Amd \- The 4.4 BSD Automounter
|
||||
.Re
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility first appeared in
|
||||
.Fx 3.0 .
|
||||
.Sh AUTHORS
|
||||
.An Erez Zadok Aq ezk@cs.sunysb.edu ,
|
||||
Computer Science Department, Stony Brook
|
||||
University, Stony Brook, New York, USA.
|
||||
.Pp
|
||||
Other authors and contributors to am-utils are listed in the
|
||||
.Pa AUTHORS
|
||||
file distributed with am-utils.
|
@ -1,257 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* File: am-utils/amq/pawd.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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>
|
||||
|
||||
|
||||
/* statics */
|
||||
static char *localhost = "localhost";
|
||||
static char transform[MAXPATHLEN];
|
||||
|
||||
|
||||
#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 */
|
||||
|
||||
xsnprintf(hesiod_lookup, sizeof(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 */
|
||||
xstrlcpy(transform, "/home/", sizeof(transform));
|
||||
xstrlcat(transform, username, sizeof(transform));
|
||||
if (*ch)
|
||||
xstrlcat(transform, ch, sizeof(transform));
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Munged to <%s>\n", transform);
|
||||
#endif /* DEBUG */
|
||||
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;
|
||||
struct timeval tmo = {10, 0};
|
||||
char *dummystr;
|
||||
amq_string *spp;
|
||||
|
||||
#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)) == NULL)
|
||||
return dir;
|
||||
memset(&server_addr, 0, sizeof(server_addr));
|
||||
/* as per POSIX, sin_len need not be set (used internally by kernel) */
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_addr = *(struct in_addr *) hp->h_addr;
|
||||
|
||||
clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, tmo, &s);
|
||||
if (clnt == NULL)
|
||||
clnt = clnttcp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, &s, 0, 0);
|
||||
if (clnt == NULL)
|
||||
return dir;
|
||||
|
||||
xstrlcpy(transform, dir, sizeof(transform));
|
||||
dummystr = transform;
|
||||
spp = amqproc_pawd_1((amq_string *) &dummystr, clnt);
|
||||
if (spp && *spp && **spp) {
|
||||
xstrlcpy(transform, *spp, sizeof(transform));
|
||||
XFREE(*spp);
|
||||
}
|
||||
clnt_destroy(clnt);
|
||||
return transform;
|
||||
}
|
||||
|
||||
|
||||
/* getawd() is a substitute for getwd() which transforms the path */
|
||||
static char *
|
||||
getawd(char *path, size_t l)
|
||||
{
|
||||
#ifdef HAVE_GETCWD
|
||||
char *wd = getcwd(path, MAXPATHLEN);
|
||||
#else /* not HAVE_GETCWD */
|
||||
char *wd = getwd(path);
|
||||
#endif /* not HAVE_GETCWD */
|
||||
|
||||
if (wd == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
xstrlcpy(path, transform_dir(wd), l);
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char tmp_buf[MAXPATHLEN], *wd;
|
||||
|
||||
if (argc == 1) {
|
||||
wd = getawd(tmp_buf, sizeof(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);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user