dfs_jffs2.c 20 KB

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