1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2012-1-7 prife the first version
9 */
10
11 #include "los_typedef.h"
12 #include "fileio.h"
13 #include "fcntl.h"
14 #include "sys/stat.h"
15 #undef mode_t
16
17 #include "vfs_jffs2.h"
18 #include "jffs2_config.h"
19 #include "porting.h"
20 #include "los_mux.h"
21 #include "inode/inode.h"
22 #include "sys/statfs.h"
23 #include "fs/dirent_fs.h"
24 #include "fs/fs.h"
25 #include "los_tables.h"
26 #include "mtd_list.h"
27 #include "port/fcntl.h"
28 #include "los_vm_filemap.h"
29
30 #ifdef LOSCFG_FS_JFFS
31
32 #if DEVICE_PART_MAX > 1
33 #error "support only one jffs2 partition on a flash device!"
34 #endif
35
36 LosMux jffs2_lock;
37 cyg_mtab_entry *mte[CONFIG_MTD_PATTITION_NUM];
38 static const char jffs2_root_path[] = ".";
39 #define BLOCK_SIZE 4096
40
jffs2_result_to_vfs(int result)41 int jffs2_result_to_vfs(int result)
42 {
43 if (result > 0)
44 result = -result;
45 return result;
46 }
47
48 struct inode *jffs_block[CONFIG_MTD_PATTITION_NUM];
vfs_jffs_bind(FAR struct inode * blkdriver,FAR const void * data,FAR void ** handle,FAR const char * relpath)49 static int vfs_jffs_bind(FAR struct inode *blkdriver,
50 FAR const void *data,
51 FAR void **handle,
52 FAR const char *relpath)
53 {
54 int result;
55 mtd_partition *p = (mtd_partition *)blkdriver->i_private;
56 int partition_num = p->patitionnum;
57 struct MtdDev *mtd = (struct MtdDev *)(p->mtd_info);
58 /* find a empty entry in partition table */
59 if (mtd == NULL) {
60 return -EINVAL;
61 }
62 if (mtd->type != MTD_NORFLASH) {
63 return -EINVAL;
64 }
65
66 mte[partition_num] = (cyg_mtab_entry*)malloc(sizeof(cyg_mtab_entry));
67 if (mte[partition_num] == NULL) {
68 return -ENOMEM;
69 }
70
71 mte[partition_num]->name = "jffs2";
72
73 /* note that, i use mte->n_private to store rtt's device
74 * while, in jffs2_mount, mte->n_private will be copy into
75 * s_dev in struct super_block, and mte->n_private will be
76 * filled with jffs2_sb(see the source of jffs2_mount.
77 */
78 /* after jffs2_mount, mte->n_private will not be dev_id any more */
79 result = jffs2_fs_type.mount(mte[partition_num], partition_num);
80 if (result != 0) {
81 free(mte[partition_num]);
82 mte[partition_num] = NULL;
83 return jffs2_result_to_vfs(result);
84 }
85 *handle = (void *)p;
86 jffs_block[partition_num] = blkdriver;
87 return 0;
88 }
89
vfs_jffs_unbind(FAR void * handle,FAR struct inode ** blkdriver)90 static int vfs_jffs_unbind(FAR void *handle, FAR struct inode **blkdriver)
91 {
92 int result;
93 mtd_partition *p = (mtd_partition *)handle;
94 int partition_num;
95
96 if (p == NULL)
97 return -EINVAL;
98
99 partition_num = p->patitionnum;
100 result = jffs2_fs_type.umount(mte[partition_num]);
101 if (result)
102 return jffs2_result_to_vfs(result);
103
104 free(mte[partition_num]);
105 mte[partition_num] = NULL;
106 free(p->mountpoint_name);
107 p->mountpoint_name = NULL;
108 *blkdriver = jffs_block[partition_num];
109 return 0;
110 }
111
oflag_convert_and_check(FAR struct file * filep,int oflags)112 static bool oflag_convert_and_check(FAR struct file *filep, int oflags)
113 {
114 int acc_mode = 0;
115 if ((oflags & O_ACCMODE) == O_RDONLY)
116 acc_mode |= READ_OP;
117 if (oflags & O_WRONLY)
118 acc_mode |= WRITE_OP;
119 if (oflags & O_RDWR)
120 acc_mode |= READ_OP | WRITE_OP;
121
122 if (oflags & O_CREAT)
123 acc_mode |= WRITE_OP;
124
125 if (oflags & O_TRUNC)
126 acc_mode |= WRITE_OP;
127
128 if (oflags & O_EXCL)
129 acc_mode |= WRITE_OP;
130 if (oflags & O_APPEND)
131 acc_mode |= WRITE_OP;
132
133 if (oflags & O_EXECVE)
134 acc_mode |= EXEC_OP;
135
136 if (filep->f_inode->mountflags == MS_RDONLY && (acc_mode & WRITE_OP) != 0) {
137 return false;
138 }
139 return true;
140 }
141
142
vfs_jffs_open(FAR struct file * filep,FAR const char * relpath,int oflags,mode_t mode)143 static int vfs_jffs_open(FAR struct file *filep,
144 FAR const char *relpath,
145 int oflags,
146 mode_t mode)
147 {
148 int result;
149 int partition_num;
150 const char *name = NULL;
151
152 cyg_file *jffs2_file = NULL;
153 mtd_partition *p = NULL;
154
155 p = (mtd_partition *)filep->f_inode->i_private;
156 partition_num = p->patitionnum;
157 jffs2_file = malloc(sizeof(cyg_file));
158 if (jffs2_file == NULL) {
159 return -ENOMEM;
160 }
161 name = relpath;
162 if ((name[0] == '/') && (name[1] == 0))
163 name = jffs2_root_path;
164 else if (name[0] == '/') /* name[0] still will be '/' */
165 name++;
166
167 if (oflag_convert_and_check(filep, oflags) != true) {
168 free(jffs2_file);
169 return -EACCES;
170 }
171
172
173 if (oflags & O_DIRECTORY) { /* operations about dir */
174 free(jffs2_file);
175 return -EACCES;
176 }
177
178
179 jffs_mutex_take(&jffs2_lock, (uint32_t)JFFS_WAITING_FOREVER);
180 result = jffs2_file_operations.open(mte[partition_num], name, oflags, mode, jffs2_file);
181 if (result != 0) {
182 jffs_mutex_release(&jffs2_lock);
183 free(jffs2_file);
184 return jffs2_result_to_vfs(result);
185 }
186 /* save this pointer, it will be used when calling read(),write(),
187 * flush(), lessk(), and will be free when calling close()
188 */
189 filep->f_priv = jffs2_file;
190 filep->f_pos = jffs2_file->f_offset;
191 jffs_mutex_release(&jffs2_lock);
192 return 0;
193 }
194
vfs_jffs_close(FAR struct file * filep)195 static int vfs_jffs_close(FAR struct file *filep)
196 {
197 int result;
198 cyg_file *jffs2_file = NULL;
199
200 LOS_ASSERT(filep->f_priv != NULL);
201 jffs2_file = (cyg_file *)(filep->f_priv);
202
203 /* regular file operations */
204 jffs_mutex_take(&jffs2_lock, (uint32_t)JFFS_WAITING_FOREVER);
205 result = jffs2_file_operations.close(jffs2_file);
206 jffs_mutex_release(&jffs2_lock);
207 if (result) {
208 return jffs2_result_to_vfs(result);
209 }
210 return 0;
211 }
212
vfs_jffs_read(FAR struct file * filep,FAR char * buffer,size_t buflen)213 static ssize_t vfs_jffs_read(FAR struct file *filep, FAR char *buffer, size_t buflen)
214 {
215 cyg_file *jffs2_file = NULL;
216 struct CYG_UIO_TAG uio_s;
217 struct CYG_IOVEC_TAG iovec;
218 int result;
219
220 LOS_ASSERT(filep->f_priv != NULL);
221 jffs2_file = (cyg_file *)(filep->f_priv);
222 uio_s.uio_iov = &iovec;
223 uio_s.uio_iov->iov_base = buffer;
224 uio_s.uio_iov->iov_len = buflen;
225 uio_s.uio_iovcnt = 1; /* must be 1 */
226 uio_s.uio_resid = uio_s.uio_iov->iov_len; /* seem no use in jffs2 */
227
228 jffs_mutex_take(&jffs2_lock, (uint32_t)JFFS_WAITING_FOREVER);
229 result = jffs2_file_operations.read(jffs2_file, &uio_s);
230 jffs_mutex_release(&jffs2_lock);
231 if (result)
232 return jffs2_result_to_vfs(result);
233
234 /* update position */
235 filep->f_pos= (loff_t)jffs2_file->f_offset;
236 return uio_s.uio_iov->iov_len - uio_s.uio_resid;
237 }
238
vfs_jffs_write(FAR struct file * filep,FAR const char * buffer,size_t buflen)239 static ssize_t vfs_jffs_write(FAR struct file *filep,
240 FAR const char *buffer,
241 size_t buflen)
242 {
243 cyg_file *jffs2_file = NULL;
244 struct CYG_UIO_TAG uio_s;
245 struct CYG_IOVEC_TAG iovec;
246 int result;
247
248 if (filep->f_inode->mountflags == MS_RDONLY) {
249 return -EACCES;
250 }
251
252 LOS_ASSERT(filep->f_priv != NULL);
253 jffs2_file = (cyg_file *)(filep->f_priv);
254 uio_s.uio_iov = &iovec;
255 uio_s.uio_iov->iov_base = (void *)buffer;
256 uio_s.uio_iov->iov_len = buflen;
257 uio_s.uio_iovcnt = 1; /* must be 1 */
258
259 uio_s.uio_resid = uio_s.uio_iov->iov_len; /* seem no use in jffs2 */
260
261 jffs_mutex_take(&jffs2_lock, (uint32_t)JFFS_WAITING_FOREVER);
262 result = jffs2_file_operations.write(jffs2_file, &uio_s);
263 jffs_mutex_release(&jffs2_lock);
264 /* update position */
265 filep->f_pos = (loff_t)jffs2_file->f_offset;
266 if (result) {
267 return jffs2_result_to_vfs(result);
268 }
269 return uio_s.uio_iov->iov_len - uio_s.uio_resid;
270 }
vfs_jffs_seek(FAR struct file * filep,off_t offset,int whence)271 static off_t vfs_jffs_seek(FAR struct file *filep, off_t offset, int whence)
272 {
273 cyg_file *jffs2_file = NULL;
274 int result;
275 LOS_ASSERT(filep->f_priv != NULL);
276 jffs2_file = (cyg_file *)(filep->f_priv);
277
278 /* set offset as current offset */
279 jffs_mutex_take(&jffs2_lock, (uint32_t)JFFS_WAITING_FOREVER);
280 result = jffs2_file_operations.lseek(jffs2_file, &offset, whence);
281 jffs_mutex_release(&jffs2_lock);
282 if (result)
283 return jffs2_result_to_vfs(result);
284 /* update file position */
285 filep->f_pos = (loff_t)offset;
286 return offset;
287 }
288
vfs_jffs_seek64(FAR struct file * filep,loff_t offset,int whence)289 static loff_t vfs_jffs_seek64(FAR struct file *filep, loff_t offset, int whence)
290 {
291 return (loff_t)vfs_jffs_seek(filep, (off_t)offset, whence);
292 }
293
vfs_jffs_ioctl(FAR struct file * filep,int cmd,unsigned long arg)294 static int vfs_jffs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
295 {
296 PRINT_DEBUG("%s NOT SUPPORT\n", __FUNCTION__);
297 return -ENOSYS;
298 }
299
vfs_jffs_sync(FAR struct file * filep)300 static int vfs_jffs_sync(FAR struct file *filep)
301 {
302 PRINT_DEBUG("%s NOT SUPPORT\n", __FUNCTION__);
303 return -ENOSYS;
304 }
305
vfs_jffs_dup(FAR const struct file * oldp,FAR struct file * newp)306 static int vfs_jffs_dup(FAR const struct file *oldp, FAR struct file *newp)
307 {
308 PRINT_DEBUG("%s NOT SUPPORT\n", __FUNCTION__);
309 return -ENOSYS;
310 }
311
vfs_jffs_opendir(FAR struct inode * mountpt,FAR const char * relpath,FAR struct fs_dirent_s * dir)312 static int vfs_jffs_opendir(FAR struct inode *mountpt,
313 FAR const char *relpath,
314 FAR struct fs_dirent_s *dir)
315 {
316 #ifdef CONFIG_JFFS2_NO_RELATIVEDIR
317 #define FILE_OFFSET 2
318 #endif
319 int result;
320 cyg_file *jffs2_file = NULL;
321 mtd_partition *p = (mtd_partition *)mountpt->i_private;
322 int partition_num = p->patitionnum;
323
324 jffs2_file = malloc(sizeof(cyg_file));
325 if (jffs2_file == NULL)
326 return -ENOMEM;
327
328 /* just escape '/' provided by vfs code */
329 if ((relpath[0] == '/') && (relpath[1] == 0))
330 relpath = jffs2_root_path;
331 else if (relpath[0] == '/') /* name[0] still will be '/' */
332 relpath ++;
333
334 /* open dir */
335 jffs_mutex_take(&jffs2_lock, (uint32_t)JFFS_WAITING_FOREVER);
336 result = jffs2_dir_operations.opendir(mte[partition_num], relpath, jffs2_file);
337 jffs_mutex_release(&jffs2_lock);
338 if (result) {
339 free(jffs2_file);
340 return jffs2_result_to_vfs(result);
341 }
342 #ifdef CONFIG_JFFS2_NO_RELATIVEDIR
343 jffs2_file->f_offset = FILE_OFFSET;
344 #endif
345 dir->u.fs_dir = (fs_dir_s)jffs2_file;
346 /* save this pointer, it will be used by vfs_jffs2_getdents */
347 return 0;
348
349 }
350
vfs_jffs_closedir(FAR struct inode * mountpt,FAR struct fs_dirent_s * dir)351 static int vfs_jffs_closedir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir)
352 {
353 int result;
354 cyg_file *jffs2_file = NULL;
355 jffs2_file = (cyg_file *)dir->u.fs_dir;
356 jffs_mutex_take(&jffs2_lock, (uint32_t)JFFS_WAITING_FOREVER);
357 result = jffs2_file_operations.close(jffs2_file);
358 jffs_mutex_release(&jffs2_lock);
359 if (result)
360 return jffs2_result_to_vfs(result);
361 return 0;
362 }
363
vfs_jffs_readdir(FAR struct inode * mountpt,FAR struct fs_dirent_s * dir)364 static int vfs_jffs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir)
365 {
366 cyg_file *jffs2_file = NULL;
367 struct CYG_UIO_TAG uio_s;
368 struct CYG_IOVEC_TAG iovec;
369 struct jffs2_dirent jffs2_d;
370 int result;
371 int i = 0;
372 uint32_t dst_name_size;
373
374 jffs2_file = (cyg_file *)(dir->u.fs_dir);
375
376 while (i < MAX_DIRENT_NUM && i < dir->read_cnt) {
377 /* set jffs2_d */
378 (void)memset_s(&jffs2_d, sizeof(struct jffs2_dirent), 0, sizeof(struct jffs2_dirent));
379 /* set CYG_UIO_TAG uio_s */
380 uio_s.uio_iov = &iovec;
381 uio_s.uio_iov->iov_base = &jffs2_d;
382 uio_s.uio_iov->iov_len = sizeof(struct jffs2_dirent);;
383 uio_s.uio_iovcnt = 1; /* must be 1 */
384 uio_s.uio_offset = 0; /* not used... */
385 uio_s.uio_resid = uio_s.uio_iov->iov_len; /* seem no use in jffs2; */
386
387 jffs_mutex_take(&jffs2_lock, (uint32_t)JFFS_WAITING_FOREVER);
388 result = jffs2_dir_operations.readdir(jffs2_file, &uio_s);
389 jffs_mutex_release(&jffs2_lock);
390
391 if (result) {
392 break;
393 }
394
395 dir->fd_dir[i].d_type = jffs2_d.d_type;
396 dst_name_size = sizeof(dir->fd_dir[i].d_name);
397 result = strncpy_s(dir->fd_dir[i].d_name, dst_name_size, jffs2_d.d_name, dst_name_size - 1);
398 if (result != EOK) {
399 return -ENAMETOOLONG;
400 }
401 dir->fd_dir[i].d_name[dst_name_size - 1] = '\0';
402 dir->fd_position++;
403 dir->fd_dir[i].d_off = dir->fd_position;
404 dir->fd_dir[i].d_reclen = (uint16_t)sizeof(struct dirent);
405
406 i++;
407 }
408 return i;
409 }
410
vfs_jffs_rewinddir(FAR struct inode * mountpt,FAR struct fs_dirent_s * dir)411 static int vfs_jffs_rewinddir(FAR struct inode *mountpt,
412 FAR struct fs_dirent_s *dir)
413 {
414 int result;
415 off_t pos = 0;
416 cyg_file *jffs2_file = (cyg_file *)(dir->u.fs_dir);
417
418 jffs_mutex_take(&jffs2_lock, (uint32_t)JFFS_WAITING_FOREVER);
419 result = jffs2_dir_operations.lseekdir(jffs2_file, &pos, SEEK_SET);
420 jffs_mutex_release(&jffs2_lock);
421
422 if (result)
423 return jffs2_result_to_vfs(result);
424 return OK;
425 }
426
vfs_jffs_mkdir(FAR struct inode * mountpt,FAR const char * relpath,mode_t mode)427 static int vfs_jffs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, mode_t mode)
428 {
429 int result;
430 mtd_partition *p = (mtd_partition *)mountpt->i_private;
431 int partition_num = p->patitionnum;
432 /* deal path */
433 if (relpath[0] == '/')
434 relpath++;
435
436 if (mountpt->mountflags == MS_RDONLY)
437 return -EACCES;
438
439 jffs_mutex_take(&jffs2_lock, (uint32_t)JFFS_WAITING_FOREVER);
440 result = jffs2_dir_inode_operations.mkdir(mte[partition_num], relpath, mode);
441 jffs_mutex_release(&jffs2_lock);
442
443 if (result)
444 return jffs2_result_to_vfs(result);
445 return OK;
446 }
447
vfs_jffs_chattr(FAR struct inode * mountpt,FAR const char * relpath,iattr * attr)448 static int vfs_jffs_chattr(FAR struct inode *mountpt, FAR const char *relpath, iattr *attr)
449 {
450 int result;
451 mtd_partition *p = (mtd_partition *)mountpt->i_private;
452 int partition_num = p->patitionnum;
453 /* deal path */
454 if (relpath[0] == '/')
455 relpath++;
456
457 if (mountpt->mountflags == MS_RDONLY)
458 return -EACCES;
459
460 jffs_mutex_take(&jffs2_lock, (uint32_t)JFFS_WAITING_FOREVER);
461 result = jffs2_file_operations.chattr(mte[partition_num],relpath, attr);
462 jffs_mutex_release(&jffs2_lock);
463
464 if (result)
465 return jffs2_result_to_vfs(result);
466 return OK;
467 }
468
469
vfs_jffs_rmdir(FAR struct inode * mountpt,FAR const char * relpath)470 static int vfs_jffs_rmdir(FAR struct inode *mountpt, FAR const char *relpath)
471 {
472 int result;
473 mtd_partition *p = (mtd_partition *)mountpt->i_private;
474 int partition_num = p->patitionnum;
475
476 /* deal path */
477 if (relpath[0] == '/')
478 relpath++;
479 else if (relpath[0] == '\0')
480 return -EBUSY;
481
482 if (mountpt->mountflags == MS_RDONLY)
483 return -EACCES;
484
485 jffs_mutex_take(&jffs2_lock, (uint32_t)JFFS_WAITING_FOREVER);
486 result = jffs2_dir_inode_operations.rmdir(mte[partition_num], relpath);
487 jffs_mutex_release(&jffs2_lock);
488
489 if (result)
490 return jffs2_result_to_vfs(result);
491 return OK;
492 }
493
vfs_jffs_unlink(FAR struct inode * mountpt,FAR const char * relpath)494 static int vfs_jffs_unlink(FAR struct inode *mountpt, FAR const char *relpath)
495 {
496 int result;
497 mtd_partition *p = (mtd_partition *)mountpt->i_private;
498 int partition_num = p->patitionnum;
499 struct jffs2_stat s;
500 /* deal path */
501 if (relpath[0] == '/')
502 relpath++;
503
504 if (mountpt->mountflags == MS_RDONLY)
505 return -EACCES;
506
507 /* judge file type, dir is to be delete by rmdir, others by unlink */
508 jffs_mutex_take(&jffs2_lock, (uint32_t)JFFS_WAITING_FOREVER);
509 result = jffs2_fs_type.stat(mte[partition_num],relpath, &s);
510 if (result) {
511 jffs_mutex_release(&jffs2_lock);
512 return jffs2_result_to_vfs(result);
513 }
514 switch (s.st_mode & JFFS2_S_IFMT) {
515 case JFFS2_S_IFREG:
516 result = jffs2_dir_inode_operations.unlink(mte[partition_num],relpath);
517 break;
518 case JFFS2_S_IFDIR:
519 result = -EISDIR;
520 break;
521 default:
522 /* unknown file type */
523 jffs_mutex_release(&jffs2_lock);
524 return -1;
525 }
526 jffs_mutex_release(&jffs2_lock);
527 if (result)
528 return jffs2_result_to_vfs(result);
529 return 0;
530 }
531
vfs_jffs_rename(FAR struct inode * mountpt,FAR const char * oldrelpath,FAR const char * newrelpath)532 static int vfs_jffs_rename(FAR struct inode *mountpt,
533 FAR const char *oldrelpath,
534 FAR const char *newrelpath)
535 {
536 int result;
537 mtd_partition *p = (mtd_partition *)mountpt->i_private;
538 int partition_num = p->patitionnum;
539 if (*oldrelpath == '/')
540 oldrelpath += 1;
541 if (*newrelpath == '/')
542 newrelpath += 1;
543
544 if (mountpt->mountflags == MS_RDONLY)
545 return -EACCES;
546
547 jffs_mutex_take(&jffs2_lock, (uint32_t)JFFS_WAITING_FOREVER);
548 result = jffs2_dir_inode_operations.rename(mte[partition_num],oldrelpath,newrelpath);
549 jffs_mutex_release(&jffs2_lock);
550 if (result)
551 return jffs2_result_to_vfs(result);
552 return 0;
553 }
554
vfs_jffs_stat(FAR struct inode * mountpt,FAR const char * relpath,FAR struct stat * buf)555 static int vfs_jffs_stat(FAR struct inode *mountpt,
556 FAR const char *relpath,
557 FAR struct stat *buf)
558 {
559 int result;
560 struct jffs2_stat s;
561 mtd_partition *p = (mtd_partition *)mountpt->i_private;
562 int partition_num = p->patitionnum;
563
564 /* deal the path for jffs2 */
565 if (relpath[0] == '/')
566 relpath++;
567
568 jffs_mutex_take(&jffs2_lock, (uint32_t)JFFS_WAITING_FOREVER);
569 result = jffs2_fs_type.stat(mte[partition_num], relpath, &s);
570 jffs_mutex_release(&jffs2_lock);
571
572 if (result)
573 return jffs2_result_to_vfs(result);
574 /* convert to vfs stat structure */
575 switch (s.st_mode & JFFS2_S_IFMT) {
576 case JFFS2_S_IFREG:
577 buf->st_mode = s.st_mode;
578 break;
579
580 case JFFS2_S_IFDIR:
581 buf->st_mode = s.st_mode;
582 break;
583
584 default:
585 buf->st_mode = DT_UNKNOWN; /* fixme */
586 break;
587 }
588
589 buf->st_dev = 0;
590 buf->st_size = s.st_size;
591 buf->st_mtim.tv_sec = s.sddst_mtime;
592 buf->st_mtim.tv_nsec = 0;
593 buf->st_atim.tv_sec = s.sddst_atime;
594 buf->st_atim.tv_nsec = 0;
595 buf->st_ctim.tv_sec = s.sddst_ctime;
596 buf->st_ctim.tv_nsec = 0;
597 buf->st_blksize = BLOCK_SIZE; /* fixme: what's this field? */
598 buf->st_ino = s.st_ino;
599 buf->st_gid = s.st_gid;
600 buf->st_uid = s.st_uid;
601 buf->st_nlink = s.st_nlink;
602 buf->st_blocks = s.st_size / BLOCK_SIZE;
603
604 return 0;
605 }
606
vfs_jffs_statfs(FAR struct inode * mountpt,FAR struct statfs * buf)607 static int vfs_jffs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf)
608 {
609 /* since the limit of unsigned long, so the max size of flash device is 4G */
610 struct jffs2_fs_info info;
611 mtd_partition *p = (mtd_partition *)mountpt->i_private;
612 int partition_num = p->patitionnum;
613 LOS_ASSERT(mte[partition_num]->data != 0);
614
615 jffs2_get_info_from_sb((void *)mte[partition_num]->data, &info);
616 buf->f_type = JFFS2_SUPER_MAGIC;
617 buf->f_bsize = JFFS2_PAGE_SIZE;
618 buf->f_blocks = (((uint64_t)info.nr_blocks) * info.sector_size) / JFFS2_PAGE_SIZE;
619 buf->f_bfree = info.free_size / JFFS2_PAGE_SIZE;
620 buf->f_bavail = buf->f_bfree;
621 buf->f_namelen = CONFIG_JFFS2_ENTRY_NAME_MAX;
622 buf->f_fsid.__val[0] = JFFS2_SUPER_MAGIC;
623 buf->f_fsid.__val[1] = 1;
624 buf->f_frsize = BLOCK_SIZE;
625 buf->f_files = 0;
626 buf->f_ffree = 0;
627 buf->f_flags = mountpt->mountflags;
628 return 0;
629 }
630
JffsMutexCreate(void)631 int JffsMutexCreate(void)
632 {
633 if (LOS_MuxInit(&jffs2_lock, NULL) != LOS_OK) {
634 PRINT_ERR("%s, LOS_MuxCreate failed\n", __FUNCTION__);
635 return -1;
636 } else {
637 return 0;
638 }
639 }
640
JffsMutexDelete(void)641 void JffsMutexDelete(void)
642 {
643 (void)LOS_MuxDestroy(&jffs2_lock);
644 }
645
646 const struct mountpt_operations jffs_operations = {
647 vfs_jffs_open, /* open */
648 vfs_jffs_close, /* close */
649 vfs_jffs_read, /* read */
650 vfs_jffs_write, /* write */
651 vfs_jffs_seek, /* seek */
652 vfs_jffs_ioctl, /* ioctl */
653 OsVfsFileMmap, /* mmap */
654
655 vfs_jffs_sync, /* sync */
656 vfs_jffs_dup, /* dup */
657 NULL, /* fstat */
658 NULL, /* truncate */
659
660 vfs_jffs_opendir, /* opendir */
661 vfs_jffs_closedir, /* closedir */
662 vfs_jffs_readdir, /* readdir */
663
664 vfs_jffs_rewinddir, /* rewinddir */
665
666 vfs_jffs_bind, /* bind */
667 vfs_jffs_unbind, /* unbind */
668 vfs_jffs_statfs, /* statfs */
669 NULL, /* virstatfs */
670 vfs_jffs_unlink, /* unlinke */
671 vfs_jffs_mkdir, /* mkdir */
672 vfs_jffs_rmdir, /* rmdir */
673 vfs_jffs_rename, /* rename */
674 vfs_jffs_stat, /* stat */
675 NULL, /* for utime */
676 vfs_jffs_chattr, /* chattr */
677 vfs_jffs_seek64, /* seek64 */
678 NULL, /* getlabel */
679 NULL, /* fallocate Contiguous blocks */
680 NULL, /* fallocate64 */
681 NULL, /* truncate64 */
682 NULL, /* fscheck */
683 NULL, /* map_pages */
684 NULL, /* readpage */
685 NULL, /* writepage */
686 };
687
688 FSMAP_ENTRY(jffs_fsmap, "jffs2", jffs_operations, TRUE, TRUE);
689
690 #endif
691