Compare commits

..
168 Commits
Author SHA1 Message Date
Ken Smith 665ce17da4 Get ready for the 6.3-RELEASE builds.
Approved by:	re (implicit)
2008-01-15 15:46:21 +00:00
Ken Smith 4dfc2a9d07 Add theoretical date of 6.3-RELEASE.
Approved by:	re (implicit)
2008-01-15 15:45:07 +00:00
Andrew Gallatin 4b81b9d4b9 MFC: Update to firmware version 1.4.29 from 1.4.25
Approved by: re (kensmith)
2008-01-15 15:41:30 +00:00
Hiroki Sato e6a99ff64f Document FreeBSD-SA-08:01.pty and FreeBSD-SA-08:02.libc.
Approved by:	re (implicitly)
2008-01-15 02:34:11 +00:00
Colin Percival 8a642c9425 Fix issues which allow snooping on ptys. [08:01]
Fix an off-by-one error in inet_network(3). [08:02]

Security: FreeBSD-SA-08:01.pty
Security: FreeBSD-SA-08:02.libc
Approved by:	re (kensmith)
Thanks to:	re@ for being so patient with us holding up the release
2008-01-14 22:56:18 +00:00
Ken Smith 8745233043 MFRELENG_6 v1.6.2.11
> Add the various packages we've ejected from the CD sets through
> recent years back on disc3.

Approved by:    re (hrs)
2008-01-14 17:42:09 +00:00
Hiroki Sato ba86d89173 Update page footer for release.
Approved by:	re (implicitly)
2008-01-14 09:58:55 +00:00
Hiroki Sato 5012fd4fd1 Bump &release.*; for 6.3R.
Approved by:	re (implicitly)
2008-01-14 09:47:24 +00:00
Doug Barton 3dfc154adc MFC the change from 1.27, removal of zones from the empty zone list that
may theoretically be allocated some day.

Approved by:	re (kensmith)
2008-01-13 20:51:09 +00:00
Gabor Kovesdan 3784aa50c6 MFC r1.5:
- This driver will first appear in FreeBSD 6.3, not 7.0

Approved by:	re (hrs)
2008-01-08 15:37:57 +00:00
John Baldwin 23da803376 MFC: Use devclass_get_count() instead of devclass_get_maxunit().
Approved by:	re (hrs)
2008-01-07 21:27:50 +00:00
Xin LI 39cd379459 - Reflect tzdata2007k update;
- Simplified Chinese translation: catchup with English version.

Approved by:	re (hrs)
2008-01-07 21:00:18 +00:00
Gabor Kovesdan 51f1c14be6 MFC r1.10:
- ipmi(4) appeared in FreeBSD 6.2, not in 6.3

Approved by:	re (hrs)
2008-01-07 14:53:59 +00:00
Peter Wemm a174ff12b1 MFC: rev 1.4: forward compatability with cvs-1.12 repository
Approved by: re (kensmith)
2008-01-07 09:08:53 +00:00
Edwin Groothuis 4fabc4e8db MFC of tzdata2007k.
Approved by:	re (ken smith)
2008-01-06 07:36:08 +00:00
Edwin Groothuis bf2fff9689 Update iso3166 with the data from Newsletter VI-1 2007-09-21:
Added SAINT BARTHELEMY (BL) and SAINT MARTIN (MF).

MFC of rev 1.17

Approved by: re (ken smith)
2008-01-06 07:25:43 +00:00
Gabor Kovesdan 49f7801ee2 MFC
r1.62:
- Document icase variable of make search, which can be used to control
  case-sensitivity
r1.63:
- Document PORT_DBDIR
r1.64:
- Remove incomplete sentence fragment

Approved by:	re (hrs)
2008-01-04 13:33:01 +00:00
Gabor Kovesdan f0727e3c7c MFC r1.7
- This driver has already appeared in 6.2

Approved by:	re (hrs)
2008-01-04 13:15:02 +00:00
Gabor Kovesdan c70d37f758 MFC r1.4
- This driver will first appear in 6.3, not 7.0

Approved by:	re (hrs)
2008-01-04 13:14:32 +00:00
Gabor Kovesdan 8f19e086a1 MFC r1.13
- This driver will first appear in 6.3, not 7.0

Approved by:	re (hrs)
2008-01-04 13:14:06 +00:00
Gabor Kovesdan 9754196968 MFC r1.3
- This driver will first appear in 6.3, not 7.0

Approved by:	re (hrs)
2008-01-04 13:13:44 +00:00
Gabor Kovesdan 945e02ca3d MFC r1.9
- This driver will first appear in 6.3, not 7.0

Approved by:	re (hrs)
2008-01-04 13:12:19 +00:00
Gabor Kovesdan 1291c3363b MFC r1.2
- This driver will first appear in 6.3, not 7.0

Approved by:	re (hrs)
2008-01-04 13:11:59 +00:00
Gabor Kovesdan 91324bfc44 MFC r1.8
- This driver will first appear in 6.3, not 7.0

Approved by:	re (hrs)
2008-01-04 13:09:04 +00:00
Warner Losh a52d0fd7f4 MFC: Happy new year
Approved by: re@
2008-01-01 09:37:09 +00:00
Andrew Thompson f3931b63eb MFC r1.8
Fix a panic where if the mbuf was consumed by the filter for requeueing
  (dummynet), ipsec_filter() would return the empty error code and the ipsec
  code would continue to forward/deference the null mbuf.

Approved by:	re (gnn)
2007-12-29 17:29:11 +00:00
Ken Smith 4b2d1164e8 MFC v1.117:
> Plug a memory leak.  Once any given package (e.g. perl) was installed
> we would leak a saved screen for every other package we tried to install
> that listed perl as one of its dependencies.  When installing things
> like gnome and kde that wound up being a LOT of leaked memory.

While here fix up some whitespace nits that show up as differences
from the other branches.

Approved by:	re (bmah)
2007-12-29 06:22:56 +00:00
Ken Smith 292c474cc5 MFC v1.78 and v1.79:
Remove process limits for datasize and stacksize which are unlimited
during a "normal login" (thanks to /etc/login.conf) but not when
sysinstall is running as part of an installation.  Fixups for error
messages and a comment that became untrue.

Build test help from:	rwatson
Approved by:		re (bmah)
2007-12-29 06:21:59 +00:00
Warner Losh 04a6d14346 MFC: Update to 2008.
Approved by: re@ (kensmith)
2007-12-26 16:49:12 +00:00
Ken Smith d92b0d8d4f MFC v1.116:
> For the INDEX file to be used on disc1 of the 7.0-RELEASE the longest
> "build dependencies" field is 5,108 characters which overflows the
> length of the junk buffer by a teeny bit.  This whole section needs
> much more error checking but for now just completely ignore stuff
> we have no interest in instead of copying it to someplace we don't
> use in the process.

Approved by:    re (bmah)
2007-12-24 06:42:35 +00:00
Doug Barton 6e402d3117 MFC version 1.55, safety belt for the (unlikely) disappearance of
the temproot before a -r run.

Approved by:	re (kensmith)
2007-12-24 05:51:45 +00:00
Marius Strobl 12b20befe5 MFC: 1.8
In openprom_ioctl() ensure appropriate permissions and that data isn't
NULL and doesn't point to a NULL pointer before dereferencing it.

Approved by:	re (kensmith)
2007-12-23 11:31:24 +00:00
Robert Watson 36b3e34efe Merge in_pcb.c:1.165.2.7 from RELENG_6 to RELENG_6_3:
When IPSEC fails to allocate policy state for an inpcb, and MAC is in use,
  free the MAC label on the inpcb before freeing the inpcb.

  Submitted by:   tanyong <tanyong at ercist dot iscas dot ac dot cn>,
                  zhouzhouyi

Approved by:	re (kensmith)
2007-12-22 21:01:53 +00:00
Robert Watson 63891de9b7 Merge mac_posix_sem.c:1.1.2.1 from HEAD to RELENG_6_3:
Fix a MAC label leak for POSIX semaphores, in which per-policy labels
  would be properly disposed of, but the global label structure for the
  semaphore wouldn't be freed.

  Reported by:    tanyong <tanyong at ercist dot iscas dot ac dot cn>,
                  zhouzhouyi

Approved by:	re (kensmith)
2007-12-22 17:04:16 +00:00
Robert Watson 55813e26c7 Merge in6_pcb.c:1.62.2.6 from RELENG_6 to RELENG_6_3:
Fix leaking MAC labels for IPv6 inpcbs by adding missing MAC label
  destroy call; this transpired because the inpcb alloc path for IPv4/IPv6
  is the same code, but IPv6 has a separate free path.  The results was
  that as new IPv6 TCP connections were created, kernel memory would
  gradually leak.

  Reported by:    tanyong <tanyong at ercist dot iscas dot ac dot cn>,
                  zhouzhouyi

Approved by:    re (kensmith)
2007-12-22 16:49:20 +00:00
Ken Smith a2b33fe311 Prepare for RC2 builds.
Approved by:	re (implicit)
2007-12-22 06:52:56 +00:00
Ken Smith a964c7817f MFS of v1.6.2.10:
> Initial pass at shifting packages around for 6.3-REL layout.  There
> is a lot of space left on disc3 that we can put to use by adding back
> in lots of the packages we've been slowly ejecting through the years.
> We'll decide exactly which ones a little bit later.

Approved by:	re (rwatson)
2007-12-22 06:33:58 +00:00
Ken Smith ef22fd9354 MFC v1.887.2.22:
> Add support for disc3.  Depending on architecture the combination of
> kde3 and gnome2 is at least 670Mb which would mean if we stick with
> just disc1/disc2 the only packages we could provide on the iso's
> would be X11, kde3, and gnome2...

Approved by:    re (rwatson)
2007-12-22 06:30:01 +00:00
Ken Smith e1b4478f4a MFC v1.253 of dist.c and v1.71 of dist.h:
> A few more adjustments needed because of changes in xorg.  Just installing
> xorg-server doesn't include any video drivers so install xorg-drivers as
> well.  And if font-alias isn't installed the X server won't start,
> complaining it can't find the font "fixed".

Approved by:    re (rwatson)
2007-12-22 06:26:54 +00:00
Andrew Thompson 64455cad26 MFC r1.25
- Use the macro to check the port status has it will also test if its
   administratively down (!IFF_UP)
 - Use the same parameters to lagg_link_active() to get the backup port as in
   the output path, this didnt actually matter in practice as sc_primary is
   always the first on the port list.

Approved by:	re (kensmith)
2007-12-21 05:35:29 +00:00
Andrew Thompson 9ca01152e8 MFC r1.108
When the bridge has an address and a packet comes in for it then drop it if
 the link has been marked discarding by Spanning Tree.

Approved by:    re (kensmith)
2007-12-21 05:30:47 +00:00
David E. O'Brien f34d9cc44c MF6: gdbserver is back.
Approved by:	re(kensmith)
2007-12-20 07:02:48 +00:00
Rui Paulo 6536499f7d MFC revision 1.679:
Disallow the legacy USB circuit to generate an SMI# via an ICH
  register (MacBooks only).
  This allows MacBooks to boot in SMP mode without any trick and
  solves the timer problems with HZ=1000.

Approved by:	     re (kensmith), njl (mentor)
2007-12-19 21:08:33 +00:00
Rui Paulo edc309ced3 MFC revision 1.662 and 1.663:
Disallow the legacy USB circuit to generate an SMI# via an ICH
  register (MacBooks only).
  This allows MacBooks to boot in SMP mode without any trick and
  solves the timer problems with HZ=1000.

Approved by:	re (kensmith), njl (mentor)
2007-12-19 21:05:43 +00:00
Peter Wemm 6b2521f3b4 MFC: Specify minimum retransmit scale factor in fractions of hz, not ticks.
Approved by:  re (kensmith)
2007-12-18 04:13:52 +00:00
John Baldwin 892b55384b MFC: Only pass paths to directories or config files that exist for ldconfig
for 32-bit binaries.

Approved by:	re (kensmith)
2007-12-18 01:35:26 +00:00
John Baldwin 46e6d5f628 MFC: Update posix_openpt(3) to handle 512 ptys.
Approved by:	re (gnn)
2007-12-18 00:36:21 +00:00
Scott Long 17cef3e101 Add the hptrr driver.
Submitted by: Highpoint
Approved by: re
2007-12-15 06:32:34 +00:00
cvs2svn 6591ff2ad5 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-12-15 00:56:19 +00:00
Doug Barton 62ee8eeee8 Merge from RELENG_6 all updates to date *except* for the combination
of the fortunes-o.real and fortunes2.o files.

Approved by:	re (kensmith)
2007-12-13 06:09:08 +00:00
John Baldwin edc0b087c3 MF6: Add the workaround in busdma for busted PYXIS chipsets along with
the 'machdep.busdma_pyxis_bug' loader tunable.

Approved by:	re (kensmith, blanket on sys/alpha)
2007-12-10 20:16:07 +00:00
Ed Maste 49e4438dd7 MFC to RELENG_6_3
aac_pci.c:1.63-1.65
aac.4 1.37-1.39

  Add PCI IDs for controllers obtained from Adaptec's latest drivers.

Approved by:    re (kensmith)
2007-12-10 19:35:43 +00:00
Ed Maste 13aae9c16d MFC to RELENG_6_3
aac_debug.c:1.23

  Respell 'Conatainer' as 'Container'.

Approved by:    re (kensmith)
2007-12-10 19:30:54 +00:00
Gabor Kovesdan 36413fd02b MFC rev 1.13:
- Add doc/hu_* and doc/mn_* to the refuse examples so that include all
  of the currently used languages

Approved by:	re (kensmith)
2007-12-10 18:47:05 +00:00
Gabor Kovesdan bc726df6ec MFC rev 1.14:
- Add doc/hu_* and doc/mn_* to the sample refuse file so that it includes all
  of the languages

Approved by:	re (kensmith)
2007-12-10 18:46:20 +00:00
Jung-uk Kim 6036d78c07 MFC: 1.3
Teach dhclient(8) about net80211 link (association) status.

Reviewed by:	brooks
Approved by:	re (kensmith)
2007-12-10 17:58:47 +00:00
Scott Long 89f4d9ca29 MFC: Support new ARC120x generation of cards.
Approved by: re
Submitted by: Erich Chen @ Areca
2007-12-09 19:53:59 +00:00
Xin LI 2e79acad5f Sync up ata(4) work by sos@ on -HEAD:
* Add preliminary SATA ATAPI support for sii 3132/3124 chips.
 * Fix speed report on Intel SATA chips in compat mode.
 * Fix broken detect of JMicron 368.

Related revisions:
 - ata-chipset.c: 1.208, 1.210
 - ata-disk.c.c:  1.205

Approved by:	re (kensmith), sos
2007-12-09 19:27:19 +00:00
cvs2svn ef3bafb1ea This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-12-09 11:02:00 +00:00
Nate Lawson f0e0b13341 MFC: 1.149-1.150. Hold Giant over device_suspend/resume() methods in apm.
Approved by:	re
2007-12-09 00:24:16 +00:00
David Malone 412c054fad Regen.
Approved by:	re (kensmith)
2007-12-08 13:46:03 +00:00
David Malone e2ccfdec35 MFC: Linuxulator statfs64 fixes.
Approved by:	re (kensmith)
2007-12-08 13:43:48 +00:00
Remko Lodder 6ded5b3a3c MFC rev 1.6 msk.4
MFC rev 1.26 if_msk.c
MFC rev 1.11 if_mskreg.h

  Bring in support for: Marvell Yukon 8039

  PR:             118401
  Submitted by:   Skip Ford <skip at menantico dot com>
  Approved by:    imp (mentor), yongari
  MFC After:      3 days

Approved by:	re (kensmith), imp (mentor, implicit)
2007-12-08 12:19:13 +00:00
Ulf Lilleengen 93d9ea5d2d - Add support for all geom class command options in the Fixit environment by
pointing GEOM_LIBRARY_PATH to the geom libraries.

PR:		misc/113543
Submitted by:	Ed Schouten <ed -at- fxq.nl>
Approved by:	re (kensmith), pjd (mentor)
2007-12-08 10:05:32 +00:00
Xin LI 01c7c45203 em(4) is updated to 6.7.2.
Approved by:	re (hrs)
2007-12-08 06:01:34 +00:00
Kip Macy 89f88be1c1 MFC: 1.317, 1.318, 1.319
Fix bit macros to work on multi-byte types

Approved by: re(kensmith)
2007-12-07 23:22:57 +00:00
Olivier Houchard a86845d51e MFC:
sys/arm/include/asmacros.h rev 1.7
sys/arm/include/atomic.h rev 1.23

Close a race.

The RAS implementation would set the end address, then the start
address.  These were used by the kernel to restart a RAS sequence if
it was interrupted.  When the thread switching code ran, it would
check these values and adjust the PC and clear them if it did.

However, there's a small flaw in this scheme.  Thread T1, sets the end
address and gets preempted.  Thread T2 runs and also does a RAS
operation.  This resets end to zero.  Thread T1 now runs again and
sets start and then begins the RAS sequence, but is preempted before
the RAS sequence executes its last instruction.  The kernel code that
would ordinarily restart the RAS sequence doesn't because the PC isn't
between start and 0, so the PC isn't set to the start of the sequence.
So when T1 is resumed again, it is at the wrong location for RAS to
produce the correct results.  This causes the wrong results for the
atomic sequence.

The window for the first race is 3 instructions.  The window for the
second race is 5-10 instructions depending on the atomic operation.
This makes this failure fairly rare and hard to reproduce.

Mutexs are implemented in libthr using atomic operations.  When the
above race would occur, a lock could get stuck locked, causing many
downstream problems, as you might expect.

Also, make sure to reset the start and end address when doing a syscall, or
a malicious process could set them before doing a syscall.

Reviewed by: imp, ups (thanks guys)
Approved by:	re (kensmith)
Pointy hat to:  cognet
2007-12-07 22:08:02 +00:00
Xin LI 7f80e86632 MFC revision 1.209
date: 2007/11/26 19:08:08;  author: sos;  state: Exp;  lines: +1 -1
Use device_set_desc_copy in the generic ident as its used on a temp buffer.

Approved by:	re (kensmith)
2007-12-07 17:59:39 +00:00
Konstantin Belousov 6426331ee1 MFC rev. 1.181:
Check for the program headers alignment of the ELF images before
dereferencing. Unaligned access could cause panic on strict alignment
architectures.

Approved by:	re (kensmith)
2007-12-07 14:30:26 +00:00
Konstantin Belousov 1f0aa93ebc MFC rev. 1.5, 1.6:
Restore the branding of the ELF executables. The structure was optimized out.

Approved by:	re (kensmith)
2007-12-07 14:16:53 +00:00
Kevin Lo 560a040057 MFC r1.18:
zic(8) should exit the loop when the end of the string is reached
due to the call to error(). The problem found by doing fuzz testing.

Approved by: re (kensmith)
2007-12-07 05:17:34 +00:00
Xin LI 3473a51bfc Bring in the latest snapshot of Simplified Chinese translation for the release
notes documentation for 6.3-RELEASE.  This is a collective work by the FreeBSD
Simplified Chinese Project team.

Submitted by:	Junfeng Wen <wjf at cn.FreeBSD.org>
		Chifeng Qu <chifeng at gmail.com>
		delphij
Obtained from:	The FreeBSD Simplified Chinese Project CVS
Approved by:	re (kensmith)
2007-12-07 04:04:52 +00:00
Andrew Thompson 38ac70031f MFC r1.209
Apply a workaround for the unkillable jail problem where some devices created
  within the jail are never freed.

Approved by:	re (kensmith)
2007-12-07 03:46:23 +00:00
Philip Paeps 6015633f10 MFC r1.33: Add a cross-reference to newgrp(1).
Approved by:	re (kensmith)
2007-12-06 10:50:35 +00:00
Philip Paeps 846d2046c0 MFC r1.13:
Fix a use-after-free.

Submitted by:	Ilja van Sprundel <ilja -at- netric.org>
Reviewed by:	secteam
Approved by:	re (kensmith)
2007-12-06 10:24:29 +00:00
Philip Paeps c78c61ea80 MFC if_iwi.c:1.59
if_ipw.c:1.34

  Plug two potential (root-only, local) information leaks.  buf is not
  initialized before use and returned integrally instead of up to size.

Submitted by:	Ilja van Sprundel <ilja -at- netric.org>
Reviewed by:	secteam
Approved by:	re (kensmith)
2007-12-06 10:23:15 +00:00
John Baldwin 3785ce0ed0 MFC: Always assume type #1 PCI config transactions for amd64 and relax the
probe for type #1 on i386.

Approved by:	re (kensmith)
2007-12-06 08:27:03 +00:00
John Baldwin 75c29c3f05 MFC: Change pci_cfgdisable() into a nop for type #1 similar to what other
OSs do.

Approved by:	re (kensmith)
2007-12-06 08:19:00 +00:00
John Baldwin b672f930d6 MFC: Don't delete files in the X11 socket directories under /tmp.
Approved by:	re (kensmith)
2007-12-06 08:11:19 +00:00
Pyun YongHyeon b6a9024bad MFC if_re.c, rev 1.98 to RELENG_6_3
Always honor promiscuous flag prior to programming Rx multicast
filter. This fixes a regression introduced in rev 1.89.

PR:	114632
Approved by:	re (kensmith)
2007-12-06 06:02:43 +00:00
Ariff Abdullah 1f95d1b8c7 Headphone / speakers automute fixup for Acer Aspire 4710 @ ALC268 laptop.
Tested by:	Liyu, She
Approved by:	re (kensmith)
2007-12-06 05:21:07 +00:00
Kip Macy 9179a53af5 Common code changes for firmware update.
Approved by: re(kensmith)
2007-12-06 00:02:00 +00:00
Kip Macy 11fd3fc4d1 - fix qset to port binding as a proper fix for the problems encountered on the 4-port
- fix the use after free seen when sending packets small enough to fit as an immediate
     and bpf peers are present
   - update to firmware rev 4.7 along with various small vendor fixes

Approved by: re(kensmith)
2007-12-05 23:46:44 +00:00
Robert Watson e9a6c4793a Merge kern_mbuf.c:1.9.2.10 from RELENG_6 to RELENG_6_3:
Call NET_LOCK_GIANT/NET_UNLOCK_GIANT around calls to protocol drain
  methods in mb_reclaim().  This is not an MFC, as debug.mpsafenet is
  not present in 7.x or 8.x.  In practice, this likely resulted in
  instability only on kernels with INVARIANTS, as the protocol drain
  paths are generally MPSAFE.

  PR:             116034
  Reported by:    Dan Lukes <[email protected]>
  Discussed with: kmacy, alc
  Approved by:    re (kensmith)
  Tested by:      Eugene Grosbein <eugen at grosbein dot pp dot ru>
2007-12-05 00:47:48 +00:00
Colin Percival 6e92d79cc6 MFC revision 1.3: Add /root/, /.cshrc, and /.profile to the default
UpdateIfUnmodified directive in order to avoid overwriting these when
users upgrade to future versions of FreeBSD.

Approved by:    re (kensmith)
2007-12-04 22:51:36 +00:00
Xin LI 8f9668f065 MFC: less v416.
Approved by:	re (kensmith)
2007-12-04 22:41:44 +00:00
David E. O'Brien 21c88ae71d MFC: turn on gdbserver for the arch that supports it.
Approved by:	re(kensmith)
2007-12-04 18:02:47 +00:00
David E. O'Brien 64c1891e95 MFC:
+ Turn on gdbserver for the arch that supports it.
+ Fix static/extern mismatch.
+ Remove extern int verbose declaration.

Approved by:	re(kensmith)
2007-12-03 21:05:20 +00:00
Joe Marcus Clarke 6a9f60381f Forced commit to correct file handle reversal in previous commit. The
message should have read:

This is a partial MFC of rev 1.126 from HEAD's libkse.  This only merges the
fix which causes stderr_debug to write output to STDOUT_FILENO instead
of STDERR_FILENO.  This is known to fix (or workaround) some mono-related
build problems.

Approved by:	re (kensmith)
2007-12-02 23:46:27 +00:00
Joe Marcus Clarke b3e34e3178 MFC: rev 1.126
This is a partial MFC of rev 1.126 from HEAD's libkse.  This only merges the
fix which causes stderr_debug to write output to STDERR_FILENO instead
of STDOUT_FILENO.  This is known to fix (or workaround) some mono-related
build problems.

Approved by:	re (kensmith)
2007-12-02 23:42:38 +00:00
Olivier Houchard df6cda3c36 MFC:
gnu/usr.bin/gdb/arch/arm/nm-fbsd.h rev 1.2
gnu/usr.bin/gdb/arch/arm/Makefile rev 1.2
gnu/usr.bin/gdb/arch/arm/armfbsd-nat.c 1.2
gnu/usr.bin/gdb/arch/arm/armfbsd-tdep.c rev 1.2
gnu/usr.bin/gdb/arch/arm/init.c rev 1.2
Allow gdb to attach live process.
Thread support for arm.

Approved by:	re (kensmith)
2007-12-02 14:38:21 +00:00
Olivier Houchard 7cf3e7ee51 MFC:
arm/at91/kb920x_machdep.c rev 1.24, 1.25 and 1.26
arm/at91/std.at91 rev 1.4
arm/at91/std.kb920x rev 1.5
arm/at91/at91rm92reg.h rev 1.6
conf/options.arm 1.18
Small tweaks to be able to load the kernel at a different address than
0x20000000 + add an option to override the default value of the master clock
frequency.
arm/at91/if_ate.c rev 1.21:
In ate_get_mac(), try to get the mac address in the right order, at least
in the same order as it's set in ate_set_mac.

arm/conf/HL200: config file for the Hot-e HL200

Approved by:	re (kensmith)
2007-12-02 14:21:27 +00:00
cvs2svn c2cbeda1e4 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-12-02 13:10:44 +00:00
Remko Lodder 279a95ed00 MFC rev 1.29 atacontrol.8
Expand the EXAMPLES section for atacontrol.8

  PR:             docs/117310
  Submitted by:   Ted Mittelstaedt <tedm at ipinc dot net>
                  with minor modifications by me.

Approved by:    re (hrs)
2007-12-02 09:09:44 +00:00
Remko Lodder 4c67461f0a MFC rev 1.64 sysctl.8
Remove mentionings of kern.dumpdev which is no longer available.

  PR:             docs/113570
  Submitted by:   lawrance
  MFC After:      3 days (where applicable)

Approved by:    re (hrs)
2007-12-02 09:08:45 +00:00
Remko Lodder ab064722fb MFC rev 1.41, 1.42 mdconfig.8
Sync with md(4)'s information regarding the swap backend.

  PR:             docs/115721
  Submitted by:   Stefan Lambrev <[email protected]>
  MFC After:      3 days

  Every newline should start on it's own line. I didn't do that in the
  previous commit, so make it happen now.

  Prodded by:     brueffer

Approved by:    re (hrs)
2007-12-02 09:07:48 +00:00
Remko Lodder e85c901792 MFC rev 1.7 newsyslog.conf.5
s/effect/affect/

  PR:             docs/118266
  Submitted by:   "Kim Scarborough" <sluggo at unknown dot nu>
  MFC After:      3 days

Approved by:    re (hrs)
2007-12-02 09:06:42 +00:00
Remko Lodder bf26f95050 MFC rev 1.8 ichsmb.4
Add information about the ICH6 and ICH7 being supported since recently.

MFC rev 1.20 ichsmb_pci.c

  Add the Intel 82801FB (ICH6) SMBus controller and the
  Intel 82801GB (ICH7) SMBus controller.

  PR:             85106 [1]
  PR:             99663 [2]
  Approved by:    imp (mentor), jhb
  Submitted by:   Oliver Fromme <olli at lurza.secnetix dot de>, [1]
                  Arthur Hartwig <arthur dot hartwig at nokia dot com>, [1]
                  Lowell Gilbert <lgfbsd at be-well dot ilk dot org> [2]@
  MFC After:      3 days

Approved by:    re (hrs), imp (mentor, implicit)
2007-12-02 09:05:38 +00:00
Remko Lodder 404123cef8 MFC rev 1.45 rl.4
Add the Planex FNW-3603TX card to the list.

MFC rev 1.172 if_rl.c
MFC rev 1.68  if_rlreg.h

  Add the FNW3603TX Planex NIC.

  PR:             76081
  Approved by:    imp (mentor)
  Submitted by:   umi at pocke dot org
  MFC After:      3 days

Approved by:    re (hrs), imp (mentor, implicit)
2007-12-02 09:04:11 +00:00
Darren Reed e1bc400aa8 MFC:
Fix 3 issues relating to the use of "auth" rules in IPFilter, from sourceforge:
1837014 Kernel panics after authentication of an outgoing packet
1836992 Potential bugs in packet auth code (w/patches)
1836967 Kernel panic when using auth rule with keep state
and another reported only to FreeBSD by Andiry (see PR)

PR:             kern/118251
Submitted by:   Andriy Syrovenko <[email protected]>
Reviewed by:    darrenr
Approved by:    re
2007-12-01 00:53:41 +00:00
Ariff Abdullah 1983dff4e5 MFC: (revision 1.47, 1.48)
- Add missing MCP65 id which was accidentally removed in previous commit.
- Add Analog Devices AD1984 codec id.
- Enable pcbeep control for Acer + ALC268 (nid 29). Give enough (fake)
  hints so the parser will grab it and allocate "speaker" control.
- Fix regression while preparing DAC and ADC for multichannel
  format. Since playback policy is to output to every possible path,
  ensure that each DAC is started.

Reported / Tested by:	Guy Brand
Approved by:		re (kensmith)
2007-11-30 15:12:06 +00:00
Bruce A. Mah f656099089 Use X.org 7.2 and FreeBSD 6.3-RELEASE manpage hyperlinks.
Approved by:	re (implicitly)
2007-11-30 05:38:35 +00:00
Bruce A. Mah 0e74c5ca31 MFC: SA-07:09.random.
Approved by:	re (implicitly)
2007-11-30 05:28:03 +00:00
Andrew Thompson 8057d81ec7 MFC r1.22
Have the lagg interface generate link up/down events, this fixes using
 carp+lagg together.

Approved by:	re (kensmith)
2007-11-29 19:05:22 +00:00
Bruce A. Mah 17501dfed7 MFC: freebsd-update(8) upgrade, ipfwpcap(8), IPFilter 4.1.28.
Approved by:	re (implicitly)
2007-11-29 17:43:30 +00:00
Simon L. B. Nielsen 99d77ab486 Correct a random value disclosure in random(4).
Security:	FreeBSD-SA-07:09.random
Approved by:	re (kensmith)
2007-11-29 16:06:54 +00:00
Tai-hwa Liang 8acd51193d MFC(1.14): Fixing a double free bug which will cause tail to dump core when
there's no tailing newline(\n) character.

PR:		bin/118267
Reviewed by:	kib
Approved by:	re (kensmith)
2007-11-29 03:54:56 +00:00
David E. O'Brien a793975d0d MFC: fix situation where GDB gives incorrect backtraces when a signal
handler is in the call chain.

Approved by:	re(kensmith)
2007-11-28 16:55:39 +00:00
David E. O'Brien 31c1d654ac Sync with HEAD.
Approved by:	re(gnn)
2007-11-28 16:41:47 +00:00
Ariff Abdullah 067993cfde * Fix support for followings:
o Acer Aspire 4520 laptop
    - jack sensing / automute
  o Toshiba Satellite A135-S4527 laptop
    - jack sensing / automute
      Tested by: lioux
  o Apple Macbook 3 (is it?)
    - require gpio0 (for speakers) and ovref50 (for headphone)
      to make it works
    - jack sensing / automute
      Tested by: Ed Schouten
* Add Nvidia MCP67 controller ids.
* Be sensible about simmilar controller with multiple pci ids.
* Connect unused DAC/ADC to stream#0 rather than forcing each of them
  managing their own stream.

Approved by:	re (kensmith)
2007-11-27 23:37:48 +00:00
Marius Strobl 2a70b4aa1e MFC: UPDATING 1.512, sys/sparc64/conf/DEFAULTS 1.11
Let sunkbd(4) emulate an AT keyboard by default.
This has the following benefits:
- allows to use the AT keyboard maps in share/syscons/keymaps with
  sunkbd(4),
- allows to use kbdmux(4) with sunkbd(4),
- allows Sun RS232 keyboards to be configured and used the same
  way as Sun USB keyboards driven by ukbd(4) (which also does AT
  keyboard emulation) with X.Org, putting an end to the problem
  of native support for the former in X.Org being broken over and
  over again.

Approved by:	re (kensmith)
2007-11-27 20:48:13 +00:00
Dmitry Morozovsky e3f2c87593 MFC revision 1.31:
devinfo(8) manual page refers to pciconfr(8).  Add back reference for
	completeness.

Approved by:	re (kensmith)
2007-11-27 20:00:29 +00:00
John Baldwin 3a76a88a0d MFC: Bump up the number of ttys supported by pty(4) to 512.
Approved by:	re (kensmith)
2007-11-27 18:43:09 +00:00
John Baldwin 9addff1cb5 MFC: Expand critical section coverage for ithread scheduling.
Approved by:	re (kensmith)
2007-11-27 17:46:18 +00:00
John Baldwin a6c0a4ae53 MF6: Sync with i386 and expand support for bounce pages, etc.
Approved by:	re (kensmith)
2007-11-27 17:45:59 +00:00
Tai-hwa Liang 93d321a90c MFC(if_an.c:1.85, if_anreg.h:1.24): Trying to eliminate a racing as well as
reducing the chance of device removal(PCCARD) panic by replacing the
timeout(9) with callout(9) APIs.

Approved by:	re (gnn)
2007-11-27 08:22:37 +00:00
Ken Smith 78fe411920 Get ready for 6.3-RC1 builds.
Approved by:	re (implicit)
2007-11-26 15:51:15 +00:00
Scott Long 1a3fe001fc MFC: Expand critical section coverage so that shared fast and ithread handlers
don't stall.  Unlike 8-CURRENT and 7-STABLE, sparc64 and powerpc in 6-STABLE
do not appear to have this problem.

Approved by: re
2007-11-26 15:42:43 +00:00
Rong-En Fan 511f2283f0 - Put __mb_sb_limit symbol back to libc to ease users' pain when upgrading
their 6-STABLE system. This is necessary because we have this symbol
  exported between 20071025 and 20071030. Binaries built during that perios
  will be broken after 602115.

Requested by:	many
Approved by:	re (kensmith)
2007-11-26 03:29:17 +00:00
David Xu b4d58a20fd MFC revision 1.27:
In _pthread_key_create() ensure that libkse is initialized.

Approved by: re (kensmith)
2007-11-26 02:52:20 +00:00
Bruce A. Mah 265d576fc9 New release notes: freebsd-update(8) -r, OpenBSM 1.0.
Approved by:	re (implicitly)
2007-11-25 18:13:09 +00:00
Bruce A. Mah 3a603deb13 Bump version numbers in the release documentation for 6.3-RELEASE.
Some more changes are required in this file to make manpage hyperlinks
work correctly.

Approved by:	re (implicitly)
2007-11-25 17:51:48 +00:00
Bruce A. Mah abb2f160d4 Update upload location for release note renderings for 6.3-RELEASE.
Approved by:	re (implicitly)
2007-11-25 17:42:08 +00:00
Bruce A. Mah 4c313eeee1 Trim release errata for 6.3-RELEASE.
Approved by:	re (implicitly)
2007-11-25 17:41:31 +00:00
Jean-Sébastien Pédron 62ecd0a768 MFC 1.193:
The kernel uses two ways to write data on a pipe:
      o  buffered write, for chunks smaller than PIPE_MINDIRECT bytes
      o  direct write, for everything else

  A call to writev(2) may receive struct iov of various size and the
  kernel may have to switch from one solution to the other. Before doing
  this, it must wake reader processes and any select/poll/kqueue up.

  This commit fixes a bug where select/poll/kqueue are not triggered
  when switching from buffered write to direct write. It adds calls to
  pipeselwakeup().

  I give more details on freebsd-arch@:
  http://lists.freebsd.org/pipermail/freebsd-arch/2007-September/006790.html

  This should fix issues with Erlang (lang/erlang) and kqueue.

Reported by:	Rickard Green (Erlang)
Approved by:	re (kensmith)
2007-11-25 17:33:54 +00:00
Ken Smith 832724a318 Prepare for packages-6.3-release to exist.
Approved by:	re (implicit)
2007-11-25 06:36:32 +00:00
Ken Smith 779c287192 Adjust __FreeBSD_version now that RELENG_6_3 exists.
Approved by:	re (implicit)
2007-11-25 06:34:58 +00:00
Ken Smith 430befc57f Adjust branch tag in example.
Approved by:	re (implicit)
2007-11-25 06:32:51 +00:00
Ken Smith 381a8fe24f Adjust build name.
Approved by:	re (implicit)
2007-11-25 06:27:23 +00:00
Ken Smith 97dafd3d02 Switch to RELENG_6_3 for "make update".
Approved by:	re (implicit)
2007-11-25 06:23:43 +00:00
cvs2svn 0ef2db398f This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-11-24 19:45:58 +00:00
cvs2svn 91fdbf85cf This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-11-21 16:47:16 +00:00
cvs2svn d18bde5885 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-11-21 01:31:51 +00:00
cvs2svn 1da0a15938 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-11-21 01:31:50 +00:00
cvs2svn 8685a14be7 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-11-18 18:11:18 +00:00
cvs2svn 185ee3fe74 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-11-18 11:03:30 +00:00
cvs2svn 4f8445a66c This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-11-15 20:20:55 +00:00
cvs2svn 4dcafe4d81 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-11-11 17:07:38 +00:00
cvs2svn 5cbcb71f0c This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-11-07 13:38:46 +00:00
cvs2svn 7ac6ceb62e This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-11-04 15:07:29 +00:00
cvs2svn 36098e1aa6 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-10-26 20:48:19 +00:00
cvs2svn a2c7519ab4 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-10-24 21:19:03 +00:00
cvs2svn e88450ee18 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-10-23 23:45:15 +00:00
cvs2svn c841908172 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-10-23 23:41:25 +00:00
cvs2svn d328d6a7f9 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-09-10 17:30:27 +00:00
cvs2svn c78dc27387 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-07-30 16:53:56 +00:00
cvs2svn de40bc2e65 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-07-13 04:46:35 +00:00
cvs2svn 5b1c0a232e This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-05-16 21:39:45 +00:00
cvs2svn 83d8069140 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-02-09 14:47:54 +00:00
cvs2svn 2cc73f8b75 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-02-07 09:15:05 +00:00
cvs2svn 2e2cc1566c This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-01-15 18:37:34 +00:00
cvs2svn aff812c270 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2007-01-07 18:38:00 +00:00
cvs2svn 95714ee293 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2006-12-01 17:13:57 +00:00
cvs2svn 0cdfbdddbd This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2006-10-13 14:27:52 +00:00
cvs2svn fa0a183de0 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2006-08-17 01:20:37 +00:00
cvs2svn c6762f5f62 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2006-08-15 12:41:11 +00:00
cvs2svn 109a275834 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2006-06-23 10:51:37 +00:00
cvs2svn 5941c0383e This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2006-04-10 20:12:20 +00:00
cvs2svn ffb96c759a This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2006-03-10 19:37:37 +00:00
cvs2svn 60e943ac64 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2006-02-08 05:58:18 +00:00
cvs2svn aba3d67b94 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2006-01-31 15:44:52 +00:00
cvs2svn 8701469d4e This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2006-01-25 08:13:47 +00:00
cvs2svn c42ecb824c This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2005-09-26 19:35:34 +00:00
cvs2svn 84d5a41287 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2005-08-25 05:01:25 +00:00
cvs2svn 02a4541cca This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2005-08-19 18:38:56 +00:00
cvs2svn aa52f66151 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2005-07-11 04:15:01 +00:00
cvs2svn d985c83698 This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2005-07-11 04:15:00 +00:00
cvs2svn 4605e0666a This commit was manufactured by cvs2svn to create branch 'RELENG_6_3'. 2005-07-11 04:14:59 +00:00
4090 changed files with 239037 additions and 490552 deletions

No files matched your search

+1 -1
View File
@@ -4,7 +4,7 @@
The compilation of software known as FreeBSD is distributed under the
following terms:
Copyright (c) 1992-2013 The FreeBSD Project. All rights reserved.
Copyright (C) 1992-2008 The FreeBSD Project. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
+1 -1
View File
@@ -73,6 +73,7 @@ pkill gad Heads-up appreciated.
ps gad I am working on a number of changes to this. Would
like advance notice of major changes planned to it.
cvs peter Heads-up appreciated, try not to break it.
ncurses peter Heads-up appreciated, try not to break it.
nvi peter Try not to break it.
libz peter Try not to break it.
pppd/chat peter Try not to break it.
@@ -124,7 +125,6 @@ lib/libsdp emax Pre-commit review preferred.
usr.bin/bluetooth emax Pre-commit review preferred.
usr.sbin/bluetooth emax Pre-commit review preferred.
gnu/usr.bin/send-pr bugmaster Pre-commit review requested.
ncurses rafan Heads-up appreciated, try not to break it.
Following are the entries from the Makefiles, and a few other sources.
Please remove stale entries from both their origin, and this file.
-2
View File
@@ -67,8 +67,6 @@
# developer convenience only. They are intentionally not documented and
# completely subject to change without notice.
#
# For more information, see the build(7) manual page.
#
TGTS= all all-man buildenv buildkernel buildworld check-old checkdpadd \
clean cleandepend cleandir delete-old delete-old-libs depend \
distribute distributeworld distrib-dirs distribution everything \
+9 -11
View File
@@ -87,7 +87,7 @@ CLEANDIR= cleandir
.endif
CVS?= cvs
CVSFLAGS?= -r RELENG_6 -P -d -I!
CVSFLAGS?= -r RELENG_6_3 -P -d -I!
SUP?= /usr/bin/csup
SUPFLAGS?= -g -L 2
.if defined(SUPHOST)
@@ -235,11 +235,11 @@ WMAKE= ${WMAKEENV} ${MAKE} -f Makefile.inc1 DESTDIR=${WORLDTMP}
LIB32TMP= ${OBJTREE}${.CURDIR}/lib32
.if empty(TARGET_CPUTYPE)
LIB32CPUFLAGS= -march=i686 -mmmx -msse -msse2
LIB32CPUTYPE= k8
.else
LIB32CPUFLAGS= -march=${TARGET_CPUTYPE}
LIB32CPUTYPE= ${TARGET_CPUTYPE}
.endif
LIB32FLAGS= -m32 ${LIB32CPUFLAGS} -mfancy-math-387 -DCOMPAT_32BIT \
LIB32FLAGS= -m32 -march=${LIB32CPUTYPE} -mfancy-math-387 -DCOMPAT_32BIT \
-iprefix ${LIB32TMP}/usr/ \
-L${LIB32TMP}/usr/lib32 \
-B${LIB32TMP}/usr/lib32
@@ -451,8 +451,8 @@ build32:
cd ${.CURDIR}; \
${LIB32WMAKE} -f Makefile.inc1 libraries
.for _t in obj depend all
cd ${.CURDIR}/libexec/rtld-elf; PROG=ld-elf32.so.1 ${LIB32WMAKE} ${_t}
cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIB32WMAKE} ${_t}
cd ${.CURDIR}/libexec/rtld-elf; \
PROG=ld-elf32.so.1 ${LIB32WMAKE} ${_t}
.endfor
distribute32 install32:
@@ -466,11 +466,10 @@ distribute32 install32:
.if !defined(NO_CRYPT)
cd ${.CURDIR}/secure/lib; ${LIB32IMAKE} ${.TARGET:S/32$//}
.endif
cd ${.CURDIR}/libexec/rtld-elf; \
PROG=ld-elf32.so.1 ${LIB32IMAKE} ${.TARGET:S/32$//}
cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIB32IMAKE} ${.TARGET:S/32$//}
cd ${.CURDIR}/libexec/rtld-elf; PROG=ld-elf32.so.1 ${LIB32IMAKE} ${.TARGET:S/32$//}
.endif
WMAKE_TGTS=
.if !defined(SUBDIR_OVERRIDE)
WMAKE_TGTS+= _worldtmp _legacy _bootstrap-tools
@@ -590,8 +589,7 @@ redistribute:
@echo "--------------------------------------------------------------"
${_+_}cd ${.CURDIR}; ${MAKE} -f Makefile.inc1 distribute
.if ${TARGET_ARCH} == "amd64" && !defined(NO_LIB32)
${_+_}cd ${.CURDIR}; ${MAKE} -f Makefile.inc1 distribute32 \
DISTRIBUTION=lib32
${_+_}cd ${.CURDIR}; ${MAKE} -f Makefile.inc1 distribute32 DISTRIBUTION=lib32
.endif
distrib-dirs distribution:
-14
View File
@@ -14,17 +14,6 @@
# The file is partitioned: OLD_FILES first, then OLD_LIBS and OLD_DIRS last.
#
# 20091129: pecoff image activator removed
.if ${TARGET_ARCH} == "i386"
OLD_FILES+=usr/include/machine/pecoff_machdep.h
.endif
# 20090203: adding_user.8 moved to adding_user.7
OLD_FILES+=usr/share/man/man8/adding_user.8.gz
# 20080407: pkg_sign has been removed
OLD_FILES+=usr/sbin/pkg_check
OLD_FILES+=usr/sbin/pkg_sign
OLD_FILES+=usr/share/man/man1/pkg_check.1.gz
OLD_FILES+=usr/share/man/man1/pkg_sign.1.gz
# 20070711: bzip2 1.0.4
OLD_FILES+=usr/share/info/bzip2.info.gz
# 20070710: Removal of the PROTO.localhost* files
@@ -267,9 +256,6 @@ OLD_FILES+=usr/sbin/ntp-genkeys
OLD_FILES+=usr/sbin/ntptimeset
OLD_FILES+=usr/share/man/man8/kernbb.8.gz
OLD_FILES+=usr/share/man/man8/ntp-genkeys.8.gz
# 20040627: usbdevs.h and usbdevs_data.h removal
OLD_FILES+=usr/include/dev/usb/usbdevs.h
OLD_FILES+=usr/include/dev/usb/usbdevs_data.h
# 200406XX
OLD_FILES+=usr/bin/gasp
OLD_FILES+=usr/bin/gdbreplay
+8 -10
View File
@@ -8,19 +8,17 @@ Items affecting the ports and packages system can be found in
/usr/ports/UPDATING. Please read that file before running
portupgrade.
20091129:
PECOFF image activator support removed.
20081128:
FreeBSD 6.4-RELEASE
20080904:
ntpd upgraded to 4.2.4p5.
20080118:
FreeBSD 6.3-RELEASE
20071126:
20080118: FreeBSD-SA-08:01.pty, FreeBSD-SA-08:02.libc
Fix issues which allow snooping on ptys. [08:01]
Fix an off-by-one error in inet_network(3). [08:02]
20071129: FreeBSD-SA-07:09.random
Correct a random value disclosure in random(4).
20071127:
The AT keyboard emulation of sunkbd(4) has been turned on
by default. In order to make the special symbols of the Sun
keyboards driven by sunkbd(4) work under X these now have
+1 -3
View File
@@ -211,6 +211,7 @@ copy_file(const FTSENT *entp, int dne)
rval = 1;
}
}
(void)close(from_fd);
/*
* Don't remove the target even after an error. The target might
@@ -230,9 +231,6 @@ copy_file(const FTSENT *entp, int dne)
rval = 1;
}
}
(void)close(from_fd);
return (rval);
}
+1 -1
View File
@@ -73,7 +73,7 @@ CFLAGS+= -DNO_NLS_CATALOGS
.else
CFLAGS+= -DHAVE_ICONV
SRCS+= iconv_stub.c
# Following links can be installed from ports/shells/tcsh_nls:
# Folloing links can be installed from ports/shells/tcsh_nls:
# NLSLINKS_de_DE.ISO8859-1 += de_AT.UTF-8 de_CH.UTF-8 de_DE.UTF-8
# NLSLINKS_el_GR.ISO8859-7 = el_GR.UTF-8
# NLSLINKS_es_ES.ISO8859-1 += es_ES.UTF-8
+10 -41
View File
@@ -12,28 +12,10 @@
/* Define to 1 if you have the <auth.h> header file. */
/* #undef HAVE_AUTH_H */
/* Define to 1 if you have the `catgets' function. */
#define HAVE_CATGETS 1
/* Define to 1 if you have the <crypt.h> header file. */
/* #undef HAVE_CRYPT_H */
/* Define to 1 if you have the declaration of `crypt', and to 0 if you don't.
*/
#define HAVE_DECL_CRYPT 1
/* Define to 1 if you have the declaration of `environ', and to 0 if you
don't. */
#define HAVE_DECL_ENVIRON 0
/* Define to 1 if you have the declaration of `gethostname', and to 0 if you
don't. */
#define HAVE_DECL_GETHOSTNAME 1
/* Define to 1 if you have the declaration of `getpgrp', and to 0 if you
don't. */
#define HAVE_DECL_GETPGRP 1
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
*/
#define HAVE_DIRENT_H 1
@@ -41,9 +23,6 @@
/* Define to 1 if you have the `dup2' function. */
#define HAVE_DUP2 1
/* Define to 1 if you have the `getauthid' function. */
/* #undef HAVE_GETAUTHID */
/* Define to 1 if you have the `getcwd' function. */
#define HAVE_GETCWD 1
@@ -56,7 +35,7 @@
/* Define to 1 if you have the `getutent' function. */
/* #undef HAVE_GETUTENT */
/* Define if you have the iconv() function. */
/* Define to 1 if you have the iconv () interface */
/* #undef HAVE_ICONV */
/* Define to 1 if you have the <inttypes.h> header file. */
@@ -65,9 +44,6 @@
/* Define to 1 if the system has the type `long long'. */
#define HAVE_LONG_LONG 1
/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
#define HAVE_MBRTOWC 1
/* Define to 1 if you have the `memmove' function. */
#define HAVE_MEMMOVE 1
@@ -104,10 +80,6 @@
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strcoll' function and it is properly defined.
*/
#define HAVE_STRCOLL 1
/* Define to 1 if you have the `strerror' function. */
#define HAVE_STRERROR 1
@@ -173,12 +145,6 @@
/* Define to 1 if you have the `wcwidth' function. */
#define HAVE_WCWIDTH 1
/* Define as const if the declaration of iconv() needs const. */
#define ICONV_CONST const
/* Support NLS. */
#define NLS 1
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""
@@ -194,6 +160,12 @@
/* Define to the version of this package. */
#define PACKAGE_VERSION ""
/* Define to 1 if the C compiler supports function prototypes. */
#define PROTOTYPES 1
/* Define as the return type of signal handlers (`int' or `void'). */
#define RETSIGTYPE void
/* Define to 1 if the `setpgrp' function takes no argument. */
/* #undef SETPGRP_VOID */
@@ -206,6 +178,9 @@
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define like PROTOTYPES; this can be used by system headers. */
#define __PROTOTYPES 1
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
@@ -221,9 +196,6 @@
/* Define to `int' if neither <sys/types.h> nor <sys/socket.h> define. */
/* #undef socklen_t */
/* Define to `int' not defined in <sys/types.h>. */
/* #undef ssize_t */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef uid_t */
@@ -237,6 +209,3 @@
#ifndef NO_NLS_CATALOGS
#define NLS_CATALOGS
#endif
/* Work around a vendor issue where config_f.h is #undef'ing this setting */
#define SYSMALLOC
+15 -1
View File
@@ -21,6 +21,11 @@
*/
#define POSIXJOBS
/*
* POSIXSIGS Use the POSIX signal facilities to emulate BSD signals.
*/
#undef POSIXSIGS
/*
* VFORK This machine has a vfork().
* It used to be that for job control to work, this define
@@ -42,10 +47,17 @@
*/
#define BSDJOBS
/*
* BSDSIGS You have 4.2-style signals, rather than USG style.
* Note: POSIX systems should not define this unless they
* have sigvec() and friends (ie: 4.3BSD-RENO, HP-UX).
*/
#define BSDSIGS
/*
* BSDTIMES You have BSD-style process time stuff (like rusage)
* This may or may not be true. For example, Apple Unix
* (OREO) has BSDJOBS but not BSDTIMES.
* (OREO) has BSDJOBS and BSDSIGS but not BSDTIMES.
*/
#define BSDTIMES
@@ -82,6 +94,8 @@
#if defined(__FreeBSD__)
#define NLS_BUGS
#define BSD_STYLE_COLORLS
/* we want to use the system malloc when we install as /bin/csh */
#define SYSMALLOC
/* Use LC_MESSAGES locale category to open the message catalog */
#define MCLoadBySet NL_CAT_LOCALE
#define BUFSIZE 8192
-11
View File
@@ -61,20 +61,9 @@ dl_iconv_open(const char *tocode, const char *fromcode)
if (iconvlib == NULL)
return (iconv_t)-1;
iconv_open = (iconv_open_t *)dlfunc(iconvlib, ICONV_OPEN);
if (iconv_open == NULL)
goto dlfunc_err;
dl_iconv = (dl_iconv_t *)dlfunc(iconvlib, ICONV_ENGINE);
if (dl_iconv == NULL)
goto dlfunc_err;
dl_iconv_close = (dl_iconv_close_t *)dlfunc(iconvlib,
ICONV_CLOSE);
if (dl_iconv_close == NULL)
goto dlfunc_err;
}
return iconv_open(tocode, fromcode);
dlfunc_err:
dlclose(iconvlib);
iconvlib = NULL;
return (iconv_t)-1;
}
+1 -6
View File
@@ -32,7 +32,7 @@
.\" @(#)dd.1 8.2 (Berkeley) 1/13/94
.\" $FreeBSD$
.\"
.Dd January 23, 2009
.Dd August 15, 2004
.Dt DD 1
.Os
.Sh NAME
@@ -392,11 +392,6 @@ Remove parity bit from a file:
Check for (even) parity errors on a file:
.Pp
.Dl "dd if=file conv=pareven | cmp -x - file"
.Pp
To create an image of a Mode-1 CD-ROM, which is a commonly used format
for data CD-ROM disks, use a block size of 2048 bytes:
.Pp
.Dl "dd if=/dev/acd0 of=filename.iso bs=2048"
.Sh SEE ALSO
.Xr cp 1 ,
.Xr mt 1 ,
+18 -59
View File
@@ -65,9 +65,6 @@ __FBSDID("$FreeBSD$");
#include <sysexits.h>
#include <unistd.h>
/* Exit code for a failed exec. */
#define EXEC_FAILED 127
int fflg, iflg, nflg, vflg;
int copy(char *, char *);
@@ -201,11 +198,6 @@ do_move(char *from, char *to)
}
}
}
/*
* Rename on FreeBSD will fail with EISDIR and ENOTDIR, before failing
* with EXDEV. Therefore, copy() doesn't have to perform the checks
* specified in the Step 3 of the POSIX mv specification.
*/
if (!rename(from, to)) {
if (vflg)
printf("%s -> %s\n", from, to);
@@ -227,7 +219,7 @@ do_move(char *from, char *to)
if (!S_ISLNK(sb.st_mode)) {
/* Can't mv(1) a mount point. */
if (realpath(from, path) == NULL) {
warn("cannot resolve %s: %s", from, path);
warnx("cannot resolve %s: %s", from, path);
return (1);
}
if (!statfs(path, &sfs) &&
@@ -260,9 +252,9 @@ fastcopy(char *from, char *to, struct stat *sbp)
struct timeval tval[2];
static u_int blen;
static char *bp;
acl_t acl;
mode_t oldmode;
int nread, from_fd, to_fd;
acl_t acl;
if ((from_fd = open(from, O_RDONLY, 0)) < 0) {
warn("%s", from);
@@ -313,7 +305,7 @@ err: if (unlink(to))
}
/*
* POSIX 1003.2c states that if _POSIX_ACL_EXTENDED is in effect
* for dest_file, then its ACLs shall reflect the ACLs of the
* for dest_file, then it's ACLs shall reflect the ACLs of the
* source_file.
*/
if (fpathconf(to_fd, _PC_ACL_EXTENDED) == 1 &&
@@ -363,76 +355,43 @@ err: if (unlink(to))
int
copy(char *from, char *to)
{
struct stat sb;
int pid, status;
if (lstat(to, &sb) == 0) {
/* Destination path exists. */
if (S_ISDIR(sb.st_mode)) {
if (rmdir(to) != 0) {
warn("rmdir %s", to);
return (1);
}
} else {
if (unlink(to) != 0) {
warn("unlink %s", to);
return (1);
}
}
} else if (errno != ENOENT) {
warn("%s", to);
return (1);
}
/* Copy source to destination. */
if (!(pid = vfork())) {
if ((pid = fork()) == 0) {
execl(_PATH_CP, "mv", vflg ? "-PRpv" : "-PRp", "--", from, to,
(char *)NULL);
_exit(EXEC_FAILED);
warn("%s", _PATH_CP);
_exit(1);
}
if (waitpid(pid, &status, 0) == -1) {
warn("%s %s %s: waitpid", _PATH_CP, from, to);
warn("%s: waitpid", _PATH_CP);
return (1);
}
if (!WIFEXITED(status)) {
warnx("%s %s %s: did not terminate normally",
_PATH_CP, from, to);
warnx("%s: did not terminate normally", _PATH_CP);
return (1);
}
switch (WEXITSTATUS(status)) {
case 0:
break;
case EXEC_FAILED:
warnx("%s %s %s: exec failed", _PATH_CP, from, to);
return (1);
default:
warnx("%s %s %s: terminated with %d (non-zero) status",
_PATH_CP, from, to, WEXITSTATUS(status));
if (WEXITSTATUS(status)) {
warnx("%s: terminated with %d (non-zero) status",
_PATH_CP, WEXITSTATUS(status));
return (1);
}
/* Delete the source. */
if (!(pid = vfork())) {
execl(_PATH_RM, "mv", "-rf", "--", from, (char *)NULL);
_exit(EXEC_FAILED);
warn("%s", _PATH_RM);
_exit(1);
}
if (waitpid(pid, &status, 0) == -1) {
warn("%s %s: waitpid", _PATH_RM, from);
warn("%s: waitpid", _PATH_RM);
return (1);
}
if (!WIFEXITED(status)) {
warnx("%s %s: did not terminate normally", _PATH_RM, from);
warnx("%s: did not terminate normally", _PATH_RM);
return (1);
}
switch (WEXITSTATUS(status)) {
case 0:
break;
case EXEC_FAILED:
warnx("%s %s: exec failed", _PATH_RM, from);
return (1);
default:
warnx("%s %s: terminated with %d (non-zero) status",
_PATH_RM, from, WEXITSTATUS(status));
if (WEXITSTATUS(status)) {
warnx("%s: terminated with %d (non-zero) status",
_PATH_RM, WEXITSTATUS(status));
return (1);
}
return (0);
+3
View File
@@ -29,6 +29,9 @@ PROG= pax
SRCS= ar_io.c ar_subs.c buf_subs.c cache.c cpio.c file_subs.c ftree.c \
gen_subs.c getoldopt.c options.c pat_rep.c pax.c sel_subs.c \
tables.c tar.c tty_subs.c
#XXX NOTYET
#MAN= pax.1 tar.1 cpio.1
#LINKS= ${BINDIR}/pax ${BINDIR}/tar ${BINDIR}/pax ${BINDIR}/cpio
.if ${MACHINE_ARCH} == "arm"
WARNS?= 3
+304
View File
@@ -0,0 +1,304 @@
.\"-
.\" Copyright (c) 1997 SigmaSoft, Th. Lockert
.\" 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.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by SigmaSoft, Th. Lockert.
.\" 4. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
.\"
.\" $OpenBSD: cpio.1,v 1.16 2001/05/01 17:58:01 aaron Exp $
.\" $FreeBSD$
.\"
.Dd February 16, 1997
.Dt CPIO 1
.Os
.Sh NAME
.Nm cpio
.Nd copy file archives in and out
.Sh SYNOPSIS
.Nm
.Fl o
.Op Fl aABcLvzZ
.Op Fl C Ar bytes
.Op Fl F Ar archive
.Op Fl H Ar format
.Op Fl O Ar archive
.No < Ar name-list
.Op No > Ar archive
.Nm
.Fl i
.Op Fl bBcdfmrsStuvzZ6
.Op Fl C Ar bytes
.Op Fl E Ar file
.Op Fl F Ar archive
.Op Fl H Ar format
.Op Fl I Ar archive
.Op Ar pattern ...
.Op No < Ar archive
.Nm
.Fl p
.Op Fl adlLmuv
.Ar destination-directory
.No < Ar name-list
.Sh DESCRIPTION
The
.Nm
command copies files to and from a
.Nm
archive.
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl o
Create an archive.
Reads the list of files to store in the
archive from standard input, and writes the archive on standard
output.
.Bl -tag -width indent
.It Fl a
Reset the access times on files that have been copied to the
archive.
.It Fl A
Append to the specified archive.
.It Fl B
Set block size of output to 5120 bytes.
.It Fl c
Use
.Tn ASCII
format for
.Nm
header for portability.
.It Fl C Ar bytes
Set the block size of output to
.Ar bytes .
.It Fl F Ar archive
.It Fl O Ar archive
Use the specified file name as the archive to write to.
.It Fl H Ar format
Write the archive in the specified format.
Recognized formats are:
.Pp
.Bl -tag -width sv4cpio -compact
.It Cm bcpio
Old binary
.Nm
format.
.It Cm cpio
Old octal character
.Nm
format.
.It Cm sv4cpio
.Tn SVR4
hex
.Nm
format.
.It Cm tar
Old tar format.
.It Cm ustar
.Tn POSIX
ustar format.
.El
.It Fl L
Follow symbolic links.
.It Fl v
Be verbose about operations.
List filenames as they are written to the archive.
.It Fl z
Compress archive using
.Xr gzip 1
format.
.It Fl Z
Compress archive using
.Xr compress 1
format.
.El
.It Fl i
Restore files from an archive.
Reads the archive file from
standard input and extracts files matching the
.Ar patterns
that were specified on the command line.
.Bl -tag -width indent
.It Fl b
Do byte and word swapping after reading in data from the
archive, for restoring archives created on systems with
a different byte order.
.It Fl B
Set the block size of the archive being read to 5120 bytes.
.It Fl c
Expect the archive headers to be in
.Tn ASCII
format.
.It Fl C Ar bytes
Read archive written with a block size of
.Ar bytes .
.It Fl d
Create any intermediate directories as needed during
restore.
.It Fl E Ar file
Read list of file name patterns to extract or list from
.Ar file .
.It Fl f
Restore all files except those matching the
.Ar patterns
given on the command line.
.It Fl F Ar archive , Fl I Ar archive
Use the specified file as the input for the archive.
.It Fl H Ar format
Read an archive of the specified format.
Recognized formats are:
.Pp
.Bl -tag -width sv4cpio -compact
.It Cm bcpio
Old binary
.Nm
format.
.It Cm cpio
Old octal character
.Nm
format.
.It Cm sv4cpio
.Tn SVR4
hex
.Nm
format.
.It Cm tar
Old tar format.
.It Cm ustar
.Tn POSIX
ustar format.
.El
.It Fl m
Restore modification times on files.
.It Fl r
Rename restored files interactively.
.It Fl s
Swap bytes after reading data from the archive.
.It Fl S
Swap words after reading data from the archive.
.It Fl t
Only list the contents of the archive, no files or
directories will be created.
.It Fl u
Overwrite files even when the file in the archive is
older than the one that will be overwritten.
.It Fl v
Be verbose about operations.
List filenames as they are copied in from the archive.
.It Fl z
Uncompress archive using
.Xr gzip 1
format.
.It Fl Z
Uncompress archive using
.Xr compress 1
format.
.It Fl 6
Process old-style
.Nm
format archives.
.El
.It Fl p
Copy files from one location to another in a single pass.
The list of files to copy are read from standard input and
written out to a directory relative to the specified
.Ar directory
argument.
.Bl -tag -width indent
.It Fl a
Reset the access times on files that have been copied.
.It Fl d
Create any intermediate directories as needed to write
the files at the new location.
.It Fl l
When possible, link files rather than creating an
extra copy.
.It Fl L
Follow symbolic links.
.It Fl m
Restore modification times on files.
.It Fl u
Overwrite files even when the original file being copied is
older than the one that will be overwritten.
.It Fl v
Be verbose about operations.
List filenames as they are copied.
.El
.El
.Sh ENVIRONMENT
.Bl -tag -width TMPDIR
.It Ev TMPDIR
Path in which to store temporary files.
.El
.Sh EXIT STATUS
The
.Nm
utility will exit with one of the following values:
.Bl -tag -width 2n
.It 0
All files were processed successfully.
.It 1
An error occurred.
.El
.Pp
Whenever
.Nm
cannot create a file or a link when extracting an archive or cannot
find a file while writing an archive, or cannot preserve the user
ID, group ID, file mode, or access and modification times when the
.Fl p
option is specified, a diagnostic message is written to standard
error and a non-zero exit value will be returned, but processing
will continue.
In the case where
.Nm
cannot create a link to a file,
.Nm
will not create a second copy of the file.
.Pp
If the extraction of a file from an archive is prematurely terminated
by a signal or error,
.Nm
may have only partially extracted the file the user wanted.
Additionally, the file modes of extracted files and directories may
have incorrect file bits, and the modification and access times may
be wrong.
.Pp
If the creation of an archive is prematurely terminated by a signal
or error,
.Nm
may have only partially created the archive which may violate the
specific archive format specification.
.Sh SEE ALSO
.Xr pax 1 ,
.Xr tar 1
.Sh AUTHORS
.An Keith Muller
at the University of California, San Diego.
.Sh BUGS
The
.Fl s
and
.Fl S
options are currently not implemented.
-1
View File
@@ -396,7 +396,6 @@ trng_add(char *str)
default:
paxwarn(1, "Bad option %c with time range %s",
*flgpt, str);
free(pt);
goto out;
}
++flgpt;
+310
View File
@@ -0,0 +1,310 @@
.\"-
.\" Copyright (c) 1996 SigmaSoft, Th. Lockert
.\" 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.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by SigmaSoft, Th. Lockert.
.\" 4. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
.\"
.\" $OpenBSD: tar.1,v 1.33 2001/05/01 17:58:01 aaron Exp $
.\" $FreeBSD$
.\"
.Dd February 7, 2001
.Dt TAR 1
.Os
.Sh NAME
.Nm tar
.Nd tape archiver
.Sh SYNOPSIS
.Nm
.Sm off
.Op Fl
.Brq Cm crtux
.Op Cm befhjmopqsvwyzHLOPXZ014578
.Sm on
.Op Ar blocksize
.Op Ar archive
.Op Ar replstr
.\" XXX how to do this right?
.Op Fl C Ar directory
.Op Fl I Ar file
.Op Ar
.Sh DESCRIPTION
The
.Nm
command creates, adds files to, or extracts files from an
archive file in
.Nm
format.
A
.Nm
archive is often stored on a magnetic tape, but can be
stored equally well on a floppy, CD-ROM, or in a regular disk file.
.Pp
One of the following flags must be present:
.Bl -tag -width indent
.It Fl c
Create new archive, or overwrite an existing archive,
adding the specified files to it.
.It Fl r
Append the named new files to existing archive.
Note that this will only work on media on which an end-of-file mark
can be overwritten.
.It Fl t
List contents of archive.
If any files are named on the
command line, only those files will be listed.
.It Fl u
Alias for
.Fl r .
.It Fl x
Extract files from archive.
If any files are named on the
command line, only those files will be extracted from the
archive.
If more than one copy of a file exists in the
archive, later copies will overwrite earlier copies during
extraction.
The file mode and modification time are preserved
if possible.
The file mode is subject to modification by the
.Xr umask 2 .
.El
.Pp
In addition to the flags mentioned above, any of the following
flags may be used:
.Bl -tag -width indent
.It Fl b Ar "blocking factor"
Set blocking factor to use for the archive, with 512 byte blocks.
The default is 20, the maximum is 126.
Archives with a blocking factor larger 63 violate the
.Tn POSIX
standard and will not be portable to all systems.
.It Fl e
Stop after first error.
.It Fl f Ar archive
Filename where the archive is stored.
Defaults to
.Pa /dev/sa0 .
.It Fl h
Follow symbolic links as if they were normal files
or directories.
.It Fl j
Compress archives using
.Xr bzip2 1 .
.It Fl m
Do not preserve modification time.
.It Fl O
Write old-style
.Pq non- Ns Tn POSIX
archives.
.It Fl o
Do not write directory information that the older (V7) style
.Nm
is unable to decode.
This implies the
.Fl O
flag.
.It Fl p
Preserve user and group ID as well as file mode regardless of
the current
.Xr umask 2 .
The setuid and setgid bits are only preserved if the user is
the superuser.
Only meaningful in conjunction with the
.Fl x
flag.
.It Fl q
Select the first archive member that matches each
.Ar pattern
operand.
No more than one archive member is matched for each
.Ar pattern .
When members of type directory are matched, the file hierarchy rooted at that
directory is also matched.
.It Fl s Ar replstr
Modify the file or archive member names specified by the
.Ar pattern
or
.Ar file
operands according to the substitution expression
.Ar replstr ,
using the syntax of the
.Xr ed 1
utility regular expressions.
The format of these regular expressions are:
.Dl /old/new/[gp]
As in
.Xr ed 1 ,
.Cm old
is a basic regular expression and
.Cm new
can contain an ampersand
.Pq Ql & ,
.Li \e Ns Ar n
(where
.Ar n
is a digit) back-references,
or subexpression matching.
The
.Cm old
string may also contain newline characters.
Any non-null character can be used as a delimiter
.Ql ( /
is shown here).
Multiple
.Fl s
expressions can be specified.
The expressions are applied in the order they are specified on the
command line, terminating with the first successful substitution.
The optional trailing
.Cm g
continues to apply the substitution expression to the pathname substring
which starts with the first character following the end of the last successful
substitution.
The first unsuccessful substitution stops the operation of the
.Cm g
option.
The optional trailing
.Cm p
will cause the final result of a successful substitution to be written to
standard error
in the following format:
.Pp
.Dl <original pathname> >> <new pathname>
.Pp
File or archive member names that substitute to the empty string
are not selected and will be skipped.
.It Fl v
Verbose operation mode.
.It Fl w
Interactively rename files.
This option causes
.Nm
to prompt the user for the filename to use when storing or
extracting files in an archive.
.It Fl y
Compress archives using
.Xr bzip2 1 .
.It Fl z
Compress archive using
.Xr gzip 1 .
.It Fl C Ar directory
This is a positional argument which sets the working directory for the
following files.
When extracting, files will be extracted into
the specified directory; when creating, the specified files will be matched
from the directory.
.It Fl H
Follow symlinks given on command line only.
.It Fl L
Follow all symlinks.
.It Fl P
Do not strip leading slashes
.Pq Ql /
from pathnames.
The default is to strip leading slashes.
.It Fl I Ar file
This is a positional argument which reads the names of files to
archive or extract from the given file, one per line.
.It Fl X
Do not cross mount points in the file system.
.It Fl Z
Compress archive using
.Xr compress 1 .
.El
.Pp
The options
.Op Fl 014578
can be used to select one of the compiled-in backup devices,
.Pa /dev/rst Ns Ar N .
.Sh ENVIRONMENT
.Bl -tag -width TMPDIR
.It Ev TMPDIR
Path in which to store temporary files.
.It Ev TAPE
Default tape device to use instead of
.Pa /dev/sa0 .
.El
.Sh FILES
.Bl -tag -width "/dev/sa0"
.It Pa /dev/sa0
default archive name
.El
.Sh EXIT STATUS
The
.Nm
utility will exit with one of the following values:
.Bl -tag -width 2n
.It 0
All files were processed successfully.
.It 1
An error occurred.
.El
.Pp
Whenever
.Nm
cannot create a file or a link when extracting an archive or cannot
find a file while writing an archive, or cannot preserve the user
ID, group ID, file mode, or access and modification times when the
.Fl p
option is specified, a diagnostic message is written to standard
error and a non-zero exit value will be returned, but processing
will continue.
In the case where
.Nm
cannot create a link to a file,
.Nm
will not create a second copy of the file.
.Pp
If the extraction of a file from an archive is prematurely terminated
by a signal or error,
.Nm
may have only partially extracted the file the user wanted.
Additionally, the file modes of extracted files and directories may
have incorrect file bits, and the modification and access times may
be wrong.
.Pp
If the creation of an archive is prematurely terminated by a signal
or error,
.Nm
may have only partially created the archive which may violate the
specific archive format specification.
.Sh COMPATIBILITY
The
.Fl L
flag is not portable to other versions of
.Nm
where it may have a different meaning.
.Sh SEE ALSO
.Xr cpio 1 ,
.Xr pax 1
.Sh HISTORY
A
.Nm
command first appeared in
.At v7 .
.Sh AUTHORS
.An Keith Muller
at the University of California, San Diego.
+1 -2
View File
@@ -39,7 +39,7 @@ extern fixpt_t ccpu;
extern int cflag, eval, fscale, nlistread, rawcpu;
extern unsigned long mempages;
extern time_t now;
extern int showthreads, sumrusage, termwidth, totwidth;
extern int sumrusage, termwidth, totwidth;
extern STAILQ_HEAD(velisthead, varent) varlist;
__BEGIN_DECLS
@@ -71,7 +71,6 @@ void priorityr(KINFO *, VARENT *);
void rgroupname(KINFO *, VARENT *);
void runame(KINFO *, VARENT *);
void rvar(KINFO *, VARENT *);
int s_comm(KINFO *);
int s_label(KINFO *);
int s_rgroupname(KINFO *);
int s_runame(KINFO *);
+9 -12
View File
@@ -79,8 +79,8 @@ static VAR var[] = {
CHAR, NULL, 0},
{"blocked", "", "sigmask", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
{"caught", "", "sigcatch", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
{"comm", "COMMAND", NULL, LJUST|DSIZ, ucomm, s_comm,
COMMLEN + OCOMMLEN + 1, 0, CHAR, NULL, 0},
{"comm", "COMMAND", NULL, LJUST, ucomm, NULL, MAXCOMLEN, 0, CHAR,
NULL, 0},
{"command", "COMMAND", NULL, COMM|LJUST|USER, command, NULL, 16, 0,
CHAR, NULL, 0},
{"cpu", "CPU", NULL, 0, kvar, NULL, 3, KOFF(ki_estcpu), UINT, "d",
@@ -135,13 +135,12 @@ static VAR var[] = {
LONG, "ld", 0},
{"nvcsw", "NVCSW", NULL, USER, rvar, NULL, 5, ROFF(ru_nvcsw),
LONG, "ld", 0},
{"nwchan", "NWCHAN", NULL, LJUST, nwchan, NULL, sizeof(void *) * 2, 0,
CHAR, NULL, 0},
{"nwchan", "NWCHAN", NULL, LJUST, nwchan, NULL, 8, 0, CHAR, NULL, 0},
{"oublk", "OUBLK", NULL, USER, rvar, NULL, 4, ROFF(ru_oublock),
LONG, "ld", 0},
{"oublock", "", "oublk", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
{"paddr", "PADDR", NULL, 0, kvar, NULL, sizeof(void *) * 2,
KOFF(ki_paddr), KPTR, "lx", 0},
{"paddr", "PADDR", NULL, 0, kvar, NULL, 8, KOFF(ki_paddr), KPTR,
"lx", 0},
{"pagein", "PAGEIN", NULL, USER, pagein, NULL, 6, 0, CHAR, NULL, 0},
{"pcpu", "", "%cpu", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
{"pending", "", "sig", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
@@ -195,13 +194,13 @@ static VAR var[] = {
{"tsiz", "TSIZ", NULL, 0, kvar, NULL, 4, KOFF(ki_tsize), PGTOK, "ld", 0},
{"tt", "TT ", NULL, 0, tname, NULL, 4, 0, CHAR, NULL, 0},
{"tty", "TTY", NULL, LJUST, longtname, NULL, 8, 0, CHAR, NULL, 0},
{"ucomm", "UCOMM", NULL, LJUST|DSIZ, ucomm, s_comm,
COMMLEN + OCOMMLEN + 1, 0, CHAR, NULL, 0},
{"ucomm", "UCOMM", NULL, LJUST, ucomm, NULL, MAXCOMLEN, 0, CHAR, NULL,
0},
{"uid", "UID", NULL, 0, kvar, NULL, UIDLEN, KOFF(ki_uid), UINT,
UIDFMT, 0},
{"upr", "UPR", NULL, 0, upr, NULL, 3, 0, CHAR, NULL, 0},
{"uprocp", "UPROCP", NULL, 0, kvar, NULL, sizeof(void *) * 2,
KOFF(ki_paddr), KPTR, "lx", 0},
{"uprocp", "UPROCP", NULL, 0, kvar, NULL, 8, KOFF(ki_paddr), KPTR,
"lx", 0},
{"user", "USER", NULL, LJUST|DSIZ, uname, s_uname, USERLEN, 0, CHAR,
NULL, 0},
{"usrpri", "", "upr", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
@@ -325,8 +324,6 @@ findvar(char *p, int user, char **header)
*/
rflen = strlen(v->alias) + strlen(hp) + 2;
realfmt = malloc(rflen);
if (realfmt == NULL)
errx(1, "malloc failed");
snprintf(realfmt, rflen, "%s=%s", v->alias, hp);
parsefmt(realfmt, user);
}
+2 -25
View File
@@ -175,22 +175,13 @@ command(KINFO *k, VARENT *ve)
void
ucomm(KINFO *k, VARENT *ve)
{
char tmpbuff[COMMLEN + OCOMMLEN + 2];
VAR *v;
v = ve->var;
if (STAILQ_NEXT(ve, next_ve) == NULL) /* last field, don't pad */
(void)printf("%s", k->ki_p->ki_comm);
else {
bzero(tmpbuff, sizeof(tmpbuff));
if (showthreads && k->ki_p->ki_numthreads > 1)
sprintf(tmpbuff, "%s/%s", k->ki_p->ki_comm,
k->ki_p->ki_ocomm);
else
sprintf(tmpbuff, "%s", k->ki_p->ki_comm);
(void)printf("%-*s", v->width, tmpbuff);
}
else
(void)printf("%-*s", v->width, k->ki_p->ki_comm);
}
void
@@ -812,20 +803,6 @@ out:
return;
}
int
s_comm(KINFO *k)
{
char tmpbuff[COMMLEN + OCOMMLEN + 2];
bzero(tmpbuff, sizeof(tmpbuff));
if (showthreads && k->ki_p->ki_numthreads > 1)
sprintf(tmpbuff, "%s/%s", k->ki_p->ki_comm,
k->ki_p->ki_ocomm);
else
sprintf(tmpbuff, "%s", k->ki_p->ki_comm);
return (strlen(tmpbuff));
}
int
s_label(KINFO *k)
{
+1 -2
View File
@@ -98,7 +98,6 @@ int rawcpu; /* -C */
int sumrusage; /* -S */
int termwidth; /* Width of the screen (0 == infinity). */
int totwidth; /* Calculated-width of requested variables. */
int showthreads; /* will threads be shown? */
struct velisthead varlist = STAILQ_HEAD_INITIALIZER(varlist);
@@ -176,7 +175,7 @@ main(int argc, char *argv[])
char *cols;
int all, ch, elem, flag, _fmt, i, lineno;
int nentries, nkept, nselectors;
int prtheader, wflag, what, xkeep, xkeep_implied;
int prtheader, showthreads, wflag, what, xkeep, xkeep_implied;
char errbuf[_POSIX2_LINE_MAX];
(void) setlocale(LC_ALL, "");
+38 -45
View File
@@ -68,9 +68,7 @@ STATIC int cdlogical(char *);
STATIC int cdphysical(char *);
STATIC int docd(char *, int, int);
STATIC char *getcomponent(void);
STATIC char *findcwd(char *);
STATIC void updatepwd(char *);
STATIC char *getpwd2(char *, size_t);
STATIC int updatepwd(char *);
STATIC char *curdir = NULL; /* current working directory */
STATIC char *prevdir; /* previous working directory */
@@ -203,11 +201,10 @@ cdlogical(char *dest)
}
INTOFF;
if ((p = findcwd(badstat ? NULL : dest)) == NULL || chdir(p) < 0) {
if (updatepwd(badstat ? NULL : dest) < 0 || chdir(curdir) < 0) {
INTON;
return (-1);
}
updatepwd(p);
INTON;
return (0);
}
@@ -215,14 +212,12 @@ cdlogical(char *dest)
STATIC int
cdphysical(char *dest)
{
char *p;
INTOFF;
if (chdir(dest) < 0 || (p = findcwd(NULL)) == NULL) {
if (chdir(dest) < 0 || updatepwd(NULL) < 0) {
INTON;
return (-1);
}
updatepwd(p);
INTON;
return (0);
}
@@ -252,20 +247,38 @@ getcomponent(void)
}
STATIC char *
findcwd(char *dir)
/*
* Update curdir (the name of the current directory) in response to a
* cd command. We also call hashcd to let the routines in exec.c know
* that the current directory has changed.
*/
STATIC int
updatepwd(char *dir)
{
char *new;
char *p;
hashcd(); /* update command hash table */
/*
* If our argument is NULL, we don't know the current directory
* any more because we traversed a symbolic link or something
* we couldn't stat().
*/
if (dir == NULL || curdir == NULL) {
p = stalloc(PATH_MAX);
return getpwd2(p, PATH_MAX);
if (prevdir)
ckfree(prevdir);
INTOFF;
prevdir = curdir;
curdir = NULL;
if (getpwd() == NULL) {
INTON;
return (-1);
}
setvar("PWD", curdir, VEXPORT);
setvar("OLDPWD", prevdir, VEXPORT);
INTON;
return (0);
}
cdcomppath = stalloc(strlen(dir) + 1);
scopy(dir, cdcomppath);
@@ -289,25 +302,16 @@ findcwd(char *dir)
if (new == stackblock())
STPUTC('/', new);
STACKSTRNUL(new);
return stackblock();
}
/*
* Update curdir (the name of the current directory) in response to a
* cd command. We also call hashcd to let the routines in exec.c know
* that the current directory has changed.
*/
STATIC void
updatepwd(char *dir)
{
hashcd(); /* update command hash table */
INTOFF;
if (prevdir)
ckfree(prevdir);
prevdir = curdir;
curdir = savestr(dir);
curdir = savestr(stackblock());
setvar("PWD", curdir, VEXPORT);
setvar("OLDPWD", prevdir, VEXPORT);
INTON;
return (0);
}
int
@@ -351,31 +355,17 @@ pwdcmd(int argc, char **argv)
}
/*
* Get the current directory and cache the result in curdir.
* Find out what the current directory is. If we already know the current
* directory, this routine returns immediately.
*/
char *
getpwd(void)
{
char buf[PATH_MAX];
char *p;
if (curdir)
return curdir;
p = getpwd2(buf, sizeof(buf));
if (p != NULL)
curdir = savestr(p);
return curdir;
}
/*
* Return the current directory.
*/
STATIC char *
getpwd2(char *buf, size_t size)
{
if (getcwd(buf, size) == NULL) {
if (getcwd(buf, sizeof(buf)) == NULL) {
char *pwd = getenv("PWD");
struct stat stdot, stpwd;
@@ -383,9 +373,12 @@ getpwd2(char *buf, size_t size)
stat(pwd, &stpwd) != -1 &&
stdot.st_dev == stpwd.st_dev &&
stdot.st_ino == stpwd.st_ino) {
return pwd;
curdir = savestr(pwd);
return curdir;
}
return NULL;
}
return buf;
curdir = savestr(buf);
return curdir;
}
-1
View File
@@ -147,7 +147,6 @@ readcmd(int argc __unused, char **argv __unused)
if (tcgetattr(0, &told) == 0) {
memcpy(&tnew, &told, sizeof(told));
cfmakeraw(&tnew);
tnew.c_iflag |= told.c_iflag & ICRNL;
tcsetattr(0, TCSANOW, &tnew);
tsaved = 1;
}
+2 -2
View File
@@ -383,7 +383,7 @@ shiftcmd(int argc, char **argv)
}
ap2 = shellparam.p;
while ((*ap2++ = *ap1++) != NULL);
shellparam.reset = 1;
shellparam.optnext = NULL;
INTON;
return 0;
}
@@ -405,7 +405,6 @@ setcmd(int argc, char **argv)
if (*argptr != NULL) {
setparam(argptr);
}
shellparam.reset = 1;
INTON;
return 0;
}
@@ -415,6 +414,7 @@ void
getoptsreset(const char *value)
{
if (number(value) == 1) {
shellparam.optnext = NULL;
shellparam.reset = 1;
}
}
-4
View File
@@ -370,10 +370,6 @@ introduces a comment if used at the beginning of a word.
The word starting with
.Ql #
and the rest of the line are ignored.
.Pp
.Tn ASCII
.Dv NUL
characters (character code 0) are not allowed in shell input.
.Ss Quoting
Quoting is used to remove the special meaning of certain characters
or words to the shell, such as operators, whitespace, keywords,
+4 -97
View File
@@ -12,11 +12,6 @@ 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 <[email protected]>
Co-maintainer of am-utils since late 1999: Linux and Solaris autofs support,
Linux NFSv3 support, major code reorganization, etc...
* Randall S. Winchester <[email protected]>
May 7, 1997: contributed a special version of upl102 that included NFS V.3
@@ -159,7 +154,7 @@ that do not allow forwarding of RPC messages to other services.
August 10, 1997: netbsd and other bsd systems have a mask flag for
pcfs_args (msdos mount).
* Christos Zoulas <christos@zoulas.com>
* Christos Zoulas <christos@deshaw.com>
September 25, 1997: fix to initialize uid/gid fields of pcfs_args_t on
netbsd.
@@ -168,19 +163,9 @@ 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 <[email protected]>
November 5, 1997: NFS v.3 support for AIX 4.2.1, which does *not* include
@@ -206,8 +191,6 @@ and proto.
January 12, 1998: minor bug in output of amd -H.
June 23, 2005: assortment of small compile bugs on aix4, and solaris 5/6/7.
* Thomas Richter <[email protected]>
January 13, 1998: use case insensitive comparisons for variables that need
@@ -319,13 +302,9 @@ January 25, 2000: allow browsable auto maps.
* Wolfram Klaus <[email protected]>.
November 21, 2000: recognize proplist mnttab flag.
* Thomas Klausner <[email protected].at>
* Thomas Klausner <[email protected].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 <[email protected]>
February 1, 2001: important Linux NFS error number mapping fixed
@@ -339,92 +318,20 @@ March 27, 2002: LDAP bug and port to HPUX-11.
* Philippe Troin <[email protected]>
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.
disabling LDAP/Hesiod, fixes for the dev/nodev option on Linux
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.
July 17, 2003: Debian fixes. Null am_pref free.
* Trond Myklebust <[email protected]>
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 <[email protected]>
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 <[email protected]>).
* Matthias Scheler <[email protected]>
June 14, 2002: patch to use "xlatecookie" NFS mount option.
* Jun-ichiro itojun Hagino <[email protected]>.
June 11, 2002: minor fixes to support NetBSD 1.6A.
* Sean Fagan <[email protected]>
March 14, 2003: detect and use the MNT2_GEN_OPT_AUTOMNTFS mount flag
on OS X / Darwin.
* Hendrik Scholz <[email protected]>
June 9, 2003: mk-amd-map should open temp db file using O_EXCL.
* Mark Davies <[email protected]>
July 14, 2003: define "xlatecookie" mnttab option if not defined (for
NetBSD). Support null hesiod entries if they start with a ".".
* Eric S. Raymond <[email protected]>
December 9, 2003: fix unbalanced [] typo in fsinfo man page.
* Martin Blapp <[email protected]>
July 6, 2004: recognize fields in pcfs_args_t in FreeBSD 5.
* Dan Nelson <[email protected]>
August 2, 2004: pawd to recognize "host" type mounts.
* Hauke Fath <[email protected]>
August 3, 2004: pawd to recognize "linkx" type mounts.
* Michael van Elst <[email protected]>
September 1, 2004: bug fix to avoid race condition in calls to mntctl on
AIX.
* Jonathan Chen <[email protected]>
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 <[email protected]>
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 <[email protected]>
January 28, 2005: basic instructions how to setup Amd on Mac OS-X.
* Dan Ottavio <[email protected]>
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 <[email protected]>
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 <[email protected]>
July 4, 2005: buffer overflow in pawd.
* Steve Plite <[email protected]>
September 22, 2005: repair reversed meaning of D_AMQ, so amq will unregister
on exit.
+9 -106
View File
@@ -1,8 +1,5 @@
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 [email protected] mailing list.
(1) mips-sgi-irix*
@@ -166,15 +163,12 @@ kernel will panic.
The Linux kernels don't support Amd's direct mounts very well, leading to
erratic behavior: shares that don't get remounted after the first timeout,
inability to restart Amd because its mount points cannot be unmounted, etc.
There are some kernel patches on the am-utils Web site, which solve these
problems. See http://www.am-utils.org/patches/.
inability to restart Amd because its mount points cannot be unmounted,
etc. There are some kernel patches on the am-utils Web site, which solve
these problems. See http://www.am-utils.org/patches/.
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).
UPDATE: kernels 2.4.10 and later completely disallow the direct mount hack,
so direct mounts are simply not possible on those Linux kernels.
(12) *-aix5.1.0.0 and *-hpux9*
@@ -183,24 +177,14 @@ 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.*
[12A] *-aix5.1.*
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.
although amd does the right thing. The bug appears to have been fixed in
AIX 5.2. No known fix/patch is available for AIX 5.1 as of now (1/25/2003).
(13) *-linux and *-darwin6.0
@@ -217,87 +201,6 @@ 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.
Erez & Ion.
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 [email protected]. ##
configure: WARNING: ## ------------------------------------ ##
please ignore them. They are not real errors, and neither
[email protected] 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 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 1997-2006 Erez Zadok
Copyright (c) 1997-2004 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.
+291 -6005
View File
File diff suppressed because it is too large. Load diff
-69
View File
@@ -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
[email protected].
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>
-123
View File
@@ -2,7 +2,6 @@ $FreeBSD$
*LSM.am-utils
*Makefile.*
*README.autofs
*README.osx
*ac*.m4
*.old
*acconfig.h
@@ -16,7 +15,6 @@ $FreeBSD$
*missing
*mkinstalldirs
*stamp-h.in
*amd/test1.sh
*amd/Makefile.*
*amq/Makefile.*
*commit
@@ -40,13 +38,10 @@ $FreeBSD$
*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
@@ -59,7 +54,6 @@ $FreeBSD$
*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
@@ -69,7 +63,6 @@ $FreeBSD$
*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
@@ -99,12 +92,6 @@ $FreeBSD$
*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
@@ -116,7 +103,6 @@ $FreeBSD$
*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
@@ -129,9 +115,7 @@ $FreeBSD$
*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
@@ -151,118 +135,11 @@ $FreeBSD$
*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
+9 -10
View File
@@ -1,19 +1,21 @@
# ex:ts=8
$FreeBSD$
AMD (am-utils) 6.1.5
originals can be found at: ftp://ftp.am-utils.org/pub/am-utils/
AMD (am-utils) 6.0.9
originals can be found at: ftp://shekel.mcl.cs.columbia.edu/pub/am-utils/
(http://www.cs.columbia.edu/~ezk/am-utils/index.html)
For the import of AMD many files were pruned by:
tar -X FREEBSD-Xlist -xf am-utils-6.1.5.tar.gz
tar -X FREEBSD-Xlist -xzf am-utils-6.0.9.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
cvs import -m 'Virgin import of AMD (am-utils) v6.0.9' \
src/contrib/amd COLUMBIA amd_6_0_9
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
@@ -23,11 +25,8 @@ 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 "[email protected]" or
https://bugzilla.am-utils.org for inclusion in the next vendor release.
All local changes should be submitted to "[email protected]"
for inclusion in the next vendor release.
Local changes:
+138 -99
View File
@@ -1,91 +1,113 @@
am-utils 6.1 compatibility list
am-utils 6.0 compatibility list
For each system, list if it autoconfigures, compiles, or runs. Fill in
email id of person who confirms the fact. A missing entry means unverified.
A 'no' or 'X' means verified broken or nonexistent (static library).
SYSTEM CONFIG COMPILE RUN SHLIB AUTOFS
========================= ======= ======= ======= ======= ======
alpha-dec-osf4.0f ro ro ro - -
alpha-dec-osf5.1 ro ro ro - -
alpha-unknown-linux-gentoo1.4.16 ezk ezk ezk ezk -
alphaev56-dec-osf4.0f ezk ezk ezk ezk -
i386-apple-darwin6.0 ezk ezk ezk ezk -
i386-pc-bsdi2.1 ion ion ion ion[X] ion[X]
i386-pc-linux-deb3.0 ezk ezk ezk ezk -
i386-pc-linux-deb3.1 ezk ezk ezk ezk -
i386-pc-linux-fc1 ezk ezk ezk ezk -
i386-pc-linux-fc2 ezk ezk ezk ezk -
i386-pc-linux-fc3 ezk ezk ezk ezk -
i386-pc-linux-fc4 ezk ezk ezk ezk -
i386-pc-linux-gentoo1.4.16 ezk ezk ezk ezk -
i386-pc-linux-rh6.2 ion ion ion ion ion
i386-pc-linux-rh7.1 ion ion ion ion ion
i386-pc-linux-rh7.2 ion ion ion ion ion
i386-pc-linux-rh7.3 ion ion ion ion ion
i386-pc-linux-rh8.0 ezk ezk ezk ezk -
i386-pc-linux-rh9 ion ion ion ion ion
i386-pc-linux-rhel3 ezk ezk ezk ezk -
i386-pc-linux-rhel4 ezk ezk ezk ezk -
i386-pc-linux-suse8.2 ezk ezk ezk ezk -
i386-pc-linux-suse9.1 ezk ezk ezk ezk -
i386-pc-linux-suse9.2 ezk ezk ezk ezk -
i386-pc-linux-suse9.3 ezk ezk ezk ezk -
i386-pc-solaris2.10 ro ro ro - -
i386-pc-solaris2.9 ro ro ro - -
i386-unknown-freebsd4.10 ezk ezk ezk ezk -
i386-unknown-freebsd4.11 ezk ezk ezk ezk -
i386-unknown-freebsd4.8 ezk ezk ezk ezk -
i386-unknown-freebsd4.9 ezk ezk ezk ezk -
i386-unknown-freebsd5.0 ezk ezk - ezk -
i386-unknown-freebsd5.1 ezk ezk ezk ezk -
i386-unknown-freebsd5.2 ezk ezk ezk ezk -
i386-unknown-freebsd5.2.1 ezk ezk ezk ezk -
i386-unknown-freebsd5.3 ezk ezk ezk ezk -
i386-unknown-freebsd5.4 ezk ezk ezk ezk -
i386-unknown-freebsd6 (BETA5) ezk ezk ezk ezk -
i386-unknown-netbsd1.6A ezk ezk ezk ezk -
i386-unknown-netbsdelf1.6.1 ezk ezk ezk ezk -
i386-unknown-netbsdelf1.6.2 ezk ezk ezk ezk -
i386-unknown-netbsdelf2.0 ezk ezk ezk ezk -
i386-unknown-netbsdelf2.0.2 ezk ezk ezk ezk -
i386-unknown-netbsdelf3.0 ezk ezk ezk ezk -
i386-unknown-openbsd3.3 ezk ezk ezk ezk -
i386-unknown-openbsd3.6 ezk ezk ezk ezk -
i386-unknown-openbsd3.7 ezk ezk ezk ezk -
i686-apple-darwin6.6 ezk ezk ezk ezk -
ia64-hp-hpux11.20 ezk ezk ezk ezk -
ia64-unknown-linux-rh2.1AS ezk ezk - ezk -
ia64-unknown-linux-rh2.1AW ezk ezk ezk ezk -
ia64-unknown-linux-rhel4 ezk ezk ezk ezk -
mips-sgi-irix6.2 ro ro ro - -[3]
mips-sgi-irix6.5 ro ro ro - -[3]
mips-unknown-linux-gentoo1.4.16 ezk ezk ezk ezk -
mipsel-unknown-linux-rhPS2 ezk ezk ezk ezk -
powerpc-apple-darwin7.6.0 ezk ezk ezk ezk -
powerpc-apple-darwin7.7.0 ezk ezk ezk ezk -
powerpc-apple-darwin7.8.0 ezk ezk ezk ezk -
powerpc-apple-darwin7.9.0 ezk ezk ezk ezk -
powerpc-apple-darwin8.2.0 ezk ezk ezk ezk -
powerpc-ibm-aix5.1.0.0 ion ion ion ion[X] ion[1,2]
powerpc-ibm-aix5.2.0.0 ezk ezk ezk ezk -
powerpc-ibm-aix5.3.0.0 ezk ezk ezk ezk -
powerpc-unknown-linux-yellowdog2.3 ezk ezk ezk ezk -
sparc-sun-solaris2.10 ro ro ro - -
sparc-sun-solaris2.5.1 ion ion ion ion ion[1]
sparc-sun-solaris2.6 ion ion ion ion ion
sparc-sun-solaris2.7 ion ion ion ion ion
sparc-sun-solaris2.8 ion ion ion ion ion
sparc-sun-solaris2.9 ro ro ro - -
sparc-unknown-linux-rh62 ion ion ion ion ion
sparc64-unknown-linux-aurora10 ion ion ion ion ion
sparc64-unknown-linux-deb3.0 ezk ezk ezk ezk -
sparc64-unknown-linux-gentoo1.4.16 ezk ezk ezk ezk -
sparc64-unknown-linux-rh62 ion ion ion ion ion
sparc64-unknown-linux-suse7.3 ezk ezk - ezk -
x86_64-unknown-linux-rh2.9.5AS ezk ezk ezk ezk -
x86_64-unknown-linux-rh3.0.0AS ion ion ion ion ion
SYSTEM CONFIG COMPILE RUN SHLIB
========================= ====== ======= ===== =====
alpha-dec-osf2.1 ezk[0] ezk ezk ezk[X]
alpha-dec-osf4.0 ezk[0] ezk dsr[3] ezk
alpha-dec-osf4.0f ezk[0] ezk dsr[3] ezk
alpha-dec-osf5.1 ro[0] ro ro ro
alphaev5-unknown-linux ezk[0] ezk finkel ezk
alphaev5-unknown-linux-rh5.2 ezk[0] ezk ezk ezk
alphaev6-dec-osf5.0 ezk[0] ezk dsr[3] ezk
hppa1.0-hp-hpux11.00 ezk[0] ezk ezk ezk
hppa1.1-hp-hpux10.10 ezk[0] ezk ezk ezk
hppa1.1-hp-hpux10.20 ezk[0] ezk ezk ezk
hppa1.1-hp-hpux11.00 ezk[0] ezk ezk ezk
hppa1.1-hp-hpux9.01 ezk[0,4]ezk[4] nrh/ezk ezk
hppa1.1-hp-hpux9.05 ezk[0,4]ezk[4] nrh/ezk ezk
hppa1.1-hp-hpux9.07 ezk[0,4]ezk[4] nrh/ezk ezk
hppa2.0w-hp-hpux11.00 ezk[0] ezk ezk ezk
i386-pc-bsdi2.1 ion ion ion ion[X]
i386-pc-bsdi3.0 ezk[0] ezk ezk ezk[X]
i386-pc-bsdi3.1 ezk[0] ezk ezk ezk[X]
i386-pc-bsdi4.0 ezk[0] ezk ezk ezk
i386-pc-bsdi4.0.1 ezk[0] ezk ezk ezk
i386-pc-bsdi4.1 ezk[0] ezk ezk ezk
i386-pc-linux ezk[0] ezk ezk ezk
i386-pc-linux-libc1 ezk[0] ezk ezk ezk
i386-pc-linux-libc1-rh4.2 ezk[0] ezk ezk ezk
i386-pc-linux-rh5.2 ezk[0] ezk ezk ezk
i386-pc-linux-rh6.0 ezk[0] ezk ezk ezk
i386-pc-linux-rh6.1 ezk[0] ezk ezk ezk
i386-pc-linux-rh6.2 ion ion ion ion
i386-pc-linux-rh7.1 ion ion ion ion
i386-pc-linux-rh7.2 ion ion ion ion
i386-pc-linux-rh7.3 ion ion ion ion
i386-pc-solaris2.5.1 ezk[0] ezk ezk ezk
i386-pc-solaris2.6 ezk[0] ezk ezk ezk
i386-pc-solaris2.7 ezk[0] ezk ezk ezk
i386-unknown-freebsd2.1.0 ezk[0] ezk ezk
i386-unknown-freebsd2.2.1 ezk[0] ezk ezk ezk
i386-unknown-freebsd2.2.6 ezk[0] ezk ezk ezk
i386-unknown-freebsd2.2.7 ezk[0] ezk ezk ezk
i386-unknown-freebsd2.2.8 ezk[0] ezk ezk ezk
i386-unknown-freebsd3.0 ezk[0] ezk ezk ezk
i386-unknown-freebsd4.2 ezk[0] ezk ezk ezk
i386-unknown-freebsd4.4 ezk[0] ezk ezk ezk
i386-unknown-freebsd5.0 ezk[0] ezk ezk ezk
i386-unknown-freebsdelf3.0 ezk[0] ezk ezk ezk
i386-unknown-freebsdelf3.1 ezk[0] ezk ezk ezk
i386-unknown-freebsdelf3.2 ezk[0] ezk ezk ezk
i386-unknown-freebsdelf3.3 ezk[0] ezk ezk ezk
i386-unknown-freebsdelf3.4 ezk[0] ezk ezk ezk
i386-unknown-freebsdelf4.0 ezk[0] ezk ezk ezk
i386-unknown-netbsd1.2.1 ezk[0] ezk ezk ezk
i386-unknown-netbsd1.3 ezk[0] ezk ezk ezk
i386-unknown-netbsd1.3.1 ezk[0] ezk ezk ezk
i386-unknown-netbsd1.3.2 ezk[0] ezk ezk ezk
i386-unknown-netbsd1.3.3 ezk[0] ezk ezk ezk
i386-unknown-netbsd1.4 ezk[0] ezk ezk ezk
i386-unknown-netbsd1.4.1 ezk[0] ezk ezk ezk
i386-unknown-openbsd2.1 ezk[0] ezk ezk ezk
i386-unknown-openbsd2.2 ezk[0] ezk ezk ezk
i386-unknown-openbsd2.3 ezk[0] ezk ezk ezk
i386-unknown-openbsd2.4 ezk[0] ezk ezk ezk
i386-unknown-openbsd2.5 ezk[0] ezk ezk ezk
i486-ncr-sysv4.3.03 ezk[0] ezk ezk
ia64-hp-hpux11.20 ezk[0] ezk ezk ezk
ia64-unknown-linux-rh7.1 ezk[0] ezk ezk ezk
ia64-unknown-linux-rh7.2 ezk[0] ezk ezk ezk
ia64-unknown-linux-rh2.1AS ezk[0] ezk ezk ezk
ia64-unknown-linux-rh2.1AW ezk[0] ezk ezk ezk
m68k-hp-hpux9.00 ezk[0,4]ezk[4] nrh/ezk
m68k-next-nextstep3 ezk[0] ezk ezk ezk[X]
m68k-sun-sunos4.1.1 ezk[0] ezk ezk[X]
mips-dec-ultrix4.3 ro[0] ro ro
mips-sgi-irix5.3 ezk[0] ezk ezk ezk
mips-sgi-irix6.2 ezk[0,1]ezk[1] ezk[1] ezk
mips-sgi-irix6.4 ezk[0] ezk ezk ezk
mips-sgi-irix6.5 ezk[0] ezk ezk
powerpc-ibm-aix4.1.5.0 ezk[0] ezk wpaul ezk[X]
powerpc-ibm-aix4.2.1.0 ezk[0] ezk ezk ezk[X]
powerpc-ibm-aix4.3.1.0 ezk[0] ezk ezk[X]
powerpc-ibm-aix5.1.0.0 ion ion ion ion[X]
powerpc-unknown-linux jose[0] jose jose
rs6000-ibm-aix3.2 ezk[0] ezk ezk
rs6000-ibm-aix3.2.5 ezk[0] ezk ezk
rs6000-ibm-aix4.1.4.0 ezk[0] ezk ezk[X]
rs6000-ibm-aix4.1.5.0 ezk[0] ezk ezk[X]
sparc-sun-solaris2.3 ezk[0] ezk ezk ezk
sparc-sun-solaris2.4 ezk[0] ezk ezk ezk
sparc-sun-solaris2.5 ezk[0] ezk ezk ezk
sparc-sun-solaris2.5.1 ion ion ion ion
sparc-sun-solaris2.6 ion ion ion ion
sparc-sun-solaris2.7 ion ion ion ion
sparc-sun-solaris2.8 ion ion ion ion
sparc-sun-sunos4.1.1 ezk[0] ezk ezk ezk
sparc-sun-sunos4.1.3 ezk[0] ezk ezk ezk
sparc-sun-sunos4.1.3C ezk[0] ezk ezk ezk
sparc-sun-sunos4.1.3_U1 ezk[0] ezk ezk ezk
sparc-sun-sunos4.1.4 ezk[0] ezk ezk ezk
sparc-unknown-linux-libc1 ezk[0] ezk ezk ezk
sparc-unknown-linux-rh6.2 ion ion ion ion
sparc-unknown-netbsd1.2E ezk[0] ezk ezk
sparc-unknown-netbsd1.2G ezk[0] ezk ezk
sparc64-unknown-linux-rh6.2 ion ion ion ion
sparc64-unknown-linux-suse7.3 ezk[0] ezk ezk ezk
EMAIL ID LEGEND:
@@ -103,22 +125,39 @@ wpaul: Bill Paul <[email protected]>
FOOTNOTES:
[1] Due to limitations in the Sun autofs v1 implementation, some amd features
cannot be properly supported. More precisely, trying to access a link mount
pointing to another amd entry will result in failure and/or deadlock.
Ordinary nfs and link mounts work well, however.
[0] These entries were tested with older 6.0 releases, but not with the
latest version. They probably still work, however.
[2] AIX autofs appears to be a variant of the Sun autofs v1 protocol, but
IBM don't provide any sort of documentation or even header files from it.
It is currently unsupported; we may add some experimental support for it at
some point, though it won't be pretty. Assistance from IBM-ers would be
highly appreciated, hint hint.
[1] If compiling with cc on Irix 6, then use
[3] IRIX 6 autofs uses the Sun autofs v1 protocol, too. The header files
are part of the onc3_eoe.sw.autofs (IRIX 6.2) or nfs.sw.autofs (IRIX 6.5)
package, which may not be installed. The autofs code is known to compile,
but hasn't been run yet. SGI's autofsd uses a barely documented system
call, syssgi(SGI_AUTOFS_SYS, ...), which may be required to get working
autofs support. Additional help from SGI would be highly appreciated.
CC="cc -32 -Wl,-woff,84" ./buildall
Erez & Ion
to build (good) "old style" 32 bit code and suppress stupid linker warnings
about unused libraries.
Also, to get NFS V3 working, you need these two patches from SGI:
patch 1615: NFS over TCP
patch 2041: NFS roll-up patch
and then add "-p tcp" to /etc/config/nfsd.options.
[2] ... has gone missing ...
[3] DU-4.0 may not use NFS (server-side) V3 by default. You may need to
adjust /etc/init.d/nfs, and change the nfsd startup line from to
if /usr/sbin/nfsd $NUM_NFSD; then
to
if /usr/sbin/nfsd -t 8 -u 8 ; then
[4] HPUX 9.X has a bad /bin/sh that runs out of fixed memory allocations.
If you use the configure script, you must run it as
/bin/ksh ./configure
Also, this system has a bad /bin/make that cannot handle VPATH well. You
cannot use --srcdir or the buildall script with it. I suggest you install
GNU make or configure locally with "/bin/ksh ./configure".
Erez.
+93 -609
View File
@@ -1,663 +1,147 @@
*** Notes specific to am-utils version 6.1.5
New amd.conf global parameter: nfs_allow_any_interface. By default it is
set to 'no' which means that Amd accepts local NFS packets only from
127.0.0.1. If set to 'yes' then Amd will accept local NFS packets from any
local interface; this is useful on hosts that may have multiple interfaces
where the system is forced to send all outgoing packets (even those bound to
the same host) via an address other than 127.0.0.1.
Add support for specifying the host to match in the mount selectors netgrp
and netgrpd. Now one can use either netgrp(<group-name>) or
netgrp(<group-name>,<host-name>).
- Bugs fixed:
* handle old-style filehandles correctly (for mount points longer
than 28 chars)
* don't turn off attribute cache for regular NFS mounts (improves
performance)
* detect G/DBM support via gdbm_compat library (Debian)
* detect NDBM support in libc (FreeBSD 6)
*** Notes specific to am-utils version 6.0.10-pre:
- minor new ports:
i386-unknown-freebsd6.1 (RELEASE)
i386-unknown-openbsd3.9
powerpc-apple-darwin8.6.0
*** Notes specific to am-utils version 6.1.4
Support new mount options for type:=pcfs mounts: longname, nowin95,
shortname, user=N, group=N, mask=N, and dirmask=N.
Two new amd.conf [global] parameters: nfs_retry_interval_toplvl and
nfs_retransmit_counter_toplvl. They are similar to nfs_retry_interval and
nfs_retransmit_counter, and allow you to set the "timeo" and "retrans" NFS
mount parameters, respectively, but ONLY for Amd's top-level mounts (which
are NFSv2/UDP currently). This is useful because on some systems you may
wish to set these parameters differently than the OS default, so as to
better tune Amd's responsiveness under heavy scheduler loads.
- minor new ports:
i386-pc-linux-fc5 (Fedora Core 5)
i386-pc-linux-suse10.1 (beta 8)
i386-unknown-freebsd6.0 (RELEASE)
i386-unknown-netbsdelf2.1
i386-unknown-netbsdelf3.0 (RELEASE)
i386-unknown-openbsd3.8
powerpc-apple-darwin8.5.0
- Bugs fixed:
* one serious memory leak in amfs_generic (caught by Coverity)
* assorted potential (but rare) NULL pointer dereferences (Coverity)
* correctly print nfs_args->addr info (sin_family/port/addr)
* pawd should resolve path repeatedly until no more to do
* use-after-free bug in amfs_lookup_mntfs (Coverity)
*** Notes specific to am-utils version 6.1.3
- Bugs fixed:
* amq should de-register properly on exit
* convert all sprintf to safer xsnprintf
* convert all strcat to safer xstrlcat
* convert all strcpy to safer xstrlcpy
* fix three buffer overruns in expand_op (amd/opts.c)
* pawd was trying UDP only, now try TCP if UDP failed
Moved pawd's path-matching functionality into Amd, where it can be done a
lot more efficiently (we no longer need to construct and send the whole
mounted tree, only to match small parts of it). This will lessen the CPU
and network load on systems that use pawd heavily, and also minimize the
chance that we exceed default or hard-coded UDP/TCP RPC packet sizes.
*** Notes specific to am-utils version 6.1.2.1
- Bugs fixed:
* properly turn off the attrcache in freebsd and openbsd
* can turn off attrcache on netbsd, but need kernel patch, see
README.attrcache
* pawd goes into an infinite loop on type:=auto
* consistent search for file system mnttab/mount names
*** Notes specific to am-utils version 6.1.2
MAJOR BUG FIXES: Synchronize Amd's view of its file systems with the
kernel's NFS client-side DNLC/dcache. Amd changes its view when it reloads
maps (automatically or via "amq -f") because new map entries could be added,
old one removed, or existing ones changed. Amd also changes its view when a
simple entry has expired and was flushed, or was forced out via "amq -u".
Amd was not updating the mtime of its parent directory (often the amd
automount point): this resulted in the kernel re-using cached entries, which
are now possibly stale. Many users had seen this problem in the form of
occasional ESTALE errors, or dangling/broken automounted symlinks,
especially on systems under heavy use. To tell the kernel to ignore (flush)
its old entries for an directory, the mtime of the directory must be updated
(monotonically incremented). Amd was indeed doing so in several places, but
unfortunately it was using time(2) which only provides a one-second
resolution clock: this was fine a decade ago, but not good enough on today's
fast systems; using only a one-second resolution clock meant that on busy
systems that invoke Amd many times a second, some rapidly changing entries
do not get flushed from the kernel, and the kernel thus uses stale entries.
The solution to all of these was to rework the whole clock timer updates to
use gettimeofday(), using a micro-second resolution timer, and to use that
time whenever Amd needs to update an mtime/atime/ctime of any node.
Finally, we now update the mtime in places that were never updated before
(when a whole map is flushed or a single entry times out).
Warning: some OSs, we discovered, are incapable of turning off their
NFS attribute cache entirely. This means that Amd cannot work fully
reliability on these systems, not under heavy load. This is documented in
detail in the README.attrcache file included with this distribution.
Include test-attrcache script to test the NFS attribute cache behavior using
Amd.
Tell syslog not to log automatically to /dev/console; it's unfriendly. If
user really wants to, they can set it in /etc/syslog.conf.
- minor new ports:
i386-pc-linux-deb3.1
i386-unknown-netbsdelf3.0
powerpc-apple-darwin8.2.0
- bugs fixed:
* minor documentation corrections
*** Notes specific to am-utils version 6.1.1
New amd.conf global parameter: forced_unmounts (default to "no"). If set to
"yes," and the client OS supports forced or lazy unmounts, then Amd will
attempt to use them if it gets any of three serious error conditions when
trying to unmount an existing mount point or mount on top of one: EIO,
ESTALE, or EBUSY. This could be useful to recover from serious conditions
such as hardware failure of mounted disks, or NFS servers which are down
permanently, were migrated, or changed their IP address. Only
"type:=toplvl" mounts hung with EBUSY are forcibly unmounted using this
option: this is useful to ensure that a new Amd can mount itself even if a
previous Amd died and left its mount points hung, or to force Amd to
shutdown cleanly, even if some processes (i.e., user shells) have their CWD
on Amd's own mount point. This functionality is available for Linux, BSD44
systems, Solaris, OSF/1, and partially for AIX.
New amd.conf global parameter: truncate_log (default to "no"). If set to
"yes", then Amd will truncate the log file (if it's a regular file) on
startup. This could be useful when conducting extensive testing on Amd maps
(or Amd itself) and you don't want to see log data from a previous run in
the same file.
- minor new ports:
i386-pc-linux-fc4
i386-pc-linux-suse9.3
i386-pc-linuxoldld-deb3.1
- bugs fixed:
* safer mtab handling for Linux (locks + handles /proc/mounts)
* small compile problems on Solaris 6 (rpcvers_t)
* small compile problems on HPUX 10 (h_errno)
* possibly missing definition of INADDR_NONE in wire.c
* extern for sleep(3) may be missing on older gcc systems
* updated nfs_args structure on aix4.
* possible running off end of exported_ap[] array.
* buffer overflow in pawd.
* aix4 clean build.
* use strlcat/snprintf in a few places for safety.
* recover from IP address change of a down NFS server
* don't discard restarted mntfs that was used.
*** Notes specific to am-utils version 6.1
- bugs fixed:
* set timeo/retrans for type:=nfs only if user asked
Also, if you want to know what's new in 6.1 compared to 6.0.x, it's
EVERYTHING below this line, up to "6.0.4." Yes, that's a lot of stuff.
*** Notes specific to am-utils version 6.1-rc7
Remove alloca from am-utils, and rewrite code that used it.
Assorted minor code cleanups.
- minor new ports:
alpha-unknown-linux-gentoo1.4.16
alphaev56-dec-osf4.0f (using both cc and gcc)
mips-sgi-irix6.5 (using both cc and gcc)
mips-unknown-linux-gentoo1.4.16
sparc64-unknown-linux-gentoo1.4.16
- bugs fixed:
* getwire() detects networks correctly on OSF/1
*** Notes specific to am-utils version 6.1-rc6
- minor new ports:
i386-pc-linux-deb3.0
i386-pc-linux-gentoo1.4.16
i386-pc-linux-suse9.2
i386-unknown-freebsd5.4
i386-unknown-netbsdelf2.0.2
i386-unknown-openbsd3.7
powerpc-unknown-linux-yellowdog2.3
- bugs fixed:
* minor compile error of nfs_subr.c on some systems.
* AIX 5.2/5.3 PPC compile fixes.
*** Notes specific to am-utils version 6.1-rc5
For NetBSD systems, $os used to say "netbsdelf1" or "netbsdelf2." Now it
just says "netbsd."
- minor new ports:
powerpc-apple-darwin7.9.0
- bugs fixed:
* silly (but nasty) null pointer dereferencing
* improved fix for '-opts' syntax for resetting map options
*** Notes specific to am-utils version 6.1-rc4
- bugs fixed:
* check for "macosx" in M4 macros properly
* minor memory leaks (thanks to Valgrind)
*** Notes specific to am-utils version 6.1-rc3
Minor fix to configure.in. Reran bootstrap to get a working configure
script that indeed checks for certain Linux nfs/autofs headers.
*** Notes specific to am-utils version 6.1-rc2
New amd.conf global parameter: normalize_slashes (default to "yes"). If set
to "no," then Amd will not condense repeated slashes or remove trailing ones
from strings representing pathnames. This is sometimes useful with SMB
mounts, which often require multiple slash characters in pathnames.
Using a custom version of strlcpy instead of strncpy (but only where it
makes sense), to minimize string overflow changes. Audited all use of
strncpy/strlcpy to ensure safety.
On Apple machines, use "powerpc" for $arch, instead of "Power Macintosh".
Also, use sw_vers to find out more appropriate OS name (macosx) and OS
version (10.3.x) than uname(3) reports.
- minor new ports:
powerpc64-unknown-linux-rhel4
powerpc64-unknown-linux-sles9
- bugs fixed:
* pawd handles all file systems
* fix double-free in type:=nfsx
* timeo and retrans shouldn't be set for type:=toplvl
* fix inconsistency in handling filehandle generation number
* document proper use of hosts.allow (don't spawn)
* single dash '-' map entry now resets the defaults
*** Notes specific to am-utils version 6.1-rc1
- minor new ports:
i386-pc-linux-fc2 (Fedora Core 2).
i386-pc-linux-fc3 (Fedora Core 3).
i386-pc-linux-rhel3
i386-pc-linux-rhel4
i386-pc-linux-suse8.2
i386-pc-linux-suse9.1
i386-pc-solaris2.10
i386-unknown-freebsd4.8
i386-unknown-freebsd4.9
i386-unknown-freebsd4.10
i386-unknown-freebsd4.11
i386-unknown-freebsd5.1 (5.1-RELEASE)
i386-unknown-freebsd5.2 (5.2-RELEASE)
i386-unknown-freebsd5.2.1 (5.2.1-RELEASE)
i386-unknown-freebsd5.3 (5.3-RELEASE)
i386-unknown-freebsd6.0 (6.0-CURRENT-SNAP001)
i386-unknown-netbsdelf1.6.1
i386-unknown-netbsdelf2.0
i386-unknown-openbsd3.6
ia64-hp-hpux11.20
ia64-unknown-linux-rhel4
mipsel-unknown-linux-rhPS2 (Linux on Sony PlayStation 2)
powerpc-apple-darwin7.6.0
powerpc-apple-darwin7.7.0
powerpc-apple-darwin7.8.0
powerpc-ibm-aix5.2.0.0
powerpc-ibm-aix5.3.0.0
sparc-sun-solaris2.10
sparc64-unknown-linux-deb3.0
x86_64-unknown-linux-rh2.9.5AS
- support for executable maps ala Sun automounter. Set map_type=exec in
amd.conf, and map_name to a program/script that takes a key as argv[1],
and returns key-value pair on stdout. See also exec_map_timeout [global]
parameter which defines how many seconds (default 10 sec) Amd will wait
for an executable map program to return output before timing out. See
am-utils manual for full details.
- new amd.conf parameter "nfs_allow_insecure_port". Used to work around
bugs in certain kernels, which cause them to try and talk to amd from
unprivileged ports.
- new amd.conf parameter: localhost_address. Used to override the localhost
(often 127.0.0.1) address Amd uses to connect to for the local NFS server
and RPC server.
- new amd.conf [global] parameter: domain_strip (default "yes"). If set to
"no," Amd won't strip domain names from host names, which is useful if
your Amd maps are served by multiple domains and you want to tell from the
logs which exact host did what.
- new amd.conf [global] parameter: auto_attrcache (default to 0). Sets
Amd's own NFS attribute-cache timeout in seconds. A value of 0 turns off
attribute caching, meaning that Amd will be consulted via a kernel-RPC
each time someone stat's the mount point (which could be abused as a
denial-of-service attack). If you're concerned, set this to something
greater than zero (a value of 1 second is currently recommended).
Warning: if you set this option to any non-zero value, especially a large
value, and you get ESTALE errors on your particular OS, then set this
value back to 0 seconds.
- four new amd.conf [global] parameters, similar to nfs_retry_interval and
nfs_retransmit_counter, which allow you to set the "timeo" and "retrans"
NFS mount parameters, respectively. Now you can set those parameters
globally and separately for UDP vs. TCP, using any of these:
nfs_retry_interval_udp, nfs_retransmit_counter_udp nfs_retry_interval_tcp,
and nfs_retransmit_counter_tcp.
- new amd.conf [global] parameter: preferred_amq_port. Allows you to select
the UDP+TCP port that Amd's amq service will use with the RPC portmapper.
Useful with firewalls and NAT'ed environments.
- new amd.conf option "debug_mtab_file". Allows user to define the mtab
file during debug-mtab mode. The default path is "/tmp/mnttab".
- new function selector xhost(ARG) which will match ARG against the current
host name. This works even if ARG is a CNAME (unlike the host==ARG
selector).
- support restarting the automounter's own mount points (only over NFS,
for now).
- fully support WebNFS as per RFC 2054. It now tries v3/TCP first, falling
back to v2/UDP if this doesn't work. The "webnfs" pseudo-mount options
has been renamed (again) to "public" to match Solaris 2.
- restructured the restarting of already-mounted filesystems, in the process
also fixing a problem with restarting nfsx components.
- support escaped slashes, needed for SMB mounts. Use '\\\/\\\/' in a
string to get a double slash.
- amd -v now prints domain, host, and hostd values: foo, example.com, and
foo.example.com, respectively.
- On Linux, if umount(2) failed with EIO or ESTALE, try the new umount2(2)
system call with MNT_FORCE+MNT_DETACH. This could be quite helpful to
unmounting hung mount points that otherwise cannot be fixed without a
reboot.
- The ping=N mount option now works. N defaults to 30 seconds for all NFS
servers. It can now be set to any value for each server separately.
Setting it to a large value can reduce the amount of NFS_NULL chatter on
your network considerably, especially in large sites. Setting this to -1
will turn off pings for that server (useful in NFS-HA setups). Setting N
to 0 will pick the default ping value in Amd (currently 30 seconds). Note
that if you have multiple Amd entries using the same file server, and each
entry sets a different value of N, then each time Amd mounts a new entry,
the ping value will be re-evaluated (and updated, turned off, or turned
back on as needed). Note that NFS_NULL pings are sent for both UDP and
TCP mounts, because even a hung TCP mount can cause user processes to
hang.
- file system inheritance code restructured, so it's no longer a pseudo file
system, but actually integrated into Amd (as it should have been).
- for type:=program, the "umount" program doesn't have to be defined; it'll
default to "unmount ${fs}".
- "amd -v" now prints the distribution name if it's known (e.g., rh9, fc3,
suse8, etc.).
- bugs fixed:
* various memory management problems (leaks, etc)
* fixed nfsx support
* fixed a race involving late replies to network queries which
arrive after the file system has already been mounted
* recognize pcfs_args_t fields in FreeBSD 5
* recognize other mount types in pawd: host, linkx, and nfsx
* allow exactly one of umount and unmount in type:=program
* race condition between calls to mntctl() on AIX
* plock/mlockall wasn't inherited by fork(); moved after
daemonizing.
* fix inconsistency between Socket and TLI RPC timeouts.
* don't warn when couldn't rmdir a dir with a readonly ancestor.
* avoid hangs of amd in ctl-amd (must chdir to /)
* workaround occasional daemonizing problems (parent won't die)
* don't hang on exit if debug_options=mtab was used
* utimeout=N mount option works with non-nfs types (ufs, pcfs, etc.)
* SEGV (null pointer deref) in type:=program and type:=cachefs
* unmount_on_exit of type:=program caused amd to hang
* match amd2ldif output with ldap.schema
*** Notes specific to am-utils version 6.1b4
- minor new ports:
i686-apple-darwin6.6
- speed up the recovery of inherited (restarted) filesystems by using the
proper waiting channels
- added support for mounting webnfs filesystems, see entry below. It doesn't
do any probing currently, so it will default to v2/UDP unless another
version and/or protocol are explicitly specified.
- pseudo-mount option "ignore_portmapper" renamed to "webnfs"
- bugs fixed:
* properly time out autofs filesystems on Linux
* link mounts with relative targets weren't working on autofs
* the link side of the nfsl file system wasn't working on autofs
* umount code was accidentally turning all symlinks into directories
during attempted umounts, causing stale filehandles
* various minor build fixes for "impossible" configurations
* prevent ldap code from dereferencing a null pointer
*** Notes specific to am-utils version 6.1b3
- new amd.conf option autofs_use_lofs, set by default to "yes". "yes" means
using in-place mounts (lofs, bind mounts, etc.), thus utilizing one of
Autofs's main advantages. "no" means using symlinks instead, which has
the "/bin/pwd" problem and certain efficiency issues on Solaris 2.6+ and
is also not supported on Solaris Autofs v1 and derivatives; however, the
autofs code that uses symlinks is simpler and more thoroughly tested.
- new amd.conf option map_default (can be used in [global] and overwritten
in the per-map section). This will overwrite the /defaults entry of the
map itself, to allow people to set defaults in amd.conf (useful when you
cannot control your amd maps, or you'd rather not modify them globally).
- for type:=program, you can use either unmount:=XXX or umount:=XXX (but not
both). This new 'unmount' name is an alias for convenience.
- fixed the "multiple matching sub-entries in a map entry" semantics to try
mounting those sub-entries one by one, until either one succeeds or all
fail. The old semantics of trying to mount everything in parallel and use
the one that mounted fastest hasn't worked in a long time; in fact, 6.0
currently simply ignores all but the first matching sub-entry.
- made amd fail much faster (instantly, in fact) if the remote server
doesn't have a functional portmapper or NFS service. Also reduced the
total timeout to 3 seconds for a completely downed server.
- new pseudo-mount option "ignore_portmapper"; not very useful currently,
will make more sense when we also accept hard-coded ports for mountd and
nfsd.
- amd will no longer query the portmapper for all possible NFS versions and
protocols if the user requested to use specific ones.
- increased the major number for the library, so that 6.0 and 6.1 can't
share libraries anymore.
- support tcpd/libwrap tcpwrappers. If your system supports libwrap, then
you can use /etc/hosts.allow and /etc/hosts.deny to control remote Amq
access to Amd. The new amd.conf parameter use_tcpwrappers is set to "yes"
by default.
- support NULL entries in Hesiod maps, if they start with a ".".
- code reorganization
- documentation cleanup, corrections, and general updates. Better
references to all man pages. Support newer texi2html. Proper building of
DVI and PSI files. Allow building of am-utils manual in one long Web
page.
- minor new ports:
ia64-unknown-linux-rh2.1AS (Red Hat Itanium Advanced Server)
i386-unknown-freebsd5.0 (5.0-RELEASE)
sparc64-unknown-linux-suse7.3
i386-unknown-netbsdelf1.6.1
i386-unknown-openbsd3.3
i386-pc-solaris2.9
i386-unknown-freebsd4.9
i386-unknown-freebsd5.2 (5.2-RELEASE)
- bugs fixed:
- new amd.conf directive "nfs_allow_insecure_port". Used to work around
bugs in certain kernels, which cause them to try and talk to amd from
unprivileged ports.
* autofs mode on Linux was segfaulting on a silly error (and noone
complained, which proves that I'm probably the only one testing
these beta releases, tsk tsk).
* fixed handling of host entries over autofs.
* fixed handling of nfsl entries over autofs.
* the matching in find_mntfs() was causing problems for inherited
filesystems, so make an exception for them. Tighten the
matching even more, to take into account the f/s type as well.
* recognize xlatecookie mnttab option on netbsd
* document Solaris lex bug (use flex)
* document AIX 5.x NFS bug (need patch)
* document Solaris 8 autofs version change (need to fix system
header file)
* ensure lex doesn't run out of output slots
* support GNU flex-2.5.31+
* force version.texi to be rebuilt unconditionally
* mk-amd-map open db file exclusively (security)
* turn off maintainer-only rules in distros
* don't core dump if log_file is NULL (Solaris)
* don't include malloc.h if stdlib.h exists
* recognize file system failures (EIO) upon reading file maps
- bug fixes:
rename log() in fsinfo to avoid glibc/gcc-3.3 conflict
am_pref free NULL pointer
compiles with modern bison/flex versions
handles sites with various combos of db, n/dbm, and gdbm
*** Notes specific to am-utils version 6.1b2
- new mount flag "softlookup", which determines how amd will respond to
lookups of NFS shares already mounted (return a valid symlink or return
EIO). The default, if "softlookup" is not specified, depends on whether the
mount is "soft" or "hard".
- return EIO instead of ENOENT if amd thinks the server is down; this allows
well-written applications to sleep and retry the operation.
- minor new ports:
*** Notes specific to am-utils version 6.0.9:
- Minor new ports:
i386-apple-darwin6.0
i386-pc-linux-rh8.0
ia64-unknown-linux-rh2.1AW
sparc-sun-solaris2.9
- automatic support for loop mounts on Linux (deprecates the "loop" mount
option)
- new amd.conf parameter ldap_proto_version (default 2) for setting the LDAP
protocol version to use.
- bugs fixed:
* redundancy mode (multiple servers for the same share) wasn't working
* non-autofs mode had some rather nasty hangs on downed file servers
* double-free'ing problem in assign_error_mntfs and free_continuation
* free'ing non-malloc'ed memory in amfs_auto_mount
* late server ping replies were not ignored
* amfs_auto_lookup_mntfs wasn't propagating errors up to callers
* autofs-v4 on Solaris 9 works
* handle std{in,out,err} correctly when releasing controlling tty
(for real this time)
* don't cast pointers between enum_t and u_long, it doesn't work on
64-bit big-endian platforms
* fix compile problem with mlockall() on Darwin
*** Notes specific to am-utils version 6.1b1
- Major Autofs work
Partial support for Sun Autofs v1
Documented known problems with Sun Autofs v1 (possible deadlocks)
Fixes for Sun Autofs v2/v3
Preliminary support for Sun Autofs v4 (Solaris 9)
Kernel-based expirations for Linux Autofs
*** Notes specific to am-utils version 6.0.8:
- Minor new ports:
i386-pc-linux-rh7.2
i386-pc-linux-rh7.3
i386-unknown-freebsd4.4
i386-unknown-freebsd5.0
ia64-hp-hpux11.20
ia64-unknown-linux-rh7.1
powerpc-ibm-aix5.1.0.0
i386-unknown-netbsd1.6A
- Work around IBM's NFSv3 ABI change in aix4.3
- trivial regression test suite started: run "make check" on a built
am-utils to execute tests. Currently only one test which checks to see if
"amd -v" executes correctly.
- Support network/netmask and network/masklen syntax in in_network()
- new command line option "amd -A arch" to overwrite the value of $arch.
- Support disabling LDAP and Hesiod support using configure
- Support xfs on Linux
- Red Hat specific Amd startup script included
- Remove (non-functional) autofs code and detection support. If you want
autofs support, use am-utils-6.1.
- bugs fixed:
* Linux loop mounts of ISO images
* assorted LDAP fixes
* strerror not found on some systems
* small fixes for hpux9 and aix43
* exclude ldap/hesiod support unless both libraries+headers exist
* fully support "xlatecookie" mount option
* security: if -D noamq option, don't listen on socket.
*** Notes specific to am-utils version 6.1a5:
- browsable_dirs support for Solaris autofs, *without* mount storms!
- new amd.conf global parameter: map_reload_interval (default 1 hour).
Determines how often Amd checks to see if maps have changed at the source
(and then reloading only those that have changed).
- "amd -v" now lists bug-reporting address.
- assorted code cleanups and porting to use latest versions of GNU
Autotools.
- opts:=loop works for type:=cdfs, for mounting ISO-9660 files on Linux.
- bugs fixed:
* fixed sublink support in Linux autofs (broken in a4)
* hlfsd takes uid 0's home from root's passwd entry instead of
defaulting to '/'
* (not really our bug) Linux ignores the microseconds field in
mtime, so hlfsd and amd need to increment the seconds field all
the time to prevent symlink caching
* generic map parsing bug which was rejecting a numerical mount
option if it was the last option in the string.
* file descriptor leak in Linux autofs.
* "nolock" is an NFS mount option, not a generic one.
* use mlockall(2) on systems that have it, for plock=yes. Now
pinning Amd's pages in memory works on Linux.
* ctl-amd/ctl-hlfsd correctly refer to @sysconfdir@ for alternate
location of configuration files.
* generic map parsing bug which was rejecting a numerical mount option
if it was the last option in the string
* MacOS X compile bug
* minor fix for GNU getopt
* Linux has no "dev" mtab option
* "nolock" is an NFS mount option, not a generic one
* Irix N32 ABI fixes with cc
* security: use mkstemp instead of mktemp
* correct timeo values for Linux tcp/udp NFS mounts
* hlfsd use of setuid() not seteuid()
* AIX ABI changes to nfs_args fixes
*** Notes specific to am-utils version 6.1a4:
*** Notes specific to am-utils version 6.0.7:
- full autofs support for Solaris 2.[67], including symlinks, sublinks and
direct mounts
- minor new ports: i386-unknown-freebsd5.0
- fixed mount/umount deadlock in Linux autofs
- bug fixes:
type:=host, don't fail mount if one share is already mounted
don't report NFS NE_IO error as success (Linux)
- fixed sublinks in Linux autofs
*** Notes specific to am-utils version 6.0.6:
- support for network/netmask pairs in the in_network() selector
- new ports:
Mac OS X support (Darwin, Rhapsody)
- support disabling LDAP and Hesiod support using configure
- reworked autoconf scripts so that newer versions of known OSs will default
their configuration to the last known version (better chance that it will
pass autoconf and work).
- forward-ported all the fixes from the stable branch (MacOS X support,
minor Linux fixes)
- linux support for lofs and "bind" mounts, so type:=lofs can work (whether
you're using autofs or not)
- bind-mount support for type==link and type==lofs with Linux 2.4+
- renamed amd.conf option "selectors_on_default" to "selectors_in_defaults"
(on -> in, and added "s"). Old name remains in place for compatibility.
- FiST lofs support under Linux (also in 6.0.6s2)
- lots of cleanups of debugging and logging messages
*** Notes specific to am-utils version 6.1a3:
- Bugs fixed:
lots of Linux-related ones, so it compiles for recent kernels
better checking on various mount options of the form foo=N or foo=STR
fixed NFS errno mapping bug which mapped ENOENT to success on Linux
- various things from the 6.0 branch:
compile fixes for Linux 2.4-ac and 2.2.19pre+
Darwin/Rhapsody/OS X support
much reduced configure script (works around a bug in Darwin's cpp)
*** Notes specific to am-utils version 6.0.5:
*** Notes specific to am-utils version 6.1a2:
- Minor ports:
alphaev6-dec-osf5.1
i386-unknown-freebsd4.2
support for Linux 2.4 kernels and newer GLIBC versions
cleanup of AIX and IRIX6 ports
- working autofs support for Solaris 2.[67], but incomplete
- Support new mount options:
proplist (ACLs over NFS, DU-4.0)
kerb, rdirplus, readdirsize, and xlatecookie (NetBSD-1.5K+)
nonlm, lock, nolock (Linux)
- forward-ported all the changes up to 6.0.5s2
- Don't force rsize/wsize on Linux 2.2.18+ and 2.4.x. Improves performance
a lot.
- removed support for amq -M
- Lots of documentation updates: texinfo, man pages, scripts, and more.
- known bugs
nfsx support is broken
linux NFS codes fixes
NFS cache aliasing fixes
lots of stuff ported from 6.0 branch
- LDAP: included proposed Schema and Internet Draft for LDAP Schema. See
README.ldap for more information.
*** Notes specific to am-utils version 6.1a1:
- Removed all remains of the dangerous amq -M code.
- working autofs (v3 and v4) support for Linux!
- Major bug fix: initialize NFS fileid field correctly, to avoid cache
aliasing problems, esp. on Linux.
- forward-ported all the changes in 6.0.4s4
- Major Linux bug fix: map errnos to NFS errors (mistakenly turned off a
while back). Also support unused errno 41.
- bugs fixed
client-side fail-over to NFSv2/UDP
- known bugs
autofs v3 will probably break with host maps
- Other bugs fixes:
default MAXHOSTNAMELEN (if undefined) is 256, not 64
truncate hostnames to MAXHOSTNAMELEN (security fix)
alignment problem in getwire() on ALPHA
other buf overflow problems (security fixes)
ctl-amd supports "condrestart" (Red Hat)
bell char is \g not \a
lostaltmail verify MAILDIR is defined
am-eject accepts "floppy" and "cdrom" as args
other assorted small bug fixes
*** Notes specific to am-utils version 6.0.4:
@@ -1030,7 +514,7 @@ the functions compute_nfs_args() and compute_automounter_nfs_args().
- bugs fixed:
mnttab name ufs/cdfs/pcfs/etc filesystems corrected
use pmap_ping for amq (a must for secure portmappers, bsdi2/3)
test for xfs (irix) as a disk-based file system
test for xfs (irix) as a disk-based filesystem
set correct nfs_prot headers for Solaris 2.5
removed stale code from lostaltmail.in
lostaltmail will look for conf file in multiple locations
@@ -1447,11 +931,11 @@ used anywhere were removed.
--enable-libs[=ARG]
configure/compile with ARG (-L/-l) library flags
- file system, mount table entries, and mount type tests can now look in
- filesystem, mount table entries, and mount type tests can now look in
/lib/modules and /proc/filesystems for statically/dyadically loadable kernel
modules (linux)
- prefer vfat over msdos/pc/etc file system for PCFS.
- prefer vfat over msdos/pc/etc filesystem for PCFS.
- moved all fixed headers to include/am_defs. Left only #define/#undef
entries in aux/acconfig.h.
-129
View File
@@ -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 [email protected], so we can record it in
this file.
Sincerely,
Erez.
+3 -6
View File
@@ -2,17 +2,14 @@ LDAP support for am-utils was originally done by Leif Johansson
<[email protected]>. 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.
small changes are needed to support LDAPv3. Volunteers and patches are
welcome.
The IANA has assigned the following Private Enterprise Number to:
10180 Am-utils Organization Erez Zadok [email protected]
There are three files in this directory that relate to LDAP:
ldap.schema:
This is the most current schema.
There are two files in this directory that relate to LDAP:
ldap-id.txt:
+62 -87
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/am_ops.c
* $Id: am_ops.c,v 1.6.2.7 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -86,6 +87,9 @@ static am_ops *vops[] =
#ifdef HAVE_AMU_FS_UNION
&amfs_union_ops, /* union F/S */
#endif /* HAVE_AMU_FS_UNION */
#ifdef HAVE_AMU_FS_INHERIT
&amfs_inherit_ops, /* inheritance F/S */
#endif /* HAVE_AMU_FS_INHERIT */
/*
* A few more native filesystems.
@@ -122,7 +126,7 @@ static am_ops *vops[] =
#endif /* HAVE_FS_UMAPFS */
/*
* These 4 should be last, in the order:
* These 5 should be last, in the order:
* (1) amfs_auto
* (2) amfs_direct
* (3) amfs_toplvl
@@ -145,111 +149,107 @@ static am_ops *vops[] =
void
ops_showamfstypes(char *buf, size_t l)
ops_showamfstypes(char *buf)
{
struct am_ops **ap;
int linesize = 0;
int l = 0;
buf[0] = '\0';
for (ap = vops; *ap; ap++) {
xstrlcat(buf, (*ap)->fs_type, l);
strcat(buf, (*ap)->fs_type);
if (ap[1])
xstrlcat(buf, ", ", l);
linesize += strlen((*ap)->fs_type) + 2;
if (linesize > 62) {
linesize = 0;
xstrlcat(buf, "\n ", l);
strcat(buf, ", ");
l += strlen((*ap)->fs_type) + 2;
if (l > 62) {
l = 0;
strcat(buf, "\n ");
}
}
}
static void
ops_show1(char *buf, size_t l, int *linesizep, const char *name)
ops_show1(char *buf, int *lp, const char *name)
{
xstrlcat(buf, name, l);
xstrlcat(buf, ", ", l);
*linesizep += strlen(name) + 2;
if (*linesizep > 60) {
xstrlcat(buf, "\t\n", l);
*linesizep = 0;
strcat(buf, name);
strcat(buf, ", ");
*lp += strlen(name) + 2;
if (*lp > 60) {
strcat(buf, "\t\n");
*lp = 0;
}
}
void
ops_showfstypes(char *buf, size_t l)
ops_showfstypes(char *buf)
{
int linesize = 0;
int l = 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);
ops_show1(buf, &l, MNTTAB_TYPE_CACHEFS);
#endif /* MNTTAB_TYPE_CACHEFS */
#ifdef MNTTAB_TYPE_CDFS
ops_show1(buf, l, &linesize, MNTTAB_TYPE_CDFS);
ops_show1(buf, &l, MNTTAB_TYPE_CDFS);
#endif /* MNTTAB_TYPE_CDFS */
#ifdef MNTTAB_TYPE_CFS
ops_show1(buf, l, &linesize, MNTTAB_TYPE_CFS);
ops_show1(buf, &l, MNTTAB_TYPE_CFS);
#endif /* MNTTAB_TYPE_CFS */
#ifdef MNTTAB_TYPE_LOFS
ops_show1(buf, l, &linesize, MNTTAB_TYPE_LOFS);
ops_show1(buf, &l, MNTTAB_TYPE_LOFS);
#endif /* MNTTAB_TYPE_LOFS */
#ifdef MNTTAB_TYPE_EFS
ops_show1(buf, l, &linesize, MNTTAB_TYPE_EFS);
ops_show1(buf, &l, MNTTAB_TYPE_EFS);
#endif /* MNTTAB_TYPE_EFS */
#ifdef MNTTAB_TYPE_MFS
ops_show1(buf, l, &linesize, MNTTAB_TYPE_MFS);
ops_show1(buf, &l, MNTTAB_TYPE_MFS);
#endif /* MNTTAB_TYPE_MFS */
#ifdef MNTTAB_TYPE_NFS
ops_show1(buf, l, &linesize, MNTTAB_TYPE_NFS);
ops_show1(buf, &l, MNTTAB_TYPE_NFS);
#endif /* MNTTAB_TYPE_NFS */
#ifdef MNTTAB_TYPE_NFS3
ops_show1(buf, l, &linesize, "nfs3"); /* always hard-code as nfs3 */
ops_show1(buf, &l, "nfs3"); /* always hard-code as nfs3 */
#endif /* MNTTAB_TYPE_NFS3 */
#ifdef MNTTAB_TYPE_NULLFS
ops_show1(buf, l, &linesize, MNTTAB_TYPE_NULLFS);
ops_show1(buf, &l, MNTTAB_TYPE_NULLFS);
#endif /* MNTTAB_TYPE_NULLFS */
#ifdef MNTTAB_TYPE_PCFS
ops_show1(buf, l, &linesize, MNTTAB_TYPE_PCFS);
ops_show1(buf, &l, MNTTAB_TYPE_PCFS);
#endif /* MNTTAB_TYPE_PCFS */
#ifdef MNTTAB_TYPE_TFS
ops_show1(buf, l, &linesize, MNTTAB_TYPE_TFS);
ops_show1(buf, &l, MNTTAB_TYPE_TFS);
#endif /* MNTTAB_TYPE_TFS */
#ifdef MNTTAB_TYPE_TMPFS
ops_show1(buf, l, &linesize, MNTTAB_TYPE_TMPFS);
ops_show1(buf, &l, MNTTAB_TYPE_TMPFS);
#endif /* MNTTAB_TYPE_TMPFS */
#ifdef MNTTAB_TYPE_UFS
ops_show1(buf, l, &linesize, MNTTAB_TYPE_UFS);
ops_show1(buf, &l, MNTTAB_TYPE_UFS);
#endif /* MNTTAB_TYPE_UFS */
#ifdef MNTTAB_TYPE_UMAPFS
ops_show1(buf, l, &linesize, MNTTAB_TYPE_UMAPFS);
ops_show1(buf, &l, MNTTAB_TYPE_UMAPFS);
#endif /* MNTTAB_TYPE_UMAPFS */
#ifdef MNTTAB_TYPE_UNIONFS
ops_show1(buf, l, &linesize, MNTTAB_TYPE_UNIONFS);
ops_show1(buf, &l, MNTTAB_TYPE_UNIONFS);
#endif /* MNTTAB_TYPE_UNIONFS */
#ifdef MNTTAB_TYPE_XFS
ops_show1(buf, l, &linesize, MNTTAB_TYPE_XFS);
ops_show1(buf, &l, MNTTAB_TYPE_XFS);
#endif /* MNTTAB_TYPE_XFS */
/* terminate with a period, newline, and NULL */
@@ -257,7 +257,7 @@ ops_showfstypes(char *buf, size_t l)
buf[strlen(buf) - 4] = '\0';
else
buf[strlen(buf) - 2] = '\0';
xstrlcat(buf, ".\n", l);
strcat(buf, ".\n");
}
@@ -289,11 +289,11 @@ reverse_option(const char *opt)
/* check if string starts with 'no' and chop it */
if (NSTREQ(opt, "no", 2)) {
xstrlcpy(buf, &opt[2], sizeof(buf));
strcpy(buf, &opt[2]);
} else {
/* finally return a string prepended with 'no' */
xstrlcpy(buf, "no", sizeof(buf));
xstrlcat(buf, opt, sizeof(buf));
strcpy(buf, "no");
strcat(buf, opt);
}
return buf;
}
@@ -315,7 +315,7 @@ merge_opts(const char *opts1, const char *opts2)
char *eq; /* pointer to whatever follows '=' within temp */
char oneopt[80]; /* one option w/o value if any */
char *revoneopt; /* reverse of oneopt */
size_t len = strlen(opts1) + strlen(opts2) + 2; /* space for "," and NULL */
int len = strlen(opts1) + strlen(opts2) + 2; /* space for "," and NULL */
char *s1 = strdup(opts1); /* copy of opts1 to munge */
/* initialization */
@@ -327,30 +327,31 @@ merge_opts(const char *opts1, const char *opts2)
tmpstr;
tmpstr = strtok(NULL, ",")) {
/* copy option to temp buffer */
xstrlcpy(oneopt, tmpstr, 80);
strncpy(oneopt, tmpstr, 80);
oneopt[79] = '\0';
/* if option has a value such as rsize=1024, chop the value part */
if ((eq = haseq(oneopt)))
*eq = '\0';
/* find reverse option of oneopt */
revoneopt = reverse_option(oneopt);
/* if option orits reverse exist in opts2, ignore it */
if (amu_hasmntopt(&mnt2, oneopt) || amu_hasmntopt(&mnt2, revoneopt))
if (hasmntopt(&mnt2, oneopt) || hasmntopt(&mnt2, revoneopt))
continue;
/* add option to returned string */
if (newstr[0]) {
xstrlcat(newstr, ",", len);
xstrlcat(newstr, tmpstr, len);
if (newstr && newstr[0]) {
strcat(newstr, ",");
strcat(newstr, tmpstr);
} else {
xstrlcpy(newstr, tmpstr, len);
strcpy(newstr, tmpstr);
}
}
/* finally, append opts2 itself */
if (newstr[0]) {
xstrlcat(newstr, ",", len);
xstrlcat(newstr, opts2, len);
if (newstr && newstr[0]) {
strcat(newstr, ",");
strcat(newstr, opts2);
} else {
xstrlcpy(newstr, opts2, len);
strcpy(newstr, opts2);
}
XFREE(s1);
@@ -359,22 +360,10 @@ merge_opts(const char *opts1, const char *opts2)
am_ops *
ops_search(char *type)
ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map)
{
am_ops **vp;
am_ops *rop = 0;
for (vp = vops; (rop = *vp); vp++)
if (STREQ(rop->fs_type, type))
break;
return rop;
}
am_ops *
ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map)
{
am_ops *rop = 0;
char *link_dir;
/*
* First crack the global opts and the local opts
@@ -388,7 +377,9 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map
/*
* Next find the correct filesystem type
*/
rop = ops_search(fo->opt_type);
for (vp = vops; (rop = *vp); vp++)
if (STREQ(rop->fs_type, fo->opt_type))
break;
if (!rop) {
plog(XLOG_USER, "fs type \"%s\" not recognized", fo->opt_type);
rop = &amfs_error_ops;
@@ -442,34 +433,18 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map
}
}
/*
* Initialize opt_mount_type to "nfs", if it's not initialized already
*/
if (!fo->opt_mount_type)
fo->opt_mount_type = "nfs";
/* Normalize the sublink and make it absolute */
link_dir = fo->opt_sublink;
if (link_dir && link_dir[0] && link_dir[0] != '/') {
link_dir = str3cat((char *) 0, fo->opt_fs, "/", link_dir);
normalize_slash(link_dir);
XFREE(fo->opt_sublink);
fo->opt_sublink = link_dir;
}
/*
* Check the filesystem is happy
*/
if (fo->fs_mtab)
XFREE(fo->fs_mtab);
fo->fs_mtab = rop->fs_match(fo);
if (fo->fs_mtab)
if ((fo->fs_mtab = (*rop->fs_match) (fo)))
return rop;
/*
* Return error file system
*/
fo->fs_mtab = amfs_error_ops.fs_match(fo);
fo->fs_mtab = (*amfs_error_ops.fs_match) (fo);
return &amfs_error_ops;
}
+90 -118
View File
@@ -1,5 +1,5 @@
.\"
.\" Copyright (c) 1997-2006 Erez Zadok
.\" Copyright (c) 1997-2004 Erez Zadok
.\" Copyright (c) 1989 Jan-Simon Pendry
.\" Copyright (c) 1989 Imperial College of Science, Technology & Medicine
.\" Copyright (c) 1989 The Regents of the University of California.
@@ -38,34 +38,39 @@
.\"
.\" %W% (Berkeley) %G%
.\"
.\" $Id: amd.8,v 1.14.2.1 2006/01/02 18:48:23 ezk Exp $
.\" $Id: amd.8,v 1.4.2.5 2004/01/06 03:15:16 ezk Exp $
.\" $FreeBSD$
.\"
.Dd January 2, 2006
.Dd April 19, 1994
.Dt AMD 8
.Os
.Sh NAME
.Nm amd
.Nd automatically mount file systems
.Sh SYNOPSIS
.Nm
.Nm amd
.Fl H
.Nm
.Nm amd
.Op Fl F Ar conf_file
.Nm
.Nm amd
.Op Fl nprvHS
.Op Fl a Ar mount_point
.Op Fl c Ar duration
.Op Fl d Ar domain
.Bk -words
.Op Fl k Ar kernel-arch
.Ek
.Op Fl l Ar logfile
.Op Fl o Ar op_sys_ver
.Op Fl t Ar timeout.retransmit
.Bk -words
.Op Fl w Ar interval
.Ek
.Op Fl x Ar log-option
.Op Fl y Ar YP-domain
.Op Fl A Ar arch
.Bk -words
.Op Fl C Ar cluster-name
.Ek
.Op Fl D Ar option
.Op Fl F Ar conf_file
.Op Fl O Ar op_sys_name
@@ -76,46 +81,41 @@
.Oc
.Ar ...
.Sh DESCRIPTION
The
.Nm
utility
is a daemon that automatically mounts file systems
whenever a file or directory
.Nm Amd
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.
File systems are automatically unmounted
when they appear to be quiescent.
.Pp
The
.Nm
utility
.Nm Amd
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 ,
.Nm amd ,
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.
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
.Nm amd
will print a short help string.
In the second form, if no options are
specified, or if the
.Fl F
is used,
.Nm
.Nm amd
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
.Bl -tag -width Ds
.It Fl a Ar temporary-directory
Specify an alternative location for the real mount points.
The default is
@@ -139,63 +139,55 @@ 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
.Em syslog ,
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.
The default syslog facility used is LOG_DAEMON.
If you wish to change it, append its name to the log file name,
delimited by a single colon.
For example, if
.Ar logfile
is the string
.Dq Li syslog:local7
then
.Nm
.Nm amd
will log messages via
.Xr syslog 3
using the
.Dv LOG_LOCAL7
facility (if it exists on the system).
using the 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.
aliases into ``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.
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 ,
.Dq 2.5.1 ,
you can override it to
.Dq Li 5.5.1 ,
.Dq 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
Print
.Em PID .
Outputs the process-id of
.Nm amd
to standard output where it can be saved into a file.
.It Fl r
Restart existing mounts.
The
.Nm
utility
.Nm Amd
will scan the mount file table to determine which file systems
are currently mounted.
Whenever one of these would have
been auto-mounted,
.Nm
.Nm amd
.Em inherits
it.
.It Fl t Ar timeout.retransmit
Specify the NFS
.Ar timeout
interval,
Specify the NFS timeout
.Ar interval ,
in tenths of a second, between
.Tn NFS/RPC
retries (for UDP only).
@@ -208,10 +200,7 @@ 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.
Amd 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
@@ -222,14 +211,13 @@ 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.
in seconds, between attempts to dismount file systems that have exceeded their
cached times.
The default is 2 minutes.
.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 , all .
The options are a comma separated list
chosen from: fatal, error, user, warn, info, map, stats, all.
.It Fl y Ar domain
Specify an alternative
.Tn NIS
@@ -240,21 +228,17 @@ The default is the system domain name.
This option is ignored if
.Tn 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
.Em no
reverses the effect of that option.
Options are cumulative.
The most useful option is
.Dq Li all .
.Ar all .
.Pp
Since
.Fl D
@@ -265,7 +249,7 @@ option
and a fuller description is available in the program source.
.It Fl F Ar conf_file
Specify an
.Nm
.Nm amd
configuration file to use.
See
.Xr amd.conf 5
@@ -273,63 +257,59 @@ 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.
.Nm amd.conf
file includes directives for every command line option amd has,
and many more that are only available via the configuration file
facility.
The configuration file specified by this option is
processed after all other options have 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 ,
Useful when the built in name is not desired for backward
compatibility reasons.
For example, if the build in name is
.Dq sunos5 ,
you can override it to
.Dq Li sos5
.Dq 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
.Nm amd
into memory.
To improve
.Nm Ns 's
.Nm amd's
performance, systems that support the
.Xr plock 3
call, could lock the
.Nm
.Nm amd
process into memory.
This way there is less chance
the operating system will schedule, page out, and swap the
.Nm
process as
needed.
This way there is less chance the operating system will
schedule, page out, and swap the
.Nm amd
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).
.Nm amd's
performance, at the cost of reserving the memory used by the
.Nm amd
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.
All Map entries tagged with 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"
.Bl -tag -width /axx
.It Pa /.amd_mnt
directory under which file systems are dynamically mounted
.It Pa /etc/amd.conf
@@ -343,17 +323,20 @@ Symbolic links on an
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
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
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
Replacing
.Xr symlink 2
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
@@ -368,34 +351,23 @@ the features.
.Xr amq 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
.Pp
.Pa http://www.am-utils.org/
.Sh HISTORY
The
.Nm
.Nm amd
utility first appeared in
.Bx 4.4 .
.Sh AUTHORS
.An Jan-Simon Pendry Aq [email protected] ,
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.
.An Erez Zadok Aq ezk@am-utils.org ,
Department of Computer Science, Columbia University,
New York, USA.
.Pp
Other authors and contributors to am-utils are listed in the
.Pa AUTHORS
+116 -140
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -36,15 +36,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amd.c,v 1.8.2.6 2004/01/06 03:15:16 ezk Exp $
* File: am-utils/amd/amd.c
* $FreeBSD$
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* Automounter
*/
@@ -57,10 +55,9 @@ __FBSDID("$FreeBSD$");
struct amu_global_options gopt; /* where global options are stored */
char pid_fsname[SIZEOF_PID_FSNAME]; /* "kiska.southseas.nz:(pid%d)" */
char pid_fsname[16 + MAXHOSTNAMELEN]; /* "kiska.southseas.nz:(pid%d)" */
char *hostdomain = "unknown.domain";
#define SIZEOF_HOSTD (2 * MAXHOSTNAMELEN + 1) /* Host+domain */
char hostd[SIZEOF_HOSTD]; /* Host+domain */
char hostd[2 * MAXHOSTNAMELEN + 1]; /* Host+domain */
char *endian = ARCH_ENDIAN; /* Big or Little endian */
char *cpu = HOST_CPU; /* CPU type */
char *PrimNetName; /* name of primary network */
@@ -75,10 +72,6 @@ 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 */
@@ -126,8 +119,10 @@ sighup(int sig)
signal(sig, sighup);
#endif /* REINSTALL_SIGNAL_HANDLER */
#ifdef DEBUG
if (sig != SIGHUP)
dlog("spurious call to sighup");
#endif /* DEBUG */
/*
* Force a reload by zero'ing the timer
*/
@@ -139,26 +134,7 @@ sighup(int sig)
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);
exit(0);
}
@@ -170,7 +146,6 @@ daemon_mode(void)
#ifdef HAVE_SIGACTION
struct sigaction sa, osa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = parent_exit;
sa.sa_flags = 0;
sigemptyset(&(sa.sa_mask));
@@ -243,7 +218,6 @@ 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));
@@ -253,15 +227,9 @@ init_global_options(void)
/* 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.
*/
@@ -293,11 +261,11 @@ init_global_options(void)
/* 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" */
}
/* NFS retransmit counter */
gopt.amfs_auto_retrans = -1;
/* NFS retry interval */
gopt.amfs_auto_timeo = -1;
/* cache duration */
gopt.am_timeo = AM_TTL;
@@ -305,13 +273,11 @@ init_global_options(void)
/* dismount interval */
gopt.am_timeo_w = AM_TTL_W;
/* map reload intervl */
gopt.map_reload_interval = ONE_HOUR;
/*
* various CFM_* flags that are on by default.
* various CFM_* flags.
* by default, only the "plock" option is on (if available).
*/
gopt.flags = CFM_DEFAULT_FLAGS;
gopt.flags = CFM_PROCESS_LOCK;
#ifdef HAVE_MAP_HESIOD
/* Hesiod rhs zone */
@@ -328,9 +294,6 @@ init_global_options(void)
/* LDAP cache */
gopt.ldap_cache_seconds = 0;
gopt.ldap_cache_maxmem = 131072;
/* LDAP protocol version */
gopt.ldap_proto_version = 2;
#endif /* HAVE_MAP_LDAP */
#ifdef HAVE_MAP_NIS
@@ -340,58 +303,17 @@ init_global_options(void)
}
/*
* Lock process text and data segment in memory (after forking the daemon)
*/
static void
do_memory_locking(void)
{
#if defined(HAVE_PLOCK) || defined(HAVE_MLOCKALL)
int locked_ok = 0;
#else /* not HAVE_PLOCK and not HAVE_MLOCKALL */
plog(XLOG_WARNING, "Process memory locking not supported by the OS");
#endif /* not HAVE_PLOCK and not HAVE_MLOCKALL */
#ifdef HAVE_PLOCK
# ifdef _AIX
/*
* On AIX you must lower the stack size using ulimit() before calling
* plock. Otherwise plock will reserve a lot of memory space based on
* your maximum stack size limit. Since it is not easily possible to
* tell what should the limit be, I print a warning before calling
* plock(). See the manual pages for ulimit(1,3,4) on your AIX system.
*/
plog(XLOG_WARNING, "AIX: may need to lower stack size using ulimit(3) before calling plock");
# endif /* _AIX */
if (!locked_ok && plock(PROCLOCK) != 0)
plog(XLOG_WARNING, "Couldn't lock process pages in memory using plock(): %m");
else
locked_ok = 1;
#endif /* HAVE_PLOCK */
#ifdef HAVE_MLOCKALL
if (!locked_ok && mlockall(MCL_CURRENT|MCL_FUTURE) != 0)
plog(XLOG_WARNING, "Couldn't lock process pages in memory using mlockall(): %m");
else
locked_ok = 1;
#endif /* HAVE_MLOCKALL */
#if defined(HAVE_PLOCK) || defined(HAVE_MLOCKALL)
if (locked_ok)
plog(XLOG_INFO, "Locked process pages in memory");
#endif /* HAVE_PLOCK || HAVE_MLOCKALL */
#if defined(HAVE_MADVISE) && defined(MADV_PROTECT)
madvise(0, 0, MADV_PROTECT); /* may be redundant of the above worked out */
#endif /* defined(HAVE_MADVISE) && defined(MADV_PROTECT) */
}
int
main(int argc, char *argv[])
{
char *domdot, *verstr, *vertmp;
char *domdot, *verstr;
int ppid = 0;
int error;
char *progname = NULL; /* "amd" */
char hostname[MAXHOSTNAMELEN + 1] = "localhost"; /* Hostname */
#ifdef HAVE_SIGACTION
struct sigaction sa;
#endif /* HAVE_SIGACTION */
/*
* Make sure some built-in assumptions are true before we start
@@ -442,6 +364,11 @@ main(int argc, char *argv[])
going_down(1);
}
#ifdef DEBUG
/* initialize debugging flags (Register AMQ, Enter daemon mode) */
debug_flags = D_AMQ | D_DAEMON;
#endif /* DEBUG */
/*
* Initialize global options structure.
*/
@@ -460,31 +387,73 @@ main(int argc, char *argv[])
*domdot++ = '\0';
hostdomain = domdot;
}
xstrlcpy(hostd, hostname, sizeof(hostd));
strcpy(hostd, hostname);
am_set_hostname(hostname);
/*
* Setup signal handlers
* Trap interrupts for shutdowns.
*/
/* 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 */
sa.sa_handler = sigterm;
sa.sa_flags = 0;
sigemptyset(&(sa.sa_mask));
sigaddset(&(sa.sa_mask), SIGINT);
sigaddset(&(sa.sa_mask), SIGTERM);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
#else /* not HAVE_SIGACTION */
(void) signal(SIGINT, sigterm);
#endif /* not HAVE_SIGACTION */
/*
* Trap Terminate so that we can shutdown gracefully (some chance)
*/
#ifdef HAVE_SIGACTION
sa.sa_handler = sigterm;
sa.sa_flags = 0;
sigemptyset(&(sa.sa_mask));
sigaddset(&(sa.sa_mask), SIGTERM);
sigaction(SIGTERM, &sa, NULL);
#else /* not HAVE_SIGACTION */
(void) signal(SIGTERM, sigterm);
#endif /* not HAVE_SIGACTION */
/*
* Hangups tell us to reload the cache
*/
#ifdef HAVE_SIGACTION
sa.sa_handler = sighup;
sa.sa_flags = 0;
sigemptyset(&(sa.sa_mask));
sigaddset(&(sa.sa_mask), SIGHUP);
sigaction(SIGHUP, &sa, NULL);
#else /* not HAVE_SIGACTION */
(void) signal(SIGHUP, sighup);
#endif /* not HAVE_SIGACTION */
/*
* Trap Death-of-a-child. These allow us to
* pick up the exit status of backgrounded mounts.
* See "sched.c".
*/
#ifdef HAVE_SIGACTION
sa.sa_handler = sigchld;
sa.sa_flags = 0;
sigemptyset(&(sa.sa_mask));
sigaddset(&(sa.sa_mask), SIGCHLD);
sigaction(SIGCHLD, &sa, NULL);
/*
* construct global "masked_sigs" used in nfs_start.c
*/
sigemptyset(&masked_sigs);
sigaddset(&masked_sigs, SIGINT);
sigaddset(&masked_sigs, SIGTERM);
sigaddset(&masked_sigs, SIGHUP);
sigaddset(&masked_sigs, SIGCHLD);
#endif /* HAVE_SIGACTION */
sigaddset(&masked_sigs, SIGTERM);
sigaddset(&masked_sigs, SIGINT);
#else /* not HAVE_SIGACTION */
(void) signal(SIGCHLD, sigchld);
#endif /* not HAVE_SIGACTION */
/*
* Fix-up any umask problems. Most systems default
@@ -505,21 +474,18 @@ main(int argc, char *argv[])
/*
* Log version information.
*/
vertmp = get_version_string();
verstr = strtok(vertmp, "\n");
verstr = strtok(get_version_string(), "\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().
* Get our own IP address so that we
* can mount the automounter.
*/
amu_get_myaddress(&myipaddr, gopt.localhost_address);
amu_get_myaddress(&myipaddr);
plog(XLOG_INFO, "My ip addr is %s", inet_ntoa(myipaddr));
/* avoid hanging on other NFS servers if started elsewhere */
@@ -534,6 +500,29 @@ main(int argc, char *argv[])
going_down(1);
}
/*
* Lock process text and data segment in memory.
*/
#ifdef HAVE_PLOCK
if (gopt.flags & CFM_PROCESS_LOCK) {
# ifdef _AIX
/*
* On AIX you must lower the stack size using ulimit() before calling
* plock. Otherwise plock will reserve a lot of memory space based on
* your maximum stack size limit. Since it is not easily possible to
* tell what should the limit be, I print a warning before calling
* plock(). See the manual pages for ulimit(1,3,4) on your AIX system.
*/
plog(XLOG_WARNING, "AIX: may need to lower stack size using ulimit(3) before calling plock");
# endif /* _AIX */
if (plock(PROCLOCK) != 0) {
plog(XLOG_WARNING, "Couldn't lock process text and data segment in memory: %m");
} else {
plog(XLOG_INFO, "Locked process text and data segment in memory");
}
}
#endif /* HAVE_PLOCK */
#ifdef HAVE_MAP_NIS
/*
* If the domain was specified then bind it here
@@ -546,17 +535,14 @@ main(int argc, char *argv[])
}
#endif /* HAVE_MAP_NIS */
if (!amuDebug(D_DAEMON))
#ifdef DEBUG
amuDebug(D_DAEMON)
#endif /* DEBUG */
ppid = daemon_mode();
/*
* Lock process text and data segment in memory.
*/
if (gopt.flags & CFM_PROCESS_LOCK) {
do_memory_locking();
}
sprintf(pid_fsname, "%s:(pid%ld)", am_get_hostname(), (long) am_mypid);
do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval;
do_mapc_reload = clocktime() + ONE_HOUR;
/*
* Register automounter with system.
@@ -564,16 +550,6 @@ main(int argc, char *argv[])
error = mount_automounter(ppid);
if (error && ppid)
kill(ppid, SIGALRM);
#ifdef HAVE_FS_AUTOFS
/*
* XXX this should be part of going_down(), but I can't move it there
* because it would be calling non-library code from the library... ugh
*/
if (amd_use_autofs)
destroy_autofs_service();
#endif /* HAVE_FS_AUTOFS */
going_down(error);
abort();
+76 -645
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/amd.h
* $Id: amd.h,v 1.8.2.8 2004/01/21 04:04:58 ib42 Exp $
*
*/
@@ -49,160 +50,33 @@
* MACROS:
*/
/*
* Define a default debug mtab path for systems
* that support mtab on file.
*/
#ifdef MOUNT_TABLE_ON_FILE
# define DEBUG_MNTTAB_FILE "/tmp/mnttab"
#endif /* MOUNT_TABLE_ON_FILE */
/* options for amd.conf */
#define CFM_BROWSABLE_DIRS 0x00000001
#define CFM_MOUNT_TYPE_AUTOFS 0x00000002 /* use kernel autofs support */
#define CFM_SELECTORS_IN_DEFAULTS 0x00000004
#define CFM_NORMALIZE_HOSTNAMES 0x00000008
#define CFM_PROCESS_LOCK 0x00000010
#define CFM_PRINT_PID 0x00000020
#define CFM_RESTART_EXISTING_MOUNTS 0x00000040
#define CFM_SHOW_STATFS_ENTRIES 0x00000080
#define CFM_FULLY_QUALIFIED_HOSTS 0x00000100
#define CFM_BROWSABLE_DIRS_FULL 0x00000200 /* allow '/' in readdir() */
#define CFM_UNMOUNT_ON_EXIT 0x00000400 /* when amd finishing */
#define CFM_USE_TCPWRAPPERS 0x00000800
#define CFM_AUTOFS_USE_LOFS 0x00001000
#define CFM_NFS_INSECURE_PORT 0x00002000
#define CFM_DOMAIN_STRIP 0x00004000
#define CFM_NORMALIZE_SLASHES 0x00008000 /* normalize slashes? */
#define CFM_FORCED_UNMOUNTS 0x00010000 /* forced unmounts? */
#define CFM_TRUNCATE_LOG 0x00020000 /* truncate log file? */
#if 0
/* XXX: reserved to sync up with am-utils-6.2 */
#define CFM_SUN_MAP_SYNTAX 0x00040000 /* Sun map syntax? */
#endif
#define CFM_NFS_ANY_INTERFACE 0x00080000 /* all interfaces are acceptable */
/* defaults global flags: plock, tcpwrappers, and autofs/lofs */
#define CFM_DEFAULT_FLAGS (CFM_PROCESS_LOCK|CFM_USE_TCPWRAPPERS|CFM_AUTOFS_USE_LOFS|CFM_DOMAIN_STRIP|CFM_NORMALIZE_SLASHES)
/*
* macro definitions for automounter vfs/vnode operations.
*/
#define VLOOK_CREATE 0x1
#define VLOOK_DELETE 0x2
#define VLOOK_LOOKUP 0x3
/*
* macro definitions for automounter vfs capabilities
*/
#define FS_DIRECTORY 0x0001 /* This looks like a dir, not a link */
#define FS_MBACKGROUND 0x0002 /* Should background this mount */
#define FS_NOTIMEOUT 0x0004 /* Don't bother with timeouts */
#define FS_MKMNT 0x0008 /* Need to make the mount point */
#define FS_UBACKGROUND 0x0010 /* Unmount in background */
#define FS_BACKGROUND (FS_MBACKGROUND|FS_UBACKGROUND)
#define FS_DISCARD 0x0020 /* Discard immediately on last reference */
#define FS_AMQINFO 0x0040 /* Amq is interested in this fs type */
#define FS_AUTOFS 0x0080 /* This filesystem can be an autofs f/s */
#define FS_DIRECT 0x0100 /* Direct mount */
#define FS_ON_AUTOFS 0x0200 /* This filesystem can be mounted directly
onto an autofs mountpoint */
/*
* macros for struct am_node (map of auto-mount points).
*/
#define AMF_NOTIMEOUT 0x0001 /* This node never times out */
#define AMF_ROOT 0x0002 /* This is a root node */
#define AMF_AUTOFS 0x0004 /* This node is part of an autofs filesystem */
#define AMF_REMOUNT 0x0008 /* This node needs to be remounted */
#define AMF_SOFTLOOKUP 0x0010 /* This node returns EIO if server is down */
/*
* macros for struct mntfs (list of mounted filesystems)
*/
#define MFF_MOUNTED 0x0001 /* Node is mounted */
#define MFF_MOUNTING 0x0002 /* Mount is in progress */
#define MFF_UNMOUNTING 0x0004 /* Unmount is in progress */
#define MFF_RESTART 0x0008 /* Restarted node */
#define MFF_MKMNT 0x0010 /* Delete this node's am_mount */
#define MFF_ERROR 0x0020 /* This node failed to mount */
#define MFF_LOGDOWN 0x0040 /* Logged that this mount is down */
#define MFF_RSTKEEP 0x0080 /* Don't timeout this filesystem - restarted */
#define MFF_WANTTIMO 0x0100 /* Need a timeout call when not busy */
#define MFF_NFSLINK 0x0200 /* nfsl type, and deemed a link */
#define MFF_IS_AUTOFS 0x0400 /* this filesystem is of type autofs */
#define MFF_NFS_SCALEDOWN 0x0800 /* the mount failed, retry with v2/UDP */
#define MFF_ON_AUTOFS 0x1000 /* autofs has a lofs/link to this f/s */
#define MFF_WEBNFS 0x2000 /* use public filehandle */
/*
* macros for struct fserver.
*/
#define FSF_VALID 0x0001 /* Valid information available */
#define FSF_DOWN 0x0002 /* This fileserver is thought to be down */
#define FSF_ERROR 0x0004 /* Permanent error has occurred */
#define FSF_WANT 0x0008 /* Want a wakeup call */
#define FSF_PINGING 0x0010 /* Already doing pings */
#define FSF_WEBNFS 0x0020 /* Don't try to contact portmapper */
#define FSF_PING_UNINIT 0x0040 /* ping values have not been initilized */
#define FSF_FORCE_UNMOUNT 0x0080 /* force umount of this fserver */
#define FSRV_ERROR(fs) ((fs) && (((fs)->fs_flags & FSF_ERROR) == FSF_ERROR))
#define FSRV_ISDOWN(fs) ((fs) && (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_DOWN|FSF_VALID)))
#define FSRV_ISUP(fs) (!(fs) || (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_VALID)))
#define CFM_BROWSABLE_DIRS 0x0001
#define CFM_MOUNT_TYPE_AUTOFS 0x0002
#define CFM_SELECTORS_IN_DEFAULTS 0x0004
#define CFM_NORMALIZE_HOSTNAMES 0x0008
#define CFM_PROCESS_LOCK 0x0010
#define CFM_PRINT_PID 0x0020
#define CFM_RESTART_EXISTING_MOUNTS 0x0040
#define CFM_SHOW_STATFS_ENTRIES 0x0080
#define CFM_FULLY_QUALIFIED_HOSTS 0x0100
#define CFM_BROWSABLE_DIRS_FULL 0x0200 /* allow '/' in readdir() */
#define CFM_UNMOUNT_ON_EXIT 0x0400 /* when amd finishing */
#define CFM_NFS_INSECURE_PORT 0x0800
/* 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) { *error_return = x; return 0; }
#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:
@@ -210,16 +84,6 @@
typedef struct cf_map cf_map_t;
typedef struct kv kv;
typedef struct am_node am_node;
typedef struct mntfs mntfs;
typedef struct am_opts am_opts;
typedef struct am_ops am_ops;
typedef struct am_stats am_stats;
typedef struct fserver fserver;
typedef voidp wchan_t;
typedef voidp opaque_t;
/*
* Cache map operations
*/
@@ -229,28 +93,6 @@ typedef int mtime_fn(mnt_map *, char *, time_t *);
typedef int isup_fn(mnt_map *, char *);
typedef int reload_fn(mnt_map *, char *, add_fn *);
typedef int search_fn(mnt_map *, char *, char *, char **, time_t *);
typedef int task_fun(opaque_t);
typedef void cb_fun(int, int, opaque_t);
typedef void fwd_fun(voidp, int, struct sockaddr_in *,
struct sockaddr_in *, opaque_t, int);
typedef int key_fun(char *, opaque_t);
typedef void callout_fun(opaque_t);
/*
* automounter vfs/vnode operations.
*/
typedef char *(*vfs_match) (am_opts *);
typedef int (*vfs_init) (mntfs *);
typedef int (*vmount_fs) (am_node *, mntfs *);
typedef int (*vumount_fs) (am_node *, mntfs *);
typedef am_node *(*vlookup_child) (am_node *, char *, int *, int);
typedef am_node *(*vmount_child) (am_node *, int *);
typedef int (*vreaddir) (am_node *, nfscookie, nfsdirlist *, nfsentry *, u_int);
typedef am_node *(*vreadlink) (am_node *, int *);
typedef void (*vmounted) (mntfs *);
typedef void (*vumounted) (mntfs *);
typedef fserver *(*vffserver) (mntfs *);
typedef wchan_t (*vget_wchan) (mntfs *);
@@ -262,7 +104,6 @@ typedef wchan_t (*vget_wchan) (mntfs *);
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 */
@@ -272,33 +113,16 @@ struct amu_global_options {
char *op_sys_vendor; /* name of OS vendor ${vendor} */
char *pid_file; /* PID file */
char *sub_domain; /* local domain */
char *localhost_address; /* localhost address (NULL means use 127.0.0.1) */
char *map_defaults; /* global map /default options */
char *map_options; /* global map options */
int map_reload_interval; /* map reload interval */
char *map_type; /* global map type */
char *search_path; /* search path for maps */
char *mount_type; /* mount type for map */
char *debug_mtab_file; /* path for the mtab file during debug mode */
u_int flags; /* various CFM_* flags */
#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 amfs_auto_retrans; /* NFS retransmit counter */
int amfs_auto_timeo; /* 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") */
int portmap_program; /* amd RPC program number */
#ifdef HAVE_MAP_HESIOD
char *hesiod_base; /* Hesiod rhs */
#endif /* HAVE_MAP_HESIOD */
@@ -307,14 +131,12 @@ struct amu_global_options {
char *ldap_hostports; /* LDAP host ports */
long ldap_cache_seconds; /* LDAP internal cache - keep seconds */
long ldap_cache_maxmem; /* LDAP internal cache - max memory (bytes) */
long ldap_proto_version; /* LDAP protocol version */
#endif /* HAVE_MAP_LDAP */
#ifdef HAVE_MAP_NIS
char *nis_domain; /* YP domain name */
#endif /* HAVE_MAP_NIS */
char *nfs_proto; /* NFS protocol (NULL, udp, tcp) */
int nfs_vers; /* NFS version (0, 2, 3, 4) */
u_int exec_map_timeout; /* timeout (seconds) for executable maps */
};
/* if you add anything here, update conf.c:reset_cf_map() */
@@ -322,12 +144,10 @@ 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) */
};
/*
@@ -356,173 +176,52 @@ struct mnt_map {
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 */
/* options available via amd conf file */
char *cf_map_type; /* file, hesiod, ndbm, nis, etc. */
char *cf_search_path; /* /etc/local:/etc/amdmaps:/misc/yp */
void *map_data; /* Map data black box */
};
/*
* Options
* Mounting a file system may take a significant period of time. The
* problem is that if this is done in the main process thread then the
* entire automounter could be blocked, possibly hanging lots of processes
* on the system. Instead we use a continuation scheme to allow mounts to
* be attempted in a sub-process. When the sub-process exits we pick up the
* exit status (by convention a UN*X error number) and continue in a
* notifier. The notifier gets handed a data structure and can then
* determine whether the mount was successful or not. If not, it updates
* the data structure and tries again until there are no more ways to try
* the mount, or some other permanent error occurs. In the mean time no RPC
* reply is sent, even after the mount is successful. We rely on the RPC
* retry mechanism to resend the lookup request which can then be handled.
*/
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 continuation {
char **ivec; /* Current mount info */
am_node *mp; /* Node we are trying to mount */
char *key; /* Map key */
char *info; /* Info string */
char **xivec; /* Saved strsplit vector */
char *auto_opts; /* Automount options */
am_opts fs_opts; /* Filesystem options */
char *def_opts; /* Default automount options */
int retry; /* Try again? */
int tried; /* Have we tried any yet? */
time_t start; /* Time we started this mount */
int callout; /* Callout identifier */
};
struct am_ops {
char *fs_type; /* type of filesystems e.g. "nfsx" */
vfs_match fs_match; /* fxn: match */
vfs_init fs_init; /* fxn: initialization */
vmount_fs mount_fs; /* fxn: mount my own vnode */
vumount_fs umount_fs; /* fxn: unmount my own vnode */
vlookup_child lookup_child; /* fxn: lookup path-name */
vmount_child mount_child; /* fxn: mount path-name */
vreaddir readdir; /* fxn: read directory */
vreadlink readlink; /* fxn: read link */
vmounted mounted; /* fxn: after-mount extra actions */
vumounted umounted; /* fxn: after-umount extra actions */
vffserver ffserver; /* fxn: find a file server */
vget_wchan get_wchan; /* fxn: get the waiting channel */
int nfs_fs_flags; /* filesystem flags FS_* for nfs mounts */
#ifdef HAVE_FS_AUTOFS
int autofs_fs_flags;/* filesystem flags FS_* for autofs mounts */
#endif /* HAVE_FS_AUTOFS */
};
/*
* List of mounted filesystems
*/
struct mntfs {
qelem mf_q; /* List of mounted filesystems */
am_ops *mf_ops; /* Operations on this mountpoint */
am_opts *mf_fo; /* File opts */
char *mf_mount; /* "/a/kiska/home/kiska" */
char *mf_info; /* Mount info */
char *mf_auto; /* Automount opts */
char *mf_mopts; /* FS mount opts */
char *mf_remopts; /* Remote FS mount opts */
char *mf_loopdev; /* loop device name for /dev/loop mounts */
fserver *mf_server; /* File server */
int mf_fsflags; /* Flags FS_* copied from mf_ops->*_fs_flags */
int mf_flags; /* Flags MFF_* */
int mf_error; /* Error code from background mount */
int mf_refc; /* Number of references to this node */
int mf_cid; /* Callout id */
void (*mf_prfree) (opaque_t); /* Free private space */
opaque_t mf_private; /* Private - per-fs data */
};
/*
* List of fileservers
*/
struct fserver {
qelem fs_q; /* List of fileservers */
int fs_refc; /* Number of references to this server */
char *fs_host; /* Normalized hostname of server */
struct sockaddr_in *fs_ip; /* Network address of server */
int fs_cid; /* Callout id */
int fs_pinger; /* Ping (keepalive) interval */
int fs_flags; /* Flags */
char *fs_type; /* File server type */
u_long fs_version; /* NFS version of server (2, 3, etc.)*/
char *fs_proto; /* NFS protocol of server (tcp, udp, etc.) */
opaque_t fs_private; /* Private data */
void (*fs_prfree) (opaque_t); /* Free private data */
};
/*
* Per-mountpoint statistics
*/
struct am_stats {
time_t s_mtime; /* Mount time */
u_short s_uid; /* Uid of mounter */
int s_getattr; /* Count of getattrs */
int s_lookup; /* Count of lookups */
int s_readdir; /* Count of readdirs */
int s_readlink; /* Count of readlinks */
int s_statfs; /* Count of statfs */
};
/*
* System statistics
*/
struct amd_stats {
int d_drops; /* Dropped requests */
int d_stale; /* Stale NFS handles */
int d_mok; /* Successful mounts */
int d_merr; /* Failed mounts */
int d_uerr; /* Failed unmounts */
};
extern struct amd_stats amd_stats;
/*
* Map of auto-mount points.
*/
struct am_node {
int am_mapno; /* Map number */
mntfs *am_mnt; /* Mounted filesystem */
mntfs **am_mfarray; /* Filesystem sources to try to mount */
char *am_name; /* "kiska": name of this node */
char *am_path; /* "/home/kiska": path of this node's mount point */
char *am_link; /* "/a/kiska/home/kiska/this/that": link to sub-dir */
am_node *am_parent; /* Parent of this node */
am_node *am_ysib; /* Younger sibling of this node */
am_node *am_osib; /* Older sibling of this node */
am_node *am_child; /* First child of this node */
nfsattrstat am_attr; /* File attributes */
#define am_fattr am_attr.ns_u.ns_attr_u
int am_flags; /* Boolean flags AMF_* */
int am_error; /* Specific mount error */
time_t am_ttl; /* Time to live */
int am_timeo_w; /* Dismount wait interval */
int am_timeo; /* Cache timeout interval */
u_int am_gen; /* Generation number */
char *am_pref; /* Mount info prefix */
am_stats am_stats; /* Statistics gathering */
SVCXPRT *am_transp; /* Info for quick reply */
dev_t am_dev; /* Device number */
dev_t am_rdev; /* Remote/real device number */
#ifdef HAVE_FS_AUTOFS
autofs_fh_t *am_autofs_fh;
time_t am_autofs_ttl; /* Time to expire autofs nodes */
#endif /* HAVE_FS_AUTOFS */
};
/*
* EXTERNALS:
*/
/*
* Amq server global functions
*/
/* Amq server global functions */
extern amq_mount_info_list *amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp);
extern amq_mount_stats *amqproc_stats_1_svc(voidp argp, struct svc_req *rqstp);
extern amq_mount_tree_list *amqproc_export_1_svc(voidp argp, struct svc_req *rqstp);
extern amq_mount_tree_p *amqproc_mnttree_1_svc(voidp argp, struct svc_req *rqstp);
extern amq_string *amqproc_getvers_1_svc(voidp argp, struct svc_req *rqstp);
extern amq_string *amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp);
extern int *amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp);
extern int *amqproc_mount_1_svc(voidp argp, struct svc_req *rqstp);
extern int *amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp);
@@ -530,134 +229,44 @@ extern voidp amqproc_null_1_svc(voidp argp, struct svc_req *rqstp);
extern voidp amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp);
/* other external definitions */
extern am_nfs_fh *get_root_nfs_fh(char *dir);
extern am_nfs_fh *root_fh(char *dir);
extern am_node *find_ap(char *);
extern am_node *get_ap_child(am_node *, char *);
extern am_node *find_ap2(char *, am_node *);
extern bool_t xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead);
extern fserver *find_nfs_srvr(mntfs *mf);
extern int 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 auto_fmount(am_node *mp);
extern int auto_fumount(am_node *mp);
extern int mount_nfs_fh(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *mf);
extern int process_last_regular_map(void);
extern int set_conf_kv(const char *section, const char *k, const char *v);
extern int mount_node(opaque_t arg);
extern int unmount_mp(am_node *mp);
extern int try_mount(voidp mvp);
extern int yyparse (void);
extern void amfs_mkcacheref(mntfs *mf);
extern int amfs_mount(am_node *mp, mntfs *mf, char *opts);
extern nfsentry *make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable);
extern void amfs_auto_cont(int rc, int term, voidp closure);
extern void amfs_auto_mkcacheref(mntfs *mf);
extern void amfs_auto_retry(int rc, int term, voidp closure);
extern void assign_error_mntfs(am_node *mp);
extern am_node *next_nonerror_node(am_node *xp);
extern void flush_srvr_nfs_cache(fserver *fs);
extern void am_mounted(am_node *);
extern void mf_mounted(mntfs *mf, bool_t call_free_opts);
extern void am_unmounted(am_node *);
extern am_node *get_exported_ap(int index);
extern am_node *get_first_exported_ap(int *index);
extern am_node *get_next_exported_ap(int *index);
extern am_node *path_to_exported_ap(char *path);
extern am_node *exported_ap_alloc(void);
extern am_node *find_mf(mntfs *);
extern am_node *next_map(int *);
extern am_ops *ops_match(am_opts *, char *, char *, char *, char *, char *);
extern am_ops *ops_search(char *);
extern fserver *dup_srvr(fserver *);
extern void srvrlog(fserver *, char *);
extern int get_mountd_port(fserver *, u_short *, wchan_t);
extern void flush_nfs_fhandle_cache(fserver *);
extern mntfs *dup_mntfs(mntfs *);
extern mntfs *find_mntfs(am_ops *, am_opts *, char *, char *, char *, char *, char *);
extern mntfs *locate_mntfs(am_ops *, am_opts *, char *, char *, char *, char *, char *);
extern mntfs *new_mntfs(void);
extern mntfs *realloc_mntfs(mntfs *, am_ops *, am_opts *, char *, char *, char *, char *, char *);
extern void flush_mntfs(void);
extern void free_mntfs(voidp);
extern void amq_program_1(struct svc_req *rqstp, SVCXPRT *transp);
extern int background(void);
extern void deslashify(char *);
extern void do_task_notify(void);
extern int eval_fs_opts(am_opts *, char *, char *, char *, char *, char *);
extern void forcibly_timeout_mp(am_node *);
extern void free_map(am_node *);
extern void free_opts(am_opts *);
extern void free_srvr(fserver *);
extern int fwd_init(void);
extern int fwd_packet(int, char *, int, struct sockaddr_in *, struct sockaddr_in *, opaque_t, fwd_fun *);
extern void fwd_reply(void);
extern void get_args(int argc, char *argv[]);
extern wchan_t get_mntfs_wchan(mntfs *mf);
extern void host_normalize(char **);
extern void init_map(am_node *, char *);
extern void ins_que(qelem *, qelem *);
extern void insert_am(am_node *, am_node *);
extern int make_nfs_auth(void);
extern void make_root_node(void);
extern void map_flush_srvr(fserver *);
extern void mapc_add_kv(mnt_map *, char *, char *);
extern mnt_map *mapc_find(char *, char *, const char *);
extern void mapc_free(opaque_t);
extern int mapc_keyiter(mnt_map *, key_fun, opaque_t);
extern void mapc_reload(void);
extern int mapc_search(mnt_map *, char *, char **);
extern void mapc_showtypes(char *buf, size_t l);
extern int mapc_type_exists(const char *type);
extern void mk_fattr(nfsfattr *, nfsftype);
extern int mount_auto_node(char *, opaque_t);
extern int mount_automounter(int);
extern int mount_exported(void);
extern void mp_to_fh(am_node *, am_nfs_fh *);
extern void new_ttl(am_node *);
extern void nfs_quick_reply(am_node *mp, int error);
extern void normalize_slash(char *);
extern void ops_showamfstypes(char *buf, size_t l);
extern void ops_showfstypes(char *outbuf, size_t l);
extern void rem_que(qelem *);
extern void reschedule_timeout_mp(void);
extern void restart(void);
extern void restart_automounter_nodes(void);
extern int root_keyiter(key_fun *, opaque_t);
extern void flush_srvr_nfs_cache(void);
extern void free_continuation(struct continuation *cp);
extern void mf_mounted(mntfs *mf);
extern void quick_reply(am_node *mp, int error);
extern void root_newmap(const char *, const char *, const char *, const cf_map_t *);
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.
*/
/* amd global variables */
extern FILE *yyin;
extern SVCXPRT *current_transp; /* For nfs_quick_reply() */
extern SVCXPRT *nfs_program_2_transp; /* For quick_reply() */
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 char *opt_gid;
extern char *opt_uid;
extern int NumChild;
extern int fwd_sock;
extern int select_intr_valid;
extern int immediate_abort; /* Should close-down unmounts be retried */
extern int usage;
extern int use_conf_file; /* use amd configuration file */
extern int task_notify_todo; /* Task notifier needs running */
extern jmp_buf select_intr;
extern qelem mfhead;
extern struct am_opts fs_static; /* copy of the options to play with */
extern struct amu_global_options gopt; /* where global options are stored */
extern time_t do_mapc_reload; /* Flush & reload mount map cache */
extern time_t next_softclock; /* Time to call softclock() */
#ifdef HAVE_SIGACTION
extern sigset_t masked_sigs;
@@ -665,88 +274,16 @@ extern sigset_t masked_sigs;
#if defined(HAVE_AMU_FS_LINK) || defined(HAVE_AMU_FS_LINKX)
extern char *amfs_link_match(am_opts *fo);
extern int amfs_link_fumount(mntfs *mf);
#endif /* defined(HAVE_AMU_FS_LINK) || defined(HAVE_AMU_FS_LINKX) */
#ifdef HAVE_FS_AUTOFS
extern int amd_use_autofs;
#ifdef HAVE_AMU_FS_NFSL
extern char *nfs_match(am_opts *fo);
#endif /* HAVE_AMU_FS_NFSL */
extern int autofs_get_fh(am_node *mp);
extern void autofs_release_fh(am_node *mp);
extern void autofs_get_mp(am_node *mp);
extern void autofs_release_mp(am_node *mp);
extern void autofs_add_fdset(fd_set *readfds);
extern int autofs_handle_fdset(fd_set *readfds, int nsel);
extern void autofs_mounted(am_node *mp);
extern void autofs_mount_succeeded(am_node *mp);
extern void autofs_mount_failed(am_node *mp);
extern int autofs_umount_succeeded(am_node *mp);
extern int autofs_umount_failed(am_node *mp);
extern int autofs_mount_fs(am_node *mp, mntfs *mf);
extern int autofs_umount_fs(am_node *mp, mntfs *mf);
extern void autofs_get_opts(char *opts, size_t l, autofs_fh_t *fh);
extern int autofs_compute_mount_flags(mntent_t *);
extern void autofs_timeout_mp(am_node *);
extern int create_autofs_service(void);
extern int destroy_autofs_service(void);
#endif /* HAVE_FS_AUTOFS */
/**************************************************************************/
/*** Generic file-system types, implemented as part of the native O/S. ***/
/**************************************************************************/
/*
* Loopback File System
* Many systems can't support this, and in any case most of the
* functionality is available with Symlink FS.
*/
#ifdef HAVE_FS_LOFS
extern am_ops lofs_ops;
extern int mount_lofs(char *mntdir, char *fs_name, char *opts, int on_autofs);
#endif /* HAVE_FS_LOFS */
/*
* CD-ROM File System (CD-ROM)
* (HSFS: High Sierra F/S on some machines)
* Many systems can't support this, and in any case most of the
* functionality is available with program FS.
*/
#ifdef HAVE_FS_CDFS
extern am_ops cdfs_ops;
#endif /* HAVE_FS_CDFS */
/*
* PC File System (MS-DOS)
* Many systems can't support this, and in any case most of the
* functionality is available with program FS.
*/
#ifdef HAVE_FS_PCFS
extern am_ops pcfs_ops;
#endif /* HAVE_FS_PCFS */
/*
* Caching File System (Solaris)
*/
#ifdef HAVE_FS_CACHEFS
extern am_ops cachefs_ops;
#endif /* HAVE_FS_CACHEFS */
/*
* Network File System
* Good, slow, NFS V.2.
*/
#ifdef HAVE_FS_NFS
extern am_ops nfs_ops; /* NFS */
extern fserver *find_nfs_srvr (mntfs *);
extern qelem nfs_srvr_list;
#endif /* HAVE_FS_NFS */
/*
* Un*x File System
* Normal local disk file system.
*/
#ifdef HAVE_FS_UFS
extern am_ops ufs_ops; /* Un*x file system */
#endif /* HAVE_FS_UFS */
#if defined(HAVE_FS_NFS3) && !defined(HAVE_XDR_MOUNTRES3)
extern bool_t xdr_mountres3(XDR *xdrs, mountres3 *objp);
#endif /* defined(HAVE_FS_NFS3) && !defined(HAVE_XDR_MOUNTRES3) */
/* Unix file system (irix) */
#ifdef HAVE_FS_XFS
@@ -758,110 +295,4 @@ extern am_ops xfs_ops; /* Un*x file system */
extern am_ops efs_ops; /* Un*x file system */
#endif /* HAVE_FS_EFS */
/**************************************************************************/
/*** Automounter file-system types, implemented by amd. ***/
/**************************************************************************/
/*
* Root AMD File System
*/
extern am_ops amfs_root_ops; /* Root file system */
/*
* Generic amfs helper methods
*/
extern am_node *amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op);
extern am_node *amfs_generic_mount_child(am_node *ap, int *error_return);
extern int amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count);
extern int amfs_generic_umount(am_node *mp, mntfs *mf);
extern void amfs_generic_mounted(mntfs *mf);
extern char *amfs_generic_match(am_opts *fo);
extern fserver *amfs_generic_find_srvr(mntfs *);
/*
* Automount File System
*/
#ifdef HAVE_AMU_FS_AUTO
extern am_ops amfs_auto_ops; /* Automount file system (this!) */
#endif /* HAVE_AMU_FS_AUTO */
/*
* Toplvl Automount File System
*/
#ifdef HAVE_AMU_FS_TOPLVL
extern am_ops amfs_toplvl_ops; /* Toplvl Automount file system */
extern int amfs_toplvl_mount(am_node *mp, mntfs *mf);
extern int amfs_toplvl_umount(am_node *mp, mntfs *mf);
#endif /* HAVE_AMU_FS_TOPLVL */
/*
* Direct Automount File System
*/
#ifdef HAVE_AMU_FS_DIRECT
extern am_ops amfs_direct_ops; /* Direct Automount file system (this too) */
#endif /* HAVE_AMU_FS_DIRECT */
/*
* Error File System
*/
#ifdef HAVE_AMU_FS_ERROR
extern am_ops amfs_error_ops; /* Error file system */
extern am_node *amfs_error_lookup_child(am_node *mp, char *fname, int *error_return, int op);
extern am_node *amfs_error_mount_child(am_node *ap, int *error_return);
extern int amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count);
#endif /* HAVE_AMU_FS_ERROR */
/*
* NFS mounts with local existence check.
*/
#ifdef HAVE_AMU_FS_NFSL
extern am_ops amfs_nfsl_ops; /* NFSL */
#endif /* HAVE_AMU_FS_NFSL */
/*
* Multi-nfs mounts.
*/
#ifdef HAVE_AMU_FS_NFSX
extern am_ops amfs_nfsx_ops; /* NFSX */
#endif /* HAVE_AMU_FS_NFSX */
/*
* NFS host - a whole tree.
*/
#ifdef HAVE_AMU_FS_HOST
extern am_ops amfs_host_ops; /* NFS host */
#endif /* HAVE_AMU_FS_HOST */
/*
* Program File System
* This is useful for things like RVD.
*/
#ifdef HAVE_AMU_FS_PROGRAM
extern am_ops amfs_program_ops; /* Program File System */
#endif /* HAVE_AMU_FS_PROGRAM */
/*
* Symbolic-link file system.
* A "filesystem" which is just a symbol link.
*/
#ifdef HAVE_AMU_FS_LINK
extern am_ops amfs_link_ops; /* Symlink FS */
#endif /* HAVE_AMU_FS_LINK */
/*
* Symbolic-link file system, which also checks that the target of
* the symlink exists.
* A "filesystem" which is just a symbol link.
*/
#ifdef HAVE_AMU_FS_LINKX
extern am_ops amfs_linkx_ops; /* Symlink FS with existence check */
#endif /* HAVE_AMU_FS_LINKX */
/*
* Union file system
*/
#ifdef HAVE_AMU_FS_UNION
extern am_ops amfs_union_ops; /* Union FS */
#endif /* HAVE_AMU_FS_UNION */
#endif /* not _AMD_H */
File diff suppressed because it is too large. Load diff
+13 -17
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/amfs_direct.c
* $Id: amfs_direct.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -62,22 +63,19 @@ static am_node *amfs_direct_readlink(am_node *mp, int *error_return);
am_ops amfs_direct_ops =
{
"direct",
amfs_generic_match,
amfs_auto_match,
0, /* amfs_direct_init */
amfs_toplvl_mount,
0,
amfs_toplvl_umount,
amfs_generic_lookup_child,
amfs_generic_mount_child,
0,
amfs_error_lookuppn,
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 */
amfs_toplvl_mounted,
0, /* amfs_auto_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO
};
@@ -94,10 +92,8 @@ amfs_direct_readlink(am_node *mp, int *error_return)
xp = next_nonerror_node(mp->am_child);
if (!xp) {
if (!mp->am_mnt->mf_private)
amfs_mkcacheref(mp->am_mnt); /* XXX */
xp = amfs_generic_lookup_child(mp, mp->am_path + 1, &rc, VLOOK_CREATE);
if (xp && rc < 0)
xp = amfs_generic_mount_child(xp, &rc);
amfs_auto_mkcacheref(mp->am_mnt); /* XXX */
xp = amfs_auto_lookuppn(mp, mp->am_path + 1, &rc, VLOOK_CREATE);
}
if (xp) {
new_ttl(xp); /* (7/12/89) from Rein Tollevik */
+31 -32
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/amfs_error.c
* $Id: amfs_error.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -56,8 +57,9 @@
#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);
static int amfs_error_fmount(mntfs *mf);
static int amfs_error_fumount(mntfs *mf);
static void amfs_error_umounted(am_node *mp);
/*
@@ -68,20 +70,17 @@ 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_auto_fmount,
amfs_error_fmount,
amfs_auto_fumount,
amfs_error_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* amfs_error_readlink */
0, /* amfs_error_mounted */
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 */
amfs_error_umounted,
find_amfs_auto_srvr,
FS_DISCARD
};
@@ -97,14 +96,14 @@ amfs_error_match(am_opts *fo)
static int
amfs_error_mount(am_node *am, mntfs *mf)
amfs_error_fmount(mntfs *mf)
{
return ENOENT;
}
static int
amfs_error_umount(am_node *am, mntfs *mf)
amfs_error_fumount(mntfs *mf)
{
/*
* Always succeed
@@ -119,20 +118,7 @@ amfs_error_umount(am_node *am, mntfs *mf)
* 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)
amfs_error_lookuppn(am_node *mp, char *fname, int *error_return, int op)
{
*error_return = ESTALE;
return 0;
@@ -145,7 +131,20 @@ amfs_error_mount_child(am_node *ap, int *error_return)
* If we do then just give an error.
*/
int
amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count)
amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count)
{
return ESTALE;
}
/*
* umounted() callback for EFS.
*
* This prevents core-dumps on callbacks to error file-systems from
* nfsx_fumount.
*/
static void
amfs_error_umounted(am_node *mp)
{
/* nothing to do */
}
File diff suppressed because it is too large. Load diff
+74 -96
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/amfs_host.c
* $Id: amfs_host.c,v 1.4.2.7 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -56,10 +57,10 @@
#include <amd.h>
static char *amfs_host_match(am_opts *fo);
static int amfs_host_fmount(mntfs *mf);
static int amfs_host_fumount(mntfs *mf);
static int amfs_host_init(mntfs *mf);
static 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);
static void amfs_host_umounted(am_node *mp);
/*
* Ops structure
@@ -69,20 +70,17 @@ 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_auto_fmount,
amfs_host_fmount,
amfs_auto_fumount,
amfs_host_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* amfs_host_readlink */
0, /* amfs_host_mounted */
amfs_host_umounted,
find_nfs_srvr,
0, /* amfs_host_get_wchan */
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO,
#ifdef HAVE_FS_AUTOFS
AUTOFS_HOST_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO
};
@@ -97,21 +95,21 @@ am_ops amfs_host_ops =
* allows the entire PC disk to be mounted.
*/
static void
make_mntpt(char *mntpt, size_t l, const exports ex, const char *mf_mount)
make_mntpt(char *mntpt, const exports ex, const mntfs *mf)
{
if (ex->ex_dir[0] == '/') {
if (ex->ex_dir[1] == 0)
xstrlcpy(mntpt, mf_mount, l);
strcpy(mntpt, (mf)->mf_mount);
else
xsnprintf(mntpt, l, "%s%s", mf_mount, ex->ex_dir);
sprintf(mntpt, "%s%s", mf->mf_mount, ex->ex_dir);
} else if (ex->ex_dir[0] >= 'a' &&
ex->ex_dir[0] <= 'z' &&
ex->ex_dir[1] == ':' &&
ex->ex_dir[2] == '/' &&
ex->ex_dir[3] == 0)
xsnprintf(mntpt, l, "%s/%c%%", mf_mount, ex->ex_dir[0]);
sprintf(mntpt, "%s/%c%%", mf->mf_mount, ex->ex_dir[0]);
else
xsnprintf(mntpt, l, "%s/%s", mf_mount, ex->ex_dir);
sprintf(mntpt, "%s/%s", mf->mf_mount, ex->ex_dir);
}
@@ -136,7 +134,8 @@ amfs_host_match(am_opts *fo)
static int
amfs_host_init(mntfs *mf)
{
u_short mountd_port;
fserver *fs;
u_short port;
if (strchr(mf->mf_info, ':') == 0)
return ENOENT;
@@ -153,39 +152,41 @@ amfs_host_init(mntfs *mf)
*/
/*
* 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
* nfs_srvr_port with our mntfs passed as the wait channel.
* nfs_srvr_port will check some things and then schedule
* it so that when the fileserver is ready, a wakeup is done
* on this mntfs. amfs_cont() is already sleeping on this mntfs
* so as soon as that wakeup happens amfs_cont() is called and
* on this mntfs. amfs_auto_cont() is already sleeping on this mntfs
* so as soon as that wakeup happens amfs_auto_cont() is called and
* this mount is retried.
*/
if (mf->mf_server)
if ((fs = mf->mf_server))
/*
* We don't really care if there's an error returned.
* Since this is just to help speed things along, the
* error will get handled properly elsewhere.
*/
get_mountd_port(mf->mf_server, &mountd_port, get_mntfs_wchan(mf));
(void) nfs_srvr_port(fs, &port, (voidp) mf);
return 0;
}
static int
do_mount(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf)
do_mount(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *mf)
{
struct stat stb;
dlog("amfs_host: mounting fs %s on %s\n", fs_name, mntdir);
#ifdef DEBUG
dlog("amfs_host: mounting fs %s on %s\n", fs_name, dir);
#endif /* DEBUG */
(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);
(void) mkdirs(dir, 0555);
if (stat(dir, &stb) < 0 || (stb.st_mode & S_IFMT) != S_IFDIR) {
plog(XLOG_ERROR, "No mount point for %s - skipping", dir);
return ENOENT;
}
return mount_nfs_fh(fhp, mntdir, fs_name, mf);
return mount_nfs_fh(fhp, dir, fs_name, opts, mf);
}
@@ -207,10 +208,6 @@ fetch_fhandle(CLIENT *client, char *dir, am_nfs_handle_t *fhp, u_long nfs_versio
{
struct timeval tv;
enum clnt_stat clnt_stat;
struct fhstatus res;
#ifdef HAVE_FS_NFS3
struct am_mountres3 res3;
#endif /* HAVE_FS_NFS3 */
/*
* Pick a number, any number...
@@ -218,7 +215,9 @@ fetch_fhandle(CLIENT *client, char *dir, am_nfs_handle_t *fhp, u_long nfs_versio
tv.tv_sec = 20;
tv.tv_usec = 0;
#ifdef DEBUG
dlog("Fetching fhandle for %s", dir);
#endif /* DEBUG */
/*
* Call the mount daemon on the remote host to
@@ -228,28 +227,25 @@ fetch_fhandle(CLIENT *client, char *dir, am_nfs_handle_t *fhp, u_long nfs_versio
plog(XLOG_INFO, "fetch_fhandle: NFS version %d", (int) nfs_version);
#ifdef HAVE_FS_NFS3
if (nfs_version == NFS_VERSION3) {
memset((char *) &res3, 0, sizeof(res3));
memset((char *) &fhp->v3, 0, sizeof(fhp->v3));
clnt_stat = clnt_call(client,
MOUNTPROC_MNT,
(XDRPROC_T_TYPE) xdr_dirpath,
(SVC_IN_ARG_TYPE) &dir,
(XDRPROC_T_TYPE) xdr_am_mountres3,
(SVC_IN_ARG_TYPE) &res3,
(XDRPROC_T_TYPE) xdr_mountres3,
(SVC_IN_ARG_TYPE) &fhp->v3,
tv);
if (clnt_stat != RPC_SUCCESS) {
plog(XLOG_ERROR, "mountd rpc failed: %s", clnt_sperrno(clnt_stat));
return EIO;
}
/* Check the status of the filehandle */
if ((errno = res3.fhs_status)) {
if ((errno = fhp->v3.fhs_status)) {
#ifdef DEBUG
dlog("fhandle fetch for mount version 3 failed: %m");
#endif /* DEBUG */
return errno;
}
memset((voidp) &fhp->v3, 0, sizeof(am_nfs_fh3));
fhp->v3.am_fh3_length = res3.mountres3_u.mountinfo.fhandle.fhandle3_len;
memmove(fhp->v3.am_fh3_data,
res3.mountres3_u.mountinfo.fhandle.fhandle3_val,
fhp->v3.am_fh3_length);
} else { /* not NFS_VERSION3 mount */
#endif /* HAVE_FS_NFS3 */
clnt_stat = clnt_call(client,
@@ -257,19 +253,20 @@ fetch_fhandle(CLIENT *client, char *dir, am_nfs_handle_t *fhp, u_long nfs_versio
(XDRPROC_T_TYPE) xdr_dirpath,
(SVC_IN_ARG_TYPE) &dir,
(XDRPROC_T_TYPE) xdr_fhstatus,
(SVC_IN_ARG_TYPE) &res,
(SVC_IN_ARG_TYPE) &fhp->v2,
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;
if (fhp->v2.fhs_status) {
errno = fhp->v2.fhs_status;
#ifdef DEBUG
dlog("fhandle fetch for mount version 1 failed: %m");
#endif /* DEBUG */
return errno;
}
memmove(&fhp->v2, &res.fhs_fh, NFS_FHSIZE);
#ifdef HAVE_FS_NFS3
} /* end of "if (nfs_version == NFS_VERSION3)" statement */
#endif /* HAVE_FS_NFS3 */
@@ -294,8 +291,11 @@ already_mounted(mntlist *mlist, char *dir)
}
/*
* Mount the export tree from a host
*/
static int
amfs_host_mount(am_node *am, mntfs *mf)
amfs_host_fmount(mntfs *mf)
{
struct timeval tv2;
CLIENT *client;
@@ -316,14 +316,6 @@ amfs_host_mount(am_node *am, mntfs *mf)
struct timeval tv;
u_long mnt_version;
/*
* WebNFS servers don't necessarily run mountd.
*/
if (mf->mf_flags & MFF_WEBNFS) {
plog(XLOG_ERROR, "amfs_host_mount: cannot support WebNFS");
return EIO;
}
/*
* Read the mount list
*/
@@ -342,10 +334,10 @@ amfs_host_mount(am_node *am, mntfs *mf)
*/
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);
plog(XLOG_INFO, "amfs_host_fmount: 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;
mnt_version = MOUNTVERS3;
else
#endif /* HAVE_FS_NFS3 */
mnt_version = MOUNTVERS;
@@ -382,7 +374,9 @@ amfs_host_mount(am_node *am, mntfs *mf)
}
client->cl_auth = nfs_auth;
#ifdef DEBUG
dlog("Fetching export list from %s", host);
#endif /* DEBUG */
/*
* Fetch the export list
@@ -398,7 +392,7 @@ amfs_host_mount(am_node *am, mntfs *mf)
tv2);
if (clnt_stat != RPC_SUCCESS) {
const char *msg = clnt_sperrno(clnt_stat);
plog(XLOG_ERROR, "host_mount rpc failed: %s", msg);
plog(XLOG_ERROR, "host_fmount rpc failed: %s", msg);
/* clnt_perror(client, "rpc"); */
error = EIO;
goto out;
@@ -418,7 +412,7 @@ amfs_host_mount(am_node *am, mntfs *mf)
*/
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);
make_mntpt(mntpt, ex, mf);
if (already_mounted(mlist, mntpt))
/* we have at least one mounted f/s, so don't fail the mount */
ok = TRUE;
@@ -448,7 +442,9 @@ amfs_host_mount(am_node *am, mntfs *mf)
for (j = k = 0; j < n_export; j++) {
/* Check and avoid a duplicated export entry */
if (j > k && ep[k] && STREQ(ep[j]->ex_dir, ep[k]->ex_dir)) {
#ifdef DEBUG
dlog("avoiding dup fhandle requested for %s", ep[j]->ex_dir);
#endif /* DEBUG */
ep[j] = 0;
} else {
k = j;
@@ -465,9 +461,9 @@ amfs_host_mount(am_node *am, mntfs *mf)
* error code 0 at the end. If they all fail then return
* the last error code.
*/
xstrlcpy(fs_name, mf->mf_info, MAXPATHLEN);
strncpy(fs_name, mf->mf_info, sizeof(fs_name));
if ((rfs_dir = strchr(fs_name, ':')) == (char *) 0) {
plog(XLOG_FATAL, "amfs_host_mount: mf_info has no colon");
plog(XLOG_FATAL, "amfs_host_fmount: mf_info has no colon");
error = EINVAL;
goto out;
}
@@ -475,15 +471,9 @@ amfs_host_mount(am_node *am, mntfs *mf)
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)
strcpy(rfs_dir, ex->ex_dir);
make_mntpt(mntpt, ex, mf);
if (do_mount(&fp[j], mntpt, fs_name, mf->mf_mopts, mf) == 0)
ok = TRUE;
}
}
@@ -532,10 +522,9 @@ directory_prefix(char *pref, char *dir)
* Unmount a mount tree
*/
static int
amfs_host_umount(am_node *am, mntfs *mf)
amfs_host_fumount(mntfs *mf)
{
mntlist *ml, *mprev;
int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
int xerror = 0;
/*
@@ -570,24 +559,18 @@ amfs_host_umount(am_node *am, mntfs *mf)
char *dir = ml->mnt->mnt_dir;
if (directory_prefix(mf->mf_mount, dir)) {
int error;
#ifdef DEBUG
dlog("amfs_host: unmounts %s", dir);
#endif /* DEBUG */
/*
* Unmount "dir"
*/
error = UMOUNT_FS(dir, mnttab_file_name, unmount_flags);
error = UMOUNT_FS(dir, mnttab_file_name);
/*
* 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)
if (!xerror)
xerror = error;
if (error != EBUSY) {
errno = error;
@@ -608,7 +591,7 @@ amfs_host_umount(am_node *am, mntfs *mf)
* Try to remount, except when we are shutting down.
*/
if (xerror && amd_state != Finishing) {
xerror = amfs_host_mount(am, mf);
xerror = amfs_host_fmount(mf);
if (!xerror) {
/*
* Don't log this - it's usually too verbose
@@ -628,8 +611,9 @@ amfs_host_umount(am_node *am, mntfs *mf)
* mountd protocol is badly broken anyway.
*/
static void
amfs_host_umounted(mntfs *mf)
amfs_host_umounted(am_node *mp)
{
mntfs *mf = mp->am_mnt;
char *host;
CLIENT *client;
enum clnt_stat clnt_stat;
@@ -641,14 +625,6 @@ amfs_host_umounted(mntfs *mf)
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.
@@ -658,7 +634,7 @@ amfs_host_umounted(mntfs *mf)
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;
mnt_version = MOUNTVERS3;
else
#endif /* HAVE_FS_NFS3 */
mnt_version = MOUNTVERS;
@@ -685,7 +661,9 @@ amfs_host_umounted(mntfs *mf)
}
client->cl_auth = nfs_auth;
#ifdef DEBUG
dlog("Unmounting all from %s", host);
#endif /* DEBUG */
clnt_stat = clnt_call(client,
MOUNTPROC_UMNTALL,
+200
View File
@@ -0,0 +1,200 @@
/*
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgment:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amfs_inherit.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
/*
* Inheritance file system.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/*
* This implements a filesystem restart.
*
* This is a *gross* hack - it knows far too
* much about the way other parts of the
* system work. See restart.c too.
*/
static char *amfs_inherit_match(am_opts *fo);
static int amfs_inherit_fmount(mntfs *mf);
static int amfs_inherit_fumount(mntfs *mf);
static int amfs_inherit_init(mntfs *mf);
static int amfs_inherit_mount(am_node *mp);
/*
* Ops structure
*/
am_ops amfs_inherit_ops =
{
"inherit",
amfs_inherit_match,
amfs_inherit_init,
amfs_inherit_mount,
amfs_inherit_fmount,
amfs_auto_fumount,
amfs_inherit_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* amfs_inherit_readlink */
0, /* amfs_inherit_mounted */
0, /* amfs_inherit_umounted */
find_amfs_auto_srvr,
FS_DISCARD
};
/*
* This should never be called.
*/
static char *
amfs_inherit_match(am_opts *fo)
{
plog(XLOG_FATAL, "amfs_inherit_match called!");
return 0;
}
static int
amfs_inherit_init(mntfs *mf)
{
mntfs *mf_link = (mntfs *) mf->mf_private;
if (mf_link == 0) {
plog(XLOG_ERROR, "Remount collision on %s?", mf->mf_mount);
plog(XLOG_FATAL, "Attempting to init not-a-filesystem");
return EINVAL;
}
if (mf_link->mf_ops->fs_init)
return (*mf_link->mf_ops->fs_init) (mf_link);
return 0;
}
/*
* Take the linked mount point and
* propagate.
*/
static mntfs *
amfs_inherit_inherit(mntfs *mf)
{
mntfs *mf_link = (mntfs *) mf->mf_private;
if (mf_link == 0) {
plog(XLOG_FATAL, "Attempting to inherit not-a-filesystem");
return 0; /* XXX */
}
mf_link->mf_fo = mf->mf_fo;
/*
* Discard the old map.
* Don't call am_unmounted since this
* node was never really mounted in the
* first place.
*/
mf->mf_private = 0;
free_mntfs(mf);
/*
* Free the dangling reference
* to the mount link.
*/
free_mntfs(mf_link);
/*
* Get a hold of the other entry
*/
mf_link->mf_flags &= ~MFF_RESTART;
/* Say what happened */
plog(XLOG_INFO, "restarting %s on %s", mf_link->mf_info, mf_link->mf_mount);
return mf_link;
}
static int
amfs_inherit_mount(am_node *mp)
{
mntfs *newmf = amfs_inherit_inherit(mp->am_mnt);
if (newmf) {
mp->am_mnt = newmf;
/*
* XXX - must do the am_mounted call here
*/
if (newmf->mf_ops->fs_flags & FS_MBACKGROUND)
am_mounted(mp);
new_ttl(mp);
return 0;
}
return EINVAL;
}
static int
amfs_inherit_fmount(mntfs *mf)
{
am_node *mp = find_mf(mf);
if (mp)
return amfs_inherit_mount(mp);
return amfs_inherit_inherit(mf) ? 0 : EINVAL;
}
static int
amfs_inherit_fumount(mntfs *mf)
{
/*
* Always succeed
*/
return 0;
}
+43 -35
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/amfs_link.c
* $Id: amfs_link.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -51,9 +52,6 @@
#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
@@ -63,20 +61,17 @@ 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_auto_fmount,
amfs_link_fmount,
amfs_auto_fumount,
amfs_link_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* amfs_link_readlink */
0, /* amfs_link_mounted */
0, /* amfs_link_umounted */
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 */
find_amfs_auto_srvr,
0
};
@@ -93,41 +88,54 @@ amfs_link_match(am_opts *fo)
}
/*
* 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.
* Bug report (14/12/89) from Jay Plett <jay@princeton.edu>
* If an automount point has the same name as an existing
* link type mount Amd hits a race condition and either hangs
* or causes a symlink loop.
*
* For example, if the link points to /usr, and /usr is a real ufs
* filesystem, then the link f/s will use the inherited ufs mntfs,
* and the end result will be that it will become unmountable.
* If fs begins with a '/' change the opt_fs & opt_sublink
* fields so that the fs option doesn't end up pointing at
* an existing symlink.
*
* 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.
* If sublink is nil then set sublink to fs
* else set sublink to fs / sublink
*
* XXX: a less hacky solution should be used...
* Finally set fs to ".".
*/
if (fo->opt_fs[0] == '/') {
char *link_hack = str3cat(NULL, ".", fo->opt_fs, "");
if (!fo->opt_sublink)
fo->opt_sublink = strdup(fo->opt_fs);
XFREE(fo->opt_fs);
fo->opt_fs = link_hack;
if (*fo->opt_fs == '/') {
char *fullpath;
char *link = fo->opt_sublink;
if (link) {
if (*link == '/')
fullpath = strdup(link);
else
fullpath = str3cat((char *) 0, fo->opt_fs, "/", link);
} else {
fullpath = strdup(fo->opt_fs);
}
if (fo->opt_sublink)
XFREE(fo->opt_sublink);
fo->opt_sublink = fullpath;
fo->opt_fs = str3cat(fo->opt_fs, ".", fullpath, "");
}
return strdup(fo->opt_fs);
}
static int
amfs_link_mount(am_node *mp, mntfs *mf)
int
amfs_link_fmount(mntfs *mf)
{
/*
* Wow - this is hard to implement! :-)
*/
return 0;
}
static int
amfs_link_umount(am_node *mp, mntfs *mf)
int
amfs_link_fumount(mntfs *mf)
{
return 0;
}
+12 -22
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/amfs_linkx.c
* $Id: amfs_linkx.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -52,8 +53,7 @@
#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);
static int amfs_linkx_mount(am_node *mp);
/*
* linkx operations
@@ -64,24 +64,21 @@ struct am_ops amfs_linkx_ops =
amfs_link_match,
0, /* amfs_linkx_init */
amfs_linkx_mount,
amfs_linkx_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
0,
amfs_auto_fumount,
amfs_link_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* amfs_linkx_readlink */
0, /* amfs_linkx_mounted */
0, /* amfs_linkx_umounted */
amfs_generic_find_srvr,
0, /* amfs_linkx_get_wchan */
FS_MBACKGROUND,
#ifdef HAVE_FS_AUTOFS
AUTOFS_LINKX_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
find_amfs_auto_srvr,
FS_MBACKGROUND
};
static int
amfs_linkx_mount(am_node *mp, mntfs *mf)
amfs_linkx_mount(am_node *mp)
{
/*
* Check for existence of target.
@@ -92,7 +89,7 @@ amfs_linkx_mount(am_node *mp, mntfs *mf)
if (mp->am_link)
ln = mp->am_link;
else /* should never occur */
ln = mf->mf_mount;
ln = mp->am_mnt->mf_mount;
/*
* Use lstat, not stat, since we don't
@@ -104,10 +101,3 @@ amfs_linkx_mount(am_node *mp, mntfs *mf)
return 0;
}
static int
amfs_linkx_umount(am_node *mp, mntfs *mf)
{
return 0;
}
+71 -72
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/amfs_nfsl.c
* $Id: amfs_nfsl.c,v 1.4.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -59,9 +60,9 @@
/* 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 int amfs_nfsl_fmount(mntfs *mf);
static int amfs_nfsl_fumount(mntfs *mf);
static void amfs_nfsl_umounted(am_node *mp);
static fserver *amfs_nfsl_ffserver(mntfs *mf);
/*
@@ -69,23 +70,20 @@ static fserver *amfs_nfsl_ffserver(mntfs *mf);
*/
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 */
"nfsl", /* name of file system */
amfs_nfsl_match, /* match */
amfs_nfsl_init, /* initialize */
amfs_auto_fmount, /* mount vnode */
amfs_nfsl_fmount, /* mount vfs */
amfs_auto_fumount, /* unmount vnode */
amfs_nfsl_fumount, /* unmount VFS */
amfs_error_lookuppn, /* lookup path-name */
amfs_error_readdir, /* read directory */
0, /* read link */
0, /* after-mount extra actions */
amfs_nfsl_umounted, /* after-umount extra actions */
amfs_nfsl_ffserver, /* find a file server */
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO /* flags */
};
@@ -96,16 +94,10 @@ am_ops amfs_nfsl_ops =
static char *
amfs_nfsl_match(am_opts *fo)
{
char *cp;
char *cp = fo->opt_fs;
char *ho = fo->opt_rhost;
char *retval;
struct stat stb;
if (fo->opt_sublink)
cp = fo->opt_sublink;
else
cp = fo->opt_fs;
if (!cp || !ho) {
plog(XLOG_USER, "amfs_nfsl: host $fs and $rhost must be specified");
return NULL;
@@ -113,20 +105,20 @@ amfs_nfsl_match(am_opts *fo)
/*
* 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().
* perform nfs_match(), same as for type:=nfs.
* If link value exists (or same host), then perform amfs_link_match(),
* same as for linkx.
*/
if (!STRCEQ(ho, am_get_hostname())) {
plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not local host, using type:=nfs", ho);
retval = nfs_ops.fs_match(fo);
return nfs_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);
return nfs_match(fo);
} else {
plog(XLOG_INFO, "amfs_nfsl: \"%s\" exists, using type:=link", cp);
retval = amfs_link_ops.fs_match(fo);
return amfs_link_match(fo);
}
return retval;
}
@@ -137,15 +129,15 @@ amfs_nfsl_match(am_opts *fo)
static int
amfs_nfsl_init(mntfs *mf)
{
int ret = 0;
/*
* If a link, do nothing (same as type:=link).
* If non-link, do nfs_init (same as type:=nfs).
*/
if (mf->mf_flags & MFF_NFSLINK) {
if (amfs_link_ops.fs_init)
ret = amfs_link_ops.fs_init(mf);
return 0;
} else {
if (nfs_ops.fs_init)
ret = nfs_ops.fs_init(mf);
return nfs_init(mf);
}
return ret;
}
@@ -154,17 +146,17 @@ amfs_nfsl_init(mntfs *mf)
* Returns: 0 if OK, non-zero (errno) if failed.
*/
static int
amfs_nfsl_mount(am_node *mp, mntfs *mf)
amfs_nfsl_fmount(mntfs *mf)
{
int ret = 0;
/*
* If a link, do run amfs_link_fmount() (same as type:=link)
* If non-link, do nfs_fmount (same as type:=nfs).
*/
if (mf->mf_flags & MFF_NFSLINK) {
if (amfs_link_ops.mount_fs)
ret = amfs_link_ops.mount_fs(mp, mf);
return amfs_link_fmount(mf);
} else {
if (nfs_ops.mount_fs)
ret = nfs_ops.mount_fs(mp, mf);
return nfs_fmount(mf);
}
return ret;
}
@@ -173,17 +165,17 @@ amfs_nfsl_mount(am_node *mp, mntfs *mf)
* Returns: 0 if OK, non-zero (errno) if failed.
*/
static int
amfs_nfsl_umount(am_node *mp, mntfs *mf)
amfs_nfsl_fumount(mntfs *mf)
{
int ret = 0;
/*
* If a link, do run amfs_link_fumount() (same as type:=link)
* If non-link, do nfs_fumount (same as type:=nfs).
*/
if (mf->mf_flags & MFF_NFSLINK) {
if (amfs_link_ops.umount_fs)
ret = amfs_link_ops.umount_fs(mp, mf);
return amfs_link_fumount(mf);
} else {
if (nfs_ops.umount_fs)
ret = nfs_ops.umount_fs(mp, mf);
return nfs_fumount(mf);
}
return ret;
}
@@ -194,14 +186,27 @@ amfs_nfsl_umount(am_node *mp, mntfs *mf)
* See amfs_auto_umounted(), host_umounted(), nfs_umounted().
*/
static void
amfs_nfsl_umounted(mntfs *mf)
amfs_nfsl_umounted(am_node *mp)
{
mntfs *mf = mp->am_mnt;
/*
* If a link, do nothing (same as type:=link)
* If non-link, do nfs_fumount (same as type:=nfs).
*/
if (mf->mf_flags & MFF_NFSLINK) {
if (amfs_link_ops.umounted)
amfs_link_ops.umounted(mf);
return;
} else {
if (nfs_ops.umounted)
nfs_ops.umounted(mf);
nfs_umounted(mp);
/*
* MUST remove mount point directories, because if they remain
* behind, the next nfsl access will think they are a link
* type file system, and not NFS! (when it performs link target
* existence test)
*/
if (mf->mf_flags & MFF_MKMNT)
rmdirs(mf->mf_mount);
return;
}
}
@@ -213,26 +218,20 @@ amfs_nfsl_umounted(mntfs *mf)
static fserver *
amfs_nfsl_ffserver(mntfs *mf)
{
char *cp;
char *cp = mf->mf_fo->opt_fs;
char *ho = mf->mf_fo->opt_rhost;
struct stat stb;
if (mf->mf_fo->opt_sublink)
cp = mf->mf_fo->opt_sublink;
else
cp = mf->mf_fo->opt_fs;
/*
* If this host is not the same as $rhost, or if link does not exist,
* call amfs_link_ops.ffserver().
* If link value exists (or same host), then call ops_nfs.ffserver().
* perform find_nfs_srvr(), same as for type:=nfs.
* If link value exists (or same host), then perform
* find_amfs_auto_srvr(), same as for linkx.
*/
if (!STRCEQ(ho, am_get_hostname()) || lstat(cp, &stb) < 0) {
return nfs_ops.ffserver(mf);
return find_nfs_srvr(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);
return find_amfs_auto_srvr(mf);
}
}
+97 -77
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/amfs_nfsx.c
* $Id: amfs_nfsx.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -66,13 +67,13 @@ struct amfs_nfsx {
int nx_c; /* Number of elements in nx_v */
amfs_nfsx_mnt *nx_v; /* Underlying mounts */
amfs_nfsx_mnt *nx_try;
am_node *nx_mp;
};
/* forward definitions */
static char *amfs_nfsx_match(am_opts *fo);
static int amfs_nfsx_mount(am_node *am, mntfs *mf);
static int amfs_nfsx_umount(am_node *am, mntfs *mf);
static int amfs_nfsx_fmount (mntfs *);
static int amfs_nfsx_fmount(mntfs *mf);
static int amfs_nfsx_fumount(mntfs *mf);
static int amfs_nfsx_init(mntfs *mf);
/*
@@ -83,20 +84,17 @@ 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_auto_fmount,
amfs_nfsx_fmount,
amfs_auto_fumount,
amfs_nfsx_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* amfs_nfsx_readlink */
0, /* amfs_nfsx_mounted */
0, /* amfs_nfsx_umounted */
find_nfs_srvr, /* XXX */
0, /* amfs_nfsx_get_wchan */
/* FS_UBACKGROUND| */ FS_AMQINFO, /* nfs_fs_flags */
#ifdef HAVE_FS_AUTOFS
AUTOFS_NFSX_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
/* FS_UBACKGROUND| */ FS_AMQINFO
};
@@ -120,7 +118,7 @@ amfs_nfsx_match(am_opts *fo)
/* set default sublink */
if (fo->opt_sublink == 0) {
ptr = strchr(fo->opt_rfs, ',');
if (ptr && ptr > (fo->opt_rfs + 1))
if (ptr && ptr != (fo->opt_rfs + 1))
fo->opt_sublink = strnsave(fo->opt_rfs + 1, ptr - fo->opt_rfs - 1);
}
@@ -150,15 +148,17 @@ amfs_nfsx_match(am_opts *fo)
* Determine magic cookie to put in mtab
*/
xmtab = str3cat((char *) 0, fo->opt_rhost, ":", fo->opt_rfs);
#ifdef DEBUG
dlog("NFSX: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
fo->opt_rhost, fo->opt_rfs, fo->opt_fs);
#endif /* DEBUG */
return xmtab;
}
static void
amfs_nfsx_prfree(opaque_t vp)
amfs_nfsx_prfree(voidp vp)
{
struct amfs_nfsx *nx = (struct amfs_nfsx *) vp;
int i;
@@ -201,7 +201,7 @@ amfs_nfsx_init(mntfs *mf)
error = EINVAL;
goto errexit;
}
pref = host + 1;
pref = host +1;
host = info;
/*
@@ -212,16 +212,14 @@ amfs_nfsx_init(mntfs *mf)
/*
* Count array size
*/
for (i = 0; ivec[i]; i++)
/* nothing */;
for (i = 0; ivec[i]; i++) ;
nx = ALLOC(struct amfs_nfsx);
mf->mf_private = (opaque_t) nx;
mf->mf_private = (voidp) nx;
mf->mf_prfree = amfs_nfsx_prfree;
nx->nx_c = i - 1; /* i-1 because we don't want the prefix */
nx->nx_v = (amfs_nfsx_mnt *) xmalloc(nx->nx_c * sizeof(amfs_nfsx_mnt));
nx->nx_mp = 0;
{
char *mp = 0;
char *xinfo = 0;
@@ -245,11 +243,11 @@ amfs_nfsx_init(mntfs *mf)
normalize_slash(xinfo);
if (pref[1] != '\0')
deslashify(xinfo);
#ifdef DEBUG
dlog("amfs_nfsx: init mount for %s on %s", xinfo, mp);
#endif /* DEBUG */
nx->nx_v[i].n_error = -1;
nx->nx_v[i].n_mnt = find_mntfs(&nfs_ops, mf->mf_fo, mp, xinfo, "", mf->mf_mopts, mf->mf_remopts);
/* propagate the on_autofs flag */
nx->nx_v[i].n_mnt->mf_flags |= mf->mf_flags & MFF_ON_AUTOFS;
}
if (rfs)
XFREE(rfs);
@@ -276,9 +274,7 @@ amfs_nfsx_init(mntfs *mf)
for (i = 0; i < nx->nx_c; i++) {
amfs_nfsx_mnt *n = &nx->nx_v[i];
mntfs *m = n->n_mnt;
int error = 0;
if (m->mf_ops->fs_init && !(mf->mf_flags & MFF_RESTART))
error = m->mf_ops->fs_init(m);
int error = (*m->mf_ops->fs_init) (m);
/*
* if you just "return error" here, you will have made a failure
* in any submounts to fail the whole group. There was old unused code
@@ -291,7 +287,7 @@ amfs_nfsx_init(mntfs *mf)
glob_error = -1;
if (!asked_for_wakeup) {
asked_for_wakeup = 1;
sched_task(wakeup_task, (opaque_t) mf, get_mntfs_wchan(m));
sched_task(wakeup_task, (voidp) mf, (voidp) m);
}
}
}
@@ -301,11 +297,10 @@ amfs_nfsx_init(mntfs *mf)
static void
amfs_nfsx_cont(int rc, int term, opaque_t arg)
amfs_nfsx_cont(int rc, int term, voidp closure)
{
mntfs *mf = (mntfs *) arg;
mntfs *mf = (mntfs *) closure;
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);
@@ -314,7 +309,7 @@ amfs_nfsx_cont(int rc, int term, opaque_t arg)
/*
* Wakeup anything waiting for this mount
*/
wakeup(get_mntfs_wchan(n->n_mnt));
wakeup((voidp) n->n_mnt);
if (rc || term) {
if (term) {
@@ -339,41 +334,52 @@ amfs_nfsx_cont(int rc, int term, opaque_t arg)
/*
* The mount worked.
*/
mf_mounted(n->n_mnt, FALSE); /* FALSE => don't free the n_mnt->am_opts */
mf_mounted(n->n_mnt);
n->n_error = 0;
}
/*
* Do the remaining bits
*/
if (amfs_nfsx_mount(mp, mf) >= 0)
wakeup(get_mntfs_wchan(mf));
if (amfs_nfsx_fmount(mf) >= 0) {
wakeup((voidp) mf);
mf->mf_flags &= ~MFF_MOUNTING;
mf_mounted(mf);
}
}
static int
try_amfs_nfsx_mount(opaque_t mv)
try_amfs_nfsx_mount(voidp 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);
mf->mf_flags |= MFF_MOUNTING;
error = (*mf->mf_ops->fmount_fs) (mf);
mf->mf_flags &= ~MFF_MOUNTING;
return error;
}
static int
amfs_nfsx_remount(am_node *am, mntfs *mf, int fg)
amfs_nfsx_remount(mntfs *mf, int fg)
{
struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private;
amfs_nfsx_mnt *n;
int glob_error = -1;
/* Save the am_node pointer for later use */
nx->nx_mp = am;
for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) {
mntfs *m = n->n_mnt;
if (n->n_error < 0) {
if (!(m->mf_flags & MFF_MKMNT) && m->mf_ops->fs_flags & FS_MKMNT) {
int error = mkdirs(m->mf_mount, 0555);
if (!error)
m->mf_flags |= MFF_MKMNT;
}
}
}
/*
* Iterate through the mntfs's and mount each filesystem
@@ -381,38 +387,40 @@ amfs_nfsx_remount(am_node *am, mntfs *mf, int fg)
*/
for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) {
mntfs *m = n->n_mnt;
if (m->mf_flags & MFF_MOUNTING)
break;
if (m->mf_flags & MFF_MOUNTED) {
mf_mounted(m, FALSE); /* FALSE => don't free the m->am_opts */
n->n_error = glob_error = 0;
continue;
}
if (n->n_error < 0) {
/* 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;
/*
* Check fmount entry pt. exists
* and then mount...
*/
if (!m->mf_ops->fmount_fs) {
n->n_error = EINVAL;
} else {
dlog("foreground mount of \"%s\" ...", mf->mf_info);
n->n_error = m->mf_ops->mount_fs(am, m);
#ifdef DEBUG
dlog("calling underlying fmount on %s", m->mf_mount);
#endif /* DEBUG */
if (!fg && foreground && (m->mf_ops->fs_flags & FS_MBACKGROUND)) {
m->mf_flags |= MFF_MOUNTING; /* XXX */
#ifdef DEBUG
dlog("backgrounding mount of \"%s\"", m->mf_info);
#endif /* DEBUG */
nx->nx_try = n;
run_task(try_amfs_nfsx_mount, (voidp) m, amfs_nfsx_cont, (voidp) mf);
n->n_error = -1;
return -1;
} else {
#ifdef DEBUG
dlog("foreground mount of \"%s\" ...", mf->mf_info);
#endif /* DEBUG */
n->n_error = (*m->mf_ops->fmount_fs) (m);
}
}
if (n->n_error > 0)
dlog("underlying fmount of %s failed: %s", m->mf_mount, strerror(n->n_error));
#ifdef DEBUG
if (n->n_error > 0) {
errno = n->n_error; /* XXX */
dlog("underlying fmount of %s failed: %m", m->mf_mount);
}
#endif /* DEBUG */
if (n->n_error == 0) {
glob_error = 0;
@@ -427,9 +435,9 @@ amfs_nfsx_remount(am_node *am, mntfs *mf, int fg)
static int
amfs_nfsx_mount(am_node *am, mntfs *mf)
amfs_nfsx_fmount(mntfs *mf)
{
return amfs_nfsx_remount(am, mf, FALSE);
return amfs_nfsx_remount(mf, FALSE);
}
@@ -439,7 +447,7 @@ amfs_nfsx_mount(am_node *am, mntfs *mf)
* and so may hang under extremely rare conditions.
*/
static int
amfs_nfsx_umount(am_node *am, mntfs *mf)
amfs_nfsx_fumount(mntfs *mf)
{
struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private;
amfs_nfsx_mnt *n;
@@ -461,8 +469,10 @@ amfs_nfsx_umount(am_node *am, mntfs *mf)
* which had been successfully unmounted.
*/
if (n->n_error == 0) {
#ifdef DEBUG
dlog("calling underlying fumount on %s", m->mf_mount);
n->n_error = m->mf_ops->umount_fs(am, m);
#endif /* DEBUG */
n->n_error = (*m->mf_ops->fumount_fs) (m);
if (n->n_error) {
glob_error = n->n_error;
n->n_error = 0;
@@ -480,7 +490,7 @@ amfs_nfsx_umount(am_node *am, mntfs *mf)
* whole lot...
*/
if (glob_error) {
glob_error = amfs_nfsx_remount(am, mf, TRUE);
glob_error = amfs_nfsx_remount(mf, TRUE);
if (glob_error) {
errno = glob_error; /* XXX */
plog(XLOG_USER, "amfs_nfsx: remount of %s failed: %m", mf->mf_mount);
@@ -492,12 +502,22 @@ amfs_nfsx_umount(am_node *am, mntfs *mf)
*/
for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) {
mntfs *m = n->n_mnt;
am_node am;
/*
* XXX: all the umounted handler needs is a
* mntfs pointer, so pass an am_node with the right
* pointer in it.
*/
memset((voidp) &am, 0, sizeof(am));
am.am_mnt = m;
#ifdef DEBUG
dlog("calling underlying umounted on %s", m->mf_mount);
if (m->mf_ops->umounted)
m->mf_ops->umounted(m);
#endif /* DEBUG */
(*m->mf_ops->umounted) (&am);
if (n->n_error < 0) {
if (m->mf_fsflags & FS_MKMNT) {
if (m->mf_ops->fs_flags & FS_MKMNT) {
(void) rmdirs(m->mf_mount);
m->mf_flags &= ~MFF_MKMNT;
}
+26 -38
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/amfs_program.c
* $Id: amfs_program.c,v 1.6.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -53,8 +54,8 @@
/* 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_fmount(mntfs *mf);
static int amfs_program_fumount(mntfs *mf);
static int amfs_program_init(mntfs *mf);
/*
@@ -65,20 +66,17 @@ 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_auto_fmount,
amfs_program_fmount,
amfs_auto_fumount,
amfs_program_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* amfs_program_readlink */
0, /* amfs_program_mounted */
0, /* amfs_program_umounted */
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 */
find_amfs_auto_srvr,
FS_BACKGROUND | FS_AMQINFO
};
@@ -90,19 +88,10 @@ 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");
if (!fo->opt_mount || !fo->opt_unmount) {
plog(XLOG_ERROR, "program: both mount and unmount must be specified");
return 0;
}
if (!fo->opt_mount) {
plog(XLOG_ERROR, "program: must specify mount command");
return 0;
}
if (!fo->opt_unmount && !fo->opt_umount) {
fo->opt_unmount = str3cat(NULL, UNMOUNT_PROGRAM, " umount ", fo->opt_fs);
plog(XLOG_INFO, "program: un/umount not specified; using default \"%s\"",
fo->opt_unmount);
}
prog = strchr(fo->opt_mount, ' ');
return strdup(prog ? prog + 1 : fo->opt_mount);
@@ -112,16 +101,13 @@ amfs_program_match(am_opts *fo)
static int
amfs_program_init(mntfs *mf)
{
/* check if already saved value */
if (mf->mf_private != NULL)
return 0;
/* save unmount (or umount) command */
if (mf->mf_fo->opt_unmount != NULL)
mf->mf_private = (opaque_t) strdup(mf->mf_fo->opt_unmount);
else
mf->mf_private = (opaque_t) strdup(mf->mf_fo->opt_umount);
mf->mf_prfree = (void (*)(opaque_t)) free;
/*
* Save unmount command
*/
if (mf->mf_refc == 1) {
mf->mf_private = (voidp) strdup(mf->mf_fo->opt_unmount);
mf->mf_prfree = (void (*)(voidp)) free;
}
return 0;
}
@@ -156,7 +142,8 @@ amfs_program_exec(char *info)
/*
* Try the exec
*/
if (amuDebug(D_FULL)) {
#ifdef DEBUG
amuDebug(D_FULL) {
char **cp = xivec;
plog(XLOG_DEBUG, "executing (un)mount command...");
while (*cp) {
@@ -164,6 +151,7 @@ amfs_program_exec(char *info)
cp++;
}
}
#endif /* DEBUG */
if (xivec[0] == 0 || xivec[1] == 0) {
errno = EINVAL;
@@ -192,14 +180,14 @@ amfs_program_exec(char *info)
static int
amfs_program_mount(am_node *am, mntfs *mf)
amfs_program_fmount(mntfs *mf)
{
return amfs_program_exec(mf->mf_fo->opt_mount);
}
static int
amfs_program_umount(am_node *am, mntfs *mf)
amfs_program_fumount(mntfs *mf)
{
return amfs_program_exec((char *) mf->mf_private);
}
+15 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/amfs_root.c
* $Id: amfs_root.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -54,7 +55,7 @@
/****************************************************************************
*** FORWARD DEFINITIONS ***
****************************************************************************/
static int amfs_root_mount(am_node *mp, mntfs *mf);
static int amfs_root_mount(am_node *mp);
/****************************************************************************
*** OPS STRUCTURES ***
@@ -65,19 +66,16 @@ am_ops amfs_root_ops =
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_auto_umount,
0,
amfs_auto_lookuppn,
amfs_auto_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 */
find_amfs_auto_srvr,
FS_NOTIMEOUT | FS_AMQINFO | FS_DIRECTORY
};
@@ -89,10 +87,12 @@ am_ops amfs_root_ops =
* Mount the root...
*/
static int
amfs_root_mount(am_node *mp, mntfs *mf)
amfs_root_mount(am_node *mp)
{
mntfs *mf = mp->am_mnt;
mf->mf_mount = strealloc(mf->mf_mount, pid_fsname);
mf->mf_private = (opaque_t) mapc_find(mf->mf_info, "", NULL);
mf->mf_private = (voidp) mapc_find(mf->mf_info, "", NULL);
mf->mf_prfree = mapc_free;
return 0;
+207 -166
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/amfs_toplvl.c
* $Id: amfs_toplvl.c,v 1.7.2.5 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -54,7 +55,7 @@
/****************************************************************************
*** FORWARD DEFINITIONS ***
****************************************************************************/
static int amfs_toplvl_init(mntfs *mf);
/****************************************************************************
*** OPS STRUCTURES ***
@@ -62,23 +63,19 @@ static int amfs_toplvl_init(mntfs *mf);
am_ops amfs_toplvl_ops =
{
"toplvl",
amfs_generic_match,
amfs_toplvl_init, /* amfs_toplvl_init */
amfs_auto_match,
0, /* amfs_auto_init */
amfs_toplvl_mount,
0,
amfs_toplvl_umount,
amfs_generic_lookup_child,
amfs_generic_mount_child,
amfs_generic_readdir,
0,
amfs_auto_lookuppn,
amfs_auto_readdir, /* browsable version of readdir() */
0, /* amfs_toplvl_readlink */
amfs_generic_mounted,
amfs_toplvl_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 */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO | FS_DIRECTORY
};
@@ -86,79 +83,166 @@ am_ops amfs_toplvl_ops =
*** FUNCTIONS ***
****************************************************************************/
static void
set_auto_attrcache_timeout(char *preopts, char *opts, size_t l)
{
#ifdef MNTTAB_OPT_NOAC
/*
* Don't cache attributes - they are changing under the kernel's feet.
* For example, IRIX5.2 will dispense with nfs lookup calls and hand stale
* filehandles to getattr unless we disable attribute caching on the
* automount points.
*/
if (gopt.auto_attrcache == 0) {
xsnprintf(preopts, l, ",%s", MNTTAB_OPT_NOAC);
xstrlcat(opts, preopts, l);
}
#endif /* MNTTAB_OPT_NOAC */
/*
* XXX: note that setting these to 0 in the past resulted in an error on
* some systems, which is why it's better to use "noac" if possible. For
* now, we're setting everything possible, but if this will cause trouble,
* then we'll have to condition the remainder of this on OPT_NOAC.
*/
#ifdef MNTTAB_OPT_ACTIMEO
xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTIMEO, gopt.auto_attrcache);
xstrlcat(opts, preopts, l);
#else /* MNTTAB_OPT_ACTIMEO */
# ifdef MNTTAB_OPT_ACDIRMIN
xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTDIRMIN, gopt.auto_attrcache);
xstrlcat(opts, preopts, l);
# endif /* MNTTAB_OPT_ACDIRMIN */
# ifdef MNTTAB_OPT_ACDIRMAX
xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTDIRMAX, gopt.auto_attrcache);
xstrlcat(opts, preopts, l);
# endif /* MNTTAB_OPT_ACDIRMAX */
# ifdef MNTTAB_OPT_ACREGMIN
xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTREGMIN, gopt.auto_attrcache);
xstrlcat(opts, preopts, l);
# endif /* MNTTAB_OPT_ACREGMIN */
# ifdef MNTTAB_OPT_ACREGMAX
xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTREGMAX, gopt.auto_attrcache);
xstrlcat(opts, preopts, l);
# endif /* MNTTAB_OPT_ACREGMAX */
#endif /* MNTTAB_OPT_ACTIMEO */
}
/*
* 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).
* Mount an automounter directory.
* The automounter is connected into the system
* as a user-level NFS server. mount_amfs_toplvl constructs
* the necessary NFS parameters to be given to the
* kernel so that it will talk back to us.
*
* 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!
* NOTE: automounter mounts in themselves are using NFS Version 2.
*/
static int
amfs_toplvl_init(mntfs *mf)
mount_amfs_toplvl(char *dir, char *opts)
{
int error = 0;
char fs_hostname[MAXHOSTNAMELEN + MAXPATHLEN + 1];
int retry, error, genflags;
mntent_t mnt;
nfs_args_t nfs_args;
am_nfs_fh *fhp;
am_nfs_handle_t anh;
MTYPE_TYPE type = MOUNT_TYPE_NFS;
#ifndef HAVE_TRANSPORT_TYPE_TLI
u_short port;
struct sockaddr_in sin;
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
#if defined(MNT2_GEN_OPT_FORCE) || defined(MNT2_GEN_OPT_DETACH)
if (gopt.flags & CFM_FORCED_UNMOUNTS) {
plog(XLOG_INFO, "amfs_toplvl_init: trying forced/lazy unmount of %s",
mf->mf_mount);
error = umount2_fs(mf->mf_mount, AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH);
if (error)
plog(XLOG_INFO, "amfs_toplvl_init: forced/lazy unmount failed: %m");
else
dlog("amfs_toplvl_init: forced/lazy unmount succeeded");
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
mnt.mnt_fsname = pid_fsname;
mnt.mnt_opts = opts;
/*
* Make sure that amd's top-level NFS mounts are hidden by default
* from df.
* If they don't appear to support the either the "ignore" mnttab
* option entry, or the "auto" one, set the mount type to "nfs".
*/
mnt.mnt_type = HIDE_MOUNT_TYPE;
retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
if (retry <= 0)
retry = 2; /* XXX */
/*
* SET MOUNT ARGS
*/
/*
* get fhandle of remote path for automount point
*/
fhp = root_fh(dir);
if (!fhp) {
plog(XLOG_FATAL, "Can't find root file handle for %s", dir);
return EINVAL;
}
#endif /* MNT2_GEN_OPT_FORCE || MNT2_GEN_OPT_DETACH */
#ifndef HAVE_TRANSPORT_TYPE_TLI
/*
* Create sockaddr to point to the local machine. 127.0.0.1
* is not used since that will not work in HP-UX clusters and
* this is no more expensive.
*/
memset((voidp) &sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr = myipaddr;
port = hasmntval(&mnt, MNTTAB_OPT_PORT);
if (port) {
sin.sin_port = htons(port);
} else {
plog(XLOG_ERROR, "no port number specified for %s", dir);
return EINVAL;
}
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/*
* Make a ``hostname'' string for the kernel
*/
sprintf(fs_hostname, "pid%ld@%s:%s",
(long) (foreground ? am_mypid : getppid()),
am_get_hostname(),
dir);
/*
* Most kernels have a name length restriction (64 bytes)...
*/
if (strlen(fs_hostname) >= MAXHOSTNAMELEN)
strcpy(fs_hostname + MAXHOSTNAMELEN - 3, "..");
#ifdef HOSTNAMESZ
/*
* ... and some of these restrictions are 32 bytes (HOSTNAMESZ)
* If you need to get the definition for HOSTNAMESZ found, you may
* add the proper header file to the conf/nfs_prot/nfs_prot_*.h file.
*/
if (strlen(fs_hostname) >= HOSTNAMESZ)
strcpy(fs_hostname + HOSTNAMESZ - 3, "..");
#endif /* HOSTNAMESZ */
/*
* Finally we can compute the mount genflags set above,
* and add any automounter specific flags.
*/
genflags = compute_mount_flags(&mnt);
genflags |= compute_automounter_mount_flags(&mnt);
/* setup the many fields and flags within nfs_args */
memmove(&anh.v2.fhs_fh, fhp, sizeof(*fhp));
#ifdef HAVE_TRANSPORT_TYPE_TLI
compute_nfs_args(&nfs_args,
&mnt,
genflags,
nfsncp,
NULL, /* remote host IP addr is set below */
NFS_VERSION, /* version 2 */
"udp",
&anh,
fs_hostname,
pid_fsname);
/*
* IMPORTANT: set the correct IP address AFTERWARDS. It cannot
* be done using the normal mechanism of compute_nfs_args(), because
* that one will allocate a new address and use NFS_SA_DREF() to copy
* parts to it, while assuming that the ip_addr passed is always
* a "struct sockaddr_in". That assumption is incorrect on TLI systems,
* because they define a special macro HOST_SELF which is DIFFERENT
* than localhost (127.0.0.1)!
*/
nfs_args.addr = &nfsxprt->xp_ltaddr;
#else /* not HAVE_TRANSPORT_TYPE_TLI */
compute_nfs_args(&nfs_args,
&mnt,
genflags,
&sin,
NFS_VERSION, /* version 2 */
"udp",
&anh,
fs_hostname,
pid_fsname);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/*************************************************************************
* NOTE: while compute_nfs_args() works ok for regular NFS mounts *
* the toplvl one is not, and so some options must be corrected by hand *
* more carefully, *after* compute_nfs_args() runs. *
*************************************************************************/
compute_automounter_nfs_args(&nfs_args, &mnt);
/* This is it! Here we try to mount amd on its mount points */
#ifdef DEBUG
amuDebug(D_TRACE) {
print_nfs_args(&nfs_args, 0);
plog(XLOG_DEBUG, "Generic mount flags 0x%x", genflags);
}
#endif /* DEBUG */
error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type,
0, NULL, mnttab_file_name);
#ifdef HAVE_TRANSPORT_TYPE_TLI
free_knetconfig(nfs_args.knconf);
/*
* local automounter mounts do not allocate a special address, so
* no need to XFREE(nfs_args.addr) under TLI.
*/
#endif /* HAVE_TRANSPORT_TYPE_TLI */
return error;
}
@@ -167,11 +251,13 @@ amfs_toplvl_init(mntfs *mf)
* Mount the top-level
*/
int
amfs_toplvl_mount(am_node *mp, mntfs *mf)
amfs_toplvl_mount(am_node *mp)
{
mntfs *mf = mp->am_mnt;
struct stat stb;
char opts[SIZEOF_OPTS], preopts[SIZEOF_OPTS], toplvl_opts[40];
char opts[256], preopts[256];
int error;
char *mnttype;
/*
* Mounting the automounter.
@@ -185,6 +271,16 @@ amfs_toplvl_mount(am_node *mp, mntfs *mf)
plog(XLOG_WARNING, "%s is not a directory", mp->am_path);
return ENOTDIR;
}
if (mf->mf_ops == &amfs_toplvl_ops)
mnttype = "indirect";
else if (mf->mf_ops == &amfs_direct_ops)
mnttype = "direct";
#ifdef HAVE_AMU_FS_UNION
else if (mf->mf_ops == &amfs_union_ops)
mnttype = "union";
#endif /* HAVE_AMU_FS_UNION */
else
mnttype = "auto";
/*
* Construct some mount options:
@@ -192,71 +288,49 @@ amfs_toplvl_mount(am_node *mp, mntfs *mf)
* 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';
preopts[0] = '\0';
#ifdef MNTTAB_OPT_INTR
xstrlcat(preopts, MNTTAB_OPT_INTR, sizeof(preopts));
xstrlcat(preopts, ",", sizeof(preopts));
strcat(preopts, MNTTAB_OPT_INTR);
strcat(preopts, ",");
#endif /* MNTTAB_OPT_INTR */
#ifdef MNTTAB_OPT_IGNORE
xstrlcat(preopts, MNTTAB_OPT_IGNORE, sizeof(preopts));
xstrlcat(preopts, ",", sizeof(preopts));
strcat(preopts, MNTTAB_OPT_IGNORE);
strcat(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_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));
}
sprintf(opts, "%s%s,%s=%d,%s=%d,%s=%d,%s,map=%s",
preopts,
MNTTAB_OPT_RW,
MNTTAB_OPT_PORT, nfs_port,
MNTTAB_OPT_TIMEO, gopt.amfs_auto_timeo,
MNTTAB_OPT_RETRANS, gopt.amfs_auto_retrans,
mnttype, mf->mf_info);
/* now do the mount */
error = amfs_mount(mp, mf, opts);
error = mount_amfs_toplvl(mf->mf_mount, opts);
if (error) {
errno = error;
plog(XLOG_FATAL, "amfs_toplvl_mount: amfs_mount failed: %m");
plog(XLOG_FATAL, "amfs_toplvl_mount: mount_amfs_toplvl failed: %m");
return error;
}
return 0;
}
void
amfs_toplvl_mounted(mntfs *mf)
{
amfs_auto_mkcacheref(mf);
}
/*
* Unmount a top-level automount node
*/
int
amfs_toplvl_umount(am_node *mp, mntfs *mf)
amfs_toplvl_umount(am_node *mp)
{
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? */
struct stat stb;
again:
/*
@@ -271,48 +345,15 @@ again:
* actually fixed the problem - so simulate an ls -ld here.
*/
if (lstat(mp->am_path, &stb) < 0) {
error = errno;
#ifdef DEBUG
dlog("lstat(%s): %m", mp->am_path);
goto out;
#endif /* DEBUG */
}
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);
error = UMOUNT_FS(mp->am_path, mnttab_file_name);
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;
}
}
sleep(1); /* XXX */
goto again;
}
out:
return error;
}
+21 -29
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/amfs_union.c
* $Id: amfs_union.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -54,7 +55,6 @@
/****************************************************************************
*** FORWARD DEFINITIONS ***
****************************************************************************/
static int create_amfs_union_node(char *dir, opaque_t arg);
static void amfs_union_mounted(mntfs *mf);
@@ -64,22 +64,19 @@ static void amfs_union_mounted(mntfs *mf);
am_ops amfs_union_ops =
{
"union",
amfs_generic_match,
0, /* amfs_union_init */
amfs_auto_match,
0, /* amfs_auto_init */
amfs_toplvl_mount,
0,
amfs_toplvl_umount,
amfs_generic_lookup_child,
amfs_generic_mount_child,
amfs_generic_readdir,
0, /* amfs_union_readlink */
0,
amfs_auto_lookuppn,
amfs_auto_readdir,
0, /* amfs_toplvl_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 */
0, /* amfs_toplvl_umounted */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO | FS_DIRECTORY
};
@@ -88,14 +85,11 @@ am_ops amfs_union_ops =
* XXX: this function may not be used anywhere...
*/
static int
create_amfs_union_node(char *dir, opaque_t arg)
create_amfs_union_node(char *dir, voidp 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)
am = amfs_generic_mount_child(am, &error);
(void) amfs_toplvl_ops.lookuppn(arg, dir, &error, VLOOK_CREATE);
if (error > 0) {
errno = error; /* XXX */
plog(XLOG_ERROR, "unionfs: could not mount %s: %m", dir);
@@ -109,22 +103,20 @@ create_amfs_union_node(char *dir, opaque_t arg)
static void
amfs_union_mounted(mntfs *mf)
{
int index;
am_node *mp;
int i;
amfs_mkcacheref(mf);
amfs_auto_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_mnt == mf) {
for (i = 0; i <= last_used_map; i++) {
am_node *mp = exported_ap[i];
if (mp && mp->am_mnt == mf) {
/* return value from create_amfs_union_node is ignored by mapc_keyiter */
(void) mapc_keyiter((mnt_map *) mp->am_mnt->mf_private,
create_amfs_union_node,
(void (*)(char *, voidp)) create_amfs_union_node,
mp);
break;
}
+32 -92
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/amq_subr.c
* $Id: amq_subr.c,v 1.6.2.6 2004/01/19 00:25:55 ezk Exp $
* $FreeBSD$
*
*/
/*
@@ -110,10 +112,8 @@ 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_val = (amq_mount_tree_p *) &exported_ap[0];
aml.amq_mount_tree_list_len = 1; /* XXX */
return &aml;
@@ -131,14 +131,16 @@ amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp)
switch (opt->as_opt) {
case AMOPT_DEBUG:
#ifdef DEBUG
if (debug_option(opt->as_str))
#endif /* DEBUG */
rc = EINVAL;
break;
case AMOPT_LOGFILE:
if (gopt.logfile && opt->as_str
&& STREQ(gopt.logfile, opt->as_str)) {
if (switch_to_logfile(opt->as_str, orig_umask, 0))
if (switch_to_logfile(opt->as_str, orig_umask))
rc = EINVAL;
} else {
rc = EACCES;
@@ -154,8 +156,8 @@ amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp)
if (amd_state == Run) {
plog(XLOG_INFO, "amq says flush cache");
do_mapc_reload = 0;
flush_nfs_fhandle_cache((fserver *) NULL);
flush_srvr_nfs_cache((fserver *) NULL);
flush_nfs_fhandle_cache((fserver *) 0);
flush_srvr_nfs_cache();
}
break;
}
@@ -167,7 +169,7 @@ amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp)
amq_mount_info_list *
amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp)
{
return (amq_mount_info_list *) ((void *)&mfhead); /* XXX */
return (amq_mount_info_list *) ((void *)&mfhead); /* XXX */
}
@@ -192,64 +194,6 @@ amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp)
}
/*
* Process PAWD string of remote pawd tool.
*
* We repeat the resolution of the string until the resolved string resolves
* to itself. This ensures that we follow path resolutions through all
* possible Amd mount points until we reach some sort of convergence. To
* prevent possible infinite loops, we break out of this loop if the strings
* do not converge after MAX_PAWD_TRIES times.
*/
amq_string *
amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp)
{
static amq_string res;
#define MAX_PAWD_TRIES 10
int index, len, maxagain = MAX_PAWD_TRIES;
am_node *mp;
char *mountpoint;
char *dir = *(char **) argp;
static char tmp_buf[MAXPATHLEN];
char prev_buf[MAXPATHLEN];
tmp_buf[0] = prev_buf[0] = '\0'; /* default is empty string: no match */
do {
for (mp = get_first_exported_ap(&index);
mp;
mp = get_next_exported_ap(&index)) {
if (STREQ(mp->am_mnt->mf_ops->fs_type, "toplvl"))
continue;
if (STREQ(mp->am_mnt->mf_ops->fs_type, "auto"))
continue;
mountpoint = (mp->am_link ? mp->am_link : mp->am_mnt->mf_mount);
len = strlen(mountpoint);
if (len == 0)
continue;
if (!NSTREQ(mountpoint, dir, len))
continue;
if (dir[len] != '\0' && dir[len] != '/')
continue;
xstrlcpy(tmp_buf, mp->am_path, sizeof(tmp_buf));
xstrlcat(tmp_buf, &dir[len], sizeof(tmp_buf));
break;
} /* end of "for" loop */
/* once tmp_buf and prev_buf are equal, break out of "do" loop */
if (STREQ(tmp_buf, prev_buf))
break;
else
xstrlcpy(prev_buf, tmp_buf, sizeof(prev_buf));
} while (--maxagain);
/* check if we couldn't resolve the string after MAX_PAWD_TRIES times */
if (maxagain <= 0)
plog(XLOG_WARNING, "path \"%s\" did not resolve after %d tries",
tmp_buf, MAX_PAWD_TRIES);
res = tmp_buf;
return &res;
}
/*
* XDR routines.
*/
@@ -258,7 +202,7 @@ amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp)
bool_t
xdr_amq_setopt(XDR *xdrs, amq_setopt *objp)
{
if (!xdr_enum(xdrs, (enum_t *) ((voidp) &objp->as_opt))) {
if (!xdr_enum(xdrs, (enum_t *) & objp->as_opt)) {
return (FALSE);
}
if (!xdr_string(xdrs, &objp->as_str, AMQ_STRLEN)) {
@@ -323,16 +267,10 @@ xdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp)
if (!xdr_amq_mount_tree_node(xdrs, objp)) {
return (FALSE);
}
if (!xdr_pointer(xdrs,
(char **) ((voidp) &mp->am_osib),
sizeof(amq_mount_tree),
(XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
if (!xdr_pointer(xdrs, (char **) &mp->am_osib, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
return (FALSE);
}
if (!xdr_pointer(xdrs,
(char **) ((voidp) &mp->am_child),
sizeof(amq_mount_tree),
(XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
if (!xdr_pointer(xdrs, (char **) &mp->am_child, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
return (FALSE);
}
return (TRUE);
@@ -343,21 +281,15 @@ bool_t
xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp)
{
am_node *mp = (am_node *) objp;
am_node *mnil = NULL;
am_node *mnil = 0;
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)) {
if (!xdr_pointer(xdrs, (char **) ((void *)&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)) {
if (!xdr_pointer(xdrs, (char **) &mp->am_child, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
return (FALSE);
}
return (TRUE);
@@ -401,7 +333,7 @@ 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),
(char **) &objp->amq_mount_tree_list_val,
(u_int *) &objp->amq_mount_tree_list_len,
~0,
sizeof(amq_mount_tree_p),
@@ -423,7 +355,7 @@ xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead)
u_int len = 0;
for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) {
if (!(mf->mf_fsflags & FS_AMQINFO))
if (!(mf->mf_ops->fs_flags & FS_AMQINFO))
continue;
len++;
}
@@ -434,7 +366,7 @@ xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead)
*/
for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) {
int up;
if (!(mf->mf_fsflags & FS_AMQINFO))
if (!(mf->mf_ops->fs_flags & FS_AMQINFO))
continue;
if (!xdr_amq_string(xdrs, &mf->mf_ops->fs_type)) {
@@ -455,12 +387,20 @@ xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead)
if (!xdr_int(xdrs, &mf->mf_refc)) {
return (FALSE);
}
if (FSRV_ERROR(mf->mf_server) || FSRV_ISDOWN(mf->mf_server))
if (mf->mf_server->fs_flags & FSF_ERROR)
up = 0;
else if (FSRV_ISUP(mf->mf_server))
up = 1;
else
up = -1;
switch (mf->mf_server->fs_flags & (FSF_DOWN | FSF_VALID)) {
case FSF_DOWN | FSF_VALID:
up = 0;
break;
case FSF_VALID:
up = 1;
break;
default:
up = -1;
break;
}
if (!xdr_int(xdrs, &up)) {
return (FALSE);
}
+3 -82
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/amq_svc.c
* $Id: amq_svc.c,v 1.4.2.5 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -50,65 +51,6 @@
/* typedefs */
typedef char *(*amqsvcproc_t)(voidp, struct svc_req *);
#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
# ifdef NEED_LIBWRAP_SEVERITY_VARIABLES
/*
* Some systems that define libwrap already define these two variables
* in libwrap, while others don't: so I need to know precisely iff
* to define these two severity variables.
*/
int allow_severity=0, deny_severity=0;
# endif /* NEED_LIBWRAP_SEVERITY_VARIABLES */
/*
* check if remote amq is authorized to access this amd.
* Returns: 1=allowed, 0=denied.
*/
static int
amqsvc_is_client_allowed(const struct sockaddr_in *addr, char *remote)
{
struct hostent *h;
char *name = NULL, **ad;
int ret = 0; /* default is 0==denied */
/* Check IP address */
if (hosts_ctl(AMD_SERVICE_NAME, "", remote, "")) {
ret = 1;
goto out;
}
/* Get address */
if (!(h = gethostbyaddr((const char *)&(addr->sin_addr),
sizeof(addr->sin_addr),
AF_INET)))
goto out;
if (!(name = strdup(h->h_name)))
goto out;
/* Paranoia check */
if (!(h = gethostbyname(name)))
goto out;
for (ad = h->h_addr_list; *ad; ad++)
if (!memcmp(*ad, &(addr->sin_addr), h->h_length))
break;
if (!*ad)
goto out;
if (hosts_ctl(AMD_SERVICE_NAME, "", h->h_name, "")) {
return 1;
goto out;
}
/* Check aliases */
for (ad = h->h_aliases; *ad; ad++)
if (hosts_ctl(AMD_SERVICE_NAME, "", *ad, "")) {
return 1;
goto out;
}
out:
if (name)
XFREE(name);
return ret;
}
#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
void
amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
@@ -122,21 +64,6 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
xdrproc_t xdr_argument, xdr_result;
amqsvcproc_t local;
#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
if (gopt.flags & CFM_USE_TCPWRAPPERS) {
struct sockaddr_in *remote_addr = svc_getcaller(rqstp->rq_xprt);
char *remote_hostname = inet_ntoa(remote_addr->sin_addr);
if (!amqsvc_is_client_allowed(remote_addr, remote_hostname)) {
plog(XLOG_WARNING, "Amd denied remote amq service to %s", remote_hostname);
svcerr_auth(transp, AUTH_FAILED);
return;
} else {
dlog("Amd allowed remote amq service to %s", remote_hostname);
}
}
#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
switch (rqstp->rq_proc) {
case AMQPROC_NULL:
@@ -193,12 +120,6 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
local = (amqsvcproc_t) amqproc_getpid_1_svc;
break;
case AMQPROC_PAWD:
xdr_argument = (xdrproc_t) xdr_amq_string;
xdr_result = (xdrproc_t) xdr_amq_string;
local = (amqsvcproc_t) amqproc_pawd_1_svc;
break;
default:
svcerr_noproc(transp);
return;
+131 -486
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/autil.c
* $Id: autil.c,v 1.4.2.6 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -51,49 +52,100 @@
#include <am_defs.h>
#include <amd.h>
int NumChildren = 0; /* number of children of primary amd */
int NumChild = 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;
int len = strlen(s) + 1;
p = (char *) xrealloc((voidp) p, len);
xstrlcpy(p, s, len);
strcpy(p, s);
#ifdef DEBUG_MEM
# if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY)
malloc_verify();
# endif /* not defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY) */
#endif /* DEBUG_MEM */
return p;
}
char **
strsplit(char *s, int ch, int qc)
{
char **ivec;
int ic = 0;
int done = 0;
ivec = (char **) xmalloc((ic + 1) * sizeof(char *));
while (!done) {
char *v;
/*
* skip to split char
*/
while (*s && (ch == ' ' ? (isascii(*s) && isspace((int)*s)) : *s == ch))
*s++ = '\0';
/*
* End of string?
*/
if (!*s)
break;
/*
* remember start of string
*/
v = s;
/*
* skip to split char
*/
while (*s && !(ch == ' ' ? (isascii(*s) && isspace((int)*s)) : *s == ch)) {
if (*s++ == qc) {
/*
* Skip past string.
*/
s++;
while (*s && *s != qc)
s++;
if (*s == qc)
s++;
}
}
if (!*s)
done = 1;
*s++ = '\0';
/*
* save string in new ivec slot
*/
ivec[ic++] = v;
ivec = (char **) xrealloc((voidp) ivec, (ic + 1) * sizeof(char *));
#ifdef DEBUG
amuDebug(D_STR)
plog(XLOG_DEBUG, "strsplit saved \"%s\"", v);
#endif /* DEBUG */
}
#ifdef DEBUG
amuDebug(D_STR)
plog(XLOG_DEBUG, "strsplit saved a total of %d strings", ic);
#endif /* DEBUG */
ivec[ic] = 0;
return ivec;
}
/*
* Strip off the trailing part of a domain
* to produce a short-form domain relative
@@ -118,8 +170,7 @@ domain_strip(char *otherdom, char *localdom)
/*
* Normalize a host name: replace cnames with real names, and decide if to
* strip domain name or not.
* Normalize a host name
*/
void
host_normalize(char **chp)
@@ -131,18 +182,20 @@ host_normalize(char **chp)
*/
if (gopt.flags & CFM_NORMALIZE_HOSTNAMES) {
struct hostent *hp;
clock_valid = 0;
hp = gethostbyname(*chp);
if (hp && hp->h_addrtype == AF_INET) {
#ifdef DEBUG
dlog("Hostname %s normalized to %s", *chp, hp->h_name);
#endif /* DEBUG */
*chp = strealloc(*chp, (char *) hp->h_name);
}
}
if (gopt.flags & CFM_DOMAIN_STRIP) {
domain_strip(*chp, hostd);
}
domain_strip(*chp, hostd);
}
/*
* Keys are not allowed to contain " ' ! or ; to avoid
* problems with macro expansions.
@@ -173,20 +226,14 @@ forcibly_timeout_mp(am_node *mp)
} else {
plog(XLOG_INFO, "\"%s\" forcibly timed out", mp->am_path);
mp->am_flags &= ~AMF_NOTIMEOUT;
mp->am_ttl = clocktime(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);
mp->am_ttl = clocktime();
reschedule_timeout_mp();
}
}
void
mf_mounted(mntfs *mf, bool_t call_free_opts)
mf_mounted(mntfs *mf)
{
int quoted;
int wasmounted = mf->mf_flags & MFF_MOUNTED;
@@ -203,33 +250,10 @@ mf_mounted(mntfs *mf, bool_t call_free_opts)
/*
* Do mounted callback
*/
if (mf->mf_ops->mounted)
mf->mf_ops->mounted(mf);
/*
* Be careful when calling free_ops and XFREE here. Some pseudo file
* systems like nfsx call this function (mf_mounted), even though it
* would be called by the lower-level amd file system functions. nfsx
* needs to call this function because of the other actions it takes.
* So we pass a boolean from the caller (yes, not so clean workaround)
* to determine if we should free or not. If we're not freeing (often
* because we're called from a callback function), then just to be sure,
* we'll zero out the am_opts structure and set the pointer to NULL.
* The parent mntfs node owns this memory and is going to free it with a
* call to mf_mounted(mntfs,TRUE) (see comment in the am_mounted code).
*/
if (call_free_opts) {
free_opts(mf->mf_fo); /* this free is needed to prevent leaks */
XFREE(mf->mf_fo); /* (also this one) */
} else {
memset(mf->mf_fo, 0, sizeof(am_opts));
mf->mf_fo = NULL;
if (mf->mf_ops->mounted) {
(*mf->mf_ops->mounted) (mf);
}
}
if (mf->mf_flags & MFF_RESTART) {
mf->mf_flags &= ~MFF_RESTART;
dlog("Restarted filesystem %s, flags 0x%x", mf->mf_mount, mf->mf_flags);
mf->mf_fo = 0;
}
/*
@@ -248,61 +272,40 @@ mf_mounted(mntfs *mf, bool_t call_free_opts)
void
am_mounted(am_node *mp)
{
int notimeout = 0; /* assume normal timeouts initially */
mntfs *mf = mp->am_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 */
mf_mounted(mf);
/*
* Patch up path for direct mounts
*/
if (mp->am_parent && mp->am_parent->am_mnt->mf_fsflags & FS_DIRECT)
if (mp->am_parent && mp->am_parent->am_mnt->mf_ops == &amfs_direct_ops)
mp->am_path = str3cat(mp->am_path, mp->am_parent->am_path, "/", ".");
/*
* Check whether this mount should be cached permanently or not,
* and handle user-requested timeouts.
* Check whether this mount should be cached permanently
*/
/* 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) {
if (mf->mf_ops->fs_flags & FS_NOTIMEOUT) {
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 */
if (mf->mf_mopts && hasmntopt(&mnt, "unmount"))
mp->am_flags &= ~AMF_NOTIMEOUT;
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;
} else if (mf->mf_mount[1] == '\0' && mf->mf_mount[0] == '/') {
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);
mntent_t mnt;
if (mf->mf_mopts) {
mnt.mnt_opts = mf->mf_mopts;
if (hasmntopt(&mnt, "nounmount"))
mp->am_flags |= AMF_NOTIMEOUT;
if (hasmntopt(&mnt, "unmount"))
mp->am_flags &= ~AMF_NOTIMEOUT;
if ((mp->am_timeo = hasmntval(&mnt, "utimeout")) == 0)
mp->am_timeo = gopt.am_timeo;
}
}
/*
@@ -310,38 +313,25 @@ am_mounted(am_node *mp)
* compute the length of the returned string.
*/
if (mp->am_fattr.na_type == NFLNK)
mp->am_fattr.na_size = strlen(mp->am_link ? mp->am_link : mf->mf_mount);
mp->am_fattr.na_size = strlen(mp->am_link ? mp->am_link : mp->am_mnt->mf_mount);
/*
* Record mount time, and update am_stats at the same time.
* Record mount time
*/
mp->am_stats.s_mtime = clocktime(&mp->am_fattr.na_mtime);
mp->am_fattr.na_mtime.nt_seconds = mp->am_stats.s_mtime = clocktime();
new_ttl(mp);
/*
* Update mtime of parent node (copying "struct nfstime" in '=' below)
* Update mtime of parent node
*/
if (mp->am_parent && mp->am_parent->am_mnt)
mp->am_parent->am_fattr.na_mtime = mp->am_fattr.na_mtime;
mp->am_parent->am_fattr.na_mtime.nt_seconds = mp->am_stats.s_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
* Now, if we can, do a reply to our NFS 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);
quick_reply(mp, 0);
/*
* Update stats
@@ -350,303 +340,21 @@ am_mounted(am_node *mp)
}
/*
* Replace mount point with a reference to an error filesystem.
* The mount point (struct mntfs) is NOT discarded,
* the caller must do it if it wants to _before_ calling this function.
*/
void
assign_error_mntfs(am_node *mp)
{
int error;
dlog("assign_error_mntfs");
/*
* Save the old error code
*/
error = mp->am_error;
if (error <= 0)
error = mp->am_mnt->mf_error;
/*
* Allocate a new error reference
*/
mp->am_mnt = new_mntfs();
/*
* Put back the error code
*/
mp->am_mnt->mf_error = error;
mp->am_mnt->mf_flags |= MFF_ERROR;
/*
* Zero the error in the mount point
*/
mp->am_error = 0;
}
/*
* Build a new map cache for this node, or re-use
* an existing cache for the same map.
*/
void
amfs_mkcacheref(mntfs *mf)
{
char *cache;
if (mf->mf_fo && mf->mf_fo->opt_cache)
cache = mf->mf_fo->opt_cache;
else
cache = "none";
mf->mf_private = (opaque_t) mapc_find(mf->mf_info,
cache,
(mf->mf_fo ? mf->mf_fo->opt_maptype : NULL));
mf->mf_prfree = mapc_free;
}
/*
* Locate next node in sibling list which is mounted
* and is not an error node.
*/
am_node *
next_nonerror_node(am_node *xp)
{
mntfs *mf;
/*
* Bug report (7/12/89) from Rein Tollevik <rein@ifi.uio.no>
* Fixes a race condition when mounting direct automounts.
* Also fixes a problem when doing a readdir on a directory
* containing hung automounts.
*/
while (xp &&
(!(mf = xp->am_mnt) || /* No mounted filesystem */
mf->mf_error != 0 || /* There was a mntfs error */
xp->am_error != 0 || /* There was a mount error */
!(mf->mf_flags & MFF_MOUNTED) || /* The fs is not mounted */
(mf->mf_server->fs_flags & FSF_DOWN)) /* The fs may be down */
)
xp = xp->am_osib;
return xp;
}
/*
* Mount an automounter directory.
* The automounter is connected into the system
* as a user-level NFS server. amfs_mount constructs
* the necessary NFS parameters to be given to the
* kernel so that it will talk back to us.
*
* NOTE: automounter mounts in themselves are using NFS Version 2 (UDP).
*
* NEW: on certain systems, mounting can be done using the
* kernel-level automount (autofs) support. In that case,
* we don't need NFS at all here.
*/
int
amfs_mount(am_node *mp, mntfs *mf, char *opts)
mount_node(am_node *mp)
{
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? */
mntfs *mf = mp->am_mnt;
int error = 0;
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
mnt.mnt_fsname = pid_fsname;
mnt.mnt_opts = opts;
mf->mf_flags |= MFF_MOUNTING;
error = (*mf->mf_ops->mount_fs) (mp);
#ifdef HAVE_FS_AUTOFS
if (mf->mf_flags & MFF_IS_AUTOFS) {
type = MOUNT_TYPE_AUTOFS;
/*
* Make sure that amd's top-level autofs mounts are hidden by default
* from df.
* XXX: It works ok on Linux, might not work on other systems.
*/
mnt.mnt_type = "autofs";
} else
#endif /* HAVE_FS_AUTOFS */
{
type = MOUNT_TYPE_NFS;
/*
* Make sure that amd's top-level NFS mounts are hidden by default
* from df.
* If they don't appear to support the either the "ignore" mnttab
* option entry, or the "auto" one, set the mount type to "nfs".
*/
mnt.mnt_type = HIDE_MOUNT_TYPE;
}
retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
if (retry <= 0)
retry = 2; /* XXX: default to 2 retries */
/*
* SET MOUNT ARGS
*/
/*
* Make a ``hostname'' string for the kernel
*/
xsnprintf(fs_hostname, sizeof(fs_hostname), "pid%ld@%s:%s",
get_server_pid(), am_get_hostname(), dir);
/*
* Most kernels have a name length restriction (64 bytes)...
*/
if (strlen(fs_hostname) >= MAXHOSTNAMELEN)
xstrlcpy(fs_hostname + MAXHOSTNAMELEN - 3, "..",
sizeof(fs_hostname) - MAXHOSTNAMELEN + 3);
#ifdef HOSTNAMESZ
/*
* ... and some of these restrictions are 32 bytes (HOSTNAMESZ)
* If you need to get the definition for HOSTNAMESZ found, you may
* add the proper header file to the conf/nfs_prot/nfs_prot_*.h file.
*/
if (strlen(fs_hostname) >= HOSTNAMESZ)
xstrlcpy(fs_hostname + HOSTNAMESZ - 3, "..",
sizeof(fs_hostname) - HOSTNAMESZ + 3);
#endif /* HOSTNAMESZ */
/*
* Finally we can compute the mount genflags set above,
* and add any automounter specific flags.
*/
genflags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
if (on_autofs)
genflags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */
genflags |= compute_automounter_mount_flags(&mnt);
again:
if (!(mf->mf_flags & MFF_IS_AUTOFS)) {
nfs_args_t nfs_args;
am_nfs_fh *fhp;
am_nfs_handle_t anh;
#ifndef HAVE_TRANSPORT_TYPE_TLI
u_short port;
struct sockaddr_in sin;
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/*
* get fhandle of remote path for automount point
*/
fhp = get_root_nfs_fh(dir);
if (!fhp) {
plog(XLOG_FATAL, "Can't find root file handle for %s", dir);
return EINVAL;
}
#ifndef HAVE_TRANSPORT_TYPE_TLI
/*
* Create sockaddr to point to the local machine.
*/
memset((voidp) &sin, 0, sizeof(sin));
/* as per POSIX, sin_len need not be set (used internally by kernel) */
sin.sin_family = AF_INET;
sin.sin_addr = myipaddr;
port = hasmntval(&mnt, MNTTAB_OPT_PORT);
if (port) {
sin.sin_port = htons(port);
} else {
plog(XLOG_ERROR, "no port number specified for %s", dir);
return EINVAL;
}
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/* setup the many fields and flags within nfs_args */
memmove(&anh.v2, fhp, sizeof(*fhp));
#ifdef HAVE_TRANSPORT_TYPE_TLI
compute_nfs_args(&nfs_args,
&mnt,
genflags,
nfsncp,
NULL, /* remote host IP addr is set below */
NFS_VERSION, /* version 2 */
"udp",
&anh,
fs_hostname,
pid_fsname);
/*
* IMPORTANT: set the correct IP address AFTERWARDS. It cannot
* be done using the normal mechanism of compute_nfs_args(), because
* that one will allocate a new address and use NFS_SA_DREF() to copy
* parts to it, while assuming that the ip_addr passed is always
* a "struct sockaddr_in". That assumption is incorrect on TLI systems,
* because they define a special macro HOST_SELF which is DIFFERENT
* than localhost (127.0.0.1)!
*/
nfs_args.addr = &nfsxprt->xp_ltaddr;
#else /* not HAVE_TRANSPORT_TYPE_TLI */
compute_nfs_args(&nfs_args,
&mnt,
genflags,
NULL,
&sin,
NFS_VERSION, /* version 2 */
"udp",
&anh,
fs_hostname,
pid_fsname);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/*************************************************************************
* NOTE: while compute_nfs_args() works ok for regular NFS mounts *
* the toplvl one is not quite regular, and so some options must be *
* corrected by hand more carefully, *after* compute_nfs_args() runs. *
*************************************************************************/
compute_automounter_nfs_args(&nfs_args, &mnt);
if (amuDebug(D_TRACE)) {
print_nfs_args(&nfs_args, 0);
plog(XLOG_DEBUG, "Generic mount flags 0x%x", genflags);
}
/* This is it! Here we try to mount amd on its mount points */
error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args,
retry, type, 0, NULL, mnttab_file_name, on_autofs);
#ifdef HAVE_TRANSPORT_TYPE_TLI
free_knetconfig(nfs_args.knconf);
/*
* local automounter mounts do not allocate a special address, so
* no need to XFREE(nfs_args.addr) under TLI.
*/
#endif /* HAVE_TRANSPORT_TYPE_TLI */
#ifdef HAVE_FS_AUTOFS
} else {
/* This is it! Here we try to mount amd on its mount points */
error = mount_fs(&mnt, genflags, (caddr_t) mp->am_autofs_fh,
retry, type, 0, NULL, mnttab_file_name, on_autofs);
#endif /* HAVE_FS_AUTOFS */
}
if (error == 0 || forced_unmount)
return error;
/*
* If user wants forced/lazy unmount semantics, then try it iff the
* current mount failed with EIO or ESTALE.
*/
if (gopt.flags & CFM_FORCED_UNMOUNTS) {
switch (errno) {
case ESTALE:
case EIO:
forced_unmount = errno;
plog(XLOG_WARNING, "Mount %s failed (%m); force unmount.", mp->am_path);
if ((error = UMOUNT_FS(mp->am_path, mnttab_file_name,
AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH)) < 0) {
plog(XLOG_WARNING, "Forced umount %s failed: %m.", mp->am_path);
errno = forced_unmount;
} else
goto again;
default:
break;
}
mf = mp->am_mnt;
if (error >= 0)
mf->mf_flags &= ~MFF_MOUNTING;
if (!error && !(mf->mf_ops->fs_flags & FS_MBACKGROUND)) {
/* ...but see ifs_mount */
am_mounted(mp);
}
return error;
@@ -665,79 +373,15 @@ am_unmounted(am_node *mp)
* 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;
(*mf->mf_ops->umounted) (mp);
/*
* Update mtime of parent node
*/
if (mp->am_parent && mp->am_parent->am_mnt)
clocktime(&mp->am_parent->am_fattr.na_mtime);
mp->am_parent->am_fattr.na_mtime.nt_seconds = clocktime();
if (mp->am_parent && (mp->am_flags & AMF_REMOUNT)) {
char *fname = strdup(mp->am_name);
am_node *mp_parent = mp->am_parent;
mntfs *mf_parent = mp_parent->am_mnt;
int error = 0;
free_map(mp);
plog(XLOG_INFO, "am_unmounted: remounting %s", fname);
mp = mf_parent->mf_ops->lookup_child(mp_parent, fname, &error, VLOOK_CREATE);
if (mp && error < 0)
mp = mf_parent->mf_ops->mount_child(mp, &error);
if (error > 0) {
errno = error;
plog(XLOG_ERROR, "am_unmounted: could not remount %s: %m", fname);
}
XFREE(fname);
} else
/*
* We have a race here.
* If this node has a pending mount and amd is going down (unmounting
* everything in the process), then we could potentially free it here
* while a struct continuation still has a reference to it. So when
* amfs_cont is called, it blows up.
* We avoid the race by refusing to free any nodes that have
* pending mounts (defined as having a non-NULL am_mfarray).
*/
if (!mp->am_mfarray)
free_map(mp);
free_map(mp);
}
@@ -762,7 +406,7 @@ top:
am_set_mypid();
foreground = 0;
} else { /* parent process, has one more child */
NumChildren++;
NumChild++;
}
return pid;
@@ -775,9 +419,10 @@ background(void)
int pid = dofork();
if (pid == 0) {
#ifdef DEBUG
dlog("backgrounded");
#endif /* DEBUG */
foreground = 0;
} else
dlog("forked process %d", pid);
}
return pid;
}
+19 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/clock.c
* $Id: clock.c,v 1.4.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -58,13 +59,14 @@
#include <am_defs.h>
#include <amd.h>
int timeout(u_int secs, void (*fn) (voidp), voidp closure);
void reschedule_timeouts(time_t now, time_t then);
typedef struct callout callout;
struct callout {
callout *c_next; /* List of callouts */
callout_fun *c_fn; /* Function to call */
opaque_t c_arg; /* Argument to pass to call */
void (*c_fn) (voidp); /* Function to call */
voidp c_closure; /* Closure to pass to call */
time_t c_time; /* Time of call */
int c_id; /* Unique identifier */
};
@@ -85,7 +87,7 @@ time_t next_softclock; /* Time of next call to softclock() */
/*
* Global assumption: valid id's are non-zero.
*/
#define CID_ALLOC() (++callout_id)
#define CID_ALLOC(struct ) (++callout_id)
#define CID_UNDEF (0)
@@ -119,22 +121,22 @@ free_callout(callout *cp)
/*
* Schedule a callout.
*
* (*fn)(fn_arg) will be called at clocktime(NULL) + secs
* (*fn)(closure) will be called at clocktime() + secs
*/
int
timeout(u_int secs, callout_fun *fn, opaque_t fn_arg)
timeout(u_int secs, void (*fn) (voidp), voidp closure)
{
callout *cp, *cp2;
time_t t = clocktime(NULL) + secs;
time_t t = clocktime() + secs;
/*
* Allocate and fill in a new callout structure
*/
callout *cpnew = alloc_callout();
cpnew->c_arg = fn_arg;
cpnew->c_closure = closure;
cpnew->c_fn = fn;
cpnew->c_time = t;
cpnew->c_id = CID_ALLOC();
cpnew->c_id = CID_ALLOC(struct );
if (t < next_softclock)
next_softclock = t;
@@ -187,8 +189,10 @@ reschedule_timeouts(time_t now, time_t then)
for (cp = callouts.c_next; cp; cp = cp->c_next) {
if (cp->c_time >= now && cp->c_time <= then) {
plog(XLOG_WARNING, "job %d rescheduled to run immediately", cp->c_id);
#ifdef DEBUG
dlog("rescheduling job %d back %ld seconds",
cp->c_id, (long) (cp->c_time - now));
#endif /* DEBUG */
next_softclock = cp->c_time = now;
}
}
@@ -208,14 +212,14 @@ softclock(void)
if (task_notify_todo)
do_task_notify();
now = clocktime(NULL);
now = clocktime();
/*
* While there are more callouts waiting...
*/
while ((cp = callouts.c_next) && cp->c_time <= now) {
/*
* Extract first from list, save fn & fn_arg and
* Extract first from list, save fn & closure and
* unlink callout from list and free.
* Finally call function.
*
@@ -224,12 +228,12 @@ softclock(void)
* function will call timeout()
* and try to allocate a callout
*/
callout_fun *fn = cp->c_fn;
opaque_t fn_arg = cp->c_arg;
void (*fn) (voidp) = cp->c_fn;
voidp closure = cp->c_closure;
callouts.c_next = cp->c_next;
free_callout(cp);
(*fn) (fn_arg);
(*fn) (closure);
}
} while (task_notify_todo);
+72 -468
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/conf.c
* $Id: conf.c,v 1.7.2.8 2004/01/21 04:04:58 ib42 Exp $
*
*/
@@ -75,18 +76,12 @@ struct _func_map {
* FORWARD DECLARATIONS:
*/
static int gopt_arch(const char *val);
static int gopt_auto_attrcache(const char *val);
static int gopt_auto_dir(const char *val);
static int gopt_autofs_use_lofs(const char *val);
static int gopt_browsable_dirs(const char *val);
static int gopt_cache_duration(const char *val);
static int gopt_cluster(const char *val);
static int gopt_debug_mtab_file(const char *val);
static int gopt_debug_options(const char *val);
static int gopt_dismount_interval(const char *val);
static int gopt_domain_strip(const char *val);
static int gopt_exec_map_timeout(const char *val);
static int gopt_forced_unmounts(const char *val);
static int gopt_full_os(const char *val);
static int gopt_fully_qualified_hosts(const char *val);
static int gopt_hesiod_base(const char *val);
@@ -95,34 +90,21 @@ static int gopt_ldap_base(const char *val);
static int gopt_ldap_cache_maxmem(const char *val);
static int gopt_ldap_cache_seconds(const char *val);
static int gopt_ldap_hostports(const char *val);
static int gopt_ldap_proto_version(const char *val);
static int gopt_local_domain(const char *val);
static int gopt_localhost_address(const char *val);
static int gopt_log_file(const char *val);
static int gopt_log_options(const char *val);
static int gopt_map_defaults(const char *val);
static int gopt_map_options(const char *val);
static int gopt_map_reload_interval(const char *val);
static int gopt_map_type(const char *val);
static int gopt_mount_type(const char *val);
static int gopt_pid_file(const char *val);
static int gopt_portmap_program(const char *val);
static int gopt_preferred_amq_port(const char *val);
static int gopt_nfs_allow_any_interface(const char *val);
static int gopt_nfs_allow_insecure_port(const char *val);
static int gopt_nfs_proto(const char *val);
static int gopt_nfs_retransmit_counter(const char *val);
static int gopt_nfs_retransmit_counter_udp(const char *val);
static int gopt_nfs_retransmit_counter_tcp(const char *val);
static int gopt_nfs_retransmit_counter_toplvl(const char *val);
static int gopt_nfs_retry_interval(const char *val);
static int gopt_nfs_retry_interval_udp(const char *val);
static int gopt_nfs_retry_interval_tcp(const char *val);
static int gopt_nfs_retry_interval_toplvl(const char *val);
static int gopt_nfs_vers(const char *val);
static int gopt_nis_domain(const char *val);
static int gopt_normalize_hostnames(const char *val);
static int gopt_normalize_slashes(const char *val);
static int gopt_os(const char *val);
static int gopt_osver(const char *val);
static int gopt_plock(const char *val);
@@ -132,43 +114,33 @@ static int gopt_restart_mounts(const char *val);
static int gopt_search_path(const char *val);
static int gopt_selectors_in_defaults(const char *val);
static int gopt_show_statfs_entries(const char *val);
static int gopt_truncate_log(const char *val);
static int gopt_unmount_on_exit(const char *val);
static int gopt_use_tcpwrappers(const char *val);
static int gopt_vendor(const char *val);
static int process_global_option(const char *key, const char *val);
static int process_one_regular_map(const cf_map_t *cfm);
static int process_regular_map(cf_map_t *cfm);
static int process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm);
static int ropt_browsable_dirs(const char *val, cf_map_t *cfm);
static int ropt_map_name(const char *val, cf_map_t *cfm);
static int ropt_map_defaults(const char *val, cf_map_t *cfm);
static int ropt_map_options(const char *val, cf_map_t *cfm);
static int ropt_map_type(const char *val, cf_map_t *cfm);
static int ropt_mount_type(const char *val, cf_map_t *cfm);
static int ropt_search_path(const char *val, cf_map_t *cfm);
static int ropt_tag(const char *val, cf_map_t *cfm);
static void init_cf_map(cf_map_t *cfm);
static void reset_cf_map(cf_map_t *cfm);
/*
* STATIC VARIABLES:
*/
static cf_map_t *head_map, *cur_map;
static cf_map_t cur_map;
static struct _func_map glob_functable[] = {
{"arch", gopt_arch},
{"auto_attrcache", gopt_auto_attrcache},
{"auto_dir", gopt_auto_dir},
{"autofs_use_lofs", gopt_autofs_use_lofs},
{"browsable_dirs", gopt_browsable_dirs},
{"cache_duration", gopt_cache_duration},
{"cluster", gopt_cluster},
{"debug_mtab_file", gopt_debug_mtab_file},
{"debug_options", gopt_debug_options},
{"dismount_interval", gopt_dismount_interval},
{"domain_strip", gopt_domain_strip},
{"exec_map_timeout", gopt_exec_map_timeout},
{"forced_unmounts", gopt_forced_unmounts},
{"fully_qualified_hosts", gopt_fully_qualified_hosts},
{"full_os", gopt_full_os},
{"hesiod_base", gopt_hesiod_base},
@@ -177,34 +149,21 @@ static struct _func_map glob_functable[] = {
{"ldap_cache_maxmem", gopt_ldap_cache_maxmem},
{"ldap_cache_seconds", gopt_ldap_cache_seconds},
{"ldap_hostports", gopt_ldap_hostports},
{"ldap_proto_version", gopt_ldap_proto_version},
{"local_domain", gopt_local_domain},
{"localhost_address", gopt_localhost_address},
{"log_file", gopt_log_file},
{"log_options", gopt_log_options},
{"map_defaults", gopt_map_defaults},
{"map_options", gopt_map_options},
{"map_reload_interval", gopt_map_reload_interval},
{"map_type", gopt_map_type},
{"mount_type", gopt_mount_type},
{"pid_file", gopt_pid_file},
{"portmap_program", gopt_portmap_program},
{"preferred_amq_port", gopt_preferred_amq_port},
{"nfs_allow_any_interface", gopt_nfs_allow_any_interface},
{"nfs_allow_insecure_port", gopt_nfs_allow_insecure_port},
{"nfs_proto", gopt_nfs_proto},
{"nfs_retransmit_counter", gopt_nfs_retransmit_counter},
{"nfs_retransmit_counter_udp", gopt_nfs_retransmit_counter_udp},
{"nfs_retransmit_counter_tcp", gopt_nfs_retransmit_counter_tcp},
{"nfs_retransmit_counter_toplvl", gopt_nfs_retransmit_counter_toplvl},
{"nfs_retry_interval", gopt_nfs_retry_interval},
{"nfs_retry_interval_udp", gopt_nfs_retry_interval_udp},
{"nfs_retry_interval_tcp", gopt_nfs_retry_interval_tcp},
{"nfs_retry_interval_toplvl", gopt_nfs_retry_interval_toplvl},
{"nfs_vers", gopt_nfs_vers},
{"nis_domain", gopt_nis_domain},
{"normalize_hostnames", gopt_normalize_hostnames},
{"normalize_slashes", gopt_normalize_slashes},
{"os", gopt_os},
{"osver", gopt_osver},
{"plock", gopt_plock},
@@ -215,43 +174,61 @@ static struct _func_map glob_functable[] = {
{"selectors_on_default", gopt_selectors_in_defaults},
{"selectors_in_defaults", gopt_selectors_in_defaults},
{"show_statfs_entries", gopt_show_statfs_entries},
{"truncate_log", gopt_truncate_log},
{"unmount_on_exit", gopt_unmount_on_exit},
{"use_tcpwrappers", gopt_use_tcpwrappers},
{"vendor", gopt_vendor},
{NULL, NULL}
};
/*
* Initialize a map from [global] defaults.
* Reset a map.
*/
static void
init_cf_map(cf_map_t *cfm)
reset_cf_map(cf_map_t *cfm)
{
if (!cfm)
return;
if (cfm->cfm_dir) {
XFREE(cfm->cfm_dir);
cfm->cfm_dir = NULL;
}
if (cfm->cfm_name) {
XFREE(cfm->cfm_name);
cfm->cfm_name = NULL;
}
if (cfm->cfm_tag) {
XFREE(cfm->cfm_tag);
cfm->cfm_tag = NULL;
}
/*
* Initialize a regular map's flags and other variables from the
* reset/initialize a regular map's flags and other variables from the
* global ones, so that they are applied to all maps. Of course, each map
* can then override the flags individually.
*
* NOTES:
* (1): Will only work for maps that appear after [global].
* (2): I'm assigning pointers directly from the global map.
* (2): Also be careful not to free() a global option.
* (3): I'm doing direct char* pointer comparison, and not strcmp(). This
* is correct!
*/
/* initialize map_type from [global] */
if (cfm->cfm_type && cfm->cfm_type != gopt.map_type)
XFREE(cfm->cfm_type);
cfm->cfm_type = gopt.map_type;
/* initialize map_defaults from [global] */
cfm->cfm_defaults = gopt.map_defaults;
/* initialize map_opts from [global] */
if (cfm->cfm_opts && cfm->cfm_opts != gopt.map_options)
XFREE(cfm->cfm_opts);
cfm->cfm_opts = gopt.map_options;
/* initialize search_path from [global] */
if (cfm->cfm_search_path && cfm->cfm_search_path != gopt.search_path)
XFREE(cfm->cfm_search_path);
cfm->cfm_search_path = gopt.search_path;
/*
@@ -265,7 +242,7 @@ init_cf_map(cf_map_t *cfm)
/*
* Process configuration file options (called from YACC parser).
* Process configuration file options.
* Return 0 if OK, 1 otherwise.
*/
int
@@ -274,67 +251,50 @@ set_conf_kv(const char *section, const char *key, const char *val)
int ret;
#ifdef DEBUG_CONF
fprintf(stderr, "set_conf_kv: section=%s, key=%s, val=%s\n",
fprintf(stderr,"set_conf_kv: section=%s, key=%s, val=%s\n",
section, key, val);
#endif /* DEBUG_CONF */
/*
* If global section, process kv pairs one at a time.
* If global section, process them one at a time.
*/
if (STREQ(section, "global")) {
/*
* Check if a regular map was configured before "global",
* and warn about it.
* and process it as needed.
*/
if (cur_map && cur_map->cfm_dir) {
static short printed_this_error;
if (!printed_this_error) {
fprintf(stderr, "found regular map \"%s\" before global one.\n",
cur_map->cfm_dir);
printed_this_error = 1;
}
if (cur_map.cfm_dir) {
fprintf(stderr,"processing regular map \"%s\" before global one.\n",
section);
ret = process_regular_map(&cur_map); /* will reset map */
if (ret != 0)
return ret;
}
/* process the global option first */
ret = process_global_option(key, val);
/* reset default options for regular maps from just updated globals */
if (ret == 0)
reset_cf_map(&cur_map);
/* return status from the processing of the global option */
return ret;
}
/*
* Otherwise we found a non-global option: store it after some testing.
* otherwise save options and process a single map all at once.
*/
/* initialize (static) global list head and current map pointer */
if (!head_map && !cur_map) {
cur_map = CALLOC(cf_map_t);
if (!cur_map) {
perror("calloc");
exit(1);
}
/* initialize first head map from global defaults */
init_cf_map(cur_map);
head_map = cur_map;
}
/* check if we found a new map, then allocate and initialize it */
if (cur_map->cfm_dir && !STREQ(cur_map->cfm_dir, section)) {
/* allocate new map struct */
cf_map_t *tmp_map = CALLOC(cf_map_t);
if (!tmp_map) {
perror("calloc");
exit(1);
}
/* initialize it from global defaults */
init_cf_map(tmp_map);
/* append it to end of linked list */
cur_map->cfm_next = tmp_map;
cur_map = tmp_map;
/* check if we found a new map, so process one already collected */
if (cur_map.cfm_dir && !STREQ(cur_map.cfm_dir, section)) {
ret = process_regular_map(&cur_map); /* will reset map */
if (ret != 0)
return ret;
}
/* now process a single entry of a regular map */
return process_regular_option(section, key, val, cur_map);
return process_regular_option(section, key, val, &cur_map);
}
@@ -371,18 +331,6 @@ gopt_arch(const char *val)
}
static int
gopt_auto_attrcache(const char *val)
{
gopt.auto_attrcache = atoi(val);
if (gopt.auto_attrcache < 0) {
fprintf(stderr, "conf: bad attrcache value: \"%s\"\n", val);
return 1;
}
return 0;
}
static int
gopt_auto_dir(const char *val)
{
@@ -391,22 +339,6 @@ gopt_auto_dir(const char *val)
}
static int
gopt_autofs_use_lofs(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_AUTOFS_USE_LOFS;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_AUTOFS_USE_LOFS;
return 0;
}
fprintf(stderr, "conf: unknown value to autofs_use_lofs \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_browsable_dirs(const char *val)
{
@@ -444,19 +376,11 @@ gopt_cluster(const char *val)
}
static int
gopt_debug_mtab_file(const char *val)
{
gopt.debug_mtab_file = strdup((char*)val);
return 0;
}
static int
gopt_debug_options(const char *val)
{
#ifdef DEBUG
usage += debug_option((char *)val);
usage += debug_option(strdup((char *)val));
return 0;
#else /* not DEBUG */
fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n",
@@ -476,74 +400,6 @@ gopt_dismount_interval(const char *val)
}
static int
gopt_domain_strip(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_DOMAIN_STRIP;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_DOMAIN_STRIP;
return 0;
}
fprintf(stderr, "conf: unknown value to domain_strip \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_exec_map_timeout(const char *val)
{
gopt.exec_map_timeout = atoi(val);
if (gopt.exec_map_timeout <= 0)
gopt.exec_map_timeout = AMFS_EXEC_MAP_TIMEOUT; /* default exec map timeout */
return 0;
}
static int
gopt_forced_unmounts(const char *val)
{
if (STREQ(val, "yes")) {
#if !defined(MNT2_GEN_OPT_DETACH) && !defined(MNT2_GEN_OPT_FORCE)
fprintf(stderr, "conf: forced_unmounts unsupported on this system.\n");
return 1;
#else /* defined(MNT2_GEN_OPT_DETACH) || defined(MNT2_GEN_OPT_FORCE) */
# ifdef __linux__
/*
* HACK ALERT: Linux has had MNT_FORCE since 2.2, but it hasn't gotten
* stable until 2.4. And it had MNT_DETACH since 2.4, but it hasn't
* gotten stable since 2.6. So alert users if they're trying to use a
* feature that may not work well on their older kernel.
*/
{
struct utsname un;
if (uname(&un) >= 0) {
# ifdef MNT2_GEN_OPT_FORCE
if (strcmp(un.release, "2.4.0") < 0)
fprintf(stderr, "warning: forced-unmounts (MNT_FORCE) may not work well before 2.4.0\n");
# endif /* MNT2_GEN_OPT_FORCE */
# ifdef MNT2_GEN_OPT_DETACH
if (strcmp(un.release, "2.6.0") < 0)
fprintf(stderr, "warning: lazy-unmounts (MNT_DETACH) may not work well before 2.6.0\n");
# endif /* MNT2_GEN_OPT_DETACH */
}
}
# endif /* __linux__ */
gopt.flags |= CFM_FORCED_UNMOUNTS;
return 0;
#endif /* defined(MNT2_GEN_OPT_DETACH) || defined(MNT2_GEN_OPT_FORCE) */
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_FORCED_UNMOUNTS;
return 0;
}
fprintf(stderr, "conf: unknown value to unmount_on_exit \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_full_os(const char *val)
{
@@ -605,14 +461,6 @@ gopt_local_domain(const char *val)
}
static int
gopt_localhost_address(const char *val)
{
gopt.localhost_address = strdup((char *)val);
return 0;
}
static int
gopt_ldap_base(const char *val)
{
@@ -678,44 +526,6 @@ gopt_ldap_hostports(const char *val)
}
static int
gopt_ldap_proto_version(const char *val)
{
#ifdef HAVE_MAP_LDAP
char *end;
gopt.ldap_proto_version = strtol((char *)val, &end, 10);
if (end == val) {
fprintf(stderr, "conf: bad ldap_proto_version option: %s\n",val);
return 1;
}
if (gopt.ldap_proto_version < 0 || gopt.ldap_proto_version > LDAP_VERSION_MAX) {
fprintf(stderr, "conf: bad ldap_proto_version option value: %s\n",val);
return 1;
}
switch (gopt.ldap_proto_version) {
/* XXX: what about LDAP_VERSION1? */
case LDAP_VERSION2:
#ifdef LDAP_VERSION3
case LDAP_VERSION3:
#endif /* LDAP_VERSION3 */
#ifdef LDAP_VERSION4
case LDAP_VERSION4:
#endif /* LDAP_VERSION4 */
break;
default:
fprintf(stderr, "conf: unsupported ldap_proto_version option value: %s\n",val);
return 1;
}
return 0;
#else /* not HAVE_MAP_LDAP */
fprintf(stderr, "conf: ldap_proto_version option ignored. No LDAP support available.\n");
return 1;
#endif /* not HAVE_MAP_LDAP */
}
static int
gopt_log_file(const char *val)
{
@@ -727,15 +537,7 @@ gopt_log_file(const char *val)
static int
gopt_log_options(const char *val)
{
usage += switch_option((char *)val);
return 0;
}
static int
gopt_map_defaults(const char *val)
{
gopt.map_defaults = strdup((char *)val);
usage += switch_option(strdup((char *)val));
return 0;
}
@@ -748,16 +550,6 @@ gopt_map_options(const char *val)
}
static int
gopt_map_reload_interval(const char *val)
{
gopt.map_reload_interval = atoi(val);
if (gopt.map_reload_interval <= 0)
gopt.map_reload_interval = ONE_HOUR;
return 0;
}
static int
gopt_map_type(const char *val)
{
@@ -775,14 +567,9 @@ static int
gopt_mount_type(const char *val)
{
if (STREQ(val, "autofs")) {
#ifdef HAVE_FS_AUTOFS
gopt.flags |= CFM_MOUNT_TYPE_AUTOFS;
amd_use_autofs++;
fprintf(stderr, "conf: no autofs support available, turning it off\n");
gopt.flags &= ~CFM_MOUNT_TYPE_AUTOFS;
return 0;
#else /* not HAVE_FS_AUTOFS */
fprintf(stderr, "conf: no autofs support available\n");
return 1;
#endif /* not HAVE_FS_AUTOFS */
} else if (STREQ(val, "nfs")) {
gopt.flags &= ~CFM_MOUNT_TYPE_AUTOFS;
return 0;
@@ -796,7 +583,7 @@ gopt_mount_type(const char *val)
static int
gopt_portmap_program(const char *val)
{
gopt.portmap_program = atol(val);
gopt.portmap_program = atoi(val);
/*
* allow alternate program numbers to be no more than 10 offset from
* official amd program number (300019).
@@ -814,35 +601,6 @@ gopt_portmap_program(const char *val)
}
static int
gopt_preferred_amq_port(const char *val)
{
gopt.preferred_amq_port = atoi(val);
/*
* No need to check value: preferred_amq_port is an unsigned short and 0
* is a valid number, meaning "any port".
*/
return 0; /* all is OK */
}
static int
gopt_nfs_allow_any_interface(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_NFS_ANY_INTERFACE;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_NFS_ANY_INTERFACE;
return 0;
}
fprintf(stderr, "conf: unknown value to nfs_allow_insecure_port \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_nfs_allow_insecure_port(const char *val)
{
@@ -874,34 +632,7 @@ gopt_nfs_proto(const char *val)
static int
gopt_nfs_retransmit_counter(const char *val)
{
int i;
for (i=0; i<AMU_TYPE_MAX; ++i)
gopt.amfs_auto_retrans[i] = atoi(val);
return 0;
}
static int
gopt_nfs_retransmit_counter_udp(const char *val)
{
gopt.amfs_auto_retrans[AMU_TYPE_UDP] = atoi(val);
return 0;
}
static int
gopt_nfs_retransmit_counter_tcp(const char *val)
{
gopt.amfs_auto_retrans[AMU_TYPE_TCP] = atoi(val);
return 0;
}
static int
gopt_nfs_retransmit_counter_toplvl(const char *val)
{
gopt.amfs_auto_retrans[AMU_TYPE_TOPLVL] = atoi(val);
gopt.amfs_auto_retrans = atoi(val);
return 0;
}
@@ -909,34 +640,7 @@ gopt_nfs_retransmit_counter_toplvl(const char *val)
static int
gopt_nfs_retry_interval(const char *val)
{
int i;
for (i=0; i<AMU_TYPE_MAX; ++i)
gopt.amfs_auto_timeo[i] = atoi(val);
return 0;
}
static int
gopt_nfs_retry_interval_udp(const char *val)
{
gopt.amfs_auto_timeo[AMU_TYPE_UDP] = atoi(val);
return 0;
}
static int
gopt_nfs_retry_interval_tcp(const char *val)
{
gopt.amfs_auto_timeo[AMU_TYPE_TCP] = atoi(val);
return 0;
}
static int
gopt_nfs_retry_interval_toplvl(const char *val)
{
gopt.amfs_auto_timeo[AMU_TYPE_TOPLVL] = atoi(val);
gopt.amfs_auto_timeo = atoi(val);
return 0;
}
@@ -984,22 +688,6 @@ gopt_normalize_hostnames(const char *val)
}
static int
gopt_normalize_slashes(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_NORMALIZE_SLASHES;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_NORMALIZE_SLASHES;
return 0;
}
fprintf(stderr, "conf: unknown value to normalize_slashes \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_os(const char *val)
{
@@ -1052,9 +740,7 @@ static int
gopt_print_version(const char *val)
{
if (STREQ(val, "yes")) {
char *vers = get_version_string();
fputs(vers, stderr);
XFREE(vers);
fputs(get_version_string(), stderr);
return 0;
} else if (STREQ(val, "no")) {
return 0;
@@ -1121,22 +807,6 @@ gopt_show_statfs_entries(const char *val)
}
static int
gopt_truncate_log(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_TRUNCATE_LOG;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_TRUNCATE_LOG;
return 0;
}
fprintf(stderr, "conf: unknown value to truncate_log \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_unmount_on_exit(const char *val)
{
@@ -1153,27 +823,6 @@ gopt_unmount_on_exit(const char *val)
}
static int
gopt_use_tcpwrappers(const char *val)
{
#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
if (STREQ(val, "yes")) {
gopt.flags |= CFM_USE_TCPWRAPPERS;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_USE_TCPWRAPPERS;
return 0;
}
#else /* not defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
fprintf(stderr, "conf: no tcpd/libwrap support available\n");
return 1;
#endif /* not defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
fprintf(stderr, "conf: unknown value to use_tcpwrappers \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_vendor(const char *val)
{
@@ -1208,9 +857,6 @@ process_regular_option(const char *section, const char *key, const char *val, cf
if (STREQ(key, "map_name"))
return ropt_map_name(val, cfm);
if (STREQ(key, "map_defaults"))
return ropt_map_defaults(val, cfm);
if (STREQ(key, "map_options"))
return ropt_map_options(val, cfm);
@@ -1259,14 +905,6 @@ ropt_map_name(const char *val, cf_map_t *cfm)
}
static int
ropt_map_defaults(const char *val, cf_map_t *cfm)
{
cfm->cfm_defaults = strdup((char *)val);
return 0;
}
static int
ropt_map_options(const char *val, cf_map_t *cfm)
{
@@ -1292,14 +930,9 @@ static int
ropt_mount_type(const char *val, cf_map_t *cfm)
{
if (STREQ(val, "autofs")) {
#ifdef HAVE_FS_AUTOFS
cfm->cfm_flags |= CFM_MOUNT_TYPE_AUTOFS;
amd_use_autofs++;
fprintf(stderr, "conf: no autofs support available, turning it off\n");
cfm->cfm_flags &= ~CFM_MOUNT_TYPE_AUTOFS;
return 0;
#else /* not HAVE_FS_AUTOFS */
fprintf(stderr, "conf: no autofs support available\n");
return 1;
#endif /* not HAVE_FS_AUTOFS */
} else if (STREQ(val, "nfs")) {
cfm->cfm_flags &= ~CFM_MOUNT_TYPE_AUTOFS;
return 0;
@@ -1330,8 +963,9 @@ ropt_tag(const char *val, cf_map_t *cfm)
* Process one collected map.
*/
static int
process_one_regular_map(const cf_map_t *cfm)
process_regular_map(cf_map_t *cfm)
{
if (!cfm->cfm_name) {
fprintf(stderr, "conf: map_name must be defined for map \"%s\"\n", cfm->cfm_dir);
return 1;
@@ -1355,52 +989,22 @@ process_one_regular_map(const cf_map_t *cfm)
fprintf(stderr, "skipping map %s...\n", cfm->cfm_dir);
}
reset_cf_map(cfm);
return 0;
}
/*
* Process all regular maps in conf file (if any)
* Process last map in conf file (if any)
*/
int
process_all_regular_maps(void)
process_last_regular_map(void)
{
cf_map_t *tmp_map = head_map;
/*
* If the amd.conf file only has a [global] section (pretty useless
* IMHO), there's nothing to process
* IMHO), do not try to process a map that does not exist.
*/
if (!tmp_map)
if (!cur_map.cfm_dir)
return 0;
while (tmp_map) {
if (process_one_regular_map(tmp_map) != 0)
return 1;
tmp_map = tmp_map->cfm_next;
}
return 0;
}
/*
* Find a cf_map_t for a given map name.
* Return NULL if not found.
*/
cf_map_t *
find_cf_map(const char *name)
{
cf_map_t *tmp_map = head_map;
if (!tmp_map || !name)
return NULL;
while (tmp_map) {
if (STREQ(tmp_map->cfm_dir,name)) {
return tmp_map;
}
tmp_map = tmp_map->cfm_next;
}
return NULL;
return process_regular_map(&cur_map);
}
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -37,7 +37,7 @@
* SUCH DAMAGE.
*
*
* File: am-utils/amd/conf_parse.y
* $Id: conf_parse.y,v 1.4.2.5 2004/05/12 15:54:31 ezk Exp $
*
*/
+2 -2
View File
@@ -1,6 +1,6 @@
%{
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -38,7 +38,7 @@
* SUCH DAMAGE.
*
*
* File: am-utils/amd/conf_tok.l
* $Id: conf_tok.l,v 1.3.2.5 2004/05/12 15:54:31 ezk Exp $
*
*/
+107 -141
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/get_args.c
* $Id: get_args.c,v 1.7.2.6 2004/01/06 03:15:16 ezk Exp $
* $FreeBSD$
*
*/
@@ -54,12 +56,17 @@
/* include auto-generated version file */
#include <build_version.h>
char *amu_conf_file = "/etc/amd.conf"; /* default amd configuration file */
char *conf_file = "/etc/amd.conf"; /* default amd configuration file */
char *conf_tag = NULL; /* default conf file tags to use */
int usage = 0;
int use_conf_file = 0; /* default don't use amd.conf file */
char *mnttab_file_name = NULL; /* symbol must be available always */
#if 0
#ifdef DEBUG
int debug_flags = D_AMQ /* Register AMQ */
| D_DAEMON; /* Enter daemon mode */
#endif /* DEBUG */
#endif
/*
* Return the version string (dynamic buffer)
@@ -67,61 +74,48 @@ char *mnttab_file_name = NULL; /* symbol must be available always */
char *
get_version_string(void)
{
char *vers = NULL;
static 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.
*/
/* first get dynamic string listing all known networks */
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-2006 Erez Zadok",
"Copyright (c) 1990 Jan-Simon Pendry",
"Copyright (c) 1990 Imperial College of Science, Technology & Medicine",
"Copyright (c) 1990 The Regents of the University of California.");
xsnprintf(tmpbuf, sizeof(tmpbuf), "%s version %s (build %d).\n",
PACKAGE_NAME, PACKAGE_VERSION, AMU_BUILD_VERSION);
strlcat(vers, tmpbuf, len);
xsnprintf(tmpbuf, sizeof(tmpbuf), "Report bugs to %s.\n", PACKAGE_BUGREPORT);
strlcat(vers, tmpbuf, len);
xsnprintf(tmpbuf, sizeof(tmpbuf), "Configured by %s@%s on date %s.\n",
USER_NAME, HOST_NAME, CONFIG_DATE);
strlcat(vers, tmpbuf, len);
xsnprintf(tmpbuf, sizeof(tmpbuf), "Built by %s@%s on date %s.\n",
BUILD_USER, BUILD_HOST, BUILD_DATE);
strlcat(vers, tmpbuf, len);
xsnprintf(tmpbuf, sizeof(tmpbuf), "cpu=%s (%s-endian), arch=%s, karch=%s.\n",
cpu, endian, gopt.arch, gopt.karch);
strlcat(vers, tmpbuf, len);
xsnprintf(tmpbuf, sizeof(tmpbuf), "full_os=%s, os=%s, osver=%s, vendor=%s, distro=%s.\n",
gopt.op_sys_full, gopt.op_sys, gopt.op_sys_ver, gopt.op_sys_vendor, DISTRO_NAME);
strlcat(vers, tmpbuf, len);
xsnprintf(tmpbuf, sizeof(tmpbuf), "domain=%s, host=%s, hostd=%s.\n",
hostdomain, am_get_hostname(), hostd);
strlcat(vers, tmpbuf, len);
vers = xmalloc(2048 + wire_buf_len);
sprintf(vers, "%s\n%s\n%s\n%s\n",
"Copyright (c) 1997-2004 Erez Zadok",
"Copyright (c) 1990 Jan-Simon Pendry",
"Copyright (c) 1990 Imperial College of Science, Technology & Medicine",
"Copyright (c) 1990 The Regents of the University of California.");
sprintf(tmpbuf, "%s version %s (build %d).\n",
PACKAGE, VERSION, AMU_BUILD_VERSION);
strcat(vers, tmpbuf);
sprintf(tmpbuf, "Built by %s@%s on date %s.\n",
USER_NAME, HOST_NAME, CONFIG_DATE);
strcat(vers, tmpbuf);
sprintf(tmpbuf, "cpu=%s (%s-endian), arch=%s, karch=%s.\n",
cpu, endian, gopt.arch, gopt.karch);
strcat(vers, tmpbuf);
sprintf(tmpbuf, "full_os=%s, os=%s, osver=%s, vendor=%s.\n",
gopt.op_sys_full, gopt.op_sys, gopt.op_sys_ver, gopt.op_sys_vendor);
strcat(vers, tmpbuf);
strlcat(vers, "Map support for: ", len);
mapc_showtypes(tmpbuf, sizeof(tmpbuf));
strlcat(vers, tmpbuf, len);
strlcat(vers, ".\nAMFS: ", len);
ops_showamfstypes(tmpbuf, sizeof(tmpbuf));
strlcat(vers, tmpbuf, len);
strlcat(vers, ", inherit.\nFS: ", len); /* hack: "show" that we support type:=inherit */
ops_showfstypes(tmpbuf, sizeof(tmpbuf));
strlcat(vers, tmpbuf, len);
strcat(vers, "Map support for: ");
mapc_showtypes(tmpbuf);
strcat(vers, tmpbuf);
strcat(vers, ".\nAMFS: ");
ops_showamfstypes(tmpbuf);
strcat(vers, tmpbuf);
strcat(vers, ".\nFS: ");
ops_showfstypes(tmpbuf);
strcat(vers, tmpbuf);
/* append list of networks if available */
if (wire_buf) {
strlcat(vers, wire_buf, len);
strcat(vers, wire_buf);
XFREE(wire_buf);
}
@@ -129,48 +123,13 @@ get_version_string(void)
}
static void
show_usage(void)
{
fprintf(stderr,
"Usage: %s [-nprvHS] [-a mount_point] [-c cache_time] [-d domain]\n\
\t[-k kernel_arch] [-l logfile%s\n\
\t[-t timeout.retrans] [-w wait_timeout] [-A arch] [-C cluster_name]\n\
\t[-o op_sys_ver] [-O op_sys_name]\n\
\t[-F conf_file] [-T conf_tag]", am_get_progname(),
#ifdef HAVE_SYSLOG
# ifdef LOG_DAEMON
"|\"syslog[:facility]\"]"
# else /* not LOG_DAEMON */
"|\"syslog\"]"
# endif /* not LOG_DAEMON */
#else /* not HAVE_SYSLOG */
"]"
#endif /* not HAVE_SYSLOG */
);
#ifdef HAVE_MAP_NIS
fputs(" [-y nis-domain]\n", stderr);
#else /* not HAVE_MAP_NIS */
fputc('\n', stderr);
#endif /* HAVE_MAP_NIS */
show_opts('x', xlog_opt);
#ifdef DEBUG
show_opts('D', dbg_opt);
#endif /* DEBUG */
fprintf(stderr, "\t[directory mapname [-map_options]] ...\n");
}
void
get_args(int argc, char *argv[])
{
int opt_ch, i;
int opt_ch;
FILE *fp = stdin;
char getopt_arguments[] = "+nprvSa:c:d:k:l:o:t:w:x:y:C:D:F:T:O:HA:";
char getopt_arguments[] = "+nprvSa:c:d:k:l:o:t:w:x:y:C:D:F:T:O:H";
char *getopt_args;
int print_version = 0; /* 1 means we should print version info */
#ifdef HAVE_GNU_GETOPT
getopt_args = getopt_arguments;
@@ -229,30 +188,24 @@ get_args(int argc, char *argv[])
break;
case 't':
/* timeo.retrans (also affects toplvl mounts) */
/* timeo.retrans */
{
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);
gopt.amfs_auto_timeo = atoi(optarg);
}
if (dot) {
for (i=0; i<AMU_TYPE_MAX; ++i)
gopt.amfs_auto_retrans[i] = atoi(dot + 1);
gopt.amfs_auto_retrans = atoi(dot + 1);
*dot = '.';
}
}
break;
case 'v':
/*
* defer to print version info after every variable had been
* initialized.
*/
print_version++;
fputs(get_version_string(), stderr);
exit(0);
break;
case 'w':
@@ -273,10 +226,6 @@ get_args(int argc, char *argv[])
#endif /* not HAVE_MAP_NIS */
break;
case 'A':
gopt.arch = optarg;
break;
case 'C':
gopt.cluster = optarg;
break;
@@ -291,13 +240,12 @@ get_args(int argc, char *argv[])
break;
case 'F':
amu_conf_file = optarg;
conf_file = optarg;
use_conf_file = 1;
break;
case 'H':
show_usage();
exit(1);
goto show_usage;
break;
case 'O':
@@ -322,19 +270,18 @@ get_args(int argc, char *argv[])
* specified, then use that amd.conf file. If the file cannot be opened,
* abort amd. If it can be found, open it, parse it, and then close it.
*/
if (use_conf_file && amu_conf_file) {
fp = fopen(amu_conf_file, "r");
if (use_conf_file && conf_file) {
fp = fopen(conf_file, "r");
if (!fp) {
char buf[128];
xsnprintf(buf, sizeof(buf), "Amd configuration file (%s)",
amu_conf_file);
sprintf(buf, "Amd configuration file (%s)", conf_file);
perror(buf);
exit(1);
}
yyin = fp;
yyparse();
fclose(fp);
if (process_all_regular_maps() != 0)
if (process_last_regular_map() != 0)
exit(1);
}
@@ -347,8 +294,8 @@ get_args(int argc, char *argv[])
#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);
if (use_conf_file && conf_file)
plog(XLOG_INFO, "using configuration file %s", conf_file);
#ifdef HAVE_MAP_LDAP
/* ensure that if ldap_base is specified, that also ldap_hostports is */
@@ -358,10 +305,8 @@ get_args(int argc, char *argv[])
}
#endif /* HAVE_MAP_LDAP */
if (usage) {
show_usage();
exit(1);
}
if (usage)
goto show_usage;
while (optind <= argc - 2) {
char *dir = argv[optind++];
@@ -383,55 +328,76 @@ get_args(int argc, char *argv[])
hostdomain = gopt.sub_domain;
if (*hostdomain == '.')
hostdomain++;
xstrlcat(hostd, ".", sizeof(hostd));
xstrlcat(hostd, hostdomain, sizeof(hostd));
strcat(hostd, ".");
strcat(hostd, hostdomain);
#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 */
# ifdef DEBUG
if (debug_flags & D_MTAB)
mnttab_file_name = DEBUG_MNTTAB;
else
# endif /* DEBUG */
mnttab_file_name = MNTTAB_FILE_NAME;
#else /* not MOUNT_TABLE_ON_FILE */
if (amuDebug(D_MTAB))
# ifdef DEBUG
if (debug_flags & D_MTAB)
dlog("-D mtab option ignored");
# endif /* DEBUG */
# ifdef MNTTAB_FILE_NAME
mnttab_file_name = MNTTAB_FILE_NAME;
# endif /* MNTTAB_FILE_NAME */
#endif /* not MOUNT_TABLE_ON_FILE */
if (switch_to_logfile(gopt.logfile, orig_umask) != 0)
plog(XLOG_USER, "Cannot switch logfile");
/*
* If the kernel architecture was not specified
* then use the machine architecture.
*/
if (gopt.karch == NULL)
if (gopt.karch == 0)
gopt.karch = gopt.arch;
if (gopt.cluster == NULL)
if (gopt.cluster == 0)
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 */
}
if (gopt.amfs_auto_timeo <= 0)
gopt.amfs_auto_timeo = AMFS_AUTO_TIMEO;
if (gopt.amfs_auto_retrans <= 0)
gopt.amfs_auto_retrans = AMFS_AUTO_RETRANS;
if (gopt.amfs_auto_retrans <= 0)
gopt.amfs_auto_retrans = 3; /* XXX */
return;
}
/* finally print version string and exit, if asked for */
if (print_version) {
fputs(get_version_string(), stderr);
exit(0);
}
show_usage:
fprintf(stderr,
"Usage: %s [-nprvHS] [-a mount_point] [-c cache_time] [-d domain]\n\
\t[-k kernel_arch] [-l logfile%s\n\
\t[-t timeout.retrans] [-w wait_timeout] [-C cluster_name]\n\
\t[-o op_sys_ver] [-O op_sys_name]\n\
\t[-F conf_file] [-T conf_tag]", am_get_progname(),
#ifdef HAVE_SYSLOG
# ifdef LOG_DAEMON
"|\"syslog[:facility]\"]"
# else /* not LOG_DAEMON */
"|\"syslog\"]"
# endif /* not LOG_DAEMON */
#else /* not HAVE_SYSLOG */
"]"
#endif /* not HAVE_SYSLOG */
);
if (switch_to_logfile(gopt.logfile, orig_umask,
(gopt.flags & CFM_TRUNCATE_LOG)) != 0)
plog(XLOG_USER, "Cannot switch logfile");
#ifdef HAVE_MAP_NIS
fputs(" [-y nis-domain]\n", stderr);
#else /* not HAVE_MAP_NIS */
fputc('\n', stderr);
#endif /* HAVE_MAP_NIS */
return;
show_opts('x', xlog_opt);
#ifdef DEBUG
show_opts('D', dbg_opt);
#endif /* DEBUG */
fprintf(stderr, "\t[directory mapname [-map_options]] ...\n");
exit(1);
}
-423
View File
@@ -1,423 +0,0 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgment:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* File: am-utils/amd/info_exec.c
*
*/
/*
* Get info from executable map
*
* Original from Erik Kline, 2004.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
#define MAX_LINE_LEN 1500
/* forward declarations */
int exec_init(mnt_map *m, char *map, time_t *tp);
int exec_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp);
/*
* a timed fgets()
*/
static char *
fgets_timed(char *s, int size, int rdfd, int secs)
{
fd_set fds;
struct timeval timeo;
time_t start, now;
int rval=0, i=0;
if (!s || size < 0 || rdfd < 0)
return 0;
s[0] = 0;
if (size == 0)
return s;
start = clocktime(NULL);
while (s[i] != '\n' && i < size-1) {
s[i+1] = 0; /* places the requisite trailing '\0' */
/* ready for reading */
rval = read(rdfd, (void *)(s+i), 1);
if (rval == 1) {
if (s[i] == 0) {
rval = 0;
break;
}
i++;
continue;
} else if (rval == 0) {
break;
} else if (rval < 0 && errno != EAGAIN && errno != EINTR) {
plog(XLOG_WARNING, "fgets_timed read error: %m");
break;
}
timeo.tv_usec = 0;
now = clocktime(NULL) - start;
if (secs <= 0)
timeo.tv_sec = 0;
else if (now < secs)
timeo.tv_sec = secs - now;
else {
/* timed out (now>=secs) */
plog(XLOG_WARNING, "executable map read timed out (> %d secs)", secs);
rval = -1;
break;
}
FD_ZERO(&fds);
FD_SET(rdfd, &fds);
rval = select(rdfd+1, &fds, 0, 0, &timeo);
if (rval < 0) {
/* error selecting */
plog(XLOG_WARNING, "fgets_timed select error: %m");
if (errno == EINTR)
continue;
rval = -1;
break;
} else if (rval == 0) {
/* timed out */
plog(XLOG_WARNING, "executable map read timed out (> %d secs)", secs);
rval = -1;
break;
}
}
if (rval > 0)
return s;
close(rdfd);
return (rval == 0 ? s : 0);
}
static int
read_line(char *buf, int size, int fd)
{
int done = 0;
while (fgets_timed(buf, size, fd, gopt.exec_map_timeout)) {
int len = strlen(buf);
done += len;
if (len > 1 && buf[len - 2] == '\\' &&
buf[len - 1] == '\n') {
buf += len - 2;
size -= len - 2;
*buf = '\n';
buf[1] = '\0';
} else {
return done;
}
}
return done;
}
/*
* Try to locate a value in a query answer
*/
static int
exec_parse_qanswer(int fd, char *map, char *key, char **pval, time_t *tp)
{
char qanswer[MAX_LINE_LEN], *dc = 0;
int chuck = 0;
int line_no = 0;
while (read_line(qanswer, sizeof(qanswer), fd)) {
char *cp;
char *hash;
int len = strlen(qanswer);
line_no++;
/*
* Make sure we got the whole line
*/
if (qanswer[len - 1] != '\n') {
plog(XLOG_WARNING, "line %d in \"%s\" is too long", line_no, map);
chuck = 1;
} else {
qanswer[len - 1] = '\0';
}
/*
* Strip comments
*/
hash = strchr(qanswer, '#');
if (hash)
*hash = '\0';
/*
* Find beginning of value (query answer)
*/
for (cp = qanswer; *cp && !isascii((int)*cp) && !isspace((int)*cp); cp++)
;;
/* Ignore blank lines */
if (!*cp)
goto again;
/*
* Return a copy of the data
*/
dc = strdup(cp);
*pval = dc;
dlog("%s returns %s", key, dc);
close(fd);
return 0;
again:
/*
* If the last read didn't get a whole line then
* throw away the remainder before continuing...
*/
if (chuck) {
while (fgets_timed(qanswer, sizeof(qanswer), fd, gopt.exec_map_timeout) &&
!strchr(qanswer, '\n')) ;
chuck = 0;
}
}
return ENOENT;
}
static int
set_nonblock(int fd)
{
int val;
if (fd < 0)
return 0;
if ((val = fcntl(fd, F_GETFL, 0)) < 0) {
plog(XLOG_WARNING, "set_nonblock fcntl F_GETFL error: %m");
return 0;
}
val |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, val) < 0) {
plog(XLOG_WARNING, "set_nonblock fcntl F_SETFL error: %m");
return 0;
}
return 1;
}
static int
exec_map_open(char *emap, char *key)
{
pid_t p1, p2;
int pdes[2], nullfd, i;
char *argv[3];
if (!emap)
return 0;
argv[0] = emap;
argv[1] = key;
argv[2] = NULL;
if ((nullfd = open("/dev/null", O_WRONLY|O_NOCTTY)) < 0)
return -1;
if (pipe(pdes) < 0) {
close(nullfd);
return -1;
}
switch ((p1 = vfork())) {
case -1:
/* parent: fork error */
close(nullfd);
close(pdes[0]);
close(pdes[1]);
return -1;
case 0:
/* child #1 */
p2 = vfork();
switch (p2) {
case -1:
/* child #1: fork error */
exit(errno);
case 0:
/* child #2: init will reap our status */
if (pdes[1] != STDOUT_FILENO) {
dup2(pdes[1], STDOUT_FILENO);
close(pdes[1]);
}
if (nullfd != STDERR_FILENO) {
dup2(nullfd, STDERR_FILENO);
close(nullfd);
}
for (i=0; i<FD_SETSIZE; i++)
if (i != STDOUT_FILENO && i != STDERR_FILENO)
close(i);
/* make the write descriptor non-blocking */
if (!set_nonblock(STDOUT_FILENO)) {
close(STDOUT_FILENO);
exit(-1);
}
execve(emap, argv, NULL);
exit(errno); /* in case execve failed */
}
/* child #1 */
exit(0);
}
/* parent */
close(nullfd);
close(pdes[1]);
/* anti-zombie insurance */
while (waitpid(p1,0,0) < 0)
if (errno != EINTR)
exit(errno);
/* make the read descriptor non-blocking */
if (!set_nonblock(pdes[0])) {
close(pdes[0]);
return -1;
}
return pdes[0];
}
/*
* Check for various permissions on executable map without trying to
* fork a new executable-map process.
*
* return: >0 (errno) if failed
* 0 if ok
*/
static int
exec_check_perm(char *map)
{
struct stat sb;
/* sanity and permission checks */
if (!map) {
dlog("exec_check_permission got a NULL map");
return EINVAL;
}
if (stat(map, &sb)) {
plog(XLOG_ERROR, "map \"%s\" stat failure: %m", map);
return errno;
}
if (!S_ISREG(sb.st_mode)) {
plog(XLOG_ERROR, "map \"%s\" should be regular file", map);
return EINVAL;
}
if (sb.st_uid != 0) {
plog(XLOG_ERROR, "map \"%s\" owned by uid %u (must be 0)", map, (u_int) sb.st_uid);
return EACCES;
}
if (!(sb.st_mode & S_IXUSR)) {
plog(XLOG_ERROR, "map \"%s\" should be executable", map);
return EACCES;
}
if (sb.st_mode & (S_ISUID|S_ISGID)) {
plog(XLOG_ERROR, "map \"%s\" should not be setuid/setgid", map);
return EACCES;
}
if (sb.st_mode & S_IWOTH) {
plog(XLOG_ERROR, "map \"%s\" should not be world writeable", map);
return EACCES;
}
return 0; /* all is well */
}
int
exec_init(mnt_map *m, char *map, time_t *tp)
{
/*
* Basically just test that the executable map can be found
* and has proper permissions.
*/
return exec_check_perm(map);
}
int
exec_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
{
int mapfd, ret;
if ((ret = exec_check_perm(map)) != 0) {
return ret;
}
if (!key)
return 0;
if (logfp)
fflush(logfp);
dlog("exec_search \"%s\", key: \"%s\"", map, key);
mapfd = exec_map_open(map, key);
if (mapfd >= 0) {
if (tp)
*tp = clocktime(NULL);
return exec_parse_qanswer(mapfd, map, key, pval, tp);
}
return errno;
}
+26 -14
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/info_file.c
* $Id: info_file.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -54,9 +55,10 @@
#define MAX_LINE_LEN 1500
/* forward declarations */
int file_init_or_mtime(mnt_map *m, char *map, time_t *tp);
int file_init(mnt_map *m, char *map, time_t *tp);
int file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *));
int file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp);
int file_mtime(mnt_map *m, char *map, time_t *tp);
static int
@@ -85,7 +87,7 @@ read_line(char *buf, int size, FILE *fp)
return done;
}
}
} while (size > 0 && !feof(fp) && !ferror(fp));
} while (size > 0 && !feof(fp));
return done;
}
@@ -95,12 +97,7 @@ read_line(char *buf, int size, FILE *fp)
* Try to locate a key in a file
*/
static int
file_search_or_reload(FILE *fp,
char *map,
char *key,
char **val,
mnt_map *m,
void (*fn) (mnt_map *m, char *, char *))
search_or_reload_file(FILE *fp, char *map, char *key, char **val, mnt_map *m, void (*fn) (mnt_map *m, char *, char *))
{
char key_val[MAX_LINE_LEN];
int chuck = 0;
@@ -164,7 +161,9 @@ file_search_or_reload(FILE *fp,
(*fn) (m, strdup(kp), dc);
} else {
*val = dc;
#ifdef DEBUG
dlog("%s returns %s", key, dc);
#endif /* DEBUG */
}
if (!fn)
return 0;
@@ -197,7 +196,7 @@ file_open(char *map, time_t *tp)
if (mapf && tp) {
struct stat stb;
if (fstat(fileno(mapf), &stb) < 0)
*tp = clocktime(NULL);
*tp = clocktime();
else
*tp = stb.st_mtime;
}
@@ -206,7 +205,7 @@ file_open(char *map, time_t *tp)
int
file_init_or_mtime(mnt_map *m, char *map, time_t *tp)
file_init(mnt_map *m, char *map, time_t *tp)
{
FILE *mapf = file_open(map, tp);
@@ -224,7 +223,7 @@ file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
FILE *mapf = file_open(map, (time_t *) 0);
if (mapf) {
int error = file_search_or_reload(mapf, map, 0, 0, m, fn);
int error = search_or_reload_file(mapf, map, 0, 0, m, fn);
(void) fclose(mapf);
return error;
}
@@ -244,10 +243,23 @@ file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
*tp = t;
error = -1;
} else {
error = file_search_or_reload(mapf, map, key, pval, 0, 0);
error = search_or_reload_file(mapf, map, key, pval, 0, 0);
}
(void) fclose(mapf);
return error;
}
return errno;
}
int
file_mtime(mnt_map *m, char *map, time_t *tp)
{
FILE *mapf = file_open(map, tp);
if (mapf) {
(void) fclose(mapf);
return 0;
}
return errno;
}
+18 -8
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/info_hesiod.c
* $Id: info_hesiod.c,v 1.6.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -74,11 +75,13 @@ int hesiod_isup(mnt_map *m, char *map);
int
amu_hesiod_init(mnt_map *m, char *map, time_t *tp)
{
#ifdef DEBUG
dlog("amu_hesiod_init(%s)", map);
#endif /* DEBUG */
*tp = 0;
#ifdef HAVE_HESIOD_INIT
if (!hesiod_context && hesiod_init(&hesiod_context) != 0)
if(!hesiod_context && hesiod_init(&hesiod_context) != 0)
return ENOENT;
#endif /* HAVE_HESIOD_INIT */
@@ -99,21 +102,22 @@ hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
int error;
#endif /* not HAVE_HESIOD_INIT */
#ifdef DEBUG
dlog("hesiod_search(m=%lx, map=%s, key=%s, pval=%lx tp=%lx)",
(unsigned long) m, map, key, (unsigned long) pval, (unsigned long) tp);
#endif /* DEBUG */
if (key[0] == '.')
return ENOENT;
xsnprintf(hes_key, sizeof(hes_key), "%s.%s", key, map + HES_PREFLEN);
sprintf(hes_key, "%s.%s", key, map + HES_PREFLEN);
/*
* Call the resolver
*/
#ifdef DEBUG
dlog("Hesiod base is: %s\n", gopt.hesiod_base);
dlog("hesiod_search: hes_resolve(%s, %s)", hes_key, gopt.hesiod_base);
if (amuDebug(D_INFO))
if (debug_flags & D_INFO)
_res.options |= RES_DEBUG;
#endif /* DEBUG */
#ifdef HAVE_HESIOD_INIT
/* new style hesiod */
@@ -140,7 +144,9 @@ hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
/*
* Otherwise reflect the hesiod error into a Un*x error
*/
# ifdef DEBUG
dlog("hesiod_search: Error: %d", hes_error());
# endif /* DEBUG */
switch (hes_error()) {
case HES_ER_NOTFOUND:
error = ENOENT;
@@ -155,7 +161,9 @@ hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
error = EINVAL;
break;
}
# ifdef DEBUG
dlog("hesiod_search: Returning: %d", error);
# endif /* DEBUG */
return error;
#endif /* not HAVE_HESIOD_INIT */
}
@@ -175,7 +183,9 @@ hesiod_isup(mnt_map *m, char *map)
static int last_status = 1; /* assume up by default */
error = hesiod_search(m, map, "/defaults", &val, &mtime);
#ifdef DEBUG
dlog("hesiod_isup(%s): %s", map, strerror(error));
#endif /* DEBUG */
if (error != 0 && error != ENOENT) {
plog(XLOG_ERROR,
"hesiod_isup: error getting `/defaults' entry in map %s: %m", map);
+140 -237
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/info_ldap.c
* $Id: info_ldap.c,v 1.9.2.9 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -47,20 +48,6 @@
* 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 */
@@ -122,7 +109,7 @@ struct he_ent {
* FORWARD DECLARATIONS:
*/
static int amu_ldap_rebind(ALD *a);
static int get_ldap_timestamp(ALD *a, char *map, time_t *ts);
static int get_ldap_timestamp(LDAP *ld, char *map, time_t *ts);
/*
@@ -180,54 +167,13 @@ cr_free(CR *c)
}
/*
* Special ldap_unbind function to handle SIGPIPE.
* We first ignore SIGPIPE, in case a remote LDAP server was
* restarted, then we reinstall the handler.
*/
static int
amu_ldap_unbind(LDAP *ld)
{
int e;
#ifdef HAVE_SIGACTION
struct sigaction sa;
#else /* not HAVE_SIGACTION */
void (*handler)(int);
#endif /* not HAVE_SIGACTION */
dlog("amu_ldap_unbind()\n");
#ifdef HAVE_SIGACTION
sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;
sigemptyset(&(sa.sa_mask));
sigaddset(&(sa.sa_mask), SIGPIPE);
sigaction(SIGPIPE, &sa, &sa); /* set IGNORE, and get old action */
#else /* not HAVE_SIGACTION */
handler = signal(SIGPIPE, SIG_IGN);
#endif /* not HAVE_SIGACTION */
e = ldap_unbind(ld);
#ifdef HAVE_SIGACTION
sigemptyset(&(sa.sa_mask));
sigaddset(&(sa.sa_mask), SIGPIPE);
sigaction(SIGPIPE, &sa, NULL);
#else /* not HAVE_SIGACTION */
(void) signal(SIGPIPE, handler);
#endif /* not HAVE_SIGACTION */
return e;
}
static void
ald_free(ALD *a)
{
he_free(a->hostent);
cr_free(a->credentials);
if (a->ldap != NULL)
amu_ldap_unbind(a->ldap);
ldap_unbind(a->ldap);
XFREE(a);
}
@@ -238,29 +184,27 @@ 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"));
} else {
return (ENOENT);
}
#ifdef DEBUG
else {
dlog("Map %s is ldap\n", map);
}
#endif /* DEBUG */
aldh = ALLOC(ALD);
creds = ALLOC(CR);
aldh->ldap = NULL;
aldh->ldap = NULL ;
aldh->hostent = string2he(gopt.ldap_hostports);
if (aldh->hostent == NULL) {
plog(XLOG_USER, "Unable to parse hostport %s for ldap map %s",
gopt.ldap_hostports ? gopt.ldap_hostports : "(null)", map);
XFREE(creds);
XFREE(aldh);
return (ENOENT);
}
creds->who = "";
@@ -268,17 +212,22 @@ amu_ldap_init(mnt_map *m, char *map, time_t *ts)
creds->method = LDAP_AUTH_SIMPLE;
aldh->credentials = creds;
aldh->timestamp = 0;
aldh->ldap = NULL;
#ifdef DEBUG
dlog("Trying for %s:%d\n", aldh->hostent->host, aldh->hostent->port);
#endif /* DEBUG */
if (amu_ldap_rebind(aldh)) {
ald_free(aldh);
return (ENOENT);
}
m->map_data = (void *) aldh;
#ifdef DEBUG
dlog("Bound to %s:%d\n", aldh->hostent->host, aldh->hostent->port);
if (get_ldap_timestamp(aldh, map, ts))
#endif /* DEBUG */
if (get_ldap_timestamp(aldh->ldap, map, ts))
return (ENOENT);
dlog("Got timestamp for map %s: %ld\n", map, (u_long) *ts);
#ifdef DEBUG
dlog("Got timestamp for map %s: %ld\n", map, *ts);
#endif /* DEBUG */
return (0);
}
@@ -290,21 +239,16 @@ amu_ldap_rebind(ALD *a)
LDAP *ld;
HE_ENT *h;
CR *c = a->credentials;
time_t now = clocktime(NULL);
time_t now = clocktime();
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);
#ifdef DEBUG
dlog("Reestablishing ldap connection\n");
#endif /* DEBUG */
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);
}
}
@@ -314,34 +258,21 @@ amu_ldap_rebind(ALD *a)
plog(XLOG_WARNING, "Unable to ldap_open to %s:%d\n", h->host, h->port);
break;
}
#if LDAP_VERSION_MAX > LDAP_VERSION2
/* handle LDAPv3 and heigher, if available and amd.conf-igured */
if (gopt.ldap_proto_version > LDAP_VERSION2) {
if (!ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &gopt.ldap_proto_version)) {
dlog("amu_ldap_rebind: LDAP protocol version set to %ld\n",
gopt.ldap_proto_version);
} else {
plog(XLOG_WARNING, "Unable to set ldap protocol version to %ld\n",
gopt.ldap_proto_version);
break;
}
}
#endif /* LDAP_VERSION_MAX > LDAP_VERSION2 */
if (ldap_bind_s(ld, c->who, c->pw, c->method) != LDAP_SUCCESS) {
plog(XLOG_WARNING, "Unable to ldap_bind to %s:%d as %s\n",
h->host, h->port, c->who);
break;
}
if (gopt.ldap_cache_seconds > 0) {
#if defined(HAVE_LDAP_ENABLE_CACHE) && defined(HAVE_EXTERN_LDAP_ENABLE_CACHE)
#ifdef HAVE_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) */
#else /* HAVE_LDAP_ENABLE_CACHE */
plog(XLOG_WARNING, "ldap_enable_cache(%ld) does not exist on this system!\n", gopt.ldap_cache_seconds);
#endif /* HAVE_LDAP_ENABLE_CACHE */
a->ldap = ld;
a->timestamp = now;
return (0);
}
a->ldap = ld;
a->timestamp = now;
return (0);
}
plog(XLOG_WARNING, "Exhausted list of ldap servers, looping.\n");
}
@@ -352,22 +283,115 @@ amu_ldap_rebind(ALD *a)
static int
get_ldap_timestamp(ALD *a, char *map, time_t *ts)
get_ldap_timestamp(LDAP *ld, 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);
LDAPMessage *res, *entry;
tv.tv_sec = 3;
tv.tv_usec = 0;
xsnprintf(filter, sizeof(filter), AMD_LDAP_TSFILTER, map);
sprintf(filter, AMD_LDAP_TSFILTER, map);
#ifdef DEBUG
dlog("Getting timestamp for map %s\n", map);
dlog("Filter is: %s\n", filter);
dlog("Base is: %s\n", gopt.ldap_base);
#endif /* DEBUG */
for (i = 0; i < AMD_LDAP_RETRIES; i++) {
err = ldap_search_st(ld,
gopt.ldap_base,
LDAP_SCOPE_SUBTREE,
filter,
0,
0,
&tv,
&res);
if (err == LDAP_SUCCESS)
break;
#ifdef DEBUG
dlog("Timestamp search timed out, trying again...\n");
#endif /* DEBUG */
}
if (err != LDAP_SUCCESS) {
*ts = 0;
plog(XLOG_USER, "LDAP timestamp search failed: %s\n",
ldap_err2string(err));
return (ENOENT);
}
nentries = ldap_count_entries(ld, res);
if (nentries == 0) {
plog(XLOG_USER, "No timestamp entry for map %s\n", map);
*ts = 0;
ldap_msgfree(res);
return (ENOENT);
}
entry = ldap_first_entry(ld, res);
vals = ldap_get_values(ld, entry, AMD_LDAP_TSATTR);
if (ldap_count_values(vals) == 0) {
plog(XLOG_USER, "Missing timestamp value for map %s\n", map);
*ts = 0;
ldap_value_free(vals);
ldap_msgfree(res);
return (ENOENT);
}
#ifdef DEBUG
dlog("TS value is:%s:\n", vals[0]);
#endif /* DEBUG */
if (vals[0]) {
*ts = (time_t) strtol(vals[0], &end, 10);
if (end == vals[0]) {
plog(XLOG_USER, "Unable to decode ldap timestamp %s for map %s\n",
vals[0], map);
err = ENOENT;
}
if (!*ts > 0) {
plog(XLOG_USER, "Nonpositive timestamp %ld for map %s\n",
*ts, map);
err = ENOENT;
}
} else {
plog(XLOG_USER, "Empty timestamp value for map %s\n", map);
*ts = 0;
err = ENOENT;
}
ldap_value_free(vals);
ldap_msgfree(res);
#ifdef DEBUG
dlog("The timestamp for %s is %ld (err=%d)\n", map, *ts, err);
#endif /* DEBUG */
return (err);
}
int
amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts)
{
char **vals, filter[MAXPATHLEN];
struct timeval tv;
int i, err = 0, nvals = 0, nentries = 0;
LDAPMessage *entry, *res;
ALD *a = (ALD *) (m->map_data);
tv.tv_sec = 2;
tv.tv_usec = 0;
if (a == NULL) {
plog(XLOG_USER, "LDAP panic: no map data\n");
return (EIO);
}
if (amu_ldap_rebind(a)) /* Check that's the handle is still valid */
return (ENOENT);
sprintf(filter, AMD_LDAP_FILTER, map, key);
#ifdef DEBUG
dlog("Search with filter: %s\n", filter);
#endif /* DEBUG */
for (i = 0; i < AMD_LDAP_RETRIES; i++) {
err = ldap_search_st(a->ldap,
gopt.ldap_base,
@@ -379,153 +403,28 @@ get_ldap_timestamp(ALD *a, char *map, time_t *ts)
&res);
if (err == LDAP_SUCCESS)
break;
if (res) {
ldap_msgfree(res);
res = NULL;
}
plog(XLOG_USER, "Timestamp LDAP search attempt %d failed: %s\n",
i + 1, ldap_err2string(err));
if (err != LDAP_TIMEOUT) {
dlog("get_ldap_timestamp: unbinding...\n");
amu_ldap_unbind(a->ldap);
a->ldap = NULL;
if (amu_ldap_rebind(a))
return (ENOENT);
}
dlog("Timestamp search failed, trying again...\n");
}
if (err != LDAP_SUCCESS) {
*ts = 0;
plog(XLOG_USER, "LDAP timestamp search failed: %s\n",
ldap_err2string(err));
if (res)
ldap_msgfree(res);
return (ENOENT);
}
nentries = ldap_count_entries(a->ldap, res);
if (nentries == 0) {
plog(XLOG_USER, "No timestamp entry for map %s\n", map);
*ts = 0;
ldap_msgfree(res);
return (ENOENT);
}
entry = ldap_first_entry(a->ldap, res);
vals = ldap_get_values(a->ldap, entry, AMD_LDAP_TSATTR);
if (ldap_count_values(vals) == 0) {
plog(XLOG_USER, "Missing timestamp value for map %s\n", map);
*ts = 0;
ldap_value_free(vals);
ldap_msgfree(res);
return (ENOENT);
}
dlog("TS value is:%s:\n", vals[0]);
if (vals[0]) {
*ts = (time_t) strtol(vals[0], &end, 10);
if (end == vals[0]) {
plog(XLOG_USER, "Unable to decode ldap timestamp %s for map %s\n",
vals[0], map);
err = ENOENT;
}
if (!*ts > 0) {
plog(XLOG_USER, "Nonpositive timestamp %ld for map %s\n",
(u_long) *ts, map);
err = ENOENT;
}
} else {
plog(XLOG_USER, "Empty timestamp value for map %s\n", map);
*ts = 0;
err = ENOENT;
}
ldap_value_free(vals);
ldap_msgfree(res);
dlog("The timestamp for %s is %ld (err=%d)\n", map, (u_long) *ts, err);
return (err);
}
int
amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts)
{
char **vals, filter[MAXPATHLEN], filter2[2 * MAXPATHLEN];
char *f1, *f2;
struct timeval tv;
int i, err = 0, nvals = 0, nentries = 0;
LDAPMessage *entry, *res = NULL;
ALD *a = (ALD *) (m->map_data);
dlog("-> amu_ldap_search: map <%s>, key <%s>\n", map, key);
tv.tv_sec = 2;
tv.tv_usec = 0;
if (a == NULL) {
plog(XLOG_USER, "LDAP panic: no map data\n");
return (EIO);
}
if (amu_ldap_rebind(a)) /* Check that's the handle is still valid */
return (ENOENT);
xsnprintf(filter, sizeof(filter), AMD_LDAP_FILTER, map, key);
/* "*" is special to ldap_search(); run through the filter escaping it. */
f1 = filter; f2 = filter2;
while (*f1) {
if (*f1 == '*') {
*f2++ = '\\'; *f2++ = '2'; *f2++ = 'a';
f1++;
} else {
*f2++ = *f1++;
}
}
*f2 = '\0';
dlog("Search with filter: <%s>\n", filter2);
for (i = 0; i < AMD_LDAP_RETRIES; i++) {
err = ldap_search_st(a->ldap,
gopt.ldap_base,
LDAP_SCOPE_SUBTREE,
filter2,
0,
0,
&tv,
&res);
if (err == LDAP_SUCCESS)
break;
if (res) {
ldap_msgfree(res);
res = NULL;
}
plog(XLOG_USER, "LDAP search attempt %d failed: %s\n",
i + 1, ldap_err2string(err));
if (err != LDAP_TIMEOUT) {
dlog("amu_ldap_search: unbinding...\n");
amu_ldap_unbind(a->ldap);
a->ldap = NULL;
if (amu_ldap_rebind(a))
return (ENOENT);
}
}
switch (err) {
case LDAP_SUCCESS:
break;
case LDAP_NO_SUCH_OBJECT:
#ifdef DEBUG
dlog("No object\n");
if (res)
ldap_msgfree(res);
#endif /* DEBUG */
ldap_msgfree(res);
return (ENOENT);
default:
plog(XLOG_USER, "LDAP search failed: %s\n",
ldap_err2string(err));
if (res)
ldap_msgfree(res);
ldap_msgfree(res);
return (EIO);
}
nentries = ldap_count_entries(a->ldap, res);
#ifdef DEBUG
dlog("Search found %d entries\n", nentries);
#endif /* DEBUG */
if (nentries == 0) {
ldap_msgfree(res);
return (ENOENT);
@@ -539,7 +438,9 @@ amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts)
ldap_msgfree(res);
return (EIO);
}
#ifdef DEBUG
dlog("Map %s, %s => %s\n", map, key, vals[0]);
#endif /* DEBUG */
if (vals[0]) {
*pval = strdup(vals[0]);
err = 0;
@@ -560,13 +461,15 @@ amu_ldap_mtime(mnt_map *m, char *map, time_t *ts)
ALD *aldh = (ALD *) (m->map_data);
if (aldh == NULL) {
#ifdef DEBUG
dlog("LDAP panic: unable to find map data\n");
#endif /* DEBUG */
return (ENOENT);
}
if (amu_ldap_rebind(aldh)) {
return (ENOENT);
}
if (get_ldap_timestamp(aldh, map, ts)) {
if (get_ldap_timestamp(aldh->ldap, map, ts)) {
return (ENOENT);
}
return (0);
+8 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/info_ndbm.c
* $Id: info_ndbm.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -85,8 +86,8 @@ ndbm_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
#ifdef DBM_SUFFIX
char dbfilename[256];
xstrlcpy(dbfilename, map, sizeof(dbfilename));
xstrlcat(dbfilename, DBM_SUFFIX, sizeof(dbfilename));
strcpy(dbfilename, map);
strcat(dbfilename, DBM_SUFFIX);
error = stat(dbfilename, &stb);
#else /* not DBM_SUFFIX */
error = fstat(dbm_pagfno(db), &stb);
@@ -116,14 +117,14 @@ ndbm_init(mnt_map *m, char *map, time_t *tp)
#ifdef DBM_SUFFIX
char dbfilename[256];
xstrlcpy(dbfilename, map, sizeof(dbfilename));
xstrlcat(dbfilename, DBM_SUFFIX, sizeof(dbfilename));
strcpy(dbfilename, map);
strcat(dbfilename, DBM_SUFFIX);
error = stat(dbfilename, &stb);
#else /* not DBM_SUFFIX */
error = fstat(dbm_pagfno(db), &stb);
#endif /* not DBM_SUFFIX */
if (error < 0)
*tp = clocktime(NULL);
*tp = clocktime();
else
*tp = stb.st_mtime;
dbm_close(db);
+15 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/info_nis.c
* $Id: info_nis.c,v 1.6.2.5 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -106,7 +107,9 @@ determine_nis_domain(void)
}
if (!*default_domain) {
nis_not_running = 1;
#ifdef DEBUG
plog(XLOG_WARNING, "NIS domain name is not set. NIS ignored.");
#endif /* DEBUG */
return ENOENT;
}
gopt.nis_domain = strdup(default_domain);
@@ -141,8 +144,12 @@ callback(int status, char *key, int kl, char *val, int vl, char *data)
/* check what went wrong */
int e = ypprot_err(status);
#ifdef DEBUG
plog(XLOG_ERROR, "yp enumeration of %s: %s, status=%d, e=%d",
ncdp->ncd_map, yperr_string(e), status, e);
#else /* not DEBUG */
plog(XLOG_ERROR, "yp enumeration of %s: %s", ncdp->ncd_map, yperr_string(e));
#endif /* not DEBUG */
}
return TRUE;
}
@@ -343,7 +350,9 @@ nis_init(mnt_map *m, char *map, time_t *tp)
/* NIS server found */
has_yp_order = 1;
*tp = (time_t) order;
#ifdef DEBUG
dlog("NIS master for %s@%s has order %lu", map, gopt.nis_domain, (unsigned long) order);
#endif /* DEBUG */
break;
case YPERR_YPERR:
/* NIS+ server found ! */
@@ -352,7 +361,9 @@ nis_init(mnt_map *m, char *map, time_t *tp)
if (yp_master(gopt.nis_domain, map, &master)) {
return ENOENT;
} else {
#ifdef DEBUG
dlog("NIS master for %s@%s is a NIS+ server", map, gopt.nis_domain);
#endif /* DEBUG */
/* Use fake timestamps */
*tp = time(NULL);
}
@@ -431,9 +442,11 @@ am_yp_all(char *indomain, char *inmap, struct ypall_callback *incallback)
&outvallen);
XFREE(outkey_old);
} while (!i);
#ifdef DEBUG
if (i) {
dlog("yp_next() returned error: %s\n", yperr_string(i));
}
#endif /* DEBUG */
if (i == YPERR_NOMORE)
return 0;
return i;
+34 -20
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/info_nisplus.c
* $Id: info_nisplus.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -73,7 +74,9 @@ nisplus_callback(const nis_name key, const nis_object *value, voidp opaquedata)
char *vp = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
struct nis_callback_data *data = (struct nis_callback_data *) opaquedata;
#ifdef DEBUG
dlog("NISplus callback for <%s,%s>", kp, vp);
#endif /* DEBUG */
(*data->ncd_fn) (data->ncd_m, kp, vp);
@@ -92,7 +95,6 @@ nisplus_reload(mnt_map *m, char *map, void (*fn) ())
nis_result *result;
char *org; /* if map does not have ".org_dir" then append it */
nis_name map_name;
size_t l;
org = strstr(map, NISPLUS_ORGDIR);
if (org == NULL)
@@ -101,20 +103,21 @@ nisplus_reload(mnt_map *m, char *map, void (*fn) ())
org = "";
/* make some room for the NIS map_name */
l = strlen(map) + sizeof(NISPLUS_ORGDIR);
map_name = xmalloc(l);
map_name = xmalloc(strlen(map) + sizeof(NISPLUS_ORGDIR));
if (map_name == NULL) {
plog(XLOG_ERROR, "Unable to create map_name %s: %s",
map, strerror(ENOMEM));
return ENOMEM;
}
xsnprintf(map_name, l, "%s%s", map, org);
sprintf(map_name, "%s%s", map, org);
data.ncd_m = m;
data.ncd_map = map_name;
data.ncd_fn = fn;
#ifdef DEBUG
dlog("NISplus reload for %s", map);
#endif /* DEBUG */
result = nis_list(map_name,
EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH,
@@ -142,8 +145,10 @@ nisplus_search_callback(const nis_name key, const nis_object *value, voidp opaqu
{
struct nisplus_search_callback_data *data = (struct nisplus_search_callback_data *) opaquedata;
#ifdef DEBUG
dlog("NISplus search callback for <%s>", ENTRY_VAL(value, 0));
dlog("NISplus search callback value <%s>", ENTRY_VAL(value, 1));
#endif /* DEBUG */
data->value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
return TRUE;
@@ -161,7 +166,6 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
struct nisplus_search_callback_data data;
nis_name index;
char *org; /* if map does not have ".org_dir" then append it */
size_t l;
org = strstr(map, NISPLUS_ORGDIR);
if (org == NULL)
@@ -170,14 +174,14 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
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);
index = xmalloc(sizeof('[') /* for opening selection criteria */
+sizeof(NISPLUS_KEY)
+ strlen(key)
+ sizeof(']') /* for closing selection criteria */
+sizeof(',') /* + 1 for , separator */
+strlen(map)
+ sizeof(NISPLUS_ORGDIR)
);
if (index == NULL) {
plog(XLOG_ERROR,
"Unable to create index %s: %s",
@@ -185,12 +189,14 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
strerror(ENOMEM));
return ENOMEM;
}
xsnprintf(index, l, "[%s%s],%s%s", NISPLUS_KEY, key, map, org);
sprintf(index, "[%s%s],%s%s", NISPLUS_KEY, key, map, org);
data.key = key;
data.value = NULL;
#ifdef DEBUG
dlog("NISplus search for %s", index);
#endif /* DEBUG */
result = nis_list(index,
EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH,
@@ -214,9 +220,11 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
if (data.value == NULL) {
nis_object *value = result->objects.objects_val;
#ifdef DEBUG
dlog("NISplus search found <nothing>");
dlog("NISplus search for %s: %s(%d)",
map, nis_sperrno(result->status), result->status);
#endif /* DEBUG */
if (value != NULL)
data.value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
@@ -225,17 +233,23 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
if (*val) {
error = 0;
#ifdef DEBUG
dlog("NISplus search found %s", *val);
#endif /* DEBUG */
} else {
error = ENOENT;
#ifdef DEBUG
dlog("NISplus search found nothing");
#endif /* DEBUG */
}
*tp = 0;
break;
case NIS_NOSUCHNAME:
#ifdef DEBUG
dlog("NISplus search returned %d", result->status);
#endif /* DEBUG */
error = ENOENT;
break;
@@ -257,7 +271,6 @@ nisplus_init(mnt_map *m, char *map, time_t *tp)
char *org; /* if map does not have ".org_dir" then append it */
nis_name map_name;
int error = 0;
size_t l;
org = strstr(map, NISPLUS_ORGDIR);
if (org == NULL)
@@ -266,8 +279,7 @@ nisplus_init(mnt_map *m, char *map, time_t *tp)
org = "";
/* make some room for the NIS map_name */
l = strlen(map) + sizeof(NISPLUS_ORGDIR);
map_name = xmalloc(l);
map_name = xmalloc(strlen(map) + sizeof(NISPLUS_ORGDIR));
if (map_name == NULL) {
plog(XLOG_ERROR,
"Unable to create map_name %s: %s",
@@ -275,7 +287,7 @@ nisplus_init(mnt_map *m, char *map, time_t *tp)
strerror(ENOMEM));
return ENOMEM;
}
xsnprintf(map_name, l, "%s%s", map, org);
sprintf(map_name, "%s%s", map, org);
result = nis_lookup(map_name, (EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH));
@@ -288,8 +300,10 @@ nisplus_init(mnt_map *m, char *map, time_t *tp)
}
if (result->status != NIS_SUCCESS) {
#ifdef DEBUG
dlog("NISplus init <%s>: %s (%d)",
map, nis_sperrno(result->status), result->status);
#endif /* DEBUG */
error = ENOENT;
}
+10 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/info_passwd.c
* $Id: info_passwd.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -150,11 +151,11 @@ passwd_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
do {
q = strrchr(p, '/');
if (q) {
xstrlcat(rhost, q + 1, sizeof(rhost));
xstrlcat(rhost, ".", sizeof(rhost));
strcat(rhost, q + 1);
strcat(rhost, ".");
*q = '\0';
} else {
xstrlcat(rhost, p, sizeof(rhost));
strcat(rhost, p);
}
} while (q);
@@ -175,9 +176,11 @@ passwd_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
p++;
else
p = "type:=nfs;rfs:=/${var0}/${var1};rhost:=${var1};sublink:=${var2};fs:=${autodir}${var3}";
xsnprintf(val, sizeof(val), "var0:=%s;var1:=%s;var2:=%s;var3:=%s;%s",
dir+1, rhost, user, pw->pw_dir, p);
sprintf(val, "var0:=%s;var1:=%s;var2:=%s;var3:=%s;%s",
dir+1, rhost, user, pw->pw_dir, p);
#ifdef DEBUG
dlog("passwd_search: map=%s key=%s -> %s", map, key, val);
#endif /* DEBUG */
if (q)
*q = '.';
*pval = strdup(val);
+15 -13
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/info_union.c
* $Id: info_union.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -80,12 +81,10 @@ union_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
char *mapd = strdup(map + UNION_PREFLEN);
char **v = strsplit(mapd, ':', '\"');
char **p;
size_t l;
for (p = v; p[1]; p++) ;
l = strlen(*p) + 5;
*pval = xmalloc(l);
xsnprintf(*pval, l, "fs:=%s", *p);
*pval = xmalloc(strlen(*p) + 5);
sprintf(*pval, "fs:=%s", *p);
XFREE(mapd);
XFREE(v);
return 0;
@@ -105,7 +104,7 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
(*fn) (m, strdup("/defaults"), strdup("type:=link;opts:=nounmount;sublink:=${key}"));
for (dir = v; *dir; dir++) {
size_t l;
int dlen;
struct dirent *dp;
DIR *dirp = opendir(*dir);
@@ -113,9 +112,11 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
plog(XLOG_USER, "Cannot read directory %s: %m", *dir);
continue;
}
l = strlen(*dir) + 5;
dlen = strlen(*dir);
#ifdef DEBUG
dlog("Reading directory %s...", *dir);
#endif /* DEBUG */
while ((dp = readdir(dirp))) {
char *val, *dpname = &dp->d_name[0];
if (dpname[0] == '.' &&
@@ -123,9 +124,11 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
(dpname[1] == '.' && dpname[2] == '\0')))
continue;
#ifdef DEBUG
dlog("... gives %s", dp->d_name);
val = xmalloc(l);
xsnprintf(val, l + 5, "fs:=%s", *dir);
#endif /* DEBUG */
val = xmalloc(dlen + 5);
sprintf(val, "fs:=%s", *dir);
(*fn) (m, strdup(dp->d_name), val);
}
closedir(dirp);
@@ -135,10 +138,9 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
* Add wildcard entry
*/
{
size_t l = strlen(*(dir-1)) + 5;
char *val = xmalloc(l);
char *val = xmalloc(strlen(dir[-1]) + 5);
xsnprintf(val, l, "fs:=%s", *(dir-1));
sprintf(val, "fs:=%s", dir[-1]);
(*fn) (m, strdup("*"), val);
}
XFREE(mapd);
+396 -340
View File
File diff suppressed because it is too large. Load diff
+201 -115
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/mapc.c
* $Id: mapc.c,v 1.7.2.7 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -84,6 +85,8 @@
#define MREC_PART 1
#define MREC_NONE 0
#define MAX_CHAIN 2048
static struct opt_tab mapc_opt[] =
{
{"all", MAPC_ALL},
@@ -198,17 +201,12 @@ extern int ndbm_search(mnt_map *, char *, char *, char **, time_t *);
extern int ndbm_mtime(mnt_map *, char *, time_t *);
#endif /* HAVE_MAP_NDBM */
/* EXECUTABLE MAPS */
#ifdef HAVE_MAP_EXEC
extern int exec_init(mnt_map *, char *, time_t *);
extern int exec_search(mnt_map *, char *, char *, char **, time_t *);
#endif /* HAVE_MAP_EXEC */
/* FILE MAPS */
#ifdef HAVE_MAP_FILE
extern int file_init_or_mtime(mnt_map *, char *, time_t *);
extern int file_init(mnt_map *, char *, time_t *);
extern int file_reload(mnt_map *, char *, add_fn *);
extern int file_search(mnt_map *, char *, char *, char **, time_t *);
extern int file_mtime(mnt_map *, char *, time_t *);
#endif /* HAVE_MAP_FILE */
@@ -304,25 +302,14 @@ static map_type maptypes[] =
#ifdef HAVE_MAP_FILE
{
"file",
file_init_or_mtime,
file_init,
file_reload,
NULL, /* isup function */
file_search,
file_init_or_mtime,
file_mtime,
MAPC_ALL
},
#endif /* HAVE_MAP_FILE */
#ifdef HAVE_MAP_EXEC
{
"exec",
exec_init,
error_reload,
NULL, /* isup function */
exec_search,
error_mtime,
MAPC_INC
},
#endif /* HAVE_MAP_EXEC */
{
"error",
error_init,
@@ -350,27 +337,16 @@ kvhash_of(char *key)
void
mapc_showtypes(char *buf, size_t l)
mapc_showtypes(char *buf)
{
map_type *mt=NULL, *lastmt;
int linesize = 0, i;
map_type *mt;
char *sep = "";
i = sizeof(maptypes) / sizeof(maptypes[0]);
lastmt = maptypes + i;
buf[0] = '\0';
for (mt = maptypes; mt < lastmt; mt++) {
xstrlcat(buf, mt->name, l);
if (mt == (lastmt-1))
break; /* if last one, don't do xstrlcat's that follows */
linesize += strlen(mt->name);
if (--i > 0) {
xstrlcat(buf, ", ", l);
linesize += 2;
}
if (linesize > 54) {
linesize = 0;
xstrlcat(buf, "\n\t\t ", l);
}
for (mt = maptypes; mt < maptypes + sizeof(maptypes) / sizeof(maptypes[0]); mt++) {
strcat(buf, sep);
strcat(buf, mt->name);
sep = ", ";
}
}
@@ -410,7 +386,9 @@ mapc_add_kv(mnt_map *m, char *key, char *val)
regex_t re;
#endif /* HAVE_REGEXEC */
#ifdef DEBUG
dlog("add_kv: %s -> %s", key, val);
#endif /* DEBUG */
#ifdef HAVE_REGEXEC
if (MAPC_ISRE(m)) {
@@ -420,7 +398,7 @@ mapc_add_kv(mnt_map *m, char *key, char *val)
/*
* Make sure the string is bound to the start and end
*/
xsnprintf(pattern, sizeof(pattern), "^%s$", key);
sprintf(pattern, "^%s$", key);
retval = regcomp(&re, pattern, REG_ICASE);
if (retval != 0) {
char errstr[256];
@@ -514,12 +492,11 @@ mapc_find_wildcard(mnt_map *m)
* Do a map reload.
* Attempt to reload without losing current data by switching the hashes
* round.
* If reloading was needed and succeeded, return 1; else return 0.
*/
static int
static void
mapc_reload_map(mnt_map *m)
{
int error, ret = 0;
int error;
kv *maphash[NKVHASH], *tmphash[NKVHASH];
time_t t;
@@ -535,9 +512,11 @@ mapc_reload_map(mnt_map *m)
if (m->reloads != 0 && do_mapc_reload != 0) {
if (t <= m->modify) {
plog(XLOG_INFO, "reload of map %s is not needed (in sync)", m->map_name);
#ifdef DEBUG
dlog("map %s last load time is %d, last modify time is %d",
m->map_name, (int) m->modify, (int) t);
return ret;
#endif /* DEBUG */
return;
}
}
@@ -545,7 +524,9 @@ mapc_reload_map(mnt_map *m)
memcpy((voidp) maphash, (voidp) m->kvhash, sizeof(m->kvhash));
memset((voidp) m->kvhash, 0, sizeof(m->kvhash));
#ifdef DEBUG
dlog("calling map reload on %s", m->map_name);
#endif /* DEBUG */
error = (*m->reload) (m, m->map_name, mapc_add_kv);
if (error) {
if (m->reloads == 0)
@@ -566,15 +547,15 @@ mapc_reload_map(mnt_map *m)
mapc_clear(m);
memcpy((voidp) m->kvhash, (voidp) tmphash, sizeof(m->kvhash));
m->modify = t;
ret = 1;
}
m->wildcard = 0;
#ifdef DEBUG
dlog("calling mapc_search for wildcard");
#endif /* DEBUG */
error = mapc_search(m, wildcard, &m->wildcard);
if (error)
m->wildcard = 0;
return ret;
}
@@ -586,7 +567,7 @@ mapc_create(char *map, char *opt, const char *type)
{
mnt_map *m = ALLOC(struct mnt_map);
map_type *mt;
time_t modify = 0;
time_t modify;
int alloc = 0;
cmdoption(opt, mapc_opt, &alloc);
@@ -622,7 +603,9 @@ mapc_create(char *map, char *opt, const char *type)
for (mt = maptypes;
mt < maptypes + sizeof(maptypes) / sizeof(maptypes[0]);
mt++) {
#ifdef DEBUG
dlog("trying to initialize map %s of type %s ...", map, mt->name);
#endif /* DEBUG */
if ((*mt->init) (m, map, &modify) == 0) {
break;
}
@@ -669,7 +652,9 @@ mapc_create(char *map, char *opt, const char *type)
#endif /* HAVE_REGEXEC */
}
#ifdef DEBUG
dlog("Map for %s coming from maptype %s", map, mt->name);
#endif /* DEBUG */
m->alloc = alloc;
m->reload = mt->reload;
@@ -682,8 +667,6 @@ mapc_create(char *map, char *opt, const char *type)
m->refc = 1;
m->wildcard = 0;
m->reloads = 0;
/* Unfortunately with current code structure, this cannot be initialized here */
m->cfm = NULL;
/*
* synchronize cache with reality
@@ -749,7 +732,7 @@ mapc_find(char *map, char *opt, const char *maptype)
* add it to the list of maps
*/
ITER(m, mnt_map, &map_list_head)
if (STREQ(m->map_name, map))
if (STREQ(m->map_name, map))
return mapc_dup(m);
m = mapc_create(map, opt, maptype);
ins_que(&m->hdr, &map_list_head);
@@ -762,9 +745,9 @@ mapc_find(char *map, char *opt, const char *maptype)
* Free a map.
*/
void
mapc_free(opaque_t arg)
mapc_free(voidp v)
{
mnt_map *m = (mnt_map *) arg;
mnt_map *m = v;
/*
* Decrement the reference count.
@@ -900,15 +883,12 @@ mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse)
* For example:
* "src/gnu/gcc" -> "src / gnu / *" -> "src / *"
*/
xstrlcpy(wildname, key, sizeof(wildname));
strcpy(wildname, key);
while (error && (subp = strrchr(wildname, '/'))) {
/*
* sizeof space left in subp is sizeof wildname minus what's left
* after the strchr above returned a pointer inside wildname into
* subp.
*/
xstrlcpy(subp, "/*", sizeof(wildname) - (subp - wildname));
strcpy(subp, "/*");
#ifdef DEBUG
dlog("mapc recurses on %s", wildname);
#endif /* DEBUG */
error = mapc_meta_search(m, wildname, pval, MREC_PART);
if (error)
*subp = 0;
@@ -937,42 +917,25 @@ mapc_search(mnt_map *m, char *key, char **pval)
static void
mapc_sync(mnt_map *m)
{
int need_mtime_update = 0;
if (m->alloc != MAPC_ROOT) {
if (m->alloc == MAPC_ROOT)
return; /* nothing to do */
/* do not clear map if map service is down */
if (m->isup) {
if (!((*m->isup)(m, m->map_name))) {
plog(XLOG_ERROR, "mapc_sync: map %s is down: not clearing map", m->map_name);
return;
/* do not clear map if map service is down */
if (m->isup) {
if (!((*m->isup)(m, m->map_name))) {
plog(XLOG_ERROR, "mapc_sync: map %s is down: not clearing map", m->map_name);
return;
}
}
}
if (m->alloc >= MAPC_ALL) {
/* mapc_reload_map() always works */
need_mtime_update = mapc_reload_map(m);
} else {
mapc_clear(m);
/*
* Attempt to find the wildcard entry
*/
mapc_find_wildcard(m);
need_mtime_update = 1; /* because mapc_clear always works */
}
/*
* To be safe, update the mtime of the mnt_map's own node, so that the
* kernel will flush all of its cached entries.
*/
if (need_mtime_update && m->cfm) {
am_node *mp = find_ap(m->cfm->cfm_dir);
if (mp) {
clocktime(&mp->am_fattr.na_mtime);
if (m->alloc >= MAPC_ALL) {
/* mapc_reload_map() always works */
mapc_reload_map(m);
} else {
plog(XLOG_ERROR, "cannot find map %s to update its mtime",
m->cfm->cfm_dir);
mapc_clear(m);
/*
* Attempt to find the wildcard entry
*/
mapc_find_wildcard(m);
}
}
}
@@ -1009,7 +972,7 @@ mapc_reload(void)
static int
root_init(mnt_map *m, char *map, time_t *tp)
{
*tp = clocktime(NULL);
*tp = clocktime();
return STREQ(map, ROOT_MAP) ? 0 : ENOENT;
}
@@ -1044,39 +1007,36 @@ root_newmap(const char *dir, const char *opts, const char *map, const cf_map_t *
if (cfm) {
if (map) {
xsnprintf(str, sizeof(str),
"cache:=mapdefault;type:=toplvl;mount_type:=%s;fs:=\"%s\"",
cfm->cfm_flags & CFM_MOUNT_TYPE_AUTOFS ? "autofs" : "nfs",
get_full_path(map, cfm->cfm_search_path, cfm->cfm_type));
sprintf(str, "cache:=mapdefault;type:=toplvl;fs:=\"%s\"",
get_full_path(map, cfm->cfm_search_path, cfm->cfm_type));
if (opts && opts[0] != '\0') {
xstrlcat(str, ";", sizeof(str));
xstrlcat(str, opts, sizeof(str));
strcat(str, ";");
strcat(str, opts);
}
if (cfm->cfm_flags & CFM_BROWSABLE_DIRS_FULL)
xstrlcat(str, ";opts:=rw,fullybrowsable", sizeof(str));
strcat(str, ";opts:=rw,fullybrowsable");
if (cfm->cfm_flags & CFM_BROWSABLE_DIRS)
xstrlcat(str, ";opts:=rw,browsable", sizeof(str));
strcat(str, ";opts:=rw,browsable");
if (cfm->cfm_type) {
xstrlcat(str, ";maptype:=", sizeof(str));
xstrlcat(str, cfm->cfm_type, sizeof(str));
strcat(str, ";maptype:=");
strcat(str, cfm->cfm_type);
}
} else {
xstrlcpy(str, opts, sizeof(str));
strcpy(str, opts);
}
} else {
if (map)
xsnprintf(str, sizeof(str),
"cache:=mapdefault;type:=toplvl;fs:=\"%s\";%s",
map, opts ? opts : "");
sprintf(str, "cache:=mapdefault;type:=toplvl;fs:=\"%s\";%s",
map, opts ? opts : "");
else
xstrlcpy(str, opts, sizeof(str));
strcpy(str, opts);
}
mapc_repl_kv(root_map, strdup((char *)dir), strdup(str));
}
int
mapc_keyiter(mnt_map *m, key_fun *fn, opaque_t arg)
mapc_keyiter(mnt_map *m, void (*fn) (char *, voidp), voidp arg)
{
int i;
int c = 0;
@@ -1096,10 +1056,10 @@ mapc_keyiter(mnt_map *m, key_fun *fn, opaque_t arg)
/*
* Iterate on the root map and call (*fn)() on the key of all the nodes.
* Returns the number of entries in the root map.
* Finally throw away the root map.
*/
int
root_keyiter(key_fun *fn, opaque_t arg)
root_keyiter(void (*fn)(char *, voidp), voidp arg)
{
if (root_map) {
int c = mapc_keyiter(root_map, fn, arg);
@@ -1110,6 +1070,132 @@ root_keyiter(key_fun *fn, opaque_t arg)
}
/*
* Was: NEW_TOPLVL_READDIR
* Search a chain for an entry with some name.
* -Erez Zadok <ezk@cs.columbia.edu>
*/
static int
key_already_in_chain(char *keyname, const nfsentry *chain)
{
const nfsentry *tmpchain = chain;
while (tmpchain) {
if (keyname && tmpchain->ne_name && STREQ(keyname, tmpchain->ne_name))
return 1;
tmpchain = tmpchain->ne_nextentry;
}
return 0;
}
/*
* Create a chain of entries which are not linked.
* -Erez Zadok <ezk@cs.columbia.edu>
*/
nfsentry *
make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable)
{
static u_int last_cookie = (u_int) 2; /* monotonically increasing */
static nfsentry chain[MAX_CHAIN];
static int max_entries = MAX_CHAIN;
char *key;
int num_entries = 0, preflen = 0, i;
nfsentry *retval = (nfsentry *) NULL;
mntfs *mf;
mnt_map *mmp;
if (!mp) {
plog(XLOG_DEBUG, "make_entry_chain: mp is (NULL)");
return retval;
}
mf = mp->am_mnt;
if (!mf) {
plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt is (NULL)");
return retval;
}
mmp = (mnt_map *) mf->mf_private;
if (!mmp) {
plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt->mf_private is (NULL)");
return retval;
}
if (mp->am_pref)
preflen = strlen(mp->am_pref);
/* iterate over keys */
for (i = 0; i < NKVHASH; i++) {
kv *k;
for (k = mmp->kvhash[i]; k ; k = k->next) {
/*
* Skip unwanted entries which are either not real entries or
* very difficult to interpret (wildcards...) This test needs
* lots of improvement. Any takers?
*/
key = k->key;
if (!key)
continue;
/* Skip '*' */
if (!fully_browsable && strchr(key, '*'))
continue;
/*
* If the map has a prefix-string then check if the key starts with
* this string, and if it does, skip over this prefix. If it has a
* prefix and it doesn't match the start of the key, skip it.
*/
if (preflen && (preflen <= (strlen(key)))) {
if (!NSTREQ(key, mp->am_pref, preflen))
continue;
key += preflen;
} else if (preflen) {
continue;
}
/* no more '/' are allowed, unless browsable_dirs=full was used */
if (!fully_browsable && strchr(key, '/'))
continue;
/* no duplicates allowed */
if (key_already_in_chain(key, current_chain))
continue;
/* fill in a cell and link the entry */
if (num_entries >= max_entries) {
/* out of space */
plog(XLOG_DEBUG, "make_entry_chain: no more space in chain");
if (num_entries > 0) {
chain[num_entries - 1].ne_nextentry = 0;
retval = &chain[0];
}
return retval;
}
/* we have space. put entry in next cell */
++last_cookie;
chain[num_entries].ne_fileid = (u_int) last_cookie;
*(u_int *) chain[num_entries].ne_cookie = (u_int) last_cookie;
chain[num_entries].ne_name = key;
if (num_entries < max_entries - 1) { /* link to next one */
chain[num_entries].ne_nextentry = &chain[num_entries + 1];
}
++num_entries;
} /* end of "while (k)" */
} /* end of "for (i ... NKVHASH ..." */
/* terminate chain */
if (num_entries > 0) {
chain[num_entries - 1].ne_nextentry = 0;
retval = &chain[0];
}
return retval;
}
/*
* Error map
*/
@@ -1174,15 +1260,15 @@ get_full_path(const char *map, const char *path, const char *type)
return map;
/* now break path into components, and search in each */
xstrlcpy(component, path, sizeof(component));
strcpy(component, path);
str = strtok(component, ":");
do {
xstrlcpy(full_path, str, sizeof(full_path));
strcpy(full_path, str);
len = strlen(full_path);
if (full_path[len - 1] != '/') /* add trailing "/" if needed */
xstrlcat(full_path, "/", sizeof(full_path));
xstrlcat(full_path, map, sizeof(full_path));
strcat(full_path, "/");
strcat(full_path, map);
if (access(full_path, R_OK) == 0)
return full_path;
str = strtok(NULL, ":");
+63 -63
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/mntfs.c
* $Id: mntfs.c,v 1.5.2.5 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -70,14 +71,12 @@ static void
init_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)
{
mf->mf_ops = ops;
mf->mf_fsflags = ops->nfs_fs_flags;
mf->mf_fo = mo;
mf->mf_mount = strdup(mp);
mf->mf_info = strdup(info);
mf->mf_auto = strdup(auto_opts);
mf->mf_mopts = strdup(mopts);
mf->mf_remopts = strdup(remopts);
mf->mf_loopdev = NULL;
mf->mf_refc = 1;
mf->mf_flags = 0;
mf->mf_error = -1;
@@ -105,25 +104,17 @@ alloc_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, cha
}
/* 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)
find_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);
#ifdef DEBUG
dlog("Locating mntfs reference to %s", mp);
#endif /* DEBUG */
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))) {
if (STREQ(mf->mf_mount, mp)) {
/*
* Handle cases where error ops are involved
*/
@@ -134,32 +125,35 @@ locate_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, ch
*/
if (mf->mf_ops != &amfs_error_ops)
continue;
return dup_mntfs(mf);
else
return dup_mntfs(mf);
} else { /* ops != &amfs_error_ops */
/*
* If the existing ops are amfs_error_ops
* then continue...
*/
if (mf->mf_ops == &amfs_error_ops)
continue;
}
dlog("mf->mf_flags = %#x", mf->mf_flags);
mf->mf_fo = mo;
if ((mf->mf_flags & MFF_RESTART) && amd_state < Finishing) {
if ((mf->mf_flags & MFF_RESTART) && amd_state == Run) {
/*
* Restart a previously mounted filesystem.
*/
mntfs *mf2 = alloc_mntfs(&amfs_inherit_ops, mo, mp, info, auto_opts, mopts, remopts);
#ifdef DEBUG
dlog("Restarting filesystem %s", mf->mf_mount);
#endif /* DEBUG */
/*
* 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.
* Remember who we are restarting
*/
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;
mf2->mf_private = (voidp) dup_mntfs(mf);
mf2->mf_prfree = free_mntfs;
return mf2;
}
mf->mf_fo = mo;
if (!(mf->mf_flags & (MFF_MOUNTED | MFF_MOUNTING | MFF_UNMOUNTING))) {
fserver *fs;
mf->mf_flags &= ~MFF_ERROR;
@@ -170,7 +164,7 @@ locate_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, ch
mf->mf_info = strealloc(mf->mf_info, info);
if (mf->mf_private && mf->mf_prfree) {
mf->mf_prfree(mf->mf_private);
(*mf->mf_prfree) (mf->mf_private);
mf->mf_private = 0;
}
@@ -183,18 +177,6 @@ locate_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, ch
} /* 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);
}
@@ -207,7 +189,7 @@ new_mntfs(void)
static void
uninit_mntfs(mntfs *mf)
uninit_mntfs(mntfs *mf, int rmd)
{
if (mf->mf_auto)
XFREE(mf->mf_auto);
@@ -220,6 +202,12 @@ uninit_mntfs(mntfs *mf)
if (mf->mf_private && mf->mf_prfree)
(*mf->mf_prfree) (mf->mf_private);
/*
* Clean up any directories that were made
*/
if (rmd && (mf->mf_flags & MFF_MKMNT))
rmdirs(mf->mf_mount);
/* free mf_mount _AFTER_ removing the directories */
if (mf->mf_mount)
XFREE(mf->mf_mount);
@@ -249,7 +237,7 @@ discard_mntfs(voidp v)
/*
* Free memory
*/
uninit_mntfs(mf);
uninit_mntfs(mf, TRUE);
XFREE(mf);
--mntfs_allocated;
@@ -272,27 +260,17 @@ flush_mntfs(void)
void
free_mntfs(opaque_t arg)
free_mntfs(voidp v)
{
mntfs *mf = (mntfs *) arg;
dlog("free_mntfs <%s> type %s mf_refc %d flags %x",
mf->mf_mount, mf->mf_ops->fs_type, mf->mf_refc, mf->mf_flags);
mntfs *mf = v;
/*
* 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)",
if(mf->mf_refc <= 0) {
plog(XLOG_ERROR, "IGNORING free_mntfs for <%s>: refc %d, flags %x",
mf->mf_mount, mf->mf_refc, mf->mf_flags);
return;
}
@@ -314,12 +292,15 @@ free_mntfs(opaque_t arg)
mf->mf_ops->fs_type, mf->mf_mount);
}
if (mf->mf_fsflags & FS_DISCARD) {
if (mf->mf_ops->fs_flags & FS_DISCARD) {
#ifdef DEBUG
dlog("Immediately discarding mntfs for %s", mf->mf_mount);
#endif /* DEBUG */
discard_mntfs(mf);
} else {
#ifdef DEBUG
if (mf->mf_flags & MFF_RESTART) {
dlog("Discarding remount hook for %s", mf->mf_mount);
} else {
@@ -328,6 +309,7 @@ free_mntfs(opaque_t arg)
}
if (mf->mf_flags & (MFF_MOUNTED | MFF_MOUNTING | MFF_UNMOUNTING))
dlog("mntfs reference for %s still active", mf->mf_mount);
#endif /* DEBUG */
mf->mf_cid = timeout(ALLOWED_MOUNT_TIME, discard_mntfs, (voidp) mf);
}
}
@@ -340,7 +322,7 @@ realloc_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *a
mntfs *mf2;
if (mf->mf_refc == 1 &&
mf->mf_flags & MFF_RESTART &&
mf->mf_ops == &amfs_inherit_ops &&
STREQ(mf->mf_mount, mp)) {
/*
* If we are inheriting then just return
@@ -362,5 +344,23 @@ realloc_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *a
mf2 = find_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
free_mntfs(mf);
#if 0
/*
* XXX: EZK IS THIS RIGHT???
* The next "if" statement is what supposedly fixes bgmount() in
* that it will actually use the ops structure of the next mount
* entry, if the previous one failed.
*/
if (mf2 &&
ops &&
mf2->mf_ops != ops &&
mf2->mf_ops != &amfs_inherit_ops &&
mf2->mf_ops != &amfs_toplvl_ops &&
mf2->mf_ops != &amfs_error_ops) {
plog(XLOG_WARNING, "realloc_mntfs: copy fallback ops \"%s\" over \"%s\"",
ops->fs_type, mf2->mf_ops->fs_type);
mf2->mf_ops = ops;
}
#endif
return mf2;
}
+19 -47
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -36,8 +36,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/nfs_prot_svc.c
* $Id: nfs_prot_svc.c,v 1.5.2.6 2004/01/21 04:04:58 ib42 Exp $
* $FreeBSD$
*
*/
@@ -68,7 +70,7 @@ extern nfsreaddirres *nfsproc_readdir_2_svc(nfsreaddirargs *, struct svc_req *);
extern nfsstatfsres *nfsproc_statfs_2_svc(am_nfs_fh *, struct svc_req *);
/* global variables */
SVCXPRT *current_transp;
SVCXPRT *nfs_program_2_transp;
/* typedefs */
typedef char *(*nfssvcproc_t)(voidp, struct svc_req *);
@@ -97,60 +99,30 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
char *result;
xdrproc_t xdr_argument, xdr_result;
nfssvcproc_t local;
#ifdef HAVE_TRANSPORT_TYPE_TLI
/*
* On TLI systems we don't use an INET network type, but a "ticlts" (see
* /etc/netconfig and conf/transp_tli.c:create_nfs_service). This means
* that packets could only come from the loopback interface, and we don't
* need to check them and filter possibly spoofed packets. Therefore we
* only need to check if the UID caller is correct.
*/
# ifdef HAVE___RPC_GET_LOCAL_UID
uid_t u;
/* extern definition for an internal libnsl function */
extern int __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid);
if (__rpc_get_local_uid(transp, &u) >= 0 && u != 0) {
plog(XLOG_WARNING, "ignoring request from UID %ld, must be 0", (long) u);
return;
}
# else /* not HAVE___RPC_GET_LOCAL_UID */
dlog("cannot verify local uid for rpc request");
# endif /* HAVE___RPC_GET_LOCAL_UID */
#else /* not HAVE_TRANPORT_TYPE_TLI */
struct sockaddr_in *sinp;
char dq[20], dq2[28];
sinp = amu_svc_getcaller(rqstp->rq_xprt);
# ifdef MNT2_NFS_OPT_RESVPORT
#ifdef MNT2_NFS_OPT_RESVPORT
/* Verify that the request comes from a reserved port */
if (sinp &&
ntohs(sinp->sin_port) >= IPPORT_RESERVED &&
if ((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),
inet_dquad(dq, sinp->sin_addr.s_addr),
ntohs(sinp->sin_port));
return;
}
# endif /* MNT2_NFS_OPT_RESVPORT */
#endif /* MNT2_NFS_OPT_RESVPORT */
/* if the address does not match, ignore the request */
if (sinp && (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;
}
if (sinp->sin_addr.s_addr && sinp->sin_addr.s_addr != myipaddr.s_addr) {
plog(XLOG_WARNING, "ignoring request from %s:%u, expected %s",
inet_dquad(dq, sinp->sin_addr.s_addr),
ntohs(sinp->sin_port),
inet_dquad(dq2, myipaddr.s_addr));
return;
}
#endif /* not HAVE_TRANPORT_TYPE_TLI */
current_transp = NULL;
nfs_program_2_transp = NULL;
switch (rqstp->rq_proc) {
@@ -187,7 +159,7 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
* be stored in the am_node structure and later used for
* quick_reply().
*/
current_transp = transp;
nfs_program_2_transp = transp;
break;
case NFSPROC_READLINK:
@@ -285,7 +257,7 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
}
result = (*local) (&argument, rqstp);
current_transp = NULL;
nfs_program_2_transp = NULL;
if (result != NULL && !svc_sendreply(transp,
(XDRPROC_T_TYPE) xdr_result,
+86 -86
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/nfs_start.c
* $Id: nfs_start.c,v 1.5.2.7 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -51,8 +52,8 @@
# define SELECT_MAXWAIT 16
#endif /* not SELECT_MAXWAIT */
SVCXPRT *nfsxprt = NULL;
u_short nfs_port = 0;
SVCXPRT *nfsxprt;
u_short nfs_port;
#ifndef HAVE_SIGACTION
# define MASKED_SIGS (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGCHLD)|sigmask(SIGHUP))
@@ -91,9 +92,7 @@ checkup(void)
}
}
#else /* not DEBUG */
#define checkup()
#endif /* not DEBUG */
#endif /* DEBUG */
static int
@@ -121,6 +120,10 @@ do_select(int smask, int fds, fd_set *fdp, struct timeval *tvp)
errno = EINTR;
} else {
select_intr_valid = 1;
/*
* Invalidate the current clock value
*/
clock_valid = 0;
/*
* Allow interrupts. If a signal
* occurs, then it will cause a longjmp
@@ -148,9 +151,9 @@ do_select(int smask, int fds, fd_set *fdp, struct timeval *tvp)
/*
* Perhaps reload the cache?
*/
if (do_mapc_reload < clocktime(NULL)) {
if (do_mapc_reload < clocktime()) {
mapc_reload();
do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval;
do_mapc_reload = clocktime() + ONE_HOUR;
}
return nsel;
}
@@ -165,17 +168,26 @@ rpc_pending_now(void)
{
struct timeval tvv;
int nsel;
#ifdef FD_SET
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(fwd_sock, &readfds);
#else /* not FD_SET */
int readfds = (1 << fwd_sock);
#endif /* not FD_SET */
tvv.tv_sec = tvv.tv_usec = 0;
nsel = select(FD_SETSIZE, &readfds, (fd_set *) 0, (fd_set *) 0, &tvv);
if (nsel < 1)
return (0);
#ifdef FD_SET
if (FD_ISSET(fwd_sock, &readfds))
return (1);
#else /* not FD_SET */
if (readfds & (1 << fwd_sock))
return (1);
#endif /* not FD_SET */
return (0);
}
@@ -191,7 +203,7 @@ run_rpc(void)
int smask = sigblock(MASKED_SIGS);
#endif /* not HAVE_SIGACTION */
next_softclock = clocktime(NULL);
next_softclock = clocktime();
amd_state = Run;
@@ -204,27 +216,31 @@ run_rpc(void)
struct timeval tvv;
int nsel;
time_t now;
#ifdef HAVE_SVC_GETREQSET
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);
#else /* not HAVE_SVC_GETREQSET */
# ifdef FD_SET
fd_set readfds;
FD_ZERO(&readfds);
readfds.fds_bits[0] = svc_fds;
FD_SET(fwd_sock, &readfds);
# else /* not FD_SET */
int readfds = svc_fds | (1 << fwd_sock);
# endif /* not FD_SET */
#endif /* not HAVE_SVC_GETREQSET */
#ifdef DEBUG
checkup();
#endif /* DEBUG */
/*
* If the full timeout code is not called,
* then recompute the time delta manually.
*/
now = clocktime(NULL);
now = clocktime();
if (next_softclock <= now) {
if (amd_state == Finishing)
@@ -235,30 +251,29 @@ run_rpc(void)
}
tvv.tv_usec = 0;
if (amd_state == Finishing && get_exported_ap(0) == NULL) {
if (amd_state == Finishing && last_used_map < 0) {
flush_mntfs();
amd_state = Quit;
break;
}
#ifdef HAVE_FS_AUTOFS
autofs_add_fdset(&readfds);
#endif /* HAVE_FS_AUTOFS */
if (tvv.tv_sec <= 0)
tvv.tv_sec = SELECT_MAXWAIT;
#ifdef DEBUG
if (tvv.tv_sec) {
dlog("Select waits for %ds", (int) tvv.tv_sec);
} else {
dlog("Select waits for Godot");
}
#endif /* DEBUG */
nsel = do_select(smask, FD_SETSIZE, &readfds, &tvv);
switch (nsel) {
case -1:
if (errno == EINTR) {
#ifdef DEBUG
dlog("select interrupted");
#endif /* DEBUG */
continue;
}
plog(XLOG_ERROR, "select: %m");
@@ -269,22 +284,22 @@ run_rpc(void)
default:
/*
* Read all pending NFS responses at once to avoid having responses
* Read all pending NFS responses at once to avoid having responses.
* queue up as a consequence of retransmissions.
*/
#ifdef FD_SET
if (FD_ISSET(fwd_sock, &readfds)) {
FD_CLR(fwd_sock, &readfds);
#else /* not FD_SET */
if (readfds & (1 << fwd_sock)) {
readfds &= ~(1 << fwd_sock);
#endif /* not FD_SET */
--nsel;
do {
fwd_reply();
} while (rpc_pending_now() > 0);
}
#ifdef HAVE_FS_AUTOFS
if (nsel)
nsel = autofs_handle_fdset(&readfds, nsel);
#endif /* HAVE_FS_AUTOFS */
if (nsel) {
/*
* Anything left must be a normal
@@ -293,11 +308,11 @@ run_rpc(void)
#ifdef HAVE_SVC_GETREQSET
svc_getreqset(&readfds);
#else /* not HAVE_SVC_GETREQSET */
# ifdef HAVE_FD_SET_FDS_BITS
# ifdef FD_SET
svc_getreq(readfds.fds_bits[0]);
# else /* not HAVE_FD_SET_FDS_BITS */
# else /* not FD_SET */
svc_getreq(readfds);
# endif /* not HAVE_FD_SET_FDS_BITS */
# endif /* not FD_SET */
#endif /* not HAVE_SVC_GETREQSET */
}
break;
@@ -329,16 +344,26 @@ mount_automounter(int ppid)
int nmount, ret;
int soNFS;
int udp_soAMQ, tcp_soAMQ;
#ifdef HAVE_TRANSPORT_TYPE_TLI
struct netconfig *udp_amqncp, *tcp_amqncp;
#endif /* HAVE_TRANSPORT_TYPE_TLI */
/*
* 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.
* Create the nfs service for amd
*/
if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS)
restart_automounter_nodes();
#ifdef HAVE_TRANSPORT_TYPE_TLI
ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
if (ret != 0)
return ret;
ret = create_amq_service(&udp_soAMQ, &udp_amqp, &udp_amqncp, &tcp_soAMQ, &tcp_amqp, &tcp_amqncp);
#else /* not HAVE_TRANSPORT_TYPE_TLI */
ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
if (ret != 0)
return ret;
ret = create_amq_service(&udp_soAMQ, &udp_amqp, &tcp_soAMQ, &tcp_amqp);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
if (ret != 0)
return ret;
/*
* Start RPC forwarding
@@ -359,46 +384,6 @@ mount_automounter(int ppid)
if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS)
restart();
/*
* Create the nfs service for amd
* If nfs_port is already initialized, it means we
* already created the service during restart_automounter_nodes().
*/
if (nfs_port == 0) {
ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
if (ret != 0)
return ret;
}
xsnprintf(pid_fsname, sizeof(pid_fsname), "%s:(pid%ld,port%u)",
am_get_hostname(), (long) am_mypid, nfs_port);
/* security: if user sets -D amq, don't even create listening socket */
if (!amuDebug(D_AMQ)) {
ret = create_amq_service(&udp_soAMQ,
&udp_amqp,
&udp_amqncp,
&tcp_soAMQ,
&tcp_amqp,
&tcp_amqncp,
gopt.preferred_amq_port);
if (ret != 0)
return ret;
}
#ifdef HAVE_FS_AUTOFS
if (amd_use_autofs) {
/*
* Create the autofs service for amd.
*/
ret = create_autofs_service();
/* if autofs service fails it is OK if using a test amd */
if (ret != 0) {
plog(XLOG_WARNING, "autofs service registration failed, turning off autofs support");
amd_use_autofs = 0;
}
}
#endif /* HAVE_FS_AUTOFS */
/*
* Mount the top-level auto-mountpoints
*/
@@ -416,26 +401,41 @@ mount_automounter(int ppid)
return 0;
}
if (!amuDebug(D_AMQ)) {
#ifdef DEBUG
amuDebug(D_AMQ) {
#endif /* DEBUG */
/*
* Complete registration of amq (first TCP service then UDP)
*/
unregister_amq();
ret = amu_svc_register(tcp_amqp, get_amd_program_number(), AMQ_VERSION,
amq_program_1, IPPROTO_TCP, tcp_amqncp);
#ifdef HAVE_TRANSPORT_TYPE_TLI
ret = svc_reg(tcp_amqp, get_amd_program_number(), AMQ_VERSION,
amq_program_1, tcp_amqncp);
#else /* not HAVE_TRANSPORT_TYPE_TLI */
ret = svc_register(tcp_amqp, get_amd_program_number(), AMQ_VERSION,
amq_program_1, IPPROTO_TCP);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
if (ret != 1) {
plog(XLOG_FATAL, "unable to register (AMQ_PROGRAM=%d, AMQ_VERSION, tcp)", get_amd_program_number());
return 3;
}
ret = amu_svc_register(udp_amqp, get_amd_program_number(), AMQ_VERSION,
amq_program_1, IPPROTO_UDP, udp_amqncp);
#ifdef HAVE_TRANSPORT_TYPE_TLI
ret = svc_reg(udp_amqp, get_amd_program_number(), AMQ_VERSION,
amq_program_1, udp_amqncp);
#else /* not HAVE_TRANSPORT_TYPE_TLI */
ret = svc_register(udp_amqp, get_amd_program_number(), AMQ_VERSION,
amq_program_1, IPPROTO_UDP);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
if (ret != 1) {
plog(XLOG_FATAL, "unable to register (AMQ_PROGRAM=%d, AMQ_VERSION, udp)", get_amd_program_number());
return 4;
}
#ifdef DEBUG
}
#endif /* DEBUG */
/*
* Start timeout_mp rolling
+81 -278
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/nfs_subr.c
* $Id: nfs_subr.c,v 1.6.2.6 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -56,45 +57,19 @@
# define nfs_error(e) ((nfsstat)(e))
#endif /* nfs_error */
/*
* File Handle structure
*
* This is interpreted by indexing the exported array
* by fhh_id (for old-style filehandles), or by retrieving
* the node name from fhh_path (for new-style filehandles).
*
* The whole structure is mapped onto a standard fhandle_t
* when transmitted.
*/
struct am_fh {
u_int fhh_gen; /* generation number */
union {
struct {
int fhh_type; /* old or new am_fh */
pid_t fhh_pid; /* process id */
int fhh_id; /* map id */
} s;
char fhh_path[NFS_FHSIZE-sizeof(u_int)]; /* path to am_node */
} u;
};
/* forward declarations */
/* converting am-filehandles to mount-points */
static am_node *fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop);
static am_node *fh_to_mp(am_nfs_fh *fhp);
static void count_map_entries(const am_node *mp, u_int *out_blocks, u_int *out_bfree, u_int *out_bavail);
static char *
do_readlink(am_node *mp, int *error_return)
do_readlink(am_node *mp, int *error_return, nfsattrstat **attrpp)
{
char *ln;
/*
* If there is a readlink method then use it,
* otherwise if a link exists use that,
* otherwise use the mount point.
* If there is a readlink method, then use
* that, otherwise if a link exists use
* that, otherwise use the mount point.
*/
if (mp->am_mnt->mf_ops->readlink) {
int retry = 0;
@@ -111,6 +86,8 @@ do_readlink(am_node *mp, int *error_return)
} else {
ln = mp->am_mnt->mf_mount;
}
if (attrpp)
*attrpp = &mp->am_attr;
return ln;
}
@@ -131,38 +108,46 @@ nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
static nfsattrstat res;
am_node *mp;
int retry;
time_t now = clocktime(NULL);
time_t now = clocktime();
if (amuDebug(D_TRACE))
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "getattr:");
#endif /* DEBUG */
mp = fh_to_mp3(argp, &retry, VLOOK_CREATE);
mp = fh_to_mp2(argp, &retry);
if (mp == 0) {
if (amuDebug(D_TRACE))
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "\tretry=%d", retry);
#endif /* DEBUG */
if (retry < 0) {
amd_stats.d_drops++;
return 0;
}
res.ns_status = nfs_error(retry);
return &res;
} else {
nfsattrstat *attrp = &mp->am_attr;
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "\tstat(%s), size = %d, mtime=%ld",
mp->am_path,
(int) attrp->ns_u.ns_attr_u.na_size,
(long) attrp->ns_u.ns_attr_u.na_mtime.nt_seconds);
#endif /* DEBUG */
/* Delay unmount of what was looked up */
if (mp->am_timeo_w < 4 * gopt.am_timeo_w)
mp->am_timeo_w += gopt.am_timeo_w;
mp->am_ttl = now + mp->am_timeo_w;
mp->am_stats.s_getattr++;
return attrp;
}
res = mp->am_attr;
if (amuDebug(D_TRACE))
plog(XLOG_DEBUG, "\tstat(%s), size = %d, mtime=%ld.%ld",
mp->am_path,
(int) res.ns_u.ns_attr_u.na_size,
(long) res.ns_u.ns_attr_u.na_mtime.nt_seconds,
(long) res.ns_u.ns_attr_u.na_mtime.nt_useconds);
/* Delay unmount of what was looked up */
if (mp->am_timeo_w < 4 * gopt.am_timeo_w)
mp->am_timeo_w += gopt.am_timeo_w;
mp->am_ttl = now + mp->am_timeo_w;
mp->am_stats.s_getattr++;
return &res;
}
@@ -199,16 +184,18 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
uid_t uid;
gid_t gid;
if (amuDebug(D_TRACE))
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "lookup:");
#endif /* DEBUG */
/* finally, find the effective uid/gid from RPC request */
if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0)
plog(XLOG_ERROR, "cannot get uid/gid from RPC credentials");
xsnprintf(opt_uid, sizeof(uid_str), "%d", (int) uid);
xsnprintf(opt_gid, sizeof(gid_str), "%d", (int) gid);
sprintf(opt_uid, "%d", (int) uid);
sprintf(opt_gid, "%d", (int) gid);
mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_CREATE);
mp = fh_to_mp2(&argp->da_fhandle, &retry);
if (mp == 0) {
if (retry < 0) {
amd_stats.d_drops++;
@@ -218,11 +205,11 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
} else {
int error;
am_node *ap;
if (amuDebug(D_TRACE))
plog(XLOG_DEBUG, "\tlookup(%s, %s)", mp->am_path, argp->da_name);
ap = mp->am_mnt->mf_ops->lookup_child(mp, argp->da_name, &error, VLOOK_CREATE);
if (ap && error < 0)
ap = mp->am_mnt->mf_ops->mount_child(ap, &error);
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "\tlookuppn(%s, %s)", mp->am_path, argp->da_name);
#endif /* DEBUG */
ap = (*mp->am_mnt->mf_ops->lookuppn) (mp, argp->da_name, &error, VLOOK_CREATE);
if (ap == 0) {
if (error < 0) {
amd_stats.d_drops++;
@@ -250,7 +237,7 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
void
nfs_quick_reply(am_node *mp, int error)
quick_reply(am_node *mp, int error)
{
SVCXPRT *transp = mp->am_transp;
nfsdiropres res;
@@ -284,8 +271,11 @@ nfs_quick_reply(am_node *mp, int error)
/*
* Free up transp. It's only used for one reply.
*/
XFREE(mp->am_transp);
XFREE(transp);
mp->am_transp = NULL;
#ifdef DEBUG
dlog("Quick reply sent for %s", mp->am_mnt->mf_mount);
#endif /* DEBUG */
}
}
@@ -297,10 +287,12 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
am_node *mp;
int retry;
if (amuDebug(D_TRACE))
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "readlink:");
#endif /* DEBUG */
mp = fh_to_mp3(argp, &retry, VLOOK_CREATE);
mp = fh_to_mp2(argp, &retry);
if (mp == 0) {
readlink_retry:
if (retry < 0) {
@@ -309,12 +301,15 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
}
res.rlr_status = nfs_error(retry);
} else {
char *ln = do_readlink(mp, &retry);
char *ln = do_readlink(mp, &retry, (nfsattrstat **) 0);
if (ln == 0)
goto readlink_retry;
res.rlr_status = NFS_OK;
if (amuDebug(D_TRACE) && ln)
plog(XLOG_DEBUG, "\treadlink(%s) = %s", mp->am_path, ln);
#ifdef DEBUG
amuDebug(D_TRACE)
if (ln)
plog(XLOG_DEBUG, "\treadlink(%s) = %s", mp->am_path, ln);
#endif /* DEBUG */
res.rlr_u.rlr_data_u = ln;
mp->am_stats.s_readlink++;
}
@@ -393,10 +388,12 @@ unlink_or_rmdir(nfsdiropargs *argp, struct svc_req *rqstp, int unlinkp)
goto out;
}
if (amuDebug(D_TRACE))
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "\tremove(%s, %s)", mp->am_path, argp->da_name);
#endif /* DEBUG */
mp = mp->am_mnt->mf_ops->lookup_child(mp, argp->da_name, &retry, VLOOK_DELETE);
mp = (*mp->am_mnt->mf_ops->lookuppn) (mp, argp->da_name, &retry, VLOOK_DELETE);
if (mp == 0) {
/*
* Ignore retries...
@@ -506,10 +503,12 @@ nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
am_node *mp;
int retry;
if (amuDebug(D_TRACE))
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "readdir:");
#endif /* DEBUG */
mp = fh_to_mp3(&argp->rda_fhandle, &retry, VLOOK_CREATE);
mp = fh_to_mp2(&argp->rda_fhandle, &retry);
if (mp == 0) {
if (retry < 0) {
amd_stats.d_drops++;
@@ -517,8 +516,10 @@ nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
}
res.rdr_status = nfs_error(retry);
} else {
if (amuDebug(D_TRACE))
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "\treaddir(%s)", mp->am_path);
#endif /* DEBUG */
res.rdr_status = nfs_error((*mp->am_mnt->mf_ops->readdir)
(mp, argp->rda_cookie,
&res.rdr_u.rdr_reply_u, e_res, argp->rda_count));
@@ -537,10 +538,12 @@ nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
int retry;
mntent_t mnt;
if (amuDebug(D_TRACE))
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "statfs:");
#endif /* DEBUG */
mp = fh_to_mp3(argp, &retry, VLOOK_CREATE);
mp = fh_to_mp2(argp, &retry);
if (mp == 0) {
if (retry < 0) {
amd_stats.d_drops++;
@@ -549,8 +552,10 @@ nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
res.sfr_status = nfs_error(retry);
} else {
nfsstatfsokres *fp;
if (amuDebug(D_TRACE))
#ifdef DEBUG
amuDebug(D_TRACE)
plog(XLOG_DEBUG, "\tstat_fs(%s)", mp->am_path);
#endif /* DEBUG */
/*
* just return faked up file system information
@@ -564,7 +569,7 @@ nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
if ((gopt.flags & CFM_SHOW_STATFS_ENTRIES) &&
mp->am_mnt && mp->am_mnt->mf_mopts) {
mnt.mnt_opts = mp->am_mnt->mf_mopts;
if (amu_hasmntopt(&mnt, "browsable")) {
if (hasmntopt(&mnt, "browsable")) {
count_map_entries(mp,
&fp->sfrok_blocks,
&fp->sfrok_bfree,
@@ -624,205 +629,3 @@ out:
*out_bfree = bfree;
*out_bavail = bavail;
}
/*
* Convert from file handle to automount node.
*/
static am_node *
fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop)
{
struct am_fh *fp = (struct am_fh *) fhp;
am_node *ap = 0;
if (fp->u.s.fhh_type != 0) {
/* New filehandle type */
int len = sizeof(*fhp) - sizeof(fp->fhh_gen);
char *path = xmalloc(len+1);
/*
* Because fhp is treated as a filehandle we use memcpy
* instead of xstrlcpy.
*/
memcpy(path, (char *) fp->u.fhh_path, len);
path[len] = '\0';
/* dlog("fh_to_mp3: new filehandle: %s", path); */
ap = path_to_exported_ap(path);
XFREE(path);
} else {
/* dlog("fh_to_mp3: old filehandle: %d", fp->u.s.fhh_id); */
/*
* Check process id matches
* If it doesn't then it is probably
* from an old kernel-cached filehandle
* which is now out of date.
*/
if (fp->u.s.fhh_pid != get_server_pid()) {
dlog("fh_to_mp3: wrong pid %ld != my pid %ld",
(long) fp->u.s.fhh_pid, get_server_pid());
goto drop;
}
/*
* Get hold of the supposed mount node
*/
ap = get_exported_ap(fp->u.s.fhh_id);
}
/*
* Check the generation number in the node
* matches the one from the kernel. If not
* then the old node has been timed out and
* a new one allocated.
*/
if (ap != NULL && ap->am_gen != fp->fhh_gen)
ap = 0;
/*
* If it doesn't exists then drop the request
*/
if (!ap)
goto drop;
#if 0
/*
* If the node is hung then locate a new node
* for it. This implements the replicated filesystem
* retries.
*/
if (ap->am_mnt && FSRV_ISDOWN(ap->am_mnt->mf_server) && ap->am_parent) {
int error;
am_node *orig_ap = ap;
dlog("fh_to_mp3: %s (%s) is hung: lookup alternative file server",
orig_ap->am_path, orig_ap->am_mnt->mf_info);
/*
* Update modify time of parent node.
* With any luck the kernel will re-stat
* the child node and get new information.
*/
clocktime(&orig_ap->am_fattr.na_mtime);
/*
* Call the parent's lookup routine for an object
* with the same name. This may return -1 in error
* if a mount is in progress. In any case, if no
* mount node is returned the error code is propagated
* to the caller.
*/
if (vop == VLOOK_CREATE) {
ap = orig_ap->am_parent->am_mnt->mf_ops->lookup_child(orig_ap->am_parent, orig_ap->am_name, &error, vop);
if (ap && error < 0)
ap = orig_ap->am_parent->am_mnt->mf_ops->mount_child(ap, &error);
} else {
ap = 0;
error = ESTALE;
}
if (ap == 0) {
if (error < 0 && amd_state == Finishing)
error = ENOENT;
*rp = error;
return 0;
}
/*
* Update last access to original node. This
* avoids timing it out and so sending ESTALE
* back to the kernel.
* XXX - Not sure we need this anymore (jsp, 90/10/6).
*/
new_ttl(orig_ap);
}
#endif
/*
* Disallow references to objects being unmounted, unless
* they are automount points.
*/
if (ap->am_mnt && (ap->am_mnt->mf_flags & MFF_UNMOUNTING) &&
!(ap->am_flags & AMF_ROOT)) {
if (amd_state == Finishing)
*rp = ENOENT;
else
*rp = -1;
return 0;
}
new_ttl(ap);
drop:
if (!ap || !ap->am_mnt) {
/*
* If we are shutting down then it is likely
* that this node has disappeared because of
* a fast timeout. To avoid things thrashing
* just pretend it doesn't exist at all. If
* ESTALE is returned, some NFS clients just
* keep retrying (stupid or what - if it's
* stale now, what's it going to be in 5 minutes?)
*/
if (amd_state == Finishing)
*rp = ENOENT;
else
*rp = ESTALE;
amd_stats.d_stale++;
}
return ap;
}
static am_node *
fh_to_mp(am_nfs_fh *fhp)
{
int dummy;
return fh_to_mp3(fhp, &dummy, VLOOK_CREATE);
}
/*
* Convert from automount node to file handle.
*/
void
mp_to_fh(am_node *mp, am_nfs_fh *fhp)
{
u_int pathlen;
struct am_fh *fp = (struct am_fh *) fhp;
memset((char *) fhp, 0, sizeof(am_nfs_fh));
/* Store the generation number */
fp->fhh_gen = mp->am_gen;
pathlen = strlen(mp->am_path);
if (pathlen <= sizeof(*fhp) - sizeof(fp->fhh_gen)) {
/* dlog("mp_to_fh: new filehandle: %s", mp->am_path); */
/*
* Because fhp is treated as a filehandle we use memcpy instead of
* xstrlcpy.
*/
memcpy(fp->u.fhh_path, mp->am_path, pathlen); /* making a filehandle */
} else {
/*
* Take the process id
*/
fp->u.s.fhh_pid = get_server_pid();
/*
* ... the map number
*/
fp->u.s.fhh_id = mp->am_mapno;
/*
* ... and the generation number (previously stored)
* to make a "unique" triple that will never
* be reallocated except across reboots (which doesn't matter)
* or if we are unlucky enough to be given the same
* pid as a previous amd (very unlikely).
*/
/* dlog("mp_to_fh: old filehandle: %d", fp->u.s.fhh_id); */
}
}
+17 -29
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/ops_TEMPLATE.c
* $Id: ops_TEMPLATE.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -61,14 +62,16 @@
/* 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 int foofs_mount(am_node *mp);
static int foofs_fmount(mntfs *mf);
static int foofs_umount(am_node *mp);
static int foofs_fumount(mntfs *mf);
static am_node *foofs_lookuppn(am_node *mp, char *fname, int *error_return, int op);
static int foofs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count);
static int foofs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count);
static am_node *foofs_readlink(am_node *mp, int *error_return);
static void foofs_mounted(am_node *am, mntfs *mf);
static void foofs_umounted(am_node *mp, mntfs *mf);
static fserver *foofs_ffserver(mntfs *mf);
static void foofs_mounted(mntfs *mf);
static void foofs_umounted(am_node *mp);
fserver *foofs_ffserver(mntfs *mf);
/*
@@ -81,19 +84,16 @@ am_ops foofs_ops =
foofs_match, /* match */
foofs_init, /* initialize */
foofs_mount, /* mount vnode */
foofs_fmount, /* mount vfs */
foofs_umount, /* unmount vnode */
foofs_lookup_child, /* lookup path-name */
foofs_mount_child, /* mount path-name */
foofs_fumount, /* unmount VFS */
foofs_lookuppn, /* lookup path-name */
foofs_readdir, /* read directory */
foofs_readlink, /* read link */
foofs_mounted, /* after-mount extra actions */
foofs_umounted, /* after-umount extra actions */
foofs_ffserver, /* find a file server */
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 */
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO /* flags */
};
@@ -220,7 +220,7 @@ foofs_lookuppn(am_node *mp, char *fname, int *error_return, int op)
* If OK, fills in ep with chain of directory entries.
*/
static int
foofs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count)
foofs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count)
{
int error = 0;
@@ -284,22 +284,10 @@ foofs_umounted(am_node *mp)
* Find a file server.
* Returns: fserver of found server, or NULL if not found.
*/
static fserver *
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;
}
+27 -40
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/ops_cachefs.c
* $Id: ops_cachefs.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -54,8 +55,8 @@
/* 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);
static int cachefs_fmount(mntfs *mf);
static int cachefs_fumount(mntfs *mf);
/*
@@ -66,20 +67,17 @@ am_ops cachefs_ops =
"cachefs",
cachefs_match,
cachefs_init,
cachefs_mount,
cachefs_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_auto_fmount,
cachefs_fmount,
amfs_auto_fumount,
cachefs_fumount,
amfs_error_lookuppn,
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 */
0, /* post-mount actions */
0, /* post-umount actions */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
};
@@ -96,7 +94,9 @@ cachefs_match(am_opts *fo)
return NULL;
}
#ifdef DEBUG
dlog("CACHEFS: using cache directory \"%s\"", fo->opt_cachedir);
#endif /* DEBUG */
/* determine magic cookie to put in mtab */
return strdup(fo->opt_cachedir);
@@ -113,7 +113,7 @@ cachefs_init(mntfs *mf)
/*
* Save cache directory name
*/
if (!mf->mf_private) {
if (mf->mf_refc == 1) {
mf->mf_private = (voidp) strdup(mf->mf_fo->opt_cachedir);
mf->mf_prfree = (void (*)(voidp)) free;
}
@@ -128,8 +128,7 @@ cachefs_init(mntfs *mf)
* cachedir is the cache directory ($cachedir)
*/
static int
mount_cachefs(char *mntdir, char *backdir, char *cachedir,
char *opts, int on_autofs)
mount_cachefs(char *mntpt, char *backdir, char *cachedir, char *opts)
{
cachefs_args_t ca;
mntent_t mnt;
@@ -143,16 +142,12 @@ mount_cachefs(char *mntdir, char *backdir, char *cachedir,
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = mntdir;
mnt.mnt_dir = mntpt;
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 */
@@ -175,13 +170,8 @@ mount_cachefs(char *mntdir, char *backdir, char *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);
/* append cacheid and mountpoint */
sprintf(ca.cfs_cacheid, "%s:%s", ca.cfs_fsid, mntpt);
/* convert '/' to '_' (Solaris does that...) */
cp = ca.cfs_cacheid;
while ((cp = strpbrk(cp, "/")) != NULL)
@@ -202,21 +192,19 @@ mount_cachefs(char *mntdir, char *backdir, char *cachedir,
/*
* Call generic mount routine
*/
return mount_fs(&mnt, flags, (caddr_t) &ca, 0, type, 0, NULL, mnttab_file_name, on_autofs);
return mount_fs(&mnt, flags, (caddr_t) &ca, 0, type, 0, NULL, mnttab_file_name);
}
static int
cachefs_mount(am_node *am, mntfs *mf)
cachefs_fmount(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);
mf->mf_mopts);
if (error) {
errno = error;
/* according to Solaris, if errno==ESRCH, "options to not match" */
@@ -232,12 +220,11 @@ cachefs_mount(am_node *am, mntfs *mf)
static int
cachefs_umount(am_node *am, mntfs *mf)
cachefs_fumount(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);
error = UMOUNT_FS(mf->mf_mount, mnttab_file_name);
/*
* In the case of cachefs, we must fsck the cache directory. Otherwise,
@@ -252,7 +239,7 @@ cachefs_umount(am_node *am, mntfs *mf)
cachedir = (char *) mf->mf_private;
plog(XLOG_INFO, "running fsck on cache directory \"%s\"", cachedir);
xsnprintf(cmd, sizeof(cmd), "fsck -F cachefs %s", cachedir);
sprintf(cmd, "fsck -F cachefs %s", cachedir);
system(cmd);
}
+33 -42
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/ops_cdfs.c
* $Id: ops_cdfs.c,v 1.4.2.5 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -53,8 +54,8 @@
/* 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);
static int cdfs_fmount(mntfs *mf);
static int cdfs_fumount(mntfs *mf);
/*
* Ops structure
@@ -64,20 +65,17 @@ am_ops cdfs_ops =
"cdfs",
cdfs_match,
0, /* cdfs_init */
cdfs_mount,
cdfs_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_auto_fmount,
cdfs_fmount,
amfs_auto_fumount,
cdfs_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* cdfs_readlink */
0, /* cdfs_mounted */
0, /* cdfs_umounted */
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 */
find_amfs_auto_srvr,
FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO
};
@@ -91,8 +89,10 @@ cdfs_match(am_opts *fo)
plog(XLOG_USER, "cdfs: no source device specified");
return 0;
}
#ifdef DEBUG
dlog("CDFS: mounting device \"%s\" on \"%s\"",
fo->opt_dev, fo->opt_fs);
#endif /* DEBUG */
/*
* Determine magic cookie to put in mtab
@@ -102,11 +102,11 @@ cdfs_match(am_opts *fo)
static int
mount_cdfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
mount_cdfs(char *dir, char *fs_name, char *opts)
{
cdfs_args_t cdfs_args;
mntent_t mnt;
int genflags, cdfs_flags, retval;
int genflags, cdfs_flags;
/*
* Figure out the name of the file system type.
@@ -120,13 +120,13 @@ mount_cdfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = mntdir;
mnt.mnt_dir = dir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_CDFS;
mnt.mnt_opts = opts;
#if defined(MNT2_CDFS_OPT_DEFPERM) && defined(MNTTAB_OPT_DEFPERM)
if (amu_hasmntopt(&mnt, MNTTAB_OPT_DEFPERM))
if (hasmntopt(&mnt, MNTTAB_OPT_DEFPERM))
# ifdef MNT2_CDFS_OPT_DEFPERM
cdfs_flags |= MNT2_CDFS_OPT_DEFPERM;
# else /* not MNT2_CDFS_OPT_DEFPERM */
@@ -135,38 +135,34 @@ mount_cdfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
#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))
if (hasmntopt(&mnt, MNTTAB_OPT_NODEFPERM))
cdfs_flags |= MNT2_CDFS_OPT_NODEFPERM;
#endif /* MNTTAB_OPT_NODEFPERM */
#if defined(MNT2_CDFS_OPT_NOVERSION) && defined(MNTTAB_OPT_NOVERSION)
if (amu_hasmntopt(&mnt, MNTTAB_OPT_NOVERSION))
if (hasmntopt(&mnt, MNTTAB_OPT_NOVERSION))
cdfs_flags |= MNT2_CDFS_OPT_NOVERSION;
#endif /* defined(MNT2_CDFS_OPT_NOVERSION) && defined(MNTTAB_OPT_NOVERSION) */
#if defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP)
if (amu_hasmntopt(&mnt, MNTTAB_OPT_RRIP))
if (hasmntopt(&mnt, MNTTAB_OPT_RRIP))
cdfs_flags |= MNT2_CDFS_OPT_RRIP;
#endif /* defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP) */
#if defined(MNT2_CDFS_OPT_NORRIP) && defined(MNTTAB_OPT_NORRIP)
if (amu_hasmntopt(&mnt, MNTTAB_OPT_NORRIP))
if (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))
if (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))
if (hasmntopt(&mnt, MNTTAB_OPT_EXTATT))
cdfs_flags |= MNT2_CDFS_OPT_EXTATT;
#endif /* defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT) */
genflags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
if (on_autofs)
genflags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */
#ifdef HAVE_CDFS_ARGS_T_FLAGS
cdfs_args.flags = cdfs_flags;
@@ -180,6 +176,10 @@ mount_cdfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
cdfs_args.iso_pgthresh = hasmntval(&mnt, MNTTAB_OPT_PGTHRESH);
#endif /* HAVE_CDFS_ARGS_T_ISO_PGTHRESH */
#ifdef HAVE_CDFS_ARGS_T_FSPEC
cdfs_args.fspec = fs_name;
#endif /* HAVE_CDFS_ARGS_T_FSPEC */
#ifdef HAVE_CDFS_ARGS_T_NORRIP
/* XXX: need to provide norrip mount opt */
cdfs_args.norrip = 0; /* use Rock-Ridge Protocol extensions */
@@ -190,26 +190,19 @@ mount_cdfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
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;
return mount_fs(&mnt, genflags, (caddr_t) &cdfs_args, 0, type, 0, NULL, mnttab_file_name);
}
static int
cdfs_mount(am_node *am, mntfs *mf)
cdfs_fmount(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);
error = mount_cdfs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_cdfs: %m");
@@ -220,9 +213,7 @@ cdfs_mount(am_node *am, mntfs *mf)
static int
cdfs_umount(am_node *am, mntfs *mf)
cdfs_fumount(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);
return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
}
+21 -29
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/ops_efs.c
* $Id: ops_efs.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -53,8 +54,8 @@
/* 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);
static int efs_fmount(mntfs *mf);
static int efs_fumount(mntfs *mf);
/*
* Ops structure
@@ -64,20 +65,17 @@ am_ops efs_ops =
"efs",
efs_match,
0, /* efs_init */
efs_mount,
efs_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_auto_fmount,
efs_fmount,
amfs_auto_fumount,
efs_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* efs_readlink */
0, /* efs_mounted */
0, /* efs_umounted */
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 */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
};
@@ -93,7 +91,9 @@ efs_match(am_opts *fo)
return 0;
}
#ifdef DEBUG
dlog("EFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
#endif /* DEBUG */
/*
* Determine magic cookie to put in mtab
@@ -103,7 +103,7 @@ efs_match(am_opts *fo)
static int
mount_efs(char *mntdir, char *fs_name, char *opts, int on_autofs)
mount_efs(char *dir, char *fs_name, char *opts)
{
efs_args_t efs_args;
mntent_t mnt;
@@ -120,16 +120,12 @@ mount_efs(char *mntdir, char *fs_name, char *opts, int on_autofs)
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = mntdir;
mnt.mnt_dir = dir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_EFS;
mnt.mnt_opts = opts;
flags = compute_mount_flags(&mnt);
#ifdef HAVE_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 */
@@ -141,17 +137,16 @@ mount_efs(char *mntdir, char *fs_name, char *opts, int on_autofs)
/*
* Call generic mount routine
*/
return mount_fs(&mnt, flags, (caddr_t) &efs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
return mount_fs(&mnt, flags, (caddr_t) &efs_args, 0, type, 0, NULL, mnttab_file_name);
}
static int
efs_mount(am_node *am, mntfs *mf)
efs_fmount(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);
error = mount_efs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_efs: %m");
@@ -163,10 +158,7 @@ efs_mount(am_node *am, mntfs *mf)
static int
efs_umount(am_node *am, mntfs *mf)
efs_fumount(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);
return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
}
+24 -29
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/ops_lofs.c
* $Id: ops_lofs.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -53,8 +54,10 @@
/* 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);
static int lofs_fmount(mntfs *mf);
static int lofs_fumount(mntfs *mf);
static int mount_lofs(char *dir, char *fs_name, char *opts);
/*
* Ops structure
@@ -64,20 +67,17 @@ am_ops lofs_ops =
"lofs",
lofs_match,
0, /* lofs_init */
lofs_mount,
lofs_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_auto_fmount,
lofs_fmount,
amfs_auto_fumount,
lofs_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* lofs_readlink */
0, /* lofs_mounted */
0, /* lofs_umounted */
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 */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
};
@@ -91,8 +91,10 @@ lofs_match(am_opts *fo)
plog(XLOG_USER, "lofs: no source filesystem specified");
return 0;
}
#ifdef DEBUG
dlog("LOFS: mounting fs \"%s\" on \"%s\"",
fo->opt_rfs, fo->opt_fs);
#endif /* DEBUG */
/*
* Determine magic cookie to put in mtab
@@ -101,8 +103,8 @@ lofs_match(am_opts *fo)
}
int
mount_lofs(char *mntdir, char *fs_name, char *opts, int on_autofs)
static int
mount_lofs(char *dir, char *fs_name, char *opts)
{
mntent_t mnt;
int flags;
@@ -116,31 +118,26 @@ mount_lofs(char *mntdir, char *fs_name, char *opts, int on_autofs)
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = mntdir;
mnt.mnt_dir = dir;
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);
return mount_fs(&mnt, flags, NULL, 0, type, 0, NULL, mnttab_file_name);
}
static int
lofs_mount(am_node *am, mntfs *mf)
lofs_fmount(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);
error = mount_lofs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_lofs: %m");
@@ -151,9 +148,7 @@ lofs_mount(am_node *am, mntfs *mf)
static int
lofs_umount(am_node *am, mntfs *mf)
lofs_fumount(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);
return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
}
+3 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/ops_mfs.c
* $Id: ops_mfs.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
+197 -435
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/ops_nfs.c
* $Id: ops_nfs.c,v 1.6.2.6 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -63,7 +64,7 @@
*/
#define FH_TTL (5 * 60) /* five minutes */
#define FH_TTL_ERROR (30) /* 30 seconds */
#define FHID_ALLOC() (++fh_id)
#define FHID_ALLOC(struct) (++fh_id)
/*
* The NFS layer maintains a cache of file handles.
@@ -91,26 +92,19 @@
typedef struct fh_cache fh_cache;
struct fh_cache {
qelem fh_q; /* List header */
wchan_t fh_wchan; /* Wait channel */
voidp fh_wchan; /* Wait channel */
int fh_error; /* Valid data? */
int fh_id; /* Unique id */
int fh_cid; /* Callout id */
u_long fh_nfs_version; /* highest NFS version on host */
am_nfs_handle_t fh_nfs_handle; /* Handle on filesystem */
int fh_status; /* Status of last rpc */
struct sockaddr_in fh_sin; /* Address of mountd */
fserver *fh_fs; /* Server holding filesystem */
char *fh_path; /* Filesystem on host */
};
/* forward definitions */
static int nfs_init(mntfs *mf);
static char *nfs_match(am_opts *fo);
static int nfs_mount(am_node *am, mntfs *mf);
static int nfs_umount(am_node *am, mntfs *mf);
static void nfs_umounted(mntfs *mf);
static int call_mountd(fh_cache *fp, u_long proc, fwd_fun f, wchan_t wchan);
static int webnfs_lookup(fh_cache *fp, fwd_fun f, wchan_t wchan);
static int call_mountd(fh_cache *fp, u_long proc, fwd_fun f, voidp wchan);
static int fh_id = 0;
/* globals */
@@ -125,28 +119,25 @@ am_ops nfs_ops =
"nfs",
nfs_match,
nfs_init,
nfs_mount,
nfs_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_auto_fmount,
nfs_fmount,
amfs_auto_fumount,
nfs_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* nfs_readlink */
0, /* nfs_mounted */
nfs_umounted,
find_nfs_srvr,
0, /* nfs_get_wchan */
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
#ifdef HAVE_FS_AUTOFS
AUTOFS_NFS_FS_FLAGS,
#endif /* HAVE_FS_AUTOFS */
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO
};
static fh_cache *
find_nfs_fhandle_cache(opaque_t arg, int done)
find_nfs_fhandle_cache(voidp idv, int done)
{
fh_cache *fp, *fp2 = 0;
int id = (long) arg; /* for 64-bit archs */
int id = (long) idv; /* for 64-bit archs */
ITER(fp, fh_cache, &fh_head) {
if (fp->fh_id == id) {
@@ -155,11 +146,13 @@ find_nfs_fhandle_cache(opaque_t arg, int done)
}
}
#ifdef DEBUG
if (fp2) {
dlog("fh cache gives fp %#lx, fs %s", (unsigned long) fp2, fp2->fh_path);
} else {
dlog("fh cache search failed");
}
#endif /* DEBUG */
if (fp2 && !done) {
fp2->fh_error = ETIMEDOUT;
@@ -171,18 +164,14 @@ find_nfs_fhandle_cache(opaque_t arg, int done)
/*
* Called when a filehandle appears via the mount protocol
* Called when a filehandle appears
*/
static void
got_nfs_fh_mount(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, opaque_t arg, int done)
got_nfs_fh(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, voidp idv, int done)
{
fh_cache *fp;
struct fhstatus res;
#ifdef HAVE_FS_NFS3
struct am_mountres3 res3;
#endif /* HAVE_FS_NFS3 */
fp = find_nfs_fhandle_cache(arg, done);
fp = find_nfs_fhandle_cache(idv, done);
if (!fp)
return;
@@ -191,109 +180,28 @@ got_nfs_fh_mount(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in
* NFS protocol version.
*/
#ifdef HAVE_FS_NFS3
if (fp->fh_nfs_version == NFS_VERSION3) {
memset(&res3, 0, sizeof(res3));
fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res3,
(XDRPROC_T_TYPE) xdr_am_mountres3);
fp->fh_status = unx_error(res3.fhs_status);
memset(&fp->fh_nfs_handle.v3, 0, sizeof(am_nfs_fh3));
fp->fh_nfs_handle.v3.am_fh3_length = res3.mountres3_u.mountinfo.fhandle.fhandle3_len;
memmove(fp->fh_nfs_handle.v3.am_fh3_data,
res3.mountres3_u.mountinfo.fhandle.fhandle3_val,
fp->fh_nfs_handle.v3.am_fh3_length);
} else {
if (fp->fh_nfs_version == NFS_VERSION3)
fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &fp->fh_nfs_handle.v3,
(XDRPROC_T_TYPE) xdr_mountres3);
else
#endif /* HAVE_FS_NFS3 */
memset(&res, 0, sizeof(res));
fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res,
fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &fp->fh_nfs_handle.v2,
(XDRPROC_T_TYPE) xdr_fhstatus);
fp->fh_status = unx_error(res.fhs_status);
memmove(&fp->fh_nfs_handle.v2, &res.fhs_fh, NFS_FHSIZE);
#ifdef HAVE_FS_NFS3
}
#endif /* HAVE_FS_NFS3 */
if (!fp->fh_error) {
#ifdef DEBUG
dlog("got filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
} else {
plog(XLOG_USER, "filehandle denied for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
#endif /* DEBUG */
/*
* Force the error to be EACCES. It's debatable whether it should be
* ENOENT instead, but the server really doesn't give us any clues, and
* EACCES is more in line with the "filehandle denied" message.
* Wakeup anything sleeping on this filehandle
*/
fp->fh_error = EACCES;
}
/*
* Wakeup anything sleeping on this filehandle
*/
if (fp->fh_wchan) {
dlog("Calling wakeup on %#lx", (unsigned long) fp->fh_wchan);
wakeup(fp->fh_wchan);
}
}
/*
* Called when a filehandle appears via WebNFS
*/
static void
got_nfs_fh_webnfs(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, opaque_t arg, int done)
{
fh_cache *fp;
nfsdiropres res;
#ifdef HAVE_FS_NFS3
am_LOOKUP3res res3;
#endif /* HAVE_FS_NFS3 */
fp = find_nfs_fhandle_cache(arg, done);
if (!fp)
return;
/*
* retrieve the correct RPC reply for the file handle, based on the
* NFS protocol version.
*/
#ifdef HAVE_FS_NFS3
if (fp->fh_nfs_version == NFS_VERSION3) {
memset(&res3, 0, sizeof(res3));
fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res3,
(XDRPROC_T_TYPE) xdr_am_LOOKUP3res);
fp->fh_status = unx_error(res3.status);
memset(&fp->fh_nfs_handle.v3, 0, sizeof(am_nfs_fh3));
fp->fh_nfs_handle.v3.am_fh3_length = res3.res_u.ok.object.am_fh3_length;
memmove(fp->fh_nfs_handle.v3.am_fh3_data,
res3.res_u.ok.object.am_fh3_data,
fp->fh_nfs_handle.v3.am_fh3_length);
} else {
#endif /* HAVE_FS_NFS3 */
memset(&res, 0, sizeof(res));
fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res,
(XDRPROC_T_TYPE) xdr_diropres);
fp->fh_status = unx_error(res.dr_status);
memmove(&fp->fh_nfs_handle.v2, &res.dr_u.dr_drok_u.drok_fhandle, NFS_FHSIZE);
#ifdef HAVE_FS_NFS3
}
#endif /* HAVE_FS_NFS3 */
if (!fp->fh_error) {
dlog("got filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
} else {
plog(XLOG_USER, "filehandle denied for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
/*
* Force the error to be EACCES. It's debatable whether it should be
* ENOENT instead, but the server really doesn't give us any clues, and
* EACCES is more in line with the "filehandle denied" message.
*/
fp->fh_error = EACCES;
}
/*
* Wakeup anything sleeping on this filehandle
*/
if (fp->fh_wchan) {
dlog("Calling wakeup on %#lx", (unsigned long) fp->fh_wchan);
wakeup(fp->fh_wchan);
if (fp->fh_wchan) {
#ifdef DEBUG
dlog("Calling wakeup on %#lx", (unsigned long) fp->fh_wchan);
#endif /* DEBUG */
wakeup(fp->fh_wchan);
}
}
}
@@ -304,12 +212,8 @@ flush_nfs_fhandle_cache(fserver *fs)
fh_cache *fp;
ITER(fp, fh_cache, &fh_head) {
if (fp->fh_fs == fs || fs == NULL) {
/*
* Only invalidate port info for non-WebNFS servers
*/
if (!(fp->fh_fs->fs_flags & FSF_WEBNFS))
fp->fh_sin.sin_port = (u_short) 0;
if (fp->fh_fs == fs || fs == 0) {
fp->fh_sin.sin_port = (u_short) 0;
fp->fh_error = -1;
}
}
@@ -317,13 +221,15 @@ flush_nfs_fhandle_cache(fserver *fs)
static void
discard_fh(opaque_t arg)
discard_fh(voidp v)
{
fh_cache *fp = (fh_cache *) arg;
fh_cache *fp = v;
rem_que(&fp->fh_q);
if (fp->fh_fs) {
#ifdef DEBUG
dlog("Discarding filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
#endif /* DEBUG */
free_srvr(fp->fh_fs);
}
if (fp->fh_path)
@@ -336,92 +242,88 @@ discard_fh(opaque_t arg)
* Determine the file handle for a node
*/
static int
prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, mntfs *mf)
prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, voidp wchan)
{
fh_cache *fp, *fp_save = 0;
int error;
int reuse_id = FALSE;
#ifdef DEBUG
dlog("Searching cache for %s:%s", fs->fs_host, path);
#endif /* DEBUG */
/*
* First search the cache
*/
ITER(fp, fh_cache, &fh_head) {
if (fs != fp->fh_fs || !STREQ(path, fp->fh_path))
continue; /* skip to next ITER item */
/* else we got a match */
switch (fp->fh_error) {
case 0:
plog(XLOG_INFO, "prime_nfs_fhandle_cache: NFS version %d", (int) fp->fh_nfs_version);
error = fp->fh_error = fp->fh_status;
if (error == 0) {
if (mf->mf_flags & MFF_NFS_SCALEDOWN) {
fp_save = fp;
/* XXX: why reuse the ID? */
reuse_id = TRUE;
break;
}
if (fhbuf) {
if (fs == fp->fh_fs && STREQ(path, fp->fh_path)) {
switch (fp->fh_error) {
case 0:
plog(XLOG_INFO, "prime_nfs_fhandle_cache: NFS version %d", (int) fp->fh_nfs_version);
#ifdef HAVE_FS_NFS3
if (fp->fh_nfs_version == NFS_VERSION3) {
memmove((voidp) &(fhbuf->v3), (voidp) &(fp->fh_nfs_handle.v3),
sizeof(fp->fh_nfs_handle.v3));
} else
if (fp->fh_nfs_version == NFS_VERSION3)
error = fp->fh_error = unx_error(fp->fh_nfs_handle.v3.fhs_status);
else
#endif /* HAVE_FS_NFS3 */
error = fp->fh_error = unx_error(fp->fh_nfs_handle.v2.fhs_status);
if (error == 0) {
if (fhbuf) {
#ifdef HAVE_FS_NFS3
if (fp->fh_nfs_version == NFS_VERSION3)
memmove((voidp) &(fhbuf->v3), (voidp) &(fp->fh_nfs_handle.v3),
sizeof(fp->fh_nfs_handle.v3));
else
#endif /* HAVE_FS_NFS3 */
{
memmove((voidp) &(fhbuf->v2), (voidp) &(fp->fh_nfs_handle.v2),
sizeof(fp->fh_nfs_handle.v2));
}
}
if (fp->fh_cid)
untimeout(fp->fh_cid);
fp->fh_cid = timeout(FH_TTL, discard_fh, (voidp) fp);
} else if (error == EACCES) {
/*
* Now decode the file handle return code.
*/
plog(XLOG_INFO, "Filehandle denied for \"%s:%s\"",
fs->fs_host, path);
} else {
errno = error; /* XXX */
plog(XLOG_INFO, "Filehandle error for \"%s:%s\": %m",
fs->fs_host, path);
}
if (fp->fh_cid)
untimeout(fp->fh_cid);
fp->fh_cid = timeout(FH_TTL, discard_fh, (opaque_t) fp);
} else if (error == EACCES) {
/*
* Now decode the file handle return code.
* The error was returned from the remote mount daemon.
* Policy: this error will be cached for now...
*/
plog(XLOG_INFO, "Filehandle denied for \"%s:%s\"",
fs->fs_host, path);
} else {
errno = error; /* XXX */
plog(XLOG_INFO, "Filehandle error for \"%s:%s\": %m",
fs->fs_host, path);
return error;
case -1:
/*
* Still thinking about it, but we can re-use.
*/
fp_save = fp;
reuse_id = TRUE;
break;
default:
/*
* Return the error.
* Policy: make sure we recompute if required again
* in case this was caused by a network failure.
* This can thrash mountd's though... If you find
* your mountd going slowly then:
* 1. Add a fork() loop to main.
* 2. Remove the call to innetgr() and don't use
* netgroups, especially if you don't use YP.
*/
error = fp->fh_error;
fp->fh_error = -1;
return error;
}
/*
* The error was returned from the remote mount daemon.
* Policy: this error will be cached for now...
*/
return error;
case -1:
/*
* Still thinking about it, but we can re-use.
*/
fp_save = fp;
reuse_id = TRUE;
break;
default:
/*
* Return the error.
* Policy: make sure we recompute if required again
* in case this was caused by a network failure.
* This can thrash mountd's though... If you find
* your mountd going slowly then:
* 1. Add a fork() loop to main.
* 2. Remove the call to innetgr() and don't use
* netgroups, especially if you don't use YP.
*/
error = fp->fh_error;
fp->fh_error = -1;
return error;
} /* end of switch statement */
} /* end of ITER loop */
}
}
/*
* Not in cache
@@ -440,13 +342,13 @@ prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, mntfs *
ins_que(&fp->fh_q, &fh_head);
}
if (!reuse_id)
fp->fh_id = FHID_ALLOC();
fp->fh_wchan = get_mntfs_wchan(mf);
fp->fh_id = FHID_ALLOC(struct );
fp->fh_wchan = wchan;
fp->fh_error = -1;
fp->fh_cid = timeout(FH_TTL, discard_fh, (opaque_t) fp);
fp->fh_cid = timeout(FH_TTL, discard_fh, (voidp) fp);
/*
* If fs->fs_ip is null, remote server is probably down.
* if fs->fs_ip is null, remote server is probably down.
*/
if (!fs->fs_ip) {
/* Mark the fileserver down and invalid again */
@@ -457,25 +359,18 @@ prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, mntfs *
}
/*
* Either fp has been freshly allocated or the address has changed.
* Initialize address and nfs version. Don't try to re-use the port
* information unless using WebNFS where the port is fixed either by
* the spec or the "port" mount option.
* If the address has changed then don't try to re-use the
* port information
*/
if (fp->fh_sin.sin_addr.s_addr != fs->fs_ip->sin_addr.s_addr) {
fp->fh_sin = *fs->fs_ip;
if (!(mf->mf_flags & MFF_WEBNFS))
fp->fh_sin.sin_port = 0;
fp->fh_sin.sin_port = 0;
fp->fh_nfs_version = fs->fs_version;
}
fp->fh_fs = dup_srvr(fs);
fp->fh_path = strdup(path);
if (mf->mf_flags & MFF_WEBNFS)
error = webnfs_lookup(fp, got_nfs_fh_webnfs, get_mntfs_wchan(mf));
else
error = call_mountd(fp, MOUNTPROC_MNT, got_nfs_fh_mount, get_mntfs_wchan(mf));
error = call_mountd(fp, MOUNTPROC_MNT, got_nfs_fh, wchan);
if (error) {
/*
* Local error - cache for a short period
@@ -483,7 +378,7 @@ prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, mntfs *
*/
untimeout(fp->fh_cid);
fp->fh_cid = timeout(error < 0 ? 2 * ALLOWED_MOUNT_TIME : FH_TTL_ERROR,
discard_fh, (opaque_t) fp);
discard_fh, (voidp) fp);
fp->fh_error = error;
} else {
error = fp->fh_error;
@@ -524,11 +419,11 @@ make_nfs_auth(void)
static int
call_mountd(fh_cache *fp, u_long proc, fwd_fun fun, wchan_t wchan)
call_mountd(fh_cache *fp, u_long proc, fwd_fun f, voidp wchan)
{
struct rpc_msg mnt_msg;
int len;
char iobuf[UDPMSGSIZE];
char iobuf[8192];
int error;
u_long mnt_version;
@@ -539,17 +434,17 @@ call_mountd(fh_cache *fp, u_long proc, fwd_fun fun, wchan_t wchan)
}
if (fp->fh_sin.sin_port == 0) {
u_short mountd_port;
error = get_mountd_port(fp->fh_fs, &mountd_port, wchan);
u_short port;
error = nfs_srvr_port(fp->fh_fs, &port, wchan);
if (error)
return error;
fp->fh_sin.sin_port = mountd_port;
fp->fh_sin.sin_port = port;
}
/* find the right version of the mount protocol */
#ifdef HAVE_FS_NFS3
if (fp->fh_nfs_version == NFS_VERSION3)
mnt_version = AM_MOUNTVERS3;
mnt_version = MOUNTVERS3;
else
#endif /* HAVE_FS_NFS3 */
mnt_version = MOUNTVERS;
@@ -567,128 +462,40 @@ call_mountd(fh_cache *fp, u_long proc, fwd_fun fun, wchan_t wchan)
if (len > 0) {
error = fwd_packet(MK_RPC_XID(RPC_XID_MOUNTD, fp->fh_id),
iobuf,
(voidp) iobuf,
len,
&fp->fh_sin,
&fp->fh_sin,
(opaque_t) ((long) fp->fh_id), /* cast to long needed for 64-bit archs */
fun);
(voidp) ((long) fp->fh_id), /* for 64-bit archs */
f);
} else {
error = -len;
}
/*
* It may be the case that we're sending to the wrong MOUNTD port. This
* occurs if mountd is restarted on the server after the port has been
* looked up and stored in the filehandle cache somewhere. The correct
* solution, if we're going to cache port numbers is to catch the ICMP
* port unreachable reply from the server and cause the portmap request
* to be redone. The quick solution here is to invalidate the MOUNTD
* port.
*/
/*
* It may be the case that we're sending to the wrong MOUNTD port. This
* occurs if mountd is restarted on the server after the port has been
* looked up and stored in the filehandle cache somewhere. The correct
* solution, if we're going to cache port numbers is to catch the ICMP
* port unreachable reply from the server and cause the portmap request
* to be redone. The quick solution here is to invalidate the MOUNTD
* port.
*/
fp->fh_sin.sin_port = 0;
return error;
}
static int
webnfs_lookup(fh_cache *fp, fwd_fun fun, wchan_t wchan)
{
struct rpc_msg wnfs_msg;
int len;
char iobuf[UDPMSGSIZE];
int error;
u_long proc;
XDRPROC_T_TYPE xdr_fn;
voidp argp;
nfsdiropargs args;
#ifdef HAVE_FS_NFS3
am_LOOKUP3args args3;
#endif
char *wnfs_path;
size_t l;
if (!nfs_auth) {
error = make_nfs_auth();
if (error)
return error;
}
if (fp->fh_sin.sin_port == 0) {
/* FIXME: wrong, don't discard sin_port in the first place for WebNFS. */
plog(XLOG_WARNING, "webnfs_lookup: port == 0 for nfs on %s, fixed",
fp->fh_fs->fs_host);
fp->fh_sin.sin_port = htons(NFS_PORT);
}
/*
* Use native path like the rest of amd (cf. RFC 2054, 6.1).
*/
l = strlen(fp->fh_path) + 2;
wnfs_path = (char *) xmalloc(l);
wnfs_path[0] = 0x80;
xstrlcpy(wnfs_path + 1, fp->fh_path, l - 1);
/* find the right program and lookup procedure */
#ifdef HAVE_FS_NFS3
if (fp->fh_nfs_version == NFS_VERSION3) {
proc = AM_NFSPROC3_LOOKUP;
xdr_fn = (XDRPROC_T_TYPE) xdr_am_LOOKUP3args;
argp = &args3;
/* WebNFS public file handle */
args3.what.dir.am_fh3_length = 0;
args3.what.name = wnfs_path;
} else {
#endif /* HAVE_FS_NFS3 */
proc = NFSPROC_LOOKUP;
xdr_fn = (XDRPROC_T_TYPE) xdr_diropargs;
argp = &args;
/* WebNFS public file handle */
memset(&args.da_fhandle, 0, NFS_FHSIZE);
args.da_name = wnfs_path;
#ifdef HAVE_FS_NFS3
}
#endif /* HAVE_FS_NFS3 */
plog(XLOG_INFO, "webnfs_lookup: NFS version %d", (int) fp->fh_nfs_version);
rpc_msg_init(&wnfs_msg, NFS_PROGRAM, fp->fh_nfs_version, proc);
len = make_rpc_packet(iobuf,
sizeof(iobuf),
proc,
&wnfs_msg,
argp,
(XDRPROC_T_TYPE) xdr_fn,
nfs_auth);
if (len > 0) {
error = fwd_packet(MK_RPC_XID(RPC_XID_WEBNFS, fp->fh_id),
iobuf,
len,
&fp->fh_sin,
&fp->fh_sin,
(opaque_t) ((long) fp->fh_id), /* cast to long needed for 64-bit archs */
fun);
} else {
error = -len;
}
XFREE(wnfs_path);
return error;
}
/*
* NFS needs the local filesystem, remote filesystem
* remote hostname.
* Local filesystem defaults to remote and vice-versa.
*/
static char *
char *
nfs_match(am_opts *fo)
{
char *xmtab;
size_t l;
if (fo->opt_fs && !fo->opt_rfs)
fo->opt_rfs = fo->opt_fs;
@@ -704,11 +511,12 @@ nfs_match(am_opts *fo)
/*
* Determine magic cookie to put in mtab
*/
l = strlen(fo->opt_rhost) + strlen(fo->opt_rfs) + 2;
xmtab = (char *) xmalloc(l);
xsnprintf(xmtab, l, "%s:%s", fo->opt_rhost, fo->opt_rfs);
xmtab = (char *) xmalloc(strlen(fo->opt_rhost) + strlen(fo->opt_rfs) + 2);
sprintf(xmtab, "%s:%s", fo->opt_rhost, fo->opt_rfs);
#ifdef DEBUG
dlog("NFS: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
fo->opt_rhost, fo->opt_rfs, fo->opt_fs);
#endif /* DEBUG */
return xmtab;
}
@@ -717,36 +525,24 @@ nfs_match(am_opts *fo)
/*
* Initialize am structure for nfs
*/
static int
int
nfs_init(mntfs *mf)
{
int error;
am_nfs_handle_t fhs;
char *colon;
if (mf->mf_private) {
if (mf->mf_flags & MFF_NFS_SCALEDOWN) {
fserver *fs;
/* tell remote mountd that we're done with this filehandle */
mf->mf_ops->umounted(mf);
mf->mf_prfree(mf->mf_private);
fs = mf->mf_ops->ffserver(mf);
free_srvr(mf->mf_server);
mf->mf_server = fs;
} else
return 0;
}
if (mf->mf_private)
return 0;
colon = strchr(mf->mf_info, ':');
if (colon == 0)
return ENOENT;
error = prime_nfs_fhandle_cache(colon + 1, mf->mf_server, &fhs, mf);
error = prime_nfs_fhandle_cache(colon + 1, mf->mf_server, &fhs, (voidp) mf);
if (!error) {
mf->mf_private = (opaque_t) ALLOC(am_nfs_handle_t);
mf->mf_prfree = (void (*)(opaque_t)) free;
mf->mf_private = (voidp) ALLOC(am_nfs_handle_t);
mf->mf_prfree = (void (*)(voidp)) free;
memmove(mf->mf_private, (voidp) &fhs, sizeof(fhs));
}
return error;
@@ -754,20 +550,18 @@ nfs_init(mntfs *mf)
int
mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf)
mount_nfs_fh(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *mf)
{
MTYPE_TYPE type;
char *colon;
char *xopts=NULL, transp_timeo_opts[40], transp_retrans_opts[40];
char *xopts;
char host[MAXHOSTNAMELEN + MAXPATHLEN + 2];
fserver *fs = mf->mf_server;
u_long nfs_version = fs->fs_version;
char *nfs_proto = fs->fs_proto; /* "tcp" or "udp" */
int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
int error;
int genflags;
int retry;
int proto = AMU_TYPE_NONE;
mntent_t mnt;
nfs_args_t nfs_args;
@@ -781,48 +575,26 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf)
#ifdef MOUNT_TABLE_ON_FILE
*colon = '\0';
#endif /* MOUNT_TABLE_ON_FILE */
xstrlcpy(host, fs_name, sizeof(host));
strncpy(host, fs_name, sizeof(host));
#ifdef MOUNT_TABLE_ON_FILE
*colon = ':';
#endif /* MOUNT_TABLE_ON_FILE */
#ifdef MAXHOSTNAMELEN
/* most kernels have a name length restriction */
if (strlen(host) >= MAXHOSTNAMELEN)
xstrlcpy(host + MAXHOSTNAMELEN - 3, "..",
sizeof(host) - MAXHOSTNAMELEN + 3);
strcpy(host + MAXHOSTNAMELEN - 3, "..");
#endif /* MAXHOSTNAMELEN */
/*
* Create option=VAL for udp/tcp specific timeouts and retrans values, but
* only if these options were specified.
*/
transp_timeo_opts[0] = transp_retrans_opts[0] = '\0'; /* initialize */
if (STREQ(nfs_proto, "udp"))
proto = AMU_TYPE_UDP;
else if (STREQ(nfs_proto, "tcp"))
proto = AMU_TYPE_TCP;
if (proto != AMU_TYPE_NONE) {
if (gopt.amfs_auto_timeo[proto] > 0)
xsnprintf(transp_timeo_opts, sizeof(transp_timeo_opts), "%s=%d,",
MNTTAB_OPT_TIMEO, gopt.amfs_auto_timeo[proto]);
if (gopt.amfs_auto_retrans[proto] > 0)
xsnprintf(transp_retrans_opts, sizeof(transp_retrans_opts), "%s=%d,",
MNTTAB_OPT_RETRANS, gopt.amfs_auto_retrans[proto]);
}
if (mf->mf_remopts && *mf->mf_remopts &&
!islocalnet(fs->fs_ip->sin_addr.s_addr)) {
plog(XLOG_INFO, "Using remopts=\"%s\"", mf->mf_remopts);
/* use transp_opts first, so map-specific opts will override */
xopts = str3cat(xopts, transp_timeo_opts, transp_retrans_opts, mf->mf_remopts);
xopts = strdup(mf->mf_remopts);
} else {
/* use transp_opts first, so map-specific opts will override */
xopts = str3cat(xopts, transp_timeo_opts, transp_retrans_opts, mf->mf_mopts);
xopts = strdup(opts);
}
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = mntdir;
mnt.mnt_dir = dir;
mnt.mnt_fsname = fs_name;
mnt.mnt_opts = xopts;
@@ -854,19 +626,18 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf)
}
#endif /* HAVE_FS_NFS3 */
plog(XLOG_INFO, "mount_nfs_fh: NFS version %d", (int) nfs_version);
#if defined(HAVE_FS_NFS3) || defined(HAVE_TRANSPORT_TYPE_TLI)
plog(XLOG_INFO, "mount_nfs_fh: using NFS transport %s", nfs_proto);
#endif /* defined(HAVE_FS_NFS3) || defined(HAVE_TRANSPORT_TYPE_TLI) */
retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
if (retry <= 0)
retry = 1; /* XXX */
genflags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
if (on_autofs)
genflags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */
/* setup the many fields and flags within nfs_args */
#ifdef HAVE_TRANSPORT_TYPE_TLI
compute_nfs_args(&nfs_args,
&mnt,
genflags,
@@ -877,14 +648,27 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf)
fhp,
host,
fs_name);
#else /* not HAVE_TRANSPORT_TYPE_TLI */
compute_nfs_args(&nfs_args,
&mnt,
genflags,
fs->fs_ip,
nfs_version,
nfs_proto,
fhp,
host,
fs_name);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/* finally call the mounting function */
if (amuDebug(D_TRACE)) {
#ifdef DEBUG
amuDebug(D_TRACE) {
print_nfs_args(&nfs_args, nfs_version);
plog(XLOG_DEBUG, "Generic mount flags 0x%x used for NFS mount", genflags);
}
#endif /* DEBUG */
error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type,
nfs_version, nfs_proto, mnttab_file_name, on_autofs);
nfs_version, nfs_proto, mnttab_file_name);
XFREE(xopts);
#ifdef HAVE_TRANSPORT_TYPE_TLI
@@ -898,62 +682,39 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf)
static int
nfs_mount(am_node *am, mntfs *mf)
mount_nfs(char *dir, char *fs_name, char *opts, mntfs *mf)
{
int error = 0;
mntent_t mnt;
if (!mf->mf_private) {
plog(XLOG_ERROR, "Missing filehandle for %s", mf->mf_info);
plog(XLOG_ERROR, "Missing filehandle for %s", fs_name);
return EINVAL;
}
mnt.mnt_opts = mf->mf_mopts;
if (amu_hasmntopt(&mnt, "softlookup") ||
(amu_hasmntopt(&mnt, "soft") && !amu_hasmntopt(&mnt, "nosoftlookup")))
am->am_flags |= AMF_SOFTLOOKUP;
return mount_nfs_fh((am_nfs_handle_t *) mf->mf_private, dir, fs_name, opts, mf);
}
error = mount_nfs_fh((am_nfs_handle_t *) mf->mf_private,
mf->mf_mount,
mf->mf_info,
mf);
int
nfs_fmount(mntfs *mf)
{
int error = 0;
error = mount_nfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, mf);
#ifdef DEBUG
if (error) {
errno = error;
dlog("mount_nfs: %m");
}
#endif /* DEBUG */
return error;
}
static int
nfs_umount(am_node *am, mntfs *mf)
int
nfs_fumount(mntfs *mf)
{
int unmount_flags, new_unmount_flags, error;
unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
#if defined(HAVE_UMOUNT2) && (defined(MNT2_GEN_OPT_FORCE) || defined(MNT2_GEN_OPT_DETACH))
/*
* If the attempt to unmount failed with EBUSY, and this fserver was
* marked for forced unmounts, then use forced/lazy unmounts.
*/
if (error == EBUSY &&
gopt.flags & CFM_FORCED_UNMOUNTS &&
mf->mf_server->fs_flags & FSF_FORCE_UNMOUNT) {
plog(XLOG_INFO, "EZK: nfs_umount: trying forced/lazy unmounts");
/*
* XXX: turning off the FSF_FORCE_UNMOUNT may not be perfectly
* incorrect. Multiple nodes may need to be timed out and restarted for
* a single hung fserver.
*/
mf->mf_server->fs_flags &= ~FSF_FORCE_UNMOUNT;
new_unmount_flags = unmount_flags | AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH;
error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, new_unmount_flags);
}
#endif /* HAVE_UMOUNT2 && (MNT2_GEN_OPT_FORCE || MNT2_GEN_OPT_DETACH) */
int error = UMOUNT_FS(mf->mf_mount, mnttab_file_name);
/*
* Here is some code to unmount 'restarted' file systems.
@@ -982,14 +743,12 @@ nfs_umount(am_node *am, mntfs *mf)
if (NSTREQ(mf->mf_mount, new_mf->mf_mount, len) &&
new_mf->mf_mount[len] == '/') {
new_unmount_flags =
(new_mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
UMOUNT_FS(new_mf->mf_mount, mnttab_file_name, new_unmount_flags);
UMOUNT_FS(new_mf->mf_mount, mnttab_file_name);
didsome = 1;
}
}
if (didsome)
error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
error = UMOUNT_FS(mf->mf_mount, mnttab_file_name);
}
if (error)
return error;
@@ -998,35 +757,38 @@ nfs_umount(am_node *am, mntfs *mf)
}
static void
nfs_umounted(mntfs *mf)
void
nfs_umounted(am_node *mp)
{
/*
* Don't bother to inform remote mountd that we are finished. Until a
* full track of filehandles is maintained the mountd unmount callback
* cannot be done correctly anyway...
*/
mntfs *mf = mp->am_mnt;
fserver *fs;
char *colon, *path;
if (mf->mf_error || mf->mf_refc > 1)
return;
/*
* No need to inform mountd when WebNFS is in use.
*/
if (mf->mf_flags & MFF_WEBNFS)
return;
fs = mf->mf_server;
/*
* Call the mount daemon on the server to announce that we are not using
* the fs any more.
*
* XXX: This is *wrong*. The mountd should be called when the fhandle is
* This is *wrong*. The mountd should be called when the fhandle is
* flushed from the cache, and a reference held to the cached entry while
* the fs is mounted...
*/
fs = mf->mf_server;
colon = path = strchr(mf->mf_info, ':');
if (fs && colon) {
fh_cache f;
#ifdef DEBUG
dlog("calling mountd for %s", mf->mf_info);
#endif /* DEBUG */
*path++ = '\0';
f.fh_path = path;
f.fh_sin = *fs->fs_ip;
@@ -1035,8 +797,8 @@ nfs_umounted(mntfs *mf)
f.fh_fs = fs;
f.fh_id = 0;
f.fh_error = 0;
prime_nfs_fhandle_cache(colon + 1, mf->mf_server, (am_nfs_handle_t *) 0, mf);
call_mountd(&f, MOUNTPROC_UMNT, (fwd_fun *) 0, (wchan_t) 0);
prime_nfs_fhandle_cache(colon + 1, mf->mf_server, (am_nfs_handle_t *) 0, (voidp) mf);
call_mountd(&f, MOUNTPROC_UMNT, (fwd_fun) 0, (voidp) 0);
*colon = ':';
}
}
+3 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/ops_nfs3.c
* $Id: ops_nfs3.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
+3 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/ops_nullfs.c
* $Id: ops_nullfs.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
+25 -67
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/ops_pcfs.c
* $Id: ops_pcfs.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
* $FreeBSD$
*
*/
@@ -53,8 +55,8 @@
/* 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);
static int pcfs_fmount(mntfs *mf);
static int pcfs_fumount(mntfs *mf);
/*
* Ops structure
@@ -64,20 +66,17 @@ am_ops pcfs_ops =
"pcfs",
pcfs_match,
0, /* pcfs_init */
pcfs_mount,
pcfs_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_auto_fmount,
pcfs_fmount,
amfs_auto_fumount,
pcfs_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* pcfs_readlink */
0, /* pcfs_mounted */
0, /* pcfs_umounted */
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 */
find_amfs_auto_srvr,
FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO
};
@@ -92,7 +91,9 @@ pcfs_match(am_opts *fo)
plog(XLOG_USER, "pcfs: no source device specified");
return 0;
}
#ifdef DEBUG
dlog("PCFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
#endif /* DEBUG */
/*
* Determine magic cookie to put in mtab
@@ -102,17 +103,11 @@ pcfs_match(am_opts *fo)
static int
mount_pcfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
mount_pcfs(char *dir, char *fs_name, char *opts)
{
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.
@@ -125,18 +120,12 @@ mount_pcfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = mntdir;
mnt.mnt_dir = dir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_PCFS;
mnt.mnt_opts = opts;
flags = compute_mount_flags(&mnt);
#ifdef HAVE_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;
@@ -144,46 +133,18 @@ mount_pcfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
#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);
pcfs_args.dirmask = 0777; /* this may be the msdos dir modes */
#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);
pcfs_args.uid = 0; /* root */
#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);
pcfs_args.gid = 0; /* wheel */
#endif /* HAVE_PCFS_ARGS_T_GID */
#ifdef HAVE_PCFS_ARGS_T_SECONDSWEST
@@ -196,17 +157,16 @@ mount_pcfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
/*
* Call generic mount routine
*/
return mount_fs(&mnt, flags, (caddr_t) & pcfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
return mount_fs(&mnt, flags, (caddr_t) & pcfs_args, 0, type, 0, NULL, mnttab_file_name);
}
static int
pcfs_mount(am_node *am, mntfs *mf)
pcfs_fmount(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);
error = mount_pcfs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_pcfs: %m");
@@ -218,9 +178,7 @@ pcfs_mount(am_node *am, mntfs *mf)
static int
pcfs_umount(am_node *am, mntfs *mf)
pcfs_fumount(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);
return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
}
+3 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/ops_tfs.c
* $Id: ops_tfs.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
+3 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/ops_tmpfs.c
* $Id: ops_tmpfs.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
+21 -28
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/ops_ufs.c
* $Id: ops_ufs.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -53,8 +54,8 @@
/* 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);
static int ufs_fmount(mntfs *mf);
static int ufs_fumount(mntfs *mf);
/*
* Ops structure
@@ -64,20 +65,17 @@ am_ops ufs_ops =
"ufs",
ufs_match,
0, /* ufs_init */
ufs_mount,
ufs_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_auto_fmount,
ufs_fmount,
amfs_auto_fumount,
ufs_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* ufs_readlink */
0, /* ufs_mounted */
0, /* ufs_umounted */
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 */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
};
@@ -93,7 +91,9 @@ ufs_match(am_opts *fo)
return 0;
}
#ifdef DEBUG
dlog("UFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
#endif /* DEBUG */
/*
* Determine magic cookie to put in mtab
@@ -103,7 +103,7 @@ ufs_match(am_opts *fo)
static int
mount_ufs(char *mntdir, char *fs_name, char *opts, int on_autofs)
mount_ufs(char *dir, char *fs_name, char *opts)
{
ufs_args_t ufs_args;
mntent_t mnt;
@@ -120,16 +120,12 @@ mount_ufs(char *mntdir, char *fs_name, char *opts, int on_autofs)
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = mntdir;
mnt.mnt_dir = dir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_UFS;
mnt.mnt_opts = opts;
genflags = compute_mount_flags(&mnt);
#ifdef HAVE_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? */
@@ -150,17 +146,16 @@ mount_ufs(char *mntdir, char *fs_name, char *opts, int on_autofs)
/*
* Call generic mount routine
*/
return mount_fs(&mnt, genflags, (caddr_t) &ufs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
return mount_fs(&mnt, genflags, (caddr_t) &ufs_args, 0, type, 0, NULL, mnttab_file_name);
}
static int
ufs_mount(am_node *am, mntfs *mf)
ufs_fmount(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);
error = mount_ufs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_ufs: %m");
@@ -172,9 +167,7 @@ ufs_mount(am_node *am, mntfs *mf)
static int
ufs_umount(am_node *am, mntfs *mf)
ufs_fumount(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);
return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
}
+3 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/ops_umapfs.c
* $Id: ops_umapfs.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
+3 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/ops_unionfs.c
* $Id: ops_unionfs.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
+21 -28
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/ops_xfs.c
* $Id: ops_xfs.c,v 1.3.2.6 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -53,8 +54,8 @@
/* 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);
static int xfs_fmount(mntfs *mf);
static int xfs_fumount(mntfs *mf);
/*
* Ops structure
@@ -64,20 +65,17 @@ am_ops xfs_ops =
"xfs",
xfs_match,
0, /* xfs_init */
xfs_mount,
xfs_umount,
amfs_error_lookup_child,
amfs_error_mount_child,
amfs_auto_fmount,
xfs_fmount,
amfs_auto_fumount,
xfs_fumount,
amfs_error_lookuppn,
amfs_error_readdir,
0, /* xfs_readlink */
0, /* xfs_mounted */
0, /* xfs_umounted */
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 */
find_amfs_auto_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
};
@@ -93,7 +91,9 @@ xfs_match(am_opts *fo)
return 0;
}
#ifdef DEBUG
dlog("XFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
#endif /* DEBUG */
/*
* Determine magic cookie to put in mtab
@@ -103,7 +103,7 @@ xfs_match(am_opts *fo)
static int
mount_xfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
mount_xfs(char *dir, char *fs_name, char *opts)
{
xfs_args_t xfs_args;
mntent_t mnt;
@@ -120,16 +120,12 @@ mount_xfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
* Fill in the mount structure
*/
memset((voidp) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = mntdir;
mnt.mnt_dir = dir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_XFS;
mnt.mnt_opts = opts;
flags = compute_mount_flags(&mnt);
#ifdef HAVE_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 */
@@ -141,17 +137,16 @@ mount_xfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
/*
* Call generic mount routine
*/
return mount_fs(&mnt, flags, (caddr_t) &xfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
return mount_fs(&mnt, flags, (caddr_t) &xfs_args, 0, type, 0, NULL, mnttab_file_name);
}
static int
xfs_mount(am_node *am, mntfs *mf)
xfs_fmount(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);
error = mount_xfs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_xfs: %m");
@@ -163,9 +158,7 @@ xfs_mount(am_node *am, mntfs *mf)
static int
xfs_umount(am_node *am, mntfs *mf)
xfs_fumount(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);
return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
}
+155 -334
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/opts.c
* $Id: opts.c,v 1.8.2.7 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -93,13 +94,11 @@ struct functable {
* FORWARD DEFINITION:
*/
static int f_in_network(char *);
static int f_xhost(char *);
static int f_netgrp(char *);
static int f_netgrpd(char *);
static int f_exists(char *);
static int f_false(char *);
static int f_true(char *);
static inline char *expand_options(char *key);
/*
* STATICS:
@@ -113,7 +112,7 @@ static char *opt_key = nullstr;
static char *opt_keyd = nullstr;
static char *opt_map = nullstr;
static char *opt_path = nullstr;
char uid_str[SIZEOF_UID_STR], gid_str[SIZEOF_GID_STR];
static char uid_str[12], gid_str[12];
char *opt_uid = uid_str;
char *opt_gid = gid_str;
static char *vars[8];
@@ -122,11 +121,11 @@ static char *literal_dollar = "$"; /* ${dollar}: a literal '$' in maps */
/*
* GLOBALS
*/
static struct am_opts fs_static; /* copy of the options to play with */
struct am_opts fs_static; /* copy of the options to play with */
/*
* Options in some order corresponding to frequency of use so that
* Options in something corresponding to frequency of use so that
* first-match algorithm is sped up.
*/
static struct opt opt_fields[] = {
@@ -192,8 +191,6 @@ static struct opt opt_fields[] = {
&fs_static.opt_mount, 0, 0, FALSE },
{ S("unmount"),
&fs_static.opt_unmount, 0, 0, FALSE },
{ S("umount"),
&fs_static.opt_umount, 0, 0, FALSE },
{ S("cache"),
&fs_static.opt_cache, 0, 0, FALSE },
{ S("user"),
@@ -204,6 +201,7 @@ static struct opt opt_fields[] = {
0, &opt_dkey, 0, FALSE },
{ S("key."),
0, &opt_keyd, 0, FALSE },
/* XXX: should maptype really be a variable? I think selector. -Erez */
{ S("maptype"),
&fs_static.opt_maptype, 0, 0, FALSE },
{ S("cachedir"),
@@ -214,8 +212,6 @@ static struct opt opt_fields[] = {
0, &opt_uid, 0, FALSE },
{ S("gid"),
0, &opt_gid, 0, FALSE },
{ S("mount_type"),
&fs_static.opt_mount_type, 0, 0, FALSE },
{ S("dollar"),
&literal_dollar, 0, 0, FALSE },
{ S("var0"),
@@ -239,7 +235,6 @@ static struct opt opt_fields[] = {
static struct functable functable[] = {
{ "in_network", f_in_network },
{ "xhost", f_xhost },
{ "netgrp", f_netgrp },
{ "netgrpd", f_netgrpd },
{ "exists", f_exists },
@@ -270,7 +265,6 @@ static opt_apply expansions[] =
{&fs_static.opt_remopts, "${opts}"},
{&fs_static.opt_mount, 0},
{&fs_static.opt_unmount, 0},
{&fs_static.opt_umount, 0},
{&fs_static.opt_cachedir, 0},
{&fs_static.opt_addopts, 0},
{0, 0},
@@ -292,7 +286,6 @@ static opt_apply to_free[] =
{&fs_static.opt_remopts, 0},
{&fs_static.opt_mount, 0},
{&fs_static.opt_unmount, 0},
{&fs_static.opt_umount, 0},
{&fs_static.opt_cachedir, 0},
{&fs_static.opt_addopts, 0},
{&vars[0], 0},
@@ -309,7 +302,6 @@ static opt_apply to_free[] =
/*
* expand backslash escape sequences
* (escaped slash is handled separately in normalize_slash)
*/
static char
backslash(char **p)
@@ -465,99 +457,33 @@ functable_lookup(char *key)
}
/*
* Fill in the global structure fs_static by
* cracking the string opts. opts may be
* scribbled on at will. Does NOT evaluate options.
* Returns 0 on error, 1 if no syntax errors were discovered.
*/
static int
split_opts(char *opts, char *mapkey)
eval_opts(char *opts, char *mapkey)
{
/*
* Fill in the global structure fs_static by
* cracking the string opts. opts may be
* scribbled on at will.
*/
char *o = opts;
char *f;
/*
* For each user-specified option
*/
for (f = opt(&o); *f; f = opt(&o)) {
while (*(f = opt(&o))) {
struct opt *op;
char *eq = strchr(f, '=');
char *opt = NULL;
if (!eq)
continue;
if (*(eq-1) == '!' ||
eq[1] == '=' ||
eq[1] == '!') { /* != or == or =! */
continue; /* we don't care about selectors */
}
if (*(eq-1) == ':') { /* := */
*(eq-1) = '\0';
} else {
/* old style assignment */
eq[0] = '\0';
}
opt = eq + 1;
/*
* For each recognized option
*/
for (op = opt_fields; op->name; op++) {
/*
* Check whether they match
*/
if (FSTREQ(op->name, f)) {
if (op->sel_p) {
plog(XLOG_USER, "key %s: Can't assign to a selector (%s)",
mapkey, op->name);
return 0;
}
*op->optp = opt; /* actual assignment into fs_static */
break; /* break out of for loop */
} /* end of "if (FSTREQ(op->name, f))" statement */
} /* end of "for (op = opt_fields..." statement */
if (!op->name)
plog(XLOG_USER, "key %s: Unrecognized key/option \"%s\"", mapkey, f);
}
return 1;
}
/*
* Just evaluate selectors, which were split by split_opts.
* Returns 0 on error or no match, 1 if matched.
*/
static int
eval_selectors(char *opts, char *mapkey)
{
char *o, *old_o;
char *f;
int ret = 0;
o = old_o = strdup(opts);
/*
* For each user-specified option
*/
for (f = opt(&o); *f; f = opt(&o)) {
struct opt *op;
enum vs_opt vs_opt;
enum vs_opt vs_opt = VarAss;
char *eq = strchr(f, '=');
char *fx;
IntFuncPtr func;
char *opt = NULL;
char *arg;
if (!eq) {
if (!eq || eq[1] == '\0' || eq == f) {
/*
* No value, is it a function call?
*/
arg = strchr(f, '(');
char *arg = strchr(f, '(');
if (!arg || arg[1] == '\0' || arg == f) {
/*
@@ -576,54 +502,43 @@ eval_selectors(char *opts, char *mapkey)
}
*fx = '\0';
if (f[0] == '!') {
vs_opt = SelNE;
f++;
} else {
vs_opt = SelEQ;
}
/*
* look up f in functable and pass it arg.
* func must return 0 on failure, and 1 on success.
*/
if ((func = functable_lookup(f))) {
int funok;
/* this allocates memory, don't forget to free */
arg = expand_options(arg);
funok = func(arg);
XFREE(arg);
if (vs_opt == SelNE)
funok = !funok;
if (!funok)
goto out;
if (!(*func) (arg)) {
return (0);
}
continue;
} else if (NSTREQ(f, "!", 1) && (func = functable_lookup(&f[1]))) {
/* then this is a negated prefixed function such as "!exists" */
plog(XLOG_INFO, "executing negated function %s", &f[1]);
if ((*func) (arg)) {
return (0);
}
continue;
} else {
plog(XLOG_USER, "key %s: unknown function \"%s\"", mapkey, f);
goto out;
}
} else {
if (eq[1] == '\0' || eq == f) {
/* misformed selector */
plog(XLOG_USER, "key %s: Bad selector \"%s\"", mapkey, f);
continue;
return (0);
}
}
/*
* Check what type of operation is happening
* !=, =! is SelNE
* == is SelEQ
* =, := is VarAss
* := is VarAss
*/
if (*(eq-1) == '!') { /* != */
if (eq[-1] == '!') { /* != */
vs_opt = SelNE;
*(eq-1) = '\0';
eq[-1] = '\0';
opt = eq + 1;
} else if (eq[-1] == ':') { /* := */
vs_opt = VarAss;
eq[-1] = '\0';
opt = eq + 1;
} else if (*(eq-1) == ':') { /* := */
continue;
} else if (eq[1] == '=') { /* == */
vs_opt = SelEQ;
eq[0] = '\0';
@@ -632,9 +547,6 @@ eval_selectors(char *opts, char *mapkey)
vs_opt = SelNE;
eq[0] = '\0';
opt = eq + 2;
} else {
/* old style assignment */
continue;
}
/*
@@ -645,47 +557,48 @@ eval_selectors(char *opts, char *mapkey)
* Check whether they match
*/
if (FSTREQ(op->name, f)) {
opt = expand_options(opt);
if (op->sel_p != NULL) {
int selok;
if (op->case_insensitive) {
selok = STRCEQ(*op->sel_p, opt);
} else {
selok = STREQ(*op->sel_p, opt);
}
if (vs_opt == SelNE)
selok = !selok;
if (!selok) {
int selok;
switch (vs_opt) {
case SelEQ:
case SelNE:
if ((selok = (op->sel_p != NULL))) {
if (op->case_insensitive) {
selok = (STRCEQ(*op->sel_p, opt) == (vs_opt == SelNE));
} else {
selok = (STREQ(*op->sel_p, opt) == (vs_opt == SelNE));
}
}
if (selok) {
plog(XLOG_MAP, "key %s: map selector %s (=%s) did not %smatch %s",
mapkey,
op->name,
*op->sel_p,
vs_opt == SelNE ? "mis" : "",
opt);
XFREE(opt);
goto out;
return 0;
}
XFREE(opt);
}
/* check if to apply a function */
if (op->fxn_p) {
int funok;
funok = op->fxn_p(opt);
if (vs_opt == SelNE)
funok = !funok;
if (!funok) {
/* check if to apply a function */
if (op->fxn_p &&
((*op->fxn_p)(opt) == (vs_opt == SelNE))) {
plog(XLOG_MAP, "key %s: map function %s did not %smatch %s",
mapkey,
op->name,
vs_opt == SelNE ? "mis" : "",
opt);
XFREE(opt);
goto out;
return 0;
}
XFREE(opt);
}
break;
case VarAss:
if (op->sel_p) {
plog(XLOG_USER, "key %s: Can't assign to a selector (%s)",
mapkey, op->name);
return 0;
}
*op->optp = opt;
break;
} /* end of "switch (vs_opt)" statement */
break; /* break out of for loop */
}
}
@@ -694,12 +607,7 @@ eval_selectors(char *opts, char *mapkey)
plog(XLOG_USER, "key %s: Unrecognized key/option \"%s\"", mapkey, f);
}
/* all is ok */
ret = 1;
out:
free(old_o);
return ret;
return 1;
}
@@ -787,9 +695,9 @@ strip_selectors(char *opts, char *mapkey)
* == is SelEQ
* := is VarAss
*/
if (*(eq-1) == '!') { /* != */
if (eq[-1] == '!') { /* != */
vs_opt = SelNE;
} else if (*(eq-1) == ':') { /* := */
} else if (eq[-1] == ':') { /* := */
vs_opt = VarAss;
} else if (eq[1] == '=') { /* == */
vs_opt = SelEQ;
@@ -807,7 +715,9 @@ strip_selectors(char *opts, char *mapkey)
case VarAss:
/* found the first assignment, return the string starting with it */
#ifdef DEBUG
dlog("found first assignment past selectors \"%s\"", o);
#endif /* DEBUG */
return oo;
}
}
@@ -828,86 +738,27 @@ f_in_network(char *arg)
int status;
if (!arg)
return 0;
return FALSE;
status = is_network_member(arg);
dlog("%s is %son a local network", arg, (status ? "" : "not "));
#ifdef DEBUG
plog(XLOG_USER, "%s is %son a local network",
arg, (status ? "" : "not "));
#endif /* DEBUG */
return status;
}
/*
* Test if arg is any of this host's names or aliases (CNAMES).
* Note: this function compares against the fully expanded host name (hostd).
* XXX: maybe we also need to compare against the stripped host name?
*/
static int
f_xhost(char *arg)
{
struct hostent *hp;
char **cp;
if (!arg)
return 0;
/* simple test: does it match main host name? */
if (STREQ(arg, opt_hostd))
return 1;
/* now find all of the names of "arg" and compare against opt_hostd */
hp = gethostbyname(arg);
if (hp == NULL) {
#ifdef HAVE_HSTRERROR
plog(XLOG_ERROR, "gethostbyname xhost(%s): %s", arg, hstrerror(h_errno));
#else /* not HAVE_HSTRERROR */
plog(XLOG_ERROR, "gethostbyname xhost(%s): h_errno %d", arg, h_errno);
#endif /* not HAVE_HSTRERROR */
return 0;
}
/* check primary name */
if (hp->h_name) {
dlog("xhost: compare %s==%s", hp->h_name, opt_hostd);
if (STREQ(hp->h_name, opt_hostd)) {
plog(XLOG_INFO, "xhost(%s): matched h_name %s", arg, hp->h_name);
return 1;
}
}
/* check all aliases, if any */
if (hp->h_aliases == NULL) {
dlog("gethostbyname(%s) has no aliases", arg);
return 0;
}
cp = hp->h_aliases;
while (*cp) {
dlog("xhost: compare alias %s==%s", *cp, opt_hostd);
if (STREQ(*cp, opt_hostd)) {
plog(XLOG_INFO, "xhost(%s): matched alias %s", arg, *cp);
return 1;
}
cp++;
}
/* nothing matched */
return 0;
}
/* test if this host (short hostname form) is in netgroup (arg) */
static int
f_netgrp(char *arg)
{
int status;
char *ptr, *nhost;
if ((ptr = strchr(arg, ',')) != NULL) {
*ptr = '\0';
nhost = ptr + 1;
} else {
nhost = opt_host;
}
status = innetgr(arg, nhost, NULL, NULL);
dlog("netgrp = %s status = %d host = %s", arg, status, nhost);
if (ptr)
*ptr = ',';
status = innetgr(arg, opt_host, NULL, NULL);
#ifdef DEBUG
plog(XLOG_USER, "netgrp = %s status = %d host = %s", arg, status, opt_host);
#endif /* DEBUG */
return status;
}
@@ -917,18 +768,11 @@ static int
f_netgrpd(char *arg)
{
int status;
char *ptr, *nhost;
if ((ptr = strchr(arg, ',')) != NULL) {
*ptr = '\0';
nhost = ptr + 1;
} else {
nhost = opt_hostd;
}
status = innetgr(arg, nhost, NULL, NULL);
dlog("netgrp = %s status = %d hostd = %s", arg, status, nhost);
if (ptr)
*ptr = ',';
status = innetgr(arg, opt_hostd, NULL, NULL);
#ifdef DEBUG
plog(XLOG_USER, "netgrp = %s status = %d hostd = %s", arg, status, opt_hostd);
#endif /* DEBUG */
return status;
}
@@ -970,6 +814,7 @@ free_op(opt_apply *p, int b)
{
if (*p->opt) {
XFREE(*p->opt);
*p->opt = 0;
}
}
@@ -980,12 +825,9 @@ free_op(opt_apply *p, int b)
void
normalize_slash(char *p)
{
char *f, *f0;
char *f = strchr(p, '/');
char *f0 = f;
if (!(gopt.flags & CFM_NORMALIZE_SLASHES))
return;
f0 = f = strchr(p, '/');
if (f) {
char *t = f;
do {
@@ -1007,9 +849,6 @@ normalize_slash(char *p)
/* assert(*f != '/'); */
/* keep copying up to next / */
while (*f && *f != '/') {
/* support escaped slashes '\/' */
if (f[0] == '\\' && f[1] == '/')
f++; /* skip backslash */
*t++ = *f++;
}
@@ -1024,20 +863,22 @@ normalize_slash(char *p)
/*
* Macro-expand an option. Note that this does not
* handle recursive expansions. They will go badly wrong.
* If sel_p is true then old expand selectors, otherwise
* If sel is true then old expand selectors, otherwise
* don't expand selectors.
*/
static char *
expand_op(char *opt, int sel_p)
static void
expand_op(opt_apply *p, int sel_p)
{
#define EXPAND_ERROR "No space to expand \"%s\""
static const char expand_error[] = "No space to expand \"%s\"";
char expbuf[MAXPATHLEN + 1];
char nbuf[NLEN + 1];
char *ep = expbuf;
char *cp = opt;
char *cp = *p->opt;
char *dp;
struct opt *op;
char *cp_orig = opt;
#ifdef DEBUG
char *cp_orig = *p->opt;
#endif /* DEBUG */
while ((dp = strchr(cp, '$'))) {
char ch;
@@ -1047,18 +888,12 @@ expand_op(char *opt, int sel_p)
{
int len = dp - cp;
if (len > 0) {
if (BUFSPACE(ep, len)) {
/*
* We use strncpy (not xstrlcpy) because 'ep' relies on its
* semantics. BUFSPACE guarantees that ep can hold len.
*/
strncpy(ep, cp, len);
ep += len;
} else {
plog(XLOG_ERROR, EXPAND_ERROR, opt);
goto out;
}
if (BUFSPACE(ep, len)) {
strncpy(ep, cp, len);
ep += len;
} else {
plog(XLOG_ERROR, expand_error, *p->opt);
goto out;
}
}
@@ -1068,7 +903,7 @@ expand_op(char *opt, int sel_p)
if (BUFSPACE(ep, 1)) {
*ep++ = '$';
} else {
plog(XLOG_ERROR, EXPAND_ERROR, opt);
plog(XLOG_ERROR, expand_error, *p->opt);
goto out;
}
} else if (ch == '{') {
@@ -1089,7 +924,7 @@ expand_op(char *opt, int sel_p)
/*
* Just give up
*/
plog(XLOG_USER, "No closing '}' in \"%s\"", opt);
plog(XLOG_USER, "No closing '}' in \"%s\"", *p->opt);
goto out;
}
len = br_p - cp;
@@ -1104,7 +939,7 @@ expand_op(char *opt, int sel_p)
todo = E_File;
cp++;
--len;
} else if (*(br_p-1) == '/') {
} else if (br_p[-1] == '/') {
/*
* Take all but the last component
*/
@@ -1117,7 +952,7 @@ expand_op(char *opt, int sel_p)
todo = E_Domain;
cp++;
--len;
} else if (*(br_p-1) == '.') {
} else if (br_p[-1] == '.') {
/*
* Take host name
*/
@@ -1141,11 +976,6 @@ expand_op(char *opt, int sel_p)
/*
* Put the string into another buffer so
* we can do comparisons.
*
* We use strncpy here (not xstrlcpy) because the dest is meant
* to be truncated and we don't want to log it as an error. The
* use of the BUFSPACE macro above guarantees the safe use of
* strncpy with nbuf.
*/
strncpy(nbuf, cp, len);
nbuf[len] = '\0';
@@ -1173,12 +1003,12 @@ expand_op(char *opt, int sel_p)
/*
* Copy the string across unexpanded
*/
xsnprintf(xbuf, sizeof(xbuf), "${%s%s%s}",
todo == E_File ? "/" :
todo == E_Domain ? "." : "",
nbuf,
todo == E_Dir ? "/" :
todo == E_Host ? "." : "");
sprintf(xbuf, "${%s%s%s}",
todo == E_File ? "/" :
todo == E_Domain ? "." : "",
nbuf,
todo == E_Dir ? "/" :
todo == E_Host ? "." : "");
val = xbuf;
/*
* Make sure expansion doesn't
@@ -1237,11 +1067,11 @@ expand_op(char *opt, int sel_p)
break;
}
if (BUFSPACE(ep, vlen+1)) {
xstrlcpy(ep, vptr, vlen+1);
if (BUFSPACE(ep, vlen)) {
strcpy(ep, vptr);
ep += vlen;
} else {
plog(XLOG_ERROR, EXPAND_ERROR, opt);
plog(XLOG_ERROR, expand_error, *p->opt);
goto out;
}
}
@@ -1266,15 +1096,17 @@ expand_op(char *opt, int sel_p)
if (env) {
int vlen = strlen(env);
if (BUFSPACE(ep, vlen+1)) {
xstrlcpy(ep, env, vlen+1);
if (BUFSPACE(ep, vlen)) {
strcpy(ep, env);
ep += vlen;
} else {
plog(XLOG_ERROR, EXPAND_ERROR, opt);
plog(XLOG_ERROR, expand_error, *p->opt);
goto out;
}
if (amuDebug(D_STR))
#ifdef DEBUG
amuDebug(D_STR)
plog(XLOG_DEBUG, "Environment gave \"%s\" -> \"%s\"", nbuf, env);
#endif /* DEBUG */
} else {
plog(XLOG_USER, "Unknown sequence \"${%s}\"", nbuf);
}
@@ -1283,7 +1115,7 @@ expand_op(char *opt, int sel_p)
/*
* Error, error
*/
plog(XLOG_USER, "Unknown $ sequence in \"%s\"", opt);
plog(XLOG_USER, "Unknown $ sequence in \"%s\"", *p->opt);
}
}
@@ -1291,33 +1123,33 @@ out:
/*
* Handle common case - no expansion
*/
if (cp == opt) {
opt = strdup(cp);
if (cp == *p->opt) {
*p->opt = strdup(cp);
} else {
/*
* Finish off the expansion
*/
int vlen = strlen(cp);
if (BUFSPACE(ep, vlen+1)) {
xstrlcpy(ep, cp, vlen+1);
/* ep += vlen; */
if (BUFSPACE(ep, strlen(cp))) {
strcpy(ep, cp);
/* ep += strlen(ep); */
} else {
plog(XLOG_ERROR, EXPAND_ERROR, opt);
plog(XLOG_ERROR, expand_error, *p->opt);
}
/*
* Save the expansion
*/
opt = strdup(expbuf);
*p->opt = strdup(expbuf);
}
normalize_slash(opt);
normalize_slash(*p->opt);
if (amuDebug(D_STR)) {
#ifdef DEBUG
amuDebug(D_STR) {
plog(XLOG_DEBUG, "Expansion of \"%s\"...", cp_orig);
plog(XLOG_DEBUG, "......... is \"%s\"", opt);
plog(XLOG_DEBUG, "... is \"%s\"", *p->opt);
}
return opt;
#endif /* DEBUG */
}
@@ -1328,15 +1160,15 @@ static void
expand_opts(opt_apply *p, int sel_p)
{
if (*p->opt) {
*p->opt = expand_op(*p->opt, sel_p);
expand_op(p, sel_p);
} else if (p->val) {
/*
* Do double expansion, remembering
* to free the string from the first
* expansion...
*/
char *s = expand_op(p->val, TRUE);
*p->opt = expand_op(s, sel_p);
char *s = *p->opt = expand_key(p->val);
expand_op(p, sel_p);
XFREE(s);
}
}
@@ -1374,22 +1206,18 @@ free_opts(am_opts *fo)
/*
* Expand selectors (variables that cannot be assigned to or overridden)
* Expand lookup key
*/
char *
expand_selectors(char *key)
expand_key(char *key)
{
return expand_op(key, TRUE);
}
opt_apply oa;
oa.opt = &key;
oa.val = 0;
expand_opts(&oa, TRUE);
/*
* Expand options (i.e. non-selectors, see above for definition)
*/
static inline char *
expand_options(char *key)
{
return expand_op(key, FALSE);
return key;
}
@@ -1397,14 +1225,10 @@ expand_options(char *key)
* Remove trailing /'s from a string
* unless the string is a single / (Steven Glassman)
* or unless it is two slashes // (Kevin D. Bond)
* or unless amd.conf says not to touch slashes.
*/
void
deslashify(char *s)
{
if (!(gopt.flags & CFM_NORMALIZE_SLASHES))
return;
if (s && *s) {
char *sl = s + strlen(s);
@@ -1452,27 +1276,24 @@ eval_fs_opts(am_opts *fo, char *opts, char *g_opts, char *path, char *key, char
/*
* Expand global options
*/
fs_static.fs_glob = expand_selectors(g_opts);
fs_static.fs_glob = expand_key(g_opts);
/*
* Expand local options
*/
fs_static.fs_local = expand_selectors(opts);
fs_static.fs_local = expand_key(opts);
/* break global options into fs_static fields */
if ((ok = split_opts(fs_static.fs_glob, key))) {
dlog("global split_opts ok");
/*
* evaluate local selectors
*/
if ((ok = eval_selectors(fs_static.fs_local, key))) {
dlog("local eval_selectors ok");
/* if the local selectors matched, then do the local overrides */
ok = split_opts(fs_static.fs_local, key);
if (ok)
dlog("local split_opts ok");
}
}
/*
* Expand default (global) options
*/
if (!eval_opts(fs_static.fs_glob, key))
ok = FALSE;
/*
* Expand local options
*/
if (ok && !eval_opts(fs_static.fs_local, key))
ok = FALSE;
/*
* Normalize remote host name.
-498
View File
@@ -1,498 +0,0 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgment:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* File: am-utils/amd/readdir.c
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/****************************************************************************
*** MACROS ***
****************************************************************************/
#define DOT_DOT_COOKIE (u_int) 1
#define MAX_CHAIN 2048
/****************************************************************************
*** FORWARD DEFINITIONS ***
****************************************************************************/
static int key_already_in_chain(char *keyname, const nfsentry *chain);
static nfsentry *make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable);
static int amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count, int fully_browsable);
/****************************************************************************
*** FUNCTIONS ***
****************************************************************************/
/*
* Was: NEW_TOPLVL_READDIR
* Search a chain for an entry with some name.
* -Erez Zadok <ezk@cs.columbia.edu>
*/
static int
key_already_in_chain(char *keyname, const nfsentry *chain)
{
const nfsentry *tmpchain = chain;
while (tmpchain) {
if (keyname && tmpchain->ne_name && STREQ(keyname, tmpchain->ne_name))
return 1;
tmpchain = tmpchain->ne_nextentry;
}
return 0;
}
/*
* Create a chain of entries which are not linked.
* -Erez Zadok <ezk@cs.columbia.edu>
*/
static nfsentry *
make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable)
{
static u_int last_cookie = (u_int) 2; /* monotonically increasing */
static nfsentry chain[MAX_CHAIN];
static int max_entries = MAX_CHAIN;
char *key;
int num_entries = 0, i;
u_int preflen = 0;
nfsentry *retval = (nfsentry *) NULL;
mntfs *mf;
mnt_map *mmp;
if (!mp) {
plog(XLOG_DEBUG, "make_entry_chain: mp is (NULL)");
return retval;
}
mf = mp->am_mnt;
if (!mf) {
plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt is (NULL)");
return retval;
}
mmp = (mnt_map *) mf->mf_private;
if (!mmp) {
plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt->mf_private is (NULL)");
return retval;
}
if (mp->am_pref)
preflen = strlen(mp->am_pref);
/* iterate over keys */
for (i = 0; i < NKVHASH; i++) {
kv *k;
for (k = mmp->kvhash[i]; k ; k = k->next) {
/*
* Skip unwanted entries which are either not real entries or
* very difficult to interpret (wildcards...) This test needs
* lots of improvement. Any takers?
*/
key = k->key;
if (!key)
continue;
/* Skip '/defaults' */
if (STREQ(key, "/defaults"))
continue;
/* Skip '*' */
if (!fully_browsable && strchr(key, '*'))
continue;
/*
* If the map has a prefix-string then check if the key starts with
* this string, and if it does, skip over this prefix. If it has a
* prefix and it doesn't match the start of the key, skip it.
*/
if (preflen) {
if (preflen > strlen(key))
continue;
if (!NSTREQ(key, mp->am_pref, preflen))
continue;
key += preflen;
}
/* no more '/' are allowed, unless browsable_dirs=full was used */
if (!fully_browsable && strchr(key, '/'))
continue;
/* no duplicates allowed */
if (key_already_in_chain(key, current_chain))
continue;
/* fill in a cell and link the entry */
if (num_entries >= max_entries) {
/* out of space */
plog(XLOG_DEBUG, "make_entry_chain: no more space in chain");
if (num_entries > 0) {
chain[num_entries - 1].ne_nextentry = 0;
retval = &chain[0];
}
return retval;
}
/* we have space. put entry in next cell */
++last_cookie;
chain[num_entries].ne_fileid = (u_int) last_cookie;
*(u_int *) chain[num_entries].ne_cookie = (u_int) last_cookie;
chain[num_entries].ne_name = key;
if (num_entries < max_entries - 1) { /* link to next one */
chain[num_entries].ne_nextentry = &chain[num_entries + 1];
}
++num_entries;
} /* end of "while (k)" */
} /* end of "for (i ... NKVHASH ..." */
/* terminate chain */
if (num_entries > 0) {
chain[num_entries - 1].ne_nextentry = 0;
retval = &chain[0];
}
return retval;
}
/* This one is called only if map is browsable */
static int
amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count, int fully_browsable)
{
u_int gen = *(u_int *) cookie;
int chain_length, i;
static nfsentry *te, *te_next;
static int j;
dp->dl_eof = FALSE; /* assume readdir not done */
if (amuDebug(D_READDIR))
plog(XLOG_DEBUG, "amfs_readdir_browsable gen=%u, count=%d",
gen, count);
if (gen == 0) {
/*
* In the default instance (which is used to start a search) we return
* "." and "..".
*
* This assumes that the count is big enough to allow both "." and ".."
* to be returned in a single packet. If it isn't (which would be
* fairly unbelievable) then tough.
*/
dlog("amfs_readdir_browsable: default search");
/*
* Check for enough room. This is extremely approximate but is more
* than enough space. Really need 2 times:
* 4byte fileid
* 4byte cookie
* 4byte name length
* 4byte name
* plus the dirlist structure */
if (count < (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp))))
return EINVAL;
/*
* compute # of entries to send in this chain.
* heuristics: 128 bytes per entry.
* This is too much probably, but it seems to work better because
* of the re-entrant nature of nfs_readdir, and esp. on systems
* like OpenBSD 2.2.
*/
chain_length = count / 128;
/* reset static state counters */
te = te_next = NULL;
dp->dl_entries = ep;
/* construct "." */
ep[0].ne_fileid = mp->am_gen;
ep[0].ne_name = ".";
ep[0].ne_nextentry = &ep[1];
*(u_int *) ep[0].ne_cookie = 0;
/* construct ".." */
if (mp->am_parent)
ep[1].ne_fileid = mp->am_parent->am_gen;
else
ep[1].ne_fileid = mp->am_gen;
ep[1].ne_name = "..";
ep[1].ne_nextentry = 0;
*(u_int *) ep[1].ne_cookie = DOT_DOT_COOKIE;
/*
* If map is browsable, call a function make_entry_chain() to construct
* a linked list of unmounted keys, and return it. Then link the chain
* to the regular list. Get the chain only once, but return
* chunks of it each time.
*/
te = make_entry_chain(mp, dp->dl_entries, fully_browsable);
if (!te)
return 0;
if (amuDebug(D_READDIR)) {
nfsentry *ne;
for (j = 0, ne = te; ne; ne = ne->ne_nextentry)
plog(XLOG_DEBUG, "gen1 key %4d \"%s\"", j++, ne->ne_name);
}
/* return only "chain_length" entries */
te_next = te;
for (i=1; i<chain_length; ++i) {
te_next = te_next->ne_nextentry;
if (!te_next)
break;
}
if (te_next) {
nfsentry *te_saved = te_next->ne_nextentry;
te_next->ne_nextentry = NULL; /* terminate "te" chain */
te_next = te_saved; /* save rest of "te" for next iteration */
dp->dl_eof = FALSE; /* tell readdir there's more */
} else {
dp->dl_eof = TRUE; /* tell readdir that's it */
}
ep[1].ne_nextentry = te; /* append this chunk of "te" chain */
if (amuDebug(D_READDIR)) {
nfsentry *ne;
for (j = 0, ne = te; ne; ne = ne->ne_nextentry)
plog(XLOG_DEBUG, "gen2 key %4d \"%s\"", j++, ne->ne_name);
for (j = 0, ne = ep; ne; ne = ne->ne_nextentry)
plog(XLOG_DEBUG, "gen2+ key %4d \"%s\" fi=%d ck=%d",
j++, ne->ne_name, ne->ne_fileid, *(u_int *)ne->ne_cookie);
plog(XLOG_DEBUG, "EOF is %d", dp->dl_eof);
}
return 0;
} /* end of "if (gen == 0)" statement */
dlog("amfs_readdir_browsable: real child");
if (gen == DOT_DOT_COOKIE) {
dlog("amfs_readdir_browsable: End of readdir in %s", mp->am_path);
dp->dl_eof = TRUE;
dp->dl_entries = 0;
return 0;
}
/*
* If browsable directories, then continue serving readdir() with another
* chunk of entries, starting from where we left off (when gen was equal
* to 0). Once again, assume last chunk served to readdir.
*/
dp->dl_eof = TRUE;
dp->dl_entries = ep;
te = te_next; /* reset 'te' from last saved te_next */
if (!te) { /* another indicator of end of readdir */
dp->dl_entries = 0;
return 0;
}
/*
* compute # of entries to send in this chain.
* heuristics: 128 bytes per entry.
*/
chain_length = count / 128;
/* return only "chain_length" entries */
for (i = 1; i < chain_length; ++i) {
te_next = te_next->ne_nextentry;
if (!te_next)
break;
}
if (te_next) {
nfsentry *te_saved = te_next->ne_nextentry;
te_next->ne_nextentry = NULL; /* terminate "te" chain */
te_next = te_saved; /* save rest of "te" for next iteration */
dp->dl_eof = FALSE; /* tell readdir there's more */
}
ep = te; /* send next chunk of "te" chain */
dp->dl_entries = ep;
if (amuDebug(D_READDIR)) {
nfsentry *ne;
plog(XLOG_DEBUG, "dl_entries=%p, te_next=%p, dl_eof=%d",
dp->dl_entries, te_next, dp->dl_eof);
for (ne = te; ne; ne = ne->ne_nextentry)
plog(XLOG_DEBUG, "gen3 key %4d \"%s\"", j++, ne->ne_name);
}
return 0;
}
/*
* This readdir function which call a special version of it that allows
* browsing if browsable_dirs=yes was set on the map.
*/
int
amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count)
{
u_int gen = *(u_int *) cookie;
am_node *xp;
mntent_t mnt;
dp->dl_eof = FALSE; /* assume readdir not done */
/* check if map is browsable */
if (mp->am_mnt && mp->am_mnt->mf_mopts) {
mnt.mnt_opts = mp->am_mnt->mf_mopts;
if (amu_hasmntopt(&mnt, "fullybrowsable"))
return amfs_readdir_browsable(mp, cookie, dp, ep, count, TRUE);
if (amu_hasmntopt(&mnt, "browsable"))
return amfs_readdir_browsable(mp, cookie, dp, ep, count, FALSE);
}
/* when gen is 0, we start reading from the beginning of the directory */
if (gen == 0) {
/*
* In the default instance (which is used to start a search) we return
* "." and "..".
*
* This assumes that the count is big enough to allow both "." and ".."
* to be returned in a single packet. If it isn't (which would be
* fairly unbelievable) then tough.
*/
dlog("amfs_generic_readdir: default search");
/*
* Check for enough room. This is extremely approximate but is more
* than enough space. Really need 2 times:
* 4byte fileid
* 4byte cookie
* 4byte name length
* 4byte name
* plus the dirlist structure */
if (count < (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp))))
return EINVAL;
xp = next_nonerror_node(mp->am_child);
dp->dl_entries = ep;
/* construct "." */
ep[0].ne_fileid = mp->am_gen;
ep[0].ne_name = ".";
ep[0].ne_nextentry = &ep[1];
*(u_int *) ep[0].ne_cookie = 0;
/* construct ".." */
if (mp->am_parent)
ep[1].ne_fileid = mp->am_parent->am_gen;
else
ep[1].ne_fileid = mp->am_gen;
ep[1].ne_name = "..";
ep[1].ne_nextentry = 0;
*(u_int *) ep[1].ne_cookie = (xp ? xp->am_gen : DOT_DOT_COOKIE);
if (!xp)
dp->dl_eof = TRUE; /* by default assume readdir done */
if (amuDebug(D_READDIR)) {
nfsentry *ne;
int j;
for (j = 0, ne = ep; ne; ne = ne->ne_nextentry)
plog(XLOG_DEBUG, "gen1 key %4d \"%s\" fi=%d ck=%d",
j++, ne->ne_name, ne->ne_fileid, *(u_int *)ne->ne_cookie);
}
return 0;
}
dlog("amfs_generic_readdir: real child");
if (gen == DOT_DOT_COOKIE) {
dlog("amfs_generic_readdir: End of readdir in %s", mp->am_path);
dp->dl_eof = TRUE;
dp->dl_entries = 0;
if (amuDebug(D_READDIR))
plog(XLOG_DEBUG, "end of readdir eof=TRUE, dl_entries=0\n");
return 0;
}
/* non-browsable directories code */
xp = mp->am_child;
while (xp && xp->am_gen != gen)
xp = xp->am_osib;
if (xp) {
int nbytes = count / 2; /* conservative */
int todo = MAX_READDIR_ENTRIES;
dp->dl_entries = ep;
do {
am_node *xp_next = next_nonerror_node(xp->am_osib);
if (xp_next) {
*(u_int *) ep->ne_cookie = xp_next->am_gen;
} else {
*(u_int *) ep->ne_cookie = DOT_DOT_COOKIE;
dp->dl_eof = TRUE;
}
ep->ne_fileid = xp->am_gen;
ep->ne_name = xp->am_name;
nbytes -= sizeof(*ep) + 1;
if (xp->am_name)
nbytes -= strlen(xp->am_name);
xp = xp_next;
if (nbytes > 0 && !dp->dl_eof && todo > 1) {
ep->ne_nextentry = ep + 1;
ep++;
--todo;
} else {
todo = 0;
}
} while (todo > 0);
ep->ne_nextentry = 0;
if (amuDebug(D_READDIR)) {
nfsentry *ne;
int j;
for (j=0,ne=ep; ne; ne=ne->ne_nextentry)
plog(XLOG_DEBUG, "gen2 key %4d \"%s\" fi=%d ck=%d",
j++, ne->ne_name, ne->ne_fileid, *(u_int *)ne->ne_cookie);
}
return 0;
}
return ESTALE;
}
+119 -199
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/restart.c
* $Id: restart.c,v 1.3.2.4 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -48,81 +49,14 @@
#include <amd.h>
static void
restart_fake_mntfs(mntent_t *me, am_ops *fs_ops)
{
mntfs *mf;
am_opts mo;
char *cp;
/*
* Partially fake up an opts structure
*/
memset(&mo, 0, sizeof(mo));
mo.opt_rhost = 0;
mo.opt_rfs = 0;
cp = strchr(me->mnt_fsname, ':');
if (cp) {
*cp = '\0';
mo.opt_rhost = strdup(me->mnt_fsname);
mo.opt_rfs = strdup(cp + 1);
*cp = ':';
} else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) {
/*
* Hacky workaround for mnttab NFS entries that only list the server
*/
plog(XLOG_WARNING, "NFS server entry assumed to be %s:/", me->mnt_fsname);
mo.opt_rhost = strdup(me->mnt_fsname);
mo.opt_rfs = strdup("/");
me->mnt_fsname = str3cat(me->mnt_fsname, mo.opt_rhost, ":", "/");
}
mo.opt_fs = me->mnt_dir;
mo.opt_opts = me->mnt_opts;
/*
* Make a new mounted filesystem
*/
mf = find_mntfs(fs_ops, &mo, me->mnt_dir,
me->mnt_fsname, "", me->mnt_opts, "");
if (mf->mf_refc == 1) {
mf->mf_flags |= MFF_RESTART | MFF_MOUNTED;
mf->mf_error = 0; /* Already mounted correctly */
mf->mf_fo = 0;
/*
* Only timeout non-NFS entries
*/
if (!STREQ(me->mnt_type, MNTTAB_TYPE_NFS))
mf->mf_flags |= MFF_RSTKEEP;
if (fs_ops->fs_init) {
/*
* Don't care whether this worked since
* it is checked again when the fs is
* inherited.
*/
(void) (*fs_ops->fs_init) (mf);
}
plog(XLOG_INFO, "%s restarted fstype %s on %s, flags 0x%x",
me->mnt_fsname, fs_ops->fs_type, me->mnt_dir, mf->mf_flags);
} else {
/* Something strange happened - two mounts at the same place! */
free_mntfs(mf);
}
/*
* Clean up mo
*/
if (mo.opt_rhost)
XFREE(mo.opt_rhost);
if (mo.opt_rfs)
XFREE(mo.opt_rfs);
}
/*
* Handle an amd restart.
*
* Scan through the mount list finding all "interesting" mount points.
* Next hack up partial data structures and add the mounted file
* system to the list of known filesystems.
* system to the list of known filesystems. This will leave a
* dangling reference to that filesystems, so when the filesystem is
* finally inherited, an extra "free" must be done on it.
*
* This module relies on internal details of other components. If
* you change something else make *sure* restart() still works.
@@ -130,19 +64,26 @@ restart_fake_mntfs(mntent_t *me, am_ops *fs_ops)
void
restart(void)
{
/*
* Read the existing mount table
*/
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 each entry, find nfs, ufs or auto mounts
* and create a partial am_node to represent it.
*/
for (mlp = ml = read_mtab("restart", mnttab_file_name);
mlp;
mlp = mlp->mnext) {
mntent_t *me = mlp->mnt;
am_ops *fs_ops = 0;
if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) {
if (STREQ(me->mnt_type, MNTTAB_TYPE_UFS)) {
/*
* UFS entry
*/
fs_ops = &ufs_ops;
} else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) {
/*
* NFS entry, or possibly an Amd entry...
* The mnt_fsname for daemon mount points is
@@ -151,21 +92,113 @@ restart(void)
* host:daemon(pidXXX)
*/
char *colon = strchr(me->mnt_fsname, ':');
if (colon && strstr(colon, "(pid"))
continue;
if (colon && strstr(colon, "(pid")) {
plog(XLOG_WARNING, "%s is an existing automount point", me->mnt_dir);
fs_ops = &amfs_link_ops;
} else {
fs_ops = &nfs_ops;
}
#ifdef MNTTAB_TYPE_NFS3
} else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS3)) {
fs_ops = &nfs_ops;
#endif /* MNTTAB_TYPE_NFS3 */
#ifdef MNTTAB_TYPE_LOFS
} else if (STREQ(me->mnt_type, MNTTAB_TYPE_LOFS)) {
fs_ops = &lofs_ops;
#endif /* MNTTAB_TYPE_LOFS */
#ifdef MNTTAB_TYPE_CDFS
} else if (STREQ(me->mnt_type, MNTTAB_TYPE_CDFS)) {
fs_ops = &cdfs_ops;
#endif /* MNTTAB_TYPE_CDFS */
#ifdef MNTTAB_TYPE_PCFS
} else if (STREQ(me->mnt_type, MNTTAB_TYPE_PCFS)) {
fs_ops = &pcfs_ops;
#endif /* MNTTAB_TYPE_PCFS */
#ifdef MNTTAB_TYPE_MFS
} else if (STREQ(me->mnt_type, MNTTAB_TYPE_MFS)) {
/*
* MFS entry. Fake with a symlink.
*/
fs_ops = &amfs_link_ops;
#endif /* MNTTAB_TYPE_MFS */
} else {
/*
* Catch everything else with symlinks to
* avoid recursive mounts. This is debatable...
*/
fs_ops = &amfs_link_ops;
}
/* 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 we found something to do
*/
if (!fs_ops)
fs_ops = &amfs_link_ops;
if (fs_ops) {
mntfs *mf;
am_opts mo;
char *cp;
cp = strchr(me->mnt_fsname, ':');
restart_fake_mntfs(me, fs_ops);
/*
* Partially fake up an opts structure
*/
mo.opt_rhost = 0;
mo.opt_rfs = 0;
if (cp) {
*cp = '\0';
mo.opt_rhost = strdup(me->mnt_fsname);
mo.opt_rfs = strdup(cp + 1);
*cp = ':';
} else if (fs_ops->ffserver == find_nfs_srvr) {
/*
* Prototype 4.4 BSD used to end up here -
* might as well keep the workaround for now
*/
plog(XLOG_WARNING, "NFS server entry assumed to be %s:/", me->mnt_fsname);
mo.opt_rhost = strdup(me->mnt_fsname);
mo.opt_rfs = strdup("/");
me->mnt_fsname = str3cat(me->mnt_fsname, mo.opt_rhost, ":", "/");
}
mo.opt_fs = me->mnt_dir;
mo.opt_opts = me->mnt_opts;
/*
* Make a new mounted filesystem
*/
mf = find_mntfs(fs_ops, &mo, me->mnt_dir,
me->mnt_fsname, "", me->mnt_opts, "");
if (mf->mf_refc == 1) {
mf->mf_flags |= MFF_RESTART | MFF_MOUNTED;
mf->mf_error = 0; /* Already mounted correctly */
mf->mf_fo = 0;
/*
* If the restarted type is a link then
* don't time out.
*/
if (fs_ops == &amfs_link_ops || fs_ops == &ufs_ops)
mf->mf_flags |= MFF_RSTKEEP;
if (fs_ops->fs_init) {
/*
* Don't care whether this worked since
* it is checked again when the fs is
* inherited.
*/
(void) (*fs_ops->fs_init) (mf);
}
plog(XLOG_INFO, "%s restarted fstype %s on %s",
me->mnt_fsname, fs_ops->fs_type, me->mnt_dir);
} else {
/* Something strange happened - two mounts at the same place! */
free_mntfs(mf);
}
/*
* Clean up mo
*/
if (mo.opt_rhost)
XFREE(mo.opt_rhost);
if (mo.opt_rfs)
XFREE(mo.opt_rfs);
}
}
/*
@@ -173,116 +206,3 @@ restart(void)
*/
free_mntlist(ml);
}
/*
* Handle an amd restart for amd's own mount points.
*
* Scan through the mount list finding all daemon mount points
* (determined by the presence of a pid inside the mount info).
* Next hack up partial data structures and add the mounted file
* system to the list of known filesystems.
*
* This module relies on internal details of other components. If
* you change something else make *sure* restart() still works.
*/
void
restart_automounter_nodes(void)
{
mntlist *ml, *mlp;
/* reasonably sized list of restarted nfs ports */
u_short old_ports[256];
memset((voidp) &old_ports, 0, sizeof(u_short) * 256);
/*
* Read the existing mount table. For each entry, find nfs, ufs or auto
* mounts and create a partial am_node to represent it.
*/
for (mlp = ml = read_mtab("restart", mnttab_file_name);
mlp;
mlp = mlp->mnext) {
mntent_t *me = mlp->mnt;
am_ops *fs_ops = 0;
char *colon;
long pid;
u_short port;
int err;
if (!STREQ(me->mnt_type, MNTTAB_TYPE_NFS))
continue; /* to next mlp */
/*
* NFS entry, or possibly an Amd entry...
* The mnt_fsname for daemon mount points is
* host:(pidXXX)
* or (seen on Solaris)
* host:daemon(pidXXX)
*/
colon = strchr(me->mnt_fsname, ':');
if (!colon || !strstr(colon, "(pid"))
continue;
/* if got here, then we matched an existing Amd mount point */
err = 1;
plog(XLOG_WARNING, "%s is an existing automount point", me->mnt_dir);
/* Is the old automounter still alive? */
if (sscanf(colon, "%*[^(](pid%ld%*[,)]", &pid) != 1) {
plog(XLOG_WARNING, "Can't parse pid in %s", me->mnt_fsname);
goto give_up;
}
if (kill(pid, 0) != -1 || errno != ESRCH) {
plog(XLOG_WARNING, "Automounter (pid: %ld) still alive", pid);
goto give_up;
}
/*
* Do we have a map for this mount point? Who cares, we'll restart
* anyway -- getting ESTALE is way better than hanging.
*/
/* Can we restart it? Only if it tells us what port it was using... */
if (sscanf(colon, "%*[^,],port%hu)", &port) != 1) {
plog(XLOG_WARNING, "No port specified for %s", me->mnt_fsname);
goto give_up;
}
/* Maybe we already own that port... */
if (port != nfs_port) {
int i;
for (i = 0; i < 256; i++) {
if (old_ports[i] == port ||
old_ports[i] == 0)
break;
}
if (i == 256) {
plog(XLOG_WARNING, "Too many open ports (256)");
goto give_up;
}
if (old_ports[i] == 0) {
int soNFS;
SVCXPRT *nfsxprt;
if (create_nfs_service(&soNFS, &port, &nfsxprt, nfs_program_2) != 0) {
plog(XLOG_WARNING, "Can't bind to port %u", port);
goto give_up;
}
old_ports[i] = nfs_port = port;
}
}
err = 0;
give_up:
if (err) {
plog(XLOG_WARNING, "Can't restart %s, leaving it alone", me->mnt_dir);
fs_ops = &amfs_link_ops;
} else {
fs_ops = &amfs_toplvl_ops;
}
restart_fake_mntfs(me, fs_ops);
} /* end of "for (mlp" */
/* free the mount list */
free_mntlist(ml);
}
+36 -38
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/rpc_fwd.c
* $Id: rpc_fwd.c,v 1.3.2.5 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -57,7 +58,7 @@
* is no need to convert to and from network byte ordering.
*/
#define XID_ALLOC() (xid++)
#define XID_ALLOC(struct ) (xid++)
#define MAX_PACKET_SIZE 8192 /* Maximum UDP packet size */
/*
@@ -74,7 +75,7 @@ struct rpc_forward {
time_t rf_ttl; /* Time to live */
u_int rf_xid; /* Packet id */
u_int rf_oldid; /* Original packet id */
fwd_fun *rf_fwd; /* Forwarding function */
fwd_fun rf_fwd; /* Forwarding function */
voidp rf_ptr;
struct sockaddr_in rf_sin;
};
@@ -93,7 +94,7 @@ static u_int xid;
static rpc_forward *
fwd_alloc(void)
{
time_t now = clocktime(NULL);
time_t now = clocktime();
rpc_forward *p = 0, *p2;
/*
@@ -116,7 +117,9 @@ fwd_alloc(void)
* Call forwarding function to say that
* this message was junked.
*/
#ifdef DEBUG
dlog("Re-using packet forwarding slot - id %#x", p->rf_xid);
#endif /* DEBUG */
if (p->rf_fwd)
(*p->rf_fwd) (0, 0, 0, &p->rf_sin, p->rf_ptr, FALSE);
rem_que(&p->rf_q);
@@ -225,7 +228,7 @@ fwd_locate(u_int id)
* 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)
fwd_packet(int type_id, voidp pkt, int len, struct sockaddr_in *fwdto, struct sockaddr_in *replyto, voidp i, fwd_fun cb)
{
rpc_forward *p;
u_int *pkt_int;
@@ -244,33 +247,36 @@ fwd_packet(int type_id, char *pkt, int len, struct sockaddr_in *fwdto, struct so
* Otherwise make sure the type_id is
* fully qualified by allocating an id here.
*/
#ifdef DEBUG
switch (type_id & RPC_XID_MASK) {
case RPC_XID_PORTMAP:
dlog("Sending PORTMAP request %#x", type_id);
dlog("Sending PORTMAP request");
break;
case RPC_XID_MOUNTD:
dlog("Sending MOUNTD request %#x", type_id);
break;
case RPC_XID_NFSPING:
dlog("Sending NFS ping %#x", type_id);
break;
case RPC_XID_WEBNFS:
dlog("Sending WebNFS lookup %#x", type_id);
dlog("Sending NFS ping");
break;
default:
dlog("UNKNOWN RPC XID %#x", type_id);
dlog("UNKNOWN RPC XID");
break;
}
#endif /* DEBUG */
if (type_id & ~RPC_XID_MASK) {
p = fwd_locate(type_id);
if (p) {
#ifdef DEBUG
dlog("Discarding earlier rpc fwd handle");
#endif /* DEBUG */
fwd_free(p);
}
} else {
#ifdef DEBUG
dlog("Allocating a new xid...");
type_id = MK_RPC_XID(type_id, XID_ALLOC());
#endif /* DEBUG */
type_id = MK_RPC_XID(type_id, XID_ALLOC(struct ));
}
p = fwd_alloc();
@@ -284,13 +290,12 @@ fwd_packet(int type_id, char *pkt, int len, struct sockaddr_in *fwdto, struct so
/*
* Get the original packet id
*/
p->rf_oldid = ntohl(*pkt_int);
p->rf_oldid = *pkt_int;
/*
* Replace with newly allocated id
*/
p->rf_xid = type_id;
*pkt_int = htonl(type_id);
p->rf_xid = *pkt_int = type_id;
/*
* The sendto may fail if, for example, the route
@@ -302,9 +307,9 @@ fwd_packet(int type_id, char *pkt, int len, struct sockaddr_in *fwdto, struct so
{
char dq[20];
if (p && fwdto)
dlog("Sending packet id %#x to %s:%d",
dlog("Sending packet id %#x to %s.%d",
p->rf_xid,
inet_dquad(dq, sizeof(dq), fwdto->sin_addr.s_addr),
inet_dquad(dq, fwdto->sin_addr.s_addr),
ntohs(fwdto->sin_port));
}
#endif /* DEBUG */
@@ -344,7 +349,7 @@ out:
p->rf_sin = *replyto;
else
memset((voidp) &p->rf_sin, 0, sizeof(p->rf_sin));
p->rf_ptr = cb_arg;
p->rf_ptr = i;
return error;
}
@@ -359,7 +364,6 @@ 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;
@@ -392,12 +396,6 @@ again:
rc = ud.udata.len;
else {
plog(XLOG_ERROR,"fwd_reply failed: t_errno=%d, errno=%d, flags=%d",t_errno,errno, flags);
/*
* Clear error indication, otherwise the error condition persists and
* amd gets into an infinite loop.
*/
if (t_errno == TLOOK)
t_rcvuderr(fwd_sock, NULL);
}
#else /* not HAVE_TRANSPORT_TYPE_TLI */
rc = recvfrom(fwd_sock,
@@ -430,29 +428,29 @@ again:
* Find packet reference
*/
pkt_int = (u_int *) pkt;
pkt_xid = ntohl(*pkt_int);
switch (pkt_xid & RPC_XID_MASK) {
#ifdef DEBUG
switch (*pkt_int & RPC_XID_MASK) {
case RPC_XID_PORTMAP:
dlog("Receiving PORTMAP reply %#x", pkt_xid);
dlog("Receiving PORTMAP reply");
break;
case RPC_XID_MOUNTD:
dlog("Receiving MOUNTD reply %#x", pkt_xid);
dlog("Receiving MOUNTD reply %#x", *pkt_int);
break;
case RPC_XID_NFSPING:
dlog("Receiving NFS ping %#x", pkt_xid);
break;
case RPC_XID_WEBNFS:
dlog("Receiving WebNFS lookup %#x", pkt_xid);
dlog("Receiving NFS ping %#x", *pkt_int);
break;
default:
dlog("UNKNOWN RPC XID %#x", pkt_xid);
dlog("UNKNOWN RPC XID");
break;
}
#endif /* DEBUG */
p = fwd_locate(pkt_xid);
p = fwd_locate(*pkt_int);
if (!p) {
dlog("Can't forward reply id %#x", pkt_xid);
#ifdef DEBUG
dlog("Can't forward reply id %#x", *pkt_int);
#endif /* DEBUG */
goto out;
}
@@ -461,7 +459,7 @@ again:
* Put the original message id back
* into the packet.
*/
*pkt_int = htonl(p->rf_oldid);
*pkt_int = p->rf_oldid;
/*
* Call forwarding function
+33 -37
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/sched.c
* $Id: sched.c,v 1.4.2.5 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -55,12 +56,12 @@
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 */
qelem hdr; /* Linked list */
int pid; /* Process ID of job */
cb_fun cb_fun; /* Callback function */
voidp cb_closure; /* Closure for callback */
int w; /* everyone these days uses int, not a "union wait" */
wchan_t wchan; /* Wait channel */
voidp wchan; /* Wait channel */
};
/* globals */
@@ -93,12 +94,12 @@ rem_que(qelem *elem)
static pjob *
sched_job(cb_fun *cf, opaque_t ca)
sched_job(cb_fun cf, voidp ca)
{
pjob *p = ALLOC(struct pjob);
p->cb_fun = cf;
p->cb_arg = ca;
p->cb_closure = ca;
/*
* Now place on wait queue
@@ -114,7 +115,7 @@ sched_job(cb_fun *cf, opaque_t ca)
* cf: Continuation function (ca is its arguments)
*/
void
run_task(task_fun *tf, opaque_t ta, cb_fun *cf, opaque_t ca)
run_task(task_fun tf, voidp ta, cb_fun cf, voidp ca)
{
pjob *p = sched_job(cf, ca);
#ifdef HAVE_SIGACTION
@@ -123,7 +124,7 @@ run_task(task_fun *tf, opaque_t ta, cb_fun *cf, opaque_t ca)
int mask;
#endif /* not HAVE_SIGACTION */
p->wchan = (wchan_t) p;
p->wchan = (voidp) p;
#ifdef HAVE_SIGACTION
sigemptyset(&new); /* initialize signal set we wish to block */
@@ -142,7 +143,7 @@ run_task(task_fun *tf, opaque_t ta, cb_fun *cf, opaque_t ca)
return;
}
/* child code runs here, parent has returned to caller */
/* child code runs here, parent have returned to caller */
exit((*tf) (ta));
/* firewall... */
@@ -154,17 +155,19 @@ run_task(task_fun *tf, opaque_t ta, cb_fun *cf, opaque_t ca)
* Schedule a task to be run when woken up
*/
void
sched_task(cb_fun *cf, opaque_t ca, wchan_t wchan)
sched_task(cb_fun cf, voidp ca, voidp wchan)
{
/*
* Allocate a new task
*/
pjob *p = sched_job(cf, ca);
dlog("SLEEP on %p", wchan);
#ifdef DEBUG
dlog("SLEEP on %#lx", (unsigned long) wchan);
#endif /* DEBUG */
p->wchan = wchan;
p->pid = 0;
p->w = 0; /* was memset (when ->w was union) */
memset((voidp) &p->w, 0, sizeof(p->w));
}
@@ -178,7 +181,7 @@ wakeupjob(pjob *p)
void
wakeup(wchan_t wchan)
wakeup(voidp wchan)
{
pjob *p, *p2;
@@ -186,7 +189,7 @@ wakeup(wchan_t wchan)
return;
/*
* Can't use ITER() here because
* Can't user ITER() here because
* wakeupjob() juggles the list.
*/
for (p = AM_FIRST(pjob, &proc_wait_list);
@@ -200,20 +203,9 @@ wakeup(wchan_t wchan)
void
wakeup_task(int rc, int term, wchan_t wchan)
wakeup_task(int rc, int term, voidp cl)
{
wakeup(wchan);
}
wchan_t
get_mntfs_wchan(mntfs *mf)
{
if (mf &&
mf->mf_ops &&
mf->mf_ops->get_wchan)
return mf->mf_ops->get_wchan(mf);
return mf;
wakeup(cl);
}
@@ -244,9 +236,9 @@ do_task_notify(void)
*/
if (p->cb_fun) {
/* these two trigraphs will ensure compatibility with strict POSIX.1 */
p->cb_fun(WIFEXITED(p->w) ? WEXITSTATUS(p->w) : 0,
WIFSIGNALED(p->w) ? WTERMSIG(p->w) : 0,
p->cb_arg);
(*p->cb_fun) (WIFEXITED(p->w) ? WEXITSTATUS(p->w) : 0,
WIFSIGNALED(p->w) ? WTERMSIG(p->w) : 0,
p->cb_closure);
}
XFREE(p);
}
@@ -269,9 +261,11 @@ sigchld(int sig)
if (WIFSIGNALED(w))
plog(XLOG_ERROR, "Process %d exited with signal %d",
pid, WTERMSIG(w));
#ifdef DEBUG
else
dlog("Process %d exited with status %d",
pid, WEXITSTATUS(w));
#endif /* DEBUG */
for (p = AM_FIRST(pjob, &proc_wait_list);
p2 = NEXT(pjob, p), p != HEAD(pjob, &proc_wait_list);
@@ -283,16 +277,18 @@ sigchld(int sig)
}
} /* end of for loop */
if (p == HEAD(pjob, &proc_wait_list))
#ifdef DEBUG
if (!p)
dlog("can't locate task block for pid %d", pid);
#endif /* DEBUG */
/*
* Must count down children inside the while loop, otherwise we won't
* count them all, and NumChildren (and later backoff) will be set
* count them all, and NumChild (and later backoff) will be set
* incorrectly. SH/RUNIT 940519.
*/
if (--NumChildren < 0)
NumChildren = 0;
if (--NumChild < 0)
NumChild = 0;
} /* end of "while wait..." loop */
#ifdef REINSTALL_SIGNAL_HANDLER
+12 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
@@ -36,8 +36,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/srvr_amfs_auto.c
* $Id: srvr_amfs_auto.c,v 1.3.2.6 2004/01/06 03:15:16 ezk Exp $
*
*/
@@ -52,9 +53,9 @@
#include <amd.h>
/* globals */
qelem amfs_auto_srvr_list = {&amfs_auto_srvr_list, &amfs_auto_srvr_list};
/* statics */
static qelem amfs_auto_srvr_list = {&amfs_auto_srvr_list, &amfs_auto_srvr_list};
static fserver *localhost;
@@ -62,7 +63,7 @@ static fserver *localhost;
* Find an nfs server for the local host
*/
fserver *
amfs_generic_find_srvr(mntfs *mf)
find_amfs_auto_srvr(mntfs *mf)
{
fserver *fs = localhost;
@@ -72,8 +73,8 @@ amfs_generic_find_srvr(mntfs *mf)
fs->fs_host = strdup("localhost");
fs->fs_ip = 0;
fs->fs_cid = 0;
fs->fs_pinger = AM_PINGER;
fs->fs_flags = FSF_VALID | FSF_PING_UNINIT;
fs->fs_pinger = 0;
fs->fs_flags = FSF_VALID;
fs->fs_type = "local";
fs->fs_private = 0;
fs->fs_prfree = 0;
@@ -118,7 +119,9 @@ timeout_srvr(voidp v)
* we are free to remove this node
*/
if (fs->fs_refc == 0) {
#ifdef DEBUG
dlog("Deleting file server %s", fs->fs_host);
#endif /* DEBUG */
if (fs->fs_flags & FSF_WANT)
wakeup_srvr(fs);
@@ -164,9 +167,11 @@ free_srvr(fserver *fs)
* removed in AM_TTL seconds if no
* other mntfs is referencing it.
*/
int ttl = (FSRV_ERROR(fs) || FSRV_ISDOWN(fs)) ? 19 : AM_TTL;
int ttl = (fs->fs_flags & (FSF_DOWN | FSF_ERROR)) ? 19 : AM_TTL;
#ifdef DEBUG
dlog("Last hard reference to file server %s - will timeout in %ds", fs->fs_host, ttl);
#endif /* DEBUG */
if (fs->fs_cid) {
untimeout(fs->fs_cid);
/*
+215 -370
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2006 Erez Zadok
* Copyright (c) 1997-2004 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
@@ -36,8 +36,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* File: am-utils/amd/srvr_nfs.c
* $Id: srvr_nfs.c,v 1.7.2.11 2004/01/06 03:15:16 ezk Exp $
* $FreeBSD$
*
*/
@@ -71,6 +73,8 @@
*/
#endif /* (FAST_NFS_PING * MAX_ALLOWED_PINGS) >= ALLOWED_MOUNT_TIME */
#define NPXID_ALLOC(struct ) (++np_xid)
/* structures and typedefs */
typedef struct nfs_private {
u_short np_mountd; /* Mount daemon port number */
@@ -85,16 +89,9 @@ typedef struct nfs_private {
qelem nfs_srvr_list = {&nfs_srvr_list, &nfs_srvr_list};
/* statics */
static int global_xid; /* For NFS pings */
#define XID_ALLOC() (++global_xid)
#ifdef HAVE_FS_NFS3
# define NUM_NFS_VERS 2
#else /* not HAVE_FS_NFS3 */
# define NUM_NFS_VERS 1
#endif /* not HAVE_FS_NFS3 */
static int ping_len[NUM_NFS_VERS];
static char ping_buf[NUM_NFS_VERS][sizeof(struct rpc_msg) + 32];
static int np_xid; /* For NFS pings */
static int ping_len;
static char ping_buf[sizeof(struct rpc_msg) + 32];
#if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3)
/*
@@ -103,8 +100,6 @@ static char ping_buf[NUM_NFS_VERS][sizeof(struct rpc_msg) + 32];
* Note that Solaris 8 and newer NetBSD systems are switching to UDP first,
* so this order may have to be adjusted for Amd in the future once more
* vendors make that change. -Erez 11/24/2000
*
* Or we might simply make this is a platform-specific order. -Ion 09/13/2003
*/
static char *protocols[] = { "tcp", "udp", NULL };
#endif /* defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
@@ -113,21 +108,20 @@ static char *protocols[] = { "tcp", "udp", NULL };
static void nfs_keepalive(voidp);
/*
* Flush cached data for an fserver (or for all, if fs==NULL)
* Flush any cached data
*/
void
flush_srvr_nfs_cache(fserver *fs)
flush_srvr_nfs_cache(void)
{
fserver *fs2 = NULL;
fserver *fs = 0;
ITER(fs2, fserver, &nfs_srvr_list) {
if (fs == NULL || fs == fs2) {
nfs_private *np = (nfs_private *) fs2->fs_private;
if (np) {
np->np_mountd_inval = TRUE;
np->np_error = -1;
}
ITER(fs, fserver, &nfs_srvr_list) {
nfs_private *np = (nfs_private *) fs->fs_private;
if (np) {
np->np_mountd_inval = TRUE;
np->np_error = -1;
}
}
}
@@ -137,7 +131,7 @@ flush_srvr_nfs_cache(fserver *fs)
* Startup the NFS ping for a particular version.
*/
static void
create_ping_payload(u_long nfs_version)
start_ping(u_long nfs_version)
{
XDR ping_xdr;
struct rpc_msg ping_msg;
@@ -147,16 +141,16 @@ create_ping_payload(u_long nfs_version)
*/
if (nfs_version == 0) {
nfs_version = NFS_VERSION;
plog(XLOG_WARNING, "create_ping_payload: nfs_version = 0, changed to 2");
} else
plog(XLOG_INFO, "create_ping_payload: nfs_version: %d", (int) nfs_version);
plog(XLOG_WARNING, "start_ping: nfs_version = 0 fixed");
}
plog(XLOG_INFO, "start_ping: nfs_version: %d", (int) nfs_version);
rpc_msg_init(&ping_msg, NFS_PROGRAM, nfs_version, NFSPROC_NULL);
/*
* Create an XDR endpoint
*/
xdrmem_create(&ping_xdr, ping_buf[nfs_version - NFS_VERSION], sizeof(ping_buf[0]), XDR_ENCODE);
xdrmem_create(&ping_xdr, ping_buf, sizeof(ping_buf), XDR_ENCODE);
/*
* Create the NFS ping message
@@ -168,7 +162,7 @@ create_ping_payload(u_long nfs_version)
/*
* Find out how long it is
*/
ping_len[nfs_version - NFS_VERSION] = xdr_getpos(&ping_xdr);
ping_len = xdr_getpos(&ping_xdr);
/*
* Destroy the XDR endpoint - we don't need it anymore
@@ -190,7 +184,7 @@ got_portmap(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia,
* Find which fileserver we are talking about
*/
ITER(fs, fserver, &nfs_srvr_list)
if (fs == fs2)
if (fs == fs2)
break;
if (fs == fs2) {
@@ -199,7 +193,9 @@ got_portmap(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia,
nfs_private *np = (nfs_private *) fs->fs_private;
if (!error && port) {
#ifdef DEBUG
dlog("got port (%d) for mountd on %s", (int) port, fs->fs_host);
#endif /* DEBUG */
/*
* Grab the port number. Portmap sends back
* an u_long in native ordering, so it
@@ -210,8 +206,10 @@ got_portmap(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia,
np->np_mountd_inval = FALSE;
np->np_error = 0;
} else {
#ifdef DEBUG
dlog("Error fetching port for mountd on %s", fs->fs_host);
dlog("\t error=%d, port=%d", error, (int) port);
#endif /* DEBUG */
/*
* Almost certainly no mountd running on remote host
*/
@@ -221,9 +219,13 @@ got_portmap(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia,
if (fs->fs_flags & FSF_WANT)
wakeup_srvr(fs);
} else if (done) {
#ifdef DEBUG
dlog("Got portmap for old port request");
#endif /* DEBUG */
} else {
#ifdef DEBUG
dlog("portmap request timed out");
#endif /* DEBUG */
}
}
@@ -257,7 +259,7 @@ call_portmap(fserver *fs, AUTH *auth, u_long prog, u_long vers, u_long prot)
memset((voidp) &sin, 0, sizeof(sin));
sin = *fs->fs_ip;
sin.sin_port = htons(PMAPPORT);
error = fwd_packet(RPC_XID_PORTMAP, iobuf, len,
error = fwd_packet(RPC_XID_PORTMAP, (voidp) iobuf, len,
&sin, &sin, (voidp) fs, got_portmap);
} else {
error = -len;
@@ -273,12 +275,6 @@ recompute_portmap(fserver *fs)
int error;
u_long mnt_version;
/*
* No portmap calls for pure WebNFS servers.
*/
if (fs->fs_flags & FSF_WEBNFS)
return;
if (nfs_auth)
error = 0;
else
@@ -293,11 +289,10 @@ recompute_portmap(fserver *fs)
if (fs->fs_version == 0)
plog(XLOG_WARNING, "recompute_portmap: nfs_version = 0 fixed");
plog(XLOG_INFO, "recompute_portmap: NFS version %d on %s",
(int) fs->fs_version, fs->fs_host);
plog(XLOG_INFO, "recompute_portmap: NFS version %d", (int) fs->fs_version);
#ifdef HAVE_FS_NFS3
if (fs->fs_version == NFS_VERSION3)
mnt_version = AM_MOUNTVERS3;
mnt_version = MOUNTVERS3;
else
#endif /* HAVE_FS_NFS3 */
mnt_version = MOUNTVERS;
@@ -307,61 +302,19 @@ recompute_portmap(fserver *fs)
}
int
get_mountd_port(fserver *fs, u_short *port, wchan_t wchan)
{
int error = -1;
if (FSRV_ISDOWN(fs))
return EWOULDBLOCK;
if (FSRV_ISUP(fs)) {
nfs_private *np = (nfs_private *) fs->fs_private;
if (np->np_error == 0) {
*port = np->np_mountd;
error = 0;
} else {
error = np->np_error;
}
/*
* Now go get the port mapping again in case it changed.
* Note that it is used even if (np_mountd_inval)
* is True. The flag is used simply as an
* indication that the mountd may be invalid, not
* that it is known to be invalid.
*/
if (np->np_mountd_inval)
recompute_portmap(fs);
else
np->np_mountd_inval = TRUE;
}
if (error < 0 && wchan && !(fs->fs_flags & FSF_WANT)) {
/*
* If a wait channel is supplied, and no
* error has yet occurred, then arrange
* that a wakeup is done on the wait channel,
* whenever a wakeup is done on this fs node.
* Wakeup's are done on the fs node whenever
* it changes state - thus causing control to
* come back here and new, better things to happen.
*/
fs->fs_flags |= FSF_WANT;
sched_task(wakeup_task, wchan, (wchan_t) fs);
}
return error;
}
/*
* This is called when we get a reply to an RPC ping.
* The value of id was taken from the nfs_private
* structure when the ping was transmitted.
*/
static void
nfs_keepalive_callback(voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp, voidp idv, int done)
nfs_pinged(voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp, voidp idv, int done)
{
int xid = (long) idv; /* cast needed for 64-bit archs */
int xid = (long) idv; /* for 64-bit archs */
fserver *fs;
#ifdef DEBUG
int found_map = 0;
#endif /* DEBUG */
if (!done)
return;
@@ -384,15 +337,19 @@ nfs_keepalive_callback(voidp pkt, int len, struct sockaddr_in *sp, struct sockad
} else {
if (np->np_ping > 1)
srvrlog(fs, "ok");
#ifdef DEBUG
else
srvrlog(fs, "starts up");
#endif /* DEBUG */
fs->fs_flags |= FSF_VALID;
}
map_flush_srvr(fs);
} else {
if (fs->fs_flags & FSF_VALID) {
#ifdef DEBUG
dlog("file server %s type nfs is still up", fs->fs_host);
#endif /* DEBUG */
} else {
if (np->np_ping > 1)
srvrlog(fs, "ok");
@@ -409,13 +366,13 @@ nfs_keepalive_callback(voidp pkt, int len, struct sockaddr_in *sp, struct sockad
/*
* Update ttl for this server
*/
np->np_ttl = clocktime(NULL) +
np->np_ttl = clocktime() +
(MAX_ALLOWED_PINGS - 1) * FAST_NFS_PING + fs->fs_pinger - 1;
/*
* New RPC xid...
*/
np->np_xid = XID_ALLOC();
np->np_xid = NPXID_ALLOC(struct );
/*
* Failed pings is zero...
@@ -428,53 +385,17 @@ nfs_keepalive_callback(voidp pkt, int len, struct sockaddr_in *sp, struct sockad
if (np->np_mountd_inval)
recompute_portmap(fs);
#ifdef DEBUG
found_map++;
#endif /* DEBUG */
break;
}
}
#ifdef DEBUG
if (found_map == 0)
dlog("Spurious ping packet");
}
static void
check_fs_addr_change(fserver *fs)
{
struct hostent *hp = NULL;
struct in_addr ia;
char *old_ipaddr, *new_ipaddr;
hp = gethostbyname(fs->fs_host);
if (!hp ||
hp->h_addrtype != AF_INET ||
!STREQ((char *) hp->h_name, fs->fs_host) ||
memcmp((voidp) &fs->fs_ip->sin_addr,
(voidp) hp->h_addr,
sizeof(fs->fs_ip->sin_addr)) == 0)
return;
/* if got here: downed server changed IP address */
old_ipaddr = strdup(inet_ntoa(fs->fs_ip->sin_addr));
memmove((voidp) &ia, (voidp) hp->h_addr, sizeof(struct in_addr));
new_ipaddr = inet_ntoa(ia); /* ntoa uses static buf */
plog(XLOG_WARNING, "EZK: down fileserver %s changed ip: %s -> %s",
fs->fs_host, old_ipaddr, new_ipaddr);
XFREE(old_ipaddr);
/* copy new IP addr */
memmove((voidp) &fs->fs_ip->sin_addr,
(voidp) hp->h_addr,
sizeof(fs->fs_ip->sin_addr));
/* XXX: do we need to un/set these flags? */
fs->fs_flags &= ~FSF_DOWN;
fs->fs_flags |= FSF_VALID | FSF_WANT;
map_flush_srvr(fs); /* XXX: a race with flush_srvr_nfs_cache? */
flush_srvr_nfs_cache(fs);
fs->fs_flags |= FSF_FORCE_UNMOUNT;
#if 0
flush_nfs_fhandle_cache(fs); /* done in caller: nfs_keepalive_timeout */
/* XXX: need to purge nfs_private so that somehow it will get re-initialized? */
#endif
#endif /* DEBUG */
}
@@ -482,7 +403,7 @@ check_fs_addr_change(fserver *fs)
* Called when no ping-reply received
*/
static void
nfs_keepalive_timeout(voidp v)
nfs_timed_out(voidp v)
{
fserver *fs = v;
nfs_private *np = (nfs_private *) fs->fs_private;
@@ -503,9 +424,11 @@ nfs_keepalive_timeout(voidp v)
/*
* If ttl has expired then guess that it is dead
*/
if (np->np_ttl < clocktime(NULL)) {
if (np->np_ttl < clocktime()) {
int oflags = fs->fs_flags;
#ifdef DEBUG
dlog("ttl has expired");
#endif /* DEBUG */
if ((fs->fs_flags & FSF_DOWN) == 0) {
/*
* Server was up, but is now down.
@@ -519,13 +442,14 @@ nfs_keepalive_timeout(voidp v)
*/
flush_nfs_fhandle_cache(fs);
np->np_error = -1;
check_fs_addr_change(fs); /* check if IP addr of fserver changed */
} else {
/*
* Known to be down
*/
#ifdef DEBUG
if ((fs->fs_flags & FSF_VALID) == 0)
srvrlog(fs, "starts down");
#endif /* DEBUG */
fs->fs_flags |= FSF_VALID;
}
if (oflags != fs->fs_flags && (fs->fs_flags & FSF_WANT))
@@ -535,15 +459,17 @@ nfs_keepalive_timeout(voidp v)
*/
np->np_ping = 0;
} else {
#ifdef DEBUG
if (np->np_ping > 1)
dlog("%d pings to %s failed - at most %d allowed", np->np_ping, fs->fs_host, MAX_ALLOWED_PINGS);
#endif /* DEBUG */
}
/*
* New RPC xid, so any late responses to the previous ping
* get ignored...
*/
np->np_xid = XID_ALLOC();
np->np_xid = NPXID_ALLOC(struct );
/*
* Run keepalive again
@@ -567,19 +493,19 @@ nfs_keepalive(voidp v)
* Send an NFS ping to this node
*/
if (ping_len[fs->fs_version - NFS_VERSION] == 0)
create_ping_payload(fs->fs_version);
if (ping_len == 0)
start_ping(fs->fs_version);
/*
* Queue the packet...
*/
error = fwd_packet(MK_RPC_XID(RPC_XID_NFSPING, np->np_xid),
ping_buf[fs->fs_version - NFS_VERSION],
ping_len[fs->fs_version - NFS_VERSION],
(voidp) ping_buf,
ping_len,
fs->fs_ip,
(struct sockaddr_in *) 0,
(voidp) ((long) np->np_xid), /* cast needed for 64-bit archs */
nfs_keepalive_callback);
(voidp) ((long) np->np_xid), /* for 64-bit archs */
nfs_pinged);
/*
* See if a hard error occurred
@@ -592,7 +518,7 @@ nfs_keepalive(voidp v)
np->np_ping = MAX_ALLOWED_PINGS; /* immediately down */
np->np_ttl = (time_t) 0;
/*
* This causes an immediate call to nfs_keepalive_timeout
* This causes an immediate call to nfs_timed_out
* whenever the server was thought to be up.
* See +++ below.
*/
@@ -600,13 +526,15 @@ nfs_keepalive(voidp v)
break;
case 0:
#ifdef DEBUG
dlog("Sent NFS ping to %s", fs->fs_host);
#endif /* DEBUG */
break;
}
/*
* Back off the ping interval if we are not getting replies and
* the remote system is known to be down.
* the remote system is know to be down.
*/
switch (fs->fs_flags & (FSF_DOWN | FSF_VALID)) {
case FSF_VALID: /* Up */
@@ -623,41 +551,73 @@ nfs_keepalive(voidp v)
break;
}
#ifdef DEBUG
dlog("NFS timeout in %d seconds", fstimeo);
#endif /* DEBUG */
fs->fs_cid = timeout(fstimeo, nfs_keepalive_timeout, (voidp) fs);
fs->fs_cid = timeout(fstimeo, nfs_timed_out, (voidp) fs);
}
int
nfs_srvr_port(fserver *fs, u_short *port, voidp wchan)
{
int error = -1;
if ((fs->fs_flags & FSF_VALID) == FSF_VALID) {
if ((fs->fs_flags & FSF_DOWN) == 0) {
nfs_private *np = (nfs_private *) fs->fs_private;
if (np->np_error == 0) {
*port = np->np_mountd;
error = 0;
} else {
error = np->np_error;
}
/*
* Now go get the port mapping again in case it changed.
* Note that it is used even if (np_mountd_inval)
* is True. The flag is used simply as an
* indication that the mountd may be invalid, not
* that it is known to be invalid.
*/
if (np->np_mountd_inval)
recompute_portmap(fs);
else
np->np_mountd_inval = TRUE;
} else {
error = EWOULDBLOCK;
}
}
if (error < 0 && wchan && !(fs->fs_flags & FSF_WANT)) {
/*
* If a wait channel is supplied, and no
* error has yet occurred, then arrange
* that a wakeup is done on the wait channel,
* whenever a wakeup is done on this fs node.
* Wakeup's are done on the fs node whenever
* it changes state - thus causing control to
* come back here and new, better things to happen.
*/
fs->fs_flags |= FSF_WANT;
sched_task(wakeup_task, wchan, (voidp) fs);
}
return error;
}
static void
start_nfs_pings(fserver *fs, int pingval)
{
if (pingval == 0) /* could be because ping mnt option not found */
pingval = AM_PINGER;
/* if pings haven't been initalized, then init them for first time */
if (fs->fs_flags & FSF_PING_UNINIT) {
fs->fs_flags &= ~FSF_PING_UNINIT;
plog(XLOG_INFO, "initializing %s's pinger to %d sec", fs->fs_host, pingval);
goto do_pings;
}
if ((fs->fs_flags & FSF_PINGING) && fs->fs_pinger == pingval) {
dlog("already running pings to %s", fs->fs_host);
if (fs->fs_flags & FSF_PINGING) {
#ifdef DEBUG
dlog("Already running pings to %s", fs->fs_host);
#endif /* DEBUG */
return;
}
/* if got here, then we need to update the ping value */
plog(XLOG_INFO, "changing %s's ping value from %d%s to %d%s",
fs->fs_host,
fs->fs_pinger, (fs->fs_pinger < 0 ? " (off)" : ""),
pingval, (pingval < 0 ? " (off)" : ""));
do_pings:
fs->fs_pinger = pingval;
if (fs->fs_cid)
untimeout(fs->fs_cid);
if (pingval < 0) {
srvrlog(fs, "wired up (pings disabled)");
srvrlog(fs, "wired up");
fs->fs_flags |= FSF_VALID;
fs->fs_flags &= ~FSF_DOWN;
} else {
@@ -674,18 +634,17 @@ fserver *
find_nfs_srvr(mntfs *mf)
{
char *host = mf->mf_fo->opt_rhost;
char *nfs_proto = NULL;
fserver *fs;
int pingval;
mntent_t mnt;
nfs_private *np;
struct hostent *hp = NULL;
struct sockaddr_in *ip = NULL;
struct hostent *hp = 0;
struct sockaddr_in *ip;
u_long nfs_version = 0; /* default is no version specified */
u_long best_nfs_version = 0;
char *nfs_proto = NULL; /* no IP protocol either */
int nfs_port = 0;
int nfs_port_opt = 0;
int fserver_is_down = 0;
#ifdef MNTTAB_OPT_PROTO
char *rfsname = mf->mf_fo->opt_rfs;
#endif /* MNTTAB_OPT_PROTO */
/*
* Get ping interval from mount options.
@@ -695,60 +654,49 @@ find_nfs_srvr(mntfs *mf)
mnt.mnt_opts = mf->mf_mopts;
pingval = hasmntval(&mnt, "ping");
if (mf->mf_flags & MFF_NFS_SCALEDOWN) {
/*
* the server granted us a filehandle, but we were unable to mount it.
* therefore, scale down to NFSv2/UDP and try again.
*/
nfs_version = NFS_VERSION;
nfs_proto = "udp";
plog(XLOG_WARNING, "find_nfs_srvr: NFS mount failed, trying again with NFSv2/UDP");
mf->mf_flags &= ~MFF_NFS_SCALEDOWN;
} else {
/*
* Get the NFS version from the mount options. This is used
* to decide the highest NFS version to try.
*/
/*
* Get the NFS version from the mount options. This is used
* to decide the highest NFS version to try.
*/
#ifdef MNTTAB_OPT_VERS
nfs_version = hasmntval(&mnt, MNTTAB_OPT_VERS);
nfs_version = hasmntval(&mnt, MNTTAB_OPT_VERS);
#endif /* MNTTAB_OPT_VERS */
#ifdef MNTTAB_OPT_PROTO
{
char *proto_opt = hasmnteq(&mnt, MNTTAB_OPT_PROTO);
if (proto_opt) {
char **p;
for (p = protocols; *p; p++)
if (NSTREQ(proto_opt, *p, strlen(*p))) {
nfs_proto = *p;
break;
}
if (*p == NULL)
plog(XLOG_WARNING, "ignoring unknown protocol option for %s:%s",
host, mf->mf_fo->opt_rfs);
}
{
char *proto_opt = hasmnteq(&mnt, MNTTAB_OPT_PROTO);
if (proto_opt) {
char **p;
for (p = protocols; *p; p ++)
if (NSTREQ(proto_opt, *p, strlen(*p))) {
nfs_proto = *p;
break;
}
if (*p == NULL)
plog(XLOG_WARNING, "ignoring unknown protocol option for %s:%s",
host, rfsname);
}
}
#endif /* MNTTAB_OPT_PROTO */
#ifdef HAVE_NFS_NFSV2_H
/* allow overriding if nfsv2 option is specified in mount options */
if (amu_hasmntopt(&mnt, "nfsv2")) {
nfs_version = NFS_VERSION;/* nullify any ``vers=X'' statements */
nfs_proto = "udp"; /* nullify any ``proto=tcp'' statements */
plog(XLOG_WARNING, "found compatibility option \"nfsv2\": set options vers=2,proto=udp for host %s", host);
}
/* allow overriding if nfsv2 option is specified in mount options */
if (hasmntopt(&mnt, "nfsv2")) {
nfs_version = (u_long) 2; /* nullify any ``vers=X'' statements */
nfs_proto = "udp"; /* nullify any ``proto=tcp'' statements */
plog(XLOG_WARNING, "found compatiblity option \"nfsv2\": set options vers=2,proto=udp for host %s", host);
}
#endif /* HAVE_NFS_NFSV2_H */
/* check if we've globally overridden the NFS version/protocol */
if (gopt.nfs_vers) {
nfs_version = gopt.nfs_vers;
plog(XLOG_INFO, "find_nfs_srvr: force NFS version to %d",
(int) nfs_version);
}
if (gopt.nfs_proto) {
nfs_proto = gopt.nfs_proto;
plog(XLOG_INFO, "find_nfs_srvr: force NFS protocol transport to %s", nfs_proto);
}
/* check if we globally overridden the NFS version/protocol */
if (gopt.nfs_vers) {
nfs_version = gopt.nfs_vers;
plog(XLOG_INFO, "find_nfs_srvr: force NFS version to %d",
(int) nfs_version);
}
if (gopt.nfs_proto) {
nfs_proto = gopt.nfs_proto;
plog(XLOG_INFO, "find_nfs_srvr: force NFS protocol transport to %s", nfs_proto);
}
/*
@@ -771,148 +719,72 @@ find_nfs_srvr(mntfs *mf)
case AF_INET:
ip = ALLOC(struct sockaddr_in);
memset((voidp) ip, 0, sizeof(*ip));
/* as per POSIX, sin_len need not be set (used internally by kernel) */
ip->sin_family = AF_INET;
memmove((voidp) &ip->sin_addr, (voidp) hp->h_addr, sizeof(ip->sin_addr));
ip->sin_port = htons(NFS_PORT);
break;
default:
plog(XLOG_USER, "No IP address for host %s", host);
goto no_dns;
ip = 0;
break;
}
} else {
plog(XLOG_USER, "Unknown host: %s", host);
goto no_dns;
ip = 0;
}
/*
* This may not be the best way to do things, but it really doesn't make
* sense to query a file server which is marked as 'down' for any
* version/proto combination.
* Get the NFS Version, and verify server is up. Probably no
* longer need to start server down below.
*/
ITER(fs, fserver, &nfs_srvr_list) {
if (FSRV_ISDOWN(fs) &&
STREQ(host, fs->fs_host)) {
plog(XLOG_WARNING, "fileserver %s is already hung - not running NFS proto/version discovery", host);
fs->fs_refc++;
if (ip)
XFREE(ip);
return fs;
}
}
/*
* Get the NFS Version, and verify server is up.
* If the client only supports NFSv2, hardcode it but still try to
* contact the remote portmapper to see if the service is running.
*/
#ifndef HAVE_FS_NFS3
nfs_version = NFS_VERSION;
nfs_proto = "udp";
plog(XLOG_INFO, "The client supports only NFS(2,udp)");
#endif /* not HAVE_FS_NFS3 */
if (amu_hasmntopt(&mnt, MNTTAB_OPT_PUBLIC)) {
/*
* Use WebNFS to obtain file handles.
*/
mf->mf_flags |= MFF_WEBNFS;
plog(XLOG_INFO, "%s option used, NOT contacting the portmapper on %s",
MNTTAB_OPT_PUBLIC, host);
/*
* Prefer NFSv3/tcp if the client supports it (cf. RFC 2054, 7).
*/
if (!nfs_version) {
if (ip) {
#ifdef HAVE_FS_NFS3
nfs_version = NFS_VERSION3;
#else /* not HAVE_FS_NFS3 */
nfs_version = NFS_VERSION;
#endif /* not HAVE_FS_NFS3 */
plog(XLOG_INFO, "No NFS version specified, will use NFSv%d",
(int) nfs_version);
}
if (!nfs_proto) {
#if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3)
nfs_proto = "tcp";
#else /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
nfs_proto = "udp";
#endif /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
plog(XLOG_INFO, "No NFS protocol transport specified, will use %s",
nfs_proto);
}
} else {
/*
* Find the best combination of NFS version and protocol.
* When given a choice, use the highest available version,
* and use TCP over UDP if available.
*/
if (check_pmap_up(host, ip)) {
if (nfs_proto) {
best_nfs_version = get_nfs_version(host, ip, nfs_version, nfs_proto);
nfs_port = ip->sin_port;
}
#ifdef MNTTAB_OPT_PROTO
else {
u_int proto_nfs_version;
char **p;
if (nfs_proto)
nfs_version = get_nfs_version(host, ip, nfs_version, nfs_proto);
else {
int best_nfs_version = 0;
int proto_nfs_version;
char **p;
for (p = protocols; *p; p++) {
proto_nfs_version = get_nfs_version(host, ip, nfs_version, *p);
for (p = protocols; *p; p++) {
proto_nfs_version = get_nfs_version(host, ip, nfs_version, *p);
if (proto_nfs_version > best_nfs_version) {
best_nfs_version = proto_nfs_version;
nfs_proto = *p;
nfs_port = ip->sin_port;
}
if (proto_nfs_version > best_nfs_version) {
best_nfs_version = proto_nfs_version;
nfs_proto = *p;
}
}
#endif /* MNTTAB_OPT_PROTO */
} else {
plog(XLOG_INFO, "portmapper service not running on %s", host);
nfs_version = best_nfs_version;
}
/* use the portmapper results only nfs_version is not set yet */
if (!best_nfs_version) {
if (!nfs_version) {
/*
* If the NFS server is down or does not support the portmapper call
* (such as certain Novell NFS servers) we mark it as version 2 and we
* let the nfs code deal with the case when it is down. If/when the
* server comes back up and it can support NFSv3 and/or TCP, it will
* let the nfs code deal with the case that is down. If when the
* server comes back up, it can support NFS V.3 and/or TCP, it will
* use those.
*/
if (nfs_version == 0) {
nfs_version = NFS_VERSION;
nfs_proto = "udp";
}
plog(XLOG_INFO, "NFS service not running on %s", host);
fserver_is_down = 1;
} else {
if (nfs_version == 0)
nfs_version = best_nfs_version;
plog(XLOG_INFO, "Using NFS version %d, protocol %s on host %s",
(int) nfs_version, nfs_proto, host);
nfs_version = NFS_VERSION;
nfs_proto = "udp";
}
#else /* not HAVE_FS_NFS3 */
nfs_version = NFS_VERSION;
#endif /* not HAVE_FS_NFS3 */
}
/*
* Determine the NFS port.
*
* A valid "port" mount option overrides anything else.
* If the port has been determined from the portmapper, use that.
* Default to NFS_PORT otherwise (cf. RFC 2054, 3).
*/
nfs_port_opt = hasmntval(&mnt, MNTTAB_OPT_PORT);
if (nfs_port_opt > 0)
nfs_port = htons(nfs_port_opt);
if (!nfs_port)
nfs_port = htons(NFS_PORT);
if (!nfs_proto)
nfs_proto = "udp";
dlog("find_nfs_srvr: using port %d for nfs on %s",
(int) ntohs(nfs_port), host);
ip->sin_port = nfs_port;
plog(XLOG_INFO, "Using NFS version %d, protocol %s on host %s",
(int) nfs_version, nfs_proto, host);
no_dns:
/*
* Try to find an existing fs server structure for this host.
* Note that differing versions or protocols have their own structures.
@@ -924,46 +796,16 @@ no_dns:
nfs_version == fs->fs_version &&
STREQ(nfs_proto, fs->fs_proto)) {
/*
* fill in the IP address -- this is only needed
* if there is a chance an IP address will change
* between mounts.
* Mike Mitchell, mcm@unx.sas.com, 09/08/93
*/
if (hp && fs->fs_ip &&
memcmp((voidp) &fs->fs_ip->sin_addr,
(voidp) hp->h_addr,
sizeof(fs->fs_ip->sin_addr)) != 0) {
struct in_addr ia;
char *old_ipaddr, *new_ipaddr;
old_ipaddr = strdup(inet_ntoa(fs->fs_ip->sin_addr));
memmove((voidp) &ia, (voidp) hp->h_addr, sizeof(struct in_addr));
new_ipaddr = inet_ntoa(ia); /* ntoa uses static buf */
plog(XLOG_WARNING, "fileserver %s changed ip: %s -> %s",
fs->fs_host, old_ipaddr, new_ipaddr);
XFREE(old_ipaddr);
flush_nfs_fhandle_cache(fs);
memmove((voidp) &fs->fs_ip->sin_addr, (voidp) hp->h_addr, sizeof(fs->fs_ip->sin_addr));
}
/*
* If the new file systems doesn't use WebNFS, the nfs pings may
* try to contact the portmapper.
*/
if (!(mf->mf_flags & MFF_WEBNFS))
fs->fs_flags &= ~FSF_WEBNFS;
/* check if pingval needs to be updated/set/reset */
start_nfs_pings(fs, pingval);
/*
* Following if statement from Mike Mitchell <mcm@unx.sas.com>
* Initialize the ping data if we aren't pinging now. The np_ttl and
* np_ping fields are especially important.
* following if statement from Mike Mitchell
* <mcm@unx.sas.com>
* Initialize the ping data if we aren't pinging
* now. The np_ttl and np_ping fields are
* especially important.
*/
if (!(fs->fs_flags & FSF_PINGING)) {
np = (nfs_private *) fs->fs_private;
np->np_mountd_inval = TRUE;
np->np_xid = XID_ALLOC();
np->np_xid = NPXID_ALLOC(struct );
np->np_error = -1;
np->np_ping = 0;
/*
@@ -971,12 +813,18 @@ no_dns:
* after MAX_ALLOWED_PINGS of the fast variety
* have failed.
*/
np->np_ttl = MAX_ALLOWED_PINGS * FAST_NFS_PING + clocktime(NULL) - 1;
start_nfs_pings(fs, pingval);
if (fserver_is_down)
fs->fs_flags |= FSF_VALID | FSF_DOWN;
np->np_ttl = MAX_ALLOWED_PINGS * FAST_NFS_PING + clocktime() - 1;
}
/*
* fill in the IP address -- this is only needed
* if there is a chance an IP address will change
* between mounts.
* Mike Mitchell, mcm@unx.sas.com, 09/08/93
*/
if (hp && fs->fs_ip)
memmove((voidp) &fs->fs_ip->sin_addr, (voidp) hp->h_addr, sizeof(fs->fs_ip->sin_addr));
start_nfs_pings(fs, pingval);
fs->fs_refc++;
if (ip)
XFREE(ip);
@@ -1005,32 +853,29 @@ no_dns:
mf->mf_flags |= MFF_ERROR;
mf->mf_error = ENOENT;
}
if (mf->mf_flags & MFF_WEBNFS)
fs->fs_flags |= FSF_WEBNFS;
fs->fs_version = nfs_version;
fs->fs_proto = nfs_proto;
fs->fs_type = MNTTAB_TYPE_NFS;
fs->fs_pinger = AM_PINGER;
fs->fs_flags |= FSF_PING_UNINIT; /* pinger hasn't been initialized */
np = ALLOC(struct nfs_private);
memset((voidp) np, 0, sizeof(*np));
np->np_mountd_inval = TRUE;
np->np_xid = XID_ALLOC();
np->np_xid = NPXID_ALLOC(struct );
np->np_error = -1;
/*
* Initially the server will be deemed dead after
* MAX_ALLOWED_PINGS of the fast variety have failed.
*/
np->np_ttl = clocktime(NULL) + MAX_ALLOWED_PINGS * FAST_NFS_PING - 1;
np->np_ttl = clocktime() + MAX_ALLOWED_PINGS * FAST_NFS_PING - 1;
fs->fs_private = (voidp) np;
fs->fs_prfree = (void (*)(voidp)) free;
if (!FSRV_ERROR(fs)) {
/* start of keepalive timer, first updating pingval */
if (!(fs->fs_flags & FSF_ERROR)) {
/*
* Start of keepalive timer
*/
start_nfs_pings(fs, pingval);
if (fserver_is_down)
fs->fs_flags |= FSF_VALID | FSF_DOWN;
}
/*
Loaded 100 of 4090 files, more files were not shown because too many files have changed in this diff. Show more