dfs_jffs2.c 19 KB

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