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