summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2007-08-07 16:14:10 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2007-08-07 16:14:10 +0000
commit862ed67c18d9677d1e76406c5638a81e03de67a8 (patch)
tree6c3f53b725369ba2ae66cc36efaec8acf459a663
parent2007-07-16 Joel Sherrill <joel.sherrill@oarcorp.com> (diff)
downloadrtems-addon-packages-862ed67c18d9677d1e76406c5638a81e03de67a8.tar.bz2
2007-08-07 Joel Sherrill <joel.sherrill@OARcorp.com>
* bit: NFS Client is now merged into main RTEMS source tree. * rtemsNfs/ChangeLog, rtemsNfs/LICENSE, rtemsNfs/Makefile, rtemsNfs/README, rtemsNfs/rfc1094.txt, rtemsNfs/rtems-filesystem-patch, rtemsNfs/proto/Makefile, rtemsNfs/proto/mount_prot.h, rtemsNfs/proto/mount_prot.x, rtemsNfs/proto/mount_prot_xdr.c, rtemsNfs/proto/nfs_prot.h, rtemsNfs/proto/nfs_prot.x, rtemsNfs/proto/nfs_prot_xdr.c, rtemsNfs/src/Makefile, rtemsNfs/src/cexphelp.c, rtemsNfs/src/dirutils.c, rtemsNfs/src/librtemsNfs.h, rtemsNfs/src/nfs.c, rtemsNfs/src/nfs.modini.c, rtemsNfs/src/rpcio.c, rtemsNfs/src/rpcio.h, rtemsNfs/src/rpcio.modini.c, rtemsNfs/src/sock_mbuf.c, rtemsNfs/src/xdr_mbuf.c: Removed.
-rw-r--r--ChangeLog15
-rwxr-xr-xbit3
-rw-r--r--rtemsNfs/ChangeLog92
-rw-r--r--rtemsNfs/LICENSE115
-rw-r--r--rtemsNfs/Makefile16
-rw-r--r--rtemsNfs/README497
-rw-r--r--rtemsNfs/proto/Makefile76
-rw-r--r--rtemsNfs/proto/mount_prot.h144
-rw-r--r--rtemsNfs/proto/mount_prot.x161
-rw-r--r--rtemsNfs/proto/mount_prot_xdr.c124
-rw-r--r--rtemsNfs/proto/nfs_prot.h453
-rw-r--r--rtemsNfs/proto/nfs_prot.x1268
-rw-r--r--rtemsNfs/proto/nfs_prot_xdr.c671
-rw-r--r--rtemsNfs/rfc1094.txt1258
-rw-r--r--rtemsNfs/rtems-filesystem-patch860
-rw-r--r--rtemsNfs/src/Makefile105
-rw-r--r--rtemsNfs/src/cexphelp.c16
-rw-r--r--rtemsNfs/src/dirutils.c357
-rw-r--r--rtemsNfs/src/librtemsNfs.h158
-rw-r--r--rtemsNfs/src/nfs.c3390
-rw-r--r--rtemsNfs/src/nfs.modini.c27
-rw-r--r--rtemsNfs/src/rpcio.c1731
-rw-r--r--rtemsNfs/src/rpcio.h205
-rw-r--r--rtemsNfs/src/rpcio.modini.c15
-rw-r--r--rtemsNfs/src/sock_mbuf.c281
-rw-r--r--rtemsNfs/src/xdr_mbuf.c534
26 files changed, 16 insertions, 12556 deletions
diff --git a/ChangeLog b/ChangeLog
index 1ddd172..a0941f5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2007-08-07 Joel Sherrill <joel.sherrill@OARcorp.com>
+
+ * bit: NFS Client is now merged into main RTEMS source tree.
+ * rtemsNfs/ChangeLog, rtemsNfs/LICENSE, rtemsNfs/Makefile,
+ rtemsNfs/README, rtemsNfs/rfc1094.txt,
+ rtemsNfs/rtems-filesystem-patch, rtemsNfs/proto/Makefile,
+ rtemsNfs/proto/mount_prot.h, rtemsNfs/proto/mount_prot.x,
+ rtemsNfs/proto/mount_prot_xdr.c, rtemsNfs/proto/nfs_prot.h,
+ rtemsNfs/proto/nfs_prot.x, rtemsNfs/proto/nfs_prot_xdr.c,
+ rtemsNfs/src/Makefile, rtemsNfs/src/cexphelp.c,
+ rtemsNfs/src/dirutils.c, rtemsNfs/src/librtemsNfs.h,
+ rtemsNfs/src/nfs.c, rtemsNfs/src/nfs.modini.c, rtemsNfs/src/rpcio.c,
+ rtemsNfs/src/rpcio.h, rtemsNfs/src/rpcio.modini.c,
+ rtemsNfs/src/sock_mbuf.c, rtemsNfs/src/xdr_mbuf.c: Removed.
+
2007-03-13 Joel Sherrill <joel@OARcorp.com>
* VERSION: Updated to rtems-addon-packages-4.7.99.1.
diff --git a/bit b/bit
index 022ad2d..0c46d58 100755
--- a/bit
+++ b/bit
@@ -9,8 +9,7 @@
#
set -ex
-# rtemsNfs is version 1.2
-PACKAGES="rtemsNfs avl-1.4.0 ncurses-5.3 readline-4.3 libtecla-1.4.1 zlib-1.1.4"
+PACKAGES="avl-1.4.0 ncurses-5.3 readline-4.3 libtecla-1.4.1 zlib-1.1.4"
# make sure it is clean before we start
for p in $PACKAGES
diff --git a/rtemsNfs/ChangeLog b/rtemsNfs/ChangeLog
deleted file mode 100644
index 75c479e..0000000
--- a/rtemsNfs/ChangeLog
+++ /dev/null
@@ -1,92 +0,0 @@
-2007-07-16 Joel Sherrill <joel.sherrill@oarcorp.com>
-
- * src/nfs.c: Fix typo.
-
-2007-07-16 Joel Sherrill <joel.sherrill@oarcorp.com>
-
- * proto/nfs_prot_xdr.c: Id string change.
- * src/Makefile: Fix install point of .h files.
- * src/nfs.c: Add some more debug.
-
-2006-08-30 Joel Sherrill <joel@OARcorp.com>
-
- * src/rpcio.c: Remove printf format warnings.
-
-Changes since RTEMS-NFS 1.3_pre2:
- RPCIOD:
- - fix a problem with NFS server clusters (reply comes from an IP address
- different from the destination of the request) by relaxing paranoia checks.
-
-Changes since RTEMS-NFS 1.2:
- NFS:
- - replaced inet_aton -> inet_pton
- - replaced unsigned32 -> uint32_t
- - added _KERNEL definition for 4.7 compilation
- - silenced compiler warnings (4.7)
- - added -Wno-unused-variable in 'proto' -- rpcgen produces a lot of them.
- - new locking scheme. The 'in-use' counters cannot be protected by a mutex
- because files might be closed when a thread is deleted from a dispatch-disabled
- section where mutexes must not be locked. The counters are now protected by
- disabling interrupts.
- The only critical race-condition I can see ATM is while the NFS is being
- unmounted and the mount point is crossed by another thread. It should be the
- generic FS code's responsibility to handle that (but AFAIK, it doesn't) --
- it's out of our scope...
- - ftruncate didn't work. The functionality is achieved by nfs_sattr()
- setting the file size to 0. However, nfs_sattr() always tried to set
- all attributes (re-applying the current values to fields we didn't
- want to change) which failed (EPERM) if we were not the owner.
- Now, we restrict modifications to the requested fields (in case of
- ftruncate this is *only* the size), adhering to rfc1094 (which states
- that unused fields shall be set to -1).
- - lseek(SEEK_END) didn't work. The underlying RTEMS filesystem code
- uses an internal file 'size' field to compute the offset whence SEEK_END.
- Instead of painfully maintaining 'size' across all system calls, we
- just tweak the offset for SEEK_END and leave 'size' unused.
- - fix: O_APPEND wasn't honoured. Note that there is no NFS 'append' call -
- the client simply uses the currently available idea of the file size
- to set the write offset. This obviously is subject to race conditions
- if multiple clients are writing the same file.
- dirutils:
- - replaced read/write calls by stdio; In case of copying to stdout, I
- experienced occasional crashes when write(fileno(stdout),...) -- according
- to the standard, mixing low-level i/o with stdio might produce undefined
- results; there we go...
-
-Changes since RTEMS-NFS 1.1:
- NFS:
- - unlink() didnt work. The underlying RTEMS filesystem code evaluates
- a '..' path on a non-directory node to find out the file's parent
- directory. Workaround to this semantically inelegant RTEMS feature
- was implemented.
-
-Changes since RTEMS-NFS 1.0.beta3:
- NFS:
- - fixed possible string overrun in nfsMount
- - nfs_read_dir() must reset the 'eofreached' flag if it skipped
- dirents present in the xdr but not fitting into the user buffer.
- - nfsMountsShow() released the wrong lock!
- RPCIO:
- - cannot delete locked binary semaphore (authlock) -- must unlock
- first (authlock was never deleted and hence effectively leaked)
- - added ASSERT paranoia around mutex primitives
- - Relaxed paranoia check / ASSERTion failure:
- paranoia_free() is called more than once on an ext_buf - it must
- undo calls to paranoia_refcnt() - hence the 0 == --refcnt check
- is too strict.
- - Added a DEBUG flag to introduce random packet losses for testing
- retransmission.
- xdr_mbuf:
- - make sure we do a signed comparison
-
-Changes since rtemsNFS-1.0.beta2:
- - moved 'tar' command to the 'config' area; use
- predefined 'make-tar' in individual Makefiles
- - use INSTALL_CHANGE for headers, not INSTALL_VARIANT (probably doesn't
- matter, though)
- - use LD not LD_FOR_TARGET (to get absolute path)
- - fixed assertion failure print format
- - print requestor id if send_event fails - had just experienced this :-(
- - hint about fprintf using FP registers is probably PPC specific
- - provided implementation for xdrmbuf_getlong_aligned(). i386-rtems
- seems to use it.
diff --git a/rtemsNfs/LICENSE b/rtemsNfs/LICENSE
deleted file mode 100644
index ba677ea..0000000
--- a/rtemsNfs/LICENSE
+++ /dev/null
@@ -1,115 +0,0 @@
-
- EPICS Open License Terms
-
- The following is the text of the EPICS Open software license agreement
- which applies to many of the unbundled EPICS extensions and support
- modules.
-
- --------------------------------------------------------------
-
- Copyright © 2002, Stanford University and
- Till Straumann <strauman@slac.stanford.edu>
-
- RTEMS-NFS is distributed subject to the following license conditions:
-
- SOFTWARE LICENSE AGREEMENT
- Software: RTEMS-NFS
-
- 1. The "Software", below, refers to RTEMS-NFS (in either source
- code, or binary form and accompanying documentation). Each
- licensee is addressed as "you" or "Licensee."
-
- RTEMS-NFS comprises all files under this directory with
- the EXCEPTION OF
- src/sock_mbuf.c
- src/xdr_mbuf.c
- proto/mount_prot.x
- proto/nfs_prot.x
- which are covered by the licenses described in the
- LICENSE.NET and LICENSE.RPCXDR files (RTEMS source topdir)
- and header comments in the mentioned files, respectively.
-
- 2. The copyright holders shown above and their third-party
- licensors hereby grant Licensee a royalty-free nonexclusive
- license, subject to the limitations stated herein and U.S.
- Government license rights.
- 3. You may modify and make a copy or copies of the Software for use
- within your organization, if you meet the following conditions:
- a. Copies in source code must include the copyright notice
- and this Software License Agreement.
- b. Copies in binary form must include the copyright notice
- and this Software License Agreement in the documentation
- and/or other materials provided with the copy.
-
- 4. You may modify a copy or copies of the Software or any portion
- of it, thus forming a work based on the Software, and distribute
- copies of such work outside your organization, if you meet all
- of the following conditions:
- a. Copies in source code must include the copyright notice
- and this Software License Agreement;
- b. Copies in binary form must include the copyright notice
- and this Software License Agreement in the documentation
- and/or other materials provided with the copy;
- c. Modified copies and works based on the Software must carry
- prominent notices stating that you changed specified
- portions of the Software.
-
- 5. Portions of the Software resulted from work developed under a
- U.S. Government contract and are subject to the following
- license: the Government is granted for itself and others acting
- on its behalf a paid-up, nonexclusive, irrevocable worldwide
- license in this computer software to reproduce, prepare
- derivative works, and perform publicly and display publicly.
- 6. WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS" WITHOUT
- WARRANTY OF ANY KIND. THE COPYRIGHT HOLDERS, THEIR THIRD PARTY
- LICENSORS, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF
- ENERGY, AND THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED
- WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
- TITLE OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY
- OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS
- OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF THE SOFTWARE
- WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4) DO NOT WARRANT
- THAT THE SOFTWARE WILL FUNCTION UNINTERRUPTED, THAT IT IS
- ERROR-FREE OR THAT ANY ERRORS WILL BE CORRECTED.
- 7. LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT HOLDERS,
- THEIR THIRD PARTY LICENSORS, THE UNITED STATES, THE UNITED
- STATES DEPARTMENT OF ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR
- ANY INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE
- DAMAGES OF ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS
- OF PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER
- SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT
- (INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE, EVEN
- IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE POSSIBILITY OF
- SUCH LOSS OR DAMAGES.
-
- Stanford Notice
- ***************
-
- Acknowledgement of sponsorship
- - - - - - - - - - - - - - - - -
- This software was produced by the Stanford Linear Accelerator Center,
- Stanford University, under Contract DE-AC03-76SFO0515 with the Department
- of Energy.
-
- Government disclaimer of liability
- - - - - - - - - - - - - - - - - -
- Neither the United States nor the United States Department of Energy,
- nor any of their employees, makes any warranty, express or implied,
- or assumes any legal liability or responsibility for the accuracy,
- completeness, or usefulness of any data, apparatus, product, or process
- disclosed, or represents that its use would not infringe privately
- owned rights.
-
- Stanford disclaimer of liability
- - - - - - - - - - - - - - - - - -
- Stanford University makes no representations or warranties, express or
- implied, nor assumes any liability for the use of this software.
-
- Maintenance of notice
- - - - - - - - - - - -
- In the interest of clarity regarding the origin and status of this
- software, Stanford University requests that any recipient of it maintain
- this notice affixed to any distribution by the recipient that contains a
- copy or derivative of this software.
-
diff --git a/rtemsNfs/Makefile b/rtemsNfs/Makefile
deleted file mode 100644
index a77b0f8..0000000
--- a/rtemsNfs/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# $Id$
-#
-
-
-include $(RTEMS_MAKEFILE_PATH)/Makefile.inc
-
-include $(RTEMS_CUSTOM)
-include $(RTEMS_ROOT)/make/directory.cfg
-
-SUBDIRS=proto src
-
-REVISION=$(filter-out $$%,$$Name$$)
-
-tar: tar-recursive
- @$(make-tar)
diff --git a/rtemsNfs/README b/rtemsNfs/README
deleted file mode 100644
index 6c261ec..0000000
--- a/rtemsNfs/README
+++ /dev/null
@@ -1,497 +0,0 @@
-RTEMS-NFS
-=========
-
-A NFS-V2 client implementation for the RTEMS real-time
-executive.
-
-Author: Till Straumann <strauman@slac.stanford.edu>, 2002
-
-Copyright 2002, Stanford University and
- Till Straumann <strauman@slac.stanford.edu>
-
-Stanford Notice
-***************
-
-Acknowledgement of sponsorship
-* * * * * * * * * * * * * * * *
-This software was produced by the Stanford Linear Accelerator Center,
-Stanford University, under Contract DE-AC03-76SFO0515 with the Department
-of Energy.
-
-
-Contents
---------
-I Overview
- 1) Performance
- 2) Reference Platform / Test Environment
-
-II Usage
- 1) Initialization
- 2) Mounting Remote Server Filesystems
- 3) Unmounting
- 4) Unloading
- 5) Dumping Information / Statistics
-
-III Implementation Details
- 1) RPCIOD
- 2) NFS
- 3) RTEMS Resources Used By NFS/RPCIOD
- 4) Caveats & Bugs
-
-IV Licensing & Disclaimers
-
-I Overview
------------
-
-This package implements a simple non-caching NFS client
-for RTEMS. Most of the system calls are supported
-with the exception of 'mount', i.e. it is not possible
-to mount another FS on top of NFS (mostly because
-of the difficulty that arises when mount points are
-deleted on the server). It shouldn't be hard to do,
-though.
-
-Note: this client supports NFS vers. 2 / MOUNT vers. 1;
- NFS Version 3 or higher are NOT supported.
-
-The package consists of two modules: RPCIOD and NFS itself.
-
- - RPCIOD is a UDP/RPC multiplexor daemon. It takes
- RPC requests from multiple local client threads,
- funnels them through a single socket to multiple
- servers and dispatches the replies back to the
- (blocked) requestor threads.
- RPCIOD does packet retransmission and handles
- timeouts etc.
- Note however, that it does NOT do any XDR
- marshalling - it is up to the requestor threads
- to do the XDR encoding/decoding. RPCIOD _is_ RPC
- specific, though, because its message dispatching
- is based on the RPC transaction ID.
-
- - The NFS package maps RTEMS filesystem calls
- to proper RPCs, it does the XDR work and
- hands marshalled RPC requests to RPCIOD.
- All of the calls are synchronous, i.e. they
- block until they get a reply.
-
-1) Performance
-- - - - - - - -
-Performance sucks (due to the lack of readahead/delayed
-write and caching). On a fast (100Mb/s) ethernet, it
-takes about 20s to copy a 10MB file from NFS to NFS.
-I found, however, that vxWorks' NFS client doesn't seem
-to be any faster...
-
-2) Reference Platform
-- - - - - - - - - - -
-RTEMS-NFS was developed and tested on
-
- o RTEMS-ss20020301 (local patches applied)
- o PowerPC G3, G4 on Synergy SVGM series board
- (custom 'SVGM' BSP, to be released soon)
- o PowerPC 604 on MVME23xx
- (powerpc/shared/motorola-powerpc BSP)
- o Test Environment:
- - RTEMS executable running CEXP
- - rpciod/nfs dynamically loaded from TFTPfs
- - EPICS application dynamically loaded from NFS;
- the executing IOC accesses all of its files
- on NFS.
-
-II Usage
----------
-
-After linking into the system and proper initialization
-(rtems-NFS supports 'magic' module initialization when
-loaded into a running system with the CEXP loader),
-you are ready for mounting NFSes from a server
-(I avoid the term NFS filesystem because NFS already
-stands for 'Network File System').
-
-You should also read the
-
- - "RTEMS Resources Used By NFS/RPCIOD"
- - "CAVEATS & BUGS"
-
-below.
-
-1) Initialization
-- - - - - - - - -
-NFS consists of two modules who must be initialized:
-
- a) the RPCIO daemon package; by calling
-
- rpcUdpInit();
-
- note that this step must be performed prior to
- initializing NFS:
-
- b) NFS is initialized by calling
-
- nfsInit( smallPoolDepth, bigPoolDepth );
-
- if you supply 0 (zero) values for the pool
- depths, the compile-time default configuration
- is used which should work fine.
-
-NOTE: when using CEXP to load these modules into a
-running system, initialization will be performed
-automagically.
-
-2) Mounting Remote Server Filesystems
-- - - - - - - - - - - - - - - - - - -
-
-There are two interfaces for mounting an NFS:
-
- - The (non-POSIX) RTEMS 'mount()' call:
-
- mount( &mount_table_entry_pointer,
- &filesystem_operations_table_pointer,
- options,
- device,
- mount_point )
-
- Note that you must specify a 'mount_table_entry_pointer'
- (use a dummy) - RTEMS' mount() doesn't grok a NULL for
- the first argument.
-
- o for the 'filesystem_operations_table_pointer', supply
-
- &nfs_fs_ops
-
- o options are constants (see RTEMS headers) for specifying
- read-only / read-write mounts.
-
- o the 'device' string specifies the remote filesystem
- who is to be mounted. NFS expects a string conforming
- to the following format (EBNF syntax):
-
- [ <uid> '.' <gid> '@' ] <hostip> ':' <path>
-
- The first optional part of the string allows you
- to specify the credentials to be used for all
- subsequent transactions with this server. If the
- string is omitted, the EUID/EGID of the executing
- thread (i.e. the thread performing the 'mount' -
- NFS will still 'remember' these values and use them
- for all future communication with this server).
-
- The <hostip> part denotes the server IP address
- in standard 'dot' notation. It is followed by
- a colon and the (absolute) path on the server.
- Note that no extra characters or whitespace must
- be present in the string. Example 'device' strings
- are:
-
- "300.99@192.168.44.3:/remote/rtems/root"
-
- "192.168.44.3:/remote/rtems/root"
-
- o the 'mount_point' string identifies the local
- directory (most probably on IMFS) where the NFS
- is to be mounted. Note that the mount point must
- already exist with proper permissions.
-
- - Alternate 'mount' interface. NFS offers a more
- convenient wrapper taking three string arguments:
-
- nfsMount(uidgid_at_host, server_path, mount_point)
-
- This interface does DNS lookup (see reentrancy note
- below) and creates the mount point if necessary.
-
- o the first argument specifies the server and
- optionally the uid/gid to be used for authentication.
- The semantics are exactly as described above:
-
- [ <uid> '.' <gid> '@' ] <host>
-
- The <host> part may be either a host _name_ or
- an IP address in 'dot' notation. In the former
- case, nfsMount() uses 'gethostbyname()' to do
- a DNS lookup.
-
- IMPORTANT NOTE: gethostbyname() is NOT reentrant/
- thread-safe and 'nfsMount()' (if not provided with an
- IP/dot address string) is hence subject to race conditions.
-
- o the 'server_path' and 'mount_point' arguments
- are described above.
- NOTE: If the mount point does not exist yet,
- nfsMount() tries to create it.
-
- o if nfsMount() is called with a NULL 'uidgid_at_host'
- argument, it lists all currently mounted NFS
-
-3) Unmounting
-- - - - - - -
-An NFS can be unmounted using RTEMS 'unmount()'
-call (yep, it is unmount() - not umount()):
-
- unmount(mount_point)
-
-Note that you _must_ supply the mount point (string
-argument). It is _not_ possible to specify the
-'mountee' when unmounting. NFS implements no
-convenience wrapper for this (yet), essentially because
-(although this sounds unbelievable) it is non-trivial
-to lookup the path leading to an RTEMS filesystem
-directory node.
-
-4) Unloading
-- - - - - - -
-After unmounting all NFS from the system, the NFS
-and RPCIOD modules may be stopped and unloaded.
-Just call 'nfsCleanup()' and 'rpcUdpCleanup()'
-in this order. You should evaluate the return value
-of these routines which is non-zero if either
-of them refuses to yield (e.g. because there are
-still mounted filesystems).
-Again, when unloading is done by CEXP this is
-transparently handled.
-
-5) Dumping Information / Statistics
-- - - - - - - - - - - - - - - - - -
-
-Rudimentary RPCIOD statistics are printed
-to a file (stdout when NULL) by
-
- int rpcUdpStats(FILE *f)
-
-A list of all currently mounted NFS can be
-printed to a file (stdout if NULL) using
-
- int nfsMountsShow(FILE *f)
-
-For convenience, this routine is also called
-by nfsMount() when supplying NULL arguments.
-
-III Implementation Details
---------------------------
-
-1) RPCIOD
-- - - - -
-
-RPCIOD was created to
-
-a) avoid non-reentrant librpc calls.
-b) support 'asynchronous' operation over a single
- socket.
-
-RPCIOD is a daemon thread handling 'transaction objects'
-(XACTs) through an UDP socket. XACTs are marshalled RPC
-calls/replies associated with RPC servers and requestor
-threads.
-
-requestor thread: network:
-
- XACT packet
- | |
- V V
- | message queue | ( socket )
- | | ^
- ----------> <----- | |
- RPCIOD |
- / --------------
- timeout/ (re) transmission
-
-
-A requestor thread drops a transaction into
-the message queue and goes to sleep. The XACT is
-picked up by rpciod who is listening for events from
-three sources:
-
- o the request queue
- o packet arrival at the socket
- o timeouts
-
-RPCIOD sends the XACT to its destination server and
-enqueues the pending XACT into an ordered list of
-outstanding transactions.
-
-When a packet arrives, RPCIOD (based on the RPC transaction
-ID) looks up the matching XACT and wakes up the requestor
-who can then XDR-decode the RPC results found in the XACT
-object's buffer.
-
-When a timeout expires, RPCIOD examines the outstanding
-XACT that is responsible for the timeout. If its lifetime
-has not expired yet, RPCIOD resends the request. Otherwise,
-the XACT's error status is set and the requestor is woken up.
-
-RPCIOD dynamically adjusts the retransmission intervals
-based on the average round-trip time measured (on a per-server
-basis).
-
-Having the requestors event driven (rather than blocking
-e.g. on a semaphore) is geared to having many different
-requestors (one synchronization object per requestor would
-be needed otherwise).
-
-Requestors who want to do asynchronous IO need a different
-interface which will be added in the future.
-
-1.a) Reentrancy
-- - - - - - - -
-RPCIOD does no non-reentrant librpc calls.
-
-1.b) Efficiency
-- - - - - - - -
-We shouldn't bother about efficiency until pipelining (read-ahead/
-delayed write) and caching are implemented. The round-trip delay
-associated with every single RPC transaction clearly is a big
-performance killer.
-
-Nevertheless, I could not withstand the temptation to eliminate
-the extra copy step involved with socket IO:
-
-A user data object has to be XDR encoded into a buffer. The
-buffer given to the socket where it is copied into MBUFs.
-(The network chip driver might even do more copying).
-
-Likewise, on reception 'recvfrom' copies MBUFS into a user
-buffer which is XDR decoded into the final user data object.
-
-Eliminating the copying into (possibly multiple) MBUFS by
-'sendto()' is actually a piece of cake. RPCIOD uses the
-'sosend()' routine [properly wrapped] supplying a single
-MBUF header who directly points to the marshalled buffer
-:-)
-
-Getting rid of the extra copy on reception was (only a little)
-harder: I derived a 'XDR-mbuf' stream from SUN's xdr_mem which
-allows for XDR-decoding out of a MBUF chain who is obtained by
-soreceive().
-
-2) NFS
-- - - -
-The actual NFS implementation is straightforward and essentially
-'passive' (no threads created). Any RTEMS task executing a
-filesystem call dispatched to NFS (such as 'opendir()', 'lseek()'
-or 'unlink()') ends up XDR encoding arguments, dropping a
-XACT into RPCIOD's message queue and going to sleep.
-When woken up by RPCIOD, the XACT is decoded (using the XDR-mbuf
-stream mentioned above) and the properly cooked-up results are
-returned.
-
-3) RTEMS Resources Used By NFS/RPCIOD
-- - - - - - - - - - - - - - - - - - -
-
-The RPCIOD/NFS package uses the following resources. Some
-parameters are compile-time configurable - consult the
-source files for details.
-
-RPCIOD:
- o 1 task
- o 1 message queue
- o 1 socket/filedescriptor
- o 2 semaphores (a third one is temporarily created during
- rpcUdpCleanup()).
- o 1 RTEMS EVENT (by default RTEMS_EVENT_30).
- IMPORTANT: this event is used by _every_ thread executing
- NFS system calls and hence is RESERVED.
- o 3 events only used by RPCIOD itself, i.e. these must not
- be sent to RPCIOD by no other thread (except for the intended
- use, of course). The events involved are 1,2,3.
- o preemption disabled sections: NONE
- o sections with interrupts disabled: NONE
- o NO 'timers' are used (timer code would run in IRQ context)
- o memory usage: n.a
-
-NFS:
- o 2 message queues
- o 2 semaphores
- o 1 semaphore per mounted NFS
- o 1 slot in driver entry table (for major number)
- o preemption disabled sections: NONE
- o sections with interrupts disabled: NONE
- o 1 task + 1 semaphore temporarily created when
- listing mounted filesystems (rtems_filesystem_resolve_location())
-
-4) CAVEATS & BUGS
-- - - - - - - - -
-Unfortunately, some bugs crawl around in the filesystem generics.
-(Some of them might already be fixed in versions later than
-rtems-ss-20020301).
-I recommend to use the patch distributed with RTEMS-NFS.
-
- o RTEMS uses/used (Joel said it has been fixed already) a 'short'
- ino_t which is not enough for NFS.
- The driver detects this problem and enables a workaround. In rare
- situations (mainly involving 'getcwd()' improper inode comparison
- may result (due to the restricted size, stat() returns st_ino modulo
- 2^16). In most cases, however, st_dev is compared along with st_ino
- which will give correct results (different files may yield identical
- st_ino but they will have different st_dev). However, there is
- code (in getcwd(), for example) who assumes that files residing
- in one directory must be hosted by the same device and hence omits
- the st_dev comparison. In such a case, the workaround will fail.
-
- NOTE: changing the size (sys/types.h) of ino_t from 'short' to 'long'
- is strongly recommended. It is NOT included in the patch, however
- as this is a major change requiring ALL of your sources to
- be recompiled.
-
- THE ino_t SIZE IS FIXED IN GCC-3.2/NEWLIB-1.10.0-2 DISTRIBUTED BY
- OAR.
-
- o You may work around most filesystem bugs by observing the following
- rules:
-
- * never use chroot() (fixed by the patch)
- * never use getpwent(), getgrent() & friends - they are NOT THREAD
- safe (fixed by the patch)
- * NEVER use rtems_libio_share_private_env() - not even with the
- patch applied. Just DONT - it is broken by design.
- * All threads who have their own userenv (who have called
- rtems_libio_set_private_env()) SHOULD 'chdir("/")' before
- terminating. Otherwise, (i.e. if their cwd is on NFS), it will
- be impossible to unmount the NFS involved.
-
- o The patch slightly changes the semantics of 'getpwent()' and
- 'getgrent()' & friends (to what is IMHO correct anyways - the patch is
- also needed to fix another problem, however): with the patch applied,
- the passwd and group files are always accessed from the 'current' user
- environment, i.e. a thread who has changed its 'root' or 'uid' might
- not be able to access these files anymore.
-
- o NOTE: RTEMS 'mount()' / 'unmount()' are NOT THREAD SAFE.
-
- o The NFS protocol has no 'append' or 'seek_end' primitive. The client
- must query the current file size (this client uses cached info) and
- change the local file pointer accordingly (in 'O_APPEND' mode).
- Obviously, this involves a race condition and hence multiple clients
- writing the same file may lead to corruption.
-
-IV Licensing & Disclaimers
---------------------------
-
-NFS is distributed under the EPICS Open License - consult the
-separate 'LICENSE' file.
-
-Government disclaimer of liability
-- - - - - - - - - - - - - - - - -
-Neither the United States nor the United States Department of Energy,
-nor any of their employees, makes any warranty, express or implied,
-or assumes any legal liability or responsibility for the accuracy,
-completeness, or usefulness of any data, apparatus, product, or process
-disclosed, or represents that its use would not infringe privately
-owned rights.
-
-Stanford disclaimer of liability
-- - - - - - - - - - - - - - - - -
-Stanford University makes no representations or warranties, express or
-implied, nor assumes any liability for the use of this software.
-
-This product is subject to the EPICS open license
-- - - - - - - - - - - - - - - - - - - - - - - - -
-Consult the LICENSE file or http://www.aps.anl.gov/epics/license/open.php
-for more information.
-
-Maintenance of notice
-- - - - - - - - - - -
-In the interest of clarity regarding the origin and status of this
-software, Stanford University requests that any recipient of it maintain
-this notice affixed to any distribution by the recipient that contains a
-copy or derivative of this software.
diff --git a/rtemsNfs/proto/Makefile b/rtemsNfs/proto/Makefile
deleted file mode 100644
index e95eaa1..0000000
--- a/rtemsNfs/proto/Makefile
+++ /dev/null
@@ -1,76 +0,0 @@
-#
-# $Id$
-#
-# Templates/Makefile.lib
-# Template library Makefile
-#
-
-
-LIBNAME=libnfsprot.a # xxx- your library names goes here
-LIB=${ARCH}/${LIBNAME}
-
-# C and C++ source names, if any, go here -- minus the .c or .cc
-C_PIECES=nfs_prot_xdr mount_prot_xdr
-C_FILES=$(C_PIECES:%=%.c)
-C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
-
-CC_PIECES=
-CC_FILES=$(CC_PIECES:%=%.cc)
-CC_O_FILES=$(CC_PIECES:%=${ARCH}/%.o)
-
-H_FILES=
-
-XFILES = $(wildcard *.x)
-
-# Assembly source names, if any, go here -- minus the .S
-S_PIECES=
-S_FILES=$(S_PIECES:%=%.S)
-S_O_FILES=$(S_FILES:%.S=${ARCH}/%.o)
-
-SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES)
-OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES)
-
-include $(RTEMS_MAKEFILE_PATH)/Makefile.inc
-
-include $(RTEMS_CUSTOM)
-include $(RTEMS_ROOT)/make/lib.cfg
-
-#
-# Add local stuff here using +=
-#
-
-DEFINES +=
-CPPFLAGS +=
-# inline declarations require -O
-# rpcgen produces unused variables
-CFLAGS += -O2 -Winline -Wno-unused-variable
-
-#
-# Add your list of files to delete here. The config files
-# already know how to delete some stuff, so you may want
-# to just run 'make clean' first to see what gets missed.
-# 'make clobber' already includes 'make clean'
-#
-
-CLEAN_ADDITIONS +=
-CLOBBER_ADDITIONS += $(XFILES:%.x=%*.c) $(XFILES:%.x=%*.h)
-
-all: ${ARCH} $(SRCS) $(LIB)
-
-$(LIB): ${OBJS}
- $(make-library)
-
-%_xdr.c: %.x %.h
- rpcgen -c $< > $@
-
-%.h: %.x
- rpcgen -h $< > $@
-
-.PRECIOUS: $(XFILES:%.x=%.h) $(XFILES:%.x=%_xdr.c)
-
-tar: $(XFILES:%.x=%.h) $(XFILES:%.x=%_xdr.c)
-
-distclean: clean
-
-# DONT install this library.
-install: all
diff --git a/rtemsNfs/proto/mount_prot.h b/rtemsNfs/proto/mount_prot.h
deleted file mode 100644
index 1cde517..0000000
--- a/rtemsNfs/proto/mount_prot.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Please do not edit this file.
- * It was generated using rpcgen.
- */
-
-#ifndef _MOUNT_PROT_H_RPCGEN
-#define _MOUNT_PROT_H_RPCGEN
-
-#include <rpc/rpc.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define MNTPATHLEN 1024
-#define MNTNAMLEN 255
-#define FHSIZE 32
-
-typedef char fhandle[FHSIZE];
-
-struct fhstatus {
- u_int fhs_status;
- union {
- fhandle fhs_fhandle;
- } fhstatus_u;
-};
-typedef struct fhstatus fhstatus;
-
-typedef char *dirpath;
-
-typedef char *name;
-
-typedef struct mountbody *mountlist;
-
-struct mountbody {
- name ml_hostname;
- dirpath ml_directory;
- mountlist ml_next;
-};
-typedef struct mountbody mountbody;
-
-typedef struct groupnode *groups;
-
-struct groupnode {
- name gr_name;
- groups gr_next;
-};
-typedef struct groupnode groupnode;
-
-typedef struct exportnode *exports;
-
-struct exportnode {
- dirpath ex_dir;
- groups ex_groups;
- exports ex_next;
-};
-typedef struct exportnode exportnode;
-
-#define MOUNTPROG 100005
-#define MOUNTVERS 1
-
-#if defined(__STDC__) || defined(__cplusplus)
-#define MOUNTPROC_NULL 0
-extern void * mountproc_null_1(void *, CLIENT *);
-extern void * mountproc_null_1_svc(void *, struct svc_req *);
-#define MOUNTPROC_MNT 1
-extern fhstatus * mountproc_mnt_1(dirpath *, CLIENT *);
-extern fhstatus * mountproc_mnt_1_svc(dirpath *, struct svc_req *);
-#define MOUNTPROC_DUMP 2
-extern mountlist * mountproc_dump_1(void *, CLIENT *);
-extern mountlist * mountproc_dump_1_svc(void *, struct svc_req *);
-#define MOUNTPROC_UMNT 3
-extern void * mountproc_umnt_1(dirpath *, CLIENT *);
-extern void * mountproc_umnt_1_svc(dirpath *, struct svc_req *);
-#define MOUNTPROC_UMNTALL 4
-extern void * mountproc_umntall_1(void *, CLIENT *);
-extern void * mountproc_umntall_1_svc(void *, struct svc_req *);
-#define MOUNTPROC_EXPORT 5
-extern exports * mountproc_export_1(void *, CLIENT *);
-extern exports * mountproc_export_1_svc(void *, struct svc_req *);
-#define MOUNTPROC_EXPORTALL 6
-extern exports * mountproc_exportall_1(void *, CLIENT *);
-extern exports * mountproc_exportall_1_svc(void *, struct svc_req *);
-extern int mountprog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
-
-#else /* K&R C */
-#define MOUNTPROC_NULL 0
-extern void * mountproc_null_1();
-extern void * mountproc_null_1_svc();
-#define MOUNTPROC_MNT 1
-extern fhstatus * mountproc_mnt_1();
-extern fhstatus * mountproc_mnt_1_svc();
-#define MOUNTPROC_DUMP 2
-extern mountlist * mountproc_dump_1();
-extern mountlist * mountproc_dump_1_svc();
-#define MOUNTPROC_UMNT 3
-extern void * mountproc_umnt_1();
-extern void * mountproc_umnt_1_svc();
-#define MOUNTPROC_UMNTALL 4
-extern void * mountproc_umntall_1();
-extern void * mountproc_umntall_1_svc();
-#define MOUNTPROC_EXPORT 5
-extern exports * mountproc_export_1();
-extern exports * mountproc_export_1_svc();
-#define MOUNTPROC_EXPORTALL 6
-extern exports * mountproc_exportall_1();
-extern exports * mountproc_exportall_1_svc();
-extern int mountprog_1_freeresult ();
-#endif /* K&R C */
-
-/* the xdr functions */
-
-#if defined(__STDC__) || defined(__cplusplus)
-extern bool_t xdr_fhandle (XDR *, fhandle);
-extern bool_t xdr_fhstatus (XDR *, fhstatus*);
-extern bool_t xdr_dirpath (XDR *, dirpath*);
-extern bool_t xdr_name (XDR *, name*);
-extern bool_t xdr_mountlist (XDR *, mountlist*);
-extern bool_t xdr_mountbody (XDR *, mountbody*);
-extern bool_t xdr_groups (XDR *, groups*);
-extern bool_t xdr_groupnode (XDR *, groupnode*);
-extern bool_t xdr_exports (XDR *, exports*);
-extern bool_t xdr_exportnode (XDR *, exportnode*);
-
-#else /* K&R C */
-extern bool_t xdr_fhandle ();
-extern bool_t xdr_fhstatus ();
-extern bool_t xdr_dirpath ();
-extern bool_t xdr_name ();
-extern bool_t xdr_mountlist ();
-extern bool_t xdr_mountbody ();
-extern bool_t xdr_groups ();
-extern bool_t xdr_groupnode ();
-extern bool_t xdr_exports ();
-extern bool_t xdr_exportnode ();
-
-#endif /* K&R C */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !_MOUNT_PROT_H_RPCGEN */
diff --git a/rtemsNfs/proto/mount_prot.x b/rtemsNfs/proto/mount_prot.x
deleted file mode 100644
index 444e998..0000000
--- a/rtemsNfs/proto/mount_prot.x
+++ /dev/null
@@ -1,161 +0,0 @@
-/* @(#)mount.x 2.1 88/08/01 4.0 RPCSRC */
-/* @(#)mount.x 1.2 87/09/18 Copyr 1987 Sun Micro */
-
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-
-/*
- * Protocol description for the mount program
- */
-
-
-const MNTPATHLEN = 1024; /* maximum bytes in a pathname argument */
-const MNTNAMLEN = 255; /* maximum bytes in a name argument */
-const FHSIZE = 32; /* size in bytes of a file handle */
-
-/*
- * The fhandle is the file handle that the server passes to the client.
- * All file operations are done using the file handles to refer to a file
- * or a directory. The file handle can contain whatever information the
- * server needs to distinguish an individual file.
- */
-typedef opaque fhandle[FHSIZE];
-
-/*
- * If a status of zero is returned, the call completed successfully, and
- * a file handle for the directory follows. A non-zero status indicates
- * some sort of error. The status corresponds with UNIX error numbers.
- */
-union fhstatus switch (unsigned fhs_status) {
-case 0:
- fhandle fhs_fhandle;
-default:
- void;
-};
-
-/*
- * The type dirpath is the pathname of a directory
- */
-typedef string dirpath<MNTPATHLEN>;
-
-/*
- * The type name is used for arbitrary names (hostnames, groupnames)
- */
-typedef string name<MNTNAMLEN>;
-
-/*
- * A list of who has what mounted
- */
-typedef struct mountbody *mountlist;
-struct mountbody {
- name ml_hostname;
- dirpath ml_directory;
- mountlist ml_next;
-};
-
-/*
- * A list of netgroups
- */
-typedef struct groupnode *groups;
-struct groupnode {
- name gr_name;
- groups gr_next;
-};
-
-/*
- * A list of what is exported and to whom
- */
-typedef struct exportnode *exports;
-struct exportnode {
- dirpath ex_dir;
- groups ex_groups;
- exports ex_next;
-};
-
-program MOUNTPROG {
- /*
- * Version one of the mount protocol communicates with version two
- * of the NFS protocol. The only connecting point is the fhandle
- * structure, which is the same for both protocols.
- */
- version MOUNTVERS {
- /*
- * Does no work. It is made available in all RPC services
- * to allow server reponse testing and timing
- */
- void
- MOUNTPROC_NULL(void) = 0;
-
- /*
- * If fhs_status is 0, then fhs_fhandle contains the
- * file handle for the directory. This file handle may
- * be used in the NFS protocol. This procedure also adds
- * a new entry to the mount list for this client mounting
- * the directory.
- * Unix authentication required.
- */
- fhstatus
- MOUNTPROC_MNT(dirpath) = 1;
-
- /*
- * Returns the list of remotely mounted filesystems. The
- * mountlist contains one entry for each hostname and
- * directory pair.
- */
- mountlist
- MOUNTPROC_DUMP(void) = 2;
-
- /*
- * Removes the mount list entry for the directory
- * Unix authentication required.
- */
- void
- MOUNTPROC_UMNT(dirpath) = 3;
-
- /*
- * Removes all of the mount list entries for this client
- * Unix authentication required.
- */
- void
- MOUNTPROC_UMNTALL(void) = 4;
-
- /*
- * Returns a list of all the exported filesystems, and which
- * machines are allowed to import it.
- */
- exports
- MOUNTPROC_EXPORT(void) = 5;
-
- /*
- * Identical to MOUNTPROC_EXPORT above
- */
- exports
- MOUNTPROC_EXPORTALL(void) = 6;
- } = 1;
-} = 100005;
diff --git a/rtemsNfs/proto/mount_prot_xdr.c b/rtemsNfs/proto/mount_prot_xdr.c
deleted file mode 100644
index b83350b..0000000
--- a/rtemsNfs/proto/mount_prot_xdr.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Please do not edit this file.
- * It was generated using rpcgen.
- */
-
-#include "mount_prot.h"
-
-bool_t
-xdr_fhandle (XDR *xdrs, fhandle objp)
-{
- register int32_t *buf;
-
- if (!xdr_opaque (xdrs, objp, FHSIZE))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_fhstatus (XDR *xdrs, fhstatus *objp)
-{
- register int32_t *buf;
-
- if (!xdr_u_int (xdrs, &objp->fhs_status))
- return FALSE;
- switch (objp->fhs_status) {
- case 0:
- if (!xdr_fhandle (xdrs, objp->fhstatus_u.fhs_fhandle))
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_dirpath (XDR *xdrs, dirpath *objp)
-{
- register int32_t *buf;
-
- if (!xdr_string (xdrs, objp, MNTPATHLEN))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_name (XDR *xdrs, name *objp)
-{
- register int32_t *buf;
-
- if (!xdr_string (xdrs, objp, MNTNAMLEN))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_mountlist (XDR *xdrs, mountlist *objp)
-{
- register int32_t *buf;
-
- if (!xdr_pointer (xdrs, (char **)objp, sizeof (struct mountbody), (xdrproc_t) xdr_mountbody))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_mountbody (XDR *xdrs, mountbody *objp)
-{
- register int32_t *buf;
-
- if (!xdr_name (xdrs, &objp->ml_hostname))
- return FALSE;
- if (!xdr_dirpath (xdrs, &objp->ml_directory))
- return FALSE;
- if (!xdr_mountlist (xdrs, &objp->ml_next))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_groups (XDR *xdrs, groups *objp)
-{
- register int32_t *buf;
-
- if (!xdr_pointer (xdrs, (char **)objp, sizeof (struct groupnode), (xdrproc_t) xdr_groupnode))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_groupnode (XDR *xdrs, groupnode *objp)
-{
- register int32_t *buf;
-
- if (!xdr_name (xdrs, &objp->gr_name))
- return FALSE;
- if (!xdr_groups (xdrs, &objp->gr_next))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_exports (XDR *xdrs, exports *objp)
-{
- register int32_t *buf;
-
- if (!xdr_pointer (xdrs, (char **)objp, sizeof (struct exportnode), (xdrproc_t) xdr_exportnode))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_exportnode (XDR *xdrs, exportnode *objp)
-{
- register int32_t *buf;
-
- if (!xdr_dirpath (xdrs, &objp->ex_dir))
- return FALSE;
- if (!xdr_groups (xdrs, &objp->ex_groups))
- return FALSE;
- if (!xdr_exports (xdrs, &objp->ex_next))
- return FALSE;
- return TRUE;
-}
diff --git a/rtemsNfs/proto/nfs_prot.h b/rtemsNfs/proto/nfs_prot.h
deleted file mode 100644
index de812db..0000000
--- a/rtemsNfs/proto/nfs_prot.h
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * Please do not edit this file.
- * It was generated using rpcgen.
- */
-
-#ifndef _NFS_PROT_H_RPCGEN
-#define _NFS_PROT_H_RPCGEN
-
-#include <rpc/rpc.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define NFS_PORT 2049
-#define NFS_MAXDATA 8192
-#define NFS_MAXPATHLEN 1024
-#define NFS_MAXNAMLEN 255
-#define NFS_FHSIZE 32
-#define NFS_COOKIESIZE 4
-#define NFS_FIFO_DEV -1
-#define NFSMODE_FMT 0170000
-#define NFSMODE_DIR 0040000
-#define NFSMODE_CHR 0020000
-#define NFSMODE_BLK 0060000
-#define NFSMODE_REG 0100000
-#define NFSMODE_LNK 0120000
-#define NFSMODE_SOCK 0140000
-#define NFSMODE_FIFO 0010000
-
-enum nfsstat {
- NFS_OK = 0,
- NFSERR_PERM = 1,
- NFSERR_NOENT = 2,
- NFSERR_IO = 5,
- NFSERR_NXIO = 6,
- NFSERR_ACCES = 13,
- NFSERR_EXIST = 17,
- NFSERR_NODEV = 19,
- NFSERR_NOTDIR = 20,
- NFSERR_ISDIR = 21,
- NFSERR_FBIG = 27,
- NFSERR_NOSPC = 28,
- NFSERR_ROFS = 30,
- NFSERR_NAMETOOLONG = 63,
- NFSERR_NOTEMPTY = 66,
- NFSERR_DQUOT = 69,
- NFSERR_STALE = 70,
- NFSERR_WFLUSH = 99,
-};
-typedef enum nfsstat nfsstat;
-
-enum ftype {
- NFNON = 0,
- NFREG = 1,
- NFDIR = 2,
- NFBLK = 3,
- NFCHR = 4,
- NFLNK = 5,
- NFSOCK = 6,
- NFBAD = 7,
- NFFIFO = 8,
-};
-typedef enum ftype ftype;
-
-struct nfs_fh {
- char data[NFS_FHSIZE];
-};
-typedef struct nfs_fh nfs_fh;
-
-struct nfstime {
- u_int seconds;
- u_int useconds;
-};
-typedef struct nfstime nfstime;
-
-struct fattr {
- ftype type;
- u_int mode;
- u_int nlink;
- u_int uid;
- u_int gid;
- u_int size;
- u_int blocksize;
- u_int rdev;
- u_int blocks;
- u_int fsid;
- u_int fileid;
- nfstime atime;
- nfstime mtime;
- nfstime ctime;
-};
-typedef struct fattr fattr;
-
-struct sattr {
- u_int mode;
- u_int uid;
- u_int gid;
- u_int size;
- nfstime atime;
- nfstime mtime;
-};
-typedef struct sattr sattr;
-
-typedef char *filename;
-
-typedef char *nfspath;
-
-struct attrstat {
- nfsstat status;
- union {
- fattr attributes;
- } attrstat_u;
-};
-typedef struct attrstat attrstat;
-
-struct sattrargs {
- nfs_fh file;
- sattr attributes;
-};
-typedef struct sattrargs sattrargs;
-
-struct diropargs {
- nfs_fh dir;
- filename name;
-};
-typedef struct diropargs diropargs;
-
-struct diropokres {
- nfs_fh file;
- fattr attributes;
-};
-typedef struct diropokres diropokres;
-
-struct diropres {
- nfsstat status;
- union {
- diropokres diropres;
- } diropres_u;
-};
-typedef struct diropres diropres;
-
-struct readlinkres {
- nfsstat status;
- union {
- nfspath data;
- } readlinkres_u;
-};
-typedef struct readlinkres readlinkres;
-
-struct readargs {
- nfs_fh file;
- u_int offset;
- u_int count;
- u_int totalcount;
-};
-typedef struct readargs readargs;
-
-struct readokres {
- fattr attributes;
- struct {
- u_int data_len;
- char *data_val;
- } data;
-};
-typedef struct readokres readokres;
-
-struct readres {
- nfsstat status;
- union {
- readokres reply;
- } readres_u;
-};
-typedef struct readres readres;
-
-struct writeargs {
- nfs_fh file;
- u_int beginoffset;
- u_int offset;
- u_int totalcount;
- struct {
- u_int data_len;
- char *data_val;
- } data;
-};
-typedef struct writeargs writeargs;
-
-struct createargs {
- diropargs where;
- sattr attributes;
-};
-typedef struct createargs createargs;
-
-struct renameargs {
- diropargs from;
- diropargs to;
-};
-typedef struct renameargs renameargs;
-
-struct linkargs {
- nfs_fh from;
- diropargs to;
-};
-typedef struct linkargs linkargs;
-
-struct symlinkargs {
- diropargs from;
- nfspath to;
- sattr attributes;
-};
-typedef struct symlinkargs symlinkargs;
-
-struct nfscookie {
- char data[NFS_COOKIESIZE];
-};
-typedef struct nfscookie nfscookie;
-
-struct readdirargs {
- nfs_fh dir;
- nfscookie cookie;
- u_int count;
-};
-typedef struct readdirargs readdirargs;
-
-struct entry {
- u_int fileid;
- filename name;
- nfscookie cookie;
- struct entry *nextentry;
-};
-typedef struct entry entry;
-
-struct dirlist {
- entry *entries;
- bool_t eof;
-};
-typedef struct dirlist dirlist;
-
-struct readdirres {
- nfsstat status;
- union {
- dirlist reply;
- } readdirres_u;
-};
-typedef struct readdirres readdirres;
-
-struct statfsokres {
- u_int tsize;
- u_int bsize;
- u_int blocks;
- u_int bfree;
- u_int bavail;
-};
-typedef struct statfsokres statfsokres;
-
-struct statfsres {
- nfsstat status;
- union {
- statfsokres reply;
- } statfsres_u;
-};
-typedef struct statfsres statfsres;
-
-#define NFS_PROGRAM 100003
-#define NFS_VERSION 2
-
-#if defined(__STDC__) || defined(__cplusplus)
-#define NFSPROC_NULL 0
-extern void * nfsproc_null_2(void *, CLIENT *);
-extern void * nfsproc_null_2_svc(void *, struct svc_req *);
-#define NFSPROC_GETATTR 1
-extern attrstat * nfsproc_getattr_2(nfs_fh *, CLIENT *);
-extern attrstat * nfsproc_getattr_2_svc(nfs_fh *, struct svc_req *);
-#define NFSPROC_SETATTR 2
-extern attrstat * nfsproc_setattr_2(sattrargs *, CLIENT *);
-extern attrstat * nfsproc_setattr_2_svc(sattrargs *, struct svc_req *);
-#define NFSPROC_ROOT 3
-extern void * nfsproc_root_2(void *, CLIENT *);
-extern void * nfsproc_root_2_svc(void *, struct svc_req *);
-#define NFSPROC_LOOKUP 4
-extern diropres * nfsproc_lookup_2(diropargs *, CLIENT *);
-extern diropres * nfsproc_lookup_2_svc(diropargs *, struct svc_req *);
-#define NFSPROC_READLINK 5
-extern readlinkres * nfsproc_readlink_2(nfs_fh *, CLIENT *);
-extern readlinkres * nfsproc_readlink_2_svc(nfs_fh *, struct svc_req *);
-#define NFSPROC_READ 6
-extern readres * nfsproc_read_2(readargs *, CLIENT *);
-extern readres * nfsproc_read_2_svc(readargs *, struct svc_req *);
-#define NFSPROC_WRITECACHE 7
-extern void * nfsproc_writecache_2(void *, CLIENT *);
-extern void * nfsproc_writecache_2_svc(void *, struct svc_req *);
-#define NFSPROC_WRITE 8
-extern attrstat * nfsproc_write_2(writeargs *, CLIENT *);
-extern attrstat * nfsproc_write_2_svc(writeargs *, struct svc_req *);
-#define NFSPROC_CREATE 9
-extern diropres * nfsproc_create_2(createargs *, CLIENT *);
-extern diropres * nfsproc_create_2_svc(createargs *, struct svc_req *);
-#define NFSPROC_REMOVE 10
-extern nfsstat * nfsproc_remove_2(diropargs *, CLIENT *);
-extern nfsstat * nfsproc_remove_2_svc(diropargs *, struct svc_req *);
-#define NFSPROC_RENAME 11
-extern nfsstat * nfsproc_rename_2(renameargs *, CLIENT *);
-extern nfsstat * nfsproc_rename_2_svc(renameargs *, struct svc_req *);
-#define NFSPROC_LINK 12
-extern nfsstat * nfsproc_link_2(linkargs *, CLIENT *);
-extern nfsstat * nfsproc_link_2_svc(linkargs *, struct svc_req *);
-#define NFSPROC_SYMLINK 13
-extern nfsstat * nfsproc_symlink_2(symlinkargs *, CLIENT *);
-extern nfsstat * nfsproc_symlink_2_svc(symlinkargs *, struct svc_req *);
-#define NFSPROC_MKDIR 14
-extern diropres * nfsproc_mkdir_2(createargs *, CLIENT *);
-extern diropres * nfsproc_mkdir_2_svc(createargs *, struct svc_req *);
-#define NFSPROC_RMDIR 15
-extern nfsstat * nfsproc_rmdir_2(diropargs *, CLIENT *);
-extern nfsstat * nfsproc_rmdir_2_svc(diropargs *, struct svc_req *);
-#define NFSPROC_READDIR 16
-extern readdirres * nfsproc_readdir_2(readdirargs *, CLIENT *);
-extern readdirres * nfsproc_readdir_2_svc(readdirargs *, struct svc_req *);
-#define NFSPROC_STATFS 17
-extern statfsres * nfsproc_statfs_2(nfs_fh *, CLIENT *);
-extern statfsres * nfsproc_statfs_2_svc(nfs_fh *, struct svc_req *);
-extern int nfs_program_2_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
-
-#else /* K&R C */
-#define NFSPROC_NULL 0
-extern void * nfsproc_null_2();
-extern void * nfsproc_null_2_svc();
-#define NFSPROC_GETATTR 1
-extern attrstat * nfsproc_getattr_2();
-extern attrstat * nfsproc_getattr_2_svc();
-#define NFSPROC_SETATTR 2
-extern attrstat * nfsproc_setattr_2();
-extern attrstat * nfsproc_setattr_2_svc();
-#define NFSPROC_ROOT 3
-extern void * nfsproc_root_2();
-extern void * nfsproc_root_2_svc();
-#define NFSPROC_LOOKUP 4
-extern diropres * nfsproc_lookup_2();
-extern diropres * nfsproc_lookup_2_svc();
-#define NFSPROC_READLINK 5
-extern readlinkres * nfsproc_readlink_2();
-extern readlinkres * nfsproc_readlink_2_svc();
-#define NFSPROC_READ 6
-extern readres * nfsproc_read_2();
-extern readres * nfsproc_read_2_svc();
-#define NFSPROC_WRITECACHE 7
-extern void * nfsproc_writecache_2();
-extern void * nfsproc_writecache_2_svc();
-#define NFSPROC_WRITE 8
-extern attrstat * nfsproc_write_2();
-extern attrstat * nfsproc_write_2_svc();
-#define NFSPROC_CREATE 9
-extern diropres * nfsproc_create_2();
-extern diropres * nfsproc_create_2_svc();
-#define NFSPROC_REMOVE 10
-extern nfsstat * nfsproc_remove_2();
-extern nfsstat * nfsproc_remove_2_svc();
-#define NFSPROC_RENAME 11
-extern nfsstat * nfsproc_rename_2();
-extern nfsstat * nfsproc_rename_2_svc();
-#define NFSPROC_LINK 12
-extern nfsstat * nfsproc_link_2();
-extern nfsstat * nfsproc_link_2_svc();
-#define NFSPROC_SYMLINK 13
-extern nfsstat * nfsproc_symlink_2();
-extern nfsstat * nfsproc_symlink_2_svc();
-#define NFSPROC_MKDIR 14
-extern diropres * nfsproc_mkdir_2();
-extern diropres * nfsproc_mkdir_2_svc();
-#define NFSPROC_RMDIR 15
-extern nfsstat * nfsproc_rmdir_2();
-extern nfsstat * nfsproc_rmdir_2_svc();
-#define NFSPROC_READDIR 16
-extern readdirres * nfsproc_readdir_2();
-extern readdirres * nfsproc_readdir_2_svc();
-#define NFSPROC_STATFS 17
-extern statfsres * nfsproc_statfs_2();
-extern statfsres * nfsproc_statfs_2_svc();
-extern int nfs_program_2_freeresult ();
-#endif /* K&R C */
-
-/* the xdr functions */
-
-#if defined(__STDC__) || defined(__cplusplus)
-extern bool_t xdr_nfsstat (XDR *, nfsstat*);
-extern bool_t xdr_ftype (XDR *, ftype*);
-extern bool_t xdr_nfs_fh (XDR *, nfs_fh*);
-extern bool_t xdr_nfstime (XDR *, nfstime*);
-extern bool_t xdr_fattr (XDR *, fattr*);
-extern bool_t xdr_sattr (XDR *, sattr*);
-extern bool_t xdr_filename (XDR *, filename*);
-extern bool_t xdr_nfspath (XDR *, nfspath*);
-extern bool_t xdr_attrstat (XDR *, attrstat*);
-extern bool_t xdr_sattrargs (XDR *, sattrargs*);
-extern bool_t xdr_diropargs (XDR *, diropargs*);
-extern bool_t xdr_diropokres (XDR *, diropokres*);
-extern bool_t xdr_diropres (XDR *, diropres*);
-extern bool_t xdr_readlinkres (XDR *, readlinkres*);
-extern bool_t xdr_readargs (XDR *, readargs*);
-extern bool_t xdr_readokres (XDR *, readokres*);
-extern bool_t xdr_readres (XDR *, readres*);
-extern bool_t xdr_writeargs (XDR *, writeargs*);
-extern bool_t xdr_createargs (XDR *, createargs*);
-extern bool_t xdr_renameargs (XDR *, renameargs*);
-extern bool_t xdr_linkargs (XDR *, linkargs*);
-extern bool_t xdr_symlinkargs (XDR *, symlinkargs*);
-extern bool_t xdr_nfscookie (XDR *, nfscookie*);
-extern bool_t xdr_readdirargs (XDR *, readdirargs*);
-extern bool_t xdr_entry (XDR *, entry*);
-extern bool_t xdr_dirlist (XDR *, dirlist*);
-extern bool_t xdr_readdirres (XDR *, readdirres*);
-extern bool_t xdr_statfsokres (XDR *, statfsokres*);
-extern bool_t xdr_statfsres (XDR *, statfsres*);
-
-#else /* K&R C */
-extern bool_t xdr_nfsstat ();
-extern bool_t xdr_ftype ();
-extern bool_t xdr_nfs_fh ();
-extern bool_t xdr_nfstime ();
-extern bool_t xdr_fattr ();
-extern bool_t xdr_sattr ();
-extern bool_t xdr_filename ();
-extern bool_t xdr_nfspath ();
-extern bool_t xdr_attrstat ();
-extern bool_t xdr_sattrargs ();
-extern bool_t xdr_diropargs ();
-extern bool_t xdr_diropokres ();
-extern bool_t xdr_diropres ();
-extern bool_t xdr_readlinkres ();
-extern bool_t xdr_readargs ();
-extern bool_t xdr_readokres ();
-extern bool_t xdr_readres ();
-extern bool_t xdr_writeargs ();
-extern bool_t xdr_createargs ();
-extern bool_t xdr_renameargs ();
-extern bool_t xdr_linkargs ();
-extern bool_t xdr_symlinkargs ();
-extern bool_t xdr_nfscookie ();
-extern bool_t xdr_readdirargs ();
-extern bool_t xdr_entry ();
-extern bool_t xdr_dirlist ();
-extern bool_t xdr_readdirres ();
-extern bool_t xdr_statfsokres ();
-extern bool_t xdr_statfsres ();
-
-#endif /* K&R C */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !_NFS_PROT_H_RPCGEN */
diff --git a/rtemsNfs/proto/nfs_prot.x b/rtemsNfs/proto/nfs_prot.x
deleted file mode 100644
index a40d9a5..0000000
--- a/rtemsNfs/proto/nfs_prot.x
+++ /dev/null
@@ -1,1268 +0,0 @@
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-
-#ifndef RPC_HDR
-%#ifndef lint
-%/*static char sccsid[] = "from: @(#)nfs_prot.x 1.2 87/10/12 Copyr 1987 Sun Micro";*/
-%/*static char sccsid[] = "from: @(#)nfs_prot.x 2.1 88/08/01 4.0 RPCSRC";*/
-%static char rcsid[] = "$Id$";
-%#endif /* not lint */
-#endif
-
-const NFS_PORT = 2049;
-const NFS_MAXDATA = 8192;
-const NFS_MAXPATHLEN = 1024;
-const NFS_MAXNAMLEN = 255;
-const NFS_FHSIZE = 32;
-const NFS_COOKIESIZE = 4;
-const NFS_FIFO_DEV = -1; /* size kludge for named pipes */
-
-/*
- * File types
- */
-const NFSMODE_FMT = 0170000; /* type of file */
-const NFSMODE_DIR = 0040000; /* directory */
-const NFSMODE_CHR = 0020000; /* character special */
-const NFSMODE_BLK = 0060000; /* block special */
-const NFSMODE_REG = 0100000; /* regular */
-const NFSMODE_LNK = 0120000; /* symbolic link */
-const NFSMODE_SOCK = 0140000; /* socket */
-const NFSMODE_FIFO = 0010000; /* fifo */
-
-/*
- * Error status
- */
-enum nfsstat {
- NFS_OK= 0, /* no error */
- NFSERR_PERM=1, /* Not owner */
- NFSERR_NOENT=2, /* No such file or directory */
- NFSERR_IO=5, /* I/O error */
- NFSERR_NXIO=6, /* No such device or address */
- NFSERR_ACCES=13, /* Permission denied */
- NFSERR_EXIST=17, /* File exists */
- NFSERR_NODEV=19, /* No such device */
- NFSERR_NOTDIR=20, /* Not a directory*/
- NFSERR_ISDIR=21, /* Is a directory */
- NFSERR_FBIG=27, /* File too large */
- NFSERR_NOSPC=28, /* No space left on device */
- NFSERR_ROFS=30, /* Read-only file system */
- NFSERR_NAMETOOLONG=63, /* File name too long */
- NFSERR_NOTEMPTY=66, /* Directory not empty */
- NFSERR_DQUOT=69, /* Disc quota exceeded */
- NFSERR_STALE=70, /* Stale NFS file handle */
- NFSERR_WFLUSH=99 /* write cache flushed */
-};
-
-/*
- * File types
- */
-enum ftype {
- NFNON = 0, /* non-file */
- NFREG = 1, /* regular file */
- NFDIR = 2, /* directory */
- NFBLK = 3, /* block special */
- NFCHR = 4, /* character special */
- NFLNK = 5, /* symbolic link */
- NFSOCK = 6, /* unix domain sockets */
- NFBAD = 7, /* unused */
- NFFIFO = 8 /* named pipe */
-};
-
-/*
- * File access handle
- */
-struct nfs_fh {
- opaque data[NFS_FHSIZE];
-};
-
-/*
- * Timeval
- */
-struct nfstime {
- unsigned seconds;
- unsigned useconds;
-};
-
-
-/*
- * File attributes
- */
-struct fattr {
- ftype type; /* file type */
- unsigned mode; /* protection mode bits */
- unsigned nlink; /* # hard links */
- unsigned uid; /* owner user id */
- unsigned gid; /* owner group id */
- unsigned size; /* file size in bytes */
- unsigned blocksize; /* prefered block size */
- unsigned rdev; /* special device # */
- unsigned blocks; /* Kb of disk used by file */
- unsigned fsid; /* device # */
- unsigned fileid; /* inode # */
- nfstime atime; /* time of last access */
- nfstime mtime; /* time of last modification */
- nfstime ctime; /* time of last change */
-};
-
-/*
- * File attributes which can be set
- */
-struct sattr {
- unsigned mode; /* protection mode bits */
- unsigned uid; /* owner user id */
- unsigned gid; /* owner group id */
- unsigned size; /* file size in bytes */
- nfstime atime; /* time of last access */
- nfstime mtime; /* time of last modification */
-};
-
-
-typedef string filename<NFS_MAXNAMLEN>;
-typedef string nfspath<NFS_MAXPATHLEN>;
-
-/*
- * Reply status with file attributes
- */
-union attrstat switch (nfsstat status) {
-case NFS_OK:
- fattr attributes;
-default:
- void;
-};
-
-struct sattrargs {
- nfs_fh file;
- sattr attributes;
-};
-
-/*
- * Arguments for directory operations
- */
-struct diropargs {
- nfs_fh dir; /* directory file handle */
- filename name; /* name (up to NFS_MAXNAMLEN bytes) */
-};
-
-struct diropokres {
- nfs_fh file;
- fattr attributes;
-};
-
-/*
- * Results from directory operation
- */
-union diropres switch (nfsstat status) {
-case NFS_OK:
- diropokres diropres;
-default:
- void;
-};
-
-union readlinkres switch (nfsstat status) {
-case NFS_OK:
- nfspath data;
-default:
- void;
-};
-
-/*
- * Arguments to remote read
- */
-struct readargs {
- nfs_fh file; /* handle for file */
- unsigned offset; /* byte offset in file */
- unsigned count; /* immediate read count */
- unsigned totalcount; /* total read count (from this offset)*/
-};
-
-/*
- * Status OK portion of remote read reply
- */
-struct readokres {
- fattr attributes; /* attributes, need for pagin*/
- opaque data<NFS_MAXDATA>;
-};
-
-union readres switch (nfsstat status) {
-case NFS_OK:
- readokres reply;
-default:
- void;
-};
-
-/*
- * Arguments to remote write
- */
-struct writeargs {
- nfs_fh file; /* handle for file */
- unsigned beginoffset; /* beginning byte offset in file */
- unsigned offset; /* current byte offset in file */
- unsigned totalcount; /* total write count (to this offset)*/
- opaque data<NFS_MAXDATA>;
-};
-
-struct createargs {
- diropargs where;
- sattr attributes;
-};
-
-struct renameargs {
- diropargs from;
- diropargs to;
-};
-
-struct linkargs {
- nfs_fh from;
- diropargs to;
-};
-
-struct symlinkargs {
- diropargs from;
- nfspath to;
- sattr attributes;
-};
-
-
-/* TS, 10/21/2002; converted cookie to struct */
-struct nfscookie {
- opaque data[NFS_COOKIESIZE];
-};
-
-/*
- * Arguments to readdir
- */
-struct readdirargs {
- nfs_fh dir; /* directory handle */
- nfscookie cookie;
- unsigned count; /* number of directory bytes to read */
-};
-
-struct entry {
- unsigned fileid;
- filename name;
- nfscookie cookie;
- entry *nextentry;
-};
-
-struct dirlist {
- entry *entries;
- bool eof;
-};
-
-union readdirres switch (nfsstat status) {
-case NFS_OK:
- dirlist reply;
-default:
- void;
-};
-
-struct statfsokres {
- unsigned tsize; /* preferred transfer size in bytes */
- unsigned bsize; /* fundamental file system block size */
- unsigned blocks; /* total blocks in file system */
- unsigned bfree; /* free blocks in fs */
- unsigned bavail; /* free blocks avail to non-superuser */
-};
-
-union statfsres switch (nfsstat status) {
-case NFS_OK:
- statfsokres reply;
-default:
- void;
-};
-
-#ifdef WANT_NFS3
-
-/*
- * NFSv3 constants and types
- */
-const NFS3_FHSIZE = 64; /* maximum size in bytes of a file handle */
-const NFS3_COOKIEVERFSIZE = 8; /* size of a cookie verifier for READDIR */
-const NFS3_CREATEVERFSIZE = 8; /* size of the verifier used for CREATE */
-const NFS3_WRITEVERFSIZE = 8; /* size of the verifier used for WRITE */
-
-typedef unsigned hyper uint64;
-typedef hyper int64;
-typedef unsigned long uint32;
-typedef long int32;
-typedef string filename3<>;
-typedef string nfspath3<>;
-typedef uint64 fileid3;
-typedef uint64 cookie3;
-typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE];
-typedef opaque createverf3[NFS3_CREATEVERFSIZE];
-typedef opaque writeverf3[NFS3_WRITEVERFSIZE];
-typedef uint32 uid3;
-typedef uint32 gid3;
-typedef uint64 size3;
-typedef uint64 offset3;
-typedef uint32 mode3;
-typedef uint32 count3;
-
-/*
- * Error status (v3)
- */
-enum nfsstat3 {
- NFS3_OK = 0,
- NFS3ERR_PERM = 1,
- NFS3ERR_NOENT = 2,
- NFS3ERR_IO = 5,
- NFS3ERR_NXIO = 6,
- NFS3ERR_ACCES = 13,
- NFS3ERR_EXIST = 17,
- NFS3ERR_XDEV = 18,
- NFS3ERR_NODEV = 19,
- NFS3ERR_NOTDIR = 20,
- NFS3ERR_ISDIR = 21,
- NFS3ERR_INVAL = 22,
- NFS3ERR_FBIG = 27,
- NFS3ERR_NOSPC = 28,
- NFS3ERR_ROFS = 30,
- NFS3ERR_MLINK = 31,
- NFS3ERR_NAMETOOLONG = 63,
- NFS3ERR_NOTEMPTY = 66,
- NFS3ERR_DQUOT = 69,
- NFS3ERR_STALE = 70,
- NFS3ERR_REMOTE = 71,
- NFS3ERR_BADHANDLE = 10001,
- NFS3ERR_NOT_SYNC = 10002,
- NFS3ERR_BAD_COOKIE = 10003,
- NFS3ERR_NOTSUPP = 10004,
- NFS3ERR_TOOSMALL = 10005,
- NFS3ERR_SERVERFAULT = 10006,
- NFS3ERR_BADTYPE = 10007,
- NFS3ERR_JUKEBOX = 10008
-};
-
-/*
- * File types (v3)
- */
-enum ftype3 {
- NF3REG = 1, /* regular file */
- NF3DIR = 2, /* directory */
- NF3BLK = 3, /* block special */
- NF3CHR = 4, /* character special */
- NF3LNK = 5, /* symbolic link */
- NF3SOCK = 6, /* unix domain sockets */
- NF3FIFO = 7 /* named pipe */
-};
-
-struct specdata3 {
- uint32 specdata1;
- uint32 specdata2;
-};
-
-/*
- * File access handle (v3)
- */
-struct nfs_fh3 {
- opaque data<NFS3_FHSIZE>;
-};
-
-/*
- * Timeval (v3)
- */
-struct nfstime3 {
- uint32 seconds;
- uint32 nseconds;
-};
-
-
-/*
- * File attributes (v3)
- */
-struct fattr3 {
- ftype3 type; /* file type */
- mode3 mode; /* protection mode bits */
- uint32 nlink; /* # hard links */
- uid3 uid; /* owner user id */
- gid3 gid; /* owner group id */
- size3 size; /* file size in bytes */
- size3 used; /* prefered block size */
- specdata3 rdev; /* special device # */
- uint64 fsid; /* device # */
- fileid3 fileid; /* inode # */
- nfstime3 atime; /* time of last access */
- nfstime3 mtime; /* time of last modification */
- nfstime3 ctime; /* time of last change */
-};
-
-union post_op_attr switch (bool attributes_follow) {
-case TRUE:
- fattr3 attributes;
-case FALSE:
- void;
-};
-
-struct wcc_attr {
- size3 size;
- nfstime3 mtime;
- nfstime3 ctime;
-};
-
-union pre_op_attr switch (bool attributes_follow) {
-case TRUE:
- wcc_attr attributes;
-case FALSE:
- void;
-};
-
-struct wcc_data {
- pre_op_attr before;
- post_op_attr after;
-};
-
-union post_op_fh3 switch (bool handle_follows) {
-case TRUE:
- nfs_fh3 handle;
-case FALSE:
- void;
-};
-
-/*
- * File attributes which can be set (v3)
- */
-enum time_how {
- DONT_CHANGE = 0,
- SET_TO_SERVER_TIME = 1,
- SET_TO_CLIENT_TIME = 2
-};
-
-union set_mode3 switch (bool set_it) {
-case TRUE:
- mode3 mode;
-default:
- void;
-};
-
-union set_uid3 switch (bool set_it) {
-case TRUE:
- uid3 uid;
-default:
- void;
-};
-
-union set_gid3 switch (bool set_it) {
-case TRUE:
- gid3 gid;
-default:
- void;
-};
-
-union set_size3 switch (bool set_it) {
-case TRUE:
- size3 size;
-default:
- void;
-};
-
-union set_atime switch (time_how set_it) {
-case SET_TO_CLIENT_TIME:
- nfstime3 atime;
-default:
- void;
-};
-
-union set_mtime switch (time_how set_it) {
-case SET_TO_CLIENT_TIME:
- nfstime3 mtime;
-default:
- void;
-};
-
-struct sattr3 {
- set_mode3 mode;
- set_uid3 uid;
- set_gid3 gid;
- set_size3 size;
- set_atime atime;
- set_mtime mtime;
-};
-
-/*
- * Arguments for directory operations (v3)
- */
-struct diropargs3 {
- nfs_fh3 dir; /* directory file handle */
- filename3 name; /* name (up to NFS_MAXNAMLEN bytes) */
-};
-
-/*
- * Arguments to getattr (v3).
- */
-struct GETATTR3args {
- nfs_fh3 object;
-};
-
-struct GETATTR3resok {
- fattr3 obj_attributes;
-};
-
-union GETATTR3res switch (nfsstat3 status) {
-case NFS3_OK:
- GETATTR3resok resok;
-default:
- void;
-};
-
-/*
- * Arguments to setattr (v3).
- */
-union sattrguard3 switch (bool check) {
-case TRUE:
- nfstime3 obj_ctime;
-case FALSE:
- void;
-};
-
-struct SETATTR3args {
- nfs_fh3 object;
- sattr3 new_attributes;
- sattrguard3 guard;
-};
-
-struct SETATTR3resok {
- wcc_data obj_wcc;
-};
-
-struct SETATTR3resfail {
- wcc_data obj_wcc;
-};
-
-union SETATTR3res switch (nfsstat3 status) {
-case NFS3_OK:
- SETATTR3resok resok;
-default:
- SETATTR3resfail resfail;
-};
-
-/*
- * Arguments to lookup (v3).
- */
-struct LOOKUP3args {
- diropargs3 what;
-};
-
-struct LOOKUP3resok {
- nfs_fh3 object;
- post_op_attr obj_attributes;
- post_op_attr dir_attributes;
-};
-
-struct LOOKUP3resfail {
- post_op_attr dir_attributes;
-};
-
-union LOOKUP3res switch (nfsstat3 status) {
-case NFS3_OK:
- LOOKUP3resok resok;
-default:
- LOOKUP3resfail resfail;
-};
-
-/*
- * Arguments to access (v3).
- */
-const ACCESS3_READ = 0x0001;
-const ACCESS3_LOOKUP = 0x0002;
-const ACCESS3_MODIFY = 0x0004;
-const ACCESS3_EXTEND = 0x0008;
-const ACCESS3_DELETE = 0x0010;
-const ACCESS3_EXECUTE = 0x0020;
-
-struct ACCESS3args {
- nfs_fh3 object;
- uint32 access;
-};
-
-struct ACCESS3resok {
- post_op_attr obj_attributes;
- uint32 access;
-};
-
-struct ACCESS3resfail {
- post_op_attr obj_attributes;
-};
-
-union ACCESS3res switch (nfsstat3 status) {
-case NFS3_OK:
- ACCESS3resok resok;
-default:
- ACCESS3resfail resfail;
-};
-
-/*
- * Arguments to readlink (v3).
- */
-struct READLINK3args {
- nfs_fh3 symlink;
-};
-
-struct READLINK3resok {
- post_op_attr symlink_attributes;
- nfspath3 data;
-};
-
-struct READLINK3resfail {
- post_op_attr symlink_attributes;
-};
-
-union READLINK3res switch (nfsstat3 status) {
-case NFS3_OK:
- READLINK3resok resok;
-default:
- READLINK3resfail resfail;
-};
-
-/*
- * Arguments to read (v3).
- */
-struct READ3args {
- nfs_fh3 file;
- offset3 offset;
- count3 count;
-};
-
-struct READ3resok {
- post_op_attr file_attributes;
- count3 count;
- bool eof;
- opaque data<>;
-};
-
-struct READ3resfail {
- post_op_attr file_attributes;
-};
-
-/* XXX: solaris 2.6 uses ``nfsstat'' here */
-union READ3res switch (nfsstat3 status) {
-case NFS3_OK:
- READ3resok resok;
-default:
- READ3resfail resfail;
-};
-
-/*
- * Arguments to write (v3).
- */
-enum stable_how {
- UNSTABLE = 0,
- DATA_SYNC = 1,
- FILE_SYNC = 2
-};
-
-struct WRITE3args {
- nfs_fh3 file;
- offset3 offset;
- count3 count;
- stable_how stable;
- opaque data<>;
-};
-
-struct WRITE3resok {
- wcc_data file_wcc;
- count3 count;
- stable_how committed;
- writeverf3 verf;
-};
-
-struct WRITE3resfail {
- wcc_data file_wcc;
-};
-
-union WRITE3res switch (nfsstat3 status) {
-case NFS3_OK:
- WRITE3resok resok;
-default:
- WRITE3resfail resfail;
-};
-
-/*
- * Arguments to create (v3).
- */
-enum createmode3 {
- UNCHECKED = 0,
- GUARDED = 1,
- EXCLUSIVE = 2
-};
-
-union createhow3 switch (createmode3 mode) {
-case UNCHECKED:
-case GUARDED:
- sattr3 obj_attributes;
-case EXCLUSIVE:
- createverf3 verf;
-};
-
-struct CREATE3args {
- diropargs3 where;
- createhow3 how;
-};
-
-struct CREATE3resok {
- post_op_fh3 obj;
- post_op_attr obj_attributes;
- wcc_data dir_wcc;
-};
-
-struct CREATE3resfail {
- wcc_data dir_wcc;
-};
-
-union CREATE3res switch (nfsstat3 status) {
-case NFS3_OK:
- CREATE3resok resok;
-default:
- CREATE3resfail resfail;
-};
-
-/*
- * Arguments to mkdir (v3).
- */
-struct MKDIR3args {
- diropargs3 where;
- sattr3 attributes;
-};
-
-struct MKDIR3resok {
- post_op_fh3 obj;
- post_op_attr obj_attributes;
- wcc_data dir_wcc;
-};
-
-struct MKDIR3resfail {
- wcc_data dir_wcc;
-};
-
-union MKDIR3res switch (nfsstat3 status) {
-case NFS3_OK:
- MKDIR3resok resok;
-default:
- MKDIR3resfail resfail;
-};
-
-/*
- * Arguments to symlink (v3).
- */
-struct symlinkdata3 {
- sattr3 symlink_attributes;
- nfspath3 symlink_data;
-};
-
-struct SYMLINK3args {
- diropargs3 where;
- symlinkdata3 symlink;
-};
-
-struct SYMLINK3resok {
- post_op_fh3 obj;
- post_op_attr obj_attributes;
- wcc_data dir_wcc;
-};
-
-struct SYMLINK3resfail {
- wcc_data dir_wcc;
-};
-
-union SYMLINK3res switch (nfsstat3 status) {
-case NFS3_OK:
- SYMLINK3resok resok;
-default:
- SYMLINK3resfail resfail;
-};
-
-/*
- * Arguments to mknod (v3).
- */
-struct devicedata3 {
- sattr3 dev_attributes;
- specdata3 spec;
-};
-
-union mknoddata3 switch (ftype3 type) {
-case NF3CHR:
-case NF3BLK:
- devicedata3 device;
-case NF3SOCK:
-case NF3FIFO:
- sattr3 pipe_attributes;
-default:
- void;
-};
-
-struct MKNOD3args {
- diropargs3 where;
- mknoddata3 what;
-};
-
-struct MKNOD3resok {
- post_op_fh3 obj;
- post_op_attr obj_attributes;
- wcc_data dir_wcc;
-};
-
-struct MKNOD3resfail {
- wcc_data dir_wcc;
-};
-
-union MKNOD3res switch (nfsstat3 status) {
-case NFS3_OK:
- MKNOD3resok resok;
-default:
- MKNOD3resfail resfail;
-};
-
-/*
- * Arguments to remove (v3).
- */
-struct REMOVE3args {
- diropargs3 object;
-};
-
-struct REMOVE3resok {
- wcc_data dir_wcc;
-};
-
-struct REMOVE3resfail {
- wcc_data dir_wcc;
-};
-
-union REMOVE3res switch (nfsstat3 status) {
-case NFS3_OK:
- REMOVE3resok resok;
-default:
- REMOVE3resfail resfail;
-};
-
-/*
- * Arguments to rmdir (v3).
- */
-struct RMDIR3args {
- diropargs3 object;
-};
-
-struct RMDIR3resok {
- wcc_data dir_wcc;
-};
-
-struct RMDIR3resfail {
- wcc_data dir_wcc;
-};
-
-union RMDIR3res switch (nfsstat3 status) {
-case NFS3_OK:
- RMDIR3resok resok;
-default:
- RMDIR3resfail resfail;
-};
-
-/*
- * Arguments to rename (v3).
- */
-struct RENAME3args {
- diropargs3 from;
- diropargs3 to;
-};
-
-struct RENAME3resok {
- wcc_data fromdir_wcc;
- wcc_data todir_wcc;
-};
-
-struct RENAME3resfail {
- wcc_data fromdir_wcc;
- wcc_data todir_wcc;
-};
-
-union RENAME3res switch (nfsstat3 status) {
-case NFS3_OK:
- RENAME3resok resok;
-default:
- RENAME3resfail resfail;
-};
-
-/*
- * Arguments to link (v3).
- */
-struct LINK3args {
- nfs_fh3 file;
- diropargs3 link;
-};
-
-struct LINK3resok {
- post_op_attr file_attributes;
- wcc_data linkdir_wcc;
-};
-
-struct LINK3resfail {
- post_op_attr file_attributes;
- wcc_data linkdir_wcc;
-};
-
-union LINK3res switch (nfsstat3 status) {
-case NFS3_OK:
- LINK3resok resok;
-default:
- LINK3resfail resfail;
-};
-
-/*
- * Arguments to readdir (v3).
- */
-struct READDIR3args {
- nfs_fh3 dir;
- cookie3 cookie;
- cookieverf3 cookieverf;
- count3 count;
-};
-
-struct entry3 {
- fileid3 fileid;
- filename3 name;
- cookie3 cookie;
- entry3 *nextentry;
-};
-
-struct dirlist3 {
- entry3 *entries;
- bool eof;
-};
-
-struct READDIR3resok {
- post_op_attr dir_attributes;
- cookieverf3 cookieverf;
- dirlist3 reply;
-};
-
-struct READDIR3resfail {
- post_op_attr dir_attributes;
-};
-
-union READDIR3res switch (nfsstat3 status) {
-case NFS3_OK:
- READDIR3resok resok;
-default:
- READDIR3resfail resfail;
-};
-
-/*
- * Arguments to readdirplus (v3).
- */
-struct READDIRPLUS3args {
- nfs_fh3 dir;
- cookie3 cookie;
- cookieverf3 cookieverf;
- count3 dircount;
- count3 maxcount;
-};
-
-struct entryplus3 {
- fileid3 fileid;
- filename3 name;
- cookie3 cookie;
- post_op_attr name_attributes;
- post_op_fh3 name_handle;
- entryplus3 *nextentry;
-};
-
-struct dirlistplus3 {
- entryplus3 *entries;
- bool eof;
-};
-
-struct READDIRPLUS3resok {
- post_op_attr dir_attributes;
- cookieverf3 cookieverf;
- dirlistplus3 reply;
-};
-
-struct READDIRPLUS3resfail {
- post_op_attr dir_attributes;
-};
-
-union READDIRPLUS3res switch (nfsstat3 status) {
-case NFS3_OK:
- READDIRPLUS3resok resok;
-default:
- READDIRPLUS3resfail resfail;
-};
-
-/*
- * Arguments to fsstat (v3).
- */
-struct FSSTAT3args {
- nfs_fh3 fsroot;
-};
-
-struct FSSTAT3resok {
- post_op_attr obj_attributes;
- size3 tbytes;
- size3 fbytes;
- size3 abytes;
- size3 tfiles;
- size3 ffiles;
- size3 afiles;
- uint32 invarsec;
-};
-
-struct FSSTAT3resfail {
- post_op_attr obj_attributes;
-};
-
-union FSSTAT3res switch (nfsstat3 status) {
-case NFS3_OK:
- FSSTAT3resok resok;
-default:
- FSSTAT3resfail resfail;
-};
-
-/*
- * Arguments to fsinfo (v3).
- */
-const FSF3_LINK = 0x0001;
-const FSF3_SYMLINK = 0x0002;
-const FSF3_HOMOGENEOUS = 0x0008;
-const FSF3_CANSETTIME = 0x0010;
-
-struct FSINFO3args {
- nfs_fh3 fsroot;
-};
-
-struct FSINFO3resok {
- post_op_attr obj_attributes;
- uint32 rtmax;
- uint32 rtpref;
- uint32 rtmult;
- uint32 wtmax;
- uint32 wtpref;
- uint32 wtmult;
- uint32 dtpref;
- size3 maxfilesize;
- nfstime3 time_delta;
- uint32 properties;
-};
-
-struct FSINFO3resfail {
- post_op_attr obj_attributes;
-};
-
-union FSINFO3res switch (nfsstat3 status) {
-case NFS3_OK:
- FSINFO3resok resok;
-default:
- FSINFO3resfail resfail;
-};
-
-/*
- * Arguments to pathconf (v3).
- */
-struct PATHCONF3args {
- nfs_fh3 object;
-};
-
-struct PATHCONF3resok {
- post_op_attr obj_attributes;
- uint32 linkmax;
- uint32 name_max;
- bool no_trunc;
- bool chown_restricted;
- bool case_insensitive;
- bool case_preserving;
-};
-
-struct PATHCONF3resfail {
- post_op_attr obj_attributes;
-};
-
-union PATHCONF3res switch (nfsstat3 status) {
-case NFS3_OK:
- PATHCONF3resok resok;
-default:
- PATHCONF3resfail resfail;
-};
-
-/*
- * Arguments to commit (v3).
- */
-struct COMMIT3args {
- nfs_fh3 file;
- offset3 offset;
- count3 count;
-};
-
-struct COMMIT3resok {
- wcc_data file_wcc;
- writeverf3 verf;
-};
-
-struct COMMIT3resfail {
- wcc_data file_wcc;
-};
-
-union COMMIT3res switch (nfsstat3 status) {
-case NFS3_OK:
- COMMIT3resok resok;
-default:
- COMMIT3resfail resfail;
-};
-
-#endif /* WANT_NFS3 */
-
-/*
- * Remote file service routines
- */
-program NFS_PROGRAM {
- version NFS_VERSION {
- void
- NFSPROC_NULL(void) = 0;
-
- attrstat
- NFSPROC_GETATTR(nfs_fh) = 1;
-
- attrstat
- NFSPROC_SETATTR(sattrargs) = 2;
-
- void
- NFSPROC_ROOT(void) = 3;
-
- diropres
- NFSPROC_LOOKUP(diropargs) = 4;
-
- readlinkres
- NFSPROC_READLINK(nfs_fh) = 5;
-
- readres
- NFSPROC_READ(readargs) = 6;
-
- void
- NFSPROC_WRITECACHE(void) = 7;
-
- attrstat
- NFSPROC_WRITE(writeargs) = 8;
-
- diropres
- NFSPROC_CREATE(createargs) = 9;
-
- nfsstat
- NFSPROC_REMOVE(diropargs) = 10;
-
- nfsstat
- NFSPROC_RENAME(renameargs) = 11;
-
- nfsstat
- NFSPROC_LINK(linkargs) = 12;
-
- nfsstat
- NFSPROC_SYMLINK(symlinkargs) = 13;
-
- diropres
- NFSPROC_MKDIR(createargs) = 14;
-
- nfsstat
- NFSPROC_RMDIR(diropargs) = 15;
-
- readdirres
- NFSPROC_READDIR(readdirargs) = 16;
-
- statfsres
- NFSPROC_STATFS(nfs_fh) = 17;
- } = 2;
-} = 100003;
-#ifdef WANT_NFS3
-program NFS3_PROGRAM {
- version NFS_V3 {
- void
- NFSPROC3_NULL(void) = 0;
-
- GETATTR3res
- NFSPROC3_GETATTR(GETATTR3args) = 1;
-
- SETATTR3res
- NFSPROC3_SETATTR(SETATTR3args) = 2;
-
- LOOKUP3res
- NFSPROC3_LOOKUP(LOOKUP3args) = 3;
-
- ACCESS3res
- NFSPROC3_ACCESS(ACCESS3args) = 4;
-
- READLINK3res
- NFSPROC3_READLINK(READLINK3args) = 5;
-
- READ3res
- NFSPROC3_READ(READ3args) = 6;
-
- WRITE3res
- NFSPROC3_WRITE(WRITE3args) = 7;
-
- CREATE3res
- NFSPROC3_CREATE(CREATE3args) = 8;
-
- MKDIR3res
- NFSPROC3_MKDIR(MKDIR3args) = 9;
-
- SYMLINK3res
- NFSPROC3_SYMLINK(SYMLINK3args) = 10;
-
- MKNOD3res
- NFSPROC3_MKNOD(MKNOD3args) = 11;
-
- REMOVE3res
- NFSPROC3_REMOVE(REMOVE3args) = 12;
-
- RMDIR3res
- NFSPROC3_RMDIR(RMDIR3args) = 13;
-
- RENAME3res
- NFSPROC3_RENAME(RENAME3args) = 14;
-
- LINK3res
- NFSPROC3_LINK(LINK3args) = 15;
-
- READDIR3res
- NFSPROC3_READDIR(READDIR3args) = 16;
-
- READDIRPLUS3res
- NFSPROC3_READDIRPLUS(READDIRPLUS3args) = 17;
-
- FSSTAT3res
- NFSPROC3_FSSTAT(FSSTAT3args) = 18;
-
- FSINFO3res
- NFSPROC3_FSINFO(FSINFO3args) = 19;
-
- PATHCONF3res
- NFSPROC3_PATHCONF(PATHCONF3args) = 20;
-
- COMMIT3res
- NFSPROC3_COMMIT(COMMIT3args) = 21;
- } = 3;
-} = 100003;
-#endif
-
diff --git a/rtemsNfs/proto/nfs_prot_xdr.c b/rtemsNfs/proto/nfs_prot_xdr.c
deleted file mode 100644
index 7e222ec..0000000
--- a/rtemsNfs/proto/nfs_prot_xdr.c
+++ /dev/null
@@ -1,671 +0,0 @@
-/*
- * Please do not edit this file.
- * It was generated using rpcgen.
- */
-
-#include "nfs_prot.h"
-#ifndef lint
-/*static char sccsid[] = "from: @(#)nfs_prot.x 1.2 87/10/12 Copyr 1987 Sun Micro";*/
-/*static char sccsid[] = "from: @(#)nfs_prot.x 2.1 88/08/01 4.0 RPCSRC";*/
-static char rcsid[] = "$Id$";
-#endif /* not lint */
-
-bool_t
-xdr_nfsstat (XDR *xdrs, nfsstat *objp)
-{
- register int32_t *buf;
-
- if (!xdr_enum (xdrs, (enum_t *) objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_ftype (XDR *xdrs, ftype *objp)
-{
- register int32_t *buf;
-
- if (!xdr_enum (xdrs, (enum_t *) objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_nfs_fh (XDR *xdrs, nfs_fh *objp)
-{
- register int32_t *buf;
-
- int i;
- if (!xdr_opaque (xdrs, objp->data, NFS_FHSIZE))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_nfstime (XDR *xdrs, nfstime *objp)
-{
- register int32_t *buf;
-
- if (!xdr_u_int (xdrs, &objp->seconds))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->useconds))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_fattr (XDR *xdrs, fattr *objp)
-{
- register int32_t *buf;
-
-
- if (xdrs->x_op == XDR_ENCODE) {
- if (!xdr_ftype (xdrs, &objp->type))
- return FALSE;
- buf = XDR_INLINE (xdrs, 10 * BYTES_PER_XDR_UNIT);
- if (buf == NULL) {
- if (!xdr_u_int (xdrs, &objp->mode))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->nlink))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->uid))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->gid))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->size))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->blocksize))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->rdev))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->blocks))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->fsid))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->fileid))
- return FALSE;
-
- } else {
- IXDR_PUT_U_LONG(buf, objp->mode);
- IXDR_PUT_U_LONG(buf, objp->nlink);
- IXDR_PUT_U_LONG(buf, objp->uid);
- IXDR_PUT_U_LONG(buf, objp->gid);
- IXDR_PUT_U_LONG(buf, objp->size);
- IXDR_PUT_U_LONG(buf, objp->blocksize);
- IXDR_PUT_U_LONG(buf, objp->rdev);
- IXDR_PUT_U_LONG(buf, objp->blocks);
- IXDR_PUT_U_LONG(buf, objp->fsid);
- IXDR_PUT_U_LONG(buf, objp->fileid);
- }
- if (!xdr_nfstime (xdrs, &objp->atime))
- return FALSE;
- if (!xdr_nfstime (xdrs, &objp->mtime))
- return FALSE;
- if (!xdr_nfstime (xdrs, &objp->ctime))
- return FALSE;
- return TRUE;
- } else if (xdrs->x_op == XDR_DECODE) {
- if (!xdr_ftype (xdrs, &objp->type))
- return FALSE;
- buf = XDR_INLINE (xdrs, 10 * BYTES_PER_XDR_UNIT);
- if (buf == NULL) {
- if (!xdr_u_int (xdrs, &objp->mode))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->nlink))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->uid))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->gid))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->size))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->blocksize))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->rdev))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->blocks))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->fsid))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->fileid))
- return FALSE;
-
- } else {
- objp->mode = IXDR_GET_U_LONG(buf);
- objp->nlink = IXDR_GET_U_LONG(buf);
- objp->uid = IXDR_GET_U_LONG(buf);
- objp->gid = IXDR_GET_U_LONG(buf);
- objp->size = IXDR_GET_U_LONG(buf);
- objp->blocksize = IXDR_GET_U_LONG(buf);
- objp->rdev = IXDR_GET_U_LONG(buf);
- objp->blocks = IXDR_GET_U_LONG(buf);
- objp->fsid = IXDR_GET_U_LONG(buf);
- objp->fileid = IXDR_GET_U_LONG(buf);
- }
- if (!xdr_nfstime (xdrs, &objp->atime))
- return FALSE;
- if (!xdr_nfstime (xdrs, &objp->mtime))
- return FALSE;
- if (!xdr_nfstime (xdrs, &objp->ctime))
- return FALSE;
- return TRUE;
- }
-
- if (!xdr_ftype (xdrs, &objp->type))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->mode))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->nlink))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->uid))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->gid))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->size))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->blocksize))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->rdev))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->blocks))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->fsid))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->fileid))
- return FALSE;
- if (!xdr_nfstime (xdrs, &objp->atime))
- return FALSE;
- if (!xdr_nfstime (xdrs, &objp->mtime))
- return FALSE;
- if (!xdr_nfstime (xdrs, &objp->ctime))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_sattr (XDR *xdrs, sattr *objp)
-{
- register int32_t *buf;
-
-
- if (xdrs->x_op == XDR_ENCODE) {
- buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT);
- if (buf == NULL) {
- if (!xdr_u_int (xdrs, &objp->mode))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->uid))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->gid))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->size))
- return FALSE;
-
- } else {
- IXDR_PUT_U_LONG(buf, objp->mode);
- IXDR_PUT_U_LONG(buf, objp->uid);
- IXDR_PUT_U_LONG(buf, objp->gid);
- IXDR_PUT_U_LONG(buf, objp->size);
- }
- if (!xdr_nfstime (xdrs, &objp->atime))
- return FALSE;
- if (!xdr_nfstime (xdrs, &objp->mtime))
- return FALSE;
- return TRUE;
- } else if (xdrs->x_op == XDR_DECODE) {
- buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT);
- if (buf == NULL) {
- if (!xdr_u_int (xdrs, &objp->mode))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->uid))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->gid))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->size))
- return FALSE;
-
- } else {
- objp->mode = IXDR_GET_U_LONG(buf);
- objp->uid = IXDR_GET_U_LONG(buf);
- objp->gid = IXDR_GET_U_LONG(buf);
- objp->size = IXDR_GET_U_LONG(buf);
- }
- if (!xdr_nfstime (xdrs, &objp->atime))
- return FALSE;
- if (!xdr_nfstime (xdrs, &objp->mtime))
- return FALSE;
- return TRUE;
- }
-
- if (!xdr_u_int (xdrs, &objp->mode))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->uid))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->gid))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->size))
- return FALSE;
- if (!xdr_nfstime (xdrs, &objp->atime))
- return FALSE;
- if (!xdr_nfstime (xdrs, &objp->mtime))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_filename (XDR *xdrs, filename *objp)
-{
- register int32_t *buf;
-
- if (!xdr_string (xdrs, objp, NFS_MAXNAMLEN))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_nfspath (XDR *xdrs, nfspath *objp)
-{
- register int32_t *buf;
-
- if (!xdr_string (xdrs, objp, NFS_MAXPATHLEN))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_attrstat (XDR *xdrs, attrstat *objp)
-{
- register int32_t *buf;
-
- if (!xdr_nfsstat (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS_OK:
- if (!xdr_fattr (xdrs, &objp->attrstat_u.attributes))
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_sattrargs (XDR *xdrs, sattrargs *objp)
-{
- register int32_t *buf;
-
- if (!xdr_nfs_fh (xdrs, &objp->file))
- return FALSE;
- if (!xdr_sattr (xdrs, &objp->attributes))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_diropargs (XDR *xdrs, diropargs *objp)
-{
- register int32_t *buf;
-
- if (!xdr_nfs_fh (xdrs, &objp->dir))
- return FALSE;
- if (!xdr_filename (xdrs, &objp->name))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_diropokres (XDR *xdrs, diropokres *objp)
-{
- register int32_t *buf;
-
- if (!xdr_nfs_fh (xdrs, &objp->file))
- return FALSE;
- if (!xdr_fattr (xdrs, &objp->attributes))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_diropres (XDR *xdrs, diropres *objp)
-{
- register int32_t *buf;
-
- if (!xdr_nfsstat (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS_OK:
- if (!xdr_diropokres (xdrs, &objp->diropres_u.diropres))
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_readlinkres (XDR *xdrs, readlinkres *objp)
-{
- register int32_t *buf;
-
- if (!xdr_nfsstat (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS_OK:
- if (!xdr_nfspath (xdrs, &objp->readlinkres_u.data))
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_readargs (XDR *xdrs, readargs *objp)
-{
- register int32_t *buf;
-
- if (!xdr_nfs_fh (xdrs, &objp->file))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->offset))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->count))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->totalcount))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_readokres (XDR *xdrs, readokres *objp)
-{
- register int32_t *buf;
-
- if (!xdr_fattr (xdrs, &objp->attributes))
- return FALSE;
- if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, NFS_MAXDATA))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_readres (XDR *xdrs, readres *objp)
-{
- register int32_t *buf;
-
- if (!xdr_nfsstat (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS_OK:
- if (!xdr_readokres (xdrs, &objp->readres_u.reply))
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_writeargs (XDR *xdrs, writeargs *objp)
-{
- register int32_t *buf;
-
-
- if (xdrs->x_op == XDR_ENCODE) {
- if (!xdr_nfs_fh (xdrs, &objp->file))
- return FALSE;
- buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
- if (buf == NULL) {
- if (!xdr_u_int (xdrs, &objp->beginoffset))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->offset))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->totalcount))
- return FALSE;
-
- } else {
- IXDR_PUT_U_LONG(buf, objp->beginoffset);
- IXDR_PUT_U_LONG(buf, objp->offset);
- IXDR_PUT_U_LONG(buf, objp->totalcount);
- }
- if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, NFS_MAXDATA))
- return FALSE;
- return TRUE;
- } else if (xdrs->x_op == XDR_DECODE) {
- if (!xdr_nfs_fh (xdrs, &objp->file))
- return FALSE;
- buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
- if (buf == NULL) {
- if (!xdr_u_int (xdrs, &objp->beginoffset))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->offset))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->totalcount))
- return FALSE;
-
- } else {
- objp->beginoffset = IXDR_GET_U_LONG(buf);
- objp->offset = IXDR_GET_U_LONG(buf);
- objp->totalcount = IXDR_GET_U_LONG(buf);
- }
- if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, NFS_MAXDATA))
- return FALSE;
- return TRUE;
- }
-
- if (!xdr_nfs_fh (xdrs, &objp->file))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->beginoffset))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->offset))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->totalcount))
- return FALSE;
- if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, NFS_MAXDATA))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_createargs (XDR *xdrs, createargs *objp)
-{
- register int32_t *buf;
-
- if (!xdr_diropargs (xdrs, &objp->where))
- return FALSE;
- if (!xdr_sattr (xdrs, &objp->attributes))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_renameargs (XDR *xdrs, renameargs *objp)
-{
- register int32_t *buf;
-
- if (!xdr_diropargs (xdrs, &objp->from))
- return FALSE;
- if (!xdr_diropargs (xdrs, &objp->to))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_linkargs (XDR *xdrs, linkargs *objp)
-{
- register int32_t *buf;
-
- if (!xdr_nfs_fh (xdrs, &objp->from))
- return FALSE;
- if (!xdr_diropargs (xdrs, &objp->to))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_symlinkargs (XDR *xdrs, symlinkargs *objp)
-{
- register int32_t *buf;
-
- if (!xdr_diropargs (xdrs, &objp->from))
- return FALSE;
- if (!xdr_nfspath (xdrs, &objp->to))
- return FALSE;
- if (!xdr_sattr (xdrs, &objp->attributes))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_nfscookie (XDR *xdrs, nfscookie *objp)
-{
- register int32_t *buf;
-
- int i;
- if (!xdr_opaque (xdrs, objp->data, NFS_COOKIESIZE))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_readdirargs (XDR *xdrs, readdirargs *objp)
-{
- register int32_t *buf;
-
- if (!xdr_nfs_fh (xdrs, &objp->dir))
- return FALSE;
- if (!xdr_nfscookie (xdrs, &objp->cookie))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->count))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_entry (XDR *xdrs, entry *objp)
-{
- register int32_t *buf;
-
- if (!xdr_u_int (xdrs, &objp->fileid))
- return FALSE;
- if (!xdr_filename (xdrs, &objp->name))
- return FALSE;
- if (!xdr_nfscookie (xdrs, &objp->cookie))
- return FALSE;
- if (!xdr_pointer (xdrs, (char **)&objp->nextentry, sizeof (entry), (xdrproc_t) xdr_entry))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_dirlist (XDR *xdrs, dirlist *objp)
-{
- register int32_t *buf;
-
- if (!xdr_pointer (xdrs, (char **)&objp->entries, sizeof (entry), (xdrproc_t) xdr_entry))
- return FALSE;
- if (!xdr_bool (xdrs, &objp->eof))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_readdirres (XDR *xdrs, readdirres *objp)
-{
- register int32_t *buf;
-
- if (!xdr_nfsstat (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS_OK:
- if (!xdr_dirlist (xdrs, &objp->readdirres_u.reply))
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_statfsokres (XDR *xdrs, statfsokres *objp)
-{
- register int32_t *buf;
-
-
- if (xdrs->x_op == XDR_ENCODE) {
- buf = XDR_INLINE (xdrs, 5 * BYTES_PER_XDR_UNIT);
- if (buf == NULL) {
- if (!xdr_u_int (xdrs, &objp->tsize))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->bsize))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->blocks))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->bfree))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->bavail))
- return FALSE;
- } else {
- IXDR_PUT_U_LONG(buf, objp->tsize);
- IXDR_PUT_U_LONG(buf, objp->bsize);
- IXDR_PUT_U_LONG(buf, objp->blocks);
- IXDR_PUT_U_LONG(buf, objp->bfree);
- IXDR_PUT_U_LONG(buf, objp->bavail);
- }
- return TRUE;
- } else if (xdrs->x_op == XDR_DECODE) {
- buf = XDR_INLINE (xdrs, 5 * BYTES_PER_XDR_UNIT);
- if (buf == NULL) {
- if (!xdr_u_int (xdrs, &objp->tsize))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->bsize))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->blocks))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->bfree))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->bavail))
- return FALSE;
- } else {
- objp->tsize = IXDR_GET_U_LONG(buf);
- objp->bsize = IXDR_GET_U_LONG(buf);
- objp->blocks = IXDR_GET_U_LONG(buf);
- objp->bfree = IXDR_GET_U_LONG(buf);
- objp->bavail = IXDR_GET_U_LONG(buf);
- }
- return TRUE;
- }
-
- if (!xdr_u_int (xdrs, &objp->tsize))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->bsize))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->blocks))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->bfree))
- return FALSE;
- if (!xdr_u_int (xdrs, &objp->bavail))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_statfsres (XDR *xdrs, statfsres *objp)
-{
- register int32_t *buf;
-
- if (!xdr_nfsstat (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS_OK:
- if (!xdr_statfsokres (xdrs, &objp->statfsres_u.reply))
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
diff --git a/rtemsNfs/rfc1094.txt b/rtemsNfs/rfc1094.txt
deleted file mode 100644
index 7ad0f73..0000000
--- a/rtemsNfs/rfc1094.txt
+++ /dev/null
@@ -1,1258 +0,0 @@
-
- RFC 1094 (RFC1094)
-
-Internet RFC/STD/FYI/BCP Archives
-
-
- RFC 1094 - NFS: Network File System Protocol specification
-
-------------------------------------------------------------------------
-
-
-Network Working Group Sun Microsystems, Inc.
-Request for Comments: 1094 March 1989
-
- NFS: Network File System Protocol Specification
-
-STATUS OF THIS MEMO
-
- This RFC describes a protocol that Sun Microsystems, Inc., and others
- are using. A new version of the protocol is under development, but
- others may benefit from the descriptions of the current protocol, and
- discussion of some of the design issues. Distribution of this memo
- is unlimited.
-
-1. INTRODUCTION
-
- The Sun Network Filesystem (NFS) protocol provides transparent remote
- access to shared files across networks. The NFS protocol is designed
- to be portable across different machines, operating systems, network
- architectures, and transport protocols. This portability is achieved
- through the use of Remote Procedure Call (RPC) primitives built on
- top of an eXternal Data Representation (XDR). Implementations
- already exist for a variety of machines, from personal computers to
- supercomputers.
-
- The supporting mount protocol allows the server to hand out remote
- access privileges to a restricted set of clients. It performs the
- operating system-specific functions that allow, for example, to
- attach remote directory trees to some local file system.
-
-1.1. Remote Procedure Call
-
- Sun's Remote Procedure Call specification provides a procedure-
- oriented interface to remote services. Each server supplies a
- "program" that is a set of procedures. NFS is one such program. The
- combination of host address, program number, and procedure number
- specifies one remote procedure. A goal of NFS was to not require any
- specific level of reliability from its lower levels, so it could
- potentially be used on many underlying transport protocols, or even
- another remote procedure call implementation. For ease of
- discussion, the rest of this document will assume NFS is implemented
- on top of Sun RPC, described in RFC 1057 </rfcs/rfc1057.html>, "RPC: Remote Procedure
- Call Protocol Specification".
-
-1.2. External Data Representation
-
- The eXternal Data Representation (XDR) standard provides a common way
- of representing a set of data types over a network. The NFS Protocol
-
- Specification is written using the RPC data description language.
- For more information, see RFC 1014 </rfcs/rfc1014.html>, "XDR: External Data
- Representation Standard". Although automated RPC/XDR compilers exist
- to generate server and client "stubs", NFS does not require their
- use. Any software that provides equivalent functionality can be
- used, and if the encoding is exactly the same it can interoperate
- with other implementations of NFS.
-
-1.3. Stateless Servers
-
- The NFS protocol was intended to be as stateless as possible. That
- is, a server should not need to maintain any protocol state
- information about any of its clients in order to function correctly.
- Stateless servers have a distinct advantage over stateful servers in
- the event of a failure. With stateless servers, a client need only
- retry a request until the server responds; it does not even need to
- know that the server has crashed, or the network temporarily went
- down. The client of a stateful server, on the other hand, needs to
- either detect a server failure and rebuild the server's state when it
- comes back up, or cause client operations to fail.
-
- This may not sound like an important issue, but it affects the
- protocol in some unexpected ways. We feel that it may be worth a bit
- of extra complexity in the protocol to be able to write very simple
- servers that do not require fancy crash recovery. Note that even if
- a so-called "reliable" transport protocol such as TCP is used, the
- client must still be able to handle interruptions of service by re-
- opening connections when they time out. Thus, a stateless protocol
- may actually simplify the implementation.
-
- On the other hand, NFS deals with objects such as files and
- directories that inherently have state -- what good would a file be
- if it did not keep its contents intact? The goal was to not
- introduce any extra state in the protocol itself. Inherently
- stateful operations such as file or record locking, and remote
- execution, were implemented as separate services, not described in
- this document.
-
- The basic way to simplify recovery was to make operations as
- "idempotent" as possible (so that they can potentially be repeated).
- Some operations in this version of the protocol did not attain this
- goal; luckily most of the operations (such as Read and Write) are
- idempotent. Also, most server failures occur between operations, not
- between the receipt of an operation and the response. Finally,
- although actual server failures may be rare, in complex networks,
- failures of any network, router, or bridge may be indistinguishable
- from a server failure.
-
-2. NFS PROTOCOL DEFINITION
-
- Servers change over time, and so can the protocol that they use. RPC
- provides a version number with each RPC request. This RFC describes
- version two of the NFS protocol. Even in the second version, there
- are a few obsolete procedures and parameters, which will be removed
- in later versions. An RFC for version three of the NFS protocol is
- currently under preparation.
-
-2.1. File System Model
-
- NFS assumes a file system that is hierarchical, with directories as
- all but the bottom level of files. Each entry in a directory (file,
- directory, device, etc.) has a string name. Different operating
- systems may have restrictions on the depth of the tree or the names
- used, as well as using different syntax to represent the "pathname",
- which is the concatenation of all the "components" (directory and
- file names) in the name. A "file system" is a tree on a single
- server (usually a single disk or physical partition) with a specified
- "root". Some operating systems provide a "mount" operation to make
- all file systems appear as a single tree, while others maintain a
- "forest" of file systems. Files are unstructured streams of
- uninterpreted bytes. Version 3 of NFS uses slightly more general
- file system model.
-
- NFS looks up one component of a pathname at a time. It may not be
- obvious why it does not just take the whole pathname, traipse down
- the directories, and return a file handle when it is done. There are
- several good reasons not to do this. First, pathnames need
- separators between the directory components, and different operating
- systems use different separators. We could define a Network Standard
- Pathname Representation, but then every pathname would have to be
- parsed and converted at each end. Other issues are discussed in
- section 3, NFS Implementation Issues.
-
- Although files and directories are similar objects in many ways,
- different procedures are used to read directories and files. This
- provides a network standard format for representing directories. The
- same argument as above could have been used to justify a procedure
- that returns only one directory entry per call. The problem is
- efficiency. Directories can contain many entries, and a remote call
- to return each would be just too slow.
-
-2.2. Server Procedures
-
- The protocol definition is given as a set of procedures with
- arguments and results defined using the RPC language (XDR language
- extended with program, version, and procedure declarations). A brief
-
- description of the function of each procedure should provide enough
- information to allow implementation. Section 2.3 describes the basic
- data types in more detail.
-
- All of the procedures in the NFS protocol are assumed to be
- synchronous. When a procedure returns to the client, the client can
- assume that the operation has completed and any data associated with
- the request is now on stable storage. For example, a client WRITE
- request may cause the server to update data blocks, filesystem
- information blocks (such as indirect blocks), and file attribute
- information (size and modify times). When the WRITE returns to the
- client, it can assume that the write is safe, even in case of a
- server crash, and it can discard the data written. This is a very
- important part of the statelessness of the server. If the server
- waited to flush data from remote requests, the client would have to
- save those requests so that it could resend them in case of a server
- crash.
-
- /*
- * Remote file service routines
- */
- program NFS_PROGRAM {
- version NFS_VERSION {
- void
- NFSPROC_NULL(void) = 0;
-
- attrstat
- NFSPROC_GETATTR(fhandle) = 1;
-
- attrstat
- NFSPROC_SETATTR(sattrargs) = 2;
-
- void
- NFSPROC_ROOT(void) = 3;
-
- diropres
- NFSPROC_LOOKUP(diropargs) = 4;
-
- readlinkres
- NFSPROC_READLINK(fhandle) = 5;
-
- readres
- NFSPROC_READ(readargs) = 6;
-
- void
- NFSPROC_WRITECACHE(void) = 7;
-
- attrstat
- NFSPROC_WRITE(writeargs) = 8;
-
- diropres
- NFSPROC_CREATE(createargs) = 9;
-
- stat
- NFSPROC_REMOVE(diropargs) = 10;
-
- stat
- NFSPROC_RENAME(renameargs) = 11;
-
- stat
- NFSPROC_LINK(linkargs) = 12;
-
- stat
- NFSPROC_SYMLINK(symlinkargs) = 13;
-
- diropres
- NFSPROC_MKDIR(createargs) = 14;
-
- stat
- NFSPROC_RMDIR(diropargs) = 15;
-
- readdirres
- NFSPROC_READDIR(readdirargs) = 16;
-
- statfsres
- NFSPROC_STATFS(fhandle) = 17;
- } = 2;
- } = 100003;
-
-2.2.1. Do Nothing
-
- void
- NFSPROC_NULL(void) = 0;
-
- This procedure does no work. It is made available in all RPC
- services to allow server response testing and timing.
-
-2.2.2. Get File Attributes
-
- attrstat
- NFSPROC_GETATTR (fhandle) = 1;
-
- If the reply status is NFS_OK, then the reply attributes contains the
- attributes for the file given by the input fhandle.
-
-2.2.3. Set File Attributes
-
- struct sattrargs {
- fhandle file;
- sattr attributes;
- };
-
- attrstat
- NFSPROC_SETATTR (sattrargs) = 2;
-
- The "attributes" argument contains fields which are either -1 or are
- the new value for the attributes of "file". If the reply status is
- NFS_OK, then the reply attributes have the attributes of the file
- after the "SETATTR" operation has completed.
-
- Notes: The use of -1 to indicate an unused field in "attributes" is
- changed in the next version of the protocol.
-
-2.2.4. Get Filesystem Root
-
- void
- NFSPROC_ROOT(void) = 3;
-
- Obsolete. This procedure is no longer used because finding the root
- file handle of a filesystem requires moving pathnames between client
- and server. To do this right, we would have to define a network
- standard representation of pathnames. Instead, the function of
- looking up the root file handle is done by the MNTPROC_MNT procedure.
- (See Appendix A, "Mount Protocol Definition", for details).
-
-2.2.5. Look Up File Name
-
- diropres
- NFSPROC_LOOKUP(diropargs) = 4;
-
- If the reply "status" is NFS_OK, then the reply "file" and reply
- "attributes" are the file handle and attributes for the file "name"
- in the directory given by "dir" in the argument.
-
-2.2.6. Read From Symbolic Link
-
- union readlinkres switch (stat status) {
- case NFS_OK:
- path data;
- default:
- void;
- };
-
- readlinkres
- NFSPROC_READLINK(fhandle) = 5;
-
- If "status" has the value NFS_OK, then the reply "data" is the data
- in the symbolic link given by the file referred to by the fhandle
- argument.
-
- Notes: Since NFS always parses pathnames on the client, the pathname
- in a symbolic link may mean something different (or be meaningless)
- on a different client or on the server if a different pathname syntax
- is used.
-
-2.2.7. Read From File
-
- struct readargs {
- fhandle file;
- unsigned offset;
- unsigned count;
- unsigned totalcount;
- };
-
- union readres switch (stat status) {
- case NFS_OK:
- fattr attributes;
- nfsdata data;
- default:
- void;
- };
-
- readres
- NFSPROC_READ(readargs) = 6;
-
- Returns up to "count" bytes of "data" from the file given by "file",
- starting at "offset" bytes from the beginning of the file. The first
- byte of the file is at offset zero. The file attributes after the
- read takes place are returned in "attributes".
-
- Notes: The argument "totalcount" is unused, and is removed in the
- next protocol revision.
-
-2.2.8. Write to Cache
-
- void
- NFSPROC_WRITECACHE(void) = 7;
-
- To be used in the next protocol revision.
-
-2.2.9. Write to File
-
- struct writeargs {
- fhandle file;
- unsigned beginoffset;
- unsigned offset;
- unsigned totalcount;
- nfsdata data;
- };
-
- attrstat
- NFSPROC_WRITE(writeargs) = 8;
-
- Writes "data" beginning "offset" bytes from the beginning of "file".
- The first byte of the file is at offset zero. If the reply "status"
- is NFS_OK, then the reply "attributes" contains the attributes of the
- file after the write has completed. The write operation is atomic.
- Data from this "WRITE" will not be mixed with data from another
- client's "WRITE".
-
- Notes: The arguments "beginoffset" and "totalcount" are ignored and
- are removed in the next protocol revision.
-
-2.2.10. Create File
-
- struct createargs {
- diropargs where;
- sattr attributes;
- };
-
- diropres
- NFSPROC_CREATE(createargs) = 9;
-
- The file "name" is created in the directory given by "dir". The
- initial attributes of the new file are given by "attributes". A
- reply "status" of NFS_OK indicates that the file was created, and
- reply "file" and reply "attributes" are its file handle and
- attributes. Any other reply "status" means that the operation failed
- and no file was created.
-
- Notes: This routine should pass an exclusive create flag, meaning
- "create the file only if it is not already there".
-
-2.2.11. Remove File
-
- stat
- NFSPROC_REMOVE(diropargs) = 10;
-
- The file "name" is removed from the directory given by "dir". A
- reply of NFS_OK means the directory entry was removed.
-
- Notes: possibly non-idempotent operation.
-
-2.2.12. Rename File
-
- struct renameargs {
- diropargs from;
- diropargs to;
- };
-
- stat
- NFSPROC_RENAME(renameargs) = 11;
-
- The existing file "from.name" in the directory given by "from.dir" is
- renamed to "to.name" in the directory given by "to.dir". If the
- reply is NFS_OK, the file was renamed. The RENAME operation is
- atomic on the server; it cannot be interrupted in the middle.
-
- Notes: possibly non-idempotent operation.
-
-2.2.13. Create Link to File
-
- Procedure 12, Version 2.
-
- struct linkargs {
- fhandle from;
- diropargs to;
- };
-
- stat
- NFSPROC_LINK(linkargs) = 12;
-
- Creates the file "to.name" in the directory given by "to.dir", which
- is a hard link to the existing file given by "from". If the return
- value is NFS_OK, a link was created. Any other return value
- indicates an error, and the link was not created.
-
- A hard link should have the property that changes to either of the
- linked files are reflected in both files. When a hard link is made
- to a file, the attributes for the file should have a value for
- "nlink" that is one greater than the value before the link.
-
- Notes: possibly non-idempotent operation.
-
-2.2.14. Create Symbolic Link
-
- struct symlinkargs {
- diropargs from;
- path to;
- sattr attributes;
- };
-
- stat
- NFSPROC_SYMLINK(symlinkargs) = 13;
-
- Creates the file "from.name" with ftype NFLNK in the directory given
- by "from.dir". The new file contains the pathname "to" and has
- initial attributes given by "attributes". If the return value is
- NFS_OK, a link was created. Any other return value indicates an
- error, and the link was not created.
-
- A symbolic link is a pointer to another file. The name given in "to"
- is not interpreted by the server, only stored in the newly created
- file. When the client references a file that is a symbolic link, the
- contents of the symbolic link are normally transparently
- reinterpreted as a pathname to substitute. A READLINK operation
- returns the data to the client for interpretation.
-
- Notes: On UNIX servers the attributes are never used, since symbolic
- links always have mode 0777.
-
-2.2.15. Create Directory
-
- diropres
- NFSPROC_MKDIR (createargs) = 14;
-
- The new directory "where.name" is created in the directory given by
- "where.dir". The initial attributes of the new directory are given
- by "attributes". A reply "status" of NFS_OK indicates that the new
- directory was created, and reply "file" and reply "attributes" are
- its file handle and attributes. Any other reply "status" means that
- the operation failed and no directory was created.
-
- Notes: possibly non-idempotent operation.
-
-2.2.16. Remove Directory
-
- stat
- NFSPROC_RMDIR(diropargs) = 15;
-
- The existing empty directory "name" in the directory given by "dir"
- is removed. If the reply is NFS_OK, the directory was removed.
-
- Notes: possibly non-idempotent operation.
-
-2.2.17. Read From Directory
-
- struct readdirargs {
- fhandle dir;
- nfscookie cookie;
- unsigned count;
- };
-
- struct entry {
- unsigned fileid;
- filename name;
- nfscookie cookie;
- entry *nextentry;
- };
-
- union readdirres switch (stat status) {
- case NFS_OK:
- struct {
- entry *entries;
- bool eof;
- } readdirok;
- default:
- void;
- };
-
- readdirres
- NFSPROC_READDIR (readdirargs) = 16;
-
- Returns a variable number of directory entries, with a total size of
- up to "count" bytes, from the directory given by "dir". If the
- returned value of "status" is NFS_OK, then it is followed by a
- variable number of "entry"s. Each "entry" contains a "fileid" which
- consists of a unique number to identify the file within a filesystem,
- the "name" of the file, and a "cookie" which is an opaque pointer to
- the next entry in the directory. The cookie is used in the next
- READDIR call to get more entries starting at a given point in the
- directory. The special cookie zero (all bits zero) can be used to
- get the entries starting at the beginning of the directory. The
- "fileid" field should be the same number as the "fileid" in the the
- attributes of the file. (See section "2.3.5. fattr" under "Basic
- Data Types".) The "eof" flag has a value of TRUE if there are no
- more entries in the directory.
-
-2.2.18. Get Filesystem Attributes
-
- union statfsres (stat status) {
- case NFS_OK:
- struct {
- unsigned tsize;
- unsigned bsize;
- unsigned blocks;
- unsigned bfree;
- unsigned bavail;
- } info;
- default:
- void;
- };
-
- statfsres
- NFSPROC_STATFS(fhandle) = 17;
-
- If the reply "status" is NFS_OK, then the reply "info" gives the
- attributes for the filesystem that contains file referred to by the
- input fhandle. The attribute fields contain the following values:
-
- tsize The optimum transfer size of the server in bytes. This is
- the number of bytes the server would like to have in the
- data part of READ and WRITE requests.
-
- bsize The block size in bytes of the filesystem.
-
- blocks The total number of "bsize" blocks on the filesystem.
-
- bfree The number of free "bsize" blocks on the filesystem.
-
- bavail The number of "bsize" blocks available to non-privileged
- users.
-
- Notes: This call does not work well if a filesystem has variable
- size blocks.
-
-2.3. Basic Data Types
-
- The following XDR definitions are basic structures and types used in
- other structures described further on.
-
-2.3.1. stat
-
- enum stat {
- NFS_OK = 0,
- NFSERR_PERM=1,
-
- NFSERR_NOENT=2,
- NFSERR_IO=5,
- NFSERR_NXIO=6,
- NFSERR_ACCES=13,
- NFSERR_EXIST=17,
- NFSERR_NODEV=19,
- NFSERR_NOTDIR=20,
- NFSERR_ISDIR=21,
- NFSERR_FBIG=27,
- NFSERR_NOSPC=28,
- NFSERR_ROFS=30,
- NFSERR_NAMETOOLONG=63,
- NFSERR_NOTEMPTY=66,
- NFSERR_DQUOT=69,
- NFSERR_STALE=70,
- NFSERR_WFLUSH=99
- };
-
- The "stat" type is returned with every procedure's results. A value
- of NFS_OK indicates that the call completed successfully and the
- results are valid. The other values indicate some kind of error
- occurred on the server side during the servicing of the procedure.
- The error values are derived from UNIX error numbers.
-
- NFSERR_PERM
- Not owner. The caller does not have correct ownership to perform
- the requested operation.
-
- NFSERR_NOENT
- No such file or directory. The file or directory specified does
- not exist.
-
- NFSERR_IO
- Some sort of hard error occurred when the operation was in
- progress. This could be a disk error, for example.
-
- NFSERR_NXIO
- No such device or address.
-
- NFSERR_ACCES
- Permission denied. The caller does not have the correct
- permission to perform the requested operation.
-
- NFSERR_EXIST
- File exists. The file specified already exists.
-
- NFSERR_NODEV
- No such device.
-
- NFSERR_NOTDIR
- Not a directory. The caller specified a non-directory in a
- directory operation.
-
- NFSERR_ISDIR
- Is a directory. The caller specified a directory in a non-
- directory operation.
-
- NFSERR_FBIG
- File too large. The operation caused a file to grow beyond the
- server's limit.
-
- NFSERR_NOSPC
- No space left on device. The operation caused the server's
- filesystem to reach its limit.
-
- NFSERR_ROFS
- Read-only filesystem. Write attempted on a read-only filesystem.
-
- NFSERR_NAMETOOLONG
- File name too long. The file name in an operation was too long.
-
- NFSERR_NOTEMPTY
- Directory not empty. Attempted to remove a directory that was not
- empty.
-
- NFSERR_DQUOT
- Disk quota exceeded. The client's disk quota on the server has
- been exceeded.
-
- NFSERR_STALE
- The "fhandle" given in the arguments was invalid. That is, the
- file referred to by that file handle no longer exists, or access
- to it has been revoked.
-
- NFSERR_WFLUSH
- The server's write cache used in the "WRITECACHE" call got flushed
- to disk.
-
-2.3.2. ftype
-
- enum ftype {
- NFNON = 0,
- NFREG = 1,
- NFDIR = 2,
- NFBLK = 3,
- NFCHR = 4,
- NFLNK = 5
- };
-
- The enumeration "ftype" gives the type of a file. The type NFNON
- indicates a non-file, NFREG is a regular file, NFDIR is a
- directory, NFBLK is a block-special device, NFCHR is a character-
- special device, and NFLNK is a symbolic link.
-
-2.3.3. fhandle
-
- typedef opaque fhandle[FHSIZE];
-
- The "fhandle" is the file handle passed between the server and the
- client. All file operations are done using file handles to refer
- to a file or directory. The file handle can contain whatever
- information the server needs to distinguish an individual file.
-
-2.3.4. timeval
-
- struct timeval {
- unsigned int seconds;
- unsigned int useconds;
- };
-
- The "timeval" structure is the number of seconds and microseconds
- since midnight January 1, 1970, Greenwich Mean Time. It is used
- to pass time and date information.
-
-2.3.5. fattr
-
- struct fattr {
- ftype type;
- unsigned int mode;
- unsigned int nlink;
- unsigned int uid;
- unsigned int gid;
- unsigned int size;
- unsigned int blocksize;
- unsigned int rdev;
- unsigned int blocks;
-
- unsigned int fsid;
- unsigned int fileid;
- timeval atime;
- timeval mtime;
- timeval ctime;
- };
-
- The "fattr" structure contains the attributes of a file; "type" is
- the type of the file; "nlink" is the number of hard links to the
- file (the number of different names for the same file); "uid" is
- the user identification number of the owner of the file; "gid" is
- the group identification number of the group of the file; "size"
- is the size in bytes of the file; "blocksize" is the size in bytes
- of a block of the file; "rdev" is the device number of the file if
- it is type NFCHR or NFBLK; "blocks" is the number of blocks the
- file takes up on disk; "fsid" is the file system identifier for
- the filesystem containing the file; "fileid" is a number that
- uniquely identifies the file within its filesystem; "atime" is the
- time when the file was last accessed for either read or write;
- "mtime" is the time when the file data was last modified
- (written); and "ctime" is the time when the status of the file was
- last changed. Writing to the file also changes "ctime" if the
- size of the file changes.
-
- "Mode" is the access mode encoded as a set of bits. Notice that
- the file type is specified both in the mode bits and in the file
- type. This is really a bug in the protocol and will be fixed in
- future versions. The descriptions given below specify the bit
- positions using octal numbers.
-
- 0040000 This is a directory; "type" field should be NFDIR.
- 0020000 This is a character special file; "type" field should
- be NFCHR.
- 0060000 This is a block special file; "type" field should be
- NFBLK.
- 0100000 This is a regular file; "type" field should be NFREG.
- 0120000 This is a symbolic link file; "type" field should be
- NFLNK.
- 0140000 This is a named socket; "type" field should be NFNON.
- 0004000 Set user id on execution.
- 0002000 Set group id on execution.
- 0001000 Save swapped text even after use.
- 0000400 Read permission for owner.
- 0000200 Write permission for owner.
- 0000100 Execute and search permission for owner.
- 0000040 Read permission for group.
- 0000020 Write permission for group.
- 0000010 Execute and search permission for group.
-
- 0000004 Read permission for others.
- 0000002 Write permission for others.
- 0000001 Execute and search permission for others.
-
- Notes: The bits are the same as the mode bits returned by the
- stat(2) system call in UNIX. The file type is specified both in
- the mode bits and in the file type. This is fixed in future
- versions.
-
- The "rdev" field in the attributes structure is an operating
- system specific device specifier. It will be removed and
- generalized in the next revision of the protocol.
-
-2.3.6. sattr
-
- struct sattr {
- unsigned int mode;
- unsigned int uid;
- unsigned int gid;
- unsigned int size;
- timeval atime;
- timeval mtime;
- };
-
- The "sattr" structure contains the file attributes which can be
- set from the client. The fields are the same as for "fattr"
- above. A "size" of zero means the file should be truncated. A
- value of -1 indicates a field that should be ignored.
-
-2.3.7. filename
-
- typedef string filename<MAXNAMLEN>;
-
- The type "filename" is used for passing file names or pathname
- components.
-
-2.3.8. path
-
- typedef string path<MAXPATHLEN>;
-
- The type "path" is a pathname. The server considers it as a
- string with no internal structure, but to the client it is the
- name of a node in a filesystem tree.
-
-2.3.9. attrstat
-
- union attrstat switch (stat status) {
- case NFS_OK:
-
- fattr attributes;
- default:
- void;
- };
-
- The "attrstat" structure is a common procedure result. It
- contains a "status" and, if the call succeeded, it also contains
- the attributes of the file on which the operation was done.
-
-2.3.10. diropargs
-
- struct diropargs {
- fhandle dir;
- filename name;
- };
-
- The "diropargs" structure is used in directory operations. The
- "fhandle" "dir" is the directory in which to find the file "name".
- A directory operation is one in which the directory is affected.
-
-2.3.11. diropres
-
- union diropres switch (stat status) {
- case NFS_OK:
- struct {
- fhandle file;
- fattr attributes;
- } diropok;
- default:
- void;
- };
-
- The results of a directory operation are returned in a "diropres"
- structure. If the call succeeded, a new file handle "file" and
- the "attributes" associated with that file are returned along with
- the "status".
-
-3. NFS IMPLEMENTATION ISSUES
-
- The NFS protocol was designed to allow different operating systems to
- share files. However, since it was designed in a UNIX environment,
- many operations have semantics similar to the operations of the UNIX
- file system. This section discusses some of the implementation-
- specific details and semantic issues.
-
-3.1. Server/Client Relationship
-
- The NFS protocol is designed to allow servers to be as simple and
-
- general as possible. Sometimes the simplicity of the server can be a
- problem, if the client wants to implement complicated filesystem
- semantics.
-
- For example, some operating systems allow removal of open files. A
- process can open a file and, while it is open, remove it from the
- directory. The file can be read and written as long as the process
- keeps it open, even though the file has no name in the filesystem.
- It is impossible for a stateless server to implement these semantics.
- The client can do some tricks such as renaming the file on remove,
- and only removing it on close. We believe that the server provides
- enough functionality to implement most file system semantics on the
- client.
-
- Every NFS client can also potentially be a server, and remote and
- local mounted filesystems can be freely intermixed. This leads to
- some interesting problems when a client travels down the directory
- tree of a remote filesystem and reaches the mount point on the server
- for another remote filesystem. Allowing the server to follow the
- second remote mount would require loop detection, server lookup, and
- user revalidation. Instead, we decided not to let clients cross a
- server's mount point. When a client does a LOOKUP on a directory on
- which the server has mounted a filesystem, the client sees the
- underlying directory instead of the mounted directory.
-
- For example, if a server has a file system called "/usr" and mounts
- another file system on "/usr/src", if a client mounts "/usr", it
- does NOT see the mounted version of "/usr/src". A client could do
- remote mounts that match the server's mount points to maintain the
- server's view. In this example, the client would also have to mount
- "/usr/src" in addition to "/usr", even if they are from the same
- server.
-
-3.2. Pathname Interpretation
-
- There are a few complications to the rule that pathnames are always
- parsed on the client. For example, symbolic links could have
- different interpretations on different clients. Another common
- problem for non-UNIX implementations is the special interpretation of
- the pathname ".." to mean the parent of a given directory. The next
- revision of the protocol uses an explicit flag to indicate the parent
- instead.
-
-3.3. Permission Issues
-
- The NFS protocol, strictly speaking, does not define the permission
- checking used by servers. However, it is expected that a server will
- do normal operating system permission checking using AUTH_UNIX style
-
- authentication as the basis of its protection mechanism. The server
- gets the client's effective "uid", effective "gid", and groups on
- each call and uses them to check permission. There are various
- problems with this method that can been resolved in interesting ways.
-
- Using "uid" and "gid" implies that the client and server share the
- same "uid" list. Every server and client pair must have the same
- mapping from user to "uid" and from group to "gid". Since every
- client can also be a server, this tends to imply that the whole
- network shares the same "uid/gid" space. AUTH_DES (and the next
- revision of the NFS protocol) uses string names instead of numbers,
- but there are still complex problems to be solved.
-
- Another problem arises due to the usually stateful open operation.
- Most operating systems check permission at open time, and then check
- that the file is open on each read and write request. With stateless
- servers, the server has no idea that the file is open and must do
- permission checking on each read and write call. On a local
- filesystem, a user can open a file and then change the permissions so
- that no one is allowed to touch it, but will still be able to write
- to the file because it is open. On a remote filesystem, by contrast,
- the write would fail. To get around this problem, the server's
- permission checking algorithm should allow the owner of a file to
- access it regardless of the permission setting.
-
- A similar problem has to do with paging in from a file over the
- network. The operating system usually checks for execute permission
- before opening a file for demand paging, and then reads blocks from
- the open file. The file may not have read permission, but after it
- is opened it does not matter. An NFS server can not tell the
- difference between a normal file read and a demand page-in read. To
- make this work, the server allows reading of files if the "uid" given
- in the call has either execute or read permission on the file.
-
- In most operating systems, a particular user (on UNIX, the user ID
- zero) has access to all files no matter what permission and ownership
- they have. This "super-user" permission may not be allowed on the
- server, since anyone who can become super-user on their workstation
- could gain access to all remote files. The UNIX server by default
- maps user id 0 to -2 before doing its access checking. This works
- except for NFS root filesystems, where super-user access cannot be
- avoided.
-
-3.4. RPC Information
-
- Authentication
- The NFS service uses AUTH_UNIX, AUTH_DES, or AUTH_SHORT style
- authentication, except in the NULL procedure where AUTH_NONE is
-
- also allowed.
-
- Transport Protocols
- NFS is supported normally on UDP.
-
- Port Number
- The NFS protocol currently uses the UDP port number 2049. This is
- not an officially assigned port, so later versions of the protocol
- use the "Portmapping" facility of RPC.
-
-3.5. Sizes of XDR Structures
-
- These are the sizes, given in decimal bytes, of various XDR
- structures used in the protocol:
-
- /*
- * The maximum number of bytes of data in a READ or WRITE
- * request.
- */
- const MAXDATA = 8192;
-
- /* The maximum number of bytes in a pathname argument. */
- const MAXPATHLEN = 1024;
-
- /* The maximum number of bytes in a file name argument. */
- const MAXNAMLEN = 255;
-
- /* The size in bytes of the opaque "cookie" passed by READDIR. */
- const COOKIESIZE = 4;
-
- /* The size in bytes of the opaque file handle. */
- const FHSIZE = 32;
-
-3.6. Setting RPC Parameters
-
- Various file system parameters and options should be set at mount
- time. The mount protocol is described in the appendix below. For
- example, "Soft" mounts as well as "Hard" mounts are usually both
- provided. Soft mounted file systems return errors when RPC
- operations fail (after a given number of optional retransmissions),
- while hard mounted file systems continue to retransmit forever. The
- maximum transfer sizes are implementation dependent. For efficient
- operation over a local network, 8192 bytes of data are normally used.
- This may result in lower-level fragmentation (such as at the IP
- level). Since some network interfaces may not allow such packets,
- for operation over slower-speed networks or hosts, or through
- gateways, transfer sizes of 512 or 1024 bytes often provide better
- results.
-
- Clients and servers may need to keep caches of recent operations to
- help avoid problems with non-idempotent operations. For example, if
- the transport protocol drops the response for a Remove File
- operation, upon retransmission the server may return an error code of
- NFSERR_NOENT instead of NFS_OK. But if the server keeps around the
- last operation requested and its result, it could return the proper
- success code. Of course, the server could be crashed and rebooted
- between retransmissions, but a small cache (even a single entry)
- would solve most problems.
-
- Appendix A. MOUNT PROTOCOL DEFINITION
-
-A.1. Introduction
-
- The mount protocol is separate from, but related to, the NFS
- protocol. It provides operating system specific services to get the
- NFS off the ground -- looking up server path names, validating user
- identity, and checking access permissions. Clients use the mount
- protocol to get the first file handle, which allows them entry into a
- remote filesystem.
-
- The mount protocol is kept separate from the NFS protocol to make it
- easy to plug in new access checking and validation methods without
- changing the NFS server protocol.
-
- Notice that the protocol definition implies stateful servers because
- the server maintains a list of client's mount requests. The mount
- list information is not critical for the correct functioning of
- either the client or the server. It is intended for advisory use
- only, for example, to warn possible clients when a server is going
- down.
-
- Version one of the mount protocol is used with version two of the NFS
- protocol. The only information communicated between these two
- protocols is the "fhandle" structure.
-
-A.2. RPC Information
-
- Authentication
- The mount service uses AUTH_UNIX and AUTH_NONE style
- authentication only.
-
- Transport Protocols
- The mount service is supported on both UDP and TCP.
-
- Port Number
- Consult the server's portmapper, described in RFC 1057 </rfcs/rfc1057.html>, "RPC:
- Remote Procedure Call Protocol Specification", to find the port
- number on which the mount service is registered.
-
-A.3. Sizes of XDR Structures
-
- These are the sizes, given in decimal bytes, of various XDR
- structures used in the protocol:
-
- /* The maximum number of bytes in a pathname argument. */
- const MNTPATHLEN = 1024;
-
- /* The maximum number of bytes in a name argument. */
- const MNTNAMLEN = 255;
-
- /* The size in bytes of the opaque file handle. */
- const FHSIZE = 32;
-
-A.4. Basic Data Types
-
- This section presents the data types used by the mount protocol. In
- many cases they are similar to the types used in NFS.
-
-A.4.1. fhandle
-
- typedef opaque fhandle[FHSIZE];
-
- The type "fhandle" is the file handle that the server passes to the
- client. All file operations are done using file handles to refer to
- a file or directory. The file handle can contain whatever
- information the server needs to distinguish an individual file.
-
- This is the same as the "fhandle" XDR definition in version 2 of the
- NFS protocol; see section "2.3.3. fhandle" under "Basic Data Types".
-
-A.4.2. fhstatus
-
- union fhstatus switch (unsigned status) {
- case 0:
- fhandle directory;
- default:
- void;
- }
-
- The type "fhstatus" is a union. If a "status" of zero is returned,
- the call completed successfully, and a file handle for the
- "directory" follows. A non-zero status indicates some sort of error.
- In this case, the status is a UNIX error number.
-
-A.4.3. dirpath
-
- typedef string dirpath<MNTPATHLEN>;
-
- The type "dirpath" is a server pathname of a directory.
-
-A.4.4. name
-
- typedef string name<MNTNAMLEN>;
-
- The type "name" is an arbitrary string used for various names.
-
-A.5. Server Procedures
-
- The following sections define the RPC procedures supplied by a mount
- server.
-
- /*
- * Protocol description for the mount program
- */
- program MOUNTPROG {
- /*
- * Version 1 of the mount protocol used with
- * version 2 of the NFS protocol.
- */
- version MOUNTVERS {
-
- void
- MOUNTPROC_NULL(void) = 0;
-
- fhstatus
- MOUNTPROC_MNT(dirpath) = 1;
-
- mountlist
- MOUNTPROC_DUMP(void) = 2;
-
- void
- MOUNTPROC_UMNT(dirpath) = 3;
-
- void
- MOUNTPROC_UMNTALL(void) = 4;
-
- exportlist
- MOUNTPROC_EXPORT(void) = 5;
- } = 1;
- } = 100005;
-
-A.5.1. Do Nothing
-
- void
- MNTPROC_NULL(void) = 0;
-
- This procedure does no work. It is made available in all RPC
- services to allow server response testing and timing.
-
-A.5.2. Add Mount Entry
-
- fhstatus
- MNTPROC_MNT(dirpath) = 1;
-
- If the reply "status" is 0, then the reply "directory" contains the
- file handle for the directory "dirname". This file handle may be
- used in the NFS protocol. This procedure also adds a new entry to
- the mount list for this client mounting "dirname".
-
-A.5.3. Return Mount Entries
-
- struct *mountlist {
- name hostname;
- dirpath directory;
- mountlist nextentry;
- };
-
- mountlist
- MNTPROC_DUMP(void) = 2;
-
- Returns the list of remote mounted filesystems. The "mountlist"
- contains one entry for each "hostname" and "directory" pair.
-
-A.5.4. Remove Mount Entry
-
- void
- MNTPROC_UMNT(dirpath) = 3;
-
- Removes the mount list entry for the input "dirpath".
-
-A.5.5. Remove All Mount Entries
-
- void
- MNTPROC_UMNTALL(void) = 4;
-
- Removes all of the mount list entries for this client.
-
-A.5.6. Return Export List
-
- struct *groups {
- name grname;
- groups grnext;
- };
-
- struct *exportlist {
- dirpath filesys;
- groups groups;
- exportlist next;
- };
-
- exportlist
- MNTPROC_EXPORT(void) = 5;
-
- Returns a variable number of export list entries. Each entry
- contains a filesystem name and a list of groups that are allowed to
- import it. The filesystem name is in "filesys", and the group name
- is in the list "groups".
-
- Notes: The exportlist should contain more information about the
- status of the filesystem, such as a read-only flag.
-
-Author's Address:
-
- Bill Nowicki
- Sun Microsystems, Inc.
- Mail Stop 1-40
- 2550 Garcia Avenue
- Mountain View, CA 94043
-
- Phone: (415) 336-7278
-
- Email: nowicki@SUN.COM <mailto:nowicki@SUN.COM>
-
-Comment on RFC 1094 </rfccomment.php?rfcnum=1094>
-
-
-
-Comments about this RFC:
-
- * RFC 1094: I am preparing for doing a project in File System in
- Network. can you specify... </qa/rfcc-377.html> by Ravik (12/4/2003)
-
-
-Previous: RFC 1093 - NSFNET routing architecture </rfcs/rfc1093.html>
-
-
-
-Next: RFC 1095 - Common Management Information Services and Protocol
-over TCP/IP (CMOT) </rfcs/rfc1095.html>
-
-
-
-------------------------------------------------------------------------
diff --git a/rtemsNfs/rtems-filesystem-patch b/rtemsNfs/rtems-filesystem-patch
deleted file mode 100644
index c2d7861..0000000
--- a/rtemsNfs/rtems-filesystem-patch
+++ /dev/null
@@ -1,860 +0,0 @@
-# Diffed against OAR_orig (ss-20020301) on Sun Nov 3 00:24:13 PST 2002
-# T.S.
-
-For more information about this patch consult README (CAVEATS section).
-
-To apply this patch,
-
-chdir to c/src/lib/libc
-
-and issue
-
- patch -p0 < this_file
-
-It is always a good idea to try a "dry-run" before applying a patch:
-
- patch --dry-run -p0 < this_file
-
-Index: Makefile.am
-===================================================================
-RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/Makefile.am,v
-retrieving revision 1.1.1.2
-retrieving revision 1.2
-diff -c -r1.1.1.2 -r1.2
-*** Makefile.am 7 Mar 2002 01:53:46 -0000 1.1.1.2
---- Makefile.am 28 Mar 2002 20:59:16 -0000 1.2
-***************
-*** 1,5 ****
- ##
-! ## $Id$
- ##
-
- AUTOMAKE_OPTIONS = foreign 1.4
---- 1,5 ----
- ##
-! ## $Id$
- ##
-
- AUTOMAKE_OPTIONS = foreign 1.4
-***************
-*** 32,37 ****
---- 32,39 ----
-
- MALLOC_C_FILES = malloc.c mallocfreespace.c __brk.c __sbrk.c
-
-+ ENVIRON_C_FILES = envlock.c
-+
- PASSWORD_GROUP_C_FILES = getpwent.c getgrent.c
-
- TERMINAL_IDENTIFICATION_C_FILES = ctermid.c isatty.c ttyname.c ttyname_r.c
-***************
-*** 42,48 ****
- UNIX_LIBC_C_FILES = unixlibc.c hosterr.c
-
- COMMON_C_FILES = gxx_wrappers.c printk.c $(BASE_FS_C_FILES) \
-! $(MALLOC_C_FILES) $(TERMIOS_C_FILES) $(ERROR_C_FILES) \
- $(ASSOCIATION_C_FILES)
-
- UNIX_C_FILES = $(UNIX_LIBC_C_FILES)
---- 44,50 ----
- UNIX_LIBC_C_FILES = unixlibc.c hosterr.c
-
- COMMON_C_FILES = gxx_wrappers.c printk.c $(BASE_FS_C_FILES) \
-! $(MALLOC_C_FILES) $(ENVIRON_C_FILES) $(TERMIOS_C_FILES) $(ERROR_C_FILES) \
- $(ASSOCIATION_C_FILES)
-
- UNIX_C_FILES = $(UNIX_LIBC_C_FILES)
-Index: base_fs.c
-===================================================================
-RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/base_fs.c,v
-retrieving revision 1.1.1.1
-diff -c -r1.1.1.1 base_fs.c
-*** base_fs.c 14 Dec 2001 22:52:31 -0000 1.1.1.1
---- base_fs.c 26 Oct 2002 02:45:15 -0000
-***************
-*** 49,54 ****
---- 49,55 ----
- int status;
- rtems_filesystem_mount_table_entry_t *entry;
- rtems_filesystem_mount_table_t *mt;
-+ rtems_filesystem_location_info_t loc;
-
- /*
- * Set the default umask to "022".
-***************
-*** 75,82 ****
- rtems_fatal_error_occurred( 0xABCD0002 );
-
- rtems_filesystem_link_counts = 0;
- rtems_filesystem_root = entry->mt_fs_root;
-! rtems_filesystem_current = rtems_filesystem_root;
-
-
- /*
---- 76,113 ----
- rtems_fatal_error_occurred( 0xABCD0002 );
-
- rtems_filesystem_link_counts = 0;
-+
-+ /* setup the 'current' and 'root' directories
-+ *
-+ * NOTE: cloning the pathlocs is not strictly
-+ * necessary. Since we implicitely let
-+ * all threads that don't call
-+ * libio_set_private_env() share the same
-+ * (initial) 'root' and 'current' locs,
-+ * we (also implicitely) assume that the
-+ * root filesystem doesn't care about
-+ * reference counts.
-+ * I just inserted the code snippet below
-+ * to remind everybody of the fact by
-+ * making it more explicit...
-+ * Ideally, every thread would have to
-+ * call either share_private_env() or
-+ * set_private_env() - but then: that's
-+ * gonna hit performance.
-+ *
-+ * Till Straumann, 10/25/2002
-+ */
- rtems_filesystem_root = entry->mt_fs_root;
-! /* Clone the root pathloc */
-! rtems_filesystem_evaluate_path("/", 0, &loc, 0);
-! rtems_filesystem_root = loc;
-! /* One more clone for the current node */
-! rtems_filesystem_evaluate_path("/", 0, &loc, 0);
-! rtems_filesystem_current = loc;
-!
-! /* Note: the global_env's refcnt doesn't matter
-! * as the global env is never released
-! */
-
-
- /*
-Index: chroot.c
-===================================================================
-RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/chroot.c,v
-retrieving revision 1.1.1.2
-diff -c -r1.1.1.2 chroot.c
-*** chroot.c 7 Mar 2002 01:53:47 -0000 1.1.1.2
---- chroot.c 29 Oct 2002 03:01:47 -0000
-***************
-*** 38,51 ****
- rtems_set_errno_and_return_minus_one( ENOTSUP );
- };
-
-- loc = rtems_filesystem_root; /* save the value */
--
- result = chdir(pathname);
- if (result) {
-- rtems_filesystem_root = loc; /* restore the value */
- rtems_set_errno_and_return_minus_one( errno );
- };
-! rtems_filesystem_root = rtems_filesystem_current;
-
- return 0;
- }
---- 38,53 ----
- rtems_set_errno_and_return_minus_one( ENOTSUP );
- };
-
- result = chdir(pathname);
- if (result) {
- rtems_set_errno_and_return_minus_one( errno );
- };
-! /* clone the new root location */
-! if (rtems_filesystem_evaluate_path(".", 0, &loc, 0)) {
-! rtems_set_errno_and_return_minus_one( errno );
-! }
-! rtems_filesystem_freenode(&rtems_filesystem_root);
-! rtems_filesystem_root = loc;
-
- return 0;
- }
-Index: eval.c
-===================================================================
-RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/eval.c,v
-retrieving revision 1.1.1.2
-retrieving revision 1.2
-diff -c -r1.1.1.2 -r1.2
-*** eval.c 7 Mar 2002 01:53:48 -0000 1.1.1.2
---- eval.c 29 Oct 2002 21:03:50 -0000 1.2
-***************
-*** 10,16 ****
- * found in the file LICENSE in this distribution or at
- * http://www.OARcorp.com/rtems/license.html.
- *
-! * $Id$
- */
-
- #if HAVE_CONFIG_H
---- 10,16 ----
- * found in the file LICENSE in this distribution or at
- * http://www.OARcorp.com/rtems/license.html.
- *
-! * $Id$
- */
-
- #if HAVE_CONFIG_H
-***************
-*** 60,76 ****
-
- if ( (result == 0) && follow_link ) {
-
-! if ( !pathloc->ops->node_type_h )
- rtems_set_errno_and_return_minus_one( ENOTSUP );
-
- type = (*pathloc->ops->node_type_h)( pathloc );
-
- if ( ( type == RTEMS_FILESYSTEM_HARD_LINK ) ||
- ( type == RTEMS_FILESYSTEM_SYM_LINK ) ) {
-
-! if ( !pathloc->ops->eval_link_h )
- rtems_set_errno_and_return_minus_one( ENOTSUP );
-
- result = (*pathloc->ops->eval_link_h)( pathloc, flags );
-
- }
---- 60,93 ----
-
- if ( (result == 0) && follow_link ) {
-
-! if ( !pathloc->ops->node_type_h ) {
-! rtems_filesystem_freenode(pathloc);
- rtems_set_errno_and_return_minus_one( ENOTSUP );
-+ }
-
- type = (*pathloc->ops->node_type_h)( pathloc );
-
- if ( ( type == RTEMS_FILESYSTEM_HARD_LINK ) ||
- ( type == RTEMS_FILESYSTEM_SYM_LINK ) ) {
-
-! if ( !pathloc->ops->eval_link_h ) {
-! rtems_filesystem_freenode(pathloc);
- rtems_set_errno_and_return_minus_one( ENOTSUP );
-+ }
-
-+ /* what to do with the valid node pathloc points to
-+ * if eval_link_h() fails?
-+ * Let the FS implementation deal with this case. It
-+ * should probably free pathloc in either case:
-+ * - if the link evaluation fails, it must free the
-+ * original (valid) pathloc because we are going
-+ * to return -1 and hence the FS generics won't
-+ * cleanup pathloc
-+ * - if the link evaluation is successful, the updated
-+ * pathloc will be passed up (and eventually released).
-+ * Hence, the (valid) original node that we submit to
-+ * eval_link_h() should be released by the handler.
-+ */
- result = (*pathloc->ops->eval_link_h)( pathloc, flags );
-
- }
-Index: fchdir.c
-===================================================================
-RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/fchdir.c,v
-retrieving revision 1.1.1.2
-diff -c -r1.1.1.2 fchdir.c
-*** fchdir.c 7 Mar 2002 01:53:48 -0000 1.1.1.2
---- fchdir.c 25 Oct 2002 23:59:03 -0000
-***************
-*** 29,34 ****
---- 29,35 ----
- )
- {
- rtems_libio_t *iop;
-+ rtems_filesystem_location_info_t loc;
-
- rtems_libio_check_fd( fd );
- iop = rtems_libio_iop( fd );
-***************
-*** 65,74 ****
- * this node which we are making here. I can
- * see the freenode interface but do not see
- * allocnode node interface. It maybe node_type.
- */
-
- rtems_filesystem_current = iop->pathinfo;
-
- return 0;
- }
--
---- 66,80 ----
- * this node which we are making here. I can
- * see the freenode interface but do not see
- * allocnode node interface. It maybe node_type.
-+ *
-+ * FIXEC: T.Straumann: it is evaluate_path()
- */
-
- rtems_filesystem_current = iop->pathinfo;
-
-+ /* clone the current node */
-+ rtems_filesystem_evaluate_path(".", 0, &loc, 0);
-+ rtems_filesystem_current = loc;
-+
- return 0;
- }
-Index: getgrent.c
-===================================================================
-RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/getgrent.c,v
-retrieving revision 1.1.1.1
-diff -c -r1.1.1.1 getgrent.c
-*** getgrent.c 14 Dec 2001 22:52:31 -0000 1.1.1.1
---- getgrent.c 27 Oct 2002 18:24:20 -0000
-***************
-*** 50,63 ****
---- 50,69 ----
- )
- {
- FILE *fp;
-+ #if 0
- rtems_user_env_t * aux=rtems_current_user_env; /* save */
-+ #endif
-
- init_etc_passwd_group();
-+ #if 0
- rtems_current_user_env=&rtems_global_user_env; /* set root */
-+ #endif
-
- if ((fp = fopen ("/etc/group", "r")) == NULL) {
- errno = EINVAL;
-+ #if 0
- rtems_current_user_env=aux; /* restore */
-+ #endif
- return -1;
- }
-
-***************
-*** 72,84 ****
---- 78,94 ----
- if (!strcmp (groupname, name)) {
- fclose (fp);
- *result = grp;
-+ #if 0
- rtems_current_user_env=aux; /* restore */
-+ #endif
- return 0;
- }
- }
- fclose (fp);
- errno = EINVAL;
-+ #if 0
- rtems_current_user_env=aux; /* restore */
-+ #endif
- return -1;
- }
-
-***************
-*** 104,118 ****
---- 114,134 ----
- )
- {
- FILE *fp;
-+ #if 0
- rtems_user_env_t * aux=rtems_current_user_env; /* save */
-+ #endif
-
-
- init_etc_passwd_group();
-+ #if 0
- rtems_current_user_env=&rtems_global_user_env; /* set root */
-+ #endif
-
- if ((fp = fopen ("/etc/group", "r")) == NULL) {
- errno = EINVAL;
-+ #if 0
- rtems_current_user_env=aux; /* restore */
-+ #endif
- return -1;
- }
-
-***************
-*** 128,140 ****
---- 144,160 ----
- if (gid == gr_group.gr_gid) {
- fclose (fp);
- *result = grp;
-+ #if 0
- rtems_current_user_env=aux; /* restore */
-+ #endif
- return 0;
- }
- }
- fclose (fp);
- errno = EINVAL;
-+ #if 0
- rtems_current_user_env=aux; /* restore */
-+ #endif
- return -1;
- }
-
-***************
-*** 174,188 ****
---- 194,214 ----
- void
- setgrent ()
- {
-+ #if 0
- rtems_user_env_t * aux=rtems_current_user_env; /* save */
-+ #endif
- init_etc_passwd_group();
-+ #if 0
- rtems_current_user_env=&rtems_global_user_env; /* set root */
-+ #endif
-
- if (group_fp != NULL)
- fclose (group_fp);
-
- group_fp = fopen ("/etc/group", "r");
-+ #if 0
- rtems_current_user_env=aux; /* restore */
-+ #endif
- }
-
- void
-Index: getpwent.c
-===================================================================
-RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/getpwent.c,v
-retrieving revision 1.1.1.1
-diff -c -r1.1.1.1 getpwent.c
-*** getpwent.c 14 Dec 2001 22:52:31 -0000 1.1.1.1
---- getpwent.c 27 Oct 2002 18:18:52 -0000
-***************
-*** 97,110 ****
---- 97,116 ----
- )
- {
- FILE *fp;
-+ #if 0
- rtems_user_env_t * aux=rtems_current_user_env; /* save */
-+ #endif
-
- init_etc_passwd_group();
-+ #if 0
- rtems_current_user_env=&rtems_global_user_env; /* set root */
-+ #endif
-
- if ((fp = fopen ("/etc/passwd", "r")) == NULL) {
- errno = EINVAL;
-+ #if 0
- rtems_current_user_env=aux; /* restore */
-+ #endif
- return -1;
- }
-
-***************
-*** 123,135 ****
---- 129,145 ----
- if (!strcmp (logname, name)) {
- fclose (fp);
- *result = pwd;
-+ #if 0
- rtems_current_user_env=aux; /* restore */
-+ #endif
- return 0;
- }
- }
- fclose (fp);
- errno = EINVAL;
-+ #if 0
- rtems_current_user_env=aux; /* restore */
-+ #endif
- return -1;
- }
-
-***************
-*** 155,168 ****
---- 165,184 ----
- )
- {
- FILE *fp;
-+ #if 0
- rtems_user_env_t * aux=rtems_current_user_env; /* save */
-+ #endif
-
- init_etc_passwd_group();
-+ #if 0
- rtems_current_user_env=&rtems_global_user_env; /* set root */
-+ #endif
-
- if ((fp = fopen ("/etc/passwd", "r")) == NULL) {
- errno = EINVAL;
-+ #if 0
- rtems_current_user_env=aux; /* restore */
-+ #endif
- return -1;
- }
-
-***************
-*** 181,193 ****
---- 197,213 ----
- if (uid == pwd->pw_uid) {
- fclose (fp);
- *result = pwd;
-+ #if 0
- rtems_current_user_env=aux; /* restore */
-+ #endif
- return 0;
- }
- }
- fclose (fp);
- errno = EINVAL;
-+ #if 0
- rtems_current_user_env=aux; /* restore */
-+ #endif
- return -1;
- }
-
-***************
-*** 230,244 ****
---- 250,270 ----
-
- void setpwent( void )
- {
-+ #if 0
- rtems_user_env_t * aux=rtems_current_user_env; /* save */
-+ #endif
- init_etc_passwd_group();
-+ #if 0
- rtems_current_user_env=&rtems_global_user_env; /* set root */
-+ #endif
-
- if (passwd_fp != NULL)
- fclose (passwd_fp);
-
- passwd_fp = fopen ("/etc/passwd", "r");
-+ #if 0
- rtems_current_user_env=aux; /* restore */
-+ #endif
- }
-
- void endpwent( void )
-Index: mknod.c
-===================================================================
-RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/mknod.c,v
-retrieving revision 1.1.1.2
-retrieving revision 1.2
-diff -c -r1.1.1.2 -r1.2
-*** mknod.c 7 Mar 2002 01:53:51 -0000 1.1.1.2
---- mknod.c 29 Oct 2002 21:03:50 -0000 1.2
-***************
-*** 12,18 ****
- * found in the file LICENSE in this distribution or at
- * http://www.OARcorp.com/rtems/license.html.
- *
-! * $Id$
- */
-
- #if HAVE_CONFIG_H
---- 12,18 ----
- * found in the file LICENSE in this distribution or at
- * http://www.OARcorp.com/rtems/license.html.
- *
-! * $Id$
- */
-
- #if HAVE_CONFIG_H
-***************
-*** 49,55 ****
- rtems_filesystem_get_start_loc( pathname, &i, &temp_loc );
-
- if ( !temp_loc.ops->evalformake_h ) {
-- rtems_filesystem_freenode( &temp_loc );
- rtems_set_errno_and_return_minus_one( ENOTSUP );
- }
-
---- 49,54 ----
-Index: mount.c
-===================================================================
-RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/mount.c,v
-retrieving revision 1.1.1.1
-diff -c -r1.1.1.1 mount.c
-*** mount.c 14 Dec 2001 22:52:33 -0000 1.1.1.1
---- mount.c 30 Oct 2002 06:39:09 -0000
-***************
-*** 14,20 ****
- * found in the file LICENSE in this distribution or at
- * http://www.OARcorp.com/rtems/license.html.
- *
-! * $Id$
- */
-
- #if HAVE_CONFIG_H
---- 14,20 ----
- * found in the file LICENSE in this distribution or at
- * http://www.OARcorp.com/rtems/license.html.
- *
-! * $Id$
- */
-
- #if HAVE_CONFIG_H
-***************
-*** 101,106 ****
---- 101,113 ----
- return -1;
- }
-
-+ /* Do they support being mounted at all ? */
-+ if ( !fs_ops->fsmount_me_h ) {
-+ errno = ENOTSUP;
-+ goto cleanup_and_bail;
-+ }
-+
-+
- /*
- * Allocate a mount table entry
- */
-***************
-*** 140,145 ****
---- 147,158 ----
- */
-
- loc_to_free = &loc;
-+
-+ if ( !loc.ops->node_type_h ) {
-+ errno = ENOTSUP;
-+ goto cleanup_and_bail;
-+ }
-+
- if ( loc.ops->node_type_h( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) {
- errno = ENOTDIR;
- goto cleanup_and_bail;
-***************
-*** 198,210 ****
- temp_mt_entry->mt_point_node.mt_entry = NULL;
- }
-
-! if ( !fs_ops->fsmount_me_h ) {
-! errno = ENOTSUP;
- goto cleanup_and_bail;
- }
--
-- if ( fs_ops->fsmount_me_h( temp_mt_entry ) )
-- goto cleanup_and_bail;
-
- /*
- * Add the mount table entry to the mount table chain
---- 211,223 ----
- temp_mt_entry->mt_point_node.mt_entry = NULL;
- }
-
-! if ( fs_ops->fsmount_me_h( temp_mt_entry ) ) {
-! /* try to undo the mount operation */
-! if ( loc.ops->unmount_h ) {
-! loc.ops->unmount_h( temp_mt_entry );
-! }
- goto cleanup_and_bail;
- }
-
- /*
- * Add the mount table entry to the mount table chain
-Index: newlibc.c
-===================================================================
-RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/newlibc.c,v
-retrieving revision 1.1.1.1
-retrieving revision 1.3
-diff -c -r1.1.1.1 -r1.3
-*** newlibc.c 14 Dec 2001 22:52:33 -0000 1.1.1.1
---- newlibc.c 16 Apr 2002 19:41:03 -0000 1.3
-***************
-*** 9,15 ****
- * found in the file LICENSE in this distribution or at
- * http://www.OARcorp.com/rtems/license.html.
- *
-! * $Id$
- *
- */
-
---- 9,15 ----
- * found in the file LICENSE in this distribution or at
- * http://www.OARcorp.com/rtems/license.html.
- *
-! * $Id$
- *
- */
-
-Index: privateenv.c
-===================================================================
-RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/privateenv.c,v
-retrieving revision 1.1.1.2
-diff -c -r1.1.1.2 privateenv.c
-*** privateenv.c 7 Mar 2002 01:53:51 -0000 1.1.1.2
---- privateenv.c 27 Oct 2002 18:35:34 -0000
-***************
-*** 23,47 ****
- #include <rtems/libio.h>
- #include <rtems/libio_.h>
-
- rtems_status_code rtems_libio_set_private_env(void) {
-! rtems_status_code sc;
-! rtems_id task_id;
-
- sc=rtems_task_ident(RTEMS_SELF,0,&task_id);
- if (sc != RTEMS_SUCCESSFUL) return sc;
-
- /* Only for the first time a malloc is necesary */
-! if (rtems_current_user_env==&rtems_global_user_env) {
-! sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,free);
-! if (sc != RTEMS_SUCCESSFUL) return sc;
-! rtems_current_user_env = malloc(sizeof(rtems_user_env_t));
-! if (!rtems_current_user_env)
- return RTEMS_NO_MEMORY;
- };
-
-- /* the side effect desired . chroot("/") */
- *rtems_current_user_env = rtems_global_user_env; /* get the global values*/
- rtems_current_user_env->task_id=task_id; /* mark the local values*/
-
- return RTEMS_SUCCESSFUL;
- }
---- 23,92 ----
- #include <rtems/libio.h>
- #include <rtems/libio_.h>
-
-+ extern Chain_Control rtems_filesystem_mount_table_control;
-+
-+ #define THE_ROOT_FS_LOC \
-+ (((rtems_filesystem_mount_table_entry_t*)\
-+ rtems_filesystem_mount_table_control.first)->mt_fs_root)
-+
-+ /* cleanup a user environment
-+ * NOTE: this must be called with
-+ * thread dispatching disabled!
-+ */
-+ static void
-+ free_user_env(rtems_user_env_t *env)
-+ {
-+ if (env != &rtems_global_user_env
-+ && --env->refcnt <= 0) {
-+ rtems_filesystem_freenode( &env->current_directory);
-+ rtems_filesystem_freenode( &env->root_directory);
-+ free(env);
-+ }
-+ }
-+
- rtems_status_code rtems_libio_set_private_env(void) {
-! rtems_status_code sc;
-! rtems_id task_id;
-! rtems_filesystem_location_info_t loc;
-
- sc=rtems_task_ident(RTEMS_SELF,0,&task_id);
- if (sc != RTEMS_SUCCESSFUL) return sc;
-
- /* Only for the first time a malloc is necesary */
-! if (rtems_current_user_env==&rtems_global_user_env) {
-! rtems_user_env_t *tmp = malloc(sizeof(rtems_user_env_t));
-! if (!tmp)
- return RTEMS_NO_MEMORY;
-+
-+ tmp->refcnt = 1;
-+
-+ sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,free_user_env);
-+ if (sc != RTEMS_SUCCESSFUL) {
-+ /* don't use free_user_env because the pathlocs are
-+ * not initialized yet
-+ */
-+ free(tmp);
-+ return sc;
-+ }
-+ rtems_current_user_env = tmp;
- };
-
- *rtems_current_user_env = rtems_global_user_env; /* get the global values*/
- rtems_current_user_env->task_id=task_id; /* mark the local values*/
-+
-+ /* get a clean root */
-+ rtems_filesystem_root = THE_ROOT_FS_LOC;
-+
-+ /* Clone the pathlocs. In contrast to most other
-+ * code we must _not_ free the original locs because
-+ * what we are trying to do here is forking off
-+ * clones.
-+ */
-+
-+ rtems_filesystem_evaluate_path("/", 0, &loc, 0);
-+ rtems_filesystem_root = loc;
-+ rtems_filesystem_evaluate_path("/", 0, &loc, 0);
-+ rtems_filesystem_current = loc;
-
- return RTEMS_SUCCESSFUL;
- }
-***************
-*** 51,56 ****
---- 96,115 ----
- * Task_id (remote) and RTEMS_SELF(current).
- */
-
-+ /* NOTE:
-+ *
-+ * THIS CODE HAS NO PROTECTION IMPLEMENTED
-+ *
-+ * Tasks who wish to share their environments must
-+ *
-+ * a) assert that no participants are concurrently
-+ * executing
-+ * libio_share_private_env() and/or libio_set_private_env()
-+ *
-+ * b) mutex access to rtems_filesystem_current, rtems_filesytem_root
-+ * while changing any of those (chdir(), chroot()).
-+ */
-+
- rtems_status_code rtems_libio_share_private_env(rtems_id task_id) {
- rtems_status_code sc;
- rtems_user_env_t * shared_user_env;
-***************
-*** 61,81 ****
-
- if (rtems_current_user_env->task_id==current_task_id) {
- /* kill the current user env & task_var*/
-! free(rtems_current_user_env);
- sc = rtems_task_variable_delete(RTEMS_SELF,(void*)&rtems_current_user_env);
- if (sc != RTEMS_SUCCESSFUL) return sc;
- };
-
- sc = rtems_task_variable_get(task_id,(void*)&rtems_current_user_env,
- (void*)&shared_user_env );
-! if (sc != RTEMS_SUCCESSFUL) return sc;
-
-! /* don't free(NULL'ed) at the task_delete. It is a shared var... */
-! sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,NULL);
-! if (sc != RTEMS_SUCCESSFUL) return sc;
-
- /* the current_user_env is the same pointer that remote env */
- rtems_current_user_env = shared_user_env;
-
- return RTEMS_SUCCESSFUL;
- }
---- 120,152 ----
-
- if (rtems_current_user_env->task_id==current_task_id) {
- /* kill the current user env & task_var*/
-! rtems_user_env_t *tmp = rtems_current_user_env;
- sc = rtems_task_variable_delete(RTEMS_SELF,(void*)&rtems_current_user_env);
- if (sc != RTEMS_SUCCESSFUL) return sc;
-+ free_user_env(tmp);
- };
-
-+ /* AT THIS POINT, rtems_current_user_env is DANGLING */
-+
- sc = rtems_task_variable_get(task_id,(void*)&rtems_current_user_env,
- (void*)&shared_user_env );
-! if (sc != RTEMS_SUCCESSFUL)
-! goto bailout;
-
-! sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,free_user_env);
-! if (sc != RTEMS_SUCCESSFUL)
-! goto bailout;
-
- /* the current_user_env is the same pointer that remote env */
- rtems_current_user_env = shared_user_env;
-
-+ /* increase the reference count */
-+ rtems_current_user_env->refcnt++;
-+
- return RTEMS_SUCCESSFUL;
-+
-+ bailout:
-+ /* fallback to the global env */
-+ rtems_current_user_env = &rtems_global_user_env;
-+ return sc;
- }
diff --git a/rtemsNfs/src/Makefile b/rtemsNfs/src/Makefile
deleted file mode 100644
index 6bb7321..0000000
--- a/rtemsNfs/src/Makefile
+++ /dev/null
@@ -1,105 +0,0 @@
-#
-# $Id$
-#
-# Templates/Makefile.leaf
-# Template leaf node Makefile
-#
-
-# if you have CEXP set this variable to 'YES'
-# and some "help" info will be compiled in.
-HAVE_CEXP=NO
-
-# C source names, if any, go here -- minus the .c
-C_PIECES_YES=rpcio nfs sock_mbuf xdr_mbuf dirutils rpcio.modini nfs.modini cexphelp
-C_PIECES_NO=rpcio nfs sock_mbuf xdr_mbuf
-
-C_PIECES=$(C_PIECES_$(HAVE_CEXP))
-
-C_FILES=$(C_PIECES:%=%.c)
-C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
-
-# C++ source names, if any, go here -- minus the .cc
-CC_PIECES=
-CC_FILES=$(CC_PIECES:%=%.cc)
-CC_O_FILES=$(CC_PIECES:%=${ARCH}/%.o)
-
-H_FILES=librtemsNfs.h rpcio.h
-INST_HEADERS=librtemsNfs.h
-
-# Assembly source names, if any, go here -- minus the .S
-S_PIECES=
-S_FILES=$(S_PIECES:%=%.S)
-S_O_FILES=$(S_FILES:%.S=${ARCH}/%.o)
-
-SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES)
-OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES) $(wildcard ../proto/$(ARCH)/*.o)
-
-PGMS=${ARCH}/nfs.obj ${ARCH}/rpcio.obj ${ARCH}/dirutils.obj
-
-LIBNAME=librtemsNfs.a
-
-LIB=$(ARCH)/$(LIBNAME)
-
-include $(RTEMS_MAKEFILE_PATH)/Makefile.inc
-include $(RTEMS_CUSTOM)
-include $(RTEMS_ROOT)/make/lib.cfg
-
-#
-# (OPTIONAL) Add local stuff here using +=
-#
-
-DEFS_CEXP_YES=-DHAVE_CEXP
-
-DEFINES += $(DEFS_CEXP_$(HAVE_CEXP))
-
-CPPFLAGS += -I. -I../proto
-
-CFLAGS +=
-
-#
-# CFLAGS_DEBUG_V are used when the `make debug' target is built.
-# To link your application with the non-optimized RTEMS routines,
-# uncomment the following line:
-# CFLAGS_DEBUG_V += -qrtems_debug
-#
-
-LDFLAGS +=
-
-#
-# Add your list of files to delete here. The config files
-# already know how to delete some stuff, so you may want
-# to just run 'make clean' first to see what gets missed.
-# 'make clobber' already includes 'make clean'
-#
-
-#CLEAN_ADDITIONS += xxx-your-debris-goes-here
-CLOBBER_ADDITIONS +=
-
-ifndef RTEMS_SITE_INSTALLDIR
-RTEMS_SITE_INSTALLDIR = $(PROJECT_RELEASE)
-endif
-
-%nfs.obj: %nfs.o %nfs.modini.o
- $(CC_FOR_TARGET) -Xlinker -r -nodefaultlibs $(CPU_CFLAGS) \
- -o $@ $^ -L../proto/$(ARCH) -lnfsprot
-
-%rpcio.obj: %rpcio.o %sock_mbuf.o %xdr_mbuf.o %rpcio.modini.o
- $(CC_FOR_TARGET) -Xlinker -r -nodefaultlibs $(CPU_CFLAGS) -o $@ $^
-
-%dirutils.obj: %dirutils.o
- $(CC_FOR_TARGET) -Xlinker -r -nodefaultlibs $(CPU_CFLAGS) -o $@ $^
-
-$(LIB): $(OBJS)
- $(make-library)
-
-all: ${ARCH} $(SRCS) $(PGMS) $(LIB)
-
-tar:
- echo not implemented
-
-# Install the program(s), appending _g or _p as appropriate.
-# for include files, just use $(INSTALL_CHANGE)
-install: all
- $(INSTALL_VARIANT) -m 555 ${PGMS} ${RTEMS_SITE_INSTALLDIR}/bin
- $(INSTALL_VARIANT) -m 555 ${LIB} ${RTEMS_SITE_INSTALLDIR}/lib
- $(INSTALL_CHANGE) -m 444 ${INST_HEADERS} ${RTEMS_SITE_INSTALLDIR}/lib/include
diff --git a/rtemsNfs/src/cexphelp.c b/rtemsNfs/src/cexphelp.c
deleted file mode 100644
index d062ed1..0000000
--- a/rtemsNfs/src/cexphelp.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <librtemsNfs.h>
-#include <cexpHelp.h>
-CEXP_HELP_TAB_BEGIN(rtemsNfs)
- HELP(
-"Mount a remote filesystem (NFS). The mount point (must not be a NFS dir)\n"
-"is created on the fly if not existing already.\n"
-"uid/gid to use may be specified:\n"
-" hostspec: [uid.gid@]hostname_or_ipaddr\n"
- , int, nfsMount, (char *hostspec, char *exportdir, char *mntpoint)
- ),
- HELP(
-"Print all currently mounted NFS directories to open file handle.\n"
-"Pass f = 0 to print to stdout\n"
- , int, nfsMountsShow, (FILE *f)
- ),
-CEXP_HELP_TAB_END
diff --git a/rtemsNfs/src/dirutils.c b/rtemsNfs/src/dirutils.c
deleted file mode 100644
index d6c47fe..0000000
--- a/rtemsNfs/src/dirutils.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/* $Id$ */
-
-/* very crude and basic fs utilities for testing the NFS */
-
-/* Till Straumann, <strauman@slac.stanford.edu>, 10/2002 */
-
-/*
- * Copyright 2002, Stanford University and
- * Till Straumann <strauman@slac.stanford.edu>
- *
- * Stanford Notice
- * ***************
- *
- * Acknowledgement of sponsorship
- * * * * * * * * * * * * * * * * *
- * This software was produced by the Stanford Linear Accelerator Center,
- * Stanford University, under Contract DE-AC03-76SFO0515 with the Department
- * of Energy.
- *
- * Government disclaimer of liability
- * - - - - - - - - - - - - - - - - -
- * Neither the United States nor the United States Department of Energy,
- * nor any of their employees, makes any warranty, express or implied,
- * or assumes any legal liability or responsibility for the accuracy,
- * completeness, or usefulness of any data, apparatus, product, or process
- * disclosed, or represents that its use would not infringe privately
- * owned rights.
- *
- * Stanford disclaimer of liability
- * - - - - - - - - - - - - - - - - -
- * Stanford University makes no representations or warranties, express or
- * implied, nor assumes any liability for the use of this software.
- *
- * This product is subject to the EPICS open license
- * - - - - - - - - - - - - - - - - - - - - - - - - -
- * Consult the LICENSE file or http://www.aps.anl.gov/epics/license/open.php
- * for more information.
- *
- * Maintenance of notice
- * - - - - - - - - - - -
- * In the interest of clarity regarding the origin and status of this
- * software, Stanford University requests that any recipient of it maintain
- * this notice affixed to any distribution by the recipient that contains a
- * copy or derivative of this software.
- */
-
-#ifdef __vxworks
-#include <vxWorks.h>
-#endif
-#include <stdio.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <stdlib.h>
-
-#ifdef HAVE_CEXP
-#include <cexpHelp.h>
-#endif
-
-#ifndef __vxworks
-int
-pwd(void)
-{
-char buf[MAXPATHLEN];
-
- if ( !getcwd(buf,MAXPATHLEN)) {
- perror("getcwd");
- return -1;
- } else {
- printf("%s\n",buf);
- }
- return 0;
-}
-
-static int
-ls_r(char *path, char *chpt, char *name, struct stat *buf)
-{
-char *t;
- sprintf(chpt, "/%s", name);
- if (lstat(path,buf)) {
- fprintf(stderr,"stat(%s): %s\n", path, strerror(errno));
- return -1;
- }
- switch ( buf->st_mode & S_IFMT ) {
- case S_IFSOCK:
- case S_IFIFO: t = "|"; break;
-
- default:
- case S_IFREG:
- case S_IFBLK:
- case S_IFCHR:
- t = ""; break;
- case S_IFDIR:
- t = "/"; break;
- case S_IFLNK:
- t = "@"; break;
- }
-
- printf("%10li, %10lib, %5i.%-5i 0%04o %s%s\n",
- buf->st_ino,
- buf->st_size,
- buf->st_uid,
- buf->st_gid,
- buf->st_mode & ~S_IFMT,
- name,
- t);
- *chpt = 0;
- return 0;
-}
-
-int
-ls(char *dir, char *opts)
-{
-struct dirent *de;
-char path[MAXPATHLEN+1];
-char *chpt;
-DIR *dp = 0;
-int rval = -1;
-struct stat buf;
-
- if ( !dir )
- dir = ".";
-
- strncpy(path, dir, MAXPATHLEN);
- path[MAXPATHLEN] = 0;
- chpt = path+strlen(path);
-
- if ( !(dp=opendir(dir)) ) {
- perror("opendir");
- goto cleanup;
- }
-
- while ( (de = readdir(dp)) ) {
- ls_r(path, chpt, de->d_name, &buf);
- }
-
- rval = 0;
-
-cleanup:
- if (dp)
- closedir(dp);
- return rval;
-}
-#endif
-
-#if 0
- fprintf(stderr, "usage: cp(""from"",[""to""[,""-f""]]\n");
- fprintf(stderr, " ""to""==NULL -> stdout\n");
- fprintf(stderr, " ""-f"" -> overwrite existing file\n");
-#endif
-
-int
-cp(char *from, char *to, char *opts)
-{
-struct stat st;
-int rval = -1;
-int fd = -1;
-FILE *fst = 0;
-FILE *tst = 0;
-int flags = O_CREAT | O_WRONLY | O_TRUNC | O_EXCL;
-
- if (from) {
-
- if ((fd=open(from,O_RDONLY,0)) < 0) {
- fprintf(stderr,
- "Opening %s for reading: %s\n",
- from,
- strerror(errno));
- goto cleanup;
- }
-
- if (fstat(fd, &st)) {
- fprintf(stderr,
- "rstat(%s): %s\n",
- from,
- strerror(errno));
- goto cleanup;
- }
-
-
- if (!S_ISREG(st.st_mode)) {
- fprintf(stderr,"Refuse to copy a non-regular file\n");
- errno = EINVAL;
- goto cleanup;
- }
- /* Now create a stream -- I experienced occasional weirdness
- * when circumventing the streams attached to fildno(stdin)
- * by reading/writing to the underlying fd's directly ->
- * for now we always go through buffered I/O...
- */
- if ( !(fst=fdopen(fd,"r")) ) {
- fprintf(stderr,
- "Opening input stream [fdopen()] failed: %s\n",
- strerror(errno));
- goto cleanup;
- }
- /* at this point, we have a stream and don't need 'fd' anymore */
- fd = -1;
-
- } else {
- fst = stdin;
- st.st_mode = 0644;
- }
-
- if (opts && strchr(opts,'f'))
- flags &= ~ O_EXCL;
-
- if (to) {
- if ( (fd=open(to,flags,st.st_mode)) < 0 ) {
- fprintf(stderr,
- "Opening %s for writing: %s\n",
- to,
- strerror(errno));
- goto cleanup;
- }
- if ( !(tst=fdopen(fd, "w")) ) {
- fprintf(stderr,
- "Opening output stream [fdopen()] failed: %s\n",
- strerror(errno));
- goto cleanup;
- }
- /* at this point we have a stream and don't need 'fd' anymore */
- fd = -1;
- } else {
- tst = stdout;
- }
-
- /* clear old errors */
- clearerr(fst);
- clearerr(tst);
-
- /* use macro versions on register vars; stdio is already buffered,
- * there's nothing to be gained by reading/writing blocks into
- * a secondary buffer...
- */
- {
- register int ch;
- register FILE *f = fst;
- register FILE *t = tst;
- while ( EOF != (ch = getc(f)) && EOF != putc(ch, t) )
- /* nothing else */;
- }
-
- if ( ferror(fst) ) {
- fprintf(stderr,"Read error: %s\n",strerror(errno));
- goto cleanup;
- }
- if ( ferror(tst) ) {
- fprintf(stderr,"Write error: %s\n",strerror(errno));
- goto cleanup;
- }
-
- rval = 0;
-
-cleanup:
-
- if ( fd >= 0 )
- close(fd);
-
- if ( fst ) {
- if ( from )
- fclose(fst);
- else
- clearerr(fst);
- }
- if ( tst ) {
- if ( to )
- fclose(tst);
- else {
- /* flush stdout */
- fflush(tst);
- clearerr(tst);
- }
- }
-
- return rval;
-}
-
-int
-ln(char *to, char *name, char *opts)
-{
- if (!to) {
- fprintf(stderr,"ln: need 'to' argument\n");
- return -1;
- }
- if (!name) {
- if ( !(name = strrchr(to,'/')) ) {
- fprintf(stderr,
- "ln: 'unable to link %s to %s\n",
- to,to);
- return -1;
- }
- name++;
- }
- if (opts || strchr(opts,'s')) {
- if (symlink(name,to)) {
- fprintf(stderr,"symlink: %s\n",strerror(errno));
- return -1;
- }
- } else {
- if (link(name,to)) {
- fprintf(stderr,"hardlink: %s\n",strerror(errno));
- return -1;
- }
- }
- return 0;
-}
-
-int
-rm(char *path)
-{
- return unlink(path);
-}
-
-int
-cd(char *path)
-{
- return chdir(path);
-}
-
-#ifdef HAVE_CEXP
-static CexpHelpTabRec _cexpHelpTabDirutils[] __attribute__((unused)) = {
- HELP(
-"copy a file: cp(""from"",[""to""[,""-f""]])\n\
- from = NULL <-- stdin\n\
- to = NULL --> stdout\n\
- option -f: overwrite existing file\n",
- int,
- cp, (char *from, char *to, char *options)
- ),
- HELP(
-"list a directory: ls([""dir""])\n",
- int,
- ls, (char *dir)
- ),
- HELP(
-"remove a file\n",
- int,
- rm, (char *path)
- ),
- HELP(
-"change the working directory\n",
- int,
- cd, (char *path)
- ),
- HELP(
-"create a link: ln(""to"",""name"",""[-s]""\n\
- -s creates a symlink\n",
- int,
- ln, (char *to, char *name, char *options)
- ),
- HELP("",,0,)
-};
-#endif
diff --git a/rtemsNfs/src/librtemsNfs.h b/rtemsNfs/src/librtemsNfs.h
deleted file mode 100644
index 880842c..0000000
--- a/rtemsNfs/src/librtemsNfs.h
+++ /dev/null
@@ -1,158 +0,0 @@
-#ifndef LIB_RTEMS_NFS_CLIENT_H
-#define LIB_RTEMS_NFS_CLIENT_H
-/* $Id$ */
-
-/* public interface to the NFS client library for RTEMS */
-
-/* Author: Till Straumann <strauman@slac.stanford.edu> 2002-2003 */
-
-/*
- * Copyright 2002-2003, Stanford University and
- * Till Straumann <strauman@slac.stanford.edu>
- *
- * Stanford Notice
- * ***************
- *
- * Acknowledgement of sponsorship
- * * * * * * * * * * * * * * * * *
- * This software was produced by the Stanford Linear Accelerator Center,
- * Stanford University, under Contract DE-AC03-76SFO0515 with the Department
- * of Energy.
- *
- * Government disclaimer of liability
- * - - - - - - - - - - - - - - - - -
- * Neither the United States nor the United States Department of Energy,
- * nor any of their employees, makes any warranty, express or implied,
- * or assumes any legal liability or responsibility for the accuracy,
- * completeness, or usefulness of any data, apparatus, product, or process
- * disclosed, or represents that its use would not infringe privately
- * owned rights.
- *
- * Stanford disclaimer of liability
- * - - - - - - - - - - - - - - - - -
- * Stanford University makes no representations or warranties, express or
- * implied, nor assumes any liability for the use of this software.
- *
- * This product is subject to the EPICS open license
- * - - - - - - - - - - - - - - - - - - - - - - - - -
- * Consult the LICENSE file or http://www.aps.anl.gov/epics/license/open.php
- * for more information.
- *
- * Maintenance of notice
- * - - - - - - - - - - -
- * In the interest of clarity regarding the origin and status of this
- * software, Stanford University requests that any recipient of it maintain
- * this notice affixed to any distribution by the recipient that contains a
- * copy or derivative of this software.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <rtems.h>
-#include <rtems/libio.h>
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <netdb.h>
-#include <ctype.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-
-#ifdef HAVE_CEXP_H
-#include <cexpHelp.h>
-#endif
-
-/* RPCIO driver interface.
- * If you need RPCIO for other purposes than NFS
- * you may want to include <rpcio.h>
-#include "rpcio.h"
- */
-
-/* Initialize the driver
- *
- * RETURNS: 0 on success, -1 on failure
- */
-int
-rpcUdpInit(void);
-
-/* Cleanup/Stop
- *
- * RETURNS: 0 on success, nonzero if still in use
- */
-int
-rpcUdpCleanup(void);
-
-/* NFS driver interface */
-
-/* Initialize the NFS driver.
- *
- * NOTE: The RPCIO driver must have been initialized prior to
- * calling this.
- *
- * ARGS: depth of the small and big
- * transaction pools, i.e. how
- * many transactions (buffers)
- * should always be kept around.
- *
- * (If more transactions are needed,
- * they are created and destroyed
- * on the fly).
- *
- * Supply zero values to have the
- * driver chose reasonable defaults.
- */
-int
-nfsInit(int smallPoolDepth, int bigPoolDepth);
-
-/* Driver cleanup code
- *
- * RETURNS: 0 on success, nonzero if still in use
- */
-int
-nfsCleanup(void);
-
-/* Dump a list of the currently mounted NFS to a file
- * (stdout is used in case f==NULL)
- */
-int
-nfsMountsShow(FILE *f);
-
-/* convenience wrapper
- *
- * NOTE: this routine calls NON-REENTRANT
- * gethostbyname() if the host is
- * not in 'dot' notation.
- */
-int
-nfsMount(char *uidhost, char *path, char *mntpoint);
-
-/* Alternatively, a pointer to the filesystem operations
- * table can be supplied to the native RTEMS (NON-POSIX!)
- * 'mount()' call.
- * Supply a "<host.in.ip.dot.notation>:<path>" string
- * for 'device' argument to 'mount()'.
- */
-extern struct _rtems_filesystem_operations_table nfs_fs_ops;
-
-/* A utility routine to find the path leading to a
- * rtems_filesystem_location_info_t node.
- *
- * This should really be present in libcsupport...
- *
- * INPUT: 'loc' and a buffer 'buf' (length 'len') to hold the
- * path.
- * OUTPUT: path copied into 'buf'
- *
- * RETURNS: 0 on success, RTEMS error code on error.
- */
-rtems_status_code
-rtems_filesystem_resolve_location(char *buf, int len, rtems_filesystem_location_info_t *loc);
-#endif
diff --git a/rtemsNfs/src/nfs.c b/rtemsNfs/src/nfs.c
deleted file mode 100644
index 41735fe..0000000
--- a/rtemsNfs/src/nfs.c
+++ /dev/null
@@ -1,3390 +0,0 @@
-/* $Id$ */
-
-/* NFS client implementation for RTEMS; hooks into the RTEMS filesystem */
-
-/* Author: Till Straumann <strauman@slac.stanford.edu> 2002 */
-
-/*
- * Copyright 2002, Stanford University and
- * Till Straumann <strauman@slac.stanford.edu>
- *
- * Stanford Notice
- * ***************
- *
- * Acknowledgement of sponsorship
- * * * * * * * * * * * * * * * * *
- * This software was produced by the Stanford Linear Accelerator Center,
- * Stanford University, under Contract DE-AC03-76SFO0515 with the Department
- * of Energy.
- *
- * Government disclaimer of liability
- * - - - - - - - - - - - - - - - - -
- * Neither the United States nor the United States Department of Energy,
- * nor any of their employees, makes any warranty, express or implied,
- * or assumes any legal liability or responsibility for the accuracy,
- * completeness, or usefulness of any data, apparatus, product, or process
- * disclosed, or represents that its use would not infringe privately
- * owned rights.
- *
- * Stanford disclaimer of liability
- * - - - - - - - - - - - - - - - - -
- * Stanford University makes no representations or warranties, express or
- * implied, nor assumes any liability for the use of this software.
- *
- * This product is subject to the EPICS open license
- * - - - - - - - - - - - - - - - - - - - - - - - - -
- * Consult the LICENSE file or http://www.aps.anl.gov/epics/license/open.php
- * for more information.
- *
- * Maintenance of notice
- * - - - - - - - - - - -
- * In the interest of clarity regarding the origin and status of this
- * software, Stanford University requests that any recipient of it maintain
- * this notice affixed to any distribution by the recipient that contains a
- * copy or derivative of this software.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <rtems.h>
-#include <rtems/libio.h>
-#include <rtems/libio_.h>
-#include <rtems/seterr.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <netdb.h>
-#include <ctype.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-
-#include <nfs_prot.h>
-#include <mount_prot.h>
-
-#include "rpcio.h"
-
-#ifdef HAVE_CEXP_H
-#include <cexpHelp.h>
-#endif
-
-
-/* Configurable parameters */
-
-/* Estimated average length of a filename (including terminating 0).
- * This was calculated by doing
- *
- * find <some root> -print -exec basename '{}' \; > feil
- * wc feil
- *
- * AVG_NAMLEN = (num_chars + num_lines)/num_lines
- */
-#define CONFIG_AVG_NAMLEN 10
-
-#define CONFIG_NFS_SMALL_XACT_SIZE 800 /* size of RPC arguments for non-write ops */
-/* lifetime of NFS attributes in a NfsNode;
- * the time is in seconds and the lifetime is
- * infinite if the symbol is #undef
- */
-#define CONFIG_ATTR_LIFETIME 10/*secs*/
-
-/* dont change this without changing the maximal write size */
-#define CONFIG_NFS_BIG_XACT_SIZE UDPMSGSIZE /* dont change this */
-
-/* The real values for these are specified further down */
-#define NFSCALL_TIMEOUT (&_nfscalltimeout)
-#define MNTCALL_TIMEOUT (&_nfscalltimeout)
-static struct timeval _nfscalltimeout = { 10, 0 }; /* {secs, us } */
-
-/* More or less fixed constants; in particular, NFS3 is not supported */
-#define DELIM '/'
-#define HOSTDELIM ':'
-#define UPDIR ".."
-#define UIDSEP '@'
-#define NFS_VERSION_2 NFS_VERSION
-
-/* we use a dynamically assigned major number */
-#define NFS_MAJOR (nfsGlob.nfs_major)
-
-
-/* NOTE: RTEMS (ss-20020301) uses a 'short st_ino' type :-( but the
- * NFS fileid is 32 bit.
- * As a workarount, we merge the upper 16bits of the fileid into the
- * minor device no. Hence, it is still possible to uniquely identify
- * a file by looking at its device number (major = nfs, minor = part
- * of the fileid + our 'nfs-id' identifier).
- *
- * This has an impact on performance, as e.g. getcwd() stats() all
- * directory entries when it believes it has crossed a mount point
- * (a.st_dev != b.st_dev).
- *
- * OTOH, it also might cause node comparison failure! E.g. 'getcwd()'
- * assumes that two nodes residing in the same directory must be located
- * on the same device and hence compares 'st_ino' only.
- * If two files in the same directory have the same inode number
- * modulo 2^16, they will be considered equal (although their device
- * number doesn't match - getcwd doesn't look at it).
- *
- * Other software might or might not be affected.
- *
- * The only clean solution to this problem is bumping up the size of
- * 'ino_t' at least to 'long'.
- * Note that this requires _all_ software (libraries etc.) to be
- * recompiled.
- */
-
-#define NFS_MAKE_DEV_T_INO_HACK(node) \
- rtems_filesystem_make_dev_t( NFS_MAJOR, \
- (((node)->nfs->id)<<16) | (SERP_ATTR((node)).fileid >> 16) )
-
-/* use our 'nfs id' and the server's fsid for the minor device number
- * this should be fairly unique
- */
-#define NFS_MAKE_DEV_T(node) \
- rtems_filesystem_make_dev_t( NFS_MAJOR, \
- (((node)->nfs->id)<<16) | (SERP_ATTR((node)).fsid & ((1<<16)-1)) )
-
-#define DIRENT_HEADER_SIZE ( sizeof(struct dirent) - \
- sizeof( ((struct dirent *)0)->d_name ) )
-
-
-/* debugging flags */
-#define DEBUG_COUNT_NODES (1<<0)
-#define DEBUG_TRACK_NODES (1<<1)
-#define DEBUG_EVALPATH (1<<2)
-#define DEBUG_READDIR (1<<3)
-#define DEBUG_SYSCALLS (1<<4)
-#define DEBUG_INIT (1<<5)
-
-/* #define DEBUG ( DEBUG_SYSCALLS | DEBUG_COUNT_NODES ) */
-
-#ifdef DEBUG
-#define STATIC
-#else
-#define STATIC static
-#endif
-
-#define MUTEX_ATTRIBUTES (RTEMS_LOCAL | \
- RTEMS_PRIORITY | \
- RTEMS_INHERIT_PRIORITY | \
- RTEMS_BINARY_SEMAPHORE)
-
-#define LOCK(s) do { \
- rtems_semaphore_obtain((s), \
- RTEMS_WAIT, \
- RTEMS_NO_TIMEOUT); \
- } while (0)
-
-#define UNLOCK(s) do { rtems_semaphore_release((s)); \
- } while (0)
-
-/*****************************************
- Types with Associated XDR Routines
- *****************************************/
-
-/* a string buffer with a maximal length.
- * If the buffer pointer is NULL, it is updated
- * with an appropriately allocated area.
- */
-typedef struct strbuf {
- char *buf;
- u_int max;
-} strbuf;
-
-static bool_t
-xdr_strbuf(XDR *xdrs, strbuf *obj)
-{
- return xdr_string(xdrs, &obj->buf, obj->max);
-}
-
-/* Read 'readlink' results into a 'strbuf'.
- * This is convenient as it avoids
- * one extra step of copying / lenght
- * checking.
- */
-typedef struct readlinkres_strbuf {
- nfsstat status;
- strbuf strbuf;
-} readlinkres_strbuf;
-
-static bool_t
-xdr_readlinkres_strbuf(XDR *xdrs, readlinkres_strbuf *objp)
-{
- if ( !xdr_nfsstat(xdrs, &objp->status) )
- return FALSE;
-
- if ( NFS_OK == objp->status ) {
- if ( !xdr_string(xdrs, &objp->strbuf.buf, objp->strbuf.max) )
- return FALSE;
- }
- return TRUE;
-}
-
-
-/* DirInfoRec is used instead of dirresargs
- * to convert recursion into iteration. The
- * 'rpcgen'erated xdr_dirresargs ends up
- * doing nested calls when unpacking the
- * 'next' pointers.
- */
-
-typedef struct DirInfoRec_ {
- readdirargs readdirargs;
- /* clone of the 'readdirres' fields;
- * the cookie is put into the readdirargs above
- */
- nfsstat status;
- char *buf, *ptr;
- int len;
- bool_t eofreached;
-} DirInfoRec, *DirInfo;
-
-/* this deals with one entry / record */
-static bool_t
-xdr_dir_info_entry(XDR *xdrs, DirInfo di)
-{
-union {
- char nambuf[NFS_MAXNAMLEN+1];
- nfscookie cookie;
-} dummy;
-struct dirent *pde = (struct dirent *)di->ptr;
-u_int fileid;
-char *name;
-register int nlen = 0,len,naligned = 0;
-nfscookie *pcookie;
-
- len = di->len;
-
- if ( !xdr_u_int(xdrs, &fileid) )
- return FALSE;
-
- /* we must pass the address of a char* */
- name = (len > NFS_MAXNAMLEN) ? pde->d_name : dummy.nambuf;
-
- if ( !xdr_filename(xdrs, &name) ) {
- return FALSE;
- }
-
- if (len >= 0) {
- nlen = strlen(name);
- naligned = nlen + 1 /* string delimiter */ + 3 /* alignment */;
- naligned &= ~3;
- len -= naligned;
- }
-
- /* if the cookie goes into the DirInfo, we hope this doesn't fail
- * - the caller ends up with an invalid readdirargs cookie otherwise...
- */
- pcookie = (len >= 0) ? &di->readdirargs.cookie : &dummy.cookie;
- if ( !xdr_nfscookie(xdrs, pcookie) ) {
- return FALSE;
- }
-
- di->len = len;
- /* adjust the buffer pointer */
- if (len >= 0) {
- pde->d_ino = fileid;
- pde->d_namlen = nlen;
- pde->d_off = di->ptr - di->buf;
- if (name == dummy.nambuf) {
- memcpy(pde->d_name, dummy.nambuf, nlen + 1);
- }
- pde->d_reclen = DIRENT_HEADER_SIZE + naligned;
- di->ptr += pde->d_reclen;
- }
-
- return TRUE;
-}
-
-/* this routine loops over all entries */
-static bool_t
-xdr_dir_info(XDR *xdrs, DirInfo di)
-{
-DirInfo dip;
-
- if ( !xdr_nfsstat(xdrs, &di->status) )
- return FALSE;
-
- if ( NFS_OK != di->status )
- return TRUE;
-
- dip = di;
-
- while (dip) {
- /* reserve space for the dirent 'header' - we assume it's word aligned! */
-#ifdef DEBUG
- assert( DIRENT_HEADER_SIZE % 4 == 0 );
-#endif
- dip->len -= DIRENT_HEADER_SIZE;
-
- /* we pass a 0 size - size is unused since
- * we always pass a non-NULL pointer
- */
- if ( !xdr_pointer(xdrs, (void*)&dip, 0 /* size */, (xdrproc_t)xdr_dir_info_entry) )
- return FALSE;
- }
-
- if ( ! xdr_bool(xdrs, &di->eofreached) )
- return FALSE;
-
- /* if everything fits into the XDR buffer but not the user's buffer,
- * they must resume reading from where xdr_dir_info_entry() started
- * skipping and 'eofreached' needs to be adjusted
- */
- if ( di->len < 0 && di->eofreached )
- di->eofreached = FALSE;
-
- return TRUE;
-}
-
-
-/* a type better suited for node operations
- * than diropres.
- * fattr and fhs are swapped so parts of this
- * structure may be used as a diroparg which
- * is practical when looking up paths.
- */
-
-/* Macro for accessing serporid fields
- */
-#define SERP_ARGS(node) ((node)->serporid.serporid_u.serporid.arg_u)
-#define SERP_ATTR(node) ((node)->serporid.serporid_u.serporid.attributes)
-#define SERP_FILE(node) ((node)->serporid.serporid_u.serporid.file)
-
-
-typedef struct serporidok {
- fattr attributes;
- nfs_fh file;
- union {
- struct {
- filename name;
- } diroparg;
- struct {
- sattr attributes;
- } sattrarg;
- struct {
- u_int offset;
- u_int count;
- u_int totalcount;
- } readarg;
- struct {
- u_int beginoffset;
- u_int offset;
- u_int totalcount;
- struct {
- u_int data_len;
- char* data_val;
- } data;
- } writearg;
- struct {
- filename name;
- sattr attributes;
- } createarg;
- struct {
- filename name;
- diropargs to;
- } renamearg;
- struct {
- diropargs to;
- } linkarg;
- struct {
- filename name;
- nfspath to;
- sattr attributes;
- } symlinkarg;
- struct {
- nfscookie cookie;
- u_int count;
- } readdirarg;
- } arg_u;
-} serporidok;
-
-typedef struct serporid {
- nfsstat status;
- union {
- serporidok serporid;
- } serporid_u;
-} serporid;
-
-/* an XDR routine to encode/decode the inverted diropres
- * into an nfsnodestat;
- *
- * NOTE: this routine only acts on
- * - 'serporid.status'
- * - 'serporid.file'
- * - 'serporid.attributes'
- * and leaves the 'arg_u' alone.
- *
- * The idea is that a 'diropres' is read into 'serporid'
- * which can then be used as an argument to subsequent
- * NFS-RPCs (after filling in the node's arg_u).
- */
-static bool_t
-xdr_serporidok(XDR *xdrs, serporidok *objp)
-{
- if (!xdr_nfs_fh (xdrs, &objp->file))
- return FALSE;
- if (!xdr_fattr (xdrs, &objp->attributes))
- return FALSE;
- return TRUE;
-}
-
-static bool_t
-xdr_serporid(XDR *xdrs, serporid *objp)
-{
- if (!xdr_nfsstat (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS_OK:
- if (!xdr_serporidok(xdrs, &objp->serporid_u.serporid))
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
-
-/*****************************************
- Data Structures and Types
- *****************************************/
-
-/* 'time()' hack with less overhead; */
-
-/* assume reading a long word is atomic */
-#define READ_LONG_IS_ATOMIC
-
-typedef uint32_t TimeStamp;
-
-static inline TimeStamp
-nowSeconds(void)
-{
-register uint32_t rval;
-#ifndef READ_LONG_IS_ATOMIC
-rtems_interrupt_level l;
-
- rtems_interrupt_disable(level);
-#endif
-
- rval = _TOD_Seconds_since_epoch;
-
-#ifndef READ_LONG_IS_ATOMIC
- rtems_interrupt_enable(level);
-#endif
- return rval;
-}
-
-
-/* Per mounted FS structure */
-typedef struct NfsRec_ {
- /* the NFS server we're talking to.
- */
- RpcUdpServer server;
- /* statistics; how many NfsNodes are
- * currently alive.
- */
- volatile int nodesInUse;
-#if DEBUG & DEBUG_COUNT_NODES
- /* statistics; how many 'NfsNode.str'
- * strings are currently allocated.
- */
- volatile int stringsInUse;
-#endif
- /* A small number who uniquely
- * identifies a mounted NFS within
- * this driver (i.e. this NfsRec).
- * Each time a NFS is mounted, the
- * global ID counter is incremented
- * and its value is assigned to the
- * newly created NfsRec.
- */
- u_short id;
- /* Our RTEMS filesystem mt_entry
- */
- rtems_filesystem_mount_table_entry_t *mt_entry;
- /* Next NfsRec on a linked list who
- * is anchored at nfsGlob
- */
- struct NfsRec_ *next;
- /* Who we pretend we are
- */
- u_long uid,gid;
-} NfsRec, *Nfs;
-
-typedef struct NfsNodeRec_ {
- /* This holds this node's attributes
- * (stats) and its nfs filehandle.
- * It also contains room for nfs rpc
- * arguments.
- */
- serporid serporid;
- /* The arguments we used when doing
- * the 'lookup' call for this node.
- * We need this information (especially
- * the directory FH) for performing
- * certain operations on this
- * node (in particular: for unlinking
- * it from a parent directory)
- */
- diropargs args;
- /* FS this node belongs to
- */
- Nfs nfs;
- /* A buffer for the string the
- * args.name points to.
- * We need this because args.name might
- * temporarily point to strings on the
- * stack. Duplicates are allocated from
- * the heap and attached to 'str' so
- * they can be released as appropriate.
- */
- char *str;
- /* A timestamp for the stats
- */
- TimeStamp age;
-} NfsNodeRec, *NfsNode;
-
-/*****************************************
- Forward Declarations
- *****************************************/
-
-static int nfs_readlink(
- rtems_filesystem_location_info_t *loc, /* IN */
- char *buf, /* OUT */
- size_t len
-);
-
-static int updateAttr(NfsNode node, int force);
-
-/* Mask bits when setting attributes.
- * Only the 'arg' fields with their
- * corresponding bit set in the mask
- * will be used. The others are left
- * unchanged.
- * The 'TOUCH' bits instruct nfs_sattr()
- * to update the respective time
- * fields to the current time
- */
-#define SATTR_MODE (1<<0)
-#define SATTR_UID (1<<1)
-#define SATTR_GID (1<<2)
-#define SATTR_SIZE (1<<3)
-#define SATTR_ATIME (1<<4)
-#define SATTR_TOUCHA (1<<5)
-#define SATTR_MTIME (1<<6)
-#define SATTR_TOUCHM (1<<7)
-#define SATTR_TOUCH (SATTR_TOUCHM | SATTR_TOUCHA)
-
-static int
-nfs_sattr(NfsNode node, sattr *arg, u_long mask);
-
-extern struct _rtems_filesystem_operations_table nfs_fs_ops;
-static struct _rtems_filesystem_file_handlers_r nfs_file_file_handlers;
-static struct _rtems_filesystem_file_handlers_r nfs_dir_file_handlers;
-static struct _rtems_filesystem_file_handlers_r nfs_link_file_handlers;
-static rtems_driver_address_table drvNfs;
-
-int
-nfsMountsShow(FILE*);
-
-rtems_status_code
-rtems_filesystem_resolve_location(char *buf, int len, rtems_filesystem_location_info_t *loc);
-
-
-/*****************************************
- Inline Routines
- *****************************************/
-
-
-/* * * * * * * * * * * * * * * * * *
- Trivial Operations on a NfsNode
- * * * * * * * * * * * * * * * * * */
-
-/* determine if a location 'l' is an NFS root node */
-static inline int
-locIsRoot(rtems_filesystem_location_info_t *l)
-{
-NfsNode me = (NfsNode) l->node_access;
-NfsNode r;
- r = (NfsNode)l->mt_entry->mt_fs_root.node_access;
- return SERP_ATTR(r).fileid == SERP_ATTR(me).fileid &&
- SERP_ATTR(r).fsid == SERP_ATTR(me).fsid;
-}
-
-/* determine if a location 'l' is an NFS node */
-static inline int
-locIsNfs(rtems_filesystem_location_info_t *l)
-{
- return l->ops == &nfs_fs_ops;
-}
-
-/* determine if two locations refer to the
- * same entity. We know that 'nfsloc' is a
- * location inside nfs. However, we needn't
- * know anything about 'anyloc'.
- */
-static inline int
-locAreEqual(
- rtems_filesystem_location_info_t *nfsloc,
- rtems_filesystem_location_info_t *anyloc
-)
-{
-NfsNode na = (NfsNode) nfsloc->node_access;
-NfsNode nb;
-
- if (!locIsNfs(anyloc))
- return 0;
-
- nb = (NfsNode) anyloc->node_access;
-
- if (na->nfs != nb->nfs)
- return 0;
-
- updateAttr(nb, 0);
-
- return SERP_ATTR(na).fileid == SERP_ATTR(nb).fileid &&
- SERP_ATTR(na).fsid == SERP_ATTR(nb).fsid;
-}
-
-
-
-/*****************************************
- Global Variables
- *****************************************/
-
-/* These are (except for MAXNAMLEN/MAXPATHLEN) copied from IMFS */
-
-static rtems_filesystem_limits_and_options_t
-nfs_limits_and_options = {
- 5, /* link_max */
- 6, /* max_canon */
- 7, /* max_input */
- NFS_MAXNAMLEN, /* name_max */
- NFS_MAXPATHLEN, /* path_max */
- 2, /* pipe_buf */
- 1, /* posix_async_io */
- 2, /* posix_chown_restrictions */
- 3, /* posix_no_trunc */
- 4, /* posix_prio_io */
- 5, /* posix_sync_io */
- 6 /* posix_vdisable */
-};
-
-/* size of an encoded 'entry' object */
-static int dirres_entry_size;
-
-/* Global stuff and statistics */
-static struct nfsstats {
- /* A lock for protecting the
- * linked ist of mounted NFS
- * and the num_mounted_fs field
- */
- rtems_id llock;
- /* A lock for protecting misc
- * stuff within the driver.
- * The lock must only be held
- * for short periods of time.
- */
- rtems_id lock;
- /* Our major number as assigned
- * by RTEMS
- */
- rtems_device_major_number nfs_major;
- /* The number of currently
- * mounted NFS
- */
- int num_mounted_fs;
- /* A list of the currently
- * mounted NFS
- */
- struct NfsRec_ *mounted_fs;
- /* A counter for allocating
- * unique IDs to each mounted
- * NFS.
- * Assume we are not going to
- * do more than 16k mounts
- * during the system lifetime
- */
- u_short fs_ids;
-} nfsGlob = {0/* IMPORTANT */};
-
-
-/* Two pools of RPC transactions;
- * One with small send buffers
- * the other with a big one.
- * The actual size of the small
- * buffer is configurable (see top).
- *
- * Note: The RX buffers are always
- * big
- */
-static RpcUdpXactPool smallPool = 0;
-static RpcUdpXactPool bigPool = 0;
-
-
-/*****************************************
- Implementation
- *****************************************/
-
-/* Create a Nfs object. This is
- * per-mounted NFS information.
- *
- * ARGS: The Nfs server handle.
- *
- * RETURNS: Nfs on success,
- * NULL on failure with
- * errno set
- *
- * NOTE: The submitted server
- * object is 'owned' by
- * this Nfs and will be
- * destroyed by nfsDestroy()
- */
-static Nfs
-nfsCreate(RpcUdpServer server)
-{
-Nfs rval = calloc(1,sizeof(*rval));
-
- if (rval) {
- rval->server = server;
- LOCK(nfsGlob.llock);
- rval->next = nfsGlob.mounted_fs;
- nfsGlob.mounted_fs = rval;
- UNLOCK(nfsGlob.llock);
- } else {
- errno = ENOMEM;
- }
- return rval;
-}
-
-/* Destroy an Nfs object and
- * its associated server
- */
-static void
-nfsDestroy(Nfs nfs)
-{
-register Nfs prev;
- if (!nfs)
- return;
-
- LOCK(nfsGlob.llock);
- if (nfs == nfsGlob.mounted_fs)
- nfsGlob.mounted_fs = nfs->next;
- else {
- for (prev = nfsGlob.mounted_fs;
- prev && prev->next != nfs;
- prev = prev->next)
- /* nothing else to do */;
- assert( prev );
- prev->next = nfs->next;
- }
- UNLOCK(nfsGlob.llock);
-
- nfs->next = 0; /* paranoia */
- rpcUdpServerDestroy(nfs->server);
- free(nfs);
-}
-
-/*
- * Create a Node. The node will
- * be associated with a particular
- * mounted NFS identified by 'nfs'
- * Optionally, a NFS file handle
- * may be copied into this node.
- *
- * ARGS: nfs of the NFS this node
- * belongs to.
- * NFS file handle identifying
- * this node.
- * RETURNS: node on success,
- * NULL on failure with errno
- * set.
- *
- * NOTE: The caller of this routine
- * is responsible for copying
- * a NFS file handle if she
- * choses to pass a NULL fh.
- *
- * The driver code assumes the
- * a node always has a valid
- * NFS filehandle and file
- * attributes (unless the latter
- * are aged).
- */
-static NfsNode
-nfsNodeCreate(Nfs nfs, nfs_fh *fh)
-{
-NfsNode rval = malloc(sizeof(*rval));
-unsigned long flags;
-
-#if DEBUG & DEBUG_TRACK_NODES
- fprintf(stderr,"NFS: creating a node\n");
-#endif
-
- if (rval) {
- if (fh)
- memcpy( &SERP_FILE(rval), fh, sizeof(*fh) );
- rtems_interrupt_disable(flags);
- nfs->nodesInUse++;
- rtems_interrupt_enable(flags);
- rval->nfs = nfs;
- rval->str = 0;
- } else {
- errno = ENOMEM;
- }
-
- return rval;
-}
-
-/* destroy a node */
-static void
-nfsNodeDestroy(NfsNode node)
-{
-unsigned long flags;
-
-#if DEBUG & DEBUG_TRACK_NODES
- fprintf(stderr,"NFS: destroying a node\n");
-#endif
-#if 0
- if (!node)
- return;
- /* this probably does nothing... */
- xdr_free(xdr_serporid, &node->serporid);
-#endif
-
- rtems_interrupt_disable(flags);
- node->nfs->nodesInUse--;
-#if DEBUG & DEBUG_COUNT_NODES
- if (node->str)
- node->nfs->stringsInUse--;
-#endif
- rtems_interrupt_enable(flags);
-
- if (node->str)
- free(node->str);
-
- free(node);
-}
-
-/* Clone a given node (AKA copy constructor),
- * i.e. create an exact copy.
- *
- * ARGS: node to clone
- * RETURNS: new node on success
- * NULL on failure with errno set.
- *
- * NOTE: a string attached to 'str'
- * is cloned as well. Outdated
- * attributes (of the new copy
- * only) will be refreshed
- * (if unsuccessful, this could
- * be a reason for failure to
- * clone a node).
- */
-static NfsNode
-nfsNodeClone(NfsNode node)
-{
-NfsNode rval = nfsNodeCreate(node->nfs, 0);
-
- if (rval) {
- *rval = *node;
-
- /* must clone the string also */
- if (node->str) {
- rval->args.name = rval->str = strdup(node->str);
- if (!rval->str) {
- nfsNodeDestroy(rval);
- return 0;
- }
-#if DEBUG & DEBUG_COUNT_NODES
- { unsigned long flags;
- rtems_interrupt_disable(flags);
- node->nfs->stringsInUse++;
- rtems_interrupt_enable(flags);
- }
-#endif
- }
-
- /* possibly update the stats */
- if (updateAttr(rval, 0 /* only if necessary */)) {
- nfsNodeDestroy(rval);
- return 0;
- }
- }
- return rval;
-}
-
-/* Initialize the driver.
- *
- * ARGS: depth of the small and big
- * transaction pools, i.e. how
- * many transactions (buffers)
- * should always be kept around.
- *
- * (If more transactions are needed,
- * they are created and destroyed
- * on the fly).
- */
-void
-nfsInit(int smallPoolDepth, int bigPoolDepth)
-{
-entry dummy;
-
- fprintf(stderr,"This is RTEMS-NFS Release $Name$\n");
- fprintf(stderr,"($Id$)\n\n");
- fprintf(stderr,"Till Straumann, Stanford/SLAC/SSRL 2002\n");
- fprintf(stderr,"See LICENSE file for licensing info\n");
-
- /* Get a major number */
-
- if (RTEMS_SUCCESSFUL != rtems_io_register_driver(0, &drvNfs, &nfsGlob.nfs_major)) {
- fprintf(stderr,"Registering NFS driver failed - %s\n", strerror(errno));
- return;
- }
-
- if (0==smallPoolDepth)
- smallPoolDepth = 20;
- if (0==bigPoolDepth)
- bigPoolDepth = 10;
-
- /* it's crucial to zero out the 'next' pointer
- * because it terminates the xdr_entry recursion
- *
- * we also must make the filename some non-zero
- * char pointer!
- */
-
- memset(&dummy, 0, sizeof(dummy));
-
- dummy.nextentry = 0;
- dummy.name = "somename"; /* guess average length of a filename */
- dirres_entry_size = xdr_sizeof((xdrproc_t)xdr_entry, &dummy);
-
- assert( smallPool = rpcUdpXactPoolCreate(
- NFS_PROGRAM,
- NFS_VERSION_2,
- CONFIG_NFS_SMALL_XACT_SIZE,
- smallPoolDepth) );
-
- assert( bigPool = rpcUdpXactPoolCreate(
- NFS_PROGRAM,
- NFS_VERSION_2,
- CONFIG_NFS_BIG_XACT_SIZE,
- bigPoolDepth) );
-
- assert( RTEMS_SUCCESSFUL == rtems_semaphore_create(
- rtems_build_name('N','F','S','l'),
- 1,
- MUTEX_ATTRIBUTES,
- 0,
- &nfsGlob.llock) );
-
- assert( RTEMS_SUCCESSFUL == rtems_semaphore_create(
- rtems_build_name('N','F','S','m'),
- 1,
- MUTEX_ATTRIBUTES,
- 0,
- &nfsGlob.lock) );
-
- if (sizeof(ino_t) < sizeof(u_int)) {
- fprintf(stderr,
- "WARNING: Using 'short st_ino' hits performance and may fail to access/find correct files\n");
- fprintf(stderr,
- "you should fix newlib's sys/stat.h - for now I'll enable a hack...\n");
-
- }
-}
-
-/* Driver cleanup code
- */
-int
-nfsCleanup(void)
-{
-rtems_id l;
-int refuse;
-
- if (!nfsGlob.llock) {
- /* registering the driver failed - let them still cleanup */
- return 0;
- }
-
- LOCK(nfsGlob.llock);
- if ( (refuse = nfsGlob.num_mounted_fs) ) {
- fprintf(stderr,"Refuse to unload NFS; %i filesystems still mounted.\n",
- refuse);
- nfsMountsShow(stderr);
- /* yes, printing is slow - but since you try to unload the driver,
- * you assume nobody is using NFS, so what if they have to wait?
- */
- UNLOCK(nfsGlob.llock);
- return -1;
- }
-
- rtems_semaphore_delete(nfsGlob.lock);
- nfsGlob.lock = 0;
-
- /* hold the lock while cleaning up... */
-
- rpcUdpXactPoolDestroy(smallPool);
- rpcUdpXactPoolDestroy(bigPool);
- l = nfsGlob.llock;
- rtems_io_unregister_driver(nfsGlob.nfs_major);
-
- rtems_semaphore_delete(l);
- nfsGlob.llock = 0;
- return 0;
-}
-
-/* NFS RPC wrapper.
- *
- * ARGS: srvr the NFS server we want to call
- * proc the NFSPROC_xx we want to invoke
- * xargs xdr routine to wrap the arguments
- * pargs pointer to the argument object
- * xres xdr routine to unwrap the results
- * pres pointer to the result object
- *
- * RETURNS: 0 on success, -1 on error with errno set.
- *
- * NOTE: the caller assumes that errno is set to
- * a nonzero value if this routine returns
- * an error (nonzero return value).
- *
- * This routine prints RPC error messages to
- * stderr.
- */
-STATIC int
-nfscall(
- RpcUdpServer srvr,
- int proc,
- xdrproc_t xargs,
- void * pargs,
- xdrproc_t xres,
- void * pres)
-{
-RpcUdpXact xact;
-enum clnt_stat stat;
-RpcUdpXactPool pool;
-int rval = -1;
-
-
- switch (proc) {
- case NFSPROC_SYMLINK:
- case NFSPROC_WRITE:
- pool = bigPool; break;
- default: pool = smallPool; break;
- }
-
- xact = rpcUdpXactPoolGet(pool, XactGetCreate);
-
- if ( !xact ) {
- errno = ENOMEM;
- return -1;
- }
-
- if ( RPC_SUCCESS != (stat=rpcUdpSend(
- xact,
- srvr,
- NFSCALL_TIMEOUT,
- proc,
- xres,
- pres,
- xargs,
- pargs,
- 0)) ||
- RPC_SUCCESS != (stat=rpcUdpRcv(xact)) ) {
-
- fprintf(stderr,
- "NFS (proc %i) - %s\n",
- proc,
- clnt_sperrno(stat));
-
- switch (stat) {
- /* TODO: this is probably not complete and/or fully accurate */
- case RPC_CANTENCODEARGS : errno = EINVAL; break;
- case RPC_AUTHERROR : errno = EPERM; break;
-
- case RPC_CANTSEND :
- case RPC_CANTRECV : /* hope they have errno set */
- case RPC_SYSTEMERROR : break;
-
- default : errno = EIO; break;
- }
- } else {
- rval = 0;
- }
-
- /* release the transaction back into the pool */
- rpcUdpXactPoolPut(xact);
-
- if (rval && !errno)
- errno = EIO;
-
- return rval;
-}
-
-/* Check the 'age' of a node's stats
- * and read the attributes from the server
- * if necessary.
- *
- * ARGS: node node to update
- * force enforce updating ignoring
- * the timestamp/age
- *
- * RETURNS: 0 on success,
- * -1 on failure with errno set
- */
-
-static int
-updateAttr(NfsNode node, int force)
-{
-
- if (force
-#ifdef CONFIG_ATTR_LIFETIME
- || (nowSeconds() - node->age > CONFIG_ATTR_LIFETIME)
-#endif
- ) {
- if ( nfscall(node->nfs->server,
- NFSPROC_GETATTR,
- (xdrproc_t)xdr_nfs_fh, &SERP_FILE(node),
- (xdrproc_t)xdr_attrstat, &node->serporid) )
- return -1;
-
- if ( NFS_OK != node->serporid.status ) {
- errno = node->serporid.status;
- return -1;
- }
-
- node->age = nowSeconds();
- }
-
- return 0;
-}
-
-/*
- * IP address helper. Note that we avoid
- * gethostbyname() since it's not reentrant.
- *
- * initialize a sockaddr_in from a
- * [<uid>'.'<gid>'@']<host>':'<path>" string and let
- * pPath point to the <path> part; retrieve the optional
- * uid/gids
- *
- * ARGS: see description above
- *
- * RETURNS: 0 on success,
- * -1 on failure with errno set
- */
-static int
-buildIpAddr(u_long *puid, u_long *pgid,
- char **pHost, struct sockaddr_in *psa,
- char **pPath)
-{
-char host[30];
-char *chpt = *pPath;
-char *path;
-int len;
-
- if ( !chpt ) {
- errno = EINVAL;
- return -1;
- }
-
- /* look for the optional uid/gid */
- if ( (chpt = strchr(chpt, UIDSEP)) ) {
- if ( 2 != sscanf(*pPath,"%li.%li",puid,pgid) ) {
- errno = EINVAL;
- return -1;
- }
- chpt++;
- } else {
- *puid = RPCIOD_DEFAULT_ID;
- *pgid = RPCIOD_DEFAULT_ID;
- chpt = *pPath;
- }
- if ( pHost )
- *pHost = chpt;
-
- /* split the device name which is in the form
- *
- * <host_ip> ':' <path>
- *
- * into its components using a local buffer
- */
-
- if ( !(path = strchr(chpt, HOSTDELIM)) ||
- (len = path - chpt) >= sizeof(host) - 1 ) {
- errno = EINVAL;
- return -1;
- }
- /* point to path beyond ':' */
- path++;
-
- strncpy(host, chpt, len);
- host[len]=0;
-
- if ( ! inet_pton(AF_INET, host, &psa->sin_addr) ) {
- errno = ENXIO;
- return -1;
- }
-
- psa->sin_family = AF_INET;
- psa->sin_port = 0;
- *pPath = path;
- return 0;
-}
-
-/* wrapper similar to nfscall.
- * However, since it is not used
- * very often, the simpler and less
- * efficient rpcUdpCallRp API is used.
- *
- * ARGS: see 'nfscall()' above
- *
- * RETURNS: RPC status
- */
-static enum clnt_stat
-mntcall(
- struct sockaddr_in *psrvr,
- int proc,
- xdrproc_t xargs,
- void * pargs,
- xdrproc_t xres,
- void * pres,
- u_long uid,
- u_long gid)
-{
-#ifdef MOUNT_V1_PORT
-int retry;
-#endif
-enum clnt_stat stat = RPC_FAILED;
-
-#ifdef MOUNT_V1_PORT
- /* if the portmapper fails, retry a fixed port */
- for (retry = 1, psrvr->sin_port = 0, stat = RPC_FAILED;
- retry >= 0 && stat;
- stat && (psrvr->sin_port = htons(MOUNT_V1_PORT)), retry-- )
-#endif
- stat = rpcUdpCallRp(
- psrvr,
- MOUNTPROG,
- MOUNTVERS,
- proc,
- xargs,
- pargs,
- xres,
- pres,
- uid,
- gid,
- MNTCALL_TIMEOUT
- );
- return stat;
-}
-
-/*****************************************
- RTEMS File System Operations for NFS
- *****************************************/
-
-#if 0 /* for reference */
-
-struct rtems_filesystem_location_info_tt
-{
- void *node_access;
- rtems_filesystem_file_handlers_r *handlers;
- rtems_filesystem_operations_table *ops;
- rtems_filesystem_mount_table_entry_t *mt_entry;
-};
-
-#endif
-
-/*
- * Evaluate a path letting 'pathloc' travel along.
- *
- * The important semantics of this operation are:
- *
- * If this routine returns -1, the caller assumes
- * pathloc to be _invalid_ and hence it will not
- * invoke rtems_filesystem_freenode() on it.
- *
- * OTOH, if evalpath returns 0,
- * rtems_filesystem_freenode() will eventually be
- * called which results in our freeing the associated
- * NfsNode attached to node_access.
- *
- * Therefore, this routine will _always_ allocate
- * a NfsNode and pass it out to *pathloc (provided
- * that the evaluation succeeds).
- *
- * However, if the evaluation finds that it has to
- * step across FS boundaries (mount point or a symlink
- * pointing outside), the NfsNode is destroyed
- * before passing control to the new FS' evalpath_h()
- *
- */
-
-STATIC int nfs_do_evalpath(
- const char *pathname, /* IN */
- void *arg,
- rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
- int forMake
-)
-{
-char *del = 0, *part;
-int e = 0;
-NfsNode node = pathloc->node_access;
-char *p = malloc(MAXPATHLEN+1);
-Nfs nfs = (Nfs)pathloc->mt_entry->fs_info;
-RpcUdpServer server = nfs->server;
-unsigned long flags;
-#if DEBUG & DEBUG_COUNT_NODES
-unsigned long niu,siu;
-#endif
-
- if ( !p ) {
- e = ENOMEM;
- goto cleanup;
- }
- strcpy(p, pathname);
-
- LOCK(nfsGlob.lock);
- node = nfsNodeClone(node);
- UNLOCK(nfsGlob.lock);
-
- /* from here on, the NFS is protected from being unmounted
- * since the node refcount is > 1
- */
-
- /* clone the node */
- if ( !node ) {
- /* nodeClone sets errno */
- goto cleanup;
- }
-
- pathloc->node_access = node;
-
- /* Special case: the RTEMS filesystem code
- * may emit '..' on a regular file node to
- * find the parent directory :-(.
- * (eval.c: rtems_filesystem_evaluate_parent())
- * Try to catch this case here:
- */
- if ( NFDIR != SERP_ATTR(node).type && '.'==*p && '.'==*(p+1) ) {
- for ( part = p+2; '/'==*part; part++ )
- /* skip trailing '/' */;
- if ( !*part ) {
- /* this is it; back out dir and let them look up the dir itself... */
- memcpy( &SERP_FILE(node),
- &node->args.dir,
- sizeof(node->args.dir));
- *(p+1)=0;
- }
- }
-
- for (part=p; part && *part; part=del) {
-
- if ( NFLNK == SERP_ATTR(node).type ) {
- /* follow midpath link */
- char *b = malloc(NFS_MAXPATHLEN+1);
- int l;
-
- if (!b) {
- e = ENOMEM;
- goto cleanup;
- }
- if (nfs_readlink(pathloc, b, NFS_MAXPATHLEN+1)) {
- free(b);
- e = errno;
- goto cleanup;
- }
-
- /* prepend the link value to the rest of the path */
- if ( (l=strlen(b)) + strlen(part) + 1 > NFS_MAXPATHLEN ) {
- free(b);
- e = EINVAL;
- goto cleanup;
- }
- /* swap string buffers and reset delimiter */
- b[l++] = DELIM;
- strcpy(b+l,part);
- part = b;
- b = p;
- p = del = part;
-
- free(b);
-
- /* back up the directory filehandle (only necessary
- * if we don't back out to the root
- */
- if (! (DELIM == *part) ) {
- memcpy( &SERP_FILE(node),
- &node->args.dir,
- sizeof(node->args.dir));
-
- if (updateAttr(node, 1 /* force */)) {
- e = errno;
- goto cleanup;
- }
- }
- }
-
- /* find delimiter and eat /// sequences
- * (only if we don't restart at the root)
- */
- if ( DELIM != *part && (del = strchr(part, DELIM))) {
- do {
- *del++=0;
- } while (DELIM==*del);
- }
-
- /* refuse to backup over the root */
- if ( 0==strcmp(part,UPDIR)
- && locAreEqual(pathloc, &rtems_filesystem_root) ) {
- part++;
- }
-
- /* cross mountpoint upwards */
- if ( (0==strcmp(part,UPDIR) && locIsRoot(pathloc)) /* cross mountpoint up */
- || DELIM == *part /* link starts at root */
- ) {
- int rval;
-
-#if DEBUG & DEBUG_EVALPATH
- fprintf(stderr,
- "Crossing mountpoint upwards\n");
-#endif
-
- if (DELIM == *part) {
- *pathloc = rtems_filesystem_root;
- } else {
- *pathloc = pathloc->mt_entry->mt_point_node;
- /* re-append the rest of the path */
- if (del)
- while ( 0 == *--del )
- *del = DELIM;
- }
-
- nfsNodeDestroy(node);
-
-#if DEBUG & DEBUG_EVALPATH
- fprintf(stderr,
- "Re-evaluating '%s'\n",
- part);
-#endif
-
- if (forMake)
- rval = pathloc->ops->evalformake_h(part, pathloc, (const char**)arg);
- else
- rval = pathloc->ops->evalpath_h(part, (int)arg, pathloc);
-
- free(p);
- return rval;
- }
-
- /* lookup one element */
- SERP_ARGS(node).diroparg.name = part;
-
- /* remember args / directory fh */
- memcpy( &node->args, &SERP_FILE(node), sizeof(node->args));
-
- /* don't lookup the item we want to create */
- if ( forMake && (!del || !*del) )
- break;
-
-#if DEBUG & DEBUG_EVALPATH
- fprintf(stderr,"Looking up '%s'\n",part);
-#endif
-
- if ( nfscall(server,
- NFSPROC_LOOKUP,
- (xdrproc_t)xdr_diropargs, &SERP_FILE(node),
- (xdrproc_t)xdr_serporid, &node->serporid) ||
- NFS_OK != (errno=node->serporid.status) ) {
- e = errno;
- goto cleanup;
- }
- node->age = nowSeconds();
-
-#if DEBUG & DEBUG_EVALPATH
- if (NFLNK == SERP_ATTR(node).type && del) {
- fprintf(stderr,
- "Following midpath link '%s'\n",
- part);
- }
-#endif
-
- }
-
- if (forMake) {
- /* remember the name - do this _before_ copying
- * the name to local storage; the caller expects a
- * pointer into pathloc
- */
- assert( node->args.name );
-
- *(const char**)arg = pathname + (node->args.name - p);
-
-#if 0
- /* restore the directory node */
-
- memcpy( &SERP_FILE(node),
- &node->args.dir,
- sizeof(node->args.dir));
-
- if ( (nfscall(nfs->server,
- NFSPROC_GETATTR,
- (xdrproc_t)xdr_nfs_fh, &SERP_FILE(node),
- (xdrproc_t)xdr_attrstat, &node->serporid) && !errno && (errno = EIO)) ||
- (NFS_OK != (errno=node->serporid.status) ) ) {
- goto cleanup;
- }
-#endif
- }
-
- if (locIsRoot(pathloc)) {
-
- /* stupid filesystem code has no 'op' for comparing nodes
- * but just compares the 'node_access' pointers.
- * Luckily, this is only done for comparing the root nodes.
- * Hence, we never give them a copy of the root but always
- * the root itself.
- */
- pathloc->node_access = pathloc->mt_entry->mt_fs_root.node_access;
- /* increment the 'in use' counter since we return one more
- * reference to the root node
- */
- rtems_interrupt_disable(flags);
- nfs->nodesInUse++;
- rtems_interrupt_enable(flags);
- nfsNodeDestroy(node);
-
-
- } else {
- switch (SERP_ATTR(node).type) {
- case NFDIR: pathloc->handlers = &nfs_dir_file_handlers; break;
- case NFREG: pathloc->handlers = &nfs_file_file_handlers; break;
- case NFLNK: pathloc->handlers = &nfs_link_file_handlers; break;
- default: pathloc->handlers = &rtems_filesystem_null_handlers; break;
- }
- pathloc->node_access = node;
-
- /* remember the name of this directory entry */
-
- if (node->args.name) {
- if (node->str) {
-#if DEBUG & DEBUG_COUNT_NODES
- rtems_interrupt_disable(flags);
- nfs->stringsInUse--;
- rtems_interrupt_enable(flags);
-#endif
- free(node->str);
- }
- node->args.name = node->str = strdup(node->args.name);
- if (!node->str) {
- e = ENOMEM;
- goto cleanup;
- }
-
-#if DEBUG & DEBUG_COUNT_NODES
- rtems_interrupt_disable(flags);
- nfs->stringsInUse++;
- rtems_interrupt_enable(flags);
-#endif
- }
-
- }
- node = 0;
-
- e = 0;
-
-cleanup:
- free(p);
-#if DEBUG & DEBUG_COUNT_NODES
- /* cache counters; nfs may be unmounted by other thread after the last
- * node is destroyed
- */
- niu = nfs->nodesInUse;
- siu = nfs->stringsInUse;
-#endif
- if (node) {
- nfsNodeDestroy(node);
- pathloc->node_access = 0;
- }
-#if DEBUG & DEBUG_COUNT_NODES
- fprintf(stderr,
- "leaving evalpath, in use count is %i nodes, %i strings\n",
- niu,siu);
-#endif
- if (e) {
-#if DEBUG & DEBUG_EVALPATH
- perror("Evalpath");
-#endif
- rtems_set_errno_and_return_minus_one(e);
- } else {
- return 0;
- }
-}
-
-/* MANDATORY; may set errno=ENOSYS and return -1 */
-static int nfs_evalformake(
- const char *path, /* IN */
- rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
- const char **pname /* OUT */
-)
-{
- return nfs_do_evalpath(path, (void*)pname, pathloc, 1 /*forMake*/);
-}
-
-static int nfs_evalpath(
- const char *path, /* IN */
- int flags, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN/OUT */
-)
-{
- return nfs_do_evalpath(path, (void*)flags, pathloc, 0 /*not forMake*/);
-}
-
-
-/* create a hard link */
-
-static int nfs_link(
- rtems_filesystem_location_info_t *to_loc, /* IN */
- rtems_filesystem_location_info_t *parent_loc, /* IN */
- const char *name /* IN */
-)
-{
-NfsNode pNode;
-nfsstat status;
-NfsNode tNode = to_loc->node_access;
-
-#if DEBUG & DEBUG_SYSCALLS
- fprintf(stderr,"Creating link '%s'\n",name);
-#endif
-
- if ( !locIsNfs(parent_loc) ) {
- errno = EXDEV;
- return -1;
- }
-
- pNode = parent_loc->node_access;
- if ( tNode->nfs != pNode->nfs ) {
- errno = EXDEV;
- return -1;
- }
- memcpy(&SERP_ARGS(tNode).linkarg.to.dir,
- &SERP_FILE(pNode),
- sizeof(SERP_FILE(pNode)));
-
- SERP_ARGS(tNode).linkarg.to.name = (filename)name;
-
- if ( nfscall(tNode->nfs->server,
- NFSPROC_LINK,
- (xdrproc_t)xdr_linkargs, &SERP_FILE(tNode),
- (xdrproc_t)xdr_nfsstat, &status)
- || (NFS_OK != (errno = status))
- ) {
-#if DEBUG & DEBUG_SYSCALLS
- perror("nfs_link");
-#endif
- return -1;
- }
-
- return 0;
-
-}
-
-static int nfs_do_unlink(
- rtems_filesystem_location_info_t *loc, /* IN */
- int proc
-)
-{
-nfsstat status;
-NfsNode node = loc->node_access;
-Nfs nfs = node->nfs;
-#if DEBUG & DEBUG_SYSCALLS
-char *name = NFSPROC_REMOVE == proc ?
- "nfs_unlink" : "nfs_rmdir";
-#endif
-
- /* The FS generics have determined that pathloc is _not_
- * a directory. Hence we may assume that the parent
- * is in our NFS.
- */
-
-#if DEBUG & DEBUG_SYSCALLS
- assert( node->args.name == node->str && node->str );
-
- fprintf(stderr,"%s '%s'\n", name, node->args.name);
-#endif
-
- if ( nfscall(nfs->server,
- proc,
- (xdrproc_t)xdr_diropargs, &node->args,
- (xdrproc_t)xdr_nfsstat, &status)
- || (NFS_OK != (errno = status))
- ) {
-#if DEBUG & DEBUG_SYSCALLS
- perror(name);
-#endif
- return -1;
- }
-
- return 0;
-}
-
-static int nfs_unlink(
- rtems_filesystem_location_info_t *loc /* IN */
-)
-{
- return nfs_do_unlink(loc, NFSPROC_REMOVE);
-}
-
-static int nfs_chown(
- rtems_filesystem_location_info_t *pathloc, /* IN */
- uid_t owner, /* IN */
- gid_t group /* IN */
-)
-{
-sattr arg;
-
- arg.uid = owner;
- arg.gid = group;
-
- return nfs_sattr(pathloc->node_access, &arg, SATTR_UID | SATTR_GID);
-
-}
-
-/* Cleanup the FS private info attached to pathloc->node_access */
-static int nfs_freenode(
- rtems_filesystem_location_info_t *pathloc /* IN */
-)
-{
-Nfs nfs = ((NfsNode)pathloc->node_access)->nfs;
-
-#if DEBUG & DEBUG_COUNT_NODES
- /* print counts at entry where they are > 0 so 'nfs' is safe from being destroyed
- * and there's no race condition
- */
- fprintf(stderr,
- "entering freenode, in use count is %i nodes, %i strings\n",
- nfs->nodesInUse,
- nfs->stringsInUse);
-#endif
-
- /* never destroy the root node; it is released by the unmount
- * code
- */
- if (locIsRoot(pathloc)) {
- unsigned long flags;
- /* just adjust the references to the root node but
- * don't really release it
- */
- rtems_interrupt_disable(flags);
- nfs->nodesInUse--;
- rtems_interrupt_enable(flags);
- } else {
- nfsNodeDestroy(pathloc->node_access);
- pathloc->node_access = 0;
- }
- return 0;
-}
-
-/* NOTE/TODO: mounting on top of NFS is not currently supported
- *
- * Challenge: stateless protocol. It would be possible to
- * delete mount points on the server. We would need some sort
- * of a 'garbage collector' looking for dead/unreachable
- * mount points and unmounting them.
- * Also, the path evaluation routine would have to check
- * for crossing mount points. Crossing over from one NFS
- * into another NFS could probably handled iteratively
- * rather than by recursion.
- */
-
-#ifdef DECLARE_BODY
-/* This routine is called when they try to mount something
- * on top of THIS filesystem, i.e. if one of our directories
- * is used as a mount point
- */
-static int nfs_mount(
- rtems_filesystem_mount_table_entry_t *mt_entry /* in */
-)DECLARE_BODY
-#else
-#define nfs_mount 0
-#endif
-
-#ifdef DECLARE_BODY
-/* This op is called when they try to unmount a FS
- * from a mountpoint managed by THIS FS.
- */
-static int nfs_unmount(
- rtems_filesystem_mount_table_entry_t *mt_entry /* in */
-)DECLARE_BODY
-#else
-#define nfs_unmount 0
-#endif
-
-#if 0
-
-/* for reference (libio.h) */
-
-struct rtems_filesystem_mount_table_entry_tt {
- Chain_Node Node;
- rtems_filesystem_location_info_t mt_point_node;
- rtems_filesystem_location_info_t mt_fs_root;
- int options;
- void *fs_info;
-
- rtems_filesystem_limits_and_options_t pathconf_limits_and_options;
-
- /*
- * When someone adds a mounted filesystem on a real device,
- * this will need to be used.
- *
- * The best option long term for this is probably an open file descriptor.
- */
- char *dev;
-};
-#endif
-
-
-/* This op is called as the last step of mounting this FS */
-STATIC int nfs_fsmount_me(
- rtems_filesystem_mount_table_entry_t *mt_entry
-)
-{
-char *host;
-struct sockaddr_in saddr;
-enum clnt_stat stat;
-fhstatus fhstat;
-u_long uid,gid;
-#ifdef NFS_V2_PORT
-int retry;
-#endif
-Nfs nfs = 0;
-NfsNode rootNode = 0;
-RpcUdpServer nfsServer = 0;
-int e = -1;
-char *path = mt_entry->dev;
-
-
- if ( buildIpAddr(&uid, &gid, &host, &saddr, &path) )
- return -1;
-
-
-#ifdef NFS_V2_PORT
- /* if the portmapper fails, retry a fixed port */
- for (retry = 1, saddr.sin_port = 0, stat = RPC_FAILED;
- retry >= 0 && stat;
- stat && (saddr.sin_port = htons(NFS_V2_PORT)), retry-- )
-#endif
- stat = rpcUdpServerCreate(
- &saddr,
- NFS_PROGRAM,
- NFS_VERSION_2,
- uid,
- gid,
- &nfsServer
- );
-
- if ( RPC_SUCCESS != stat ) {
- fprintf(stderr,
- "Unable to contact NFS server - invalid port? (%s)\n",
- clnt_sperrno(stat));
- e = EPROTONOSUPPORT;
- goto cleanup;
- }
-
-
- /* first, try to ping the NFS server by
- * calling the NULL proc.
- */
-#if DEBUG & DEBUG_INIT
- printf( "---> NFS Ping server\n" );
-#endif
- if ( nfscall(nfsServer,
- NFSPROC_NULL,
- (xdrproc_t)xdr_void, 0,
- (xdrproc_t)xdr_void, 0) ) {
-
- fputs("NFS Ping ",stderr);
- fwrite(host, 1, path-host-1, stderr);
- fprintf(stderr," failed: %s\n", strerror(errno));
-
- e = errno ? errno : EIO;
- goto cleanup;
- }
-
- /* that seemed to work - we now try the
- * actual mount
- */
-
- /* reuse server address but let the mntcall()
- * search for the mountd's port
- */
- saddr.sin_port = 0;
-
-#if DEBUG & DEBUG_INIT
- printf( "---> NFS make mount call\n" );
-#endif
- rtems_time_of_day time;
- stat = mntcall( &saddr,
- MOUNTPROC_MNT,
- (xdrproc_t)xdr_dirpath,
- &path,
- (xdrproc_t)xdr_fhstatus,
- &fhstat,
- uid,
- gid );
-
- if (stat) {
- fprintf(stderr,"MOUNT -- %s\n",clnt_sperrno(stat));
- if ( e<=0 )
- e = EIO;
- goto cleanup;
- } else if (NFS_OK != (e=fhstat.fhs_status)) {
- fprintf(stderr,"MOUNT: %s\n",strerror(e));
- goto cleanup;
- }
-
- assert( nfs = nfsCreate(nfsServer) );
- nfsServer = 0;
-
- nfs->uid = uid;
- nfs->gid = gid;
-
- /* that seemed to work - we now create the root node
- * and we also must obtain the root node attributes
- */
-#if DEBUG & DEBUG_INIT
- printf( "---> NFS remote node attributes\n" );
-#endif
- assert( rootNode = nfsNodeCreate(nfs, (nfs_fh*)&fhstat.fhstatus_u.fhs_fhandle ) );
-
- if ( updateAttr(rootNode, 1 /* force */) ) {
- e = errno;
- goto cleanup;
- }
-
- /* looks good so far */
-
- mt_entry->mt_fs_root.node_access = rootNode;
-
- rootNode = 0;
-
- mt_entry->mt_fs_root.ops = &nfs_fs_ops;
- mt_entry->mt_fs_root.handlers = &nfs_dir_file_handlers;
- mt_entry->pathconf_limits_and_options = nfs_limits_and_options;
-
- LOCK(nfsGlob.llock);
- nfsGlob.num_mounted_fs++;
- /* allocate a new ID for this FS */
- nfs->id = nfsGlob.fs_ids++;
- UNLOCK(nfsGlob.llock);
-
- mt_entry->fs_info = nfs;
- nfs->mt_entry = mt_entry;
- nfs = 0;
-
- e = 0;
-
-cleanup:
-#if DEBUG & DEBUG_INIT
- printf( "---> NFS mount cleanup\n" );
-#endif
- if (nfs)
- nfsDestroy(nfs);
- if (nfsServer)
- rpcUdpServerDestroy(nfsServer);
- if (rootNode)
- nfsNodeDestroy(rootNode);
- if (e)
- rtems_set_errno_and_return_minus_one(e);
- else
- return 0;
-}
-
-/* This op is called when they try to unmount THIS fs */
-STATIC int nfs_fsunmount_me(
- rtems_filesystem_mount_table_entry_t *mt_entry /* in */
-)
-{
-enum clnt_stat stat;
-struct sockaddr_in saddr;
-char *path = mt_entry->dev;
-int nodesInUse;
-u_long uid,gid;
-
-LOCK(nfsGlob.llock);
- nodesInUse = ((Nfs)mt_entry->fs_info)->nodesInUse;
-
- if (nodesInUse > 1 /* one ref to the root node used by us */) {
- UNLOCK(nfsGlob.llock);
- fprintf(stderr,
- "Refuse to unmount; there are still %i nodes in use (1 used by us)\n",
- nodesInUse);
- rtems_set_errno_and_return_minus_one(EBUSY);
- }
-
- assert( 0 == buildIpAddr(&uid, &gid, 0, &saddr, &path) );
-
- stat = mntcall( &saddr,
- MOUNTPROC_UMNT,
- (xdrproc_t)xdr_dirpath, &path,
- (xdrproc_t)xdr_void, 0,
- uid,
- gid
- );
-
- if (stat) {
- UNLOCK(nfsGlob.llock);
- fprintf(stderr,"NFS UMOUNT -- %s\n", clnt_sperrno(stat));
- errno = EIO;
- return -1;
- }
-
- nfsNodeDestroy(mt_entry->mt_fs_root.node_access);
- mt_entry->mt_fs_root.node_access = 0;
-
- nfsDestroy(mt_entry->fs_info);
- mt_entry->fs_info = 0;
-
- nfsGlob.num_mounted_fs--;
-UNLOCK(nfsGlob.llock);
-
- return 0;
-}
-
-/* OPTIONAL; may be NULL - BUT: CAUTION; mount() doesn't check
- * for this handler to be present - a fs bug
- * //NOTE: (10/25/2002) patch submitted and probably applied
- */
-static rtems_filesystem_node_types_t nfs_node_type(
- rtems_filesystem_location_info_t *pathloc /* in */
-)
-{
-NfsNode node = pathloc->node_access;
-
- if (updateAttr(node, 0 /* only if old */))
- return -1;
-
- switch( SERP_ATTR(node).type ) {
- default:
- /* rtems has no value for 'unknown';
- */
- case NFNON:
- case NFSOCK:
- case NFBAD:
- case NFFIFO:
- break;
-
-
- case NFREG: return RTEMS_FILESYSTEM_MEMORY_FILE;
- case NFDIR: return RTEMS_FILESYSTEM_DIRECTORY;
-
- case NFBLK:
- case NFCHR: return RTEMS_FILESYSTEM_DEVICE;
-
- case NFLNK: return RTEMS_FILESYSTEM_SYM_LINK;
- }
- return -1;
-}
-
-static int nfs_mknod(
- const char *path, /* IN */
- mode_t mode, /* IN */
- dev_t dev, /* IN */
- rtems_filesystem_location_info_t *pathloc /* IN/OUT */
-)
-{
-rtems_clock_time_value now;
-diropres res;
-NfsNode node = pathloc->node_access;
-mode_t type = S_IFMT & mode;
-
- if (type != S_IFDIR && type != S_IFREG)
- rtems_set_errno_and_return_minus_one(ENOTSUP);
-
-#if DEBUG & DEBUG_SYSCALLS
- fprintf(stderr,"nfs_mknod: creating %s\n", path);
-#endif
-
- rtems_clock_get(RTEMS_CLOCK_GET_TIME_VALUE, &now);
-
- SERP_ARGS(node).createarg.name = (filename)path;
- SERP_ARGS(node).createarg.attributes.mode = mode;
- /* TODO: either use our uid or use the Nfs credentials */
- SERP_ARGS(node).createarg.attributes.uid = 0;
- SERP_ARGS(node).createarg.attributes.gid = 0;
- SERP_ARGS(node).createarg.attributes.size = 0;
- SERP_ARGS(node).createarg.attributes.atime.seconds = now.seconds;
- SERP_ARGS(node).createarg.attributes.atime.useconds = now.microseconds;
- SERP_ARGS(node).createarg.attributes.mtime.seconds = now.seconds;
- SERP_ARGS(node).createarg.attributes.mtime.useconds = now.microseconds;
-
- if ( nfscall( node->nfs->server,
- NFSPROC_CREATE,
- (xdrproc_t)xdr_createargs, &SERP_FILE(node),
- (xdrproc_t)xdr_diropres, &res)
- || (NFS_OK != (errno = res.status)) ) {
-#if DEBUG & DEBUG_SYSCALLS
- perror("nfs_mknod");
-#endif
- return -1;
- }
-
- return 0;
-}
-
-static int nfs_utime(
- rtems_filesystem_location_info_t *pathloc, /* IN */
- time_t actime, /* IN */
- time_t modtime /* IN */
-)
-{
-sattr arg;
-
- /* TODO: add rtems EPOCH - UNIX EPOCH seconds */
- arg.atime.seconds = actime;
- arg.atime.useconds = 0;
- arg.mtime.seconds = modtime;
- arg.mtime.useconds = 0;
-
- return nfs_sattr(pathloc->node_access, &arg, SATTR_ATIME | SATTR_MTIME);
-}
-
-static int nfs_symlink(
- rtems_filesystem_location_info_t *loc, /* IN */
- const char *link_name, /* IN */
- const char *node_name
-)
-{
-rtems_clock_time_value now;
-nfsstat status;
-NfsNode node = loc->node_access;
-
-
-#if DEBUG & DEBUG_SYSCALLS
- fprintf(stderr,"nfs_symlink: creating %s -> %s\n", link_name, node_name);
-#endif
-
- rtems_clock_get(RTEMS_CLOCK_GET_TIME_VALUE, &now);
-
- SERP_ARGS(node).symlinkarg.name = (filename)link_name;
- SERP_ARGS(node).symlinkarg.to = (nfspath) node_name;
-
- SERP_ARGS(node).symlinkarg.attributes.mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
- /* TODO */
- SERP_ARGS(node).symlinkarg.attributes.uid = 0;
- SERP_ARGS(node).symlinkarg.attributes.gid = 0;
- SERP_ARGS(node).symlinkarg.attributes.size = 0;
- SERP_ARGS(node).symlinkarg.attributes.atime.seconds = now.seconds;
- SERP_ARGS(node).symlinkarg.attributes.atime.useconds = now.microseconds;
- SERP_ARGS(node).symlinkarg.attributes.mtime.seconds = now.seconds;
- SERP_ARGS(node).symlinkarg.attributes.mtime.useconds = now.microseconds;
-
- if ( nfscall( node->nfs->server,
- NFSPROC_SYMLINK,
- (xdrproc_t)xdr_symlinkargs, &SERP_FILE(node),
- (xdrproc_t)xdr_nfsstat, &status)
- || (NFS_OK != (errno = status)) ) {
-#if DEBUG & DEBUG_SYSCALLS
- perror("nfs_symlink");
-#endif
- return -1;
- }
-
- return 0;
-}
-
-static int nfs_do_readlink(
- rtems_filesystem_location_info_t *loc, /* IN */
- strbuf *psbuf /* IN/OUT */
-)
-{
-NfsNode node = loc->node_access;
-Nfs nfs = node->nfs;
-readlinkres_strbuf rr;
-int wasAlloced;
-int rval;
-
- rr.strbuf = *psbuf;
-
- wasAlloced = (0 == psbuf->buf);
-
- if ( (rval = nfscall(nfs->server,
- NFSPROC_READLINK,
- (xdrproc_t)xdr_nfs_fh, &SERP_FILE(node),
- (xdrproc_t)xdr_readlinkres_strbuf, &rr)) ) {
- if (wasAlloced)
- xdr_free( (xdrproc_t)xdr_strbuf, (caddr_t)&rr.strbuf );
- }
-
-
- if (NFS_OK != rr.status) {
- if (wasAlloced)
- xdr_free( (xdrproc_t)xdr_strbuf, (caddr_t)&rr.strbuf );
- rtems_set_errno_and_return_minus_one(rr.status);
- }
-
- *psbuf = rr.strbuf;
-
- return 0;
-}
-
-static int nfs_readlink(
- rtems_filesystem_location_info_t *loc, /* IN */
- char *buf, /* OUT */
- size_t len
-)
-{
-strbuf sbuf;
- sbuf.buf = buf;
- sbuf.max = len;
-
- return nfs_do_readlink(loc, &sbuf);
-}
-
-/* The semantics of this routine are:
- *
- * The caller submits a valid pathloc, i.e. it has
- * an NfsNode attached to node_access.
- * On return, pathloc points to the target node which
- * may or may not be an NFS node.
- * Hence, the original NFS node is released in either
- * case:
- * - link evaluation fails; pathloc points to no valid node
- * - link evaluation success; pathloc points to a new valid
- * node. If it's an NFS node, a new NfsNode will be attached
- * to node_access...
- */
-
-#define LINKVAL_BUFLEN (MAXPATHLEN+1)
-#define RVAL_ERR_BUT_DONT_FREENODE (-1)
-#define RVAL_ERR_AND_DO_FREENODE ( 1)
-#define RVAL_OK ( 0)
-
-static int nfs_eval_link(
- rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
- int flags /* IN */
-)
-{
-rtems_filesystem_node_types_t type;
-char *buf = malloc(LINKVAL_BUFLEN);
-int rval = RVAL_ERR_AND_DO_FREENODE;
-
- if (!buf) {
- errno = ENOMEM;
- goto cleanup;
- }
-
- /* in this loop, we must not use NFS specific ops as we might
- * step out of our FS during the process...
- * This algorithm should actually be performed by the
- * generic's evaluate_path routine :-(
- *
- * Unfortunately, there is no way of finding the
- * directory node who contains 'pathloc', however :-(
- */
- do {
- /* assume the generics have verified 'pathloc' to be
- * a link...
- */
- if ( !pathloc->ops->readlink_h ) {
- errno = ENOTSUP;
- goto cleanup;
- }
-
- if ( pathloc->ops->readlink_h(pathloc, buf, LINKVAL_BUFLEN) ) {
- goto cleanup;
- }
-
-#if DEBUG & DEBUG_EVALPATH
- fprintf(stderr, "link value is '%s'\n", buf);
-#endif
-
- /* is the link value an absolute path ? */
- if ( DELIM != *buf ) {
- /* NO; a relative path */
-
- /* we must backup to the link's directory - we
- * know only how to do that for NFS, however.
- * In this special case, we can avoid recursion.
- * Otherwise (i.e. if the link is on another FS),
- * we must step into its eval_link_h().
- */
- if (locIsNfs(pathloc)) {
- NfsNode node = pathloc->node_access;
- int err;
-
- memcpy( &SERP_FILE(node),
- &node->args.dir,
- sizeof(node->args.dir) );
-
- if (updateAttr(node, 1 /* force */))
- goto cleanup;
-
- if (SERP_ATTR(node).type != NFDIR) {
- errno = ENOTDIR;
- goto cleanup;
- }
-
- pathloc->handlers = &nfs_dir_file_handlers;
-
- err = nfs_evalpath(buf, flags, pathloc);
-
- /* according to its semantics,
- * nfs_evalpath cloned the node attached
- * to pathloc. Hence we have to
- * release the old one (referring to
- * the link; the new clone has been
- * updated and refers to the link _value_).
- */
- nfsNodeDestroy(node);
-
- if (err) {
- /* nfs_evalpath has set errno;
- * pathloc->node_access has no
- * valid node attached in this case
- */
- rval = RVAL_ERR_BUT_DONT_FREENODE;
- goto cleanup;
- }
-
- } else {
- if ( ! pathloc->ops->eval_link_h ) {
- errno = ENOTSUP;
- goto cleanup;
- }
- if (!pathloc->ops->eval_link_h(pathloc, flags)) {
- /* FS is responsible for freeing its pathloc->node_access
- * if necessary
- */
- rval = RVAL_ERR_BUT_DONT_FREENODE;
- goto cleanup;
- }
- }
- } else {
- /* link points to an absolute path '/xxx' */
-
- /* release this node; filesystem_evaluate_path() will
- * lookup a new one.
- */
- rtems_filesystem_freenode(pathloc);
-
- if (rtems_filesystem_evaluate_path(buf, flags, pathloc, 1)) {
- goto cleanup;
- }
- }
-
- if ( !pathloc->ops->node_type_h ) {
- errno = ENOTSUP;
- goto cleanup;
- }
-
- type = pathloc->ops->node_type_h(pathloc);
-
-
- /* I dont know what to do about hard links */
- } while ( RTEMS_FILESYSTEM_SYM_LINK == type );
-
- rval = RVAL_OK;
-
-cleanup:
-
- free(buf);
-
- if (RVAL_ERR_AND_DO_FREENODE == rval) {
- rtems_filesystem_freenode(pathloc);
- return -1;
- }
-
- return rval;
-}
-
-
-struct _rtems_filesystem_operations_table nfs_fs_ops = {
- nfs_evalpath, /* MANDATORY */
- nfs_evalformake, /* MANDATORY; may set errno=ENOSYS and return -1 */
- nfs_link, /* OPTIONAL; may be NULL */
- nfs_unlink, /* OPTIONAL; may be NULL */
- nfs_node_type, /* OPTIONAL; may be NULL; BUG in mount - no test!! */
- nfs_mknod, /* OPTIONAL; may be NULL */
- nfs_chown, /* OPTIONAL; may be NULL */
- nfs_freenode, /* OPTIONAL; may be NULL; (release node_access) */
- nfs_mount, /* OPTIONAL; may be NULL */
- nfs_fsmount_me, /* OPTIONAL; may be NULL -- but this makes NO SENSE */
- nfs_unmount, /* OPTIONAL; may be NULL */
- nfs_fsunmount_me, /* OPTIONAL; may be NULL */
- nfs_utime, /* OPTIONAL; may be NULL */
- nfs_eval_link, /* OPTIONAL; may be NULL */
- nfs_symlink, /* OPTIONAL; may be NULL */
- nfs_readlink, /* OPTIONAL; may be NULL */
-};
-
-/*****************************************
- File Handlers
-
- NOTE: the FS generics expect a FS'
- evalpath_h() to switch the
- pathloc->handlers according
- to the pathloc/node's file
- type.
- We currently have 'file' and
- 'directory' handlers and very
- few 'symlink' handlers.
-
- The handlers for each type are
- implemented or #defined ZERO
- in a 'nfs_file_xxx',
- 'nfs_dir_xxx', 'nfs_link_xxx'
- sequence below this point.
-
- In some cases, a common handler,
- can be used for all file types.
- It is then simply called
- 'nfs_xxx'.
- *****************************************/
-
-
-#if 0
-/* from rtems/libio.h for convenience */
-struct rtems_libio_tt {
- rtems_driver_name_t *driver;
- off_t size; /* size of file */
- off_t offset; /* current offset into file */
- uint32_t flags;
- rtems_filesystem_location_info_t pathinfo;
- Objects_Id sem;
- uint32_t data0; /* private to "driver" */
- void *data1; /* ... */
- void *file_info; /* used by file handlers */
- rtems_filesystem_file_handlers_r *handlers; /* type specific handlers */
-};
-#endif
-
-/* stateless NFS protocol makes this trivial */
-static int nfs_file_open(
- rtems_libio_t *iop,
- const char *pathname,
- uint32_t flag,
- uint32_t mode
-)
-{
- iop->file_info = 0;
- return 0;
-}
-
-/* reading directories is not stateless; we must
- * remember the last 'read' position, i.e.
- * the server 'cookie'. We do manage this information
- * attached to the iop->file_info.
- */
-static int nfs_dir_open(
- rtems_libio_t *iop,
- const char *pathname,
- uint32_t flag,
- uint32_t mode
-)
-{
-NfsNode node = iop->pathinfo.node_access;
-DirInfo di;
-
- /* create a readdirargs object and copy the file handle;
- * attach to the file_info.
- */
-
- di = (DirInfo) malloc(sizeof(*di));
- iop->file_info = di;
-
- if ( !di ) {
- errno = ENOMEM;
- return -1;
- }
-
- memcpy( &di->readdirargs.dir,
- &SERP_FILE(node),
- sizeof(di->readdirargs.dir) );
-
- /* rewind cookie */
- memset( &di->readdirargs.cookie,
- 0,
- sizeof(di->readdirargs.cookie) );
-
- di->eofreached = FALSE;
-
- return 0;
-}
-
-#define nfs_link_open 0
-
-static int nfs_file_close(
- rtems_libio_t *iop
-)
-{
- return 0;
-}
-
-static int nfs_dir_close(
- rtems_libio_t *iop
-)
-{
- free(iop->file_info);
- iop->file_info = 0;
- return 0;
-}
-
-#define nfs_link_close 0
-
-static int nfs_file_read(
- rtems_libio_t *iop,
- void *buffer,
- uint32_t count
-)
-{
-readres rr;
-NfsNode node = iop->pathinfo.node_access;
-Nfs nfs = node->nfs;
-
- if (count > NFS_MAXDATA)
- count = NFS_MAXDATA;
-
- SERP_ARGS(node).readarg.offset = iop->offset;
- SERP_ARGS(node).readarg.count = count;
- SERP_ARGS(node).readarg.totalcount = 0xdeadbeef;
-
- rr.readres_u.reply.data.data_val = buffer;
-
- if ( nfscall( nfs->server,
- NFSPROC_READ,
- (xdrproc_t)xdr_readargs, &SERP_FILE(node),
- (xdrproc_t)xdr_readres, &rr) ) {
- return -1;
- }
-
-
- if (NFS_OK != rr.status) {
- rtems_set_errno_and_return_minus_one(rr.status);
- }
-
-#if DEBUG & DEBUG_SYSCALLS
- fprintf(stderr,
- "Read %i (asked for %i) bytes from offset %i to 0x%08x\n",
- rr.readres_u.reply.data.data_len,
- count,
- iop->offset,
- rr.readres_u.reply.data.data_val);
-#endif
-
-
- return rr.readres_u.reply.data.data_len;
-}
-
-/* this is called by readdir() / getdents() */
-static int nfs_dir_read(
- rtems_libio_t *iop,
- void *buffer,
- uint32_t count
-)
-{
-DirInfo di = iop->file_info;
-RpcUdpServer server = ((Nfs)iop->pathinfo.mt_entry->fs_info)->server;
-
- if ( di->eofreached )
- return 0;
-
- di->ptr = di->buf = buffer;
-
- /* align + round down the buffer */
- count &= ~ (DIRENT_HEADER_SIZE - 1);
- di->len = count;
-
-#if 0
- /* now estimate the number of entries we should ask for */
- count /= DIRENT_HEADER_SIZE + CONFIG_AVG_NAMLEN;
-
- /* estimate the encoded size that might take up */
- count *= dirres_entry_size + CONFIG_AVG_NAMLEN;
-#else
- /* integer arithmetics are better done the other way round */
- count *= dirres_entry_size + CONFIG_AVG_NAMLEN;
- count /= DIRENT_HEADER_SIZE + CONFIG_AVG_NAMLEN;
-#endif
-
- if (count > NFS_MAXDATA)
- count = NFS_MAXDATA;
-
- di->readdirargs.count = count;
-
-#if DEBUG & DEBUG_READDIR
- fprintf(stderr,
- "Readdir: asking for %i XDR bytes, buffer is %i\n",
- count, di->len);
-#endif
-
- if ( nfscall(
- server,
- NFSPROC_READDIR,
- (xdrproc_t)xdr_readdirargs, &di->readdirargs,
- (xdrproc_t)xdr_dir_info, di) ) {
- return -1;
- }
-
-
- if (NFS_OK != di->status) {
- rtems_set_errno_and_return_minus_one(di->status);
- }
-
- return (char*)di->ptr - (char*)buffer;
-}
-
-#define nfs_link_read 0
-
-static int nfs_file_write(
- rtems_libio_t *iop,
- const void *buffer,
- uint32_t count
-)
-{
-NfsNode node = iop->pathinfo.node_access;
-Nfs nfs = node->nfs;
-int e;
-
- if (count > NFS_MAXDATA)
- count = NFS_MAXDATA;
-
-
- SERP_ARGS(node).writearg.beginoffset = 0xdeadbeef;
- if ( LIBIO_FLAGS_APPEND & iop->flags ) {
- if ( updateAttr(node, 0) ) {
- return -1;
- }
- SERP_ARGS(node).writearg.offset = SERP_ATTR(node).size;
- } else {
- SERP_ARGS(node).writearg.offset = iop->offset;
- }
- SERP_ARGS(node).writearg.totalcount = 0xdeadbeef;
- SERP_ARGS(node).writearg.data.data_len = count;
- SERP_ARGS(node).writearg.data.data_val = (void*)buffer;
-
- /* write XDR buffer size will be chosen by nfscall based
- * on the PROC specifier
- */
-
- if ( nfscall( nfs->server,
- NFSPROC_WRITE,
- (xdrproc_t)xdr_writeargs, &SERP_FILE(node),
- (xdrproc_t)xdr_attrstat, &node->serporid) ) {
- return -1;
- }
-
-
- if (NFS_OK != (e=node->serporid.status) ) {
- /* try at least to recover the current attributes */
- updateAttr(node, 1 /* force */);
- rtems_set_errno_and_return_minus_one(e);
- }
-
- node->age = nowSeconds();
-
- return count;
-}
-
-#define nfs_dir_write 0
-#define nfs_link_write 0
-
-/* IOCTL is unneeded/unsupported */
-#ifdef DECLARE_BODY
-static int nfs_file_ioctl(
- rtems_libio_t *iop,
- uint32_t command,
- void *buffer
-)DECLARE_BODY
-#else
-#define nfs_file_ioctl 0
-#define nfs_dir_ioctl 0
-#define nfs_link_ioctl 0
-#endif
-
-static int nfs_file_lseek(
- rtems_libio_t *iop,
- off_t length,
- int whence
-)
-{
-#if DEBUG & DEBUG_SYSCALLS
- fprintf(stderr,
- "lseek to %i (length %i, whence %i)\n",
- iop->offset,
- length,
- whence);
-#endif
- if ( SEEK_END == whence ) {
- /* rtems (4.6.2) libcsupport code 'lseek' uses iop->size to
- * compute the offset. We don't want to track the file size
- * by updating 'iop->size' constantly.
- * Since lseek is the only place using iop->size, we work
- * around this by tweaking the offset here...
- */
- NfsNode node = iop->pathinfo.node_access;
- fattr *fa = &SERP_ATTR(node);
-
- if (updateAttr(node, 0 /* only if old */)) {
- return -1;
- }
- iop->offset = fa->size;
- }
-
- /* this is particularly easy :-) */
- return iop->offset;
-}
-
-static int nfs_dir_lseek(
- rtems_libio_t *iop,
- off_t length,
- int whence
-)
-{
-DirInfo di = iop->file_info;
-
- /* we don't support anything other than
- * rewinding
- */
- if (SEEK_SET != whence || 0 != length) {
- errno = ENOTSUP;
- return -1;
- }
-
- /* rewind cookie */
- memset( &di->readdirargs.cookie,
- 0,
- sizeof(di->readdirargs.cookie) );
-
- di->eofreached = FALSE;
-
- return iop->offset;
-}
-
-#define nfs_link_lseek 0
-
-#if 0 /* structure types for reference */
-struct fattr {
- ftype type;
- u_int mode;
- u_int nlink;
- u_int uid;
- u_int gid;
- u_int size;
- u_int blocksize;
- u_int rdev;
- u_int blocks;
- u_int fsid;
- u_int fileid;
- nfstime atime;
- nfstime mtime;
- nfstime ctime;
-};
-
-struct stat
-{
- dev_t st_dev;
- ino_t st_ino;
- mode_t st_mode;
- nlink_t st_nlink;
- uid_t st_uid;
- gid_t st_gid;
- dev_t st_rdev;
- off_t st_size;
- /* SysV/sco doesn't have the rest... But Solaris, eabi does. */
-#if defined(__svr4__) && !defined(__PPC__) && !defined(__sun__)
- time_t st_atime;
- time_t st_mtime;
- time_t st_ctime;
-#else
- time_t st_atime;
- long st_spare1;
- time_t st_mtime;
- long st_spare2;
- time_t st_ctime;
- long st_spare3;
- long st_blksize;
- long st_blocks;
- long st_spare4[2];
-#endif
-};
-#endif
-
-/* common for file/dir/link */
-static int nfs_fstat(
- rtems_filesystem_location_info_t *loc,
- struct stat *buf
-)
-{
-NfsNode node = loc->node_access;
-fattr *fa = &SERP_ATTR(node);
-
- if (updateAttr(node, 0 /* only if old */)) {
- return -1;
- }
-
-/* done by caller
- memset(buf, 0, sizeof(*buf));
- */
-
- /* translate */
-
- /* one of the branches hopefully is optimized away */
- if (sizeof(ino_t) < sizeof(u_int)) {
- buf->st_dev = NFS_MAKE_DEV_T_INO_HACK((NfsNode)loc->node_access);
- } else {
- buf->st_dev = NFS_MAKE_DEV_T((NfsNode)loc->node_access);
- }
- buf->st_mode = fa->mode;
- buf->st_nlink = fa->nlink;
- buf->st_uid = fa->uid;
- buf->st_gid = fa->gid;
- buf->st_size = fa->size;
- /* TODO: set to "preferred size" of this NFS client implementation */
- buf->st_blksize = fa->blocksize;
- buf->st_rdev = fa->rdev;
- buf->st_blocks = fa->blocks;
- buf->st_ino = fa->fileid;
- buf->st_atime = fa->atime.seconds;
- buf->st_mtime = fa->mtime.seconds;
- buf->st_ctime = fa->ctime.seconds;
-
-#if 0 /* NFS should return the modes */
- switch(fa->type) {
- default:
- case NFNON:
- case NFBAD:
- break;
-
- case NFSOCK: buf->st_mode |= S_IFSOCK; break;
- case NFFIFO: buf->st_mode |= S_IFIFO; break;
- case NFREG : buf->st_mode |= S_IFREG; break;
- case NFDIR : buf->st_mode |= S_IFDIR; break;
- case NFBLK : buf->st_mode |= S_IFBLK; break;
- case NFCHR : buf->st_mode |= S_IFCHR; break;
- case NFLNK : buf->st_mode |= S_IFLNK; break;
- }
-#endif
-
- return 0;
-}
-
-/* a helper which does the real work for
- * a couple of handlers (such as chmod,
- * ftruncate or utime)
- */
-static int
-nfs_sattr(NfsNode node, sattr *arg, u_long mask)
-{
-
-rtems_clock_time_value now;
-nfstime nfsnow, t;
-int e;
-u_int mode;
-
- if (updateAttr(node, 0 /* only if old */))
- return -1;
-
- rtems_clock_get(RTEMS_CLOCK_GET_TIME_VALUE, &now);
-
- /* TODO: add rtems EPOCH - UNIX EPOCH seconds */
- nfsnow.seconds = now.seconds;
- nfsnow.useconds = now.microseconds;
-
- /* merge permission bits into existing type bits */
- mode = SERP_ATTR(node).mode;
- if (mask & SATTR_MODE) {
- mode &= S_IFMT;
- mode |= arg->mode & ~S_IFMT;
- } else {
- mode = -1;
- }
- SERP_ARGS(node).sattrarg.attributes.mode = mode;
-
- SERP_ARGS(node).sattrarg.attributes.uid =
- (mask & SATTR_UID) ? arg->uid : -1;
-
- SERP_ARGS(node).sattrarg.attributes.gid =
- (mask & SATTR_GID) ? arg->gid : -1;
-
- SERP_ARGS(node).sattrarg.attributes.size =
- (mask & SATTR_SIZE) ? arg->size : -1;
-
- if (mask & SATTR_ATIME)
- t = arg->atime;
- else if (mask & SATTR_TOUCHA)
- t = nfsnow;
- else
- t.seconds = t.useconds = -1;
- SERP_ARGS(node).sattrarg.attributes.atime = t;
-
- if (mask & SATTR_ATIME)
- t = arg->mtime;
- else if (mask & SATTR_TOUCHA)
- t = nfsnow;
- else
- t.seconds = t.useconds = -1;
- SERP_ARGS(node).sattrarg.attributes.mtime = t;
-
- node->serporid.status = NFS_OK;
-
- if ( nfscall( node->nfs->server,
- NFSPROC_SETATTR,
- (xdrproc_t)xdr_sattrargs, &SERP_FILE(node),
- (xdrproc_t)xdr_attrstat, &node->serporid) ) {
-#if DEBUG & DEBUG_SYSCALLS
- fprintf(stderr,
- "nfs_sattr (mask 0x%08x): %s",
- mask,
- strerror(errno));
-#endif
- return -1;
- }
-
- if (NFS_OK != (e=node->serporid.status) ) {
-#if DEBUG & DEBUG_SYSCALLS
- fprintf(stderr,"nfs_sattr: %s\n",strerror(e));
-#endif
- /* try at least to recover the current attributes */
- updateAttr(node, 1 /* force */);
- rtems_set_errno_and_return_minus_one(e);
- }
-
- node->age = nowSeconds();
-
- return 0;
-}
-
-
-/* common for file/dir/link */
-static int nfs_fchmod(
- rtems_filesystem_location_info_t *loc,
- mode_t mode
-)
-{
-sattr arg;
-
- arg.mode = mode;
- return nfs_sattr(loc->node_access, &arg, SATTR_MODE);
-
-}
-
-/* just set the size attribute to 'length'
- * the server will take care of the rest :-)
- */
-static int nfs_file_ftruncate(
- rtems_libio_t *iop,
- off_t length
-)
-{
-sattr arg;
-
- arg.size = length;
- /* must not modify any other attribute; if we are not the owner
- * of the file or directory but only have write access changing
- * any attribute besides 'size' will fail...
- */
- return nfs_sattr(iop->pathinfo.node_access,
- &arg,
- SATTR_SIZE);
-}
-
-#define nfs_dir_ftruncate 0
-#define nfs_link_ftruncate 0
-
-/* not implemented */
-#ifdef DECLARE_BODY
-static int nfs_file_fpathconf(
- rtems_libio_t *iop,
- int name
-)DECLARE_BODY
-#else
-#define nfs_file_fpathconf 0
-#define nfs_dir_fpathconf 0
-#define nfs_link_fpathconf 0
-#endif
-
-/* unused */
-#ifdef DECLARE_BODY
-static int nfs_file_fsync(
- rtems_libio_t *iop
-)DECLARE_BODY
-#else
-#define nfs_file_fsync 0
-#define nfs_dir_fsync 0
-#define nfs_link_fsync 0
-#endif
-
-/* unused */
-#ifdef DECLARE_BODY
-static int nfs_file_fdatasync(
- rtems_libio_t *iop
-)DECLARE_BODY
-#else
-#define nfs_file_fdatasync 0
-#define nfs_dir_fdatasync 0
-#define nfs_link_fdatasync 0
-#endif
-
-/* unused */
-#ifdef DECLARE_BODY
-static int nfs_file_fcntl(
- int cmd,
- rtems_libio_t *iop
-)DECLARE_BODY
-#else
-#define nfs_file_fcntl 0
-#define nfs_dir_fcntl 0
-#define nfs_link_fcntl 0
-#endif
-
-/* files and symlinks are removed
- * by the common nfs_unlink() routine.
- * NFS has a different NFSPROC_RMDIR
- * call, though...
- */
-static int nfs_dir_rmnod(
- rtems_filesystem_location_info_t *pathloc /* IN */
-)
-{
- return nfs_do_unlink(pathloc, NFSPROC_RMDIR);
-}
-
-/* the file handlers table */
-static
-struct _rtems_filesystem_file_handlers_r nfs_file_file_handlers = {
- nfs_file_open, /* OPTIONAL; may be NULL */
- nfs_file_close, /* OPTIONAL; may be NULL */
- nfs_file_read, /* OPTIONAL; may be NULL */
- nfs_file_write, /* OPTIONAL; may be NULL */
- nfs_file_ioctl, /* OPTIONAL; may be NULL */
- nfs_file_lseek, /* OPTIONAL; may be NULL */
- nfs_fstat, /* OPTIONAL; may be NULL */
- nfs_fchmod, /* OPTIONAL; may be NULL */
- nfs_file_ftruncate, /* OPTIONAL; may be NULL */
- nfs_file_fpathconf, /* OPTIONAL; may be NULL - UNUSED */
- nfs_file_fsync, /* OPTIONAL; may be NULL */
- nfs_file_fdatasync, /* OPTIONAL; may be NULL */
- nfs_file_fcntl, /* OPTIONAL; may be NULL */
- nfs_unlink, /* OPTIONAL; may be NULL */
-};
-
-/* the directory handlers table */
-static
-struct _rtems_filesystem_file_handlers_r nfs_dir_file_handlers = {
- nfs_dir_open, /* OPTIONAL; may be NULL */
- nfs_dir_close, /* OPTIONAL; may be NULL */
- nfs_dir_read, /* OPTIONAL; may be NULL */
- nfs_dir_write, /* OPTIONAL; may be NULL */
- nfs_dir_ioctl, /* OPTIONAL; may be NULL */
- nfs_dir_lseek, /* OPTIONAL; may be NULL */
- nfs_fstat, /* OPTIONAL; may be NULL */
- nfs_fchmod, /* OPTIONAL; may be NULL */
- nfs_dir_ftruncate, /* OPTIONAL; may be NULL */
- nfs_dir_fpathconf, /* OPTIONAL; may be NULL - UNUSED */
- nfs_dir_fsync, /* OPTIONAL; may be NULL */
- nfs_dir_fdatasync, /* OPTIONAL; may be NULL */
- nfs_dir_fcntl, /* OPTIONAL; may be NULL */
- nfs_dir_rmnod, /* OPTIONAL; may be NULL */
-};
-
-/* the link handlers table */
-static
-struct _rtems_filesystem_file_handlers_r nfs_link_file_handlers = {
- nfs_link_open, /* OPTIONAL; may be NULL */
- nfs_link_close, /* OPTIONAL; may be NULL */
- nfs_link_read, /* OPTIONAL; may be NULL */
- nfs_link_write, /* OPTIONAL; may be NULL */
- nfs_link_ioctl, /* OPTIONAL; may be NULL */
- nfs_link_lseek, /* OPTIONAL; may be NULL */
- nfs_fstat, /* OPTIONAL; may be NULL */
- nfs_fchmod, /* OPTIONAL; may be NULL */
- nfs_link_ftruncate, /* OPTIONAL; may be NULL */
- nfs_link_fpathconf, /* OPTIONAL; may be NULL - UNUSED */
- nfs_link_fsync, /* OPTIONAL; may be NULL */
- nfs_link_fdatasync, /* OPTIONAL; may be NULL */
- nfs_link_fcntl, /* OPTIONAL; may be NULL */
- nfs_unlink, /* OPTIONAL; may be NULL */
-};
-
-/* we need a dummy driver entry table to get a
- * major number from the system
- */
-static
-rtems_device_driver nfs_initialize(
- rtems_device_major_number major,
- rtems_device_minor_number minor,
- void *arg
-)
-{
- /* we don't really use this routine because
- * we cannot supply an argument (contrary
- * to what the 'arg' parameter suggests - it
- * is always set to 0 by the generics :-()
- * and because we don't want the user to
- * have to deal with the major number (which
- * OTOH is something WE are interested in. The
- * only reason for using this API was getting
- * a major number, after all).
- *
- * Something must be present, however, to
- * reserve a slot in the driver table.
- */
- return RTEMS_SUCCESSFUL;
-}
-
-static rtems_driver_address_table drvNfs = {
- nfs_initialize,
- 0, /* open */
- 0, /* close */
- 0, /* read */
- 0, /* write */
- 0 /* control */
-};
-
-/* Dump a list of the currently mounted NFS to a file */
-int
-nfsMountsShow(FILE *f)
-{
-char *mntpt = 0;
-Nfs nfs;
-
- if (!f)
- f = stdout;
-
- if ( !(mntpt=malloc(MAXPATHLEN)) ) {
- fprintf(stderr,"nfsMountsShow(): no memory\n");
- return -1;
- }
-
- fprintf(f,"Currently Mounted NFS:\n");
-
- LOCK(nfsGlob.llock);
-
- for (nfs = nfsGlob.mounted_fs; nfs; nfs=nfs->next) {
- fprintf(f,"%s on ", nfs->mt_entry->dev);
- if (rtems_filesystem_resolve_location(mntpt, MAXPATHLEN, &nfs->mt_entry->mt_fs_root))
- fprintf(f,"<UNABLE TO LOOKUP MOUNTPOINT>\n");
- else
- fprintf(f,"%s\n",mntpt);
- }
-
- UNLOCK(nfsGlob.llock);
-
- free(mntpt);
- return 0;
-}
-
-/* convenience wrapper
- *
- * NOTE: this routine calls NON-REENTRANT
- * gethostbyname() if the host is
- * not in 'dot' notation.
- */
-int
-nfsMount(char *uidhost, char *path, char *mntpoint)
-{
-rtems_filesystem_mount_table_entry_t *mtab;
-struct stat st;
-int devl;
-char *host;
-int rval = -1;
-char *dev = 0;
-
- if (!uidhost || !path || !mntpoint) {
- fprintf(stderr,"usage: nfsMount(""[uid.gid@]host"",""path"",""mountpoint"")\n");
- nfsMountsShow(stderr);
- return -1;
- }
-
- if ( !(dev = malloc((devl=strlen(uidhost) + 20 + strlen(path)+1))) ) {
- fprintf(stderr,"nfsMount: out of memory\n");
- return -1;
- }
-
- /* Try to create the mount point if nonexistent */
- if (stat(mntpoint, &st)) {
- if (ENOENT != errno) {
- perror("nfsMount trying to create mount point - stat failed");
- goto cleanup;
- } else if (mkdir(mntpoint,0777)) {
- perror("nfsMount trying to create mount point");
- goto cleanup;
- }
- }
-
- if ( !(host=strchr(uidhost,UIDSEP)) ) {
- host = uidhost;
- } else {
- host++;
- }
-
- if (isdigit(*host)) {
- /* avoid using gethostbyname */
- sprintf(dev,"%s:%s",uidhost,path);
- } else {
- struct hostent *h;
-
- /* copy the uid part (hostname will be
- * overwritten)
- */
- strcpy(dev, uidhost);
-
- /* NOTE NOTE NOTE: gethostbyname is NOT
- * thread safe. This is UGLY
- */
-
-/* BEGIN OF NON-THREAD SAFE REGION */
-
- h = gethostbyname(host);
-
- if ( !h ||
- !inet_ntop( AF_INET,
- (struct in_addr*)h->h_addr_list[0],
- dev + (host - uidhost),
- devl - (host - uidhost) )
- ) {
- fprintf(stderr,"nfsMount: host '%s' not found\n",host);
- goto cleanup;
- }
-
-/* END OF NON-THREAD SAFE REGION */
-
- /* append ':<path>' */
- strcat(dev,":");
- strcat(dev,path);
- }
-
- printf("Trying to mount %s on %s\n",dev,mntpoint);
-
- if (mount(&mtab,
- &nfs_fs_ops,
- RTEMS_FILESYSTEM_READ_WRITE,
- dev,
- mntpoint)) {
- perror("nfsMount - mount");
- goto cleanup;
- }
-
- rval = 0;
-
-cleanup:
- free(dev);
- return rval;
-}
-
-/* HERE COMES A REALLY UGLY HACK */
-
-/* This is stupid; it is _very_ hard to find the path
- * leading to a rtems_filesystem_location_info_t node :-(
- * The only easy way is making the location the current
- * directory and issue a getcwd().
- * However, since we don't want to tamper with the
- * current directory, we must create a separate
- * task to do the job for us - sigh.
- */
-
-typedef struct ResolvePathArgRec_ {
- rtems_filesystem_location_info_t *loc; /* IN: location to resolve */
- char *buf; /* IN/OUT: buffer where to put the path */
- int len; /* IN: buffer length */
- rtems_id sync; /* IN: synchronization */
- rtems_status_code status; /* OUT: result */
-} ResolvePathArgRec, *ResolvePathArg;
-
-static void
-resolve_path(rtems_task_argument arg)
-{
-ResolvePathArg rpa = (ResolvePathArg)arg;
-rtems_filesystem_location_info_t old;
-
- /* IMPORTANT: let the helper task have its own libio environment (i.e. cwd) */
- if (RTEMS_SUCCESSFUL == (rpa->status = rtems_libio_set_private_env())) {
-
- old = rtems_filesystem_current;
-
- rtems_filesystem_current = *(rpa->loc);
-
- if ( !getcwd(rpa->buf, rpa->len) )
- rpa->status = RTEMS_UNSATISFIED;
-
- /* must restore the cwd because 'freenode' will be called on it */
- rtems_filesystem_current = old;
- }
- rtems_semaphore_release(rpa->sync);
- rtems_task_delete(RTEMS_SELF);
-}
-
-
-/* a utility routine to find the path leading to a
- * rtems_filesystem_location_info_t node
- *
- * INPUT: 'loc' and a buffer 'buf' (length 'len') to hold the
- * path.
- * OUTPUT: path copied into 'buf'
- *
- * RETURNS: 0 on success, RTEMS error code on error.
- */
-rtems_status_code
-rtems_filesystem_resolve_location(char *buf, int len, rtems_filesystem_location_info_t *loc)
-{
-ResolvePathArgRec arg;
-rtems_id tid = 0;
-rtems_task_priority pri;
-rtems_status_code status;
-
- arg.loc = loc;
- arg.buf = buf;
- arg.len = len;
- arg.sync = 0;
-
- status = rtems_semaphore_create(
- rtems_build_name('r','e','s','s'),
- 0,
- RTEMS_SIMPLE_BINARY_SEMAPHORE,
- 0,
- &arg.sync);
-
- if (RTEMS_SUCCESSFUL != status)
- goto cleanup;
-
- rtems_task_set_priority(RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &pri);
-
- status = rtems_task_create(
- rtems_build_name('r','e','s','s'),
- pri,
- RTEMS_MINIMUM_STACK_SIZE + 50000,
- RTEMS_DEFAULT_MODES,
- RTEMS_DEFAULT_ATTRIBUTES,
- &tid);
-
- if (RTEMS_SUCCESSFUL != status)
- goto cleanup;
-
- status = rtems_task_start(tid, resolve_path, (rtems_task_argument)&arg);
-
- if (RTEMS_SUCCESSFUL != status) {
- rtems_task_delete(tid);
- goto cleanup;
- }
-
-
- /* synchronize with the helper task */
- rtems_semaphore_obtain(arg.sync, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-
- status = arg.status;
-
-cleanup:
- if (arg.sync)
- rtems_semaphore_delete(arg.sync);
-
- return status;
-}
diff --git a/rtemsNfs/src/nfs.modini.c b/rtemsNfs/src/nfs.modini.c
deleted file mode 100644
index 834102e..0000000
--- a/rtemsNfs/src/nfs.modini.c
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "librtemsNfs.h"
-
-/* CEXP dynamic loader support */
-
-void
-_cexpModuleInitialize(void *mod)
-{
-#if defined(DEBUG)
- /* print load address (in case we crash while initializing) */
-unsigned lr;
- __asm__ __volatile__(
- " bl thisis_loaded_at \n"
- "thisis_loaded_at: \n"
- " mflr %0 \n"
- : "=r"(lr) ::"lr");
- printf("thisis_loaded_at: 0x%08x\n",lr);
-#endif
- nfsInit(0,0);
-}
-
-int
-_cexpModuleFinalize(void *mod)
-{
- return nfsCleanup();
-}
-
-
diff --git a/rtemsNfs/src/rpcio.c b/rtemsNfs/src/rpcio.c
deleted file mode 100644
index 1743a5e..0000000
--- a/rtemsNfs/src/rpcio.c
+++ /dev/null
@@ -1,1731 +0,0 @@
-/* $Id$ */
-
-/* RPC multiplexor for a multitasking environment */
-
-/* Author: Till Straumann <strauman@slac.stanford.edu>, 2002 */
-
-/* This code funnels arbitrary task's UDP/RPC requests
- * through one socket to arbitrary servers.
- * The replies are gathered and dispatched to the
- * requestors.
- * One task handles all the sending and receiving
- * work including retries.
- * It is up to the requestor, however, to do
- * the XDR encoding of the arguments / decoding
- * of the results (except for the RPC header which
- * is handled by the daemon).
- *
- * Copyright 2002, Stanford University and
- * Till Straumann <strauman@slac.stanford.edu>
- *
- * Stanford Notice
- * ***************
- *
- * Acknowledgement of sponsorship
- * * * * * * * * * * * * * * * * *
- * This software was produced by the Stanford Linear Accelerator Center,
- * Stanford University, under Contract DE-AC03-76SFO0515 with the Department
- * of Energy.
- *
- * Government disclaimer of liability
- * - - - - - - - - - - - - - - - - -
- * Neither the United States nor the United States Department of Energy,
- * nor any of their employees, makes any warranty, express or implied,
- * or assumes any legal liability or responsibility for the accuracy,
- * completeness, or usefulness of any data, apparatus, product, or process
- * disclosed, or represents that its use would not infringe privately
- * owned rights.
- *
- * Stanford disclaimer of liability
- * - - - - - - - - - - - - - - - - -
- * Stanford University makes no representations or warranties, express or
- * implied, nor assumes any liability for the use of this software.
- *
- * This product is subject to the EPICS open license
- * - - - - - - - - - - - - - - - - - - - - - - - - -
- * Consult the LICENSE file or http://www.aps.anl.gov/epics/license/open.php
- * for more information.
- *
- * Maintenance of notice
- * - - - - - - - - - - -
- * In the interest of clarity regarding the origin and status of this
- * software, Stanford University requests that any recipient of it maintain
- * this notice affixed to any distribution by the recipient that contains a
- * copy or derivative of this software.
- */
-
-#include <rtems.h>
-#include <rtems/error.h>
-#include <stdlib.h>
-#include <time.h>
-#include <rpc/rpc.h>
-#include <rpc/pmap_prot.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <inttypes.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include "rpcio.h"
-
-/****************************************************************/
-/* CONFIGURABLE PARAMETERS */
-/****************************************************************/
-
-#define MBUF_RX /* If defined: use mbuf XDR stream for
- * decoding directly out of mbufs
- * Otherwise, the regular 'recvfrom()'
- * interface will be used involving an
- * extra buffer allocation + copy step.
- */
-
-#define MBUF_TX /* If defined: avoid copying data when
- * sending. Instead, use a wrapper to
- * 'sosend()' which will point an MBUF
- * directly to our buffer space.
- * Note that the BSD stack does not copy
- * data when fragmenting packets - it
- * merely uses an mbuf chain pointing
- * into different areas of the data.
- *
- * If undefined, the regular 'sendto()'
- * interface is used.
- */
-
-#undef REJECT_SERVERIP_MISMATCH
- /* If defined, RPC replies must come from the server
- * that was queried. Eric Norum has reported problems
- * with clustered NFS servers. So we disable this
- * reducing paranoia...
- */
-
-/* daemon task parameters */
-#define RPCIOD_STACK 10000
-#define RPCIOD_PRIO 50
-
-/* depth of the message queue for sending
- * RPC requests to the daemon
- */
-#define RPCIOD_QDEPTH 20
-
-/* Maximum retry limit for retransmission */
-#define RPCIOD_RETX_CAP_S 3 /* seconds */
-
-/* Default timeout for RPC calls */
-#define RPCIOD_DEFAULT_TIMEOUT (&_rpc_default_timeout)
-static struct timeval _rpc_default_timeout = { 10 /* secs */, 0 /* usecs */ };
-
-/* how many times should we try to resend a failed
- * transaction with refreshed AUTHs
- */
-#define RPCIOD_REFRESH 2
-
-/* Events we are using; the RPC_EVENT
- * MUST NOT be used by any application
- * thread doing RPC IO (e.g. NFS)
- */
-#define RTEMS_RPC_EVENT RTEMS_EVENT_30 /* THE event used by RPCIO. Every task doing
- * RPC IO will receive this - hence it is
- * RESERVED
- */
-#define RPCIOD_RX_EVENT RTEMS_EVENT_1 /* Events the RPCIOD is using/waiting for */
-#define RPCIOD_TX_EVENT RTEMS_EVENT_2
-#define RPCIOD_KILL_EVENT RTEMS_EVENT_3 /* send to the daemon to kill it */
-
-#define LD_XACT_HASH 8 /* ld of the size of the transaction hash table */
-
-
-/* Debugging Flags */
-
-/* NOTE: defining DEBUG 0 leaves some 'assert()' paranoia checks
- * but produces no output
- */
-
-#define DEBUG_TRACE_XACT (1<<0)
-#define DEBUG_EVENTS (1<<1)
-#define DEBUG_MALLOC (1<<2)
-#define DEBUG_TIMEOUT (1<<3)
-#define DEBUG_PACKLOSS (1<<4) /* This introduces random, artificial packet losses to test retransmission */
-
-#define DEBUG_PACKLOSS_FRACT (0xffffffff/10)
-
-/* USE PARENTHESIS WHEN 'or'ing MULTIPLE FLAGS: (DEBUG_XX | DEBUG_YY) */
-#define DEBUG (0)
-
-/****************************************************************/
-/* END OF CONFIGURABLE SECTION */
-/****************************************************************/
-
-/* prevent rollover of our timers by readjusting the epoch on the fly */
-#if (DEBUG) & DEBUG_TIMEOUT
-#define RPCIOD_EPOCH_SECS 10
-#else
-#define RPCIOD_EPOCH_SECS 10000
-#endif
-
-#ifdef DEBUG
-#define ASSERT(arg) assert(arg)
-#else
-#define ASSERT(arg) if (arg)
-#endif
-
-/****************************************************************/
-/* MACROS */
-/****************************************************************/
-
-
-#define XACT_HASHS (1<<(LD_XACT_HASH)) /* the hash table size derived from the ld */
-#define XACT_HASH_MSK ((XACT_HASHS)-1) /* mask to extract the hash index from a RPC-XID */
-
-
-#define MU_LOCK(mutex) do { \
- assert( \
- RTEMS_SUCCESSFUL == \
- rtems_semaphore_obtain( \
- (mutex), \
- RTEMS_WAIT, \
- RTEMS_NO_TIMEOUT \
- ) ); \
- } while(0)
-
-#define MU_UNLOCK(mutex) do { \
- assert( \
- RTEMS_SUCCESSFUL == \
- rtems_semaphore_release( \
- (mutex) \
- ) ); \
- } while(0)
-
-#define MU_CREAT(pmutex) do { \
- assert( \
- RTEMS_SUCCESSFUL == \
- rtems_semaphore_create( \
- rtems_build_name( \
- 'R','P','C','l' \
- ), \
- 1, \
- MUTEX_ATTRIBUTES, \
- 0, \
- (pmutex)) ); \
- } while (0)
-
-
-#define MU_DESTROY(mutex) do { \
- assert( \
- RTEMS_SUCCESSFUL == \
- rtems_semaphore_delete( \
- mutex \
- ) ); \
- } while (0)
-
-#define MUTEX_ATTRIBUTES (RTEMS_LOCAL | \
- RTEMS_PRIORITY | \
- RTEMS_INHERIT_PRIORITY | \
- RTEMS_BINARY_SEMAPHORE)
-
-#define FIRST_ATTEMPT 0x88888888 /* some time that is never reached */
-
-/****************************************************************/
-/* TYPE DEFINITIONS */
-/****************************************************************/
-
-typedef rtems_interval TimeoutT;
-
-/* 100000th implementation of a doubly linked list;
- * since only one thread is looking at these,
- * we need no locking
- */
-typedef struct ListNodeRec_ {
- struct ListNodeRec_ *next, *prev;
-} ListNodeRec, *ListNode;
-
-
-/* Structure representing an RPC server */
-typedef struct RpcUdpServerRec_ {
- RpcUdpServer next; /* linked list of all servers; protected by hlock */
- struct sockaddr_in addr;
- AUTH *auth;
- rtems_id authlock; /* must MUTEX the auth object - it's not clear
- * what is better:
- * 1 having one (MUTEXed) auth per server
- * who is shared among all transactions
- * using that server
- * 2 maintaining an AUTH per transaction
- * (there are then other options: manage
- * XACT pools on a per-server basis instead
- * of associating a server with a XACT when
- * sending)
- * experience will show if the current (1)
- * approach has to be changed.
- */
- TimeoutT retry_period; /* dynamically adjusted retry period
- * (based on packet roundtrip time)
- */
- /* STATISTICS */
- unsigned long retrans; /* how many retries were issued by this server */
- unsigned long requests; /* how many requests have been sent */
- unsigned long timeouts; /* how many requests have timed out */
- unsigned long errors; /* how many errors have occurred (other than timeouts) */
- char name[20]; /* server's address in IP 'dot' notation */
-} RpcUdpServerRec;
-
-typedef union RpcBufU_ {
- u_long xid;
- char buf[1];
-} RpcBufU, *RpcBuf;
-
-/* RX Buffer implementation; this is either
- * an MBUF chain (MBUF_RX configuration)
- * or a buffer allocated from the heap
- * where recvfrom copies the (encoded) reply
- * to. The XDR routines the copy/decode
- * it into the user's data structures.
- */
-#ifdef MBUF_RX
-typedef struct mbuf * RxBuf; /* an MBUF chain */
-static void bufFree(struct mbuf **m);
-#define XID(ibuf) (*(mtod((ibuf), u_long *)))
-extern void xdrmbuf_create(XDR *, struct mbuf *, enum xdr_op);
-#else
-typedef RpcBuf RxBuf;
-#define bufFree(b) do { MY_FREE(*(b)); *(b)=0; } while(0)
-#define XID(ibuf) ((ibuf)->xid)
-#endif
-
-/* A RPC 'transaction' consisting
- * of server and requestor information,
- * buffer space and an XDR object
- * (for encoding arguments).
- */
-typedef struct RpcUdpXactRec_ {
- ListNodeRec node; /* so we can put XACTs on a list */
- RpcUdpServer server; /* server this XACT goes to */
- long lifetime; /* during the lifetime, retry attempts are made */
- long tolive; /* lifetime timer */
- struct rpc_err status; /* RPC reply error status */
- long age; /* age info; needed to manage retransmission */
- long trip; /* record round trip time in ticks */
- rtems_id requestor; /* the task waiting for this XACT to complete */
- RpcUdpXactPool pool; /* if this XACT belong to a pool, this is it */
- XDR xdrs; /* argument encoder stream */
- int xdrpos; /* stream position after the (permanent) header */
- xdrproc_t xres; /* reply decoder proc - TODO needn't be here */
- caddr_t pres; /* reply decoded obj - TODO needn't be here */
-#ifndef MBUF_RX
- int ibufsize; /* size of the ibuf (bytes) */
-#endif
-#ifdef MBUF_TX
- int refcnt; /* mbuf external storage reference count */
-#endif
- int obufsize; /* size of the obuf (bytes) */
- RxBuf ibuf; /* pointer to input buffer assigned by daemon */
- RpcBufU obuf; /* output buffer (encoded args) APPENDED HERE */
-} RpcUdpXactRec;
-
-typedef struct RpcUdpXactPoolRec_ {
- rtems_id box;
- int prog;
- int version;
- int xactSize;
-} RpcUdpXactPoolRec;
-
-/* a global hash table where all 'living' transaction
- * objects are registered.
- * A number of bits in a transaction's XID maps 1:1 to
- * an index in this table. Hence, the XACT matching
- * an RPC/UDP reply packet can quickly be found
- * The size of this table imposes a hard limit on the
- * number of all created transactions in the system.
- */
-static RpcUdpXact xactHashTbl[XACT_HASHS]={0};
-
-/* forward declarations */
-static RpcUdpXact
-sockRcv(void);
-
-static void
-rpcio_daemon(rtems_task_argument);
-
-#ifdef MBUF_TX
-ssize_t
-sendto_nocpy (
- int s,
- const void *buf, size_t buflen,
- int flags,
- const struct sockaddr *toaddr, int tolen,
- void *closure,
- void (*freeproc)(caddr_t, u_int),
- void (*refproc)(caddr_t, u_int)
-);
-static void paranoia_free(caddr_t closure, u_int size);
-static void paranoia_ref (caddr_t closure, u_int size);
-#define SENDTO sendto_nocpy
-#else
-#define SENDTO sendto
-#endif
-
-static RpcUdpServer rpcUdpServers = 0; /* linked list of all servers; protected by llock */
-
-static int ourSock = -1; /* the socket we are using for communication */
-static rtems_id rpciod = 0; /* task id of the RPC daemon */
-static rtems_id msgQ = 0; /* message queue where the daemon picks up
- * requests
- */
-static rtems_id llock = 0; /* MUTEX protecting the server list */
-static rtems_id hlock = 0; /* MUTEX protecting the hash table and the list of servers */
-static rtems_id fini = 0; /* a synchronization semaphore we use during
- * module cleanup / driver unloading
- */
-static rtems_interval ticksPerSec; /* cached system clock rate (WHO IS ASSUMED NOT
- * TO CHANGE)
- */
-#if (DEBUG) & DEBUG_MALLOC
-/* malloc wrappers for debugging */
-static int nibufs = 0;
-
-static inline void *MY_MALLOC(int s)
-{
- if (s) {
- void *rval;
- MU_LOCK(hlock);
- assert(nibufs++ < 2000);
- MU_UNLOCK(hlock);
- assert(rval = malloc(s));
- return rval;
- }
- return 0;
-}
-
-static inline void *MY_CALLOC(int n, int s)
-{
- if (s) {
- void *rval;
- MU_LOCK(hlock);
- assert(nibufs++ < 2000);
- MU_UNLOCK(hlock);
- assert(rval = calloc(n,s));
- return rval;
- }
- return 0;
-}
-
-
-static inline void MY_FREE(void *p)
-{
- if (p) {
- MU_LOCK(hlock);
- nibufs--;
- MU_UNLOCK(hlock);
- free(p);
- }
-}
-#else
-#define MY_MALLOC malloc
-#define MY_CALLOC calloc
-#define MY_FREE free
-#endif
-
-static inline bool_t
-locked_marshal(RpcUdpServer s, XDR *xdrs)
-{
-bool_t rval;
- MU_LOCK(s->authlock);
- rval = AUTH_MARSHALL(s->auth, xdrs);
- MU_UNLOCK(s->authlock);
- return rval;
-}
-
-/* Locked operations on a server's auth object */
-static inline bool_t
-locked_validate(RpcUdpServer s, struct opaque_auth *v)
-{
-bool_t rval;
- MU_LOCK(s->authlock);
- rval = AUTH_VALIDATE(s->auth, v);
- MU_UNLOCK(s->authlock);
- return rval;
-}
-
-static inline bool_t
-locked_refresh(RpcUdpServer s)
-{
-bool_t rval;
- MU_LOCK(s->authlock);
- rval = AUTH_REFRESH(s->auth);
- MU_UNLOCK(s->authlock);
- return rval;
-}
-
-/* Create a server object
- *
- */
-enum clnt_stat
-rpcUdpServerCreate(
- struct sockaddr_in *paddr,
- int prog,
- int vers,
- u_long uid,
- u_long gid,
- RpcUdpServer *psrv
- )
-{
-RpcUdpServer rval;
-u_short port;
-char hname[MAX_MACHINE_NAME + 1];
-int theuid, thegid;
-int thegids[NGRPS];
-gid_t gids[NGROUPS];
-int len,i;
-AUTH *auth;
-enum clnt_stat pmap_err;
-struct pmap pmaparg;
-
- if ( gethostname(hname, MAX_MACHINE_NAME) ) {
- fprintf(stderr,
- "RPCIO - error: I have no hostname ?? (%s)\n",
- strerror(errno));
- return RPC_UNKNOWNHOST;
- }
-
- if ( (len = getgroups(NGROUPS, gids) < 0 ) ) {
- fprintf(stderr,
- "RPCIO - error: I unable to get group ids (%s)\n",
- strerror(errno));
- return RPC_FAILED;
- }
-
- if ( len > NGRPS )
- len = NGRPS;
-
- for (i=0; i<len; i++)
- thegids[i] = (int)gids[i];
-
- theuid = (int) ((RPCIOD_DEFAULT_ID == uid) ? geteuid() : uid);
- thegid = (int) ((RPCIOD_DEFAULT_ID == gid) ? getegid() : gid);
-
- if ( !(auth = authunix_create(hname, theuid, thegid, len, thegids)) ) {
- fprintf(stderr,
- "RPCIO - error: unable to create RPC AUTH\n");
- return RPC_FAILED;
- }
-
- /* if they specified no port try to ask the portmapper */
- if (!paddr->sin_port) {
-
- paddr->sin_port = htons(PMAPPORT);
-
- pmaparg.pm_prog = prog;
- pmaparg.pm_vers = vers;
- pmaparg.pm_prot = IPPROTO_UDP;
- pmaparg.pm_port = 0; /* not needed or used */
-
-
- /* dont use non-reentrant pmap_getport ! */
-
- pmap_err = rpcUdpCallRp(
- paddr,
- PMAPPROG,
- PMAPVERS,
- PMAPPROC_GETPORT,
- xdr_pmap,
- &pmaparg,
- xdr_u_short,
- &port,
- uid,
- gid,
- 0);
-
- if ( RPC_SUCCESS != pmap_err ) {
- paddr->sin_port = 0;
- return pmap_err;
- }
-
- paddr->sin_port = htons(port);
- }
-
- if (0==paddr->sin_port) {
- return RPC_PROGNOTREGISTERED;
- }
-
- rval = (RpcUdpServer)MY_MALLOC(sizeof(*rval));
- memset(rval, 0, sizeof(*rval));
-
- if (!inet_ntop(AF_INET, &paddr->sin_addr, rval->name, sizeof(rval->name)))
- sprintf(rval->name,"?.?.?.?");
- rval->addr = *paddr;
-
- /* start with a long retransmission interval - it
- * will be adapted dynamically
- */
- rval->retry_period = RPCIOD_RETX_CAP_S * ticksPerSec;
-
- rval->auth = auth;
-
- MU_CREAT( &rval->authlock );
-
- /* link into list */
- MU_LOCK( llock );
- rval->next = rpcUdpServers;
- rpcUdpServers = rval;
- MU_UNLOCK( llock );
-
- *psrv = rval;
- return RPC_SUCCESS;
-}
-
-void
-rpcUdpServerDestroy(RpcUdpServer s)
-{
-RpcUdpServer prev;
- if (!s)
- return;
- /* we should probably verify (but how?) that nobody
- * (at least: no outstanding XACTs) is using this
- * server;
- */
-
- /* remove from server list */
- MU_LOCK(llock);
- prev = rpcUdpServers;
- if ( s == prev ) {
- rpcUdpServers = s->next;
- } else {
- for ( ; prev ; prev = prev->next) {
- if (prev->next == s) {
- prev->next = s->next;
- break;
- }
- }
- }
- MU_UNLOCK(llock);
-
- /* MUST have found it */
- assert(prev);
-
- auth_destroy(s->auth);
-
- MU_DESTROY(s->authlock);
- MY_FREE(s);
-}
-
-int
-rpcUdpStats(FILE *f)
-{
-RpcUdpServer s;
-
- if (!f) f = stdout;
-
- fprintf(f,"RPCIOD statistics:\n");
-
- MU_LOCK(llock);
- for (s = rpcUdpServers; s; s=s->next) {
- fprintf(f,"\nServer -- %s:\n", s->name);
- fprintf(f," requests sent: %10ld, retransmitted: %10ld\n",
- s->requests, s->retrans);
- fprintf(f," timed out: %10ld, send errors: %10ld\n",
- s->timeouts, s->errors);
- fprintf(f," current retransmission interval: %" PRId32 "ms\n",
- s->retry_period * 1000 / ticksPerSec );
- }
- MU_UNLOCK(llock);
-
- return 0;
-}
-
-RpcUdpXact
-rpcUdpXactCreate(
- u_long program,
- u_long version,
- u_long size
- )
-{
-RpcUdpXact rval=0;
-struct rpc_msg header;
-register int i,j;
-
- if (!size)
- size = UDPMSGSIZE;
- /* word align */
- size = (size + 3) & ~3;
-
- rval = (RpcUdpXact)MY_CALLOC(1,sizeof(*rval) - sizeof(rval->obuf) + size);
-
- if (rval) {
-
- header.rm_xid = 0;
- header.rm_direction = CALL;
- header.rm_call.cb_rpcvers = RPC_MSG_VERSION;
- header.rm_call.cb_prog = program;
- header.rm_call.cb_vers = version;
- xdrmem_create(&(rval->xdrs), rval->obuf.buf, size, XDR_ENCODE);
-
- if (!xdr_callhdr(&(rval->xdrs), &header)) {
- MY_FREE(rval);
- return 0;
- }
- /* pick a free table slot and initialize the XID */
- rval->obuf.xid = time(0) ^ (unsigned long)rval;
- MU_LOCK(hlock);
- i=j=(rval->obuf.xid & XACT_HASH_MSK);
- if (msgQ) {
- /* if there's no message queue, refuse to
- * give them transactions; we might be in the process to
- * go away...
- */
- do {
- i=(i+1) & XACT_HASH_MSK; /* cheap modulo */
- if (!xactHashTbl[i]) {
-#if (DEBUG) & DEBUG_TRACE_XACT
- fprintf(stderr,"RPCIO: entering index %i, val %x\n",i,rval);
-#endif
- xactHashTbl[i]=rval;
- j=-1;
- break;
- }
- } while (i!=j);
- }
- MU_UNLOCK(hlock);
- if (i==j) {
- XDR_DESTROY(&rval->xdrs);
- MY_FREE(rval);
- return 0;
- }
- rval->obuf.xid = (rval->obuf.xid << LD_XACT_HASH) | i;
- rval->xdrpos = XDR_GETPOS(&(rval->xdrs));
- rval->obufsize = size;
- }
- return rval;
-}
-
-void
-rpcUdpXactDestroy(RpcUdpXact xact)
-{
-int i = xact->obuf.xid & XACT_HASH_MSK;
-
-#if (DEBUG) & DEBUG_TRACE_XACT
- fprintf(stderr,"RPCIO: removing index %i, val %x\n",i,xact);
-#endif
-
- ASSERT( xactHashTbl[i]==xact );
-
- MU_LOCK(hlock);
- xactHashTbl[i]=0;
- MU_UNLOCK(hlock);
-
- bufFree(&xact->ibuf);
-
- XDR_DESTROY(&xact->xdrs);
- MY_FREE(xact);
-}
-
-
-
-/* Send a transaction, i.e. enqueue it to the
- * RPC daemon who will actually send it.
- */
-enum clnt_stat
-rpcUdpSend(
- RpcUdpXact xact,
- RpcUdpServer srvr,
- struct timeval *timeout,
- u_long proc,
- xdrproc_t xres, caddr_t pres,
- xdrproc_t xargs, caddr_t pargs,
- ...
- )
-{
-register XDR *xdrs;
-unsigned long ms;
-va_list ap;
-
- va_start(ap,pargs);
-
- if (!timeout)
- timeout = RPCIOD_DEFAULT_TIMEOUT;
-
- ms = 1000 * timeout->tv_sec + timeout->tv_usec/1000;
-
- xact->lifetime = ms * ticksPerSec / 1000;
-#if (DEBUG) & DEBUG_TIMEOUT
- {
- static int once=0;
- if (!once++) {
- fprintf(stderr,
- "Initial lifetime: %i (ticks)\n",
- xact->lifetime);
- }
- }
-#endif
-
- xact->tolive = xact->lifetime;
-
- xact->xres = xres;
- xact->pres = pres;
- xact->server = srvr;
-
- xdrs = &xact->xdrs;
- xdrs->x_op = XDR_ENCODE;
- /* increment transaction ID */
- xact->obuf.xid += XACT_HASHS;
- XDR_SETPOS(xdrs, xact->xdrpos);
- if ( !XDR_PUTLONG(xdrs,(long*)&proc) || !locked_marshal(srvr, xdrs) ||
- !xargs(xdrs, pargs) ) {
- va_end(ap);
- return(xact->status.re_status=RPC_CANTENCODEARGS);
- }
- while ((xargs=va_arg(ap,xdrproc_t))) {
- if (!xargs(xdrs, va_arg(ap,caddr_t)))
- va_end(ap);
- return(xact->status.re_status=RPC_CANTENCODEARGS);
- }
-
- va_end(ap);
-
- rtems_task_ident(RTEMS_SELF, RTEMS_WHO_AM_I, &xact->requestor);
- if ( rtems_message_queue_send( msgQ, &xact, sizeof(xact)) ) {
- return RPC_CANTSEND;
- }
- /* wakeup the rpciod */
- ASSERT( RTEMS_SUCCESSFUL==rtems_event_send(rpciod, RPCIOD_TX_EVENT) );
-
- return RPC_SUCCESS;
-}
-
-/* Block for the RPC reply to an outstanding
- * transaction.
- * The caller is woken by the RPC daemon either
- * upon reception of the reply or on timeout.
- */
-enum clnt_stat
-rpcUdpRcv(RpcUdpXact xact)
-{
-int refresh;
-XDR reply_xdrs;
-struct rpc_msg reply_msg;
-rtems_event_set gotEvents;
-
- refresh = 0;
-
- do {
-
- /* block for the reply */
- ASSERT( RTEMS_SUCCESSFUL ==
- rtems_event_receive(
- RTEMS_RPC_EVENT,
- RTEMS_WAIT | RTEMS_EVENT_ANY,
- RTEMS_NO_TIMEOUT,
- &gotEvents) );
-
- if (xact->status.re_status) {
-#ifdef MBUF_RX
- /* add paranoia */
- ASSERT( !xact->ibuf );
-#endif
- return xact->status.re_status;
- }
-
-#ifdef MBUF_RX
- xdrmbuf_create(&reply_xdrs, xact->ibuf, XDR_DECODE);
-#else
- xdrmem_create(&reply_xdrs, xact->ibuf->buf, xact->ibufsize, XDR_DECODE);
-#endif
-
- reply_msg.acpted_rply.ar_verf = _null_auth;
- reply_msg.acpted_rply.ar_results.where = xact->pres;
- reply_msg.acpted_rply.ar_results.proc = xact->xres;
-
- if (xdr_replymsg(&reply_xdrs, &reply_msg)) {
- /* OK */
- _seterr_reply(&reply_msg, &xact->status);
- if (RPC_SUCCESS == xact->status.re_status) {
- if ( !locked_validate(xact->server,
- &reply_msg.acpted_rply.ar_verf) ) {
- xact->status.re_status = RPC_AUTHERROR;
- xact->status.re_why = AUTH_INVALIDRESP;
- }
- if (reply_msg.acpted_rply.ar_verf.oa_base) {
- reply_xdrs.x_op = XDR_FREE;
- xdr_opaque_auth(&reply_xdrs, &reply_msg.acpted_rply.ar_verf);
- }
- refresh = 0;
- } else {
- /* should we try to refresh our credentials ? */
- if ( !refresh ) {
- /* had never tried before */
- refresh = RPCIOD_REFRESH;
- }
- }
- } else {
- reply_xdrs.x_op = XDR_FREE;
- xdr_replymsg(&reply_xdrs, &reply_msg);
- xact->status.re_status = RPC_CANTDECODERES;
- }
- XDR_DESTROY(&reply_xdrs);
-
- bufFree(&xact->ibuf);
-
-#ifndef MBUF_RX
- xact->ibufsize = 0;
-#endif
-
- if (refresh && locked_refresh(xact->server)) {
- rtems_task_ident(RTEMS_SELF, RTEMS_WHO_AM_I, &xact->requestor);
- if ( rtems_message_queue_send(msgQ, &xact, sizeof(xact)) ) {
- return RPC_CANTSEND;
- }
- /* wakeup the rpciod */
- fprintf(stderr,"RPCIO INFO: refreshing my AUTH\n");
- ASSERT( RTEMS_SUCCESSFUL==rtems_event_send(rpciod, RPCIOD_TX_EVENT) );
- }
-
- } while ( 0 && refresh-- > 0 );
-
- return xact->status.re_status;
-}
-
-
-/* On RTEMS, I'm told to avoid select(); this seems to
- * be more efficient
- */
-static void
-rxWakeupCB(struct socket *sock, caddr_t arg)
-{
-rtems_event_send((rtems_id)arg, RPCIOD_RX_EVENT);
-}
-
-int
-rpcUdpInit(void)
-{
-int noblock = 1;
-struct sockwakeup wkup;
-
- fprintf(stderr,"This is RTEMS-RPCIOD Release $Name$\n");
- fprintf(stderr,"($Id$)\n\n");
- fprintf(stderr,"Till Straumann, Stanford/SLAC/SSRL 2002\n");
- fprintf(stderr,"See LICENSE file for licensing info\n");
-
- if (ourSock < 0) {
- ourSock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (ourSock>=0) {
- bindresvport(ourSock,(struct sockaddr_in*)0);
- assert( 0==ioctl(ourSock, FIONBIO, (char*)&noblock) );
- /* assume nobody tampers with the clock !! */
- assert( RTEMS_SUCCESSFUL == rtems_clock_get(
- RTEMS_CLOCK_GET_TICKS_PER_SECOND,
- &ticksPerSec));
- MU_CREAT( &hlock );
- MU_CREAT( &llock );
-
- assert( RTEMS_SUCCESSFUL == rtems_task_create(
- rtems_build_name('R','P','C','d'),
- RPCIOD_PRIO,
- RPCIOD_STACK,
- RTEMS_DEFAULT_MODES,
- /* fprintf saves/restores FP registers on PPC :-( */
- RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
- &rpciod) );
- wkup.sw_pfn = rxWakeupCB;
- wkup.sw_arg = (caddr_t)rpciod;
- assert( 0==setsockopt(ourSock, SOL_SOCKET, SO_RCVWAKEUP, &wkup, sizeof(wkup)) );
- assert( RTEMS_SUCCESSFUL == rtems_message_queue_create(
- rtems_build_name('R','P','C','q'),
- RPCIOD_QDEPTH,
- sizeof(RpcUdpXact),
- RTEMS_DEFAULT_ATTRIBUTES,
- &msgQ) );
- assert( RTEMS_SUCCESSFUL == rtems_task_start(
- rpciod,
- rpcio_daemon,
- 0 ) );
-
- } else {
- return -1;
- }
- }
- return 0;
-}
-
-int
-rpcUdpCleanup(void)
-{
- rtems_semaphore_create(
- rtems_build_name('R','P','C','f'),
- 0,
- RTEMS_DEFAULT_ATTRIBUTES,
- 0,
- &fini);
- rtems_event_send(rpciod, RPCIOD_KILL_EVENT);
- /* synchronize with daemon */
- rtems_semaphore_obtain(fini, RTEMS_WAIT, 5*ticksPerSec);
- /* if the message queue is still there, something went wrong */
- if (!msgQ) {
- rtems_task_delete(rpciod);
- }
- rtems_semaphore_delete(fini);
- return (msgQ !=0);
-}
-
-/* Another API - simpler but less efficient.
- * For each RPCall, a server and a Xact
- * are created and destroyed on the fly.
- *
- * This should be used for infrequent calls
- * (e.g. a NFS mount request).
- *
- * This is roughly compatible with the original
- * clnt_call() etc. API - but it uses our
- * daemon and is fully reentrant.
- */
-enum clnt_stat
-rpcUdpClntCreate(
- struct sockaddr_in *psaddr,
- int prog,
- int vers,
- u_long uid,
- u_long gid,
- RpcUdpClnt *pclnt
-)
-{
-RpcUdpXact x;
-RpcUdpServer s;
-enum clnt_stat err;
-
- if ( RPC_SUCCESS != (err=rpcUdpServerCreate(psaddr, prog, vers, uid, gid, &s)) )
- return err;
-
- if ( !(x=rpcUdpXactCreate(prog, vers, UDPMSGSIZE)) ) {
- rpcUdpServerDestroy(s);
- return RPC_FAILED;
- }
- /* TODO: could maintain a server cache */
-
- x->server = s;
-
- *pclnt = x;
-
- return RPC_SUCCESS;
-}
-
-void
-rpcUdpClntDestroy(RpcUdpClnt xact)
-{
- rpcUdpServerDestroy(xact->server);
- rpcUdpXactDestroy(xact);
-}
-
-enum clnt_stat
-rpcUdpClntCall(
- RpcUdpClnt xact,
- u_long proc,
- XdrProcT xargs,
- CaddrT pargs,
- XdrProcT xres,
- CaddrT pres,
- struct timeval *timeout
- )
-{
-enum clnt_stat stat;
-
- if ( (stat = rpcUdpSend(xact, xact->server, timeout, proc,
- xres, pres,
- xargs, pargs,
- 0)) ) {
- fprintf(stderr,"RPCIO Send failed: %i\n",stat);
- return stat;
- }
- return rpcUdpRcv(xact);
-}
-
-/* a yet simpler interface */
-enum clnt_stat
-rpcUdpCallRp(
- struct sockaddr_in *psrvr,
- u_long prog,
- u_long vers,
- u_long proc,
- XdrProcT xargs,
- CaddrT pargs,
- XdrProcT xres,
- CaddrT pres,
- u_long uid, /* RPCIO_DEFAULT_ID picks default */
- u_long gid, /* RPCIO_DEFAULT_ID picks default */
- struct timeval *timeout /* NULL picks default */
-)
-{
-RpcUdpClnt clp;
-enum clnt_stat stat;
-
- stat = rpcUdpClntCreate(
- psrvr,
- prog,
- vers,
- uid,
- gid,
- &clp);
-
- if ( RPC_SUCCESS != stat )
- return stat;
-
- stat = rpcUdpClntCall(
- clp,
- proc,
- xargs, pargs,
- xres, pres,
- timeout);
-
- rpcUdpClntDestroy(clp);
-
- return stat;
-}
-
-/* linked list primitives */
-static void
-nodeXtract(ListNode n)
-{
- if (n->prev)
- n->prev->next = n->next;
- if (n->next)
- n->next->prev = n->prev;
- n->next = n->prev = 0;
-}
-
-static void
-nodeAppend(ListNode l, ListNode n)
-{
- if ( (n->next = l->next) )
- n->next->prev = n;
- l->next = n;
- n->prev = l;
-
-}
-
-/* this code does the work */
-static void
-rpcio_daemon(rtems_task_argument arg)
-{
-rtems_status_code stat;
-RpcUdpXact xact;
-RpcUdpServer srv;
-rtems_interval next_retrans, then, unow;
-long now; /* need to do signed comparison with age! */
-rtems_event_set events;
-ListNode newList;
-uint32_t size;
-rtems_id q = 0;
-ListNodeRec listHead = {0};
-unsigned long epoch = RPCIOD_EPOCH_SECS * ticksPerSec;
-unsigned long max_period = RPCIOD_RETX_CAP_S * ticksPerSec;
-
- assert( RTEMS_SUCCESSFUL == rtems_clock_get(
- RTEMS_CLOCK_GET_TICKS_SINCE_BOOT,
- &then) );
-
- for (next_retrans = epoch;;) {
-
- if ( RTEMS_SUCCESSFUL !=
- (stat = rtems_event_receive(
- RPCIOD_RX_EVENT | RPCIOD_TX_EVENT | RPCIOD_KILL_EVENT,
- RTEMS_WAIT | RTEMS_EVENT_ANY,
- next_retrans,
- &events)) ) {
- ASSERT( RTEMS_TIMEOUT == stat );
- events = 0;
- }
-
- if (events & RPCIOD_KILL_EVENT) {
- int i;
-
-#if (DEBUG) & DEBUG_EVENTS
- fprintf(stderr,"RPCIO: got KILL event\n");
-#endif
-
- MU_LOCK(hlock);
- for (i=XACT_HASHS-1; i>=0; i--) {
- if (xactHashTbl[i]) {
- break;
- }
- }
- if (i<0) {
- /* prevent them from creating and enqueueing more messages */
- q=msgQ;
- /* messages queued after we executed this assignment will fail */
- msgQ=0;
- }
- MU_UNLOCK(hlock);
- if (i>=0) {
- fprintf(stderr,"RPCIO There are still transactions circulating; I refuse to go away\n");
- fprintf(stderr,"(1st in slot %i)\n",i);
- rtems_semaphore_release(fini);
- } else {
- break;
- }
- }
-
- ASSERT( RTEMS_SUCCESSFUL == rtems_clock_get(
- RTEMS_CLOCK_GET_TICKS_SINCE_BOOT,
- &unow ) );
-
- /* measure everything relative to then to protect against
- * rollover
- */
- now = unow - then;
-
- /* NOTE: we don't lock the hash table while we are operating
- * on transactions; the paradigm is that we 'own' a particular
- * transaction (and hence it's hash table slot) from the
- * time the xact was put into the message queue until we
- * wake up the requestor.
- */
-
- if (RPCIOD_RX_EVENT & events) {
-
-#if (DEBUG) & DEBUG_EVENTS
- fprintf(stderr,"RPCIO: got RX event\n");
-#endif
-
- while ((xact=sockRcv())) {
-
- /* extract from the retransmission list */
- nodeXtract(&xact->node);
-
- /* change the ID - there might already be
- * a retransmission on the way. When it's
- * reply arrives we must not find it's ID
- * in the hashtable
- */
- xact->obuf.xid += XACT_HASHS;
-
- xact->status.re_status = RPC_SUCCESS;
-
- /* calculate roundtrip ticks */
- xact->trip = now - xact->trip;
-
- srv = xact->server;
-
- /* adjust the server's retry period */
- {
- register TimeoutT rtry = srv->retry_period;
- register TimeoutT trip = xact->trip;
-
- ASSERT( trip >= 0 );
-
- if ( 0==trip )
- trip = 1;
-
- /* retry_new = 0.75*retry_old + 0.25 * 8 * roundrip */
- rtry = (3*rtry + (trip << 3)) >> 2;
-
- if ( rtry > max_period )
- rtry = max_period;
-
- srv->retry_period = rtry;
- }
-
- /* wakeup requestor */
- rtems_event_send(xact->requestor, RTEMS_RPC_EVENT);
- }
- }
-
- if (RPCIOD_TX_EVENT & events) {
-
-#if (DEBUG) & DEBUG_EVENTS
- fprintf(stderr,"RPCIO: got TX event\n");
-#endif
-
- while (RTEMS_SUCCESSFUL == rtems_message_queue_receive(
- msgQ,
- &xact,
- &size,
- RTEMS_NO_WAIT,
- RTEMS_NO_TIMEOUT)) {
- /* put to the head of timeout q */
- nodeAppend(&listHead, &xact->node);
-
- xact->age = now;
- xact->trip = FIRST_ATTEMPT;
- }
- }
-
-
- /* work the timeout q */
- newList = 0;
- for ( xact=(RpcUdpXact)listHead.next;
- xact && xact->age <= now;
- xact=(RpcUdpXact)listHead.next ) {
-
- /* extract from the list */
- nodeXtract(&xact->node);
-
- srv = xact->server;
-
- if (xact->tolive < 0) {
- /* this one timed out */
- xact->status.re_errno = ETIMEDOUT;
- xact->status.re_status = RPC_TIMEDOUT;
-
- srv->timeouts++;
-
-#if (DEBUG) & DEBUG_TIMEOUT
- fprintf(stderr,"RPCIO XACT timed out; waking up requestor\n");
-#endif
- if ( rtems_event_send(xact->requestor, RTEMS_RPC_EVENT) ) {
- rtems_panic("RPCIO PANIC file %s line: %i, requestor id was 0x%08x",
- __FILE__,
- __LINE__,
- xact->requestor);
- }
-
- } else {
- int len;
-
- len = (int)XDR_GETPOS(&xact->xdrs);
-
-#ifdef MBUF_TX
- xact->refcnt = 1; /* sendto itself */
-#endif
- if ( len != SENDTO( ourSock,
- xact->obuf.buf,
- len,
- 0,
- (struct sockaddr*) &srv->addr,
- sizeof(srv->addr)
-#ifdef MBUF_TX
- , xact,
- paranoia_free,
- paranoia_ref
-#endif
- ) ) {
-
- xact->status.re_errno = errno;
- xact->status.re_status = RPC_CANTSEND;
- srv->errors++;
-
- /* wakeup requestor */
- fprintf(stderr,"RPCIO: SEND failure\n");
- ASSERT( RTEMS_SUCCESSFUL ==
- rtems_event_send(xact->requestor, RTEMS_RPC_EVENT) );
-
- } else {
- /* send successful; calculate retransmission time
- * and enqueue to temporary list
- */
- if (FIRST_ATTEMPT != xact->trip) {
-#if (DEBUG) & DEBUG_TIMEOUT
- fprintf(stderr,
- "timed out; tolive is %i (ticks), retry period is %i (ticks)\n",
- xact->tolive,
- srv->retry_period);
-#endif
- /* this is a real retry; we backup
- * the server's retry interval
- */
- if ( srv->retry_period < max_period ) {
-
- /* If multiple transactions for this server
- * fail (e.g. because it died) this will
- * back-off very agressively (doubling
- * the retransmission period for every
- * timed out transaction up to the CAP limit)
- * which is desirable - single packet failure
- * is treated more gracefully by this algorithm.
- */
-
- srv->retry_period<<=1;
-#if (DEBUG) & DEBUG_TIMEOUT
- fprintf(stderr,
- "adjusted to; retry period %i\n",
- srv->retry_period);
-#endif
- } else {
- /* never wait longer than RPCIOD_RETX_CAP_S seconds */
- fprintf(stderr,
- "RPCIO: server '%s' not responding - still trying\n",
- srv->name);
- }
- if ( 0 == ++srv->retrans % 1000) {
- fprintf(stderr,
- "RPCIO - statistics: already %li retries to server %s\n",
- srv->retrans,
- srv->name);
- }
- } else {
- srv->requests++;
- }
- xact->trip = now;
- xact->age = now + srv->retry_period;
- xact->tolive -= srv->retry_period;
- /* enqueue to the list of newly sent transactions */
- xact->node.next = newList;
- newList = &xact->node;
-#if (DEBUG) & DEBUG_TIMEOUT
- fprintf(stderr,
- "XACT (0x%08x) age is 0x%x, now: 0x%x\n",
- xact,
- xact->age,
- now);
-#endif
- }
- }
- }
-
- /* insert the newly sent transactions into the
- * sorted retransmission list
- */
- for (; (xact = (RpcUdpXact)newList); ) {
- register ListNode p,n;
- newList = newList->next;
- for ( p=&listHead; (n=p->next) && xact->age > ((RpcUdpXact)n)->age; p=n )
- /* nothing else to do */;
- nodeAppend(p, &xact->node);
- }
-
- if (now > epoch) {
- /* every now and then, readjust the epoch */
- register ListNode n;
- then += now;
- for (n=listHead.next; n; n=n->next) {
- /* readjust outstanding time intervals subject to the
- * condition that the 'absolute' time must remain
- * the same. 'age' and 'trip' are measured with
- * respect to 'then' - hence:
- *
- * abs_age == old_age + old_then == new_age + new_then
- *
- * ==> new_age = old_age + old_then - new_then == old_age - 'now'
- */
- ((RpcUdpXact)n)->age -= now;
- ((RpcUdpXact)n)->trip -= now;
-#if (DEBUG) & DEBUG_TIMEOUT
- fprintf(stderr,
- "readjusted XACT (0x%08x); age is 0x%x, trip: 0x%x now: 0x%x\n",
- (RpcUdpXact)n,
- ((RpcUdpXact)n)->trip,
- ((RpcUdpXact)n)->age,
- now);
-#endif
- }
- now = 0;
- }
-
- next_retrans = listHead.next ?
- ((RpcUdpXact)listHead.next)->age - now :
- epoch; /* make sure we don't miss updating the epoch */
-#if (DEBUG) & DEBUG_TIMEOUT
- fprintf(stderr,"RPCIO: next timeout is %x\n",next_retrans);
-#endif
- }
- /* close our socket; shut down the receiver */
- close(ourSock);
-
-#if 0 /* if we get here, no transactions exist, hence there can be none
- * in the queue whatsoever
- */
- /* flush the message queue */
- while (RTEMS_SUCCESSFUL == rtems_message_queue_receive(
- q,
- &xact,
- &size,
- RTEMS_NO_WAIT,
- RTEMS_NO_TIMEOUT)) {
- /* TODO enque xact */
- }
-
- /* flush all outstanding transactions */
-
- for (xact=((RpcUdpXact)listHead.next); xact; xact=((RpcUdpXact)xact->node.next)) {
- xact->status.re_status = RPC_TIMEDOUT;
- rtems_event_send(xact->requestor, RTEMS_RPC_EVENT);
- }
-#endif
-
- rtems_message_queue_delete(q);
-
- MU_DESTROY(hlock);
-
- fprintf(stderr,"RPC daemon exited...\n");
-
- rtems_semaphore_release(fini);
- rtems_task_suspend(RTEMS_SELF);
-}
-
-
-/* support for transaction 'pools'. A number of XACT objects
- * is always kept around. The initial number is 0 but it
- * is allowed to grow up to a maximum.
- * If the need grows beyond the maximum, behavior depends:
- * Users can either block until a transaction becomes available,
- * they can create a new XACT on the fly or get an error
- * if no free XACT is available from the pool.
- */
-
-RpcUdpXactPool
-rpcUdpXactPoolCreate(
- int prog, int version,
- int xactsize, int poolsize)
-{
-RpcUdpXactPool rval = MY_MALLOC(sizeof(*rval));
-
- ASSERT( rval &&
- RTEMS_SUCCESSFUL == rtems_message_queue_create(
- rtems_build_name('R','P','C','p'),
- poolsize,
- sizeof(RpcUdpXact),
- RTEMS_DEFAULT_ATTRIBUTES,
- &rval->box) );
- rval->prog = prog;
- rval->version = version;
- rval->xactSize = xactsize;
- return rval;
-}
-
-void
-rpcUdpXactPoolDestroy(RpcUdpXactPool pool)
-{
-RpcUdpXact xact;
-
- while ((xact = rpcUdpXactPoolGet(pool, XactGetFail))) {
- rpcUdpXactDestroy(xact);
- }
- rtems_message_queue_delete(pool->box);
- MY_FREE(pool);
-}
-
-RpcUdpXact
-rpcUdpXactPoolGet(RpcUdpXactPool pool, XactPoolGetMode mode)
-{
-RpcUdpXact xact = 0;
-uint32_t size;
-
- if (RTEMS_SUCCESSFUL != rtems_message_queue_receive(
- pool->box,
- &xact,
- &size,
- XactGetWait == mode ?
- RTEMS_WAIT : RTEMS_NO_WAIT,
- RTEMS_NO_TIMEOUT)) {
-
- /* nothing found in box; should we create a new one ? */
-
- xact = (XactGetCreate == mode) ?
- rpcUdpXactCreate(
- pool->prog,
- pool->version,
- pool->xactSize) : 0 ;
- if (xact)
- xact->pool = pool;
-
- }
- return xact;
-}
-
-void
-rpcUdpXactPoolPut(RpcUdpXact xact)
-{
-RpcUdpXactPool pool;
- ASSERT( pool=xact->pool );
- if (RTEMS_SUCCESSFUL != rtems_message_queue_send(
- pool->box,
- &xact,
- sizeof(xact)))
- rpcUdpXactDestroy(xact);
-}
-
-#ifdef MBUF_RX
-
-/* WORKAROUND: include sys/mbuf.h (or other bsdnet headers) only
- * _after_ using malloc()/free() & friends because
- * the RTEMS/BSDNET headers redefine those :-(
- */
-
-#define KERNEL
-#define _KERNEL
-#include <sys/mbuf.h>
-
-ssize_t
-recv_mbuf_from(int s, struct mbuf **ppm, long len, struct sockaddr *fromaddr, int *fromlen);
-
-static void
-bufFree(struct mbuf **m)
-{
- if (*m) {
- rtems_bsdnet_semaphore_obtain();
- m_freem(*m);
- rtems_bsdnet_semaphore_release();
- *m = 0;
- }
-}
-#endif
-
-#ifdef MBUF_TX
-static void
-paranoia_free(caddr_t closure, u_int size)
-{
-#if (DEBUG)
-RpcUdpXact xact = (RpcUdpXact)closure;
-int len = (int)XDR_GETPOS(&xact->xdrs);
-
- ASSERT( --xact->refcnt >= 0 && size == len );
-#endif
-}
-
-static void
-paranoia_ref (caddr_t closure, u_int size)
-{
-#if (DEBUG)
-RpcUdpXact xact = (RpcUdpXact)closure;
-int len = (int)XDR_GETPOS(&xact->xdrs);
- ASSERT( size == len );
- xact->refcnt++;
-#endif
-}
-#endif
-
-/* receive from a socket and find
- * the transaction corresponding to the
- * transaction ID received in the server
- * reply.
- *
- * The semantics of the 'pibuf' pointer are
- * as follows:
- *
- * MBUF_RX:
- *
- */
-
-#define RPCIOD_RXBUFSZ UDPMSGSIZE
-
-static RpcUdpXact
-sockRcv(void)
-{
-int len,i;
-u_long xid;
-struct sockaddr_in fromAddr;
-int fromLen = sizeof(fromAddr);
-RxBuf ibuf = 0;
-RpcUdpXact xact = 0;
-
- do {
-
- /* rcv_mbuf() and recvfrom() differ in that the
- * former allocates buffers and passes them back
- * to us whereas the latter requires us to provide
- * buffer space.
- * Hence, in the first case whe have to make sure
- * no old buffer is leaked - in the second case,
- * we might well re-use an old buffer but must
- * make sure we have one allocated
- */
-#ifdef MBUF_RX
- if (ibuf)
- bufFree(&ibuf);
-
- len = recv_mbuf_from(
- ourSock,
- &ibuf,
- RPCIOD_RXBUFSZ,
- (struct sockaddr*)&fromAddr,
- &fromLen);
-#else
- if ( !ibuf )
- ibuf = (RpcBuf)MY_MALLOC(RPCIOD_RXBUFSZ);
- if ( !ibuf )
- goto cleanup; /* no memory - drop this message */
-
- len = recvfrom(ourSock,
- ibuf->buf,
- RPCIOD_RXBUFSZ,
- 0,
- (struct sockaddr*)&fromAddr,
- &fromLen);
-#endif
-
- if (len <= 0) {
- if (EAGAIN != errno)
- fprintf(stderr,"RECV failed: %s\n",strerror(errno));
- goto cleanup;
- }
-
-#if (DEBUG) & DEBUG_PACKLOSS
- if ( (unsigned)rand() < DEBUG_PACKLOSS_FRACT ) {
- /* lose packets once in a while */
- static int xxx = 0;
- if ( ++xxx % 16 == 0 )
- fprintf(stderr,"DEBUG: dropped %i packets, so far...\n",xxx);
- if ( ibuf )
- bufFree( &ibuf );
- continue;
- }
-#endif
-
- i = (xid=XID(ibuf)) & XACT_HASH_MSK;
-
- if ( !(xact=xactHashTbl[i]) ||
- xact->obuf.xid != xid ||
-#ifdef REJECT_SERVERIP_MISMATCH
- xact->server->addr.sin_addr.s_addr != fromAddr.sin_addr.s_addr ||
-#endif
- xact->server->addr.sin_port != fromAddr.sin_port ) {
-
- if (xact) {
- if (
-#ifdef REJECT_SERVERIP_MISMATCH
- xact->server->addr.sin_addr.s_addr == fromAddr.sin_addr.s_addr &&
-#endif
- xact->server->addr.sin_port == fromAddr.sin_port &&
- ( xact->obuf.xid == xid + XACT_HASHS ||
- xact->obuf.xid == xid + 2*XACT_HASHS )
- ) {
-#ifndef DEBUG /* don't complain if it's just a late arrival of a retry */
- fprintf(stderr,"RPCIO - FYI sockRcv(): dropping late/redundant retry answer\n");
-#endif
- } else {
- fprintf(stderr,"RPCIO WARNING sockRcv(): transaction mismatch\n");
- fprintf(stderr,"xact: xid 0x%08lx -- got 0x%08lx\n",
- xact->obuf.xid, xid);
- fprintf(stderr,"xact: addr 0x%08lx -- got 0x%08lx\n",
- xact->server->addr.sin_addr.s_addr,
- fromAddr.sin_addr.s_addr);
- fprintf(stderr,"xact: port 0x%08x -- got 0x%08x\n",
- xact->server->addr.sin_port,
- fromAddr.sin_port);
- }
- } else {
- fprintf(stderr,
- "RPCIO WARNING sockRcv(): got xid 0x%08lx but its slot is empty\n",
- xid);
- }
- /* forget about this one and try again */
- xact = 0;
- }
-
- } while ( !xact );
-
- xact->ibuf = ibuf;
-#ifndef MBUF_RX
- xact->ibufsize = RPCIOD_RXBUFSZ;
-#endif
-
- return xact;
-
-cleanup:
-
- bufFree(&ibuf);
-
- return 0;
-}
-
-
-#include <rtems/rtems_bsdnet_internal.h>
-/* double check the event configuration; should probably globally
- * manage system events!!
- * We do this at the end of the file for the same reason we had
- * included mbuf.h only a couple of lines above - see comment up
- * there...
- */
-#if RTEMS_RPC_EVENT & SOSLEEP_EVENT & SBWAIT_EVENT & NETISR_EVENTS
-#error ILLEGAL EVENT CONFIGURATION
-#endif
diff --git a/rtemsNfs/src/rpcio.h b/rtemsNfs/src/rpcio.h
deleted file mode 100644
index 922bc0d..0000000
--- a/rtemsNfs/src/rpcio.h
+++ /dev/null
@@ -1,205 +0,0 @@
-#ifndef RPCIO_H
-#define RPCIO_H
-/* $Id$ */
-
-/* A multihreaded RPC/UDP multiplexor */
-
-/* Author: Till Straumann, <strauman@slac.stanford.edu>, 2002 */
-
-/*
- * Copyright 2002, Stanford University and
- * Till Straumann <strauman@slac.stanford.edu>
- *
- * Stanford Notice
- * ***************
- *
- * Acknowledgement of sponsorship
- * * * * * * * * * * * * * * * * *
- * This software was produced by the Stanford Linear Accelerator Center,
- * Stanford University, under Contract DE-AC03-76SFO0515 with the Department
- * of Energy.
- *
- * Government disclaimer of liability
- * - - - - - - - - - - - - - - - - -
- * Neither the United States nor the United States Department of Energy,
- * nor any of their employees, makes any warranty, express or implied,
- * or assumes any legal liability or responsibility for the accuracy,
- * completeness, or usefulness of any data, apparatus, product, or process
- * disclosed, or represents that its use would not infringe privately
- * owned rights.
- *
- * Stanford disclaimer of liability
- * - - - - - - - - - - - - - - - - -
- * Stanford University makes no representations or warranties, express or
- * implied, nor assumes any liability for the use of this software.
- *
- * This product is subject to the EPICS open license
- * - - - - - - - - - - - - - - - - - - - - - - - - -
- * Consult the LICENSE file or http://www.aps.anl.gov/epics/license/open.php
- * for more information.
- *
- * Maintenance of notice
- * - - - - - - - - - - -
- * In the interest of clarity regarding the origin and status of this
- * software, Stanford University requests that any recipient of it maintain
- * this notice affixed to any distribution by the recipient that contains a
- * copy or derivative of this software.
- */
-
-
-#ifdef __rtems
-#include <rtems.h>
-#endif
-
-#include <rpc/rpc.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/param.h>
-#include <stdarg.h>
-
-typedef struct RpcUdpServerRec_ *RpcUdpServer;
-typedef struct RpcUdpXactRec_ *RpcUdpXact;
-
-typedef RpcUdpXact RpcUdpClnt;
-
-#define RPCIOD_DEFAULT_ID 0xdef10000
-
-int
-rpcUdpInit(void);
-
-enum clnt_stat
-rpcUdpServerCreate(
- struct sockaddr_in *paddr,
- int prog,
- int vers,
- u_long uid, /* RPCIO_DEFAULT_ID picks default */
- u_long gid, /* RPCIO_DEFAULT_ID picks default */
- RpcUdpServer *pclnt /* new server is returned here */
- );
-
-
-void
-rpcUdpServerDestroy(RpcUdpServer s);
-
-/* Dump statistics to a file (stdout if NULL);
- * returns 0 for convenience
- */
-int
-rpcUdpStats(FILE *f);
-
-enum clnt_stat
-rpcUdpClntCreate(
- struct sockaddr_in *psaddr,
- int prog,
- int vers,
- u_long uid, /* RPCIO_DEFAULT_ID picks default */
- u_long gid, /* RPCIO_DEFAULT_ID picks default */
- RpcUdpClnt *pclnt /* new client is returned here */
- );
-
-void
-RpcUdpClntDestroy(RpcUdpClnt clnt);
-
-/* mute compiler warnings */
-typedef void *XdrProcT;
-typedef void *CaddrT;
-
-enum clnt_stat
-rpcUdpClntCall(
- RpcUdpClnt clnt,
- u_long proc,
- XdrProcT xargs,
- CaddrT pargs,
- XdrProcT xres,
- CaddrT pres,
- struct timeval *timeout /* optional timeout; maybe NULL to pick default */
- );
-
-RpcUdpXact
-rpcUdpXactCreate(
- u_long program,
- u_long version,
- u_long size
- );
-
-void
-rpcUdpXactDestroy(
- RpcUdpXact xact
- );
-
-/* send a transaction */
-enum clnt_stat
-rpcUdpSend(
- RpcUdpXact xact,
- RpcUdpServer srvr,
- struct timeval *timeout, /* maybe NULL to pick default */
- u_long proc,
- xdrproc_t xres,
- caddr_t pres,
- xdrproc_t xargs,
- caddr_t pargs,
- ... /* 0 terminated xdrproc/pobj additional argument list */
- );
-
-/* wait for a transaction to complete */
-enum clnt_stat
-rpcUdpRcv(RpcUdpXact xact);
-
-/* a yet simpler interface */
-enum clnt_stat
-rpcUdpCallRp(
- struct sockaddr_in *pserver_addr,
- u_long prog,
- u_long vers,
- u_long proc,
- XdrProcT xargs,
- CaddrT pargs,
- XdrProcT xres,
- CaddrT pres,
- u_long uid, /* RPCIO_DEFAULT_ID picks default */
- u_long gid, /* RPCIO_DEFAULT_ID picks default */
- struct timeval *timeout /* NULL picks default */
-);
-
-
-/* manage pools of transactions */
-
-/* A pool of transactions. The idea is not to malloc/free them
- * all the time but keep a limited number around in a 'pool'.
- * Users who need a XACT may get it from the pool and put it back
- * when done.
- * The pool is implemented by RTEMS message queues who manage
- * the required task synchronization.
- * A requestor has different options if the pool is empty:
- * - it can wait (block) for a XACT to become available
- * - it can get an error status
- * - or it can malloc an extra XACT from the heap which
- * will eventually be released.
- */
-
-typedef struct RpcUdpXactPoolRec_ *RpcUdpXactPool;
-
-/* NOTE: the pool is empty initially, must get messages (in
- * GetCreate mode
- */
-RpcUdpXactPool
-rpcUdpXactPoolCreate(
- int prog, int version,
- int xactsize, int poolsize);
-
-void
-rpcUdpXactPoolDestroy(RpcUdpXactPool pool);
-
-typedef enum {
- XactGetFail, /* call fails if no transaction available */
- XactGetWait, /* call blocks until transaction available */
- XactGetCreate /* a new transaction is allocated (and freed when put back to the pool */
-} XactPoolGetMode;
-
-RpcUdpXact
-rpcUdpXactPoolGet(RpcUdpXactPool pool, XactPoolGetMode mode);
-
-void
-rpcUdpXactPoolPut(RpcUdpXact xact);
-
-#endif
diff --git a/rtemsNfs/src/rpcio.modini.c b/rtemsNfs/src/rpcio.modini.c
deleted file mode 100644
index 7773b3d..0000000
--- a/rtemsNfs/src/rpcio.modini.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include "librtemsNfs.h"
-/* CEXP module support (magic init) */
-void
-_cexpModuleInitialize(void *mod)
-{
- rpcUdpInit();
-}
-
-int
-_cexpModuleFinalize(void *mod)
-{
- return rpcUdpCleanup();
-}
-
-
diff --git a/rtemsNfs/src/sock_mbuf.c b/rtemsNfs/src/sock_mbuf.c
deleted file mode 100644
index 217d8b6..0000000
--- a/rtemsNfs/src/sock_mbuf.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * $Id$
- *
- * NOTE:
- * This is derived from libnetworking/rtems/rtems_syscall.c
- *
- * RTEMS/libnetworking LICENSING restrictions may apply
- *
- * Author (modifications only):
- * Copyright: 2002, Stanford University and
- * Till Straumann, <strauman@slac.stanford.edu>
- * Licensing: 'LICENSE.NET' file in the RTEMS top source directory
- * for more information.
- */
-
-/*
-The RTEMS TCP/IP stack is a port of the FreeBSD TCP/IP stack. The following
-copyright and licensing information applies to this code.
-
-This code is found under the c/src/libnetworking directory but does not
-constitute the entire contents of that subdirectory.
-
-=============================================================================
-
-Copyright (c) 1980, 1983, 1988, 1993
- The Regents of the University of California. 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 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.
-
--
-Portions Copyright (c) 1993 by Digital Equipment Corporation.
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies, and that
-the name of Digital Equipment Corporation not be used in advertising or
-publicity pertaining to distribution of the document or software without
-specific, written prior permission.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
-WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
-CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
-DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
-PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-=============================================================================
-*/
-
-
-#include <string.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-#include <rtems.h>
-#include <rtems/libio.h>
-#include <rtems/error.h>
-
-#define KERNEL
-#define _KERNEL
-#define __BSD_VISIBLE 1
-#include <rtems/rtems_bsdnet.h>
-
-#include <sys/errno.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/protosw.h>
-#include <sys/proc.h>
-#include <sys/fcntl.h>
-#include <sys/filio.h>
-
-#include <net/if.h>
-#include <net/route.h>
-
-struct socket *rtems_bsdnet_fdToSocket(int fd);
-
-/*
- * Package system call argument into mbuf.
- *
- * (unfortunately, the original is not public)
- */
-static int
-sockaddrtombuf (struct mbuf **mp, const struct sockaddr *buf, int buflen)
-{
-struct mbuf *m;
-struct sockaddr *sa;
-
- if ((u_int)buflen > MLEN)
- return (EINVAL);
-
- rtems_bsdnet_semaphore_obtain();
- m = m_get(M_WAIT, MT_SONAME);
- rtems_bsdnet_semaphore_release();
-
- if (m == NULL)
- return (ENOBUFS);
- m->m_len = buflen;
- memcpy (mtod(m, caddr_t), buf, buflen);
- *mp = m;
- sa = mtod(m, struct sockaddr *);
- sa->sa_len = buflen;
-
- return 0;
-}
-
-static void
-dummyproc(caddr_t ext_buf, u_int ext_size)
-{
-}
-
-/*
- * send data by simply allocating an MBUF packet
- * header and pointing it to our data region.
- *
- * Optionally, the caller may supply 'reference'
- * and 'free' procs. (The latter may call the
- * user back once the networking stack has
- * released the buffer).
- *
- * The callbacks are provided with the 'closure'
- * pointer and the 'buflen' argument.
- */
-ssize_t
-sendto_nocpy (
- int s,
- const void *buf, size_t buflen,
- int flags,
- const struct sockaddr *toaddr, int tolen,
- void *closure,
- void (*freeproc)(caddr_t, u_int),
- void (*refproc)(caddr_t, u_int)
-)
-{
- int error;
- struct socket *so;
- struct mbuf *to, *m;
- int ret = -1;
-
- rtems_bsdnet_semaphore_obtain ();
- if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
- rtems_bsdnet_semaphore_release ();
- return -1;
- }
-
- error = sockaddrtombuf (&to, toaddr, tolen);
- if (error) {
- errno = error;
- rtems_bsdnet_semaphore_release ();
- return -1;
- }
-
- MGETHDR(m, M_WAIT, MT_DATA);
- m->m_pkthdr.len = 0;
- m->m_pkthdr.rcvif = (struct ifnet *) 0;
-
- m->m_flags |= M_EXT;
- m->m_ext.ext_buf = closure ? closure : (void*)buf;
- m->m_ext.ext_size = buflen;
- /* we _must_ supply non-null procs; otherwise,
- * the kernel code assumes it's a mbuf cluster
- */
- m->m_ext.ext_free = freeproc ? freeproc : dummyproc;
- m->m_ext.ext_ref = refproc ? refproc : dummyproc;
- m->m_pkthdr.len += buflen;
- m->m_len = buflen;
- m->m_data = (void*)buf;
-
- error = sosend (so, to, NULL, m, NULL, flags);
- if (error) {
- if (/*auio.uio_resid != len &&*/ (error == EINTR || error == EWOULDBLOCK))
- error = 0;
- }
- if (error)
- errno = error;
- else
- ret = buflen;
- if (to)
- m_freem(to);
- rtems_bsdnet_semaphore_release ();
- return (ret);
-}
-
-
-/*
- * receive data in an 'mbuf chain'.
- * The chain must be released once the
- * data has been extracted:
- *
- * rtems_bsdnet_semaphore_obtain();
- * m_freem(chain);
- * rtems_bsdnet_semaphore_release();
- */
-ssize_t
-recv_mbuf_from(int s, struct mbuf **ppm, long len, struct sockaddr *fromaddr, int *fromlen)
-{
- int ret = -1;
- int error;
- struct uio auio;
- struct socket *so;
- struct mbuf *from = NULL;
-
- memset(&auio, 0, sizeof(auio));
- *ppm = 0;
-
- rtems_bsdnet_semaphore_obtain ();
- if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
- rtems_bsdnet_semaphore_release ();
- return -1;
- }
-/* auio.uio_iov = mp->msg_iov;
- auio.uio_iovcnt = mp->msg_iovlen;
- auio.uio_segflg = UIO_USERSPACE;
- auio.uio_rw = UIO_READ;
- auio.uio_offset = 0;
-*/
- auio.uio_resid = len;
- error = soreceive (so, &from, &auio, (struct mbuf **) ppm,
- (struct mbuf **)NULL,
- NULL);
- if (error) {
- if (auio.uio_resid != len && (error == EINTR || error == EWOULDBLOCK))
- error = 0;
- }
- if (error) {
- errno = error;
- }
- else {
- ret = len - auio.uio_resid;
- if (fromaddr) {
- len = *fromlen;
- if ((len <= 0) || (from == NULL)) {
- len = 0;
- }
- else {
- if (len > from->m_len)
- len = from->m_len;
- memcpy (fromaddr, mtod(from, caddr_t), len);
- }
- *fromlen = len;
- }
- }
- if (from)
- m_freem (from);
- if (error && *ppm) {
- m_freem(*ppm);
- *ppm = 0;
- }
- rtems_bsdnet_semaphore_release ();
- return (ret);
-}
diff --git a/rtemsNfs/src/xdr_mbuf.c b/rtemsNfs/src/xdr_mbuf.c
deleted file mode 100644
index 22f972d..0000000
--- a/rtemsNfs/src/xdr_mbuf.c
+++ /dev/null
@@ -1,534 +0,0 @@
-/* $Id$ */
-
-/* xdr_mbuf is derived from xdr_mem */
-
-/* Author (mbuf specifica): Till Straumann <strauman@slac.stanford.edu>, 10/2002 */
-
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_mem.c,v 1.8 1999/08/28 00:02:56 peter Exp $";
-#endif
-
-/*
- * xdr_mbuf, XDR implementation using mbuf buffers
- *
- * derived from:
- *
- * xdr_mem.h, XDR implementation using memory buffers.
- *
- * Copyright (C) 1984, Sun Microsystems, Inc.
- *
- * The MBUF stream is useful for BSDNET kernel (or RTEMS for that matter)
- * use.
- */
-
-#include <string.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
-#include <netinet/in.h>
-
-#include <stdlib.h>
-
-#define TODO
-
-/* TODO remove: a hack because malloc is redefined */
-#ifdef TODO
-static inline void *
-my_malloc(size_t i)
-{
- return malloc(i);
-}
-
-static inline void
-my_free(void *p)
-{
- return free(p);
-}
-#endif
-
-#define DEBUG_ASSERT (1<<0)
-#define DEBUG_VERB (1<<1)
-
-#define DEBUG DEBUG_ASSERT
-
-#define KERNEL
-#include <sys/mbuf.h>
-
-#include <assert.h>
-
-#if DEBUG & DEBUG_VERB || defined(TODO)
-#include <stdio.h>
-#endif
-
-static bool_t xdrmbuf_getlong_aligned();
-static bool_t xdrmbuf_putlong_aligned();
-static bool_t xdrmbuf_getlong_unaligned();
-static bool_t xdrmbuf_putlong_unaligned();
-static bool_t xdrmbuf_getbytes();
-static bool_t xdrmbuf_putbytes();
-static u_int xdrmbuf_getpos(); /* XXX w/64-bit pointers, u_int not enough! */
-static bool_t xdrmbuf_setpos();
-static int32_t *xdrmbuf_inline_aligned();
-static int32_t *xdrmbuf_inline_unaligned();
-static void xdrmbuf_destroy();
-
-static struct xdr_ops xdrmbuf_ops_aligned = {
- xdrmbuf_getlong_aligned,
- xdrmbuf_putlong_aligned,
- xdrmbuf_getbytes,
- xdrmbuf_putbytes,
- xdrmbuf_getpos,
- xdrmbuf_setpos,
- xdrmbuf_inline_aligned,
- xdrmbuf_destroy
-};
-
-static struct xdr_ops xdrmbuf_ops_unaligned = {
- xdrmbuf_getlong_unaligned,
- xdrmbuf_putlong_unaligned,
- xdrmbuf_getbytes,
- xdrmbuf_putbytes,
- xdrmbuf_getpos,
- xdrmbuf_setpos,
- xdrmbuf_inline_unaligned,
- xdrmbuf_destroy
-};
-
-typedef struct MBPrivateRec_ {
- struct mbuf *mchain;
- struct mbuf *mcurrent;
- u_int pos; /* number of bytes contained in all MUBFS ahead
- * of mcurrent
- */
-} MBPrivateRec, *MBPrivate;
-
-/* NOTE: the stream position helper 'pos'
- * must be managed by the caller!
- */
-static inline void
-xdrmbuf_setup(XDR *xdrs, struct mbuf *m)
-{
-MBPrivate mbp = (MBPrivate)xdrs->x_base;
-
- mbp->mcurrent = m;
- xdrs->x_private = mtod(m,caddr_t);
- xdrs->x_handy = m->m_len;
- xdrs->x_ops = ((size_t)xdrs->x_private & (sizeof(int32_t) - 1))
- ? &xdrmbuf_ops_unaligned : &xdrmbuf_ops_aligned;
-}
-
-static struct mbuf *
-xdrmbuf_next(XDR *xdrs)
-{
-struct mbuf *rval;
-MBPrivate mbp = (MBPrivate)xdrs->x_base;
-
- if (mbp->mcurrent) {
- mbp->pos += mbp->mcurrent->m_len;
- rval = mbp->mcurrent->m_next;
- } else {
- rval = 0;
- }
-
- if (rval) {
- xdrmbuf_setup(xdrs, rval);
- }
-#if DEBUG & DEBUG_VERB
- else {
- fprintf(stderr,"xdrmbuf: end of chain\n");
- }
-#endif
-
- return rval;
-}
-
-/*
- * The procedure xdrmbuf_create initializes a stream descriptor for a
- * memory buffer.
- */
-void
-xdrmbuf_create(XDR *xdrs, struct mbuf *mbuf, enum xdr_op op)
-{
-MBPrivate mbp;
-
- xdrs->x_op = op;
- assert( mbp = (MBPrivate)my_malloc(sizeof(*mbp)) );
- xdrs->x_base = (caddr_t) mbp;
-
- mbp->mchain = mbuf;
- mbp->pos = 0;
-
-#if DEBUG & DEBUG_VERB
- {
- struct mbuf *mbf;
- fprintf(stderr,"Dumping chain:\n");
- for (mbf = mbuf; mbf; mbf=mbf->m_next) {
- int ii;
- fprintf(stderr,"MBUF------------");
- for (ii=0; ii<mbf->m_len; ii++) {
- fprintf(stderr,"%02x ",mtod(mbf,char*)[ii]);
- if (ii%16==0)
- fputc('\n',stderr);
- }
- fputc('\n',stderr);
- }
- }
-#endif
-
- xdrmbuf_setup(xdrs, mbuf);
-}
-
-static void
-xdrmbuf_destroy(XDR *xdrs)
-{
-MBPrivate mbp = (MBPrivate)xdrs->x_base;
-#if 0 /* leave destroying the chain to the user */
-struct mbuf *m = mbp->mchain;
-
- rtems_bsdnet_semaphore_obtain();
- m_freem(m);
- rtems_bsdnet_semaphore_release();
-#endif
-
- my_free(mbp);
-}
-
-static bool_t
-xdrmbuf_getlong_aligned(register XDR *xdrs, register long *lp)
-{
- while ( (signed int)(xdrs->x_handy -= sizeof(int32_t)) < 0) {
- if ((xdrs->x_handy += sizeof(int32_t)) == 0) {
- /* handy was 0 on entry; request a new buffer.
- * Coded this way, so the most frequently executed
- * path needs only one comparison...
- */
- if (!xdrmbuf_next(xdrs))
- return FALSE;
- } else {
- /* uh-oh an aligned long spread over two MBUFS ??
- * let the unaligned handler deal with this rare
- * situation.
- */
- return xdrmbuf_getlong_unaligned(xdrs,lp);
- }
- }
- *lp = ntohl(*(int32_t *)(xdrs->x_private));
- xdrs->x_private += sizeof(int32_t);
-#if DEBUG & DEBUG_VERB
- fprintf(stderr,"Got aligned long %x\n",*lp);
-#endif
- return (TRUE);
-}
-
-static bool_t
-xdrmbuf_putlong_aligned(xdrs, lp)
- register XDR *xdrs;
- long *lp;
-{
-fprintf(stderr,"TODO: xdrmbuf_putlong_aligned() is unimplemented\n");
- return FALSE;
-#if 0
- if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
- return (FALSE);
- *(int32_t *)xdrs->x_private = htonl(*lp);
- xdrs->x_private += sizeof(int32_t);
- return (TRUE);
-#endif
-}
-
-static bool_t
-xdrmbuf_getlong_unaligned(xdrs, lp)
- register XDR *xdrs;
- long *lp;
-{
-union {
- int32_t l;
- char c[sizeof(int32_t)];
-} u;
-
-register int i,j;
-register char *cp,*sp;
-
- i = xdrs->x_handy - sizeof(int32_t);
-
- /* handle the most common case first */
- if ( i >= 0 ) {
-
- xdrs->x_handy = i;
- sp = (char*)xdrs->x_private;
- xdrs->x_private = sp + sizeof(int32_t);
-
-#ifdef CANDO_UNALIGNED
- {
- *lp = ntohl(*(int32_t *)sp);
-# if DEBUG & DEBUG_VERB
- fprintf(stderr,"Got unaligned long %x (%i remaining)\n",*lp, xdrs->x_handy);
-# endif
- return TRUE;
- }
-#else /* machine can't do unaligned access */
- {
- u.c[0] = *sp;
- u.c[1] = *++sp;
- u.c[2] = *++sp;
- u.c[3] = *++sp;
-
- goto done;
- }
-#endif /* CANDO_UNALIGNED */
- }
-
- /* here the messy 'crossing buffers' business starts */
-
-
- j = sizeof(int32_t);
-
- cp = u.c-1;
-
- /* NOTE: on entry to this section, handy < j holds */
- do {
- sp = ((char*)xdrs->x_private)-1;
-
- if ( (i=xdrs->x_handy) >= j ) {
- /* more data in the buffer than we need:
- * copy everything we need and goto 'done'
- */
- xdrs->x_handy = i-j;
- do {
- *++cp = *++sp;
- } while (--j > 0);
- xdrs->x_private = (caddr_t)++sp;
-
- goto done;
-
- } else {
- /* not enough data - copy as much as possible
- * then get retrieve the next MBUF and start
- * over
- */
- j-=i;
- while (i--)
- *++cp = *++sp;
- if (!xdrmbuf_next(xdrs))
- return FALSE;
-#if DEBUG & DEBUG_VERB
- fprintf(stderr,"getlong_unaligned: crossed mbuf boundary\n");
-#endif
- }
- } while (j > 0);
-
-done:
-
- *lp = ntohl(u.l);
-
-#if DEBUG & DEBUG_VERB
- fprintf(stderr,"Got unaligned long %x (%i remaining)\n",*lp, xdrs->x_handy);
-#endif
- return (TRUE);
-}
-
-static bool_t
-xdrmbuf_putlong_unaligned(xdrs, lp)
- register XDR *xdrs;
- long *lp;
-{
-
- fprintf(stderr,"TODO: xdrmbuf_putlong_unaligned() is unimplemented\n");
- return FALSE;
-#if 0
- {
- int32_t l;
-
- if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
- return (FALSE);
- l = htonl(*lp);
- memcpy(xdrs->x_private, &l, sizeof(int32_t));
- xdrs->x_private += sizeof(int32_t);
- return (TRUE);
- }
-#endif
-}
-
-static bool_t
-xdrmbuf_getbytes(xdrs, addr, len)
- register XDR *xdrs;
- caddr_t addr;
- register u_int len;
-{
-#if DEBUG & DEBUG_VERB
-int olen=len,bufs=0;
-#endif
-
-#if DEBUG & DEBUG_VERB
- fprintf(stderr,"wanting %i bytes (have %i)\n",olen,xdrs->x_handy);
-#endif
-
- while (len>0) {
- if (xdrs->x_handy >= len) {
- memcpy(addr, xdrs->x_private, len);
- xdrs->x_private += len;
- xdrs->x_handy -= len;
-#if 0 /* save a couple of instructions */
- len = 0;
-#else
- goto done;
-#endif
- } else {
- if (xdrs->x_handy > 0) {
- memcpy(addr, xdrs->x_private, xdrs->x_handy);
- len -= xdrs->x_handy;
- addr += xdrs->x_handy;
- }
- if (!xdrmbuf_next(xdrs))
- return FALSE;
-#if DEBUG & DEBUG_VERB
- bufs++;
-#endif
- }
- }
-done:
-#if DEBUG & DEBUG_VERB
- fprintf(stderr,"Got %i bytes (out of %i mbufs)\n",olen,bufs);
-#endif
- return (TRUE);
-}
-
-static bool_t
-xdrmbuf_putbytes(xdrs, addr, len)
- register XDR *xdrs;
- caddr_t addr;
- register u_int len;
-{
-
- fprintf(stderr,"TODO: xdrmbuf_putbytes() is unimplemented\n");
- return FALSE;
-#if 0
- if ((xdrs->x_handy -= len) < 0)
- return (FALSE);
- memcpy(xdrs->x_private, addr, len);
- xdrs->x_private += len;
- return (TRUE);
-#endif
-}
-
-static u_int
-xdrmbuf_getpos(xdrs)
- register XDR *xdrs;
-{
-#if 1
-MBPrivate mbp = (MBPrivate)xdrs->x_base;
-struct mbuf *m = mbp->mcurrent;
-u_int rval = mbp->pos;
-
- if (m) {
- rval += (u_long)xdrs->x_private - mtod(m, u_long);
- }
-#else
-struct mbuf *m;
-u_int rval = 0;
-MBPrivate mbp = (MBPrivate)xdrs->x_base;
-
- for ( m = mbp->mchain; m && m != mbp->mcurrent; m = m->m_next )
- rval += m->m_len;
- if (m) {
- rval += (u_long)xdrs->x_private - mtod(m, u_long);
- }
-
-#endif
- return rval;
-}
-
-static bool_t
-xdrmbuf_setpos(xdrs, pos)
- register XDR *xdrs;
- u_int pos;
-{
-struct mbuf *m;
-MBPrivate mbp = (MBPrivate)xdrs->x_base;
-
- if (pos >= mbp->pos) {
- pos -= mbp->pos;
- m = mbp->mcurrent;
- } else {
- m = mbp->mchain;
- mbp->pos = 0;
- }
-
- while ( m && pos >= m->m_len ) {
- pos -= m->m_len;
- mbp->pos += m->m_len;
- m = m->m_next;
- }
-
- if (m) {
- xdrmbuf_setup(xdrs, m);
- xdrs->x_private += pos;
- return TRUE;
- }
-
- return 0 == pos ? TRUE : FALSE;
-}
-
-static int32_t *
-xdrmbuf_inline_aligned(xdrs, len)
- register XDR *xdrs;
- int len;
-{
-int32_t *buf = 0;
-
- if (xdrs->x_handy == 0 && !xdrmbuf_next(xdrs))
- return 0;
-
- if (xdrs->x_handy >= len) {
- xdrs->x_handy -= len;
- buf = (int32_t *) xdrs->x_private;
- xdrs->x_private += len;
-#if DEBUG & DEBUG_VERB
- fprintf(stderr,"Got %i aligned inline bytes at %x\n", len, buf);
-#endif
- }
-#if DEBUG & DEBUG_VERB
- else {
- fprintf(stderr,"Skipped %i aligned inline bytes\n",len);
- }
-#endif
- return (buf);
-}
-
-static int32_t *
-xdrmbuf_inline_unaligned(xdrs, len)
- register XDR *xdrs;
- int len;
-{
- return (0);
-}