dfs_posix.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2009-05-27 Yi.qiu The first version
  9. * 2018-02-07 Bernard Change the 3rd parameter of open/fcntl/ioctl to '...'
  10. * 2022-01-19 Meco Man add creat()
  11. */
  12. #include <dfs_file.h>
  13. #include <dfs_private.h>
  14. #include <sys/errno.h>
  15. #ifdef RT_USING_SMART
  16. #include <lwp.h>
  17. #endif
  18. /**
  19. * @addtogroup FsPosixApi
  20. * @{
  21. */
  22. /**
  23. * this function is a POSIX compliant version, which will open a file and
  24. * return a file descriptor according specified flags.
  25. *
  26. * @param file the path name of file.
  27. * @param flags the file open flags.
  28. *
  29. * @return the non-negative integer on successful open, others for failed.
  30. */
  31. int open(const char *file, int flags, ...)
  32. {
  33. int fd, result;
  34. struct dfs_file *d;
  35. /* allocate a fd */
  36. fd = fd_new();
  37. if (fd < 0)
  38. {
  39. rt_set_errno(-ENOMEM);
  40. return -1;
  41. }
  42. d = fd_get(fd);
  43. result = dfs_file_open(d, file, flags);
  44. if (result < 0)
  45. {
  46. /* release the ref-count of fd */
  47. fd_release(fd);
  48. rt_set_errno(result);
  49. return -1;
  50. }
  51. return fd;
  52. }
  53. RTM_EXPORT(open);
  54. #ifndef AT_FDCWD
  55. #define AT_FDCWD (-100)
  56. #endif
  57. int openat(int dirfd, const char *path, int flag, ...)
  58. {
  59. struct dfs_file *d;
  60. char *fullpath;
  61. int fd;
  62. if (!path)
  63. {
  64. rt_set_errno(-EBADF);
  65. return -1;
  66. }
  67. fullpath = (char*)path;
  68. if (path[0] != '/')
  69. {
  70. if (dirfd != AT_FDCWD)
  71. {
  72. d = fd_get(dirfd);
  73. if (!d || !d->vnode)
  74. {
  75. rt_set_errno(-EBADF);
  76. return -1;
  77. }
  78. fullpath = dfs_dentry_full_path(d->dentry);
  79. if (!fullpath)
  80. {
  81. rt_set_errno(-ENOMEM);
  82. return -1;
  83. }
  84. }
  85. }
  86. fd = open(fullpath, flag, 0);
  87. if (fullpath != path)
  88. {
  89. rt_free(fullpath);
  90. }
  91. return fd;
  92. }
  93. /**
  94. * this function is a POSIX compliant version,
  95. * which will create a new file or rewrite an existing one
  96. *
  97. * @param path the path name of file.
  98. * @param mode the file permission bits to be used in creating the file (not used, can be 0)
  99. *
  100. * @return the non-negative integer on successful open, others for failed.
  101. */
  102. int creat(const char *path, mode_t mode)
  103. {
  104. return open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
  105. }
  106. RTM_EXPORT(creat);
  107. /**
  108. * this function is a POSIX compliant version, which will close the open
  109. * file descriptor.
  110. *
  111. * @param fd the file descriptor.
  112. *
  113. * @return 0 on successful, -1 on failed.
  114. */
  115. int close(int fd)
  116. {
  117. int result;
  118. struct dfs_file *d;
  119. d = fd_get(fd);
  120. if (d == NULL)
  121. {
  122. rt_set_errno(-EBADF);
  123. return -1;
  124. }
  125. result = dfs_file_close(d);
  126. if (result < 0)
  127. {
  128. rt_set_errno(result);
  129. return -1;
  130. }
  131. fd_release(fd);
  132. return 0;
  133. }
  134. RTM_EXPORT(close);
  135. /**
  136. * this function is a POSIX compliant version, which will read specified data
  137. * buffer length for an open file descriptor.
  138. *
  139. * @param fd the file descriptor.
  140. * @param buf the buffer to save the read data.
  141. * @param len the maximal length of data buffer
  142. *
  143. * @return the actual read data buffer length. If the returned value is 0, it
  144. * may be reach the end of file, please check errno.
  145. */
  146. #ifdef _READ_WRITE_RETURN_TYPE
  147. _READ_WRITE_RETURN_TYPE read(int fd, void *buf, size_t len) /* some gcc tool chains will use different data structure */
  148. #else
  149. ssize_t read(int fd, void *buf, size_t len)
  150. #endif
  151. {
  152. int result;
  153. struct dfs_file *d;
  154. /* get the fd */
  155. d = fd_get(fd);
  156. if (d == NULL)
  157. {
  158. rt_set_errno(-EBADF);
  159. return -1;
  160. }
  161. result = dfs_file_read(d, buf, len);
  162. if (result < 0)
  163. {
  164. rt_set_errno(result);
  165. return -1;
  166. }
  167. return result;
  168. }
  169. RTM_EXPORT(read);
  170. /**
  171. * this function is a POSIX compliant version, which will write specified data
  172. * buffer length for an open file descriptor.
  173. *
  174. * @param fd the file descriptor
  175. * @param buf the data buffer to be written.
  176. * @param len the data buffer length.
  177. *
  178. * @return the actual written data buffer length.
  179. */
  180. #ifdef _READ_WRITE_RETURN_TYPE
  181. _READ_WRITE_RETURN_TYPE write(int fd, const void *buf, size_t len) /* some gcc tool chains will use different data structure */
  182. #else
  183. ssize_t write(int fd, const void *buf, size_t len)
  184. #endif
  185. {
  186. int result;
  187. struct dfs_file *d;
  188. /* get the fd */
  189. d = fd_get(fd);
  190. if (d == NULL)
  191. {
  192. rt_set_errno(-EBADF);
  193. return -1;
  194. }
  195. result = dfs_file_write(d, buf, len);
  196. if (result < 0)
  197. {
  198. rt_set_errno(result);
  199. return -1;
  200. }
  201. return result;
  202. }
  203. RTM_EXPORT(write);
  204. /**
  205. * this function is a POSIX compliant version, which will seek the offset for
  206. * an open file descriptor.
  207. *
  208. * @param fd the file descriptor.
  209. * @param offset the offset to be seeked.
  210. * @param whence the directory of seek.
  211. *
  212. * @return the current read/write position in the file, or -1 on failed.
  213. */
  214. off_t lseek(int fd, off_t offset, int whence)
  215. {
  216. int result;
  217. struct dfs_file *d;
  218. d = fd_get(fd);
  219. if (d == NULL)
  220. {
  221. rt_set_errno(-EBADF);
  222. return -1;
  223. }
  224. switch (whence)
  225. {
  226. case SEEK_SET:
  227. break;
  228. case SEEK_CUR:
  229. offset += d->pos;
  230. break;
  231. case SEEK_END:
  232. offset += d->vnode->size;
  233. break;
  234. default:
  235. rt_set_errno(-EINVAL);
  236. return -1;
  237. }
  238. if (offset < 0)
  239. {
  240. rt_set_errno(-EINVAL);
  241. return -1;
  242. }
  243. result = dfs_file_lseek(d, offset);
  244. if (result < 0)
  245. {
  246. rt_set_errno(result);
  247. return -1;
  248. }
  249. return offset;
  250. }
  251. RTM_EXPORT(lseek);
  252. #ifndef _WIN32
  253. /**
  254. * this function is a POSIX compliant version, which will rename old file name
  255. * to new file name.
  256. *
  257. * @param old_file the old file name.
  258. * @param new_file the new file name.
  259. *
  260. * @return 0 on successful, -1 on failed.
  261. *
  262. * note: the old and new file name must be belong to a same file system.
  263. */
  264. int rename(const char *old_file, const char *new_file)
  265. {
  266. int result;
  267. result = dfs_file_rename(old_file, new_file);
  268. if (result < 0)
  269. {
  270. rt_set_errno(result);
  271. return -1;
  272. }
  273. return 0;
  274. }
  275. RTM_EXPORT(rename);
  276. #endif
  277. /**
  278. * this function is a POSIX compliant version, which will unlink (remove) a
  279. * specified path file from file system.
  280. *
  281. * @param pathname the specified path name to be unlinked.
  282. *
  283. * @return 0 on successful, -1 on failed.
  284. */
  285. int unlink(const char *pathname)
  286. {
  287. int result;
  288. result = dfs_file_unlink(pathname);
  289. if (result < 0)
  290. {
  291. rt_set_errno(result);
  292. return -1;
  293. }
  294. return 0;
  295. }
  296. RTM_EXPORT(unlink);
  297. /**
  298. * this function is a POSIX compliant version, which will get file information.
  299. *
  300. * @param file the file name
  301. * @param buf the data buffer to save stat description.
  302. *
  303. * @return 0 on successful, -1 on failed.
  304. */
  305. int stat(const char *file, struct stat *buf)
  306. {
  307. int result;
  308. result = dfs_file_stat(file, buf);
  309. if (result < 0)
  310. {
  311. rt_set_errno(result);
  312. return -1;
  313. }
  314. return result;
  315. }
  316. RTM_EXPORT(stat);
  317. /**
  318. * this function is a POSIX compliant version, which will get file status.
  319. *
  320. * @param fildes the file description
  321. * @param buf the data buffer to save stat description.
  322. *
  323. * @return 0 on successful, -1 on failed.
  324. */
  325. int fstat(int fildes, struct stat *buf)
  326. {
  327. struct dfs_file *d;
  328. /* get the fd */
  329. d = fd_get(fildes);
  330. if (d == NULL)
  331. {
  332. rt_set_errno(-EBADF);
  333. return -1;
  334. }
  335. return stat(d->vnode->fullpath, buf);
  336. }
  337. RTM_EXPORT(fstat);
  338. /**
  339. * this function is a POSIX compliant version, which shall request that all data
  340. * for the open file descriptor named by fildes is to be transferred to the storage
  341. * device associated with the file described by fildes.
  342. *
  343. * @param fildes the file description
  344. *
  345. * @return 0 on successful completion. Otherwise, -1 shall be returned and errno
  346. * set to indicate the error.
  347. */
  348. int fsync(int fildes)
  349. {
  350. int ret;
  351. struct dfs_file *d;
  352. /* get the fd */
  353. d = fd_get(fildes);
  354. if (d == NULL)
  355. {
  356. rt_set_errno(-EBADF);
  357. return -1;
  358. }
  359. ret = dfs_file_flush(d);
  360. return ret;
  361. }
  362. RTM_EXPORT(fsync);
  363. /**
  364. * this function is a POSIX compliant version, which shall perform a variety of
  365. * control functions on devices.
  366. *
  367. * @param fildes the file description
  368. * @param cmd the specified command
  369. * @param ... represents the additional information that is needed by this
  370. * specific device to perform the requested function.
  371. *
  372. * @return 0 on successful completion. Otherwise, -1 shall be returned and errno
  373. * set to indicate the error.
  374. */
  375. int fcntl(int fildes, int cmd, ...)
  376. {
  377. int ret = -1;
  378. struct dfs_file *d;
  379. /* get the fd */
  380. d = fd_get(fildes);
  381. if (d)
  382. {
  383. void *arg;
  384. va_list ap;
  385. va_start(ap, cmd);
  386. arg = va_arg(ap, void *);
  387. va_end(ap);
  388. ret = dfs_file_ioctl(d, cmd, arg);
  389. }
  390. else ret = -EBADF;
  391. if (ret < 0)
  392. {
  393. rt_set_errno(ret);
  394. ret = -1;
  395. }
  396. return ret;
  397. }
  398. RTM_EXPORT(fcntl);
  399. /**
  400. * this function is a POSIX compliant version, which shall perform a variety of
  401. * control functions on devices.
  402. *
  403. * @param fildes the file description
  404. * @param cmd the specified command
  405. * @param ... represents the additional information that is needed by this
  406. * specific device to perform the requested function.
  407. *
  408. * @return 0 on successful completion. Otherwise, -1 shall be returned and errno
  409. * set to indicate the error.
  410. */
  411. int ioctl(int fildes, int cmd, ...)
  412. {
  413. void *arg;
  414. va_list ap;
  415. va_start(ap, cmd);
  416. arg = va_arg(ap, void *);
  417. va_end(ap);
  418. /* we use fcntl for this API. */
  419. return fcntl(fildes, cmd, arg);
  420. }
  421. RTM_EXPORT(ioctl);
  422. /**
  423. *
  424. * this function is a POSIX compliant version, which cause the regular file
  425. * referenced by fd to be truncated to a size of precisely length bytes.
  426. * @param fd the file descriptor.
  427. * @param length the length to be truncated.
  428. *
  429. * @return Upon successful completion, ftruncate() shall return 0;
  430. * otherwise, -1 shall be returned and errno set to indicate the error.
  431. */
  432. int ftruncate(int fd, off_t length)
  433. {
  434. int result;
  435. struct dfs_file *d;
  436. d = fd_get(fd);
  437. if (d == NULL)
  438. {
  439. rt_set_errno(-EBADF);
  440. return -1;
  441. }
  442. if (length < 0)
  443. {
  444. rt_set_errno(-EINVAL);
  445. return -1;
  446. }
  447. result = dfs_file_ftruncate(d, length);
  448. if (result < 0)
  449. {
  450. rt_set_errno(result);
  451. return -1;
  452. }
  453. return 0;
  454. }
  455. RTM_EXPORT(ftruncate);
  456. /**
  457. * this function is a POSIX compliant version, which will return the
  458. * information about a mounted file system.
  459. *
  460. * @param path the path which mounted file system.
  461. * @param buf the buffer to save the returned information.
  462. *
  463. * @return 0 on successful, others on failed.
  464. */
  465. int statfs(const char *path, struct statfs *buf)
  466. {
  467. int result;
  468. result = dfs_statfs(path, buf);
  469. if (result < 0)
  470. {
  471. rt_set_errno(result);
  472. return -1;
  473. }
  474. return result;
  475. }
  476. RTM_EXPORT(statfs);
  477. /**
  478. * this function is a POSIX compliant version, which will return the
  479. * information about a mounted file system.
  480. *
  481. * @param fildes the file description.
  482. * @param buf the buffer to save the returned information.
  483. *
  484. * @return 0 on successful, others on failed.
  485. */
  486. int fstatfs(int fildes, struct statfs *buf)
  487. {
  488. struct dfs_file *d;
  489. /* get the fd */
  490. d = fd_get(fildes);
  491. if (d == NULL)
  492. {
  493. rt_set_errno(-EBADF);
  494. return -1;
  495. }
  496. return statfs(d->vnode->fullpath, buf);
  497. }
  498. RTM_EXPORT(fstatfs);
  499. /**
  500. * this function is a POSIX compliant version, which will make a directory
  501. *
  502. * @param path the directory path to be made.
  503. * @param mode
  504. *
  505. * @return 0 on successful, others on failed.
  506. */
  507. int mkdir(const char *path, mode_t mode)
  508. {
  509. int fd;
  510. struct dfs_file *d;
  511. int result;
  512. fd = fd_new();
  513. if (fd == -1)
  514. {
  515. rt_set_errno(-ENOMEM);
  516. return -1;
  517. }
  518. d = fd_get(fd);
  519. result = dfs_file_open(d, path, O_DIRECTORY | O_CREAT);
  520. if (result < 0)
  521. {
  522. fd_release(fd);
  523. rt_set_errno(result);
  524. return -1;
  525. }
  526. dfs_file_close(d);
  527. fd_release(fd);
  528. return 0;
  529. }
  530. RTM_EXPORT(mkdir);
  531. /**
  532. * this function is a POSIX compliant version, which will remove a directory.
  533. *
  534. * @param pathname the path name to be removed.
  535. *
  536. * @return 0 on successful, others on failed.
  537. */
  538. int rmdir(const char *pathname)
  539. {
  540. int result;
  541. result = dfs_file_unlink(pathname);
  542. if (result < 0)
  543. {
  544. rt_set_errno(result);
  545. return -1;
  546. }
  547. return 0;
  548. }
  549. RTM_EXPORT(rmdir);
  550. /**
  551. * this function is a POSIX compliant version, which will open a directory.
  552. *
  553. * @param name the path name to be open.
  554. *
  555. * @return the DIR pointer of directory, NULL on open directory failed.
  556. */
  557. DIR *opendir(const char *name)
  558. {
  559. struct dfs_file *d;
  560. int fd, result;
  561. DIR *t;
  562. t = NULL;
  563. /* allocate a fd */
  564. fd = fd_new();
  565. if (fd == -1)
  566. {
  567. rt_set_errno(-ENOMEM);
  568. return NULL;
  569. }
  570. d = fd_get(fd);
  571. result = dfs_file_open(d, name, O_RDONLY | O_DIRECTORY);
  572. if (result >= 0)
  573. {
  574. /* open successfully */
  575. t = (DIR *) rt_malloc(sizeof(DIR));
  576. if (t == NULL)
  577. {
  578. dfs_file_close(d);
  579. fd_release(fd);
  580. }
  581. else
  582. {
  583. rt_memset(t, 0, sizeof(DIR));
  584. t->fd = fd;
  585. }
  586. return t;
  587. }
  588. /* open failed */
  589. fd_release(fd);
  590. rt_set_errno(result);
  591. return NULL;
  592. }
  593. RTM_EXPORT(opendir);
  594. /**
  595. * this function is a POSIX compliant version, which will return a pointer
  596. * to a dirent structure representing the next directory entry in the
  597. * directory stream.
  598. *
  599. * @param d the directory stream pointer.
  600. *
  601. * @return the next directory entry, NULL on the end of directory or failed.
  602. */
  603. struct dirent *readdir(DIR *d)
  604. {
  605. int result;
  606. struct dfs_file *fd;
  607. fd = fd_get(d->fd);
  608. if (fd == NULL)
  609. {
  610. rt_set_errno(-EBADF);
  611. return NULL;
  612. }
  613. if (d->num)
  614. {
  615. struct dirent *dirent_ptr;
  616. dirent_ptr = (struct dirent *)&d->buf[d->cur];
  617. d->cur += dirent_ptr->d_reclen;
  618. }
  619. if (!d->num || d->cur >= d->num)
  620. {
  621. /* get a new entry */
  622. result = dfs_file_getdents(fd,
  623. (struct dirent *)d->buf,
  624. sizeof(d->buf) - 1);
  625. if (result <= 0)
  626. {
  627. rt_set_errno(result);
  628. return NULL;
  629. }
  630. d->num = result;
  631. d->cur = 0; /* current entry index */
  632. }
  633. return (struct dirent *)(d->buf + d->cur);
  634. }
  635. RTM_EXPORT(readdir);
  636. /**
  637. * this function is a POSIX compliant version, which will return current
  638. * location in directory stream.
  639. *
  640. * @param d the directory stream pointer.
  641. *
  642. * @return the current location in directory stream.
  643. */
  644. long telldir(DIR *d)
  645. {
  646. struct dfs_file *fd;
  647. long result;
  648. fd = fd_get(d->fd);
  649. if (fd == NULL)
  650. {
  651. rt_set_errno(-EBADF);
  652. return 0;
  653. }
  654. result = fd->pos - d->num + d->cur;
  655. return result;
  656. }
  657. RTM_EXPORT(telldir);
  658. /**
  659. * this function is a POSIX compliant version, which will set position of
  660. * next directory structure in the directory stream.
  661. *
  662. * @param d the directory stream.
  663. * @param offset the offset in directory stream.
  664. */
  665. void seekdir(DIR *d, long offset)
  666. {
  667. struct dfs_file *fd;
  668. fd = fd_get(d->fd);
  669. if (fd == NULL)
  670. {
  671. rt_set_errno(-EBADF);
  672. return ;
  673. }
  674. /* seek to the offset position of directory */
  675. if (dfs_file_lseek(fd, offset) >= 0)
  676. d->num = d->cur = 0;
  677. }
  678. RTM_EXPORT(seekdir);
  679. /**
  680. * this function is a POSIX compliant version, which will reset directory
  681. * stream.
  682. *
  683. * @param d the directory stream.
  684. */
  685. void rewinddir(DIR *d)
  686. {
  687. struct dfs_file *fd;
  688. fd = fd_get(d->fd);
  689. if (fd == NULL)
  690. {
  691. rt_set_errno(-EBADF);
  692. return ;
  693. }
  694. /* seek to the beginning of directory */
  695. if (dfs_file_lseek(fd, 0) >= 0)
  696. d->num = d->cur = 0;
  697. }
  698. RTM_EXPORT(rewinddir);
  699. /**
  700. * this function is a POSIX compliant version, which will close a directory
  701. * stream.
  702. *
  703. * @param d the directory stream.
  704. *
  705. * @return 0 on successful, -1 on failed.
  706. */
  707. int closedir(DIR *d)
  708. {
  709. int result;
  710. struct dfs_file *fd;
  711. fd = fd_get(d->fd);
  712. if (fd == NULL)
  713. {
  714. rt_set_errno(-EBADF);
  715. return -1;
  716. }
  717. result = dfs_file_close(fd);
  718. fd_release(d->fd);
  719. rt_free(d);
  720. if (result < 0)
  721. {
  722. rt_set_errno(result);
  723. return -1;
  724. }
  725. else
  726. return 0;
  727. }
  728. RTM_EXPORT(closedir);
  729. #ifdef DFS_USING_WORKDIR
  730. /**
  731. * this function is a POSIX compliant version, which will change working
  732. * directory.
  733. *
  734. * @param path the path name to be changed to.
  735. *
  736. * @return 0 on successful, -1 on failed.
  737. */
  738. int chdir(const char *path)
  739. {
  740. char *fullpath;
  741. DIR *d;
  742. if (path == NULL)
  743. {
  744. dfs_lock();
  745. #ifdef DFS_USING_WORKDIR
  746. rt_kprintf("%s\n", working_directory);
  747. #endif
  748. dfs_unlock();
  749. return 0;
  750. }
  751. if (strlen(path) > DFS_PATH_MAX)
  752. {
  753. rt_set_errno(-ENOTDIR);
  754. return -1;
  755. }
  756. fullpath = dfs_normalize_path(NULL, path);
  757. if (fullpath == NULL)
  758. {
  759. rt_set_errno(-ENOTDIR);
  760. return -1; /* build path failed */
  761. }
  762. dfs_lock();
  763. d = opendir(fullpath);
  764. if (d == NULL)
  765. {
  766. rt_free(fullpath);
  767. /* this is a not exist directory */
  768. dfs_unlock();
  769. return -1;
  770. }
  771. /* close directory stream */
  772. closedir(d);
  773. #ifdef RT_USING_SMART
  774. /* copy full path to working directory */
  775. lwp_setcwd(fullpath);
  776. #else
  777. rt_strncpy(working_directory, fullpath, DFS_PATH_MAX);
  778. #endif
  779. /* release normalize directory path name */
  780. rt_free(fullpath);
  781. dfs_unlock();
  782. return 0;
  783. }
  784. RTM_EXPORT(chdir);
  785. #ifdef RT_USING_FINSH
  786. FINSH_FUNCTION_EXPORT_ALIAS(chdir, cd, change current working directory);
  787. #endif
  788. #endif
  789. /**
  790. * this function is a POSIX compliant version, which shall check the file named
  791. * by the pathname pointed to by the path argument for accessibility according
  792. * to the bit pattern contained in amode.
  793. *
  794. * @param path the specified file/dir path.
  795. * @param amode the value is either the bitwise-inclusive OR of the access
  796. * permissions to be checked (R_OK, W_OK, X_OK) or the existence test (F_OK).
  797. */
  798. int access(const char *path, int amode)
  799. {
  800. struct stat sb;
  801. if (stat(path, &sb) < 0)
  802. return -1; /* already sets errno */
  803. /* ignore R_OK,W_OK,X_OK condition */
  804. return 0;
  805. }
  806. /**
  807. * this function is a POSIX compliant version, which will set current
  808. * working directory.
  809. *
  810. * @param buf the current directory.
  811. */
  812. void setcwd(char *buf)
  813. {
  814. #ifdef DFS_USING_WORKDIR
  815. dfs_lock();
  816. #ifdef RT_USING_SMART
  817. lwp_setcwd(buf);
  818. #else
  819. rt_strncpy(working_directory, buf, DFS_PATH_MAX);
  820. #endif
  821. dfs_unlock();
  822. #else
  823. rt_kprintf(NO_WORKING_DIR);
  824. #endif
  825. return ;
  826. }
  827. RTM_EXPORT(setcwd);
  828. /**
  829. * this function is a POSIX compliant version, which will return current
  830. * working directory.
  831. *
  832. * @param buf the returned current directory.
  833. * @param size the buffer size.
  834. *
  835. * @return the returned current directory.
  836. */
  837. char *getcwd(char *buf, size_t size)
  838. {
  839. #ifdef DFS_USING_WORKDIR
  840. char *dir_buf = RT_NULL;
  841. dfs_lock();
  842. #ifdef RT_USING_SMART
  843. dir_buf = lwp_getcwd();
  844. #else
  845. dir_buf = &working_directory[0];
  846. #endif
  847. /* copy to buf parameter */
  848. if (buf)
  849. {
  850. rt_strncpy(buf, dir_buf, size);
  851. }
  852. dfs_unlock();
  853. #else
  854. rt_kprintf(NO_WORKING_DIR);
  855. #endif
  856. return buf;
  857. }
  858. RTM_EXPORT(getcwd);
  859. /**@}*/