diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-06-09 19:29:49 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-06-09 19:29:49 +0000 |
commit | 59f64eb3c5ade626a3366355ae49344765d1a4c1 (patch) | |
tree | 503bd40e4c9634ec1b28fc23d26761878d266675 /nuttx/fs/nfs/nfs_util.c | |
parent | 41375ad4a6216e206030e71aca39c54c94e00a57 (diff) | |
download | px4-nuttx-59f64eb3c5ade626a3366355ae49344765d1a4c1.tar.gz px4-nuttx-59f64eb3c5ade626a3366355ae49344765d1a4c1.tar.bz2 px4-nuttx-59f64eb3c5ade626a3366355ae49344765d1a4c1.zip |
NFS update
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4821 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/fs/nfs/nfs_util.c')
-rw-r--r--[-rwxr-xr-x] | nuttx/fs/nfs/nfs_util.c | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/nuttx/fs/nfs/nfs_util.c b/nuttx/fs/nfs/nfs_util.c index 11d0573e6..63070b76f 100755..100644 --- a/nuttx/fs/nfs/nfs_util.c +++ b/nuttx/fs/nfs/nfs_util.c @@ -53,9 +53,13 @@ #include <nuttx/fs/dirent.h> +#include "rpc.h" +#include "nfs.h" #include "nfs_proto.h" #include "nfs_mount.h" #include "nfs_node.h" +#include "nfs_socket.h" +#include "xdr_subs.h" /**************************************************************************** * Private Types @@ -77,6 +81,56 @@ * 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; + } + } +} /**************************************************************************** * Public Functions ****************************************************************************/ @@ -141,3 +195,196 @@ int nfs_checkmount(struct nfsmount *nmp) return 0; } +/**************************************************************************** + * 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_reply_fsinfo fsp; + struct FS3args fsinfo; + uint32_t pref; + uint32_t max; + int error = 0; + + memset(&fsinfo, 0, sizeof(struct FS3args)); + memset(&fsp, 0, sizeof(struct rpc_reply_fsinfo)); + + nfsstats.rpccnt[NFSPROC_FSINFO]++; + fsinfo.fsroot.length = txdr_unsigned(nmp->nm_fhsize); + fsinfo.fsroot.handle = nmp->nm_fh; + + /* Request FSINFO from the server */ + + error = nfs_request(nmp, NFSPROC_FSINFO, (FAR const void *)&fsinfo, + (FAR void *)&fsp, sizeof(struct rpc_reply_fsinfo)); + if (error) + { + return error; + } + + /* Save the root file system attributes */ +#if 0 + memcpy(&nmp->nm_fattr. &fsp.obj_attributes, sizeof(struct nfs_fattr)); +#endif + + 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; + } + } + + nmp->nm_flag |= NFSMNT_GOTFSINFO; + + return 0; +} + +/**************************************************************************** + * 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 item 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; + int error; + + /* Start with the file handle and attributes of the root directory */ + + fhandle->length = nmp->nm_fhsize; + memcpy(&fhandle->handle, &nmp->nm_fh, sizeof(nfsfh_t)); + +#warning "Where do we get the attributes of the root file system?" + memset(obj_attributes, 0, sizeof(struct nfs_fattr)); + memset(dir_attributes, 0, sizeof(struct nfs_fattr)); + + /* 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 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 != 0) + { + /* 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 */ + + nfsstats.rpccnt[NFSPROC_LOOKUP]++; + error = rpcclnt_lookup(nmp->nm_rpcclnt, buffer, fhandle, + obj_attributes, dir_attributes); + if (error != 0) + { + fdbg("rpcclnt_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. + */ + + if (obj_attributes->fa_type != NFDIR) + { + /* Ooops.. we found something else */ + + fdbg("ERROR: Intermediate segment \"%s\" of \'%s\" is not a directory\n", + buffer, path); + return ENOTDIR; + } + } +} |