From 6692e03e9d1b8fae6526b828460c96b3db18d1d5 Mon Sep 17 00:00:00 2001 From: Vijay Kumar Banerjee Date: Wed, 24 Feb 2021 19:08:51 -0700 Subject: cpukit/libfs: Remove nfsclient Update #3850 --- cpukit/libfs/src/nfsclient/ChangeLog.slac | 112 - cpukit/libfs/src/nfsclient/LICENSE | 44 - cpukit/libfs/src/nfsclient/README | 548 ---- cpukit/libfs/src/nfsclient/proto/mount_prot.h | 155 - cpukit/libfs/src/nfsclient/proto/mount_prot.x | 161 - cpukit/libfs/src/nfsclient/proto/mount_prot_xdr.c | 112 - cpukit/libfs/src/nfsclient/proto/nfs_prot.h | 460 --- cpukit/libfs/src/nfsclient/proto/nfs_prot.x | 1268 -------- cpukit/libfs/src/nfsclient/proto/nfs_prot_xdr.c | 629 ---- cpukit/libfs/src/nfsclient/rfc1094.txt | 1258 -------- cpukit/libfs/src/nfsclient/src/nfs.c | 3203 -------------------- cpukit/libfs/src/nfsclient/src/nfsclient-private.h | 14 - cpukit/libfs/src/nfsclient/src/rpcio.c | 1774 ----------- cpukit/libfs/src/nfsclient/src/rpcio.h | 226 -- cpukit/libfs/src/nfsclient/src/sock_mbuf.c | 285 -- cpukit/libfs/src/nfsclient/src/xdr_mbuf.c | 548 ---- 16 files changed, 10797 deletions(-) delete mode 100644 cpukit/libfs/src/nfsclient/ChangeLog.slac delete mode 100644 cpukit/libfs/src/nfsclient/LICENSE delete mode 100644 cpukit/libfs/src/nfsclient/README delete mode 100644 cpukit/libfs/src/nfsclient/proto/mount_prot.h delete mode 100644 cpukit/libfs/src/nfsclient/proto/mount_prot.x delete mode 100644 cpukit/libfs/src/nfsclient/proto/mount_prot_xdr.c delete mode 100644 cpukit/libfs/src/nfsclient/proto/nfs_prot.h delete mode 100644 cpukit/libfs/src/nfsclient/proto/nfs_prot.x delete mode 100644 cpukit/libfs/src/nfsclient/proto/nfs_prot_xdr.c delete mode 100644 cpukit/libfs/src/nfsclient/rfc1094.txt delete mode 100644 cpukit/libfs/src/nfsclient/src/nfs.c delete mode 100644 cpukit/libfs/src/nfsclient/src/nfsclient-private.h delete mode 100644 cpukit/libfs/src/nfsclient/src/rpcio.c delete mode 100644 cpukit/libfs/src/nfsclient/src/rpcio.h delete mode 100644 cpukit/libfs/src/nfsclient/src/sock_mbuf.c delete mode 100644 cpukit/libfs/src/nfsclient/src/xdr_mbuf.c (limited to 'cpukit/libfs/src') diff --git a/cpukit/libfs/src/nfsclient/ChangeLog.slac b/cpukit/libfs/src/nfsclient/ChangeLog.slac deleted file mode 100644 index 94dea06763..0000000000 --- a/cpukit/libfs/src/nfsclient/ChangeLog.slac +++ /dev/null @@ -1,112 +0,0 @@ -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 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. diff --git a/cpukit/libfs/src/nfsclient/LICENSE b/cpukit/libfs/src/nfsclient/LICENSE deleted file mode 100644 index 4687f9a22f..0000000000 --- a/cpukit/libfs/src/nfsclient/LICENSE +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Authorship - * ---------- - * This software (NFS-2 client implementation for RTEMS) was created by - * Till Straumann , 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 - */ diff --git a/cpukit/libfs/src/nfsclient/README b/cpukit/libfs/src/nfsclient/README deleted file mode 100644 index 944b830e2e..0000000000 --- a/cpukit/libfs/src/nfsclient/README +++ /dev/null @@ -1,548 +0,0 @@ -RTEMS-NFS -========= - -A NFS-V2 client implementation for the RTEMS real-time -executive. - -Author: Till Straumann , 2002 - -Copyright 2002, Stanford University and - Till Straumann - -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): - - [ '.' '@' ] ':' - - 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 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: - - [ '.' '@' ] - - The 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. diff --git a/cpukit/libfs/src/nfsclient/proto/mount_prot.h b/cpukit/libfs/src/nfsclient/proto/mount_prot.h deleted file mode 100644 index 11ef3cc23f..0000000000 --- a/cpukit/libfs/src/nfsclient/proto/mount_prot.h +++ /dev/null @@ -1,155 +0,0 @@ -/** - * @file - * - * @brief Nfsclient Mount Prot - * - * @ingroup RTEMSFileSystemNFSMountProt - */ - -#ifndef _MOUNT_PROT_H_RPCGEN -#define _MOUNT_PROT_H_RPCGEN - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup RTEMSFileSystemNFSMountProt Mount Prot - * - * @ingroup RTEMSFileSystemNFS - * - * @{ - */ - -#define MNTPATHLEN 1024 -#define MNTNAMLEN 255 -#define FHSIZE 32 - -typedef char fhandle[FHSIZE]; - -struct fhstatus { - u_int fhs_status; - union { - fhandle fhs_fhandle; - } fhstatus_u; -}; -typedef struct fhstatus fhstatus; - -typedef char *dirpath; - -typedef char *name; - -typedef struct mountbody *mountlist; - -struct mountbody { - name ml_hostname; - dirpath ml_directory; - mountlist ml_next; -}; -typedef struct mountbody mountbody; - -typedef struct groupnode *groups; - -struct groupnode { - name gr_name; - groups gr_next; -}; -typedef struct groupnode groupnode; - -typedef struct exportnode *exports; - -struct exportnode { - dirpath ex_dir; - groups ex_groups; - exports ex_next; -}; -typedef struct exportnode exportnode; - -#define MOUNTPROG 100005 -#define MOUNTVERS 1 - -#if defined(__STDC__) || defined(__cplusplus) -#define MOUNTPROC_NULL 0 -extern void * mountproc_null_1(void *, CLIENT *); -extern void * mountproc_null_1_svc(void *, struct svc_req *); -#define MOUNTPROC_MNT 1 -extern fhstatus * mountproc_mnt_1(dirpath *, CLIENT *); -extern fhstatus * mountproc_mnt_1_svc(dirpath *, struct svc_req *); -#define MOUNTPROC_DUMP 2 -extern mountlist * mountproc_dump_1(void *, CLIENT *); -extern mountlist * mountproc_dump_1_svc(void *, struct svc_req *); -#define MOUNTPROC_UMNT 3 -extern void * mountproc_umnt_1(dirpath *, CLIENT *); -extern void * mountproc_umnt_1_svc(dirpath *, struct svc_req *); -#define MOUNTPROC_UMNTALL 4 -extern void * mountproc_umntall_1(void *, CLIENT *); -extern void * mountproc_umntall_1_svc(void *, struct svc_req *); -#define MOUNTPROC_EXPORT 5 -extern exports * mountproc_export_1(void *, CLIENT *); -extern exports * mountproc_export_1_svc(void *, struct svc_req *); -#define MOUNTPROC_EXPORTALL 6 -extern exports * mountproc_exportall_1(void *, CLIENT *); -extern exports * mountproc_exportall_1_svc(void *, struct svc_req *); -extern int mountprog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t); - -#else /* K&R C */ -#define MOUNTPROC_NULL 0 -extern void * mountproc_null_1(); -extern void * mountproc_null_1_svc(); -#define MOUNTPROC_MNT 1 -extern fhstatus * mountproc_mnt_1(); -extern fhstatus * mountproc_mnt_1_svc(); -#define MOUNTPROC_DUMP 2 -extern mountlist * mountproc_dump_1(); -extern mountlist * mountproc_dump_1_svc(); -#define MOUNTPROC_UMNT 3 -extern void * mountproc_umnt_1(); -extern void * mountproc_umnt_1_svc(); -#define MOUNTPROC_UMNTALL 4 -extern void * mountproc_umntall_1(); -extern void * mountproc_umntall_1_svc(); -#define MOUNTPROC_EXPORT 5 -extern exports * mountproc_export_1(); -extern exports * mountproc_export_1_svc(); -#define MOUNTPROC_EXPORTALL 6 -extern exports * mountproc_exportall_1(); -extern exports * mountproc_exportall_1_svc(); -extern int mountprog_1_freeresult (); -#endif /* K&R C */ - -/* the xdr functions */ - -#if defined(__STDC__) || defined(__cplusplus) -extern bool_t xdr_fhandle (XDR *, fhandle); -extern bool_t xdr_fhstatus (XDR *, fhstatus*); -extern bool_t xdr_dirpath (XDR *, dirpath*); -extern bool_t xdr_name (XDR *, name*); -extern bool_t xdr_mountlist (XDR *, mountlist*); -extern bool_t xdr_mountbody (XDR *, mountbody*); -extern bool_t xdr_groups (XDR *, groups*); -extern bool_t xdr_groupnode (XDR *, groupnode*); -extern bool_t xdr_exports (XDR *, exports*); -extern bool_t xdr_exportnode (XDR *, exportnode*); - -#else /* K&R C */ -extern bool_t xdr_fhandle (); -extern bool_t xdr_fhstatus (); -extern bool_t xdr_dirpath (); -extern bool_t xdr_name (); -extern bool_t xdr_mountlist (); -extern bool_t xdr_mountbody (); -extern bool_t xdr_groups (); -extern bool_t xdr_groupnode (); -extern bool_t xdr_exports (); -extern bool_t xdr_exportnode (); - -#endif /* K&R C */ - -/**@}*/ - -#ifdef __cplusplus -} -#endif -#endif /* !_MOUNT_PROT_H_RPCGEN */ diff --git a/cpukit/libfs/src/nfsclient/proto/mount_prot.x b/cpukit/libfs/src/nfsclient/proto/mount_prot.x deleted file mode 100644 index 7e0d7f3ad6..0000000000 --- a/cpukit/libfs/src/nfsclient/proto/mount_prot.x +++ /dev/null @@ -1,161 +0,0 @@ -/* @(#)mount.x 2.1 88/08/01 4.0 RPCSRC */ -/* @(#)mount.x 1.2 87/09/18 Copyr 1987 Sun Micro */ - -/* - * Sun RPC is a product of Sun Microsystems, Inc. and is provided for - * unrestricted use provided that this legend is included on all tape - * media and as a part of the software program in whole or part. Users - * may copy or modify Sun RPC without charge, but are not authorized - * to license or distribute it to anyone else except as part of a product or - * program developed by the user. - * - * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE - * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun RPC is provided with no support and without any obligation on the - * part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ - -/* - * Protocol description for the mount program - */ - - -const MNTPATHLEN = 1024; /* maximum bytes in a pathname argument */ -const MNTNAMLEN = 255; /* maximum bytes in a name argument */ -const FHSIZE = 32; /* size in bytes of a file handle */ - -/* - * The fhandle is the file handle that the server passes to the client. - * All file operations are done using the file handles to refer to a file - * or a directory. The file handle can contain whatever information the - * server needs to distinguish an individual file. - */ -typedef opaque fhandle[FHSIZE]; - -/* - * If a status of zero is returned, the call completed successfully, and - * a file handle for the directory follows. A non-zero status indicates - * some sort of error. The status corresponds with UNIX error numbers. - */ -union fhstatus switch (unsigned fhs_status) { -case 0: - fhandle fhs_fhandle; -default: - void; -}; - -/* - * The type dirpath is the pathname of a directory - */ -typedef string dirpath; - -/* - * The type name is used for arbitrary names (hostnames, groupnames) - */ -typedef string name; - -/* - * A list of who has what mounted - */ -typedef struct mountbody *mountlist; -struct mountbody { - name ml_hostname; - dirpath ml_directory; - mountlist ml_next; -}; - -/* - * A list of netgroups - */ -typedef struct groupnode *groups; -struct groupnode { - name gr_name; - groups gr_next; -}; - -/* - * A list of what is exported and to whom - */ -typedef struct exportnode *exports; -struct exportnode { - dirpath ex_dir; - groups ex_groups; - exports ex_next; -}; - -program MOUNTPROG { - /* - * Version one of the mount protocol communicates with version two - * of the NFS protocol. The only connecting point is the fhandle - * structure, which is the same for both protocols. - */ - version MOUNTVERS { - /* - * Does no work. It is made available in all RPC services - * to allow server reponse testing and timing - */ - void - MOUNTPROC_NULL(void) = 0; - - /* - * If fhs_status is 0, then fhs_fhandle contains the - * file handle for the directory. This file handle may - * be used in the NFS protocol. This procedure also adds - * a new entry to the mount list for this client mounting - * the directory. - * Unix authentication required. - */ - fhstatus - MOUNTPROC_MNT(dirpath) = 1; - - /* - * Returns the list of remotely mounted filesystems. The - * mountlist contains one entry for each hostname and - * directory pair. - */ - mountlist - MOUNTPROC_DUMP(void) = 2; - - /* - * Removes the mount list entry for the directory - * Unix authentication required. - */ - void - MOUNTPROC_UMNT(dirpath) = 3; - - /* - * Removes all of the mount list entries for this client - * Unix authentication required. - */ - void - MOUNTPROC_UMNTALL(void) = 4; - - /* - * Returns a list of all the exported filesystems, and which - * machines are allowed to import it. - */ - exports - MOUNTPROC_EXPORT(void) = 5; - - /* - * Identical to MOUNTPROC_EXPORT above - */ - exports - MOUNTPROC_EXPORTALL(void) = 6; - } = 1; -} = 100005; diff --git a/cpukit/libfs/src/nfsclient/proto/mount_prot_xdr.c b/cpukit/libfs/src/nfsclient/proto/mount_prot_xdr.c deleted file mode 100644 index 85a7b9ba2e..0000000000 --- a/cpukit/libfs/src/nfsclient/proto/mount_prot_xdr.c +++ /dev/null @@ -1,112 +0,0 @@ -/** - * @file - * - * @ingroup RTEMSFileSystemNFSMountProt Mount Prot - * - * @brief Mount Prot XDR - */ - -/* - * Please do not edit this file. - * It was generated using rpcgen. - */ - -#include "mount_prot.h" - -bool_t -xdr_fhandle (XDR *xdrs, fhandle objp) -{ - if (!xdr_opaque (xdrs, objp, FHSIZE)) - return FALSE; - return TRUE; -} - -bool_t -xdr_fhstatus (XDR *xdrs, fhstatus *objp) -{ - 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) -{ - if (!xdr_string (xdrs, objp, MNTPATHLEN)) - return FALSE; - return TRUE; -} - -bool_t -xdr_name (XDR *xdrs, name *objp) -{ - if (!xdr_string (xdrs, objp, MNTNAMLEN)) - return FALSE; - return TRUE; -} - -bool_t -xdr_mountlist (XDR *xdrs, mountlist *objp) -{ - 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) -{ - 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) -{ - 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) -{ - 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) -{ - 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) -{ - if (!xdr_dirpath (xdrs, &objp->ex_dir)) - return FALSE; - if (!xdr_groups (xdrs, &objp->ex_groups)) - return FALSE; - if (!xdr_exports (xdrs, &objp->ex_next)) - return FALSE; - return TRUE; -} diff --git a/cpukit/libfs/src/nfsclient/proto/nfs_prot.h b/cpukit/libfs/src/nfsclient/proto/nfs_prot.h deleted file mode 100644 index 48bf0fb063..0000000000 --- a/cpukit/libfs/src/nfsclient/proto/nfs_prot.h +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Please do not edit this file. - * It was generated using rpcgen. - */ - -#ifndef _NFS_PROT_H_RPCGEN -#define _NFS_PROT_H_RPCGEN - -#include - -/** - * @defgroup RTEMSFileSystemNFSProt NFS Prot - * - * @ingroup RTEMSFileSystemNFS - */ -/**@{*/ -#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, - _NFSSTAT = 0xffffffff -}; -typedef enum nfsstat nfsstat; - -enum ftype { - NFNON = 0, - NFREG = 1, - NFDIR = 2, - NFBLK = 3, - NFCHR = 4, - NFLNK = 5, - NFSOCK = 6, - NFBAD = 7, - NFFIFO = 8, - _FTYPE = 0xffffffff -}; -typedef enum ftype ftype; - -struct nfs_fh { - char data[NFS_FHSIZE]; -}; -typedef struct nfs_fh nfs_fh; - -struct nfstime { - u_int seconds; - u_int useconds; -}; -typedef struct nfstime nfstime; - -struct fattr { - ftype type; - u_int mode; - u_int nlink; - u_int uid; - u_int gid; - u_int size; - u_int blocksize; - u_int rdev; - u_int blocks; - u_int fsid; - u_int fileid; - nfstime atime; - nfstime mtime; - nfstime ctime; -}; -typedef struct fattr fattr; - -struct sattr { - u_int mode; - u_int uid; - u_int gid; - u_int size; - nfstime atime; - nfstime mtime; -}; -typedef struct sattr sattr; - -typedef char *filename; - -typedef char *nfspath; - -struct attrstat { - nfsstat status; - union { - fattr attributes; - } attrstat_u; -}; -typedef struct attrstat attrstat; - -struct sattrargs { - nfs_fh file; - sattr attributes; -}; -typedef struct sattrargs sattrargs; - -struct diropargs { - nfs_fh dir; - filename name; -}; -typedef struct diropargs diropargs; - -struct diropokres { - nfs_fh file; - fattr attributes; -}; -typedef struct diropokres diropokres; - -struct diropres { - nfsstat status; - union { - diropokres diropres; - } diropres_u; -}; -typedef struct diropres diropres; - -struct readlinkres { - nfsstat status; - union { - nfspath data; - } readlinkres_u; -}; -typedef struct readlinkres readlinkres; - -struct readargs { - nfs_fh file; - u_int offset; - u_int count; - u_int totalcount; -}; -typedef struct readargs readargs; - -struct readokres { - fattr attributes; - struct { - u_int data_len; - char *data_val; - } data; -}; -typedef struct readokres readokres; - -struct readres { - nfsstat status; - union { - readokres reply; - } readres_u; -}; -typedef struct readres readres; - -struct writeargs { - nfs_fh file; - u_int beginoffset; - u_int offset; - u_int totalcount; - struct { - u_int data_len; - char *data_val; - } data; -}; -typedef struct writeargs writeargs; - -struct createargs { - diropargs where; - sattr attributes; -}; -typedef struct createargs createargs; - -struct renameargs { - diropargs from; - diropargs to; -}; -typedef struct renameargs renameargs; - -struct linkargs { - nfs_fh from; - diropargs to; -}; -typedef struct linkargs linkargs; - -struct symlinkargs { - diropargs from; - nfspath to; - sattr attributes; -}; -typedef struct symlinkargs symlinkargs; - -struct nfscookie { - char data[NFS_COOKIESIZE]; -}; -typedef struct nfscookie nfscookie; - -struct readdirargs { - nfs_fh dir; - nfscookie cookie; - u_int count; -}; -typedef struct readdirargs readdirargs; - -struct entry { - u_int fileid; - filename name; - nfscookie cookie; - struct entry *nextentry; -}; -typedef struct entry entry; - -struct dirlist { - entry *entries; - bool_t eof; -}; -typedef struct dirlist dirlist; - -struct readdirres { - nfsstat status; - union { - dirlist reply; - } readdirres_u; -}; -typedef struct readdirres readdirres; - -struct statfsokres { - u_int tsize; - u_int bsize; - u_int blocks; - u_int bfree; - u_int bavail; -}; -typedef struct statfsokres statfsokres; - -struct statfsres { - nfsstat status; - union { - statfsokres reply; - } statfsres_u; -}; -typedef struct statfsres statfsres; - -#define NFS_PROGRAM 100003 -#define NFS_VERSION 2 - -#if defined(__STDC__) || defined(__cplusplus) -#define NFSPROC_NULL 0 -extern void * nfsproc_null_2(void *, CLIENT *); -extern void * nfsproc_null_2_svc(void *, struct svc_req *); -#define NFSPROC_GETATTR 1 -extern attrstat * nfsproc_getattr_2(nfs_fh *, CLIENT *); -extern attrstat * nfsproc_getattr_2_svc(nfs_fh *, struct svc_req *); -#define NFSPROC_SETATTR 2 -extern attrstat * nfsproc_setattr_2(sattrargs *, CLIENT *); -extern attrstat * nfsproc_setattr_2_svc(sattrargs *, struct svc_req *); -#define NFSPROC_ROOT 3 -extern void * nfsproc_root_2(void *, CLIENT *); -extern void * nfsproc_root_2_svc(void *, struct svc_req *); -#define NFSPROC_LOOKUP 4 -extern diropres * nfsproc_lookup_2(diropargs *, CLIENT *); -extern diropres * nfsproc_lookup_2_svc(diropargs *, struct svc_req *); -#define NFSPROC_READLINK 5 -extern readlinkres * nfsproc_readlink_2(nfs_fh *, CLIENT *); -extern readlinkres * nfsproc_readlink_2_svc(nfs_fh *, struct svc_req *); -#define NFSPROC_READ 6 -extern readres * nfsproc_read_2(readargs *, CLIENT *); -extern readres * nfsproc_read_2_svc(readargs *, struct svc_req *); -#define NFSPROC_WRITECACHE 7 -extern void * nfsproc_writecache_2(void *, CLIENT *); -extern void * nfsproc_writecache_2_svc(void *, struct svc_req *); -#define NFSPROC_WRITE 8 -extern attrstat * nfsproc_write_2(writeargs *, CLIENT *); -extern attrstat * nfsproc_write_2_svc(writeargs *, struct svc_req *); -#define NFSPROC_CREATE 9 -extern diropres * nfsproc_create_2(createargs *, CLIENT *); -extern diropres * nfsproc_create_2_svc(createargs *, struct svc_req *); -#define NFSPROC_REMOVE 10 -extern nfsstat * nfsproc_remove_2(diropargs *, CLIENT *); -extern nfsstat * nfsproc_remove_2_svc(diropargs *, struct svc_req *); -#define NFSPROC_RENAME 11 -extern nfsstat * nfsproc_rename_2(renameargs *, CLIENT *); -extern nfsstat * nfsproc_rename_2_svc(renameargs *, struct svc_req *); -#define NFSPROC_LINK 12 -extern nfsstat * nfsproc_link_2(linkargs *, CLIENT *); -extern nfsstat * nfsproc_link_2_svc(linkargs *, struct svc_req *); -#define NFSPROC_SYMLINK 13 -extern nfsstat * nfsproc_symlink_2(symlinkargs *, CLIENT *); -extern nfsstat * nfsproc_symlink_2_svc(symlinkargs *, struct svc_req *); -#define NFSPROC_MKDIR 14 -extern diropres * nfsproc_mkdir_2(createargs *, CLIENT *); -extern diropres * nfsproc_mkdir_2_svc(createargs *, struct svc_req *); -#define NFSPROC_RMDIR 15 -extern nfsstat * nfsproc_rmdir_2(diropargs *, CLIENT *); -extern nfsstat * nfsproc_rmdir_2_svc(diropargs *, struct svc_req *); -#define NFSPROC_READDIR 16 -extern readdirres * nfsproc_readdir_2(readdirargs *, CLIENT *); -extern readdirres * nfsproc_readdir_2_svc(readdirargs *, struct svc_req *); -#define NFSPROC_STATFS 17 -extern statfsres * nfsproc_statfs_2(nfs_fh *, CLIENT *); -extern statfsres * nfsproc_statfs_2_svc(nfs_fh *, struct svc_req *); -extern int nfs_program_2_freeresult (SVCXPRT *, xdrproc_t, caddr_t); - -#else /* K&R C */ -#define NFSPROC_NULL 0 -extern void * nfsproc_null_2(); -extern void * nfsproc_null_2_svc(); -#define NFSPROC_GETATTR 1 -extern attrstat * nfsproc_getattr_2(); -extern attrstat * nfsproc_getattr_2_svc(); -#define NFSPROC_SETATTR 2 -extern attrstat * nfsproc_setattr_2(); -extern attrstat * nfsproc_setattr_2_svc(); -#define NFSPROC_ROOT 3 -extern void * nfsproc_root_2(); -extern void * nfsproc_root_2_svc(); -#define NFSPROC_LOOKUP 4 -extern diropres * nfsproc_lookup_2(); -extern diropres * nfsproc_lookup_2_svc(); -#define NFSPROC_READLINK 5 -extern readlinkres * nfsproc_readlink_2(); -extern readlinkres * nfsproc_readlink_2_svc(); -#define NFSPROC_READ 6 -extern readres * nfsproc_read_2(); -extern readres * nfsproc_read_2_svc(); -#define NFSPROC_WRITECACHE 7 -extern void * nfsproc_writecache_2(); -extern void * nfsproc_writecache_2_svc(); -#define NFSPROC_WRITE 8 -extern attrstat * nfsproc_write_2(); -extern attrstat * nfsproc_write_2_svc(); -#define NFSPROC_CREATE 9 -extern diropres * nfsproc_create_2(); -extern diropres * nfsproc_create_2_svc(); -#define NFSPROC_REMOVE 10 -extern nfsstat * nfsproc_remove_2(); -extern nfsstat * nfsproc_remove_2_svc(); -#define NFSPROC_RENAME 11 -extern nfsstat * nfsproc_rename_2(); -extern nfsstat * nfsproc_rename_2_svc(); -#define NFSPROC_LINK 12 -extern nfsstat * nfsproc_link_2(); -extern nfsstat * nfsproc_link_2_svc(); -#define NFSPROC_SYMLINK 13 -extern nfsstat * nfsproc_symlink_2(); -extern nfsstat * nfsproc_symlink_2_svc(); -#define NFSPROC_MKDIR 14 -extern diropres * nfsproc_mkdir_2(); -extern diropres * nfsproc_mkdir_2_svc(); -#define NFSPROC_RMDIR 15 -extern nfsstat * nfsproc_rmdir_2(); -extern nfsstat * nfsproc_rmdir_2_svc(); -#define NFSPROC_READDIR 16 -extern readdirres * nfsproc_readdir_2(); -extern readdirres * nfsproc_readdir_2_svc(); -#define NFSPROC_STATFS 17 -extern statfsres * nfsproc_statfs_2(); -extern statfsres * nfsproc_statfs_2_svc(); -extern int nfs_program_2_freeresult (); -#endif /* K&R C */ - -/* the xdr functions */ - -#if defined(__STDC__) || defined(__cplusplus) -extern bool_t xdr_nfsstat (XDR *, nfsstat*); -extern bool_t xdr_ftype (XDR *, ftype*); -extern bool_t xdr_nfs_fh (XDR *, nfs_fh*); -extern bool_t xdr_nfstime (XDR *, nfstime*); -extern bool_t xdr_fattr (XDR *, fattr*); -extern bool_t xdr_sattr (XDR *, sattr*); -extern bool_t xdr_filename (XDR *, filename*); -extern bool_t xdr_nfspath (XDR *, nfspath*); -extern bool_t xdr_attrstat (XDR *, attrstat*); -extern bool_t xdr_sattrargs (XDR *, sattrargs*); -extern bool_t xdr_diropargs (XDR *, diropargs*); -extern bool_t xdr_diropokres (XDR *, diropokres*); -extern bool_t xdr_diropres (XDR *, diropres*); -extern bool_t xdr_readlinkres (XDR *, readlinkres*); -extern bool_t xdr_readargs (XDR *, readargs*); -extern bool_t xdr_readokres (XDR *, readokres*); -extern bool_t xdr_readres (XDR *, readres*); -extern bool_t xdr_writeargs (XDR *, writeargs*); -extern bool_t xdr_createargs (XDR *, createargs*); -extern bool_t xdr_renameargs (XDR *, renameargs*); -extern bool_t xdr_linkargs (XDR *, linkargs*); -extern bool_t xdr_symlinkargs (XDR *, symlinkargs*); -extern bool_t xdr_nfscookie (XDR *, nfscookie*); -extern bool_t xdr_readdirargs (XDR *, readdirargs*); -extern bool_t xdr_entry (XDR *, entry*); -extern bool_t xdr_dirlist (XDR *, dirlist*); -extern bool_t xdr_readdirres (XDR *, readdirres*); -extern bool_t xdr_statfsokres (XDR *, statfsokres*); -extern bool_t xdr_statfsres (XDR *, statfsres*); - -#else /* K&R C */ -extern bool_t xdr_nfsstat (); -extern bool_t xdr_ftype (); -extern bool_t xdr_nfs_fh (); -extern bool_t xdr_nfstime (); -extern bool_t xdr_fattr (); -extern bool_t xdr_sattr (); -extern bool_t xdr_filename (); -extern bool_t xdr_nfspath (); -extern bool_t xdr_attrstat (); -extern bool_t xdr_sattrargs (); -extern bool_t xdr_diropargs (); -extern bool_t xdr_diropokres (); -extern bool_t xdr_diropres (); -extern bool_t xdr_readlinkres (); -extern bool_t xdr_readargs (); -extern bool_t xdr_readokres (); -extern bool_t xdr_readres (); -extern bool_t xdr_writeargs (); -extern bool_t xdr_createargs (); -extern bool_t xdr_renameargs (); -extern bool_t xdr_linkargs (); -extern bool_t xdr_symlinkargs (); -extern bool_t xdr_nfscookie (); -extern bool_t xdr_readdirargs (); -extern bool_t xdr_entry (); -extern bool_t xdr_dirlist (); -extern bool_t xdr_readdirres (); -extern bool_t xdr_statfsokres (); -extern bool_t xdr_statfsres (); - -#endif /* K&R C */ - -#ifdef __cplusplus -} -#endif -/**@}*/ -#endif /* !_NFS_PROT_H_RPCGEN */ diff --git a/cpukit/libfs/src/nfsclient/proto/nfs_prot.x b/cpukit/libfs/src/nfsclient/proto/nfs_prot.x deleted file mode 100644 index a40d9a5f5f..0000000000 --- a/cpukit/libfs/src/nfsclient/proto/nfs_prot.x +++ /dev/null @@ -1,1268 +0,0 @@ -/* - * Sun RPC is a product of Sun Microsystems, Inc. and is provided for - * unrestricted use provided that this legend is included on all tape - * media and as a part of the software program in whole or part. Users - * may copy or modify Sun RPC without charge, but are not authorized - * to license or distribute it to anyone else except as part of a product or - * program developed by the user. - * - * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE - * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun RPC is provided with no support and without any obligation on the - * part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ - -#ifndef RPC_HDR -%#ifndef lint -%/*static char sccsid[] = "from: @(#)nfs_prot.x 1.2 87/10/12 Copyr 1987 Sun Micro";*/ -%/*static char sccsid[] = "from: @(#)nfs_prot.x 2.1 88/08/01 4.0 RPCSRC";*/ -%static char rcsid[] = "$Id$"; -%#endif /* not lint */ -#endif - -const NFS_PORT = 2049; -const NFS_MAXDATA = 8192; -const NFS_MAXPATHLEN = 1024; -const NFS_MAXNAMLEN = 255; -const NFS_FHSIZE = 32; -const NFS_COOKIESIZE = 4; -const NFS_FIFO_DEV = -1; /* size kludge for named pipes */ - -/* - * File types - */ -const NFSMODE_FMT = 0170000; /* type of file */ -const NFSMODE_DIR = 0040000; /* directory */ -const NFSMODE_CHR = 0020000; /* character special */ -const NFSMODE_BLK = 0060000; /* block special */ -const NFSMODE_REG = 0100000; /* regular */ -const NFSMODE_LNK = 0120000; /* symbolic link */ -const NFSMODE_SOCK = 0140000; /* socket */ -const NFSMODE_FIFO = 0010000; /* fifo */ - -/* - * Error status - */ -enum nfsstat { - NFS_OK= 0, /* no error */ - NFSERR_PERM=1, /* Not owner */ - NFSERR_NOENT=2, /* No such file or directory */ - NFSERR_IO=5, /* I/O error */ - NFSERR_NXIO=6, /* No such device or address */ - NFSERR_ACCES=13, /* Permission denied */ - NFSERR_EXIST=17, /* File exists */ - NFSERR_NODEV=19, /* No such device */ - NFSERR_NOTDIR=20, /* Not a directory*/ - NFSERR_ISDIR=21, /* Is a directory */ - NFSERR_FBIG=27, /* File too large */ - NFSERR_NOSPC=28, /* No space left on device */ - NFSERR_ROFS=30, /* Read-only file system */ - NFSERR_NAMETOOLONG=63, /* File name too long */ - NFSERR_NOTEMPTY=66, /* Directory not empty */ - NFSERR_DQUOT=69, /* Disc quota exceeded */ - NFSERR_STALE=70, /* Stale NFS file handle */ - NFSERR_WFLUSH=99 /* write cache flushed */ -}; - -/* - * File types - */ -enum ftype { - NFNON = 0, /* non-file */ - NFREG = 1, /* regular file */ - NFDIR = 2, /* directory */ - NFBLK = 3, /* block special */ - NFCHR = 4, /* character special */ - NFLNK = 5, /* symbolic link */ - NFSOCK = 6, /* unix domain sockets */ - NFBAD = 7, /* unused */ - NFFIFO = 8 /* named pipe */ -}; - -/* - * File access handle - */ -struct nfs_fh { - opaque data[NFS_FHSIZE]; -}; - -/* - * Timeval - */ -struct nfstime { - unsigned seconds; - unsigned useconds; -}; - - -/* - * File attributes - */ -struct fattr { - ftype type; /* file type */ - unsigned mode; /* protection mode bits */ - unsigned nlink; /* # hard links */ - unsigned uid; /* owner user id */ - unsigned gid; /* owner group id */ - unsigned size; /* file size in bytes */ - unsigned blocksize; /* prefered block size */ - unsigned rdev; /* special device # */ - unsigned blocks; /* Kb of disk used by file */ - unsigned fsid; /* device # */ - unsigned fileid; /* inode # */ - nfstime atime; /* time of last access */ - nfstime mtime; /* time of last modification */ - nfstime ctime; /* time of last change */ -}; - -/* - * File attributes which can be set - */ -struct sattr { - unsigned mode; /* protection mode bits */ - unsigned uid; /* owner user id */ - unsigned gid; /* owner group id */ - unsigned size; /* file size in bytes */ - nfstime atime; /* time of last access */ - nfstime mtime; /* time of last modification */ -}; - - -typedef string filename; -typedef string nfspath; - -/* - * Reply status with file attributes - */ -union attrstat switch (nfsstat status) { -case NFS_OK: - fattr attributes; -default: - void; -}; - -struct sattrargs { - nfs_fh file; - sattr attributes; -}; - -/* - * Arguments for directory operations - */ -struct diropargs { - nfs_fh dir; /* directory file handle */ - filename name; /* name (up to NFS_MAXNAMLEN bytes) */ -}; - -struct diropokres { - nfs_fh file; - fattr attributes; -}; - -/* - * Results from directory operation - */ -union diropres switch (nfsstat status) { -case NFS_OK: - diropokres diropres; -default: - void; -}; - -union readlinkres switch (nfsstat status) { -case NFS_OK: - nfspath data; -default: - void; -}; - -/* - * Arguments to remote read - */ -struct readargs { - nfs_fh file; /* handle for file */ - unsigned offset; /* byte offset in file */ - unsigned count; /* immediate read count */ - unsigned totalcount; /* total read count (from this offset)*/ -}; - -/* - * Status OK portion of remote read reply - */ -struct readokres { - fattr attributes; /* attributes, need for pagin*/ - opaque data; -}; - -union readres switch (nfsstat status) { -case NFS_OK: - readokres reply; -default: - void; -}; - -/* - * Arguments to remote write - */ -struct writeargs { - nfs_fh file; /* handle for file */ - unsigned beginoffset; /* beginning byte offset in file */ - unsigned offset; /* current byte offset in file */ - unsigned totalcount; /* total write count (to this offset)*/ - opaque data; -}; - -struct createargs { - diropargs where; - sattr attributes; -}; - -struct renameargs { - diropargs from; - diropargs to; -}; - -struct linkargs { - nfs_fh from; - diropargs to; -}; - -struct symlinkargs { - diropargs from; - nfspath to; - sattr attributes; -}; - - -/* TS, 10/21/2002; converted cookie to struct */ -struct nfscookie { - opaque data[NFS_COOKIESIZE]; -}; - -/* - * Arguments to readdir - */ -struct readdirargs { - nfs_fh dir; /* directory handle */ - nfscookie cookie; - unsigned count; /* number of directory bytes to read */ -}; - -struct entry { - unsigned fileid; - filename name; - nfscookie cookie; - entry *nextentry; -}; - -struct dirlist { - entry *entries; - bool eof; -}; - -union readdirres switch (nfsstat status) { -case NFS_OK: - dirlist reply; -default: - void; -}; - -struct statfsokres { - unsigned tsize; /* preferred transfer size in bytes */ - unsigned bsize; /* fundamental file system block size */ - unsigned blocks; /* total blocks in file system */ - unsigned bfree; /* free blocks in fs */ - unsigned bavail; /* free blocks avail to non-superuser */ -}; - -union statfsres switch (nfsstat status) { -case NFS_OK: - statfsokres reply; -default: - void; -}; - -#ifdef WANT_NFS3 - -/* - * NFSv3 constants and types - */ -const NFS3_FHSIZE = 64; /* maximum size in bytes of a file handle */ -const NFS3_COOKIEVERFSIZE = 8; /* size of a cookie verifier for READDIR */ -const NFS3_CREATEVERFSIZE = 8; /* size of the verifier used for CREATE */ -const NFS3_WRITEVERFSIZE = 8; /* size of the verifier used for WRITE */ - -typedef unsigned hyper uint64; -typedef hyper int64; -typedef unsigned long uint32; -typedef long int32; -typedef string filename3<>; -typedef string nfspath3<>; -typedef uint64 fileid3; -typedef uint64 cookie3; -typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE]; -typedef opaque createverf3[NFS3_CREATEVERFSIZE]; -typedef opaque writeverf3[NFS3_WRITEVERFSIZE]; -typedef uint32 uid3; -typedef uint32 gid3; -typedef uint64 size3; -typedef uint64 offset3; -typedef uint32 mode3; -typedef uint32 count3; - -/* - * Error status (v3) - */ -enum nfsstat3 { - NFS3_OK = 0, - NFS3ERR_PERM = 1, - NFS3ERR_NOENT = 2, - NFS3ERR_IO = 5, - NFS3ERR_NXIO = 6, - NFS3ERR_ACCES = 13, - NFS3ERR_EXIST = 17, - NFS3ERR_XDEV = 18, - NFS3ERR_NODEV = 19, - NFS3ERR_NOTDIR = 20, - NFS3ERR_ISDIR = 21, - NFS3ERR_INVAL = 22, - NFS3ERR_FBIG = 27, - NFS3ERR_NOSPC = 28, - NFS3ERR_ROFS = 30, - NFS3ERR_MLINK = 31, - NFS3ERR_NAMETOOLONG = 63, - NFS3ERR_NOTEMPTY = 66, - NFS3ERR_DQUOT = 69, - NFS3ERR_STALE = 70, - NFS3ERR_REMOTE = 71, - NFS3ERR_BADHANDLE = 10001, - NFS3ERR_NOT_SYNC = 10002, - NFS3ERR_BAD_COOKIE = 10003, - NFS3ERR_NOTSUPP = 10004, - NFS3ERR_TOOSMALL = 10005, - NFS3ERR_SERVERFAULT = 10006, - NFS3ERR_BADTYPE = 10007, - NFS3ERR_JUKEBOX = 10008 -}; - -/* - * File types (v3) - */ -enum ftype3 { - NF3REG = 1, /* regular file */ - NF3DIR = 2, /* directory */ - NF3BLK = 3, /* block special */ - NF3CHR = 4, /* character special */ - NF3LNK = 5, /* symbolic link */ - NF3SOCK = 6, /* unix domain sockets */ - NF3FIFO = 7 /* named pipe */ -}; - -struct specdata3 { - uint32 specdata1; - uint32 specdata2; -}; - -/* - * File access handle (v3) - */ -struct nfs_fh3 { - opaque data; -}; - -/* - * Timeval (v3) - */ -struct nfstime3 { - uint32 seconds; - uint32 nseconds; -}; - - -/* - * File attributes (v3) - */ -struct fattr3 { - ftype3 type; /* file type */ - mode3 mode; /* protection mode bits */ - uint32 nlink; /* # hard links */ - uid3 uid; /* owner user id */ - gid3 gid; /* owner group id */ - size3 size; /* file size in bytes */ - size3 used; /* prefered block size */ - specdata3 rdev; /* special device # */ - uint64 fsid; /* device # */ - fileid3 fileid; /* inode # */ - nfstime3 atime; /* time of last access */ - nfstime3 mtime; /* time of last modification */ - nfstime3 ctime; /* time of last change */ -}; - -union post_op_attr switch (bool attributes_follow) { -case TRUE: - fattr3 attributes; -case FALSE: - void; -}; - -struct wcc_attr { - size3 size; - nfstime3 mtime; - nfstime3 ctime; -}; - -union pre_op_attr switch (bool attributes_follow) { -case TRUE: - wcc_attr attributes; -case FALSE: - void; -}; - -struct wcc_data { - pre_op_attr before; - post_op_attr after; -}; - -union post_op_fh3 switch (bool handle_follows) { -case TRUE: - nfs_fh3 handle; -case FALSE: - void; -}; - -/* - * File attributes which can be set (v3) - */ -enum time_how { - DONT_CHANGE = 0, - SET_TO_SERVER_TIME = 1, - SET_TO_CLIENT_TIME = 2 -}; - -union set_mode3 switch (bool set_it) { -case TRUE: - mode3 mode; -default: - void; -}; - -union set_uid3 switch (bool set_it) { -case TRUE: - uid3 uid; -default: - void; -}; - -union set_gid3 switch (bool set_it) { -case TRUE: - gid3 gid; -default: - void; -}; - -union set_size3 switch (bool set_it) { -case TRUE: - size3 size; -default: - void; -}; - -union set_atime switch (time_how set_it) { -case SET_TO_CLIENT_TIME: - nfstime3 atime; -default: - void; -}; - -union set_mtime switch (time_how set_it) { -case SET_TO_CLIENT_TIME: - nfstime3 mtime; -default: - void; -}; - -struct sattr3 { - set_mode3 mode; - set_uid3 uid; - set_gid3 gid; - set_size3 size; - set_atime atime; - set_mtime mtime; -}; - -/* - * Arguments for directory operations (v3) - */ -struct diropargs3 { - nfs_fh3 dir; /* directory file handle */ - filename3 name; /* name (up to NFS_MAXNAMLEN bytes) */ -}; - -/* - * Arguments to getattr (v3). - */ -struct GETATTR3args { - nfs_fh3 object; -}; - -struct GETATTR3resok { - fattr3 obj_attributes; -}; - -union GETATTR3res switch (nfsstat3 status) { -case NFS3_OK: - GETATTR3resok resok; -default: - void; -}; - -/* - * Arguments to setattr (v3). - */ -union sattrguard3 switch (bool check) { -case TRUE: - nfstime3 obj_ctime; -case FALSE: - void; -}; - -struct SETATTR3args { - nfs_fh3 object; - sattr3 new_attributes; - sattrguard3 guard; -}; - -struct SETATTR3resok { - wcc_data obj_wcc; -}; - -struct SETATTR3resfail { - wcc_data obj_wcc; -}; - -union SETATTR3res switch (nfsstat3 status) { -case NFS3_OK: - SETATTR3resok resok; -default: - SETATTR3resfail resfail; -}; - -/* - * Arguments to lookup (v3). - */ -struct LOOKUP3args { - diropargs3 what; -}; - -struct LOOKUP3resok { - nfs_fh3 object; - post_op_attr obj_attributes; - post_op_attr dir_attributes; -}; - -struct LOOKUP3resfail { - post_op_attr dir_attributes; -}; - -union LOOKUP3res switch (nfsstat3 status) { -case NFS3_OK: - LOOKUP3resok resok; -default: - LOOKUP3resfail resfail; -}; - -/* - * Arguments to access (v3). - */ -const ACCESS3_READ = 0x0001; -const ACCESS3_LOOKUP = 0x0002; -const ACCESS3_MODIFY = 0x0004; -const ACCESS3_EXTEND = 0x0008; -const ACCESS3_DELETE = 0x0010; -const ACCESS3_EXECUTE = 0x0020; - -struct ACCESS3args { - nfs_fh3 object; - uint32 access; -}; - -struct ACCESS3resok { - post_op_attr obj_attributes; - uint32 access; -}; - -struct ACCESS3resfail { - post_op_attr obj_attributes; -}; - -union ACCESS3res switch (nfsstat3 status) { -case NFS3_OK: - ACCESS3resok resok; -default: - ACCESS3resfail resfail; -}; - -/* - * Arguments to readlink (v3). - */ -struct READLINK3args { - nfs_fh3 symlink; -}; - -struct READLINK3resok { - post_op_attr symlink_attributes; - nfspath3 data; -}; - -struct READLINK3resfail { - post_op_attr symlink_attributes; -}; - -union READLINK3res switch (nfsstat3 status) { -case NFS3_OK: - READLINK3resok resok; -default: - READLINK3resfail resfail; -}; - -/* - * Arguments to read (v3). - */ -struct READ3args { - nfs_fh3 file; - offset3 offset; - count3 count; -}; - -struct READ3resok { - post_op_attr file_attributes; - count3 count; - bool eof; - opaque data<>; -}; - -struct READ3resfail { - post_op_attr file_attributes; -}; - -/* XXX: solaris 2.6 uses ``nfsstat'' here */ -union READ3res switch (nfsstat3 status) { -case NFS3_OK: - READ3resok resok; -default: - READ3resfail resfail; -}; - -/* - * Arguments to write (v3). - */ -enum stable_how { - UNSTABLE = 0, - DATA_SYNC = 1, - FILE_SYNC = 2 -}; - -struct WRITE3args { - nfs_fh3 file; - offset3 offset; - count3 count; - stable_how stable; - opaque data<>; -}; - -struct WRITE3resok { - wcc_data file_wcc; - count3 count; - stable_how committed; - writeverf3 verf; -}; - -struct WRITE3resfail { - wcc_data file_wcc; -}; - -union WRITE3res switch (nfsstat3 status) { -case NFS3_OK: - WRITE3resok resok; -default: - WRITE3resfail resfail; -}; - -/* - * Arguments to create (v3). - */ -enum createmode3 { - UNCHECKED = 0, - GUARDED = 1, - EXCLUSIVE = 2 -}; - -union createhow3 switch (createmode3 mode) { -case UNCHECKED: -case GUARDED: - sattr3 obj_attributes; -case EXCLUSIVE: - createverf3 verf; -}; - -struct CREATE3args { - diropargs3 where; - createhow3 how; -}; - -struct CREATE3resok { - post_op_fh3 obj; - post_op_attr obj_attributes; - wcc_data dir_wcc; -}; - -struct CREATE3resfail { - wcc_data dir_wcc; -}; - -union CREATE3res switch (nfsstat3 status) { -case NFS3_OK: - CREATE3resok resok; -default: - CREATE3resfail resfail; -}; - -/* - * Arguments to mkdir (v3). - */ -struct MKDIR3args { - diropargs3 where; - sattr3 attributes; -}; - -struct MKDIR3resok { - post_op_fh3 obj; - post_op_attr obj_attributes; - wcc_data dir_wcc; -}; - -struct MKDIR3resfail { - wcc_data dir_wcc; -}; - -union MKDIR3res switch (nfsstat3 status) { -case NFS3_OK: - MKDIR3resok resok; -default: - MKDIR3resfail resfail; -}; - -/* - * Arguments to symlink (v3). - */ -struct symlinkdata3 { - sattr3 symlink_attributes; - nfspath3 symlink_data; -}; - -struct SYMLINK3args { - diropargs3 where; - symlinkdata3 symlink; -}; - -struct SYMLINK3resok { - post_op_fh3 obj; - post_op_attr obj_attributes; - wcc_data dir_wcc; -}; - -struct SYMLINK3resfail { - wcc_data dir_wcc; -}; - -union SYMLINK3res switch (nfsstat3 status) { -case NFS3_OK: - SYMLINK3resok resok; -default: - SYMLINK3resfail resfail; -}; - -/* - * Arguments to mknod (v3). - */ -struct devicedata3 { - sattr3 dev_attributes; - specdata3 spec; -}; - -union mknoddata3 switch (ftype3 type) { -case NF3CHR: -case NF3BLK: - devicedata3 device; -case NF3SOCK: -case NF3FIFO: - sattr3 pipe_attributes; -default: - void; -}; - -struct MKNOD3args { - diropargs3 where; - mknoddata3 what; -}; - -struct MKNOD3resok { - post_op_fh3 obj; - post_op_attr obj_attributes; - wcc_data dir_wcc; -}; - -struct MKNOD3resfail { - wcc_data dir_wcc; -}; - -union MKNOD3res switch (nfsstat3 status) { -case NFS3_OK: - MKNOD3resok resok; -default: - MKNOD3resfail resfail; -}; - -/* - * Arguments to remove (v3). - */ -struct REMOVE3args { - diropargs3 object; -}; - -struct REMOVE3resok { - wcc_data dir_wcc; -}; - -struct REMOVE3resfail { - wcc_data dir_wcc; -}; - -union REMOVE3res switch (nfsstat3 status) { -case NFS3_OK: - REMOVE3resok resok; -default: - REMOVE3resfail resfail; -}; - -/* - * Arguments to rmdir (v3). - */ -struct RMDIR3args { - diropargs3 object; -}; - -struct RMDIR3resok { - wcc_data dir_wcc; -}; - -struct RMDIR3resfail { - wcc_data dir_wcc; -}; - -union RMDIR3res switch (nfsstat3 status) { -case NFS3_OK: - RMDIR3resok resok; -default: - RMDIR3resfail resfail; -}; - -/* - * Arguments to rename (v3). - */ -struct RENAME3args { - diropargs3 from; - diropargs3 to; -}; - -struct RENAME3resok { - wcc_data fromdir_wcc; - wcc_data todir_wcc; -}; - -struct RENAME3resfail { - wcc_data fromdir_wcc; - wcc_data todir_wcc; -}; - -union RENAME3res switch (nfsstat3 status) { -case NFS3_OK: - RENAME3resok resok; -default: - RENAME3resfail resfail; -}; - -/* - * Arguments to link (v3). - */ -struct LINK3args { - nfs_fh3 file; - diropargs3 link; -}; - -struct LINK3resok { - post_op_attr file_attributes; - wcc_data linkdir_wcc; -}; - -struct LINK3resfail { - post_op_attr file_attributes; - wcc_data linkdir_wcc; -}; - -union LINK3res switch (nfsstat3 status) { -case NFS3_OK: - LINK3resok resok; -default: - LINK3resfail resfail; -}; - -/* - * Arguments to readdir (v3). - */ -struct READDIR3args { - nfs_fh3 dir; - cookie3 cookie; - cookieverf3 cookieverf; - count3 count; -}; - -struct entry3 { - fileid3 fileid; - filename3 name; - cookie3 cookie; - entry3 *nextentry; -}; - -struct dirlist3 { - entry3 *entries; - bool eof; -}; - -struct READDIR3resok { - post_op_attr dir_attributes; - cookieverf3 cookieverf; - dirlist3 reply; -}; - -struct READDIR3resfail { - post_op_attr dir_attributes; -}; - -union READDIR3res switch (nfsstat3 status) { -case NFS3_OK: - READDIR3resok resok; -default: - READDIR3resfail resfail; -}; - -/* - * Arguments to readdirplus (v3). - */ -struct READDIRPLUS3args { - nfs_fh3 dir; - cookie3 cookie; - cookieverf3 cookieverf; - count3 dircount; - count3 maxcount; -}; - -struct entryplus3 { - fileid3 fileid; - filename3 name; - cookie3 cookie; - post_op_attr name_attributes; - post_op_fh3 name_handle; - entryplus3 *nextentry; -}; - -struct dirlistplus3 { - entryplus3 *entries; - bool eof; -}; - -struct READDIRPLUS3resok { - post_op_attr dir_attributes; - cookieverf3 cookieverf; - dirlistplus3 reply; -}; - -struct READDIRPLUS3resfail { - post_op_attr dir_attributes; -}; - -union READDIRPLUS3res switch (nfsstat3 status) { -case NFS3_OK: - READDIRPLUS3resok resok; -default: - READDIRPLUS3resfail resfail; -}; - -/* - * Arguments to fsstat (v3). - */ -struct FSSTAT3args { - nfs_fh3 fsroot; -}; - -struct FSSTAT3resok { - post_op_attr obj_attributes; - size3 tbytes; - size3 fbytes; - size3 abytes; - size3 tfiles; - size3 ffiles; - size3 afiles; - uint32 invarsec; -}; - -struct FSSTAT3resfail { - post_op_attr obj_attributes; -}; - -union FSSTAT3res switch (nfsstat3 status) { -case NFS3_OK: - FSSTAT3resok resok; -default: - FSSTAT3resfail resfail; -}; - -/* - * Arguments to fsinfo (v3). - */ -const FSF3_LINK = 0x0001; -const FSF3_SYMLINK = 0x0002; -const FSF3_HOMOGENEOUS = 0x0008; -const FSF3_CANSETTIME = 0x0010; - -struct FSINFO3args { - nfs_fh3 fsroot; -}; - -struct FSINFO3resok { - post_op_attr obj_attributes; - uint32 rtmax; - uint32 rtpref; - uint32 rtmult; - uint32 wtmax; - uint32 wtpref; - uint32 wtmult; - uint32 dtpref; - size3 maxfilesize; - nfstime3 time_delta; - uint32 properties; -}; - -struct FSINFO3resfail { - post_op_attr obj_attributes; -}; - -union FSINFO3res switch (nfsstat3 status) { -case NFS3_OK: - FSINFO3resok resok; -default: - FSINFO3resfail resfail; -}; - -/* - * Arguments to pathconf (v3). - */ -struct PATHCONF3args { - nfs_fh3 object; -}; - -struct PATHCONF3resok { - post_op_attr obj_attributes; - uint32 linkmax; - uint32 name_max; - bool no_trunc; - bool chown_restricted; - bool case_insensitive; - bool case_preserving; -}; - -struct PATHCONF3resfail { - post_op_attr obj_attributes; -}; - -union PATHCONF3res switch (nfsstat3 status) { -case NFS3_OK: - PATHCONF3resok resok; -default: - PATHCONF3resfail resfail; -}; - -/* - * Arguments to commit (v3). - */ -struct COMMIT3args { - nfs_fh3 file; - offset3 offset; - count3 count; -}; - -struct COMMIT3resok { - wcc_data file_wcc; - writeverf3 verf; -}; - -struct COMMIT3resfail { - wcc_data file_wcc; -}; - -union COMMIT3res switch (nfsstat3 status) { -case NFS3_OK: - COMMIT3resok resok; -default: - COMMIT3resfail resfail; -}; - -#endif /* WANT_NFS3 */ - -/* - * Remote file service routines - */ -program NFS_PROGRAM { - version NFS_VERSION { - void - NFSPROC_NULL(void) = 0; - - attrstat - NFSPROC_GETATTR(nfs_fh) = 1; - - attrstat - NFSPROC_SETATTR(sattrargs) = 2; - - void - NFSPROC_ROOT(void) = 3; - - diropres - NFSPROC_LOOKUP(diropargs) = 4; - - readlinkres - NFSPROC_READLINK(nfs_fh) = 5; - - readres - NFSPROC_READ(readargs) = 6; - - void - NFSPROC_WRITECACHE(void) = 7; - - attrstat - NFSPROC_WRITE(writeargs) = 8; - - diropres - NFSPROC_CREATE(createargs) = 9; - - nfsstat - NFSPROC_REMOVE(diropargs) = 10; - - nfsstat - NFSPROC_RENAME(renameargs) = 11; - - nfsstat - NFSPROC_LINK(linkargs) = 12; - - nfsstat - NFSPROC_SYMLINK(symlinkargs) = 13; - - diropres - NFSPROC_MKDIR(createargs) = 14; - - nfsstat - NFSPROC_RMDIR(diropargs) = 15; - - readdirres - NFSPROC_READDIR(readdirargs) = 16; - - statfsres - NFSPROC_STATFS(nfs_fh) = 17; - } = 2; -} = 100003; -#ifdef WANT_NFS3 -program NFS3_PROGRAM { - version NFS_V3 { - void - NFSPROC3_NULL(void) = 0; - - GETATTR3res - NFSPROC3_GETATTR(GETATTR3args) = 1; - - SETATTR3res - NFSPROC3_SETATTR(SETATTR3args) = 2; - - LOOKUP3res - NFSPROC3_LOOKUP(LOOKUP3args) = 3; - - ACCESS3res - NFSPROC3_ACCESS(ACCESS3args) = 4; - - READLINK3res - NFSPROC3_READLINK(READLINK3args) = 5; - - READ3res - NFSPROC3_READ(READ3args) = 6; - - WRITE3res - NFSPROC3_WRITE(WRITE3args) = 7; - - CREATE3res - NFSPROC3_CREATE(CREATE3args) = 8; - - MKDIR3res - NFSPROC3_MKDIR(MKDIR3args) = 9; - - SYMLINK3res - NFSPROC3_SYMLINK(SYMLINK3args) = 10; - - MKNOD3res - NFSPROC3_MKNOD(MKNOD3args) = 11; - - REMOVE3res - NFSPROC3_REMOVE(REMOVE3args) = 12; - - RMDIR3res - NFSPROC3_RMDIR(RMDIR3args) = 13; - - RENAME3res - NFSPROC3_RENAME(RENAME3args) = 14; - - LINK3res - NFSPROC3_LINK(LINK3args) = 15; - - READDIR3res - NFSPROC3_READDIR(READDIR3args) = 16; - - READDIRPLUS3res - NFSPROC3_READDIRPLUS(READDIRPLUS3args) = 17; - - FSSTAT3res - NFSPROC3_FSSTAT(FSSTAT3args) = 18; - - FSINFO3res - NFSPROC3_FSINFO(FSINFO3args) = 19; - - PATHCONF3res - NFSPROC3_PATHCONF(PATHCONF3args) = 20; - - COMMIT3res - NFSPROC3_COMMIT(COMMIT3args) = 21; - } = 3; -} = 100003; -#endif - diff --git a/cpukit/libfs/src/nfsclient/proto/nfs_prot_xdr.c b/cpukit/libfs/src/nfsclient/proto/nfs_prot_xdr.c deleted file mode 100644 index 8d541c9625..0000000000 --- a/cpukit/libfs/src/nfsclient/proto/nfs_prot_xdr.c +++ /dev/null @@ -1,629 +0,0 @@ -/** - * @file - * - * @ingroup RTEMSFileSystemNFSProt NFS Prot - * - * @brief NFS Prot XDR - */ - -/* - * 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";*/ - #if !defined(__rtems__) - static char rcsid[] = "$Id$"; - #endif -#endif /* not lint */ - -bool_t -xdr_nfsstat (XDR *xdrs, nfsstat *objp) -{ - if (!xdr_enum (xdrs, (enum_t *) objp)) - return FALSE; - return TRUE; -} - -bool_t -xdr_ftype (XDR *xdrs, ftype *objp) -{ - if (!xdr_enum (xdrs, (enum_t *) objp)) - return FALSE; - return TRUE; -} - -bool_t -xdr_nfs_fh (XDR *xdrs, nfs_fh *objp) -{ - if (!xdr_opaque (xdrs, objp->data, NFS_FHSIZE)) - return FALSE; - return TRUE; -} - -bool_t -xdr_nfstime (XDR *xdrs, nfstime *objp) -{ - 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) -{ - if (!xdr_string (xdrs, objp, NFS_MAXNAMLEN)) - return FALSE; - return TRUE; -} - -bool_t -xdr_nfspath (XDR *xdrs, nfspath *objp) -{ - if (!xdr_string (xdrs, objp, NFS_MAXPATHLEN)) - return FALSE; - return TRUE; -} - -bool_t -xdr_attrstat (XDR *xdrs, attrstat *objp) -{ - 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) -{ - 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) -{ - 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) -{ - 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) -{ - 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) -{ - 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) -{ - 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) -{ - 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) -{ - 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) -{ - 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) -{ - 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) -{ - 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) -{ - 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) -{ - if (!xdr_opaque (xdrs, objp->data, NFS_COOKIESIZE)) - return FALSE; - return TRUE; -} - -bool_t -xdr_readdirargs (XDR *xdrs, readdirargs *objp) -{ - 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) -{ - 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) -{ - 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) -{ - 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) -{ - if (!xdr_nfsstat (xdrs, &objp->status)) - return FALSE; - switch (objp->status) { - case NFS_OK: - if (!xdr_statfsokres (xdrs, &objp->statfsres_u.reply)) - return FALSE; - break; - default: - break; - } - return TRUE; -} diff --git a/cpukit/libfs/src/nfsclient/rfc1094.txt b/cpukit/libfs/src/nfsclient/rfc1094.txt deleted file mode 100644 index 7ad0f737ef..0000000000 --- a/cpukit/libfs/src/nfsclient/rfc1094.txt +++ /dev/null @@ -1,1258 +0,0 @@ - - RFC 1094 (RFC1094) - -Internet RFC/STD/FYI/BCP Archives - - - RFC 1094 - NFS: Network File System Protocol specification - ------------------------------------------------------------------------- - - -Network Working Group Sun Microsystems, Inc. -Request for Comments: 1094 March 1989 - - NFS: Network File System Protocol Specification - -STATUS OF THIS MEMO - - This RFC describes a protocol that Sun Microsystems, Inc., and others - are using. A new version of the protocol is under development, but - others may benefit from the descriptions of the current protocol, and - discussion of some of the design issues. Distribution of this memo - is unlimited. - -1. INTRODUCTION - - The Sun Network Filesystem (NFS) protocol provides transparent remote - access to shared files across networks. The NFS protocol is designed - to be portable across different machines, operating systems, network - architectures, and transport protocols. This portability is achieved - through the use of Remote Procedure Call (RPC) primitives built on - top of an eXternal Data Representation (XDR). Implementations - already exist for a variety of machines, from personal computers to - supercomputers. - - The supporting mount protocol allows the server to hand out remote - access privileges to a restricted set of clients. It performs the - operating system-specific functions that allow, for example, to - attach remote directory trees to some local file system. - -1.1. Remote Procedure Call - - Sun's Remote Procedure Call specification provides a procedure- - oriented interface to remote services. Each server supplies a - "program" that is a set of procedures. NFS is one such program. The - combination of host address, program number, and procedure number - specifies one remote procedure. A goal of NFS was to not require any - specific level of reliability from its lower levels, so it could - potentially be used on many underlying transport protocols, or even - another remote procedure call implementation. For ease of - discussion, the rest of this document will assume NFS is implemented - on top of Sun RPC, described in RFC 1057 , "RPC: Remote Procedure - Call Protocol Specification". - -1.2. External Data Representation - - The eXternal Data Representation (XDR) standard provides a common way - of representing a set of data types over a network. The NFS Protocol - - Specification is written using the RPC data description language. - For more information, see RFC 1014 , "XDR: External Data - Representation Standard". Although automated RPC/XDR compilers exist - to generate server and client "stubs", NFS does not require their - use. Any software that provides equivalent functionality can be - used, and if the encoding is exactly the same it can interoperate - with other implementations of NFS. - -1.3. Stateless Servers - - The NFS protocol was intended to be as stateless as possible. That - is, a server should not need to maintain any protocol state - information about any of its clients in order to function correctly. - Stateless servers have a distinct advantage over stateful servers in - the event of a failure. With stateless servers, a client need only - retry a request until the server responds; it does not even need to - know that the server has crashed, or the network temporarily went - down. The client of a stateful server, on the other hand, needs to - either detect a server failure and rebuild the server's state when it - comes back up, or cause client operations to fail. - - This may not sound like an important issue, but it affects the - protocol in some unexpected ways. We feel that it may be worth a bit - of extra complexity in the protocol to be able to write very simple - servers that do not require fancy crash recovery. Note that even if - a so-called "reliable" transport protocol such as TCP is used, the - client must still be able to handle interruptions of service by re- - opening connections when they time out. Thus, a stateless protocol - may actually simplify the implementation. - - On the other hand, NFS deals with objects such as files and - directories that inherently have state -- what good would a file be - if it did not keep its contents intact? The goal was to not - introduce any extra state in the protocol itself. Inherently - stateful operations such as file or record locking, and remote - execution, were implemented as separate services, not described in - this document. - - The basic way to simplify recovery was to make operations as - "idempotent" as possible (so that they can potentially be repeated). - Some operations in this version of the protocol did not attain this - goal; luckily most of the operations (such as Read and Write) are - idempotent. Also, most server failures occur between operations, not - between the receipt of an operation and the response. Finally, - although actual server failures may be rare, in complex networks, - failures of any network, router, or bridge may be indistinguishable - from a server failure. - -2. NFS PROTOCOL DEFINITION - - Servers change over time, and so can the protocol that they use. RPC - provides a version number with each RPC request. This RFC describes - version two of the NFS protocol. Even in the second version, there - are a few obsolete procedures and parameters, which will be removed - in later versions. An RFC for version three of the NFS protocol is - currently under preparation. - -2.1. File System Model - - NFS assumes a file system that is hierarchical, with directories as - all but the bottom level of files. Each entry in a directory (file, - directory, device, etc.) has a string name. Different operating - systems may have restrictions on the depth of the tree or the names - used, as well as using different syntax to represent the "pathname", - which is the concatenation of all the "components" (directory and - file names) in the name. A "file system" is a tree on a single - server (usually a single disk or physical partition) with a specified - "root". Some operating systems provide a "mount" operation to make - all file systems appear as a single tree, while others maintain a - "forest" of file systems. Files are unstructured streams of - uninterpreted bytes. Version 3 of NFS uses slightly more general - file system model. - - NFS looks up one component of a pathname at a time. It may not be - obvious why it does not just take the whole pathname, traipse down - the directories, and return a file handle when it is done. There are - several good reasons not to do this. First, pathnames need - separators between the directory components, and different operating - systems use different separators. We could define a Network Standard - Pathname Representation, but then every pathname would have to be - parsed and converted at each end. Other issues are discussed in - section 3, NFS Implementation Issues. - - Although files and directories are similar objects in many ways, - different procedures are used to read directories and files. This - provides a network standard format for representing directories. The - same argument as above could have been used to justify a procedure - that returns only one directory entry per call. The problem is - efficiency. Directories can contain many entries, and a remote call - to return each would be just too slow. - -2.2. Server Procedures - - The protocol definition is given as a set of procedures with - arguments and results defined using the RPC language (XDR language - extended with program, version, and procedure declarations). A brief - - description of the function of each procedure should provide enough - information to allow implementation. Section 2.3 describes the basic - data types in more detail. - - All of the procedures in the NFS protocol are assumed to be - synchronous. When a procedure returns to the client, the client can - assume that the operation has completed and any data associated with - the request is now on stable storage. For example, a client WRITE - request may cause the server to update data blocks, filesystem - information blocks (such as indirect blocks), and file attribute - information (size and modify times). When the WRITE returns to the - client, it can assume that the write is safe, even in case of a - server crash, and it can discard the data written. This is a very - important part of the statelessness of the server. If the server - waited to flush data from remote requests, the client would have to - save those requests so that it could resend them in case of a server - crash. - - /* - * Remote file service routines - */ - program NFS_PROGRAM { - version NFS_VERSION { - void - NFSPROC_NULL(void) = 0; - - attrstat - NFSPROC_GETATTR(fhandle) = 1; - - attrstat - NFSPROC_SETATTR(sattrargs) = 2; - - void - NFSPROC_ROOT(void) = 3; - - diropres - NFSPROC_LOOKUP(diropargs) = 4; - - readlinkres - NFSPROC_READLINK(fhandle) = 5; - - readres - NFSPROC_READ(readargs) = 6; - - void - NFSPROC_WRITECACHE(void) = 7; - - attrstat - NFSPROC_WRITE(writeargs) = 8; - - diropres - NFSPROC_CREATE(createargs) = 9; - - stat - NFSPROC_REMOVE(diropargs) = 10; - - stat - NFSPROC_RENAME(renameargs) = 11; - - stat - NFSPROC_LINK(linkargs) = 12; - - stat - NFSPROC_SYMLINK(symlinkargs) = 13; - - diropres - NFSPROC_MKDIR(createargs) = 14; - - stat - NFSPROC_RMDIR(diropargs) = 15; - - readdirres - NFSPROC_READDIR(readdirargs) = 16; - - statfsres - NFSPROC_STATFS(fhandle) = 17; - } = 2; - } = 100003; - -2.2.1. Do Nothing - - void - NFSPROC_NULL(void) = 0; - - This procedure does no work. It is made available in all RPC - services to allow server response testing and timing. - -2.2.2. Get File Attributes - - attrstat - NFSPROC_GETATTR (fhandle) = 1; - - If the reply status is NFS_OK, then the reply attributes contains the - attributes for the file given by the input fhandle. - -2.2.3. Set File Attributes - - struct sattrargs { - fhandle file; - sattr attributes; - }; - - attrstat - NFSPROC_SETATTR (sattrargs) = 2; - - The "attributes" argument contains fields which are either -1 or are - the new value for the attributes of "file". If the reply status is - NFS_OK, then the reply attributes have the attributes of the file - after the "SETATTR" operation has completed. - - Notes: The use of -1 to indicate an unused field in "attributes" is - changed in the next version of the protocol. - -2.2.4. Get Filesystem Root - - void - NFSPROC_ROOT(void) = 3; - - Obsolete. This procedure is no longer used because finding the root - file handle of a filesystem requires moving pathnames between client - and server. To do this right, we would have to define a network - standard representation of pathnames. Instead, the function of - looking up the root file handle is done by the MNTPROC_MNT procedure. - (See Appendix A, "Mount Protocol Definition", for details). - -2.2.5. Look Up File Name - - diropres - NFSPROC_LOOKUP(diropargs) = 4; - - If the reply "status" is NFS_OK, then the reply "file" and reply - "attributes" are the file handle and attributes for the file "name" - in the directory given by "dir" in the argument. - -2.2.6. Read From Symbolic Link - - union readlinkres switch (stat status) { - case NFS_OK: - path data; - default: - void; - }; - - readlinkres - NFSPROC_READLINK(fhandle) = 5; - - If "status" has the value NFS_OK, then the reply "data" is the data - in the symbolic link given by the file referred to by the fhandle - argument. - - Notes: Since NFS always parses pathnames on the client, the pathname - in a symbolic link may mean something different (or be meaningless) - on a different client or on the server if a different pathname syntax - is used. - -2.2.7. Read From File - - struct readargs { - fhandle file; - unsigned offset; - unsigned count; - unsigned totalcount; - }; - - union readres switch (stat status) { - case NFS_OK: - fattr attributes; - nfsdata data; - default: - void; - }; - - readres - NFSPROC_READ(readargs) = 6; - - Returns up to "count" bytes of "data" from the file given by "file", - starting at "offset" bytes from the beginning of the file. The first - byte of the file is at offset zero. The file attributes after the - read takes place are returned in "attributes". - - Notes: The argument "totalcount" is unused, and is removed in the - next protocol revision. - -2.2.8. Write to Cache - - void - NFSPROC_WRITECACHE(void) = 7; - - To be used in the next protocol revision. - -2.2.9. Write to File - - struct writeargs { - fhandle file; - unsigned beginoffset; - unsigned offset; - unsigned totalcount; - nfsdata data; - }; - - attrstat - NFSPROC_WRITE(writeargs) = 8; - - Writes "data" beginning "offset" bytes from the beginning of "file". - The first byte of the file is at offset zero. If the reply "status" - is NFS_OK, then the reply "attributes" contains the attributes of the - file after the write has completed. The write operation is atomic. - Data from this "WRITE" will not be mixed with data from another - client's "WRITE". - - Notes: The arguments "beginoffset" and "totalcount" are ignored and - are removed in the next protocol revision. - -2.2.10. Create File - - struct createargs { - diropargs where; - sattr attributes; - }; - - diropres - NFSPROC_CREATE(createargs) = 9; - - The file "name" is created in the directory given by "dir". The - initial attributes of the new file are given by "attributes". A - reply "status" of NFS_OK indicates that the file was created, and - reply "file" and reply "attributes" are its file handle and - attributes. Any other reply "status" means that the operation failed - and no file was created. - - Notes: This routine should pass an exclusive create flag, meaning - "create the file only if it is not already there". - -2.2.11. Remove File - - stat - NFSPROC_REMOVE(diropargs) = 10; - - The file "name" is removed from the directory given by "dir". A - reply of NFS_OK means the directory entry was removed. - - Notes: possibly non-idempotent operation. - -2.2.12. Rename File - - struct renameargs { - diropargs from; - diropargs to; - }; - - stat - NFSPROC_RENAME(renameargs) = 11; - - The existing file "from.name" in the directory given by "from.dir" is - renamed to "to.name" in the directory given by "to.dir". If the - reply is NFS_OK, the file was renamed. The RENAME operation is - atomic on the server; it cannot be interrupted in the middle. - - Notes: possibly non-idempotent operation. - -2.2.13. Create Link to File - - Procedure 12, Version 2. - - struct linkargs { - fhandle from; - diropargs to; - }; - - stat - NFSPROC_LINK(linkargs) = 12; - - Creates the file "to.name" in the directory given by "to.dir", which - is a hard link to the existing file given by "from". If the return - value is NFS_OK, a link was created. Any other return value - indicates an error, and the link was not created. - - A hard link should have the property that changes to either of the - linked files are reflected in both files. When a hard link is made - to a file, the attributes for the file should have a value for - "nlink" that is one greater than the value before the link. - - Notes: possibly non-idempotent operation. - -2.2.14. Create Symbolic Link - - struct symlinkargs { - diropargs from; - path to; - sattr attributes; - }; - - stat - NFSPROC_SYMLINK(symlinkargs) = 13; - - Creates the file "from.name" with ftype NFLNK in the directory given - by "from.dir". The new file contains the pathname "to" and has - initial attributes given by "attributes". If the return value is - NFS_OK, a link was created. Any other return value indicates an - error, and the link was not created. - - A symbolic link is a pointer to another file. The name given in "to" - is not interpreted by the server, only stored in the newly created - file. When the client references a file that is a symbolic link, the - contents of the symbolic link are normally transparently - reinterpreted as a pathname to substitute. A READLINK operation - returns the data to the client for interpretation. - - Notes: On UNIX servers the attributes are never used, since symbolic - links always have mode 0777. - -2.2.15. Create Directory - - diropres - NFSPROC_MKDIR (createargs) = 14; - - The new directory "where.name" is created in the directory given by - "where.dir". The initial attributes of the new directory are given - by "attributes". A reply "status" of NFS_OK indicates that the new - directory was created, and reply "file" and reply "attributes" are - its file handle and attributes. Any other reply "status" means that - the operation failed and no directory was created. - - Notes: possibly non-idempotent operation. - -2.2.16. Remove Directory - - stat - NFSPROC_RMDIR(diropargs) = 15; - - The existing empty directory "name" in the directory given by "dir" - is removed. If the reply is NFS_OK, the directory was removed. - - Notes: possibly non-idempotent operation. - -2.2.17. Read From Directory - - struct readdirargs { - fhandle dir; - nfscookie cookie; - unsigned count; - }; - - struct entry { - unsigned fileid; - filename name; - nfscookie cookie; - entry *nextentry; - }; - - union readdirres switch (stat status) { - case NFS_OK: - struct { - entry *entries; - bool eof; - } readdirok; - default: - void; - }; - - readdirres - NFSPROC_READDIR (readdirargs) = 16; - - Returns a variable number of directory entries, with a total size of - up to "count" bytes, from the directory given by "dir". If the - returned value of "status" is NFS_OK, then it is followed by a - variable number of "entry"s. Each "entry" contains a "fileid" which - consists of a unique number to identify the file within a filesystem, - the "name" of the file, and a "cookie" which is an opaque pointer to - the next entry in the directory. The cookie is used in the next - READDIR call to get more entries starting at a given point in the - directory. The special cookie zero (all bits zero) can be used to - get the entries starting at the beginning of the directory. The - "fileid" field should be the same number as the "fileid" in the the - attributes of the file. (See section "2.3.5. fattr" under "Basic - Data Types".) The "eof" flag has a value of TRUE if there are no - more entries in the directory. - -2.2.18. Get Filesystem Attributes - - union statfsres (stat status) { - case NFS_OK: - struct { - unsigned tsize; - unsigned bsize; - unsigned blocks; - unsigned bfree; - unsigned bavail; - } info; - default: - void; - }; - - statfsres - NFSPROC_STATFS(fhandle) = 17; - - If the reply "status" is NFS_OK, then the reply "info" gives the - attributes for the filesystem that contains file referred to by the - input fhandle. The attribute fields contain the following values: - - tsize The optimum transfer size of the server in bytes. This is - the number of bytes the server would like to have in the - data part of READ and WRITE requests. - - bsize The block size in bytes of the filesystem. - - blocks The total number of "bsize" blocks on the filesystem. - - bfree The number of free "bsize" blocks on the filesystem. - - bavail The number of "bsize" blocks available to non-privileged - users. - - Notes: This call does not work well if a filesystem has variable - size blocks. - -2.3. Basic Data Types - - The following XDR definitions are basic structures and types used in - other structures described further on. - -2.3.1. stat - - enum stat { - NFS_OK = 0, - NFSERR_PERM=1, - - NFSERR_NOENT=2, - NFSERR_IO=5, - NFSERR_NXIO=6, - NFSERR_ACCES=13, - NFSERR_EXIST=17, - NFSERR_NODEV=19, - NFSERR_NOTDIR=20, - NFSERR_ISDIR=21, - NFSERR_FBIG=27, - NFSERR_NOSPC=28, - NFSERR_ROFS=30, - NFSERR_NAMETOOLONG=63, - NFSERR_NOTEMPTY=66, - NFSERR_DQUOT=69, - NFSERR_STALE=70, - NFSERR_WFLUSH=99 - }; - - The "stat" type is returned with every procedure's results. A value - of NFS_OK indicates that the call completed successfully and the - results are valid. The other values indicate some kind of error - occurred on the server side during the servicing of the procedure. - The error values are derived from UNIX error numbers. - - NFSERR_PERM - Not owner. The caller does not have correct ownership to perform - the requested operation. - - NFSERR_NOENT - No such file or directory. The file or directory specified does - not exist. - - NFSERR_IO - Some sort of hard error occurred when the operation was in - progress. This could be a disk error, for example. - - NFSERR_NXIO - No such device or address. - - NFSERR_ACCES - Permission denied. The caller does not have the correct - permission to perform the requested operation. - - NFSERR_EXIST - File exists. The file specified already exists. - - NFSERR_NODEV - No such device. - - NFSERR_NOTDIR - Not a directory. The caller specified a non-directory in a - directory operation. - - NFSERR_ISDIR - Is a directory. The caller specified a directory in a non- - directory operation. - - NFSERR_FBIG - File too large. The operation caused a file to grow beyond the - server's limit. - - NFSERR_NOSPC - No space left on device. The operation caused the server's - filesystem to reach its limit. - - NFSERR_ROFS - Read-only filesystem. Write attempted on a read-only filesystem. - - NFSERR_NAMETOOLONG - File name too long. The file name in an operation was too long. - - NFSERR_NOTEMPTY - Directory not empty. Attempted to remove a directory that was not - empty. - - NFSERR_DQUOT - Disk quota exceeded. The client's disk quota on the server has - been exceeded. - - NFSERR_STALE - The "fhandle" given in the arguments was invalid. That is, the - file referred to by that file handle no longer exists, or access - to it has been revoked. - - NFSERR_WFLUSH - The server's write cache used in the "WRITECACHE" call got flushed - to disk. - -2.3.2. ftype - - enum ftype { - NFNON = 0, - NFREG = 1, - NFDIR = 2, - NFBLK = 3, - NFCHR = 4, - NFLNK = 5 - }; - - The enumeration "ftype" gives the type of a file. The type NFNON - indicates a non-file, NFREG is a regular file, NFDIR is a - directory, NFBLK is a block-special device, NFCHR is a character- - special device, and NFLNK is a symbolic link. - -2.3.3. fhandle - - typedef opaque fhandle[FHSIZE]; - - The "fhandle" is the file handle passed between the server and the - client. All file operations are done using file handles to refer - to a file or directory. The file handle can contain whatever - information the server needs to distinguish an individual file. - -2.3.4. timeval - - struct timeval { - unsigned int seconds; - unsigned int useconds; - }; - - The "timeval" structure is the number of seconds and microseconds - since midnight January 1, 1970, Greenwich Mean Time. It is used - to pass time and date information. - -2.3.5. fattr - - struct fattr { - ftype type; - unsigned int mode; - unsigned int nlink; - unsigned int uid; - unsigned int gid; - unsigned int size; - unsigned int blocksize; - unsigned int rdev; - unsigned int blocks; - - unsigned int fsid; - unsigned int fileid; - timeval atime; - timeval mtime; - timeval ctime; - }; - - The "fattr" structure contains the attributes of a file; "type" is - the type of the file; "nlink" is the number of hard links to the - file (the number of different names for the same file); "uid" is - the user identification number of the owner of the file; "gid" is - the group identification number of the group of the file; "size" - is the size in bytes of the file; "blocksize" is the size in bytes - of a block of the file; "rdev" is the device number of the file if - it is type NFCHR or NFBLK; "blocks" is the number of blocks the - file takes up on disk; "fsid" is the file system identifier for - the filesystem containing the file; "fileid" is a number that - uniquely identifies the file within its filesystem; "atime" is the - time when the file was last accessed for either read or write; - "mtime" is the time when the file data was last modified - (written); and "ctime" is the time when the status of the file was - last changed. Writing to the file also changes "ctime" if the - size of the file changes. - - "Mode" is the access mode encoded as a set of bits. Notice that - the file type is specified both in the mode bits and in the file - type. This is really a bug in the protocol and will be fixed in - future versions. The descriptions given below specify the bit - positions using octal numbers. - - 0040000 This is a directory; "type" field should be NFDIR. - 0020000 This is a character special file; "type" field should - be NFCHR. - 0060000 This is a block special file; "type" field should be - NFBLK. - 0100000 This is a regular file; "type" field should be NFREG. - 0120000 This is a symbolic link file; "type" field should be - NFLNK. - 0140000 This is a named socket; "type" field should be NFNON. - 0004000 Set user id on execution. - 0002000 Set group id on execution. - 0001000 Save swapped text even after use. - 0000400 Read permission for owner. - 0000200 Write permission for owner. - 0000100 Execute and search permission for owner. - 0000040 Read permission for group. - 0000020 Write permission for group. - 0000010 Execute and search permission for group. - - 0000004 Read permission for others. - 0000002 Write permission for others. - 0000001 Execute and search permission for others. - - Notes: The bits are the same as the mode bits returned by the - stat(2) system call in UNIX. The file type is specified both in - the mode bits and in the file type. This is fixed in future - versions. - - The "rdev" field in the attributes structure is an operating - system specific device specifier. It will be removed and - generalized in the next revision of the protocol. - -2.3.6. sattr - - struct sattr { - unsigned int mode; - unsigned int uid; - unsigned int gid; - unsigned int size; - timeval atime; - timeval mtime; - }; - - The "sattr" structure contains the file attributes which can be - set from the client. The fields are the same as for "fattr" - above. A "size" of zero means the file should be truncated. A - value of -1 indicates a field that should be ignored. - -2.3.7. filename - - typedef string filename; - - The type "filename" is used for passing file names or pathname - components. - -2.3.8. path - - typedef string path; - - The type "path" is a pathname. The server considers it as a - string with no internal structure, but to the client it is the - name of a node in a filesystem tree. - -2.3.9. attrstat - - union attrstat switch (stat status) { - case NFS_OK: - - fattr attributes; - default: - void; - }; - - The "attrstat" structure is a common procedure result. It - contains a "status" and, if the call succeeded, it also contains - the attributes of the file on which the operation was done. - -2.3.10. diropargs - - struct diropargs { - fhandle dir; - filename name; - }; - - The "diropargs" structure is used in directory operations. The - "fhandle" "dir" is the directory in which to find the file "name". - A directory operation is one in which the directory is affected. - -2.3.11. diropres - - union diropres switch (stat status) { - case NFS_OK: - struct { - fhandle file; - fattr attributes; - } diropok; - default: - void; - }; - - The results of a directory operation are returned in a "diropres" - structure. If the call succeeded, a new file handle "file" and - the "attributes" associated with that file are returned along with - the "status". - -3. NFS IMPLEMENTATION ISSUES - - The NFS protocol was designed to allow different operating systems to - share files. However, since it was designed in a UNIX environment, - many operations have semantics similar to the operations of the UNIX - file system. This section discusses some of the implementation- - specific details and semantic issues. - -3.1. Server/Client Relationship - - The NFS protocol is designed to allow servers to be as simple and - - general as possible. Sometimes the simplicity of the server can be a - problem, if the client wants to implement complicated filesystem - semantics. - - For example, some operating systems allow removal of open files. A - process can open a file and, while it is open, remove it from the - directory. The file can be read and written as long as the process - keeps it open, even though the file has no name in the filesystem. - It is impossible for a stateless server to implement these semantics. - The client can do some tricks such as renaming the file on remove, - and only removing it on close. We believe that the server provides - enough functionality to implement most file system semantics on the - client. - - Every NFS client can also potentially be a server, and remote and - local mounted filesystems can be freely intermixed. This leads to - some interesting problems when a client travels down the directory - tree of a remote filesystem and reaches the mount point on the server - for another remote filesystem. Allowing the server to follow the - second remote mount would require loop detection, server lookup, and - user revalidation. Instead, we decided not to let clients cross a - server's mount point. When a client does a LOOKUP on a directory on - which the server has mounted a filesystem, the client sees the - underlying directory instead of the mounted directory. - - For example, if a server has a file system called "/usr" and mounts - another file system on "/usr/src", if a client mounts "/usr", it - does NOT see the mounted version of "/usr/src". A client could do - remote mounts that match the server's mount points to maintain the - server's view. In this example, the client would also have to mount - "/usr/src" in addition to "/usr", even if they are from the same - server. - -3.2. Pathname Interpretation - - There are a few complications to the rule that pathnames are always - parsed on the client. For example, symbolic links could have - different interpretations on different clients. Another common - problem for non-UNIX implementations is the special interpretation of - the pathname ".." to mean the parent of a given directory. The next - revision of the protocol uses an explicit flag to indicate the parent - instead. - -3.3. Permission Issues - - The NFS protocol, strictly speaking, does not define the permission - checking used by servers. However, it is expected that a server will - do normal operating system permission checking using AUTH_UNIX style - - authentication as the basis of its protection mechanism. The server - gets the client's effective "uid", effective "gid", and groups on - each call and uses them to check permission. There are various - problems with this method that can been resolved in interesting ways. - - Using "uid" and "gid" implies that the client and server share the - same "uid" list. Every server and client pair must have the same - mapping from user to "uid" and from group to "gid". Since every - client can also be a server, this tends to imply that the whole - network shares the same "uid/gid" space. AUTH_DES (and the next - revision of the NFS protocol) uses string names instead of numbers, - but there are still complex problems to be solved. - - Another problem arises due to the usually stateful open operation. - Most operating systems check permission at open time, and then check - that the file is open on each read and write request. With stateless - servers, the server has no idea that the file is open and must do - permission checking on each read and write call. On a local - filesystem, a user can open a file and then change the permissions so - that no one is allowed to touch it, but will still be able to write - to the file because it is open. On a remote filesystem, by contrast, - the write would fail. To get around this problem, the server's - permission checking algorithm should allow the owner of a file to - access it regardless of the permission setting. - - A similar problem has to do with paging in from a file over the - network. The operating system usually checks for execute permission - before opening a file for demand paging, and then reads blocks from - the open file. The file may not have read permission, but after it - is opened it does not matter. An NFS server can not tell the - difference between a normal file read and a demand page-in read. To - make this work, the server allows reading of files if the "uid" given - in the call has either execute or read permission on the file. - - In most operating systems, a particular user (on UNIX, the user ID - zero) has access to all files no matter what permission and ownership - they have. This "super-user" permission may not be allowed on the - server, since anyone who can become super-user on their workstation - could gain access to all remote files. The UNIX server by default - maps user id 0 to -2 before doing its access checking. This works - except for NFS root filesystems, where super-user access cannot be - avoided. - -3.4. RPC Information - - Authentication - The NFS service uses AUTH_UNIX, AUTH_DES, or AUTH_SHORT style - authentication, except in the NULL procedure where AUTH_NONE is - - also allowed. - - Transport Protocols - NFS is supported normally on UDP. - - Port Number - The NFS protocol currently uses the UDP port number 2049. This is - not an officially assigned port, so later versions of the protocol - use the "Portmapping" facility of RPC. - -3.5. Sizes of XDR Structures - - These are the sizes, given in decimal bytes, of various XDR - structures used in the protocol: - - /* - * The maximum number of bytes of data in a READ or WRITE - * request. - */ - const MAXDATA = 8192; - - /* The maximum number of bytes in a pathname argument. */ - const MAXPATHLEN = 1024; - - /* The maximum number of bytes in a file name argument. */ - const MAXNAMLEN = 255; - - /* The size in bytes of the opaque "cookie" passed by READDIR. */ - const COOKIESIZE = 4; - - /* The size in bytes of the opaque file handle. */ - const FHSIZE = 32; - -3.6. Setting RPC Parameters - - Various file system parameters and options should be set at mount - time. The mount protocol is described in the appendix below. For - example, "Soft" mounts as well as "Hard" mounts are usually both - provided. Soft mounted file systems return errors when RPC - operations fail (after a given number of optional retransmissions), - while hard mounted file systems continue to retransmit forever. The - maximum transfer sizes are implementation dependent. For efficient - operation over a local network, 8192 bytes of data are normally used. - This may result in lower-level fragmentation (such as at the IP - level). Since some network interfaces may not allow such packets, - for operation over slower-speed networks or hosts, or through - gateways, transfer sizes of 512 or 1024 bytes often provide better - results. - - Clients and servers may need to keep caches of recent operations to - help avoid problems with non-idempotent operations. For example, if - the transport protocol drops the response for a Remove File - operation, upon retransmission the server may return an error code of - NFSERR_NOENT instead of NFS_OK. But if the server keeps around the - last operation requested and its result, it could return the proper - success code. Of course, the server could be crashed and rebooted - between retransmissions, but a small cache (even a single entry) - would solve most problems. - - Appendix A. MOUNT PROTOCOL DEFINITION - -A.1. Introduction - - The mount protocol is separate from, but related to, the NFS - protocol. It provides operating system specific services to get the - NFS off the ground -- looking up server path names, validating user - identity, and checking access permissions. Clients use the mount - protocol to get the first file handle, which allows them entry into a - remote filesystem. - - The mount protocol is kept separate from the NFS protocol to make it - easy to plug in new access checking and validation methods without - changing the NFS server protocol. - - Notice that the protocol definition implies stateful servers because - the server maintains a list of client's mount requests. The mount - list information is not critical for the correct functioning of - either the client or the server. It is intended for advisory use - only, for example, to warn possible clients when a server is going - down. - - Version one of the mount protocol is used with version two of the NFS - protocol. The only information communicated between these two - protocols is the "fhandle" structure. - -A.2. RPC Information - - Authentication - The mount service uses AUTH_UNIX and AUTH_NONE style - authentication only. - - Transport Protocols - The mount service is supported on both UDP and TCP. - - Port Number - Consult the server's portmapper, described in RFC 1057 , "RPC: - Remote Procedure Call Protocol Specification", to find the port - number on which the mount service is registered. - -A.3. Sizes of XDR Structures - - These are the sizes, given in decimal bytes, of various XDR - structures used in the protocol: - - /* The maximum number of bytes in a pathname argument. */ - const MNTPATHLEN = 1024; - - /* The maximum number of bytes in a name argument. */ - const MNTNAMLEN = 255; - - /* The size in bytes of the opaque file handle. */ - const FHSIZE = 32; - -A.4. Basic Data Types - - This section presents the data types used by the mount protocol. In - many cases they are similar to the types used in NFS. - -A.4.1. fhandle - - typedef opaque fhandle[FHSIZE]; - - The type "fhandle" is the file handle that the server passes to the - client. All file operations are done using file handles to refer to - a file or directory. The file handle can contain whatever - information the server needs to distinguish an individual file. - - This is the same as the "fhandle" XDR definition in version 2 of the - NFS protocol; see section "2.3.3. fhandle" under "Basic Data Types". - -A.4.2. fhstatus - - union fhstatus switch (unsigned status) { - case 0: - fhandle directory; - default: - void; - } - - The type "fhstatus" is a union. If a "status" of zero is returned, - the call completed successfully, and a file handle for the - "directory" follows. A non-zero status indicates some sort of error. - In this case, the status is a UNIX error number. - -A.4.3. dirpath - - typedef string dirpath; - - The type "dirpath" is a server pathname of a directory. - -A.4.4. name - - typedef string name; - - The type "name" is an arbitrary string used for various names. - -A.5. Server Procedures - - The following sections define the RPC procedures supplied by a mount - server. - - /* - * Protocol description for the mount program - */ - program MOUNTPROG { - /* - * Version 1 of the mount protocol used with - * version 2 of the NFS protocol. - */ - version MOUNTVERS { - - void - MOUNTPROC_NULL(void) = 0; - - fhstatus - MOUNTPROC_MNT(dirpath) = 1; - - mountlist - MOUNTPROC_DUMP(void) = 2; - - void - MOUNTPROC_UMNT(dirpath) = 3; - - void - MOUNTPROC_UMNTALL(void) = 4; - - exportlist - MOUNTPROC_EXPORT(void) = 5; - } = 1; - } = 100005; - -A.5.1. Do Nothing - - void - MNTPROC_NULL(void) = 0; - - This procedure does no work. It is made available in all RPC - services to allow server response testing and timing. - -A.5.2. Add Mount Entry - - fhstatus - MNTPROC_MNT(dirpath) = 1; - - If the reply "status" is 0, then the reply "directory" contains the - file handle for the directory "dirname". This file handle may be - used in the NFS protocol. This procedure also adds a new entry to - the mount list for this client mounting "dirname". - -A.5.3. Return Mount Entries - - struct *mountlist { - name hostname; - dirpath directory; - mountlist nextentry; - }; - - mountlist - MNTPROC_DUMP(void) = 2; - - Returns the list of remote mounted filesystems. The "mountlist" - contains one entry for each "hostname" and "directory" pair. - -A.5.4. Remove Mount Entry - - void - MNTPROC_UMNT(dirpath) = 3; - - Removes the mount list entry for the input "dirpath". - -A.5.5. Remove All Mount Entries - - void - MNTPROC_UMNTALL(void) = 4; - - Removes all of the mount list entries for this client. - -A.5.6. Return Export List - - struct *groups { - name grname; - groups grnext; - }; - - struct *exportlist { - dirpath filesys; - groups groups; - exportlist next; - }; - - exportlist - MNTPROC_EXPORT(void) = 5; - - Returns a variable number of export list entries. Each entry - contains a filesystem name and a list of groups that are allowed to - import it. The filesystem name is in "filesys", and the group name - is in the list "groups". - - Notes: The exportlist should contain more information about the - status of the filesystem, such as a read-only flag. - -Author's Address: - - Bill Nowicki - Sun Microsystems, Inc. - Mail Stop 1-40 - 2550 Garcia Avenue - Mountain View, CA 94043 - - Phone: (415) 336-7278 - - Email: nowicki@SUN.COM - -Comment on RFC 1094 - - - -Comments about this RFC: - - * RFC 1094: I am preparing for doing a project in File System in - Network. can you specify... by Ravik (12/4/2003) - - -Previous: RFC 1093 - NSFNET routing architecture - - - -Next: RFC 1095 - Common Management Information Services and Protocol -over TCP/IP (CMOT) - - - ------------------------------------------------------------------------- diff --git a/cpukit/libfs/src/nfsclient/src/nfs.c b/cpukit/libfs/src/nfsclient/src/nfs.c deleted file mode 100644 index bc9a2c6246..0000000000 --- a/cpukit/libfs/src/nfsclient/src/nfs.c +++ /dev/null @@ -1,3203 +0,0 @@ -/** - * @file - * - * @ingroup RTEMSFileSystemNFS - * - * @brief NFS Client Implementation for RTEMS - * - * Hooks Into the RTEMS NFS Filesystem - */ - -/* - * Author: Till Straumann , 2002 - * - * Hacked on by others. - * - * Modifications to support reference counting in the file system are - * Copyright (c) 2012 embedded brains GmbH. - * - * Authorship - * ---------- - * This software (NFS-2 client implementation for RTEMS) was created by - * Till Straumann , 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../proto/nfs_prot.h" -#include "../proto/mount_prot.h" - -#include "rpcio.h" -#include "librtemsNfs.h" - -/* Configurable parameters */ - -/* Estimated average length of a filename (including terminating 0). - * This was calculated by doing - * - * find -print -exec basename '{}' \; > feil - * wc feil - * - * AVG_NAMLEN = (num_chars + num_lines)/num_lines - */ -#define CONFIG_AVG_NAMLEN 10 - -#define CONFIG_NFS_SMALL_XACT_SIZE 800 /* size of RPC arguments for non-write ops */ -/* lifetime of NFS attributes in a NfsNode; - * the time is in seconds and the lifetime is - * infinite if the symbol is #undef - */ -#define CONFIG_ATTR_LIFETIME 10/*secs*/ - -/* - * The 'st_blksize' (stat(2)) value this nfs - * client should report. If set to zero then the server's fattr data - * is passed throught which is not necessary optimal. - * Newlib's stdio uses 'st_blksize' (if built with HAVE_BLKSIZE defined) - * to size the default buffer. - * Due to the overhead of NFS it is probably better to use the maximum - * size of an NFS read request (8k) rather than the optimal block - * size on the server. - * This value can be overridden at run-time by setting the global - * variable 'nfsStBlksize'. - * Thanks to Steven Johnson for helping - * working on this issue. - */ -#define DEFAULT_NFS_ST_BLKSIZE NFS_MAXDATA - -/* dont change this without changing the maximal write size */ -#define CONFIG_NFS_BIG_XACT_SIZE UDPMSGSIZE /* dont change this */ - -/* The real values for these are specified further down */ -#define NFSCALL_TIMEOUT (&_nfscalltimeout) -#define MNTCALL_TIMEOUT (&_nfscalltimeout) -static struct timeval _nfscalltimeout = { 10, 0 }; /* {secs, us } */ - -/* More or less fixed constants; in particular, NFS3 is not supported */ -#define DELIM '/' -#define HOSTDELIM ':' -#define UPDIR ".." -#define UIDSEP '@' -#define NFS_VERSION_2 NFS_VERSION - -/* we use a dynamically assigned major number */ -#define NFS_MAJOR (nfsGlob.nfs_major) - - -/* NOTE: RTEMS (ss-20020301) uses a 'short st_ino' type :-( but the - * NFS fileid is 32 bit. [Later versions of RTEMS have fixed this; - * nfsInit() issues a warning if you run a version with 'short st_ino'.] - * - * As a workarount, we merge the upper 16bits of the fileid into the - * minor device no. Hence, it is still possible to uniquely identify - * a file by looking at its device number (major = nfs, minor = part - * of the fileid + our 'nfs-id' identifier). - * - * This has an impact on performance, as e.g. getcwd() stats() all - * directory entries when it believes it has crossed a mount point - * (a.st_dev != b.st_dev). - * - * OTOH, it also might cause node comparison failure! E.g. 'getcwd()' - * assumes that two nodes residing in the same directory must be located - * on the same device and hence compares 'st_ino' only. - * If two files in the same directory have the same inode number - * modulo 2^16, they will be considered equal (although their device - * number doesn't match - getcwd doesn't look at it). - * - * Other software might or might not be affected. - * - * The only clean solution to this problem is bumping up the size of - * 'ino_t' at least to 'long'. - * Note that this requires _all_ software (libraries etc.) to be - * recompiled. - */ - -#define NFS_MAKE_DEV_T_INO_HACK(node) \ - rtems_filesystem_make_dev_t( NFS_MAJOR, \ - (((rtems_device_minor_number)((node)->nfs->id))<<16) | (((rtems_device_minor_number)SERP_ATTR((node)).fileid) >> 16) ) - -/* use our 'nfs id' and the server's fsid for the minor device number - * this should be fairly unique - */ -#define NFS_MAKE_DEV_T(node) \ - rtems_filesystem_make_dev_t( NFS_MAJOR, \ - (((rtems_device_minor_number)((node)->nfs->id))<<16) | (SERP_ATTR((node)).fsid & (((rtems_device_minor_number)1<<16)-1)) ) - -#define DIRENT_HEADER_SIZE ( sizeof(struct dirent) - \ - sizeof( ((struct dirent *)0)->d_name ) ) - - -/* debugging flags */ -#define DEBUG_COUNT_NODES (1<<0) -#define DEBUG_TRACK_NODES (1<<1) -#define DEBUG_EVALPATH (1<<2) -#define DEBUG_READDIR (1<<3) -#define DEBUG_SYSCALLS (1<<4) - -/* #define DEBUG ( DEBUG_SYSCALLS | DEBUG_COUNT_NODES ) */ - -#ifdef DEBUG -#define STATIC -#else -#define STATIC static -#endif - -#define LOCK(s) rtems_recursive_mutex_lock(&(s)) - -#define UNLOCK(s) rtems_recursive_mutex_unlock(&(s)) - -RTEMS_INTERRUPT_LOCK_DEFINE(static, nfs_global_lock, "NFS") - -#define NFS_GLOBAL_ACQUIRE(lock_context) \ - rtems_interrupt_lock_acquire(&nfs_global_lock, lock_context) - -#define NFS_GLOBAL_RELEASE(lock_context) \ - rtems_interrupt_lock_release(&nfs_global_lock, lock_context) - -static inline char * -nfs_dupname(const char *name, size_t namelen) -{ - char *dupname = malloc(namelen + 1); - - if (dupname != NULL) { - memcpy(dupname, name, namelen); - dupname [namelen] = '\0'; - } else { - errno = ENOMEM; - } - - return dupname; -} - -/***************************************** - Types with Associated XDR Routines - *****************************************/ - -/* a string buffer with a maximal length. - * If the buffer pointer is NULL, it is updated - * with an appropriately allocated area. - */ -typedef struct strbuf { - char *buf; - u_int max; -} strbuf; - -/* Read 'readlink' results into a 'strbuf'. - * This is convenient as it avoids - * one extra step of copying / length - * checking. - */ -typedef struct readlinkres_strbuf { - nfsstat status; - strbuf strbuf; -} readlinkres_strbuf; - -static bool_t -xdr_readlinkres_strbuf(XDR *xdrs, readlinkres_strbuf *objp) -{ - if ( !xdr_nfsstat(xdrs, &objp->status) ) - return FALSE; - - if ( NFS_OK == objp->status ) { - if ( !xdr_string(xdrs, &objp->strbuf.buf, objp->strbuf.max) ) - return FALSE; - } - return TRUE; -} - - -/* DirInfoRec is used instead of dirresargs - * to convert recursion into iteration. The - * 'rpcgen'erated xdr_dirresargs ends up - * doing nested calls when unpacking the - * 'next' pointers. - */ - -typedef struct DirInfoRec_ { - readdirargs readdirargs; - /* clone of the 'readdirres' fields; - * the cookie is put into the readdirargs above - */ - nfsstat status; - char *buf, *ptr; - int len; - bool_t eofreached; -} DirInfoRec, *DirInfo; - -/* this deals with one entry / record */ -static bool_t -xdr_dir_info_entry(XDR *xdrs, DirInfo di) -{ -union { - char nambuf[NFS_MAXNAMLEN+1]; - nfscookie cookie; -} dummy; -struct dirent *pde = (struct dirent *)di->ptr; -u_int fileid; -char *name; -register int nlen = 0,len,naligned = 0; -nfscookie *pcookie; - - len = di->len; - - if ( !xdr_u_int(xdrs, &fileid) ) - return FALSE; - - /* we must pass the address of a char* */ - name = (len > NFS_MAXNAMLEN) ? pde->d_name : dummy.nambuf; - - if ( !xdr_filename(xdrs, &name) ) { - return FALSE; - } - - if (len >= 0) { - nlen = strlen(name); - naligned = nlen + 1 /* string delimiter */ + 3 /* alignment */; - naligned &= ~3; - len -= naligned; - } - - /* if the cookie goes into the DirInfo, we hope this doesn't fail - * - the caller ends up with an invalid readdirargs cookie otherwise... - */ - pcookie = (len >= 0) ? &di->readdirargs.cookie : &dummy.cookie; - if ( !xdr_nfscookie(xdrs, pcookie) ) { - return FALSE; - } - - di->len = len; - /* adjust the buffer pointer */ - if (len >= 0) { - pde->d_ino = fileid; - pde->d_namlen = nlen; - pde->d_off = di->ptr - di->buf; -#ifdef DT_UNKNOWN - pde->d_type = DT_UNKNOWN; -#endif - if (name == dummy.nambuf) { - memcpy(pde->d_name, dummy.nambuf, nlen + 1); - } - pde->d_reclen = DIRENT_HEADER_SIZE + naligned; - di->ptr += pde->d_reclen; - } - - return TRUE; -} - -/* this routine loops over all entries */ -static bool_t -xdr_dir_info(XDR *xdrs, DirInfo di) -{ -DirInfo dip; - - if ( !xdr_nfsstat(xdrs, &di->status) ) - return FALSE; - - if ( NFS_OK != di->status ) - return TRUE; - - dip = di; - - while (dip) { - /* reserve space for the dirent 'header' - we assume it's word aligned! */ -#ifdef DEBUG - assert( DIRENT_HEADER_SIZE % 4 == 0 ); -#endif - dip->len -= DIRENT_HEADER_SIZE; - - /* we pass a 0 size - size is unused since - * we always pass a non-NULL pointer - */ - if ( !xdr_pointer(xdrs, (void*)&dip, 0 /* size */, (xdrproc_t)xdr_dir_info_entry) ) - return FALSE; - } - - if ( ! xdr_bool(xdrs, &di->eofreached) ) - return FALSE; - - /* if everything fits into the XDR buffer but not the user's buffer, - * they must resume reading from where xdr_dir_info_entry() started - * skipping and 'eofreached' needs to be adjusted - */ - if ( di->len < 0 && di->eofreached ) - di->eofreached = FALSE; - - return TRUE; -} - - -/* a type better suited for node operations - * than diropres. - * fattr and fhs are swapped so parts of this - * structure may be used as a diroparg which - * is practical when looking up paths. - */ - -/* Macro for accessing serporid fields - */ -#define SERP_ARGS(node) ((node)->serporid.serporid_u.serporid.arg_u) -#define SERP_ATTR(node) ((node)->serporid.serporid_u.serporid.attributes) -#define SERP_FILE(node) ((node)->serporid.serporid_u.serporid.file) - - -typedef struct serporidok { - fattr attributes; - nfs_fh file; - union { - struct { - filename name; - } diroparg; - struct { - sattr attributes; - } sattrarg; - struct { - uint32_t offset; - uint32_t count; - uint32_t totalcount; - } readarg; - struct { - uint32_t beginoffset; - uint32_t offset; - uint32_t totalcount; - struct { - uint32_t data_len; - char* data_val; - } data; - } writearg; - struct { - filename name; - sattr attributes; - } createarg; - struct { - filename name; - diropargs to; - } renamearg; - struct { - diropargs to; - } linkarg; - struct { - filename name; - nfspath to; - sattr attributes; - } symlinkarg; - struct { - nfscookie cookie; - uint32_t count; - } readdirarg; - } arg_u; -} serporidok; - -typedef struct serporid { - nfsstat status; - union { - serporidok serporid; - } serporid_u; -} serporid; - -/* an XDR routine to encode/decode the inverted diropres - * into an nfsnodestat; - * - * NOTE: this routine only acts on - * - 'serporid.status' - * - 'serporid.file' - * - 'serporid.attributes' - * and leaves the 'arg_u' alone. - * - * The idea is that a 'diropres' is read into 'serporid' - * which can then be used as an argument to subsequent - * NFS-RPCs (after filling in the node's arg_u). - */ -static bool_t -xdr_serporidok(XDR *xdrs, serporidok *objp) -{ - if (!xdr_nfs_fh (xdrs, &objp->file)) - return FALSE; - if (!xdr_fattr (xdrs, &objp->attributes)) - return FALSE; - return TRUE; -} - -static bool_t -xdr_serporid(XDR *xdrs, serporid *objp) -{ - if (!xdr_nfsstat (xdrs, &objp->status)) - return FALSE; - switch (objp->status) { - case NFS_OK: - if (!xdr_serporidok(xdrs, &objp->serporid_u.serporid)) - return FALSE; - break; - default: - break; - } - return TRUE; -} - -/***************************************** - Data Structures and Types - *****************************************/ - -/* 'time()' hack with less overhead; */ - -/* assume reading a long word is atomic */ -#define READ_LONG_IS_ATOMIC - -typedef uint32_t TimeStamp; - -static inline TimeStamp -nowSeconds(void) -{ - rtems_interval rval; - rtems_clock_get_seconds_since_epoch( &rval ); - return rval; -} - - -/* Per mounted FS structure */ -typedef struct NfsRec_ { - /* the NFS server we're talking to. - */ - RpcUdpServer server; - /* statistics; how many NfsNodes are - * currently alive. - */ - volatile int nodesInUse; -#if DEBUG & DEBUG_COUNT_NODES - /* statistics; how many 'NfsNode.str' - * strings are currently allocated. - */ - volatile int stringsInUse; -#endif - /* A small number who uniquely - * identifies a mounted NFS within - * this driver (i.e. this NfsRec). - * Each time a NFS is mounted, the - * global ID counter is incremented - * and its value is assigned to the - * newly created NfsRec. - */ - u_short id; - /* Our RTEMS filesystem mt_entry - */ - rtems_filesystem_mount_table_entry_t *mt_entry; - /* Next NfsRec on a linked list who - * is anchored at nfsGlob - */ - struct NfsRec_ *next; - /* Who we pretend we are - */ - u_long uid,gid; -} NfsRec, *Nfs; - -typedef struct NfsNodeRec_ { - /* This holds this node's attributes - * (stats) and its nfs filehandle. - * It also contains room for nfs rpc - * arguments. - */ - serporid serporid; - /* The arguments we used when doing - * the 'lookup' call for this node. - * We need this information (especially - * the directory FH) for performing - * certain operations on this - * node (in particular: for unlinking - * it from a parent directory) - */ - diropargs args; - /* FS this node belongs to - */ - Nfs nfs; - /* A buffer for the string the - * args.name points to. - * We need this because args.name might - * temporarily point to strings on the - * stack. Duplicates are allocated from - * the heap and attached to 'str' so - * they can be released as appropriate. - */ - char *str; - /* A timestamp for the stats - */ - TimeStamp age; -} NfsNodeRec, *NfsNode; - -/***************************************** - Forward Declarations - *****************************************/ - -static ssize_t nfs_readlink_with_node( - NfsNode node, - char *buf, - size_t len -); - -static int updateAttr(NfsNode node, int force); - -/* Mask bits when setting attributes. - * Only the 'arg' fields with their - * corresponding bit set in the mask - * will be used. The others are left - * unchanged. - * The 'TOUCH' bits instruct nfs_sattr() - * to update the respective time - * fields to the current time - */ -#define SATTR_MODE (1<<0) -#define SATTR_UID (1<<1) -#define SATTR_GID (1<<2) -#define SATTR_SIZE (1<<3) -#define SATTR_ATIME (1<<4) -#define SATTR_TOUCHA (1<<5) -#define SATTR_MTIME (1<<6) -#define SATTR_TOUCHM (1<<7) -#define SATTR_TOUCH (SATTR_TOUCHM | SATTR_TOUCHA) - -static int -nfs_sattr(NfsNode node, sattr *arg, u_long mask); - -extern const struct _rtems_filesystem_operations_table nfs_fs_ops; -static const struct _rtems_filesystem_file_handlers_r nfs_file_file_handlers; -static const struct _rtems_filesystem_file_handlers_r nfs_dir_file_handlers; -static const struct _rtems_filesystem_file_handlers_r nfs_link_file_handlers; -static rtems_driver_address_table drvNfs; - -int -nfsMountsShow(FILE*); - -rtems_status_code -rtems_filesystem_resolve_location(char *buf, int len, rtems_filesystem_location_info_t *loc); - -/***************************************** - Global Variables - *****************************************/ - -/* These are (except for MAXNAMLEN/MAXPATHLEN) copied from IMFS */ - -static const rtems_filesystem_limits_and_options_t -nfs_limits_and_options = { - 5, /* link_max */ - 6, /* max_canon */ - 7, /* max_input */ - NFS_MAXNAMLEN, /* name_max */ - NFS_MAXPATHLEN, /* path_max */ - 2, /* pipe_buf */ - 1, /* posix_async_io */ - 2, /* posix_chown_restrictions */ - 3, /* posix_no_trunc */ - 4, /* posix_prio_io */ - 5, /* posix_sync_io */ - 6 /* posix_vdisable */ -}; - -/* size of an encoded 'entry' object */ -static int dirres_entry_size; - -/* Global stuff and statistics */ -static struct nfsstats { - /* A lock for protecting the - * linked ist of mounted NFS - * and the num_mounted_fs field - */ - rtems_recursive_mutex llock; - /* A lock for protecting misc - * stuff within the driver. - * The lock must only be held - * for short periods of time. - */ - rtems_recursive_mutex lock; - /* Our major number as assigned - * by RTEMS - */ - rtems_device_major_number nfs_major; - /* The number of currently - * mounted NFS - */ - int num_mounted_fs; - /* A list of the currently - * mounted NFS - */ - struct NfsRec_ *mounted_fs; - /* A counter for allocating - * unique IDs to each mounted - * NFS. - * Assume we are not going to - * do more than 16k mounts - * during the system lifetime - */ - u_short fs_ids; - - /* Two pools of RPC transactions; - * One with small send buffers - * the other with a big one. - * The actual size of the small - * buffer is configurable (see top). - * - * Note: The RX buffers are always - * big - */ - RpcUdpXactPool smallPool; - RpcUdpXactPool bigPool; -} nfsGlob = {RTEMS_RECURSIVE_MUTEX_INITIALIZER("NFS List"), RTEMS_RECURSIVE_MUTEX_INITIALIZER("NFS Misc"), 0xffffffff, 0, 0, 0, NULL, NULL}; - -/* - * Global variable to tune the 'st_blksize' (stat(2)) value this nfs - * client should report. - * size on the server. - */ -#ifndef DEFAULT_NFS_ST_BLKSIZE -#define DEFAULT_NFS_ST_BLKSIZE NFS_MAXDATA -#endif -int nfsStBlksize = DEFAULT_NFS_ST_BLKSIZE; - - -/***************************************** - Implementation - *****************************************/ - -static int nfsEvaluateStatus(nfsstat nfsStatus) -{ - static const uint8_t nfsStatusToErrno [71] = { - [NFS_OK] = 0, - [NFSERR_PERM] = EPERM, - [NFSERR_NOENT] = ENOENT, - [3] = EIO, - [4] = EIO, - [NFSERR_IO] = EIO, - [NFSERR_NXIO] = ENXIO, - [7] = EIO, - [8] = EIO, - [9] = EIO, - [10] = EIO, - [11] = EIO, - [12] = EIO, - [NFSERR_ACCES] = EACCES, - [14] = EIO, - [15] = EIO, - [16] = EIO, - [NFSERR_EXIST] = EEXIST, - [18] = EIO, - [NFSERR_NODEV] = ENODEV, - [NFSERR_NOTDIR] = ENOTDIR, - [NFSERR_ISDIR] = EISDIR, - [22] = EIO, - [24] = EIO, - [25] = EIO, - [26] = EIO, - [27] = EIO, - [NFSERR_FBIG] = EFBIG, - [NFSERR_NOSPC] = ENOSPC, - [29] = EIO, - [NFSERR_ROFS] = EROFS, - [31] = EIO, - [32] = EIO, - [34] = EIO, - [35] = EIO, - [36] = EIO, - [37] = EIO, - [38] = EIO, - [39] = EIO, - [40] = EIO, - [41] = EIO, - [42] = EIO, - [44] = EIO, - [45] = EIO, - [46] = EIO, - [47] = EIO, - [48] = EIO, - [49] = EIO, - [50] = EIO, - [51] = EIO, - [52] = EIO, - [54] = EIO, - [55] = EIO, - [56] = EIO, - [57] = EIO, - [58] = EIO, - [59] = EIO, - [60] = EIO, - [61] = EIO, - [62] = EIO, - [NFSERR_NAMETOOLONG] = ENAMETOOLONG, - [64] = EIO, - [65] = EIO, - [NFSERR_NOTEMPTY] = ENOTEMPTY, - [67] = EIO, - [68] = EIO, - [NFSERR_DQUOT] = EDQUOT, - [NFSERR_STALE] = ESTALE - }; - - size_t idx = (size_t) nfsStatus; - int eno = EIO; - int rv = 0; - - if (idx < sizeof(nfsStatusToErrno) / sizeof(nfsStatusToErrno [0])) { - eno = nfsStatusToErrno [idx]; - } - - if (eno != 0) { - errno = eno; - rv = -1; - } - - return rv; -} - -/* Create a Nfs object. This is - * per-mounted NFS information. - * - * ARGS: The Nfs server handle. - * - * RETURNS: Nfs on success, - * NULL on failure with - * errno set - * - * NOTE: The submitted server - * object is 'owned' by - * this Nfs and will be - * destroyed by nfsDestroy() - */ -static Nfs -nfsCreate(RpcUdpServer server) -{ -Nfs rval = calloc(1,sizeof(*rval)); - - if (rval) { - rval->server = server; - LOCK(nfsGlob.llock); - rval->next = nfsGlob.mounted_fs; - nfsGlob.mounted_fs = rval; - UNLOCK(nfsGlob.llock); - } else { - errno = ENOMEM; - } - return rval; -} - -/* Destroy an Nfs object and - * its associated server - */ -static void -nfsDestroy(Nfs nfs) -{ -register Nfs prev; - if (!nfs) - return; - - LOCK(nfsGlob.llock); - if (nfs == nfsGlob.mounted_fs) - nfsGlob.mounted_fs = nfs->next; - else { - for (prev = nfsGlob.mounted_fs; - prev && prev->next != nfs; - prev = prev->next) - /* nothing else to do */; - assert( prev ); - prev->next = nfs->next; - } - UNLOCK(nfsGlob.llock); - - nfs->next = 0; /* paranoia */ - rpcUdpServerDestroy(nfs->server); - free(nfs); -} - -/* - * Create a Node. The node will - * be associated with a particular - * mounted NFS identified by 'nfs' - * Optionally, a NFS file handle - * may be copied into this node. - * - * ARGS: nfs of the NFS this node - * belongs to. - * NFS file handle identifying - * this node. - * RETURNS: node on success, - * NULL on failure with errno - * set. - * - * NOTE: The caller of this routine - * is responsible for copying - * a NFS file handle if she - * choses to pass a NULL fh. - * - * The driver code assumes the - * a node always has a valid - * NFS filehandle and file - * attributes (unless the latter - * are aged). - */ -static NfsNode -nfsNodeCreate(Nfs nfs, fhandle *fh) -{ -NfsNode rval = malloc(sizeof(*rval)); -rtems_interrupt_lock_context lock_context; - -#if DEBUG & DEBUG_TRACK_NODES - fprintf(stderr,"NFS: creating a node\n"); -#endif - - if (rval) { - if (fh) - memcpy( &SERP_FILE(rval), fh, sizeof(*fh) ); - NFS_GLOBAL_ACQUIRE(&lock_context); - nfs->nodesInUse++; - NFS_GLOBAL_RELEASE(&lock_context); - rval->nfs = nfs; - rval->str = 0; - } else { - errno = ENOMEM; - } - - return rval; -} - -/* destroy a node */ -static void -nfsNodeDestroy(NfsNode node) -{ -rtems_interrupt_lock_context lock_context; - -#if DEBUG & DEBUG_TRACK_NODES - fprintf(stderr,"NFS: destroying a node\n"); -#endif -#if 0 - if (!node) - return; - /* this probably does nothing... */ - xdr_free(xdr_serporid, &node->serporid); -#endif - - NFS_GLOBAL_ACQUIRE(&lock_context); - node->nfs->nodesInUse--; -#if DEBUG & DEBUG_COUNT_NODES - if (node->str) - node->nfs->stringsInUse--; -#endif - NFS_GLOBAL_RELEASE(&lock_context); - - if (node->str) - free(node->str); - - free(node); -} - -/* Clone a given node (AKA copy constructor), - * i.e. create an exact copy. - * - * ARGS: node to clone - * RETURNS: new node on success - * NULL on failure with errno set. - * - * NOTE: a string attached to 'str' - * is cloned as well. Outdated - * attributes (of the new copy - * only) will be refreshed - * (if unsuccessful, this could - * be a reason for failure to - * clone a node). - */ -static NfsNode -nfsNodeClone(NfsNode node) -{ -NfsNode rval = nfsNodeCreate(node->nfs, 0); - - if (rval) { - *rval = *node; - - /* must clone the string also */ - if (node->str) { - rval->args.name = rval->str = strdup(node->str); - if (!rval->str) { - errno = ENOMEM; - nfsNodeDestroy(rval); - return 0; - } -#if DEBUG & DEBUG_COUNT_NODES - { rtems_interrupt_lock_context lock_context; - NFS_GLOBAL_ACQUIRE(&lock_context); - node->nfs->stringsInUse++; - NFS_GLOBAL_RELEASE(&lock_context); - } -#endif - } - - /* possibly update the stats */ - if (updateAttr(rval, 0 /* only if necessary */)) { - nfsNodeDestroy(rval); - return 0; - } - } - return rval; -} - -/* Initialize the driver. - * - * ARGS: depth of the small and big - * transaction pools, i.e. how - * many transactions (buffers) - * should always be kept around. - * - * (If more transactions are needed, - * they are created and destroyed - * on the fly). - */ -int -nfsInit(int smallPoolDepth, int bigPoolDepth) -{ -static int initialised = 0; -entry dummy; - - if (initialised) - return 0; - - initialised = 1; - - fprintf(stderr, - "RTEMS-NFS, " \ - "Till Straumann, Stanford/SLAC/SSRL 2002, " \ - "See LICENSE file for licensing info.\n"); - - /* Get a major number */ - - if (RTEMS_SUCCESSFUL != rtems_io_register_driver(0, &drvNfs, &nfsGlob.nfs_major)) { - fprintf(stderr,"Registering NFS driver failed - %s\n", strerror(errno)); - errno = ENOMEM; - return -1; - } - - if (0==smallPoolDepth) - smallPoolDepth = 20; - if (0==bigPoolDepth) - bigPoolDepth = 10; - - rtems_recursive_mutex_init(&nfsGlob.llock, "NFSl"); - rtems_recursive_mutex_init(&nfsGlob.lock, "NFSm"); - - /* it's crucial to zero out the 'next' pointer - * because it terminates the xdr_entry recursion - * - * we also must make the filename some non-zero - * char pointer! - */ - - memset(&dummy, 0, sizeof(dummy)); - - dummy.nextentry = 0; - dummy.name = "somename"; /* guess average length of a filename */ - dirres_entry_size = xdr_sizeof((xdrproc_t)xdr_entry, &dummy); - - nfsGlob.smallPool = rpcUdpXactPoolCreate( - NFS_PROGRAM, - NFS_VERSION_2, - CONFIG_NFS_SMALL_XACT_SIZE, - smallPoolDepth); - if (nfsGlob.smallPool == NULL) { - goto cleanup; - } - - nfsGlob.bigPool = rpcUdpXactPoolCreate( - NFS_PROGRAM, - NFS_VERSION_2, - CONFIG_NFS_BIG_XACT_SIZE, - bigPoolDepth); - if (nfsGlob.bigPool == NULL) { - goto cleanup; - } - - if (sizeof(ino_t) < sizeof(u_int)) { - fprintf(stderr, - "WARNING: Using 'short st_ino' hits performance and may fail to access/find correct files\n"); - fprintf(stderr, - "you should fix newlib's sys/stat.h - for now I'll enable a hack...\n"); - - } - - return 0; - -cleanup: - - nfsCleanup(); - initialised = 0; - - return -1; -} - -/* Driver cleanup code - */ -int -nfsCleanup(void) -{ -int refuse; - - LOCK(nfsGlob.llock); - if ( (refuse = nfsGlob.num_mounted_fs) ) { - fprintf(stderr,"Refuse to unload NFS; %i filesystems still mounted.\n", - refuse); - nfsMountsShow(stderr); - /* yes, printing is slow - but since you try to unload the driver, - * you assume nobody is using NFS, so what if they have to wait? - */ - UNLOCK(nfsGlob.llock); - return -1; - } - - if (nfsGlob.smallPool != NULL) { - rpcUdpXactPoolDestroy(nfsGlob.smallPool); - nfsGlob.smallPool = NULL; - } - - if (nfsGlob.bigPool != NULL) { - rpcUdpXactPoolDestroy(nfsGlob.bigPool); - nfsGlob.bigPool = NULL; - } - - if (nfsGlob.nfs_major != 0xffffffff) { - rtems_io_unregister_driver(nfsGlob.nfs_major); - nfsGlob.nfs_major = 0xffffffff; - } - - UNLOCK(nfsGlob.llock); - - rtems_recursive_mutex_destroy(&nfsGlob.lock); - rtems_recursive_mutex_destroy(&nfsGlob.llock); - - return 0; -} - -/* NFS RPC wrapper. - * - * ARGS: srvr the NFS server we want to call - * proc the NFSPROC_xx we want to invoke - * xargs xdr routine to wrap the arguments - * pargs pointer to the argument object - * xres xdr routine to unwrap the results - * pres pointer to the result object - * - * RETURNS: 0 on success, -1 on error with errno set. - * - * NOTE: the caller assumes that errno is set to - * a nonzero value if this routine returns - * an error (nonzero return value). - * - * This routine prints RPC error messages to - * stderr. - */ -STATIC int -nfscall( - RpcUdpServer srvr, - int proc, - xdrproc_t xargs, - void * pargs, - xdrproc_t xres, - void * pres) -{ -RpcUdpXact xact; -enum clnt_stat stat; -RpcUdpXactPool pool; -int rval = -1; - - - switch (proc) { - case NFSPROC_SYMLINK: - case NFSPROC_WRITE: - pool = nfsGlob.bigPool; break; - default: pool = nfsGlob.smallPool; break; - } - - xact = rpcUdpXactPoolGet(pool, XactGetCreate); - - if ( !xact ) { - errno = ENOMEM; - return -1; - } - - if ( RPC_SUCCESS != (stat=rpcUdpSend( - xact, - srvr, - NFSCALL_TIMEOUT, - proc, - xres, - pres, - xargs, - pargs, - 0)) || - RPC_SUCCESS != (stat=rpcUdpRcv(xact)) ) { - - fprintf(stderr, - "NFS (proc %i) - %s\n", - proc, - clnt_sperrno(stat)); - - switch (stat) { - /* TODO: this is probably not complete and/or fully accurate */ - case RPC_CANTENCODEARGS : errno = EINVAL; break; - case RPC_AUTHERROR : errno = EPERM; break; - - case RPC_CANTSEND : - case RPC_CANTRECV : /* hope they have errno set */ - case RPC_SYSTEMERROR : break; - - default : errno = EIO; break; - } - } else { - rval = 0; - } - - /* release the transaction back into the pool */ - rpcUdpXactPoolPut(xact); - - if (rval && !errno) - errno = EIO; - - return rval; -} - -/* Check the 'age' of a node's stats - * and read the attributes from the server - * if necessary. - * - * ARGS: node node to update - * force enforce updating ignoring - * the timestamp/age - * - * RETURNS: 0 on success, - * -1 on failure with errno set - */ - -static int -updateAttr(NfsNode node, int force) -{ - int rv = 0; - - if (force -#ifdef CONFIG_ATTR_LIFETIME - || (nowSeconds() - node->age > CONFIG_ATTR_LIFETIME) -#endif - ) { - rv = nfscall( - node->nfs->server, - NFSPROC_GETATTR, - (xdrproc_t) xdr_nfs_fh, &SERP_FILE(node), - (xdrproc_t) xdr_attrstat, &node->serporid - ); - - if (rv == 0) { - rv = nfsEvaluateStatus(node->serporid.status); - - if (rv == 0) { - node->age = nowSeconds(); - } - } - } - - return rv; -} - -/* - * IP address helper. - * - * initialize a sockaddr_in from a - * ['.''@']':'" string and let - * pPath point to the part; retrieve the optional - * uid/gids - * - * ARGS: see description above - * - * RETURNS: 0 on success, - * -1 on failure with errno set - */ -static int -buildIpAddr(u_long *puid, u_long *pgid, - char **pHost, struct sockaddr_in *psa, - char **pPath) -{ -struct hostent *h; -char host[64]; -char *chpt = *pPath; -char *path; -int len; - - if ( !chpt ) { - errno = EINVAL; - return -1; - } - - /* look for the optional uid/gid */ - if ( (chpt = strchr(chpt, UIDSEP)) ) { - if ( 2 != sscanf(*pPath,"%li.%li",puid,pgid) ) { - errno = EINVAL; - return -1; - } - chpt++; - } else { - *puid = geteuid(); - *pgid = getegid(); - chpt = *pPath; - } - if ( pHost ) - *pHost = chpt; - - /* split the device name which is in the form - * - * ':' - * - * into its components using a local buffer - */ - - if ( !(path = strchr(chpt, HOSTDELIM)) || - (len = path - chpt) >= sizeof(host) - 1 ) { - errno = EINVAL; - return -1; - } - /* point to path beyond ':' */ - path++; - - strncpy(host, chpt, len); - host[len]=0; - - /* BEGIN OF NON-THREAD SAFE REGION */ - - h = gethostbyname(host); - - if ( !h ) { - errno = EINVAL; - return -1; - } - - memcpy(&psa->sin_addr, h->h_addr, sizeof (struct in_addr)); - - /* END OF NON-THREAD SAFE REGION */ - - psa->sin_family = AF_INET; - psa->sin_port = 0; - *pPath = path; - return 0; -} - -/* wrapper similar to nfscall. - * However, since it is not used - * very often, the simpler and less - * efficient rpcUdpCallRp API is used. - * - * ARGS: see 'nfscall()' above - * - * RETURNS: RPC status - */ -static enum clnt_stat -mntcall( - struct sockaddr_in *psrvr, - int proc, - xdrproc_t xargs, - void * pargs, - xdrproc_t xres, - void * pres, - u_long uid, - u_long gid) -{ -#ifdef MOUNT_V1_PORT -int retry; -#endif -enum clnt_stat stat = RPC_FAILED; - -#ifdef MOUNT_V1_PORT - /* if the portmapper fails, retry a fixed port */ - for (retry = 1, psrvr->sin_port = 0, stat = RPC_FAILED; - retry >= 0 && stat; - stat && (psrvr->sin_port = htons(MOUNT_V1_PORT)), retry-- ) -#endif - stat = rpcUdpCallRp( - psrvr, - MOUNTPROG, - MOUNTVERS, - proc, - xargs, - pargs, - xres, - pres, - uid, - gid, - MNTCALL_TIMEOUT - ); - return stat; -} - -/***************************************** - RTEMS File System Operations for NFS - *****************************************/ - -static bool nfs_is_directory( - rtems_filesystem_eval_path_context_t *ctx, - void *arg -) -{ - bool is_dir = false; - rtems_filesystem_location_info_t *currentloc = - rtems_filesystem_eval_path_get_currentloc(ctx); - NfsNode node = currentloc->node_access; - int force_update = 0; - - if (updateAttr(node, force_update) == 0) { - is_dir = SERP_ATTR(node).type == NFDIR; - } - - return is_dir; -} - -static int nfs_search_in_directory( - Nfs nfs, - const NfsNode dir, - char *part, - NfsNode entry -) -{ - int rv; - - entry->nfs = nfs; - - /* lookup one element */ - SERP_ATTR(entry) = SERP_ATTR(dir); - SERP_FILE(entry) = SERP_FILE(dir); - SERP_ARGS(entry).diroparg.name = part; - - /* remember args / directory fh */ - memcpy(&entry->args, &SERP_FILE(dir), sizeof(dir->args)); - -#if DEBUG & DEBUG_EVALPATH - fprintf(stderr,"Looking up '%s'\n",part); -#endif - - rv = nfscall( - nfs->server, - NFSPROC_LOOKUP, - (xdrproc_t) xdr_diropargs, &SERP_FILE(entry), - (xdrproc_t) xdr_serporid, &entry->serporid - ); - - if (rv == 0 && entry->serporid.status == NFS_OK) { - int force_update = 1; - - rv = updateAttr(entry, force_update); - } else { - rv = -1; - } - - return rv; -} - -static void nfs_eval_follow_link( - rtems_filesystem_eval_path_context_t *ctx, - NfsNode link -) -{ - const size_t len = NFS_MAXPATHLEN + 1; - char *buf = malloc(len); - - if (buf != NULL) { - ssize_t rv = nfs_readlink_with_node(link, buf, len); - - if (rv >= 0) { - rtems_filesystem_eval_path_recursive(ctx, buf, (size_t) rv); - } else { - rtems_filesystem_eval_path_error(ctx, 0); - } - - free(buf); - } else { - rtems_filesystem_eval_path_error(ctx, ENOMEM); - } -} - -static void nfs_eval_set_handlers( - rtems_filesystem_eval_path_context_t *ctx, - ftype type -) -{ - rtems_filesystem_location_info_t *currentloc = - rtems_filesystem_eval_path_get_currentloc(ctx); - - switch (type) { - case NFDIR: - currentloc->handlers = &nfs_dir_file_handlers; - break; - case NFREG: - currentloc->handlers = &nfs_file_file_handlers; - break; - case NFLNK: - currentloc->handlers = &nfs_link_file_handlers; - break; - default: - currentloc->handlers = &rtems_filesystem_handlers_default; - break; - } -} - -static int nfs_move_node(NfsNode dst, const NfsNode src, const char *part) -{ - int rv = 0; - - if (dst->str != NULL) { -#if DEBUG & DEBUG_COUNT_NODES - rtems_interrupt_lock_context lock_context; - NFS_GLOBAL_ACQUIRE(&lock_context); - dst->nfs->stringsInUse--; - NFS_GLOBAL_RELEASE(&lock_context); -#endif - free(dst->str); - } - - *dst = *src; - - dst->str = dst->args.name = strdup(part); - if (dst->str != NULL) { -#if DEBUG & DEBUG_COUNT_NODES - rtems_interrupt_lock_context lock_context; - NFS_GLOBAL_ACQUIRE(&lock_context); - dst->nfs->stringsInUse++; - NFS_GLOBAL_RELEASE(&lock_context); -#endif - } else { - rv = -1; - } - - return rv; -} - -static rtems_filesystem_eval_path_generic_status nfs_eval_part( - rtems_filesystem_eval_path_context_t *ctx, - char *part -) -{ - rtems_filesystem_eval_path_generic_status status = - RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE; - rtems_filesystem_location_info_t *currentloc = - rtems_filesystem_eval_path_get_currentloc(ctx); - Nfs nfs = currentloc->mt_entry->fs_info; - NfsNode dir = currentloc->node_access; - NfsNodeRec entry; - int rv = nfs_search_in_directory(nfs, dir, part, &entry); - - if (rv == 0) { - bool terminal = !rtems_filesystem_eval_path_has_path(ctx); - int eval_flags = rtems_filesystem_eval_path_get_flags(ctx); - bool follow_sym_link = (eval_flags & RTEMS_FS_FOLLOW_SYM_LINK) != 0; - ftype type = SERP_ATTR(&entry).type; - - rtems_filesystem_eval_path_clear_token(ctx); - - if (type == NFLNK && (follow_sym_link || !terminal)) { - nfs_eval_follow_link(ctx, &entry); - } else { - rv = nfs_move_node(dir, &entry, part); - if (rv == 0) { - nfs_eval_set_handlers(ctx, type); - if (!terminal) { - status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE; - } - } else { - rtems_filesystem_eval_path_error(ctx, ENOMEM); - } - } - } else { - status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY; - } - - return status; -} - -static rtems_filesystem_eval_path_generic_status nfs_eval_token( - rtems_filesystem_eval_path_context_t *ctx, - void *arg, - const char *token, - size_t tokenlen -) -{ - rtems_filesystem_eval_path_generic_status status = - RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE; - - if (rtems_filesystem_is_current_directory(token, tokenlen)) { - rtems_filesystem_eval_path_clear_token(ctx); - if (rtems_filesystem_eval_path_has_path(ctx)) { - status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE; - } - } else { - char *part = nfs_dupname(token, tokenlen); - - if (part != NULL) { - status = nfs_eval_part(ctx, part); - free(part); - } else { - rtems_filesystem_eval_path_error(ctx, ENOMEM); - } - } - - return status; -} - -static const rtems_filesystem_eval_path_generic_config nfs_eval_config = { - .is_directory = nfs_is_directory, - .eval_token = nfs_eval_token -}; - -static void nfs_eval_path(rtems_filesystem_eval_path_context_t *ctx) -{ - rtems_filesystem_eval_path_generic(ctx, NULL, &nfs_eval_config); -} - -/* create a hard link */ - -static int nfs_link( - const rtems_filesystem_location_info_t *parentloc, - const rtems_filesystem_location_info_t *targetloc, - const char *name, - size_t namelen -) -{ -int rv = 0; -NfsNode pNode = parentloc->node_access; -nfsstat status; -NfsNode tNode = targetloc->node_access; -char *dupname; - - dupname = nfs_dupname(name, namelen); - if (dupname == NULL) - return -1; - -#if DEBUG & DEBUG_SYSCALLS - fprintf(stderr,"Creating link '%s'\n",dupname); -#endif - - memcpy(&SERP_ARGS(tNode).linkarg.to.dir, - &SERP_FILE(pNode), - sizeof(SERP_FILE(pNode))); - - SERP_ARGS(tNode).linkarg.to.name = dupname; - - rv = nfscall( - tNode->nfs->server, - NFSPROC_LINK, - (xdrproc_t)xdr_linkargs, &SERP_FILE(tNode), - (xdrproc_t)xdr_nfsstat, &status - ); - - if (rv == 0) { - rv = nfsEvaluateStatus(status); -#if DEBUG & DEBUG_SYSCALLS - if (rv != 0) { - perror("nfs_link"); - } -#endif - } - - free(dupname); - - return rv; - -} - -static int nfs_do_unlink( - const rtems_filesystem_location_info_t *parentloc, - const rtems_filesystem_location_info_t *loc, - int proc -) -{ -int rv = 0; -nfsstat status; -NfsNode node = loc->node_access; -Nfs nfs = node->nfs; -#if DEBUG & DEBUG_SYSCALLS -char *name = NFSPROC_REMOVE == proc ? - "nfs_unlink" : "nfs_rmdir"; -#endif - - /* The FS generics have determined that pathloc is _not_ - * a directory. Hence we may assume that the parent - * is in our NFS. - */ - -#if DEBUG & DEBUG_SYSCALLS - assert( node->args.name == node->str && node->str ); - - fprintf(stderr,"%s '%s'\n", name, node->args.name); -#endif - - rv = nfscall( - nfs->server, - proc, - (xdrproc_t)xdr_diropargs, &node->args, - (xdrproc_t)xdr_nfsstat, &status - ); - - if (rv == 0) { - rv = nfsEvaluateStatus(status); -#if DEBUG & DEBUG_SYSCALLS - if (rv != 0) { - perror(name); - } -#endif - } - - return rv; -} - -static int nfs_chown( - const rtems_filesystem_location_info_t *pathloc, /* IN */ - uid_t owner, /* IN */ - gid_t group /* IN */ -) -{ -sattr arg; - - arg.uid = owner; - arg.gid = group; - - return nfs_sattr(pathloc->node_access, &arg, SATTR_UID | SATTR_GID); - -} - -static int nfs_clonenode(rtems_filesystem_location_info_t *loc) -{ - NfsNode node = loc->node_access; - - LOCK(nfsGlob.lock); - node = nfsNodeClone(node); - UNLOCK(nfsGlob.lock); - - loc->node_access = node; - - return node != NULL ? 0 : -1; -} - -/* Cleanup the FS private info attached to pathloc->node_access */ -static void nfs_freenode( - const rtems_filesystem_location_info_t *pathloc /* IN */ -) -{ -#if DEBUG & DEBUG_COUNT_NODES -Nfs nfs = ((NfsNode)pathloc->node_access)->nfs; - - /* print counts at entry where they are > 0 so 'nfs' is safe from being destroyed - * and there's no race condition - */ - fprintf(stderr, - "entering freenode, in use count is %i nodes, %i strings\n", - nfs->nodesInUse, - nfs->stringsInUse); -#endif - - nfsNodeDestroy(pathloc->node_access); -} - -/* NOTE/TODO: mounting on top of NFS is not currently supported - * - * Challenge: stateless protocol. It would be possible to - * delete mount points on the server. We would need some sort - * of a 'garbage collector' looking for dead/unreachable - * mount points and unmounting them. - * Also, the path evaluation routine would have to check - * for crossing mount points. Crossing over from one NFS - * into another NFS could probably handled iteratively - * rather than by recursion. - */ - -int rtems_nfs_initialize( - rtems_filesystem_mount_table_entry_t *mt_entry, - const void *data -) -{ -char *host; -struct sockaddr_in saddr; -enum clnt_stat stat; -fhstatus fhstat; -u_long uid,gid; -#ifdef NFS_V2_PORT -int retry; -#endif -Nfs nfs = 0; -NfsNode rootNode = 0; -RpcUdpServer nfsServer = 0; -int e = -1; -char *path = mt_entry->dev; - - if (rpcUdpInit () < 0) { - fprintf (stderr, "error: initialising RPC\n"); - return -1; - } - - if (nfsInit(0, 0) != 0) { - fprintf (stderr, "error: initialising NFS\n"); - return -1; - }; - -#if 0 - printf("Trying to mount %s on %s\n",path,mntpoint); -#endif - - if ( buildIpAddr(&uid, &gid, &host, &saddr, &path) ) - return -1; - -#ifdef NFS_V2_PORT - /* if the portmapper fails, retry a fixed port */ - for (retry = 1, saddr.sin_port = 0, stat = RPC_FAILED; - retry >= 0 && stat; - stat && (saddr.sin_port = htons(NFS_V2_PORT)), retry-- ) -#endif - stat = rpcUdpServerCreate( - &saddr, - NFS_PROGRAM, - NFS_VERSION_2, - uid, - gid, - &nfsServer - ); - - if ( RPC_SUCCESS != stat ) { - fprintf(stderr, - "Unable to contact NFS server - invalid port? (%s)\n", - clnt_sperrno(stat)); - e = EPROTONOSUPPORT; - goto cleanup; - } - - - /* first, try to ping the NFS server by - * calling the NULL proc. - */ - if ( nfscall(nfsServer, - NFSPROC_NULL, - (xdrproc_t)xdr_void, 0, - (xdrproc_t)xdr_void, 0) ) { - - fputs("NFS Ping ",stderr); - fwrite(host, 1, path-host-1, stderr); - fprintf(stderr," failed: %s\n", strerror(errno)); - - e = errno ? errno : EIO; - goto cleanup; - } - - /* that seemed to work - we now try the - * actual mount - */ - - /* reuse server address but let the mntcall() - * search for the mountd's port - */ - saddr.sin_port = 0; - - stat = mntcall( &saddr, - MOUNTPROC_MNT, - (xdrproc_t)xdr_dirpath, - &path, - (xdrproc_t)xdr_fhstatus, - &fhstat, - uid, - gid ); - - if (stat) { - fprintf(stderr,"MOUNT -- %s\n",clnt_sperrno(stat)); - if ( e<=0 ) - e = EIO; - goto cleanup; - } else if (NFS_OK != (e=fhstat.fhs_status)) { - fprintf(stderr,"MOUNT: %s\n",strerror(e)); - goto cleanup; - } - - nfs = nfsCreate(nfsServer); - assert( nfs ); - nfsServer = 0; - - nfs->uid = uid; - nfs->gid = gid; - - /* that seemed to work - we now create the root node - * and we also must obtain the root node attributes - */ - rootNode = nfsNodeCreate(nfs, &fhstat.fhstatus_u.fhs_fhandle); - assert( rootNode ); - - if ( updateAttr(rootNode, 1 /* force */) ) { - e = errno; - goto cleanup; - } - - /* looks good so far */ - - mt_entry->mt_fs_root->location.node_access = rootNode; - - rootNode = 0; - - mt_entry->ops = &nfs_fs_ops; - mt_entry->mt_fs_root->location.handlers = &nfs_dir_file_handlers; - mt_entry->pathconf_limits_and_options = &nfs_limits_and_options; - - LOCK(nfsGlob.llock); - nfsGlob.num_mounted_fs++; - /* allocate a new ID for this FS */ - nfs->id = nfsGlob.fs_ids++; - UNLOCK(nfsGlob.llock); - - mt_entry->fs_info = nfs; - nfs->mt_entry = mt_entry; - nfs = 0; - - e = 0; - -cleanup: - if (nfs) - nfsDestroy(nfs); - if (nfsServer) - rpcUdpServerDestroy(nfsServer); - if (rootNode) - nfsNodeDestroy(rootNode); - if (e) - rtems_set_errno_and_return_minus_one(e); - else - return 0; -} - -/* This op is called when they try to unmount THIS fs */ -STATIC void nfs_fsunmount_me( - rtems_filesystem_mount_table_entry_t *mt_entry /* in */ -) -{ -enum clnt_stat stat; -struct sockaddr_in saddr; -char *path = mt_entry->dev; -int nodesInUse; -u_long uid,gid; -int status; - -LOCK(nfsGlob.llock); - nodesInUse = ((Nfs)mt_entry->fs_info)->nodesInUse; - - if (nodesInUse > 1 /* one ref to the root node used by us */) { - UNLOCK(nfsGlob.llock); - fprintf(stderr, - "Refuse to unmount; there are still %i nodes in use (1 used by us)\n", - nodesInUse); - rtems_fatal_error_occurred(0xdeadbeef); - return; - } - - status = buildIpAddr(&uid, &gid, 0, &saddr, &path); - assert( !status ); - - stat = mntcall( &saddr, - MOUNTPROC_UMNT, - (xdrproc_t)xdr_dirpath, &path, - (xdrproc_t)xdr_void, 0, - uid, - gid - ); - - if (stat) { - UNLOCK(nfsGlob.llock); - fprintf(stderr,"NFS UMOUNT -- %s\n", clnt_sperrno(stat)); - return; - } - - nfsNodeDestroy(mt_entry->mt_fs_root->location.node_access); - mt_entry->mt_fs_root->location.node_access = 0; - - nfsDestroy(mt_entry->fs_info); - mt_entry->fs_info = 0; - - nfsGlob.num_mounted_fs--; -UNLOCK(nfsGlob.llock); -} - -static int nfs_mknod( - const rtems_filesystem_location_info_t *parentloc, - const char *name, - size_t namelen, - mode_t mode, - dev_t dev -) -{ - -int rv = 0; -struct timeval now; -diropres res; -NfsNode node = parentloc->node_access; -Nfs nfs = node->nfs; -mode_t type = S_IFMT & mode; -char *dupname; - - if (type != S_IFDIR && type != S_IFREG) - rtems_set_errno_and_return_minus_one(ENOTSUP); - - dupname = nfs_dupname(name, namelen); - if (dupname == NULL) - return -1; - -#if DEBUG & DEBUG_SYSCALLS - fprintf(stderr,"nfs_mknod: creating %s\n", dupname); -#endif - - rtems_clock_get_tod_timeval(&now); - - SERP_ARGS(node).createarg.name = dupname; - SERP_ARGS(node).createarg.attributes.mode = mode; - SERP_ARGS(node).createarg.attributes.uid = nfs->uid; - SERP_ARGS(node).createarg.attributes.gid = nfs->gid; - SERP_ARGS(node).createarg.attributes.size = 0; - SERP_ARGS(node).createarg.attributes.atime.seconds = now.tv_sec; - SERP_ARGS(node).createarg.attributes.atime.useconds = now.tv_usec; - SERP_ARGS(node).createarg.attributes.mtime.seconds = now.tv_sec; - SERP_ARGS(node).createarg.attributes.mtime.useconds = now.tv_usec; - - rv = nfscall( - nfs->server, - (type == S_IFDIR) ? NFSPROC_MKDIR : NFSPROC_CREATE, - (xdrproc_t)xdr_createargs, &SERP_FILE(node), - (xdrproc_t)xdr_diropres, &res - ); - - if (rv == 0) { - rv = nfsEvaluateStatus(res.status); -#if DEBUG & DEBUG_SYSCALLS - if (rv != 0) { - perror("nfs_mknod"); - } -#endif - } - - free(dupname); - - return rv; -} - -static int nfs_rmnod( - const rtems_filesystem_location_info_t *parentloc, - const rtems_filesystem_location_info_t *loc -) -{ - int rv = 0; - NfsNode node = loc->node_access; - int force_update = 0; - - if (updateAttr(node, force_update) == 0) { - int proc = SERP_ATTR(node).type == NFDIR - ? NFSPROC_RMDIR - : NFSPROC_REMOVE; - - rv = nfs_do_unlink(parentloc, loc, proc); - } else { - rv = -1; - } - - return rv; -} - -static int nfs_utime( - const rtems_filesystem_location_info_t *pathloc, /* IN */ - time_t actime, /* IN */ - time_t modtime /* IN */ -) -{ -sattr arg; - - /* TODO: add rtems EPOCH - UNIX EPOCH seconds */ - arg.atime.seconds = actime; - arg.atime.useconds = 0; - arg.mtime.seconds = modtime; - arg.mtime.useconds = 0; - - return nfs_sattr(pathloc->node_access, &arg, SATTR_ATIME | SATTR_MTIME); -} - -static int nfs_symlink( - const rtems_filesystem_location_info_t *parentloc, - const char *name, - size_t namelen, - const char *target -) -{ -int rv = 0; -struct timeval now; -nfsstat status; -NfsNode node = parentloc->node_access; -Nfs nfs = node->nfs; -char *dupname; - - dupname = nfs_dupname(name, namelen); - if (dupname == NULL) - return -1; - -#if DEBUG & DEBUG_SYSCALLS - fprintf(stderr,"nfs_symlink: creating %s -> %s\n", dupname, target); -#endif - - rtems_clock_get_tod_timeval(&now); - - SERP_ARGS(node).symlinkarg.name = dupname; - SERP_ARGS(node).symlinkarg.to = (nfspath) target; - - SERP_ARGS(node).symlinkarg.attributes.mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; - SERP_ARGS(node).symlinkarg.attributes.uid = nfs->uid; - SERP_ARGS(node).symlinkarg.attributes.gid = nfs->gid; - SERP_ARGS(node).symlinkarg.attributes.size = 0; - SERP_ARGS(node).symlinkarg.attributes.atime.seconds = now.tv_sec; - SERP_ARGS(node).symlinkarg.attributes.atime.useconds = now.tv_usec; - SERP_ARGS(node).symlinkarg.attributes.mtime.seconds = now.tv_sec; - SERP_ARGS(node).symlinkarg.attributes.mtime.useconds = now.tv_usec; - - rv = nfscall( - nfs->server, - NFSPROC_SYMLINK, - (xdrproc_t)xdr_symlinkargs, &SERP_FILE(node), - (xdrproc_t)xdr_nfsstat, &status - ); - - if (rv == 0) { - rv = nfsEvaluateStatus(status); -#if DEBUG & DEBUG_SYSCALLS - perror("nfs_symlink"); -#endif - } - - free(dupname); - - return rv; -} - -static ssize_t nfs_readlink_with_node( - NfsNode node, - char *buf, - size_t len -) -{ - ssize_t rv; - Nfs nfs = node->nfs; - readlinkres_strbuf rr; - - rr.strbuf.buf = buf; - rr.strbuf.max = len - 1; - - rv = nfscall( - nfs->server, - NFSPROC_READLINK, - (xdrproc_t)xdr_nfs_fh, &SERP_FILE(node), - (xdrproc_t)xdr_readlinkres_strbuf, &rr - ); - - if (rv == 0) { - rv = nfsEvaluateStatus(rr.status); - - if (rv == 0) { - rv = (ssize_t) strlen(rr.strbuf.buf); - } else { -#if DEBUG & DEBUG_SYSCALLS - perror("nfs_readlink_with_node"); -#endif - } - } - - return rv; -} - -static ssize_t nfs_readlink( - const rtems_filesystem_location_info_t *loc, - char *buf, - size_t len -) -{ - NfsNode node = loc->node_access; - - return nfs_readlink_with_node(node, buf, len); -} - -static int nfs_rename( - const rtems_filesystem_location_info_t *oldparentloc, - const rtems_filesystem_location_info_t *oldloc, - const rtems_filesystem_location_info_t *newparentloc, - const char *name, - size_t namelen -) -{ - int rv = 0; - char *dupname = nfs_dupname(name, namelen); - - if (dupname != NULL) { - NfsNode oldParentNode = oldparentloc->node_access; - NfsNode oldNode = oldloc->node_access; - NfsNode newParentNode = newparentloc->node_access; - Nfs nfs = oldParentNode->nfs; - const nfs_fh *toDirSrc = &SERP_FILE(newParentNode); - nfs_fh *toDirDst = &SERP_ARGS(oldParentNode).renamearg.to.dir; - nfsstat status; - - SERP_ARGS(oldParentNode).renamearg.name = oldNode->str; - SERP_ARGS(oldParentNode).renamearg.to.name = dupname; - memcpy(toDirDst, toDirSrc, sizeof(*toDirDst)); - - rv = nfscall( - nfs->server, - NFSPROC_RENAME, - (xdrproc_t) xdr_renameargs, - &SERP_FILE(oldParentNode), - (xdrproc_t) xdr_nfsstat, - &status - ); - - if (rv == 0) { - rv = nfsEvaluateStatus(status); - } - - free(dupname); - } else { - rv = -1; - } - - return rv; -} - -static void nfs_lock(const rtems_filesystem_mount_table_entry_t *mt_entry) -{ -} - -static void nfs_unlock(const rtems_filesystem_mount_table_entry_t *mt_entry) -{ -} - -static bool nfs_are_nodes_equal( - const rtems_filesystem_location_info_t *a, - const rtems_filesystem_location_info_t *b -) -{ - bool equal = false; - NfsNode na = a->node_access; - - if (updateAttr(na, 0) == 0) { - NfsNode nb = b->node_access; - - if (updateAttr(nb, 0) == 0) { - equal = SERP_ATTR(na).fileid == SERP_ATTR(nb).fileid - && SERP_ATTR(na).fsid == SERP_ATTR(nb).fsid; - } - } - - return equal; -} - -static int nfs_fchmod( - const rtems_filesystem_location_info_t *loc, - mode_t mode -) -{ -sattr arg; - - arg.mode = mode; - return nfs_sattr(loc->node_access, &arg, SATTR_MODE); - -} - -const struct _rtems_filesystem_operations_table nfs_fs_ops = { - .lock_h = nfs_lock, - .unlock_h = nfs_unlock, - .eval_path_h = nfs_eval_path, - .link_h = nfs_link, - .are_nodes_equal_h = nfs_are_nodes_equal, - .mknod_h = nfs_mknod, - .rmnod_h = nfs_rmnod, - .fchmod_h = nfs_fchmod, - .chown_h = nfs_chown, - .clonenod_h = nfs_clonenode, - .freenod_h = nfs_freenode, - .mount_h = rtems_filesystem_default_mount, - .unmount_h = rtems_filesystem_default_unmount, - .fsunmount_me_h = nfs_fsunmount_me, - .utime_h = nfs_utime, - .symlink_h = nfs_symlink, - .readlink_h = nfs_readlink, - .rename_h = nfs_rename, - .statvfs_h = rtems_filesystem_default_statvfs -}; - -/***************************************** - File Handlers - - NOTE: the FS generics expect a FS' - evalpath_h() to switch the - pathloc->handlers according - to the pathloc/node's file - type. - We currently have 'file' and - 'directory' handlers and very - few 'symlink' handlers. - - The handlers for each type are - implemented or #defined ZERO - in a 'nfs_file_xxx', - 'nfs_dir_xxx', 'nfs_link_xxx' - sequence below this point. - - In some cases, a common handler, - can be used for all file types. - It is then simply called - 'nfs_xxx'. - *****************************************/ - -/* stateless NFS protocol makes this trivial */ -static int nfs_file_open( - rtems_libio_t *iop, - const char *pathname, - int oflag, - mode_t mode -) -{ - return 0; -} - -/* reading directories is not stateless; we must - * remember the last 'read' position, i.e. - * the server 'cookie'. We do manage this information - * attached to the pathinfo.node_access_2. - */ -static int nfs_dir_open( - rtems_libio_t *iop, - const char *pathname, - int oflag, - mode_t mode -) -{ -NfsNode node = iop->pathinfo.node_access; -DirInfo di; - - /* create a readdirargs object and copy the file handle; - * attach to the pathinfo.node_access_2 - */ - - di = (DirInfo) malloc(sizeof(*di)); - iop->pathinfo.node_access_2 = di; - - if ( !di ) { - errno = ENOMEM; - return -1; - } - - memcpy( &di->readdirargs.dir, - &SERP_FILE(node), - sizeof(di->readdirargs.dir) ); - - /* rewind cookie */ - memset( &di->readdirargs.cookie, - 0, - sizeof(di->readdirargs.cookie) ); - - di->eofreached = FALSE; - - return 0; -} - -static int nfs_file_close( - rtems_libio_t *iop -) -{ - return 0; -} - -static int nfs_dir_close( - rtems_libio_t *iop -) -{ - free(iop->pathinfo.node_access_2); - iop->pathinfo.node_access_2 = 0; - return 0; -} - -static ssize_t nfs_file_read_chunk( - NfsNode node, - uint32_t offset, - void *buffer, - size_t count -) -{ -ssize_t rv; -readres rr; -Nfs nfs = node->nfs; - - SERP_ARGS(node).readarg.offset = offset; - SERP_ARGS(node).readarg.count = count; - SERP_ARGS(node).readarg.totalcount = UINT32_C(0xdeadbeef); - - rr.readres_u.reply.data.data_val = buffer; - - rv = nfscall( - nfs->server, - NFSPROC_READ, - (xdrproc_t)xdr_readargs, &SERP_FILE(node), - (xdrproc_t)xdr_readres, &rr - ); - - if (rv == 0) { - rv = nfsEvaluateStatus(rr.status); - - if (rv == 0) { - rv = rr.readres_u.reply.data.data_len; - -#if DEBUG & DEBUG_SYSCALLS - fprintf(stderr, - "Read %i (asked for %i) bytes from offset %i to 0x%08x\n", - rr.readres_u.reply.data.data_len, - count, - iop->offset, - rr.readres_u.reply.data.data_val); -#endif - } - } - - return rv; -} - -static ssize_t nfs_file_read( - rtems_libio_t *iop, - void *buffer, - size_t count -) -{ - ssize_t rv = 0; - NfsNode node = iop->pathinfo.node_access; - uint32_t offset = iop->offset; - char *in = buffer; - - if (iop->offset < 0) { - errno = EINVAL; - return -1; - } - - if ((uintmax_t) iop->offset >= UINT32_MAX) { - errno = EFBIG; - return -1; - } - - if (count > UINT32_MAX - offset) { - count = UINT32_MAX - offset; - } - - do { - size_t chunk = count <= NFS_MAXDATA ? count : NFS_MAXDATA; - ssize_t done = nfs_file_read_chunk(node, offset, in, chunk); - - if (done > 0) { - offset += (uint32_t) done; - in += done; - count -= (size_t) done; - rv += done; - } else { - count = 0; - if (done < 0) { - rv = -1; - } - } - } while (count > 0); - - if (rv > 0) { - iop->offset = offset; - } - - return rv; -} - -/* this is called by readdir() / getdents() */ -static ssize_t nfs_dir_read( - rtems_libio_t *iop, - void *buffer, - size_t count -) -{ -ssize_t rv; -DirInfo di = iop->pathinfo.node_access_2; -RpcUdpServer server = ((Nfs)iop->pathinfo.mt_entry->fs_info)->server; - - if ( di->eofreached ) - return 0; - - di->ptr = di->buf = buffer; - - /* align + round down the buffer */ - count &= ~ (DIRENT_HEADER_SIZE - 1); - di->len = count; - -#if 0 - /* now estimate the number of entries we should ask for */ - count /= DIRENT_HEADER_SIZE + CONFIG_AVG_NAMLEN; - - /* estimate the encoded size that might take up */ - count *= dirres_entry_size + CONFIG_AVG_NAMLEN; -#else - /* integer arithmetics are better done the other way round */ - count *= dirres_entry_size + CONFIG_AVG_NAMLEN; - count /= DIRENT_HEADER_SIZE + CONFIG_AVG_NAMLEN; -#endif - - if (count > NFS_MAXDATA) - count = NFS_MAXDATA; - - di->readdirargs.count = count; - -#if DEBUG & DEBUG_READDIR - fprintf(stderr, - "Readdir: asking for %i XDR bytes, buffer is %i\n", - count, di->len); -#endif - - rv = nfscall( - server, - NFSPROC_READDIR, - (xdrproc_t)xdr_readdirargs, &di->readdirargs, - (xdrproc_t)xdr_dir_info, di - ); - - if (rv == 0) { - rv = nfsEvaluateStatus(di->status); - - if (rv == 0) { - rv = (char*)di->ptr - (char*)buffer; - } - } - - return rv; -} - -static ssize_t nfs_file_write( - rtems_libio_t *iop, - const void *buffer, - size_t count -) -{ -ssize_t rv; -NfsNode node = iop->pathinfo.node_access; -Nfs nfs = node->nfs; - - if (count > NFS_MAXDATA) - count = NFS_MAXDATA; - - - SERP_ARGS(node).writearg.beginoffset = UINT32_C(0xdeadbeef); - if (rtems_libio_iop_is_append(iop)) { - if ( updateAttr(node, 0) ) { - return -1; - } - if (SERP_ATTR(node).size >= UINT32_MAX) { - errno = EFBIG; - return -1; - } - SERP_ARGS(node).writearg.offset = SERP_ATTR(node).size; - } else { - if (iop->offset < 0) { - errno = EINVAL; - return -1; - } - if ((uintmax_t) iop->offset >= UINT32_MAX) { - errno = EFBIG; - return -1; - } - SERP_ARGS(node).writearg.offset = iop->offset; - } - - if (count > UINT32_MAX - SERP_ARGS(node).writearg.offset) { - count = UINT32_MAX - SERP_ARGS(node).writearg.offset; - } - - SERP_ARGS(node).writearg.totalcount = UINT32_C(0xdeadbeef); - SERP_ARGS(node).writearg.data.data_len = count; - SERP_ARGS(node).writearg.data.data_val = (void*)buffer; - - /* write XDR buffer size will be chosen by nfscall based - * on the PROC specifier - */ - - rv = nfscall( - nfs->server, - NFSPROC_WRITE, - (xdrproc_t)xdr_writeargs, &SERP_FILE(node), - (xdrproc_t)xdr_attrstat, &node->serporid - ); - - if (rv == 0) { - rv = nfsEvaluateStatus(node->serporid.status); - - if (rv == 0) { - node->age = nowSeconds(); - - iop->offset += count; - rv = count; - } else { - /* try at least to recover the current attributes */ - updateAttr(node, 1 /* force */); - } - } - - return rv; -} - -static off_t nfs_dir_lseek( - rtems_libio_t *iop, - off_t length, - int whence -) -{ - off_t rv = rtems_filesystem_default_lseek_directory(iop, length, whence); - - if (rv == 0) { - DirInfo di = iop->pathinfo.node_access_2; - nfscookie *cookie = &di->readdirargs.cookie; - - di->eofreached = FALSE; - - /* rewind cookie */ - memset(cookie, 0, sizeof(*cookie)); - } - - return rv; -} - -#if 0 /* structure types for reference */ -struct fattr { - ftype type; - u_int mode; - u_int nlink; - u_int uid; - u_int gid; - u_int size; - u_int blocksize; - u_int rdev; - u_int blocks; - u_int fsid; - u_int fileid; - nfstime atime; - nfstime mtime; - nfstime ctime; -}; - -struct stat -{ - dev_t st_dev; - ino_t st_ino; - mode_t st_mode; - nlink_t st_nlink; - uid_t st_uid; - gid_t st_gid; - dev_t st_rdev; - off_t st_size; - /* SysV/sco doesn't have the rest... But Solaris, eabi does. */ -#if defined(__svr4__) && !defined(__PPC__) && !defined(__sun__) - time_t st_atime; - time_t st_mtime; - time_t st_ctime; -#else - time_t st_atime; - long st_spare1; - time_t st_mtime; - long st_spare2; - time_t st_ctime; - long st_spare3; - long st_blksize; - long st_blocks; - long st_spare4[2]; -#endif -}; -#endif - -/* common for file/dir/link */ -static int nfs_fstat( - const rtems_filesystem_location_info_t *loc, - struct stat *buf -) -{ -NfsNode node = loc->node_access; -fattr *fa = &SERP_ATTR(node); - - if (updateAttr(node, 0 /* only if old */)) { - return -1; - } - -/* done by caller - memset(buf, 0, sizeof(*buf)); - */ - - /* translate */ - - /* one of the branches hopefully is optimized away */ - if (sizeof(ino_t) < sizeof(u_int)) { - buf->st_dev = NFS_MAKE_DEV_T_INO_HACK((NfsNode)loc->node_access); - } else { - buf->st_dev = NFS_MAKE_DEV_T((NfsNode)loc->node_access); - } - buf->st_mode = fa->mode; - buf->st_nlink = fa->nlink; - buf->st_uid = fa->uid; - buf->st_gid = fa->gid; - buf->st_size = fa->size; - /* Set to "preferred size" of this NFS client implementation */ - buf->st_blksize = nfsStBlksize ? nfsStBlksize : fa->blocksize; - buf->st_rdev = fa->rdev; - buf->st_blocks = fa->blocks; - buf->st_ino = fa->fileid; - buf->st_atime = fa->atime.seconds; - buf->st_mtime = fa->mtime.seconds; - buf->st_ctime = fa->ctime.seconds; - -#if 0 /* NFS should return the modes */ - switch(fa->type) { - default: - case NFNON: - case NFBAD: - break; - - case NFSOCK: buf->st_mode |= S_IFSOCK; break; - case NFFIFO: buf->st_mode |= S_IFIFO; break; - case NFREG : buf->st_mode |= S_IFREG; break; - case NFDIR : buf->st_mode |= S_IFDIR; break; - case NFBLK : buf->st_mode |= S_IFBLK; break; - case NFCHR : buf->st_mode |= S_IFCHR; break; - case NFLNK : buf->st_mode |= S_IFLNK; break; - } -#endif - - return 0; -} - -/* a helper which does the real work for - * a couple of handlers (such as chmod, - * ftruncate or utime) - */ -static int -nfs_sattr(NfsNode node, sattr *arg, u_long mask) -{ -int rv; -struct timeval now; -nfstime nfsnow, t; -u_int mode; - - if (updateAttr(node, 0 /* only if old */)) - return -1; - - rtems_clock_get_tod_timeval(&now); - - /* TODO: add rtems EPOCH - UNIX EPOCH seconds */ - nfsnow.seconds = now.tv_sec; - nfsnow.useconds = now.tv_usec; - - /* merge permission bits into existing type bits */ - mode = SERP_ATTR(node).mode; - if (mask & SATTR_MODE) { - mode &= S_IFMT; - mode |= arg->mode & ~S_IFMT; - } else { - mode = -1; - } - SERP_ARGS(node).sattrarg.attributes.mode = mode; - - SERP_ARGS(node).sattrarg.attributes.uid = - (mask & SATTR_UID) ? arg->uid : -1; - - SERP_ARGS(node).sattrarg.attributes.gid = - (mask & SATTR_GID) ? arg->gid : -1; - - SERP_ARGS(node).sattrarg.attributes.size = - (mask & SATTR_SIZE) ? arg->size : -1; - - if (mask & SATTR_ATIME) - t = arg->atime; - else if (mask & SATTR_TOUCHA) - t = nfsnow; - else - t.seconds = t.useconds = -1; - SERP_ARGS(node).sattrarg.attributes.atime = t; - - if (mask & SATTR_ATIME) - t = arg->mtime; - else if (mask & SATTR_TOUCHA) - t = nfsnow; - else - t.seconds = t.useconds = -1; - SERP_ARGS(node).sattrarg.attributes.mtime = t; - - node->serporid.status = NFS_OK; - - rv = nfscall( - node->nfs->server, - NFSPROC_SETATTR, - (xdrproc_t)xdr_sattrargs, &SERP_FILE(node), - (xdrproc_t)xdr_attrstat, &node->serporid - ); - - if (rv == 0) { - rv = nfsEvaluateStatus(node->serporid.status); - - if (rv == 0) { - node->age = nowSeconds(); - } else { -#if DEBUG & DEBUG_SYSCALLS - fprintf(stderr,"nfs_sattr: %s\n",strerror(errno)); -#endif - /* try at least to recover the current attributes */ - updateAttr(node, 1 /* force */); - } - } else { -#if DEBUG & DEBUG_SYSCALLS - fprintf(stderr, - "nfs_sattr (mask 0x%08x): %s", - mask, - strerror(errno)); -#endif - } - - return rv; -} - -/* just set the size attribute to 'length' - * the server will take care of the rest :-) - */ -static int nfs_file_ftruncate( - rtems_libio_t *iop, - off_t length -) -{ -sattr arg; - - if (length < 0) { - errno = EINVAL; - return -1; - } - - if ((uintmax_t) length > UINT32_MAX) { - errno = EFBIG; - return -1; - } - - arg.size = length; - /* must not modify any other attribute; if we are not the owner - * of the file or directory but only have write access changing - * any attribute besides 'size' will fail... - */ - return nfs_sattr(iop->pathinfo.node_access, - &arg, - SATTR_SIZE); -} - -/* the file handlers table */ -static const -struct _rtems_filesystem_file_handlers_r nfs_file_file_handlers = { - .open_h = nfs_file_open, - .close_h = nfs_file_close, - .read_h = nfs_file_read, - .write_h = nfs_file_write, - .ioctl_h = rtems_filesystem_default_ioctl, - .lseek_h = rtems_filesystem_default_lseek_file, - .fstat_h = nfs_fstat, - .ftruncate_h = nfs_file_ftruncate, - .fsync_h = rtems_filesystem_default_fsync_or_fdatasync, - .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync, - .fcntl_h = rtems_filesystem_default_fcntl, - .kqfilter_h = rtems_filesystem_default_kqfilter, - .mmap_h = rtems_filesystem_default_mmap, - .poll_h = rtems_filesystem_default_poll, - .readv_h = rtems_filesystem_default_readv, - .writev_h = rtems_filesystem_default_writev -}; - -/* the directory handlers table */ -static const -struct _rtems_filesystem_file_handlers_r nfs_dir_file_handlers = { - .open_h = nfs_dir_open, - .close_h = nfs_dir_close, - .read_h = nfs_dir_read, - .write_h = rtems_filesystem_default_write, - .ioctl_h = rtems_filesystem_default_ioctl, - .lseek_h = nfs_dir_lseek, - .fstat_h = nfs_fstat, - .ftruncate_h = rtems_filesystem_default_ftruncate_directory, - .fsync_h = rtems_filesystem_default_fsync_or_fdatasync, - .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync, - .fcntl_h = rtems_filesystem_default_fcntl, - .kqfilter_h = rtems_filesystem_default_kqfilter, - .mmap_h = rtems_filesystem_default_mmap, - .poll_h = rtems_filesystem_default_poll, - .readv_h = rtems_filesystem_default_readv, - .writev_h = rtems_filesystem_default_writev -}; - -/* the link handlers table */ -static const -struct _rtems_filesystem_file_handlers_r nfs_link_file_handlers = { - .open_h = rtems_filesystem_default_open, - .close_h = rtems_filesystem_default_close, - .read_h = rtems_filesystem_default_read, - .write_h = rtems_filesystem_default_write, - .ioctl_h = rtems_filesystem_default_ioctl, - .lseek_h = rtems_filesystem_default_lseek, - .fstat_h = nfs_fstat, - .ftruncate_h = rtems_filesystem_default_ftruncate, - .fsync_h = rtems_filesystem_default_fsync_or_fdatasync, - .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync, - .fcntl_h = rtems_filesystem_default_fcntl, - .kqfilter_h = rtems_filesystem_default_kqfilter, - .mmap_h = rtems_filesystem_default_mmap, - .poll_h = rtems_filesystem_default_poll, - .readv_h = rtems_filesystem_default_readv, - .writev_h = rtems_filesystem_default_writev -}; - -/* we need a dummy driver entry table to get a - * major number from the system - */ -static -rtems_device_driver nfs_initialize( - rtems_device_major_number major, - rtems_device_minor_number minor, - void *arg -) -{ - /* we don't really use this routine because - * we cannot supply an argument (contrary - * to what the 'arg' parameter suggests - it - * is always set to 0 by the generics :-() - * and because we don't want the user to - * have to deal with the major number (which - * OTOH is something WE are interested in. The - * only reason for using this API was getting - * a major number, after all). - * - * Something must be present, however, to - * reserve a slot in the driver table. - */ - return RTEMS_SUCCESSFUL; -} - -static rtems_driver_address_table drvNfs = { - nfs_initialize, - 0, /* open */ - 0, /* close */ - 0, /* read */ - 0, /* write */ - 0 /* control */ -}; - -/* Dump a list of the currently mounted NFS to a file */ -int -nfsMountsShow(FILE *f) -{ -char *mntpt = 0; -Nfs nfs; - - if (!f) - f = stdout; - - if ( !(mntpt=malloc(MAXPATHLEN)) ) { - fprintf(stderr,"nfsMountsShow(): no memory\n"); - return -1; - } - - fprintf(f,"Currently Mounted NFS:\n"); - - LOCK(nfsGlob.llock); - - for (nfs = nfsGlob.mounted_fs; nfs; nfs=nfs->next) { - fprintf(f,"%s on ", nfs->mt_entry->dev); - if (rtems_filesystem_resolve_location(mntpt, MAXPATHLEN, &nfs->mt_entry->mt_fs_root->location)) - fprintf(f,"\n"); - else - fprintf(f,"%s\n",mntpt); - } - - UNLOCK(nfsGlob.llock); - - free(mntpt); - return 0; -} - -#if 0 -CCJ_REMOVE_MOUNT -/* 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) -{ -struct stat st; -int devl; -char *host; -int rval = -1; -char *dev = 0; - - if (!uidhost || !path || !mntpoint) { - fprintf(stderr,"usage: nfsMount(""[uid.gid@]host"",""path"",""mountpoint"")\n"); - nfsMountsShow(stderr); - return -1; - } - - if ( !(dev = malloc((devl=strlen(uidhost) + 20 + strlen(path)+1))) ) { - fprintf(stderr,"nfsMount: out of memory\n"); - return -1; - } - - /* Try to create the mount point if nonexistent */ - if (stat(mntpoint, &st)) { - if (ENOENT != errno) { - perror("nfsMount trying to create mount point - stat failed"); - goto cleanup; - } else if (mkdir(mntpoint,0777)) { - perror("nfsMount trying to create mount point"); - goto cleanup; - } - } - - if ( !(host=strchr(uidhost,UIDSEP)) ) { - host = uidhost; - } else { - host++; - } - - if (isdigit((unsigned char)*host)) { - /* avoid using gethostbyname */ - sprintf(dev,"%s:%s",uidhost,path); - } else { - struct hostent *h; - - /* copy the uid part (hostname will be - * overwritten) - */ - strcpy(dev, uidhost); - - /* NOTE NOTE NOTE: gethostbyname is NOT - * thread safe. This is UGLY - */ - -/* BEGIN OF NON-THREAD SAFE REGION */ - - h = gethostbyname(host); - - if ( !h || - !inet_ntop( AF_INET, - (struct in_addr*)h->h_addr_list[0], - dev + (host - uidhost), - devl - (host - uidhost) ) - ) { - fprintf(stderr,"nfsMount: host '%s' not found\n",host); - goto cleanup; - } - -/* END OF NON-THREAD SAFE REGION */ - - /* append ':' */ - strcat(dev,":"); - strcat(dev,path); - } - - printf("Trying to mount %s on %s\n",dev,mntpoint); - - if (mount(dev, - mntpoint, - "nfs", - RTEMS_FILESYSTEM_READ_WRITE, - NULL)) { - perror("nfsMount - mount"); - goto cleanup; - } - - rval = 0; - -cleanup: - free(dev); - return rval; -} -#endif - -/* HERE COMES A REALLY UGLY HACK */ - -/* This is stupid; it is _very_ hard to find the path - * leading to a rtems_filesystem_location_info_t node :-( - * The only easy way is making the location the current - * directory and issue a getcwd(). - * However, since we don't want to tamper with the - * current directory, we must create a separate - * task to do the job for us - sigh. - */ - -typedef struct ResolvePathArgRec_ { - rtems_filesystem_location_info_t *loc; /* IN: location to resolve */ - char *buf; /* IN/OUT: buffer where to put the path */ - int len; /* IN: buffer length */ - rtems_binary_semaphore sync; /* IN: synchronization */ - rtems_status_code status; /* OUT: result */ -} ResolvePathArgRec, *ResolvePathArg; - -static void -resolve_path(rtems_task_argument arg) -{ -ResolvePathArg rpa = (ResolvePathArg)arg; -rtems_filesystem_location_info_t old; - - /* IMPORTANT: let the helper task have its own libio environment (i.e. cwd) */ - if (RTEMS_SUCCESSFUL == (rpa->status = rtems_libio_set_private_env())) { - - old = rtems_filesystem_current->location; - - rtems_filesystem_current->location = *(rpa->loc); - - if ( !getcwd(rpa->buf, rpa->len) ) - rpa->status = RTEMS_UNSATISFIED; - - /* must restore the cwd because 'freenode' will be called on it */ - rtems_filesystem_current->location = old; - } - rtems_binary_semaphore_post(&rpa->sync); - rtems_task_exit(); -} - - -/* a utility routine to find the path leading to a - * rtems_filesystem_location_info_t node - * - * INPUT: 'loc' and a buffer 'buf' (length 'len') to hold the - * path. - * OUTPUT: path copied into 'buf' - * - * RETURNS: 0 on success, RTEMS error code on error. - */ -rtems_status_code -rtems_filesystem_resolve_location(char *buf, int len, rtems_filesystem_location_info_t *loc) -{ -ResolvePathArgRec arg; -rtems_id tid = 0; -rtems_task_priority pri; -rtems_status_code status; - - arg.loc = loc; - arg.buf = buf; - arg.len = len; - - rtems_binary_semaphore_init(&arg.sync, "NFSress"); - - rtems_task_set_priority(RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &pri); - - status = rtems_task_create( - rtems_build_name('r','e','s','s'), - pri, - RTEMS_MINIMUM_STACK_SIZE + 50000, - RTEMS_DEFAULT_MODES, - RTEMS_DEFAULT_ATTRIBUTES, - &tid); - - if (RTEMS_SUCCESSFUL != status) - goto cleanup; - - status = rtems_task_start(tid, resolve_path, (rtems_task_argument)&arg); - - if (RTEMS_SUCCESSFUL != status) { - rtems_task_delete(tid); - goto cleanup; - } - - - /* synchronize with the helper task */ - rtems_binary_semaphore_wait(&arg.sync); - - status = arg.status; - -cleanup: - rtems_binary_semaphore_destroy(&arg.sync); - - return status; -} - -int -nfsSetTimeout(uint32_t timeout_ms) -{ -rtems_interrupt_lock_context lock_context; -uint32_t s,us; - - if ( timeout_ms > 100000 ) { - /* out of range */ - return -1; - } - - s = timeout_ms/1000; - us = (timeout_ms % 1000) * 1000; - - NFS_GLOBAL_ACQUIRE(&lock_context); - _nfscalltimeout.tv_sec = s; - _nfscalltimeout.tv_usec = us; - NFS_GLOBAL_RELEASE(&lock_context); - - return 0; -} - -uint32_t -nfsGetTimeout( void ) -{ -rtems_interrupt_lock_context lock_context; -uint32_t s,us; - NFS_GLOBAL_ACQUIRE(&lock_context); - s = _nfscalltimeout.tv_sec; - us = _nfscalltimeout.tv_usec; - NFS_GLOBAL_RELEASE(&lock_context); - return s*1000 + us/1000; -} diff --git a/cpukit/libfs/src/nfsclient/src/nfsclient-private.h b/cpukit/libfs/src/nfsclient/src/nfsclient-private.h deleted file mode 100644 index e1d81a40f6..0000000000 --- a/cpukit/libfs/src/nfsclient/src/nfsclient-private.h +++ /dev/null @@ -1,14 +0,0 @@ -struct mbuf; -struct sockaddr; - -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)); - -ssize_t recv_mbuf_from(int s, struct mbuf **ppm, long len, - struct sockaddr *fromaddr, int *fromlen); - -struct __rpc_xdr; -enum xdr_op; - -void xdrmbuf_create(struct __rpc_xdr *, struct mbuf *, enum xdr_op); diff --git a/cpukit/libfs/src/nfsclient/src/rpcio.c b/cpukit/libfs/src/nfsclient/src/rpcio.c deleted file mode 100644 index ce5abe3149..0000000000 --- a/cpukit/libfs/src/nfsclient/src/rpcio.c +++ /dev/null @@ -1,1774 +0,0 @@ -/** - * @file - * - * @ingroup RTEMSFileSystemNFS - * - * @brief RPC Multiplexor for a Multitasking Environment - * - * This code funnels arbitrary task's UDP/RPC requests - * through one socket to arbitrary servers. - * The replies are gathered and dispatched to the - * requestors. - * One task handles all the sending and receiving - * work including retries. - * It is up to the requestor, however, to do - * the XDR encoding of the arguments / decoding - * of the results (except for the RPC header which - * is handled by the daemon). - */ - -/* - * Author: Till Straumann , 2002 - * - * Authorship - * ---------- - * This software (NFS-2 client implementation for RTEMS) was created by - * Till Straumann , 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rpcio.h" -#include "nfsclient-private.h" - -/****************************************************************/ -/* CONFIGURABLE PARAMETERS */ -/****************************************************************/ - -#define MBUF_RX /* If defined: use mbuf XDR stream for - * decoding directly out of mbufs - * Otherwise, the regular 'recvfrom()' - * interface will be used involving an - * extra buffer allocation + copy step. - */ - -#define MBUF_TX /* If defined: avoid copying data when - * sending. Instead, use a wrapper to - * 'sosend()' which will point an MBUF - * directly to our buffer space. - * Note that the BSD stack does not copy - * data when fragmenting packets - it - * merely uses an mbuf chain pointing - * into different areas of the data. - * - * If undefined, the regular 'sendto()' - * interface is used. - */ - -#undef REJECT_SERVERIP_MISMATCH - /* If defined, RPC replies must come from the server - * that was queried. Eric Norum has reported problems - * with clustered NFS servers. So we disable this - * reducing paranoia... - */ - -/* daemon task parameters */ -#define RPCIOD_STACK 10000 -#define RPCIOD_PRIO 100 /* *fallback* priority */ - -/* depth of the message queue for sending - * RPC requests to the daemon - */ -#define RPCIOD_QDEPTH 20 - -/* Maximum retry limit for retransmission */ -#define RPCIOD_RETX_CAP_S 3 /* seconds */ - -/* Default timeout for RPC calls */ -#define RPCIOD_DEFAULT_TIMEOUT (&_rpc_default_timeout) -static struct timeval _rpc_default_timeout = { 10 /* secs */, 0 /* usecs */ }; - -/* how many times should we try to resend a failed - * transaction with refreshed AUTHs - */ -#define RPCIOD_REFRESH 2 - -/* Events we are using; the RPC_EVENT - * MUST NOT be used by any application - * thread doing RPC IO (e.g. NFS) - */ -#define RTEMS_RPC_EVENT RTEMS_EVENT_30 /* THE event used by RPCIO. Every task doing - * RPC IO will receive this - hence it is - * RESERVED - */ -#define RPCIOD_RX_EVENT RTEMS_EVENT_1 /* Events the RPCIOD is using/waiting for */ -#define RPCIOD_TX_EVENT RTEMS_EVENT_2 -#define RPCIOD_KILL_EVENT RTEMS_EVENT_3 /* send to the daemon to kill it */ - -#define LD_XACT_HASH 8 /* ld of the size of the transaction hash table */ - - -/* Debugging Flags */ - -/* NOTE: defining DEBUG 0 leaves some 'assert()' paranoia checks - * but produces no output - */ - -#define DEBUG_TRACE_XACT (1<<0) -#define DEBUG_EVENTS (1<<1) -#define DEBUG_MALLOC (1<<2) -#define DEBUG_TIMEOUT (1<<3) -#define DEBUG_PACKLOSS (1<<4) /* This introduces random, artificial packet losses to test retransmission */ - -#define DEBUG_PACKLOSS_FRACT (0xffffffff/10) - -/* USE PARENTHESIS WHEN 'or'ing MULTIPLE FLAGS: (DEBUG_XX | DEBUG_YY) */ -#define DEBUG (0) - -/****************************************************************/ -/* END OF CONFIGURABLE SECTION */ -/****************************************************************/ - -/* prevent rollover of our timers by readjusting the epoch on the fly */ -#if (DEBUG) & DEBUG_TIMEOUT -#define RPCIOD_EPOCH_SECS 10 -#else -#define RPCIOD_EPOCH_SECS 10000 -#endif - -#ifdef DEBUG -#define ASSERT(arg) assert(arg) -#else -#define ASSERT(arg) if (arg) -#endif - -/****************************************************************/ -/* MACROS */ -/****************************************************************/ - - -#define XACT_HASHS (1<<(LD_XACT_HASH)) /* the hash table size derived from the ld */ -#define XACT_HASH_MSK ((XACT_HASHS)-1) /* mask to extract the hash index from a RPC-XID */ - - -#define MU_LOCK(mutex) rtems_recursive_mutex_lock(&(mutex)) - -#define MU_UNLOCK(mutex) rtems_recursive_mutex_unlock(&(mutex)) - -#define MU_CREAT(pmutex) rtems_recursive_mutex_init((pmutex), "RPCl") - -#define MU_DESTROY(mutex) rtems_recursive_mutex_destroy(&(mutex)) - -#define FIRST_ATTEMPT 0x88888888 /* some time that is never reached */ - -/****************************************************************/ -/* TYPE DEFINITIONS */ -/****************************************************************/ - -typedef rtems_interval TimeoutT; - -/* 100000th implementation of a doubly linked list; - * since only one thread is looking at these, - * we need no locking - */ -typedef struct ListNodeRec_ { - struct ListNodeRec_ *next, *prev; -} ListNodeRec, *ListNode; - - -/* Structure representing an RPC server */ -typedef struct RpcUdpServerRec_ { - RpcUdpServer next; /* linked list of all servers; protected by hlock */ - union { - struct sockaddr_in sin; - struct sockaddr sa; - } addr; - AUTH *auth; - rtems_recursive_mutex authlock; /* must MUTEX the auth object - it's not clear - * what is better: - * 1 having one (MUTEXed) auth per server - * who is shared among all transactions - * using that server - * 2 maintaining an AUTH per transaction - * (there are then other options: manage - * XACT pools on a per-server basis instead - * of associating a server with a XACT when - * sending) - * experience will show if the current (1) - * approach has to be changed. - */ - TimeoutT retry_period; /* dynamically adjusted retry period - * (based on packet roundtrip time) - */ - /* STATISTICS */ - unsigned long retrans; /* how many retries were issued by this server */ - unsigned long requests; /* how many requests have been sent */ - unsigned long timeouts; /* how many requests have timed out */ - unsigned long errors; /* how many errors have occurred (other than timeouts) */ - char name[20]; /* server's address in IP 'dot' notation */ -} RpcUdpServerRec; - -typedef union RpcBufU_ { - uint32_t xid; - char buf[1]; -} RpcBufU, *RpcBuf; - -/* RX Buffer implementation; this is either - * an MBUF chain (MBUF_RX configuration) - * or a buffer allocated from the heap - * where recvfrom copies the (encoded) reply - * to. The XDR routines the copy/decode - * it into the user's data structures. - */ -#ifdef MBUF_RX -typedef struct mbuf * RxBuf; /* an MBUF chain */ -static void bufFree(struct mbuf **m); -#define XID(ibuf) (*(mtod((ibuf), u_long *))) -#else -typedef RpcBuf RxBuf; -#define bufFree(b) do { MY_FREE(*(b)); *(b)=0; } while(0) -#define XID(ibuf) ((ibuf)->xid) -#endif - -/* A RPC 'transaction' consisting - * of server and requestor information, - * buffer space and an XDR object - * (for encoding arguments). - */ -typedef struct RpcUdpXactRec_ { - ListNodeRec node; /* so we can put XACTs on a list */ - RpcUdpServer server; /* server this XACT goes to */ - long lifetime; /* during the lifetime, retry attempts are made */ - long tolive; /* lifetime timer */ - struct rpc_err status; /* RPC reply error status */ - long age; /* age info; needed to manage retransmission */ - long trip; /* record round trip time in ticks */ - rtems_id requestor; /* the task waiting for this XACT to complete */ - RpcUdpXactPool pool; /* if this XACT belong to a pool, this is it */ - XDR xdrs; /* argument encoder stream */ - int xdrpos; /* stream position after the (permanent) header */ - xdrproc_t xres; /* reply decoder proc - TODO needn't be here */ - caddr_t pres; /* reply decoded obj - TODO needn't be here */ -#ifndef MBUF_RX - int ibufsize; /* size of the ibuf (bytes) */ -#endif -#ifdef MBUF_TX - int refcnt; /* mbuf external storage reference count */ -#endif - int obufsize; /* size of the obuf (bytes) */ - RxBuf ibuf; /* pointer to input buffer assigned by daemon */ - RpcBufU obuf; /* output buffer (encoded args) APPENDED HERE */ -} RpcUdpXactRec; - -typedef struct RpcUdpXactPoolRec_ { - rtems_id box; - int prog; - int version; - int xactSize; -} RpcUdpXactPoolRec; - -/* a global hash table where all 'living' transaction - * objects are registered. - * A number of bits in a transaction's XID maps 1:1 to - * an index in this table. Hence, the XACT matching - * an RPC/UDP reply packet can quickly be found - * The size of this table imposes a hard limit on the - * number of all created transactions in the system. - */ -static RpcUdpXact xactHashTbl[XACT_HASHS]={0}; -static u_long xidUpper [XACT_HASHS]={0}; -static unsigned xidHashSeed = 0 ; - -/* forward declarations */ -static RpcUdpXact -sockRcv(void); - -static void -rpcio_daemon(rtems_task_argument); - -#ifdef MBUF_TX -ssize_t -sendto_nocpy ( - int s, - const void *buf, size_t buflen, - int flags, - const struct sockaddr *toaddr, int tolen, - void *closure, - void (*freeproc)(caddr_t, u_int), - void (*refproc)(caddr_t, u_int) -); -static void paranoia_free(caddr_t closure, u_int size); -static void paranoia_ref (caddr_t closure, u_int size); -#define SENDTO sendto_nocpy -#else -#define SENDTO sendto -#endif - -static RpcUdpServer rpcUdpServers = 0; /* linked list of all servers; protected by llock */ - -static int ourSock = -1; /* the socket we are using for communication */ -static rtems_id rpciod = 0; /* task id of the RPC daemon */ -static rtems_id msgQ = 0; /* message queue where the daemon picks up - * requests - */ -#ifndef NDEBUG -static rtems_recursive_mutex llock; /* MUTEX protecting the server list */ -static rtems_recursive_mutex hlock; /* MUTEX protecting the hash table and the list of servers */ -#endif -static rtems_binary_semaphore fini = RTEMS_BINARY_SEMAPHORE_INITIALIZER("RPCf"); /* a synchronization semaphore we use during - * module cleanup / driver unloading - */ -static rtems_interval ticksPerSec; /* cached system clock rate (WHO IS ASSUMED NOT - * TO CHANGE) - */ - -rtems_task_priority rpciodPriority = 0; -#ifdef RTEMS_SMP -const cpu_set_t *rpciodCpuset = 0; -size_t rpciodCpusetSize = 0; -#endif - -#if (DEBUG) & DEBUG_MALLOC -/* malloc wrappers for debugging */ -static int nibufs = 0; - -static inline void *MY_MALLOC(int s) -{ - if (s) { - void *rval; - MU_LOCK(hlock); - assert(nibufs++ < 2000); - MU_UNLOCK(hlock); - assert((rval = malloc(s)) != 0); - return rval; - } - return 0; -} - -static inline void *MY_CALLOC(int n, int s) -{ - if (s) { - void *rval; - MU_LOCK(hlock); - assert(nibufs++ < 2000); - MU_UNLOCK(hlock); - assert((rval = calloc(n,s)) != 0); - return rval; - } - return 0; -} - - -static inline void MY_FREE(void *p) -{ - if (p) { - MU_LOCK(hlock); - nibufs--; - MU_UNLOCK(hlock); - free(p); - } -} -#else -#define MY_MALLOC malloc -#define MY_CALLOC calloc -#define MY_FREE free -#endif - -static inline bool_t -locked_marshal(RpcUdpServer s, XDR *xdrs) -{ -bool_t rval; - MU_LOCK(s->authlock); - rval = AUTH_MARSHALL(s->auth, xdrs); - MU_UNLOCK(s->authlock); - return rval; -} - -/* Locked operations on a server's auth object */ -static inline bool_t -locked_validate(RpcUdpServer s, struct opaque_auth *v) -{ -bool_t rval; - MU_LOCK(s->authlock); - rval = AUTH_VALIDATE(s->auth, v); - MU_UNLOCK(s->authlock); - return rval; -} - -static inline bool_t -locked_refresh(RpcUdpServer s) -{ -bool_t rval; - MU_LOCK(s->authlock); - rval = AUTH_REFRESH(s->auth); - MU_UNLOCK(s->authlock); - return rval; -} - -/* Create a server object - * - */ -enum clnt_stat -rpcUdpServerCreate( - struct sockaddr_in *paddr, - rpcprog_t prog, - rpcvers_t vers, - u_long uid, - u_long gid, - RpcUdpServer *psrv - ) -{ -RpcUdpServer rval; -u_short port; -char hname[MAX_MACHINE_NAME + 1]; -int theuid, thegid; -int thegids[NGRPS]; -gid_t gids[NGROUPS]; -int len,i; -AUTH *auth; -enum clnt_stat pmap_err; -struct pmap pmaparg; - - if ( gethostname(hname, MAX_MACHINE_NAME) ) { - fprintf(stderr, - "RPCIO - error: I have no hostname ?? (%s)\n", - strerror(errno)); - return RPC_UNKNOWNHOST; - } - - len = getgroups(NGROUPS, gids); - if (len < 0 ) { - fprintf(stderr, - "RPCIO - error: I unable to get group ids (%s)\n", - strerror(errno)); - return RPC_FAILED; - } - - if ( len > NGRPS ) - len = NGRPS; - - for (i=0; isin_port) { - - paddr->sin_port = htons(PMAPPORT); - - pmaparg.pm_prog = prog; - pmaparg.pm_vers = vers; - pmaparg.pm_prot = IPPROTO_UDP; - pmaparg.pm_port = 0; /* not needed or used */ - - - /* dont use non-reentrant pmap_getport ! */ - - pmap_err = rpcUdpCallRp( - paddr, - PMAPPROG, - PMAPVERS, - PMAPPROC_GETPORT, - xdr_pmap, - &pmaparg, - xdr_u_short, - &port, - uid, - gid, - 0); - - if ( RPC_SUCCESS != pmap_err ) { - paddr->sin_port = 0; - return pmap_err; - } - - paddr->sin_port = htons(port); - } - - if (0==paddr->sin_port) { - return RPC_PROGNOTREGISTERED; - } - - rval = (RpcUdpServer)MY_MALLOC(sizeof(*rval)); - memset(rval, 0, sizeof(*rval)); - - if (!inet_ntop(AF_INET, &paddr->sin_addr, rval->name, sizeof(rval->name))) - sprintf(rval->name,"?.?.?.?"); - rval->addr.sin = *paddr; - - /* start with a long retransmission interval - it - * will be adapted dynamically - */ - rval->retry_period = RPCIOD_RETX_CAP_S * ticksPerSec; - - rval->auth = auth; - - MU_CREAT( &rval->authlock ); - - /* link into list */ - MU_LOCK( llock ); - rval->next = rpcUdpServers; - rpcUdpServers = rval; - MU_UNLOCK( llock ); - - *psrv = rval; - return RPC_SUCCESS; -} - -void -rpcUdpServerDestroy(RpcUdpServer s) -{ -RpcUdpServer prev; - if (!s) - return; - /* we should probably verify (but how?) that nobody - * (at least: no outstanding XACTs) is using this - * server; - */ - - /* remove from server list */ - MU_LOCK(llock); - prev = rpcUdpServers; - if ( s == prev ) { - rpcUdpServers = s->next; - } else { - for ( ; prev ; prev = prev->next) { - if (prev->next == s) { - prev->next = s->next; - break; - } - } - } - MU_UNLOCK(llock); - - /* MUST have found it */ - assert(prev); - - auth_destroy(s->auth); - - MU_DESTROY(s->authlock); - MY_FREE(s); -} - -int -rpcUdpStats(FILE *f) -{ -RpcUdpServer s; - - if (!f) f = stdout; - - fprintf(f,"RPCIOD statistics:\n"); - - MU_LOCK(llock); - for (s = rpcUdpServers; s; s=s->next) { - fprintf(f,"\nServer -- %s:\n", s->name); - fprintf(f," requests sent: %10ld, retransmitted: %10ld\n", - s->requests, s->retrans); - fprintf(f," timed out: %10ld, send errors: %10ld\n", - s->timeouts, s->errors); - fprintf(f," current retransmission interval: %dms\n", - (unsigned)(s->retry_period * 1000 / ticksPerSec) ); - } - MU_UNLOCK(llock); - - return 0; -} - -RpcUdpXact -rpcUdpXactCreate( - u_long program, - u_long version, - u_long size - ) -{ -RpcUdpXact rval=0; -struct rpc_msg header; -register int i,j; - - if (!size) - size = UDPMSGSIZE; - /* word align */ - size = (size + 3) & ~3; - - rval = (RpcUdpXact)MY_CALLOC(1,sizeof(*rval) - sizeof(rval->obuf) + size); - - if (rval) { - - header.rm_xid = 0; - header.rm_direction = CALL; - header.rm_call.cb_rpcvers = RPC_MSG_VERSION; - header.rm_call.cb_prog = program; - header.rm_call.cb_vers = version; - xdrmem_create(&(rval->xdrs), rval->obuf.buf, size, XDR_ENCODE); - - if (!xdr_callhdr(&(rval->xdrs), &header)) { - MY_FREE(rval); - return 0; - } - /* pick a free table slot and initialize the XID */ - MU_LOCK(hlock); - rval->obuf.xid = (xidHashSeed++ ^ ((uintptr_t)rval>>10)) & XACT_HASH_MSK; - i=j=(rval->obuf.xid & XACT_HASH_MSK); - if (msgQ) { - /* if there's no message queue, refuse to - * give them transactions; we might be in the process to - * go away... - */ - do { - i=(i+1) & XACT_HASH_MSK; /* cheap modulo */ - if (!xactHashTbl[i]) { -#if (DEBUG) & DEBUG_TRACE_XACT - fprintf(stderr,"RPCIO: entering index %i, val %x\n",i,rval); -#endif - xactHashTbl[i]=rval; - j=-1; - break; - } - } while (i!=j); - } - MU_UNLOCK(hlock); - if (i==j) { - XDR_DESTROY(&rval->xdrs); - MY_FREE(rval); - return 0; - } - rval->obuf.xid = xidUpper[i] | i; - rval->xdrpos = XDR_GETPOS(&(rval->xdrs)); - rval->obufsize = size; - } - return rval; -} - -void -rpcUdpXactDestroy(RpcUdpXact xact) -{ -int i = xact->obuf.xid & XACT_HASH_MSK; - -#if (DEBUG) & DEBUG_TRACE_XACT - fprintf(stderr,"RPCIO: removing index %i, val %x\n",i,xact); -#endif - - ASSERT( xactHashTbl[i]==xact ); - - MU_LOCK(hlock); - xactHashTbl[i]=0; - /* remember XID we used last time so we can avoid - * reusing the same one (incremented by rpcUdpSend routine) - */ - xidUpper[i] = xact->obuf.xid; - MU_UNLOCK(hlock); - - bufFree(&xact->ibuf); - - XDR_DESTROY(&xact->xdrs); - MY_FREE(xact); -} - - - -/* Send a transaction, i.e. enqueue it to the - * RPC daemon who will actually send it. - */ -enum clnt_stat -rpcUdpSend( - RpcUdpXact xact, - RpcUdpServer srvr, - struct timeval *timeout, - u_long proc, - xdrproc_t xres, caddr_t pres, - xdrproc_t xargs, caddr_t pargs, - ... - ) -{ -register XDR *xdrs; -unsigned long ms; -va_list ap; - - va_start(ap,pargs); - - if (!timeout) - timeout = RPCIOD_DEFAULT_TIMEOUT; - - ms = 1000 * timeout->tv_sec + timeout->tv_usec/1000; - - /* round lifetime to closest # of ticks */ - xact->lifetime = (ms * ticksPerSec + 500) / 1000; - if ( 0 == xact->lifetime ) - xact->lifetime = 1; - -#if (DEBUG) & DEBUG_TIMEOUT - { - static int once=0; - if (!once++) { - fprintf(stderr, - "Initial lifetime: %i (ticks)\n", - xact->lifetime); - } - } -#endif - - xact->tolive = xact->lifetime; - - xact->xres = xres; - xact->pres = pres; - xact->server = srvr; - - xdrs = &xact->xdrs; - xdrs->x_op = XDR_ENCODE; - /* increment transaction ID */ - xact->obuf.xid += XACT_HASHS; - XDR_SETPOS(xdrs, xact->xdrpos); - if ( !XDR_PUTLONG(xdrs,(long*)&proc) || !locked_marshal(srvr, xdrs) || - !xargs(xdrs, pargs) ) { - va_end(ap); - return(xact->status.re_status=RPC_CANTENCODEARGS); - } - while ((xargs=va_arg(ap,xdrproc_t))) { - if (!xargs(xdrs, va_arg(ap,caddr_t))) - va_end(ap); - return(xact->status.re_status=RPC_CANTENCODEARGS); - } - - va_end(ap); - - rtems_task_ident(RTEMS_SELF, RTEMS_WHO_AM_I, &xact->requestor); - if ( rtems_message_queue_send( msgQ, &xact, sizeof(xact)) ) { - return RPC_CANTSEND; - } - /* wakeup the rpciod */ - ASSERT( RTEMS_SUCCESSFUL==rtems_event_send(rpciod, RPCIOD_TX_EVENT) ); - - return RPC_SUCCESS; -} - -/* Block for the RPC reply to an outstanding - * transaction. - * The caller is woken by the RPC daemon either - * upon reception of the reply or on timeout. - */ -enum clnt_stat -rpcUdpRcv(RpcUdpXact xact) -{ -int refresh; -XDR reply_xdrs; -struct rpc_msg reply_msg; -rtems_status_code status; -rtems_event_set gotEvents; - - refresh = 0; - - do { - - /* block for the reply */ - status = rtems_event_receive( - RTEMS_RPC_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &gotEvents); - ASSERT( status == RTEMS_SUCCESSFUL ); - - if (xact->status.re_status) { -#ifdef MBUF_RX - /* add paranoia */ - ASSERT( !xact->ibuf ); -#endif - return xact->status.re_status; - } - -#ifdef MBUF_RX - xdrmbuf_create(&reply_xdrs, xact->ibuf, XDR_DECODE); -#else - xdrmem_create(&reply_xdrs, xact->ibuf->buf, xact->ibufsize, XDR_DECODE); -#endif - - reply_msg.acpted_rply.ar_verf = _null_auth; - reply_msg.acpted_rply.ar_results.where = xact->pres; - reply_msg.acpted_rply.ar_results.proc = xact->xres; - - if (xdr_replymsg(&reply_xdrs, &reply_msg)) { - /* OK */ - _seterr_reply(&reply_msg, &xact->status); - if (RPC_SUCCESS == xact->status.re_status) { - if ( !locked_validate(xact->server, - &reply_msg.acpted_rply.ar_verf) ) { - xact->status.re_status = RPC_AUTHERROR; - xact->status.re_why = AUTH_INVALIDRESP; - } - if (reply_msg.acpted_rply.ar_verf.oa_base) { - reply_xdrs.x_op = XDR_FREE; - xdr_opaque_auth(&reply_xdrs, &reply_msg.acpted_rply.ar_verf); - } - refresh = 0; - } else { - /* should we try to refresh our credentials ? */ - if ( !refresh ) { - /* had never tried before */ - refresh = RPCIOD_REFRESH; - } - } - } else { - reply_xdrs.x_op = XDR_FREE; - xdr_replymsg(&reply_xdrs, &reply_msg); - xact->status.re_status = RPC_CANTDECODERES; - } - XDR_DESTROY(&reply_xdrs); - - bufFree(&xact->ibuf); - -#ifndef MBUF_RX - xact->ibufsize = 0; -#endif - - if (refresh && locked_refresh(xact->server)) { - rtems_task_ident(RTEMS_SELF, RTEMS_WHO_AM_I, &xact->requestor); - if ( rtems_message_queue_send(msgQ, &xact, sizeof(xact)) ) { - return RPC_CANTSEND; - } - /* wakeup the rpciod */ - fprintf(stderr,"RPCIO INFO: refreshing my AUTH\n"); - ASSERT( RTEMS_SUCCESSFUL==rtems_event_send(rpciod, RPCIOD_TX_EVENT) ); - } - - } while ( 0 && refresh-- > 0 ); - - return xact->status.re_status; -} - - -/* On RTEMS, I'm told to avoid select(); this seems to - * be more efficient - */ -static void -rxWakeupCB(struct socket *sock, void *arg) -{ - rtems_id *rpciod = (rtems_id*) arg; - rtems_event_send(*rpciod, RPCIOD_RX_EVENT); -} - -void -rpcSetXIDs(uint32_t xid) -{ - uint32_t i; - - xid &= ~XACT_HASH_MSK; - - for (i = 0; i < XACT_HASHS; ++i) { - xidUpper[i] = xid | i; - } -} - -int -rpcUdpInit(void) -{ -int s; -rtems_status_code status; -int noblock = 1; -struct sockwakeup wkup; - - if (ourSock < 0) { - fprintf(stderr,"RTEMS-RPCIOD, " \ - "Till Straumann, Stanford/SLAC/SSRL 2002, " \ - "See LICENSE file for licensing info.\n"); - - ourSock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (ourSock>=0) { - bindresvport(ourSock,(struct sockaddr_in*)0); - s = ioctl(ourSock, FIONBIO, (char*)&noblock); - assert( s == 0 ); - /* assume nobody tampers with the clock !! */ - ticksPerSec = rtems_clock_get_ticks_per_second(); - MU_CREAT( &hlock ); - MU_CREAT( &llock ); - - if ( !rpciodPriority ) { - /* use configured networking priority */ - if ( ! (rpciodPriority = rtems_bsdnet_config.network_task_priority) ) - rpciodPriority = RPCIOD_PRIO; /* fallback value */ - } - - status = rtems_task_create( - rtems_build_name('R','P','C','d'), - rpciodPriority, - RPCIOD_STACK, - RTEMS_DEFAULT_MODES, - /* fprintf saves/restores FP registers on PPC :-( */ - RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, - &rpciod); - assert( status == RTEMS_SUCCESSFUL ); - -#ifdef RTEMS_SMP - if ( rpciodCpuset == 0 ) { - rpciodCpuset = rtems_bsdnet_config.network_task_cpuset; - rpciodCpusetSize = rtems_bsdnet_config.network_task_cpuset_size; - } - if ( rpciodCpuset != 0 ) - rtems_task_set_affinity( rpciod, rpciodCpusetSize, rpciodCpuset ); -#endif - - wkup.sw_pfn = rxWakeupCB; - wkup.sw_arg = &rpciod; - assert( 0==setsockopt(ourSock, SOL_SOCKET, SO_RCVWAKEUP, &wkup, sizeof(wkup)) ); - status = rtems_message_queue_create( - rtems_build_name('R','P','C','q'), - RPCIOD_QDEPTH, - sizeof(RpcUdpXact), - RTEMS_DEFAULT_ATTRIBUTES, - &msgQ); - assert( status == RTEMS_SUCCESSFUL ); - status = rtems_task_start( rpciod, rpcio_daemon, 0 ); - assert( status == RTEMS_SUCCESSFUL ); - - } else { - return -1; - } - } - return 0; -} - -int -rpcUdpCleanup(void) -{ - rtems_event_send(rpciod, RPCIOD_KILL_EVENT); - /* synchronize with daemon */ - rtems_binary_semaphore_wait_timed_ticks(&fini, 5*ticksPerSec); - /* if the message queue is still there, something went wrong */ - if (!msgQ) { - rtems_task_delete(rpciod); - } - return (msgQ !=0); -} - -/* Another API - simpler but less efficient. - * For each RPCall, a server and a Xact - * are created and destroyed on the fly. - * - * This should be used for infrequent calls - * (e.g. a NFS mount request). - * - * This is roughly compatible with the original - * clnt_call() etc. API - but it uses our - * daemon and is fully reentrant. - */ -enum clnt_stat -rpcUdpClntCreate( - struct sockaddr_in *psaddr, - rpcprog_t prog, - rpcvers_t vers, - u_long uid, - u_long gid, - RpcUdpClnt *pclnt -) -{ -RpcUdpXact x; -RpcUdpServer s; -enum clnt_stat err; - - if ( RPC_SUCCESS != (err=rpcUdpServerCreate(psaddr, prog, vers, uid, gid, &s)) ) - return err; - - if ( !(x=rpcUdpXactCreate(prog, vers, UDPMSGSIZE)) ) { - rpcUdpServerDestroy(s); - return RPC_FAILED; - } - /* TODO: could maintain a server cache */ - - x->server = s; - - *pclnt = x; - - return RPC_SUCCESS; -} - -static void -rpcUdpClntDestroy(RpcUdpClnt xact) -{ - rpcUdpServerDestroy(xact->server); - rpcUdpXactDestroy(xact); -} - -enum clnt_stat -rpcUdpClntCall( - RpcUdpClnt xact, - u_long proc, - XdrProcT xargs, - CaddrT pargs, - XdrProcT xres, - CaddrT pres, - struct timeval *timeout - ) -{ -enum clnt_stat stat; - - if ( (stat = rpcUdpSend(xact, xact->server, timeout, proc, - xres, pres, - xargs, pargs, - 0)) ) { - fprintf(stderr,"RPCIO Send failed: %i\n",stat); - return stat; - } - return rpcUdpRcv(xact); -} - -/* a yet simpler interface */ -enum clnt_stat -rpcUdpCallRp( - struct sockaddr_in *psrvr, - u_long prog, - u_long vers, - u_long proc, - XdrProcT xargs, - CaddrT pargs, - XdrProcT xres, - CaddrT pres, - u_long uid, /* RPCIO_DEFAULT_ID picks default */ - u_long gid, /* RPCIO_DEFAULT_ID picks default */ - struct timeval *timeout /* NULL picks default */ -) -{ -RpcUdpClnt clp; -enum clnt_stat stat; - - stat = rpcUdpClntCreate( - psrvr, - prog, - vers, - uid, - gid, - &clp); - - if ( RPC_SUCCESS != stat ) - return stat; - - stat = rpcUdpClntCall( - clp, - proc, - xargs, pargs, - xres, pres, - timeout); - - rpcUdpClntDestroy(clp); - - return stat; -} - -/* linked list primitives */ -static void -nodeXtract(ListNode n) -{ - if (n->prev) - n->prev->next = n->next; - if (n->next) - n->next->prev = n->prev; - n->next = n->prev = 0; -} - -static void -nodeAppend(ListNode l, ListNode n) -{ - if ( (n->next = l->next) ) - n->next->prev = n; - l->next = n; - n->prev = l; - -} - -/* this code does the work */ -static void -rpcio_daemon(rtems_task_argument arg) -{ -rtems_status_code stat; -RpcUdpXact xact; -RpcUdpServer srv; -rtems_interval next_retrans, then, unow; -long now; /* need to do signed comparison with age! */ -rtems_event_set events; -ListNode newList; -size_t size; -rtems_id q = 0; -ListNodeRec listHead = {0, 0}; -unsigned long epoch = RPCIOD_EPOCH_SECS * ticksPerSec; -unsigned long max_period = RPCIOD_RETX_CAP_S * ticksPerSec; -rtems_status_code status; - - - then = rtems_clock_get_ticks_since_boot(); - - for (next_retrans = epoch;;) { - - if ( RTEMS_SUCCESSFUL != - (stat = rtems_event_receive( - RPCIOD_RX_EVENT | RPCIOD_TX_EVENT | RPCIOD_KILL_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - next_retrans, - &events)) ) { - ASSERT( RTEMS_TIMEOUT == stat ); - events = 0; - } - - if (events & RPCIOD_KILL_EVENT) { - int i; - -#if (DEBUG) & DEBUG_EVENTS - fprintf(stderr,"RPCIO: got KILL event\n"); -#endif - - MU_LOCK(hlock); - for (i=XACT_HASHS-1; i>=0; i--) { - if (xactHashTbl[i]) { - break; - } - } - if (i<0) { - /* prevent them from creating and enqueueing more messages */ - q=msgQ; - /* messages queued after we executed this assignment will fail */ - msgQ=0; - } - MU_UNLOCK(hlock); - if (i>=0) { - fprintf(stderr,"RPCIO There are still transactions circulating; I refuse to go away\n"); - fprintf(stderr,"(1st in slot %i)\n",i); - rtems_binary_semaphore_post(&fini); - } else { - break; - } - } - - unow = rtems_clock_get_ticks_since_boot(); - - /* measure everything relative to then to protect against - * rollover - */ - now = unow - then; - - /* NOTE: we don't lock the hash table while we are operating - * on transactions; the paradigm is that we 'own' a particular - * transaction (and hence it's hash table slot) from the - * time the xact was put into the message queue until we - * wake up the requestor. - */ - - if (RPCIOD_RX_EVENT & events) { - -#if (DEBUG) & DEBUG_EVENTS - fprintf(stderr,"RPCIO: got RX event\n"); -#endif - - while ((xact=sockRcv())) { - - /* extract from the retransmission list */ - nodeXtract(&xact->node); - - /* change the ID - there might already be - * a retransmission on the way. When it's - * reply arrives we must not find it's ID - * in the hashtable - */ - xact->obuf.xid += XACT_HASHS; - - xact->status.re_status = RPC_SUCCESS; - - /* calculate roundtrip ticks */ - xact->trip = now - xact->trip; - - srv = xact->server; - - /* adjust the server's retry period */ - { - register TimeoutT rtry = srv->retry_period; - register TimeoutT trip = xact->trip; - - ASSERT( trip >= 0 ); - - if ( 0==trip ) - trip = 1; - - /* retry_new = 0.75*retry_old + 0.25 * 8 * roundrip */ - rtry = (3*rtry + (trip << 3)) >> 2; - - if ( rtry > max_period ) - rtry = max_period; - - srv->retry_period = rtry; - } - - /* wakeup requestor */ - rtems_event_send(xact->requestor, RTEMS_RPC_EVENT); - } - } - - if (RPCIOD_TX_EVENT & events) { - -#if (DEBUG) & DEBUG_EVENTS - fprintf(stderr,"RPCIO: got TX event\n"); -#endif - - while (RTEMS_SUCCESSFUL == rtems_message_queue_receive( - msgQ, - &xact, - &size, - RTEMS_NO_WAIT, - RTEMS_NO_TIMEOUT)) { - /* put to the head of timeout q */ - nodeAppend(&listHead, &xact->node); - - xact->age = now; - xact->trip = FIRST_ATTEMPT; - } - } - - - /* work the timeout q */ - newList = 0; - for ( xact=(RpcUdpXact)listHead.next; - xact && xact->age <= now; - xact=(RpcUdpXact)listHead.next ) { - - /* extract from the list */ - nodeXtract(&xact->node); - - srv = xact->server; - - if (xact->tolive < 0) { - /* this one timed out */ - xact->status.re_errno = ETIMEDOUT; - xact->status.re_status = RPC_TIMEDOUT; - - srv->timeouts++; - - /* Change the ID - there might still be - * a reply on the way. When it arrives we - * must not find it's ID in the hash table - * - * Thanks to Steven Johnson for hunting this - * one down. - */ - xact->obuf.xid += XACT_HASHS; - -#if (DEBUG) & DEBUG_TIMEOUT - fprintf(stderr,"RPCIO XACT timed out; waking up requestor\n"); -#endif - if ( rtems_event_send(xact->requestor, RTEMS_RPC_EVENT) ) { - rtems_panic("RPCIO PANIC: requestor id was 0x%08" PRIx32, - xact->requestor); - } - - } else { - int len; - - len = (int)XDR_GETPOS(&xact->xdrs); - -#ifdef MBUF_TX - xact->refcnt = 1; /* sendto itself */ -#endif - if ( len != SENDTO( ourSock, - xact->obuf.buf, - len, - 0, - &srv->addr.sa, - sizeof(srv->addr.sin) -#ifdef MBUF_TX - , xact, - paranoia_free, - paranoia_ref -#endif - ) ) { - - xact->status.re_errno = errno; - xact->status.re_status = RPC_CANTSEND; - srv->errors++; - - /* wakeup requestor */ - fprintf(stderr,"RPCIO: SEND failure\n"); - status = rtems_event_send(xact->requestor, RTEMS_RPC_EVENT); - assert( status == RTEMS_SUCCESSFUL ); - - } else { - /* send successful; calculate retransmission time - * and enqueue to temporary list - */ - if (FIRST_ATTEMPT != xact->trip) { -#if (DEBUG) & DEBUG_TIMEOUT - fprintf(stderr, - "timed out; tolive is %i (ticks), retry period is %i (ticks)\n", - xact->tolive, - srv->retry_period); -#endif - /* this is a real retry; we backup - * the server's retry interval - */ - if ( srv->retry_period < max_period ) { - - /* If multiple transactions for this server - * fail (e.g. because it died) this will - * back-off very agressively (doubling - * the retransmission period for every - * timed out transaction up to the CAP limit) - * which is desirable - single packet failure - * is treated more gracefully by this algorithm. - */ - - srv->retry_period<<=1; -#if (DEBUG) & DEBUG_TIMEOUT - fprintf(stderr, - "adjusted to; retry period %i\n", - srv->retry_period); -#endif - } else { - /* never wait longer than RPCIOD_RETX_CAP_S seconds */ - fprintf(stderr, - "RPCIO: server '%s' not responding - still trying\n", - srv->name); - } - if ( 0 == ++srv->retrans % 1000) { - fprintf(stderr, - "RPCIO - statistics: already %li retries to server %s\n", - srv->retrans, - srv->name); - } - } else { - srv->requests++; - } - xact->trip = now; - { - long capped_period = srv->retry_period; - if ( xact->lifetime < capped_period ) - capped_period = xact->lifetime; - xact->age = now + capped_period; - xact->tolive -= capped_period; - } - /* enqueue to the list of newly sent transactions */ - xact->node.next = newList; - newList = &xact->node; -#if (DEBUG) & DEBUG_TIMEOUT - fprintf(stderr, - "XACT (0x%08x) age is 0x%x, now: 0x%x\n", - xact, - xact->age, - now); -#endif - } - } - } - - /* insert the newly sent transactions into the - * sorted retransmission list - */ - for (; (xact = (RpcUdpXact)newList); ) { - register ListNode p,n; - newList = newList->next; - for ( p=&listHead; (n=p->next) && xact->age > ((RpcUdpXact)n)->age; p=n ) - /* nothing else to do */; - nodeAppend(p, &xact->node); - } - - if (now > epoch) { - /* every now and then, readjust the epoch */ - register ListNode n; - then += now; - for (n=listHead.next; n; n=n->next) { - /* readjust outstanding time intervals subject to the - * condition that the 'absolute' time must remain - * the same. 'age' and 'trip' are measured with - * respect to 'then' - hence: - * - * abs_age == old_age + old_then == new_age + new_then - * - * ==> new_age = old_age + old_then - new_then == old_age - 'now' - */ - ((RpcUdpXact)n)->age -= now; - ((RpcUdpXact)n)->trip -= now; -#if (DEBUG) & DEBUG_TIMEOUT - fprintf(stderr, - "readjusted XACT (0x%08x); age is 0x%x, trip: 0x%x now: 0x%x\n", - (RpcUdpXact)n, - ((RpcUdpXact)n)->trip, - ((RpcUdpXact)n)->age, - now); -#endif - } - now = 0; - } - - next_retrans = listHead.next ? - ((RpcUdpXact)listHead.next)->age - now : - epoch; /* make sure we don't miss updating the epoch */ -#if (DEBUG) & DEBUG_TIMEOUT - fprintf(stderr,"RPCIO: next timeout is %x\n",next_retrans); -#endif - } - /* close our socket; shut down the receiver */ - close(ourSock); - -#if 0 /* if we get here, no transactions exist, hence there can be none - * in the queue whatsoever - */ - /* flush the message queue */ - while (RTEMS_SUCCESSFUL == rtems_message_queue_receive( - q, - &xact, - &size, - RTEMS_NO_WAIT, - RTEMS_NO_TIMEOUT)) { - /* TODO enque xact */ - } - - /* flush all outstanding transactions */ - - for (xact=((RpcUdpXact)listHead.next); xact; xact=((RpcUdpXact)xact->node.next)) { - xact->status.re_status = RPC_TIMEDOUT; - rtems_event_send(xact->requestor, RTEMS_RPC_EVENT); - } -#endif - - rtems_message_queue_delete(q); - - MU_DESTROY(hlock); - - fprintf(stderr,"RPC daemon exited...\n"); - - rtems_binary_semaphore_post(&fini); - rtems_task_suspend(RTEMS_SELF); -} - - -/* support for transaction 'pools'. A number of XACT objects - * is always kept around. The initial number is 0 but it - * is allowed to grow up to a maximum. - * If the need grows beyond the maximum, behavior depends: - * Users can either block until a transaction becomes available, - * they can create a new XACT on the fly or get an error - * if no free XACT is available from the pool. - */ - -RpcUdpXactPool -rpcUdpXactPoolCreate( - rpcprog_t prog, rpcvers_t version, - int xactsize, int poolsize) -{ -RpcUdpXactPool rval = MY_MALLOC(sizeof(*rval)); -rtems_status_code status; - - ASSERT( rval ); - status = rtems_message_queue_create( - rtems_build_name('R','P','C','p'), - poolsize, - sizeof(RpcUdpXact), - RTEMS_DEFAULT_ATTRIBUTES, - &rval->box); - assert( status == RTEMS_SUCCESSFUL ); - - rval->prog = prog; - rval->version = version; - rval->xactSize = xactsize; - return rval; -} - -void -rpcUdpXactPoolDestroy(RpcUdpXactPool pool) -{ -RpcUdpXact xact; - - while ((xact = rpcUdpXactPoolGet(pool, XactGetFail))) { - rpcUdpXactDestroy(xact); - } - rtems_message_queue_delete(pool->box); - MY_FREE(pool); -} - -RpcUdpXact -rpcUdpXactPoolGet(RpcUdpXactPool pool, XactPoolGetMode mode) -{ -RpcUdpXact xact = 0; -size_t size; - - if (RTEMS_SUCCESSFUL != rtems_message_queue_receive( - pool->box, - &xact, - &size, - XactGetWait == mode ? - RTEMS_WAIT : RTEMS_NO_WAIT, - RTEMS_NO_TIMEOUT)) { - - /* nothing found in box; should we create a new one ? */ - - xact = (XactGetCreate == mode) ? - rpcUdpXactCreate( - pool->prog, - pool->version, - pool->xactSize) : 0 ; - if (xact) - xact->pool = pool; - - } - return xact; -} - -void -rpcUdpXactPoolPut(RpcUdpXact xact) -{ -RpcUdpXactPool pool; - - pool = xact->pool; - ASSERT( pool ); - - if (RTEMS_SUCCESSFUL != rtems_message_queue_send( - pool->box, - &xact, - sizeof(xact))) - rpcUdpXactDestroy(xact); -} - -#ifdef MBUF_RX - -/* WORKAROUND: include sys/mbuf.h (or other bsdnet headers) only - * _after_ using malloc()/free() & friends because - * the RTEMS/BSDNET headers redefine those :-( - */ - -#define _KERNEL -#include - -static void -bufFree(struct mbuf **m) -{ - if (*m) { - rtems_bsdnet_semaphore_obtain(); - m_freem(*m); - rtems_bsdnet_semaphore_release(); - *m = 0; - } -} -#endif - -#ifdef MBUF_TX -static void -paranoia_free(caddr_t closure, u_int size) -{ -#if (DEBUG) -RpcUdpXact xact = (RpcUdpXact)closure; -int len = (int)XDR_GETPOS(&xact->xdrs); - - ASSERT( --xact->refcnt >= 0 && size == len ); -#endif -} - -static void -paranoia_ref (caddr_t closure, u_int size) -{ -#if (DEBUG) -RpcUdpXact xact = (RpcUdpXact)closure; -int len = (int)XDR_GETPOS(&xact->xdrs); - ASSERT( size == len ); - xact->refcnt++; -#endif -} -#endif - -/* receive from a socket and find - * the transaction corresponding to the - * transaction ID received in the server - * reply. - * - * The semantics of the 'pibuf' pointer are - * as follows: - * - * MBUF_RX: - * - */ - -#define RPCIOD_RXBUFSZ UDPMSGSIZE - -static RpcUdpXact -sockRcv(void) -{ -int len,i; -uint32_t xid; -union { - struct sockaddr_in sin; - struct sockaddr sa; -} fromAddr; -int fromLen = sizeof(fromAddr.sin); -RxBuf ibuf = 0; -RpcUdpXact xact = 0; - - do { - - /* rcv_mbuf() and recvfrom() differ in that the - * former allocates buffers and passes them back - * to us whereas the latter requires us to provide - * buffer space. - * Hence, in the first case whe have to make sure - * no old buffer is leaked - in the second case, - * we might well re-use an old buffer but must - * make sure we have one allocated - */ -#ifdef MBUF_RX - if (ibuf) - bufFree(&ibuf); - - len = recv_mbuf_from( - ourSock, - &ibuf, - RPCIOD_RXBUFSZ, - &fromAddr.sa, - &fromLen); -#else - if ( !ibuf ) - ibuf = (RpcBuf)MY_MALLOC(RPCIOD_RXBUFSZ); - if ( !ibuf ) - goto cleanup; /* no memory - drop this message */ - - len = recvfrom(ourSock, - ibuf->buf, - RPCIOD_RXBUFSZ, - 0, - &fromAddr.sa, - &fromLen); -#endif - - if (len <= 0) { - if (EAGAIN != errno) - fprintf(stderr,"RECV failed: %s\n",strerror(errno)); - goto cleanup; - } - -#if (DEBUG) & DEBUG_PACKLOSS - if ( (unsigned)rand() < DEBUG_PACKLOSS_FRACT ) { - /* lose packets once in a while */ - static int xxx = 0; - if ( ++xxx % 16 == 0 ) - fprintf(stderr,"DEBUG: dropped %i packets, so far...\n",xxx); - if ( ibuf ) - bufFree( &ibuf ); - continue; - } -#endif - - i = (xid=XID(ibuf)) & XACT_HASH_MSK; - - if ( !(xact=xactHashTbl[i]) || - xact->obuf.xid != xid || -#ifdef REJECT_SERVERIP_MISMATCH - xact->server->addr.sin.sin_addr.s_addr != fromAddr.sin.sin_addr.s_addr || -#endif - xact->server->addr.sin.sin_port != fromAddr.sin.sin_port ) { - - if (xact) { - if ( -#ifdef REJECT_SERVERIP_MISMATCH - xact->server->addr.sin.sin_addr.s_addr == fromAddr.sin.sin_addr.s_addr && -#endif - xact->server->addr.sin.sin_port == fromAddr.sin.sin_port && - ( xact->obuf.xid == xid + XACT_HASHS || - xact->obuf.xid == xid + 2*XACT_HASHS ) - ) { -#ifndef DEBUG /* don't complain if it's just a late arrival of a retry */ - fprintf(stderr,"RPCIO - FYI sockRcv(): dropping late/redundant retry answer\n"); -#endif - } else { - fprintf(stderr,"RPCIO WARNING sockRcv(): transaction mismatch\n"); - fprintf(stderr,"xact: xid 0x%08" PRIx32 " -- got 0x%08" PRIx32 "\n", - xact->obuf.xid, xid); - fprintf(stderr,"xact: addr 0x%08" PRIx32 " -- got 0x%08" PRIx32 "\n", - xact->server->addr.sin.sin_addr.s_addr, - fromAddr.sin.sin_addr.s_addr); - fprintf(stderr,"xact: port 0x%08x -- got 0x%08x\n", - xact->server->addr.sin.sin_port, - fromAddr.sin.sin_port); - } - } else { - fprintf(stderr, - "RPCIO WARNING sockRcv(): got xid 0x%08" PRIx32 " but its slot is empty\n", - xid); - } - /* forget about this one and try again */ - xact = 0; - } - - } while ( !xact ); - - xact->ibuf = ibuf; -#ifndef MBUF_RX - xact->ibufsize = RPCIOD_RXBUFSZ; -#endif - - return xact; - -cleanup: - - bufFree(&ibuf); - - return 0; -} - - -#include -/* double check the event configuration; should probably globally - * manage system events!! - * We do this at the end of the file for the same reason we had - * included mbuf.h only a couple of lines above - see comment up - * there... - */ -#if RTEMS_RPC_EVENT & SOSLEEP_EVENT & SBWAIT_EVENT & NETISR_EVENTS -#error ILLEGAL EVENT CONFIGURATION -#endif diff --git a/cpukit/libfs/src/nfsclient/src/rpcio.h b/cpukit/libfs/src/nfsclient/src/rpcio.h deleted file mode 100644 index bc88e768c0..0000000000 --- a/cpukit/libfs/src/nfsclient/src/rpcio.h +++ /dev/null @@ -1,226 +0,0 @@ -/** - * @file - * - * @brief A Multithreaded RPC/UDP Multiplexor - * - * @ingroup rtems-nfsclient - */ - -/* - * Author: Till Straumann, , 2002 - * - * Authorship - * ---------- - * This software (NFS-2 client implementation for RTEMS) was created by - * Till Straumann , 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 - */ - -#ifndef RPCIO_H -#define RPCIO_H - -/** - * @defgroup rtems-nfsclient RPC/UDP Multiplexor - * - * @ingroup nfsclient - * @{ - */ - -#include -#include -#include -#include -#include - -#include "librtemsNfs.h" - -typedef struct RpcUdpServerRec_ *RpcUdpServer; -typedef struct RpcUdpXactRec_ *RpcUdpXact; - -typedef RpcUdpXact RpcUdpClnt; - -#define RPCIOD_DEFAULT_ID 0xdef10000 - -enum clnt_stat -rpcUdpServerCreate( - struct sockaddr_in *paddr, - rpcprog_t prog, - rpcvers_t 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); - -/** - * @brief Dump statistics to a file (stdout if NULL); - * @retval 0 for convenience - */ -int -rpcUdpStats(FILE *f); - -enum clnt_stat -rpcUdpClntCreate( - struct sockaddr_in *psaddr, - rpcprog_t prog, - rpcvers_t 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); - -/** - * @brief 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 */ - ); - -/** - * @brief 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 */ -); - - - -/* - * @brief 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( - rpcprog_t prog, rpcvers_t version, - int xactsize, int poolsize); - -void -rpcUdpXactPoolDestroy(RpcUdpXactPool pool); - -typedef enum { - XactGetFail, /* call fails if no transaction available */ - XactGetWait, /* call blocks until transaction available */ - XactGetCreate /* a new transaction is allocated (and freed when put back to the pool */ -} XactPoolGetMode; - -RpcUdpXact -rpcUdpXactPoolGet(RpcUdpXactPool pool, XactPoolGetMode mode); - -void -rpcUdpXactPoolPut(RpcUdpXact xact); - -/** @} */ -#endif diff --git a/cpukit/libfs/src/nfsclient/src/sock_mbuf.c b/cpukit/libfs/src/nfsclient/src/sock_mbuf.c deleted file mode 100644 index fa519f70fa..0000000000 --- a/cpukit/libfs/src/nfsclient/src/sock_mbuf.c +++ /dev/null @@ -1,285 +0,0 @@ -/** - * @file - * - * @ingroup RTEMSFileSystemNFS - * - * @brief Sock Mbuf - */ - -/* - * 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, - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _KERNEL - -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "nfsclient-private.h" - -struct socket *rtems_bsdnet_fdToSocket(int fd); - -/* - * Package system call argument into mbuf. - * - * (unfortunately, the original is not public) - */ -static int -sockaddrtombuf (struct mbuf **mp, const struct sockaddr *buf, int buflen) -{ -struct mbuf *m; -struct sockaddr *sa; - - if ((u_int)buflen > MLEN) - return (EINVAL); - - rtems_bsdnet_semaphore_obtain(); - m = m_get(M_WAIT, MT_SONAME); - rtems_bsdnet_semaphore_release(); - - if (m == NULL) - return (ENOBUFS); - m->m_len = buflen; - memcpy (mtod(m, caddr_t), buf, buflen); - *mp = m; - sa = mtod(m, struct sockaddr *); - sa->sa_len = buflen; - - return 0; -} - -static void -dummyproc(caddr_t ext_buf, u_int ext_size) -{ -} - -/* - * send data by simply allocating an MBUF packet - * header and pointing it to our data region. - * - * Optionally, the caller may supply 'reference' - * and 'free' procs. (The latter may call the - * user back once the networking stack has - * released the buffer). - * - * The callbacks are provided with the 'closure' - * pointer and the 'buflen' argument. - */ -ssize_t -sendto_nocpy ( - int s, - const void *buf, size_t buflen, - int flags, - const struct sockaddr *toaddr, int tolen, - void *closure, - void (*freeproc)(caddr_t, u_int), - void (*refproc)(caddr_t, u_int) -) -{ - int error; - struct socket *so; - struct mbuf *to, *m; - int ret = -1; - - rtems_bsdnet_semaphore_obtain (); - if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) { - rtems_bsdnet_semaphore_release (); - return -1; - } - - error = sockaddrtombuf (&to, toaddr, tolen); - if (error) { - errno = error; - rtems_bsdnet_semaphore_release (); - return -1; - } - - MGETHDR(m, M_WAIT, MT_DATA); - m->m_pkthdr.len = 0; - m->m_pkthdr.rcvif = (struct ifnet *) 0; - - m->m_flags |= M_EXT; - m->m_ext.ext_buf = closure ? closure : (void*)buf; - m->m_ext.ext_size = buflen; - /* we _must_ supply non-null procs; otherwise, - * the kernel code assumes it's a mbuf cluster - */ - m->m_ext.ext_free = freeproc ? freeproc : dummyproc; - m->m_ext.ext_ref = refproc ? refproc : dummyproc; - m->m_pkthdr.len += buflen; - m->m_len = buflen; - m->m_data = (void*)buf; - - error = sosend (so, to, NULL, m, NULL, flags); - if (error) { - if (/*auio.uio_resid != len &&*/ (error == EINTR || error == EWOULDBLOCK)) - error = 0; - } - if (error) - errno = error; - else - ret = buflen; - if (to) - m_freem(to); - rtems_bsdnet_semaphore_release (); - return (ret); -} - - -/* - * receive data in an 'mbuf chain'. - * The chain must be released once the - * data has been extracted: - * - * rtems_bsdnet_semaphore_obtain(); - * m_freem(chain); - * rtems_bsdnet_semaphore_release(); - */ -ssize_t -recv_mbuf_from(int s, struct mbuf **ppm, long len, struct sockaddr *fromaddr, int *fromlen) -{ - int ret = -1; - int error; - struct uio auio; - struct socket *so; - struct mbuf *from = NULL; - - memset(&auio, 0, sizeof(auio)); - *ppm = 0; - - rtems_bsdnet_semaphore_obtain (); - if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) { - rtems_bsdnet_semaphore_release (); - return -1; - } -/* auio.uio_iov = mp->msg_iov; - auio.uio_iovcnt = mp->msg_iovlen; - auio.uio_segflg = UIO_USERSPACE; - auio.uio_rw = UIO_READ; - auio.uio_offset = 0; -*/ - auio.uio_resid = len; - error = soreceive (so, &from, &auio, (struct mbuf **) ppm, - (struct mbuf **)NULL, - NULL); - if (error) { - if (auio.uio_resid != len && (error == EINTR || error == EWOULDBLOCK)) - error = 0; - } - if (error) { - errno = error; - } - else { - ret = len - auio.uio_resid; - if (fromaddr) { - len = *fromlen; - if ((len <= 0) || (from == NULL)) { - len = 0; - } - else { - if (len > from->m_len) - len = from->m_len; - memcpy (fromaddr, mtod(from, caddr_t), len); - } - *fromlen = len; - } - } - if (from) - m_freem (from); - if (error && *ppm) { - m_freem(*ppm); - *ppm = 0; - } - rtems_bsdnet_semaphore_release (); - return (ret); -} diff --git a/cpukit/libfs/src/nfsclient/src/xdr_mbuf.c b/cpukit/libfs/src/nfsclient/src/xdr_mbuf.c deleted file mode 100644 index 20f2f9f6e8..0000000000 --- a/cpukit/libfs/src/nfsclient/src/xdr_mbuf.c +++ /dev/null @@ -1,548 +0,0 @@ -/** - * @file - * - * @ingroup RTEMSFileSystemNFS - * - * @brief XDR Implementation Using mbuf Buffers - * - * xdr_mbuf is derived from xdr_mem - */ - -/* - * Author (mbuf specifica): Till Straumann , 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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include - -#include - -#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 - -#include - -#if DEBUG & DEBUG_VERB || defined(TODO) -#include -#endif - -#include "nfsclient-private.h" - -static bool_t xdrmbuf_getlong_aligned(XDR *xdrs, long *lp); -static bool_t xdrmbuf_putlong_aligned(XDR *xdrs, const long *lp); -static bool_t xdrmbuf_getlong_unaligned(XDR *xdrs, long *lp); -static bool_t xdrmbuf_putlong_unaligned(XDR *xdrs, const long *lp); -static bool_t xdrmbuf_getbytes(XDR *xdrs, caddr_t addr, u_int len); -static bool_t xdrmbuf_putbytes(XDR *xdrs, const char *addr, u_int len); -static u_int xdrmbuf_getpos(XDR *xdrs); /* XXX w/64-bit pointers, u_int not enough! */ -static bool_t xdrmbuf_setpos(XDR *xdrs, u_int pos); -static int32_t *xdrmbuf_inline_aligned(XDR *xdrs, u_int len); -static int32_t *xdrmbuf_inline_unaligned(XDR *xdrs, u_int len); -static void xdrmbuf_destroy(XDR *); - -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 = ((uintptr_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; - mbp = (MBPrivate)my_malloc(sizeof(*mbp)); - assert( 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; iim_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( - XDR *xdrs, - const 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( - 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( - XDR *xdrs, - const 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( - XDR *xdrs, - caddr_t addr, - 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( - XDR *xdrs, - const char *addr, - 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( - XDR *xdrs) -{ -#if 1 -MBPrivate mbp = (MBPrivate)xdrs->x_base; -struct mbuf *m = mbp->mcurrent; -u_int rval = mbp->pos; - - if (m) { - rval += xdrs->x_private - mtod(m, void*); - } -#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( - 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( - XDR *xdrs, - u_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( - XDR *xdrs, - u_int len ) -{ - return (0); -} -- cgit v1.2.3