summaryrefslogtreecommitdiff
path: root/nuttx/fs
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-06-09 15:55:10 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-06-09 15:55:10 +0000
commit41375ad4a6216e206030e71aca39c54c94e00a57 (patch)
treeb2bcdba62940f6fdedc7ba0ab8e96f6d7622ddec /nuttx/fs
parentcd9f8ddacbdfdcfa75938f9fb803a86a4e2bbea4 (diff)
downloadpx4-nuttx-41375ad4a6216e206030e71aca39c54c94e00a57.tar.gz
px4-nuttx-41375ad4a6216e206030e71aca39c54c94e00a57.tar.bz2
px4-nuttx-41375ad4a6216e206030e71aca39c54c94e00a57.zip
NFS update
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4820 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/fs')
-rw-r--r--nuttx/fs/nfs/nfs_vfsops.c271
-rw-r--r--nuttx/fs/nfs/rpc_clnt.c152
2 files changed, 239 insertions, 184 deletions
diff --git a/nuttx/fs/nfs/nfs_vfsops.c b/nuttx/fs/nfs/nfs_vfsops.c
index c78825fe8..0f948b574 100644
--- a/nuttx/fs/nfs/nfs_vfsops.c
+++ b/nuttx/fs/nfs/nfs_vfsops.c
@@ -99,6 +99,8 @@ struct nfs_dirent
* Private Function Prototypes
****************************************************************************/
+static int nfs_create(FAR struct nfsmount *nmp, struct nfsnode *np,
+ FAR const char *relpath, mode_t mode);
static int nfs_open(FAR struct file *filep, const char *relpath,
int oflags, mode_t mode);
static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen);
@@ -172,6 +174,72 @@ const struct mountpt_operations nfs_operations =
****************************************************************************/
/****************************************************************************
+ * Name: nfs_create
+ *
+ * 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_create(FAR struct nfsmount *nmp, struct nfsnode *np,
+ FAR const char *relpath, mode_t mode)
+{
+//struct nfs_fattr vap;
+ struct nfsv3_sattr sp;
+ struct CREATE3args create;
+ struct rpc_reply_create resok;
+ int error = 0;
+
+ do
+ {
+ nfsstats.rpccnt[NFSPROC_CREATE]++;
+ memset(&sp, 0, sizeof(struct nfsv3_sattr));
+ //memset(&vap, 0, sizeof(struct nfs_fattr));
+ //vap = nmp->nm_head->n_fattr;
+ sp.sa_modetrue = true;
+ sp.sa_mode = txdr_unsigned(mode);
+ sp.sa_uidfalse = nfs_xdrneg1;
+ sp.sa_gidfalse = nfs_xdrneg1;
+ sp.sa_sizefalse = 0;
+ sp.sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
+ sp.sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
+ //txdr_nfsv3time2(&vap.fa3_atime, &sp.sa_atime);
+ //txdr_nfsv3time2(&vap.fa3_mtime, &sp.sa_mtime);
+
+ memset(&create, 0, sizeof(struct CREATE3args));
+ memset(&resok, 0, sizeof(struct rpc_reply_create));
+ memcpy(&create.how, &sp, sizeof(struct nfsv3_sattr));
+#warning "BUG HERE: np has not yet been initialized"
+ create.where.dir.length = txdr_unsigned(np->n_fhsize);
+ memcpy(&create.where.dir.handle, &np->n_fhp, sizeof(nfsfh_t));
+ create.where.length = txdr_unsigned(64);
+ strncpy(create.where.name, relpath, 64);
+
+ error = nfs_request(nmp, NFSPROC_CREATE, (FAR const void *)&create,
+ (void *)&resok, sizeof(struct rpc_reply_create));
+ }
+ while (error == EOPNOTSUPP);
+
+ if (error == 0)
+ {
+ //np->nfsv3_type = fxdr_unsigned(uint32_t, resok.attributes.fa_type);
+
+ np->n_open = true;
+ memcpy(&np->n_fhp, &resok.create.fshandle.handle, sizeof(nfsfh_t));
+ np->n_size = fxdr_hyper(&resok.create.attributes.fa3_size);
+ memcpy(&resok.create.attributes, &np->n_fattr, sizeof(struct nfs_fattr));
+ fxdr_nfsv3time(&resok.create.attributes.fa3_mtime, &np->n_mtime)
+ np->n_ctime = fxdr_hyper(&resok.create.attributes.fa3_ctime);
+ }
+
+ return error;
+}
+
+ /****************************************************************************
* Name: nfs_open
*
* Description:
@@ -186,13 +254,12 @@ const struct mountpt_operations nfs_operations =
static int nfs_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode)
{
+ struct stat buf;
struct inode *in;
//struct nfs_fattr vap;
- struct nfsv3_sattr sp;
struct nfsmount *nmp;
struct nfsnode *np;
- struct CREATE3args create;
- struct rpc_reply_create resok;
+ bool readonly;
int error = 0;
/* Sanity checks */
@@ -203,12 +270,20 @@ static int nfs_open(FAR struct file *filep, FAR const char *relpath,
* mountpoint private data from the inode structure
*/
- in = filep->f_inode;
+ in = filep->f_inode;
nmp = (struct nfsmount*)in->i_private;
- np = (struct nfsnode*)filep->f_priv;
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);
@@ -218,121 +293,133 @@ static int nfs_open(FAR struct file *filep, FAR const char *relpath,
goto errout_with_semaphore;
}
- if (oflags == O_CREAT)
- {
- /* Sanity checks */
-
- DEBUGASSERT(filep->f_priv == NULL);
-again:
- nfsstats.rpccnt[NFSPROC_CREATE]++;
- memset(&sp, 0, sizeof(struct nfsv3_sattr));
- //memset(&vap, 0, sizeof(struct nfs_fattr));
- //vap = nmp->nm_head->n_fattr;
- sp.sa_modetrue = true;
- sp.sa_mode = txdr_unsigned(mode);
- sp.sa_uidfalse = nfs_xdrneg1;
- sp.sa_gidfalse = nfs_xdrneg1;
- sp.sa_sizefalse = 0;
- sp.sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
- sp.sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
- //txdr_nfsv3time2(&vap.fa3_atime, &sp.sa_atime);
- //txdr_nfsv3time2(&vap.fa3_mtime, &sp.sa_mtime);
+ /* First check if the file already exists */
- memset(&create, 0, sizeof(struct CREATE3args));
- memset(&resok, 0, sizeof(struct rpc_reply_create));
- memcpy(&create.how, &sp, sizeof(struct nfsv3_sattr));
- create.where.dir.length = txdr_unsigned(np->n_fhsize);
- memcpy(&create.where.dir.handle, &np->n_fhp, sizeof(nfsfh_t));
- create.where.length = txdr_unsigned(64);
- strncpy(create.where.name, relpath, 64);
+ error = nfs_getfsinfo(nmp, relpath, &buf);
+ if (error == 0)
+ {
+ /* Check if the file is a directory */
- error = nfs_request(nmp, NFSPROC_CREATE, (FAR const void *)&create,
- (void *)&resok, sizeof(struct rpc_reply_create));
- if (!error)
+ if (S_ISDIR(buf.st_mode))
{
- /* Create an instance of 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");
- error = -ENOMEM;
- goto errout_with_semaphore;
- }
-
- /* Initialize the file private data (only need to initialize
- * non-zero elements)
- */
-
- // np->nfsv3_type = fxdr_unsigned(uint32_t, resok.attributes.fa_type);
+ /* Exit with EISDIR if we attempt to open an directory */
- /* The full path exists -- but is the final component a file
- * or a directory?
- */
+ fdbg("ERROR: Path is a directory\n");
+ error = EISDIR;
+ goto errout_with_semaphore;
+ }
- if (np->nfsv3_type == NFDIR)
- {
- /* It is a directory */
+ /* Check if the caller has sufficient privileges to open the file */
- error = EISDIR;
- fdbg("ERROR: '%s' is a directory\n", relpath);
- goto errout_with_semaphore;
- }
+ readonly = ((buf.st_mode & (S_IWOTH|S_IWGRP|S_IXUSR)) == 0);
+ if (((oflags & O_WRONLY) != 0) && readonly)
+ {
+ fdbg("ERROR: File is read-only\n");
+ error = EACCES;
+ goto errout_with_semaphore;
+ }
- np->n_open = true;
- memcpy(&np->n_fhp, &resok.create.fshandle.handle, sizeof(nfsfh_t));
- np->n_size = fxdr_hyper(&resok.create.attributes.fa3_size);
- memcpy(&resok.create.attributes, &np->n_fattr, sizeof(struct nfs_fattr));
- fxdr_nfsv3time(&resok.create.attributes.fa3_mtime, &np->n_mtime)
- np->n_ctime = fxdr_hyper(&resok.create.attributes.fa3_ctime);
+ /* It would be an error if we are asked to create it exclusively */
- /* Attach the private date to the struct file instance */
+ if ((oflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
+ {
+ /* Already exists -- can't create it exclusively */
- filep->f_priv = np;
+ fdbg("ERROR: File exists\n");
+ error = EEXIST;
+ goto errout_with_semaphore;
+ }
- /* Then insert the new instance into the mountpoint structure.
- * 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
- * (but a simple reference count could have done that).
- */
+ /* 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.
+ */
- np->n_next = nmp->nm_head;
- nmp->nm_head = np->n_next;
- error = 0;
- }
- else
+ if ((oflags & (O_TRUNC|O_WRONLY)) == (O_TRUNC|O_WRONLY))
{
- if (error == EOPNOTSUPP)
- {
- goto again;
- }
+ /* Truncate the file to zero length */
+
+ fvdbg("Truncating file\n");
+#warning "Missing logic"
}
- np->n_flag |= NMODIFIED;
+ /* Initialize the file private data from the FSINFO return data */
+ /* NOTE: This will require some re-structuring */
+#if 0
+ np->n_open = true;
+ memcpy(&np->n_fhp, &resok.fsinfo.fshandle.handle, sizeof(nfsfh_t));
+ np->n_size = fxdr_hyper(&resok.fsinfo.attributes.fa3_size);
+ memcpy(&resok.fsinfo.attributes, &np->n_fattr, sizeof(struct nfs_fattr));
+ fxdr_nfsv3time(&resok.fsinfo.attributes.fa3_mtime, &np->n_mtime)
+ np->n_ctime = fxdr_hyper(&resok.fsinfo.attributes.fa3_ctime);
+#else
+#warning "Missing logic"
+ fdbg("ERROR: Logic to open an existing file is not fully implemented");
+ errno = ENOSYS; /* Just fail for now */
+ goto errout_with_semaphore;
+#endif
+ /* Fall through to finish the file open operation */
}
+
+ /* An error occurred while getting the file status */
+
else
{
- if (np->nfsv3_type != NFREG)
+ /* Check if the stat failed because the file does not exist. */
+#warning "Missing logic"
+
+ /* If the file does not exist then 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)
{
- fdbg("ERROR: open eacces typ=%d\n", np->nfsv3_type);
- error = EACCES;
+ /* 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 */
- if (np->n_flag & NMODIFIED)
+ error = nfs_create(nmp, np, relpath, mode);
+ if (error != 0)
{
- if (np->nfsv3_type == NFDIR)
- {
- np->n_direofoffset = 0;
- }
+ fdbg("ERROR: nfs_create failed: %d\n", error);
+ goto errout_with_semaphore;
}
+
+ /* Fall through to finish the file open operation */
}
+ /* Initialize the file private data (only need to initialize
+ * non-zero elements)
+ */
+
+ /* Attach the private data to the struct file instance */
+
+ filep->f_priv = np;
+
+ /* Then insert the new instance into the mountpoint structure.
+ * 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
+ * (but a simple reference count could have done that).
+ */
+
+ np->n_next = nmp->nm_head;
+ np->n_flag |= NMODIFIED;
+ nmp->nm_head = np->n_next;
+
/* For open/close consistency. */
NFS_INVALIDATE_ATTRCACHE(np);
+ nfs_semgive(nmp);
+ return OK;
errout_with_semaphore:
kfree(np);
diff --git a/nuttx/fs/nfs/rpc_clnt.c b/nuttx/fs/nfs/rpc_clnt.c
index 243bbb0f0..a78bc6d78 100644
--- a/nuttx/fs/nfs/rpc_clnt.c
+++ b/nuttx/fs/nfs/rpc_clnt.c
@@ -241,10 +241,12 @@ rpcclnt_send(struct socket *so, struct sockaddr *nam, int procid, int prog,
void *call, struct rpctask *rep)
{
struct sockaddr *sendnam;
+ ssize_t nbytes;
int error = ESRCH;
#ifdef CONFIG_NFS_TCPIP
int soflags;
#endif
+ int length;
int flags;
if (rep != NULL)
@@ -290,34 +292,29 @@ rpcclnt_send(struct socket *so, struct sockaddr *nam, int procid, int prog,
flags = 0;
}
+ /* Get the length of the call messsage */
+
+ error = 0;
if (prog == PMAPPROG)
{
- if (procid == PMAPPROC_GETPORT)
+ if (procid == PMAPPROC_GETPORT || procid == PMAPPROC_UNSET)
{
- struct rpc_call_pmap *callmsg = (struct rpc_call_pmap *)call;
- error = psock_sendto(so, callmsg, sizeof(*callmsg), flags,
- sendnam, sizeof(*sendnam));
+ length = sizeof(struct rpc_call_pmap);
}
- else if (procid == PMAPPROC_UNSET)
+ else
{
- struct rpc_call_pmap *callmsg = (struct rpc_call_pmap *)call;
- error = psock_sendto(so, callmsg, sizeof(*callmsg), flags,
- sendnam, sizeof(*sendnam));
+ error = EINVAL;
}
}
else if (prog == RPCPROG_MNT)
{
- if (procid == RPCMNT_UMOUNT)
+ if (procid == RPCMNT_UMOUNT || procid == RPCMNT_MOUNT)
{
- struct rpc_call_mount *callmsg = (struct rpc_call_mount *)call;
- error = psock_sendto(so, callmsg, sizeof(*callmsg), flags,
- sendnam, sizeof(*sendnam));
+ length = sizeof(struct rpc_call_mount);
}
- else if (procid == RPCMNT_MOUNT)
+ else
{
- struct rpc_call_mount *callmsg = (struct rpc_call_mount *)call;
- error = psock_sendto(so, callmsg, sizeof(*callmsg), flags,
- sendnam, sizeof(*sendnam));
+ error = EINVAL;
}
}
else if (prog == NFS_PROG)
@@ -325,127 +322,98 @@ rpcclnt_send(struct socket *so, struct sockaddr *nam, int procid, int prog,
switch (procid)
{
case NFSPROC_CREATE:
- {
- struct rpc_call_create *callmsg = (struct rpc_call_create *)call;
- error = psock_sendto(so, callmsg, sizeof(*callmsg), flags,
- sendnam, sizeof(*sendnam));
- }
+ length = sizeof(struct rpc_call_create);
break;
case NFSPROC_READ:
- {
- struct rpc_call_read *callmsg = (struct rpc_call_read *)call;
- error = psock_sendto(so, callmsg, sizeof(*callmsg), flags,
- sendnam, sizeof(*sendnam));
- }
+ length = sizeof(struct rpc_call_read);
break;
case NFSPROC_WRITE:
- {
- struct rpc_call_write *callmsg = (struct rpc_call_write *)call;
- error = psock_sendto(so, callmsg, sizeof(*callmsg), flags,
- sendnam, sizeof(*sendnam));
- }
+ length = sizeof(struct rpc_call_write);
break;
case NFSPROC_READDIR:
- {
- struct rpc_call_readdir *callmsg = (struct rpc_call_readdir *)call;
- error = psock_sendto(so, callmsg, sizeof(*callmsg), flags,
- sendnam, sizeof(*sendnam));
- }
+ length = sizeof(struct rpc_call_readdir);
break;
case NFSPROC_FSSTAT:
- {
- struct rpc_call_fs *callmsg = (struct rpc_call_fs *)call;
- error = psock_sendto(so, callmsg, sizeof(*callmsg), flags,
- sendnam, sizeof(*sendnam));
- }
+ length = sizeof(struct rpc_call_fs);
break;
case NFSPROC_GETATTR:
- {
- struct rpc_call_fs *callmsg = (struct rpc_call_fs *)call;
- error = psock_sendto(so, callmsg, sizeof(*callmsg), flags,
- sendnam, sizeof(*sendnam));
- }
+ length = sizeof(struct rpc_call_fs);
break;
case NFSPROC_REMOVE:
- {
- struct rpc_call_remove *callmsg = (struct rpc_call_remove *)call;
- error = psock_sendto(so, callmsg, sizeof(*callmsg), flags,
- sendnam, sizeof(*sendnam));
- }
+ length = sizeof(struct rpc_call_remove);
break;
case NFSPROC_MKDIR:
- {
- struct rpc_call_mkdir *callmsg = (struct rpc_call_mkdir *)call;
- error = psock_sendto(so, callmsg, sizeof(*callmsg), flags,
- sendnam, sizeof(*sendnam));
- }
+ length = sizeof(struct rpc_call_mkdir);
break;
case NFSPROC_RMDIR:
- {
- struct rpc_call_rmdir *callmsg = (struct rpc_call_rmdir *)call;
- error = psock_sendto(so, callmsg, sizeof(*callmsg), flags,
- sendnam, sizeof(*sendnam));
- }
+ length = sizeof(struct rpc_call_rmdir);
break;
case NFSPROC_RENAME:
- {
- struct rpc_call_rename *callmsg = (struct rpc_call_rename *)call;
- error = psock_sendto(so, callmsg, sizeof(*callmsg), flags,
- sendnam, sizeof(*sendnam));
- }
+ length = sizeof(struct rpc_call_rename);
break;
case NFSPROC_FSINFO:
- {
- struct rpc_call_fs *callmsg = (struct rpc_call_fs *)call;
- error = psock_sendto(so, callmsg, sizeof(*callmsg), flags,
- sendnam, sizeof(*sendnam));
- }
+ length = sizeof(struct rpc_call_fs);
break;
default:
+ error = EINVAL;
break;
}
}
+ else
+ {
+ error = EINVAL;
+ }
- if (error < 0)
+ /* Send the call message */
+
+ if (error == 0)
{
- if (rep != NULL)
+ /* On success, psock_sendto returns the number of bytes sent;
+ * On failure, it returns -1 with the specific error in errno.
+ */
+
+ nbytes = psock_sendto(so, call, length, flags,
+ sendnam, sizeof(struct sockaddr));
+ if (nbytes < 0)
{
- fdbg("rpc send error %d for service %s\n", error,
- rep->r_rpcclnt->rc_prog->prog_name);
+ /* psock_sendto failed, Sample the error value (subsequent
+ * calls can change the errno value!
+ */
- /* Deal with errors for the client side. */
+ error = errno;
+ fdbg("ERROR: psock_sendto failed: %d\n", error);
- if (rep->r_flags & TASK_SOFTTERM)
+ if (rep != NULL)
{
- error = EINTR;
- }
- else
- {
- rep->r_flags |= TASK_MUSTRESEND;
+ fdbg("rpc send error %d for service %s\n", error,
+ rep->r_rpcclnt->rc_prog->prog_name);
+
+ /* Deal with errors for the client side. */
+
+ if (rep->r_flags & TASK_SOFTTERM)
+ {
+ error = EINTR;
+ }
+ else
+ {
+ rep->r_flags |= TASK_MUSTRESEND;
+ }
}
}
- else
- {
- fdbg("rpc service send error %d\n", error);
- }
-
- return error;
- }
- else
- {
- return 0;
}
+
+ return error;
}
/* Receive a Sun RPC Request/Reply. For SOCK_DGRAM, the work is all