dfs_jffs2.c 19 KB

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