This commit was generated by cvs2svn to compensate for changes in r15677,

which included commits to RCS files with non-trunk default branches.
This commit is contained in:
Ralf Corsepius
2007-07-25 05:22:23 +00:00
25 changed files with 13055 additions and 0 deletions

112
c/src/nfsclient/ChangeLog Normal file
View File

@@ -0,0 +1,112 @@
Changes since RTEMS-NFS 1.4:
LICENSE:
- changed license terms; RTEMS-NFS is now released under the more liberal
'SLAC license'.
NFS:
- silenced compiler warnings (follow handler declaration changes in libio.h
by using 'size_t' instead of 'uint32_t' etc.).
Changes since RTEMS-NFS 1.3:
RPCIOD:
- round timeout to next system clock tick and ensure it is at least
1 tick.
- cap retransmission timeout to transaction lifetime.
- BUGFIX (reported by Steven Johnson, 12/5/06): we must change the XID
before sending a timed-out transaction back to the requestor to prevent
a late reply from being accepted.
- Made task priority run-time configurable (and read from rtems_bsdnet_config
by default).
NFS:
- added nfsGetTimeout() and nfsSetTimeout() to retrieve and modify,
respectively the (global) timeout for NFS/MOUNT operations.
- Minor mod. to fix 'type-punned pointer' warning (can avoid pointer cast).
- Added global variable 'nfsStBlksize' (defaults to 8k) which is now
used to report the file system's 'preferred' blocksize (stat(2)/st_blksize).
The old behavior (server's fattr.st_blksize is passed through) can be
obtained by setting nfsStBlksize=0.
The new feature lets stdio use 8k buffers (only if newlib was built with
HAVE_BLKSIZE defined). This enhances NFS (buffered) read performance quite
a bit. Thanks to Steven Johnson <sjohnson@sakuraindustries.com> for helping
with this.
- Updated README (performance section).
- Added simple performance test: nfsTest.c
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.

44
c/src/nfsclient/LICENSE Normal file
View File

@@ -0,0 +1,44 @@
/*
* Authorship
* ----------
* This software (NFS-2 client implementation for RTEMS) was created by
* Till Straumann <strauman@slac.stanford.edu>, 2002-2007,
* Stanford Linear Accelerator Center, Stanford University.
*
* Acknowledgement of sponsorship
* ------------------------------
* The NFS-2 client implementation for RTEMS 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.
*
* Stanford disclaimer of copyright
* --------------------------------
* Stanford University, owner of the copyright, hereby disclaims its
* copyright and all other rights in this software. Hence, anyone may
* freely use it for any purpose without restriction.
*
* Maintenance of notices
* ----------------------
* In the interest of clarity regarding the origin and status of this
* SLAC software, this and all the preceding Stanford University notices
* are to remain affixed to any copy or derivative of this software made
* or distributed by the recipient and are to be affixed to any copy of
* software made or distributed by the recipient that contains a copy or
* derivative of this software.
*
* ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
*/

16
c/src/nfsclient/Makefile Normal file
View File

@@ -0,0 +1,16 @@
#
# $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)

548
c/src/nfsclient/README Normal file
View File

@@ -0,0 +1,548 @@
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...
Since there is no buffer cache with read-ahead
implemented, all NFS reads are synchronous RPC
calls. Every read operation involves sending a
request and waiting for the reply. As long as the
overhead (sending request + processing it on the
server) is significant compared to the time it
takes to transferring the actual data, increasing
the amount of data per request results in better
throughput. The UDP packet size limit imposes a
limit of 8k per RPC call, hence reading from NFS
in chunks of 8k is better than chunks of 1k [but
chunks >8k are not possible, i.e., simply not
honoured: read(a_nfs_fd, buf, 20000) returns
8192]. This is similar to the old linux days
(mount with rsize=8k). You can let stdio take
care of the buffering or use 8k buffers with
explicit read(2) operations. Note that stdio
honours the file-system's st_blksize field
if newlib is compiled with HAVE_BLKSIZE defined.
In this case, stdio uses 8k buffers for files
on NFS transparently. The blocksize NFS
reports can be tuned with a global variable
setting (see nfs.c for details).
Further increase of throughput can be achieved
with read-ahead (issuing RPC calls in parallel
[send out request for block n+1 while you are
waiting for data of block n to arrive]). Since
this is not handled by the file system itself, you
would have to code this yourself e.g., using
parallel threads to read from a single file from
interleaved offsets.
Another obvious improvement can be achieved if
processing the data takes a significant amount of
time. Then, having a pipeline of threads for
reading data and processing them makes sense
[thread b processes chunk n while thread a blocks
in read(chunk n+1)].
Some performance figures:
Software: src/nfsTest.c:nfsReadTest() [data not
processed in any way].
Hardware: MVME6100
Network: 100baseT-FD
Server: Linux-2.6/RHEL4-smp [dell precision 420]
File: 10MB
Results:
Single threaded ('normal') NFS read, 1k buffers: 3.46s (2.89MB/s)
Single threaded ('normal') NFS read, 8k buffers: 1.31s (7.63MB/s)
Multi threaded; 2 readers, 8k buffers/xfers: 1.12s (8.9 MB/s)
Multi threaded; 3 readers, 8k buffers/xfers: 1.04s (9.6 MB/s)
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 SLAC 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.
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.

View File

@@ -0,0 +1,76 @@
#
# $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 -C $< > $@
%.h: %.x
rpcgen -h -C $< > $@
.PRECIOUS: $(XFILES:%.x=%.h) $(XFILES:%.x=%_xdr.c)
tar: $(XFILES:%.x=%.h) $(XFILES:%.x=%_xdr.c)
distclean: clean
# DONT install this library.
install: all

View File

@@ -0,0 +1,144 @@
/*
* 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 */

View File

@@ -0,0 +1,161 @@
/* @(#)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;

View File

@@ -0,0 +1,124 @@
/*
* 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;
}

View File

@@ -0,0 +1,453 @@
/*
* 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 */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,671 @@
/*
* 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;
}

1258
c/src/nfsclient/rfc1094.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,860 @@
# 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;
}

View File

@@ -0,0 +1,104 @@
#
# $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=YES
# 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
$(LD) -r -o $@ $^ -L../proto/$(ARCH) -lnfsprot
%rpcio.obj: %rpcio.o %sock_mbuf.o %xdr_mbuf.o %rpcio.modini.o
$(LD) -r -o $@ $^
%dirutils.obj: %dirutils.o
$(LD) -r -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}/include

View File

@@ -0,0 +1,16 @@
#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

View File

@@ -0,0 +1,362 @@
/* $Id$ */
/* very crude and basic fs utilities for testing the NFS */
/* Till Straumann, <strauman@slac.stanford.edu>, 10/2002 */
/*
* Authorship
* ----------
* This software (NFS-2 client implementation for RTEMS) was created by
* Till Straumann <strauman@slac.stanford.edu>, 2002-2007,
* Stanford Linear Accelerator Center, Stanford University.
*
* Acknowledgement of sponsorship
* ------------------------------
* The NFS-2 client implementation for RTEMS 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.
*
* Stanford disclaimer of copyright
* --------------------------------
* Stanford University, owner of the copyright, hereby disclaims its
* copyright and all other rights in this software. Hence, anyone may
* freely use it for any purpose without restriction.
*
* Maintenance of notices
* ----------------------
* In the interest of clarity regarding the origin and status of this
* SLAC software, this and all the preceding Stanford University notices
* are to remain affixed to any copy or derivative of this software made
* or distributed by the recipient and are to be affixed to any copy of
* software made or distributed by the recipient that contains a copy or
* derivative of this software.
*
* ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
*/
#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

View File

@@ -0,0 +1,182 @@
#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 */
/*
* Authorship
* ----------
* This software (NFS-2 client implementation for RTEMS) was created by
* Till Straumann <strauman@slac.stanford.edu>, 2002-2007,
* Stanford Linear Accelerator Center, Stanford University.
*
* Acknowledgement of sponsorship
* ------------------------------
* The NFS-2 client implementation for RTEMS 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.
*
* Stanford disclaimer of copyright
* --------------------------------
* Stanford University, owner of the copyright, hereby disclaims its
* copyright and all other rights in this software. Hence, anyone may
* freely use it for any purpose without restriction.
*
* Maintenance of notices
* ----------------------
* In the interest of clarity regarding the origin and status of this
* SLAC software, this and all the preceding Stanford University notices
* are to remain affixed to any copy or derivative of this software made
* or distributed by the recipient and are to be affixed to any copy of
* software made or distributed by the recipient that contains a copy or
* derivative of this software.
*
* ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
*/
#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"
*/
/* Priority of daemon; may be setup prior to calling rpcUdpInit();
* otherwise the network task priority from the rtems_bsdnet_config
* is used...
*/
extern rtems_task_priority rpciodPriority;
/* 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);
/* Set the timeout (initial default: 10s) for NFS and mount calls.
*
* RETURNS 0 on success, nonzero if the requested timeout is less than
* a clock tick or if the system clock rate cannot be determined.
*/
int
nfsSetTimeout(uint32_t timeout_ms);
/* Read current timeout (in milliseconds) */
uint32_t
nfsGetTimeout();
#endif

3442
c/src/nfsclient/src/nfs.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
#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();
}

