dfs.c 20 KB

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