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 * 2012-1-7 prife the first version
9*10465441SEvalZero */
10*10465441SEvalZero
11*10465441SEvalZero #include <rtthread.h>
12*10465441SEvalZero #include <rtdevice.h>
13*10465441SEvalZero
14*10465441SEvalZero #include "cyg/infra/cyg_type.h"
15*10465441SEvalZero #include "cyg/fileio/fileio.h"
16*10465441SEvalZero #include "port/codes.h"
17*10465441SEvalZero #include "port/fcntl.h"
18*10465441SEvalZero #undef mode_t
19*10465441SEvalZero
20*10465441SEvalZero #include <dfs_fs.h>
21*10465441SEvalZero #include <dfs_file.h>
22*10465441SEvalZero
23*10465441SEvalZero #include "dfs_jffs2.h"
24*10465441SEvalZero #include "jffs2_config.h"
25*10465441SEvalZero #include "porting.h"
26*10465441SEvalZero #include <string.h>
27*10465441SEvalZero
28*10465441SEvalZero #if DEVICE_PART_MAX > 1
29*10465441SEvalZero #error "support only one jffs2 partition on a flash device!"
30*10465441SEvalZero #endif
31*10465441SEvalZero
32*10465441SEvalZero /* make sure the following struct var had been initilased to 0! */
33*10465441SEvalZero struct device_part
34*10465441SEvalZero {
35*10465441SEvalZero struct cyg_mtab_entry * mte;
36*10465441SEvalZero struct rt_mtd_nor_device *dev;
37*10465441SEvalZero };
38*10465441SEvalZero static struct device_part device_partition[DEVICE_PART_MAX] = {0};
39*10465441SEvalZero static struct rt_mutex jffs2_lock;
40*10465441SEvalZero
41*10465441SEvalZero #define jffs2_mount jffs2_fste.mount
42*10465441SEvalZero #define jffs2_umount jffs2_fste.umount
43*10465441SEvalZero #define jffs2_open jffs2_fste.open
44*10465441SEvalZero #define jffs2_file_unlink jffs2_fste.unlink
45*10465441SEvalZero #define jffs2_mkdir jffs2_fste.mkdir
46*10465441SEvalZero #define jffs2_rmdir jffs2_fste.rmdir
47*10465441SEvalZero #define jffs2_rename jffs2_fste.rename
48*10465441SEvalZero #define jffs2_link jffs2_fste.link
49*10465441SEvalZero #define jffs2_opendir jffs2_fste.opendir
50*10465441SEvalZero #define jffs2_chdir jffs2_fste.chdir
51*10465441SEvalZero #define jffs2_ops_stat jffs2_fste.stat
52*10465441SEvalZero #define jffs2_getinfo jffs2_fste.getinfo
53*10465441SEvalZero #define jffs2_setinfo jffs2_fste.setinfo
54*10465441SEvalZero
55*10465441SEvalZero #define jffs2_file_read jffs2_fileops.fo_read
56*10465441SEvalZero #define jffs2_file_write jffs2_fileops.fo_write
57*10465441SEvalZero #define jffs2_file_lseek jffs2_fileops.fo_lseek
58*10465441SEvalZero #define jffs2_file_ioctl jffs2_fileops.fo_ioctl
59*10465441SEvalZero #define jffs2_file_select jffs2_fileops.fo_select
60*10465441SEvalZero #define jffs2_file_fsync jffs2_fileops.fo_fsync
61*10465441SEvalZero #define jffs2_file_colse jffs2_fileops.fo_close
62*10465441SEvalZero #define jffs2_file_fstat jffs2_fileops.fo_fstat
63*10465441SEvalZero #define jffs2_file_getinfo jffs2_fileops.fo_getinfo
64*10465441SEvalZero #define jffs2_file_setinfo jffs2_fileops.fo_setinfo
65*10465441SEvalZero
66*10465441SEvalZero #define jffs2_dir_read jffs2_dirops.fo_read
67*10465441SEvalZero //#define jffs2_dir_write jffs2_dirops.fo_write
68*10465441SEvalZero #define jffs2_dir_lseek jffs2_dirops.fo_lseek
69*10465441SEvalZero //#define jffs2_dir_ioctl jffs2_dirops.fo_ioctl
70*10465441SEvalZero #define jffs2_dir_select jffs2_dirops.fo_select
71*10465441SEvalZero //#define jffs2_dir_fsync jffs2_dirops.fo_fsync
72*10465441SEvalZero #define jffs2_dir_colse jffs2_dirops.fo_close
73*10465441SEvalZero //#define jffs2_dir_fstat jffs2_dirops.fo_fstat
74*10465441SEvalZero //#define jffs2_dir_getinfo jffs2_dirops.fo_getinfo
75*10465441SEvalZero //#define jffs2_dir_setinfo jffs2_dirops.fo_setinfo
76*10465441SEvalZero
77*10465441SEvalZero /*
78*10465441SEvalZero * RT-Thread Device Interface for jffs2
79*10465441SEvalZero */
80*10465441SEvalZero
81*10465441SEvalZero /* these code is in src/flashio.c */
jffs2_result_to_dfs(int result)82*10465441SEvalZero static int jffs2_result_to_dfs(int result)
83*10465441SEvalZero {
84*10465441SEvalZero if (result < 0) return result;
85*10465441SEvalZero if (result > 0) return -result;
86*10465441SEvalZero
87*10465441SEvalZero return 0;
88*10465441SEvalZero }
89*10465441SEvalZero
90*10465441SEvalZero /*
91*10465441SEvalZero * RT-Thread DFS Interface for jffs2
92*10465441SEvalZero */
dfs_jffs2_mount(struct dfs_filesystem * fs,unsigned long rwflag,const void * data)93*10465441SEvalZero static int dfs_jffs2_mount(struct dfs_filesystem* fs,
94*10465441SEvalZero unsigned long rwflag,
95*10465441SEvalZero const void* data)
96*10465441SEvalZero {
97*10465441SEvalZero unsigned index;
98*10465441SEvalZero struct cyg_mtab_entry * mte;
99*10465441SEvalZero int result;
100*10465441SEvalZero
101*10465441SEvalZero /* find a empty entry in partition table */
102*10465441SEvalZero for (index = 0; index < DEVICE_PART_MAX; index ++)
103*10465441SEvalZero {
104*10465441SEvalZero if (device_partition[index].dev == RT_NULL)
105*10465441SEvalZero break;
106*10465441SEvalZero }
107*10465441SEvalZero if (index == DEVICE_PART_MAX)
108*10465441SEvalZero return -ENOSPC;
109*10465441SEvalZero
110*10465441SEvalZero mte = rt_malloc(sizeof(struct cyg_mtab_entry));
111*10465441SEvalZero if (mte == RT_NULL)
112*10465441SEvalZero return -ENOMEM;
113*10465441SEvalZero
114*10465441SEvalZero mte->name = fs->path;
115*10465441SEvalZero mte->fsname = "jffs2";
116*10465441SEvalZero mte->devname = NULL;
117*10465441SEvalZero /* note that, i use mte->data to store rtt's device
118*10465441SEvalZero * while, in jffs2_mount, mte->data will be copy into
119*10465441SEvalZero * s_dev in struct super_block, and mte->data will be
120*10465441SEvalZero * filled with jffs2_sb(see the source of jffs2_mount.
121*10465441SEvalZero */
122*10465441SEvalZero mte->data = (CYG_ADDRWORD)fs->dev_id;
123*10465441SEvalZero
124*10465441SEvalZero device_partition[index].dev = RT_MTD_NOR_DEVICE(fs->dev_id);
125*10465441SEvalZero /* after jffs2_mount, mte->data will not be dev_id any more */
126*10465441SEvalZero result = jffs2_mount(NULL, mte);
127*10465441SEvalZero if (result != 0)
128*10465441SEvalZero {
129*10465441SEvalZero device_partition[index].dev = NULL;
130*10465441SEvalZero return jffs2_result_to_dfs(result);
131*10465441SEvalZero }
132*10465441SEvalZero
133*10465441SEvalZero /* save this pointer */
134*10465441SEvalZero device_partition[index].mte = mte;
135*10465441SEvalZero return 0;
136*10465441SEvalZero }
137*10465441SEvalZero
_find_fs(struct cyg_mtab_entry ** mte,rt_device_t dev_id)138*10465441SEvalZero static int _find_fs(struct cyg_mtab_entry ** mte, rt_device_t dev_id)
139*10465441SEvalZero {
140*10465441SEvalZero unsigned index;
141*10465441SEvalZero
142*10465441SEvalZero /* find device index */
143*10465441SEvalZero for (index = 0; index < DEVICE_PART_MAX; index++)
144*10465441SEvalZero {
145*10465441SEvalZero if (device_partition[index].dev == RT_MTD_NOR_DEVICE(dev_id))
146*10465441SEvalZero {
147*10465441SEvalZero *mte = device_partition[index].mte;
148*10465441SEvalZero return 0;
149*10465441SEvalZero }
150*10465441SEvalZero }
151*10465441SEvalZero
152*10465441SEvalZero rt_kprintf("error, could not found the fs!");
153*10465441SEvalZero return -1;
154*10465441SEvalZero }
155*10465441SEvalZero
dfs_jffs2_unmount(struct dfs_filesystem * fs)156*10465441SEvalZero static int dfs_jffs2_unmount(struct dfs_filesystem* fs)
157*10465441SEvalZero {
158*10465441SEvalZero int result;
159*10465441SEvalZero unsigned index;
160*10465441SEvalZero
161*10465441SEvalZero /* find device index, then umount it */
162*10465441SEvalZero for (index = 0; index < DEVICE_PART_MAX; index++)
163*10465441SEvalZero {
164*10465441SEvalZero if (device_partition[index].dev == RT_MTD_NOR_DEVICE(fs->dev_id))
165*10465441SEvalZero {
166*10465441SEvalZero result = jffs2_umount(device_partition[index].mte);
167*10465441SEvalZero if (result) return jffs2_result_to_dfs(result);
168*10465441SEvalZero
169*10465441SEvalZero rt_free(device_partition[index].mte);
170*10465441SEvalZero device_partition[index].dev = NULL;
171*10465441SEvalZero device_partition[index].mte = NULL;
172*10465441SEvalZero return RT_EOK;
173*10465441SEvalZero }
174*10465441SEvalZero }
175*10465441SEvalZero
176*10465441SEvalZero return -ENOENT;
177*10465441SEvalZero }
178*10465441SEvalZero
dfs_jffs2_mkfs(rt_device_t dev_id)179*10465441SEvalZero static int dfs_jffs2_mkfs(rt_device_t dev_id)
180*10465441SEvalZero {
181*10465441SEvalZero /* just erase all blocks on this nand partition */
182*10465441SEvalZero return -ENOSYS;
183*10465441SEvalZero }
184*10465441SEvalZero
dfs_jffs2_statfs(struct dfs_filesystem * fs,struct statfs * buf)185*10465441SEvalZero static int dfs_jffs2_statfs(struct dfs_filesystem* fs,
186*10465441SEvalZero struct statfs *buf)
187*10465441SEvalZero {
188*10465441SEvalZero /* since the limit of unsigned long, so the max size of flash device is 4G */
189*10465441SEvalZero struct cyg_mtab_entry * mte;
190*10465441SEvalZero struct jffs2_fs_info info;
191*10465441SEvalZero int result;
192*10465441SEvalZero
193*10465441SEvalZero result = _find_fs(&mte, fs->dev_id);
194*10465441SEvalZero if (result)
195*10465441SEvalZero return -ENOENT;
196*10465441SEvalZero
197*10465441SEvalZero RT_ASSERT(mte->data != 0);
198*10465441SEvalZero
199*10465441SEvalZero jffs2_get_info_from_sb((void *)mte->data, &info);
200*10465441SEvalZero buf->f_bsize = info.sector_size;
201*10465441SEvalZero buf->f_blocks = info.nr_blocks;
202*10465441SEvalZero buf->f_bfree = info.free_size / info.sector_size;
203*10465441SEvalZero
204*10465441SEvalZero return 0;
205*10465441SEvalZero }
206*10465441SEvalZero
207*10465441SEvalZero static const char jffs2_root_path[] = ".";
208*10465441SEvalZero
dfs_jffs2_open(struct dfs_fd * file)209*10465441SEvalZero static int dfs_jffs2_open(struct dfs_fd* file)
210*10465441SEvalZero {
211*10465441SEvalZero int result;
212*10465441SEvalZero int oflag, mode;
213*10465441SEvalZero const char * name;
214*10465441SEvalZero cyg_file * jffs2_file;
215*10465441SEvalZero struct dfs_filesystem *fs;
216*10465441SEvalZero struct cyg_mtab_entry * mte;
217*10465441SEvalZero
218*10465441SEvalZero oflag = file->flags;
219*10465441SEvalZero fs = (struct dfs_filesystem *)file->data;
220*10465441SEvalZero RT_ASSERT(fs != RT_NULL);
221*10465441SEvalZero
222*10465441SEvalZero jffs2_file = rt_malloc(sizeof(cyg_file));
223*10465441SEvalZero if (jffs2_file == RT_NULL)
224*10465441SEvalZero return -ENOMEM;
225*10465441SEvalZero
226*10465441SEvalZero /* just escape '/' provided by dfs code */
227*10465441SEvalZero name = file->path;
228*10465441SEvalZero if ((name[0] == '/') && (name[1] == 0))
229*10465441SEvalZero name = jffs2_root_path;
230*10465441SEvalZero else /* name[0] still will be '/' */
231*10465441SEvalZero name ++;
232*10465441SEvalZero
233*10465441SEvalZero result = _find_fs(&mte, fs->dev_id);
234*10465441SEvalZero if (result)
235*10465441SEvalZero {
236*10465441SEvalZero rt_free(jffs2_file);
237*10465441SEvalZero return -ENOENT;
238*10465441SEvalZero }
239*10465441SEvalZero
240*10465441SEvalZero /* set mount table */
241*10465441SEvalZero jffs2_file->f_mte = mte;
242*10465441SEvalZero
243*10465441SEvalZero if (oflag & O_DIRECTORY) /* operations about dir */
244*10465441SEvalZero {
245*10465441SEvalZero rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER);
246*10465441SEvalZero if (oflag & O_CREAT) /* create a dir*/
247*10465441SEvalZero {
248*10465441SEvalZero /* fixme, should test file->path can end with '/' */
249*10465441SEvalZero result = jffs2_mkdir(mte, mte->root, name);
250*10465441SEvalZero if (result)
251*10465441SEvalZero {
252*10465441SEvalZero rt_mutex_release(&jffs2_lock);
253*10465441SEvalZero rt_free(jffs2_file);
254*10465441SEvalZero return jffs2_result_to_dfs(result);
255*10465441SEvalZero }
256*10465441SEvalZero }
257*10465441SEvalZero
258*10465441SEvalZero /* open dir */
259*10465441SEvalZero result = jffs2_opendir(mte, mte->root, name, jffs2_file);
260*10465441SEvalZero rt_mutex_release(&jffs2_lock);
261*10465441SEvalZero if (result)
262*10465441SEvalZero {
263*10465441SEvalZero rt_free(jffs2_file);
264*10465441SEvalZero return jffs2_result_to_dfs(result);
265*10465441SEvalZero }
266*10465441SEvalZero #ifdef CONFIG_JFFS2_NO_RELATIVEDIR
267*10465441SEvalZero jffs2_file->f_offset = 2;
268*10465441SEvalZero #endif
269*10465441SEvalZero /* save this pointer, it will be used by dfs_jffs2_getdents*/
270*10465441SEvalZero file->data = jffs2_file;
271*10465441SEvalZero return 0;
272*10465441SEvalZero }
273*10465441SEvalZero /* regular file operations */
274*10465441SEvalZero mode = JFFS2_O_RDONLY;
275*10465441SEvalZero if (oflag & O_WRONLY) mode |= JFFS2_O_WRONLY;
276*10465441SEvalZero if (oflag & O_RDWR) mode |= JFFS2_O_RDWR;
277*10465441SEvalZero /* Opens the file, if it is existing. If not, a new file is created. */
278*10465441SEvalZero if (oflag & O_CREAT) mode |= JFFS2_O_CREAT;
279*10465441SEvalZero /* Creates a new file. If the file is existing, it is truncated and overwritten. */
280*10465441SEvalZero if (oflag & O_TRUNC) mode |= JFFS2_O_TRUNC;
281*10465441SEvalZero /* Creates a new file. The function fails if the file is already existing. */
282*10465441SEvalZero if (oflag & O_EXCL) mode |= JFFS2_O_EXCL;
283*10465441SEvalZero
284*10465441SEvalZero rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER);
285*10465441SEvalZero result = jffs2_open(mte, 0, name, mode, jffs2_file);
286*10465441SEvalZero if (result != 0)
287*10465441SEvalZero {
288*10465441SEvalZero rt_mutex_release(&jffs2_lock);
289*10465441SEvalZero rt_free(jffs2_file);
290*10465441SEvalZero return jffs2_result_to_dfs(result);
291*10465441SEvalZero }
292*10465441SEvalZero
293*10465441SEvalZero /* save this pointer, it will be used when calling read(), write(),
294*10465441SEvalZero flush(), lessk(), and will be rt_free when calling close()*/
295*10465441SEvalZero file->data = jffs2_file;
296*10465441SEvalZero file->pos = jffs2_file->f_offset;
297*10465441SEvalZero file->size = 0;
298*10465441SEvalZero jffs2_file_lseek(jffs2_file, (off_t *)(&(file->size)), SEEK_END);
299*10465441SEvalZero jffs2_file->f_offset = (off_t)file->pos;
300*10465441SEvalZero rt_mutex_release(&jffs2_lock);
301*10465441SEvalZero
302*10465441SEvalZero if (oflag & O_APPEND)
303*10465441SEvalZero {
304*10465441SEvalZero file->pos = file->size;
305*10465441SEvalZero jffs2_file->f_offset = file->size;
306*10465441SEvalZero }
307*10465441SEvalZero
308*10465441SEvalZero return 0;
309*10465441SEvalZero }
310*10465441SEvalZero
dfs_jffs2_close(struct dfs_fd * file)311*10465441SEvalZero static int dfs_jffs2_close(struct dfs_fd* file)
312*10465441SEvalZero {
313*10465441SEvalZero int result;
314*10465441SEvalZero cyg_file * jffs2_file;
315*10465441SEvalZero
316*10465441SEvalZero RT_ASSERT(file->data != NULL);
317*10465441SEvalZero jffs2_file = (cyg_file *)(file->data);
318*10465441SEvalZero
319*10465441SEvalZero if (file->flags & O_DIRECTORY) /* operations about dir */
320*10465441SEvalZero {
321*10465441SEvalZero rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER);
322*10465441SEvalZero result = jffs2_dir_colse(jffs2_file);
323*10465441SEvalZero rt_mutex_release(&jffs2_lock);
324*10465441SEvalZero if (result)
325*10465441SEvalZero return jffs2_result_to_dfs(result);
326*10465441SEvalZero
327*10465441SEvalZero rt_free(jffs2_file);
328*10465441SEvalZero return 0;
329*10465441SEvalZero }
330*10465441SEvalZero /* regular file operations */
331*10465441SEvalZero rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER);
332*10465441SEvalZero result = jffs2_file_colse(jffs2_file);
333*10465441SEvalZero rt_mutex_release(&jffs2_lock);
334*10465441SEvalZero if (result)
335*10465441SEvalZero return jffs2_result_to_dfs(result);
336*10465441SEvalZero
337*10465441SEvalZero /* release memory */
338*10465441SEvalZero rt_free(jffs2_file);
339*10465441SEvalZero return 0;
340*10465441SEvalZero }
341*10465441SEvalZero
dfs_jffs2_ioctl(struct dfs_fd * file,int cmd,void * args)342*10465441SEvalZero static int dfs_jffs2_ioctl(struct dfs_fd* file, int cmd, void* args)
343*10465441SEvalZero {
344*10465441SEvalZero return -ENOSYS;
345*10465441SEvalZero }
346*10465441SEvalZero
dfs_jffs2_read(struct dfs_fd * file,void * buf,size_t len)347*10465441SEvalZero static int dfs_jffs2_read(struct dfs_fd* file, void* buf, size_t len)
348*10465441SEvalZero {
349*10465441SEvalZero cyg_file * jffs2_file;
350*10465441SEvalZero struct CYG_UIO_TAG uio_s;
351*10465441SEvalZero struct CYG_IOVEC_TAG iovec;
352*10465441SEvalZero int char_read;
353*10465441SEvalZero int result;
354*10465441SEvalZero
355*10465441SEvalZero RT_ASSERT(file->data != NULL);
356*10465441SEvalZero jffs2_file = (cyg_file *)(file->data);
357*10465441SEvalZero uio_s.uio_iov = &iovec;
358*10465441SEvalZero uio_s.uio_iov->iov_base = buf;
359*10465441SEvalZero uio_s.uio_iov->iov_len = len;
360*10465441SEvalZero uio_s.uio_iovcnt = 1; //must be 1
361*10465441SEvalZero //uio_s.uio_offset //not used...
362*10465441SEvalZero uio_s.uio_resid = uio_s.uio_iov->iov_len; //seem no use in jffs2;
363*10465441SEvalZero
364*10465441SEvalZero char_read = jffs2_file->f_offset; /* the current offset */
365*10465441SEvalZero rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER);
366*10465441SEvalZero result = jffs2_file_read(jffs2_file, &uio_s);
367*10465441SEvalZero rt_mutex_release(&jffs2_lock);
368*10465441SEvalZero if (result)
369*10465441SEvalZero return jffs2_result_to_dfs(result);
370*10465441SEvalZero
371*10465441SEvalZero /* update position */
372*10465441SEvalZero file->pos = jffs2_file->f_offset;
373*10465441SEvalZero char_read = jffs2_file->f_offset - char_read;
374*10465441SEvalZero return char_read;
375*10465441SEvalZero }
376*10465441SEvalZero
dfs_jffs2_write(struct dfs_fd * file,const void * buf,size_t len)377*10465441SEvalZero static int dfs_jffs2_write(struct dfs_fd* file,
378*10465441SEvalZero const void* buf,
379*10465441SEvalZero size_t len)
380*10465441SEvalZero {
381*10465441SEvalZero cyg_file * jffs2_file;
382*10465441SEvalZero struct CYG_UIO_TAG uio_s;
383*10465441SEvalZero struct CYG_IOVEC_TAG iovec;
384*10465441SEvalZero int char_write;
385*10465441SEvalZero int result;
386*10465441SEvalZero
387*10465441SEvalZero RT_ASSERT(file->data != NULL);
388*10465441SEvalZero jffs2_file = (cyg_file *)(file->data);
389*10465441SEvalZero uio_s.uio_iov = &iovec;
390*10465441SEvalZero uio_s.uio_iov->iov_base = (void *)buf;
391*10465441SEvalZero uio_s.uio_iov->iov_len = len;
392*10465441SEvalZero uio_s.uio_iovcnt = 1; //must be 1
393*10465441SEvalZero //uio_s.uio_offset //not used...
394*10465441SEvalZero uio_s.uio_resid = uio_s.uio_iov->iov_len; //seem no use in jffs2;
395*10465441SEvalZero
396*10465441SEvalZero char_write = jffs2_file->f_offset;
397*10465441SEvalZero rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER);
398*10465441SEvalZero result = jffs2_file_write(jffs2_file, &uio_s);
399*10465441SEvalZero rt_mutex_release(&jffs2_lock);
400*10465441SEvalZero if (result)
401*10465441SEvalZero return jffs2_result_to_dfs(result);
402*10465441SEvalZero
403*10465441SEvalZero /* update position */
404*10465441SEvalZero file->pos = jffs2_file->f_offset;
405*10465441SEvalZero char_write = jffs2_file->f_offset - char_write;
406*10465441SEvalZero return char_write;
407*10465441SEvalZero }
408*10465441SEvalZero
dfs_jffs2_flush(struct dfs_fd * file)409*10465441SEvalZero static int dfs_jffs2_flush(struct dfs_fd* file)
410*10465441SEvalZero {
411*10465441SEvalZero /* infact, jffs2 not support, jffs2_fo_sync just return ok */
412*10465441SEvalZero return -ENOSYS;
413*10465441SEvalZero }
414*10465441SEvalZero
415*10465441SEvalZero /* fixme warning: the offset is rt_off_t, so maybe the size of a file is must <= 2G*/
dfs_jffs2_lseek(struct dfs_fd * file,rt_off_t offset)416*10465441SEvalZero static int dfs_jffs2_lseek(struct dfs_fd* file,
417*10465441SEvalZero rt_off_t offset)
418*10465441SEvalZero {
419*10465441SEvalZero cyg_file * jffs2_file;
420*10465441SEvalZero int result;
421*10465441SEvalZero
422*10465441SEvalZero RT_ASSERT(file->data != NULL);
423*10465441SEvalZero jffs2_file = (cyg_file *)(file->data);
424*10465441SEvalZero
425*10465441SEvalZero /* set offset as current offset */
426*10465441SEvalZero rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER);
427*10465441SEvalZero result = jffs2_file_lseek(jffs2_file, &offset, SEEK_SET);
428*10465441SEvalZero rt_mutex_release(&jffs2_lock);
429*10465441SEvalZero if (result)
430*10465441SEvalZero return jffs2_result_to_dfs(result);
431*10465441SEvalZero /* update file position */
432*10465441SEvalZero file->pos = offset;
433*10465441SEvalZero return offset;
434*10465441SEvalZero }
435*10465441SEvalZero
436*10465441SEvalZero /* return the size of struct dirent*/
dfs_jffs2_getdents(struct dfs_fd * file,struct dirent * dirp,rt_uint32_t count)437*10465441SEvalZero static int dfs_jffs2_getdents(struct dfs_fd* file,
438*10465441SEvalZero struct dirent* dirp,
439*10465441SEvalZero rt_uint32_t count)
440*10465441SEvalZero {
441*10465441SEvalZero cyg_file * jffs2_file;
442*10465441SEvalZero struct CYG_UIO_TAG uio_s;
443*10465441SEvalZero struct CYG_IOVEC_TAG iovec;
444*10465441SEvalZero struct jffs2_dirent jffs2_d;
445*10465441SEvalZero struct dirent * d;
446*10465441SEvalZero rt_uint32_t index;
447*10465441SEvalZero #if !defined (CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE)
448*10465441SEvalZero struct jffs2_stat s;
449*10465441SEvalZero cyg_mtab_entry * mte;
450*10465441SEvalZero char * fullname;
451*10465441SEvalZero #endif
452*10465441SEvalZero int result;
453*10465441SEvalZero
454*10465441SEvalZero RT_ASSERT(file->data != RT_NULL);
455*10465441SEvalZero jffs2_file = (cyg_file*)(file->data);
456*10465441SEvalZero mte = jffs2_file->f_mte;
457*10465441SEvalZero
458*10465441SEvalZero //set jffs2_d
459*10465441SEvalZero memset(&jffs2_d, 0, sizeof(struct jffs2_dirent));
460*10465441SEvalZero //set CYG_UIO_TAG uio_s
461*10465441SEvalZero uio_s.uio_iov = &iovec;
462*10465441SEvalZero uio_s.uio_iov->iov_base = &jffs2_d;
463*10465441SEvalZero uio_s.uio_iov->iov_len = sizeof(struct jffs2_dirent);;
464*10465441SEvalZero uio_s.uio_iovcnt = 1; //must be 1
465*10465441SEvalZero uio_s.uio_offset = 0;//not used...
466*10465441SEvalZero uio_s.uio_resid = uio_s.uio_iov->iov_len; //seem no use in jffs2;
467*10465441SEvalZero
468*10465441SEvalZero /* make integer count, usually count is 1 */
469*10465441SEvalZero count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
470*10465441SEvalZero if (count == 0) return -EINVAL;
471*10465441SEvalZero
472*10465441SEvalZero index = 0;
473*10465441SEvalZero /* usually, the while loop should only be looped only once! */
474*10465441SEvalZero while (1)
475*10465441SEvalZero {
476*10465441SEvalZero d = dirp + index;
477*10465441SEvalZero rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER);
478*10465441SEvalZero result = jffs2_dir_read(jffs2_file, &uio_s);
479*10465441SEvalZero rt_mutex_release(&jffs2_lock);
480*10465441SEvalZero /* if met a error or all entry are read over, break while*/
481*10465441SEvalZero if (result || jffs2_d.d_name[0] == 0)
482*10465441SEvalZero break;
483*10465441SEvalZero
484*10465441SEvalZero #if defined (CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE)
485*10465441SEvalZero switch(jffs2_d.d_type & JFFS2_S_IFMT)
486*10465441SEvalZero {
487*10465441SEvalZero case JFFS2_S_IFREG: d->d_type = DT_REG; break;
488*10465441SEvalZero case JFFS2_S_IFDIR: d->d_type = DT_DIR; break;
489*10465441SEvalZero default: d->d_type = DT_UNKNOWN; break;
490*10465441SEvalZero }
491*10465441SEvalZero #else
492*10465441SEvalZero fullname = rt_malloc(FILE_PATH_MAX);
493*10465441SEvalZero if(fullname == RT_NULL)
494*10465441SEvalZero return -ENOMEM;
495*10465441SEvalZero
496*10465441SEvalZero /* make a right entry */
497*10465441SEvalZero if ((file->path[0] == '/') )
498*10465441SEvalZero {
499*10465441SEvalZero if (file->path[1] == 0)
500*10465441SEvalZero strcpy(fullname, jffs2_d.d_name);
501*10465441SEvalZero else
502*10465441SEvalZero rt_sprintf(fullname, "%s/%s", file->path+1, jffs2_d.d_name);
503*10465441SEvalZero }
504*10465441SEvalZero else
505*10465441SEvalZero rt_sprintf(fullname, "%s/%s", file->path, jffs2_d.d_name);
506*10465441SEvalZero rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER);
507*10465441SEvalZero result = jffs2_porting_stat(mte, mte->root, fullname, (void *)&s);
508*10465441SEvalZero rt_mutex_release(&jffs2_lock);
509*10465441SEvalZero if (result)
510*10465441SEvalZero return jffs2_result_to_dfs(result);
511*10465441SEvalZero
512*10465441SEvalZero rt_free(fullname);
513*10465441SEvalZero /* convert to dfs stat structure */
514*10465441SEvalZero switch(s.st_mode & JFFS2_S_IFMT)
515*10465441SEvalZero {
516*10465441SEvalZero case JFFS2_S_IFREG: d->d_type = DT_REG; break;
517*10465441SEvalZero case JFFS2_S_IFDIR: d->d_type = DT_DIR; break;
518*10465441SEvalZero default: d->d_type = DT_UNKNOWN; break;
519*10465441SEvalZero }
520*10465441SEvalZero #endif
521*10465441SEvalZero /* write the rest fields of struct dirent* dirp */
522*10465441SEvalZero d->d_namlen = rt_strlen(jffs2_d.d_name);
523*10465441SEvalZero d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
524*10465441SEvalZero rt_strncpy(d->d_name, jffs2_d.d_name, d->d_namlen + 1);
525*10465441SEvalZero
526*10465441SEvalZero index ++;
527*10465441SEvalZero if (index * sizeof(struct dirent) >= count)
528*10465441SEvalZero break;
529*10465441SEvalZero }
530*10465441SEvalZero if (result)
531*10465441SEvalZero return jffs2_result_to_dfs(result);
532*10465441SEvalZero return index * sizeof(struct dirent);
533*10465441SEvalZero }
534*10465441SEvalZero
dfs_jffs2_unlink(struct dfs_filesystem * fs,const char * path)535*10465441SEvalZero static int dfs_jffs2_unlink(struct dfs_filesystem* fs, const char* path)
536*10465441SEvalZero {
537*10465441SEvalZero int result;
538*10465441SEvalZero struct jffs2_stat s;
539*10465441SEvalZero cyg_mtab_entry * mte;
540*10465441SEvalZero
541*10465441SEvalZero result = _find_fs(&mte, fs->dev_id);
542*10465441SEvalZero if (result)
543*10465441SEvalZero return -ENOENT;
544*10465441SEvalZero
545*10465441SEvalZero /* deal path */
546*10465441SEvalZero if (path[0] == '/')
547*10465441SEvalZero path++;
548*10465441SEvalZero
549*10465441SEvalZero /* judge file type, dir is to be delete by rmdir, others by unlink */
550*10465441SEvalZero rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER);
551*10465441SEvalZero result = jffs2_porting_stat(mte, mte->root, path, (void *)&s);
552*10465441SEvalZero if (result)
553*10465441SEvalZero {
554*10465441SEvalZero rt_mutex_release(&jffs2_lock);
555*10465441SEvalZero return jffs2_result_to_dfs(result);
556*10465441SEvalZero }
557*10465441SEvalZero
558*10465441SEvalZero switch(s.st_mode & JFFS2_S_IFMT)
559*10465441SEvalZero {
560*10465441SEvalZero case JFFS2_S_IFREG:
561*10465441SEvalZero result = jffs2_file_unlink(mte, mte->root, path);
562*10465441SEvalZero break;
563*10465441SEvalZero case JFFS2_S_IFDIR:
564*10465441SEvalZero result = jffs2_rmdir(mte, mte->root, path);
565*10465441SEvalZero break;
566*10465441SEvalZero default:
567*10465441SEvalZero /* unknown file type */
568*10465441SEvalZero rt_mutex_release(&jffs2_lock);
569*10465441SEvalZero return -1;
570*10465441SEvalZero }
571*10465441SEvalZero rt_mutex_release(&jffs2_lock);
572*10465441SEvalZero if (result)
573*10465441SEvalZero return jffs2_result_to_dfs(result);
574*10465441SEvalZero return 0;
575*10465441SEvalZero }
576*10465441SEvalZero
dfs_jffs2_rename(struct dfs_filesystem * fs,const char * oldpath,const char * newpath)577*10465441SEvalZero static int dfs_jffs2_rename(struct dfs_filesystem* fs,
578*10465441SEvalZero const char* oldpath,
579*10465441SEvalZero const char* newpath)
580*10465441SEvalZero {
581*10465441SEvalZero int result;
582*10465441SEvalZero cyg_mtab_entry * mte;
583*10465441SEvalZero
584*10465441SEvalZero result = _find_fs(&mte, fs->dev_id);
585*10465441SEvalZero if (result)
586*10465441SEvalZero return -ENOENT;
587*10465441SEvalZero
588*10465441SEvalZero if (*oldpath == '/')
589*10465441SEvalZero oldpath += 1;
590*10465441SEvalZero if (*newpath == '/')
591*10465441SEvalZero newpath += 1;
592*10465441SEvalZero rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER);
593*10465441SEvalZero result = jffs2_rename(mte, mte->root, oldpath, mte->root, newpath);
594*10465441SEvalZero rt_mutex_release(&jffs2_lock);
595*10465441SEvalZero if (result)
596*10465441SEvalZero return jffs2_result_to_dfs(result);
597*10465441SEvalZero return 0;
598*10465441SEvalZero }
599*10465441SEvalZero
dfs_jffs2_stat(struct dfs_filesystem * fs,const char * path,struct stat * st)600*10465441SEvalZero static int dfs_jffs2_stat(struct dfs_filesystem* fs, const char *path, struct stat *st)
601*10465441SEvalZero {
602*10465441SEvalZero int result;
603*10465441SEvalZero struct jffs2_stat s;
604*10465441SEvalZero cyg_mtab_entry * mte;
605*10465441SEvalZero
606*10465441SEvalZero /* deal the path for jffs2 */
607*10465441SEvalZero RT_ASSERT(!((path[0] == '/') && (path[1] == 0)));
608*10465441SEvalZero
609*10465441SEvalZero if (path[0] == '/')
610*10465441SEvalZero path++;
611*10465441SEvalZero
612*10465441SEvalZero result = _find_fs(&mte, fs->dev_id);
613*10465441SEvalZero if (result)
614*10465441SEvalZero return -ENOENT;
615*10465441SEvalZero
616*10465441SEvalZero rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER);
617*10465441SEvalZero result = jffs2_porting_stat(mte, mte->root, path, (void *)&s);
618*10465441SEvalZero rt_mutex_release(&jffs2_lock);
619*10465441SEvalZero
620*10465441SEvalZero if (result)
621*10465441SEvalZero return jffs2_result_to_dfs(result);
622*10465441SEvalZero /* convert to dfs stat structure */
623*10465441SEvalZero switch(s.st_mode & JFFS2_S_IFMT)
624*10465441SEvalZero {
625*10465441SEvalZero case JFFS2_S_IFREG:
626*10465441SEvalZero st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
627*10465441SEvalZero S_IWUSR | S_IWGRP | S_IWOTH;
628*10465441SEvalZero break;
629*10465441SEvalZero
630*10465441SEvalZero case JFFS2_S_IFDIR:
631*10465441SEvalZero st->st_mode = S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
632*10465441SEvalZero break;
633*10465441SEvalZero
634*10465441SEvalZero default:
635*10465441SEvalZero st->st_mode = DT_UNKNOWN; //fixme
636*10465441SEvalZero break;
637*10465441SEvalZero }
638*10465441SEvalZero
639*10465441SEvalZero st->st_dev = 0;
640*10465441SEvalZero st->st_size = s.st_size;
641*10465441SEvalZero st->st_mtime = s.st_mtime;
642*10465441SEvalZero
643*10465441SEvalZero return 0;
644*10465441SEvalZero }
645*10465441SEvalZero
646*10465441SEvalZero static const struct dfs_file_ops _jffs2_fops =
647*10465441SEvalZero {
648*10465441SEvalZero dfs_jffs2_open,
649*10465441SEvalZero dfs_jffs2_close,
650*10465441SEvalZero dfs_jffs2_ioctl,
651*10465441SEvalZero dfs_jffs2_read,
652*10465441SEvalZero dfs_jffs2_write,
653*10465441SEvalZero dfs_jffs2_flush,
654*10465441SEvalZero dfs_jffs2_lseek,
655*10465441SEvalZero dfs_jffs2_getdents,
656*10465441SEvalZero };
657*10465441SEvalZero
658*10465441SEvalZero static const struct dfs_filesystem_ops _jffs2_ops =
659*10465441SEvalZero {
660*10465441SEvalZero "jffs2",
661*10465441SEvalZero DFS_FS_FLAG_DEFAULT,
662*10465441SEvalZero &_jffs2_fops,
663*10465441SEvalZero
664*10465441SEvalZero dfs_jffs2_mount,
665*10465441SEvalZero dfs_jffs2_unmount,
666*10465441SEvalZero dfs_jffs2_mkfs,
667*10465441SEvalZero dfs_jffs2_statfs,
668*10465441SEvalZero
669*10465441SEvalZero dfs_jffs2_unlink,
670*10465441SEvalZero dfs_jffs2_stat,
671*10465441SEvalZero dfs_jffs2_rename,
672*10465441SEvalZero };
673*10465441SEvalZero
dfs_jffs2_init(void)674*10465441SEvalZero int dfs_jffs2_init(void)
675*10465441SEvalZero {
676*10465441SEvalZero /* register fatfs file system */
677*10465441SEvalZero dfs_register(&_jffs2_ops);
678*10465441SEvalZero
679*10465441SEvalZero /* initialize mutex */
680*10465441SEvalZero if (rt_mutex_init(&jffs2_lock, "jffs2lock", RT_IPC_FLAG_FIFO) != RT_EOK)
681*10465441SEvalZero {
682*10465441SEvalZero rt_kprintf("init jffs2 lock mutex failed\n");
683*10465441SEvalZero }
684*10465441SEvalZero rt_kprintf("init jffs2 lock mutex okay\n");
685*10465441SEvalZero return 0;
686*10465441SEvalZero }
687*10465441SEvalZero INIT_COMPONENT_EXPORT(dfs_jffs2_init);
688