dfs_cromfs.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348
  1. /*
  2. * Copyright (c) 2006-2020, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020/08/21 ShaoJinchun first version
  9. */
  10. #include <rtthread.h>
  11. #include <dfs.h>
  12. #include <dfs_fs.h>
  13. #include <dfs_file.h>
  14. #include <dfs_dentry.h>
  15. #include <dfs_mnt.h>
  16. #include "dfs_cromfs.h"
  17. #include <stdint.h>
  18. #include "zlib.h"
  19. /**********************************/
  20. #define CROMFS_PATITION_HEAD_SIZE 256
  21. #define CROMFS_DIRENT_CACHE_SIZE 8
  22. #define CROMFS_MAGIC "CROMFSMG"
  23. #define CROMFS_CT_ASSERT(name, x) \
  24. struct assert_##name {char ary[2 * (x) - 1];}
  25. #define CROMFS_POS_ROOT (0x0UL)
  26. #define CROMFS_POS_ERROR (0x1UL)
  27. typedef struct
  28. {
  29. uint8_t magic[8]; /* CROMFS_MAGIC */
  30. uint32_t version;
  31. uint32_t partition_attr; /* expand, now reserved 0 */
  32. uint32_t partition_size; /* with partition head */
  33. uint32_t root_dir_pos; /* root dir pos */
  34. uint32_t root_dir_size;
  35. } partition_head_data;
  36. typedef struct
  37. {
  38. partition_head_data head;
  39. uint8_t padding[CROMFS_PATITION_HEAD_SIZE - sizeof(partition_head_data)];
  40. } partition_head;
  41. enum
  42. {
  43. CROMFS_DIRENT_ATTR_FILE = 0x0UL,
  44. CROMFS_DIRENT_ATTR_DIR = 0x1UL,
  45. CROMFS_DIRENT_ATTR_SYMLINK = 0x2UL,
  46. };
  47. typedef struct
  48. {
  49. uint16_t attr; /* dir or file add other */
  50. uint16_t name_size; /* name real size */
  51. uint32_t file_size; /* file data size */
  52. uint32_t file_origin_size; /* file size before compress */
  53. uint32_t parition_pos; /* offset of data */
  54. uint8_t name[0]; /* name data */
  55. } cromfs_dirent;
  56. #define CROMFS_ALIGN_SIZE_BIT 4
  57. #define CROMFS_ALIGN_SIZE (1UL << CROMFS_ALIGN_SIZE_BIT) /* must be same as sizeof cromfs_dirent */
  58. #define CROMFS_ALIGN_SIZE_MASK (CROMFS_ALIGN_SIZE - 1)
  59. CROMFS_CT_ASSERT(align_size, CROMFS_ALIGN_SIZE == sizeof(cromfs_dirent));
  60. typedef union
  61. {
  62. cromfs_dirent dirent;
  63. uint8_t name[CROMFS_ALIGN_SIZE];
  64. } cromfs_dirent_item;
  65. /**********************************/
  66. typedef struct
  67. {
  68. rt_list_t list;
  69. uint32_t partition_pos;
  70. uint32_t size;
  71. uint8_t *buff;
  72. } cromfs_dirent_cache;
  73. typedef struct st_cromfs_info
  74. {
  75. rt_device_t device;
  76. uint32_t partition_size;
  77. uint32_t bytes_per_sector;
  78. uint32_t (*read_bytes)(struct st_cromfs_info *ci, uint32_t pos, void *buf, uint32_t size);
  79. partition_head_data part_info;
  80. struct rt_mutex lock;
  81. struct cromfs_avl_struct *cromfs_avl_root;
  82. rt_list_t cromfs_dirent_cache_head;
  83. int cromfs_dirent_cache_nr;
  84. const void *data;
  85. } cromfs_info;
  86. typedef struct
  87. {
  88. uint32_t ref;
  89. uint32_t partition_pos;
  90. cromfs_info *ci;
  91. uint32_t size;
  92. uint8_t *buff;
  93. uint32_t partition_size;
  94. int data_valid;
  95. } file_info;
  96. /**********************************/
  97. #define avl_key_t uint32_t
  98. #define AVL_EMPTY (struct cromfs_avl_struct *)0
  99. #define avl_maxheight 32
  100. #define heightof(tree) ((tree) == AVL_EMPTY ? 0 : (tree)->avl_height)
  101. struct cromfs_avl_struct
  102. {
  103. struct cromfs_avl_struct *avl_left;
  104. struct cromfs_avl_struct *avl_right;
  105. int avl_height;
  106. avl_key_t avl_key;
  107. file_info *fi;
  108. };
  109. static void cromfs_avl_remove(struct cromfs_avl_struct *node_to_delete, struct cromfs_avl_struct **ptree);
  110. static void cromfs_avl_insert(struct cromfs_avl_struct *new_node, struct cromfs_avl_struct **ptree);
  111. static struct cromfs_avl_struct* cromfs_avl_find(avl_key_t key, struct cromfs_avl_struct *ptree);
  112. static void cromfs_avl_rebalance(struct cromfs_avl_struct ***nodeplaces_ptr, int count)
  113. {
  114. for (;count > 0; count--)
  115. {
  116. struct cromfs_avl_struct **nodeplace = *--nodeplaces_ptr;
  117. struct cromfs_avl_struct *node = *nodeplace;
  118. struct cromfs_avl_struct *nodeleft = node->avl_left;
  119. struct cromfs_avl_struct *noderight = node->avl_right;
  120. int heightleft = heightof(nodeleft);
  121. int heightright = heightof(noderight);
  122. if (heightright + 1 < heightleft)
  123. {
  124. struct cromfs_avl_struct * nodeleftleft = nodeleft->avl_left;
  125. struct cromfs_avl_struct * nodeleftright = nodeleft->avl_right;
  126. int heightleftright = heightof(nodeleftright);
  127. if (heightof(nodeleftleft) >= heightleftright)
  128. {
  129. node->avl_left = nodeleftright;
  130. nodeleft->avl_right = node;
  131. nodeleft->avl_height = 1 + (node->avl_height = 1 + heightleftright);
  132. *nodeplace = nodeleft;
  133. }
  134. else
  135. {
  136. nodeleft->avl_right = nodeleftright->avl_left;
  137. node->avl_left = nodeleftright->avl_right;
  138. nodeleftright->avl_left = nodeleft;
  139. nodeleftright->avl_right = node;
  140. nodeleft->avl_height = node->avl_height = heightleftright;
  141. nodeleftright->avl_height = heightleft;
  142. *nodeplace = nodeleftright;
  143. }
  144. }
  145. else if (heightleft + 1 < heightright)
  146. {
  147. struct cromfs_avl_struct *noderightright = noderight->avl_right;
  148. struct cromfs_avl_struct *noderightleft = noderight->avl_left;
  149. int heightrightleft = heightof(noderightleft);
  150. if (heightof(noderightright) >= heightrightleft)
  151. {
  152. node->avl_right = noderightleft;
  153. noderight->avl_left = node;
  154. noderight->avl_height = 1 + (node->avl_height = 1 + heightrightleft);
  155. *nodeplace = noderight;
  156. }
  157. else
  158. {
  159. noderight->avl_left = noderightleft->avl_right;
  160. node->avl_right = noderightleft->avl_left;
  161. noderightleft->avl_right = noderight;
  162. noderightleft->avl_left = node;
  163. noderight->avl_height = node->avl_height = heightrightleft;
  164. noderightleft->avl_height = heightright;
  165. *nodeplace = noderightleft;
  166. }
  167. }
  168. else {
  169. int height = (heightleft<heightright ? heightright : heightleft) + 1;
  170. if (height == node->avl_height)
  171. {
  172. break;
  173. }
  174. node->avl_height = height;
  175. }
  176. }
  177. }
  178. static void cromfs_avl_remove(struct cromfs_avl_struct *node_to_delete, struct cromfs_avl_struct **ptree)
  179. {
  180. avl_key_t key = node_to_delete->avl_key;
  181. struct cromfs_avl_struct **nodeplace = ptree;
  182. struct cromfs_avl_struct **stack[avl_maxheight];
  183. uint32_t stack_count = 0;
  184. struct cromfs_avl_struct ***stack_ptr = &stack[0]; /* = &stack[stackcount] */
  185. struct cromfs_avl_struct **nodeplace_to_delete;
  186. for (;;)
  187. {
  188. struct cromfs_avl_struct *node = *nodeplace;
  189. if (node == AVL_EMPTY)
  190. {
  191. return;
  192. }
  193. *stack_ptr++ = nodeplace;
  194. stack_count++;
  195. if (key == node->avl_key)
  196. {
  197. break;
  198. }
  199. if (key < node->avl_key)
  200. {
  201. nodeplace = &node->avl_left;
  202. }
  203. else
  204. {
  205. nodeplace = &node->avl_right;
  206. }
  207. }
  208. nodeplace_to_delete = nodeplace;
  209. if (node_to_delete->avl_left == AVL_EMPTY)
  210. {
  211. *nodeplace_to_delete = node_to_delete->avl_right;
  212. stack_ptr--;
  213. stack_count--;
  214. }
  215. else
  216. {
  217. struct cromfs_avl_struct *** stack_ptr_to_delete = stack_ptr;
  218. struct cromfs_avl_struct ** nodeplace = &node_to_delete->avl_left;
  219. struct cromfs_avl_struct * node;
  220. for (;;)
  221. {
  222. node = *nodeplace;
  223. if (node->avl_right == AVL_EMPTY)
  224. {
  225. break;
  226. }
  227. *stack_ptr++ = nodeplace;
  228. stack_count++;
  229. nodeplace = &node->avl_right;
  230. }
  231. *nodeplace = node->avl_left;
  232. node->avl_left = node_to_delete->avl_left;
  233. node->avl_right = node_to_delete->avl_right;
  234. node->avl_height = node_to_delete->avl_height;
  235. *nodeplace_to_delete = node;
  236. *stack_ptr_to_delete = &node->avl_left;
  237. }
  238. cromfs_avl_rebalance(stack_ptr,stack_count);
  239. }
  240. static void cromfs_avl_insert(struct cromfs_avl_struct *new_node, struct cromfs_avl_struct **ptree)
  241. {
  242. avl_key_t key = new_node->avl_key;
  243. struct cromfs_avl_struct **nodeplace = ptree;
  244. struct cromfs_avl_struct **stack[avl_maxheight];
  245. int stack_count = 0;
  246. struct cromfs_avl_struct ***stack_ptr = &stack[0]; /* = &stack[stackcount] */
  247. for (;;)
  248. {
  249. struct cromfs_avl_struct * node = *nodeplace;
  250. if (node == AVL_EMPTY)
  251. {
  252. break;
  253. }
  254. *stack_ptr++ = nodeplace;
  255. stack_count++;
  256. if (key < node->avl_key)
  257. {
  258. nodeplace = &node->avl_left;
  259. }
  260. else
  261. {
  262. nodeplace = &node->avl_right;
  263. }
  264. }
  265. new_node->avl_left = AVL_EMPTY;
  266. new_node->avl_right = AVL_EMPTY;
  267. new_node->avl_height = 1;
  268. *nodeplace = new_node;
  269. cromfs_avl_rebalance(stack_ptr,stack_count);
  270. }
  271. static struct cromfs_avl_struct* cromfs_avl_find(avl_key_t key, struct cromfs_avl_struct* ptree)
  272. {
  273. for (;;)
  274. {
  275. if (ptree == AVL_EMPTY)
  276. {
  277. return (struct cromfs_avl_struct *)0;
  278. }
  279. if (key == ptree->avl_key)
  280. {
  281. break;
  282. }
  283. if (key < ptree->avl_key)
  284. {
  285. ptree = ptree->avl_left;
  286. }
  287. else
  288. {
  289. ptree = ptree->avl_right;
  290. }
  291. }
  292. return ptree;
  293. }
  294. /**********************************/
  295. static uint32_t cromfs_read_bytes(cromfs_info *ci, uint32_t pos, void *buf, uint32_t size)
  296. {
  297. if (pos >= ci->partition_size || pos + size > ci->partition_size)
  298. {
  299. return 0;
  300. }
  301. return ci->read_bytes(ci, pos, buf, size);
  302. }
  303. static uint32_t cromfs_noblk_read_bytes(cromfs_info *ci, uint32_t pos, void *buf, uint32_t size)
  304. {
  305. uint32_t ret = 0;
  306. ret = rt_device_read(ci->device, pos, buf, size);
  307. if (ret != size)
  308. {
  309. return 0;
  310. }
  311. else
  312. {
  313. return ret;
  314. }
  315. }
  316. static uint32_t cromfs_data_read_bytes(cromfs_info *ci, uint32_t pos, void *buf, uint32_t size)
  317. {
  318. uint32_t ret = 0;
  319. uint8_t *data = (uint8_t *)ci->data;
  320. if (data)
  321. {
  322. memcpy(buf, data + pos, size);
  323. ret = size;
  324. }
  325. return ret;
  326. }
  327. static uint32_t cromfs_blk_read_bytes(cromfs_info *ci, uint32_t pos, void *buf, uint32_t size)
  328. {
  329. uint32_t ret = 0;
  330. uint32_t size_bak = size;
  331. uint32_t start_blk = 0;
  332. uint32_t end_blk = 0;
  333. uint32_t off_s = 0;
  334. uint32_t sector_nr = 0;
  335. uint8_t *block_buff = NULL;
  336. uint32_t ret_len = 0;
  337. if (!size || !buf)
  338. {
  339. return 0;
  340. }
  341. block_buff = (uint8_t *)malloc(2 * ci->bytes_per_sector);
  342. if (!block_buff)
  343. {
  344. return 0;
  345. }
  346. start_blk = pos / ci->bytes_per_sector;
  347. off_s = pos % ci->bytes_per_sector;
  348. end_blk = (pos + size - 1) / ci->bytes_per_sector;
  349. sector_nr = end_blk - start_blk;
  350. if (sector_nr < 2)
  351. {
  352. ret_len = rt_device_read(ci->device, start_blk, block_buff, sector_nr + 1);
  353. if (ret_len != sector_nr + 1)
  354. {
  355. goto end;
  356. }
  357. memcpy(buf, block_buff + off_s, size);
  358. }
  359. else
  360. {
  361. ret_len = rt_device_read(ci->device, start_blk, block_buff, 1);
  362. if (ret_len != 1)
  363. {
  364. goto end;
  365. }
  366. memcpy(buf, block_buff + off_s, ci->bytes_per_sector - off_s);
  367. off_s = (ci->bytes_per_sector - off_s);
  368. size -= off_s;
  369. sector_nr--;
  370. start_blk++;
  371. if (sector_nr)
  372. {
  373. ret_len = rt_device_read(ci->device, start_blk, (char*)buf + off_s, sector_nr);
  374. if (ret_len != sector_nr)
  375. {
  376. goto end;
  377. }
  378. start_blk += sector_nr;
  379. off_s += (sector_nr * ci->bytes_per_sector);
  380. size -= (sector_nr * ci->bytes_per_sector);
  381. }
  382. ret_len = rt_device_read(ci->device, start_blk, block_buff, 1);
  383. if (ret_len != 1)
  384. {
  385. goto end;
  386. }
  387. memcpy((char*)buf + off_s, block_buff, size);
  388. }
  389. ret = size_bak;
  390. end:
  391. free(block_buff);
  392. return ret;
  393. }
  394. /**********************************/
  395. static uint8_t *cromfs_dirent_cache_get(cromfs_info *ci, uint32_t pos, uint32_t size)
  396. {
  397. rt_list_t *l = NULL;
  398. cromfs_dirent_cache *dir = NULL;
  399. uint32_t len = 0;
  400. /* find */
  401. for (l = ci->cromfs_dirent_cache_head.next; l != &ci->cromfs_dirent_cache_head; l = l->next)
  402. {
  403. dir = (cromfs_dirent_cache *)l;
  404. if (dir->partition_pos == pos)
  405. {
  406. RT_ASSERT(dir->size == size);
  407. rt_list_remove(l);
  408. rt_list_insert_after(&ci->cromfs_dirent_cache_head, l);
  409. return dir->buff;
  410. }
  411. }
  412. /* not found */
  413. if (ci->cromfs_dirent_cache_nr >= CROMFS_DIRENT_CACHE_SIZE)
  414. {
  415. l = ci->cromfs_dirent_cache_head.prev;
  416. dir = (cromfs_dirent_cache *)l;
  417. rt_list_remove(l);
  418. free(dir->buff);
  419. free(dir);
  420. ci->cromfs_dirent_cache_nr--;
  421. }
  422. dir = (cromfs_dirent_cache *)malloc(sizeof *dir);
  423. if (!dir)
  424. {
  425. return NULL;
  426. }
  427. dir->buff = (uint8_t *)malloc(size);
  428. if (!dir->buff)
  429. {
  430. free(dir);
  431. return NULL;
  432. }
  433. len = cromfs_read_bytes(ci, pos, dir->buff, size);
  434. if (len != size)
  435. {
  436. free(dir->buff);
  437. free(dir);
  438. return NULL;
  439. }
  440. rt_list_insert_after(&ci->cromfs_dirent_cache_head, (rt_list_t *)dir);
  441. ci->cromfs_dirent_cache_nr++;
  442. dir->partition_pos = pos;
  443. dir->size = size;
  444. return dir->buff;
  445. }
  446. static void cromfs_dirent_cache_destroy(cromfs_info *ci)
  447. {
  448. rt_list_t *l = NULL;
  449. cromfs_dirent_cache *dir = NULL;
  450. while ((l = ci->cromfs_dirent_cache_head.next) != &ci->cromfs_dirent_cache_head)
  451. {
  452. rt_list_remove(l);
  453. dir = (cromfs_dirent_cache *)l;
  454. free(dir->buff);
  455. free(dir);
  456. ci->cromfs_dirent_cache_nr--;
  457. }
  458. }
  459. /**********************************/
  460. static int dfs_cromfs_mount(struct dfs_mnt *mnt, unsigned long rwflag, const void *data)
  461. {
  462. struct rt_device_blk_geometry geometry;
  463. uint32_t len = 0;
  464. cromfs_info *ci = NULL;
  465. ci = (cromfs_info *)malloc(sizeof *ci);
  466. if (!ci)
  467. {
  468. return -ENOMEM;
  469. }
  470. memset(ci, 0, sizeof *ci);
  471. ci->device = mnt->dev_id;
  472. ci->partition_size = UINT32_MAX;
  473. if (ci->device)
  474. {
  475. rt_err_t ret = rt_device_open(ci->device, RT_DEVICE_OFLAG_RDONLY);
  476. if (ret != RT_EOK)
  477. {
  478. free(ci);
  479. return ret;
  480. }
  481. if (ci->device->type == RT_Device_Class_Block)
  482. {
  483. rt_device_control(ci->device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
  484. ci->bytes_per_sector = geometry.bytes_per_sector;
  485. ci->read_bytes = cromfs_blk_read_bytes;
  486. }
  487. else
  488. {
  489. ci->read_bytes = cromfs_noblk_read_bytes;
  490. }
  491. }
  492. else if (data)
  493. {
  494. ci->data = data;
  495. ci->read_bytes = cromfs_data_read_bytes;
  496. }
  497. else
  498. {
  499. free(ci);
  500. return -RT_EIO;
  501. }
  502. len = cromfs_read_bytes(ci, 0, &ci->part_info, sizeof ci->part_info);
  503. if (len != sizeof ci->part_info ||
  504. memcmp(ci->part_info.magic, CROMFS_MAGIC, sizeof ci->part_info.magic) != 0)
  505. {
  506. free(ci);
  507. return -RT_ERROR;
  508. }
  509. ci->partition_size = ci->part_info.partition_size;
  510. mnt->data = ci;
  511. rt_mutex_init(&ci->lock, "crom", RT_IPC_FLAG_FIFO);
  512. ci->cromfs_avl_root = NULL;
  513. rt_list_init(&ci->cromfs_dirent_cache_head);
  514. ci->cromfs_dirent_cache_nr = 0;
  515. return RT_EOK;
  516. }
  517. static int dfs_cromfs_unmount(struct dfs_mnt *mnt)
  518. {
  519. rt_err_t result = RT_EOK;
  520. cromfs_info *ci = NULL;
  521. ci = (cromfs_info *)mnt->data;
  522. result = rt_mutex_take(&ci->lock, RT_WAITING_FOREVER);
  523. if (result != RT_EOK)
  524. {
  525. return -RT_ERROR;
  526. }
  527. cromfs_dirent_cache_destroy(ci);
  528. while (ci->cromfs_avl_root)
  529. {
  530. struct cromfs_avl_struct *node;
  531. file_info *fi = NULL;
  532. node = ci->cromfs_avl_root;
  533. fi = node->fi;
  534. cromfs_avl_remove(node, &ci->cromfs_avl_root);
  535. free(node);
  536. if (fi->buff)
  537. {
  538. free(fi->buff);
  539. }
  540. free(fi);
  541. }
  542. if (ci->device)
  543. {
  544. rt_device_close(ci->device);
  545. }
  546. rt_mutex_detach(&ci->lock);
  547. free(ci);
  548. return RT_EOK;
  549. }
  550. static uint32_t cromfs_lookup(cromfs_info *ci, const char *path, int* file_type, uint32_t *size, uint32_t *osize)
  551. {
  552. uint32_t cur_size = 0, cur_pos = 0, cur_osize = 0;
  553. const char *subpath = NULL, *subpath_end = NULL;
  554. void *di_mem = NULL;
  555. int _file_type = 0;
  556. if (path[0] == '\0')
  557. {
  558. return CROMFS_POS_ERROR;
  559. }
  560. cur_size = ci->part_info.root_dir_size;
  561. cur_osize = 0;
  562. cur_pos = ci->part_info.root_dir_pos;
  563. _file_type = CROMFS_DIRENT_ATTR_DIR;
  564. subpath_end = path;
  565. while (1)
  566. {
  567. cromfs_dirent_item *di_iter = NULL;
  568. int found = 0;
  569. /* skip /// */
  570. while (*subpath_end && *subpath_end == '/')
  571. {
  572. subpath_end++;
  573. }
  574. subpath = subpath_end;
  575. while ((*subpath_end != '/') && *subpath_end)
  576. {
  577. subpath_end++;
  578. }
  579. if (*subpath == '\0')
  580. {
  581. break;
  582. }
  583. /* if not dir or empty dir, error */
  584. if (_file_type != CROMFS_DIRENT_ATTR_DIR || !cur_size)
  585. {
  586. return CROMFS_POS_ERROR;
  587. }
  588. /* find subpath */
  589. di_mem = cromfs_dirent_cache_get(ci, cur_pos, cur_size);
  590. if (!di_mem)
  591. {
  592. return CROMFS_POS_ERROR;
  593. }
  594. found = 0;
  595. di_iter = (cromfs_dirent_item *)di_mem;
  596. while (1)
  597. {
  598. uint32_t name_len = subpath_end - subpath;
  599. uint32_t name_block = 0;
  600. if (di_iter->dirent.name_size == name_len)
  601. {
  602. if (memcmp(di_iter->dirent.name, subpath, name_len) == 0)
  603. {
  604. found = 1;
  605. cur_size = di_iter->dirent.file_size;
  606. cur_osize = di_iter->dirent.file_origin_size;
  607. cur_pos = di_iter->dirent.parition_pos;
  608. if (di_iter->dirent.attr == CROMFS_DIRENT_ATTR_FILE)
  609. {
  610. _file_type = CROMFS_DIRENT_ATTR_FILE;
  611. }
  612. else if (di_iter->dirent.attr == CROMFS_DIRENT_ATTR_DIR)
  613. {
  614. _file_type = CROMFS_DIRENT_ATTR_DIR;
  615. }
  616. else if (di_iter->dirent.attr == CROMFS_DIRENT_ATTR_SYMLINK)
  617. {
  618. _file_type = CROMFS_DIRENT_ATTR_SYMLINK;
  619. }
  620. else
  621. {
  622. RT_ASSERT(0);
  623. }
  624. break;
  625. }
  626. }
  627. name_block = (di_iter->dirent.name_size + CROMFS_ALIGN_SIZE_MASK) >> CROMFS_ALIGN_SIZE_BIT;
  628. di_iter += (1 + name_block);
  629. if ((uint32_t)(intptr_t)di_iter - (uint32_t)(intptr_t)di_mem >= cur_size)
  630. {
  631. break;
  632. }
  633. }
  634. if (!found)
  635. {
  636. return CROMFS_POS_ERROR;
  637. }
  638. }
  639. *size = cur_size;
  640. *osize = cur_osize;
  641. *file_type = _file_type;
  642. return cur_pos;
  643. }
  644. static uint32_t __dfs_cromfs_lookup(cromfs_info *ci, const char *path, int* file_type, uint32_t *size, uint32_t *osize)
  645. {
  646. rt_err_t result = RT_EOK;
  647. uint32_t ret = 0;
  648. result = rt_mutex_take(&ci->lock, RT_WAITING_FOREVER);
  649. if (result != RT_EOK)
  650. {
  651. return CROMFS_POS_ERROR;
  652. }
  653. ret = cromfs_lookup(ci, path, file_type, size, osize);
  654. rt_mutex_release(&ci->lock);
  655. return ret;
  656. }
  657. static int fill_file_data(file_info *fi)
  658. {
  659. int ret = -1;
  660. cromfs_info *ci = NULL;
  661. void *compressed_file_buff = NULL;
  662. uint32_t size = 0, osize = 0;
  663. if (!fi->data_valid)
  664. {
  665. RT_ASSERT(fi->buff != NULL);
  666. ci = fi->ci;
  667. osize = fi->size;
  668. size = fi->partition_size;
  669. compressed_file_buff = (void *)malloc(size);
  670. if (!compressed_file_buff)
  671. {
  672. goto end;
  673. }
  674. if (cromfs_read_bytes(ci, fi->partition_pos, compressed_file_buff, size) != size)
  675. {
  676. goto end;
  677. }
  678. if (uncompress((uint8_t *)fi->buff, (uLongf *)&osize, (uint8_t *)compressed_file_buff, size) != Z_OK)
  679. {
  680. goto end;
  681. }
  682. fi->data_valid = 1;
  683. }
  684. ret = 0;
  685. end:
  686. if (compressed_file_buff)
  687. {
  688. free(compressed_file_buff);
  689. }
  690. return ret;
  691. }
  692. static ssize_t dfs_cromfs_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
  693. {
  694. rt_err_t result = RT_EOK;
  695. file_info *fi = NULL;
  696. cromfs_info *ci = NULL;
  697. uint32_t length = 0;
  698. ci = (cromfs_info *)file->dentry->mnt->data;
  699. fi = (file_info *)file->vnode->data;
  700. if (count < file->vnode->size - *pos)
  701. {
  702. length = count;
  703. }
  704. else
  705. {
  706. length = file->vnode->size - *pos;
  707. }
  708. if (length > 0)
  709. {
  710. RT_ASSERT(fi->size != 0);
  711. if (fi->buff)
  712. {
  713. int fill_ret = 0;
  714. result = rt_mutex_take(&ci->lock, RT_WAITING_FOREVER);
  715. if (result != RT_EOK)
  716. {
  717. return 0;
  718. }
  719. fill_ret = fill_file_data(fi);
  720. rt_mutex_release(&ci->lock);
  721. if (fill_ret < 0)
  722. {
  723. return 0;
  724. }
  725. memcpy(buf, fi->buff + *pos, length);
  726. }
  727. else
  728. {
  729. void *di_mem = NULL;
  730. result = rt_mutex_take(&ci->lock, RT_WAITING_FOREVER);
  731. if (result != RT_EOK)
  732. {
  733. return 0;
  734. }
  735. di_mem = cromfs_dirent_cache_get(ci, fi->partition_pos, fi->size);
  736. if (di_mem)
  737. {
  738. memcpy(buf, (char*)di_mem + *pos, length);
  739. }
  740. rt_mutex_release(&ci->lock);
  741. if (!di_mem)
  742. {
  743. return 0;
  744. }
  745. }
  746. /* update file current position */
  747. *pos += length;
  748. }
  749. return length;
  750. }
  751. static file_info *get_file_info(cromfs_info *ci, uint32_t partition_pos, int inc_ref)
  752. {
  753. struct cromfs_avl_struct* node = cromfs_avl_find(partition_pos, ci->cromfs_avl_root);
  754. if (node)
  755. {
  756. if (inc_ref)
  757. {
  758. node->fi->ref++;
  759. }
  760. return node->fi;
  761. }
  762. return NULL;
  763. }
  764. static file_info *inset_file_info(cromfs_info *ci, uint32_t partition_pos, int file_type, uint32_t size, uint32_t osize)
  765. {
  766. file_info *fi = NULL;
  767. void *file_buff = NULL;
  768. struct cromfs_avl_struct *node = NULL;
  769. fi = (file_info *)malloc(sizeof *fi);
  770. if (!fi)
  771. {
  772. goto err;
  773. }
  774. fi->partition_pos = partition_pos;
  775. fi->ci = ci;
  776. if (file_type == CROMFS_DIRENT_ATTR_DIR)
  777. {
  778. fi->size = size;
  779. }
  780. else
  781. {
  782. fi->size = osize;
  783. fi->partition_size = size;
  784. fi->data_valid = 0;
  785. if (osize)
  786. {
  787. file_buff = (void *)malloc(osize);
  788. if (!file_buff)
  789. {
  790. goto err;
  791. }
  792. }
  793. }
  794. fi->buff = file_buff;
  795. fi->ref = 1;
  796. node = (struct cromfs_avl_struct *)malloc(sizeof *node);
  797. if (!node)
  798. {
  799. goto err;
  800. }
  801. node->avl_key = partition_pos;
  802. node->fi = fi;
  803. cromfs_avl_insert(node, &ci->cromfs_avl_root);
  804. return fi;
  805. err:
  806. if (file_buff)
  807. {
  808. free(file_buff);
  809. }
  810. if (fi)
  811. {
  812. free(fi);
  813. }
  814. return NULL;
  815. }
  816. static void deref_file_info(cromfs_info *ci, uint32_t partition_pos)
  817. {
  818. struct cromfs_avl_struct* node = cromfs_avl_find(partition_pos, ci->cromfs_avl_root);
  819. file_info *fi = NULL;
  820. if (node)
  821. {
  822. node->fi->ref--;
  823. if (node->fi->ref == 0)
  824. {
  825. fi = node->fi;
  826. cromfs_avl_remove(node, &ci->cromfs_avl_root);
  827. free(node);
  828. if (fi->buff)
  829. {
  830. free(fi->buff);
  831. }
  832. free(fi);
  833. }
  834. }
  835. }
  836. static int dfs_cromfs_close(struct dfs_file *file)
  837. {
  838. file_info *fi = NULL;
  839. cromfs_info *ci = NULL;
  840. rt_err_t result = 0;
  841. RT_ASSERT(file->vnode->ref_count > 0);
  842. if (file->vnode->ref_count > 1)
  843. {
  844. return 0;
  845. }
  846. fi = (file_info *)file->vnode->data;
  847. ci = (cromfs_info *)file->dentry->mnt->data;
  848. result = rt_mutex_take(&ci->lock, RT_WAITING_FOREVER);
  849. if (result != RT_EOK)
  850. {
  851. return -RT_ERROR;
  852. }
  853. deref_file_info(ci, fi->partition_pos);
  854. rt_mutex_release(&ci->lock);
  855. file->vnode->data = NULL;
  856. return RT_EOK;
  857. }
  858. static int dfs_cromfs_open(struct dfs_file *file)
  859. {
  860. int ret = 0;
  861. file_info *fi = NULL;
  862. cromfs_info *ci = NULL;
  863. uint32_t file_pos = 0;
  864. uint32_t size = 0, osize = 0;
  865. int file_type = 0;
  866. rt_err_t result = RT_EOK;
  867. if (file->flags & (O_CREAT | O_WRONLY | O_APPEND | O_TRUNC | O_RDWR))
  868. {
  869. return -EINVAL;
  870. }
  871. RT_ASSERT(file->vnode->ref_count > 0);
  872. if (file->vnode->ref_count > 1)
  873. {
  874. if (file->vnode->type == FT_DIRECTORY
  875. && !(file->flags & O_DIRECTORY))
  876. {
  877. return -ENOENT;
  878. }
  879. file->fpos = 0;
  880. return 0;
  881. }
  882. ci = (cromfs_info *)file->dentry->mnt->data;
  883. file_pos = __dfs_cromfs_lookup(ci, file->dentry->pathname, &file_type, &size, &osize);
  884. if (file_pos == CROMFS_POS_ERROR)
  885. {
  886. ret = -ENOENT;
  887. goto end;
  888. }
  889. /* entry is a directory file type */
  890. if (file_type == CROMFS_DIRENT_ATTR_DIR)
  891. {
  892. if (!(file->flags & O_DIRECTORY))
  893. {
  894. ret = -ENOENT;
  895. goto end;
  896. }
  897. file->vnode->type = FT_DIRECTORY;
  898. }
  899. else if (file_type == CROMFS_DIRENT_ATTR_SYMLINK)
  900. {
  901. file->vnode->type = FT_SYMLINK;
  902. }
  903. else
  904. {
  905. /* entry is a file, but open it as a directory */
  906. if (file->flags & O_DIRECTORY)
  907. {
  908. ret = -ENOENT;
  909. goto end;
  910. }
  911. file->vnode->type = FT_REGULAR;
  912. }
  913. result = rt_mutex_take(&ci->lock, RT_WAITING_FOREVER);
  914. if (result != RT_EOK)
  915. {
  916. ret = -EINTR;
  917. goto end;
  918. }
  919. fi = get_file_info(ci, file_pos, 1);
  920. if (!fi)
  921. {
  922. fi = inset_file_info(ci, file_pos, file_type, size, osize);
  923. }
  924. rt_mutex_release(&ci->lock);
  925. if (!fi)
  926. {
  927. ret = -ENOENT;
  928. goto end;
  929. }
  930. file->vnode->data = fi;
  931. if (file_type)
  932. {
  933. file->vnode->size = size;
  934. }
  935. else
  936. {
  937. file->vnode->size = osize;
  938. }
  939. file->fpos = 0;
  940. ret = RT_EOK;
  941. end:
  942. return ret;
  943. }
  944. static int dfs_cromfs_stat(struct dfs_dentry *dentry, struct stat *st)
  945. {
  946. uint32_t size = 0, osize = 0;
  947. int file_type = 0;
  948. cromfs_info *ci = NULL;
  949. uint32_t file_pos = 0;
  950. ci = (cromfs_info *)dentry->mnt->data;
  951. file_pos = __dfs_cromfs_lookup(ci, dentry->pathname, &file_type, &size, &osize);
  952. if (file_pos == CROMFS_POS_ERROR)
  953. {
  954. return -ENOENT;
  955. }
  956. st->st_dev = 0;
  957. st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
  958. S_IWUSR | S_IWGRP | S_IWOTH;
  959. if (file_type == CROMFS_DIRENT_ATTR_DIR)
  960. {
  961. st->st_mode &= ~S_IFREG;
  962. st->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
  963. st->st_size = size;
  964. }
  965. else if(file_type == CROMFS_DIRENT_ATTR_SYMLINK)
  966. {
  967. st->st_mode &= ~S_IFREG;
  968. st->st_mode |= S_IFLNK | S_IXUSR | S_IXGRP | S_IXOTH;
  969. st->st_size = osize;
  970. }
  971. else
  972. {
  973. st->st_size = osize;
  974. }
  975. st->st_mtime = 0;
  976. return RT_EOK;
  977. }
  978. static int dfs_cromfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
  979. {
  980. uint32_t index = 0;
  981. uint8_t *name = NULL;
  982. struct dirent *d = NULL;
  983. file_info *fi = NULL;
  984. cromfs_info *ci = NULL;
  985. cromfs_dirent_item *dirent = NULL, *sub_dirent = NULL;
  986. void *di_mem = NULL;
  987. rt_err_t result = RT_EOK;
  988. fi = (file_info *)file->vnode->data;
  989. ci = fi->ci;
  990. RT_ASSERT(fi->buff == NULL);
  991. if (!fi->size)
  992. {
  993. return -EINVAL;
  994. }
  995. dirent = (cromfs_dirent_item *)malloc(fi->size);
  996. if (!dirent)
  997. {
  998. return -ENOMEM;
  999. }
  1000. result = rt_mutex_take(&ci->lock, RT_WAITING_FOREVER);
  1001. if (result != RT_EOK)
  1002. {
  1003. free(dirent);
  1004. return -EINTR;
  1005. }
  1006. di_mem = cromfs_dirent_cache_get(ci, fi->partition_pos, fi->size);
  1007. if (di_mem)
  1008. {
  1009. memcpy(dirent, di_mem, fi->size);
  1010. }
  1011. rt_mutex_release(&ci->lock);
  1012. if (!di_mem)
  1013. {
  1014. free(dirent);
  1015. return -ENOMEM;
  1016. }
  1017. /* make integer count */
  1018. count = (count / sizeof(struct dirent));
  1019. if (count == 0)
  1020. {
  1021. free(dirent);
  1022. return -EINVAL;
  1023. }
  1024. for (index = 0; index < count && file->fpos < file->vnode->size; index++)
  1025. {
  1026. uint32_t name_size = 0;
  1027. d = dirp + index;
  1028. sub_dirent = &dirent[file->fpos >> CROMFS_ALIGN_SIZE_BIT];
  1029. name = sub_dirent->dirent.name;
  1030. /* fill dirent */
  1031. if (sub_dirent->dirent.attr == CROMFS_DIRENT_ATTR_DIR)
  1032. {
  1033. d->d_type = DT_DIR;
  1034. }
  1035. else
  1036. {
  1037. d->d_type = DT_REG;
  1038. }
  1039. d->d_namlen = sub_dirent->dirent.name_size;
  1040. d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
  1041. memcpy(d->d_name, (char *)name, sub_dirent->dirent.name_size);
  1042. d->d_name[sub_dirent->dirent.name_size] = '\0';
  1043. name_size = (sub_dirent->dirent.name_size + CROMFS_ALIGN_SIZE_MASK) & ~CROMFS_ALIGN_SIZE_MASK;
  1044. /* move to next position */
  1045. file->fpos += (name_size + sizeof *sub_dirent);
  1046. }
  1047. free(dirent);
  1048. return index * sizeof(struct dirent);
  1049. }
  1050. static struct dfs_vnode *dfs_cromfs_lookup (struct dfs_dentry *dentry)
  1051. {
  1052. struct dfs_vnode *vnode = RT_NULL;
  1053. cromfs_info *ci = NULL;
  1054. RT_ASSERT(dentry != RT_NULL);
  1055. RT_ASSERT(dentry->mnt != RT_NULL);
  1056. ci = (cromfs_info *)dentry->mnt->data;
  1057. if (ci)
  1058. {
  1059. uint32_t size = 0, osize = 0;
  1060. int file_type = 0;
  1061. uint32_t file_pos = __dfs_cromfs_lookup(ci, dentry->pathname, &file_type, &size, &osize);
  1062. if (file_pos != CROMFS_POS_ERROR)
  1063. {
  1064. vnode = dfs_vnode_create();
  1065. if (vnode)
  1066. {
  1067. vnode->nlink = 1;
  1068. if (file_type == CROMFS_DIRENT_ATTR_DIR)
  1069. {
  1070. vnode->mode = S_IFDIR | (0555);
  1071. vnode->type = FT_DIRECTORY;
  1072. vnode->size = size;
  1073. }
  1074. else if (file_type == CROMFS_DIRENT_ATTR_SYMLINK)
  1075. {
  1076. vnode->mode = S_IFLNK | (0555);
  1077. vnode->type = FT_SYMLINK;
  1078. vnode->size = osize;
  1079. }
  1080. else
  1081. {
  1082. vnode->mode = S_IFREG | (0555);
  1083. vnode->type = FT_REGULAR;
  1084. vnode->size = osize;
  1085. }
  1086. vnode->mnt = dentry->mnt;
  1087. }
  1088. }
  1089. }
  1090. return vnode;
  1091. }
  1092. static int dfs_cromfs_free_vnode(struct dfs_vnode *vnode)
  1093. {
  1094. return 0;
  1095. }
  1096. static int cromfs_readlink(cromfs_info *ci, char *path, char *buf, int len)
  1097. {
  1098. int ret = 0;
  1099. file_info *fi = NULL;
  1100. uint32_t file_pos = 0;
  1101. int file_type = 0;
  1102. uint32_t size = 0, osize = 0;
  1103. rt_err_t result = RT_EOK;
  1104. file_pos = __dfs_cromfs_lookup(ci, path, &file_type, &size, &osize);
  1105. if (file_pos == CROMFS_POS_ERROR)
  1106. {
  1107. ret = -ENOENT;
  1108. goto end1;
  1109. }
  1110. result = rt_mutex_take(&ci->lock, RT_WAITING_FOREVER);
  1111. if (result != RT_EOK)
  1112. {
  1113. ret = -EINTR;
  1114. goto end;
  1115. }
  1116. fi = get_file_info(ci, file_pos, 1);
  1117. if (!fi)
  1118. {
  1119. fi = inset_file_info(ci, file_pos, file_type, size, osize);
  1120. }
  1121. rt_mutex_release(&ci->lock);
  1122. if (!fi)
  1123. {
  1124. ret = -ENOENT;
  1125. goto end;
  1126. }
  1127. if (len > 0)
  1128. {
  1129. RT_ASSERT(fi->size != 0);
  1130. RT_ASSERT(fi->buff);
  1131. int fill_ret = 0;
  1132. fill_ret = fill_file_data(fi);
  1133. if (fill_ret < 0)
  1134. {
  1135. ret = -ENOENT;
  1136. deref_file_info(ci, fi->partition_pos);
  1137. goto end;
  1138. }
  1139. len = len - 1;
  1140. osize = osize < len ? osize : len;
  1141. memcpy(buf, fi->buff, osize);
  1142. }
  1143. if (ret == 0)
  1144. {
  1145. buf[osize] = '\0';
  1146. ret = osize;
  1147. }
  1148. deref_file_info(ci, fi->partition_pos);
  1149. end:
  1150. rt_mutex_release(&ci->lock);
  1151. end1:
  1152. return ret;
  1153. }
  1154. static int dfs_cromfs_readlink(struct dfs_dentry *dentry, char *buf, int len)
  1155. {
  1156. cromfs_info *ci = NULL;
  1157. if (dentry && buf)
  1158. {
  1159. ci = (cromfs_info *)dentry->mnt->data;
  1160. return cromfs_readlink(ci, dentry->pathname, buf, len);
  1161. }
  1162. return -EBADF;
  1163. }
  1164. static const struct dfs_file_ops _crom_fops =
  1165. {
  1166. .open = dfs_cromfs_open,
  1167. .close = dfs_cromfs_close,
  1168. .lseek = generic_dfs_lseek,
  1169. .read = dfs_cromfs_read,
  1170. .getdents = dfs_cromfs_getdents,
  1171. };
  1172. static const struct dfs_filesystem_ops _cromfs_ops =
  1173. {
  1174. .name = "crom",
  1175. .flags = 0,
  1176. .default_fops = &_crom_fops,
  1177. .mount = dfs_cromfs_mount,
  1178. .umount = dfs_cromfs_unmount,
  1179. .readlink = dfs_cromfs_readlink,
  1180. .stat = dfs_cromfs_stat,
  1181. .lookup = dfs_cromfs_lookup,
  1182. .free_vnode = dfs_cromfs_free_vnode
  1183. };
  1184. static struct dfs_filesystem_type _cromfs =
  1185. {
  1186. .fs_ops = &_cromfs_ops,
  1187. };
  1188. int dfs_cromfs_init(void)
  1189. {
  1190. /* register crom file system */
  1191. dfs_register(&_cromfs);
  1192. return 0;
  1193. }
  1194. INIT_COMPONENT_EXPORT(dfs_cromfs_init);