dfs_jffs2.c 16 KB

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