mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-05 15:15:44 +00:00
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:
112
c/src/nfsclient/ChangeLog
Normal file
112
c/src/nfsclient/ChangeLog
Normal 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
44
c/src/nfsclient/LICENSE
Normal 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
16
c/src/nfsclient/Makefile
Normal 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
548
c/src/nfsclient/README
Normal 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.
|
||||
76
c/src/nfsclient/proto/Makefile
Normal file
76
c/src/nfsclient/proto/Makefile
Normal 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
|
||||
144
c/src/nfsclient/proto/mount_prot.h
Normal file
144
c/src/nfsclient/proto/mount_prot.h
Normal 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 */
|
||||
161
c/src/nfsclient/proto/mount_prot.x
Normal file
161
c/src/nfsclient/proto/mount_prot.x
Normal 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;
|
||||
124
c/src/nfsclient/proto/mount_prot_xdr.c
Normal file
124
c/src/nfsclient/proto/mount_prot_xdr.c
Normal 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;
|
||||
}
|
||||
453
c/src/nfsclient/proto/nfs_prot.h
Normal file
453
c/src/nfsclient/proto/nfs_prot.h
Normal 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 */
|
||||
1268
c/src/nfsclient/proto/nfs_prot.x
Normal file
1268
c/src/nfsclient/proto/nfs_prot.x
Normal file
File diff suppressed because it is too large
Load Diff
671
c/src/nfsclient/proto/nfs_prot_xdr.c
Normal file
671
c/src/nfsclient/proto/nfs_prot_xdr.c
Normal 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
1258
c/src/nfsclient/rfc1094.txt
Normal file
File diff suppressed because it is too large
Load Diff
860
c/src/nfsclient/rtems-filesystem-patch
Normal file
860
c/src/nfsclient/rtems-filesystem-patch
Normal 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;
|
||||
}
|
||||
104
c/src/nfsclient/src/Makefile
Normal file
104
c/src/nfsclient/src/Makefile
Normal 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
|
||||
16
c/src/nfsclient/src/cexphelp.c
Normal file
16
c/src/nfsclient/src/cexphelp.c
Normal 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
|
||||
362
c/src/nfsclient/src/dirutils.c
Normal file
362
c/src/nfsclient/src/dirutils.c
Normal 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
|
||||
182
c/src/nfsclient/src/librtemsNfs.h
Normal file
182
c/src/nfsclient/src/librtemsNfs.h
Normal 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
3442
c/src/nfsclient/src/nfs.c
Normal file
File diff suppressed because it is too large
Load Diff
27
c/src/nfsclient/src/nfs.modini.c
Normal file
27
c/src/nfsclient/src/nfs.modini.c
Normal 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();
|
||||
}
|
||||
|
||||
|
||||
377
c/src/nfsclient/src/nfsTest.c
Normal file
377
c/src/nfsclient/src/nfsTest.c
Normal 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
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
209
c/src/nfsclient/src/rpcio.h
Normal 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
|
||||
15
c/src/nfsclient/src/rpcio.modini.c
Normal file
15
c/src/nfsclient/src/rpcio.modini.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "librtemsNfs.h"
|
||||
/* CEXP module support (magic init) */
|
||||
void
|
||||
_cexpModuleInitialize(void *mod)
|
||||
{
|
||||
rpcUdpInit();
|
||||
}
|
||||
|
||||
int
|
||||
_cexpModuleFinalize(void *mod)
|
||||
{
|
||||
return rpcUdpCleanup();
|
||||
}
|
||||
|
||||
|
||||
281
c/src/nfsclient/src/sock_mbuf.c
Normal file
281
c/src/nfsclient/src/sock_mbuf.c
Normal 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);
|
||||
}
|
||||
534
c/src/nfsclient/src/xdr_mbuf.c
Normal file
534
c/src/nfsclient/src/xdr_mbuf.c
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user