xref: /nrf52832-nimble/rt-thread/components/dfs/src/dfs_file.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  * 2011-12-08     Bernard      Merges rename patch from iamcacy.
10*10465441SEvalZero  * 2015-05-27     Bernard      Fix the fd clear issue.
11*10465441SEvalZero  * 2019-01-24     Bernard      Remove file repeatedly open check.
12*10465441SEvalZero  */
13*10465441SEvalZero 
14*10465441SEvalZero #include <dfs.h>
15*10465441SEvalZero #include <dfs_file.h>
16*10465441SEvalZero #include <dfs_private.h>
17*10465441SEvalZero 
18*10465441SEvalZero /**
19*10465441SEvalZero  * @addtogroup FileApi
20*10465441SEvalZero  */
21*10465441SEvalZero 
22*10465441SEvalZero /*@{*/
23*10465441SEvalZero 
24*10465441SEvalZero /**
25*10465441SEvalZero  * this function will open a file which specified by path with specified flags.
26*10465441SEvalZero  *
27*10465441SEvalZero  * @param fd the file descriptor pointer to return the corresponding result.
28*10465441SEvalZero  * @param path the specified file path.
29*10465441SEvalZero  * @param flags the flags for open operator.
30*10465441SEvalZero  *
31*10465441SEvalZero  * @return 0 on successful, -1 on failed.
32*10465441SEvalZero  */
dfs_file_open(struct dfs_fd * fd,const char * path,int flags)33*10465441SEvalZero int dfs_file_open(struct dfs_fd *fd, const char *path, int flags)
34*10465441SEvalZero {
35*10465441SEvalZero     struct dfs_filesystem *fs;
36*10465441SEvalZero     char *fullpath;
37*10465441SEvalZero     int result;
38*10465441SEvalZero 
39*10465441SEvalZero     /* parameter check */
40*10465441SEvalZero     if (fd == NULL)
41*10465441SEvalZero         return -EINVAL;
42*10465441SEvalZero 
43*10465441SEvalZero     /* make sure we have an absolute path */
44*10465441SEvalZero     fullpath = dfs_normalize_path(NULL, path);
45*10465441SEvalZero     if (fullpath == NULL)
46*10465441SEvalZero     {
47*10465441SEvalZero         return -ENOMEM;
48*10465441SEvalZero     }
49*10465441SEvalZero 
50*10465441SEvalZero     LOG_D("open file:%s", fullpath);
51*10465441SEvalZero 
52*10465441SEvalZero     /* find filesystem */
53*10465441SEvalZero     fs = dfs_filesystem_lookup(fullpath);
54*10465441SEvalZero     if (fs == NULL)
55*10465441SEvalZero     {
56*10465441SEvalZero         rt_free(fullpath); /* release path */
57*10465441SEvalZero 
58*10465441SEvalZero         return -ENOENT;
59*10465441SEvalZero     }
60*10465441SEvalZero 
61*10465441SEvalZero     LOG_D("open in filesystem:%s", fs->ops->name);
62*10465441SEvalZero     fd->fs    = fs;             /* set file system */
63*10465441SEvalZero     fd->fops  = fs->ops->fops;  /* set file ops */
64*10465441SEvalZero 
65*10465441SEvalZero     /* initialize the fd item */
66*10465441SEvalZero     fd->type  = FT_REGULAR;
67*10465441SEvalZero     fd->flags = flags;
68*10465441SEvalZero     fd->size  = 0;
69*10465441SEvalZero     fd->pos   = 0;
70*10465441SEvalZero     fd->data  = fs;
71*10465441SEvalZero 
72*10465441SEvalZero     if (!(fs->ops->flags & DFS_FS_FLAG_FULLPATH))
73*10465441SEvalZero     {
74*10465441SEvalZero         if (dfs_subdir(fs->path, fullpath) == NULL)
75*10465441SEvalZero             fd->path = rt_strdup("/");
76*10465441SEvalZero         else
77*10465441SEvalZero             fd->path = rt_strdup(dfs_subdir(fs->path, fullpath));
78*10465441SEvalZero         rt_free(fullpath);
79*10465441SEvalZero         LOG_D("Actual file path: %s", fd->path);
80*10465441SEvalZero     }
81*10465441SEvalZero     else
82*10465441SEvalZero     {
83*10465441SEvalZero         fd->path = fullpath;
84*10465441SEvalZero     }
85*10465441SEvalZero 
86*10465441SEvalZero     /* specific file system open routine */
87*10465441SEvalZero     if (fd->fops->open == NULL)
88*10465441SEvalZero     {
89*10465441SEvalZero         /* clear fd */
90*10465441SEvalZero         rt_free(fd->path);
91*10465441SEvalZero         fd->path = NULL;
92*10465441SEvalZero 
93*10465441SEvalZero         return -ENOSYS;
94*10465441SEvalZero     }
95*10465441SEvalZero 
96*10465441SEvalZero     if ((result = fd->fops->open(fd)) < 0)
97*10465441SEvalZero     {
98*10465441SEvalZero         /* clear fd */
99*10465441SEvalZero         rt_free(fd->path);
100*10465441SEvalZero         fd->path = NULL;
101*10465441SEvalZero 
102*10465441SEvalZero         LOG_E("open failed");
103*10465441SEvalZero 
104*10465441SEvalZero         return result;
105*10465441SEvalZero     }
106*10465441SEvalZero 
107*10465441SEvalZero     fd->flags |= DFS_F_OPEN;
108*10465441SEvalZero     if (flags & O_DIRECTORY)
109*10465441SEvalZero     {
110*10465441SEvalZero         fd->type = FT_DIRECTORY;
111*10465441SEvalZero         fd->flags |= DFS_F_DIRECTORY;
112*10465441SEvalZero     }
113*10465441SEvalZero 
114*10465441SEvalZero     LOG_I("open successful");
115*10465441SEvalZero     return 0;
116*10465441SEvalZero }
117*10465441SEvalZero 
118*10465441SEvalZero /**
119*10465441SEvalZero  * this function will close a file descriptor.
120*10465441SEvalZero  *
121*10465441SEvalZero  * @param fd the file descriptor to be closed.
122*10465441SEvalZero  *
123*10465441SEvalZero  * @return 0 on successful, -1 on failed.
124*10465441SEvalZero  */
dfs_file_close(struct dfs_fd * fd)125*10465441SEvalZero int dfs_file_close(struct dfs_fd *fd)
126*10465441SEvalZero {
127*10465441SEvalZero     int result = 0;
128*10465441SEvalZero 
129*10465441SEvalZero     if (fd == NULL)
130*10465441SEvalZero         return -ENXIO;
131*10465441SEvalZero 
132*10465441SEvalZero     if (fd->fops->close != NULL)
133*10465441SEvalZero         result = fd->fops->close(fd);
134*10465441SEvalZero 
135*10465441SEvalZero     /* close fd error, return */
136*10465441SEvalZero     if (result < 0)
137*10465441SEvalZero         return result;
138*10465441SEvalZero 
139*10465441SEvalZero     rt_free(fd->path);
140*10465441SEvalZero     fd->path = NULL;
141*10465441SEvalZero 
142*10465441SEvalZero     return result;
143*10465441SEvalZero }
144*10465441SEvalZero 
145*10465441SEvalZero /**
146*10465441SEvalZero  * this function will perform a io control on a file descriptor.
147*10465441SEvalZero  *
148*10465441SEvalZero  * @param fd the file descriptor.
149*10465441SEvalZero  * @param cmd the command to send to file descriptor.
150*10465441SEvalZero  * @param args the argument to send to file descriptor.
151*10465441SEvalZero  *
152*10465441SEvalZero  * @return 0 on successful, -1 on failed.
153*10465441SEvalZero  */
dfs_file_ioctl(struct dfs_fd * fd,int cmd,void * args)154*10465441SEvalZero int dfs_file_ioctl(struct dfs_fd *fd, int cmd, void *args)
155*10465441SEvalZero {
156*10465441SEvalZero     if (fd == NULL)
157*10465441SEvalZero         return -EINVAL;
158*10465441SEvalZero 
159*10465441SEvalZero     /* regular file system fd */
160*10465441SEvalZero     if (fd->type == FT_REGULAR)
161*10465441SEvalZero     {
162*10465441SEvalZero         switch (cmd)
163*10465441SEvalZero         {
164*10465441SEvalZero         case F_GETFL:
165*10465441SEvalZero             return fd->flags; /* return flags */
166*10465441SEvalZero         case F_SETFL:
167*10465441SEvalZero             {
168*10465441SEvalZero                 int flags = (int)(rt_base_t)args;
169*10465441SEvalZero                 int mask  = O_NONBLOCK | O_APPEND;
170*10465441SEvalZero 
171*10465441SEvalZero                 flags &= mask;
172*10465441SEvalZero                 fd->flags &= ~mask;
173*10465441SEvalZero                 fd->flags |= flags;
174*10465441SEvalZero             }
175*10465441SEvalZero             return 0;
176*10465441SEvalZero         }
177*10465441SEvalZero     }
178*10465441SEvalZero 
179*10465441SEvalZero     if (fd->fops->ioctl != NULL)
180*10465441SEvalZero         return fd->fops->ioctl(fd, cmd, args);
181*10465441SEvalZero 
182*10465441SEvalZero     return -ENOSYS;
183*10465441SEvalZero }
184*10465441SEvalZero 
185*10465441SEvalZero /**
186*10465441SEvalZero  * this function will read specified length data from a file descriptor to a
187*10465441SEvalZero  * buffer.
188*10465441SEvalZero  *
189*10465441SEvalZero  * @param fd the file descriptor.
190*10465441SEvalZero  * @param buf the buffer to save the read data.
191*10465441SEvalZero  * @param len the length of data buffer to be read.
192*10465441SEvalZero  *
193*10465441SEvalZero  * @return the actual read data bytes or 0 on end of file or failed.
194*10465441SEvalZero  */
dfs_file_read(struct dfs_fd * fd,void * buf,size_t len)195*10465441SEvalZero int dfs_file_read(struct dfs_fd *fd, void *buf, size_t len)
196*10465441SEvalZero {
197*10465441SEvalZero     int result = 0;
198*10465441SEvalZero 
199*10465441SEvalZero     if (fd == NULL)
200*10465441SEvalZero         return -EINVAL;
201*10465441SEvalZero 
202*10465441SEvalZero     if (fd->fops->read == NULL)
203*10465441SEvalZero         return -ENOSYS;
204*10465441SEvalZero 
205*10465441SEvalZero     if ((result = fd->fops->read(fd, buf, len)) < 0)
206*10465441SEvalZero         fd->flags |= DFS_F_EOF;
207*10465441SEvalZero 
208*10465441SEvalZero     return result;
209*10465441SEvalZero }
210*10465441SEvalZero 
211*10465441SEvalZero /**
212*10465441SEvalZero  * this function will fetch directory entries from a directory descriptor.
213*10465441SEvalZero  *
214*10465441SEvalZero  * @param fd the directory descriptor.
215*10465441SEvalZero  * @param dirp the dirent buffer to save result.
216*10465441SEvalZero  * @param nbytes the available room in the buffer.
217*10465441SEvalZero  *
218*10465441SEvalZero  * @return the read dirent, others on failed.
219*10465441SEvalZero  */
dfs_file_getdents(struct dfs_fd * fd,struct dirent * dirp,size_t nbytes)220*10465441SEvalZero int dfs_file_getdents(struct dfs_fd *fd, struct dirent *dirp, size_t nbytes)
221*10465441SEvalZero {
222*10465441SEvalZero     /* parameter check */
223*10465441SEvalZero     if (fd == NULL || fd->type != FT_DIRECTORY)
224*10465441SEvalZero         return -EINVAL;
225*10465441SEvalZero 
226*10465441SEvalZero     if (fd->fops->getdents != NULL)
227*10465441SEvalZero         return fd->fops->getdents(fd, dirp, nbytes);
228*10465441SEvalZero 
229*10465441SEvalZero     return -ENOSYS;
230*10465441SEvalZero }
231*10465441SEvalZero 
232*10465441SEvalZero /**
233*10465441SEvalZero  * this function will unlink (remove) a specified path file from file system.
234*10465441SEvalZero  *
235*10465441SEvalZero  * @param path the specified path file to be unlinked.
236*10465441SEvalZero  *
237*10465441SEvalZero  * @return 0 on successful, -1 on failed.
238*10465441SEvalZero  */
dfs_file_unlink(const char * path)239*10465441SEvalZero int dfs_file_unlink(const char *path)
240*10465441SEvalZero {
241*10465441SEvalZero     int result;
242*10465441SEvalZero     char *fullpath;
243*10465441SEvalZero     struct dfs_filesystem *fs;
244*10465441SEvalZero 
245*10465441SEvalZero     /* Make sure we have an absolute path */
246*10465441SEvalZero     fullpath = dfs_normalize_path(NULL, path);
247*10465441SEvalZero     if (fullpath == NULL)
248*10465441SEvalZero     {
249*10465441SEvalZero         return -EINVAL;
250*10465441SEvalZero     }
251*10465441SEvalZero 
252*10465441SEvalZero     /* get filesystem */
253*10465441SEvalZero     if ((fs = dfs_filesystem_lookup(fullpath)) == NULL)
254*10465441SEvalZero     {
255*10465441SEvalZero         result = -ENOENT;
256*10465441SEvalZero         goto __exit;
257*10465441SEvalZero     }
258*10465441SEvalZero 
259*10465441SEvalZero     /* Check whether file is already open */
260*10465441SEvalZero     if (fd_is_open(fullpath) == 0)
261*10465441SEvalZero     {
262*10465441SEvalZero         result = -EBUSY;
263*10465441SEvalZero         goto __exit;
264*10465441SEvalZero     }
265*10465441SEvalZero 
266*10465441SEvalZero     if (fs->ops->unlink != NULL)
267*10465441SEvalZero     {
268*10465441SEvalZero         if (!(fs->ops->flags & DFS_FS_FLAG_FULLPATH))
269*10465441SEvalZero         {
270*10465441SEvalZero             if (dfs_subdir(fs->path, fullpath) == NULL)
271*10465441SEvalZero                 result = fs->ops->unlink(fs, "/");
272*10465441SEvalZero             else
273*10465441SEvalZero                 result = fs->ops->unlink(fs, dfs_subdir(fs->path, fullpath));
274*10465441SEvalZero         }
275*10465441SEvalZero         else
276*10465441SEvalZero             result = fs->ops->unlink(fs, fullpath);
277*10465441SEvalZero     }
278*10465441SEvalZero     else result = -ENOSYS;
279*10465441SEvalZero 
280*10465441SEvalZero __exit:
281*10465441SEvalZero     rt_free(fullpath);
282*10465441SEvalZero     return result;
283*10465441SEvalZero }
284*10465441SEvalZero 
285*10465441SEvalZero /**
286*10465441SEvalZero  * this function will write some specified length data to file system.
287*10465441SEvalZero  *
288*10465441SEvalZero  * @param fd the file descriptor.
289*10465441SEvalZero  * @param buf the data buffer to be written.
290*10465441SEvalZero  * @param len the data buffer length
291*10465441SEvalZero  *
292*10465441SEvalZero  * @return the actual written data length.
293*10465441SEvalZero  */
dfs_file_write(struct dfs_fd * fd,const void * buf,size_t len)294*10465441SEvalZero int dfs_file_write(struct dfs_fd *fd, const void *buf, size_t len)
295*10465441SEvalZero {
296*10465441SEvalZero     if (fd == NULL)
297*10465441SEvalZero         return -EINVAL;
298*10465441SEvalZero 
299*10465441SEvalZero     if (fd->fops->write == NULL)
300*10465441SEvalZero         return -ENOSYS;
301*10465441SEvalZero 
302*10465441SEvalZero     return fd->fops->write(fd, buf, len);
303*10465441SEvalZero }
304*10465441SEvalZero 
305*10465441SEvalZero /**
306*10465441SEvalZero  * this function will flush buffer on a file descriptor.
307*10465441SEvalZero  *
308*10465441SEvalZero  * @param fd the file descriptor.
309*10465441SEvalZero  *
310*10465441SEvalZero  * @return 0 on successful, -1 on failed.
311*10465441SEvalZero  */
dfs_file_flush(struct dfs_fd * fd)312*10465441SEvalZero int dfs_file_flush(struct dfs_fd *fd)
313*10465441SEvalZero {
314*10465441SEvalZero     if (fd == NULL)
315*10465441SEvalZero         return -EINVAL;
316*10465441SEvalZero 
317*10465441SEvalZero     if (fd->fops->flush == NULL)
318*10465441SEvalZero         return -ENOSYS;
319*10465441SEvalZero 
320*10465441SEvalZero     return fd->fops->flush(fd);
321*10465441SEvalZero }
322*10465441SEvalZero 
323*10465441SEvalZero /**
324*10465441SEvalZero  * this function will seek the offset for specified file descriptor.
325*10465441SEvalZero  *
326*10465441SEvalZero  * @param fd the file descriptor.
327*10465441SEvalZero  * @param offset the offset to be sought.
328*10465441SEvalZero  *
329*10465441SEvalZero  * @return the current position after seek.
330*10465441SEvalZero  */
dfs_file_lseek(struct dfs_fd * fd,off_t offset)331*10465441SEvalZero int dfs_file_lseek(struct dfs_fd *fd, off_t offset)
332*10465441SEvalZero {
333*10465441SEvalZero     int result;
334*10465441SEvalZero 
335*10465441SEvalZero     if (fd == NULL)
336*10465441SEvalZero         return -EINVAL;
337*10465441SEvalZero 
338*10465441SEvalZero     if (fd->fops->lseek == NULL)
339*10465441SEvalZero         return -ENOSYS;
340*10465441SEvalZero 
341*10465441SEvalZero     result = fd->fops->lseek(fd, offset);
342*10465441SEvalZero 
343*10465441SEvalZero     /* update current position */
344*10465441SEvalZero     if (result >= 0)
345*10465441SEvalZero         fd->pos = result;
346*10465441SEvalZero 
347*10465441SEvalZero     return result;
348*10465441SEvalZero }
349*10465441SEvalZero 
350*10465441SEvalZero /**
351*10465441SEvalZero  * this function will get file information.
352*10465441SEvalZero  *
353*10465441SEvalZero  * @param path the file path.
354*10465441SEvalZero  * @param buf the data buffer to save stat description.
355*10465441SEvalZero  *
356*10465441SEvalZero  * @return 0 on successful, -1 on failed.
357*10465441SEvalZero  */
dfs_file_stat(const char * path,struct stat * buf)358*10465441SEvalZero int dfs_file_stat(const char *path, struct stat *buf)
359*10465441SEvalZero {
360*10465441SEvalZero     int result;
361*10465441SEvalZero     char *fullpath;
362*10465441SEvalZero     struct dfs_filesystem *fs;
363*10465441SEvalZero 
364*10465441SEvalZero     fullpath = dfs_normalize_path(NULL, path);
365*10465441SEvalZero     if (fullpath == NULL)
366*10465441SEvalZero     {
367*10465441SEvalZero         return -1;
368*10465441SEvalZero     }
369*10465441SEvalZero 
370*10465441SEvalZero     if ((fs = dfs_filesystem_lookup(fullpath)) == NULL)
371*10465441SEvalZero     {
372*10465441SEvalZero         LOG_E(
373*10465441SEvalZero                 "can't find mounted filesystem on this path:%s", fullpath);
374*10465441SEvalZero         rt_free(fullpath);
375*10465441SEvalZero 
376*10465441SEvalZero         return -ENOENT;
377*10465441SEvalZero     }
378*10465441SEvalZero 
379*10465441SEvalZero     if ((fullpath[0] == '/' && fullpath[1] == '\0') ||
380*10465441SEvalZero         (dfs_subdir(fs->path, fullpath) == NULL))
381*10465441SEvalZero     {
382*10465441SEvalZero         /* it's the root directory */
383*10465441SEvalZero         buf->st_dev   = 0;
384*10465441SEvalZero 
385*10465441SEvalZero         buf->st_mode  = S_IRUSR | S_IRGRP | S_IROTH |
386*10465441SEvalZero                         S_IWUSR | S_IWGRP | S_IWOTH;
387*10465441SEvalZero         buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
388*10465441SEvalZero 
389*10465441SEvalZero         buf->st_size    = 0;
390*10465441SEvalZero         buf->st_mtime   = 0;
391*10465441SEvalZero 
392*10465441SEvalZero         /* release full path */
393*10465441SEvalZero         rt_free(fullpath);
394*10465441SEvalZero 
395*10465441SEvalZero         return RT_EOK;
396*10465441SEvalZero     }
397*10465441SEvalZero     else
398*10465441SEvalZero     {
399*10465441SEvalZero         if (fs->ops->stat == NULL)
400*10465441SEvalZero         {
401*10465441SEvalZero             rt_free(fullpath);
402*10465441SEvalZero             LOG_E(
403*10465441SEvalZero                     "the filesystem didn't implement this function");
404*10465441SEvalZero 
405*10465441SEvalZero             return -ENOSYS;
406*10465441SEvalZero         }
407*10465441SEvalZero 
408*10465441SEvalZero         /* get the real file path and get file stat */
409*10465441SEvalZero         if (fs->ops->flags & DFS_FS_FLAG_FULLPATH)
410*10465441SEvalZero             result = fs->ops->stat(fs, fullpath, buf);
411*10465441SEvalZero         else
412*10465441SEvalZero             result = fs->ops->stat(fs, dfs_subdir(fs->path, fullpath), buf);
413*10465441SEvalZero     }
414*10465441SEvalZero 
415*10465441SEvalZero     rt_free(fullpath);
416*10465441SEvalZero 
417*10465441SEvalZero     return result;
418*10465441SEvalZero }
419*10465441SEvalZero 
420*10465441SEvalZero /**
421*10465441SEvalZero  * this function will rename an old path name to a new path name.
422*10465441SEvalZero  *
423*10465441SEvalZero  * @param oldpath the old path name.
424*10465441SEvalZero  * @param newpath the new path name.
425*10465441SEvalZero  *
426*10465441SEvalZero  * @return 0 on successful, -1 on failed.
427*10465441SEvalZero  */
dfs_file_rename(const char * oldpath,const char * newpath)428*10465441SEvalZero int dfs_file_rename(const char *oldpath, const char *newpath)
429*10465441SEvalZero {
430*10465441SEvalZero     int result;
431*10465441SEvalZero     struct dfs_filesystem *oldfs, *newfs;
432*10465441SEvalZero     char *oldfullpath, *newfullpath;
433*10465441SEvalZero 
434*10465441SEvalZero     result = RT_EOK;
435*10465441SEvalZero     newfullpath = NULL;
436*10465441SEvalZero     oldfullpath = NULL;
437*10465441SEvalZero 
438*10465441SEvalZero     oldfullpath = dfs_normalize_path(NULL, oldpath);
439*10465441SEvalZero     if (oldfullpath == NULL)
440*10465441SEvalZero     {
441*10465441SEvalZero         result = -ENOENT;
442*10465441SEvalZero         goto __exit;
443*10465441SEvalZero     }
444*10465441SEvalZero 
445*10465441SEvalZero     newfullpath = dfs_normalize_path(NULL, newpath);
446*10465441SEvalZero     if (newfullpath == NULL)
447*10465441SEvalZero     {
448*10465441SEvalZero         result = -ENOENT;
449*10465441SEvalZero         goto __exit;
450*10465441SEvalZero     }
451*10465441SEvalZero 
452*10465441SEvalZero     oldfs = dfs_filesystem_lookup(oldfullpath);
453*10465441SEvalZero     newfs = dfs_filesystem_lookup(newfullpath);
454*10465441SEvalZero 
455*10465441SEvalZero     if (oldfs == newfs)
456*10465441SEvalZero     {
457*10465441SEvalZero         if (oldfs->ops->rename == NULL)
458*10465441SEvalZero         {
459*10465441SEvalZero             result = -ENOSYS;
460*10465441SEvalZero         }
461*10465441SEvalZero         else
462*10465441SEvalZero         {
463*10465441SEvalZero             if (oldfs->ops->flags & DFS_FS_FLAG_FULLPATH)
464*10465441SEvalZero                 result = oldfs->ops->rename(oldfs, oldfullpath, newfullpath);
465*10465441SEvalZero             else
466*10465441SEvalZero                 /* use sub directory to rename in file system */
467*10465441SEvalZero                 result = oldfs->ops->rename(oldfs,
468*10465441SEvalZero                                             dfs_subdir(oldfs->path, oldfullpath),
469*10465441SEvalZero                                             dfs_subdir(newfs->path, newfullpath));
470*10465441SEvalZero         }
471*10465441SEvalZero     }
472*10465441SEvalZero     else
473*10465441SEvalZero     {
474*10465441SEvalZero         result = -EXDEV;
475*10465441SEvalZero     }
476*10465441SEvalZero 
477*10465441SEvalZero __exit:
478*10465441SEvalZero     rt_free(oldfullpath);
479*10465441SEvalZero     rt_free(newfullpath);
480*10465441SEvalZero 
481*10465441SEvalZero     /* not at same file system, return EXDEV */
482*10465441SEvalZero     return result;
483*10465441SEvalZero }
484*10465441SEvalZero 
485*10465441SEvalZero #ifdef RT_USING_FINSH
486*10465441SEvalZero #include <finsh.h>
487*10465441SEvalZero 
488*10465441SEvalZero static struct dfs_fd fd;
489*10465441SEvalZero static struct dirent dirent;
ls(const char * pathname)490*10465441SEvalZero void ls(const char *pathname)
491*10465441SEvalZero {
492*10465441SEvalZero     struct stat stat;
493*10465441SEvalZero     int length;
494*10465441SEvalZero     char *fullpath, *path;
495*10465441SEvalZero 
496*10465441SEvalZero     fullpath = NULL;
497*10465441SEvalZero     if (pathname == NULL)
498*10465441SEvalZero     {
499*10465441SEvalZero #ifdef DFS_USING_WORKDIR
500*10465441SEvalZero         /* open current working directory */
501*10465441SEvalZero         path = rt_strdup(working_directory);
502*10465441SEvalZero #else
503*10465441SEvalZero         path = rt_strdup("/");
504*10465441SEvalZero #endif
505*10465441SEvalZero         if (path == NULL)
506*10465441SEvalZero             return ; /* out of memory */
507*10465441SEvalZero     }
508*10465441SEvalZero     else
509*10465441SEvalZero     {
510*10465441SEvalZero         path = (char *)pathname;
511*10465441SEvalZero     }
512*10465441SEvalZero 
513*10465441SEvalZero     /* list directory */
514*10465441SEvalZero     if (dfs_file_open(&fd, path, O_DIRECTORY) == 0)
515*10465441SEvalZero     {
516*10465441SEvalZero         rt_kprintf("Directory %s:\n", path);
517*10465441SEvalZero         do
518*10465441SEvalZero         {
519*10465441SEvalZero             memset(&dirent, 0, sizeof(struct dirent));
520*10465441SEvalZero             length = dfs_file_getdents(&fd, &dirent, sizeof(struct dirent));
521*10465441SEvalZero             if (length > 0)
522*10465441SEvalZero             {
523*10465441SEvalZero                 memset(&stat, 0, sizeof(struct stat));
524*10465441SEvalZero 
525*10465441SEvalZero                 /* build full path for each file */
526*10465441SEvalZero                 fullpath = dfs_normalize_path(path, dirent.d_name);
527*10465441SEvalZero                 if (fullpath == NULL)
528*10465441SEvalZero                     break;
529*10465441SEvalZero 
530*10465441SEvalZero                 if (dfs_file_stat(fullpath, &stat) == 0)
531*10465441SEvalZero                 {
532*10465441SEvalZero                     rt_kprintf("%-20s", dirent.d_name);
533*10465441SEvalZero                     if (S_ISDIR(stat.st_mode))
534*10465441SEvalZero                     {
535*10465441SEvalZero                         rt_kprintf("%-25s\n", "<DIR>");
536*10465441SEvalZero                     }
537*10465441SEvalZero                     else
538*10465441SEvalZero                     {
539*10465441SEvalZero                         rt_kprintf("%-25lu\n", stat.st_size);
540*10465441SEvalZero                     }
541*10465441SEvalZero                 }
542*10465441SEvalZero                 else
543*10465441SEvalZero                     rt_kprintf("BAD file: %s\n", dirent.d_name);
544*10465441SEvalZero                 rt_free(fullpath);
545*10465441SEvalZero             }
546*10465441SEvalZero         }while(length > 0);
547*10465441SEvalZero 
548*10465441SEvalZero         dfs_file_close(&fd);
549*10465441SEvalZero     }
550*10465441SEvalZero     else
551*10465441SEvalZero     {
552*10465441SEvalZero         rt_kprintf("No such directory\n");
553*10465441SEvalZero     }
554*10465441SEvalZero     if (pathname == NULL)
555*10465441SEvalZero         rt_free(path);
556*10465441SEvalZero }
557*10465441SEvalZero FINSH_FUNCTION_EXPORT(ls, list directory contents);
558*10465441SEvalZero 
rm(const char * filename)559*10465441SEvalZero void rm(const char *filename)
560*10465441SEvalZero {
561*10465441SEvalZero     if (dfs_file_unlink(filename) < 0)
562*10465441SEvalZero     {
563*10465441SEvalZero         rt_kprintf("Delete %s failed\n", filename);
564*10465441SEvalZero     }
565*10465441SEvalZero }
566*10465441SEvalZero FINSH_FUNCTION_EXPORT(rm, remove files or directories);
567*10465441SEvalZero 
cat(const char * filename)568*10465441SEvalZero void cat(const char* filename)
569*10465441SEvalZero {
570*10465441SEvalZero     uint32_t length;
571*10465441SEvalZero     char buffer[81];
572*10465441SEvalZero 
573*10465441SEvalZero     if (dfs_file_open(&fd, filename, O_RDONLY) < 0)
574*10465441SEvalZero     {
575*10465441SEvalZero         rt_kprintf("Open %s failed\n", filename);
576*10465441SEvalZero 
577*10465441SEvalZero         return;
578*10465441SEvalZero     }
579*10465441SEvalZero 
580*10465441SEvalZero     do
581*10465441SEvalZero     {
582*10465441SEvalZero         memset(buffer, 0, sizeof(buffer));
583*10465441SEvalZero         length = dfs_file_read(&fd, buffer, sizeof(buffer)-1 );
584*10465441SEvalZero         if (length > 0)
585*10465441SEvalZero         {
586*10465441SEvalZero             rt_kprintf("%s", buffer);
587*10465441SEvalZero         }
588*10465441SEvalZero     }while (length > 0);
589*10465441SEvalZero 
590*10465441SEvalZero     dfs_file_close(&fd);
591*10465441SEvalZero }
592*10465441SEvalZero FINSH_FUNCTION_EXPORT(cat, print file);
593*10465441SEvalZero 
594*10465441SEvalZero #define BUF_SZ  4096
copyfile(const char * src,const char * dst)595*10465441SEvalZero static void copyfile(const char *src, const char *dst)
596*10465441SEvalZero {
597*10465441SEvalZero     struct dfs_fd src_fd;
598*10465441SEvalZero     rt_uint8_t *block_ptr;
599*10465441SEvalZero     rt_int32_t read_bytes;
600*10465441SEvalZero 
601*10465441SEvalZero     block_ptr = rt_malloc(BUF_SZ);
602*10465441SEvalZero     if (block_ptr == NULL)
603*10465441SEvalZero     {
604*10465441SEvalZero         rt_kprintf("out of memory\n");
605*10465441SEvalZero 
606*10465441SEvalZero         return;
607*10465441SEvalZero     }
608*10465441SEvalZero 
609*10465441SEvalZero     if (dfs_file_open(&src_fd, src, O_RDONLY) < 0)
610*10465441SEvalZero     {
611*10465441SEvalZero         rt_free(block_ptr);
612*10465441SEvalZero         rt_kprintf("Read %s failed\n", src);
613*10465441SEvalZero 
614*10465441SEvalZero         return;
615*10465441SEvalZero     }
616*10465441SEvalZero     if (dfs_file_open(&fd, dst, O_WRONLY | O_CREAT) < 0)
617*10465441SEvalZero     {
618*10465441SEvalZero         rt_free(block_ptr);
619*10465441SEvalZero         dfs_file_close(&src_fd);
620*10465441SEvalZero 
621*10465441SEvalZero         rt_kprintf("Write %s failed\n", dst);
622*10465441SEvalZero 
623*10465441SEvalZero         return;
624*10465441SEvalZero     }
625*10465441SEvalZero 
626*10465441SEvalZero     do
627*10465441SEvalZero     {
628*10465441SEvalZero         read_bytes = dfs_file_read(&src_fd, block_ptr, BUF_SZ);
629*10465441SEvalZero         if (read_bytes > 0)
630*10465441SEvalZero         {
631*10465441SEvalZero             int length;
632*10465441SEvalZero 
633*10465441SEvalZero             length = dfs_file_write(&fd, block_ptr, read_bytes);
634*10465441SEvalZero             if (length != read_bytes)
635*10465441SEvalZero             {
636*10465441SEvalZero                 /* write failed. */
637*10465441SEvalZero                 rt_kprintf("Write file data failed, errno=%d\n", length);
638*10465441SEvalZero                 break;
639*10465441SEvalZero             }
640*10465441SEvalZero         }
641*10465441SEvalZero     } while (read_bytes > 0);
642*10465441SEvalZero 
643*10465441SEvalZero     dfs_file_close(&src_fd);
644*10465441SEvalZero     dfs_file_close(&fd);
645*10465441SEvalZero     rt_free(block_ptr);
646*10465441SEvalZero }
647*10465441SEvalZero 
648*10465441SEvalZero extern int mkdir(const char *path, mode_t mode);
copydir(const char * src,const char * dst)649*10465441SEvalZero static void copydir(const char * src, const char * dst)
650*10465441SEvalZero {
651*10465441SEvalZero     struct dirent dirent;
652*10465441SEvalZero     struct stat stat;
653*10465441SEvalZero     int length;
654*10465441SEvalZero     struct dfs_fd cpfd;
655*10465441SEvalZero     if (dfs_file_open(&cpfd, src, O_DIRECTORY) < 0)
656*10465441SEvalZero     {
657*10465441SEvalZero         rt_kprintf("open %s failed\n", src);
658*10465441SEvalZero         return ;
659*10465441SEvalZero     }
660*10465441SEvalZero 
661*10465441SEvalZero     do
662*10465441SEvalZero     {
663*10465441SEvalZero         memset(&dirent, 0, sizeof(struct dirent));
664*10465441SEvalZero 
665*10465441SEvalZero         length = dfs_file_getdents(&cpfd, &dirent, sizeof(struct dirent));
666*10465441SEvalZero         if (length > 0)
667*10465441SEvalZero         {
668*10465441SEvalZero             char * src_entry_full = NULL;
669*10465441SEvalZero             char * dst_entry_full = NULL;
670*10465441SEvalZero 
671*10465441SEvalZero             if (strcmp(dirent.d_name, "..") == 0 || strcmp(dirent.d_name, ".") == 0)
672*10465441SEvalZero                 continue;
673*10465441SEvalZero 
674*10465441SEvalZero             /* build full path for each file */
675*10465441SEvalZero             if ((src_entry_full = dfs_normalize_path(src, dirent.d_name)) == NULL)
676*10465441SEvalZero             {
677*10465441SEvalZero                 rt_kprintf("out of memory!\n");
678*10465441SEvalZero                 break;
679*10465441SEvalZero             }
680*10465441SEvalZero             if ((dst_entry_full = dfs_normalize_path(dst, dirent.d_name)) == NULL)
681*10465441SEvalZero             {
682*10465441SEvalZero                 rt_kprintf("out of memory!\n");
683*10465441SEvalZero                 rt_free(src_entry_full);
684*10465441SEvalZero                 break;
685*10465441SEvalZero             }
686*10465441SEvalZero 
687*10465441SEvalZero             memset(&stat, 0, sizeof(struct stat));
688*10465441SEvalZero             if (dfs_file_stat(src_entry_full, &stat) != 0)
689*10465441SEvalZero             {
690*10465441SEvalZero                 rt_kprintf("open file: %s failed\n", dirent.d_name);
691*10465441SEvalZero                 continue;
692*10465441SEvalZero             }
693*10465441SEvalZero 
694*10465441SEvalZero             if (S_ISDIR(stat.st_mode))
695*10465441SEvalZero             {
696*10465441SEvalZero                 mkdir(dst_entry_full, 0);
697*10465441SEvalZero                 copydir(src_entry_full, dst_entry_full);
698*10465441SEvalZero             }
699*10465441SEvalZero             else
700*10465441SEvalZero             {
701*10465441SEvalZero                 copyfile(src_entry_full, dst_entry_full);
702*10465441SEvalZero             }
703*10465441SEvalZero             rt_free(src_entry_full);
704*10465441SEvalZero             rt_free(dst_entry_full);
705*10465441SEvalZero         }
706*10465441SEvalZero     }while(length > 0);
707*10465441SEvalZero 
708*10465441SEvalZero     dfs_file_close(&cpfd);
709*10465441SEvalZero }
710*10465441SEvalZero 
_get_path_lastname(const char * path)711*10465441SEvalZero static const char *_get_path_lastname(const char *path)
712*10465441SEvalZero {
713*10465441SEvalZero     char * ptr;
714*10465441SEvalZero     if ((ptr = strrchr(path, '/')) == NULL)
715*10465441SEvalZero         return path;
716*10465441SEvalZero 
717*10465441SEvalZero     /* skip the '/' then return */
718*10465441SEvalZero     return ++ptr;
719*10465441SEvalZero }
copy(const char * src,const char * dst)720*10465441SEvalZero void copy(const char *src, const char *dst)
721*10465441SEvalZero {
722*10465441SEvalZero #define FLAG_SRC_TYPE      0x03
723*10465441SEvalZero #define FLAG_SRC_IS_DIR    0x01
724*10465441SEvalZero #define FLAG_SRC_IS_FILE   0x02
725*10465441SEvalZero #define FLAG_SRC_NON_EXSIT 0x00
726*10465441SEvalZero 
727*10465441SEvalZero #define FLAG_DST_TYPE      0x0C
728*10465441SEvalZero #define FLAG_DST_IS_DIR    0x04
729*10465441SEvalZero #define FLAG_DST_IS_FILE   0x08
730*10465441SEvalZero #define FLAG_DST_NON_EXSIT 0x00
731*10465441SEvalZero 
732*10465441SEvalZero     struct stat stat;
733*10465441SEvalZero     uint32_t flag = 0;
734*10465441SEvalZero 
735*10465441SEvalZero     /* check the staus of src and dst */
736*10465441SEvalZero     if (dfs_file_stat(src, &stat) < 0)
737*10465441SEvalZero     {
738*10465441SEvalZero         rt_kprintf("copy failed, bad %s\n", src);
739*10465441SEvalZero         return;
740*10465441SEvalZero     }
741*10465441SEvalZero     if (S_ISDIR(stat.st_mode))
742*10465441SEvalZero         flag |= FLAG_SRC_IS_DIR;
743*10465441SEvalZero     else
744*10465441SEvalZero         flag |= FLAG_SRC_IS_FILE;
745*10465441SEvalZero 
746*10465441SEvalZero     if (dfs_file_stat(dst, &stat) < 0)
747*10465441SEvalZero     {
748*10465441SEvalZero         flag |= FLAG_DST_NON_EXSIT;
749*10465441SEvalZero     }
750*10465441SEvalZero     else
751*10465441SEvalZero     {
752*10465441SEvalZero         if (S_ISDIR(stat.st_mode))
753*10465441SEvalZero             flag |= FLAG_DST_IS_DIR;
754*10465441SEvalZero         else
755*10465441SEvalZero             flag |= FLAG_DST_IS_FILE;
756*10465441SEvalZero     }
757*10465441SEvalZero 
758*10465441SEvalZero     //2. check status
759*10465441SEvalZero     if ((flag & FLAG_SRC_IS_DIR) && (flag & FLAG_DST_IS_FILE))
760*10465441SEvalZero     {
761*10465441SEvalZero         rt_kprintf("cp faild, cp dir to file is not permitted!\n");
762*10465441SEvalZero         return ;
763*10465441SEvalZero     }
764*10465441SEvalZero 
765*10465441SEvalZero     //3. do copy
766*10465441SEvalZero     if (flag & FLAG_SRC_IS_FILE)
767*10465441SEvalZero     {
768*10465441SEvalZero         if (flag & FLAG_DST_IS_DIR)
769*10465441SEvalZero         {
770*10465441SEvalZero             char * fdst;
771*10465441SEvalZero             fdst = dfs_normalize_path(dst, _get_path_lastname(src));
772*10465441SEvalZero             if (fdst == NULL)
773*10465441SEvalZero             {
774*10465441SEvalZero                 rt_kprintf("out of memory\n");
775*10465441SEvalZero                 return;
776*10465441SEvalZero             }
777*10465441SEvalZero             copyfile(src, fdst);
778*10465441SEvalZero             rt_free(fdst);
779*10465441SEvalZero         }
780*10465441SEvalZero         else
781*10465441SEvalZero         {
782*10465441SEvalZero             copyfile(src, dst);
783*10465441SEvalZero         }
784*10465441SEvalZero     }
785*10465441SEvalZero     else //flag & FLAG_SRC_IS_DIR
786*10465441SEvalZero     {
787*10465441SEvalZero         if (flag & FLAG_DST_IS_DIR)
788*10465441SEvalZero         {
789*10465441SEvalZero             char * fdst;
790*10465441SEvalZero             fdst = dfs_normalize_path(dst, _get_path_lastname(src));
791*10465441SEvalZero             if (fdst == NULL)
792*10465441SEvalZero             {
793*10465441SEvalZero                 rt_kprintf("out of memory\n");
794*10465441SEvalZero                 return;
795*10465441SEvalZero             }
796*10465441SEvalZero             mkdir(fdst, 0);
797*10465441SEvalZero             copydir(src, fdst);
798*10465441SEvalZero             rt_free(fdst);
799*10465441SEvalZero         }
800*10465441SEvalZero         else if ((flag & FLAG_DST_TYPE) == FLAG_DST_NON_EXSIT)
801*10465441SEvalZero         {
802*10465441SEvalZero             mkdir(dst, 0);
803*10465441SEvalZero             copydir(src, dst);
804*10465441SEvalZero         }
805*10465441SEvalZero         else
806*10465441SEvalZero         {
807*10465441SEvalZero             copydir(src, dst);
808*10465441SEvalZero         }
809*10465441SEvalZero     }
810*10465441SEvalZero }
811*10465441SEvalZero FINSH_FUNCTION_EXPORT(copy, copy file or dir)
812*10465441SEvalZero 
813*10465441SEvalZero #endif
814*10465441SEvalZero /* @} */
815*10465441SEvalZero 
816