dfs.c 20 KB

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