dfs_posix.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. /*
  2. * File : dfs_posix.c
  3. * This file is part of Device File System in RT-Thread RTOS
  4. * COPYRIGHT (C) 2004-2010, 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. * 2009-05-27 Yi.qiu The first version
  13. */
  14. #include <dfs.h>
  15. #include <dfs_posix.h>
  16. /**
  17. * @addtogroup FsPosixApi
  18. */
  19. /*@{*/
  20. /**
  21. * this function is a POSIX compliant version, which will open a file and return
  22. * a file descriptor.
  23. *
  24. * @param file the path name of file.
  25. * @param flags the file open flags.
  26. * @param mode
  27. *
  28. * @return the non-negative integer on successful open, others for failed.
  29. */
  30. int open(const char *file, int flags, int mode)
  31. {
  32. int fd, result;
  33. struct dfs_fd* d;
  34. /* allocate a fd */
  35. fd = fd_new();
  36. if (fd < 0) return -1;
  37. d = fd_get(fd);
  38. result = dfs_file_open(d, file, flags);
  39. if (result < 0)
  40. {
  41. rt_set_errno(result);
  42. /* release the ref-count of fd */
  43. fd_put(d);
  44. fd_put(d);
  45. return -1;
  46. }
  47. /* release the ref-count of fd */
  48. fd_put(d);
  49. return fd;
  50. }
  51. /**
  52. * this function is a POSIX compliant version, which will close the open
  53. * file descriptor.
  54. *
  55. * @param fd the file descriptor.
  56. *
  57. * @return 0 on successful, -1 on failed.
  58. */
  59. int close(int fd)
  60. {
  61. int result;
  62. struct dfs_fd* d;
  63. d = fd_get(fd);
  64. if (d == RT_NULL)
  65. {
  66. rt_set_errno(-RT_ERROR);
  67. return -1;
  68. }
  69. result = dfs_file_close(d);
  70. fd_put(d);
  71. if (result < 0)
  72. {
  73. rt_set_errno(result);
  74. return -1;
  75. }
  76. fd_put(d);
  77. return 0;
  78. }
  79. /**
  80. * this function is a POSIX compliant version, which will read specified data buffer
  81. * length for an open file descriptor.
  82. *
  83. * @param fd the file descriptor.
  84. * @param buf the buffer to save the read data.
  85. * @param len the maximal length of data buffer
  86. *
  87. * @return the actual read data buffer length
  88. */
  89. int read(int fd, void *buf, size_t len)
  90. {
  91. int result;
  92. struct dfs_fd* d;
  93. /* get the fd */
  94. d = fd_get(fd);
  95. if (d == RT_NULL)
  96. {
  97. rt_set_errno(-RT_ERROR);
  98. return -1;
  99. }
  100. result = dfs_file_read(d, buf, len);
  101. if (result < 0)
  102. {
  103. rt_set_errno(result);
  104. fd_put(d);
  105. return -1;
  106. }
  107. /* release the ref-count of fd */
  108. fd_put(d);
  109. return result;
  110. }
  111. /**
  112. * this function is a POSIX compliant version, which will write pecified data buffer
  113. * length for an open file descriptor.
  114. *
  115. * @param fd the file descriptor
  116. * @param buf the data buffer to be written.
  117. * @param len the data buffer length.
  118. *
  119. * @return the actual written data buffer length.
  120. */
  121. int write(int fd, const void *buf, size_t len)
  122. {
  123. int result;
  124. struct dfs_fd* d;
  125. /* get the fd */
  126. d = fd_get(fd);
  127. if (d == RT_NULL)
  128. {
  129. rt_set_errno(-RT_ERROR);
  130. return -1;
  131. }
  132. result = dfs_file_write(d, buf, len);
  133. if (result < 0)
  134. {
  135. rt_set_errno(result);
  136. fd_put(d);
  137. return -1;
  138. }
  139. /* release the ref-count of fd */
  140. fd_put(d);
  141. return result;
  142. }
  143. /**
  144. * this function is a POSIX compliant version, which will seek the offset for an
  145. * open file descriptor.
  146. *
  147. * @param fd the file descriptor.
  148. * @param offset the offset to be seeked.
  149. * @param whence the directory of seek.
  150. *
  151. * @return the current file position, or -1 on failed.
  152. */
  153. off_t lseek(int fd, off_t offset, int whence)
  154. {
  155. int result;
  156. struct dfs_fd* d;
  157. d = fd_get(fd);
  158. if (d == RT_NULL)
  159. {
  160. rt_set_errno(-RT_ERROR);
  161. return -1;
  162. }
  163. switch (whence)
  164. {
  165. case DFS_SEEK_SET:
  166. break;
  167. case DFS_SEEK_CUR:
  168. offset += d->pos;
  169. break;
  170. case DFS_SEEK_END:
  171. offset += d->size;
  172. break;
  173. }
  174. result = dfs_file_lseek(d, offset);
  175. if (result < 0)
  176. {
  177. rt_set_errno(result);
  178. fd_put(d);
  179. return -1;
  180. }
  181. /* release the ref-count of fd */
  182. fd_put(d);
  183. return offset;
  184. }
  185. /**
  186. * this function is a POSIX compliant version, which will rename old file name to
  187. * new file name.
  188. *
  189. * @param old the old file name.
  190. * @param new the new file name.
  191. *
  192. * @return 0 on successful, -1 on failed.
  193. *
  194. * note: the old and new file name must be belong to a same file system.
  195. */
  196. int rename(const char* old, const char* new)
  197. {
  198. int result;
  199. result = dfs_file_rename(old, new);
  200. if (result < 0)
  201. {
  202. rt_set_errno(result);
  203. return -1;
  204. }
  205. return 0;
  206. }
  207. /**
  208. * this function is a POSIX compliant version, which will unlink (remove) a
  209. * specified path file from file system.
  210. *
  211. * @param pathname the specified path name to be unlinked.
  212. *
  213. * @return 0 on successful, -1 on failed.
  214. */
  215. int unlink(const char *pathname)
  216. {
  217. int result;
  218. result = dfs_file_unlink(pathname);
  219. if (result < 0)
  220. {
  221. rt_set_errno(result);
  222. return -1;
  223. }
  224. return 0;
  225. }
  226. /**
  227. * this function is a POSIX compliant version, which will get file information.
  228. *
  229. * @param file the file name
  230. * @param buf the data buffer to save stat description.
  231. *
  232. * @return 0 on successful, -1 on failed.
  233. */
  234. int stat(const char *file, struct stat *buf)
  235. {
  236. int result;
  237. result = dfs_file_stat(file, buf);
  238. if (result < 0)
  239. {
  240. rt_set_errno(result);
  241. return -1;
  242. }
  243. return result;
  244. }
  245. /**
  246. * this function is a POSIX compliant version, which will get file status.
  247. *
  248. * @param fildes the file description
  249. * @param buf the data buffer to save stat description.
  250. */
  251. int fstat(int fildes, struct stat *buf)
  252. {
  253. struct dfs_fd* d;
  254. /* get the fd */
  255. d = fd_get(fildes);
  256. if (d == RT_NULL)
  257. {
  258. rt_set_errno(-RT_ERROR);
  259. return -1;
  260. }
  261. /* it's the root directory */
  262. buf->st_dev = 0;
  263. buf->st_mode = DFS_S_IFREG | DFS_S_IRUSR | DFS_S_IRGRP | DFS_S_IROTH |
  264. DFS_S_IWUSR | DFS_S_IWGRP | DFS_S_IWOTH;
  265. if (d->type == FT_DIRECTORY)
  266. {
  267. buf->st_mode &= ~DFS_S_IFREG;
  268. buf->st_mode |= DFS_S_IFDIR | DFS_S_IXUSR | DFS_S_IXGRP | DFS_S_IXOTH;
  269. }
  270. buf->st_size = d->size;
  271. buf->st_mtime = 0;
  272. buf->st_blksize = 512;
  273. fd_put(d);
  274. return DFS_STATUS_OK;
  275. }
  276. /**
  277. * this function is a POSIX compliant version, which will return the
  278. * information about a mounted file system.
  279. *
  280. * @param path the path which mounted file system.
  281. * @param buf the buffer to save the returned information.
  282. *
  283. * @return 0 on successful, others on failed.
  284. */
  285. int statfs(const char *path, struct statfs *buf)
  286. {
  287. int result;
  288. result = dfs_statfs(path, buf);
  289. if (result < 0)
  290. {
  291. rt_set_errno(result);
  292. return -1;
  293. }
  294. return result;
  295. }
  296. /**
  297. * this function is a POSIX compliant version, which will make a directory
  298. *
  299. * @param path the directory path to be made.
  300. * @param mode
  301. *
  302. * @return 0 on successful, others on failed.
  303. */
  304. int mkdir (const char *path, mode_t mode)
  305. {
  306. int fd;
  307. struct dfs_fd* d;
  308. int result;
  309. fd = fd_new();
  310. if (fd == -1) { rt_kprintf("no fd\n"); return -1; }
  311. d = fd_get(fd);
  312. result = dfs_file_open(d, path, DFS_O_DIRECTORY | DFS_O_CREAT);
  313. if (result < 0)
  314. {
  315. rt_set_errno(result);
  316. fd_put(d);
  317. return -1;
  318. }
  319. dfs_file_close(d);
  320. fd_put(d);
  321. return 0;
  322. }
  323. #ifdef RT_USING_FINSH
  324. #include <finsh.h>
  325. FINSH_FUNCTION_EXPORT(mkdir, create a directory);
  326. #endif
  327. /**
  328. * this function is a POSIX compliant version, which will remove a directory.
  329. *
  330. * @param pathname the path name to be removed.
  331. *
  332. * @return 0 on sucessfull, others on failed.
  333. */
  334. int rmdir(const char *pathname)
  335. {
  336. int result;
  337. result = dfs_file_unlink(pathname);
  338. if (result < 0)
  339. {
  340. rt_set_errno(result);
  341. return -1;
  342. }
  343. return 0;
  344. }
  345. /**
  346. * this function is a POSIX compliant version, which will open a directory.
  347. *
  348. * @param name the path name to be open.
  349. *
  350. * @return the DIR pointer of directory, NULL on open failed.
  351. */
  352. DIR* opendir(const char* name)
  353. {
  354. struct dfs_fd* d;
  355. int fd, result;
  356. DIR* t;
  357. t = RT_NULL;
  358. /* allocate a fd */
  359. fd = fd_new();
  360. if (fd == -1) { rt_kprintf("no fd\n"); return RT_NULL; }
  361. d = fd_get(fd);
  362. result = dfs_file_open(d, name, DFS_O_RDONLY | DFS_O_DIRECTORY);
  363. if (result >= 0)
  364. {
  365. /* open successfully */
  366. t = (DIR *) rt_malloc (sizeof(DIR));
  367. if (t == RT_NULL)
  368. {
  369. dfs_file_close(d);
  370. fd_put(d);
  371. }
  372. else
  373. {
  374. rt_memset(t, 0, sizeof(DIR));
  375. t->fd = fd;
  376. }
  377. fd_put(d);
  378. return t;
  379. }
  380. /* open failed */
  381. fd_put(d);
  382. fd_put(d);
  383. rt_set_errno(result);
  384. return RT_NULL;
  385. }
  386. /**
  387. * this function is a POSIX compliant version, which will return a pointer
  388. * to a dirent structure representing the next directory entry in the
  389. * directory stream.
  390. *
  391. * @param d the directory stream pointer.
  392. *
  393. * @return the next directory entry, NULL on the end of directory or failed.
  394. */
  395. struct dirent* readdir(DIR *d)
  396. {
  397. int result;
  398. struct dfs_fd* fd;
  399. fd = fd_get(d->fd);
  400. if (fd == RT_NULL)
  401. {
  402. rt_set_errno(-RT_ERROR);
  403. return RT_NULL;
  404. }
  405. if (!d->num || (d->cur += ((struct dirent*)(d->buf + d->cur))->d_reclen) >= d->num)
  406. {
  407. /* get a new entry */
  408. result = dfs_file_getdents(fd, (struct dirent*)d->buf, sizeof(d->buf) - 1);
  409. if (result <= 0)
  410. {
  411. rt_set_errno(result);
  412. fd_put(fd);
  413. return RT_NULL;
  414. }
  415. d->num = result;
  416. d->cur = 0; /* current entry index */
  417. }
  418. fd_put(fd);
  419. return (struct dirent*)(d->buf+d->cur);
  420. }
  421. /**
  422. * this function is a POSIX compliant version, which will return current
  423. * location in directory stream.
  424. *
  425. * @param d the directory stream pointer.
  426. *
  427. * @return the current location in directory stream.
  428. */
  429. long telldir(DIR *d)
  430. {
  431. struct dfs_fd* fd;
  432. long result;
  433. fd = fd_get(d->fd);
  434. if (fd == RT_NULL)
  435. {
  436. rt_set_errno(-RT_ERROR);
  437. return 0;
  438. }
  439. result = fd->pos - d->num + d->cur;
  440. fd_put(fd);
  441. return result;
  442. }
  443. /**
  444. * this function is a POSIX compliant version, which will set position of
  445. * next directory structure in the directory stream.
  446. *
  447. * @param d the directory stream.
  448. * @param offset the offset in directory stream.
  449. */
  450. void seekdir(DIR *d, off_t offset)
  451. {
  452. struct dfs_fd* fd;
  453. fd = fd_get(d->fd);
  454. if (fd == RT_NULL)
  455. {
  456. rt_set_errno(-RT_ERROR);
  457. return ;
  458. }
  459. /* seek to the offset position of directory */
  460. if (dfs_file_lseek(fd, offset) >= 0) d->num = d->cur = 0;
  461. fd_put(fd);
  462. }
  463. /**
  464. * this function is a POSIX compliant version, which will reset directory stream.
  465. *
  466. * @param d the directory stream.
  467. */
  468. void rewinddir(DIR *d)
  469. {
  470. struct dfs_fd* fd;
  471. fd = fd_get(d->fd);
  472. if (fd == RT_NULL)
  473. {
  474. rt_set_errno(-RT_ERROR);
  475. return ;
  476. }
  477. /* seek to the beginning of directory */
  478. if (dfs_file_lseek(fd, 0) >= 0) d->num = d->cur = 0;
  479. fd_put(fd);
  480. }
  481. /**
  482. * this function is a POSIX compliant version, which will close a directory
  483. * stream.
  484. *
  485. * @param d the directory stream.
  486. *
  487. * @return 0 on successful, -1 on failed.
  488. */
  489. int closedir(DIR* d)
  490. {
  491. int result;
  492. struct dfs_fd* fd;
  493. fd = fd_get(d->fd);
  494. if (fd == RT_NULL)
  495. {
  496. rt_set_errno(-RT_ERROR);
  497. return -1;
  498. }
  499. result = dfs_file_close(fd);
  500. fd_put(fd);
  501. fd_put(fd);
  502. rt_free(d);
  503. if (result < 0)
  504. {
  505. rt_set_errno(result);
  506. return -1;
  507. }
  508. else return 0;
  509. }
  510. #ifdef DFS_USING_WORKDIR
  511. /**
  512. * this function is a POSIX compliant version, which will change working directory.
  513. *
  514. * @param path the path name to be changed to.
  515. *
  516. * @return 0 on successful, -1 on failed.
  517. */
  518. int chdir(const char *path)
  519. {
  520. char* fullpath;
  521. DIR* d;
  522. if(path == RT_NULL)
  523. {
  524. dfs_lock();
  525. rt_kprintf("%s\n", working_directory);
  526. dfs_unlock();
  527. return 0;
  528. }
  529. if (rt_strlen(path) > DFS_PATH_MAX)
  530. return -1;
  531. fullpath = dfs_normalize_path(NULL, path);
  532. if (fullpath == RT_NULL)
  533. return -1; /* build path failed */
  534. dfs_lock();
  535. d = opendir(fullpath);
  536. if (d == RT_NULL)
  537. {
  538. rt_free(fullpath);
  539. /* this is a not exist directory */
  540. dfs_unlock();
  541. return -1;
  542. }
  543. /* close directory stream */
  544. closedir(d);
  545. /* copy full path to working directory */
  546. strncpy(working_directory, fullpath, DFS_PATH_MAX);
  547. rt_free(fullpath); /* release normalize directory path name */
  548. dfs_unlock();
  549. return 0;
  550. }
  551. #ifdef RT_USING_FINSH
  552. FINSH_FUNCTION_EXPORT_ALIAS(chdir, cd, change current working directory);
  553. #endif
  554. #endif
  555. /**
  556. * this function is a POSIX compliant version, which will return current
  557. * working directory.
  558. *
  559. * @param buf the returned current directory.
  560. * @param size the buffer size.
  561. *
  562. * @return the returned current directory.
  563. */
  564. char *getcwd(char *buf, size_t size)
  565. {
  566. #ifdef DFS_USING_WORKDIR
  567. rt_enter_critical();
  568. rt_strncpy(buf, working_directory, size);
  569. rt_exit_critical();
  570. #else
  571. rt_kprintf("WARNING: not support working directory\n");
  572. #endif
  573. return buf;
  574. }
  575. /* @} */