diff --git a/components/dfs/SConscript b/components/dfs/SConscript index d647c5f3d..d598c5110 100644 --- a/components/dfs/SConscript +++ b/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' diff --git a/components/dfs/filesystems/nfs/SConscript b/components/dfs/filesystems/nfs/SConscript deleted file mode 100644 index d0f671806..000000000 --- a/components/dfs/filesystems/nfs/SConscript +++ /dev/null @@ -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') diff --git a/components/dfs/filesystems/nfs/dfs_nfs.c b/components/dfs/filesystems/nfs/dfs_nfs.c index 8aca46ec1..dd52aca7e 100644 --- a/components/dfs/filesystems/nfs/dfs_nfs.c +++ b/components/dfs/filesystems/nfs/dfs_nfs.c @@ -3,7 +3,6 @@ #include #include -#ifdef RT_USING_LWIP /* NFSv3 must use lwip as network protocol */ #include #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; - - 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) + if (nfs_is_directory(nfs, path) == RT_FALSE) { - args.object.name=(char *)path; + /* remove file */ + REMOVE3args args; + REMOVE3res res; + nfs_fh3 *handle; + + 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; + } + + memset(&res, 0, sizeof(res)); + + 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 + { + /* remove directory */ + RMDIR3args args; + RMDIR3res res; + nfs_fh3 *handle; + + 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; + } + + 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; + } + + xdr_free((xdrproc_t)xdr_RMDIR3res, (char *)&res); + xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle); } - memset(&res, 0, sizeof(res)); - - 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); - return ret; -} - -int nfs_rmdir(struct nfs_filesystem* nfs, const char *name) -{ - RMDIR3args args; - RMDIR3res res; - int ret=0; - nfs_fh3 *handle; - - if(nfs->nfs_client==RT_NULL) - return -1; - - handle=get_dir_handle(nfs, name); - if(handle==RT_NULL) - return -1; - - 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)); - - 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); 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 -void nfs_test(char* host) -{ - dfs_mount(RT_NULL, "/nfs", "nfs", 0, (void*)host); -} -FINSH_FUNCTION_EXPORT(nfs_test, test nfs mount); - -#endif diff --git a/components/dfs/filesystems/nfs/rpc/clnt_udp.c b/components/dfs/filesystems/nfs/rpc/clnt_udp.c index 177e61acf..e161c1c07 100644 --- a/components/dfs/filesystems/nfs/rpc/clnt_udp.c +++ b/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: - cu->cu_total = *(struct timeval *) info; - - /* set socket option */ - setsockopt(cu->cu_sock, SOL_SOCKET, SO_RCVTIMEO, &cu->cu_total, sizeof(cu->cu_total)); + { + int mtimeout; + cu->cu_total = *(struct timeval *) info; + 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; diff --git a/components/dfs/filesystems/nfs/rpc/types.h b/components/dfs/filesystems/nfs/rpc/types.h index b4d63693e..fea5274fd 100644 --- a/components/dfs/filesystems/nfs/rpc/types.h +++ b/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; diff --git a/components/dfs/src/dfs_fs.c b/components/dfs/src/dfs_fs.c index 9745ea0c4..926a98229 100644 --- a/components/dfs/src/dfs_fs.c +++ b/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));