Prechádzať zdrojové kódy

update NFSv3.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@727 bbd45198-f89e-11dd-88c7-29a3b14d5316
bernard.xiong@gmail.com 15 rokov pred
rodič
commit
9c7ed22d04

+ 19 - 0
components/dfs/SConscript

@@ -48,6 +48,21 @@ filesystems/yaffs2/yaffs_checkptrw.c
 filesystems/yaffs2/yaffs_qsort.c
 """)
 
+nfs = Split('''
+filesystems/nfs/mount_clnt.c
+filesystems/nfs/mount_xdr.c
+filesystems/nfs/nfs_clnt.c
+filesystems/nfs/nfs_xdr.c
+filesystems/nfs/dfs_nfs.c
+filesystems/nfs/rpc/auth_none.c
+filesystems/nfs/rpc/clnt_generic.c
+filesystems/nfs/rpc/clnt_udp.c
+filesystems/nfs/rpc/rpc_prot.c
+filesystems/nfs/rpc/pmap.c
+filesystems/nfs/rpc/xdr.c
+filesystems/nfs/rpc/xdr_mem.c
+''')
+
 src_local = dfs
 # The set of source files associated with this SConscript file.
 path = [RTT_ROOT + '/components/dfs', RTT_ROOT + '/components/dfs/include']
@@ -62,6 +77,10 @@ if 'RT_DFS_ELM_USE_LFN' in dir(rtconfig) and rtconfig.RT_DFS_ELM_USE_LFN:
 if 'RT_USING_DFS_ELMFAT' in dir(rtconfig) and rtconfig.RT_USING_DFS_ELMFAT:
     src_local = src_local + elmfat
 
+if 'RT_USING_DFS_NFS' in dir(rtconfig) and rtconfig.RT_USING_DFS_NFS:
+    src_local = src_local + nfs
+    path = path + [RTT_ROOT + '/components/dfs/filesystems/nfs']
+
 # group definitions
 group = {}
 group['name'] = 'Filesystem'

+ 0 - 40
components/dfs/filesystems/nfs/SConscript

@@ -1,40 +0,0 @@
-Import('env')
-Import('projects')
-Import('RTT_ROOT')
-Import('rtconfig')
-
-src = Split('''
-mount_clnt.c
-mount_xdr.c
-nfs_clnt.c
-nfs_xdr.c
-dfs_nfs.c
-rpc/auth_none.c
-rpc/clnt_generic.c
-rpc/clnt_udp.c
-rpc/rpc_prot.c
-rpc/pmap.c
-rpc/xdr.c
-rpc/xdr_mem.c
-''')
-
-# group definitions
-group = {}
-group['name'] = 'nfsclient'
-group['src'] = File(src) #Glob('*.c')
-group['CCFLAGS'] = ''
-group['CPPPATH'] = [RTT_ROOT + '/components/dfs/filesystems/nfs']
-group['CPPDEFINES'] = ''
-group['LINKFLAGS'] = ''
-
-# add group to project list
-projects.append(group)
-
-env.Append(CCFLAGS = group['CCFLAGS'])
-env.Append(CPPPATH = group['CPPPATH'])
-env.Append(CPPDEFINES = group['CPPDEFINES'])
-env.Append(LINKFLAGS = group['LINKFLAGS'])
-
-objs = env.Object(group['src'])
-
-Return('objs')

+ 138 - 71
components/dfs/filesystems/nfs/dfs_nfs.c

@@ -3,7 +3,6 @@
 #include <dfs_fs.h>
 #include <dfs_def.h>
 
-#ifdef RT_USING_LWIP /* NFSv3 must use lwip as network protocol */
 #include <rpc/rpc.h>
 
 #include "mount.h"
@@ -17,6 +16,7 @@ struct nfs_file
 	size_t offset;		/* current offset */
 
 	size_t size;		/* total size */
+	bool_t eof;			/* end of file */
 };
 
 struct nfs_dir
@@ -253,6 +253,43 @@ static size_t nfs_get_filesize(struct nfs_filesystem* nfs, nfs_fh3 *handle)
 	return size;
 }
 
+rt_bool_t nfs_is_directory(struct nfs_filesystem* nfs, const char* name)
+{
+	GETATTR3args args;
+	GETATTR3res res;
+	fattr3 *info;
+	nfs_fh3 *handle;
+	rt_bool_t result;
+
+	result = RT_FALSE;
+	handle = get_handle(nfs, name);
+	if(handle == RT_NULL) return RT_FALSE;
+
+	args.object = *handle;
+
+	memset(&res, '\0', sizeof(res));
+
+	if (nfsproc3_getattr_3(args, &res, nfs->nfs_client)!=RPC_SUCCESS)
+	{
+		rt_kprintf("GetAttr failed\n");
+		return RT_FALSE;
+	}
+	else if(res.status!=NFS3_OK)
+	{
+		rt_kprintf("Getattr failed: %d\n", res.status);
+		return RT_FALSE;
+	}
+
+	info=&res.GETATTR3res_u.resok.obj_attributes;
+
+	if (info->type == NFS3DIR) result = RT_TRUE;
+
+	xdr_free((xdrproc_t)xdr_GETATTR3res, (char *)&res);
+	xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle);
+
+	return result;
+}
+
 int nfs_create(struct nfs_filesystem* nfs, const char *name, mode_t mode)
 {
 	CREATE3args args;
@@ -489,12 +526,15 @@ int nfs_read(struct dfs_fd* file, void *buf, rt_size_t count)
 	if(nfs->nfs_client==RT_NULL)
 		return -1;
 
+	/* end of file */
+	if (fd->eof == TRUE) return 0;
+
 	args.file=fd->handle;
 	args.offset=fd->offset;
 	args.count=count;
 
 	memset(&res, 0, sizeof(res));
-	if(nfsproc3_read_3(args, &res, nfs->nfs_client)!=RPC_SUCCESS)
+	if(nfsproc3_read_3(args, &res, nfs->nfs_client) != RPC_SUCCESS)
 	{
 		rt_kprintf("Read failed\n");
 		bytes = 0;
@@ -509,6 +549,7 @@ int nfs_read(struct dfs_fd* file, void *buf, rt_size_t count)
 		if(res.READ3res_u.resok.eof)
 		{
 			/* something should probably be here */
+			fd->eof = TRUE;
 		}
 		bytes=res.READ3res_u.resok.count;
 		fd->offset += bytes;
@@ -659,6 +700,7 @@ int nfs_open(struct dfs_fd* file)
 		/* get size of file */
 		fp->size = nfs_get_filesize(nfs, handle);
 		fp->offset=0;
+		fp->eof = FALSE;
 
 		copy_handle(&fp->handle, handle);
 		xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle);
@@ -706,7 +748,7 @@ int nfs_stat(struct dfs_filesystem* fs, const char *path, struct dfs_stat *st)
 		return -1;
 	}
 
-	info=&res.GETATTR3res_u.resok.obj_attributes;
+	info = &res.GETATTR3res_u.resok.obj_attributes;
 
 	st->st_dev   = 0;
 
@@ -804,82 +846,79 @@ char *nfs_readdir(struct nfs_filesystem* nfs, nfs_dir *dir)
 
 int nfs_unlink(struct dfs_filesystem* fs, const char* path)
 {
-	REMOVE3args args;
-	REMOVE3res res;
-	int ret=0;
-	nfs_fh3 *handle;
+	int ret = 0;
 	struct nfs_filesystem* nfs;
 
 	RT_ASSERT(fs != RT_NULL);
 	RT_ASSERT(fs->data != RT_NULL);
 	nfs = (struct nfs_filesystem *)fs->data;
 
-	if(nfs->nfs_client==RT_NULL)
-		return -1;
+	if (nfs_is_directory(nfs, path) == RT_FALSE)
+	{
+		/* remove file */
+		REMOVE3args args;
+		REMOVE3res res;
+		nfs_fh3 *handle;
 
-	handle = get_dir_handle(nfs, path);
-	if(handle == RT_NULL)
-		return -1;
+		handle = get_dir_handle(nfs, path);
+		if(handle == RT_NULL) return -1;
 
-	args.object.dir=*handle;
-	args.object.name=strrchr(path, '/');
-	if(args.object.name==RT_NULL)
-	{
-		args.object.name=(char *)path;
-	}
+		args.object.dir=*handle;
+		args.object.name=strrchr(path, '/');
+		if(args.object.name==RT_NULL)
+		{
+			args.object.name=(char *)path;
+		}
 
-	memset(&res, 0, sizeof(res));
+		memset(&res, 0, sizeof(res));
 
-	if(nfsproc3_remove_3(args, &res, nfs->nfs_client)!=RPC_SUCCESS)
-	{
-		rt_kprintf("Remove failed\n");
-		ret=-1;
+		if(nfsproc3_remove_3(args, &res, nfs->nfs_client)!=RPC_SUCCESS)
+		{
+			rt_kprintf("Remove failed\n");
+			ret=-1;
+		}
+		else if(res.status!=NFS3_OK)
+		{
+			rt_kprintf("Remove failed: %d\n", res.status);
+			ret=-1;
+		}
+		xdr_free((xdrproc_t)xdr_REMOVE3res, (char *)&res);
+		xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle);
 	}
-	else if(res.status!=NFS3_OK)
+	else
 	{
-		rt_kprintf("Remove failed: %d\n", res.status);
-		ret=-1;
-	}
-	xdr_free((xdrproc_t)xdr_REMOVE3res, (char *)&res);
-	xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle);
-	return ret;
-}
-
-int nfs_rmdir(struct nfs_filesystem* nfs, const char *name)
-{
-	RMDIR3args args;
-	RMDIR3res res;
-	int ret=0;
-	nfs_fh3 *handle;
+		/* remove directory */
+		RMDIR3args args;
+		RMDIR3res res;
+		nfs_fh3 *handle;
 
-	if(nfs->nfs_client==RT_NULL)
-		return -1;
+		handle=get_dir_handle(nfs, path);
+		if(handle==RT_NULL) return -1;
 
-	handle=get_dir_handle(nfs, name);
-	if(handle==RT_NULL)
-		return -1;
+		args.object.dir=*handle;
+		args.object.name=strrchr(path, '/');
+		if(args.object.name==RT_NULL)
+		{
+			args.object.name=(char *)path;
+		}
 
-	args.object.dir=*handle;
-	args.object.name=strrchr(name, '/');
-	if(args.object.name==RT_NULL)
-	{
-		args.object.name=(char *)name;
-	}
+		memset(&res, 0, sizeof(res));
 
-	memset(&res, 0, sizeof(res));
+		if(nfsproc3_rmdir_3(args, &res, nfs->nfs_client)!=RPC_SUCCESS)
+		{
+			rt_kprintf("Rmdir failed\n");
+			ret = -1;
+		}
+		else if(res.status!=NFS3_OK)
+		{
+			rt_kprintf("Rmdir failed: %d\n", res.status);
+			ret = -1;
+		}
 
-	if(nfsproc3_rmdir_3(args, &res, nfs->nfs_client)!=RPC_SUCCESS)
-	{
-		rt_kprintf("Rmdir failed\n");
-		ret = -1;
-	}
-	else if(res.status!=NFS3_OK)
-	{
-		rt_kprintf("Rmdir failed: %d\n", res.status);
-		ret = -1;
+		xdr_free((xdrproc_t)xdr_RMDIR3res, (char *)&res);
+		xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle);
 	}
-	xdr_free((xdrproc_t)xdr_RMDIR3res, (char *)&res);
-	xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle);
+
 	return ret;
 }
 
@@ -938,7 +977,44 @@ int nfs_rename(struct dfs_filesystem* fs, const char *src, const char *dest)
 
 int nfs_getdents(struct dfs_fd* file, struct dfs_dirent* dirp, rt_uint32_t count)
 {
-	return 0;
+	nfs_dir *dir;
+	rt_uint32_t index;
+	struct dfs_dirent* d;
+	struct nfs_filesystem* nfs;
+	char *name;
+
+	dir = (nfs_dir *)(file->data);
+	RT_ASSERT(dir != RT_NULL);
+	RT_ASSERT(file->fs != RT_NULL);
+	RT_ASSERT(file->fs->data != RT_NULL);
+	nfs = (struct nfs_filesystem *)file->fs->data;
+
+	/* make integer count */
+	count = (count / sizeof(struct dfs_dirent)) * sizeof(struct dfs_dirent);
+	if ( count == 0 ) return -DFS_STATUS_EINVAL;
+
+	index = 0;
+	while (1)
+	{
+		char *fn;
+
+		d = dirp + index;
+
+		name = nfs_readdir(nfs, dir);
+		if (name == RT_NULL) break;
+
+		d->d_type &= DFS_DT_REG;
+
+		d->d_namlen = rt_strlen(name);
+		d->d_reclen = (rt_uint16_t)sizeof(struct dfs_dirent);
+		rt_strncpy(d->d_name, name, rt_strlen(name) + 1);
+
+		index ++;
+		if ( index * sizeof(struct dfs_dirent) >= count )
+			break;
+	}
+
+	return index * sizeof(struct dfs_dirent);
 }
 
 static struct dfs_filesystem_operation _nfs;
@@ -964,12 +1040,3 @@ int nfs_init(void)
 
 	return RT_EOK;
 }
-
-#include <finsh.h>
-void nfs_test(char* host)
-{
-	dfs_mount(RT_NULL, "/nfs", "nfs", 0, (void*)host);
-}
-FINSH_FUNCTION_EXPORT(nfs_test, test nfs mount);
-
-#endif

+ 14 - 13
components/dfs/filesystems/nfs/rpc/clnt_udp.c

@@ -200,8 +200,7 @@ CLIENT *clntudp_create(struct sockaddr_in *raddr,
 							  UDPMSGSIZE, UDPMSGSIZE));
 }
 
-static enum clnt_stat
-clntudp_call(CLIENT *cl, unsigned long proc, 
+static enum clnt_stat clntudp_call(CLIENT *cl, unsigned long proc, 
 	xdrproc_t xargs, char* argsp, 
 	xdrproc_t xresults, char* resultsp, 
 	struct timeval utimeout)
@@ -210,7 +209,6 @@ clntudp_call(CLIENT *cl, unsigned long proc,
 	register XDR *xdrs;
 	register int outlen;
 	register int inlen;
-	struct timeval singlewait;
 	socklen_t fromlen;
 
 	struct sockaddr_in from;
@@ -223,10 +221,12 @@ call_again:
 	xdrs = &(cu->cu_outxdrs);
 	xdrs->x_op = XDR_ENCODE;
 	XDR_SETPOS(xdrs, cu->cu_xdrpos);
+
 	/*
 	 * the transaction is the first thing in the out buffer
 	 */
-	(*(uint32_t *) (cu->cu_outbuf))++;
+	(*(unsigned long *) (cu->cu_outbuf))++;
+
 	if ((!XDR_PUTLONG(xdrs, (long *) &proc)) ||
 			(!AUTH_MARSHALL(cl->cl_auth, xdrs)) || (!(*xargs) (xdrs, argsp)))
 		return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
@@ -258,9 +258,6 @@ send_again:
 		inlen = recvfrom(cu->cu_sock, cu->cu_inbuf,
 						 (int) cu->cu_recvsz, 0,
 						 (struct sockaddr *) &from, &fromlen);
-
-		if (inlen <= 0)
-			rt_kprintf("recv error: len %d, errno %d\n", inlen, lwip_get_error(cu->cu_sock));
 	}while (inlen < 0 && errno == EINTR);
 
 	if (inlen < 4)
@@ -296,8 +293,7 @@ send_again:
 			if (reply_msg.acpted_rply.ar_verf.oa_base != NULL)
 			{
 				xdrs->x_op = XDR_FREE;
-				(void) xdr_opaque_auth(xdrs,
-									   &(reply_msg.acpted_rply.ar_verf));
+				(void) xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf));
 			}
 		} /* end successful completion */
 		else
@@ -308,7 +304,7 @@ send_again:
 				nrefreshes--;
 				goto call_again;
 			}
-		}						/* end of unsuccessful completion */
+		} /* end of unsuccessful completion */
 	} /* end of valid reply message */
 	else
 	{
@@ -345,11 +341,16 @@ static bool_t clntudp_control(CLIENT *cl, int request, char *info)
 	switch (request)
 	{
 	case CLSET_TIMEOUT:
+		{
+		int mtimeout;
+
 		cu->cu_total = *(struct timeval *) info;
-		
-		/* set socket option */
-		setsockopt(cu->cu_sock, SOL_SOCKET, SO_RCVTIMEO, &cu->cu_total, sizeof(cu->cu_total));
+		mtimeout = ((cu->cu_total.tv_sec * 1000) + ((cu->cu_total.tv_usec + 500)/1000));
 
+		/* set socket option, note: lwip only support msecond timeout */
+		setsockopt(cu->cu_sock, SOL_SOCKET, SO_RCVTIMEO, 
+			&mtimeout, sizeof(mtimeout));
+		}
 		break;
 	case CLGET_TIMEOUT:
 		*(struct timeval *) info = cu->cu_total;

+ 3 - 1
components/dfs/filesystems/nfs/rpc/types.h

@@ -41,7 +41,6 @@
 typedef unsigned int u_int;
 typedef unsigned char u_char;
 typedef unsigned long u_long;
-typedef rt_int32_t  ssize_t;
 
 typedef rt_int8_t   int8_t;
 typedef rt_uint8_t  uint8_t;
@@ -56,8 +55,11 @@ typedef unsigned long long uint64_t;
 typedef int bool_t;
 typedef int enum_t;
 
+#ifndef RT_USING_NEWLIB
+typedef rt_int32_t  ssize_t;
 typedef unsigned long mode_t;
 typedef unsigned long dev_t;
+#endif
 
 /* This needs to be changed to uint32_t in the future */
 typedef unsigned long rpcprog_t;

+ 2 - 1
components/dfs/src/dfs_fs.c

@@ -378,7 +378,8 @@ int dfs_unmount(const char *specialfile)
     }
 
     /* close device, but do not check the status of device */
-    rt_device_close(fs->dev_id);
+	if (fs->dev_id != RT_NULL)
+	    rt_device_close(fs->dev_id);
 
     /* clear this filesystem table entry */
     rt_memset(fs, 0, sizeof(struct dfs_filesystem));