diff options
Diffstat (limited to 'nuttx/fs/nfs')
-rw-r--r-- | nuttx/fs/nfs/Kconfig | 24 | ||||
-rw-r--r-- | nuttx/fs/nfs/Make.defs | 53 | ||||
-rw-r--r-- | nuttx/fs/nfs/nfs.h | 149 | ||||
-rw-r--r-- | nuttx/fs/nfs/nfs_mount.h | 140 | ||||
-rw-r--r-- | nuttx/fs/nfs/nfs_node.h | 83 | ||||
-rw-r--r-- | nuttx/fs/nfs/nfs_proto.h | 571 | ||||
-rw-r--r-- | nuttx/fs/nfs/nfs_util.c | 601 | ||||
-rw-r--r-- | nuttx/fs/nfs/nfs_vfsops.c | 2622 | ||||
-rw-r--r-- | nuttx/fs/nfs/rpc.h | 491 | ||||
-rw-r--r-- | nuttx/fs/nfs/rpc_clnt.c | 805 | ||||
-rw-r--r-- | nuttx/fs/nfs/xdr_subs.h | 128 |
11 files changed, 0 insertions, 5667 deletions
diff --git a/nuttx/fs/nfs/Kconfig b/nuttx/fs/nfs/Kconfig deleted file mode 100644 index 3838efffa..000000000 --- a/nuttx/fs/nfs/Kconfig +++ /dev/null @@ -1,24 +0,0 @@ -# -# For a description of the syntax of this configuration file, -# see misc/tools/kconfig-language.txt. -# - -config NFS - bool "NFS client file system" - default n - depends on NET && !DISABLE_MOUNTPOINT - ---help--- - Enable network file system (NFS) client file system - -#if NFS - -config NFS_STATISTICS - bool "NFS Stastics" - default n - depends on NFS - ---help--- - Collect support for NFS statistics. There is no user interface to - obtain these statistics, however. So they would only be of value - if you add debug instrumentation or use a debugger. - -#endif diff --git a/nuttx/fs/nfs/Make.defs b/nuttx/fs/nfs/Make.defs deleted file mode 100644 index ec2177fcf..000000000 --- a/nuttx/fs/nfs/Make.defs +++ /dev/null @@ -1,53 +0,0 @@ -############################################################################ -# Make.defs -# -# Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. -# Author: Gregory Nutt <gnutt@nuttx.org> -# -# 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. Neither the name Nuttx 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 COPYRIGHT HOLDERS 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 -# COPYRIGHT OWNER 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. -# -############################################################################ - -ifeq ($(CONFIG_NFS),y) -# Files required for NFS file system support - -ASRCS += -CSRCS += - -# Files required for NFS RPC - -ASRCS += -CSRCS += rpc_clnt.c nfs_util.c nfs_vfsops.c - -# Include NFS build support - -DEPPATH += --dep-path nfs -VPATH += :nfs -CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)fs$(DELIM)nfs} - -endif diff --git a/nuttx/fs/nfs/nfs.h b/nuttx/fs/nfs/nfs.h deleted file mode 100644 index af24357a4..000000000 --- a/nuttx/fs/nfs/nfs.h +++ /dev/null @@ -1,149 +0,0 @@ -/**************************************************************************** - * fs/nfs/nfs.h - * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. - * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. - * Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com> - * Gregory Nutt <gnutt@nuttx.org> - * - * Leveraged from OpenBSD: - * - * Copyright (c) 1989, 1993, 1995 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Rick Macklem at The University of Guelph. - * - * 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. 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. - * - ****************************************************************************/ - -#ifndef __FS_NFS_NFS_H -#define __FS_NFS_NFS_H - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include "nfs_mount.h" - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#define NFS_TICKINTVL MSEC_PER_TICK /* Smallest that we can get */ -#define NFS_TICKS 1 /* Number of system ticks */ -#define NFS_HZ CLOCKS_PER_SEC /* Ticks/sec */ -#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */ -#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */ -#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */ -#define NFS_TIMEOUTMUL 2 /* Timeout/Delay multiplier */ -#define NFS_MAXREXMIT 100 /* Stop counting after this many */ -#define NFS_RETRANS 10 /* Num of retrans for soft mounts */ -#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */ -#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */ -#define NFS_READDIRSIZE 8192 /* Def. readdir size */ -#define NFS_NPROCS 23 - -/* Ideally, NFS_DIRBLKSIZ should be bigger, but I've seen servers with - * broken NFS/ethernet drivers that won't work with anything bigger (Linux..) - */ - -#define NFS_DIRBLKSIZ 1024 /* Must be a multiple of DIRBLKSIZ */ - -/* Increment NFS statistics */ - -#ifdef CONFIG_NFS_STATISTICS -# define nfs_statistics(n) do { nfsstats.rpccnt[n]++; } while (0) -#else -# define nfs_statistics(n) -#endif - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -extern uint32_t nfs_true; -extern uint32_t nfs_false; -extern uint32_t nfs_xdrneg1; -#ifdef CONFIG_NFS_STATISTICS -extern struct nfsstats nfsstats; -#endif - -/**************************************************************************** - * Public Types - ****************************************************************************/ - -/* NFS statistics structure */ - -struct nfsstats -{ - uint64_t rpccnt[NFS_NPROCS]; -}; - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/**************************************************************************** - * Public Function Prototypes - ****************************************************************************/ - -#undef EXTERN -#if defined(__cplusplus) -#define EXTERN extern "C" -extern "C" { -#else -#define EXTERN extern -#endif - -EXTERN void nfs_semtake(FAR struct nfsmount *nmp); -EXTERN void nfs_semgive(FAR struct nfsmount *nmp); -EXTERN int nfs_checkmount(FAR struct nfsmount *nmp); -EXTERN int nfs_fsinfo(FAR struct nfsmount *nmp); -EXTERN int nfs_request(struct nfsmount *nmp, int procnum, - FAR void *request, size_t reqlen, - FAR void *response, size_t resplen); -EXTERN int nfs_lookup(FAR struct nfsmount *nmp, FAR const char *filename, - FAR struct file_handle *fhandle, - FAR struct nfs_fattr *obj_attributes, - FAR struct nfs_fattr *dir_attributes); -EXTERN int nfs_findnode(FAR struct nfsmount *nmp, FAR const char *relpath, - FAR struct file_handle *fhandle, - FAR struct nfs_fattr *obj_attributes, - FAR struct nfs_fattr *dir_attributes); -EXTERN int nfs_finddir(FAR struct nfsmount *nmp, FAR const char *relpath, - FAR struct file_handle *fhandle, - FAR struct nfs_fattr *attributes, FAR char *filename); -EXTERN void nfs_attrupdate(FAR struct nfsnode *np, - FAR struct nfs_fattr *attributes); - -#undef EXTERN -#if defined(__cplusplus) -} -#endif - -#endif /* _NFS_NFS_H */ diff --git a/nuttx/fs/nfs/nfs_mount.h b/nuttx/fs/nfs/nfs_mount.h deleted file mode 100644 index 8f1f7be53..000000000 --- a/nuttx/fs/nfs/nfs_mount.h +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** - * fs/nfs/nfs_mount.h - * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. - * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. - * Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com> - * Gregory Nutt <gnutt@nuttx.org> - * - * Leveraged from OpenBSD: - * - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Rick Macklem at The University of Guelph. - * - * 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. - * 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. - * - ****************************************************************************/ - -#ifndef __FS_NFS_NFS_MOUNT_H -#define __FS_NFS_NFS_MOUNT_H - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include <sys/socket.h> - -#include "rpc.h" - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Public Types - ****************************************************************************/ - -/* Mount structure. One mount structure is allocated for each NFS mount. This - * structure holds NFS specific information for mount. - */ - -struct nfsmount -{ - struct nfsnode *nm_head; /* A list of all files opened on this mountpoint */ - sem_t nm_sem; /* Used to assure thread-safe access */ - nfsfh_t nm_fh; /* File handle of root dir */ - char nm_path[90]; /* server's path of the directory being mounted */ - struct nfs_fattr nm_fattr; /* nfs file attribute cache */ - struct rpcclnt *nm_rpcclnt; /* RPC state */ - struct socket *nm_so; /* RPC socket */ - struct sockaddr nm_nam; /* Addr of server */ - bool nm_mounted; /* true: The file system is ready */ - uint8_t nm_fhsize; /* Size of root file handle (host order) */ - uint8_t nm_sotype; /* Type of socket */ - uint8_t nm_retry; /* Max retries */ - uint16_t nm_timeo; /* Timeout value (in system clock ticks) */ - uint16_t nm_rsize; /* Max size of read RPC */ - uint16_t nm_wsize; /* Max size of write RPC */ - uint16_t nm_readdirsize; /* Size of a readdir RPC */ - uint16_t nm_buflen; /* Size of I/O buffer */ - - /* Set aside memory on the stack to hold the largest call message. NOTE - * that for the case of the write call message, it is the reply message that - * is in this union. - */ - - union - { - struct rpc_call_pmap pmap; - struct rpc_call_mount mountd; - struct rpc_call_create create; - struct rpc_call_lookup lookup; - struct rpc_call_read read; - struct rpc_call_remove removef; - struct rpc_call_rename renamef; - struct rpc_call_mkdir mkdir; - struct rpc_call_rmdir rmdir; - struct rpc_call_readdir readdir; - struct rpc_call_fs fsstat; - struct rpc_call_setattr setattr; - struct rpc_call_fs fs; - struct rpc_reply_write write; - } nm_msgbuffer; - - /* I/O buffer (must be a aligned to 32-bit boundaries). This buffer used for all - * reply messages EXCEPT for the WRITE RPC. In that case it is used for the WRITE - * call message that contains the data to be written. This buffer must be - * dynamically sized based on the characteristics of the server and upon the - * configuration of the NuttX network. It must be sized to hold the largest - * possible WRITE call message or READ response message. - */ - - uint32_t nm_iobuffer[1]; /* Actual size is given by nm_buflen */ -}; - -/* The size of the nfsmount structure will debug on the size of the allocated I/O - * buffer. - */ - -#define SIZEOF_nfsmount(n) (sizeof(struct nfsmount) + ((n + 3) & ~3) - sizeof(uint32_t)) - -/* Mount parameters structure. This structure is use in nfs_decode_args funtion before one - * mount structure is allocated in each NFS mount. - */ - -struct nfs_mount_parameters -{ - uint8_t timeo; /* Timeout value (in deciseconds) */ - uint8_t retry; /* Max retries */ - uint16_t rsize; /* Max size of read RPC */ - uint16_t wsize; /* Max size of write RPC */ - uint16_t readdirsize; /* Size of a readdir RPC */ -}; - -#endif diff --git a/nuttx/fs/nfs/nfs_node.h b/nuttx/fs/nfs/nfs_node.h deleted file mode 100644 index 408bd1993..000000000 --- a/nuttx/fs/nfs/nfs_node.h +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** - * fs/nfs/nfs_node.h - * - * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. - * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. - * Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com> - * Gregory Nutt <gnutt@nuttx.org> - * - * Leveraged from OpenBSD: - * - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Rick Macklem at The University of Guelph. - * - * 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. 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. - * - ****************************************************************************/ - -#ifndef __FS_NFS_NFS_NODE_H -#define __FS_NFS_NFS_NODE_H - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include "nfs_proto.h" - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* Flags for struct nfsnode n_flag */ - -#define NFSNODE_OPEN (1 << 0) /* File is still open */ -#define NFSNODE_MODIFIED (1 << 1) /* Might have a modified buffer */ - -/**************************************************************************** - * Public Types - ****************************************************************************/ - -/* There is a unique nfsnode allocated for each active file. An nfsnode is - * 'named' by its file handle. - */ - -struct nfsnode -{ - struct nfsnode *n_next; /* Retained in a singly linked list. */ - uint8_t n_crefs; /* Reference count (for nfs_dup) */ - uint8_t n_type; /* File type */ - uint8_t n_fhsize; /* Size in bytes of the file handle */ - uint8_t n_flags; /* Node flags */ - struct timespec n_mtime; /* File modification time (see NOTE) */ - time_t n_ctime; /* File creation time (see NOTE) */ - nfsfh_t n_fhandle; /* NFS File Handle */ - uint64_t n_size; /* Current size of file (see NOTE) */ -}; - -#endif /* __FS_NFS_NFS_NODE_H */ diff --git a/nuttx/fs/nfs/nfs_proto.h b/nuttx/fs/nfs/nfs_proto.h deleted file mode 100644 index 676ee6232..000000000 --- a/nuttx/fs/nfs/nfs_proto.h +++ /dev/null @@ -1,571 +0,0 @@ -/**************************************************************************** - * fs/nfs/nfs_proto.h - * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. - * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. - * Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com> - * Gregory Nutt <gnutt@nuttx.org> - * - * Leveraged from OpenBSD: - * - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Rick Macklem at The University of Guelph. - * - * 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. 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. - * - ****************************************************************************/ - -#ifndef __FS_NFS_NFS_PROTO_H -#define __FS_NFS_NFS_PROTO_H - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* Constants as defined in the Sun NFS Version 2 and 3 specs. - * "NFS: Network File System Protocol Specification" RFC1094 - * and in the "NFS: Network File System Version 3 Protocol - * Specification" - */ - -#define NFS_PORT 2049 -#define NFS_PROG 100003 -#define NFS_VER2 2 -#define NFS_VER3 3 -#define NFS_VER4 4 -#define NFS_MAXDGRAMDATA 32768 -#define MAXBSIZE 64000 -#define NFS_MAXDATA MAXBSIZE -#define NFS_MAXPATHLEN 1024 -#define NFS_MAXNAMLEN 255 -#define NFS_MAXPKTHDR 404 -#define NFS_MAXPACKET (NFS_MAXPKTHDR + NFS_MAXDATA) -#define NFS_MINPACKET 20 -#define NFS_FABLKSIZE 512 /* Size in bytes of a block wrt fa_blocks */ - -/* Stat numbers for rpc returns (version 2 and 3) */ - -#define NFS_OK 0 -#define NFSERR_PERM 1 -#define NFSERR_NOENT 2 -#define NFSERR_IO 5 -#define NFSERR_NXIO 6 -#define NFSERR_ACCES 13 -#define NFSERR_EXIST 17 -#define NFSERR_XDEV 18 /* Version 3 only */ -#define NFSERR_NODEV 19 -#define NFSERR_NOTDIR 20 -#define NFSERR_ISDIR 21 -#define NFSERR_INVAL 22 /* Version 3 only */ -#define NFSERR_FBIG 27 -#define NFSERR_NOSPC 28 -#define NFSERR_ROFS 30 -#define NFSERR_MLINK 31 /* Version 3 only */ -#define NFSERR_NAMETOL 63 -#define NFSERR_NOTEMPTY 66 -#define NFSERR_DQUOT 69 -#define NFSERR_STALE 70 -#define NFSERR_REMOTE 71 /* Version 3 only */ -#define NFSERR_WFLUSH 99 /* Version 2 only */ -#define NFSERR_BADHANDLE 10001 /* The rest Version 3 only */ -#define NFSERR_NOT_SYNC 10002 -#define NFSERR_BAD_COOKIE 10003 -#define NFSERR_NOTSUPP 10004 -#define NFSERR_TOOSMALL 10005 -#define NFSERR_SERVERFAULT 10006 -#define NFSERR_BADTYPE 10007 -#define NFSERR_JUKEBOX 10008 -#define NFSERR_TRYLATER NFSERR_JUKEBOX -#define NFSERR_STALEWRITEVERF 30001 /* Fake return for nfs_commit() */ - -#define NFSERR_RETVOID 0x20000000 /* Return void, not error */ -#define NFSERR_AUTHERR 0x40000000 /* Mark an authentication error */ -#define NFSERR_RETERR 0x80000000 /* Mark an error return for V3 */ - -/* Sizes in bytes of various nfs rpc components */ - -#define NFSX_UNSIGNED 4 - -/* Specific to NFS Version 3 */ - -#define NFSX_V3FH (sizeof (fhandle_t)) /* size this server uses */ -#define NFSX_V3FHMAX 64 /* max. allowed by protocol */ -#define NFSX_V3FATTR 84 -#define NFSX_V3SATTR 60 /* max. all fields filled in */ -#define NFSX_V3SRVSATTR (sizeof (struct nfsv3_sattr)) -#define NFSX_V3POSTOPATTR (NFSX_V3FATTR + NFSX_UNSIGNED) -#define NFSX_V3WCCDATA (NFSX_V3POSTOPATTR + 8 * NFSX_UNSIGNED) -#define NFSX_V3COOKIEVERF 8 -#define NFSX_V3WRITEVERF 8 -#define NFSX_V3CREATEVERF 8 -#define NFSX_V3STATFS 52 -#define NFSX_V3FSINFO 48 -#define NFSX_V3PATHCONF 24 - -/* NFS RPC procedure numbers (before version mapping) */ - -#define NFSPROC_NULL 0 -#define NFSPROC_GETATTR 1 -#define NFSPROC_SETATTR 2 -#define NFSPROC_LOOKUP 3 -#define NFSPROC_ACCESS 4 -#define NFSPROC_READLINK 5 -#define NFSPROC_READ 6 -#define NFSPROC_WRITE 7 -#define NFSPROC_CREATE 8 -#define NFSPROC_MKDIR 9 -#define NFSPROC_SYMLINK 10 -#define NFSPROC_MKNOD 11 -#define NFSPROC_REMOVE 12 -#define NFSPROC_RMDIR 13 -#define NFSPROC_RENAME 14 -#define NFSPROC_LINK 15 -#define NFSPROC_READDIR 16 -#define NFSPROC_READDIRPLUS 17 -#define NFSPROC_FSSTAT 18 -#define NFSPROC_FSINFO 19 -#define NFSPROC_PATHCONF 20 -#define NFSPROC_COMMIT 21 -#define NFSPROC_NOOP 22 -#define NFS_NPROCS 23 - - -/* Constants used by the Version 3 protocol for various RPCs */ - -#define NFSV3SATTRTIME_DONTCHANGE 0 -#define NFSV3SATTRTIME_TOSERVER 1 -#define NFSV3SATTRTIME_TOCLIENT 2 - -#define NFSV3ACCESS_READ 0x01 -#define NFSV3ACCESS_LOOKUP 0x02 -#define NFSV3ACCESS_MODIFY 0x04 -#define NFSV3ACCESS_EXTEND 0x08 -#define NFSV3ACCESS_DELETE 0x10 -#define NFSV3ACCESS_EXECUTE 0x20 - -#define NFSV3WRITE_UNSTABLE 0 -#define NFSV3WRITE_DATASYNC 1 -#define NFSV3WRITE_FILESYNC 2 - -#define NFSV3CREATE_UNCHECKED 0 -#define NFSV3CREATE_GUARDED 1 -#define NFSV3CREATE_EXCLUSIVE 2 - -#define NFSV3FSINFO_LINK 0x01 -#define NFSV3FSINFO_SYMLINK 0x02 -#define NFSV3FSINFO_HOMOGENEOUS 0x08 -#define NFSV3FSINFO_CANSETTIME 0x10 - -/* Conversion macros */ - -#define vtonfsv3_mode(m) txdr_unsigned((m) & 07777) -#define nfstov_mode(a) (fxdr_unsigned(u_int16_t, (a))&07777) -#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((int32_t)(a))]) -#define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(uint32_t,(a))&0x7] - -/* Mode bit values */ - -#define NFSMODE_IXOTH (1 << 0) /* Execute permission for others on a file */ -#define NFSMODE_IWOTH (1 << 1) /* Write permission for others */ -#define NFSMODE_IROTH (1 << 2) /* Read permission for others */ -#define NFSMODE_IXGRP (1 << 3) /* Execute permission for group on a file */ -#define NFSMODE_IWGRP (1 << 4) /* Write permission for group */ -#define NFSMODE_IRGRP (1 << 5) /* Read permission for group */ -#define NFSMODE_IXUSR (1 << 6) /* Execute permission for owner on a file */ -#define NFSMODE_IWUSR (1 << 7) /* Write permission for owner */ -#define NFSMODE_IRUSR (1 << 8) /* Read permission for owner */ -#define NFSMODE_SAVETEXT (1 << 9) /* Save swapped text */ -#define NFSMODE_ISGID (1 << 10) /* Set group ID on execution */ -#define NFSMODE_ISUID (1 << 11) /* Set user ID on execution */ - -/* File identifier */ - -#define MAXFIDSZ 16 - -/**************************************************************************** - * Public Types - ****************************************************************************/ - -/* File types */ - -typedef enum -{ - NFNON = 0, /* Unknown type */ - NFREG = 1, /* Regular file */ - NFDIR = 2, /* Directory */ - NFBLK = 3, /* Block special device file */ - NFCHR = 4, /* Character special device file */ - NFLNK = 5, /* Symbolic link */ - NFSOCK = 6, /* Socket */ - NFFIFO = 7 /* Named FIFO */ -} nfstype; - -/* File Handle variable is up to 64 bytes for version 3. This structures a - * ariable sized and are provided only for setting aside maximum memory - * allocations for a file handle. - */ - -struct nfsfh -{ - uint8_t fh_bytes[NFSX_V3FHMAX]; -}; -typedef struct nfsfh nfsfh_t; -#define SIZEOF_nfsfh_t(n) (n) - -struct nfsv3_time -{ - uint32_t nfsv3_sec; - uint32_t nfsv3_nsec; -}; -typedef struct nfsv3_time nfstime3; - -/* Quads are defined as arrays of 2 longs to ensure dense packing for the - * protocol and to facilitate xdr conversion. - */ - -struct nfs_uquad -{ - uint32_t nfsuquad[2]; -}; -typedef struct nfs_uquad nfsuint64; - -/* NFS Version 3 special file number. */ - -struct nfsv3_spec -{ - uint32_t specdata1; - uint32_t specdata2; -}; -typedef struct nfsv3_spec nfsv3spec; - -/* File attributes and setable attributes. These structures cover both - * NFS version 2 and the version 3 protocol. Note that the union is only - * used so that one pointer can refer to both variants. These structures - * go out on the wire and must be densely packed, so no quad data types - * are used. (all fields are longs or u_longs or structures of same) - */ - -struct nfs_fattr -{ - uint32_t fa_type; - uint32_t fa_mode; - uint32_t fa_nlink; - uint32_t fa_uid; - uint32_t fa_gid; - nfsuint64 fa_size; - nfsuint64 fa_used; - nfsv3spec fa_rdev; - nfsuint64 fa_fsid; - nfsuint64 fa_fileid; - nfstime3 fa_atime; - nfstime3 fa_mtime; - nfstime3 fa_ctime; -}; - -/* NFS Version 3 sattr structure for the new node creation case. This is the - * maximum size of the attributes; the actual size may vary if values are not - * include. - */ - -struct nfsv3_sattr -{ - uint32_t sa_modefollows; /* TRUE: Mode value follows */ - uint32_t sa_mode; /* Mode value */ - uint32_t sa_uidfollows; /* TRUE: Uid value follows */ - uint32_t sa_uid; /* Uid value */ - uint32_t sa_gidfollows; /* TRUE: Mode value follows */ - uint32_t sa_gid; /* Mode value */ - uint32_t sa_sizefollows; /* TRUE: Size value follows */ - uint32_t sa_size; /* Size value */ - uint32_t sa_atimetype; /* Don't change, use server timer, or use client time */ - nfstime3 sa_atime; /* Client time */ - uint32_t sa_mtimetype; /* Don't change, use server timer, or use client time */ - nfstime3 sa_mtime; /* Client time */ -}; - -struct nfs_statfs -{ - struct nfs_fattr obj_attributes; - nfsuint64 sf_tbytes; - nfsuint64 sf_fbytes; - nfsuint64 sf_abytes; - nfsuint64 sf_tfiles; - nfsuint64 sf_ffiles; - nfsuint64 sf_afiles; - uint32_t sf_invarsec; -}; - -struct post_attr -{ - uint32_t obj_attributesfalse; - struct nfs_fattr attributes; -}; - -struct nfsv3_fsinfo -{ -//struct post_attr obj_attributes; - uint32_t obj_attributesfalse; - uint32_t fs_rtmax; - uint32_t fs_rtpref; - uint32_t fs_rtmult; - uint32_t fs_wtmax; - uint32_t fs_wtpref; - uint32_t fs_wtmult; - uint32_t fs_dtpref; - nfsuint64 fs_maxfilesize; - nfstime3 fs_timedelta; - uint32_t fs_properties; -}; - -/* NFS procedures args */ - -struct wcc_attr -{ - nfsuint64 size; - nfstime3 mtime; - nfstime3 ctime; -}; - -struct wcc_data -{ - uint32_t wcc_attr_follows; /* True if data follows */ - struct wcc_attr before; - uint32_t nfs_attr_follow; /* True if attributes present */ - struct nfs_fattr after; -}; - -struct file_handle -{ - uint32_t length; - nfsfh_t handle; -}; -#define SIZEOF_file_handle(n) (sizeof(uint32_t) + SIZEOF_nfsfh_t(n)) - -struct diropargs3 -{ - struct file_handle fhandle; /* Variable length */ - uint32_t length; /* Size of name[] */ - uint32_t name[(NAME_MAX+3) >> 2]; /* Variable length */ -}; - -struct CREATE3args -{ - struct diropargs3 where; - uint32_t create_mode; - struct nfsv3_sattr how; -}; - -struct CREATE3resok -{ - uint32_t handle_follows; /* True, handle follows */ - struct file_handle fhandle; /* Variable length */ - uint32_t attributes_follows; /* True, attributes follows */ - struct nfs_fattr attributes; /* File attributes */ - struct wcc_data dir_wcc; -}; - -/* The actual size of the lookup argument is variable. These structures are, therefore, - * only useful in setting aside maximum memory usage for the LOOKUP arguments. - */ - -struct LOOKUP3filename -{ - uint32_t namelen; /* Size of name[] */ - uint32_t name[(NAME_MAX+3) >> 2]; /* Variable length */ -}; - -struct LOOKUP3args -{ - struct file_handle dirhandle; /* Variable length */ - struct LOOKUP3filename name; /* Variable length */ -}; - -struct SETATTR3args -{ - struct file_handle fhandle; /* Variable length */ - struct nfsv3_sattr new_attributes; /* Variable length */ - uint32_t guard; /* Guard value */ -}; - -struct SETATTR3resok -{ - struct wcc_data wcc_data; -}; - -/* Actual size of LOOKUP3args */ - -#define SIZEOF_LOOKUP3filename(b) (sizeof(uint32_t) + (((b)+3) & ~3)) -#define SIZEOF_LOOKUP3args(a,b) (SIZEOF_file_handle(a) + SIZEOF_LOOKUP3filename(b)) - -struct LOOKUP3resok -{ - struct file_handle fhandle; - uint32_t obj_attributes_follow; - struct nfs_fattr obj_attributes; - uint32_t dir_attributes_follow; - struct nfs_fattr dir_attributes; -}; - -struct READ3args -{ - struct file_handle fhandle; /* Variable length */ - uint64_t offset; - uint32_t count; -}; - -struct nfs_rdhdr_s -{ - uint32_t attributes_follow; - struct nfs_fattr attributes; /* Will not be present if attributes_follow == 0 */ - uint32_t count; /* Number of bytes read */ - uint32_t eof; /* Non-zero if at the end of file */ - uint32_t length; /* Length of data (same as count?) */ -}; - -struct READ3resok -{ - struct nfs_rdhdr_s hdr; - uint8_t data[1]; /* Actual data size depends on count */ -}; -#define SIZEOF_READ3resok(n) (sizeof(struct nfs_rdhdr_s) + (n)) - -struct nfs_wrhdr_s -{ - struct file_handle fhandle; /* Variable length */ - uint64_t offset; - uint32_t count; - uint32_t stable; -}; - -struct WRITE3args -{ - struct nfs_wrhdr_s hdr; - uint8_t data[1]; /* Actual data size depends on count */ -}; -#define SIZEOF_WRITE3args(n) (sizeof(struct nfs_wrhdr_s) + (n)) - -struct WRITE3resok -{ - struct wcc_data file_wcc; - uint32_t count; - uint32_t committed; - uint8_t verf[NFSX_V3WRITEVERF]; -}; - -struct REMOVE3args -{ - struct diropargs3 object; -}; - -struct REMOVE3resok -{ - struct wcc_data dir_wcc; -}; - -struct RENAME3args -{ - struct diropargs3 from; - struct diropargs3 to; -}; - -struct RENAME3resok -{ - struct wcc_data fromdir_wcc; - struct wcc_data todir_wcc; -}; - -struct MKDIR3args -{ - struct diropargs3 where; - struct nfsv3_sattr how; -}; - -struct MKDIR3resok -{ - uint32_t handle_follows; /* True, handle follows */ - struct file_handle fhandle; /* Variable length */ - uint32_t attributes_follows; /* True, attributes follows */ - struct nfs_fattr attributes; /* Directory attributes */ - struct wcc_data dir_wcc; -}; - -struct RMDIR3args -{ - struct diropargs3 object; -}; - -struct RMDIR3resok -{ - struct wcc_data dir_wcc; -}; - -/* The actual size of the lookup argument is variable. This structures is, therefore, - * only useful in setting aside maximum memory usage for the LOOKUP arguments. - */ - -struct READDIR3args -{ - struct file_handle dir; /* Variable length */ - nfsuint64 cookie; - uint8_t cookieverf[NFSX_V3COOKIEVERF]; - uint32_t count; -}; - -/* The READDIR reply is variable length and consists of multiple entries, each - * of form: - * - * EOF - OR - - * - * File ID (8 bytes) - * Name length (4 bytes) - * Name string (varaiable size but in multiples of 4 bytes) - * Cookie (8 bytes) - * next entry (4 bytes) - */ - -struct READDIR3resok -{ - uint32_t attributes_follow; - struct nfs_fattr dir_attributes; - uint8_t cookieverf[NFSX_V3COOKIEVERF]; - uint32_t value_follows; - uint32_t reply[1]; /* Variable length reply begins here */ -}; - -struct FS3args -{ - struct file_handle fsroot; -}; - -#endif /* __FS_NFS_NFS_PROTO_H */ - diff --git a/nuttx/fs/nfs/nfs_util.c b/nuttx/fs/nfs/nfs_util.c deleted file mode 100644 index e7d28b3d7..000000000 --- a/nuttx/fs/nfs/nfs_util.c +++ /dev/null @@ -1,601 +0,0 @@ -/**************************************************************************** - * fs/nfs/nfs_util.c - * - * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <gnutt@nuttx.org> - * - * 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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 - * COPYRIGHT OWNER 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. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include <nuttx/config.h> -#include <sys/types.h> -#include <sys/time.h> - -#include <stdint.h> -#include <queue.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <errno.h> -#include <assert.h> -#include <debug.h> - -#include <nuttx/fs/dirent.h> - -#include "rpc.h" -#include "nfs.h" -#include "nfs_proto.h" -#include "nfs_mount.h" -#include "nfs_node.h" -#include "xdr_subs.h" - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -/**************************************************************************** - * Private Variables - ****************************************************************************/ - -/**************************************************************************** - * Public Variables - ****************************************************************************/ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -static inline int nfs_pathsegment(FAR const char **path, FAR char *buffer, - FAR char *terminator) -{ - FAR const char *src = *path; - FAR char *dest = buffer; - int nbytes = 0; - char ch; - - /* Loop until the name is successfully parsed or an error occurs */ - - for (;;) - { - /* Get the next byte from the path */ - - ch = *src++; - - /* Check if this the last byte in this segment name */ - - if (ch == '\0' || ch == '/') - { - /* This logic just suppors "//" sequences in the path name */ - - if (ch == '\0' || nbytes > 0 ) - { - /* NULL terminate the parsed path segment */ - - *dest = '\0'; - - /* Return next path and the terminating character */ - - *terminator = ch; - *path = src; - return OK; - } - - /* Just skip over any leading '/' characters */ - } - else if (nbytes >= NAME_MAX) - { - fdbg("File name segment is too long: %d\n", *path); - return EFBIG; - } - else - { - /* Save next character in the accumulated name */ - - *dest++ = ch; - nbytes++; - } - } -} -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: nfs_semtake - ****************************************************************************/ - -void nfs_semtake(struct nfsmount *nmp) -{ - /* Take the semaphore (perhaps waiting) */ - - while (sem_wait(&nmp->nm_sem) != 0) - { - /* The only case that an error should occur here is if - * the wait was awakened by a signal. - */ - - ASSERT(*get_errno_ptr() == EINTR); - } -} - -/**************************************************************************** - * Name: nfs_semgive - ****************************************************************************/ - -void nfs_semgive(struct nfsmount *nmp) -{ - sem_post(&nmp->nm_sem); -} - -/**************************************************************************** - * Name: nfs_checkmount - * - * Desciption: Check if the mountpoint is still valid. - * - * The caller should hold the mountpoint semaphore - * - ****************************************************************************/ - -int nfs_checkmount(struct nfsmount *nmp) -{ - struct nfsnode *file; - - /* If the nm_mounted flag is false, then we have already handled the loss - * of the mount. - */ - - DEBUGASSERT(nmp); - if (!nmp->nm_mounted) - { - /* Make sure that this is flagged in every opened file */ - - for (file = nmp->nm_head; file; file = file->n_next) - { - file->n_flags &= ~NFSNODE_OPEN; - } - - return -ENODEV; - } - - return 0; -} - -/**************************************************************************** - * Name: nfs_request - * - * Desciption: - * Perform the NFS request. On successful receipt, it verifies the NFS level of the - * returned values. - * - * Return Value: - * Zero on success; a positive errno value on failure. - * - ****************************************************************************/ - -int nfs_request(struct nfsmount *nmp, int procnum, - FAR void *request, size_t reqlen, - FAR void *response, size_t resplen) -{ - struct rpcclnt *clnt = nmp->nm_rpcclnt; - struct nfs_reply_header replyh; - int error; - -tryagain: - error = rpcclnt_request(clnt, procnum, NFS_PROG, NFS_VER3, - request, reqlen, response, resplen); - if (error != 0) - { - fdbg("ERROR: rpcclnt_request failed: %d\n", error); - return error; - } - - memcpy(&replyh, response, sizeof(struct nfs_reply_header)); - - if (replyh.nfs_status != 0) - { - if (fxdr_unsigned(uint32_t, replyh.nfs_status) > 32) - { - error = EOPNOTSUPP; - } - else - { - /* NFS_ERRORS are the same as NuttX errno values */ - - error = fxdr_unsigned(uint32_t, replyh.nfs_status); - } - - return error; - } - - if (replyh.rpc_verfi.authtype != 0) - { - error = fxdr_unsigned(int, replyh.rpc_verfi.authtype); - - if (error == EAGAIN) - { - error = 0; - goto tryagain; - } - - fdbg("ERROR: NFS error %d from server\n", error); - return error; - } - - fvdbg("NFS_SUCCESS\n"); - return OK; -} - -/**************************************************************************** - * Name: nfs_lookup - * - * Desciption: - * Given a directory file handle, and the path to file in the directory, - * return the file handle of the path and attributes of both the file and - * the directory containing the file. - * - * NOTE: The LOOKUP call differs from other RPC messages in that the - * call message is variable length, depending upon the size of the path - * name. - * - ****************************************************************************/ - -int nfs_lookup(struct nfsmount *nmp, FAR const char *filename, - FAR struct file_handle *fhandle, - FAR struct nfs_fattr *obj_attributes, - FAR struct nfs_fattr *dir_attributes) -{ - FAR uint32_t *ptr; - uint32_t value; - int reqlen; - int namelen; - int error = 0; - - DEBUGASSERT(nmp && filename && fhandle); - - /* Get the length of the string to be sent */ - - namelen = strlen(filename); - if (namelen > NAME_MAX) - { - fdbg("Length of the string is too big: %d\n", namelen); - return E2BIG; - } - - /* Initialize the request */ - - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.lookup.lookup; - reqlen = 0; - - /* Copy the variable length, directory file handle */ - - *ptr++ = txdr_unsigned(fhandle->length); - reqlen += sizeof(uint32_t); - - memcpy(ptr, &fhandle->handle, fhandle->length); - reqlen += fhandle->length; - ptr += uint32_increment(fhandle->length); - - /* Copy the variable-length file name */ - - *ptr++ = txdr_unsigned(namelen); - reqlen += sizeof(uint32_t); - - memcpy(ptr, filename, namelen); - reqlen += uint32_alignup(namelen); - - /* Request LOOKUP from the server */ - - nfs_statistics(NFSPROC_LOOKUP); - error = nfs_request(nmp, NFSPROC_LOOKUP, - (FAR void *)&nmp->nm_msgbuffer.lookup, reqlen, - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); - - if (error) - { - fdbg("ERROR: nfs_request failed: %d\n", error); - return error; - } - - /* Return the data to the caller's buffers. NOTE: Here we ignore the - * the exact layout of the rpc_reply_lookup structure. File handles - * may differ in size whereas struct rpc_reply_lookup uses a fixed size. - */ - - ptr = (FAR uint32_t *)&((FAR struct rpc_reply_lookup *)nmp->nm_iobuffer)->lookup; - - /* Get the length of the file handle */ - - value = *ptr++; - value = fxdr_unsigned(uint32_t, value); - if (value > NFSX_V3FHMAX) - { - fdbg("ERROR: Bad file handle length: %d\n", value); - return EIO; - } - - /* Return the file handle */ - - fhandle->length = value; - memcpy(&fhandle->handle, ptr, value); - ptr += uint32_increment(value); - - /* Check if there are object attributes and, if so, copy them to the user - * buffer - */ - - value = *ptr++; - if (value) - { - if (obj_attributes) - { - memcpy(obj_attributes, ptr, sizeof(struct nfs_fattr)); - } - ptr += uint32_increment(sizeof(struct nfs_fattr)); - } - - /* Check if there are directory attributes and, if so, copy them to the - * user buffer - */ - - value = *ptr++; - if (value && dir_attributes) - { - memcpy(dir_attributes, ptr, sizeof(struct nfs_fattr)); - } - - return OK; -} - -/**************************************************************************** - * Name: nfs_findnode - * - * Desciption: - * Given a path to something that may or may not be in the file system, - * return the handle of the directory entry of the requested object. - * - * Return Value: - * Zero on success; a positive errno value on failure. - * - ****************************************************************************/ - -int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath, - FAR struct file_handle *fhandle, FAR struct nfs_fattr *obj_attributes, - FAR struct nfs_fattr *dir_attributes) -{ - FAR const char *path = relpath; - char buffer[NAME_MAX+1]; - char terminator; - uint32_t tmp; - int error; - - /* Start with the file handle of the root directory. */ - - fhandle->length = nmp->nm_fhsize; - memcpy(&fhandle->handle, &nmp->nm_fh, nmp->nm_fhsize); - - /* If no path was provided, then the root directory must be exactly what - * the caller is looking for. - */ - - if (*path == '\0' || strlen(path) == 0) - { - /* Return the root directory attributes */ - - if (obj_attributes) - { - memcpy(obj_attributes, &nmp->nm_fattr, sizeof(struct nfs_fattr)); - } - - if (dir_attributes) - { - memcpy(dir_attributes, &nmp->nm_fattr, sizeof(struct nfs_fattr)); - } - - return OK; - } - - /* This is not the root directory. Loop until the directory entry corresponding - * to the path is found. - */ - - for (;;) - { - /* Extract the next path segment name. */ - - error = nfs_pathsegment(&path, buffer, &terminator); - if (error != OK) - { - /* The filename segment contains is too long. */ - - fdbg("nfs_pathsegment of \"%s\" failed after \"%s\": %d\n", - relpath, buffer, error); - return error; - } - - /* Look-up this path segment */ - - error = nfs_lookup(nmp, buffer, fhandle, obj_attributes, dir_attributes); - if (error != OK) - { - fdbg("nfs_lookup of \"%s\" failed at \"%s\": %d\n", - relpath, buffer, error); - return error; - } - - /* If the terminator character in the path was the end of the string - * then we have successfully found the directory entry that describes - * the path. - */ - - if (!terminator) - { - /* Return success meaning that the description the matching - * directory entry is in fhandle, obj_attributes, and dir_attributes. - */ - - return OK; - } - - /* No.. then we have found one of the intermediate directories on - * the way to the final path target. In this case, make sure - * the thing that we found is, indeed, a directory. - */ - - tmp = fxdr_unsigned(uint32_t, obj_attributes->fa_type); - if (tmp != NFDIR) - { - /* Ooops.. we found something else */ - - fdbg("ERROR: Intermediate segment \"%s\" of \'%s\" is not a directory\n", - buffer, path); - return ENOTDIR; - } - } -} - -/**************************************************************************** - * Name: nfs_finddir - * - * Desciption: - * Given a path to something that may or may not be in the file system, - * return the handle of the entry of the directory containing the requested -* object. - * - * Return Value: - * Zero on success; a positive errno value on failure. - * - ****************************************************************************/ - -int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath, - FAR struct file_handle *fhandle, - FAR struct nfs_fattr *attributes, FAR char *filename) -{ - FAR const char *path = relpath; - uint32_t tmp; - char terminator; - int error; - - /* Verify that a path was provided */ - - if (*path == '\0' || strlen(path) == 0) - { - /* Return the root directory attributes */ - - return ENOENT; - } - - /* Start with the file handle of the root directory. */ - - fhandle->length = nmp->nm_fhsize; - memcpy(&fhandle->handle, &nmp->nm_fh, nmp->nm_fhsize); - memcpy(attributes, &nmp->nm_fattr, sizeof(struct nfs_fattr)); - - /* Loop until the directory entry containing the path is found. */ - - for (;;) - { - /* Extract the next path segment name. */ - - error = nfs_pathsegment(&path, filename, &terminator); - if (error != OK) - { - /* The filename segment contains is too long. */ - - fdbg("nfs_pathsegment of \"%s\" failed after \"%s\": %d\n", - relpath, filename, error); - return error; - } - - /* If the terminator character in the path was the end of the string - * then we have successfully found the directory that contains the name - * of interest. - */ - - if (!terminator) - { - /* Return success meaning that the description of the directory - * containing the object is in fhandle and attributes. - */ - - return OK; - } - - /* Look-up the next path segment */ - - error = nfs_lookup(nmp, filename, fhandle, attributes, NULL); - if (error != OK) - { - fdbg("nfs_lookup of \"%s\" failed at \"%s\": %d\n", - relpath, filename, error); - return error; - } - - /* Make sure the thing that we found is, indeed, a directory. */ - - tmp = fxdr_unsigned(uint32_t, attributes->fa_type); - if (tmp != NFDIR) - { - /* Ooops.. we found something else */ - - fdbg("ERROR: Intermediate segment \"%s\" of \'%s\" is not a directory\n", - filename, path); - return ENOTDIR; - } - } -} - -/**************************************************************************** - * Name: nfs_attrupdate - * - * Desciption: - * Update file attributes on write or after the file is modified. - * - * Return Value: - * None. - * - ****************************************************************************/ - -void nfs_attrupdate(FAR struct nfsnode *np, FAR struct nfs_fattr *attributes) -{ - /* Save a few of the files attribute values in file structur (host order) */ - - np->n_type = fxdr_unsigned(uint32_t, attributes->fa_type); - np->n_size = fxdr_hyper(&attributes->fa_size); - fxdr_nfsv3time(&attributes->fa_mtime, &np->n_mtime) - np->n_ctime = fxdr_hyper(&attributes->fa_ctime); -} diff --git a/nuttx/fs/nfs/nfs_vfsops.c b/nuttx/fs/nfs/nfs_vfsops.c deleted file mode 100644 index 2ff4ff9d3..000000000 --- a/nuttx/fs/nfs/nfs_vfsops.c +++ /dev/null @@ -1,2622 +0,0 @@ -/**************************************************************************** - * fs/nfs/nfs_vfsops.c - * - * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. - * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. - * Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com> - * Gregory Nutt <gnutt@nuttx.org> - * - * Leveraged from OpenBSD: - * - * Copyright (c) 1989, 1993, 1995 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Rick Macklem at The University of Guelph. - * - * 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. 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. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include <nuttx/config.h> - -#include <sys/socket.h> -#include <sys/statfs.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include <stdint.h> -#include <stdbool.h> -#include <stdlib.h> -#include <queue.h> -#include <string.h> -#include <fcntl.h> -#include <time.h> -#include <semaphore.h> -#include <assert.h> -#include <errno.h> -#include <debug.h> - -#include <nuttx/kmalloc.h> -#include <nuttx/fs/dirent.h> -#include <nuttx/fs/fs.h> -#include <nuttx/fs/nfs.h> -#include <nuttx/net/uip/uip.h> -#include <nuttx/net/uip/uip-udp.h> -#include <nuttx/net/uip/uipopt.h> - -#include <net/if.h> -#include <netinet/in.h> - -#include "nfs.h" -#include "rpc.h" -#include "nfs_proto.h" -#include "nfs_node.h" -#include "nfs_mount.h" -#include "xdr_subs.h" - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* The V3 EXCLUSIVE file creation logic is not fully supported. */ - -#define USE_GUARDED_CREATE 1 - -/* include/nuttx/fs/dirent.h has its own version of these lengths. They must - * match the NFS versions. - */ - -#if NFSX_V3FHMAX != DIRENT_NFS_MAXHANDLE -# error "Length of file handle in fs_dirent_s is incorrect" -#endif - -#if NFSX_V3COOKIEVERF != DIRENT_NFS_VERFLEN -# error "Length of cookie verify in fs_dirent_s is incorrect" -#endif - -/**************************************************************************** - * Public Variables - ****************************************************************************/ - -uint32_t nfs_true; -uint32_t nfs_false; -uint32_t nfs_xdrneg1; - -#ifdef CONFIG_NFS_STATISTICS -struct nfsstats nfsstats; -#endif - -/**************************************************************************** - * Private Type Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np, - FAR const char *relpath, mode_t mode); -static int nfs_filetruncate(FAR struct nfsmount *nmp, struct nfsnode *np); -static int nfs_fileopen(FAR struct nfsmount *nmp, struct nfsnode *np, - FAR const char *relpath, int oflags, mode_t mode); -static int nfs_open(FAR struct file *filep, const char *relpath, - int oflags, mode_t mode); -static int nfs_close(FAR struct file *filep); -static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen); -static ssize_t nfs_write(FAR struct file *filep, const char *buffer, - size_t buflen); -static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp); -static int nfs_opendir(struct inode *mountpt, const char *relpath, - struct fs_dirent_s *dir); -static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir); -static int nfs_rewinddir(FAR struct inode *mountpt, - FAR struct fs_dirent_s *dir); -static void nfs_decode_args(FAR struct nfs_mount_parameters *nprmt, - FAR struct nfs_args *argp); -static int nfs_bind(FAR struct inode *blkdriver, const void *data, - void **handle); -static int nfs_unbind(void *handle, FAR struct inode **blkdriver); -static int nfs_statfs(struct inode *mountpt, struct statfs *buf); -static int nfs_remove(struct inode *mountpt, const char *relpath); -static int nfs_mkdir(struct inode *mountpt, const char *relpath, - mode_t mode); -static int nfs_rmdir(struct inode *mountpt, const char *relpath); -static int nfs_rename(struct inode *mountpt, const char *oldrelpath, - const char *newrelpath); -static int nfs_stat(struct inode *mountpt, const char *relpath, - struct stat *buf); - -/**************************************************************************** - * Public Data - ****************************************************************************/ -/* nfs vfs operations. */ - -const struct mountpt_operations nfs_operations = -{ - nfs_open, /* open */ - nfs_close, /* close */ - nfs_read, /* read */ - nfs_write, /* write */ - NULL, /* seek */ - NULL, /* ioctl */ - - NULL, /* sync */ - nfs_dup, /* dup */ - - nfs_opendir, /* opendir */ - NULL, /* closedir */ - nfs_readdir, /* readdir */ - nfs_rewinddir, /* rewinddir */ - - nfs_bind, /* bind */ - nfs_unbind, /* unbind */ - nfs_statfs, /* statfs */ - - nfs_remove, /* unlink */ - nfs_mkdir, /* mkdir */ - nfs_rmdir, /* rmdir */ - nfs_rename, /* rename */ - nfs_stat /* stat */ -}; - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: nfs_filecreate - * - * Description: - * Create a file. This is part of the file open logic that is executed if - * the user asks to create a file. - * - * Returned Value: - * 0 on success; a positive errno value on failure. - * - ****************************************************************************/ - -static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np, - FAR const char *relpath, mode_t mode) -{ - struct file_handle fhandle; - struct nfs_fattr fattr; - char filename[NAME_MAX + 1]; - FAR uint32_t *ptr; - uint32_t tmp; - int namelen; - int reqlen; - int error; - - /* Find the NFS node of the directory containing the file to be created */ - - error = nfs_finddir(nmp, relpath, &fhandle, &fattr, filename); - if (error != OK) - { - fdbg("ERROR: nfs_finddir returned: %d\n", error); - return error; - } - - /* Create the CREATE RPC call arguments */ - - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.create.create; - reqlen = 0; - - /* Copy the variable length, directory file handle */ - - *ptr++ = txdr_unsigned(fhandle.length); - reqlen += sizeof(uint32_t); - - memcpy(ptr, &fhandle.handle, fhandle.length); - reqlen += (int)fhandle.length; - ptr += uint32_increment(fhandle.length); - - /* Copy the variable-length file name */ - - namelen = strlen(filename); - - *ptr++ = txdr_unsigned(namelen); - reqlen += sizeof(uint32_t); - - memcpy(ptr, filename, namelen); - ptr += uint32_increment(namelen); - reqlen += uint32_alignup(namelen); - - /* Set the creation mode */ - - if ((mode & O_CREAT) != 0) - { -#ifdef USE_GUARDED_CREATE - *ptr++ = HTONL(NFSV3CREATE_GUARDED); -#else - *ptr++ = HTONL(NFSV3CREATE_EXCLUSIVE); -#endif - } - else - { - *ptr++ = HTONL(NFSV3CREATE_UNCHECKED); - } - reqlen += sizeof(uint32_t); - - /* Mode information is not provided if EXCLUSIVE creation is used. - * in this case, we must call SETATTR after successfully creating - * the file. - */ - -#ifndef USE_GUARDED_CREATE - if ((mode & O_CREAT) == 0) -#endif - { - /* Set the mode. NOTE: Here we depend on the fact that the NuttX and NFS - * bit settings are the same (at least for the bits of interest). - */ - - *ptr++ = nfs_true; /* True: mode value follows */ - reqlen += sizeof(uint32_t); - - tmp = mode & (NFSMODE_IWOTH | NFSMODE_IROTH | NFSMODE_IWGRP | - NFSMODE_IRGRP | NFSMODE_IWUSR | NFSMODE_IRUSR); - *ptr++ = txdr_unsigned(tmp); - reqlen += sizeof(uint32_t); - - /* Set the user ID to zero */ - - *ptr++ = nfs_true; /* True: Uid value follows */ - *ptr++ = 0; /* UID = 0 (nobody) */ - reqlen += 2*sizeof(uint32_t); - - /* Set the group ID to one */ - - *ptr++ = nfs_true; /* True: Gid value follows */ - *ptr++ = HTONL(1); /* GID = 1 (nogroup) */ - reqlen += 2*sizeof(uint32_t); - - /* Set the size to zero */ - - *ptr++ = nfs_true; /* True: Size value follows */ - *ptr++ = 0; /* Size = 0 */ - *ptr++ = 0; - reqlen += 3*sizeof(uint32_t); - - /* Don't change times */ - - *ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change atime */ - *ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change mtime */ - reqlen += 2*sizeof(uint32_t); - } - - /* Send the NFS request. Note there is special logic here to handle version 3 - * exclusive open semantics. - */ - - do - { - nfs_statistics(NFSPROC_CREATE); - error = nfs_request(nmp, NFSPROC_CREATE, - (FAR void *)&nmp->nm_msgbuffer.create, reqlen, - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); - } -#ifdef USE_GUARDED_CREATE - while (0); -#else - while (((mode & O_CREAT) != 0) && error == EOPNOTSUPP); -#endif - - /* Check for success */ - - if (error == OK) - { - /* Parse the returned data */ - - ptr = (FAR uint32_t *)&((FAR struct rpc_reply_create *)nmp->nm_iobuffer)->create; - - /* Save the file handle in the file data structure */ - - tmp = *ptr++; /* handle_follows */ - if (!tmp) - { - fdbg("ERROR: no file handle follows\n"); - return EINVAL; - } - - tmp = *ptr++; - tmp = fxdr_unsigned(uint32_t, tmp); - DEBUGASSERT(tmp <= NFSX_V3FHMAX); - - np->n_fhsize = (uint8_t)tmp; - memcpy(&np->n_fhandle, ptr, tmp); - ptr += uint32_increment(tmp); - - /* Save the attributes in the file data structure */ - - tmp = *ptr; /* handle_follows */ - if (!tmp) - { - fdbg("WARNING: no file attributes\n"); - } - else - { - /* Initialize the file attributes */ - - nfs_attrupdate(np, (FAR struct nfs_fattr *)ptr); - } - - /* Any following dir_wcc data is ignored for now */ - } - - return error; -} - -/**************************************************************************** - * Name: nfs_fileopen - * - * Description: - * Truncate an open file to zero length. This is part of the file open - * logic. - * - * Returned Value: - * 0 on success; a positive errno value on failure. - * - ****************************************************************************/ - -static int nfs_filetruncate(FAR struct nfsmount *nmp, struct nfsnode *np) -{ - FAR uint32_t *ptr; - int reqlen; - int error; - - fvdbg("Truncating file\n"); - - /* Create the SETATTR RPC call arguments */ - - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.setattr.setattr; - reqlen = 0; - - /* Copy the variable length, directory file handle */ - - *ptr++ = txdr_unsigned(np->n_fhsize); - reqlen += sizeof(uint32_t); - - memcpy(ptr, &np->n_fhandle, np->n_fhsize); - reqlen += (int)np->n_fhsize; - ptr += uint32_increment(np->n_fhsize); - - /* Copy the variable-length attributes */ - - *ptr++ = nfs_false; /* Don't change mode */ - *ptr++ = nfs_false; /* Don't change uid */ - *ptr++ = nfs_false; /* Don't change gid */ - *ptr++ = nfs_true; /* Use the following size */ - *ptr++ = 0; /* Truncate to zero length */ - *ptr++ = 0; - *ptr++ = HTONL(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */ - *ptr++ = HTONL(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */ - *ptr++ = nfs_false; /* No guard value */ - reqlen += 9 * sizeof(uint32_t); - - /* Perform the SETATTR RPC */ - - nfs_statistics(NFSPROC_SETATTR); - error = nfs_request(nmp, NFSPROC_SETATTR, - (FAR void *)&nmp->nm_msgbuffer.setattr, reqlen, - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); - if (error != OK) - { - fdbg("ERROR: nfs_request failed: %d\n", error); - return error; - } - - /* Indicate that the file now has zero length */ - - np->n_size = 0; - return OK; -} - -/**************************************************************************** - * Name: nfs_fileopen - * - * Description: - * Open a file. This is part of the file open logic that attempts to open - * an existing file. - * - * Returned Value: - * 0 on success; a positive errno value on failure. - * - ****************************************************************************/ - -static int nfs_fileopen(FAR struct nfsmount *nmp, struct nfsnode *np, - FAR const char *relpath, int oflags, mode_t mode) -{ - struct file_handle fhandle; - struct nfs_fattr fattr; - uint32_t tmp; - int error = 0; - - /* Find the NFS node associate with the path */ - - error = nfs_findnode(nmp, relpath, &fhandle, &fattr, NULL); - if (error != OK) - { - fdbg("ERROR: nfs_findnode returned: %d\n", error); - return error; - } - - /* Check if the object is a directory */ - - tmp = fxdr_unsigned(uint32_t, fattr.fa_type); - if (tmp == NFDIR) - { - /* Exit with EISDIR if we attempt to open a directory */ - - fdbg("ERROR: Path is a directory\n"); - return EISDIR; - } - - /* Check if the caller has sufficient privileges to open the file */ - - if ((oflags & O_WRONLY) != 0) - { - /* Check if anyone has priveleges to write to the file -- owner, - * group, or other (we are probably "other" and may still not be - * able to write). - */ - - tmp = fxdr_unsigned(uint32_t, fattr.fa_mode); - if ((tmp & (NFSMODE_IWOTH|NFSMODE_IWGRP|NFSMODE_IWUSR)) == 0) - { - fdbg("ERROR: File is read-only: %08x\n", tmp); - return EACCES; - } - } - - /* It would be an error if we are asked to create the file exclusively */ - - if ((oflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) - { - /* Already exists -- can't create it exclusively */ - - fdbg("ERROR: File exists\n"); - return EEXIST; - } - - /* Initialize the file private data */ - /* Copy the file handle */ - - np->n_fhsize = (uint8_t)fhandle.length; - memcpy(&np->n_fhandle, &fhandle.handle, fhandle.length); - - /* Save the file attributes */ - - nfs_attrupdate(np, &fattr); - - /* If O_TRUNC is specified and the file is opened for writing, - * then truncate the file. This operation requires that the file is - * writable, but we have already checked that. O_TRUNC without write - * access is ignored. - */ - - if ((oflags & (O_TRUNC|O_WRONLY)) == (O_TRUNC|O_WRONLY)) - { - /* Truncate the file to zero length. I think we can do this with - * the SETATTR call by setting the length to zero. - */ - - return nfs_filetruncate(nmp, np); - } - - return OK; -} - -/**************************************************************************** - * Name: nfs_open - * - * Description: - * If oflags == O_CREAT it creates a file, if not it check to see if the - * type is ok and that deletion is not in progress. - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_open(FAR struct file *filep, FAR const char *relpath, - int oflags, mode_t mode) -{ - struct nfsmount *nmp; - struct nfsnode *np; - int error; - - /* Sanity checks */ - - DEBUGASSERT(filep->f_inode != NULL); - - /* Get the mountpoint inode reference from the file structure and the - * mountpoint private data from the inode structure - */ - - nmp = (struct nfsmount*)filep->f_inode->i_private; - DEBUGASSERT(nmp != NULL); - - /* Pre-allocate the file private data to describe the opened file. */ - - np = (struct nfsnode *)kzalloc(sizeof(struct nfsnode)); - if (!np) - { - fdbg("ERROR: Failed to allocate private data\n"); - return -ENOMEM; - } - - /* Check if the mount is still healthy */ - - nfs_semtake(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - fdbg("ERROR: nfs_checkmount failed: %d\n", error); - goto errout_with_semaphore; - } - - /* Try to open an existing file at that path */ - - error = nfs_fileopen(nmp, np, relpath, oflags, mode); - if (error != OK) - { - /* An error occurred while trying to open the existing file. Check if - * the open failed because the file does not exist. That is not - * necessarily an error; that may only mean that we have to create the - * file. - */ - - if (error != ENOENT) - { - fdbg("ERROR: nfs_findnode failed: %d\n", error); - goto errout_with_semaphore; - } - - /* The file does not exist. Check if we were asked to create the file. If - * the O_CREAT bit is set in the oflags then we should create the file if it - * does not exist. - */ - - if ((oflags & O_CREAT) == 0) - { - /* Return ENOENT if the file does not exist and we were not asked - * to create it. - */ - - fdbg("ERROR: File does not exist\n"); - error = ENOENT; - goto errout_with_semaphore; - } - - /* Create the file */ - - error = nfs_filecreate(nmp, np, relpath, mode); - if (error != OK) - { - fdbg("ERROR: nfs_filecreate failed: %d\n", error); - goto errout_with_semaphore; - } - } - - /* Initialize the file private data (only need to initialize - * non-zero elements) - */ - - np->n_crefs = 1; - - /* Attach the private data to the struct file instance */ - - filep->f_priv = np; - - /* Then insert the new instance at the head of the list in the mountpoint - * tructure. It needs to be there (1) to handle error conditions that effect - * all files, and (2) to inform the umount logic that we are busy. We - * cannot unmount the file system if this list is not empty! - */ - - np->n_next = nmp->nm_head; - nmp->nm_head = np; - - np->n_flags |= (NFSNODE_OPEN | NFSNODE_MODIFIED); - nfs_semgive(nmp); - return OK; - -errout_with_semaphore: - if (np) - { - kfree(np); - } - - nfs_semgive(nmp); - return -error; -} - -/**************************************************************************** - * Name: nfs_close - * - * Description: - * Close a file. - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_close(FAR struct file *filep) -{ - FAR struct nfsmount *nmp; - FAR struct nfsnode *np; - FAR struct nfsnode *prev; - FAR struct nfsnode *curr; - int ret; - - /* Sanity checks */ - - DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); - - /* Recover our private data from the struct file instance */ - - nmp = (struct nfsmount*) filep->f_inode->i_private; - np = (struct nfsnode*) filep->f_priv; - - DEBUGASSERT(nmp != NULL); - - /* Get exclusive access to the mount structure. */ - - nfs_semtake(nmp); - - /* Decrement the reference count. If the reference count would not - * decrement to zero, then that is all we have to do. - */ - - if (np->n_crefs > 1) - { - np->n_crefs--; - ret = OK; - } - - /* There are no more references to the file structure. Now we need to - * free up all resources associated with the open file. - * - * First, find our file structure in the list of file structures - * containted in the mount structure. - */ - - else - { - /* Assume file structure will not be found. This should never happen. */ - - ret = -EINVAL; - - for (prev = NULL, curr = nmp->nm_head; - curr; - prev = curr, curr = curr->n_next) - { - /* Check if this node is ours */ - - if (np == curr) - { - /* Yes.. remove it from the list of file structures */ - - if (prev) - { - /* Remove from mid-list */ - - prev->n_next = np->n_next; - } - else - { - /* Remove from the head of the list */ - - nmp->nm_head = np->n_next; - } - - /* Then deallocate the file structure and return success */ - - kfree(np); - ret = OK; - break; - } - } - } - - filep->f_priv = NULL; - nfs_semgive(nmp); - return ret; -} - -/**************************************************************************** - * Name: nfs_read - * - * Returned Value: - * The (non-negative) number of bytes read on success; a negated errno - * value on failure. - * - ****************************************************************************/ - -static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen) -{ - FAR struct nfsmount *nmp; - FAR struct nfsnode *np; - ssize_t readsize; - ssize_t tmp; - ssize_t bytesread; - size_t reqlen; - FAR uint32_t *ptr; - int error = 0; - - fvdbg("Read %d bytes from offset %d\n", buflen, filep->f_pos); - - /* Sanity checks */ - - DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); - - /* Recover our private data from the struct file instance */ - - nmp = (struct nfsmount*)filep->f_inode->i_private; - np = (struct nfsnode*)filep->f_priv; - - DEBUGASSERT(nmp != NULL); - - /* Make sure that the mount is still healthy */ - - nfs_semtake(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - fdbg("nfs_checkmount failed: %d\n", error); - goto errout_with_semaphore; - } - - /* Get the number of bytes left in the file and truncate read count so that - * it does not exceed the number of bytes left in the file. - */ - - tmp = np->n_size - filep->f_pos; - if (buflen > tmp) - { - buflen = tmp; - fvdbg("Read size truncated to %d\n", buflen); - } - - /* Now loop until we fill the user buffer (or hit the end of the file) */ - - for (bytesread = 0; bytesread < buflen; ) - { - /* Make sure that the attempted read size does not exceed the RPC maximum */ - - readsize = buflen; - if (readsize > nmp->nm_rsize) - { - readsize = nmp->nm_rsize; - } - - /* Make sure that the attempted read size does not exceed the IO buffer size */ - - tmp = SIZEOF_rpc_reply_read(readsize); - if (tmp > nmp->nm_buflen) - { - readsize -= (tmp - nmp->nm_buflen); - } - - /* Initialize the request */ - - ptr = (FAR uint32_t*)&nmp->nm_msgbuffer.read.read; - reqlen = 0; - - /* Copy the variable length, file handle */ - - *ptr++ = txdr_unsigned((uint32_t)np->n_fhsize); - reqlen += sizeof(uint32_t); - - memcpy(ptr, &np->n_fhandle, np->n_fhsize); - reqlen += (int)np->n_fhsize; - ptr += uint32_increment((int)np->n_fhsize); - - /* Copy the file offset */ - - txdr_hyper((uint64_t)filep->f_pos, ptr); - ptr += 2; - reqlen += 2*sizeof(uint32_t); - - /* Set the readsize */ - - *ptr = txdr_unsigned(readsize); - reqlen += sizeof(uint32_t); - - /* Perform the read */ - - fvdbg("Reading %d bytes\n", readsize); - nfs_statistics(NFSPROC_READ); - error = nfs_request(nmp, NFSPROC_READ, - (FAR void *)&nmp->nm_msgbuffer.read, reqlen, - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); - if (error) - { - fdbg("ERROR: nfs_request failed: %d\n", error); - goto errout_with_semaphore; - } - - /* The read was successful. Get a pointer to the beginning of the NFS - * response data. - */ - - ptr = (FAR uint32_t *)&((FAR struct rpc_reply_read *)nmp->nm_iobuffer)->read; - - /* Check if attributes are included in the responses */ - - tmp = *ptr++; - if (*ptr != 0) - { - /* Yes... just skip over the attributes for now */ - - ptr += uint32_increment(sizeof(struct nfs_fattr)); - } - - /* This is followed by the count of data read. Isn't this - * the same as the length that is included in the read data? - * - * Just skip over if for now. - */ - - ptr++; - - /* Next comes an EOF indication. Save that in tmp for now. */ - - tmp = *ptr++; - - /* Then the length of the read data followed by the read data itself */ - - readsize = fxdr_unsigned(uint32_t, *ptr); - ptr++; - - /* Copy the read data into the user buffer */ - - memcpy(buffer, ptr, readsize); - - /* Update the read state data */ - - filep->f_pos += readsize; - bytesread += readsize; - buffer += readsize; - - /* Check if we hit the end of file */ - - if (tmp != 0) - { - break; - } - } - - fvdbg("Read %d bytes\n", bytesread); - nfs_semgive(nmp); - return bytesread; - -errout_with_semaphore: - nfs_semgive(nmp); - return -error; -} - -/**************************************************************************** - * Name: nfs_write - * - * Returned Value: - * The (non-negative) number of bytes written on success; a negated errno - * value on failure. - * - ****************************************************************************/ - -static ssize_t nfs_write(FAR struct file *filep, const char *buffer, - size_t buflen) -{ - struct nfsmount *nmp; - struct nfsnode *np; - ssize_t writesize; - ssize_t bufsize; - ssize_t byteswritten; - size_t reqlen; - FAR uint32_t *ptr; - uint32_t tmp; - int commit = 0; - int committed = NFSV3WRITE_FILESYNC; - int error; - - fvdbg("Write %d bytes to offset %d\n", buflen, filep->f_pos); - - /* Sanity checks */ - - DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); - - /* Recover our private data from the struct file instance */ - - nmp = (struct nfsmount*)filep->f_inode->i_private; - np = (struct nfsnode*)filep->f_priv; - - DEBUGASSERT(nmp != NULL); - - /* Make sure that the mount is still healthy */ - - nfs_semtake(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - fdbg("nfs_checkmount failed: %d\n", error); - goto errout_with_semaphore; - } - - /* Check if the file size would exceed the range of off_t */ - - if (np->n_size + buflen < np->n_size) - { - error = EFBIG; - goto errout_with_semaphore; - } - - /* Now loop until we send the entire user buffer */ - - writesize = 0; - for (byteswritten = 0; byteswritten < buflen; ) - { - /* Make sure that the attempted write size does not exceed the RPC maximum */ - - writesize = buflen; - if (writesize > nmp->nm_wsize) - { - writesize = nmp->nm_wsize; - } - - /* Make sure that the attempted read size does not exceed the IO buffer size */ - - bufsize = SIZEOF_rpc_call_write(writesize); - if (bufsize > nmp->nm_buflen) - { - writesize -= (bufsize - nmp->nm_buflen); - } - - /* Initialize the request. Here we need an offset pointer to the write - * arguments, skipping over the RPC header. Write is unique among the - * RPC calls in that the entry RPC calls messasge lies in the I/O buffer - */ - - ptr = (FAR uint32_t *)&((FAR struct rpc_call_write *)nmp->nm_iobuffer)->write; - reqlen = 0; - - /* Copy the variable length, file handle */ - - *ptr++ = txdr_unsigned((uint32_t)np->n_fhsize); - reqlen += sizeof(uint32_t); - - memcpy(ptr, &np->n_fhandle, np->n_fhsize); - reqlen += (int)np->n_fhsize; - ptr += uint32_increment((int)np->n_fhsize); - - /* Copy the file offset */ - - txdr_hyper((uint64_t)filep->f_pos, ptr); - ptr += 2; - reqlen += 2*sizeof(uint32_t); - - /* Copy the count and stable values */ - - *ptr++ = txdr_unsigned(buflen); - *ptr++ = txdr_unsigned(committed); - reqlen += 2*sizeof(uint32_t); - - /* Copy a chunk of the user data into the I/O buffer */ - - *ptr++ = txdr_unsigned(buflen); - reqlen += sizeof(uint32_t); - memcpy(ptr, buffer, writesize); - reqlen += uint32_alignup(writesize); - - /* Perform the write */ - - nfs_statistics(NFSPROC_WRITE); - error = nfs_request(nmp, NFSPROC_WRITE, - (FAR void *)nmp->nm_iobuffer, reqlen, - (FAR void *)&nmp->nm_msgbuffer.write, sizeof(struct rpc_reply_write)); - if (error) - { - fdbg("ERROR: nfs_request failed: %d\n", error); - goto errout_with_semaphore; - } - - /* Get a pointer to the WRITE reply data */ - - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.write.write; - - /* Parse file_wcc. First, check if WCC attributes follow. */ - - tmp = *ptr++; - if (tmp != 0) - { - /* Yes.. WCC attributes follow. But we just skip over them. */ - - ptr += uint32_increment(sizeof(struct wcc_attr)); - } - - /* Check if normal file attributes follow */ - - tmp = *ptr++; - if (tmp != 0) - { - /* Yes.. Update the cached file status in the file structure. */ - - nfs_attrupdate(np, (FAR struct nfs_fattr *)ptr); - ptr += uint32_increment(sizeof(struct nfs_fattr)); - } - - /* Get the count of bytes actually written */ - - tmp = fxdr_unsigned(uint32_t, *ptr); - ptr++; - - if (tmp < 1 || tmp > writesize) - { - error = EIO; - goto errout_with_semaphore; - } - - writesize = tmp; - - /* Determine the lowest committment level obtained by any of the RPCs. */ - - commit = *ptr++; - if (committed == NFSV3WRITE_FILESYNC) - { - committed = commit; - } - else if (committed == NFSV3WRITE_DATASYNC && - commit == NFSV3WRITE_UNSTABLE) - { - committed = commit; - } - - /* Update the read state data */ - - filep->f_pos += writesize; - byteswritten += writesize; - buffer += writesize; - } - - nfs_semgive(nmp); - return writesize; - -errout_with_semaphore: - nfs_semgive(nmp); - return -error; -} - -/**************************************************************************** - * Name: binfs_dup - * - * Description: - * Duplicate open file data in the new file structure. - * - ****************************************************************************/ - -static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp) -{ - struct nfsmount *nmp; - FAR struct nfsnode *np; - int error; - - fvdbg("Dup %p->%p\n", oldp, newp); - - /* Sanity checks */ - - DEBUGASSERT(oldp->f_priv != NULL && oldp->f_inode != NULL); - - /* Recover our private data from the struct file instance */ - - nmp = (struct nfsmount*)oldp->f_inode->i_private; - np = (struct nfsnode*)oldp->f_priv; - - DEBUGASSERT(nmp != NULL); - - /* Check if the mount is still healthy */ - - nfs_semtake(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - fdbg("ERROR: nfs_checkmount failed: %d\n", error); - nfs_semgive(nmp); - return -error; - } - - /* Increment the reference count on the NFS node structure */ - - DEBUGASSERT(np->n_crefs < 0xff); - np->n_crefs++; - - /* And save this as the file data for the new node */ - - newp->f_priv = np; - - /* Then insert the new instance at the head of the list in the mountpoint - * tructure. It needs to be there (1) to handle error conditions that effect - * all files, and (2) to inform the umount logic that we are busy. We - * cannot unmount the file system if this list is not empty! - */ - - np->n_next = nmp->nm_head; - nmp->nm_head = np; - - nfs_semgive(nmp); - return OK; -} - -/**************************************************************************** - * Name: nfs_opendir - * - * Description: - * Open a directory for read access - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_opendir(struct inode *mountpt, const char *relpath, - struct fs_dirent_s *dir) -{ - struct nfsmount *nmp; - struct file_handle fhandle; - struct nfs_fattr obj_attributes; - uint32_t objtype; - int error; - - fvdbg("relpath: \"%s\"\n", relpath ? relpath : "NULL"); - - /* Sanity checks */ - - DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL && dir); - - /* Recover our private data from the inode instance */ - - nmp = mountpt->i_private; - - /* Initialize the NFS-specific portions of dirent structure to zero */ - - memset(&dir->u.nfs, 0, sizeof(struct nfsdir_s)); - - /* Make sure that the mount is still healthy */ - - nfs_semtake(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - fdbg("ERROR: nfs_checkmount failed: %d\n", error); - goto errout_with_semaphore; - } - - /* Find the NFS node associate with the path */ - - error = nfs_findnode(nmp, relpath, &fhandle, &obj_attributes, NULL); - if (error != OK) - { - fdbg("ERROR: nfs_findnode failed: %d\n", error); - goto errout_with_semaphore; - } - - /* The entry is a directory */ - - objtype = fxdr_unsigned(uint32_t, obj_attributes.fa_type); - if (objtype != NFDIR) - { - fdbg("ERROR: Not a directory, type=%d\n", objtype); - error = ENOTDIR; - goto errout_with_semaphore; - } - - /* Save the directory information in struct fs_dirent_s so that it can be - * used later when readdir() is called. - */ - - dir->u.nfs.nfs_fhsize = (uint8_t)fhandle.length; - DEBUGASSERT(fhandle.length <= DIRENT_NFS_MAXHANDLE); - - memcpy(dir->u.nfs.nfs_fhandle, &fhandle.handle, DIRENT_NFS_MAXHANDLE); - error = OK; - -errout_with_semaphore: - nfs_semgive(nmp); - return -error; -} - -/**************************************************************************** - * Name: nfs_readdir - * - * Description: Read from directory - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) -{ - struct nfsmount *nmp; - struct file_handle fhandle; - struct nfs_fattr obj_attributes; - uint32_t tmp; - uint32_t *ptr; - uint8_t *name; - unsigned int length; - int reqlen; - int error = 0; - - fvdbg("Entry\n"); - - /* Sanity checks */ - - DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); - - /* Recover our private data from the inode instance */ - - nmp = mountpt->i_private; - - /* Make sure that the mount is still healthy */ - - nfs_semtake(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - fdbg("ERROR: nfs_checkmount failed: %d\n", error); - goto errout_with_semaphore; - } - - /* Request a block directory entries, copying directory information from - * the dirent structure. - */ - - ptr = (FAR uint32_t*)&nmp->nm_msgbuffer.readdir.readdir; - reqlen = 0; - - /* Copy the variable length, directory file handle */ - - *ptr++ = txdr_unsigned((uint32_t)dir->u.nfs.nfs_fhsize); - reqlen += sizeof(uint32_t); - - memcpy(ptr, dir->u.nfs.nfs_fhandle, dir->u.nfs.nfs_fhsize); - reqlen += (int)dir->u.nfs.nfs_fhsize; - ptr += uint32_increment((int)dir->u.nfs.nfs_fhsize); - - /* Cookie and cookie verifier */ - - ptr[0] = dir->u.nfs.nfs_cookie[0]; - ptr[1] = dir->u.nfs.nfs_cookie[1]; - ptr += 2; - reqlen += 2*sizeof(uint32_t); - - memcpy(ptr, dir->u.nfs.nfs_verifier, DIRENT_NFS_VERFLEN); - ptr += uint32_increment(DIRENT_NFS_VERFLEN); - reqlen += DIRENT_NFS_VERFLEN; - - /* Number of directory entries (We currently only process one entry at a time) */ - - *ptr = txdr_unsigned(nmp->nm_readdirsize); - reqlen += sizeof(uint32_t); - - /* And read the directory */ - - nfs_statistics(NFSPROC_READDIR); - error = nfs_request(nmp, NFSPROC_READDIR, - (FAR void *)&nmp->nm_msgbuffer.readdir, reqlen, - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); - if (error != OK) - { - fdbg("ERROR: nfs_request failed: %d\n", error); - goto errout_with_semaphore; - } - - /* A new group of entries was successfully read. Process the - * information contained in the response header. This information - * includes: - * - * 1) Attributes follow indication - 4 bytes - * 2) Directory attributes - sizeof(struct nfs_fattr) - * 3) Cookie verifier - NFSX_V3COOKIEVERF bytes - * 4) Values follows indication - 4 bytes - */ - - ptr = (uint32_t *)&((FAR struct rpc_reply_readdir *)nmp->nm_iobuffer)->readdir; - - /* Check if attributes follow, if 0 so Skip over the attributes */ - - tmp = *ptr++; - if (tmp != 0) - { - /* Attributes are not currently used */ - - ptr += uint32_increment(sizeof(struct nfs_fattr)); - } - - /* Save the verification cookie */ - - memcpy(dir->u.nfs.nfs_verifier, ptr, DIRENT_NFS_VERFLEN); - ptr += uint32_increment(DIRENT_NFS_VERFLEN); - - /* Check if values follow. If no values follow, then the EOF indication - * will appear next. - */ - - tmp = *ptr++; - if (tmp == 0) - { - /* No values follow, then the reply should consist only of a 4-byte - * end-of-directory indication. - */ - - tmp = *ptr++; - if (tmp != 0) - { - fvdbg("End of directory\n"); - error = ENOENT; - } - - /* What would it mean if there were not data and we not at the end of - * file? - */ - - else - { - fvdbg("No data but not end of directory???\n"); - error = EAGAIN; - } - - goto errout_with_semaphore; - } - - /* If we are not at the end of the directory listing, then a set of entries - * will follow the header. Each entry is of the form: - * - * File ID (8 bytes) - * Name length (4 bytes) - * Name string (varaiable size but in multiples of 4 bytes) - * Cookie (8 bytes) - * next entry (4 bytes) - */ - - /* There is an entry. Skip over the file ID and point to the length */ - - ptr += 2; - - /* Get the length and point to the name */ - - tmp = *ptr++; - length = fxdr_unsigned(uint32_t, tmp); - name = (uint8_t*)ptr; - - /* Increment the pointer past the name (allowing for padding). ptr - * now points to the cookie. - */ - - ptr += uint32_increment(length); - - /* Save the cookie and increment the pointer to the next entry */ - - dir->u.nfs.nfs_cookie[0] = *ptr++; - dir->u.nfs.nfs_cookie[1] = *ptr++; - - ptr++; /* Just skip over the nextentry for now */ - - /* Return the name of the node to the caller */ - - if (length > NAME_MAX) - { - length = NAME_MAX; - } - - memcpy(dir->fd_dir.d_name, name, length); - dir->fd_dir.d_name[length] = '\0'; - fvdbg("name: \"%s\"\n", dir->fd_dir.d_name); - - /* Get the file attributes associated with this name and return - * the file type. - */ - - fhandle.length = (uint32_t)dir->u.nfs.nfs_fhsize; - memcpy(&fhandle.handle, dir->u.nfs.nfs_fhandle, DIRENT_NFS_MAXHANDLE); - - error = nfs_lookup(nmp, dir->fd_dir.d_name, &fhandle, &obj_attributes, NULL); - if (error != OK) - { - fdbg("nfs_lookup failed: %d\n", error); - goto errout_with_semaphore; - } - - /* Set the dirent file type */ - - tmp = fxdr_unsigned(uint32_t, obj_attributes.fa_type); - switch (tmp) - { - default: - case NFNON: /* Unknown type */ - case NFSOCK: /* Socket */ - case NFLNK: /* Symbolic link */ - break; - - case NFREG: /* Regular file */ - dir->fd_dir.d_type = DTYPE_FILE; - break; - - case NFDIR: /* Directory */ - dir->fd_dir.d_type = DTYPE_DIRECTORY; - break; - - case NFBLK: /* Block special device file */ - dir->fd_dir.d_type = DTYPE_BLK; - break; - - case NFFIFO: /* Named FIFO */ - case NFCHR: /* Character special device file */ - dir->fd_dir.d_type = DTYPE_CHR; - break; - } - fvdbg("type: %d->%d\n", (int)tmp, dir->fd_dir.d_type); - -errout_with_semaphore: - nfs_semgive(nmp); - return -error; -} - -/**************************************************************************** - * Name: nfs_rewinddir - * - * Description: - * Reset the directory traveral logic to the first entry in the open - * directory. - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_rewinddir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir) -{ - fvdbg("Entry\n"); - - /* Sanity checks */ - - DEBUGASSERT(mountpt != NULL && dir != NULL); - - /* Reset the NFS-specific portions of dirent structure, retaining only the - * file handle. - */ - - memset(&dir->u.nfs.nfs_verifier, 0, DIRENT_NFS_VERFLEN); - dir->u.nfs.nfs_cookie[0] = 0; - dir->u.nfs.nfs_cookie[1] = 0; - return OK; -} - -/**************************************************************************** - * Name: nfs_decode_args - * - * Returned Value: - * None - * - ****************************************************************************/ - -static void nfs_decode_args(FAR struct nfs_mount_parameters *nprmt, - FAR struct nfs_args *argp) -{ - int maxio; - - /* Get the selected timeout value */ - - if ((argp->flags & NFSMNT_TIMEO) != 0 && argp->timeo > 0) - { - uint32_t tmp = ((uint32_t)argp->timeo * NFS_HZ + 5) / 10; - if (tmp < NFS_MINTIMEO) - { - tmp = NFS_MINTIMEO; - } - else if (tmp > NFS_MAXTIMEO) - { - tmp = NFS_MAXTIMEO; - } - nprmt->timeo = tmp; - } - - /* Get the selected retransmission count */ - - if ((argp->flags & NFSMNT_RETRANS) != 0 && argp->retrans > 1) - { - if (argp->retrans < NFS_MAXREXMIT) - { - nprmt->retry = argp->retrans; - } - else - { - nprmt->retry = NFS_MAXREXMIT; - } - } - - if ((argp->flags & NFSMNT_SOFT) == 0) - { - nprmt->retry = NFS_MAXREXMIT + 1; /* Past clip limit */ - } - - /* Get the maximum amount of data that can be transferred in one packet */ - - if ((argp->sotype == SOCK_DGRAM) != 0) - { - maxio = NFS_MAXDGRAMDATA; - } - else - { - fdbg("ERROR: Only SOCK_DRAM is supported\n"); - maxio = NFS_MAXDATA; - } - - /* Get the maximum amount of data that can be transferred in one write transfer */ - - if ((argp->flags & NFSMNT_WSIZE) != 0 && argp->wsize > 0) - { - nprmt->wsize = argp->wsize; - - /* Round down to multiple of blocksize */ - - nprmt->wsize &= ~(NFS_FABLKSIZE - 1); - if (nprmt->wsize <= 0) - { - nprmt->wsize = NFS_FABLKSIZE; - } - } - - if (nprmt->wsize > maxio) - { - nprmt->wsize = maxio; - } - - if (nprmt->wsize > MAXBSIZE) - { - nprmt->wsize = MAXBSIZE; - } - - /* Get the maximum amount of data that can be transferred in one read transfer */ - - if ((argp->flags & NFSMNT_RSIZE) != 0 && argp->rsize > 0) - { - nprmt->rsize = argp->rsize; - - /* Round down to multiple of blocksize */ - - nprmt->rsize &= ~(NFS_FABLKSIZE - 1); - if (nprmt->rsize <= 0) - { - nprmt->rsize = NFS_FABLKSIZE; - } - } - - if (nprmt->rsize > maxio) - { - nprmt->rsize = maxio; - } - - if (nprmt->rsize > MAXBSIZE) - { - nprmt->rsize = MAXBSIZE; - } - - /* Get the maximum amount of data that can be transferred in directory transfer */ - - if ((argp->flags & NFSMNT_READDIRSIZE) != 0 && argp->readdirsize > 0) - { - nprmt->readdirsize = argp->readdirsize; - - /* Round down to multiple of blocksize */ - - nprmt->readdirsize &= ~(NFS_DIRBLKSIZ - 1); - if (nprmt->readdirsize < NFS_DIRBLKSIZ) - { - nprmt->readdirsize = NFS_DIRBLKSIZ; - } - } - else if (argp->flags & NFSMNT_RSIZE) - { - nprmt->readdirsize = nprmt->rsize; - } - - if (nprmt->readdirsize > maxio) - { - nprmt->readdirsize = maxio; - } -} - -/**************************************************************************** - * Name: nfs_bind - * - * Description: - * This implements a portion of the mount operation. This function allocates - * and initializes the mountpoint private data and gets mount information - * from the NFS server. The final binding of the private data (containing - * NFS server mount information) to the mountpoint is performed by mount(). - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_bind(FAR struct inode *blkdriver, FAR const void *data, - FAR void **handle) -{ - FAR struct nfs_args *argp = (FAR struct nfs_args *)data; - FAR struct nfsmount *nmp; - struct rpcclnt *rpc; - struct rpc_call_fs getattr; - struct rpc_reply_getattr resok; - struct nfs_mount_parameters nprmt; - uint32_t buflen; - uint32_t tmp; - int error = 0; - - DEBUGASSERT(data && handle); - - /* Set default values of the parameters. These may be overridden by - * settings in the argp->flags. - */ - - nprmt.timeo = NFS_TIMEO; - nprmt.retry = NFS_RETRANS; - nprmt.wsize = NFS_WSIZE; - nprmt.rsize = NFS_RSIZE; - nprmt.readdirsize = NFS_READDIRSIZE; - - nfs_decode_args(&nprmt, argp); - - /* Determine the size of a buffer that will hold one RPC data transfer. - * First, get the maximum size of a read and a write transfer */ - - buflen = SIZEOF_rpc_call_write(nprmt.wsize); - tmp = SIZEOF_rpc_reply_read(nprmt.rsize); - - /* The buffer size will be the maximum of those two sizes */ - - if (tmp > buflen) - { - buflen = tmp; - } - - /* But don't let the buffer size exceed the MSS of the socket type */ - - if (buflen > UIP_UDP_MSS) - { - buflen = UIP_UDP_MSS; - } - - /* Create an instance of the mountpt state structure */ - - nmp = (FAR struct nfsmount *)kzalloc(SIZEOF_nfsmount(buflen)); - if (!nmp) - { - fdbg("ERROR: Failed to allocate mountpoint structure\n"); - return ENOMEM; - } - - /* Save the allocated I/O buffer size */ - - nmp->nm_buflen = (uint16_t)buflen; - - /* Initialize the allocated mountpt state structure. */ - - /* Initialize the semaphore that controls access. The initial count - * is zero, but nfs_semgive() is called at the completion of initialization, - * incrementing the count to one. - */ - - sem_init(&nmp->nm_sem, 0, 0); /* Initialize the semaphore that controls access */ - - /* Initialize NFS */ - - nfs_true = txdr_unsigned(TRUE); - nfs_false = txdr_unsigned(FALSE); - nfs_xdrneg1 = txdr_unsigned(-1); - - rpcclnt_init(); - - /* Set initial values of other fields */ - - nmp->nm_timeo = nprmt.timeo; - nmp->nm_retry = nprmt.retry; - nmp->nm_wsize = nprmt.wsize; - nmp->nm_rsize = nprmt.rsize; - nmp->nm_readdirsize = nprmt.readdirsize; - nmp->nm_fhsize = NFSX_V3FHMAX; - - strncpy(nmp->nm_path, argp->path, 90); - memcpy(&nmp->nm_nam, &argp->addr, argp->addrlen); - - /* Set up the sockets and per-host congestion */ - - nmp->nm_sotype = argp->sotype; - - if (nmp->nm_sotype == SOCK_DGRAM) - { - /* Connection-less... connect now */ - - /* Create an instance of the rpc state structure */ - - rpc = (struct rpcclnt *)kzalloc(sizeof(struct rpcclnt)); - if (!rpc) - { - fdbg("ERROR: Failed to allocate rpc structure\n"); - return ENOMEM; - } - - fvdbg("Connecting\n"); - - /* Translate nfsmnt flags -> rpcclnt flags */ - - rpc->rc_path = nmp->nm_path; - rpc->rc_name = &nmp->nm_nam; - rpc->rc_sotype = nmp->nm_sotype; - rpc->rc_retry = nmp->nm_retry; - - nmp->nm_rpcclnt = rpc; - - error = rpcclnt_connect(nmp->nm_rpcclnt); - if (error != OK) - { - fdbg("ERROR: nfs_connect failed: %d\n", error); - goto bad; - } - } - - nmp->nm_mounted = true; - nmp->nm_so = nmp->nm_rpcclnt->rc_so; - memcpy(&nmp->nm_fh, &nmp->nm_rpcclnt->rc_fh, sizeof(nfsfh_t)); - - /* Get the file attributes */ - - getattr.fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize); - memcpy(&getattr.fs.fsroot.handle, &nmp->nm_fh, sizeof(nfsfh_t)); - - error = nfs_request(nmp, NFSPROC_GETATTR, - (FAR void *)&getattr, sizeof(struct FS3args), - (FAR void*)&resok, sizeof(struct rpc_reply_getattr)); - if (error) - { - fdbg("ERROR: nfs_request failed: %d\n", error); - goto bad; - } - - /* Save the file attributes */ - - memcpy(&nmp->nm_fattr, &resok.attr, sizeof(struct nfs_fattr)); - - /* Mounted! */ - - *handle = (void*)nmp; - nfs_semgive(nmp); - - fvdbg("Successfully mounted\n"); - return OK; - -bad: - if (nmp) - { - /* Disconnect from the server */ - - rpcclnt_disconnect(nmp->nm_rpcclnt); - - /* Free connection-related resources */ - - sem_destroy(&nmp->nm_sem); - if (nmp->nm_so) - { - kfree(nmp->nm_so); - } - - if (nmp->nm_rpcclnt) - { - kfree(nmp->nm_rpcclnt); - } - - kfree(nmp); - } - - return error; -} - -/**************************************************************************** - * Name: nfs_unbind - * - * Description: This implements the filesystem portion of the umount - * operation. - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -int nfs_unbind(FAR void *handle, FAR struct inode **blkdriver) -{ - FAR struct nfsmount *nmp = (FAR struct nfsmount *)handle; - int error; - - fvdbg("Entry\n"); - DEBUGASSERT(nmp); - - /* Get exclusive access to the mount structure */ - - nfs_semtake(nmp); - - /* Are there any open files? We can tell if there are open files by looking - * at the list of file structures in the mount structure. If this list - * not empty, then there are open files and we cannot unmount now (or a - * crash is sure to follow). - */ - - if (nmp->nm_head != NULL) - { - fdbg("ERROR; There are open files: %p\n", nmp->nm_head); - error = EBUSY; - goto errout_with_semaphore; - } - - /* No open file... Umount the file system. */ - - error = rpcclnt_umount(nmp->nm_rpcclnt); - if (error) - { - fdbg("ERROR: rpcclnt_umount failed: %d\n", error); - } - - /* Disconnect from the server */ - - rpcclnt_disconnect(nmp->nm_rpcclnt); - - /* And free any allocated resources */ - - sem_destroy(&nmp->nm_sem); - kfree(nmp->nm_so); - kfree(nmp->nm_rpcclnt); - kfree(nmp); - - return -error; - -errout_with_semaphore: - nfs_semgive(nmp); - return -error; -} - -/**************************************************************************** - * Name: nfs_fsinfo - * - * Description: - * Return information about root directory. - * - * Returned Value: - * 0 on success; positive errno value on failure - * - * Assumptions: - * The caller has exclusive access to the NFS mount structure - * - ****************************************************************************/ - -int nfs_fsinfo(FAR struct nfsmount *nmp) -{ - struct rpc_call_fs fsinfo; - struct rpc_reply_fsinfo fsp; - uint32_t pref; - uint32_t max; - int error = 0; - - fsinfo.fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize); - fsinfo.fs.fsroot.handle = nmp->nm_fh; - - /* Request FSINFO from the server */ - - nfs_statistics(NFSPROC_FSINFO); - error = nfs_request(nmp, NFSPROC_FSINFO, - (FAR void *)&fsinfo, sizeof(struct FS3args), - (FAR void *)&fsp, sizeof(struct rpc_reply_fsinfo)); - if (error) - { - return error; - } - - /* Save the root file system attributes */ - -//memcpy(&nmp->nm_fattr. &fsp.obj_attributes, sizeof(struct nfs_fattr)); - - pref = fxdr_unsigned(uint32_t, fsp.fsinfo.fs_wtpref); - if (pref < nmp->nm_wsize) - { - nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); - } - - max = fxdr_unsigned(uint32_t, fsp.fsinfo.fs_wtmax); - if (max < nmp->nm_wsize) - { - nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1); - if (nmp->nm_wsize == 0) - { - nmp->nm_wsize = max; - } - } - - pref = fxdr_unsigned(uint32_t, fsp.fsinfo.fs_rtpref); - if (pref < nmp->nm_rsize) - { - nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); - } - - max = fxdr_unsigned(uint32_t, fsp.fsinfo.fs_rtmax); - if (max < nmp->nm_rsize) - { - nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1); - if (nmp->nm_rsize == 0) - { - nmp->nm_rsize = max; - } - } - - pref = fxdr_unsigned(uint32_t, fsp.fsinfo.fs_dtpref); - if (pref < nmp->nm_readdirsize) - { - nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) & ~(NFS_DIRBLKSIZ - 1); - } - - if (max < nmp->nm_readdirsize) - { - nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1); - if (nmp->nm_readdirsize == 0) - { - nmp->nm_readdirsize = max; - } - } - - return OK; -} - -/**************************************************************************** - * Name: nfs_statfs - * - * Description: - * Return filesystem statistics - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_statfs(FAR struct inode *mountpt, FAR struct statfs *sbp) -{ - FAR struct nfsmount *nmp; - FAR struct rpc_call_fs *fsstat; - FAR struct rpc_reply_fsstat *sfp; - int error = 0; - uint64_t tquad; - - /* Sanity checks */ - - DEBUGASSERT(mountpt && mountpt->i_private); - - /* Get the mountpoint private data from the inode structure */ - - nmp = (struct nfsmount*)mountpt->i_private; - - /* Check if the mount is still healthy */ - - nfs_semtake(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - fdbg("ERROR: nfs_checkmount failed: %d\n", error); - goto errout_with_semaphore; - } - - /* Fill in the statfs info */ - - sbp->f_type = NFS_SUPER_MAGIC; - - (void)nfs_fsinfo(nmp); - - fsstat = &nmp->nm_msgbuffer.fsstat; - fsstat->fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize); - memcpy(&fsstat->fs.fsroot.handle, &nmp->nm_fh, sizeof(nfsfh_t)); - - nfs_statistics(NFSPROC_FSSTAT); - error = nfs_request(nmp, NFSPROC_FSSTAT, - (FAR void *)fsstat, sizeof(struct FS3args), - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); - if (error) - { - goto errout_with_semaphore; - } - - sfp = (FAR struct rpc_reply_fsstat *)nmp->nm_iobuffer; - sbp->f_bsize = NFS_FABLKSIZE; - tquad = fxdr_hyper(&sfp->fsstat.sf_tbytes); - sbp->f_blocks = tquad / (uint64_t) NFS_FABLKSIZE; - tquad = fxdr_hyper(&sfp->fsstat.sf_fbytes); - sbp->f_bfree = tquad / (uint64_t) NFS_FABLKSIZE; - tquad = fxdr_hyper(&sfp->fsstat.sf_abytes); - sbp->f_bavail = tquad / (uint64_t) NFS_FABLKSIZE; - tquad = fxdr_hyper(&sfp->fsstat.sf_tfiles); - sbp->f_files = tquad; - tquad = fxdr_hyper(&sfp->fsstat.sf_ffiles); - sbp->f_ffree = tquad; - sbp->f_namelen = NAME_MAX; - -errout_with_semaphore: - nfs_semgive(nmp); - return -error; -} - -/**************************************************************************** - * Name: nfs_remove - * - * Description: - * Remove a file - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_remove(struct inode *mountpt, const char *relpath) -{ - FAR struct nfsmount *nmp; - struct file_handle fhandle; - struct nfs_fattr fattr; - char filename[NAME_MAX + 1]; - FAR uint32_t *ptr; - int namelen; - int reqlen; - int error; - - /* Sanity checks */ - - DEBUGASSERT(mountpt && mountpt->i_private); - - /* Get the mountpoint private data from the inode structure */ - - nmp = (struct nfsmount*)mountpt->i_private; - - /* Check if the mount is still healthy */ - - nfs_semtake(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - fdbg("ERROR: nfs_checkmount failed: %d\n", error); - goto errout_with_semaphore; - } - - /* Find the NFS node of the directory containing the file to be deleted */ - - error = nfs_finddir(nmp, relpath, &fhandle, &fattr, filename); - if (error != OK) - { - fdbg("ERROR: nfs_finddir returned: %d\n", error); - goto errout_with_semaphore; - } - - /* Create the REMOVE RPC call arguments */ - - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.removef.remove; - reqlen = 0; - - /* Copy the variable length, directory file handle */ - - *ptr++ = txdr_unsigned(fhandle.length); - reqlen += sizeof(uint32_t); - - memcpy(ptr, &fhandle.handle, fhandle.length); - reqlen += (int)fhandle.length; - ptr += uint32_increment(fhandle.length); - - /* Copy the variable-length file name */ - - namelen = strlen(filename); - - *ptr++ = txdr_unsigned(namelen); - reqlen += sizeof(uint32_t); - - memcpy(ptr, filename, namelen); - reqlen += uint32_alignup(namelen); - - /* Perform the REMOVE RPC call */ - - nfs_statistics(NFSPROC_REMOVE); - error = nfs_request(nmp, NFSPROC_REMOVE, - (FAR void *)&nmp->nm_msgbuffer.removef, reqlen, - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); - -errout_with_semaphore: - nfs_semgive(nmp); - return -error; -} - -/**************************************************************************** - * Name: nfs_mkdir - * - * Description: - * Create a directory - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) -{ - struct nfsmount *nmp; - struct file_handle fhandle; - struct nfs_fattr fattr; - char dirname[NAME_MAX + 1]; - FAR uint32_t *ptr; - uint32_t tmp; - int namelen; - int reqlen; - int error; - - /* Sanity checks */ - - DEBUGASSERT(mountpt && mountpt->i_private); - - /* Get the mountpoint private data from the inode structure */ - - nmp = (struct nfsmount*) mountpt->i_private; - - /* Check if the mount is still healthy */ - - nfs_semtake(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - fdbg("ERROR: nfs_checkmount: %d\n", error); - goto errout_with_semaphore; - } - - /* Find the NFS node of the directory containing the directory to be created */ - - error = nfs_finddir(nmp, relpath, &fhandle, &fattr, dirname); - if (error != OK) - { - fdbg("ERROR: nfs_finddir returned: %d\n", error); - return error; - } - - /* Format the MKDIR call message arguments */ - - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.mkdir.mkdir; - reqlen = 0; - - /* Copy the variable length, directory file handle */ - - *ptr++ = txdr_unsigned(fhandle.length); - reqlen += sizeof(uint32_t); - - memcpy(ptr, &fhandle.handle, fhandle.length); - ptr += uint32_increment(fhandle.length); - reqlen += (int)fhandle.length; - - /* Copy the variable-length directory name */ - - namelen = strlen(dirname); - - *ptr++ = txdr_unsigned(namelen); - reqlen += sizeof(uint32_t); - - memcpy(ptr, dirname, namelen); - ptr += uint32_increment(namelen); - reqlen += uint32_alignup(namelen); - - /* Set the mode. NOTE: Here we depend on the fact that the NuttX and NFS - * bit settings are the same (at least for the bits of interest). - */ - - *ptr++ = nfs_true; /* True: mode value follows */ - reqlen += sizeof(uint32_t); - - tmp = mode & (NFSMODE_IXOTH | NFSMODE_IWOTH | NFSMODE_IROTH | - NFSMODE_IXGRP | NFSMODE_IWGRP | NFSMODE_IRGRP | - NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR); - *ptr++ = txdr_unsigned(tmp); - reqlen += sizeof(uint32_t); - - /* Set the user ID to zero */ - - *ptr++ = nfs_true; /* True: Uid value follows */ - *ptr++ = 0; /* UID = 0 (nobody) */ - reqlen += 2*sizeof(uint32_t); - - /* Set the group ID to one */ - - *ptr++ = nfs_true; /* True: Gid value follows */ - *ptr++ = HTONL(1); /* GID = 1 (nogroup) */ - reqlen += 2*sizeof(uint32_t); - - /* No size */ - - *ptr++ = nfs_false; /* False: No size value follows */ - reqlen += sizeof(uint32_t); - - /* Don't change times */ - - *ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change atime */ - *ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change mtime */ - reqlen += 2*sizeof(uint32_t); - - /* Perform the MKDIR RPC */ - - nfs_statistics(NFSPROC_MKDIR); - error = nfs_request(nmp, NFSPROC_MKDIR, - (FAR void *)&nmp->nm_msgbuffer.mkdir, reqlen, - (FAR void *)&nmp->nm_iobuffer, nmp->nm_buflen); - if (error) - { - fdbg("ERROR: nfs_request failed: %d\n", error); - } - -errout_with_semaphore: - nfs_semgive(nmp); - return -error; -} - -/**************************************************************************** - * Name: nfs_rmdir - * - * Description: - * Remove a directory - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_rmdir(struct inode *mountpt, const char *relpath) -{ - struct nfsmount *nmp; - struct file_handle fhandle; - struct nfs_fattr fattr; - char dirname[NAME_MAX + 1]; - FAR uint32_t *ptr; - int namelen; - int reqlen; - int error; - - /* Sanity checks */ - - DEBUGASSERT(mountpt && mountpt->i_private); - - /* Get the mountpoint private data from the inode structure */ - - nmp = (struct nfsmount *)mountpt->i_private; - - /* Check if the mount is still healthy */ - - nfs_semtake(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - fdbg("ERROR: nfs_checkmount failed: %d\n", error); - goto errout_with_semaphore; - } - - /* Find the NFS node of the directory containing the directory to be removed */ - - error = nfs_finddir(nmp, relpath, &fhandle, &fattr, dirname); - if (error != OK) - { - fdbg("ERROR: nfs_finddir returned: %d\n", error); - return error; - } - - /* Set up the RMDIR call message arguments */ - - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.rmdir.rmdir; - reqlen = 0; - - /* Copy the variable length, directory file handle */ - - *ptr++ = txdr_unsigned(fhandle.length); - reqlen += sizeof(uint32_t); - - memcpy(ptr, &fhandle.handle, fhandle.length); - reqlen += (int)fhandle.length; - ptr += uint32_increment(fhandle.length); - - /* Copy the variable-length directory name */ - - namelen = strlen(dirname); - - *ptr++ = txdr_unsigned(namelen); - reqlen += sizeof(uint32_t); - - memcpy(ptr, dirname, namelen); - reqlen += uint32_alignup(namelen); - - /* Perform the RMDIR RPC */ - - nfs_statistics(NFSPROC_RMDIR); - error = nfs_request(nmp, NFSPROC_RMDIR, - (FAR void *)&nmp->nm_msgbuffer.rmdir, reqlen, - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); - -errout_with_semaphore: - nfs_semgive(nmp); - return -error; -} - -/**************************************************************************** - * Name: nfs_rename - * - * Description: - * Rename a file or directory - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_rename(struct inode *mountpt, const char *oldrelpath, - const char *newrelpath) -{ - struct nfsmount *nmp; - struct file_handle from_handle; - struct file_handle to_handle; - char from_name[NAME_MAX+1]; - char to_name[NAME_MAX+1]; - struct nfs_fattr fattr; - FAR uint32_t *ptr; - int namelen; - int reqlen; - int error; - - /* Sanity checks */ - - DEBUGASSERT(mountpt && mountpt->i_private); - - /* Get the mountpoint private data from the inode structure */ - - nmp = (struct nfsmount *)mountpt->i_private; - - /* Check if the mount is still healthy */ - - nfs_semtake(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - fdbg("ERROR: nfs_checkmount returned: %d\n", error); - goto errout_with_semaphore; - } - - /* Find the NFS node of the directory containing the 'from' object */ - - error = nfs_finddir(nmp, oldrelpath, &from_handle, &fattr, from_name); - if (error != OK) - { - fdbg("ERROR: nfs_finddir returned: %d\n", error); - return error; - } - - /* Find the NFS node of the directory containing the 'from' object */ - - error = nfs_finddir(nmp, newrelpath, &to_handle, &fattr, to_name); - if (error != OK) - { - fdbg("ERROR: nfs_finddir returned: %d\n", error); - return error; - } - - /* Format the RENAME RPC arguments */ - - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.renamef.rename; - reqlen = 0; - - /* Copy the variable length, 'from' directory file handle */ - - *ptr++ = txdr_unsigned(from_handle.length); - reqlen += sizeof(uint32_t); - - memcpy(ptr, &from_handle.handle, from_handle.length); - reqlen += (int)from_handle.length; - ptr += uint32_increment(from_handle.length); - - /* Copy the variable-length 'from' object name */ - - namelen = strlen(from_name); - - *ptr++ = txdr_unsigned(namelen); - reqlen += sizeof(uint32_t); - - memcpy(ptr, from_name, namelen); - reqlen += uint32_alignup(namelen); - ptr += uint32_increment(namelen); - - /* Copy the variable length, 'to' directory file handle */ - - *ptr++ = txdr_unsigned(to_handle.length); - reqlen += sizeof(uint32_t); - - memcpy(ptr, &to_handle.handle, to_handle.length); - ptr += uint32_increment(to_handle.length); - reqlen += (int)to_handle.length; - - /* Copy the variable-length 'to' object name */ - - namelen = strlen(to_name); - - *ptr++ = txdr_unsigned(namelen); - reqlen += sizeof(uint32_t); - - memcpy(ptr, to_name, namelen); - reqlen += uint32_alignup(namelen); - - /* Perform the RENAME RPC */ - - nfs_statistics(NFSPROC_RENAME); - error = nfs_request(nmp, NFSPROC_RENAME, - (FAR void *)&nmp->nm_msgbuffer.renamef, reqlen, - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); - -errout_with_semaphore: - nfs_semgive(nmp); - return -error; -} - -/**************************************************************************** - * Name: nfs_stat - * - * Description: - * Return information about the file system object at 'relpath' - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_stat(struct inode *mountpt, const char *relpath, - struct stat *buf) -{ - struct nfsmount *nmp; - struct file_handle fhandle; - struct nfs_fattr obj_attributes; - uint32_t tmp; - uint32_t mode; - int error; - - /* Sanity checks */ - - DEBUGASSERT(mountpt && mountpt->i_private); - - /* Get the mountpoint private data from the inode structure */ - - nmp = (struct nfsmount*)mountpt->i_private; - DEBUGASSERT(nmp && buf); - - /* Check if the mount is still healthy */ - - nfs_semtake(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - fdbg("ERROR: nfs_checkmount failed: %d\n", error); - goto errout_with_semaphore; - } - - /* Get the file handle attributes of the requested node */ - - error = nfs_findnode(nmp, relpath, &fhandle, &obj_attributes, NULL); - if (error != OK) - { - fdbg("ERROR: nfs_findnode failed: %d\n", error); - goto errout_with_semaphore; - } - - /* Construct the file mode. This is a 32-bit, encoded value containing - * both the access mode and the file type. - */ - - tmp = fxdr_unsigned(uint32_t, obj_attributes.fa_mode); - - /* Here we exploit the fact that most mode bits are the same in NuttX - * as in the NFSv3 spec. - */ - - mode = tmp & (NFSMODE_IXOTH|NFSMODE_IWOTH|NFSMODE_IROTH| - NFSMODE_IXGRP|NFSMODE_IWGRP|NFSMODE_IRGRP| - NFSMODE_IXUSR|NFSMODE_IWUSR|NFSMODE_IRUSR); - - /* Handle the cases that are not the same */ - - if ((mode & NFSMODE_ISGID) != 0) - { - mode |= S_ISGID; - } - - if ((mode & NFSMODE_ISUID) != 0) - { - mode |= S_ISUID; - } - - /* Now OR in the file type */ - - tmp = fxdr_unsigned(uint32_t, obj_attributes.fa_type); - switch (tmp) - { - default: - case NFNON: /* Unknown type */ - break; - - case NFREG: /* Regular file */ - mode |= S_IFREG; - break; - - case NFDIR: /* Directory */ - mode |= S_IFDIR; - break; - - case NFBLK: /* Block special device file */ - mode |= S_IFBLK; - break; - - case NFCHR: /* Character special device file */ - mode |= S_IFCHR; - break; - - case NFLNK: /* Symbolic link */ - mode |= S_IFLNK; - break; - - case NFSOCK: /* Socket */ - mode |= S_IFSOCK; - break; - - case NFFIFO: /* Named pipe */ - mode |= S_IFMT; - break; - } - - buf->st_mode = mode; - buf->st_size = fxdr_hyper(&obj_attributes.fa_size); - buf->st_blksize = 0; - buf->st_blocks = 0; - buf->st_mtime = fxdr_hyper(&obj_attributes.fa_mtime); - buf->st_atime = fxdr_hyper(&obj_attributes.fa_atime); - buf->st_ctime = fxdr_hyper(&obj_attributes.fa_ctime); - -errout_with_semaphore: - nfs_semgive(nmp); - return -error; -} diff --git a/nuttx/fs/nfs/rpc.h b/nuttx/fs/nfs/rpc.h deleted file mode 100644 index 27366557d..000000000 --- a/nuttx/fs/nfs/rpc.h +++ /dev/null @@ -1,491 +0,0 @@ -/**************************************************************************** - * fs/nfs/rpc.h - * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. - * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. - * Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com> - * Gregory Nutt <gnutt@nuttx.org> - * - * Leveraged from OpenBSD: - * - * copyright (c) 2003 - * the regents of the university of michigan - * all rights reserved - * - * permission is granted to use, copy, create derivative works and redistribute - * this software and such derivative works for any purpose, so long as the name - * of the university of michigan is not used in any advertising or publicity - * pertaining to the use or distribution of this software without specific, - * written prior authorization. if the above copyright notice or any other - * identification of the university of michigan is included in any copy of any - * portion of this software, then the disclaimer below must also be included. - * - * this software is provided as is, without representation from the university - * of michigan as to its fitness for any purpose, and without warranty by the - * university of michigan of any kind, either express or implied, including - * without limitation the implied warranties of merchantability and fitness for - * a particular purpose. the regents of the university of michigan shall not be - * liable for any damages, including special, indirect, incidental, or - * consequential damages, with respect to any claim arising out of or in - * connection with the use of the software, even if it has been or is hereafter - * advised of the possibility of such damages. - * - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Rick Macklem at The University of Guelph. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by 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. - * - ****************************************************************************/ - -#ifndef __FS_NFS_RPC_H -#define __FS_NFS_RPC_H - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include <sys/types.h> -#include "nfs_proto.h" - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* Version # */ - -#define RPC_VER2 2 - -/* Authentication */ - -#define RPCAUTH_NULL 0 -#define RPCAUTH_UNIX 1 -#define RPCAUTH_SHORT 2 -#define RPCAUTH_KERB4 4 -#define RPCAUTH_MAXSIZ 400 -#define RPCVERF_MAXSIZ 12 - /* For Kerb, can actually be 400 */ -#define RPCAUTH_UNIXGIDS 16 - -/* Constants associated with authentication flavours. */ - -#define RPCAKN_FULLNAME 0 -#define RPCAKN_NICKNAME 1 - -/* RPC Constants */ - -#define RPC_CALL 0 -#define RPC_REPLY 1 -#define RPC_MSGACCEPTED 0 -#define RPC_MSGDENIED 1 -#define RPC_PROGUNAVAIL 1 -#define RPC_PROGMISMATCH 2 -#define RPC_PROCUNAVAIL 3 -#define RPC_GARBAGE 4 - -#define RPC_MISMATCH 0 -#define RPC_AUTHERR 1 - -/* Authentication failures */ - -#define AUTH_BADCRED 1 -#define AUTH_REJECTCRED 2 -#define AUTH_BADVERF 3 -#define AUTH_REJECTVERF 4 -#define AUTH_TOOWEAK 5 - -/* Sizes of RPC header parts */ - -#define RPC_SIZ 24 -#define RPC_REPLYSIZ 28 - -/* RPC Prog definitions */ - -#define RPCPROG_MNT 100005 -#define RPCMNT_VER1 1 -#define RPCMNT_VER3 3 -#define RPCMNT_MOUNT 1 -#define RPCMNT_DUMP 2 -#define RPCMNT_UMOUNT 3 -#define RPCMNT_UMNTALL 4 -#define RPCMNT_EXPORT 5 -#define RPCMNT_NAMELEN 255 -#define RPCMNT_PATHLEN 1024 -#define RPCPROG_NFS 100003 - -/* RPC definitions for the portmapper. */ - -#define PMAPPORT 111 -#define PMAPPROG 100000 -#define PMAPVERS 2 - -#define PMAPPROC_NULL 0 -#define PMAPPROC_SET 1 -#define PMAPPROC_UNSET 2 -#define PMAPPROC_GETPORT 3 -#define PMAPPROC_DUMP 4 -#define PMAPPROC_CALLIT 5 - -#define RPC_SUCCESS 0 - -/**************************************************************************** - * Public Types - ****************************************************************************/ - -/* Global RPC statistics */ - -#ifdef CONFIG_NFS_STATISTICS -struct rpcstats -{ - int rpcretries; - int rpcrequests; - int rpctimeouts; - int rpcinvalid; -}; -#endif - -/* PMAP headers */ - -struct call_args_pmap -{ - uint32_t prog; - uint32_t vers; - uint32_t proc; - uint32_t port; -}; - -struct call_result_pmap -{ - uint32_t port; -}; - -/* MOUNTD headers */ - -struct call_args_mount -{ - uint32_t len; - char rpath[90]; -}; - -struct call_args_umount -{ - uint32_t len; - char rpath[90]; -}; - -struct call_result_mount -{ - uint32_t status; - nfsfh_t fhandle; -}; - -/* Generic RPC call headers */ - -enum auth_flavor -{ - AUTH_NONE = 0, - AUTH_SYS = 1, - AUTH_SHORT = 2 - /* and more to be defined */ -}; - -struct rpc_auth_info -{ - uint32_t authtype; /* auth type */ - uint32_t authlen; /* auth length */ -}; - -struct auth_unix -{ - int32_t stamp; - uint8_t hostname; /* null */ - int32_t uid; - int32_t gid; - int32_t gidlist; /* null */ -}; - -struct rpc_call_header -{ - uint32_t rp_xid; /* request transaction id */ - int32_t rp_direction; /* call direction (0) */ - uint32_t rp_rpcvers; /* RPC version (2) */ - uint32_t rp_prog; /* program */ - uint32_t rp_vers; /* version */ - uint32_t rp_proc; /* procedure */ - struct rpc_auth_info rpc_auth; - struct rpc_auth_info rpc_verf; -}; - -struct rpc_call_pmap -{ - struct rpc_call_header ch; - struct call_args_pmap pmap; -}; - -struct rpc_call_mount -{ - struct rpc_call_header ch; - struct call_args_mount mount; -}; - -struct rpc_call_umount -{ - struct rpc_call_header ch; - struct call_args_umount umount; -}; - -struct rpc_call_create -{ - struct rpc_call_header ch; - struct CREATE3args create; -}; - -struct rpc_call_lookup -{ - struct rpc_call_header ch; - struct LOOKUP3args lookup; -}; -#define SIZEOF_rpc_call_lookup(n) (sizeof(struct rpc_call_header) + SIZEOF_LOOKUP3args(n)) - -struct rpc_call_read -{ - struct rpc_call_header ch; - struct READ3args read; -}; - -struct rpc_call_write -{ - struct rpc_call_header ch; - struct WRITE3args write; /* Variable length */ -}; -#define SIZEOF_rpc_call_write(n) (sizeof(struct rpc_call_header) + SIZEOF_WRITE3args(n)) - -struct rpc_call_remove -{ - struct rpc_call_header ch; - struct REMOVE3args remove; -}; - -struct rpc_call_rename -{ - struct rpc_call_header ch; - struct RENAME3args rename; -}; - -struct rpc_call_mkdir -{ - struct rpc_call_header ch; - struct MKDIR3args mkdir; -}; - -struct rpc_call_rmdir -{ - struct rpc_call_header ch; - struct RMDIR3args rmdir; -}; - -struct rpc_call_readdir -{ - struct rpc_call_header ch; - struct READDIR3args readdir; -}; - -struct rpc_call_setattr -{ - struct rpc_call_header ch; - struct SETATTR3args setattr; -}; - -struct rpc_call_fs -{ - struct rpc_call_header ch; - struct FS3args fs; -}; - -/* Generic RPC reply headers */ - -struct rpc_reply_header -{ - uint32_t rp_xid; /* Request transaction id */ - uint32_t rp_direction; /* Call direction (1) */ - uint32_t type; - struct rpc_auth_info rpc_verfi; - uint32_t status; -}; - -struct nfs_reply_header -{ - uint32_t rp_xid; /* Request transaction id */ - uint32_t rp_direction; /* Call direction (1) */ - uint32_t type; - struct rpc_auth_info rpc_verfi; - uint32_t status; - uint32_t nfs_status; -}; - -struct rpc_reply_pmap -{ - struct rpc_reply_header rh; - struct call_result_pmap pmap; -}; - -struct rpc_reply_mount -{ - struct rpc_reply_header rh; - struct call_result_mount mount; -}; - -struct rpc_reply_umount -{ - struct rpc_reply_header rh; -}; - -struct rpc_reply_create -{ - struct rpc_reply_header rh; - uint32_t status; - struct CREATE3resok create; -}; - -struct rpc_reply_lookup -{ - struct rpc_reply_header rh; - uint32_t status; - struct LOOKUP3resok lookup; -}; - -struct rpc_reply_write -{ - struct rpc_reply_header rh; - uint32_t status; - struct WRITE3resok write; /* Variable length */ -}; - -struct rpc_reply_read -{ - struct rpc_reply_header rh; - uint32_t status; - struct READ3resok read; /* Variable length */ -}; -#define SIZEOF_rpc_reply_read(n) (sizeof(struct rpc_reply_header) + sizeof(uint32_t) + SIZEOF_READ3resok(n)) - -struct rpc_reply_remove -{ - struct rpc_reply_header rh; - uint32_t status; - struct REMOVE3resok remove; -}; - -struct rpc_reply_rename -{ - struct rpc_reply_header rh; - uint32_t status; - struct RENAME3resok rename; -}; - -struct rpc_reply_mkdir -{ - struct rpc_reply_header rh; - uint32_t status; - struct MKDIR3resok mkdir; -}; - -struct rpc_reply_rmdir -{ - struct rpc_reply_header rh; - uint32_t status; - struct RMDIR3resok rmdir; -}; - -struct rpc_reply_readdir -{ - struct rpc_reply_header rh; - uint32_t status; - struct READDIR3resok readdir; -}; - -struct rpc_reply_fsinfo -{ - struct rpc_reply_header rh; - uint32_t status; - struct nfsv3_fsinfo fsinfo; -}; - -struct rpc_reply_fsstat -{ - struct rpc_reply_header rh; - uint32_t status; - struct nfs_statfs fsstat; -}; - -struct rpc_reply_getattr -{ - struct rpc_reply_header rh; - uint32_t status; - struct nfs_fattr attr; -}; - -struct rpc_reply_setattr -{ - struct rpc_reply_header rh; - uint32_t status; - struct SETATTR3resok setattr; -}; - -struct rpcclnt -{ - nfsfh_t rc_fh; /* File handle of the root directory */ - char *rc_path; /* Server's path of the mounted directory */ - - struct sockaddr *rc_name; - struct socket *rc_so; /* RPC socket */ - - bool rc_timeout; /* Receipt of reply timed out */ - uint8_t rc_sotype; /* Type of socket */ - uint8_t rc_retry; /* Max retries */ -}; - -/**************************************************************************** - * Public Function Prototypes - ****************************************************************************/ - -void rpcclnt_init(void); -int rpcclnt_connect(FAR struct rpcclnt *rpc); -int rpcclnt_reconnect(FAR struct rpcclnt *rpc); -void rpcclnt_disconnect(FAR struct rpcclnt *rpc); -int rpcclnt_umount(FAR struct rpcclnt *rpc); -void rpcclnt_safedisconnect(FAR struct rpcclnt *rpc); -int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, int version, - FAR void *request, size_t reqlen, - FAR void *response, size_t resplen); - -#endif /* __FS_NFS_RPC_H */ diff --git a/nuttx/fs/nfs/rpc_clnt.c b/nuttx/fs/nfs/rpc_clnt.c deleted file mode 100644 index 9c2ada4f2..000000000 --- a/nuttx/fs/nfs/rpc_clnt.c +++ /dev/null @@ -1,805 +0,0 @@ -/**************************************************************************** - * fs/nfs/rpc_clnt.c - * - * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. - * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. - * Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com> - * Gregory Nutt <gnutt@nuttx.org> - * - * Leveraged from OpenBSD: - * - * Copyright (c) 2004 The Regents of the University of Michigan. - * All rights reserved. - * - * Copyright (c) 2004 Weston Andros Adamson <muzzle@umich.edu>. - * Copyright (c) 2004 Marius Aamodt Eriksen <marius@umich.edu>. - * 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. 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 ``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. - * - * Copyright (c) 1989, 1991, 1993, 1995 The Regents of the University of - * California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by Rick Macklem at - * The University of Guelph. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. 3. All advertising - * materials mentioning features or use of this software must display the - * following acknowledgement: This product includes software developed by 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. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include <sys/socket.h> -#include <queue.h> -#include <time.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <debug.h> -#include <nuttx/kmalloc.h> - -#include "xdr_subs.h" -#include "nfs_proto.h" -#include "rpc.h" - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* Increment RPC statistics */ - -#ifdef CONFIG_NFS_STATISTICS -# define rpc_statistics(n) do { rpcstats.(n)++; } while (0) -#else -# define rpc_statistics(n) -#endif - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -/* Static data, mostly RPC constants in XDR form */ - -static uint32_t rpc_reply; -static uint32_t rpc_call; -static uint32_t rpc_vers; -static uint32_t rpc_msgdenied; -static uint32_t rpc_mismatch; -static uint32_t rpc_auth_unix; -static uint32_t rpc_msgaccepted; -static uint32_t rpc_autherr; -static uint32_t rpc_auth_null; - -/* Global statics for all client instances. Cleared by NuttX on boot-up. */ - -#ifdef CONFIG_NFS_STATISTICS -static struct rpcstats rpcstats; -#endif - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog, - FAR void *call, int reqlen); -static int rpcclnt_receive(FAR struct rpcclnt *rpc, struct sockaddr *aname, - int proc, int program, void *reply, size_t resplen); -static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog, - void *reply, size_t resplen); -static uint32_t rpcclnt_newxid(void); -static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch, - uint32_t xid, int procid, int prog, int vers); - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: rpcclnt_send - * - * Description: - * This is the nfs send routine. - * - * Returned Value: - * Returns zero on success or a (positive) errno value on failure. - * - ****************************************************************************/ - -static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog, - FAR void *call, int reqlen) -{ - ssize_t nbytes; - int error = OK; - - /* Send the call message - * - * On success, psock_sendto returns the number of bytes sent; - * On failure, it returns -1 with the specific error in errno. - */ - - nbytes = psock_sendto(rpc->rc_so, call, reqlen, 0, - rpc->rc_name, sizeof(struct sockaddr)); - if (nbytes < 0) - { - /* psock_sendto failed */ - - error = errno; - fdbg("ERROR: psock_sendto failed: %d\n", error); - } - - return error; -} - -/**************************************************************************** - * Name: rpcclnt_receive - * - * Description: - * Receive a Sun RPC Request/Reply. For SOCK_DGRAM, the work is all done - * by psock_recvfrom(). - * - ****************************************************************************/ - -static int rpcclnt_receive(FAR struct rpcclnt *rpc, FAR struct sockaddr *aname, - int proc, int program, FAR void *reply, - size_t resplen) -{ - ssize_t nbytes; - int error = 0; - - socklen_t fromlen = sizeof(struct sockaddr); - nbytes = psock_recvfrom(rpc->rc_so, reply, resplen, 0, aname, &fromlen); - if (nbytes < 0) - { - error = errno; - fdbg("ERROR: psock_recvfrom failed: %d\n", error); - } - - return error; -} - -/**************************************************************************** - * Name: rpcclnt_reply - * - * Description: - * Received the RPC reply on the socket. - * - ****************************************************************************/ - -static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog, - FAR void *reply, size_t resplen) -{ - int error; - - /* Get the next RPC reply from the socket */ - - error = rpcclnt_receive(rpc, rpc->rc_name, procid, prog, reply, resplen); - if (error != 0) - { - fdbg("ERROR: rpcclnt_receive returned: %d\n", error); - - /* If we failed because of a timeout, then try sending the CALL - * message again. - */ - - if (error == EAGAIN || error == ETIMEDOUT) - { - rpc->rc_timeout = true; - } - } - - /* Get the xid and check that it is an RPC replysvr */ - - else - { - FAR struct rpc_reply_header *replyheader = - (FAR struct rpc_reply_header *)reply; - - if (replyheader->rp_direction != rpc_reply) - { - fdbg("ERROR: Different RPC REPLY returned\n"); - rpc_statistics(rpcinvalid); - error = EPROTO; - } - } - - return error; -} - -/**************************************************************************** - * Name: rpcclnt_newxid - * - * Description: - * Get a new (non-zero) xid - * - ****************************************************************************/ - -static uint32_t rpcclnt_newxid(void) -{ - static uint32_t rpcclnt_xid = 0; - static uint32_t rpcclnt_xid_touched = 0; - - srand(time(NULL)); - if ((rpcclnt_xid == 0) && (rpcclnt_xid_touched == 0)) - { - rpcclnt_xid = rand(); - rpcclnt_xid_touched = 1; - } - else - { - int xidp = 0; - do - { - xidp = rand(); - } - while ((xidp % 256) == 0); - - rpcclnt_xid += xidp; - } - - return rpcclnt_xid; -} - -/**************************************************************************** - * Name: rpcclnt_fmtheader - * - * Description: - * Format the common part of the call header - * - ****************************************************************************/ - -static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch, - uint32_t xid, int prog, int vers, int procid) -{ - /* Format the call header */ - - ch->rp_xid = txdr_unsigned(xid); - ch->rp_direction = rpc_call; - ch->rp_rpcvers = rpc_vers; - ch->rp_prog = txdr_unsigned(prog); - ch->rp_vers = txdr_unsigned(vers); - ch->rp_proc = txdr_unsigned(procid); - - /* rpc_auth part (auth_null) */ - - ch->rpc_auth.authtype = rpc_auth_null; - ch->rpc_auth.authlen = 0; - - /* rpc_verf part (auth_null) */ - - ch->rpc_verf.authtype = rpc_auth_null; - ch->rpc_verf.authlen = 0; -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: rpcclnt_init - * - * Description: - * Initialize the RPC client - * - ****************************************************************************/ - -void rpcclnt_init(void) -{ - /* RPC constants how about actually using more than one of these! */ - - rpc_reply = txdr_unsigned(RPC_REPLY); - rpc_vers = txdr_unsigned(RPC_VER2); - rpc_call = txdr_unsigned(RPC_CALL); - rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED); - rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED); - rpc_mismatch = txdr_unsigned(RPC_MISMATCH); - rpc_autherr = txdr_unsigned(RPC_AUTHERR); - rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX); - rpc_auth_null = txdr_unsigned(RPCAUTH_NULL); - - fvdbg("RPC initialized\n"); -} - -/**************************************************************************** - * Name: rpcclnt_connect - * - * Description: - * Initialize sockets for a new RPC connection. We do not free the - * sockaddr if an error occurs. - * - ****************************************************************************/ - -int rpcclnt_connect(struct rpcclnt *rpc) -{ - struct socket *so; - int error; - struct sockaddr *saddr; - struct sockaddr_in sin; - struct sockaddr_in *sa; - - union - { - struct rpc_call_pmap sdata; - struct rpc_call_mount mountd; - } request; - - union - { - struct rpc_reply_pmap rdata; - struct rpc_reply_mount mdata; - } response; - - struct timeval tv; - uint16_t tport; - int errval; - - fvdbg("Connecting\n"); - - /* Create the socket */ - - saddr = rpc->rc_name; - - /* Create an instance of the socket state structure */ - - so = (struct socket *)kzalloc(sizeof(struct socket)); - if (!so) - { - fdbg("ERROR: Failed to allocate socket structure\n"); - return ENOMEM; - } - - error = psock_socket(saddr->sa_family, rpc->rc_sotype, IPPROTO_UDP, so); - if (error < 0) - { - errval = errno; - fdbg("ERROR: psock_socket failed: %d", errval); - return error; - } - - so->s_crefs = 1; - rpc->rc_so = so; - - /* Always set receive timeout to detect server crash and reconnect. - * Otherwise, we can get stuck in psock_receive forever. - */ - - tv.tv_sec = 1; - tv.tv_usec = 0; - - error = psock_setsockopt(rpc->rc_so, SOL_SOCKET, SO_RCVTIMEO, - (const void *)&tv, sizeof(tv)); - if (error < 0) - { - errval = errno; - fdbg("ERROR: psock_setsockopt failed: %d\n", errval); - goto bad; - } - - /* Some servers require that the client port be a reserved port - * number. We always allocate a reserved port, as this prevents - * filehandle disclosure through UDP port capture. - */ - - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; - tport = 1024; - - errval = 0; - do - { - tport--; - sin.sin_port = htons(tport); - error = psock_bind(rpc->rc_so, (struct sockaddr *)&sin, sizeof(sin)); - if (error < 0) - { - errval = errno; - fdbg("ERROR: psock_bind failed: %d\n", errval); - } - } - while (errval == EADDRINUSE && tport > 1024 / 2); - - if (error) - { - fdbg("ERROR: psock_bind failed: %d\n", errval); - goto bad; - } - - /* Protocols that do not require connections may be optionally left - * unconnected for servers that reply from a port other than - * NFS_PORT. - */ - - error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr)); - if (error < 0) - { - errval = errno; - fdbg("ERROR: psock_connect to PMAP port failed: %d", errval); - goto bad; - } - - /* Do the RPC to get a dynamic bounding with the server using ppmap. - * Get port number for MOUNTD. - */ - - request.sdata.pmap.prog = txdr_unsigned(RPCPROG_MNT); - request.sdata.pmap.vers = txdr_unsigned(RPCMNT_VER1); - request.sdata.pmap.proc = txdr_unsigned(IPPROTO_UDP); - request.sdata.pmap.port = 0; - - error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, - (FAR void *)&request.sdata, sizeof(struct call_args_pmap), - (FAR void *)&response.rdata, sizeof(struct rpc_reply_pmap)); - if (error != 0) - { - fdbg("ERROR: rpcclnt_request failed: %d\n", error); - goto bad; - } - - sa = (FAR struct sockaddr_in *)saddr; - sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port)); - - error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr)); - if (error < 0) - { - errval = errno; - fdbg("ERROR: psock_connect MOUNTD port failed: %d\n", errval); - goto bad; - } - - /* Do RPC to mountd. */ - - strncpy(request.mountd.mount.rpath, rpc->rc_path, 90); - request.mountd.mount.len = txdr_unsigned(sizeof(request.mountd.mount.rpath)); - - error = rpcclnt_request(rpc, RPCMNT_MOUNT, RPCPROG_MNT, RPCMNT_VER1, - (FAR void *)&request.mountd, sizeof(struct call_args_mount), - (FAR void *)&response.mdata, sizeof(struct rpc_reply_mount)); - if (error != 0) - { - fdbg("ERROR: rpcclnt_request failed: %d\n", error); - goto bad; - } - - error = fxdr_unsigned(uint32_t, response.mdata.mount.status); - if (error != 0) - { - fdbg("ERROR: Bad mount status: %d\n", error); - goto bad; - } - - memcpy(&rpc->rc_fh, &response.mdata.mount.fhandle, sizeof(nfsfh_t)); - - /* Do the RPC to get a dynamic bounding with the server using PMAP. - * NFS port in the socket. - */ - - sa->sin_port = htons(PMAPPORT); - - error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr)); - if (error < 0) - { - errval = errno; - fdbg("ERROR: psock_connect PMAP port failed: %d\n", errval); - goto bad; - } - - request.sdata.pmap.prog = txdr_unsigned(NFS_PROG); - request.sdata.pmap.vers = txdr_unsigned(NFS_VER3); - request.sdata.pmap.proc = txdr_unsigned(IPPROTO_UDP); - request.sdata.pmap.port = 0; - - error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, - (FAR void *)&request.sdata, sizeof(struct call_args_pmap), - (FAR void *)&response.rdata, sizeof(struct rpc_reply_pmap)); - if (error != 0) - { - fdbg("ERROR: rpcclnt_request failed: %d\n", error); - goto bad; - } - - sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port)); - - error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr)); - if (error) - { - fdbg("psock_connect NFS port returns %d\n", error); - goto bad; - } - - return OK; - -bad: - rpcclnt_disconnect(rpc); - return error; -} - -/**************************************************************************** - * Name: rpcclnt_disconnect - * - * Description: - * Disconnect from the NFS server. - * - ****************************************************************************/ - -void rpcclnt_disconnect(struct rpcclnt *rpc) -{ - if (rpc->rc_so != NULL) - { - (void)psock_close(rpc->rc_so); - } -} - -/**************************************************************************** - * Name: rpcclnt_umount - * - * Description: - * Un-mount the NFS file system. - * - ****************************************************************************/ - -int rpcclnt_umount(struct rpcclnt *rpc) -{ - struct sockaddr *saddr; - struct sockaddr_in *sa; - - union - { - struct rpc_call_pmap sdata; - struct rpc_call_umount mountd; - } request; - - union - { - struct rpc_reply_pmap rdata; - struct rpc_reply_umount mdata; - } response; - - int error; - int ret; - - saddr = rpc->rc_name; - sa = (FAR struct sockaddr_in *)saddr; - - /* Do the RPC to get a dynamic bounding with the server using ppmap. - * Get port number for MOUNTD. - */ - - sa->sin_port = htons(PMAPPORT); - - ret = psock_connect(rpc->rc_so, saddr, sizeof(*saddr)); - if (ret < 0) - { - error = errno; - fdbg("ERROR: psock_connect failed [port=%d]: %d\n", - ntohs(sa->sin_port), error); - goto bad; - } - - request.sdata.pmap.prog = txdr_unsigned(RPCPROG_MNT); - request.sdata.pmap.vers = txdr_unsigned(RPCMNT_VER1); - request.sdata.pmap.proc = txdr_unsigned(IPPROTO_UDP); - request.sdata.pmap.port = 0; - - error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, - (FAR void *)&request.sdata, sizeof(struct call_args_pmap), - (FAR void *)&response.rdata, sizeof(struct rpc_reply_pmap)); - if (error != 0) - { - fdbg("ERROR: rpcclnt_request failed: %d\n", error); - goto bad; - } - - sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port)); - - ret = psock_connect(rpc->rc_so, saddr, sizeof(*saddr)); - if (ret < 0) - { - error = errno; - fdbg("ERROR: psock_connect failed [port=%d]: %d\n", - ntohs(sa->sin_port), error); - goto bad; - } - - /* Do RPC to umountd. */ - - strncpy(request.mountd.umount.rpath, rpc->rc_path, 92); - request.mountd.umount.len = txdr_unsigned(sizeof(request.mountd.umount.rpath)); - - error = rpcclnt_request(rpc, RPCMNT_UMOUNT, RPCPROG_MNT, RPCMNT_VER1, - (FAR void *)&request.mountd, sizeof(struct call_args_umount), - (FAR void *)&response.mdata, sizeof(struct rpc_reply_umount)); - if (error != 0) - { - fdbg("ERROR: rpcclnt_request failed: %d\n", error); - goto bad; - } - - return OK; - -bad: - rpcclnt_disconnect(rpc); - return error; -} - -/**************************************************************************** - * Name: rpcclnt_request - * - * Description: - * Perform the RPC request. Logic formats the RPC CALL message and calls - * rpcclnt_send to send the RPC CALL message. It then calls rpcclnt_reply() - * to get the response. It may attempt to re-send the CALL message on - * certain errors. - * - * On successful receipt, it verifies the RPC level of the returned values. - * (There may still be be NFS layer errors that will be deted by calling - * logic). - * - ****************************************************************************/ - -int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, - int version, FAR void *request, size_t reqlen, - FAR void *response, size_t resplen) -{ - struct rpc_reply_header *replymsg; - uint32_t tmp; - uint32_t xid; - int retries; - int error = 0; - - /* Get a new (non-zero) xid */ - - xid = rpcclnt_newxid(); - - /* Initialize the RPC header fields */ - - rpcclnt_fmtheader((FAR struct rpc_call_header *)request, - xid, prog, version, procnum); - - /* Get the full size of the message (the size of variable data plus the size of - * the messages header). - */ - - reqlen += sizeof(struct rpc_call_header); - - /* Send the RPC call messsages and receive the RPC response. A limited - * number of re-tries will be attempted, but only for the case of response - * timeouts. - */ - - retries = 0; - do - { - /* Do the client side RPC. */ - - rpc_statistics(rpcrequests); - rpc->rc_timeout = false; - - /* Send the RPC CALL message */ - - error = rpcclnt_send(rpc, procnum, prog, request, reqlen); - if (error != OK) - { - fvdbg("ERROR rpcclnt_send failed: %d\n", error); - } - - /* Wait for the reply from our send */ - - else - { - error = rpcclnt_reply(rpc, procnum, prog, response, resplen); - if (error != OK) - { - fvdbg("ERROR rpcclnt_reply failed: %d\n", error); - } - } - - retries++; - } - while (rpc->rc_timeout && retries <= rpc->rc_retry); - - if (error != OK) - { - fdbg("ERROR: RPC failed: %d\n", error); - return error; - } - - /* Break down the RPC header and check if it is OK */ - - replymsg = (FAR struct rpc_reply_header *)response; - - tmp = fxdr_unsigned(uint32_t, replymsg->type); - if (tmp == RPC_MSGDENIED) - { - tmp = fxdr_unsigned(uint32_t, replymsg->status); - switch (tmp) - { - case RPC_MISMATCH: - fdbg("RPC_MSGDENIED: RPC_MISMATCH error\n"); - return EOPNOTSUPP; - - case RPC_AUTHERR: - fdbg("RPC_MSGDENIED: RPC_AUTHERR error\n"); - return EACCES; - - default: - return EOPNOTSUPP; - } - } - else if (tmp != RPC_MSGACCEPTED) - { - return EOPNOTSUPP; - } - - tmp = fxdr_unsigned(uint32_t, replymsg->status); - if (tmp == RPC_SUCCESS) - { - fvdbg("RPC_SUCCESS\n"); - } - else if (tmp == RPC_PROGMISMATCH) - { - fdbg("RPC_MSGACCEPTED: RPC_PROGMISMATCH error\n"); - return EOPNOTSUPP; - } - else if (tmp > 5) - { - fdbg("ERROR: Other RPC type: %d\n", tmp); - return EOPNOTSUPP; - } - - return OK; -} diff --git a/nuttx/fs/nfs/xdr_subs.h b/nuttx/fs/nfs/xdr_subs.h deleted file mode 100644 index 891af004c..000000000 --- a/nuttx/fs/nfs/xdr_subs.h +++ /dev/null @@ -1,128 +0,0 @@ -/**************************************************************************** - * fs/nfs/xdr_subs.h - * Definitions for Sun RPC Version 2, from - * "RPC: Remote Procedure Call Protocol Specification" RFC1057 - * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. - * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. - * Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com> - * Gregory Nutt <gnutt@nuttx.org> - * - * Leveraged from OpenBSD: - * - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Rick Macklem at The University of Guelph. - * - * 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. 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. - * - ****************************************************************************/ - -#ifndef __FS_NFS_XDR_SUBS_H -#define __FS_NFS_XDR_SUBS_H - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include <arpa/inet.h> - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ -/* Macros used for conversion to/from xdr representation by nfs... - * These use the MACHINE DEPENDENT routines ntohl, htonl - * As defined by "XDR: External Data Representation Standard" RFC1014 - * - * To simplify the implementation, we use ntohl/htonl even on big-endian - * machines, and count on them being `#define'd away. Some of these - * might be slightly more efficient as int64_t copies on a big-endian, - * but we cannot count on their alignment anyway. - */ - -#define fxdr_unsigned(t, v) ((t)ntohl(v)) -#define txdr_unsigned(v) (htonl(v)) - -#define fxdr_nfsv2time(f, t) \ -{ \ - (t)->tv_sec = ntohl(((struct nfsv2_time *)(f))->nfsv2_sec); \ - if (((struct nfsv2_time *)(f))->nfsv2_usec != 0xffffffff) \ - (t)->tv_nsec = 1000 * ntohl(((struct nfsv2_time *)(f))->nfsv2_usec); \ - else \ - (t)->tv_nsec = 0; \ -} - -#define txdr_nfsv2time(f, t) \ -{ \ - ((struct nfsv2_time *)(t))->nfsv2_sec = htonl((f)->tv_sec); \ - if ((f)->tv_nsec != -1) \ - ((struct nfsv2_time *)(t))->nfsv2_usec = htonl((f)->tv_nsec / 1000); \ - else \ - ((struct nfsv2_time *)(t))->nfsv2_usec = 0xffffffff; \ -} - -#define fxdr_nfsv3time(f, t) \ -{ \ - (t)->tv_sec = ntohl(((struct nfsv3_time *)(f))->nfsv3_sec); \ - (t)->tv_nsec = ntohl(((struct nfsv3_time *)(f))->nfsv3_nsec); \ -} - -#define fxdr_nfsv3time2(f, t) { \ - (t)->nfsv3_sec = ntohl(((struct nfsv3_time *)(f))->nfsv3_sec); \ - (t)->nfsv3_nsec = ntohl(((struct nfsv3_time *)(f))->nfsv3_nsec); \ -} - -#define txdr_nfsv3time(f, t) \ -{ \ - ((struct nfsv3_time *)(t))->nfsv3_sec = htonl((f)->tv_sec); \ - ((struct nfsv3_time *)(t))->nfsv3_nsec = htonl((f)->tv_nsec); \ -} - -#define txdr_nfsv3time2(f, t) \ -{ \ - ((struct nfsv3_time *)(t))->nfsv3_sec = htonl((f)->nfsv3_sec); \ - ((struct nfsv3_time *)(t))->nfsv3_nsec = htonl((f)->nfsv3_nsec); \ -} - -#define fxdr_hyper(f) \ - ((((uint64_t)ntohl(((uint32_t *)(f))[0])) << 32) | \ - (uint64_t)(ntohl(((uint32_t *)(f))[1]))) - -#define txdr_hyper(f, t) \ -{ \ - ((uint32_t *)(t))[0] = htonl((uint32_t)((f) >> 32)); \ - ((uint32_t *)(t))[1] = htonl((uint32_t)((f) & 0xffffffff)); \ -} - -/* Macros for dealing with byte data saved in uint32_t aligned memory */ - -#define uint32_aligndown(b) ((b) & ~3) -#define uint32_alignup(b) (((b) + 3) & ~3) -#define uint32_increment(b) (((b) + 3) >> 2) - -#endif /* __FS_NFS_XDR_SUBS_H */ |