mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-11-03 23:51:35 +08:00
NFS update
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4829 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
@@ -88,7 +88,7 @@ struct nfsmount
|
|||||||
uint32_t nm_sent; /* Request send count */
|
uint32_t nm_sent; /* Request send count */
|
||||||
uint32_t nm_cwnd; /* Request send window */
|
uint32_t nm_cwnd; /* Request send window */
|
||||||
uint32_t nm_timeouts; /* Request timeouts */
|
uint32_t nm_timeouts; /* Request timeouts */
|
||||||
uint32_t nm_deadthresh; /* Threshold of timeouts-->dead server */
|
//uint32_t nm_deadthresh; /* Threshold of timeouts-->dead server */
|
||||||
uint32_t nm_rsize; /* Max size of read rpc */
|
uint32_t nm_rsize; /* Max size of read rpc */
|
||||||
uint32_t nm_wsize; /* Max size of write rpc */
|
uint32_t nm_wsize; /* Max size of write rpc */
|
||||||
uint32_t nm_readdirsize; /* Size of a readdir rpc */
|
uint32_t nm_readdirsize; /* Size of a readdir rpc */
|
||||||
|
|||||||
@@ -334,7 +334,6 @@ struct nfsfh
|
|||||||
typedef struct nfsfh nfsfh_t;
|
typedef struct nfsfh nfsfh_t;
|
||||||
#define SIZEOF_nfsfh_t(n) (n)
|
#define SIZEOF_nfsfh_t(n) (n)
|
||||||
|
|
||||||
|
|
||||||
struct nfsv3_time
|
struct nfsv3_time
|
||||||
{
|
{
|
||||||
uint32_t nfsv3_sec;
|
uint32_t nfsv3_sec;
|
||||||
@@ -590,14 +589,15 @@ struct RENAME3resok
|
|||||||
struct MKDIR3args
|
struct MKDIR3args
|
||||||
{
|
{
|
||||||
struct diropargs3 where;
|
struct diropargs3 where;
|
||||||
struct nfsv3_sattr attributes;
|
struct nfsv3_sattr how;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MKDIR3resok
|
struct MKDIR3resok
|
||||||
{
|
{
|
||||||
struct file_handle fhandle;
|
uint32_t handle_follows; /* True, handle follows */
|
||||||
uint32_t obj_attributesfalse;
|
struct file_handle fhandle; /* Variable length */
|
||||||
struct nfs_fattr obj_attributes;
|
uint32_t attributes_follows; /* True, attributes follows */
|
||||||
|
struct nfs_fattr attributes; /* Directory attributes */
|
||||||
struct wcc_data dir_wcc;
|
struct wcc_data dir_wcc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+35
-22
@@ -141,28 +141,24 @@ int nfs_connect(struct nfsmount *nmp)
|
|||||||
nfsmnt_to_rpcclnt(nmp->nm_flag, rpc->rc_flag, NOCONN);
|
nfsmnt_to_rpcclnt(nmp->nm_flag, rpc->rc_flag, NOCONN);
|
||||||
nfsmnt_to_rpcclnt(nmp->nm_flag, rpc->rc_flag, DUMBTIMR);
|
nfsmnt_to_rpcclnt(nmp->nm_flag, rpc->rc_flag, DUMBTIMR);
|
||||||
|
|
||||||
//rpc->rc_flag |= RPCCLNT_REDIRECT; /* Make this a mount option. */
|
rpc->rc_authtype = RPCAUTH_NULL; /* for now */
|
||||||
|
rpc->rc_path = nmp->nm_path;
|
||||||
|
rpc->rc_name = &nmp->nm_nam;
|
||||||
|
|
||||||
//rpc->rc_authtype = RPCAUTH_NULL; /* for now */
|
rpc->rc_sotype = nmp->nm_sotype;
|
||||||
rpc->rc_path = nmp->nm_path;
|
rpc->rc_soproto = nmp->nm_soproto;
|
||||||
rpc->rc_name = &nmp->nm_nam;
|
rpc->rc_rsize = (nmp->nm_rsize > nmp->nm_readdirsize) ? nmp->nm_rsize : nmp->nm_readdirsize;
|
||||||
//rpc->rc_fh = nmp->nm_fh;
|
rpc->rc_wsize = nmp->nm_wsize;
|
||||||
|
|
||||||
rpc->rc_sotype = nmp->nm_sotype;
|
|
||||||
rpc->rc_soproto = nmp->nm_soproto;
|
|
||||||
rpc->rc_rsize = (nmp->nm_rsize > nmp->nm_readdirsize) ?
|
|
||||||
nmp->nm_rsize : nmp->nm_readdirsize;
|
|
||||||
rpc->rc_wsize = nmp->nm_wsize;
|
|
||||||
//rpc->rc_deadthresh = nmp->nm_deadthresh;
|
//rpc->rc_deadthresh = nmp->nm_deadthresh;
|
||||||
rpc->rc_timeo = nmp->nm_timeo;
|
rpc->rc_timeo = nmp->nm_timeo;
|
||||||
rpc->rc_retry = nmp->nm_retry;
|
rpc->rc_retry = nmp->nm_retry;
|
||||||
|
|
||||||
/* v3 need to use this */
|
/* v3 needs to use this */
|
||||||
|
|
||||||
rpc->rc_proctlen = 0;
|
rpc->rc_proctlen = 0;
|
||||||
rpc->rc_proct = NULL;
|
rpc->rc_proct = NULL;
|
||||||
|
|
||||||
nmp->nm_rpcclnt = rpc;
|
nmp->nm_rpcclnt = rpc;
|
||||||
|
|
||||||
return rpcclnt_connect(rpc);
|
return rpcclnt_connect(rpc);
|
||||||
}
|
}
|
||||||
@@ -185,14 +181,14 @@ int nfs_request(struct nfsmount *nmp, int procnum,
|
|||||||
FAR const void *request, size_t reqlen,
|
FAR const void *request, size_t reqlen,
|
||||||
FAR void *response, size_t resplen)
|
FAR void *response, size_t resplen)
|
||||||
{
|
{
|
||||||
struct rpcclnt *clnt= nmp->nm_rpcclnt;
|
struct rpcclnt *clnt = nmp->nm_rpcclnt;
|
||||||
struct rpc_reply_header replyh;
|
struct nfs_reply_header replyh;
|
||||||
int trylater_delay;
|
int trylater_delay;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
tryagain:
|
tryagain:
|
||||||
|
|
||||||
memset(&replyh, 0, sizeof(struct rpc_reply_header));
|
memset(&replyh, 0, sizeof(struct nfs_reply_header));
|
||||||
|
|
||||||
error = rpcclnt_request(clnt, procnum, nmp->nm_rpcclnt->rc_prog->prog_id,
|
error = rpcclnt_request(clnt, procnum, nmp->nm_rpcclnt->rc_prog->prog_id,
|
||||||
nmp->nm_rpcclnt->rc_prog->prog_version, request, reqlen,
|
nmp->nm_rpcclnt->rc_prog->prog_version, request, reqlen,
|
||||||
@@ -203,7 +199,23 @@ tryagain:
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&replyh, response, sizeof(struct rpc_reply_header));
|
memcpy(&replyh, response, sizeof(struct nfs_reply_header));
|
||||||
|
|
||||||
|
if (replyh.nfs_status != 0)
|
||||||
|
{
|
||||||
|
if (fxdr_unsigned(uint32_t, replyh.nfs_status) > 32)
|
||||||
|
{
|
||||||
|
error = EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* NFS_ERRORS are the same as NuttX errno values */
|
||||||
|
|
||||||
|
error = fxdr_unsigned(uint32_t, replyh.nfs_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (replyh.rpc_verfi.authtype != 0)
|
if (replyh.rpc_verfi.authtype != 0)
|
||||||
{
|
{
|
||||||
@@ -239,7 +251,8 @@ tryagain:
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
fvdbg("NFS_SUCCESS\n");
|
||||||
|
return OK;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return error;
|
return error;
|
||||||
|
|||||||
@@ -380,7 +380,7 @@ int nfs_lookup(struct nfsmount *nmp, FAR const char *filename,
|
|||||||
|
|
||||||
value = *ptr++;
|
value = *ptr++;
|
||||||
value = fxdr_unsigned(uint32_t, value);
|
value = fxdr_unsigned(uint32_t, value);
|
||||||
if (value > NFSX_V2FH)
|
if (value > NFSX_V3FHMAX)
|
||||||
{
|
{
|
||||||
fdbg("ERROR: Bad file handle length: %d\n", value);
|
fdbg("ERROR: Bad file handle length: %d\n", value);
|
||||||
return EIO;
|
return EIO;
|
||||||
@@ -444,7 +444,7 @@ int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath,
|
|||||||
/* Start with the file handle of the root directory. */
|
/* Start with the file handle of the root directory. */
|
||||||
|
|
||||||
fhandle->length = nmp->nm_fhsize;
|
fhandle->length = nmp->nm_fhsize;
|
||||||
memcpy(&fhandle->handle, &nmp->nm_fh, sizeof(nfsfh_t));
|
memcpy(&fhandle->handle, &nmp->nm_fh, nmp->nm_fhsize);
|
||||||
|
|
||||||
/* If no path was provided, then the root directory must be exactly what
|
/* If no path was provided, then the root directory must be exactly what
|
||||||
* the caller is looking for.
|
* the caller is looking for.
|
||||||
@@ -560,7 +560,7 @@ int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath,
|
|||||||
/* Start with the file handle of the root directory. */
|
/* Start with the file handle of the root directory. */
|
||||||
|
|
||||||
fhandle->length = nmp->nm_fhsize;
|
fhandle->length = nmp->nm_fhsize;
|
||||||
memcpy(&fhandle->handle, &nmp->nm_fh, sizeof(nfsfh_t));
|
memcpy(&fhandle->handle, &nmp->nm_fh, nmp->nm_fhsize);
|
||||||
memcpy(attributes, &nmp->nm_fattr, sizeof(struct nfs_fattr));
|
memcpy(attributes, &nmp->nm_fattr, sizeof(struct nfs_fattr));
|
||||||
|
|
||||||
/* Loop until the directory entry containing the path is found. */
|
/* Loop until the directory entry containing the path is found. */
|
||||||
|
|||||||
+340
-289
@@ -201,7 +201,7 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np,
|
|||||||
{
|
{
|
||||||
struct file_handle fhandle;
|
struct file_handle fhandle;
|
||||||
char filename[NAME_MAX + 1];
|
char filename[NAME_MAX + 1];
|
||||||
struct CREATE3args create;
|
struct CREATE3args request;
|
||||||
struct rpc_reply_create resok;
|
struct rpc_reply_create resok;
|
||||||
FAR uint32_t *ptr;
|
FAR uint32_t *ptr;
|
||||||
uint32_t tmp;
|
uint32_t tmp;
|
||||||
@@ -220,7 +220,7 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np,
|
|||||||
|
|
||||||
/* Create the CREATE RPC call arguments */
|
/* Create the CREATE RPC call arguments */
|
||||||
|
|
||||||
ptr = (FAR uint32_t *)&create;
|
ptr = (FAR uint32_t *)&request;
|
||||||
reqlen = 0;
|
reqlen = 0;
|
||||||
|
|
||||||
/* Copy the variable length, directory file handle */
|
/* Copy the variable length, directory file handle */
|
||||||
@@ -240,6 +240,7 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np,
|
|||||||
reqlen += sizeof(uint32_t);
|
reqlen += sizeof(uint32_t);
|
||||||
|
|
||||||
memcpy(ptr, filename, namelen);
|
memcpy(ptr, filename, namelen);
|
||||||
|
ptr += uint32_increment(namelen);
|
||||||
reqlen += uint32_alignup(namelen);
|
reqlen += uint32_alignup(namelen);
|
||||||
|
|
||||||
/* Set the creation mode */
|
/* Set the creation mode */
|
||||||
@@ -320,7 +321,7 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np,
|
|||||||
{
|
{
|
||||||
nfsstats.rpccnt[NFSPROC_CREATE]++;
|
nfsstats.rpccnt[NFSPROC_CREATE]++;
|
||||||
error = nfs_request(nmp, NFSPROC_CREATE,
|
error = nfs_request(nmp, NFSPROC_CREATE,
|
||||||
(FAR const void *)&create, reqlen,
|
(FAR const void *)&request, reqlen,
|
||||||
(FAR void *)&resok, sizeof(struct rpc_reply_create));
|
(FAR void *)&resok, sizeof(struct rpc_reply_create));
|
||||||
}
|
}
|
||||||
#ifdef USE_GUARDED_CREATE
|
#ifdef USE_GUARDED_CREATE
|
||||||
@@ -696,7 +697,7 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen)
|
|||||||
ssize_t tmp;
|
ssize_t tmp;
|
||||||
ssize_t bytesread;
|
ssize_t bytesread;
|
||||||
size_t reqlen;
|
size_t reqlen;
|
||||||
struct READ3args read;
|
struct READ3args request;
|
||||||
FAR uint32_t *ptr;
|
FAR uint32_t *ptr;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
@@ -756,7 +757,7 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen)
|
|||||||
|
|
||||||
/* Initialize the request */
|
/* Initialize the request */
|
||||||
|
|
||||||
ptr = (FAR uint32_t*)&read;
|
ptr = (FAR uint32_t*)&request;
|
||||||
reqlen = 0;
|
reqlen = 0;
|
||||||
|
|
||||||
/* Copy the variable length, directory file handle */
|
/* Copy the variable length, directory file handle */
|
||||||
@@ -784,7 +785,7 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen)
|
|||||||
fvdbg("Reading %d bytes\n", readsize);
|
fvdbg("Reading %d bytes\n", readsize);
|
||||||
nfsstats.rpccnt[NFSPROC_READ]++;
|
nfsstats.rpccnt[NFSPROC_READ]++;
|
||||||
error = nfs_request(nmp, NFSPROC_READ,
|
error = nfs_request(nmp, NFSPROC_READ,
|
||||||
(FAR const void *)&read, reqlen,
|
(FAR const void *)&request, reqlen,
|
||||||
(FAR void *)np->n_iobuffer, np->n_buflen);
|
(FAR void *)np->n_iobuffer, np->n_buflen);
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
@@ -1089,8 +1090,8 @@ errout_with_semaphore:
|
|||||||
static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
|
static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
|
||||||
{
|
{
|
||||||
struct nfsmount *nmp;
|
struct nfsmount *nmp;
|
||||||
uint32_t buffer[64]; /* Needs to go into struct fs_dirent_s nuttx/dirent.h */
|
uint32_t buffer[64];
|
||||||
struct READDIR3args rddir;
|
struct READDIR3args request;
|
||||||
struct rpc_reply_readdir *resok;
|
struct rpc_reply_readdir *resok;
|
||||||
struct file_handle fhandle;
|
struct file_handle fhandle;
|
||||||
struct nfs_fattr obj_attributes;
|
struct nfs_fattr obj_attributes;
|
||||||
@@ -1098,8 +1099,6 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
|
|||||||
uint32_t *ptr;
|
uint32_t *ptr;
|
||||||
uint8_t *name;
|
uint8_t *name;
|
||||||
unsigned int length;
|
unsigned int length;
|
||||||
bool more;
|
|
||||||
bool eod;
|
|
||||||
int reqlen;
|
int reqlen;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
@@ -1123,121 +1122,110 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
|
|||||||
goto errout_with_semaphore;
|
goto errout_with_semaphore;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check in 'dir' if we are have directories entries?
|
/* Request a block directory entries, copying directory information from
|
||||||
* 1) have data, and
|
* the dirent structure.
|
||||||
* 2) Index of the last returned entry has nextentry != 0
|
|
||||||
*
|
|
||||||
* If we have returned entries then read more entries if:
|
|
||||||
* 3) EOF = 0
|
|
||||||
*/
|
|
||||||
|
|
||||||
more = false; /* Set 'more' to true if we have buffered entries to be processed */
|
|
||||||
eod = false; /* Set 'eod' if we are at the end of the directory */
|
|
||||||
|
|
||||||
/* Loop while we need more data (!more) and we are not at the end of
|
|
||||||
* the directory (!eod)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
while (!more && !eod)
|
ptr = (FAR uint32_t*)&request;
|
||||||
|
reqlen = 0;
|
||||||
|
|
||||||
|
/* Copy the variable length, directory file handle */
|
||||||
|
|
||||||
|
*ptr++ = txdr_unsigned((uint32_t)dir->u.nfs.nfs_fhsize);
|
||||||
|
reqlen += sizeof(uint32_t);
|
||||||
|
|
||||||
|
memcpy(ptr, dir->u.nfs.nfs_fhandle, dir->u.nfs.nfs_fhsize);
|
||||||
|
reqlen += (int)dir->u.nfs.nfs_fhsize;
|
||||||
|
ptr += uint32_increment((int)dir->u.nfs.nfs_fhsize);
|
||||||
|
|
||||||
|
/* Cookie and cookie verifier */
|
||||||
|
|
||||||
|
ptr[0] = dir->u.nfs.nfs_cookie[0];
|
||||||
|
ptr[1] = dir->u.nfs.nfs_cookie[1];
|
||||||
|
ptr += 2;
|
||||||
|
reqlen += 2*sizeof(uint32_t);
|
||||||
|
|
||||||
|
memcpy(ptr, dir->u.nfs.nfs_verifier, DIRENT_NFS_VERFLEN);
|
||||||
|
ptr += uint32_increment(DIRENT_NFS_VERFLEN);
|
||||||
|
reqlen += DIRENT_NFS_VERFLEN;
|
||||||
|
|
||||||
|
/* Number of directory entries (We currently only process one entry at a time) */
|
||||||
|
|
||||||
|
*ptr = txdr_unsigned(nmp->nm_readdirsize);
|
||||||
|
reqlen += sizeof(uint32_t);
|
||||||
|
|
||||||
|
/* And read the directory */
|
||||||
|
|
||||||
|
nfsstats.rpccnt[NFSPROC_READDIR]++;
|
||||||
|
error = nfs_request(nmp, NFSPROC_READDIR,
|
||||||
|
(FAR const void *)&request, reqlen,
|
||||||
|
(FAR void *)buffer, sizeof(buffer));
|
||||||
|
if (error != OK)
|
||||||
{
|
{
|
||||||
/* Request a block directory entries, copying directory information from
|
fdbg("ERROR: nfs_request failed: %d\n", error);
|
||||||
* the dirent structure.
|
goto errout_with_semaphore;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A new group of entries was successfully read. Process the
|
||||||
|
* information contained in the response header. This information
|
||||||
|
* includes:
|
||||||
|
*
|
||||||
|
* 1) Attributes follow indication - 4 bytes
|
||||||
|
* 2) Directory attributes - sizeof(struct nfs_fattr)
|
||||||
|
* 3) Cookie verifier - NFSX_V3COOKIEVERF bytes
|
||||||
|
* 4) Values follows indication - 4 bytes
|
||||||
|
*/
|
||||||
|
|
||||||
|
resok = (struct rpc_reply_readdir *)buffer;
|
||||||
|
|
||||||
|
/* Start with the first entry */
|
||||||
|
|
||||||
|
ptr = (uint32_t*)&resok->readdir;
|
||||||
|
|
||||||
|
/* Check if attributes follow, if 0 so Skip over the attributes */
|
||||||
|
|
||||||
|
tmp = *ptr++;
|
||||||
|
if (tmp != 0)
|
||||||
|
{
|
||||||
|
/* Attributes are not currently used */
|
||||||
|
|
||||||
|
ptr += uint32_increment(sizeof(struct nfs_fattr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save the verification cookie */
|
||||||
|
|
||||||
|
memcpy(dir->u.nfs.nfs_verifier, ptr, DIRENT_NFS_VERFLEN);
|
||||||
|
ptr += uint32_increment(DIRENT_NFS_VERFLEN);
|
||||||
|
|
||||||
|
/* Check if values follow. If no values follow, then the EOF indication
|
||||||
|
* will appear next.
|
||||||
|
*/
|
||||||
|
|
||||||
|
tmp = *ptr++;
|
||||||
|
if (tmp == 0)
|
||||||
|
{
|
||||||
|
/* No values follow, then the reply should consist only of a 4-byte
|
||||||
|
* end-of-directory indication.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
memset(&rddir, 0, sizeof(struct READDIR3args));
|
tmp = *ptr++;
|
||||||
|
if (tmp != 0)
|
||||||
/* Initialize the request */
|
|
||||||
|
|
||||||
ptr = (FAR uint32_t*)&rddir;
|
|
||||||
reqlen = 0;
|
|
||||||
|
|
||||||
/* Copy the variable length, directory file handle */
|
|
||||||
|
|
||||||
*ptr++ = txdr_unsigned((uint32_t)dir->u.nfs.nfs_fhsize);
|
|
||||||
reqlen += sizeof(uint32_t);
|
|
||||||
|
|
||||||
memcpy(ptr, dir->u.nfs.nfs_fhandle, dir->u.nfs.nfs_fhsize);
|
|
||||||
reqlen += (int)dir->u.nfs.nfs_fhsize;
|
|
||||||
ptr += uint32_increment((int)dir->u.nfs.nfs_fhsize);
|
|
||||||
|
|
||||||
/* Cookie and cookie verifier */
|
|
||||||
|
|
||||||
ptr[0] = dir->u.nfs.nfs_cookie[0];
|
|
||||||
ptr[1] = dir->u.nfs.nfs_cookie[1];
|
|
||||||
ptr += 2;
|
|
||||||
reqlen += 2*sizeof(uint32_t);
|
|
||||||
|
|
||||||
memcpy(ptr, dir->u.nfs.nfs_verifier, DIRENT_NFS_VERFLEN);
|
|
||||||
ptr += uint32_increment(DIRENT_NFS_VERFLEN);
|
|
||||||
reqlen += DIRENT_NFS_VERFLEN;
|
|
||||||
|
|
||||||
/* Number of directory entries (We currently only process one entry at a time) */
|
|
||||||
|
|
||||||
*ptr = txdr_unsigned(nmp->nm_readdirsize);
|
|
||||||
reqlen += sizeof(uint32_t);
|
|
||||||
|
|
||||||
/* And read the directory */
|
|
||||||
|
|
||||||
nfsstats.rpccnt[NFSPROC_READDIR]++;
|
|
||||||
error = nfs_request(nmp, NFSPROC_READDIR,
|
|
||||||
(FAR const void *)&rddir, reqlen,
|
|
||||||
(FAR void *)buffer, sizeof(buffer));
|
|
||||||
if (error != OK)
|
|
||||||
{
|
{
|
||||||
fdbg("ERROR: nfs_request failed: %d\n", error);
|
fvdbg("End of directory\n");
|
||||||
goto errout_with_semaphore;
|
error = ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A new group of entries was successfully read. Process the
|
/* What would it mean if there were not data and we not at the end of
|
||||||
* information contained in the response header. This information
|
* file?
|
||||||
* includes:
|
|
||||||
*
|
|
||||||
* 1) Attributes follow indication - 4 bytes
|
|
||||||
* 2) Directory attributes - sizeof(struct nfs_fattr)
|
|
||||||
* 3) Cookie verifier - NFSX_V3COOKIEVERF bytes
|
|
||||||
* 4) Values follows indication - 4 bytes
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
resok = (struct rpc_reply_readdir *)buffer;
|
else
|
||||||
|
{
|
||||||
/* Start with the first entry */
|
fvdbg("No data but not end of directory???\n");
|
||||||
|
error = EAGAIN;
|
||||||
ptr = (uint32_t*)&resok->readdir;
|
|
||||||
|
|
||||||
/* Check if attributes follow, if 0 so Skip over the attributes */
|
|
||||||
|
|
||||||
if (resok->readdir.attributes_follow == 1)
|
|
||||||
{
|
|
||||||
/* Attributes are not currently used */
|
|
||||||
}
|
}
|
||||||
#warning "Won't the structure format be wrong if there are no attributes -- this will need to be parsed too"
|
|
||||||
|
|
||||||
/* Save the verification cookie */
|
goto errout_with_semaphore;
|
||||||
|
|
||||||
memcpy(dir->u.nfs.nfs_verifier, &resok->readdir.cookieverf, DIRENT_NFS_VERFLEN);
|
|
||||||
|
|
||||||
/* Get a pointer to the diretory entries (if any) */
|
|
||||||
|
|
||||||
ptr = (uint32_t*)&resok->readdir.reply;
|
|
||||||
|
|
||||||
/* Check if values follow. If no values follow, then the EOF indication
|
|
||||||
* will appear next.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (resok->readdir.value_follows == 0)
|
|
||||||
{
|
|
||||||
/* No values follow, then the reply should consist only of a 4-byte
|
|
||||||
* end-of-directory indication.
|
|
||||||
*/
|
|
||||||
|
|
||||||
more = false; /* No entries follow */
|
|
||||||
eod = (*ptr != 0); /* We are (probably) at the end of the directory */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
more = true; /* Assume that entries follow */
|
|
||||||
eod = false; /* Assume that we are not at the end of the directory */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we are not at the end of the directory listing, then a set of entries
|
/* If we are not at the end of the directory listing, then a set of entries
|
||||||
@@ -1248,108 +1236,85 @@ static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
|
|||||||
* Name string (varaiable size but in multiples of 4 bytes)
|
* Name string (varaiable size but in multiples of 4 bytes)
|
||||||
* Cookie (8 bytes)
|
* Cookie (8 bytes)
|
||||||
* next entry (4 bytes)
|
* next entry (4 bytes)
|
||||||
*
|
|
||||||
* If 'more' is true, then we have more directory entries to process.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (more)
|
/* There is an entry. Skip over the file ID and point to the length */
|
||||||
|
|
||||||
|
ptr += 2;
|
||||||
|
|
||||||
|
/* Get the length and point to the name */
|
||||||
|
|
||||||
|
tmp = *ptr++;
|
||||||
|
length = fxdr_unsigned(uint32_t, tmp);
|
||||||
|
name = (uint8_t*)ptr;
|
||||||
|
|
||||||
|
/* Increment the pointer past the name (allowing for padding). ptr
|
||||||
|
* now points to the cookie.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ptr += uint32_increment(length);
|
||||||
|
|
||||||
|
/* Save the cookie and increment the pointer to the next entry */
|
||||||
|
|
||||||
|
dir->u.nfs.nfs_cookie[0] = *ptr++;
|
||||||
|
dir->u.nfs.nfs_cookie[1] = *ptr++;
|
||||||
|
|
||||||
|
ptr++; /* Just skip over the nextentry for now */
|
||||||
|
|
||||||
|
/* Return the name of the node to the caller */
|
||||||
|
|
||||||
|
if (length > NAME_MAX)
|
||||||
{
|
{
|
||||||
/* There is an entry. Get the file ID and point to the length */
|
length = NAME_MAX;
|
||||||
/* Missing logic to get the file ID */
|
|
||||||
|
|
||||||
ptr += 2;
|
|
||||||
|
|
||||||
/* Get the length and point to the name */
|
|
||||||
|
|
||||||
tmp = *ptr++;
|
|
||||||
length = fxdr_unsigned(uint32_t, tmp);
|
|
||||||
name = (uint8_t*)ptr;
|
|
||||||
|
|
||||||
/* Increment the pointer past the name (allowing for padding). ptr
|
|
||||||
* now points to the cookie.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ptr += uint32_increment(length);
|
|
||||||
|
|
||||||
/* Save the cookie and increment the pointer to the next entry */
|
|
||||||
|
|
||||||
dir->u.nfs.nfs_cookie[0] = *ptr++;
|
|
||||||
dir->u.nfs.nfs_cookie[1] = *ptr++;
|
|
||||||
|
|
||||||
ptr++; /* Just skip over the nextentry for now */
|
|
||||||
|
|
||||||
/* Return the name of the node to the caller */
|
|
||||||
|
|
||||||
if (length > NAME_MAX)
|
|
||||||
{
|
|
||||||
length = NAME_MAX;
|
|
||||||
}
|
|
||||||
memcpy(dir->fd_dir.d_name, name, length);
|
|
||||||
dir->fd_dir.d_name[length] = '\0';
|
|
||||||
fvdbg("name: \"%s\"\n", dir->fd_dir.d_name);
|
|
||||||
|
|
||||||
/* Get the file attributes associated with this name and return
|
|
||||||
* the file type.
|
|
||||||
*/
|
|
||||||
|
|
||||||
fhandle.length = (uint32_t)dir->u.nfs.nfs_fhsize;
|
|
||||||
memcpy(&fhandle.handle, dir->u.nfs.nfs_fhandle, DIRENT_NFS_MAXHANDLE);
|
|
||||||
|
|
||||||
error = nfs_lookup(nmp, dir->fd_dir.d_name, &fhandle, &obj_attributes, NULL);
|
|
||||||
if (error != OK)
|
|
||||||
{
|
|
||||||
fdbg("nfs_lookup failed: %d\n", error);
|
|
||||||
goto errout_with_semaphore;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the dirent file type */
|
|
||||||
|
|
||||||
tmp = fxdr_unsigned(uint32_t, obj_attributes.fa_type);
|
|
||||||
switch (tmp)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
case NFNON: /* Unknown type */
|
|
||||||
case NFSOCK: /* Socket */
|
|
||||||
case NFLNK: /* Symbolic link */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NFREG: /* Regular file */
|
|
||||||
dir->fd_dir.d_type = DTYPE_FILE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NFDIR: /* Directory */
|
|
||||||
dir->fd_dir.d_type = DTYPE_DIRECTORY;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NFBLK: /* Block special device file */
|
|
||||||
dir->fd_dir.d_type = DTYPE_BLK;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NFFIFO: /* Named FIFO */
|
|
||||||
case NFCHR: /* Character special device file */
|
|
||||||
dir->fd_dir.d_type = DTYPE_CHR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fvdbg("type: %d->%d\n", (int)tmp, dir->fd_dir.d_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We are at the end of the directory. If 'eod' is true then we all of the
|
memcpy(dir->fd_dir.d_name, name, length);
|
||||||
* directory entries have been processed and we are at the end of the
|
dir->fd_dir.d_name[length] = '\0';
|
||||||
* directory.
|
fvdbg("name: \"%s\"\n", dir->fd_dir.d_name);
|
||||||
|
|
||||||
|
/* Get the file attributes associated with this name and return
|
||||||
|
* the file type.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (eod)
|
fhandle.length = (uint32_t)dir->u.nfs.nfs_fhsize;
|
||||||
{
|
memcpy(&fhandle.handle, dir->u.nfs.nfs_fhandle, DIRENT_NFS_MAXHANDLE);
|
||||||
/* We signal the end of the directory by returning the
|
|
||||||
* special error -ENOENT
|
|
||||||
*/
|
|
||||||
|
|
||||||
fvdbg("End of directory\n");
|
error = nfs_lookup(nmp, dir->fd_dir.d_name, &fhandle, &obj_attributes, NULL);
|
||||||
error = ENOENT;
|
if (error != OK)
|
||||||
|
{
|
||||||
|
fdbg("nfs_lookup failed: %d\n", error);
|
||||||
goto errout_with_semaphore;
|
goto errout_with_semaphore;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = 0;
|
/* Set the dirent file type */
|
||||||
|
|
||||||
|
tmp = fxdr_unsigned(uint32_t, obj_attributes.fa_type);
|
||||||
|
switch (tmp)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case NFNON: /* Unknown type */
|
||||||
|
case NFSOCK: /* Socket */
|
||||||
|
case NFLNK: /* Symbolic link */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NFREG: /* Regular file */
|
||||||
|
dir->fd_dir.d_type = DTYPE_FILE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NFDIR: /* Directory */
|
||||||
|
dir->fd_dir.d_type = DTYPE_DIRECTORY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NFBLK: /* Block special device file */
|
||||||
|
dir->fd_dir.d_type = DTYPE_BLK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NFFIFO: /* Named FIFO */
|
||||||
|
case NFCHR: /* Character special device file */
|
||||||
|
dir->fd_dir.d_type = DTYPE_CHR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fvdbg("type: %d->%d\n", (int)tmp, dir->fd_dir.d_type);
|
||||||
|
|
||||||
errout_with_semaphore:
|
errout_with_semaphore:
|
||||||
nfs_semgive(nmp);
|
nfs_semgive(nmp);
|
||||||
@@ -1866,7 +1831,7 @@ static int nfs_statfs(struct inode *mountpt, struct statfs *sbp)
|
|||||||
error = nfs_checkmount(nmp);
|
error = nfs_checkmount(nmp);
|
||||||
if (error != OK)
|
if (error != OK)
|
||||||
{
|
{
|
||||||
fdbg("nfs_checkmount failed: %d\n", error);
|
fdbg("ERROR: nfs_checkmount failed: %d\n", error);
|
||||||
goto errout_with_semaphore;
|
goto errout_with_semaphore;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1933,7 +1898,6 @@ static int nfs_remove(struct inode *mountpt, const char *relpath)
|
|||||||
struct REMOVE3args remove;
|
struct REMOVE3args remove;
|
||||||
struct rpc_reply_remove resok;
|
struct rpc_reply_remove resok;
|
||||||
FAR uint32_t *ptr;
|
FAR uint32_t *ptr;
|
||||||
uint32_t tmp;
|
|
||||||
int namelen;
|
int namelen;
|
||||||
int reqlen;
|
int reqlen;
|
||||||
int error;
|
int error;
|
||||||
@@ -1967,9 +1931,8 @@ static int nfs_remove(struct inode *mountpt, const char *relpath)
|
|||||||
|
|
||||||
/* We found something at this path. Make sure that it is not a directory. */
|
/* We found something at this path. Make sure that it is not a directory. */
|
||||||
|
|
||||||
#if 0 /* We don't have the attributes of the object to be deleted */
|
#if 0 /* We have the attributes of the directory, not of the object to be deleted */
|
||||||
tmp = fxdr_unsigned(uint32_t, fattr.fa_type);
|
if (fxdr_unsigned(uint32_t, fattr.fa_type) == NFDIR)
|
||||||
if (tmp == NFDIR)
|
|
||||||
{
|
{
|
||||||
fdbg("ERROR: \"%s\" is a directory\n", relpath);
|
fdbg("ERROR: \"%s\" is a directory\n", relpath);
|
||||||
error = EISDIR;
|
error = EISDIR;
|
||||||
@@ -2013,9 +1976,9 @@ static int nfs_remove(struct inode *mountpt, const char *relpath)
|
|||||||
#ifdef CONFIG_NFS_TCPIP
|
#ifdef CONFIG_NFS_TCPIP
|
||||||
if (error == ENOENT)
|
if (error == ENOENT)
|
||||||
{
|
{
|
||||||
/* Kludge City: If the first reply to the remove rpc is lost, the reply
|
/* If the first reply to the remove rpc is lost, the reply to the
|
||||||
* to the retransmitted request will be ENOENT since the file was in
|
* retransmitted request may be ENOENT if the file was in fact removed.
|
||||||
* fact removed. Therefore, we cheat and return success.
|
* Therefore, we cheat and return success.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
error = OK;
|
error = OK;
|
||||||
@@ -2040,12 +2003,17 @@ errout_with_semaphore:
|
|||||||
|
|
||||||
static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
|
static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
|
||||||
{
|
{
|
||||||
struct nfsv3_sattr sp;
|
struct nfsmount *nmp;
|
||||||
struct nfsmount *nmp;
|
struct file_handle fhandle;
|
||||||
struct nfsnode *np;
|
struct nfs_fattr fattr;
|
||||||
struct MKDIR3args mkir;
|
char dirname[NAME_MAX + 1];
|
||||||
|
struct MKDIR3args request;
|
||||||
struct rpc_reply_mkdir resok;
|
struct rpc_reply_mkdir resok;
|
||||||
int error = 0;
|
FAR uint32_t *ptr;
|
||||||
|
uint32_t tmp;
|
||||||
|
int namelen;
|
||||||
|
int reqlen;
|
||||||
|
int error;
|
||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
|
|
||||||
@@ -2054,7 +2022,6 @@ static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
|
|||||||
/* Get the mountpoint private data from the inode structure */
|
/* Get the mountpoint private data from the inode structure */
|
||||||
|
|
||||||
nmp = (struct nfsmount*) mountpt->i_private;
|
nmp = (struct nfsmount*) mountpt->i_private;
|
||||||
np = nmp->nm_head;
|
|
||||||
|
|
||||||
/* Check if the mount is still healthy */
|
/* Check if the mount is still healthy */
|
||||||
|
|
||||||
@@ -2062,46 +2029,97 @@ static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
|
|||||||
error = nfs_checkmount(nmp);
|
error = nfs_checkmount(nmp);
|
||||||
if (error != OK)
|
if (error != OK)
|
||||||
{
|
{
|
||||||
|
fdbg("ERROR: nfs_checkmount: %d\n", error);
|
||||||
goto errout_with_semaphore;
|
goto errout_with_semaphore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find the NFS node of the directory containing the directory to be created */
|
||||||
|
|
||||||
|
error = nfs_finddir(nmp, relpath, &fhandle, &fattr, dirname);
|
||||||
|
if (error != OK)
|
||||||
|
{
|
||||||
|
fdbg("ERROR: nfs_finddir returned: %d\n", error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Format the MKDIR call message arguments */
|
||||||
|
|
||||||
|
ptr = (FAR uint32_t *)&request;
|
||||||
|
reqlen = 0;
|
||||||
|
|
||||||
|
/* Copy the variable length, directory file handle */
|
||||||
|
|
||||||
|
*ptr++ = txdr_unsigned(fhandle.length);
|
||||||
|
reqlen += sizeof(uint32_t);
|
||||||
|
|
||||||
|
memcpy(ptr, &fhandle.handle, fhandle.length);
|
||||||
|
ptr += uint32_increment(fhandle.length);
|
||||||
|
reqlen += (int)fhandle.length;
|
||||||
|
|
||||||
|
/* Copy the variable-length directory name */
|
||||||
|
|
||||||
|
namelen = strlen(dirname);
|
||||||
|
|
||||||
|
*ptr++ = txdr_unsigned(namelen);
|
||||||
|
reqlen += sizeof(uint32_t);
|
||||||
|
|
||||||
|
memcpy(ptr, dirname, namelen);
|
||||||
|
ptr += uint32_increment(namelen);
|
||||||
|
reqlen += uint32_alignup(namelen);
|
||||||
|
|
||||||
|
/* Set the mode. NOTE: Here we depend on the fact that the NuttX and NFS
|
||||||
|
* bit settings are the same (at least for the bits of interest).
|
||||||
|
*/
|
||||||
|
|
||||||
|
*ptr++ = nfs_true; /* True: mode value follows */
|
||||||
|
reqlen += sizeof(uint32_t);
|
||||||
|
|
||||||
|
tmp = mode & (NFSMODE_IXOTH | NFSMODE_IWOTH | NFSMODE_IROTH |
|
||||||
|
NFSMODE_IXGRP | NFSMODE_IWGRP | NFSMODE_IRGRP |
|
||||||
|
NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR);
|
||||||
|
*ptr++ = txdr_unsigned(tmp);
|
||||||
|
reqlen += sizeof(uint32_t);
|
||||||
|
|
||||||
|
/* Set the user ID to zero */
|
||||||
|
|
||||||
|
*ptr++ = nfs_true; /* True: Uid value follows */
|
||||||
|
reqlen += sizeof(uint32_t);
|
||||||
|
|
||||||
|
*ptr++ = 0;
|
||||||
|
reqlen += sizeof(uint32_t);
|
||||||
|
|
||||||
|
/* Set the group ID to one */
|
||||||
|
|
||||||
|
*ptr++ = nfs_true; /* True: Gid value follows */
|
||||||
|
reqlen += sizeof(uint32_t);
|
||||||
|
|
||||||
|
*ptr++ = HTONL(1);
|
||||||
|
reqlen += sizeof(uint32_t);
|
||||||
|
|
||||||
|
/* No size */
|
||||||
|
|
||||||
|
*ptr++ = nfs_false; /* False: No size value follows */
|
||||||
|
reqlen += sizeof(uint32_t);
|
||||||
|
|
||||||
|
/* Don't change times */
|
||||||
|
|
||||||
|
*ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change atime */
|
||||||
|
reqlen += sizeof(uint32_t);
|
||||||
|
|
||||||
|
*ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change mtime */
|
||||||
|
reqlen += sizeof(uint32_t);
|
||||||
|
|
||||||
|
/* Perform the MKDIR RPC */
|
||||||
|
|
||||||
nfsstats.rpccnt[NFSPROC_MKDIR]++;
|
nfsstats.rpccnt[NFSPROC_MKDIR]++;
|
||||||
memset(&mkir, 0, sizeof(struct MKDIR3args));
|
|
||||||
memset(&resok, 0, sizeof(struct rpc_reply_mkdir));
|
|
||||||
mkir.where.fhandle.length = txdr_unsigned(np->n_fhsize);
|
|
||||||
memcpy(&mkir.where.fhandle.handle, &np->n_fhandle, sizeof(nfsfh_t));
|
|
||||||
mkir.where.length = txdr_unsigned(64);
|
|
||||||
strncpy((FAR char *)mkir.where.name, relpath, 64);
|
|
||||||
|
|
||||||
sp.sa_modefollows = nfs_true;
|
|
||||||
sp.sa_mode = txdr_unsigned(mode);
|
|
||||||
sp.sa_uidfollows = 0;
|
|
||||||
sp.sa_gidfollows = 0;
|
|
||||||
sp.sa_sizefollows = 0;
|
|
||||||
sp.sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
|
|
||||||
sp.sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
|
|
||||||
|
|
||||||
//memset(&sp.sa_atime, 0, sizeof(nfstime3));
|
|
||||||
//memset(&sp.sa_mtime, 0, sizeof(nfstime3));
|
|
||||||
|
|
||||||
memcpy(&mkir.attributes, &sp, sizeof(struct nfsv3_sattr));
|
|
||||||
|
|
||||||
error = nfs_request(nmp, NFSPROC_MKDIR,
|
error = nfs_request(nmp, NFSPROC_MKDIR,
|
||||||
(FAR const void *)&mkir, sizeof(struct MKDIR3args),
|
(FAR const void *)&request, reqlen,
|
||||||
(FAR void *)&resok, sizeof(struct rpc_reply_mkdir));
|
(FAR void *)&resok, sizeof(struct rpc_reply_mkdir));
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
goto errout_with_semaphore;
|
fdbg("ERROR: nfs_request failed: %d\n", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
np->n_type = fxdr_unsigned(uint32_t, resok.mkdir.obj_attributes.fa_type);
|
|
||||||
memcpy(&np->n_fhandle, &resok.mkdir.fhandle.handle, sizeof(nfsfh_t));
|
|
||||||
np->n_size = fxdr_hyper(&resok.mkdir.obj_attributes.fa_size);
|
|
||||||
memcpy(&np->n_fattr, &resok.mkdir.obj_attributes, sizeof(struct nfs_fattr));
|
|
||||||
fxdr_nfsv3time(&resok.mkdir.obj_attributes.fa_mtime, &np->n_mtime)
|
|
||||||
np->n_ctime = fxdr_hyper(&resok.mkdir.obj_attributes.fa_ctime);
|
|
||||||
np->n_flags |= (NFSNODE_OPEN | NFSNODE_MODIFIED);
|
|
||||||
|
|
||||||
errout_with_semaphore:
|
errout_with_semaphore:
|
||||||
nfs_semgive(nmp);
|
nfs_semgive(nmp);
|
||||||
return -error;
|
return -error;
|
||||||
@@ -2120,11 +2138,16 @@ errout_with_semaphore:
|
|||||||
|
|
||||||
static int nfs_rmdir(struct inode *mountpt, const char *relpath)
|
static int nfs_rmdir(struct inode *mountpt, const char *relpath)
|
||||||
{
|
{
|
||||||
struct nfsmount *nmp;
|
struct nfsmount *nmp;
|
||||||
struct nfsnode *np;
|
struct file_handle fhandle;
|
||||||
struct RMDIR3args rmdir;
|
struct nfs_fattr fattr;
|
||||||
|
char dirname[NAME_MAX + 1];
|
||||||
|
struct RMDIR3args request;
|
||||||
struct rpc_reply_rmdir resok;
|
struct rpc_reply_rmdir resok;
|
||||||
int error = 0;
|
FAR uint32_t *ptr;
|
||||||
|
int namelen;
|
||||||
|
int reqlen;
|
||||||
|
int error;
|
||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
|
|
||||||
@@ -2133,49 +2156,70 @@ static int nfs_rmdir(struct inode *mountpt, const char *relpath)
|
|||||||
/* Get the mountpoint private data from the inode structure */
|
/* Get the mountpoint private data from the inode structure */
|
||||||
|
|
||||||
nmp = (struct nfsmount *)mountpt->i_private;
|
nmp = (struct nfsmount *)mountpt->i_private;
|
||||||
np = nmp->nm_head;
|
|
||||||
|
|
||||||
/* Check if the mount is still healthy */
|
/* Check if the mount is still healthy */
|
||||||
|
|
||||||
nfs_semtake(nmp);
|
nfs_semtake(nmp);
|
||||||
error = nfs_checkmount(nmp);
|
error = nfs_checkmount(nmp);
|
||||||
if (error == OK)
|
if (error != OK)
|
||||||
{
|
{
|
||||||
/* Remove the directory */
|
fdbg("ERROR: nfs_checkmount failed: %d\n", error);
|
||||||
|
goto errout_with_semaphore;
|
||||||
if (np->n_type != NFDIR)
|
|
||||||
{
|
|
||||||
error = EPERM;
|
|
||||||
goto errout_with_semaphore;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do the rpc */
|
|
||||||
|
|
||||||
nfsstats.rpccnt[NFSPROC_RMDIR]++;
|
|
||||||
memset(&rmdir, 0, sizeof(struct RMDIR3args));
|
|
||||||
memset(&resok, 0, sizeof(struct rpc_reply_rmdir));
|
|
||||||
rmdir.object.fhandle.length = txdr_unsigned(np->n_fhsize);
|
|
||||||
memcpy(&rmdir.object.fhandle.handle, &np->n_fhandle, sizeof(nfsfh_t));
|
|
||||||
rmdir.object.length = txdr_unsigned(64);
|
|
||||||
strncpy((FAR char *)rmdir.object.name, relpath, 64);
|
|
||||||
|
|
||||||
error = nfs_request(nmp, NFSPROC_RMDIR,
|
|
||||||
(FAR const void *)&rmdir, sizeof(struct RMDIR3args),
|
|
||||||
(FAR void *)&resok, sizeof(struct rpc_reply_rmdir));
|
|
||||||
if (error == ENOENT)
|
|
||||||
{
|
|
||||||
error = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
goto errout_with_semaphore;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&np->n_fattr, &resok.rmdir.dir_wcc.after, sizeof(struct nfs_fattr));
|
|
||||||
np->n_flags |= NFSNODE_MODIFIED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find the NFS node of the directory containing the directory to be removed */
|
||||||
|
|
||||||
|
error = nfs_finddir(nmp, relpath, &fhandle, &fattr, dirname);
|
||||||
|
if (error != OK)
|
||||||
|
{
|
||||||
|
fdbg("ERROR: nfs_finddir returned: %d\n", error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up the RMDIR call message arguments */
|
||||||
|
|
||||||
|
ptr = (FAR uint32_t *)&request;
|
||||||
|
reqlen = 0;
|
||||||
|
|
||||||
|
/* Copy the variable length, directory file handle */
|
||||||
|
|
||||||
|
*ptr++ = txdr_unsigned(fhandle.length);
|
||||||
|
reqlen += sizeof(uint32_t);
|
||||||
|
|
||||||
|
memcpy(ptr, &fhandle.handle, fhandle.length);
|
||||||
|
reqlen += (int)fhandle.length;
|
||||||
|
ptr += uint32_increment(fhandle.length);
|
||||||
|
|
||||||
|
/* Copy the variable-length directory name */
|
||||||
|
|
||||||
|
namelen = strlen(dirname);
|
||||||
|
|
||||||
|
*ptr++ = txdr_unsigned(namelen);
|
||||||
|
reqlen += sizeof(uint32_t);
|
||||||
|
|
||||||
|
memcpy(ptr, dirname, namelen);
|
||||||
|
reqlen += uint32_alignup(namelen);
|
||||||
|
|
||||||
|
/* Perform the RMDIR RPC */
|
||||||
|
|
||||||
|
nfsstats.rpccnt[NFSPROC_RMDIR]++;
|
||||||
|
error = nfs_request(nmp, NFSPROC_RMDIR,
|
||||||
|
(FAR const void *)&request, reqlen,
|
||||||
|
(FAR void *)&resok, sizeof(struct rpc_reply_rmdir));
|
||||||
|
|
||||||
|
/* Check if the removal was successful */
|
||||||
|
|
||||||
|
#ifdef CONFIG_NFS_TCPIP
|
||||||
|
if (error == ENOENT)
|
||||||
|
{
|
||||||
|
/* If the first reply to the remove rpc is lost, the reply to the
|
||||||
|
* retransmitted request may be ENOENT if the file was in fact removed.
|
||||||
|
* Therefore, we cheat and return success.
|
||||||
|
*/
|
||||||
|
error = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
errout_with_semaphore:
|
errout_with_semaphore:
|
||||||
nfs_semgive(nmp);
|
nfs_semgive(nmp);
|
||||||
return -error;
|
return -error;
|
||||||
@@ -2242,12 +2286,19 @@ static int nfs_rename(struct inode *mountpt, const char *oldrelpath,
|
|||||||
(FAR const void *)&rename, sizeof(struct RENAME3args),
|
(FAR const void *)&rename, sizeof(struct RENAME3args),
|
||||||
(FAR void *)&resok, sizeof(struct rpc_reply_rename));
|
(FAR void *)&resok, sizeof(struct rpc_reply_rename));
|
||||||
|
|
||||||
/* ENOENT => 0 assuming that it is a reply to a retry. */
|
/* Check if the rename was successful */
|
||||||
|
|
||||||
|
#ifdef CONFIG_NFS_TCPIP
|
||||||
if (error == ENOENT)
|
if (error == ENOENT)
|
||||||
{
|
{
|
||||||
|
/* If the first reply to the remove rpc is lost, the reply to the
|
||||||
|
* retransmitted request may be ENOENT if the file was in fact removed.
|
||||||
|
* Therefore, we cheat and return success.
|
||||||
|
*/
|
||||||
|
|
||||||
error = 0;
|
error = 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
@@ -2302,7 +2353,7 @@ static int nfs_stat(struct inode *mountpt, const char *relpath,
|
|||||||
goto errout_with_semaphore;
|
goto errout_with_semaphore;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the attributes of the requested node */
|
/* Get the file handle attributes of the requested node */
|
||||||
|
|
||||||
error = nfs_findnode(nmp, relpath, &fhandle, &obj_attributes, NULL);
|
error = nfs_findnode(nmp, relpath, &fhandle, &obj_attributes, NULL);
|
||||||
if (error != OK)
|
if (error != OK)
|
||||||
|
|||||||
+16
-10
@@ -281,7 +281,7 @@ enum auth_flavor
|
|||||||
|
|
||||||
struct rpc_auth_info
|
struct rpc_auth_info
|
||||||
{
|
{
|
||||||
enum auth_flavor authtype; /* auth type */
|
uint32_t authtype; /* auth type */
|
||||||
uint32_t authlen; /* auth length */
|
uint32_t authlen; /* auth length */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -394,6 +394,16 @@ struct rpc_reply_header
|
|||||||
uint32_t status;
|
uint32_t status;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct nfs_reply_header
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
uint32_t nfs_status;
|
||||||
|
};
|
||||||
|
|
||||||
struct rpc_reply_pmap
|
struct rpc_reply_pmap
|
||||||
{
|
{
|
||||||
struct rpc_reply_header rh;
|
struct rpc_reply_header rh;
|
||||||
@@ -538,27 +548,23 @@ struct rpcclnt
|
|||||||
int rc_sent; /* Request send count */
|
int rc_sent; /* Request send count */
|
||||||
int rc_cwnd; /* Request send window */
|
int rc_cwnd; /* Request send window */
|
||||||
int rc_timeouts; /* Request timeouts */
|
int rc_timeouts; /* Request timeouts */
|
||||||
|
int rc_authtype; /* Authenticator type */
|
||||||
//int rc_deadthresh; /* Threshold of timeouts-->dead server*/
|
//int rc_deadthresh; /* Threshold of timeouts-->dead server*/
|
||||||
|
|
||||||
/* authentication: */
|
/* authentication: */
|
||||||
/* currently can be RPCAUTH_NULL, RPCAUTH_KERBV4, RPCAUTH_UNIX */
|
/* currently can be RPCAUTH_NULL, RPCAUTH_KERBV4, RPCAUTH_UNIX */
|
||||||
/* should be kept in XDR form */
|
/* should be kept in XDR form */
|
||||||
|
|
||||||
// int rc_authtype; /* Authenticator type */
|
/* RPCAUTH_UNIX */
|
||||||
#ifdef CONFIG_NFS_UNIX_AUTH
|
#ifdef CONFIG_NFS_UNIX_AUTH
|
||||||
/* RPCAUTH_UNIX*/
|
|
||||||
|
|
||||||
struct rpc_auth_info rc_oldauth; /* authentication */
|
struct rpc_auth_info rc_oldauth; /* authentication */
|
||||||
|
void *rc_auth;
|
||||||
#endif
|
#endif
|
||||||
//void *rc_auth;
|
|
||||||
|
|
||||||
struct rpc_program *rc_prog;
|
struct rpc_program *rc_prog;
|
||||||
|
|
||||||
//char *rc_servername;
|
int rc_proctlen; /* if == 0 then rc_proct == NULL */
|
||||||
|
int *rc_proct;
|
||||||
int rc_proctlen; /* if == 0 then rc_proct == NULL */
|
|
||||||
int *rc_proct;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
+23
-31
@@ -1206,15 +1206,18 @@ static int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int ve
|
|||||||
|
|
||||||
case NFSPROC_REMOVE:
|
case NFSPROC_REMOVE:
|
||||||
{
|
{
|
||||||
/* Copy the variable, caller-provided data into the call message structure */
|
/* Copy the variable length, caller-provided data into the call
|
||||||
|
* message structure.
|
||||||
|
*/
|
||||||
|
|
||||||
struct rpc_call_remove *callmsg = (struct rpc_call_remove *)msgbuf;
|
struct rpc_call_remove *callmsg = (struct rpc_call_remove *)msgbuf;
|
||||||
memcpy(&callmsg->remove, request, *reqlen);
|
memcpy(&callmsg->remove, request, *reqlen);
|
||||||
|
|
||||||
/* Return the full size of the message (including messages headers) */
|
/* Return the full size of the message (the size of variable data
|
||||||
|
* plus the size of the messages header).
|
||||||
|
*/
|
||||||
|
|
||||||
DEBUGASSERT(*reqlen == sizeof(struct REMOVE3args));
|
*reqlen += sizeof(struct rpc_call_header);
|
||||||
*reqlen = sizeof(struct rpc_call_remove);
|
|
||||||
|
|
||||||
/* Format the message header */
|
/* Format the message header */
|
||||||
|
|
||||||
@@ -1244,15 +1247,18 @@ static int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int ve
|
|||||||
|
|
||||||
case NFSPROC_MKDIR:
|
case NFSPROC_MKDIR:
|
||||||
{
|
{
|
||||||
/* Copy the variable, caller-provided data into the call message structure */
|
/* Copy the variable length, caller-provided data into the call
|
||||||
|
* message structure.
|
||||||
|
*/
|
||||||
|
|
||||||
struct rpc_call_mkdir *callmsg = (struct rpc_call_mkdir *)msgbuf;
|
struct rpc_call_mkdir *callmsg = (struct rpc_call_mkdir *)msgbuf;
|
||||||
memcpy(&callmsg->mkdir, request, *reqlen);
|
memcpy(&callmsg->mkdir, request, *reqlen);
|
||||||
|
|
||||||
/* Return the full size of the message (including messages headers) */
|
/* Return the full size of the message (the size of variable data
|
||||||
|
* plus the size of the messages header).
|
||||||
|
*/
|
||||||
|
|
||||||
DEBUGASSERT(*reqlen == sizeof(struct MKDIR3args));
|
*reqlen += sizeof(struct rpc_call_header);
|
||||||
*reqlen = sizeof(struct rpc_call_mkdir);
|
|
||||||
|
|
||||||
/* Format the message header */
|
/* Format the message header */
|
||||||
|
|
||||||
@@ -1263,15 +1269,18 @@ static int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int ve
|
|||||||
|
|
||||||
case NFSPROC_RMDIR:
|
case NFSPROC_RMDIR:
|
||||||
{
|
{
|
||||||
/* Copy the variable, caller-provided data into the call message structure */
|
/* Copy the variable length, caller-provided data into the call
|
||||||
|
* message structure.
|
||||||
|
*/
|
||||||
|
|
||||||
struct rpc_call_rmdir *callmsg = (struct rpc_call_rmdir *)msgbuf;
|
struct rpc_call_rmdir *callmsg = (struct rpc_call_rmdir *)msgbuf;
|
||||||
memcpy(&callmsg->rmdir, request, *reqlen);
|
memcpy(&callmsg->rmdir, request, *reqlen);
|
||||||
|
|
||||||
/* Return the full size of the message (including messages headers) */
|
/* Return the full size of the message (the size of variable data
|
||||||
|
* plus the size of the messages header).
|
||||||
|
*/
|
||||||
|
|
||||||
DEBUGASSERT(*reqlen == sizeof(struct RMDIR3args));
|
*reqlen += sizeof(struct rpc_call_header);
|
||||||
*reqlen = sizeof(struct rpc_call_rmdir);
|
|
||||||
|
|
||||||
/* Format the message header */
|
/* Format the message header */
|
||||||
|
|
||||||
@@ -1922,6 +1931,7 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog,
|
|||||||
|
|
||||||
memset(&replymgs, 0, sizeof(replymgs));
|
memset(&replymgs, 0, sizeof(replymgs));
|
||||||
memcpy(&replyheader, response, sizeof(struct rpc_reply_header));
|
memcpy(&replyheader, response, sizeof(struct rpc_reply_header));
|
||||||
|
|
||||||
replymgs.type = fxdr_unsigned(uint32_t, replyheader.type);
|
replymgs.type = fxdr_unsigned(uint32_t, replyheader.type);
|
||||||
if (replymgs.type == RPC_MSGDENIED)
|
if (replymgs.type == RPC_MSGDENIED)
|
||||||
{
|
{
|
||||||
@@ -1929,16 +1939,11 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog,
|
|||||||
switch (replymgs.status)
|
switch (replymgs.status)
|
||||||
{
|
{
|
||||||
case RPC_MISMATCH:
|
case RPC_MISMATCH:
|
||||||
/*replymgs.stat.mismatch_info.low =
|
|
||||||
fxdr_unsigned(uint32_t, replyheader.stat.mismatch_info.low);
|
|
||||||
replymgs.stat.mismatch_info.high =
|
|
||||||
fxdr_unsigned(uint32_t, replyheader.stat.mismatch_info.high);*/
|
|
||||||
fdbg("RPC_MSGDENIED: RPC_MISMATCH error\n");
|
fdbg("RPC_MSGDENIED: RPC_MISMATCH error\n");
|
||||||
error = EOPNOTSUPP;
|
error = EOPNOTSUPP;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RPC_AUTHERR:
|
case RPC_AUTHERR:
|
||||||
//replymgs.stat.autherr = fxdr_unsigned(uint32_t, replyheader.stat.autherr);
|
|
||||||
fdbg("RPC_MSGDENIED: RPC_AUTHERR error\n");
|
fdbg("RPC_MSGDENIED: RPC_AUTHERR error\n");
|
||||||
error = EACCES;
|
error = EACCES;
|
||||||
break;
|
break;
|
||||||
@@ -1947,6 +1952,7 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog,
|
|||||||
error = EOPNOTSUPP;
|
error = EOPNOTSUPP;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
goto rpcmout;
|
goto rpcmout;
|
||||||
}
|
}
|
||||||
else if (replymgs.type != RPC_MSGACCEPTED)
|
else if (replymgs.type != RPC_MSGACCEPTED)
|
||||||
@@ -1955,24 +1961,12 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog,
|
|||||||
goto rpcmout;
|
goto rpcmout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verifier */
|
|
||||||
|
|
||||||
/*replymgs.rpc_verfi.authtype =
|
|
||||||
fxdr_unsigned(enum auth_flavor, replyheader.rpc_verfi.authtype);
|
|
||||||
replymgs.rpc_verfi.authlen =
|
|
||||||
fxdr_unsigned(uint32_t, replyheader.rpc_verfi.authlen);*/
|
|
||||||
|
|
||||||
if (replymgs.status == RPC_SUCCESS)
|
if (replymgs.status == RPC_SUCCESS)
|
||||||
{
|
{
|
||||||
fvdbg("RPC_SUCCESS\n");
|
fvdbg("RPC_SUCCESS\n");
|
||||||
}
|
}
|
||||||
else if (replymgs.status == RPC_PROGMISMATCH)
|
else if (replymgs.status == RPC_PROGMISMATCH)
|
||||||
{
|
{
|
||||||
/*replymgs.stat.mismatch_info.low =
|
|
||||||
fxdr_unsigned(uint32_t, replyheader.stat.mismatch_info.low);
|
|
||||||
replymgs.stat.mismatch_info.high =
|
|
||||||
fxdr_unsigned(uint32_t, replyheader.stat.mismatch_info.high);*/
|
|
||||||
|
|
||||||
fdbg("RPC_MSGACCEPTED: RPC_PROGMISMATCH error\n");
|
fdbg("RPC_MSGACCEPTED: RPC_PROGMISMATCH error\n");
|
||||||
error = EOPNOTSUPP;
|
error = EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
@@ -2123,9 +2117,7 @@ void rpcclnt_timer(void *arg, struct rpc_call *call)
|
|||||||
|
|
||||||
// rpcclnt_timer_handle = timeout(rpcclnt_timer, NULL, rpcclnt_ticks);
|
// rpcclnt_timer_handle = timeout(rpcclnt_timer, NULL, rpcclnt_ticks);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef COMP
|
|
||||||
int rpcclnt_cancelreqs(struct rpcclnt *rpc)
|
int rpcclnt_cancelreqs(struct rpcclnt *rpc)
|
||||||
{
|
{
|
||||||
struct rpctask *task;
|
struct rpctask *task;
|
||||||
|
|||||||
Reference in New Issue
Block a user