file.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. #include <stdio.h>
  2. #include "ndsvfs.h"
  3. #include "dirent.h"
  4. __attribute__((used))
  5. FILE *fopen(const char *path_name, const char *mode)
  6. {
  7. NDSVFS_DENTRY *vde = HAL_NULL;
  8. NDSVFS_FILE *file = HAL_NULL;
  9. UINT32 mode_len;
  10. UINT32 fmode = 0;
  11. UINT32 i;
  12. if (HAL_SUCCESS != _ndsvfs_lock())
  13. return HAL_NULL;
  14. // alloc file object
  15. file = _ndsvfs_alloc_file();
  16. if (file == HAL_NULL)
  17. goto _safe_exit;
  18. // open flags
  19. if (mode == HAL_NULL)
  20. mode_len = 0;
  21. else
  22. mode_len = (UINT32)strlen(mode);
  23. for (i = 0; i < mode_len; ++i)
  24. {
  25. switch (mode[i])
  26. {
  27. case 'r':
  28. fmode |= NDSVFS_FOPEN_READ;
  29. break;
  30. case 'w':
  31. fmode |= NDSVFS_FOPEN_WRITE;
  32. break;
  33. case 'a':
  34. fmode |= NDSVFS_FOPEN_APPEND;
  35. break;
  36. case '+':
  37. fmode |= NDSVFS_FOPEN_PLUS;
  38. break;
  39. }
  40. }
  41. if (fmode == 0)
  42. goto _safe_exit;
  43. #if 0
  44. // (todo) current imp should be read only
  45. if (fmode & ~NDSVFS_FOPEN_READ)
  46. goto _safe_exit;
  47. if (!(fmode & NDSVFS_FOPEN_READ))
  48. goto _safe_exit;
  49. // ~(todo)
  50. #endif
  51. // lookup file entry
  52. if (path_name == HAL_NULL)
  53. goto _safe_exit;
  54. if ((INT)strlen(path_name) == 0)
  55. goto _safe_exit;
  56. vde = _ndsvfs_path_lookup((const char *)path_name);
  57. if (!vde)
  58. {
  59. // (todo) create the file if not exist and flag is not read only
  60. goto _safe_exit;
  61. }
  62. // current imp allows only regular file
  63. // we can open dir now, so I comments the codes
  64. #if 0
  65. if (vde->inode->mode & NDSVFS_INM_ATTR_MASK)
  66. goto _safe_exit;
  67. #endif
  68. // notify file system to open the file
  69. // (todo) call this only when user mode reference to the file is 0.
  70. if (HAL_SUCCESS != vde->sb->open_file(vde, fmode))
  71. goto _safe_exit;
  72. file->flags = fmode;
  73. file->vde = vde;
  74. //file->pos = 0;
  75. //DEBUG(0, 1,"fopen() 0x%08lx\r\n", (UINT32)file);
  76. _ndsvfs_unlock();
  77. // todo
  78. return (FILE *)file;
  79. _safe_exit:
  80. if (vde)
  81. NDSVFS_DEREF(vde);
  82. file->vde = HAL_NULL;
  83. if (file)
  84. NDSVFS_DEREF(file);
  85. _ndsvfs_unlock();
  86. return HAL_NULL;
  87. }
  88. __attribute__((used))
  89. int fclose(FILE *stream)
  90. {
  91. if (stream == HAL_NULL)
  92. return (int)-NDS_VFSD_INVALID_PARAMETER;
  93. if (HAL_SUCCESS != _ndsvfs_lock())
  94. return (int)HAL_ERR_INVALID_OPERATION;
  95. //DEBUG(0, 1,"fclose() 0x%08lx\r\n", (UINT32)stream);
  96. // (todo) flush the file contents if ever been modified
  97. // notify file system to close the file
  98. // (todo) call this only when user mode reference to the file decreased to 0.
  99. ((NDSVFS_FILE *)stream)->vde->sb->close_file(((NDSVFS_FILE *)stream)->vde);
  100. // release file references
  101. if (stream)
  102. NDSVFS_DEREF(stream);
  103. if (HAL_SUCCESS != _ndsvfs_unlock())
  104. return (int)HAL_ERR_INVALID_OPERATION;
  105. return (int)HAL_SUCCESS;
  106. }
  107. __attribute__((used))
  108. size_t fread(void *ptr, size_t size, size_t count, FILE *stream)
  109. {
  110. STATUS status;
  111. UINT32 d_size = (UINT32)size * (UINT32)count;
  112. UINT32 r_size; // size actually been read
  113. #if 1
  114. DEBUG(0, 1,"fread() 0x%08lx ptr(0x%08lx) size(0x%08lx) count(0x%08lx)\r\n",
  115. (UINT32)stream, (UINT32)ptr, (UINT32)size, (UINT32)count);
  116. #endif
  117. if (stream == HAL_NULL)
  118. {
  119. ((NDSVFS_FILE *)stream)->err = NDS_VFSD_INVALID_PARAMETER;
  120. return 0;
  121. }
  122. if (HAL_SUCCESS != _ndsvfs_lock())
  123. {
  124. ((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_OPERATION;
  125. return 0;
  126. }
  127. DEBUG(0, 1,"fread() 0x%08lx >>\r\n", (UINT32)stream);
  128. if (((NDSVFS_FILE *)stream)->pos < 0)
  129. {
  130. DEBUG(0, 1,"fread() 0x%08lx <<\r\n", (UINT32)stream);
  131. _ndsvfs_unlock();
  132. ((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_START;
  133. return 0;
  134. }
  135. status = ((NDSVFS_FILE *)stream)->vde->sb->read_file(((NDSVFS_FILE *)stream)->vde,
  136. ptr, (UINT32)((NDSVFS_FILE *)stream)->pos, d_size, &r_size);
  137. if (status == NDS_VFSD_END_OF_FILE)
  138. {
  139. ((NDSVFS_FILE *)stream)->eof = HAL_TRUE;
  140. status = HAL_SUCCESS;
  141. }
  142. if (status == HAL_SUCCESS)
  143. ((NDSVFS_FILE *)stream)->pos += (INT32)r_size;
  144. else
  145. r_size = 0;
  146. DEBUG(0, 1,"fread() 0x%08lx <<\r\n", (UINT32)stream);
  147. if (HAL_SUCCESS != _ndsvfs_unlock())
  148. {
  149. ((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_OPERATION;
  150. DEBUG(0, 1,"fread() 0x%08lx << unlock fail\r\n", (UINT32)stream);
  151. return 0;
  152. }
  153. return (int)((size_t)r_size / size);
  154. }
  155. __attribute__((used))
  156. size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
  157. {
  158. STATUS status;
  159. UINT32 d_size = (UINT32)size * (UINT32)count;
  160. UINT32 w_size; // size actually been write
  161. #if 1
  162. DEBUG(0, 1,"fwrite() 0x%08lx ptr(0x%08lx) size(0x%08lx) count(0x%08lx)\r\n",
  163. (UINT32)stream, (UINT32)ptr, (UINT32)size, (UINT32)count);
  164. #endif
  165. if (stream == HAL_NULL)
  166. {
  167. ((NDSVFS_FILE *)stream)->err = NDS_VFSD_INVALID_PARAMETER;
  168. return 0;
  169. }
  170. if (HAL_SUCCESS != _ndsvfs_lock())
  171. {
  172. ((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_OPERATION;
  173. return 0;
  174. }
  175. DEBUG(0, 1,"fwrite() 0x%08lx >>\r\n", (UINT32)stream);
  176. if (((NDSVFS_FILE *)stream)->pos < 0)
  177. {
  178. DEBUG(0, 1,"fwrite() 0x%08lx <<\r\n", (UINT32)stream);
  179. _ndsvfs_unlock();
  180. ((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_START;
  181. return 0;
  182. }
  183. status = ((NDSVFS_FILE *)stream)->vde->sb->write_file(((NDSVFS_FILE *)stream)->vde,
  184. ptr, (UINT32)((NDSVFS_FILE *)stream)->pos, d_size, &w_size);
  185. if (status == NDS_VFSD_END_OF_FILE)
  186. {
  187. ((NDSVFS_FILE *)stream)->eof = HAL_TRUE;
  188. status = HAL_SUCCESS;
  189. }
  190. if (status == HAL_SUCCESS)
  191. ((NDSVFS_FILE *)stream)->pos += (INT32)w_size;
  192. else
  193. w_size = 0;
  194. DEBUG(0, 1,"fwrite() 0x%08lx <<\r\n", (UINT32)stream);
  195. if (HAL_SUCCESS != _ndsvfs_unlock())
  196. {
  197. ((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_OPERATION;
  198. DEBUG(0, 1,"fwrite() 0x%08lx << unlock fail\r\n", (UINT32)stream);
  199. return 0;
  200. }
  201. return (int)((size_t)w_size / size);
  202. }
  203. __attribute__((used))
  204. int fflush(FILE *stream)
  205. {
  206. if (stream == HAL_NULL)
  207. return (int)NDS_VFSD_INVALID_PARAMETER;
  208. // todo
  209. return (int)HAL_SUCCESS;
  210. }
  211. __attribute__((used))
  212. int fseek(FILE *stream, int offset, int origin)
  213. {
  214. INT32 pos;
  215. if (stream == HAL_NULL)
  216. return (int)NDS_VFSD_INVALID_PARAMETER;
  217. if (HAL_SUCCESS != _ndsvfs_lock())
  218. return (int)HAL_ERR_INVALID_OPERATION;
  219. pos = ((NDSVFS_FILE *)stream)->pos;
  220. //DEBUG(0, 1,"fseek() 0x%08lx >>\r\n", (UINT32)stream);
  221. //DEBUG(0, 1,"pos (cur) : 0x%08lx\r\n", pos);
  222. //DEBUG(0, 1,"offset : 0x%08lx\r\n", offset);
  223. switch (origin)
  224. {
  225. case FSEEK_CUR:
  226. pos += offset;
  227. break;
  228. case FSEEK_END:
  229. pos = (INT32)((NDSVFS_FILE *)stream)->vde->inode->size + offset;
  230. break;
  231. case FSEEK_SET:
  232. pos = offset;
  233. break;
  234. default:
  235. //DEBUG(0, 1,"fseek() 0x%08lx <<\r\n", (UINT32)stream);
  236. _ndsvfs_unlock();
  237. return (int)NDS_VFSD_INVALID_PARAMETER;
  238. }
  239. //DEBUG(0, 1,"pos (new) : 0x%08lx\r\n", pos);
  240. /*
  241. if (pos > ((NDSVFS_FILE *)stream)->vde->inode->size)
  242. {
  243. _ndsvfs_unlock();
  244. return (int)NDS_VFSD_INVALID_PARAMETER; // todo: might be a valid condition for write-mode
  245. }*/
  246. ((NDSVFS_FILE *)stream)->pos = pos;
  247. //DEBUG(0, 1,"fseek() 0x%08lx <<\r\n", (UINT32)stream);
  248. if (HAL_SUCCESS != _ndsvfs_unlock())
  249. return (int)HAL_ERR_INVALID_OPERATION;
  250. return (int)HAL_SUCCESS;
  251. }
  252. __attribute__((used))
  253. long ftell(FILE *stream)
  254. {
  255. long pos;
  256. if (stream == HAL_NULL)
  257. return (int)HAL_ERR_INVALID_OPERATION;
  258. if (HAL_SUCCESS != _ndsvfs_lock())
  259. return (int)HAL_ERR_INVALID_OPERATION;
  260. pos = (long)((NDSVFS_FILE *)stream)->pos;
  261. if (HAL_SUCCESS != _ndsvfs_unlock())
  262. return (int)HAL_ERR_INVALID_OPERATION;
  263. return pos;
  264. }
  265. void frewind(FILE *stream)
  266. {
  267. if (stream == HAL_NULL)
  268. return;
  269. if (HAL_SUCCESS != _ndsvfs_lock())
  270. return;
  271. ((NDSVFS_FILE *)stream)->pos = 0;
  272. ((NDSVFS_FILE *)stream)->err = 0;
  273. ((NDSVFS_FILE *)stream)->eof = 0;
  274. if (HAL_SUCCESS != _ndsvfs_unlock())
  275. return;
  276. }
  277. __attribute__((used))
  278. int fgetpos(FILE *stream, fpos_t *position)
  279. {
  280. if (stream == HAL_NULL)
  281. return (int)NDS_VFSD_INVALID_PARAMETER;
  282. if (position == HAL_NULL)
  283. return (int)NDS_VFSD_INVALID_PARAMETER;
  284. if (HAL_SUCCESS != _ndsvfs_lock())
  285. return (int)HAL_ERR_INVALID_OPERATION;
  286. *position = ((NDSVFS_FILE *)stream)->pos;
  287. if (HAL_SUCCESS != _ndsvfs_unlock())
  288. return (int)HAL_ERR_INVALID_OPERATION;
  289. return (int)HAL_SUCCESS;
  290. }
  291. __attribute__((used))
  292. int fsetpos(FILE *stream, const fpos_t *position)
  293. {
  294. if (stream == HAL_NULL)
  295. return (int)NDS_VFSD_INVALID_PARAMETER;
  296. if (position == HAL_NULL)
  297. return (int)NDS_VFSD_INVALID_PARAMETER;
  298. if (HAL_SUCCESS != _ndsvfs_lock())
  299. return (int)HAL_ERR_INVALID_OPERATION;
  300. if (*position > (INT32)((NDSVFS_FILE *)stream)->vde->inode->size)
  301. {
  302. _ndsvfs_unlock();
  303. return (int)NDS_VFSD_INVALID_PARAMETER; // todo: might be a valid condition for write-mode
  304. }
  305. ((NDSVFS_FILE *)stream)->pos = *position;
  306. ((NDSVFS_FILE *)stream)->eof = 0; // ?? todo: signal eof if position reaches end of file?
  307. if (HAL_SUCCESS != _ndsvfs_unlock())
  308. return (int)HAL_ERR_INVALID_OPERATION;
  309. return (int)HAL_SUCCESS;
  310. }
  311. __attribute__((used))
  312. int feof(FILE *stream)
  313. {
  314. UINT32 eof;
  315. if (HAL_SUCCESS != _ndsvfs_lock())
  316. return (int)HAL_ERR_INVALID_OPERATION;
  317. eof = ((NDSVFS_FILE *)stream)->eof > 0 ? HAL_TRUE : HAL_FALSE;
  318. if (HAL_SUCCESS != _ndsvfs_unlock())
  319. return (int)HAL_ERR_INVALID_OPERATION;
  320. return eof;
  321. }
  322. __attribute__((used))
  323. int ferror(FILE *stream)
  324. {
  325. UINT32 err;
  326. if (HAL_SUCCESS != _ndsvfs_lock())
  327. return (int)HAL_ERR_INVALID_OPERATION;
  328. err = ((NDSVFS_FILE *)stream)->err > 0 ? 1 : 0;
  329. if (HAL_SUCCESS != _ndsvfs_unlock())
  330. return (int)HAL_ERR_INVALID_OPERATION;
  331. return err;
  332. }
  333. void fclearerr(FILE *stream)
  334. {
  335. if (HAL_SUCCESS != _ndsvfs_lock())
  336. return;
  337. ((NDSVFS_FILE *)stream)->err = 0;
  338. ((NDSVFS_FILE *)stream)->eof = 0;
  339. if (HAL_SUCCESS != _ndsvfs_unlock())
  340. return;
  341. }
  342. extern STATUS _ndsvfs_read_dirs(NDSVFS_DENTRY *vde_parent, NDSVFS_DENTRY **vde_list);
  343. __attribute__((used))
  344. struct dir *opendir(const char *path)
  345. {
  346. NDSVFS_FILE *file = NULL;
  347. struct dir *dirp = NULL;
  348. int status;
  349. file = (NDSVFS_FILE *)fopen(path, "rb");
  350. if (file == NULL) {
  351. // ERROR("fopen path=%s\n",path);
  352. return (void*)0;
  353. }
  354. if (!S_ISDIR(file->vde->inode)){
  355. fclose((FILE *)file);
  356. // ERROR("Not a dir path=%s\n",path);
  357. return (void*)0;
  358. }
  359. if (!file->dirp){
  360. file->dirp = malloc(sizeof(struct dir));
  361. KASSERT(file->dirp);
  362. dirp = (struct dir*)file->dirp;
  363. dirp->d_dirent = malloc(sizeof(struct dirent));
  364. KASSERT(dirp->d_dirent);
  365. dirp->d_file = file;
  366. dirp->d_off = 0;
  367. }
  368. status = _ndsvfs_read_dirs(file->vde, &(dirp->vde_list));
  369. dirp->vde_head = dirp->vde_list;
  370. dirp->vde_list = NULL;
  371. if(status == HAL_FAILURE)
  372. return HAL_NULL;
  373. return dirp;
  374. }
  375. __attribute__((used))
  376. int closedir(struct dir *dirp)
  377. {
  378. NDSVFS_FILE *file = dirp->d_file;
  379. if (dirp == NULL)
  380. return -1;
  381. if (file == NULL)
  382. return -1;
  383. if (dirp->d_dirent != NULL)
  384. free(dirp->d_dirent);
  385. free(dirp);
  386. return fclose((FILE *)file);
  387. }
  388. __attribute__((used))
  389. struct dirent *readdir(struct dir *dirp)
  390. {
  391. /* this is the first time, becasue the vde_list is pointed to null */
  392. if (dirp->vde_list == NULL && dirp->vde_head != NULL) {
  393. strcpy(dirp->d_dirent->d_name, dirp->vde_head->name.utf_name);
  394. dirp->vde_list = NDS_LIST_ENTITY(dirp->vde_head->c_chain.next, NDSVFS_DENTRY, c_chain);
  395. return dirp->d_dirent;
  396. }
  397. /* this is not the first time. */
  398. else if (dirp->vde_list != dirp->vde_head) {
  399. strcpy(dirp->d_dirent->d_name, dirp->vde_list->name.utf_name);
  400. dirp->vde_list = NDS_LIST_ENTITY(dirp->vde_list->c_chain.next, NDSVFS_DENTRY, c_chain);
  401. return dirp->d_dirent;
  402. }
  403. else
  404. return NULL;
  405. }
  406. __attribute__((used))
  407. int fstat(FILE* fd, struct stat *buf)
  408. {
  409. NDSVFS_FILE *file = (NDSVFS_FILE *)fd;
  410. if (file == HAL_NULL)
  411. return -1;
  412. return file->vde->sb->stat_file(file->vde, buf);
  413. }