dfs.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977
  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 <posix/stdio.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_vnode_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_file_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_file_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_file **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_file **)rt_realloc(fdt->fds, nr * sizeof(struct dfs_file *));
  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_file *fd = NULL;
  190. idx = fd_slot_alloc(fdt, startfd);
  191. /* allocate 'struct dfs_file' */
  192. if (idx < 0)
  193. {
  194. return -1;
  195. }
  196. fd = (struct dfs_file *)rt_calloc(1, sizeof(struct dfs_file));
  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_file_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_file_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_file *fdt_fd_get(struct dfs_fdtable* fdt, int fd)
  244. {
  245. struct dfs_file *d;
  246. if (fd < 0 || fd >= (int)fdt->maxfd)
  247. {
  248. return NULL;
  249. }
  250. dfs_file_lock();
  251. d = fdt->fds[fd];
  252. /* check dfs_file valid or not */
  253. if ((d == NULL) || (d->magic != DFS_FD_MAGIC))
  254. {
  255. dfs_file_unlock();
  256. return NULL;
  257. }
  258. dfs_file_unlock();
  259. return d;
  260. }
  261. struct dfs_file *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_file *fd_slot = NULL;
  275. RT_ASSERT(fdt != NULL);
  276. dfs_file_lock();
  277. if ((fd < 0) || (fd >= fdt->maxfd))
  278. {
  279. dfs_file_unlock();
  280. return;
  281. }
  282. fd_slot = fdt->fds[fd];
  283. if (fd_slot == NULL)
  284. {
  285. dfs_file_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_vnode *vnode = fd_slot->vnode;
  296. if (vnode)
  297. {
  298. vnode->ref_count--;
  299. if(vnode->ref_count == 0)
  300. {
  301. rt_free(vnode);
  302. fd_slot->vnode = RT_NULL;
  303. }
  304. }
  305. rt_free(fd_slot);
  306. }
  307. dfs_file_unlock();
  308. }
  309. void fd_release(int fd)
  310. {
  311. struct dfs_fdtable *fdt;
  312. fdt = dfs_fdtable_get();
  313. fdt_fd_release(fdt, fd);
  314. }
  315. rt_err_t sys_dup(int oldfd)
  316. {
  317. int newfd = -1;
  318. struct dfs_fdtable *fdt = NULL;
  319. dfs_file_lock();
  320. /* check old fd */
  321. fdt = dfs_fdtable_get();
  322. if ((oldfd < 0) || (oldfd >= fdt->maxfd))
  323. {
  324. goto exit;
  325. }
  326. if (!fdt->fds[oldfd])
  327. {
  328. goto exit;
  329. }
  330. /* get a new fd */
  331. newfd = fd_slot_alloc(fdt, DFS_STDIO_OFFSET);
  332. if (newfd >= 0)
  333. {
  334. fdt->fds[newfd] = fdt->fds[oldfd];
  335. /* inc ref_count */
  336. fdt->fds[newfd]->ref_count++;
  337. }
  338. exit:
  339. dfs_file_unlock();
  340. return newfd;
  341. }
  342. #endif /* DFS_USING_POSIX */
  343. /**
  344. * @ingroup Fd
  345. *
  346. * This function will return whether this file has been opend.
  347. *
  348. * @param pathname the file path name.
  349. *
  350. * @return 0 on file has been open successfully, -1 on open failed.
  351. */
  352. int fd_is_open(const char *pathname)
  353. {
  354. char *fullpath;
  355. unsigned int index;
  356. struct dfs_filesystem *fs;
  357. struct dfs_file *fd;
  358. struct dfs_fdtable *fdt;
  359. fdt = dfs_fdtable_get();
  360. fullpath = dfs_normalize_path(NULL, pathname);
  361. if (fullpath != NULL)
  362. {
  363. char *mountpath;
  364. fs = dfs_filesystem_lookup(fullpath);
  365. if (fs == NULL)
  366. {
  367. /* can't find mounted file system */
  368. rt_free(fullpath);
  369. return -1;
  370. }
  371. /* get file path name under mounted file system */
  372. if (fs->path[0] == '/' && fs->path[1] == '\0')
  373. mountpath = fullpath;
  374. else
  375. mountpath = fullpath + strlen(fs->path);
  376. dfs_lock();
  377. for (index = 0; index < fdt->maxfd; index++)
  378. {
  379. fd = fdt->fds[index];
  380. if (fd == NULL || fd->vnode->fops == NULL || fd->vnode->path == NULL) continue;
  381. if (fd->vnode->fs == fs && strcmp(fd->vnode->path, mountpath) == 0)
  382. {
  383. /* found file in file descriptor table */
  384. rt_free(fullpath);
  385. dfs_unlock();
  386. return 0;
  387. }
  388. }
  389. dfs_unlock();
  390. rt_free(fullpath);
  391. }
  392. return -1;
  393. }
  394. rt_err_t sys_dup2(int oldfd, int newfd)
  395. {
  396. struct dfs_fdtable *fdt = NULL;
  397. int ret = 0;
  398. int retfd = -1;
  399. dfs_file_lock();
  400. /* check old fd */
  401. fdt = dfs_fdtable_get();
  402. if ((oldfd < 0) || (oldfd >= fdt->maxfd))
  403. {
  404. goto exit;
  405. }
  406. if (!fdt->fds[oldfd])
  407. {
  408. goto exit;
  409. }
  410. if (newfd < 0)
  411. {
  412. goto exit;
  413. }
  414. if (newfd >= fdt->maxfd)
  415. {
  416. newfd = fd_slot_expand(fdt, newfd);
  417. if (newfd < 0)
  418. {
  419. goto exit;
  420. }
  421. }
  422. if (fdt->fds[newfd] == fdt->fds[oldfd])
  423. {
  424. /* ok, return newfd */
  425. retfd = newfd;
  426. goto exit;
  427. }
  428. if (fdt->fds[newfd])
  429. {
  430. ret = dfs_file_close(fdt->fds[newfd]);
  431. if (ret < 0)
  432. {
  433. goto exit;
  434. }
  435. fd_release(newfd);
  436. }
  437. fdt->fds[newfd] = fdt->fds[oldfd];
  438. /* inc ref_count */
  439. fdt->fds[newfd]->ref_count++;
  440. retfd = newfd;
  441. exit:
  442. dfs_file_unlock();
  443. return retfd;
  444. }
  445. static int fd_get_fd_index_form_fdt(struct dfs_fdtable *fdt, struct dfs_file *file)
  446. {
  447. int fd = -1;
  448. if (file == RT_NULL)
  449. {
  450. return -1;
  451. }
  452. dfs_file_lock();
  453. for(int index = 0; index < (int)fdt->maxfd; index++)
  454. {
  455. if(fdt->fds[index] == file)
  456. {
  457. fd = index;
  458. break;
  459. }
  460. }
  461. dfs_file_unlock();
  462. return fd;
  463. }
  464. int fd_get_fd_index(struct dfs_file *file)
  465. {
  466. struct dfs_fdtable *fdt;
  467. fdt = dfs_fdtable_get();
  468. return fd_get_fd_index_form_fdt(fdt, file);
  469. }
  470. int fd_associate(struct dfs_fdtable *fdt, int fd, struct dfs_file *file)
  471. {
  472. int retfd = -1;
  473. if (!file)
  474. {
  475. return retfd;
  476. }
  477. if (!fdt)
  478. {
  479. return retfd;
  480. }
  481. dfs_file_lock();
  482. /* check old fd */
  483. if ((fd < 0) || (fd >= fdt->maxfd))
  484. {
  485. goto exit;
  486. }
  487. if (fdt->fds[fd])
  488. {
  489. goto exit;
  490. }
  491. /* inc ref_count */
  492. file->ref_count++;
  493. fdt->fds[fd] = file;
  494. retfd = fd;
  495. exit:
  496. dfs_file_unlock();
  497. return retfd;
  498. }
  499. void fd_init(struct dfs_file *fd)
  500. {
  501. if (fd)
  502. {
  503. fd->magic = DFS_FD_MAGIC;
  504. fd->ref_count = 1;
  505. fd->pos = 0;
  506. fd->vnode = NULL;
  507. fd->data = NULL;
  508. }
  509. }
  510. /**
  511. * this function will return a sub-path name under directory.
  512. *
  513. * @param directory the parent directory.
  514. * @param filename the filename.
  515. *
  516. * @return the subdir pointer in filename
  517. */
  518. const char *dfs_subdir(const char *directory, const char *filename)
  519. {
  520. const char *dir;
  521. if (strlen(directory) == strlen(filename)) /* it's a same path */
  522. return NULL;
  523. dir = filename + strlen(directory);
  524. if ((*dir != '/') && (dir != filename))
  525. {
  526. dir --;
  527. }
  528. return dir;
  529. }
  530. RTM_EXPORT(dfs_subdir);
  531. /**
  532. * this function will normalize a path according to specified parent directory
  533. * and file name.
  534. *
  535. * @param directory the parent path
  536. * @param filename the file name
  537. *
  538. * @return the built full file path (absolute path)
  539. */
  540. char *dfs_normalize_path(const char *directory, const char *filename)
  541. {
  542. char *fullpath;
  543. char *dst0, *dst, *src;
  544. /* check parameters */
  545. RT_ASSERT(filename != NULL);
  546. #ifdef DFS_USING_WORKDIR
  547. if (directory == NULL) /* shall use working directory */
  548. {
  549. #ifdef RT_USING_SMART
  550. directory = lwp_getcwd();
  551. #else
  552. directory = &working_directory[0];
  553. #endif
  554. }
  555. #else
  556. if ((directory == NULL) && (filename[0] != '/'))
  557. {
  558. rt_kprintf(NO_WORKING_DIR);
  559. return NULL;
  560. }
  561. #endif
  562. if (filename[0] != '/') /* it's a absolute path, use it directly */
  563. {
  564. fullpath = (char *)rt_malloc(strlen(directory) + strlen(filename) + 2);
  565. if (fullpath == NULL)
  566. return NULL;
  567. /* join path and file name */
  568. rt_snprintf(fullpath, strlen(directory) + strlen(filename) + 2,
  569. "%s/%s", directory, filename);
  570. }
  571. else
  572. {
  573. fullpath = rt_strdup(filename); /* copy string */
  574. if (fullpath == NULL)
  575. return NULL;
  576. }
  577. src = fullpath;
  578. dst = fullpath;
  579. dst0 = dst;
  580. while (1)
  581. {
  582. char c = *src;
  583. if (c == '.')
  584. {
  585. if (!src[1]) src++; /* '.' and ends */
  586. else if (src[1] == '/')
  587. {
  588. /* './' case */
  589. src += 2;
  590. while ((*src == '/') && (*src != '\0'))
  591. src++;
  592. continue;
  593. }
  594. else if (src[1] == '.')
  595. {
  596. if (!src[2])
  597. {
  598. /* '..' and ends case */
  599. src += 2;
  600. goto up_one;
  601. }
  602. else if (src[2] == '/')
  603. {
  604. /* '../' case */
  605. src += 3;
  606. while ((*src == '/') && (*src != '\0'))
  607. src++;
  608. goto up_one;
  609. }
  610. }
  611. }
  612. /* copy up the next '/' and erase all '/' */
  613. while ((c = *src++) != '\0' && c != '/')
  614. *dst++ = c;
  615. if (c == '/')
  616. {
  617. *dst++ = '/';
  618. while (c == '/')
  619. c = *src++;
  620. src--;
  621. }
  622. else if (!c)
  623. break;
  624. continue;
  625. up_one:
  626. /* keep the topmost root directory */
  627. if (dst - dst0 != 1 || dst[-1] != '/')
  628. {
  629. dst--;
  630. if (dst < dst0)
  631. {
  632. rt_free(fullpath);
  633. return NULL;
  634. }
  635. }
  636. while (dst0 < dst && dst[-1] != '/')
  637. dst--;
  638. }
  639. *dst = '\0';
  640. /* remove '/' in the end of path if exist */
  641. dst--;
  642. if (dst > fullpath && (*dst == '/'))
  643. *dst = '\0';
  644. /* final check fullpath is not empty, for the special path of lwext "/.." */
  645. if ('\0' == fullpath[0])
  646. {
  647. fullpath[0] = '/';
  648. fullpath[1] = '\0';
  649. }
  650. return fullpath;
  651. }
  652. RTM_EXPORT(dfs_normalize_path);
  653. /**
  654. * This function will get the file descriptor table of current process.
  655. */
  656. struct dfs_fdtable *dfs_fdtable_get(void)
  657. {
  658. struct dfs_fdtable *fdt;
  659. #ifdef RT_USING_SMART
  660. struct rt_lwp *lwp;
  661. lwp = (struct rt_lwp *)rt_thread_self()->lwp;
  662. if (lwp)
  663. fdt = &lwp->fdt;
  664. else
  665. fdt = &_fdtab;
  666. #else
  667. fdt = &_fdtab;
  668. #endif
  669. return fdt;
  670. }
  671. #ifdef RT_USING_SMART
  672. struct dfs_fdtable *dfs_fdtable_get_pid(int pid)
  673. {
  674. struct rt_lwp *lwp = RT_NULL;
  675. struct dfs_fdtable *fdt = RT_NULL;
  676. lwp_pid_lock_take();
  677. lwp = lwp_from_pid_locked(pid);
  678. if (lwp)
  679. {
  680. fdt = &lwp->fdt;
  681. }
  682. lwp_pid_lock_release();
  683. return fdt;
  684. }
  685. #endif
  686. struct dfs_fdtable *dfs_fdtable_get_global(void)
  687. {
  688. return &_fdtab;
  689. }
  690. #ifdef RT_USING_FINSH
  691. int list_fd(void)
  692. {
  693. int index;
  694. struct dfs_fdtable *fd_table;
  695. fd_table = dfs_fdtable_get();
  696. if (!fd_table) return -1;
  697. dfs_lock();
  698. rt_kprintf("fd type ref magic path\n");
  699. rt_kprintf("-- ------ --- ----- ------\n");
  700. for (index = 0; index < (int)fd_table->maxfd; index++)
  701. {
  702. struct dfs_file *fd = fd_table->fds[index];
  703. if (fd && fd->vnode->fops)
  704. {
  705. rt_kprintf("%2d ", index);
  706. if (fd->vnode->type == FT_DIRECTORY) rt_kprintf("%-7.7s ", "dir");
  707. else if (fd->vnode->type == FT_REGULAR) rt_kprintf("%-7.7s ", "file");
  708. else if (fd->vnode->type == FT_SOCKET) rt_kprintf("%-7.7s ", "socket");
  709. else if (fd->vnode->type == FT_USER) rt_kprintf("%-7.7s ", "user");
  710. else if (fd->vnode->type == FT_DEVICE) rt_kprintf("%-7.7s ", "device");
  711. else rt_kprintf("%-8.8s ", "unknown");
  712. rt_kprintf("%3d ", fd->vnode->ref_count);
  713. rt_kprintf("%04x ", fd->magic);
  714. if (fd->vnode->path)
  715. {
  716. rt_kprintf("%s\n", fd->vnode->path);
  717. }
  718. else
  719. {
  720. rt_kprintf("\n");
  721. }
  722. }
  723. }
  724. dfs_unlock();
  725. return 0;
  726. }
  727. #ifdef RT_USING_SMART
  728. static int lsofp(int pid)
  729. {
  730. int index;
  731. struct dfs_fdtable *fd_table = RT_NULL;
  732. if (pid == (-1))
  733. {
  734. fd_table = dfs_fdtable_get();
  735. if (!fd_table) return -1;
  736. }
  737. else
  738. {
  739. fd_table = dfs_fdtable_get_pid(pid);
  740. if (!fd_table)
  741. {
  742. rt_kprintf("PID %s is not a applet(lwp)\n", pid);
  743. return -1;
  744. }
  745. }
  746. rt_kprintf("--- -- ------ ------ ----- ---------- ---------- ---------- ------\n");
  747. rt_enter_critical();
  748. for (index = 0; index < (int)fd_table->maxfd; index++)
  749. {
  750. struct dfs_file *fd = fd_table->fds[index];
  751. if (fd && fd->vnode->fops)
  752. {
  753. if(pid == (-1))
  754. {
  755. rt_kprintf(" K ");
  756. }
  757. else
  758. {
  759. rt_kprintf("%3d ", pid);
  760. }
  761. rt_kprintf("%2d ", index);
  762. if (fd->vnode->type == FT_DIRECTORY) rt_kprintf("%-7.7s ", "dir");
  763. else if (fd->vnode->type == FT_REGULAR) rt_kprintf("%-7.7s ", "file");
  764. else if (fd->vnode->type == FT_SOCKET) rt_kprintf("%-7.7s ", "socket");
  765. else if (fd->vnode->type == FT_USER) rt_kprintf("%-7.7s ", "user");
  766. else if (fd->vnode->type == FT_DEVICE) rt_kprintf("%-7.7s ", "device");
  767. else rt_kprintf("%-8.8s ", "unknown");
  768. rt_kprintf("%6d ", fd->vnode->ref_count);
  769. rt_kprintf("%04x 0x%.8x ", fd->magic, (int)(size_t)fd->vnode);
  770. if(fd->vnode == RT_NULL)
  771. {
  772. rt_kprintf("0x%.8x 0x%.8x ", (int)0x00000000, (int)(size_t)fd);
  773. }
  774. else
  775. {
  776. rt_kprintf("0x%.8x 0x%.8x ", (int)(size_t)(fd->vnode->data), (int)(size_t)fd);
  777. }
  778. if (fd->vnode->path)
  779. {
  780. rt_kprintf("%s \n", fd->vnode->path);
  781. }
  782. else
  783. {
  784. rt_kprintf("\n");
  785. }
  786. }
  787. }
  788. rt_exit_critical();
  789. return 0;
  790. }
  791. int lsof(int argc, char *argv[])
  792. {
  793. rt_kprintf("PID fd type fd-ref magic vnode vnode/data addr path \n");
  794. if (argc == 1)
  795. {
  796. struct rt_list_node *node, *list;
  797. struct lwp_avl_struct *pids = lwp_get_pid_ary();
  798. lsofp(-1);
  799. for (int index = 0; index < RT_LWP_MAX_NR; index++)
  800. {
  801. struct rt_lwp *lwp = (struct rt_lwp *)pids[index].data;
  802. if (lwp)
  803. {
  804. list = &lwp->t_grp;
  805. for (node = list->next; node != list; node = node->next)
  806. {
  807. lsofp(lwp_to_pid(lwp));
  808. }
  809. }
  810. }
  811. }
  812. else if (argc == 3)
  813. {
  814. if (argv[1][0] == '-' && argv[1][1] == 'p')
  815. {
  816. int pid = atoi(argv[2]);
  817. lsofp(pid);
  818. }
  819. }
  820. return 0;
  821. }
  822. MSH_CMD_EXPORT(lsof, list open files);
  823. #endif /* RT_USING_SMART */
  824. #endif
  825. /**@}*/