diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h index 600e533507..34cf01b12b 100644 --- a/fs/nfs/nfs.h +++ b/fs/nfs/nfs.h @@ -192,6 +192,16 @@ #define ND_NFSV3 0x08 #define NFSD_CHECKSLP 0x01 +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern uint32_t nfs_true; +extern uint32_t nfs_false; +extern uint32_t nfs_xdrneg1; +extern struct nfsstats nfsstats; +extern int nfs_ticks; + /**************************************************************************** * Public Types ****************************************************************************/ @@ -352,6 +362,11 @@ extern "C" { EXTERN void nfs_semtake(struct nfsmount *nmp); EXTERN void nfs_semgive(struct nfsmount *nmp); EXTERN int nfs_checkmount(struct nfsmount *nmp); +EXTERN int nfs_fsinfo(struct nfsmount *nmp); +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); #undef EXTERN #if defined(__cplusplus) diff --git a/fs/nfs/nfs_proto.h b/fs/nfs/nfs_proto.h index 78b5842383..20e80d8334 100644 --- a/fs/nfs/nfs_proto.h +++ b/fs/nfs/nfs_proto.h @@ -584,6 +584,24 @@ struct CREATE3resok struct wcc_data dir_wcc; }; +struct LOOKUP3args +{ + struct file_handle dirhandle; + uint32_t namelen; + uint32_t name[1]; /* Actual size determined by namelen */ +}; +#define SIZEOF_LOOKUP3args(n) \ + (sizeof(struct LOOKUP3args) + ((((n)+3) >> 2) - 1)*sizeof(uint32_t)) + +struct LOOKUP3resok +{ + struct file_handle fshandle; + uint32_t obj_attributes_follow; + struct nfs_fattr obj_attributes; + uint32_t dir_attributes_follow; + struct nfs_fattr dir_attributes; +}; + struct READ3args { nfstype file; @@ -698,3 +716,4 @@ struct FS3args }; #endif /* __FS_NFS_NFS_PROTO_H */ + diff --git a/fs/nfs/nfs_util.c b/fs/nfs/nfs_util.c old mode 100755 new mode 100644 index 11d0573e69..63070b76fc --- a/fs/nfs/nfs_util.c +++ b/fs/nfs/nfs_util.c @@ -53,9 +53,13 @@ #include +#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; + } + } +} diff --git a/fs/nfs/nfs_vfsops.c b/fs/nfs/nfs_vfsops.c index 0f948b5741..6de2195865 100644 --- a/fs/nfs/nfs_vfsops.c +++ b/fs/nfs/nfs_vfsops.c @@ -53,6 +53,7 @@ #include #include +#include #include #include #include @@ -119,21 +120,11 @@ 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_getfsinfo(struct nfsmount *nmp, const char *relpath, +static int nfs_getstat(struct nfsmount *nmp, const char *relpath, struct stat *buf); -static int nfs_fsinfo(struct inode *mountpt, const char *relpath, +static int nfs_stat(struct inode *mountpt, const char *relpath, struct stat *buf); -/**************************************************************************** - * External Public Data (this belong in a header file) - ****************************************************************************/ - -extern uint32_t nfs_true; -extern uint32_t nfs_false; -extern uint32_t nfs_xdrneg1; -extern struct nfsstats nfsstats; -extern int nfs_ticks; - /**************************************************************************** * Public Data ****************************************************************************/ @@ -162,7 +153,7 @@ const struct mountpt_operations nfs_operations = nfs_mkdir, /* mkdir */ nfs_rmdir, /* rmdir */ nfs_rename, /* rename */ - nfs_fsinfo /* stat */ + nfs_stat /* stat */ }; /**************************************************************************** @@ -173,7 +164,7 @@ const struct mountpt_operations nfs_operations = * Public Functions ****************************************************************************/ - /**************************************************************************** +/**************************************************************************** * Name: nfs_create * * Description: @@ -295,7 +286,7 @@ static int nfs_open(FAR struct file *filep, FAR const char *relpath, /* First check if the file already exists */ - error = nfs_getfsinfo(nmp, relpath, &buf); + error = nfs_getstat(nmp, relpath, &buf); if (error == 0) { /* Check if the file is a directory */ @@ -362,31 +353,37 @@ static int nfs_open(FAR struct file *filep, FAR const char *relpath, /* Fall through to finish the file open operation */ } - /* An error occurred while getting the file status */ + /* An error occurred while getting the file status. Check if the stat failed + * because the file does not exist. That is not necessarily an error; that + * may only mean that we have to create the file. + */ + + else if (error != ENOENT) + { + fdbg("ERROR: nfs_getstat 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. + */ + + else 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 */ else { - /* 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) - { - /* 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_create(nmp, np, relpath, mode); if (error != 0) { @@ -522,7 +519,7 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen) if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3) { - (void)nfs_getfsinfo(nmp, NULL, NULL); + (void)nfs_fsinfo(nmp); } /* Get the number of bytes left in the file */ @@ -962,11 +959,10 @@ int nfs_readdirrpc(struct nfsmount *nmp, struct nfsnode *np, /* Get the file attributes associated with this name and return * the file type. */ - #if 0 /* There is no point in enabling until nfs_getfsinfo handles the relative path */ if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3) { - struct stat buf + struct stat buf; char *path; /* Construct the full path to the file */ @@ -976,7 +972,7 @@ int nfs_readdirrpc(struct nfsmount *nmp, struct nfsnode *np, { /* Then stat the file */ - int ret = nfs_getfsinfo(nmp, path, &buf); + int ret = nfs_getstat(nmp, path, &buf); if (ret == OK) { if (S_ISREG(buf.st_mode)) @@ -1006,9 +1002,6 @@ int nfs_readdirrpc(struct nfsmount *nmp, struct nfsnode *np, kfree(path); } } -#else -#warning "Missing logic" - dir->fd_dir.d_type = DTYPE_FILE; #endif error = 0; } @@ -1093,7 +1086,7 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3) { - (void)nfs_getfsinfo(nmp, NULL, NULL); + (void)nfs_fsinfo(nmp); } /* Read and return one directory entry. */ @@ -1633,7 +1626,7 @@ static int nfs_statfs(struct inode *mountpt, struct statfs *sbp) if ((nmp->nm_flag & NFSMNT_GOTFSINFO) == 0) { - (void)nfs_getfsinfo(nmp, NULL, NULL); + (void)nfs_fsinfo(nmp); } nfsstats.rpccnt[NFSPROC_FSSTAT]++; @@ -1994,11 +1987,11 @@ errout_with_semaphore: } /**************************************************************************** - * Name: nfs_getfsinfo + * Name: nfs_getstat * * Description: - * Return information about root directory. This is an internal version - * used only within this file. + * Return information about the object at the specified path. This is an + * internal version of stat() used only within this file. * * Returned Value: * 0 on success; positive errno value on failure @@ -2008,178 +2001,116 @@ errout_with_semaphore: * ****************************************************************************/ -static int nfs_getfsinfo(struct nfsmount *nmp, const char *relpath, - struct stat *buf) +static int nfs_getstat(struct nfsmount *nmp, const char *relpath, + struct stat *buf) { - struct rpc_reply_fsinfo fsp; - struct FS3args fsinfo; - uint32_t pref; - uint32_t max; - int error = 0; + struct file_handle fhandle; + struct nfs_fattr obj_attributes; + struct nfs_fattr dir_attributes; + uint32_t tmp; + uint32_t mode; + int error = 0; -#warning "relpath is not used! Additional logic will be required!" + DEBUGASSERT(nmp && buf); - memset(&fsinfo, 0, sizeof(struct FS3args)); - memset(&fsp, 0, sizeof(struct rpc_reply_fsinfo)); + /* Get the attributes of the requested node */ - 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) + error = nfs_findnode(nmp, relpath, &fhandle, &obj_attributes, + &dir_attributes); + if (error != 0) { + fdbg("ERROR: nfs_findnode failed: %d\n", error); return error; } -//nmp->nm_fattr = fsp.obj_attributes; - 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; - } - } - - /* Verify that the caller has provided a non-NULL location to return the - * FSINFO data. + /* Construct the file mode. This is a 32-bit, encoded value containing + * both the access mode and the file type. */ - if (buf) - { - /* Construct the file mode. This is a 32-bit, encoded value containing - * both the access mode and the file type. - */ - - uint32_t tmp = fxdr_unsigned(uint32_t, nmp->nm_fattr.fa_mode); + 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. - */ + /* Here we exploit the fact that most mode bits are the same in NuttX + * as in the NFSv3 spec. + */ - uint32_t mode = tmp & (NFSMMODE_IXOTH|NFSMMODE_IWOTH|NFSMMODE_IROTH| - NFSMMODE_IXGRP|NFSMMODE_IWGRP|NFSMMODE_IRGRP| - NFSMMODE_IXUSR|NFSMMODE_IWUSR|NFSMMODE_IRUSR); + mode = tmp & (NFSMMODE_IXOTH|NFSMMODE_IWOTH|NFSMMODE_IROTH| + NFSMMODE_IXGRP|NFSMMODE_IWGRP|NFSMMODE_IRGRP| + NFSMMODE_IXUSR|NFSMMODE_IWUSR|NFSMMODE_IRUSR); - /* Handle the cases that are not the same */ + /* Handle the cases that are not the same */ - if ((mode & NFSMMODE_ISGID) != 0) - { - mode |= S_ISGID; - } - - if ((mode & NFSMMODE_ISUID) != 0) - { - mode |= S_ISUID; - } - - /* Now OR in the file type */ - - tmp = fxdr_unsigned(uint32_t, nmp->nm_fattr.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(&nmp->nm_fattr.fa3_size); - buf->st_blksize = 0; - buf->st_blocks = 0; - buf->st_mtime = fxdr_hyper(&nmp->nm_fattr.fa3_mtime); - buf->st_atime = fxdr_hyper(&nmp->nm_fattr.fa3_atime); - buf->st_ctime = fxdr_hyper(&nmp->nm_fattr.fa3_ctime); + if ((mode & NFSMMODE_ISGID) != 0) + { + mode |= S_ISGID; } - nmp->nm_flag |= NFSMNT_GOTFSINFO; + if ((mode & NFSMMODE_ISUID) != 0) + { + mode |= S_ISUID; + } - return 0; + /* 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.fa3_size); + buf->st_blksize = 0; + buf->st_blocks = 0; + buf->st_mtime = fxdr_hyper(&obj_attributes.fa3_mtime); + buf->st_atime = fxdr_hyper(&obj_attributes.fa3_atime); + buf->st_ctime = fxdr_hyper(&obj_attributes.fa3_ctime); + + return OK; } /**************************************************************************** - * Name: nfs_fsinfo + * Name: nfs_stat * * Description: - * Return information about root directory + * Return information about the file system object at 'relpath' * * Returned Value: * 0 on success; a negated errno value on failure. * ****************************************************************************/ -static int nfs_fsinfo(struct inode *mountpt, const char *relpath, - struct stat *buf) +static int nfs_stat(struct inode *mountpt, const char *relpath, + struct stat *buf) { struct nfsmount *nmp; int error; @@ -2200,7 +2131,7 @@ static int nfs_fsinfo(struct inode *mountpt, const char *relpath, { /* Get the requested FSINFO */ - error = nfs_getfsinfo(nmp, relpath, buf); + error = nfs_getstat(nmp, relpath, buf); } nfs_semgive(nmp); diff --git a/fs/nfs/rpc.h b/fs/nfs/rpc.h index 9a0b9fc01c..4199797a14 100644 --- a/fs/nfs/rpc.h +++ b/fs/nfs/rpc.h @@ -240,6 +240,7 @@ struct rpcstats }; /* PMAP headers */ + struct call_args_pmap { uint32_t prog; @@ -325,6 +326,12 @@ struct rpc_call_create struct CREATE3args create; }; +struct rpc_call_lookup +{ + struct rpc_call_header ch; + struct LOOKUP3args lookup; +}; + struct rpc_call_read { struct rpc_call_header ch; @@ -377,8 +384,8 @@ struct rpc_call_fs struct rpc_reply_header { - uint32_t rp_xid; /* request transaction id */ - uint32_t rp_direction; /* call direction (1) */ + 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; @@ -553,7 +560,13 @@ int rpcclnt_reconnect(struct rpctask *); void rpcclnt_disconnect(struct rpcclnt *); int rpcclnt_umount(struct rpcclnt *); void rpcclnt_safedisconnect(struct rpcclnt *); -int rpcclnt_request(struct rpcclnt *, int, int, int, void *, FAR const void *, size_t); +int rpcclnt_request(FAR struct rpcclnt *, int, int, int, void *, + FAR const void *, size_t); +int rpcclnt_lookup(FAR struct rpcclnt *rpc, FAR const char *relpath, + FAR struct file_handle *fhandle, + FAR struct nfs_fattr *obj_attributes, + FAR struct nfs_fattr *dir_attributes); + #undef COMP #ifdef COMP int rpcclnt_cancelreqs(struct rpcclnt *); diff --git a/fs/nfs/rpc_clnt.c b/fs/nfs/rpc_clnt.c index a78bc6d78e..dba71a4112 100644 --- a/fs/nfs/rpc_clnt.c +++ b/fs/nfs/rpc_clnt.c @@ -186,8 +186,6 @@ static uint32_t rpc_msgaccepted; static uint32_t rpc_autherr; static uint32_t rpc_auth_null; -static uint32_t rpcclnt_xid = 0; -static uint32_t rpcclnt_xid_touched = 0; int rpcclnt_ticks; struct rpcstats rpcstats; //struct rpc_call *callmgs; @@ -1505,7 +1503,7 @@ int rpcclnt_request(struct rpcclnt *rpc, int procnum, int prog, int version, } task->r_rpcclnt = rpc; - task->r_xid = value.xid; + task->r_xid = value.xid; task->r_procnum = procnum; if (rpc->rc_flag & RPCCLNT_SOFT) @@ -1809,19 +1807,15 @@ void rpcclnt_timer(void *arg, struct rpc_call *call) } #endif -/* Build the RPC header and fill in the authorization info. */ +/* Get a new (non-zero) xid */ -int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, - struct xidr *value, FAR const void *datain, - void *dataout) +uint32_t rpcclnt_newxid(void) { - srand(time(NULL)); + static uint32_t rpcclnt_xid = 0; + static uint32_t rpcclnt_xid_touched = 0; int xidp = 0; - /* The RPC header.*/ - - /* Get a new (non-zero) xid */ - + srand(time(NULL)); if ((rpcclnt_xid == 0) && (rpcclnt_xid_touched == 0)) { rpcclnt_xid = rand(); @@ -1838,6 +1832,23 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, rpcclnt_xid += xidp; } + return rpcclnt_xid; +} + +/* Build the RPC header and fill in the authorization info. */ + +int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, + struct xidr *value, FAR const void *datain, + void *dataout) +{ + uint32_t xid; + + /* The RPC header.*/ + + /* Get a new (non-zero) xid */ + + xid = rpcclnt_newxid(); + /* Perform the binding depending on the protocol type */ if (prog == PMAPPROG) @@ -1847,7 +1858,7 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, struct rpc_call_pmap *callmsg = (struct rpc_call_pmap *)dataout; memcpy(&callmsg->pmap, datain, sizeof(struct call_args_pmap)); - callmsg->ch.rp_xid = txdr_unsigned(rpcclnt_xid); + callmsg->ch.rp_xid = txdr_unsigned(xid); value->xid = callmsg->ch.rp_xid; callmsg->ch.rp_direction = rpc_call; callmsg->ch.rp_rpcvers = rpc_vers; @@ -1876,7 +1887,7 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, { struct rpc_call_pmap *callmsg = (struct rpc_call_pmap *)dataout;; memcpy(&callmsg->pmap, datain, sizeof(struct call_args_pmap)); - callmsg->ch.rp_xid = txdr_unsigned(rpcclnt_xid); + callmsg->ch.rp_xid = txdr_unsigned(xid); value->xid = callmsg->ch.rp_xid; callmsg->ch.rp_direction = rpc_call; callmsg->ch.rp_rpcvers = rpc_vers; @@ -1908,7 +1919,7 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, { struct rpc_call_mount *callmsg = (struct rpc_call_mount *)dataout; memcpy(&callmsg->mount, datain, sizeof(struct call_args_mount)); - callmsg->ch.rp_xid = txdr_unsigned(rpcclnt_xid); + callmsg->ch.rp_xid = txdr_unsigned(xid); value->xid = callmsg->ch.rp_xid; callmsg->ch.rp_direction = rpc_call; callmsg->ch.rp_rpcvers = rpc_vers; @@ -1937,7 +1948,7 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, { struct rpc_call_mount *callmsg = (struct rpc_call_mount *)dataout; memcpy(&callmsg->mount, datain, sizeof(struct call_args_mount)); - callmsg->ch.rp_xid = txdr_unsigned(rpcclnt_xid); + callmsg->ch.rp_xid = txdr_unsigned(xid); value->xid = callmsg->ch.rp_xid; callmsg->ch.rp_direction = rpc_call; callmsg->ch.rp_rpcvers = rpc_vers; @@ -1971,7 +1982,7 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, { struct rpc_call_create *callmsg = (struct rpc_call_create *)dataout; memcpy(&callmsg->create, datain, sizeof(struct CREATE3args)); - callmsg->ch.rp_xid = txdr_unsigned(rpcclnt_xid); + callmsg->ch.rp_xid = txdr_unsigned(xid); value->xid = callmsg->ch.rp_xid; callmsg->ch.rp_direction = rpc_call; callmsg->ch.rp_rpcvers = rpc_vers; @@ -2001,7 +2012,7 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, { struct rpc_call_read *callmsg = (struct rpc_call_read *)dataout; memcpy(&callmsg->read, datain, sizeof(struct READ3args)); - callmsg->ch.rp_xid = txdr_unsigned(rpcclnt_xid); + callmsg->ch.rp_xid = txdr_unsigned(xid); value->xid = callmsg->ch.rp_xid; callmsg->ch.rp_direction = rpc_call; callmsg->ch.rp_rpcvers = rpc_vers; @@ -2032,7 +2043,7 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, { struct rpc_call_write *callmsg = (struct rpc_call_write *)dataout; memcpy(&callmsg->write, datain, sizeof(struct WRITE3args)); - callmsg->ch.rp_xid = txdr_unsigned(rpcclnt_xid); + callmsg->ch.rp_xid = txdr_unsigned(xid); value->xid = callmsg->ch.rp_xid; callmsg->ch.rp_direction = rpc_call; callmsg->ch.rp_rpcvers = rpc_vers; @@ -2063,7 +2074,7 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, { struct rpc_call_readdir *callmsg = (struct rpc_call_readdir *)dataout; memcpy(&callmsg->readdir, datain, sizeof(struct READDIR3args)); - callmsg->ch.rp_xid = txdr_unsigned(rpcclnt_xid); + callmsg->ch.rp_xid = txdr_unsigned(xid); value->xid = callmsg->ch.rp_xid; callmsg->ch.rp_direction = rpc_call; callmsg->ch.rp_rpcvers = rpc_vers; @@ -2094,7 +2105,7 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, { struct rpc_call_fs *callmsg = (struct rpc_call_fs *)dataout; memcpy(&callmsg->fs, datain, sizeof(struct FS3args)); - callmsg->ch.rp_xid = txdr_unsigned(rpcclnt_xid); + callmsg->ch.rp_xid = txdr_unsigned(xid); value->xid = callmsg->ch.rp_xid; callmsg->ch.rp_direction = rpc_call; callmsg->ch.rp_rpcvers = rpc_vers; @@ -2125,7 +2136,7 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, { struct rpc_call_remove *callmsg = (struct rpc_call_remove *)dataout; memcpy(&callmsg->remove, datain, sizeof(struct REMOVE3args)); - callmsg->ch.rp_xid = txdr_unsigned(rpcclnt_xid); + callmsg->ch.rp_xid = txdr_unsigned(xid); value->xid = callmsg->ch.rp_xid; callmsg->ch.rp_direction = rpc_call; callmsg->ch.rp_rpcvers = rpc_vers; @@ -2156,7 +2167,7 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, { struct rpc_call_fs *callmsg = (struct rpc_call_fs *)dataout; memcpy(&callmsg->fs, datain, sizeof(struct FS3args)); - callmsg->ch.rp_xid = txdr_unsigned(rpcclnt_xid); + callmsg->ch.rp_xid = txdr_unsigned(xid); value->xid = callmsg->ch.rp_xid; callmsg->ch.rp_direction = rpc_call; callmsg->ch.rp_rpcvers = rpc_vers; @@ -2187,7 +2198,7 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, { struct rpc_call_mkdir *callmsg = (struct rpc_call_mkdir *)dataout; memcpy(&callmsg->mkdir, datain, sizeof(struct MKDIR3args)); - callmsg->ch.rp_xid = txdr_unsigned(rpcclnt_xid); + callmsg->ch.rp_xid = txdr_unsigned(xid); value->xid = callmsg->ch.rp_xid; callmsg->ch.rp_direction = rpc_call; callmsg->ch.rp_rpcvers = rpc_vers; @@ -2218,7 +2229,7 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, { struct rpc_call_rmdir *callmsg = (struct rpc_call_rmdir *)dataout; memcpy(&callmsg->rmdir, datain, sizeof(struct RMDIR3args)); - callmsg->ch.rp_xid = txdr_unsigned(rpcclnt_xid); + callmsg->ch.rp_xid = txdr_unsigned(xid); value->xid = callmsg->ch.rp_xid; callmsg->ch.rp_direction = rpc_call; callmsg->ch.rp_rpcvers = rpc_vers; @@ -2249,7 +2260,7 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, { struct rpc_call_rename *callmsg = (struct rpc_call_rename *)dataout; memcpy(&callmsg->rename, datain, sizeof(struct RENAME3args)); - callmsg->ch.rp_xid = txdr_unsigned(rpcclnt_xid); + callmsg->ch.rp_xid = txdr_unsigned(xid); value->xid = callmsg->ch.rp_xid; callmsg->ch.rp_direction = rpc_call; callmsg->ch.rp_rpcvers = rpc_vers; @@ -2280,7 +2291,7 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, { struct rpc_call_fs *callmsg = (struct rpc_call_fs *)dataout; memcpy(&callmsg->fs, datain, sizeof(struct FS3args)); - callmsg->ch.rp_xid = txdr_unsigned(rpcclnt_xid); + callmsg->ch.rp_xid = txdr_unsigned(xid); value->xid = callmsg->ch.rp_xid; callmsg->ch.rp_direction = rpc_call; callmsg->ch.rp_rpcvers = rpc_vers; @@ -2315,6 +2326,29 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers, return ESRCH; } +/**************************************************************************** + * Name: rpcclnt_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 rpcclnt_lookup(FAR struct rpcclnt *rpc, FAR const char *relpath, + FAR struct file_handle *fhandle, + FAR struct nfs_fattr *obj_attributes, + FAR struct nfs_fattr *dir_attributes) +{ +#warning "Missing logic" + return ENOSYS; +} + #ifdef COMP int rpcclnt_cancelreqs(struct rpcclnt *rpc) {