dfs.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962
  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. * 2005-02-22 Bernard The first version.
  9. * 2017-12-11 Bernard Use rt_free to instead of free in fd_is_open().
  10. * 2018-03-20 Heyuanjie dynamic allocation FD
  11. */
  12. #include <dfs.h>
  13. #include <dfs_fs.h>
  14. #include <dfs_file.h>
  15. #include "dfs_private.h"
  16. #ifdef RT_USING_LWP
  17. #include <lwp.h>
  18. #endif
  19. /* Global variables */
  20. const struct dfs_filesystem_ops *filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX];
  21. struct dfs_filesystem filesystem_table[DFS_FILESYSTEMS_MAX];
  22. /* device filesystem lock */
  23. static struct rt_mutex fslock;
  24. static struct rt_mutex fdlock;
  25. #ifdef DFS_USING_WORKDIR
  26. char working_directory[DFS_PATH_MAX] = {"/"};
  27. #endif
  28. static struct dfs_fdtable _fdtab;
  29. static int fd_alloc(struct dfs_fdtable *fdt, int startfd);
  30. /**
  31. * @addtogroup DFS
  32. */
  33. /*@{*/
  34. /**
  35. * this function will initialize device file system.
  36. */
  37. int dfs_init(void)
  38. {
  39. static rt_bool_t init_ok = RT_FALSE;
  40. if (init_ok)
  41. {
  42. rt_kprintf("dfs already init.\n");
  43. return 0;
  44. }
  45. /* init fnode hash table */
  46. dfs_fnode_mgr_init();
  47. /* clear filesystem operations table */
  48. memset((void *)filesystem_operation_table, 0, sizeof(filesystem_operation_table));
  49. /* clear filesystem table */
  50. memset(filesystem_table, 0, sizeof(filesystem_table));
  51. /* clean fd table */
  52. memset(&_fdtab, 0, sizeof(_fdtab));
  53. /* create device filesystem lock */
  54. rt_mutex_init(&fslock, "fslock", RT_IPC_FLAG_FIFO);
  55. rt_mutex_init(&fdlock, "fdlock", RT_IPC_FLAG_FIFO);
  56. #ifdef DFS_USING_WORKDIR
  57. /* set current working directory */
  58. memset(working_directory, 0, sizeof(working_directory));
  59. working_directory[0] = '/';
  60. #endif
  61. #ifdef RT_USING_DFS_DEVFS
  62. {
  63. extern int devfs_init(void);
  64. /* if enable devfs, initialize and mount it as soon as possible */
  65. devfs_init();
  66. dfs_mount(NULL, "/dev", "devfs", 0, 0);
  67. }
  68. #endif
  69. init_ok = RT_TRUE;
  70. return 0;
  71. }
  72. INIT_PREV_EXPORT(dfs_init);
  73. /**
  74. * this function will lock device file system.
  75. *
  76. * @note please don't invoke it on ISR.
  77. */
  78. void dfs_lock(void)
  79. {
  80. rt_err_t result = -RT_EBUSY;
  81. while (result == -RT_EBUSY)
  82. {
  83. result = rt_mutex_take(&fslock, RT_WAITING_FOREVER);
  84. }
  85. if (result != RT_EOK)
  86. {
  87. RT_ASSERT(0);
  88. }
  89. }
  90. void dfs_fd_lock(void)
  91. {
  92. rt_err_t result = -RT_EBUSY;
  93. while (result == -RT_EBUSY)
  94. {
  95. result = rt_mutex_take(&fdlock, RT_WAITING_FOREVER);
  96. }
  97. if (result != RT_EOK)
  98. {
  99. RT_ASSERT(0);
  100. }
  101. }
  102. /**
  103. * this function will lock device file system.
  104. *
  105. * @note please don't invoke it on ISR.
  106. */
  107. void dfs_unlock(void)
  108. {
  109. rt_mutex_release(&fslock);
  110. }
  111. void dfs_fd_unlock(void)
  112. {
  113. rt_mutex_release(&fdlock);
  114. }
  115. static int fd_slot_expand(struct dfs_fdtable *fdt, int fd)
  116. {
  117. int nr;
  118. int index;
  119. struct dfs_fd **fds = NULL;
  120. if (fd < fdt->maxfd)
  121. {
  122. return fd;
  123. }
  124. if (fd >= DFS_FD_MAX)
  125. {
  126. return -1;
  127. }
  128. nr = ((fd + 4) & ~3);
  129. if (nr > DFS_FD_MAX)
  130. {
  131. nr = DFS_FD_MAX;
  132. }
  133. fds = (struct dfs_fd **)rt_realloc(fdt->fds, nr * sizeof(struct dfs_fd *));
  134. if (!fds)
  135. {
  136. return -1;
  137. }
  138. /* clean the new allocated fds */
  139. for (index = fdt->maxfd; index < nr; index++)
  140. {
  141. fds[index] = NULL;
  142. }
  143. fdt->fds = fds;
  144. fdt->maxfd = nr;
  145. return fd;
  146. }
  147. static int fd_slot_alloc(struct dfs_fdtable *fdt, int startfd)
  148. {
  149. int idx;
  150. /* find an empty fd slot */
  151. for (idx = startfd; idx < (int)fdt->maxfd; idx++)
  152. {
  153. if (fdt->fds[idx] == RT_NULL)
  154. {
  155. return idx;
  156. }
  157. }
  158. idx = fdt->maxfd;
  159. if (idx < startfd)
  160. {
  161. idx = startfd;
  162. }
  163. if (fd_slot_expand(fdt, idx) < 0)
  164. {
  165. return -1;
  166. }
  167. return idx;
  168. }
  169. static int fd_alloc(struct dfs_fdtable *fdt, int startfd)
  170. {
  171. int idx;
  172. struct dfs_fd *fd = NULL;
  173. idx = fd_slot_alloc(fdt, startfd);
  174. /* allocate 'struct dfs_fd' */
  175. if (idx < 0)
  176. {
  177. return -1;
  178. }
  179. fd = (struct dfs_fd *)rt_calloc(1, sizeof(struct dfs_fd));
  180. if (!fd)
  181. {
  182. return -1;
  183. }
  184. fd->ref_count = 1;
  185. fd->magic = DFS_FD_MAGIC;
  186. fd->fnode = NULL;
  187. fdt->fds[idx] = fd;
  188. return idx;
  189. }
  190. /**
  191. * @ingroup Fd
  192. * This function will allocate a file descriptor.
  193. *
  194. * @return -1 on failed or the allocated file descriptor.
  195. */
  196. int fdt_fd_new(struct dfs_fdtable *fdt)
  197. {
  198. int idx;
  199. /* lock filesystem */
  200. dfs_fd_lock();
  201. /* find an empty fd entry */
  202. idx = fd_alloc(fdt, DFS_STDIO_OFFSET);
  203. /* can't find an empty fd entry */
  204. if (idx < 0)
  205. {
  206. LOG_E("DFS fd new is failed! Could not found an empty fd entry.");
  207. }
  208. dfs_fd_unlock();
  209. return idx;
  210. }
  211. int fd_new(void)
  212. {
  213. struct dfs_fdtable *fdt = NULL;
  214. fdt = dfs_fdtable_get();
  215. return fdt_fd_new(fdt);
  216. }
  217. /**
  218. * @ingroup Fd
  219. *
  220. * This function will return a file descriptor structure according to file
  221. * descriptor.
  222. *
  223. * @return NULL on on this file descriptor or the file descriptor structure
  224. * pointer.
  225. */
  226. struct dfs_fd *fdt_fd_get(struct dfs_fdtable* fdt, int fd)
  227. {
  228. struct dfs_fd *d;
  229. if (fd < 0 || fd >= (int)fdt->maxfd)
  230. {
  231. return NULL;
  232. }
  233. dfs_fd_lock();
  234. d = fdt->fds[fd];
  235. /* check dfs_fd valid or not */
  236. if ((d == NULL) || (d->magic != DFS_FD_MAGIC))
  237. {
  238. dfs_fd_unlock();
  239. return NULL;
  240. }
  241. dfs_fd_unlock();
  242. return d;
  243. }
  244. struct dfs_fd *fd_get(int fd)
  245. {
  246. struct dfs_fdtable *fdt;
  247. fdt = dfs_fdtable_get();
  248. return fdt_fd_get(fdt, fd);
  249. }
  250. /**
  251. * @ingroup Fd
  252. *
  253. * This function will put the file descriptor.
  254. */
  255. void fdt_fd_release(struct dfs_fdtable* fdt, int fd)
  256. {
  257. struct dfs_fd *fd_slot = NULL;
  258. RT_ASSERT(fdt != NULL);
  259. dfs_fd_lock();
  260. if ((fd < 0) || (fd >= fdt->maxfd))
  261. {
  262. dfs_fd_unlock();
  263. return;
  264. }
  265. fd_slot = fdt->fds[fd];
  266. if (fd_slot == NULL)
  267. {
  268. dfs_fd_unlock();
  269. return;
  270. }
  271. fdt->fds[fd] = NULL;
  272. /* check fd */
  273. RT_ASSERT(fd_slot->magic == DFS_FD_MAGIC);
  274. fd_slot->ref_count--;
  275. /* clear this fd entry */
  276. if (fd_slot->ref_count == 0)
  277. {
  278. struct dfs_fnode *fnode = fd_slot->fnode;
  279. if (fnode)
  280. {
  281. fnode->ref_count--;
  282. }
  283. rt_free(fd_slot);
  284. }
  285. dfs_fd_unlock();
  286. }
  287. void fd_release(int fd)
  288. {
  289. struct dfs_fdtable *fdt;
  290. fdt = dfs_fdtable_get();
  291. fdt_fd_release(fdt, fd);
  292. }
  293. int sys_dup(int oldfd)
  294. {
  295. int newfd = -1;
  296. struct dfs_fdtable *fdt = NULL;
  297. dfs_fd_lock();
  298. /* check old fd */
  299. fdt = dfs_fdtable_get();
  300. if ((oldfd < 0) || (oldfd >= fdt->maxfd))
  301. {
  302. goto exit;
  303. }
  304. if (!fdt->fds[oldfd])
  305. {
  306. goto exit;
  307. }
  308. /* get a new fd */
  309. newfd = fd_slot_alloc(fdt, DFS_STDIO_OFFSET);
  310. if (newfd >= 0)
  311. {
  312. fdt->fds[newfd] = fdt->fds[oldfd];
  313. /* inc ref_count */
  314. fdt->fds[newfd]->ref_count++;
  315. }
  316. exit:
  317. dfs_fd_unlock();
  318. return newfd;
  319. }
  320. int sys_dup2(int oldfd, int newfd)
  321. {
  322. struct dfs_fdtable *fdt = NULL;
  323. int ret = 0;
  324. int retfd = -1;
  325. dfs_fd_lock();
  326. /* check old fd */
  327. fdt = dfs_fdtable_get();
  328. if ((oldfd < 0) || (oldfd >= fdt->maxfd))
  329. {
  330. goto exit;
  331. }
  332. if (!fdt->fds[oldfd])
  333. {
  334. goto exit;
  335. }
  336. if (newfd < 0)
  337. {
  338. goto exit;
  339. }
  340. if (newfd >= fdt->maxfd)
  341. {
  342. newfd = fd_slot_expand(fdt, newfd);
  343. if (newfd < 0)
  344. {
  345. goto exit;
  346. }
  347. }
  348. if (fdt->fds[newfd] == fdt->fds[oldfd])
  349. {
  350. /* ok, return newfd */
  351. retfd = newfd;
  352. goto exit;
  353. }
  354. if (fdt->fds[newfd])
  355. {
  356. ret = dfs_file_close(fdt->fds[newfd]);
  357. if (ret < 0)
  358. {
  359. goto exit;
  360. }
  361. fd_release(newfd);
  362. }
  363. fdt->fds[newfd] = fdt->fds[oldfd];
  364. /* inc ref_count */
  365. fdt->fds[newfd]->ref_count++;
  366. retfd = newfd;
  367. exit:
  368. dfs_fd_unlock();
  369. return retfd;
  370. }
  371. static int fd_get_fd_index_form_fdt(struct dfs_fdtable *fdt, struct dfs_fd *file)
  372. {
  373. int fd = -1;
  374. if (file == RT_NULL)
  375. {
  376. return -1;
  377. }
  378. dfs_fd_lock();
  379. for(int index = 0; index < (int)fdt->maxfd; index++)
  380. {
  381. if(fdt->fds[index] == file)
  382. {
  383. fd = index;
  384. break;
  385. }
  386. }
  387. dfs_fd_unlock();
  388. return fd;
  389. }
  390. int fd_get_fd_index(struct dfs_fd *file)
  391. {
  392. struct dfs_fdtable *fdt;
  393. fdt = dfs_fdtable_get();
  394. return fd_get_fd_index_form_fdt(fdt, file);
  395. }
  396. int fd_associate(struct dfs_fdtable *fdt, int fd, struct dfs_fd *file)
  397. {
  398. int retfd = -1;
  399. if (!file)
  400. {
  401. return retfd;
  402. }
  403. if (!fdt)
  404. {
  405. return retfd;
  406. }
  407. dfs_fd_lock();
  408. /* check old fd */
  409. if ((fd < 0) || (fd >= fdt->maxfd))
  410. {
  411. goto exit;
  412. }
  413. if (fdt->fds[fd])
  414. {
  415. goto exit;
  416. }
  417. /* inc ref_count */
  418. file->ref_count++;
  419. fdt->fds[fd] = file;
  420. retfd = fd;
  421. exit:
  422. dfs_fd_unlock();
  423. return retfd;
  424. }
  425. void fd_init(struct dfs_fd *fd)
  426. {
  427. if (fd)
  428. {
  429. fd->magic = DFS_FD_MAGIC;
  430. fd->ref_count = 1;
  431. fd->pos = 0;
  432. fd->fnode = NULL;
  433. fd->data = NULL;
  434. }
  435. }
  436. /**
  437. * this function will return a sub-path name under directory.
  438. *
  439. * @param directory the parent directory.
  440. * @param filename the filename.
  441. *
  442. * @return the subdir pointer in filename
  443. */
  444. const char *dfs_subdir(const char *directory, const char *filename)
  445. {
  446. const char *dir;
  447. if (strlen(directory) == strlen(filename)) /* it's a same path */
  448. return NULL;
  449. dir = filename + strlen(directory);
  450. if ((*dir != '/') && (dir != filename))
  451. {
  452. dir--;
  453. }
  454. return dir;
  455. }
  456. RTM_EXPORT(dfs_subdir);
  457. /**
  458. * this function will normalize a path according to specified parent directory
  459. * and file name.
  460. *
  461. * @param directory the parent path
  462. * @param filename the file name
  463. *
  464. * @return the built full file path (absolute path)
  465. */
  466. char *dfs_normalize_path(const char *directory, const char *filename)
  467. {
  468. char *fullpath;
  469. char *dst0, *dst, *src;
  470. /* check parameters */
  471. RT_ASSERT(filename != NULL);
  472. #ifdef DFS_USING_WORKDIR
  473. if (directory == NULL) /* shall use working directory */
  474. {
  475. #ifdef RT_USING_LWP
  476. directory = lwp_getcwd();
  477. #else
  478. directory = &working_directory[0];
  479. #endif
  480. }
  481. #else
  482. if ((directory == NULL) && (filename[0] != '/'))
  483. {
  484. rt_kprintf(NO_WORKING_DIR);
  485. return NULL;
  486. }
  487. #endif
  488. if (filename[0] != '/') /* it's a absolute path, use it directly */
  489. {
  490. fullpath = (char *)rt_malloc(strlen(directory) + strlen(filename) + 2);
  491. if (fullpath == NULL)
  492. return NULL;
  493. /* join path and file name */
  494. rt_snprintf(fullpath, strlen(directory) + strlen(filename) + 2,
  495. "%s/%s", directory, filename);
  496. }
  497. else
  498. {
  499. fullpath = rt_strdup(filename); /* copy string */
  500. if (fullpath == NULL)
  501. return NULL;
  502. }
  503. src = fullpath;
  504. dst = fullpath;
  505. dst0 = dst;
  506. while (1)
  507. {
  508. char c = *src;
  509. if (c == '.')
  510. {
  511. if (!src[1]) src++; /* '.' and ends */
  512. else if (src[1] == '/')
  513. {
  514. /* './' case */
  515. src += 2;
  516. while ((*src == '/') && (*src != '\0'))
  517. src++;
  518. continue;
  519. }
  520. else if (src[1] == '.')
  521. {
  522. if (!src[2])
  523. {
  524. /* '..' and ends case */
  525. src += 2;
  526. goto up_one;
  527. }
  528. else if (src[2] == '/')
  529. {
  530. /* '../' case */
  531. src += 3;
  532. while ((*src == '/') && (*src != '\0'))
  533. src++;
  534. goto up_one;
  535. }
  536. }
  537. }
  538. /* copy up the next '/' and erase all '/' */
  539. while ((c = *src++) != '\0' && c != '/')
  540. *dst++ = c;
  541. if (c == '/')
  542. {
  543. *dst++ = '/';
  544. while (c == '/')
  545. c = *src++;
  546. src--;
  547. }
  548. else if (!c)
  549. break;
  550. continue;
  551. up_one:
  552. dst--;
  553. if (dst < dst0)
  554. {
  555. rt_free(fullpath);
  556. return NULL;
  557. }
  558. while (dst0 < dst && dst[-1] != '/')
  559. dst--;
  560. }
  561. *dst = '\0';
  562. /* remove '/' in the end of path if exist */
  563. dst--;
  564. if ((dst != fullpath) && (*dst == '/'))
  565. *dst = '\0';
  566. /* final check fullpath is not empty, for the special path of lwext "/.." */
  567. if ('\0' == fullpath[0])
  568. {
  569. fullpath[0] = '/';
  570. fullpath[1] = '\0';
  571. }
  572. return fullpath;
  573. }
  574. RTM_EXPORT(dfs_normalize_path);
  575. /**
  576. * This function will get the file descriptor table of current process.
  577. */
  578. struct dfs_fdtable *dfs_fdtable_get(void)
  579. {
  580. struct dfs_fdtable *fdt;
  581. #ifdef RT_USING_LWP
  582. struct rt_lwp *lwp;
  583. lwp = (struct rt_lwp *)rt_thread_self()->lwp;
  584. if (lwp)
  585. fdt = &lwp->fdt;
  586. else
  587. fdt = &_fdtab;
  588. #else
  589. fdt = &_fdtab;
  590. #endif
  591. return fdt;
  592. }
  593. #ifdef RT_USING_LWP
  594. struct dfs_fdtable *dfs_fdtable_get_pid(int pid)
  595. {
  596. struct rt_lwp *lwp = RT_NULL;
  597. struct dfs_fdtable *fdt = RT_NULL;
  598. lwp = lwp_from_pid(pid);
  599. if (lwp)
  600. {
  601. fdt = &lwp->fdt;
  602. }
  603. return fdt;
  604. }
  605. #endif
  606. struct dfs_fdtable *dfs_fdtable_get_global(void)
  607. {
  608. return &_fdtab;
  609. }
  610. #ifdef RT_USING_FINSH
  611. #include <finsh.h>
  612. int list_fd(void)
  613. {
  614. int index;
  615. struct dfs_fdtable *fd_table;
  616. fd_table = dfs_fdtable_get();
  617. if (!fd_table) return -1;
  618. rt_enter_critical();
  619. rt_kprintf("fd type ref magic path\n");
  620. rt_kprintf("-- ------ --- ----- ------\n");
  621. for (index = 0; index < (int)fd_table->maxfd; index++)
  622. {
  623. struct dfs_fd *fd = fd_table->fds[index];
  624. if (fd && fd->fnode->fops)
  625. {
  626. rt_kprintf("%2d ", index);
  627. if (fd->fnode->type == FT_DIRECTORY) rt_kprintf("%-7.7s ", "dir");
  628. else if (fd->fnode->type == FT_REGULAR) rt_kprintf("%-7.7s ", "file");
  629. else if (fd->fnode->type == FT_SOCKET) rt_kprintf("%-7.7s ", "socket");
  630. else if (fd->fnode->type == FT_USER) rt_kprintf("%-7.7s ", "user");
  631. else if (fd->fnode->type == FT_DEVICE) rt_kprintf("%-7.7s ", "device");
  632. else rt_kprintf("%-8.8s ", "unknown");
  633. rt_kprintf("%3d ", fd->fnode->ref_count);
  634. rt_kprintf("%04x ", fd->magic);
  635. if (fd->fnode->path)
  636. {
  637. rt_kprintf("%s\n", fd->fnode->path);
  638. }
  639. else
  640. {
  641. rt_kprintf("\n");
  642. }
  643. }
  644. }
  645. rt_exit_critical();
  646. return 0;
  647. }
  648. MSH_CMD_EXPORT(list_fd, list file descriptor);
  649. #ifdef RT_USING_LWP
  650. static int lsofp(int pid)
  651. {
  652. int index;
  653. struct dfs_fdtable *fd_table = RT_NULL;
  654. if (pid == (-1))
  655. {
  656. fd_table = dfs_fdtable_get();
  657. if (!fd_table) return -1;
  658. }
  659. else
  660. {
  661. fd_table = dfs_fdtable_get_pid(pid);
  662. if (!fd_table)
  663. {
  664. rt_kprintf("PID %s is not a applet(lwp)\n", pid);
  665. return -1;
  666. }
  667. }
  668. rt_kprintf("--- -- ------ ------ ----- ---------- ---------- ---------- ------\n");
  669. rt_enter_critical();
  670. for (index = 0; index < (int)fd_table->maxfd; index++)
  671. {
  672. struct dfs_fd *fd = fd_table->fds[index];
  673. if (fd && fd->fnode->fops)
  674. {
  675. if(pid == (-1))
  676. {
  677. rt_kprintf(" K ");
  678. }
  679. else
  680. {
  681. rt_kprintf("%3d ", pid);
  682. }
  683. rt_kprintf("%2d ", index);
  684. if (fd->fnode->type == FT_DIRECTORY) rt_kprintf("%-7.7s ", "dir");
  685. else if (fd->fnode->type == FT_REGULAR) rt_kprintf("%-7.7s ", "file");
  686. else if (fd->fnode->type == FT_SOCKET) rt_kprintf("%-7.7s ", "socket");
  687. else if (fd->fnode->type == FT_USER) rt_kprintf("%-7.7s ", "user");
  688. else if (fd->fnode->type == FT_DEVICE) rt_kprintf("%-7.7s ", "device");
  689. else rt_kprintf("%-8.8s ", "unknown");
  690. rt_kprintf("%6d ", fd->fnode->ref_count);
  691. rt_kprintf("%04x 0x%.8x ", fd->magic, (int)(size_t)fd->fnode);
  692. if(fd->fnode == RT_NULL)
  693. {
  694. rt_kprintf("0x%.8x 0x%.8x ", (int)0x00000000, (int)(size_t)fd);
  695. }
  696. else
  697. {
  698. rt_kprintf("0x%.8x 0x%.8x ", (int)(size_t)(fd->fnode->data), (int)(size_t)fd);
  699. }
  700. if (fd->fnode->path)
  701. {
  702. rt_kprintf("%s \n", fd->fnode->path);
  703. }
  704. else
  705. {
  706. rt_kprintf("\n");
  707. }
  708. }
  709. }
  710. rt_exit_critical();
  711. return 0;
  712. }
  713. int lsof(int argc, char *argv[])
  714. {
  715. rt_kprintf("PID fd type fd-ref magic fnode fnode/data addr path \n");
  716. if (argc == 1)
  717. {
  718. struct rt_list_node *node, *list;
  719. struct lwp_avl_struct *pids = lwp_get_pid_ary();
  720. lsofp(-1);
  721. for (int index = 0; index < RT_LWP_MAX_NR; index++)
  722. {
  723. struct rt_lwp *lwp = (struct rt_lwp *)pids[index].data;
  724. if (lwp)
  725. {
  726. list = &lwp->t_grp;
  727. for (node = list->next; node != list; node = node->next)
  728. {
  729. lsofp(lwp_to_pid(lwp));
  730. }
  731. }
  732. }
  733. }
  734. else if (argc == 3)
  735. {
  736. if (argv[1][0] == '-' && argv[1][1] == 'p')
  737. {
  738. int pid = atoi(argv[2]);
  739. lsofp(pid);
  740. }
  741. }
  742. return 0;
  743. }
  744. MSH_CMD_EXPORT(lsof, list open files);
  745. #endif /* RT_USING_LWP */
  746. /*
  747. * If no argument is specified, display the mount history;
  748. * If there are 3 arguments, mount the filesystem.
  749. * The order of the arguments is:
  750. * argv[1]: device name
  751. * argv[2]: mountpoint path
  752. * argv[3]: filesystem type
  753. */
  754. int mount(int argc, char *argv[])
  755. {
  756. if (argc == 1) /* display the mount history */
  757. {
  758. struct dfs_filesystem *iter;
  759. rt_kprintf("filesystem device mountpoint\n");
  760. rt_kprintf("---------- ------ ----------\n");
  761. for (iter = &filesystem_table[0];
  762. iter < &filesystem_table[DFS_FILESYSTEMS_MAX]; iter++)
  763. {
  764. if ((iter != NULL) && (iter->path != NULL))
  765. {
  766. rt_kprintf("%-10s %-6s %-s\n",
  767. iter->ops->name, iter->dev_id->parent.name, iter->path);
  768. }
  769. }
  770. return 0;
  771. }
  772. else if (argc == 4)
  773. { /* mount a filesystem to the specified directory */
  774. char *device = argv[1];
  775. char *path = argv[2];
  776. char *fstype = argv[3];
  777. rt_kprintf("mount device %s(%s) onto %s ... ", device, fstype, path);
  778. if (dfs_mount(device, path, fstype, 0, 0) == 0)
  779. {
  780. rt_kprintf("succeed!\n");
  781. return 0;
  782. }
  783. else
  784. {
  785. rt_kprintf("failed!\n");
  786. return -1;
  787. }
  788. }
  789. else
  790. {
  791. rt_kprintf("Usage: mount <device> <mountpoint> <fstype>.\n");
  792. return -1;
  793. }
  794. }
  795. MSH_CMD_EXPORT(mount, mount<device><mountpoint><fstype>);
  796. /* unmount the filesystem from the specified mountpoint */
  797. int unmount(int argc, char *argv[])
  798. {
  799. if (argc != 2)
  800. {
  801. rt_kprintf("Usage: unmount <mountpoint>.\n");
  802. return -1;
  803. }
  804. char *path = argv[1];
  805. rt_kprintf("unmount %s ... ", path);
  806. if (dfs_unmount(path) < 0)
  807. {
  808. rt_kprintf("failed!\n");
  809. return -1;
  810. } else {
  811. rt_kprintf("succeed!\n");
  812. return 0;
  813. }
  814. }
  815. MSH_CMD_EXPORT(unmount, unmount the mountpoint);
  816. #endif
  817. /*@}*/