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 * 2011-10-22 prife the first version
9*10465441SEvalZero * 2012-03-28 prife use mtd device interface
10*10465441SEvalZero * 2012-04-05 prife update uffs with official repo and use uffs_UnMount/Mount
11*10465441SEvalZero * 2017-04-12 lizhen9880 fix the f_bsize and f_blocks issue in function dfs_uffs_statfs
12*10465441SEvalZero */
13*10465441SEvalZero
14*10465441SEvalZero #include <rtthread.h>
15*10465441SEvalZero
16*10465441SEvalZero #include <dfs_fs.h>
17*10465441SEvalZero #include <dfs_file.h>
18*10465441SEvalZero #include <rtdevice.h>
19*10465441SEvalZero
20*10465441SEvalZero #include "dfs_uffs.h"
21*10465441SEvalZero
22*10465441SEvalZero #include "uffs/uffs_fd.h" /* posix file api is here */
23*10465441SEvalZero #include "uffs/uffs_mtb.h"
24*10465441SEvalZero #include "uffs/uffs_mem.h"
25*10465441SEvalZero #include "uffs/uffs_utils.h"
26*10465441SEvalZero
27*10465441SEvalZero /*
28*10465441SEvalZero * RT-Thread DFS Interface for uffs
29*10465441SEvalZero */
30*10465441SEvalZero #define UFFS_DEVICE_MAX 2 /* the max partions on a nand deivce*/
31*10465441SEvalZero #define UFFS_MOUNT_PATH_MAX 128 /* the mount point max length */
32*10465441SEvalZero #define FILE_PATH_MAX 256 /* the longest file path */
33*10465441SEvalZero
34*10465441SEvalZero struct _nand_dev
35*10465441SEvalZero {
36*10465441SEvalZero struct rt_mtd_nand_device * dev;
37*10465441SEvalZero struct uffs_StorageAttrSt storage;
38*10465441SEvalZero uffs_Device uffs_dev;
39*10465441SEvalZero uffs_MountTable mount_table;
40*10465441SEvalZero char mount_path[UFFS_MOUNT_PATH_MAX];
41*10465441SEvalZero void * data; /* when uffs use static buf, it will save ptr here */
42*10465441SEvalZero };
43*10465441SEvalZero /* make sure the following struct var had been initilased to 0! */
44*10465441SEvalZero static struct _nand_dev nand_part[UFFS_DEVICE_MAX] = {0};
45*10465441SEvalZero
uffs_result_to_dfs(int result)46*10465441SEvalZero static int uffs_result_to_dfs(int result)
47*10465441SEvalZero {
48*10465441SEvalZero int status = -1;
49*10465441SEvalZero
50*10465441SEvalZero result = result < 0 ? -result : result;
51*10465441SEvalZero switch (result)
52*10465441SEvalZero {
53*10465441SEvalZero case UENOERR:/** no error */
54*10465441SEvalZero break;
55*10465441SEvalZero case UEACCES:/** Tried to open read-only file for writing, or files sharing mode
56*10465441SEvalZero does not allow specified operations, or given path is directory */
57*10465441SEvalZero status = -EINVAL;
58*10465441SEvalZero break;/* no suitable */
59*10465441SEvalZero case UEEXIST: /** _O_CREAT and _O_EXCL flags specified, but filename already exists */
60*10465441SEvalZero status = -EEXIST;
61*10465441SEvalZero break;
62*10465441SEvalZero case UEINVAL: /** Invalid oflag or pmode argument */
63*10465441SEvalZero status = -EINVAL;
64*10465441SEvalZero break;
65*10465441SEvalZero case UEMFILE: /** No more file handles available(too many open files) */
66*10465441SEvalZero status = -1;
67*10465441SEvalZero break;
68*10465441SEvalZero case UENOENT: /** file or path not found */
69*10465441SEvalZero status = -ENOENT;
70*10465441SEvalZero break;
71*10465441SEvalZero case UETIME: /** can't set file time */
72*10465441SEvalZero status = -1;
73*10465441SEvalZero break;
74*10465441SEvalZero case UEBADF: /** invalid file handle */
75*10465441SEvalZero status = -EBADF;
76*10465441SEvalZero break;
77*10465441SEvalZero case UENOMEM:/** no enough memory */
78*10465441SEvalZero status = -ENOSPC;
79*10465441SEvalZero break;
80*10465441SEvalZero case UEIOERR: /** I/O error from lower level flash operation */
81*10465441SEvalZero status = -EIO;
82*10465441SEvalZero break;
83*10465441SEvalZero case UENOTDIR: /** Not a directory */
84*10465441SEvalZero status = -ENOTDIR;
85*10465441SEvalZero break;
86*10465441SEvalZero case UEISDIR: /** Is a directory */
87*10465441SEvalZero status = -EISDIR;
88*10465441SEvalZero break;
89*10465441SEvalZero case UEUNKNOWN_ERR:
90*10465441SEvalZero default:
91*10465441SEvalZero status = -1;
92*10465441SEvalZero break; /* unknown error! */
93*10465441SEvalZero }
94*10465441SEvalZero
95*10465441SEvalZero return status;
96*10465441SEvalZero }
97*10465441SEvalZero
_device_init(uffs_Device * dev)98*10465441SEvalZero static URET _device_init(uffs_Device *dev)
99*10465441SEvalZero {
100*10465441SEvalZero dev->attr->_private = NULL; // hook nand_chip data structure to attr->_private
101*10465441SEvalZero dev->ops = (struct uffs_FlashOpsSt *)&nand_ops;
102*10465441SEvalZero
103*10465441SEvalZero return U_SUCC;
104*10465441SEvalZero }
105*10465441SEvalZero
_device_release(uffs_Device * dev)106*10465441SEvalZero static URET _device_release(uffs_Device *dev)
107*10465441SEvalZero {
108*10465441SEvalZero return U_SUCC;
109*10465441SEvalZero }
110*10465441SEvalZero
init_uffs_fs(struct _nand_dev * nand_part)111*10465441SEvalZero static int init_uffs_fs(
112*10465441SEvalZero struct _nand_dev * nand_part)
113*10465441SEvalZero {
114*10465441SEvalZero uffs_MountTable * mtb;
115*10465441SEvalZero struct rt_mtd_nand_device * nand;
116*10465441SEvalZero struct uffs_StorageAttrSt * flash_storage;
117*10465441SEvalZero
118*10465441SEvalZero mtb = &nand_part->mount_table;
119*10465441SEvalZero nand = nand_part->dev;
120*10465441SEvalZero flash_storage = &nand_part->storage;
121*10465441SEvalZero
122*10465441SEvalZero /* setup nand storage attributes */
123*10465441SEvalZero uffs_setup_storage(flash_storage, nand);
124*10465441SEvalZero
125*10465441SEvalZero /* register mount table */
126*10465441SEvalZero if(mtb->dev)
127*10465441SEvalZero {
128*10465441SEvalZero /* set memory allocator for uffs */
129*10465441SEvalZero #if CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR > 0
130*10465441SEvalZero uffs_MemSetupSystemAllocator(&mtb->dev->mem);
131*10465441SEvalZero #endif
132*10465441SEvalZero /* setup device init/release entry */
133*10465441SEvalZero mtb->dev->Init = _device_init;
134*10465441SEvalZero mtb->dev->Release = _device_release;
135*10465441SEvalZero mtb->dev->attr = flash_storage;
136*10465441SEvalZero
137*10465441SEvalZero uffs_RegisterMountTable(mtb);
138*10465441SEvalZero }
139*10465441SEvalZero /* mount uffs partion on nand device */
140*10465441SEvalZero return uffs_Mount(nand_part->mount_path) == U_SUCC ? 0 : -1;
141*10465441SEvalZero }
142*10465441SEvalZero
dfs_uffs_mount(struct dfs_filesystem * fs,unsigned long rwflag,const void * data)143*10465441SEvalZero static int dfs_uffs_mount(
144*10465441SEvalZero struct dfs_filesystem* fs,
145*10465441SEvalZero unsigned long rwflag,
146*10465441SEvalZero const void* data)
147*10465441SEvalZero {
148*10465441SEvalZero rt_base_t index;
149*10465441SEvalZero uffs_MountTable * mount_part;
150*10465441SEvalZero struct rt_mtd_nand_device * dev;
151*10465441SEvalZero
152*10465441SEvalZero RT_ASSERT(rt_strlen(fs->path) < (UFFS_MOUNT_PATH_MAX-1));
153*10465441SEvalZero dev = RT_MTD_NAND_DEVICE(fs->dev_id);
154*10465441SEvalZero
155*10465441SEvalZero /*1. find a empty entry in partition table */
156*10465441SEvalZero for (index = 0; index < UFFS_DEVICE_MAX ; index ++)
157*10465441SEvalZero {
158*10465441SEvalZero if (nand_part[index].dev == RT_NULL)
159*10465441SEvalZero break;
160*10465441SEvalZero }
161*10465441SEvalZero if (index == UFFS_DEVICE_MAX)
162*10465441SEvalZero return -ENOENT;
163*10465441SEvalZero
164*10465441SEvalZero /*2. fill partition structure */
165*10465441SEvalZero nand_part[index].dev = dev;
166*10465441SEvalZero
167*10465441SEvalZero /* make a right mount path for uffs, end with '/' */
168*10465441SEvalZero rt_snprintf(nand_part[index].mount_path, UFFS_MOUNT_PATH_MAX, "%s/", fs->path);
169*10465441SEvalZero if (nand_part[index].mount_path[1] == '/')
170*10465441SEvalZero nand_part[index].mount_path[1] = 0;
171*10465441SEvalZero
172*10465441SEvalZero mount_part = &(nand_part[index].mount_table);
173*10465441SEvalZero mount_part->mount = nand_part[index].mount_path;
174*10465441SEvalZero mount_part->dev = &(nand_part[index].uffs_dev);
175*10465441SEvalZero rt_memset(mount_part->dev, 0, sizeof(uffs_Device));//in order to make uffs happy.
176*10465441SEvalZero mount_part->dev->_private = dev; /* save dev_id into uffs */
177*10465441SEvalZero mount_part->start_block = dev->block_start;
178*10465441SEvalZero mount_part->end_block = dev->block_end;
179*10465441SEvalZero /*3. mount uffs */
180*10465441SEvalZero if (init_uffs_fs(&nand_part[index]) < 0)
181*10465441SEvalZero {
182*10465441SEvalZero return uffs_result_to_dfs(uffs_get_error());
183*10465441SEvalZero }
184*10465441SEvalZero return 0;
185*10465441SEvalZero }
186*10465441SEvalZero
dfs_uffs_unmount(struct dfs_filesystem * fs)187*10465441SEvalZero static int dfs_uffs_unmount(struct dfs_filesystem* fs)
188*10465441SEvalZero {
189*10465441SEvalZero rt_base_t index;
190*10465441SEvalZero int result;
191*10465441SEvalZero
192*10465441SEvalZero /* find the device index and then unmount it */
193*10465441SEvalZero for (index = 0; index < UFFS_DEVICE_MAX; index++)
194*10465441SEvalZero {
195*10465441SEvalZero if (nand_part[index].dev == RT_MTD_NAND_DEVICE(fs->dev_id))
196*10465441SEvalZero {
197*10465441SEvalZero nand_part[index].dev = RT_NULL;
198*10465441SEvalZero result = uffs_UnMount(nand_part[index].mount_path);
199*10465441SEvalZero if (result != U_SUCC)
200*10465441SEvalZero break;
201*10465441SEvalZero
202*10465441SEvalZero result = uffs_UnRegisterMountTable(& nand_part[index].mount_table);
203*10465441SEvalZero return (result == U_SUCC) ? RT_EOK : -1;
204*10465441SEvalZero }
205*10465441SEvalZero }
206*10465441SEvalZero return -ENOENT;
207*10465441SEvalZero }
208*10465441SEvalZero
dfs_uffs_mkfs(rt_device_t dev_id)209*10465441SEvalZero static int dfs_uffs_mkfs(rt_device_t dev_id)
210*10465441SEvalZero {
211*10465441SEvalZero rt_base_t index;
212*10465441SEvalZero rt_uint32_t block;
213*10465441SEvalZero struct rt_mtd_nand_device * mtd;
214*10465441SEvalZero
215*10465441SEvalZero /*1. find the device index */
216*10465441SEvalZero for (index = 0; index < UFFS_DEVICE_MAX; index++)
217*10465441SEvalZero {
218*10465441SEvalZero if (nand_part[index].dev == (struct rt_mtd_nand_device *)dev_id)
219*10465441SEvalZero break;
220*10465441SEvalZero }
221*10465441SEvalZero
222*10465441SEvalZero if (index == UFFS_DEVICE_MAX)
223*10465441SEvalZero {
224*10465441SEvalZero /* can't find device driver */
225*10465441SEvalZero return -ENOENT;
226*10465441SEvalZero }
227*10465441SEvalZero
228*10465441SEvalZero /*2. then unmount the partition */
229*10465441SEvalZero uffs_Mount(nand_part[index].mount_path);
230*10465441SEvalZero mtd = nand_part[index].dev;
231*10465441SEvalZero
232*10465441SEvalZero /*3. erase all blocks on the partition */
233*10465441SEvalZero block = mtd->block_start;
234*10465441SEvalZero for (; block <= mtd->block_end; block++)
235*10465441SEvalZero {
236*10465441SEvalZero rt_mtd_nand_erase_block(mtd, block);
237*10465441SEvalZero if (rt_mtd_nand_check_block(mtd, block) != RT_EOK)
238*10465441SEvalZero {
239*10465441SEvalZero rt_kprintf("found bad block %d\n", block);
240*10465441SEvalZero rt_mtd_nand_mark_badblock(mtd, block);
241*10465441SEvalZero }
242*10465441SEvalZero }
243*10465441SEvalZero
244*10465441SEvalZero /*4. remount it */
245*10465441SEvalZero if (init_uffs_fs(&nand_part[index]) < 0)
246*10465441SEvalZero {
247*10465441SEvalZero return uffs_result_to_dfs(uffs_get_error());
248*10465441SEvalZero }
249*10465441SEvalZero return RT_EOK;
250*10465441SEvalZero }
251*10465441SEvalZero
dfs_uffs_statfs(struct dfs_filesystem * fs,struct statfs * buf)252*10465441SEvalZero static int dfs_uffs_statfs(struct dfs_filesystem* fs,
253*10465441SEvalZero struct statfs *buf)
254*10465441SEvalZero {
255*10465441SEvalZero rt_base_t index;
256*10465441SEvalZero struct rt_mtd_nand_device * mtd = RT_MTD_NAND_DEVICE(fs->dev_id);
257*10465441SEvalZero
258*10465441SEvalZero RT_ASSERT(mtd != RT_NULL);
259*10465441SEvalZero
260*10465441SEvalZero /* find the device index */
261*10465441SEvalZero for (index = 0; index < UFFS_DEVICE_MAX; index++)
262*10465441SEvalZero {
263*10465441SEvalZero if (nand_part[index].dev == (void *)mtd)
264*10465441SEvalZero break;
265*10465441SEvalZero }
266*10465441SEvalZero if (index == UFFS_DEVICE_MAX)
267*10465441SEvalZero return -ENOENT;
268*10465441SEvalZero
269*10465441SEvalZero buf->f_bsize = mtd->page_size*mtd->pages_per_block;
270*10465441SEvalZero buf->f_blocks = (mtd->block_end - mtd->block_start + 1);
271*10465441SEvalZero buf->f_bfree = uffs_GetDeviceFree(&nand_part[index].uffs_dev)/buf->f_bsize ;
272*10465441SEvalZero
273*10465441SEvalZero return 0;
274*10465441SEvalZero }
275*10465441SEvalZero
dfs_uffs_open(struct dfs_fd * file)276*10465441SEvalZero static int dfs_uffs_open(struct dfs_fd* file)
277*10465441SEvalZero {
278*10465441SEvalZero int fd;
279*10465441SEvalZero int oflag, mode;
280*10465441SEvalZero char * file_path;
281*10465441SEvalZero
282*10465441SEvalZero oflag = file->flags;
283*10465441SEvalZero if (oflag & O_DIRECTORY) /* operations about dir */
284*10465441SEvalZero {
285*10465441SEvalZero uffs_DIR * dir;
286*10465441SEvalZero
287*10465441SEvalZero if (oflag & O_CREAT) /* create a dir*/
288*10465441SEvalZero {
289*10465441SEvalZero if (uffs_mkdir(file->path) < 0)
290*10465441SEvalZero return uffs_result_to_dfs(uffs_get_error());
291*10465441SEvalZero }
292*10465441SEvalZero /* open dir */
293*10465441SEvalZero file_path = rt_malloc(FILE_PATH_MAX);
294*10465441SEvalZero if(file_path == RT_NULL)
295*10465441SEvalZero return -ENOMEM;
296*10465441SEvalZero
297*10465441SEvalZero if (file->path[0] == '/' && !(file->path[1] == 0))
298*10465441SEvalZero rt_snprintf(file_path, FILE_PATH_MAX, "%s/", file->path);
299*10465441SEvalZero else
300*10465441SEvalZero {
301*10465441SEvalZero file_path[0] = '/';
302*10465441SEvalZero file_path[1] = 0;
303*10465441SEvalZero }
304*10465441SEvalZero
305*10465441SEvalZero dir = uffs_opendir(file_path);
306*10465441SEvalZero
307*10465441SEvalZero if (dir == RT_NULL)
308*10465441SEvalZero {
309*10465441SEvalZero rt_free(file_path);
310*10465441SEvalZero return uffs_result_to_dfs(uffs_get_error());
311*10465441SEvalZero }
312*10465441SEvalZero /* save this pointer,will used by dfs_uffs_getdents*/
313*10465441SEvalZero file->data = dir;
314*10465441SEvalZero rt_free(file_path);
315*10465441SEvalZero return RT_EOK;
316*10465441SEvalZero }
317*10465441SEvalZero /* regular file operations */
318*10465441SEvalZero /* int uffs_open(const char *name, int oflag, ...); what is this?
319*10465441SEvalZero * uffs_open can open dir!! **/
320*10465441SEvalZero mode = 0;
321*10465441SEvalZero if (oflag & O_RDONLY) mode |= UO_RDONLY;
322*10465441SEvalZero if (oflag & O_WRONLY) mode |= UO_WRONLY;
323*10465441SEvalZero if (oflag & O_RDWR) mode |= UO_RDWR;
324*10465441SEvalZero /* Opens the file, if it is existing. If not, a new file is created. */
325*10465441SEvalZero if (oflag & O_CREAT) mode |= UO_CREATE;
326*10465441SEvalZero /* Creates a new file. If the file is existing, it is truncated and overwritten. */
327*10465441SEvalZero if (oflag & O_TRUNC) mode |= UO_TRUNC;
328*10465441SEvalZero /* Creates a new file. The function fails if the file is already existing. */
329*10465441SEvalZero if (oflag & O_EXCL) mode |= UO_EXCL;
330*10465441SEvalZero
331*10465441SEvalZero fd = uffs_open(file->path, mode);
332*10465441SEvalZero if (fd < 0)
333*10465441SEvalZero {
334*10465441SEvalZero return uffs_result_to_dfs(uffs_get_error());
335*10465441SEvalZero }
336*10465441SEvalZero
337*10465441SEvalZero /* save this pointer, it will be used when calling read(), write(),
338*10465441SEvalZero * flush(), seek(), and will be free when calling close()*/
339*10465441SEvalZero
340*10465441SEvalZero file->data = (void *)fd;
341*10465441SEvalZero file->pos = uffs_seek(fd, 0, USEEK_CUR);
342*10465441SEvalZero file->size = uffs_seek(fd, 0, USEEK_END);
343*10465441SEvalZero uffs_seek(fd, file->pos, USEEK_SET);
344*10465441SEvalZero
345*10465441SEvalZero if (oflag & O_APPEND)
346*10465441SEvalZero {
347*10465441SEvalZero file->pos = uffs_seek(fd, 0, USEEK_END);
348*10465441SEvalZero }
349*10465441SEvalZero return 0;
350*10465441SEvalZero }
351*10465441SEvalZero
dfs_uffs_close(struct dfs_fd * file)352*10465441SEvalZero static int dfs_uffs_close(struct dfs_fd* file)
353*10465441SEvalZero {
354*10465441SEvalZero int oflag;
355*10465441SEvalZero int fd;
356*10465441SEvalZero
357*10465441SEvalZero oflag = file->flags;
358*10465441SEvalZero if (oflag & O_DIRECTORY)
359*10465441SEvalZero {
360*10465441SEvalZero /* operations about dir */
361*10465441SEvalZero if (uffs_closedir((uffs_DIR *)(file->data)) < 0)
362*10465441SEvalZero return uffs_result_to_dfs(uffs_get_error());
363*10465441SEvalZero
364*10465441SEvalZero return 0;
365*10465441SEvalZero }
366*10465441SEvalZero /* regular file operations */
367*10465441SEvalZero fd = (int)(file->data);
368*10465441SEvalZero
369*10465441SEvalZero if (uffs_close(fd) == 0)
370*10465441SEvalZero return 0;
371*10465441SEvalZero
372*10465441SEvalZero return uffs_result_to_dfs(uffs_get_error());
373*10465441SEvalZero }
374*10465441SEvalZero
dfs_uffs_ioctl(struct dfs_fd * file,int cmd,void * args)375*10465441SEvalZero static int dfs_uffs_ioctl(struct dfs_fd * file, int cmd, void* args)
376*10465441SEvalZero {
377*10465441SEvalZero return -ENOSYS;
378*10465441SEvalZero }
379*10465441SEvalZero
dfs_uffs_read(struct dfs_fd * file,void * buf,size_t len)380*10465441SEvalZero static int dfs_uffs_read(struct dfs_fd * file, void* buf, size_t len)
381*10465441SEvalZero {
382*10465441SEvalZero int fd;
383*10465441SEvalZero int char_read;
384*10465441SEvalZero
385*10465441SEvalZero fd = (int)(file->data);
386*10465441SEvalZero char_read = uffs_read(fd, buf, len);
387*10465441SEvalZero if (char_read < 0)
388*10465441SEvalZero return uffs_result_to_dfs(uffs_get_error());
389*10465441SEvalZero
390*10465441SEvalZero /* update position */
391*10465441SEvalZero file->pos = uffs_seek(fd, 0, USEEK_CUR);
392*10465441SEvalZero return char_read;
393*10465441SEvalZero }
394*10465441SEvalZero
dfs_uffs_write(struct dfs_fd * file,const void * buf,size_t len)395*10465441SEvalZero static int dfs_uffs_write(struct dfs_fd* file,
396*10465441SEvalZero const void* buf,
397*10465441SEvalZero size_t len)
398*10465441SEvalZero {
399*10465441SEvalZero int fd;
400*10465441SEvalZero int char_write;
401*10465441SEvalZero
402*10465441SEvalZero fd = (int)(file->data);
403*10465441SEvalZero
404*10465441SEvalZero char_write = uffs_write(fd, buf, len);
405*10465441SEvalZero if (char_write < 0)
406*10465441SEvalZero return uffs_result_to_dfs(uffs_get_error());
407*10465441SEvalZero
408*10465441SEvalZero /* update position */
409*10465441SEvalZero file->pos = uffs_seek(fd, 0, USEEK_CUR);
410*10465441SEvalZero return char_write;
411*10465441SEvalZero }
412*10465441SEvalZero
dfs_uffs_flush(struct dfs_fd * file)413*10465441SEvalZero static int dfs_uffs_flush(struct dfs_fd* file)
414*10465441SEvalZero {
415*10465441SEvalZero int fd;
416*10465441SEvalZero int result;
417*10465441SEvalZero
418*10465441SEvalZero fd = (int)(file->data);
419*10465441SEvalZero
420*10465441SEvalZero result = uffs_flush(fd);
421*10465441SEvalZero if (result < 0 )
422*10465441SEvalZero return uffs_result_to_dfs(uffs_get_error());
423*10465441SEvalZero return 0;
424*10465441SEvalZero }
425*10465441SEvalZero
uffs_seekdir(uffs_DIR * dir,long offset)426*10465441SEvalZero int uffs_seekdir(uffs_DIR *dir, long offset)
427*10465441SEvalZero {
428*10465441SEvalZero int i = 0;
429*10465441SEvalZero
430*10465441SEvalZero while(i < offset)
431*10465441SEvalZero {
432*10465441SEvalZero if (uffs_readdir(dir) == RT_NULL)
433*10465441SEvalZero return -1;
434*10465441SEvalZero i++;
435*10465441SEvalZero }
436*10465441SEvalZero return 0;
437*10465441SEvalZero }
438*10465441SEvalZero
439*10465441SEvalZero
dfs_uffs_seek(struct dfs_fd * file,rt_off_t offset)440*10465441SEvalZero static int dfs_uffs_seek(struct dfs_fd* file,
441*10465441SEvalZero rt_off_t offset)
442*10465441SEvalZero {
443*10465441SEvalZero int result;
444*10465441SEvalZero
445*10465441SEvalZero /* set offset as current offset */
446*10465441SEvalZero if (file->type == FT_DIRECTORY)
447*10465441SEvalZero {
448*10465441SEvalZero uffs_rewinddir((uffs_DIR *)(file->data));
449*10465441SEvalZero result = uffs_seekdir((uffs_DIR *)(file->data), offset/sizeof(struct dirent));
450*10465441SEvalZero if (result >= 0)
451*10465441SEvalZero {
452*10465441SEvalZero file->pos = offset;
453*10465441SEvalZero return offset;
454*10465441SEvalZero }
455*10465441SEvalZero }
456*10465441SEvalZero else if (file->type == FT_REGULAR)
457*10465441SEvalZero {
458*10465441SEvalZero result = uffs_seek((int)(file->data), offset, USEEK_SET);
459*10465441SEvalZero if (result >= 0)
460*10465441SEvalZero return offset;
461*10465441SEvalZero }
462*10465441SEvalZero
463*10465441SEvalZero return uffs_result_to_dfs(uffs_get_error());
464*10465441SEvalZero }
465*10465441SEvalZero
466*10465441SEvalZero /* return the size of struct dirent*/
dfs_uffs_getdents(struct dfs_fd * file,struct dirent * dirp,uint32_t count)467*10465441SEvalZero static int dfs_uffs_getdents(
468*10465441SEvalZero struct dfs_fd* file,
469*10465441SEvalZero struct dirent* dirp,
470*10465441SEvalZero uint32_t count)
471*10465441SEvalZero {
472*10465441SEvalZero rt_uint32_t index;
473*10465441SEvalZero char * file_path;
474*10465441SEvalZero struct dirent* d;
475*10465441SEvalZero uffs_DIR* dir;
476*10465441SEvalZero struct uffs_dirent * uffs_d;
477*10465441SEvalZero
478*10465441SEvalZero dir = (uffs_DIR*)(file->data);
479*10465441SEvalZero RT_ASSERT(dir != RT_NULL);
480*10465441SEvalZero
481*10465441SEvalZero /* round count, count is always 1 */
482*10465441SEvalZero count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
483*10465441SEvalZero if (count == 0) return -EINVAL;
484*10465441SEvalZero
485*10465441SEvalZero /* allocate file name */
486*10465441SEvalZero file_path = rt_malloc(FILE_PATH_MAX);
487*10465441SEvalZero if (file_path == RT_NULL)
488*10465441SEvalZero return -ENOMEM;
489*10465441SEvalZero
490*10465441SEvalZero index = 0;
491*10465441SEvalZero /* usually, the while loop should only be looped only once! */
492*10465441SEvalZero while (1)
493*10465441SEvalZero {
494*10465441SEvalZero struct uffs_stat s;
495*10465441SEvalZero
496*10465441SEvalZero d = dirp + index;
497*10465441SEvalZero
498*10465441SEvalZero uffs_d = uffs_readdir(dir);
499*10465441SEvalZero if (uffs_d == RT_NULL)
500*10465441SEvalZero {
501*10465441SEvalZero rt_free(file_path);
502*10465441SEvalZero return (uffs_result_to_dfs(uffs_get_error()));
503*10465441SEvalZero }
504*10465441SEvalZero
505*10465441SEvalZero if (file->path[0] == '/' && !(file->path[1] == 0))
506*10465441SEvalZero rt_snprintf(file_path, FILE_PATH_MAX, "%s/%s", file->path, uffs_d->d_name);
507*10465441SEvalZero else
508*10465441SEvalZero rt_strncpy(file_path, uffs_d->d_name, FILE_PATH_MAX);
509*10465441SEvalZero
510*10465441SEvalZero uffs_stat(file_path, &s);
511*10465441SEvalZero switch(s.st_mode & US_IFMT) /* file type mark */
512*10465441SEvalZero {
513*10465441SEvalZero case US_IFREG: /* directory */
514*10465441SEvalZero d->d_type = DT_REG;
515*10465441SEvalZero break;
516*10465441SEvalZero case US_IFDIR: /* regular file */
517*10465441SEvalZero d->d_type = DT_DIR;
518*10465441SEvalZero break;
519*10465441SEvalZero case US_IFLNK: /* symbolic link */
520*10465441SEvalZero case US_IREAD: /* read permission */
521*10465441SEvalZero case US_IWRITE:/* write permission */
522*10465441SEvalZero default:
523*10465441SEvalZero d->d_type = DT_UNKNOWN;
524*10465441SEvalZero break;
525*10465441SEvalZero }
526*10465441SEvalZero
527*10465441SEvalZero /* write the rest args of struct dirent* dirp */
528*10465441SEvalZero d->d_namlen = rt_strlen(uffs_d->d_name);
529*10465441SEvalZero d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
530*10465441SEvalZero rt_strncpy(d->d_name, uffs_d->d_name, rt_strlen(uffs_d->d_name) + 1);
531*10465441SEvalZero
532*10465441SEvalZero index ++;
533*10465441SEvalZero if (index * sizeof(struct dirent) >= count)
534*10465441SEvalZero break;
535*10465441SEvalZero }
536*10465441SEvalZero
537*10465441SEvalZero /* free file name buf */
538*10465441SEvalZero rt_free(file_path);
539*10465441SEvalZero
540*10465441SEvalZero if (index == 0)
541*10465441SEvalZero return uffs_result_to_dfs(uffs_get_error());
542*10465441SEvalZero
543*10465441SEvalZero file->pos += index * sizeof(struct dirent);
544*10465441SEvalZero
545*10465441SEvalZero return index * sizeof(struct dirent);
546*10465441SEvalZero }
547*10465441SEvalZero
dfs_uffs_unlink(struct dfs_filesystem * fs,const char * path)548*10465441SEvalZero static int dfs_uffs_unlink(struct dfs_filesystem* fs, const char* path)
549*10465441SEvalZero {
550*10465441SEvalZero int result;
551*10465441SEvalZero struct uffs_stat s;
552*10465441SEvalZero
553*10465441SEvalZero /* judge file type, dir is to be delete by uffs_rmdir, others by uffs_remove */
554*10465441SEvalZero if (uffs_lstat(path, &s) < 0)
555*10465441SEvalZero {
556*10465441SEvalZero return uffs_result_to_dfs(uffs_get_error());
557*10465441SEvalZero }
558*10465441SEvalZero
559*10465441SEvalZero switch(s.st_mode & US_IFMT)
560*10465441SEvalZero {
561*10465441SEvalZero case US_IFREG:
562*10465441SEvalZero result = uffs_remove(path);
563*10465441SEvalZero break;
564*10465441SEvalZero case US_IFDIR:
565*10465441SEvalZero result = uffs_rmdir(path);
566*10465441SEvalZero break;
567*10465441SEvalZero default:
568*10465441SEvalZero /* unknown file type */
569*10465441SEvalZero return -1;
570*10465441SEvalZero }
571*10465441SEvalZero if (result < 0)
572*10465441SEvalZero return uffs_result_to_dfs(uffs_get_error());
573*10465441SEvalZero
574*10465441SEvalZero return 0;
575*10465441SEvalZero }
576*10465441SEvalZero
dfs_uffs_rename(struct dfs_filesystem * fs,const char * oldpath,const char * newpath)577*10465441SEvalZero static int dfs_uffs_rename(
578*10465441SEvalZero struct dfs_filesystem* fs,
579*10465441SEvalZero const char* oldpath,
580*10465441SEvalZero const char* newpath)
581*10465441SEvalZero {
582*10465441SEvalZero int result;
583*10465441SEvalZero
584*10465441SEvalZero result = uffs_rename(oldpath, newpath);
585*10465441SEvalZero if (result < 0)
586*10465441SEvalZero return uffs_result_to_dfs(uffs_get_error());
587*10465441SEvalZero
588*10465441SEvalZero return 0;
589*10465441SEvalZero }
590*10465441SEvalZero
dfs_uffs_stat(struct dfs_filesystem * fs,const char * path,struct stat * st)591*10465441SEvalZero static int dfs_uffs_stat(struct dfs_filesystem* fs, const char *path, struct stat *st)
592*10465441SEvalZero {
593*10465441SEvalZero int result;
594*10465441SEvalZero struct uffs_stat s;
595*10465441SEvalZero
596*10465441SEvalZero result = uffs_stat(path, &s);
597*10465441SEvalZero if (result < 0)
598*10465441SEvalZero return uffs_result_to_dfs(uffs_get_error());
599*10465441SEvalZero
600*10465441SEvalZero /* convert uffs stat to dfs stat structure */
601*10465441SEvalZero /* FIXME, these field may not be the same */
602*10465441SEvalZero st->st_dev = 0;
603*10465441SEvalZero st->st_mode = s.st_mode;
604*10465441SEvalZero st->st_size = s.st_size;
605*10465441SEvalZero st->st_mtime = s.st_mtime;
606*10465441SEvalZero
607*10465441SEvalZero return 0;
608*10465441SEvalZero }
609*10465441SEvalZero
610*10465441SEvalZero static const struct dfs_file_ops dfs_uffs_fops =
611*10465441SEvalZero {
612*10465441SEvalZero dfs_uffs_open,
613*10465441SEvalZero dfs_uffs_close,
614*10465441SEvalZero dfs_uffs_ioctl,
615*10465441SEvalZero dfs_uffs_read,
616*10465441SEvalZero dfs_uffs_write,
617*10465441SEvalZero dfs_uffs_flush,
618*10465441SEvalZero dfs_uffs_seek,
619*10465441SEvalZero dfs_uffs_getdents,
620*10465441SEvalZero };
621*10465441SEvalZero
622*10465441SEvalZero static const struct dfs_filesystem_ops dfs_uffs_ops =
623*10465441SEvalZero {
624*10465441SEvalZero "uffs", /* file system type: uffs */
625*10465441SEvalZero #if RTTHREAD_VERSION >= 10100
626*10465441SEvalZero DFS_FS_FLAG_FULLPATH,
627*10465441SEvalZero #else
628*10465441SEvalZero #error "uffs can only work with rtthread whose version should >= 1.01\n"
629*10465441SEvalZero #endif
630*10465441SEvalZero &dfs_uffs_fops,
631*10465441SEvalZero
632*10465441SEvalZero dfs_uffs_mount,
633*10465441SEvalZero dfs_uffs_unmount,
634*10465441SEvalZero dfs_uffs_mkfs,
635*10465441SEvalZero dfs_uffs_statfs,
636*10465441SEvalZero
637*10465441SEvalZero dfs_uffs_unlink,
638*10465441SEvalZero dfs_uffs_stat,
639*10465441SEvalZero dfs_uffs_rename,
640*10465441SEvalZero };
641*10465441SEvalZero
dfs_uffs_init(void)642*10465441SEvalZero int dfs_uffs_init(void)
643*10465441SEvalZero {
644*10465441SEvalZero /* register uffs file system */
645*10465441SEvalZero dfs_register(&dfs_uffs_ops);
646*10465441SEvalZero
647*10465441SEvalZero if (uffs_InitObjectBuf() == U_SUCC)
648*10465441SEvalZero {
649*10465441SEvalZero if (uffs_DirEntryBufInit() == U_SUCC)
650*10465441SEvalZero {
651*10465441SEvalZero uffs_InitGlobalFsLock();
652*10465441SEvalZero return RT_EOK;
653*10465441SEvalZero }
654*10465441SEvalZero }
655*10465441SEvalZero return -RT_ERROR;
656*10465441SEvalZero }
657*10465441SEvalZero INIT_COMPONENT_EXPORT(dfs_uffs_init);
658*10465441SEvalZero
659