xref: /nrf52832-nimble/rt-thread/components/dfs/src/dfs.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  * 2005-02-22     Bernard      The first version.
9*10465441SEvalZero  * 2017-12-11     Bernard      Use rt_free to instead of free in fd_is_open().
10*10465441SEvalZero  * 2018-03-20     Heyuanjie    dynamic allocation FD
11*10465441SEvalZero  */
12*10465441SEvalZero 
13*10465441SEvalZero #include <dfs.h>
14*10465441SEvalZero #include <dfs_fs.h>
15*10465441SEvalZero #include <dfs_file.h>
16*10465441SEvalZero #include "dfs_private.h"
17*10465441SEvalZero #ifdef RT_USING_LWP
18*10465441SEvalZero #include <lwp.h>
19*10465441SEvalZero #endif
20*10465441SEvalZero 
21*10465441SEvalZero #if defined(RT_USING_DFS_DEVFS) && defined(RT_USING_POSIX)
22*10465441SEvalZero #include <libc.h>
23*10465441SEvalZero #endif
24*10465441SEvalZero 
25*10465441SEvalZero /* Global variables */
26*10465441SEvalZero const struct dfs_filesystem_ops *filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX];
27*10465441SEvalZero struct dfs_filesystem filesystem_table[DFS_FILESYSTEMS_MAX];
28*10465441SEvalZero 
29*10465441SEvalZero /* device filesystem lock */
30*10465441SEvalZero static struct rt_mutex fslock;
31*10465441SEvalZero 
32*10465441SEvalZero #ifdef DFS_USING_WORKDIR
33*10465441SEvalZero char working_directory[DFS_PATH_MAX] = {"/"};
34*10465441SEvalZero #endif
35*10465441SEvalZero 
36*10465441SEvalZero static struct dfs_fdtable _fdtab;
37*10465441SEvalZero static int  fd_alloc(struct dfs_fdtable *fdt, int startfd);
38*10465441SEvalZero 
39*10465441SEvalZero /**
40*10465441SEvalZero  * @addtogroup DFS
41*10465441SEvalZero  */
42*10465441SEvalZero 
43*10465441SEvalZero /*@{*/
44*10465441SEvalZero 
45*10465441SEvalZero /**
46*10465441SEvalZero  * this function will initialize device file system.
47*10465441SEvalZero  */
dfs_init(void)48*10465441SEvalZero int dfs_init(void)
49*10465441SEvalZero {
50*10465441SEvalZero     static rt_bool_t init_ok = RT_FALSE;
51*10465441SEvalZero 
52*10465441SEvalZero     if (init_ok)
53*10465441SEvalZero     {
54*10465441SEvalZero         rt_kprintf("dfs already init.\n");
55*10465441SEvalZero         return 0;
56*10465441SEvalZero     }
57*10465441SEvalZero 
58*10465441SEvalZero     /* clear filesystem operations table */
59*10465441SEvalZero     memset((void *)filesystem_operation_table, 0, sizeof(filesystem_operation_table));
60*10465441SEvalZero     /* clear filesystem table */
61*10465441SEvalZero     memset(filesystem_table, 0, sizeof(filesystem_table));
62*10465441SEvalZero     /* clean fd table */
63*10465441SEvalZero     memset(&_fdtab, 0, sizeof(_fdtab));
64*10465441SEvalZero 
65*10465441SEvalZero     /* create device filesystem lock */
66*10465441SEvalZero     rt_mutex_init(&fslock, "fslock", RT_IPC_FLAG_FIFO);
67*10465441SEvalZero 
68*10465441SEvalZero #ifdef DFS_USING_WORKDIR
69*10465441SEvalZero     /* set current working directory */
70*10465441SEvalZero     memset(working_directory, 0, sizeof(working_directory));
71*10465441SEvalZero     working_directory[0] = '/';
72*10465441SEvalZero #endif
73*10465441SEvalZero 
74*10465441SEvalZero #ifdef RT_USING_DFS_DEVFS
75*10465441SEvalZero     {
76*10465441SEvalZero         extern int devfs_init(void);
77*10465441SEvalZero 
78*10465441SEvalZero         /* if enable devfs, initialize and mount it as soon as possible */
79*10465441SEvalZero         devfs_init();
80*10465441SEvalZero 
81*10465441SEvalZero         dfs_mount(NULL, "/dev", "devfs", 0, 0);
82*10465441SEvalZero     }
83*10465441SEvalZero #endif
84*10465441SEvalZero 
85*10465441SEvalZero     init_ok = RT_TRUE;
86*10465441SEvalZero 
87*10465441SEvalZero     return 0;
88*10465441SEvalZero }
89*10465441SEvalZero INIT_PREV_EXPORT(dfs_init);
90*10465441SEvalZero 
91*10465441SEvalZero /**
92*10465441SEvalZero  * this function will lock device file system.
93*10465441SEvalZero  *
94*10465441SEvalZero  * @note please don't invoke it on ISR.
95*10465441SEvalZero  */
dfs_lock(void)96*10465441SEvalZero void dfs_lock(void)
97*10465441SEvalZero {
98*10465441SEvalZero     rt_err_t result = -RT_EBUSY;
99*10465441SEvalZero 
100*10465441SEvalZero     while (result == -RT_EBUSY)
101*10465441SEvalZero     {
102*10465441SEvalZero         result = rt_mutex_take(&fslock, RT_WAITING_FOREVER);
103*10465441SEvalZero     }
104*10465441SEvalZero 
105*10465441SEvalZero     if (result != RT_EOK)
106*10465441SEvalZero     {
107*10465441SEvalZero         RT_ASSERT(0);
108*10465441SEvalZero     }
109*10465441SEvalZero }
110*10465441SEvalZero 
111*10465441SEvalZero /**
112*10465441SEvalZero  * this function will lock device file system.
113*10465441SEvalZero  *
114*10465441SEvalZero  * @note please don't invoke it on ISR.
115*10465441SEvalZero  */
dfs_unlock(void)116*10465441SEvalZero void dfs_unlock(void)
117*10465441SEvalZero {
118*10465441SEvalZero     rt_mutex_release(&fslock);
119*10465441SEvalZero }
120*10465441SEvalZero 
fd_alloc(struct dfs_fdtable * fdt,int startfd)121*10465441SEvalZero static int fd_alloc(struct dfs_fdtable *fdt, int startfd)
122*10465441SEvalZero {
123*10465441SEvalZero     int idx;
124*10465441SEvalZero 
125*10465441SEvalZero     /* find an empty fd entry */
126*10465441SEvalZero     for (idx = startfd; idx < fdt->maxfd; idx++)
127*10465441SEvalZero     {
128*10465441SEvalZero         if (fdt->fds[idx] == RT_NULL)
129*10465441SEvalZero             break;
130*10465441SEvalZero         if (fdt->fds[idx]->ref_count == 0)
131*10465441SEvalZero             break;
132*10465441SEvalZero     }
133*10465441SEvalZero 
134*10465441SEvalZero     /* allocate a larger FD container */
135*10465441SEvalZero     if (idx == fdt->maxfd && fdt->maxfd < DFS_FD_MAX)
136*10465441SEvalZero     {
137*10465441SEvalZero         int cnt, index;
138*10465441SEvalZero         struct dfs_fd **fds;
139*10465441SEvalZero 
140*10465441SEvalZero         /* increase the number of FD with 4 step length */
141*10465441SEvalZero         cnt = fdt->maxfd + 4;
142*10465441SEvalZero         cnt = cnt > DFS_FD_MAX? DFS_FD_MAX : cnt;
143*10465441SEvalZero 
144*10465441SEvalZero         fds = rt_realloc(fdt->fds, cnt * sizeof(struct dfs_fd *));
145*10465441SEvalZero         if (fds == NULL) goto __exit; /* return fdt->maxfd */
146*10465441SEvalZero 
147*10465441SEvalZero         /* clean the new allocated fds */
148*10465441SEvalZero         for (index = fdt->maxfd; index < cnt; index ++)
149*10465441SEvalZero         {
150*10465441SEvalZero             fds[index] = NULL;
151*10465441SEvalZero         }
152*10465441SEvalZero 
153*10465441SEvalZero         fdt->fds   = fds;
154*10465441SEvalZero         fdt->maxfd = cnt;
155*10465441SEvalZero     }
156*10465441SEvalZero 
157*10465441SEvalZero     /* allocate  'struct dfs_fd' */
158*10465441SEvalZero     if (idx < fdt->maxfd &&fdt->fds[idx] == RT_NULL)
159*10465441SEvalZero     {
160*10465441SEvalZero         fdt->fds[idx] = rt_calloc(1, sizeof(struct dfs_fd));
161*10465441SEvalZero         if (fdt->fds[idx] == RT_NULL)
162*10465441SEvalZero             idx = fdt->maxfd;
163*10465441SEvalZero     }
164*10465441SEvalZero 
165*10465441SEvalZero __exit:
166*10465441SEvalZero     return idx;
167*10465441SEvalZero }
168*10465441SEvalZero 
169*10465441SEvalZero /**
170*10465441SEvalZero  * @ingroup Fd
171*10465441SEvalZero  * This function will allocate a file descriptor.
172*10465441SEvalZero  *
173*10465441SEvalZero  * @return -1 on failed or the allocated file descriptor.
174*10465441SEvalZero  */
fd_new(void)175*10465441SEvalZero int fd_new(void)
176*10465441SEvalZero {
177*10465441SEvalZero     struct dfs_fd *d;
178*10465441SEvalZero     int idx;
179*10465441SEvalZero     struct dfs_fdtable *fdt;
180*10465441SEvalZero 
181*10465441SEvalZero     fdt = dfs_fdtable_get();
182*10465441SEvalZero     /* lock filesystem */
183*10465441SEvalZero     dfs_lock();
184*10465441SEvalZero 
185*10465441SEvalZero     /* find an empty fd entry */
186*10465441SEvalZero     idx = fd_alloc(fdt, 0);
187*10465441SEvalZero 
188*10465441SEvalZero     /* can't find an empty fd entry */
189*10465441SEvalZero     if (idx == fdt->maxfd)
190*10465441SEvalZero     {
191*10465441SEvalZero         idx = -(1 + DFS_FD_OFFSET);
192*10465441SEvalZero         LOG_E( "DFS fd new is failed! Could not found an empty fd entry.");
193*10465441SEvalZero         goto __result;
194*10465441SEvalZero     }
195*10465441SEvalZero 
196*10465441SEvalZero     d = fdt->fds[idx];
197*10465441SEvalZero     d->ref_count = 1;
198*10465441SEvalZero     d->magic = DFS_FD_MAGIC;
199*10465441SEvalZero 
200*10465441SEvalZero __result:
201*10465441SEvalZero     dfs_unlock();
202*10465441SEvalZero     return idx + DFS_FD_OFFSET;
203*10465441SEvalZero }
204*10465441SEvalZero 
205*10465441SEvalZero /**
206*10465441SEvalZero  * @ingroup Fd
207*10465441SEvalZero  *
208*10465441SEvalZero  * This function will return a file descriptor structure according to file
209*10465441SEvalZero  * descriptor.
210*10465441SEvalZero  *
211*10465441SEvalZero  * @return NULL on on this file descriptor or the file descriptor structure
212*10465441SEvalZero  * pointer.
213*10465441SEvalZero  */
fd_get(int fd)214*10465441SEvalZero struct dfs_fd *fd_get(int fd)
215*10465441SEvalZero {
216*10465441SEvalZero     struct dfs_fd *d;
217*10465441SEvalZero     struct dfs_fdtable *fdt;
218*10465441SEvalZero 
219*10465441SEvalZero #if defined(RT_USING_DFS_DEVFS) && defined(RT_USING_POSIX)
220*10465441SEvalZero     if ((0 <= fd) && (fd <= 2))
221*10465441SEvalZero         fd = libc_stdio_get_console();
222*10465441SEvalZero #endif
223*10465441SEvalZero 
224*10465441SEvalZero     fdt = dfs_fdtable_get();
225*10465441SEvalZero     fd = fd - DFS_FD_OFFSET;
226*10465441SEvalZero     if (fd < 0 || fd >= fdt->maxfd)
227*10465441SEvalZero         return NULL;
228*10465441SEvalZero 
229*10465441SEvalZero     dfs_lock();
230*10465441SEvalZero     d = fdt->fds[fd];
231*10465441SEvalZero 
232*10465441SEvalZero     /* check dfs_fd valid or not */
233*10465441SEvalZero     if ((d == NULL) || (d->magic != DFS_FD_MAGIC))
234*10465441SEvalZero     {
235*10465441SEvalZero         dfs_unlock();
236*10465441SEvalZero         return NULL;
237*10465441SEvalZero     }
238*10465441SEvalZero 
239*10465441SEvalZero     /* increase the reference count */
240*10465441SEvalZero     d->ref_count ++;
241*10465441SEvalZero     dfs_unlock();
242*10465441SEvalZero 
243*10465441SEvalZero     return d;
244*10465441SEvalZero }
245*10465441SEvalZero 
246*10465441SEvalZero /**
247*10465441SEvalZero  * @ingroup Fd
248*10465441SEvalZero  *
249*10465441SEvalZero  * This function will put the file descriptor.
250*10465441SEvalZero  */
fd_put(struct dfs_fd * fd)251*10465441SEvalZero void fd_put(struct dfs_fd *fd)
252*10465441SEvalZero {
253*10465441SEvalZero     RT_ASSERT(fd != NULL);
254*10465441SEvalZero 
255*10465441SEvalZero     dfs_lock();
256*10465441SEvalZero 
257*10465441SEvalZero     fd->ref_count --;
258*10465441SEvalZero 
259*10465441SEvalZero     /* clear this fd entry */
260*10465441SEvalZero     if (fd->ref_count == 0)
261*10465441SEvalZero     {
262*10465441SEvalZero         int index;
263*10465441SEvalZero         struct dfs_fdtable *fdt;
264*10465441SEvalZero 
265*10465441SEvalZero         fdt = dfs_fdtable_get();
266*10465441SEvalZero         for (index = 0; index < fdt->maxfd; index ++)
267*10465441SEvalZero         {
268*10465441SEvalZero             if (fdt->fds[index] == fd)
269*10465441SEvalZero             {
270*10465441SEvalZero                 rt_free(fd);
271*10465441SEvalZero                 fdt->fds[index] = 0;
272*10465441SEvalZero                 break;
273*10465441SEvalZero             }
274*10465441SEvalZero         }
275*10465441SEvalZero     }
276*10465441SEvalZero     dfs_unlock();
277*10465441SEvalZero }
278*10465441SEvalZero 
279*10465441SEvalZero /**
280*10465441SEvalZero  * @ingroup Fd
281*10465441SEvalZero  *
282*10465441SEvalZero  * This function will return whether this file has been opend.
283*10465441SEvalZero  *
284*10465441SEvalZero  * @param pathname the file path name.
285*10465441SEvalZero  *
286*10465441SEvalZero  * @return 0 on file has been open successfully, -1 on open failed.
287*10465441SEvalZero  */
fd_is_open(const char * pathname)288*10465441SEvalZero int fd_is_open(const char *pathname)
289*10465441SEvalZero {
290*10465441SEvalZero     char *fullpath;
291*10465441SEvalZero     unsigned int index;
292*10465441SEvalZero     struct dfs_filesystem *fs;
293*10465441SEvalZero     struct dfs_fd *fd;
294*10465441SEvalZero     struct dfs_fdtable *fdt;
295*10465441SEvalZero 
296*10465441SEvalZero     fdt = dfs_fdtable_get();
297*10465441SEvalZero     fullpath = dfs_normalize_path(NULL, pathname);
298*10465441SEvalZero     if (fullpath != NULL)
299*10465441SEvalZero     {
300*10465441SEvalZero         char *mountpath;
301*10465441SEvalZero         fs = dfs_filesystem_lookup(fullpath);
302*10465441SEvalZero         if (fs == NULL)
303*10465441SEvalZero         {
304*10465441SEvalZero             /* can't find mounted file system */
305*10465441SEvalZero             rt_free(fullpath);
306*10465441SEvalZero 
307*10465441SEvalZero             return -1;
308*10465441SEvalZero         }
309*10465441SEvalZero 
310*10465441SEvalZero         /* get file path name under mounted file system */
311*10465441SEvalZero         if (fs->path[0] == '/' && fs->path[1] == '\0')
312*10465441SEvalZero             mountpath = fullpath;
313*10465441SEvalZero         else
314*10465441SEvalZero             mountpath = fullpath + strlen(fs->path);
315*10465441SEvalZero 
316*10465441SEvalZero         dfs_lock();
317*10465441SEvalZero 
318*10465441SEvalZero         for (index = 0; index < fdt->maxfd; index++)
319*10465441SEvalZero         {
320*10465441SEvalZero             fd = fdt->fds[index];
321*10465441SEvalZero             if (fd == NULL || fd->fops == NULL || fd->path == NULL) continue;
322*10465441SEvalZero 
323*10465441SEvalZero             if (fd->fs == fs && strcmp(fd->path, mountpath) == 0)
324*10465441SEvalZero             {
325*10465441SEvalZero                 /* found file in file descriptor table */
326*10465441SEvalZero                 rt_free(fullpath);
327*10465441SEvalZero                 dfs_unlock();
328*10465441SEvalZero 
329*10465441SEvalZero                 return 0;
330*10465441SEvalZero             }
331*10465441SEvalZero         }
332*10465441SEvalZero         dfs_unlock();
333*10465441SEvalZero 
334*10465441SEvalZero         rt_free(fullpath);
335*10465441SEvalZero     }
336*10465441SEvalZero 
337*10465441SEvalZero     return -1;
338*10465441SEvalZero }
339*10465441SEvalZero 
340*10465441SEvalZero /**
341*10465441SEvalZero  * this function will return a sub-path name under directory.
342*10465441SEvalZero  *
343*10465441SEvalZero  * @param directory the parent directory.
344*10465441SEvalZero  * @param filename the filename.
345*10465441SEvalZero  *
346*10465441SEvalZero  * @return the subdir pointer in filename
347*10465441SEvalZero  */
dfs_subdir(const char * directory,const char * filename)348*10465441SEvalZero const char *dfs_subdir(const char *directory, const char *filename)
349*10465441SEvalZero {
350*10465441SEvalZero     const char *dir;
351*10465441SEvalZero 
352*10465441SEvalZero     if (strlen(directory) == strlen(filename)) /* it's a same path */
353*10465441SEvalZero         return NULL;
354*10465441SEvalZero 
355*10465441SEvalZero     dir = filename + strlen(directory);
356*10465441SEvalZero     if ((*dir != '/') && (dir != filename))
357*10465441SEvalZero     {
358*10465441SEvalZero         dir --;
359*10465441SEvalZero     }
360*10465441SEvalZero 
361*10465441SEvalZero     return dir;
362*10465441SEvalZero }
363*10465441SEvalZero RTM_EXPORT(dfs_subdir);
364*10465441SEvalZero 
365*10465441SEvalZero /**
366*10465441SEvalZero  * this function will normalize a path according to specified parent directory
367*10465441SEvalZero  * and file name.
368*10465441SEvalZero  *
369*10465441SEvalZero  * @param directory the parent path
370*10465441SEvalZero  * @param filename the file name
371*10465441SEvalZero  *
372*10465441SEvalZero  * @return the built full file path (absolute path)
373*10465441SEvalZero  */
dfs_normalize_path(const char * directory,const char * filename)374*10465441SEvalZero char *dfs_normalize_path(const char *directory, const char *filename)
375*10465441SEvalZero {
376*10465441SEvalZero     char *fullpath;
377*10465441SEvalZero     char *dst0, *dst, *src;
378*10465441SEvalZero 
379*10465441SEvalZero     /* check parameters */
380*10465441SEvalZero     RT_ASSERT(filename != NULL);
381*10465441SEvalZero 
382*10465441SEvalZero #ifdef DFS_USING_WORKDIR
383*10465441SEvalZero     if (directory == NULL) /* shall use working directory */
384*10465441SEvalZero         directory = &working_directory[0];
385*10465441SEvalZero #else
386*10465441SEvalZero     if ((directory == NULL) && (filename[0] != '/'))
387*10465441SEvalZero     {
388*10465441SEvalZero         rt_kprintf(NO_WORKING_DIR);
389*10465441SEvalZero 
390*10465441SEvalZero         return NULL;
391*10465441SEvalZero     }
392*10465441SEvalZero #endif
393*10465441SEvalZero 
394*10465441SEvalZero     if (filename[0] != '/') /* it's a absolute path, use it directly */
395*10465441SEvalZero     {
396*10465441SEvalZero         fullpath = rt_malloc(strlen(directory) + strlen(filename) + 2);
397*10465441SEvalZero 
398*10465441SEvalZero         if (fullpath == NULL)
399*10465441SEvalZero             return NULL;
400*10465441SEvalZero 
401*10465441SEvalZero         /* join path and file name */
402*10465441SEvalZero         rt_snprintf(fullpath, strlen(directory) + strlen(filename) + 2,
403*10465441SEvalZero             "%s/%s", directory, filename);
404*10465441SEvalZero     }
405*10465441SEvalZero     else
406*10465441SEvalZero     {
407*10465441SEvalZero         fullpath = rt_strdup(filename); /* copy string */
408*10465441SEvalZero 
409*10465441SEvalZero         if (fullpath == NULL)
410*10465441SEvalZero             return NULL;
411*10465441SEvalZero     }
412*10465441SEvalZero 
413*10465441SEvalZero     src = fullpath;
414*10465441SEvalZero     dst = fullpath;
415*10465441SEvalZero 
416*10465441SEvalZero     dst0 = dst;
417*10465441SEvalZero     while (1)
418*10465441SEvalZero     {
419*10465441SEvalZero         char c = *src;
420*10465441SEvalZero 
421*10465441SEvalZero         if (c == '.')
422*10465441SEvalZero         {
423*10465441SEvalZero             if (!src[1]) src ++; /* '.' and ends */
424*10465441SEvalZero             else if (src[1] == '/')
425*10465441SEvalZero             {
426*10465441SEvalZero                 /* './' case */
427*10465441SEvalZero                 src += 2;
428*10465441SEvalZero 
429*10465441SEvalZero                 while ((*src == '/') && (*src != '\0'))
430*10465441SEvalZero                     src ++;
431*10465441SEvalZero                 continue;
432*10465441SEvalZero             }
433*10465441SEvalZero             else if (src[1] == '.')
434*10465441SEvalZero             {
435*10465441SEvalZero                 if (!src[2])
436*10465441SEvalZero                 {
437*10465441SEvalZero                     /* '..' and ends case */
438*10465441SEvalZero                     src += 2;
439*10465441SEvalZero                     goto up_one;
440*10465441SEvalZero                 }
441*10465441SEvalZero                 else if (src[2] == '/')
442*10465441SEvalZero                 {
443*10465441SEvalZero                     /* '../' case */
444*10465441SEvalZero                     src += 3;
445*10465441SEvalZero 
446*10465441SEvalZero                     while ((*src == '/') && (*src != '\0'))
447*10465441SEvalZero                         src ++;
448*10465441SEvalZero                     goto up_one;
449*10465441SEvalZero                 }
450*10465441SEvalZero             }
451*10465441SEvalZero         }
452*10465441SEvalZero 
453*10465441SEvalZero         /* copy up the next '/' and erase all '/' */
454*10465441SEvalZero         while ((c = *src++) != '\0' && c != '/')
455*10465441SEvalZero             *dst ++ = c;
456*10465441SEvalZero 
457*10465441SEvalZero         if (c == '/')
458*10465441SEvalZero         {
459*10465441SEvalZero             *dst ++ = '/';
460*10465441SEvalZero             while (c == '/')
461*10465441SEvalZero                 c = *src++;
462*10465441SEvalZero 
463*10465441SEvalZero             src --;
464*10465441SEvalZero         }
465*10465441SEvalZero         else if (!c)
466*10465441SEvalZero             break;
467*10465441SEvalZero 
468*10465441SEvalZero         continue;
469*10465441SEvalZero 
470*10465441SEvalZero up_one:
471*10465441SEvalZero         dst --;
472*10465441SEvalZero         if (dst < dst0)
473*10465441SEvalZero         {
474*10465441SEvalZero             rt_free(fullpath);
475*10465441SEvalZero             return NULL;
476*10465441SEvalZero         }
477*10465441SEvalZero         while (dst0 < dst && dst[-1] != '/')
478*10465441SEvalZero             dst --;
479*10465441SEvalZero     }
480*10465441SEvalZero 
481*10465441SEvalZero     *dst = '\0';
482*10465441SEvalZero 
483*10465441SEvalZero     /* remove '/' in the end of path if exist */
484*10465441SEvalZero     dst --;
485*10465441SEvalZero     if ((dst != fullpath) && (*dst == '/'))
486*10465441SEvalZero         *dst = '\0';
487*10465441SEvalZero 
488*10465441SEvalZero     /* final check fullpath is not empty, for the special path of lwext "/.." */
489*10465441SEvalZero     if ('\0' == fullpath[0])
490*10465441SEvalZero     {
491*10465441SEvalZero         fullpath[0] = '/';
492*10465441SEvalZero         fullpath[1] = '\0';
493*10465441SEvalZero     }
494*10465441SEvalZero 
495*10465441SEvalZero     return fullpath;
496*10465441SEvalZero }
497*10465441SEvalZero RTM_EXPORT(dfs_normalize_path);
498*10465441SEvalZero 
499*10465441SEvalZero /**
500*10465441SEvalZero  * This function will get the file descriptor table of current process.
501*10465441SEvalZero  */
dfs_fdtable_get(void)502*10465441SEvalZero struct dfs_fdtable* dfs_fdtable_get(void)
503*10465441SEvalZero {
504*10465441SEvalZero     struct dfs_fdtable *fdt;
505*10465441SEvalZero #ifdef RT_USING_LWP
506*10465441SEvalZero     struct rt_lwp *lwp;
507*10465441SEvalZero 
508*10465441SEvalZero     lwp = (struct rt_lwp *)rt_thread_self()->lwp;
509*10465441SEvalZero     if (lwp)
510*10465441SEvalZero         fdt = &lwp->fdt;
511*10465441SEvalZero     else
512*10465441SEvalZero         fdt = &_fdtab;
513*10465441SEvalZero #else
514*10465441SEvalZero     fdt = &_fdtab;
515*10465441SEvalZero #endif
516*10465441SEvalZero 
517*10465441SEvalZero     return fdt;
518*10465441SEvalZero }
519*10465441SEvalZero 
520*10465441SEvalZero #ifdef RT_USING_FINSH
521*10465441SEvalZero #include <finsh.h>
list_fd(void)522*10465441SEvalZero int list_fd(void)
523*10465441SEvalZero {
524*10465441SEvalZero     int index;
525*10465441SEvalZero     struct dfs_fdtable *fd_table;
526*10465441SEvalZero 
527*10465441SEvalZero     fd_table = dfs_fdtable_get();
528*10465441SEvalZero     if (!fd_table) return -1;
529*10465441SEvalZero 
530*10465441SEvalZero     rt_enter_critical();
531*10465441SEvalZero 
532*10465441SEvalZero     rt_kprintf("fd type    ref magic  path\n");
533*10465441SEvalZero     rt_kprintf("-- ------  --- ----- ------\n");
534*10465441SEvalZero     for (index = 0; index < fd_table->maxfd; index ++)
535*10465441SEvalZero     {
536*10465441SEvalZero         struct dfs_fd *fd = fd_table->fds[index];
537*10465441SEvalZero 
538*10465441SEvalZero         if (fd && fd->fops)
539*10465441SEvalZero         {
540*10465441SEvalZero             rt_kprintf("%2d ", index);
541*10465441SEvalZero             if (fd->type == FT_DIRECTORY)    rt_kprintf("%-7.7s ", "dir");
542*10465441SEvalZero             else if (fd->type == FT_REGULAR) rt_kprintf("%-7.7s ", "file");
543*10465441SEvalZero             else if (fd->type == FT_SOCKET)  rt_kprintf("%-7.7s ", "socket");
544*10465441SEvalZero             else if (fd->type == FT_USER)    rt_kprintf("%-7.7s ", "user");
545*10465441SEvalZero             else rt_kprintf("%-8.8s ", "unknown");
546*10465441SEvalZero             rt_kprintf("%3d ", fd->ref_count);
547*10465441SEvalZero             rt_kprintf("%04x  ", fd->magic);
548*10465441SEvalZero             if (fd->path)
549*10465441SEvalZero             {
550*10465441SEvalZero                 rt_kprintf("%s\n", fd->path);
551*10465441SEvalZero             }
552*10465441SEvalZero             else
553*10465441SEvalZero             {
554*10465441SEvalZero                 rt_kprintf("\n");
555*10465441SEvalZero             }
556*10465441SEvalZero         }
557*10465441SEvalZero     }
558*10465441SEvalZero     rt_exit_critical();
559*10465441SEvalZero 
560*10465441SEvalZero     return 0;
561*10465441SEvalZero }
562*10465441SEvalZero MSH_CMD_EXPORT(list_fd, list file descriptor);
563*10465441SEvalZero #endif
564*10465441SEvalZero /*@}*/
565*10465441SEvalZero 
566