procfs.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. */
  9. #include <rthw.h>
  10. #include <rtdbg.h>
  11. #include <fcntl.h>
  12. #include <errno.h>
  13. #include <dfs.h>
  14. #include <dfs_fs.h>
  15. #include <dfs_file.h>
  16. #include <dfs_posix.h>
  17. #include <dfs_mnt.h>
  18. #include <dfs_dentry.h>
  19. #include "proc.h"
  20. #include "procfs.h"
  21. #define PROC_DEBUG(...) //rt_kprintf
  22. static int dfs_procfs_open(struct dfs_file *file)
  23. {
  24. rt_err_t ret = RT_EOK;
  25. struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
  26. RT_ASSERT(file->ref_count > 0);
  27. // this file is opened and in an fdtable
  28. if (file->ref_count > 1)
  29. {
  30. file->fpos = 0;
  31. return ret;
  32. }
  33. if (entry->fops && entry->fops->open)
  34. {
  35. ret = entry->fops->open(file);
  36. }
  37. PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, file->dentry->pathname, ret);
  38. return ret;
  39. }
  40. static int dfs_procfs_close(struct dfs_file *file)
  41. {
  42. rt_err_t ret = RT_EOK;
  43. struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
  44. RT_ASSERT(file->vnode->ref_count > 0);
  45. if (file->vnode->ref_count > 1)
  46. {
  47. return ret;
  48. }
  49. if (entry && entry->fops && entry->fops->close)
  50. {
  51. ret = entry->fops->close(file);
  52. }
  53. PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, file->dentry->pathname, ret);
  54. return ret;
  55. }
  56. static ssize_t dfs_procfs_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
  57. {
  58. ssize_t ret = -RT_ERROR;
  59. struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
  60. if (entry && entry->fops && entry->fops->read)
  61. {
  62. ret = entry->fops->read(file, buf, count, pos);
  63. }
  64. PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, file->dentry->pathname, ret);
  65. return ret;
  66. }
  67. static ssize_t dfs_procfs_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos)
  68. {
  69. ssize_t ret = -RT_ERROR;
  70. struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
  71. if (entry && entry->fops && entry->fops->write)
  72. {
  73. ret = entry->fops->write(file, buf, count, pos);
  74. }
  75. PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, file->dentry->pathname, ret);
  76. return ret;
  77. }
  78. static int dfs_procfs_ioctl(struct dfs_file *file, int cmd, void *args)
  79. {
  80. int ret = -RT_ERROR;
  81. struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
  82. if (entry && entry->fops && entry->fops->ioctl)
  83. {
  84. ret = entry->fops->ioctl(file, cmd, args);
  85. }
  86. PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, file->dentry->pathname, ret);
  87. return ret;
  88. }
  89. static int dfs_procfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
  90. {
  91. int ret = 0;
  92. rt_uint32_t index = 0;
  93. struct dirent *d;
  94. struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
  95. if (entry)
  96. {
  97. struct proc_dentry *iter = RT_NULL, *tmp;
  98. /* make integer count */
  99. count = (count / sizeof(struct dirent));
  100. if (count == 0)
  101. {
  102. return -EINVAL;
  103. }
  104. dfs_vfs_for_each_subnode(iter, tmp, entry, node)
  105. {
  106. if (iter == RT_NULL)
  107. {
  108. break;
  109. }
  110. if (index >= file->fpos)
  111. {
  112. d = dirp + index - file->fpos;
  113. if (S_ISDIR(entry->mode))
  114. {
  115. d->d_type = DT_DIR;
  116. }
  117. else if (S_ISLNK(entry->mode))
  118. {
  119. d->d_type = DT_SYMLINK;
  120. }
  121. else
  122. {
  123. d->d_type = DT_REG;
  124. }
  125. d->d_namlen = rt_strlen(iter->name);
  126. d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
  127. rt_strncpy(d->d_name, iter->name, rt_strlen(iter->name) + 1);
  128. ret ++;
  129. }
  130. index++;
  131. if (index - file->fpos >= count)
  132. {
  133. break;
  134. }
  135. }
  136. if (ret > 0)
  137. {
  138. file->fpos = index;
  139. }
  140. if (entry->fops && entry->fops->getdents && ret < count)
  141. {
  142. int r;
  143. file->fpos -= index;
  144. r = entry->fops->getdents(file, dirp + ret, (count - ret) * sizeof(struct dirent));
  145. ret = ret * sizeof(struct dirent);
  146. if (r > 0)
  147. {
  148. ret += r;
  149. }
  150. file->fpos += index;
  151. }
  152. else
  153. {
  154. ret = ret * sizeof(struct dirent);
  155. }
  156. }
  157. PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, file->dentry->pathname, ret);
  158. return ret;
  159. }
  160. static int dfs_procfs_poll(struct dfs_file *file, struct rt_pollreq *req)
  161. {
  162. int ret = -RT_ERROR;
  163. struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
  164. if (entry && entry->fops && entry->fops->poll)
  165. {
  166. ret = entry->fops->poll(file, req);
  167. }
  168. PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, file->dentry->pathname, ret);
  169. return ret;
  170. }
  171. static int dfs_procfs_flush(struct dfs_file *file)
  172. {
  173. int ret = -RT_ERROR;
  174. struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
  175. if (entry && entry->fops && entry->fops->flush)
  176. {
  177. ret = entry->fops->flush(file);
  178. }
  179. PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, file->dentry->pathname, ret);
  180. return ret;
  181. }
  182. static int dfs_procfs_mount(struct dfs_mnt *mnt, unsigned long rwflag, const void *data)
  183. {
  184. RT_ASSERT(mnt != RT_NULL);
  185. return RT_EOK;
  186. }
  187. static int dfs_procfs_umount(struct dfs_mnt *mnt)
  188. {
  189. RT_ASSERT(mnt != RT_NULL);
  190. return RT_EOK;
  191. }
  192. static int dfs_procfs_readlink(struct dfs_dentry *dentry, char *buf, int len)
  193. {
  194. int ret = 0;
  195. struct proc_dentry *entry = dfs_proc_find(dentry->pathname);
  196. if (entry)
  197. {
  198. if (S_ISLNK(entry->mode) && entry->data)
  199. {
  200. if (entry->ops && entry->ops->readlink)
  201. {
  202. ret = entry->ops->readlink(entry, buf, len);
  203. }
  204. else
  205. {
  206. rt_strncpy(buf, (const char *)entry->data, len);
  207. buf[len - 1] = '\0';
  208. ret = rt_strlen(buf);
  209. }
  210. }
  211. proc_release(entry);
  212. }
  213. PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, dentry->pathname, ret);
  214. return ret;
  215. }
  216. static int dfs_procfs_unlink(struct dfs_dentry *dentry)
  217. {
  218. PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, dentry->pathname, -1);
  219. return -RT_ERROR;
  220. }
  221. static int dfs_procfs_stat(struct dfs_dentry *dentry, struct stat *st)
  222. {
  223. int ret = RT_EOK;
  224. struct dfs_vnode *vnode;
  225. if (dentry && dentry->vnode)
  226. {
  227. vnode = dentry->vnode;
  228. st->st_dev = (dev_t)(dentry->mnt->dev_id);
  229. st->st_ino = (ino_t)dfs_dentry_full_path_crc32(dentry);
  230. st->st_gid = vnode->gid;
  231. st->st_uid = vnode->uid;
  232. st->st_mode = vnode->mode;
  233. st->st_nlink = vnode->nlink;
  234. st->st_size = vnode->size;
  235. st->st_mtim.tv_nsec = vnode->mtime.tv_nsec;
  236. st->st_mtim.tv_sec = vnode->mtime.tv_sec;
  237. st->st_ctim.tv_nsec = vnode->ctime.tv_nsec;
  238. st->st_ctim.tv_sec = vnode->ctime.tv_sec;
  239. st->st_atim.tv_nsec = vnode->atime.tv_nsec;
  240. st->st_atim.tv_sec = vnode->atime.tv_sec;
  241. }
  242. PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, dentry->pathname, ret);
  243. return ret;
  244. }
  245. static int dfs_procfs_statfs(struct dfs_mnt *mnt, struct statfs *buf)
  246. {
  247. if (mnt && buf)
  248. {
  249. buf->f_bsize = 512;
  250. buf->f_blocks = 2048 * 64; // 64M
  251. buf->f_bfree = buf->f_blocks;
  252. buf->f_bavail = buf->f_bfree;
  253. }
  254. PROC_DEBUG(" %s %d\n", __func__, __LINE__);
  255. return RT_EOK;
  256. }
  257. static struct dfs_vnode *dfs_procfs_lookup(struct dfs_dentry *dentry)
  258. {
  259. struct dfs_vnode *vnode = RT_NULL;
  260. struct proc_dentry *entry = dfs_proc_find(dentry->pathname);
  261. if (entry)
  262. {
  263. vnode = dfs_vnode_create();
  264. if (vnode)
  265. {
  266. vnode->nlink = 1;
  267. vnode->size = 0;
  268. if (S_ISDIR(entry->mode))
  269. {
  270. vnode->mode = entry->mode;
  271. vnode->type = FT_DIRECTORY;
  272. }
  273. else if (S_ISLNK(entry->mode))
  274. {
  275. vnode->mode = entry->mode;
  276. vnode->type = FT_SYMLINK;
  277. }
  278. else
  279. {
  280. vnode->mode = entry->mode;
  281. vnode->type = FT_REGULAR;
  282. }
  283. vnode->data = entry;
  284. vnode->mnt = dentry->mnt;
  285. }
  286. proc_release(entry);
  287. }
  288. PROC_DEBUG(" %s %d >> %s\n", __func__, __LINE__, dentry->pathname);
  289. return vnode;
  290. }
  291. static struct dfs_vnode *dfs_procfs_create_vnode(struct dfs_dentry *dentry, int type, mode_t mode)
  292. {
  293. return RT_NULL;
  294. }
  295. static int dfs_procfs_free_vnode(struct dfs_vnode *vnode)
  296. {
  297. return 0;
  298. }
  299. static const struct dfs_file_ops _procfs_fops =
  300. {
  301. .open = dfs_procfs_open,
  302. .close = dfs_procfs_close,
  303. .lseek = generic_dfs_lseek,
  304. .read = dfs_procfs_read,
  305. .write = dfs_procfs_write,
  306. .ioctl = dfs_procfs_ioctl,
  307. .getdents = dfs_procfs_getdents,
  308. .poll = dfs_procfs_poll,
  309. .flush = dfs_procfs_flush,
  310. };
  311. static const struct dfs_filesystem_ops _procfs_ops =
  312. {
  313. .name = "procfs",
  314. .default_fops = &_procfs_fops,
  315. .mount = dfs_procfs_mount,
  316. .umount = dfs_procfs_umount,
  317. .readlink = dfs_procfs_readlink,
  318. .unlink = dfs_procfs_unlink,
  319. .stat = dfs_procfs_stat,
  320. .statfs = dfs_procfs_statfs,
  321. .lookup = dfs_procfs_lookup,
  322. .create_vnode = dfs_procfs_create_vnode,
  323. .free_vnode = dfs_procfs_free_vnode,
  324. };
  325. static struct dfs_filesystem_type _procfs =
  326. {
  327. .fs_ops = &_procfs_ops,
  328. };
  329. int dfs_procfs_init(void)
  330. {
  331. /* register procfs file system */
  332. dfs_register(&_procfs);
  333. return 0;
  334. }
  335. INIT_COMPONENT_EXPORT(dfs_procfs_init);
  336. int proc_read_data(struct dfs_file *file, void *buf, size_t count, off_t *pos)
  337. {
  338. if (file->fpos >= file->vnode->size)
  339. {
  340. return 0;
  341. }
  342. if (file->data)
  343. {
  344. count = file->vnode->size - file->fpos >= count ? count : file->vnode->size - file->fpos;
  345. rt_strncpy(buf, file->data + file->fpos, count);
  346. file->fpos += count;
  347. *pos = file->fpos;
  348. }
  349. else
  350. {
  351. return 0;
  352. }
  353. return count;
  354. }