retire amd(8)
autofs was introduced with FreeBSD 10.1 and is the supported method for automounting filesystems. As of r296194 the amd man page claimed that it is deprecated. Remove it from base now; the sysutils/am-utils port is still available if necessary. Discussed with: cy Relnotes: Yes Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
9b7938dcf3
commit
13f7dbe822
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=358821
@ -2284,11 +2284,6 @@ _basic_bootstrap_tools+=sbin/sysctl bin/chflags
|
|||||||
# mkfifo is used by sys/conf/newvers.sh
|
# mkfifo is used by sys/conf/newvers.sh
|
||||||
_basic_bootstrap_tools+=usr.bin/mkfifo
|
_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"
|
.if ${MK_BOOT} != "no"
|
||||||
_basic_bootstrap_tools+=bin/dd
|
_basic_bootstrap_tools+=bin/dd
|
||||||
# xz/unxz is used by EFI
|
# xz/unxz is used by EFI
|
||||||
|
@ -36,6 +36,28 @@
|
|||||||
# xargs -n1 | sort | uniq -d;
|
# xargs -n1 | sort | uniq -d;
|
||||||
# done
|
# done
|
||||||
|
|
||||||
|
# 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
|
# 20200301: bktr removed
|
||||||
OLD_DIRS+=usr/include/dev/bktr
|
OLD_DIRS+=usr/include/dev/bktr
|
||||||
OLD_FILES+=usr/include/dev/bktr/ioctl_bktr.h
|
OLD_FILES+=usr/include/dev/bktr/ioctl_bktr.h
|
||||||
|
5
UPDATING
5
UPDATING
@ -26,6 +26,11 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW:
|
|||||||
disable the most expensive debugging functionality run
|
disable the most expensive debugging functionality run
|
||||||
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
|
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
|
||||||
|
|
||||||
|
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:
|
20200301:
|
||||||
Removed brooktree driver (bktr.4) from the tree.
|
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…
Reference in New Issue
Block a user