View File

@@ -0,0 +1,377 @@
/* $Id$ */
/* Test program for evaluating NFS read throughput */
/* Author: Till Straumann <strauman@slac.stanford.edu>, 2006 */
/* This test code allows for evaluating NFS read performance
* under various scenarios:
* - synchronous reads with various buffer sizes (select
* 'num_readers' == 0, see below).
* - pseudo 'read-ahead' using multiple threads that issue
* NFS reads from the same file (but from different offsets)
* in parallel.
* Rationale: each NFS read request is synchronous, i.e., the
* caller sends a request to the server and waits for the
* reply to come back. Performance enhancement can be expected
* by requesting multiple blocks in parallel rather than
* sequentially.
*
* rtems_interval
* nfsTestRead(char *file_name, int chunk_size, int num_readers);
*
* 1) creates 'num_readers' threads, each opening 'file_name' for
* reading on a separate file descriptor.
* 2) creates message queues for communicating with reader threads
*
* 3) read file using nfsTestReadBigbuf() until EOF is reached
*
* 4) releases resources.
*
* RETURNS: Time elapsed during step 3 in ms. This is measured
* using the system clock so make sure the test file
* is big enough.
*
* nfsTestReadBigbuf() synchronously reads a block of
* 'num_readers * chunk_size' (which may be bigger than
* the UDP limit of 8k) using 'num_reader' threads to
* retrieve the various pieces of the big block in parallel.
* This speeds up things since several RPC calls can
* be in the works at once.
*
* NOTES:
* - if 'num_readers' == 0 this corresponds to an 'ordinary'
* NFS read. 'num_readers' == 1 schedules a single reader
* thread (== ordinary NFS read + message passing overhead).
* - no actual processing on the data is done; they are simply
* thrown away. A real, performance-critical application could
* pipeline 'reader' and 'cruncher' threads.
* - read is not completely asynchronous; synchronization is still
* performed at 'big block' boundaries (num_readers * chunk_size).
*/
/*
* Authorship
* ----------
* This software (NFS-2 client implementation for RTEMS) was created by
* Till Straumann <strauman@slac.stanford.edu>, 2002-2007,
* Stanford Linear Accelerator Center, Stanford University.
*
* Acknowledgement of sponsorship
* ------------------------------
* The NFS-2 client implementation for RTEMS 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.
*
* Stanford disclaimer of copyright
* --------------------------------
* Stanford University, owner of the copyright, hereby disclaims its
* copyright and all other rights in this software. Hence, anyone may
* freely use it for any purpose without restriction.
*
* Maintenance of notices
* ----------------------
* In the interest of clarity regarding the origin and status of this
* SLAC software, this and all the preceding Stanford University notices
* are to remain affixed to any copy or derivative of this software made
* or distributed by the recipient and are to be affixed to any copy of
* software made or distributed by the recipient that contains a copy or
* derivative of this software.
*
* ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
*/
#include <rtems.h>
#include <rtems/error.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
unsigned nfsTestReaderPri = 80;
struct nfsTestReq_ {
unsigned offset; /* file offset */
int size; /* IN: block size to read (must be < 8192), OUT: bytes actually read */
void *buf; /* data buffer address */
};
/* Queue for sending requests to parallel reader tasks */
rtems_id nfsTestRQ = 0;
/* Queue to pickup replies from parallel reader tasks */
rtems_id nfsTestAQ = 0;
/* Reader task; opens its own file descriptor
* and works on requests:
* - obtain request from request queue.
* - lseek to the requested file offset
* - NFS read into buffer
* - queue reply.
*
* Note that this implementation is very simple
* - no full error checking.
* - file is opened/closed by thread
* it's main purpose is running quick tests.
*/
static rtems_task
nfsTestReader(rtems_task_argument arg)
{
int fd = open((char*)arg,O_RDONLY);
unsigned long s;
struct nfsTestReq_ r;
rtems_status_code sc;
if ( fd < 0 ) {
perror("nfsReader: opening file");
goto cleanup;
}
do {
s = sizeof(r);
sc = rtems_message_queue_receive(nfsTestRQ, &r, &s, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
if ( RTEMS_SUCCESSFUL != sc ) {
rtems_error(sc, "(Error) reading from message queue");
goto cleanup;
}
if ( !r.buf ) {
/* They send a NULL buffer as a shutdown request */
break;
}
#ifdef DEBUG
printf("Reader: reading offset %u, size %i to %p ... ",
r.offset, r.size, r.buf);
#endif
/* seek to requested offset */
lseek(fd, r.offset, SEEK_SET);
r.size = read(fd, r.buf, r.size);
#ifdef DEBUG
printf("got %i\n",r.size);
#endif
rtems_message_queue_send(nfsTestAQ, &r, sizeof(r));
} while (1) ;
cleanup:
if ( fd >= 0 )
close(fd);
rtems_task_delete(RTEMS_SELF);
}
/* helper to create and start a reader task */
static rtems_id
taskSpawn(char *filenm, int inst)
{
rtems_status_code sc;
rtems_id tid;
sc = rtems_task_create(
rtems_build_name('n','t','t','0'+inst),
nfsTestReaderPri,
1400,
RTEMS_DEFAULT_MODES,
RTEMS_DEFAULT_ATTRIBUTES,
&tid);
if ( RTEMS_SUCCESSFUL != sc ) {
rtems_error(sc,"(Error) Creating nfs reader task %i",inst);
return 0;
}
sc = rtems_task_start(tid, nfsTestReader, (rtems_task_argument)filenm);
if ( RTEMS_SUCCESSFUL != sc ) {
rtems_error(sc,"(Error) Staritng nfs reader task %i",inst);
rtems_task_delete(tid);
return 0;
}
return tid;
}
/*
* Read nrd*sz bytes into 'buf' from file offset 'off'
* using 'nrd' parallel reader tasks to do the job.
* This helper routine schedules 'nrd' requests to
* the reader tasks and waits for all requests to
* finish.
*
* RETURNS: number of bytes read or -1 (error).
*
* CAVEATS:
* - assumes read requests always return 'sz' bytes
* unless the end of file is reached.
* THIS ASSUMPTION SHOULD NOT BE MADE WHEN WRITING
* ANY 'REAL' CODE.
*/
static int
nfsTestReadBigbuf(char *buf, int off, int sz, int nrd)
{
int i,rval=0;
struct nfsTestReq_ r;
r.buf = buf;
r.size = sz;
r.offset = off;
/* send out parallel requests */
for (i=0; i<nrd; i++) {
rtems_message_queue_send(nfsTestRQ, &r, sizeof(r));
r.offset += sz;
r.buf += sz;
}
/* wait for answers */
for (i=0; i<nrd; i++) {
unsigned long s = sizeof(r);
rtems_message_queue_receive(nfsTestAQ, &r, &s, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
if ( r.size < 0 ) {
fprintf(stderr,"A reader failed\n");
rval = -1;
} else {
/* FIXME sanity checks:
* - catch case where any-but-last read returns < sz
*/
if ( rval >= 0 ) {
rval += r.size;
}
}
}
return rval;
}
/* Main test routine
*
* Read file 'fname' usint 'nrd' parallel reader tasks,
* each operating on chunks of 'sz' bytes.
*
* RETURNS: time elapsed in milliseconds. This is measured
* using the system clock. Hence, for the result
* to be meaningful, the file must be big enough.
*
*/
rtems_interval
nfsTestRead(char *fnam, int sz, int nrd)
{
int i;
unsigned off;
rtems_interval now=-1, then, tickspsec;
rtems_status_code sc;
int fd=-1;
char *buf=0;
if ( nrd < 0 )
nrd = 0;
if ( sz < 0 || sz > 8192 ) {
fprintf(stderr,"\n");
return -1;
}
nfsTestRQ = nfsTestAQ = 0;
/* Allocate buffer */
if ( ! (buf=malloc(sz*(nrd ? nrd : 1))) ) {
perror("allocating buffer");
goto cleanup;
}
/* Don't bother proceeding if we can't open the file for reading */
if ( (fd=open(fnam,O_RDONLY)) < 0 ) {
perror("opening file");
goto cleanup;
}
if ( nrd ) {
close(fd); fd = -1;
}
/* Create request queue */
if ( nrd ) {
sc = rtems_message_queue_create(
rtems_build_name('n','t','r','q'),
nrd,
sizeof(struct nfsTestReq_),
RTEMS_DEFAULT_ATTRIBUTES,
& nfsTestRQ );
if ( RTEMS_SUCCESSFUL != sc ) {
rtems_error(sc, "(Error) creating request queue");
nfsTestRQ = 0;
goto cleanup;
}
/* Spawn reader tasks */
for ( i=0; i<nrd; i++ ) {
if ( ! taskSpawn(fnam, i) )
goto cleanup;
}
/* Create reply queue */
sc = rtems_message_queue_create(
rtems_build_name('n','t','a','q'),
nrd,
sizeof(struct nfsTestReq_),
RTEMS_DEFAULT_ATTRIBUTES,
& nfsTestAQ );
if ( RTEMS_SUCCESSFUL != sc ) {
rtems_error(sc, "(Error) creating reply queue");
nfsTestAQ = 0;
goto cleanup;
}
}
/* Timed main loop */
rtems_clock_get( RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
if ( nrd ) {
off = 0;
while ((i = nfsTestReadBigbuf(buf, off, sz, nrd)) > 0 ) {
#ifdef DEBUG
printf("bigbuf got %i\n", i);
#endif
off += i;
}
} else {
while ( (i = read(fd, buf, sz)) > 0 )
/* nothing else to do */;
if ( i < 0 ) {
perror("reading");
goto cleanup;
}
}
rtems_clock_get( RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
now = (now-then)*1000;
rtems_clock_get( RTEMS_CLOCK_GET_TICKS_PER_SECOND, &tickspsec);
now /= tickspsec; /* time in ms */
cleanup:
if ( fd >= 0 )
close(fd);
if ( nfsTestRQ ) {
/* request tasks to shutdown by sending NULL buf request */
struct nfsTestReq_ r;
r.buf = 0;
for ( i=0; i<nrd; i++ ) {
rtems_message_queue_send( nfsTestRQ, &r, sizeof(r) );
}
/* cheat: instead of proper synchronization with shutdown we simply
* delay for a second...
*/
rtems_task_wake_after( tickspsec );
rtems_message_queue_delete( nfsTestRQ );
}
if ( nfsTestAQ )
rtems_message_queue_delete( nfsTestAQ );
free(buf);
return now;
}

1771
c/src/nfsclient/src/rpcio.c Normal file

File diff suppressed because it is too large Load Diff

209
c/src/nfsclient/src/rpcio.h Normal file
View File

@@ -0,0 +1,209 @@
#ifndef RPCIO_H
#define RPCIO_H
/* $Id$ */
/* A multihreaded RPC/UDP multiplexor */
/* Author: Till Straumann, <strauman@slac.stanford.edu>, 2002 */
/*
* Authorship
* ----------
* This software (NFS-2 client implementation for RTEMS) was created by
* Till Straumann <strauman@slac.stanford.edu>, 2002-2007,
* Stanford Linear Accelerator Center, Stanford University.
*
* Acknowledgement of sponsorship
* ------------------------------
* The NFS-2 client implementation for RTEMS 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.
*
* Stanford disclaimer of copyright
* --------------------------------
* Stanford University, owner of the copyright, hereby disclaims its
* copyright and all other rights in this software. Hence, anyone may
* freely use it for any purpose without restriction.
*
* Maintenance of notices
* ----------------------
* In the interest of clarity regarding the origin and status of this
* SLAC software, this and all the preceding Stanford University notices
* are to remain affixed to any copy or derivative of this software made
* or distributed by the recipient and are to be affixed to any copy of
* software made or distributed by the recipient that contains a copy or
* derivative of this software.
*
* ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
*/
#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

View File

@@ -0,0 +1,15 @@
#include "librtemsNfs.h"
/* CEXP module support (magic init) */
void
_cexpModuleInitialize(void *mod)
{
rpcUdpInit();
}
int
_cexpModuleFinalize(void *mod)
{
return rpcUdpCleanup();
}

View File

@@ -0,0 +1,281 @@
/*
* $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);
}

View File

@@ -0,0 +1,534 @@
/* $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);
}