forked from Archive/PX4-Autopilot
NFS update
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4821 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
parent
fd5446a23b
commit
3581588fde
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <queue.h>
|
||||
#include <string.h>
|
||||
|
@ -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);
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue