xref: /nrf52832-nimble/rt-thread/components/dfs/filesystems/nfs/dfs_nfs.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero  * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero  *
4*10465441SEvalZero  * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero  *
6*10465441SEvalZero  * Change Logs:
7*10465441SEvalZero  * Date           Author       Notes
8*10465441SEvalZero  */
9*10465441SEvalZero 
10*10465441SEvalZero #include <stdio.h>
11*10465441SEvalZero #include <rtthread.h>
12*10465441SEvalZero #include <dfs_fs.h>
13*10465441SEvalZero #include <dfs.h>
14*10465441SEvalZero #include <dfs_file.h>
15*10465441SEvalZero 
16*10465441SEvalZero #include <rpc/rpc.h>
17*10465441SEvalZero 
18*10465441SEvalZero #include "mount.h"
19*10465441SEvalZero #include "nfs.h"
20*10465441SEvalZero 
21*10465441SEvalZero #define NAME_MAX    64
22*10465441SEvalZero #define DFS_NFS_MAX_MTU  1024
23*10465441SEvalZero 
24*10465441SEvalZero #ifdef _WIN32
25*10465441SEvalZero #define strtok_r strtok_s
26*10465441SEvalZero #endif
27*10465441SEvalZero 
28*10465441SEvalZero struct nfs_file
29*10465441SEvalZero {
30*10465441SEvalZero     nfs_fh3 handle;     /* handle */
31*10465441SEvalZero     size_t offset;      /* current offset */
32*10465441SEvalZero 
33*10465441SEvalZero     size_t size;        /* total size */
34*10465441SEvalZero     bool_t eof;         /* end of file */
35*10465441SEvalZero };
36*10465441SEvalZero 
37*10465441SEvalZero struct nfs_dir
38*10465441SEvalZero {
39*10465441SEvalZero     nfs_fh3 handle;
40*10465441SEvalZero     cookie3 cookie;
41*10465441SEvalZero     cookieverf3 cookieverf;
42*10465441SEvalZero     entry3 *entry;
43*10465441SEvalZero     bool_t eof;
44*10465441SEvalZero     READDIR3res res;
45*10465441SEvalZero };
46*10465441SEvalZero 
47*10465441SEvalZero #define HOST_LENGTH         32
48*10465441SEvalZero #define EXPORT_PATH_LENGTH  32
49*10465441SEvalZero 
50*10465441SEvalZero struct nfs_filesystem
51*10465441SEvalZero {
52*10465441SEvalZero     nfs_fh3 root_handle;
53*10465441SEvalZero     nfs_fh3 current_handle;
54*10465441SEvalZero     CLIENT *nfs_client;
55*10465441SEvalZero     CLIENT *mount_client;
56*10465441SEvalZero 
57*10465441SEvalZero     char host[HOST_LENGTH];
58*10465441SEvalZero     char export[EXPORT_PATH_LENGTH];
59*10465441SEvalZero     void *data;             /* nfs_file or nfs_dir */
60*10465441SEvalZero };
61*10465441SEvalZero 
62*10465441SEvalZero typedef struct nfs_filesystem nfs_filesystem;
63*10465441SEvalZero typedef struct nfs_file nfs_file;
64*10465441SEvalZero typedef struct nfs_dir nfs_dir;
65*10465441SEvalZero 
66*10465441SEvalZero nfs_dir *nfs_opendir(nfs_filesystem *nfs, const char *path);
67*10465441SEvalZero 
nfs_parse_host_export(const char * host_export,char * host,size_t host_len,char * export,size_t export_len)68*10465441SEvalZero static int nfs_parse_host_export(const char *host_export,
69*10465441SEvalZero                                  char       *host,
70*10465441SEvalZero                                  size_t      host_len,
71*10465441SEvalZero                                  char       *export,
72*10465441SEvalZero                                  size_t      export_len)
73*10465441SEvalZero {
74*10465441SEvalZero     int index;
75*10465441SEvalZero 
76*10465441SEvalZero     for (index = 0; index < host_len; index ++)
77*10465441SEvalZero     {
78*10465441SEvalZero         /* it's end of string, failed */
79*10465441SEvalZero         if (host_export[index] == 0)
80*10465441SEvalZero             return -1;
81*10465441SEvalZero 
82*10465441SEvalZero         /* copy to host buffer */
83*10465441SEvalZero         if (host_export[index] != ':')
84*10465441SEvalZero             host[index] = host_export[index];
85*10465441SEvalZero         else
86*10465441SEvalZero             break;
87*10465441SEvalZero     }
88*10465441SEvalZero 
89*10465441SEvalZero     /* host buffer is not enough, failed */
90*10465441SEvalZero     if (index == host_len)
91*10465441SEvalZero         return -1;
92*10465441SEvalZero 
93*10465441SEvalZero     /* make NULL */
94*10465441SEvalZero     host_len = index;
95*10465441SEvalZero     host[host_len] = '\0';
96*10465441SEvalZero 
97*10465441SEvalZero     host_len ++;
98*10465441SEvalZero 
99*10465441SEvalZero     /* copy export path */
100*10465441SEvalZero     for (index = host_len; index < host_len + export_len; index ++)
101*10465441SEvalZero     {
102*10465441SEvalZero         if (host_export[index] == 0)
103*10465441SEvalZero         {
104*10465441SEvalZero             export[index - host_len] = '\0';
105*10465441SEvalZero 
106*10465441SEvalZero             return 0;
107*10465441SEvalZero         }
108*10465441SEvalZero 
109*10465441SEvalZero         export[index - host_len] = host_export[index];
110*10465441SEvalZero     }
111*10465441SEvalZero 
112*10465441SEvalZero     return -1;
113*10465441SEvalZero }
114*10465441SEvalZero 
copy_handle(nfs_fh3 * dest,const nfs_fh3 * source)115*10465441SEvalZero static void copy_handle(nfs_fh3 *dest, const nfs_fh3 *source)
116*10465441SEvalZero {
117*10465441SEvalZero     dest->data.data_len = source->data.data_len;
118*10465441SEvalZero     dest->data.data_val = rt_malloc(dest->data.data_len);
119*10465441SEvalZero     if (dest->data.data_val == NULL)
120*10465441SEvalZero     {
121*10465441SEvalZero         dest->data.data_len = 0;
122*10465441SEvalZero 
123*10465441SEvalZero         return;
124*10465441SEvalZero     }
125*10465441SEvalZero 
126*10465441SEvalZero     memcpy(dest->data.data_val, source->data.data_val, dest->data.data_len);
127*10465441SEvalZero }
128*10465441SEvalZero 
get_handle(nfs_filesystem * nfs,const char * name)129*10465441SEvalZero static nfs_fh3 *get_handle(nfs_filesystem *nfs, const char *name)
130*10465441SEvalZero {
131*10465441SEvalZero     nfs_fh3 *handle = NULL;
132*10465441SEvalZero     char *file;
133*10465441SEvalZero     char *path;
134*10465441SEvalZero     char *init;
135*10465441SEvalZero 
136*10465441SEvalZero     init = path = rt_malloc(strlen(name)+1);
137*10465441SEvalZero     if (init == NULL)
138*10465441SEvalZero         return NULL;
139*10465441SEvalZero 
140*10465441SEvalZero     memcpy(init, name, strlen(name)+1);
141*10465441SEvalZero 
142*10465441SEvalZero     handle = rt_malloc(sizeof(nfs_fh3));
143*10465441SEvalZero     if (handle == NULL)
144*10465441SEvalZero     {
145*10465441SEvalZero         rt_free(init);
146*10465441SEvalZero 
147*10465441SEvalZero         return NULL;
148*10465441SEvalZero     }
149*10465441SEvalZero 
150*10465441SEvalZero     if (path[0] == '/')
151*10465441SEvalZero     {
152*10465441SEvalZero         path ++;
153*10465441SEvalZero         copy_handle(handle, &nfs->root_handle);
154*10465441SEvalZero     }
155*10465441SEvalZero     else
156*10465441SEvalZero     {
157*10465441SEvalZero         copy_handle(handle, &nfs->current_handle);
158*10465441SEvalZero     }
159*10465441SEvalZero 
160*10465441SEvalZero     while ((file = strtok_r(NULL, "/", &path)) != NULL)
161*10465441SEvalZero     {
162*10465441SEvalZero         LOOKUP3args args;
163*10465441SEvalZero         LOOKUP3res res;
164*10465441SEvalZero         memset(&res, 0, sizeof(res));
165*10465441SEvalZero         copy_handle(&args.what.dir, handle);
166*10465441SEvalZero         xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle);
167*10465441SEvalZero         args.what.name = file;
168*10465441SEvalZero 
169*10465441SEvalZero         if (nfsproc3_lookup_3(args, &res, nfs->nfs_client) != RPC_SUCCESS)
170*10465441SEvalZero         {
171*10465441SEvalZero             rt_kprintf("Lookup failed\n");
172*10465441SEvalZero             rt_free(init);
173*10465441SEvalZero             rt_free(handle);
174*10465441SEvalZero             xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)&args.what.dir);
175*10465441SEvalZero 
176*10465441SEvalZero             return NULL;
177*10465441SEvalZero         }
178*10465441SEvalZero         else if (res.status != NFS3_OK)
179*10465441SEvalZero         {
180*10465441SEvalZero             rt_kprintf("Lookup failed: %d\n", res.status);
181*10465441SEvalZero             rt_free(init);
182*10465441SEvalZero             rt_free(handle);
183*10465441SEvalZero             xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)&args.what.dir);
184*10465441SEvalZero             xdr_free((xdrproc_t)xdr_LOOKUP3res, (char *)&res);
185*10465441SEvalZero 
186*10465441SEvalZero             return NULL;
187*10465441SEvalZero         }
188*10465441SEvalZero         copy_handle(handle, &res.LOOKUP3res_u.resok.object);
189*10465441SEvalZero         xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)&args.what.dir);
190*10465441SEvalZero         xdr_free((xdrproc_t)xdr_LOOKUP3res, (char *)&res);
191*10465441SEvalZero     }
192*10465441SEvalZero 
193*10465441SEvalZero     rt_free(init);
194*10465441SEvalZero 
195*10465441SEvalZero     return handle;
196*10465441SEvalZero }
197*10465441SEvalZero 
get_dir_handle(nfs_filesystem * nfs,const char * name)198*10465441SEvalZero static nfs_fh3 *get_dir_handle(nfs_filesystem *nfs, const char *name)
199*10465441SEvalZero {
200*10465441SEvalZero     nfs_fh3 *handle = NULL;
201*10465441SEvalZero     char *file;
202*10465441SEvalZero     char *path;
203*10465441SEvalZero     char *init;
204*10465441SEvalZero 
205*10465441SEvalZero     init = path = rt_malloc(strlen(name)+1);
206*10465441SEvalZero     if (init == NULL)
207*10465441SEvalZero         return NULL;
208*10465441SEvalZero     memcpy(init, name, strlen(name)+1);
209*10465441SEvalZero 
210*10465441SEvalZero     handle = rt_malloc(sizeof(nfs_fh3));
211*10465441SEvalZero     if (handle == NULL)
212*10465441SEvalZero     {
213*10465441SEvalZero         rt_free(init);
214*10465441SEvalZero 
215*10465441SEvalZero         return NULL;
216*10465441SEvalZero     }
217*10465441SEvalZero 
218*10465441SEvalZero     if (path[0] == '/')
219*10465441SEvalZero     {
220*10465441SEvalZero         path ++;
221*10465441SEvalZero         copy_handle(handle, &nfs->root_handle);
222*10465441SEvalZero     }
223*10465441SEvalZero     else
224*10465441SEvalZero     {
225*10465441SEvalZero         copy_handle(handle, &nfs->current_handle);
226*10465441SEvalZero     }
227*10465441SEvalZero 
228*10465441SEvalZero     while ((file = strtok_r(NULL, "/", &path)) != NULL && path[0] != 0)
229*10465441SEvalZero     {
230*10465441SEvalZero         LOOKUP3args args;
231*10465441SEvalZero         LOOKUP3res res;
232*10465441SEvalZero         memset(&res, 0, sizeof(res));
233*10465441SEvalZero         copy_handle(&args.what.dir, handle);
234*10465441SEvalZero         xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle);
235*10465441SEvalZero         args.what.name = file;
236*10465441SEvalZero 
237*10465441SEvalZero         if (nfsproc3_lookup_3(args, &res, nfs->nfs_client) != RPC_SUCCESS)
238*10465441SEvalZero         {
239*10465441SEvalZero             rt_kprintf("Lookup failed\n");
240*10465441SEvalZero             rt_free(init);
241*10465441SEvalZero             rt_free(handle);
242*10465441SEvalZero             xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)&args.what.dir);
243*10465441SEvalZero 
244*10465441SEvalZero             return NULL;
245*10465441SEvalZero         }
246*10465441SEvalZero         else if (res.status != NFS3_OK)
247*10465441SEvalZero         {
248*10465441SEvalZero             rt_kprintf("Lookup failed: %d\n", res.status);
249*10465441SEvalZero             rt_free(init);
250*10465441SEvalZero             rt_free(handle);
251*10465441SEvalZero             xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)&args.what.dir);
252*10465441SEvalZero             xdr_free((xdrproc_t)xdr_LOOKUP3res, (char *)&res);
253*10465441SEvalZero 
254*10465441SEvalZero             return NULL;
255*10465441SEvalZero         }
256*10465441SEvalZero         copy_handle(handle, &res.LOOKUP3res_u.resok.object);
257*10465441SEvalZero         xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)&args.what.dir);
258*10465441SEvalZero         xdr_free((xdrproc_t)xdr_LOOKUP3res, (char *)&res);
259*10465441SEvalZero     }
260*10465441SEvalZero 
261*10465441SEvalZero     rt_free(init);
262*10465441SEvalZero 
263*10465441SEvalZero     return handle;
264*10465441SEvalZero }
265*10465441SEvalZero 
nfs_get_filesize(nfs_filesystem * nfs,nfs_fh3 * handle)266*10465441SEvalZero static size_t nfs_get_filesize(nfs_filesystem *nfs, nfs_fh3 *handle)
267*10465441SEvalZero {
268*10465441SEvalZero     GETATTR3args args;
269*10465441SEvalZero     GETATTR3res res;
270*10465441SEvalZero     fattr3 *info;
271*10465441SEvalZero     size_t size;
272*10465441SEvalZero 
273*10465441SEvalZero     args.object = *handle;
274*10465441SEvalZero 
275*10465441SEvalZero     memset(&res, '\0', sizeof(res));
276*10465441SEvalZero 
277*10465441SEvalZero     if ((nfsproc3_getattr_3(args, &res, nfs->nfs_client)!=RPC_SUCCESS) ||
278*10465441SEvalZero         res.status != NFS3_OK)
279*10465441SEvalZero     {
280*10465441SEvalZero         rt_kprintf("GetAttr failed: %d\n", res.status);
281*10465441SEvalZero 
282*10465441SEvalZero         return 0;
283*10465441SEvalZero     }
284*10465441SEvalZero 
285*10465441SEvalZero     info = &res.GETATTR3res_u.resok.obj_attributes;
286*10465441SEvalZero     size = info->size;
287*10465441SEvalZero     xdr_free((xdrproc_t)xdr_GETATTR3res, (char *)&res);
288*10465441SEvalZero 
289*10465441SEvalZero     return size;
290*10465441SEvalZero }
291*10465441SEvalZero 
nfs_is_directory(nfs_filesystem * nfs,const char * name)292*10465441SEvalZero rt_bool_t nfs_is_directory(nfs_filesystem *nfs, const char *name)
293*10465441SEvalZero {
294*10465441SEvalZero     GETATTR3args args;
295*10465441SEvalZero     GETATTR3res res;
296*10465441SEvalZero     fattr3 *info;
297*10465441SEvalZero     nfs_fh3 *handle;
298*10465441SEvalZero     rt_bool_t result;
299*10465441SEvalZero 
300*10465441SEvalZero     result = RT_FALSE;
301*10465441SEvalZero     handle = get_handle(nfs, name);
302*10465441SEvalZero     if (handle == NULL)
303*10465441SEvalZero         return RT_FALSE;
304*10465441SEvalZero 
305*10465441SEvalZero     args.object = *handle;
306*10465441SEvalZero 
307*10465441SEvalZero     memset(&res, '\0', sizeof(res));
308*10465441SEvalZero 
309*10465441SEvalZero     if (nfsproc3_getattr_3(args, &res, nfs->nfs_client) != RPC_SUCCESS)
310*10465441SEvalZero     {
311*10465441SEvalZero         rt_kprintf("GetAttr failed\n");
312*10465441SEvalZero 
313*10465441SEvalZero         return RT_FALSE;
314*10465441SEvalZero     }
315*10465441SEvalZero     else if (res.status != NFS3_OK)
316*10465441SEvalZero     {
317*10465441SEvalZero         rt_kprintf("Getattr failed: %d\n", res.status);
318*10465441SEvalZero 
319*10465441SEvalZero         return RT_FALSE;
320*10465441SEvalZero     }
321*10465441SEvalZero 
322*10465441SEvalZero     info=&res.GETATTR3res_u.resok.obj_attributes;
323*10465441SEvalZero 
324*10465441SEvalZero     if (info->type == NFS3DIR)
325*10465441SEvalZero         result = RT_TRUE;
326*10465441SEvalZero 
327*10465441SEvalZero     xdr_free((xdrproc_t)xdr_GETATTR3res, (char *)&res);
328*10465441SEvalZero     xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle);
329*10465441SEvalZero     rt_free(handle);
330*10465441SEvalZero 
331*10465441SEvalZero     return result;
332*10465441SEvalZero }
333*10465441SEvalZero 
nfs_create(nfs_filesystem * nfs,const char * name,mode_t mode)334*10465441SEvalZero int nfs_create(nfs_filesystem *nfs, const char *name, mode_t mode)
335*10465441SEvalZero {
336*10465441SEvalZero     CREATE3args args;
337*10465441SEvalZero     CREATE3res res;
338*10465441SEvalZero     int ret = 0;
339*10465441SEvalZero     nfs_fh3 *handle;
340*10465441SEvalZero 
341*10465441SEvalZero     if (nfs->nfs_client == NULL)
342*10465441SEvalZero     {
343*10465441SEvalZero         return -1;
344*10465441SEvalZero     }
345*10465441SEvalZero 
346*10465441SEvalZero     handle = get_dir_handle(nfs, name);
347*10465441SEvalZero     if (handle == NULL)
348*10465441SEvalZero     {
349*10465441SEvalZero         return -1;
350*10465441SEvalZero     }
351*10465441SEvalZero     args.where.dir = *handle;
352*10465441SEvalZero     args.where.name = strrchr(name, '/') + 1;
353*10465441SEvalZero     if (args.where.name == NULL)
354*10465441SEvalZero     {
355*10465441SEvalZero         args.where.name = (char *)name;
356*10465441SEvalZero     }
357*10465441SEvalZero     args.how.mode = GUARDED;
358*10465441SEvalZero 
359*10465441SEvalZero     args.how.createhow3_u.obj_attributes.mode.set_it = TRUE;
360*10465441SEvalZero     args.how.createhow3_u.obj_attributes.mode.set_mode3_u.mode = mode;
361*10465441SEvalZero     args.how.createhow3_u.obj_attributes.uid.set_it = FALSE;
362*10465441SEvalZero     args.how.createhow3_u.obj_attributes.gid.set_it = FALSE;
363*10465441SEvalZero     args.how.createhow3_u.obj_attributes.size.set_it = FALSE;
364*10465441SEvalZero     args.how.createhow3_u.obj_attributes.atime.set_it = DONT_CHANGE;
365*10465441SEvalZero     args.how.createhow3_u.obj_attributes.mtime.set_it = DONT_CHANGE;
366*10465441SEvalZero 
367*10465441SEvalZero     memset(&res, 0, sizeof(res));
368*10465441SEvalZero 
369*10465441SEvalZero     if (nfsproc3_create_3(args, &res, nfs->nfs_client) != RPC_SUCCESS)
370*10465441SEvalZero     {
371*10465441SEvalZero         rt_kprintf("Create failed\n");
372*10465441SEvalZero         ret = -1;
373*10465441SEvalZero     }
374*10465441SEvalZero     else if (res.status != NFS3_OK)
375*10465441SEvalZero     {
376*10465441SEvalZero         rt_kprintf("Create failed: %d\n", res.status);
377*10465441SEvalZero         ret = -1;
378*10465441SEvalZero     }
379*10465441SEvalZero     xdr_free((xdrproc_t)xdr_CREATE3res, (char *)&res);
380*10465441SEvalZero     xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle);
381*10465441SEvalZero     rt_free(handle);
382*10465441SEvalZero 
383*10465441SEvalZero     return ret;
384*10465441SEvalZero }
385*10465441SEvalZero 
nfs_mkdir(nfs_filesystem * nfs,const char * name,mode_t mode)386*10465441SEvalZero int nfs_mkdir(nfs_filesystem *nfs, const char *name, mode_t mode)
387*10465441SEvalZero {
388*10465441SEvalZero     MKDIR3args args;
389*10465441SEvalZero     MKDIR3res res;
390*10465441SEvalZero     int ret = 0;
391*10465441SEvalZero     nfs_fh3 *handle;
392*10465441SEvalZero 
393*10465441SEvalZero     if (nfs->nfs_client == NULL)
394*10465441SEvalZero         return -1;
395*10465441SEvalZero 
396*10465441SEvalZero     handle = get_dir_handle(nfs, name);
397*10465441SEvalZero     if (handle == NULL)
398*10465441SEvalZero         return -1;
399*10465441SEvalZero 
400*10465441SEvalZero     args.where.dir = *handle;
401*10465441SEvalZero     args.where.name = strrchr(name, '/') + 1;
402*10465441SEvalZero     if (args.where.name == NULL)
403*10465441SEvalZero     {
404*10465441SEvalZero         args.where.name = (char *)name;
405*10465441SEvalZero     }
406*10465441SEvalZero 
407*10465441SEvalZero     args.attributes.mode.set_it = TRUE;
408*10465441SEvalZero     args.attributes.mode.set_mode3_u.mode = mode;
409*10465441SEvalZero     args.attributes.uid.set_it = FALSE;
410*10465441SEvalZero     args.attributes.gid.set_it = FALSE;
411*10465441SEvalZero     args.attributes.size.set_it = FALSE;
412*10465441SEvalZero     args.attributes.atime.set_it = DONT_CHANGE;
413*10465441SEvalZero     args.attributes.mtime.set_it = DONT_CHANGE;
414*10465441SEvalZero 
415*10465441SEvalZero     memset(&res, 0, sizeof(res));
416*10465441SEvalZero 
417*10465441SEvalZero     if (nfsproc3_mkdir_3(args, &res, nfs->nfs_client) != RPC_SUCCESS)
418*10465441SEvalZero     {
419*10465441SEvalZero         rt_kprintf("Mkdir failed\n");
420*10465441SEvalZero         ret = -1;
421*10465441SEvalZero     }
422*10465441SEvalZero     else if (res.status != NFS3_OK)
423*10465441SEvalZero     {
424*10465441SEvalZero         rt_kprintf("Mkdir failed: %d\n", res.status);
425*10465441SEvalZero         ret = -1;
426*10465441SEvalZero     }
427*10465441SEvalZero     xdr_free((xdrproc_t)xdr_MKDIR3res, (char *)&res);
428*10465441SEvalZero     xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle);
429*10465441SEvalZero     rt_free(handle);
430*10465441SEvalZero 
431*10465441SEvalZero     return ret;
432*10465441SEvalZero }
433*10465441SEvalZero 
434*10465441SEvalZero /* mount(NULL, "/mnt", "nfs", 0, "192.168.1.1:/export") */
nfs_mount(struct dfs_filesystem * fs,unsigned long rwflag,const void * data)435*10465441SEvalZero int nfs_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *data)
436*10465441SEvalZero {
437*10465441SEvalZero     mountres3 res;
438*10465441SEvalZero     nfs_filesystem *nfs;
439*10465441SEvalZero 
440*10465441SEvalZero     nfs = (nfs_filesystem *)rt_malloc(sizeof(nfs_filesystem));
441*10465441SEvalZero     memset(nfs, 0, sizeof(nfs_filesystem));
442*10465441SEvalZero 
443*10465441SEvalZero     if (nfs_parse_host_export((const char *)data, nfs->host, HOST_LENGTH,
444*10465441SEvalZero         nfs->export, EXPORT_PATH_LENGTH) < 0)
445*10465441SEvalZero     {
446*10465441SEvalZero         rt_kprintf("host or export path error\n");
447*10465441SEvalZero         goto __return;
448*10465441SEvalZero     }
449*10465441SEvalZero 
450*10465441SEvalZero     nfs->mount_client=clnt_create((char *)nfs->host, MOUNT_PROGRAM, MOUNT_V3, "udp");
451*10465441SEvalZero     if (nfs->mount_client == NULL)
452*10465441SEvalZero     {
453*10465441SEvalZero         rt_kprintf("create mount client failed\n");
454*10465441SEvalZero         goto __return;
455*10465441SEvalZero     }
456*10465441SEvalZero 
457*10465441SEvalZero     memset(&res, '\0', sizeof(mountres3));
458*10465441SEvalZero     if (mountproc3_mnt_3((char *)nfs->export, &res, nfs->mount_client) != RPC_SUCCESS)
459*10465441SEvalZero     {
460*10465441SEvalZero         rt_kprintf("nfs mount failed\n");
461*10465441SEvalZero         goto __return;
462*10465441SEvalZero     }
463*10465441SEvalZero     else if (res.fhs_status != MNT3_OK)
464*10465441SEvalZero     {
465*10465441SEvalZero         rt_kprintf("nfs mount failed\n");
466*10465441SEvalZero         goto __return;
467*10465441SEvalZero     }
468*10465441SEvalZero     nfs->nfs_client=clnt_create((char *)nfs->host, NFS_PROGRAM, NFS_V3, "udp");
469*10465441SEvalZero     if (nfs->nfs_client == NULL)
470*10465441SEvalZero     {
471*10465441SEvalZero         rt_kprintf("creat nfs client failed\n");
472*10465441SEvalZero         goto __return;
473*10465441SEvalZero     }
474*10465441SEvalZero     copy_handle(&nfs->root_handle, (nfs_fh3 *)&res.mountres3_u.mountinfo.fhandle);
475*10465441SEvalZero     copy_handle(&nfs->current_handle, &nfs->root_handle);
476*10465441SEvalZero 
477*10465441SEvalZero     nfs->nfs_client->cl_auth = authnone_create();
478*10465441SEvalZero     fs->data = nfs;
479*10465441SEvalZero 
480*10465441SEvalZero     return 0;
481*10465441SEvalZero 
482*10465441SEvalZero __return:
483*10465441SEvalZero     if (nfs != NULL)
484*10465441SEvalZero     {
485*10465441SEvalZero         if (nfs->mount_client != NULL)
486*10465441SEvalZero         {
487*10465441SEvalZero             clnt_destroy(nfs->mount_client);
488*10465441SEvalZero         }
489*10465441SEvalZero         if (nfs->nfs_client != NULL)
490*10465441SEvalZero         {
491*10465441SEvalZero             if (nfs->nfs_client->cl_auth != NULL)
492*10465441SEvalZero             {
493*10465441SEvalZero                 auth_destroy(nfs->nfs_client->cl_auth);
494*10465441SEvalZero             }
495*10465441SEvalZero             clnt_destroy(nfs->nfs_client);
496*10465441SEvalZero         }
497*10465441SEvalZero         rt_free(nfs);
498*10465441SEvalZero     }
499*10465441SEvalZero 
500*10465441SEvalZero     return -1;
501*10465441SEvalZero }
502*10465441SEvalZero 
nfs_unmount(struct dfs_filesystem * fs)503*10465441SEvalZero int nfs_unmount(struct dfs_filesystem *fs)
504*10465441SEvalZero {
505*10465441SEvalZero     nfs_filesystem *nfs;
506*10465441SEvalZero 
507*10465441SEvalZero     RT_ASSERT(fs != NULL);
508*10465441SEvalZero     RT_ASSERT(fs->data != NULL);
509*10465441SEvalZero     nfs = (nfs_filesystem *)fs->data;
510*10465441SEvalZero 
511*10465441SEvalZero     if (nfs->mount_client != NULL &&
512*10465441SEvalZero         mountproc3_umnt_3((char *)nfs->export, NULL, nfs->mount_client) != RPC_SUCCESS)
513*10465441SEvalZero     {
514*10465441SEvalZero         rt_kprintf("unmount failed\n");
515*10465441SEvalZero 
516*10465441SEvalZero         return -1;
517*10465441SEvalZero     }
518*10465441SEvalZero 
519*10465441SEvalZero     /* destroy nfs client */
520*10465441SEvalZero     if (nfs->nfs_client != NULL)
521*10465441SEvalZero     {
522*10465441SEvalZero         if (nfs->nfs_client->cl_auth != NULL)
523*10465441SEvalZero         {
524*10465441SEvalZero             auth_destroy(nfs->nfs_client->cl_auth);
525*10465441SEvalZero             nfs->nfs_client->cl_auth = NULL;
526*10465441SEvalZero         }
527*10465441SEvalZero         clnt_destroy(nfs->nfs_client);
528*10465441SEvalZero         nfs->nfs_client = NULL;
529*10465441SEvalZero     }
530*10465441SEvalZero 
531*10465441SEvalZero     /* destroy mount client */
532*10465441SEvalZero     if (nfs->mount_client != NULL)
533*10465441SEvalZero     {
534*10465441SEvalZero         if (nfs->mount_client->cl_auth != NULL)
535*10465441SEvalZero         {
536*10465441SEvalZero             auth_destroy(nfs->mount_client->cl_auth);
537*10465441SEvalZero             nfs->mount_client->cl_auth = NULL;
538*10465441SEvalZero         }
539*10465441SEvalZero         clnt_destroy(nfs->mount_client);
540*10465441SEvalZero         nfs->mount_client = NULL;
541*10465441SEvalZero     }
542*10465441SEvalZero 
543*10465441SEvalZero     rt_free(nfs);
544*10465441SEvalZero     fs->data = NULL;
545*10465441SEvalZero 
546*10465441SEvalZero     return 0;
547*10465441SEvalZero }
548*10465441SEvalZero 
nfs_ioctl(struct dfs_fd * file,int cmd,void * args)549*10465441SEvalZero int nfs_ioctl(struct dfs_fd *file, int cmd, void *args)
550*10465441SEvalZero {
551*10465441SEvalZero     return -ENOSYS;
552*10465441SEvalZero }
553*10465441SEvalZero 
nfs_read(struct dfs_fd * file,void * buf,size_t count)554*10465441SEvalZero int nfs_read(struct dfs_fd *file, void *buf, size_t count)
555*10465441SEvalZero {
556*10465441SEvalZero     READ3args args;
557*10465441SEvalZero     READ3res res;
558*10465441SEvalZero     ssize_t bytes, total=0;
559*10465441SEvalZero     nfs_file *fd;
560*10465441SEvalZero     nfs_filesystem *nfs;
561*10465441SEvalZero 
562*10465441SEvalZero     if (file->type == FT_DIRECTORY)
563*10465441SEvalZero         return -EISDIR;
564*10465441SEvalZero 
565*10465441SEvalZero 
566*10465441SEvalZero     RT_ASSERT(file->data != NULL);
567*10465441SEvalZero     struct dfs_filesystem *dfs_nfs  = ((struct dfs_filesystem*)(file->data));
568*10465441SEvalZero     nfs = (struct nfs_filesystem *)(dfs_nfs->data);
569*10465441SEvalZero     fd = (nfs_file *)(nfs->data);
570*10465441SEvalZero     RT_ASSERT(fd != NULL);
571*10465441SEvalZero 
572*10465441SEvalZero     if (nfs->nfs_client == NULL)
573*10465441SEvalZero         return -1;
574*10465441SEvalZero 
575*10465441SEvalZero     /* end of file */
576*10465441SEvalZero     if (fd->eof == TRUE)
577*10465441SEvalZero         return 0;
578*10465441SEvalZero 
579*10465441SEvalZero     args.file = fd->handle;
580*10465441SEvalZero     do {
581*10465441SEvalZero         args.offset = fd->offset;
582*10465441SEvalZero         args.count = count > DFS_NFS_MAX_MTU ? DFS_NFS_MAX_MTU : count;
583*10465441SEvalZero         count -= args.count;
584*10465441SEvalZero 
585*10465441SEvalZero         memset(&res, 0, sizeof(res));
586*10465441SEvalZero         if (nfsproc3_read_3(args, &res, nfs->nfs_client) != RPC_SUCCESS)
587*10465441SEvalZero         {
588*10465441SEvalZero             rt_kprintf("Read failed\n");
589*10465441SEvalZero             total = 0;
590*10465441SEvalZero             break;
591*10465441SEvalZero         }
592*10465441SEvalZero         else if (res.status != NFS3_OK)
593*10465441SEvalZero         {
594*10465441SEvalZero             rt_kprintf("Read failed: %d\n", res.status);
595*10465441SEvalZero             total = 0;
596*10465441SEvalZero             break;
597*10465441SEvalZero         }
598*10465441SEvalZero         else
599*10465441SEvalZero         {
600*10465441SEvalZero             bytes = res.READ3res_u.resok.count;
601*10465441SEvalZero             total += bytes;
602*10465441SEvalZero             fd->offset += bytes;
603*10465441SEvalZero             /* update current position */
604*10465441SEvalZero             file->pos = fd->offset;
605*10465441SEvalZero             memcpy(buf, res.READ3res_u.resok.data.data_val, bytes);
606*10465441SEvalZero             buf = (void *)((char *)buf + args.count);
607*10465441SEvalZero             if (res.READ3res_u.resok.eof)
608*10465441SEvalZero             {
609*10465441SEvalZero                 /* something should probably be here */
610*10465441SEvalZero                 fd->eof = TRUE;
611*10465441SEvalZero                 break;
612*10465441SEvalZero             }
613*10465441SEvalZero         }
614*10465441SEvalZero         xdr_free((xdrproc_t)xdr_READ3res, (char *)&res);
615*10465441SEvalZero     } while(count > 0);
616*10465441SEvalZero 
617*10465441SEvalZero     xdr_free((xdrproc_t)xdr_READ3res, (char *)&res);
618*10465441SEvalZero 
619*10465441SEvalZero     return total;
620*10465441SEvalZero }
621*10465441SEvalZero 
nfs_write(struct dfs_fd * file,const void * buf,size_t count)622*10465441SEvalZero int nfs_write(struct dfs_fd *file, const void *buf, size_t count)
623*10465441SEvalZero {
624*10465441SEvalZero     WRITE3args args;
625*10465441SEvalZero     WRITE3res res;
626*10465441SEvalZero     ssize_t bytes, total=0;
627*10465441SEvalZero     nfs_file *fd;
628*10465441SEvalZero     nfs_filesystem *nfs;
629*10465441SEvalZero 
630*10465441SEvalZero     if (file->type == FT_DIRECTORY)
631*10465441SEvalZero         return -EISDIR;
632*10465441SEvalZero 
633*10465441SEvalZero     RT_ASSERT(file->data != NULL);
634*10465441SEvalZero     struct dfs_filesystem *dfs_nfs  = ((struct dfs_filesystem*)(file->data));
635*10465441SEvalZero     nfs = (struct nfs_filesystem *)(dfs_nfs->data);
636*10465441SEvalZero     fd = (nfs_file *)(nfs->data);
637*10465441SEvalZero     RT_ASSERT(fd != NULL);
638*10465441SEvalZero 
639*10465441SEvalZero     if (nfs->nfs_client == NULL)
640*10465441SEvalZero         return -1;
641*10465441SEvalZero 
642*10465441SEvalZero     args.file = fd->handle;
643*10465441SEvalZero     args.stable = FILE_SYNC;
644*10465441SEvalZero 
645*10465441SEvalZero     do {
646*10465441SEvalZero         args.offset = fd->offset;
647*10465441SEvalZero 
648*10465441SEvalZero         memset(&res, 0, sizeof(res));
649*10465441SEvalZero         args.data.data_val=(void *)buf;
650*10465441SEvalZero         args.count = count > DFS_NFS_MAX_MTU ? DFS_NFS_MAX_MTU : count;
651*10465441SEvalZero         args.data.data_len = args.count;
652*10465441SEvalZero         count -= args.count;
653*10465441SEvalZero         buf = (const void *)((char *)buf + args.count);
654*10465441SEvalZero 
655*10465441SEvalZero         if (nfsproc3_write_3(args, &res, nfs->nfs_client) != RPC_SUCCESS)
656*10465441SEvalZero         {
657*10465441SEvalZero             rt_kprintf("Write failed\n");
658*10465441SEvalZero             total = 0;
659*10465441SEvalZero             break;
660*10465441SEvalZero         }
661*10465441SEvalZero         else if (res.status != NFS3_OK)
662*10465441SEvalZero         {
663*10465441SEvalZero             rt_kprintf("Write failed: %d\n", res.status);
664*10465441SEvalZero             total = 0;
665*10465441SEvalZero             break;
666*10465441SEvalZero         }
667*10465441SEvalZero         else
668*10465441SEvalZero         {
669*10465441SEvalZero             bytes = res.WRITE3res_u.resok.count;
670*10465441SEvalZero             fd->offset += bytes;
671*10465441SEvalZero             total += bytes;
672*10465441SEvalZero             /* update current position */
673*10465441SEvalZero             file->pos = fd->offset;
674*10465441SEvalZero             /* update file size */
675*10465441SEvalZero             if (fd->size < fd->offset) fd->size = fd->offset;
676*10465441SEvalZero             file->size = fd->size;
677*10465441SEvalZero         }
678*10465441SEvalZero         xdr_free((xdrproc_t)xdr_WRITE3res, (char *)&res);
679*10465441SEvalZero     } while (count > 0);
680*10465441SEvalZero 
681*10465441SEvalZero     xdr_free((xdrproc_t)xdr_WRITE3res, (char *)&res);
682*10465441SEvalZero 
683*10465441SEvalZero     return total;
684*10465441SEvalZero }
685*10465441SEvalZero 
nfs_lseek(struct dfs_fd * file,off_t offset)686*10465441SEvalZero int nfs_lseek(struct dfs_fd *file, off_t offset)
687*10465441SEvalZero {
688*10465441SEvalZero     nfs_file *fd;
689*10465441SEvalZero     nfs_filesystem *nfs;
690*10465441SEvalZero 
691*10465441SEvalZero     if (file->type == FT_DIRECTORY)
692*10465441SEvalZero         return -EISDIR;
693*10465441SEvalZero 
694*10465441SEvalZero     RT_ASSERT(file->data != NULL);
695*10465441SEvalZero     struct dfs_filesystem *dfs_nfs  = ((struct dfs_filesystem*)(file->data));
696*10465441SEvalZero     nfs = (struct nfs_filesystem *)(dfs_nfs->data);
697*10465441SEvalZero     fd = (nfs_file *)(nfs->data);
698*10465441SEvalZero     RT_ASSERT(fd != NULL);
699*10465441SEvalZero 
700*10465441SEvalZero     if (offset <= fd->size)
701*10465441SEvalZero     {
702*10465441SEvalZero         fd->offset = offset;
703*10465441SEvalZero 
704*10465441SEvalZero         return offset;
705*10465441SEvalZero     }
706*10465441SEvalZero 
707*10465441SEvalZero     return -EIO;
708*10465441SEvalZero }
709*10465441SEvalZero 
nfs_close(struct dfs_fd * file)710*10465441SEvalZero int nfs_close(struct dfs_fd *file)
711*10465441SEvalZero {
712*10465441SEvalZero     nfs_filesystem *nfs;
713*10465441SEvalZero     RT_ASSERT(file->data != NULL);
714*10465441SEvalZero     struct dfs_filesystem *dfs_nfs  = ((struct dfs_filesystem*)(file->data));
715*10465441SEvalZero     nfs = (struct nfs_filesystem *)(dfs_nfs->data);
716*10465441SEvalZero 
717*10465441SEvalZero     if (file->type == FT_DIRECTORY)
718*10465441SEvalZero     {
719*10465441SEvalZero         struct nfs_dir *dir;
720*10465441SEvalZero 
721*10465441SEvalZero         dir = (struct nfs_dir *)nfs->data;
722*10465441SEvalZero         xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)&dir->handle);
723*10465441SEvalZero         xdr_free((xdrproc_t)xdr_READDIR3res, (char *)&dir->res);
724*10465441SEvalZero         rt_free(dir);
725*10465441SEvalZero     }
726*10465441SEvalZero     else if (file->type == FT_REGULAR)
727*10465441SEvalZero     {
728*10465441SEvalZero         struct nfs_file *fd;
729*10465441SEvalZero 
730*10465441SEvalZero         fd = (struct nfs_file *)nfs->data;
731*10465441SEvalZero 
732*10465441SEvalZero         xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)&fd->handle);
733*10465441SEvalZero         rt_free(fd);
734*10465441SEvalZero     }
735*10465441SEvalZero 
736*10465441SEvalZero     nfs->data = NULL;
737*10465441SEvalZero     return 0;
738*10465441SEvalZero }
739*10465441SEvalZero 
nfs_open(struct dfs_fd * file)740*10465441SEvalZero int nfs_open(struct dfs_fd *file)
741*10465441SEvalZero {
742*10465441SEvalZero     nfs_filesystem *nfs;
743*10465441SEvalZero     RT_ASSERT(file->data != NULL);
744*10465441SEvalZero     struct dfs_filesystem *dfs_nfs  = ((struct dfs_filesystem*)(file->data));
745*10465441SEvalZero     nfs = (struct nfs_filesystem *)(dfs_nfs->data);
746*10465441SEvalZero 
747*10465441SEvalZero 
748*10465441SEvalZero     if (file->flags & O_DIRECTORY)
749*10465441SEvalZero     {
750*10465441SEvalZero         nfs_dir *dir;
751*10465441SEvalZero 
752*10465441SEvalZero         if (file->flags & O_CREAT)
753*10465441SEvalZero         {
754*10465441SEvalZero             if (nfs_mkdir(nfs, file->path, 0755) < 0)
755*10465441SEvalZero                 return -EAGAIN;
756*10465441SEvalZero         }
757*10465441SEvalZero 
758*10465441SEvalZero         /* open directory */
759*10465441SEvalZero         dir = nfs_opendir(nfs, file->path);
760*10465441SEvalZero         if (dir == NULL) return -ENOENT;
761*10465441SEvalZero         nfs->data = dir;
762*10465441SEvalZero     }
763*10465441SEvalZero     else
764*10465441SEvalZero     {
765*10465441SEvalZero         nfs_file *fp;
766*10465441SEvalZero         nfs_fh3 *handle;
767*10465441SEvalZero 
768*10465441SEvalZero         /* create file */
769*10465441SEvalZero         if (file->flags & O_CREAT)
770*10465441SEvalZero         {
771*10465441SEvalZero             if (nfs_create(nfs, file->path, 0664) < 0)
772*10465441SEvalZero                 return -EAGAIN;
773*10465441SEvalZero         }
774*10465441SEvalZero 
775*10465441SEvalZero         /* open file (get file handle ) */
776*10465441SEvalZero         fp = rt_malloc(sizeof(nfs_file));
777*10465441SEvalZero         if (fp == NULL)
778*10465441SEvalZero             return -ENOMEM;
779*10465441SEvalZero 
780*10465441SEvalZero         handle = get_handle(nfs, file->path);
781*10465441SEvalZero         if (handle == NULL)
782*10465441SEvalZero         {
783*10465441SEvalZero             rt_free(fp);
784*10465441SEvalZero 
785*10465441SEvalZero             return -ENOENT;
786*10465441SEvalZero         }
787*10465441SEvalZero 
788*10465441SEvalZero         /* get size of file */
789*10465441SEvalZero         fp->size = nfs_get_filesize(nfs, handle);
790*10465441SEvalZero         fp->offset = 0;
791*10465441SEvalZero         fp->eof = FALSE;
792*10465441SEvalZero 
793*10465441SEvalZero         copy_handle(&fp->handle, handle);
794*10465441SEvalZero         xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle);
795*10465441SEvalZero         rt_free(handle);
796*10465441SEvalZero 
797*10465441SEvalZero         if (file->flags & O_APPEND)
798*10465441SEvalZero         {
799*10465441SEvalZero             fp->offset = fp->size;
800*10465441SEvalZero         }
801*10465441SEvalZero 
802*10465441SEvalZero         /* set private file */
803*10465441SEvalZero         nfs->data = fp;
804*10465441SEvalZero         file->size = fp->size;
805*10465441SEvalZero     }
806*10465441SEvalZero 
807*10465441SEvalZero     return 0;
808*10465441SEvalZero }
809*10465441SEvalZero 
nfs_stat(struct dfs_filesystem * fs,const char * path,struct stat * st)810*10465441SEvalZero int nfs_stat(struct dfs_filesystem *fs, const char *path, struct stat *st)
811*10465441SEvalZero {
812*10465441SEvalZero     GETATTR3args args;
813*10465441SEvalZero     GETATTR3res res;
814*10465441SEvalZero     fattr3 *info;
815*10465441SEvalZero     nfs_fh3 *handle;
816*10465441SEvalZero     nfs_filesystem *nfs;
817*10465441SEvalZero 
818*10465441SEvalZero     RT_ASSERT(fs != NULL);
819*10465441SEvalZero     RT_ASSERT(fs->data != NULL);
820*10465441SEvalZero     nfs = (nfs_filesystem *)fs->data;
821*10465441SEvalZero 
822*10465441SEvalZero     handle = get_handle(nfs, path);
823*10465441SEvalZero     if (handle == NULL)
824*10465441SEvalZero         return -1;
825*10465441SEvalZero 
826*10465441SEvalZero     args.object = *handle;
827*10465441SEvalZero 
828*10465441SEvalZero     memset(&res, '\0', sizeof(res));
829*10465441SEvalZero 
830*10465441SEvalZero     if (nfsproc3_getattr_3(args, &res, nfs->nfs_client) != RPC_SUCCESS)
831*10465441SEvalZero     {
832*10465441SEvalZero         rt_kprintf("GetAttr failed\n");
833*10465441SEvalZero         return -1;
834*10465441SEvalZero     }
835*10465441SEvalZero     else if (res.status != NFS3_OK)
836*10465441SEvalZero     {
837*10465441SEvalZero         rt_kprintf("Getattr failed: %d\n", res.status);
838*10465441SEvalZero         return -1;
839*10465441SEvalZero     }
840*10465441SEvalZero 
841*10465441SEvalZero     info = &res.GETATTR3res_u.resok.obj_attributes;
842*10465441SEvalZero 
843*10465441SEvalZero     st->st_dev = 0;
844*10465441SEvalZero 
845*10465441SEvalZero     st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH;
846*10465441SEvalZero     if (info->type == NFS3DIR)
847*10465441SEvalZero     {
848*10465441SEvalZero         st->st_mode &= ~S_IFREG;
849*10465441SEvalZero         st->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
850*10465441SEvalZero     }
851*10465441SEvalZero 
852*10465441SEvalZero     st->st_size  = info->size;
853*10465441SEvalZero     st->st_mtime = info->mtime.seconds;
854*10465441SEvalZero 
855*10465441SEvalZero     xdr_free((xdrproc_t)xdr_GETATTR3res, (char *)&res);
856*10465441SEvalZero     xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle);
857*10465441SEvalZero     rt_free(handle);
858*10465441SEvalZero 
859*10465441SEvalZero     return 0;
860*10465441SEvalZero }
861*10465441SEvalZero 
nfs_opendir(nfs_filesystem * nfs,const char * path)862*10465441SEvalZero nfs_dir *nfs_opendir(nfs_filesystem *nfs, const char *path)
863*10465441SEvalZero {
864*10465441SEvalZero     nfs_dir *dir;
865*10465441SEvalZero     nfs_fh3 *handle;
866*10465441SEvalZero 
867*10465441SEvalZero     dir = rt_malloc(sizeof(nfs_dir));
868*10465441SEvalZero     if (dir == NULL)
869*10465441SEvalZero     {
870*10465441SEvalZero         return NULL;
871*10465441SEvalZero     }
872*10465441SEvalZero 
873*10465441SEvalZero     handle = get_handle(nfs, path);
874*10465441SEvalZero     if (handle == NULL)
875*10465441SEvalZero     {
876*10465441SEvalZero         rt_free(dir);
877*10465441SEvalZero         return NULL;
878*10465441SEvalZero     }
879*10465441SEvalZero 
880*10465441SEvalZero     copy_handle(&dir->handle, handle);
881*10465441SEvalZero     xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle);
882*10465441SEvalZero     rt_free(handle);
883*10465441SEvalZero 
884*10465441SEvalZero     dir->cookie = 0;
885*10465441SEvalZero     memset(&dir->cookieverf, '\0', sizeof(cookieverf3));
886*10465441SEvalZero     dir->entry = NULL;
887*10465441SEvalZero     dir->eof = FALSE;
888*10465441SEvalZero     memset(&dir->res, '\0', sizeof(dir->res));
889*10465441SEvalZero 
890*10465441SEvalZero     return dir;
891*10465441SEvalZero }
892*10465441SEvalZero 
nfs_readdir(nfs_filesystem * nfs,nfs_dir * dir)893*10465441SEvalZero char *nfs_readdir(nfs_filesystem *nfs, nfs_dir *dir)
894*10465441SEvalZero {
895*10465441SEvalZero     static char name[NAME_MAX];
896*10465441SEvalZero 
897*10465441SEvalZero     if (nfs->nfs_client == NULL || dir == NULL)
898*10465441SEvalZero         return NULL;
899*10465441SEvalZero 
900*10465441SEvalZero     if (dir->entry == NULL)
901*10465441SEvalZero     {
902*10465441SEvalZero         READDIR3args args;
903*10465441SEvalZero 
904*10465441SEvalZero         xdr_free((xdrproc_t)xdr_READDIR3res, (char *)&dir->res);
905*10465441SEvalZero         memset(&dir->res, '\0', sizeof(dir->res));
906*10465441SEvalZero 
907*10465441SEvalZero         args.dir = dir->handle;
908*10465441SEvalZero         args.cookie = dir->cookie;
909*10465441SEvalZero         memcpy(&args.cookieverf, &dir->cookieverf, sizeof(cookieverf3));
910*10465441SEvalZero         args.count = 1024;
911*10465441SEvalZero 
912*10465441SEvalZero         if (nfsproc3_readdir_3(args, &dir->res, nfs->nfs_client) != RPC_SUCCESS)
913*10465441SEvalZero         {
914*10465441SEvalZero             rt_kprintf("Readdir failed\n");
915*10465441SEvalZero 
916*10465441SEvalZero             return NULL;
917*10465441SEvalZero         }
918*10465441SEvalZero         else if (dir->res.status != NFS3_OK)
919*10465441SEvalZero         {
920*10465441SEvalZero             rt_kprintf("Readdir failed: %d\n", dir->res.status);
921*10465441SEvalZero 
922*10465441SEvalZero             return NULL;
923*10465441SEvalZero         }
924*10465441SEvalZero 
925*10465441SEvalZero         memcpy(&dir->cookieverf, &dir->res.READDIR3res_u.resok.cookieverf, sizeof(cookieverf3));
926*10465441SEvalZero         dir->eof = dir->res.READDIR3res_u.resok.reply.eof;
927*10465441SEvalZero         dir->entry = dir->res.READDIR3res_u.resok.reply.entries;
928*10465441SEvalZero     }
929*10465441SEvalZero     if (dir->eof == TRUE && dir->entry == NULL)
930*10465441SEvalZero         return NULL;
931*10465441SEvalZero 
932*10465441SEvalZero     dir->cookie = dir->entry->cookie;
933*10465441SEvalZero     strncpy(name, dir->entry->name, NAME_MAX-1);
934*10465441SEvalZero     dir->entry = dir->entry->nextentry;
935*10465441SEvalZero     name[NAME_MAX - 1] = '\0';
936*10465441SEvalZero 
937*10465441SEvalZero     return name;
938*10465441SEvalZero }
939*10465441SEvalZero 
nfs_unlink(struct dfs_filesystem * fs,const char * path)940*10465441SEvalZero int nfs_unlink(struct dfs_filesystem *fs, const char *path)
941*10465441SEvalZero {
942*10465441SEvalZero     int ret = 0;
943*10465441SEvalZero     nfs_filesystem *nfs;
944*10465441SEvalZero 
945*10465441SEvalZero     RT_ASSERT(fs != NULL);
946*10465441SEvalZero     RT_ASSERT(fs->data != NULL);
947*10465441SEvalZero     nfs = (nfs_filesystem *)fs->data;
948*10465441SEvalZero 
949*10465441SEvalZero     if (nfs_is_directory(nfs, path) == RT_FALSE)
950*10465441SEvalZero     {
951*10465441SEvalZero         /* remove file */
952*10465441SEvalZero         REMOVE3args args;
953*10465441SEvalZero         REMOVE3res res;
954*10465441SEvalZero         nfs_fh3 *handle;
955*10465441SEvalZero 
956*10465441SEvalZero         handle = get_dir_handle(nfs, path);
957*10465441SEvalZero         if (handle == NULL)
958*10465441SEvalZero             return -1;
959*10465441SEvalZero 
960*10465441SEvalZero         args.object.dir = *handle;
961*10465441SEvalZero         args.object.name = strrchr(path, '/') + 1;
962*10465441SEvalZero         if (args.object.name == NULL)
963*10465441SEvalZero         {
964*10465441SEvalZero             args.object.name = (char *)path;
965*10465441SEvalZero         }
966*10465441SEvalZero 
967*10465441SEvalZero         memset(&res, 0, sizeof(res));
968*10465441SEvalZero 
969*10465441SEvalZero         if (nfsproc3_remove_3(args, &res, nfs->nfs_client) != RPC_SUCCESS)
970*10465441SEvalZero         {
971*10465441SEvalZero             rt_kprintf("Remove failed\n");
972*10465441SEvalZero             ret = -1;
973*10465441SEvalZero         }
974*10465441SEvalZero         else if (res.status != NFS3_OK)
975*10465441SEvalZero         {
976*10465441SEvalZero             rt_kprintf("Remove failed: %d\n", res.status);
977*10465441SEvalZero             ret = -1;
978*10465441SEvalZero         }
979*10465441SEvalZero         xdr_free((xdrproc_t)xdr_REMOVE3res, (char *)&res);
980*10465441SEvalZero         xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle);
981*10465441SEvalZero         rt_free(handle);
982*10465441SEvalZero     }
983*10465441SEvalZero     else
984*10465441SEvalZero     {
985*10465441SEvalZero         /* remove directory */
986*10465441SEvalZero         RMDIR3args args;
987*10465441SEvalZero         RMDIR3res res;
988*10465441SEvalZero         nfs_fh3 *handle;
989*10465441SEvalZero 
990*10465441SEvalZero         handle = get_dir_handle(nfs, path);
991*10465441SEvalZero         if (handle == NULL)
992*10465441SEvalZero             return -1;
993*10465441SEvalZero 
994*10465441SEvalZero         args.object.dir = *handle;
995*10465441SEvalZero         args.object.name = strrchr(path, '/') + 1;
996*10465441SEvalZero         if (args.object.name == NULL)
997*10465441SEvalZero         {
998*10465441SEvalZero             args.object.name = (char *)path;
999*10465441SEvalZero         }
1000*10465441SEvalZero 
1001*10465441SEvalZero         memset(&res, 0, sizeof(res));
1002*10465441SEvalZero 
1003*10465441SEvalZero         if (nfsproc3_rmdir_3(args, &res, nfs->nfs_client) != RPC_SUCCESS)
1004*10465441SEvalZero         {
1005*10465441SEvalZero             rt_kprintf("Rmdir failed\n");
1006*10465441SEvalZero             ret = -1;
1007*10465441SEvalZero         }
1008*10465441SEvalZero         else if (res.status != NFS3_OK)
1009*10465441SEvalZero         {
1010*10465441SEvalZero             rt_kprintf("Rmdir failed: %d\n", res.status);
1011*10465441SEvalZero             ret = -1;
1012*10465441SEvalZero         }
1013*10465441SEvalZero 
1014*10465441SEvalZero         xdr_free((xdrproc_t)xdr_RMDIR3res, (char *)&res);
1015*10465441SEvalZero         xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle);
1016*10465441SEvalZero         rt_free(handle);
1017*10465441SEvalZero     }
1018*10465441SEvalZero 
1019*10465441SEvalZero     return ret;
1020*10465441SEvalZero }
1021*10465441SEvalZero 
nfs_rename(struct dfs_filesystem * fs,const char * src,const char * dest)1022*10465441SEvalZero int nfs_rename(struct dfs_filesystem *fs, const char *src, const char *dest)
1023*10465441SEvalZero {
1024*10465441SEvalZero     RENAME3args args;
1025*10465441SEvalZero     RENAME3res res;
1026*10465441SEvalZero     nfs_fh3 *sHandle;
1027*10465441SEvalZero     nfs_fh3 *dHandle;
1028*10465441SEvalZero     int ret = 0;
1029*10465441SEvalZero     nfs_filesystem *nfs;
1030*10465441SEvalZero 
1031*10465441SEvalZero     RT_ASSERT(fs != NULL);
1032*10465441SEvalZero     RT_ASSERT(fs->data != NULL);
1033*10465441SEvalZero     nfs = (nfs_filesystem *)fs->data;
1034*10465441SEvalZero 
1035*10465441SEvalZero     if (nfs->nfs_client == NULL)
1036*10465441SEvalZero         return -1;
1037*10465441SEvalZero 
1038*10465441SEvalZero     sHandle = get_dir_handle(nfs, src);
1039*10465441SEvalZero     if (sHandle == NULL)
1040*10465441SEvalZero         return -1;
1041*10465441SEvalZero 
1042*10465441SEvalZero     dHandle = get_dir_handle(nfs, dest);
1043*10465441SEvalZero     if (dHandle == NULL)
1044*10465441SEvalZero         return -1;
1045*10465441SEvalZero 
1046*10465441SEvalZero     args.from.dir = *sHandle;
1047*10465441SEvalZero     args.from.name = strrchr(src, '/') + 1;
1048*10465441SEvalZero     if (args.from.name == NULL)
1049*10465441SEvalZero         args.from.name = (char *)src;
1050*10465441SEvalZero 
1051*10465441SEvalZero     args.to.dir = *dHandle;
1052*10465441SEvalZero     args.to.name = strrchr(src, '/') + 1;
1053*10465441SEvalZero     if (args.to.name == NULL)
1054*10465441SEvalZero         args.to.name = (char *)dest;
1055*10465441SEvalZero 
1056*10465441SEvalZero     memset(&res, '\0', sizeof(res));
1057*10465441SEvalZero 
1058*10465441SEvalZero     if (nfsproc3_rename_3(args, &res, nfs->nfs_client) != RPC_SUCCESS)
1059*10465441SEvalZero     {
1060*10465441SEvalZero         rt_kprintf("Rename failed\n");
1061*10465441SEvalZero         ret = -1;
1062*10465441SEvalZero     }
1063*10465441SEvalZero     else if (res.status != NFS3_OK)
1064*10465441SEvalZero     {
1065*10465441SEvalZero         rt_kprintf("Rename failed: %d\n", res.status);
1066*10465441SEvalZero         ret = -1;
1067*10465441SEvalZero     }
1068*10465441SEvalZero 
1069*10465441SEvalZero     xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)sHandle);
1070*10465441SEvalZero     xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)dHandle);
1071*10465441SEvalZero     xdr_free((xdrproc_t)xdr_RENAME3res, (char *)&res);
1072*10465441SEvalZero 
1073*10465441SEvalZero     return ret;
1074*10465441SEvalZero }
1075*10465441SEvalZero 
nfs_getdents(struct dfs_fd * file,struct dirent * dirp,uint32_t count)1076*10465441SEvalZero int nfs_getdents(struct dfs_fd *file, struct dirent *dirp, uint32_t count)
1077*10465441SEvalZero {
1078*10465441SEvalZero     nfs_dir *dir;
1079*10465441SEvalZero     rt_uint32_t index;
1080*10465441SEvalZero     struct dirent *d;
1081*10465441SEvalZero     nfs_filesystem *nfs;
1082*10465441SEvalZero     char *name;
1083*10465441SEvalZero 
1084*10465441SEvalZero 
1085*10465441SEvalZero     RT_ASSERT(file->data != NULL);
1086*10465441SEvalZero     struct dfs_filesystem *dfs_nfs  = ((struct dfs_filesystem*)(file->data));
1087*10465441SEvalZero     nfs = (struct nfs_filesystem *)(dfs_nfs->data);
1088*10465441SEvalZero     dir = (nfs_dir *)(nfs->data);
1089*10465441SEvalZero     RT_ASSERT(dir != NULL);
1090*10465441SEvalZero 
1091*10465441SEvalZero     /* make integer count */
1092*10465441SEvalZero     count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
1093*10465441SEvalZero     if (count == 0)
1094*10465441SEvalZero         return -EINVAL;
1095*10465441SEvalZero 
1096*10465441SEvalZero     index = 0;
1097*10465441SEvalZero     while (1)
1098*10465441SEvalZero     {
1099*10465441SEvalZero         d = dirp + index;
1100*10465441SEvalZero 
1101*10465441SEvalZero         name = nfs_readdir(nfs, dir);
1102*10465441SEvalZero         if (name == NULL)
1103*10465441SEvalZero             break;
1104*10465441SEvalZero 
1105*10465441SEvalZero         d->d_type = DT_REG;
1106*10465441SEvalZero 
1107*10465441SEvalZero         d->d_namlen = rt_strlen(name);
1108*10465441SEvalZero         d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
1109*10465441SEvalZero         rt_strncpy(d->d_name, name, rt_strlen(name) + 1);
1110*10465441SEvalZero 
1111*10465441SEvalZero         index ++;
1112*10465441SEvalZero         if (index * sizeof(struct dirent) >= count)
1113*10465441SEvalZero             break;
1114*10465441SEvalZero     }
1115*10465441SEvalZero 
1116*10465441SEvalZero     return index * sizeof(struct dirent);
1117*10465441SEvalZero }
1118*10465441SEvalZero 
1119*10465441SEvalZero static const struct dfs_file_ops nfs_fops =
1120*10465441SEvalZero {
1121*10465441SEvalZero         nfs_open,
1122*10465441SEvalZero         nfs_close,
1123*10465441SEvalZero         nfs_ioctl,
1124*10465441SEvalZero         nfs_read,
1125*10465441SEvalZero         nfs_write,
1126*10465441SEvalZero         NULL, /* flush */
1127*10465441SEvalZero         nfs_lseek,
1128*10465441SEvalZero         nfs_getdents,
1129*10465441SEvalZero         NULL, /* poll */
1130*10465441SEvalZero };
1131*10465441SEvalZero 
1132*10465441SEvalZero static const struct dfs_filesystem_ops _nfs =
1133*10465441SEvalZero {
1134*10465441SEvalZero     "nfs",
1135*10465441SEvalZero     DFS_FS_FLAG_DEFAULT,
1136*10465441SEvalZero     &nfs_fops,
1137*10465441SEvalZero     nfs_mount,
1138*10465441SEvalZero     nfs_unmount,
1139*10465441SEvalZero     NULL, /* mkfs */
1140*10465441SEvalZero     NULL, /* statfs */
1141*10465441SEvalZero     nfs_unlink,
1142*10465441SEvalZero     nfs_stat,
1143*10465441SEvalZero     nfs_rename,
1144*10465441SEvalZero };
1145*10465441SEvalZero 
nfs_init(void)1146*10465441SEvalZero int nfs_init(void)
1147*10465441SEvalZero {
1148*10465441SEvalZero     /* register nfs file system */
1149*10465441SEvalZero     dfs_register(&_nfs);
1150*10465441SEvalZero 
1151*10465441SEvalZero     return RT_EOK;
1152*10465441SEvalZero }
1153*10465441SEvalZero INIT_COMPONENT_EXPORT(nfs_init);
1154*10465441SEvalZero 
1155