diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h index d3f47e0262..da0d5735c9 100644 --- a/fs/nfs/nfs.h +++ b/fs/nfs/nfs.h @@ -372,6 +372,9 @@ EXTERN 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); +EXTERN int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath, + FAR struct file_handle *fhandle, + FAR struct nfs_fattr *attributes); #undef EXTERN #if defined(__cplusplus) diff --git a/fs/nfs/nfs_util.c b/fs/nfs/nfs_util.c index 8309b8d78d..5964248e78 100644 --- a/fs/nfs/nfs_util.c +++ b/fs/nfs/nfs_util.c @@ -423,7 +423,7 @@ int nfs_lookup(struct nfsmount *nmp, FAR const char *filename, * * 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 item object. + * return the handle of the directory entry of the requested object. * * Return Value: * Zero on success; a positive errno value on failure. @@ -437,6 +437,7 @@ int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath, 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. */ @@ -512,7 +513,100 @@ int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath, * the thing that we found is, indeed, a directory. */ - if (obj_attributes->fa_type != NFDIR) + 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 const char *path = relpath; + char buffer[NAME_MAX+1]; + 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, sizeof(nfsfh_t)); + 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, buffer, &terminator); + if (error != 0) + { + /* The filename segment contains is too long. */ + + fdbg("nfs_pathsegment of \"%s\" failed after \"%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 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, buffer, fhandle, attributes, NULL); + if (error != 0) + { + fdbg("nfs_lookup of \"%s\" failed at \"%s\": %d\n", + relpath, buffer, 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 */ diff --git a/fs/nfs/nfs_vfsops.c b/fs/nfs/nfs_vfsops.c index 4f19b9a6e7..1529140250 100644 --- a/fs/nfs/nfs_vfsops.c +++ b/fs/nfs/nfs_vfsops.c @@ -136,8 +136,6 @@ static int nfs_mkdir(struct inode *mountpt, const char *relpath, 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_getstat(struct nfsmount *nmp, const char *relpath, - struct stat *buf); static int nfs_stat(struct inode *mountpt, const char *relpath, struct stat *buf); @@ -332,6 +330,7 @@ static int nfs_open(FAR struct file *filep, FAR const char *relpath, error = nfs_checkmount(nmp); if (error != 0) { + fdbg("ERROR: nfs_checkmount failed: %d\n", error); goto errout_with_semaphore; } @@ -419,7 +418,7 @@ static int nfs_open(FAR struct file *filep, FAR const char *relpath, else if (error != ENOENT) { - fdbg("ERROR: nfs_getstat failed: %d\n", error); + fdbg("ERROR: nfs_findnode failed: %d\n", error); goto errout_with_semaphore; } @@ -738,6 +737,7 @@ static ssize_t nfs_write(FAR struct file *filep, const char *buffer, error = nfs_checkmount(nmp); if (error != 0) { + fdbg("ERROR: nfs_checkmount failed: %d\n", error); goto errout_with_semaphore; } @@ -1704,7 +1704,7 @@ static int nfs_statfs(struct inode *mountpt, struct statfs *sbp) nfs_semtake(nmp); error = nfs_checkmount(nmp); - if (error < 0) + if (error != 0) { fdbg("nfs_checkmount failed: %d\n", error); goto errout_with_semaphore; @@ -2075,38 +2075,52 @@ errout_with_semaphore: } /**************************************************************************** - * Name: nfs_getstat + * Name: nfs_stat * * Description: - * Return information about the object at the specified path. This is an - * internal version of stat() used only within this file. + * Return information about the file system object at 'relpath' * * Returned Value: - * 0 on success; positive errno value on failure - * - * Assumptions: - * The caller has exclusive access to the NFS mount structure + * 0 on success; a negated errno value on failure. * ****************************************************************************/ -static int nfs_getstat(struct nfsmount *nmp, const char *relpath, - struct stat *buf) +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 = 0; + 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 != 0) + { + fdbg("ERROR: nfs_checkmount failed: %d\n", error); + goto errout_with_semaphore; + } + /* Get the attributes of the requested node */ error = nfs_findnode(nmp, relpath, &fhandle, &obj_attributes, NULL); if (error != 0) { fdbg("ERROR: nfs_findnode failed: %d\n", error); - return error; + goto errout_with_semaphore; } /* Construct the file mode. This is a 32-bit, encoded value containing @@ -2181,45 +2195,7 @@ static int nfs_getstat(struct nfsmount *nmp, const char *relpath, buf->st_atime = fxdr_hyper(&obj_attributes.fa3_atime); buf->st_ctime = fxdr_hyper(&obj_attributes.fa3_ctime); - return OK; -} - -/**************************************************************************** - * 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; - 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 == 0) - { - /* Get the requested FSINFO */ - - error = nfs_getstat(nmp, relpath, buf); - } - +errout_with_semaphore: nfs_semgive(nmp); return -error; } @@ -2260,6 +2236,7 @@ int nfs_sync(struct file *filep) error = nfs_checkmount(nmp); if (error != 0) { + fdbg("ERROR: nfs_checkmount failed: %d\n", error); goto errout_with_semaphore; }