• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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