fs_skeleton.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. /****************************************************************************
  2. * fs/procfs/fs_skeleton.c
  3. *
  4. * Copyright (C) 2017 Gregory Nutt. All rights reserved.
  5. * Copyright (C) 2015 Ken Pettit. All rights reserved.
  6. * Author: Ken Pettit <pettitkd@gmail.com>
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. * 3. Neither the name NuttX nor the names of its contributors may be
  19. * used to endorse or promote products derived from this software
  20. * without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  25. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  26. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  27. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  28. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  29. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  30. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  32. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33. * POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. ****************************************************************************/
  36. /****************************************************************************
  37. * Included Files
  38. ****************************************************************************/
  39. #include <nuttx/config.h>
  40. #include <sys/types.h>
  41. #include <sys/stat.h>
  42. #include <stdint.h>
  43. #include <stdbool.h>
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. #include <fcntl.h>
  48. #include <assert.h>
  49. #include <errno.h>
  50. #include <debug.h>
  51. #include <nuttx/arch.h>
  52. #include <nuttx/sched.h>
  53. #include <nuttx/kmalloc.h>
  54. #include <nuttx/fs/fs.h>
  55. #include <nuttx/fs/procfs.h>
  56. #include <nuttx/fs/dirent.h>
  57. #include <arch/irq.h>
  58. #if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_PROCFS)
  59. /****************************************************************************
  60. * Pre-processor Definitions
  61. ****************************************************************************/
  62. /****************************************************************************
  63. * Private Types
  64. ****************************************************************************/
  65. /* This enumeration identifies all of the thread attributes that can be
  66. * accessed via the procfs file system.
  67. */
  68. /* This structure describes one open "file" */
  69. struct skel_file_s
  70. {
  71. struct procfs_file_s base; /* Base open file structure */
  72. /* Add context specific data types for managing an open file here */
  73. };
  74. /* Level 1 is the directory of attributes */
  75. struct skel_level1_s
  76. {
  77. struct procfs_dir_priv_s base; /* Base directory private data */
  78. /* Add context specific data types here for managing the directory
  79. * open / read / stat, etc.
  80. */
  81. };
  82. /****************************************************************************
  83. * Private Function Prototypes
  84. ****************************************************************************/
  85. /* File system methods */
  86. static int skel_open(FAR struct file *filep, FAR const char *relpath,
  87. int oflags, mode_t mode);
  88. static int skel_close(FAR struct file *filep);
  89. static ssize_t skel_read(FAR struct file *filep, FAR char *buffer,
  90. size_t buflen);
  91. /* TODO: Should not support skel_write if read-only */
  92. static ssize_t skel_write(FAR struct file *filep, FAR const char *buffer,
  93. size_t buflen);
  94. static int skel_dup(FAR const struct file *oldp,
  95. FAR struct file *newp);
  96. static int skel_opendir(FAR const char *relpath,
  97. FAR struct fs_dirent_s *dir);
  98. static int skel_closedir(FAR struct fs_dirent_s *dir);
  99. static int skel_readdir(FAR struct fs_dirent_s *dir);
  100. static int skel_rewinddir(FAR struct fs_dirent_s *dir);
  101. static int skel_stat(FAR const char *relpath, FAR struct stat *buf);
  102. /****************************************************************************
  103. * Private Data
  104. ****************************************************************************/
  105. /****************************************************************************
  106. * Public Data
  107. ****************************************************************************/
  108. /* See include/nutts/fs/procfs.h
  109. * We use the old-fashioned kind of initializers so that this will compile
  110. * with any compiler.
  111. */
  112. const struct procfs_operations skel_procfsoperations =
  113. {
  114. skel_open, /* open */
  115. skel_close, /* close */
  116. skel_read, /* read */
  117. /* TODO: Decide if this procfs entry supports write access */
  118. #if 0 /* NULL if the procfs entry does not support write access. */
  119. NULL, /* write */
  120. #else
  121. skel_write, /* write */
  122. #endif
  123. skel_dup, /* dup */
  124. skel_opendir, /* opendir */
  125. skel_closedir, /* closedir */
  126. skel_readdir, /* readdir */
  127. skel_rewinddir, /* rewinddir */
  128. skel_stat /* stat */
  129. };
  130. /****************************************************************************
  131. * Private Functions
  132. ****************************************************************************/
  133. /****************************************************************************
  134. * Name: skel_open
  135. ****************************************************************************/
  136. static int skel_open(FAR struct file *filep, FAR const char *relpath,
  137. int oflags, mode_t mode)
  138. {
  139. FAR struct skel_file_s *priv;
  140. finfo("Open '%s'\n", relpath);
  141. /* If PROCFS is read-only, then the (1) the skel_write() method must not
  142. * be provided and (2) any attempt to open with any kind of write access
  143. * can not be permitted.
  144. */
  145. if (((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0) &&
  146. (skel_procfsoperations.write == NULL))
  147. {
  148. ferr("ERROR: Only O_RDONLY supported\n");
  149. return -EACCES;
  150. }
  151. /* Allocate the open file structure */
  152. priv = (FAR struct skel_file_s *)kmm_zalloc(sizeof(struct skel_file_s));
  153. if (!priv)
  154. {
  155. ferr("ERROR: Failed to allocate file attributes\n");
  156. return -ENOMEM;
  157. }
  158. /* TODO: Initialize the context specific data here */
  159. /* Save the open file structure as the open-specific state in
  160. * filep->f_priv.
  161. */
  162. filep->f_priv = (FAR void *)priv;
  163. return OK;
  164. }
  165. /****************************************************************************
  166. * Name: skel_close
  167. ****************************************************************************/
  168. static int skel_close(FAR struct file *filep)
  169. {
  170. FAR struct skel_file_s *priv;
  171. /* Recover our private data from the struct file instance */
  172. priv = (FAR struct skel_file_s *)filep->f_priv;
  173. DEBUGASSERT(priv);
  174. /* Release the file attributes structure */
  175. kmm_free(priv);
  176. filep->f_priv = NULL;
  177. return OK;
  178. }
  179. /****************************************************************************
  180. * Name: skel_read
  181. *
  182. * Description:
  183. * Handle read from procfs file.
  184. *
  185. ****************************************************************************/
  186. static ssize_t skel_read(FAR struct file *filep, FAR char *buffer,
  187. size_t buflen)
  188. {
  189. FAR struct skel_file_s *priv;
  190. ssize_t ret;
  191. finfo("buffer=%p buflen=%d\n", buffer, (int)buflen);
  192. /* Recover our private data from the struct file instance */
  193. priv = (FAR struct skel_file_s *)filep->f_priv;
  194. DEBUGASSERT(priv);
  195. /* TODO: Provide the requested data.
  196. * Take into account current filep->f_pos and 'buflen'. The read
  197. * could require several calls to skel_read().
  198. */
  199. ret = 0;
  200. /* Update the file offset */
  201. if (ret > 0)
  202. {
  203. filep->f_pos += ret;
  204. }
  205. return ret;
  206. }
  207. /****************************************************************************
  208. * Name: skel_write
  209. *
  210. * Description:
  211. * Handle write3 to procfs file.
  212. *
  213. ****************************************************************************/
  214. /* TODO: Should not support skel_write if read-only */
  215. static ssize_t skel_write(FAR struct file *filep, FAR const char *buffer,
  216. size_t buflen)
  217. {
  218. FAR struct skel_file_s *priv;
  219. ssize_t ret;
  220. finfo("buffer=%p buflen=%d\n", buffer, (int)buflen);
  221. /* Recover our private data from the struct file instance */
  222. priv = (FAR struct skel_file_s *)filep->f_priv;
  223. DEBUGASSERT(priv);
  224. /* TODO: Verify that the write is within range */
  225. /* TODO: Handle the write data as appropriate to function of file.
  226. * Take into account current filep->f_pos and 'buflen' since the
  227. * write may require several calls to skel_write().
  228. */
  229. ret = 0;
  230. /* Update the file offset */
  231. if (ret > 0)
  232. {
  233. filep->f_pos += ret;
  234. }
  235. return ret;
  236. }
  237. /****************************************************************************
  238. * Name: skel_dup
  239. *
  240. * Description:
  241. * Duplicate open file data in the new file structure.
  242. *
  243. ****************************************************************************/
  244. static int skel_dup(FAR const struct file *oldp, FAR struct file *newp)
  245. {
  246. FAR struct skel_file_s *oldpriv;
  247. FAR struct skel_file_s *newpriv;
  248. finfo("Dup %p->%p\n", oldp, newp);
  249. /* Recover our private data from the old struct file instance */
  250. oldpriv = (FAR struct skel_file_s *)oldp->f_priv;
  251. DEBUGASSERT(oldpriv);
  252. /* Allocate a new container to hold the task and attribute selection */
  253. newpriv = (FAR struct skel_file_s *)kmm_zalloc(sizeof(struct skel_file_s));
  254. if (!newpriv)
  255. {
  256. ferr("ERROR: Failed to allocate file attributes\n");
  257. return -ENOMEM;
  258. }
  259. /* The copy the file attribute from the old attributes to the new */
  260. memcpy(newpriv, oldpriv, sizeof(struct skel_file_s));
  261. /* Save the new attributes in the new file structure */
  262. newp->f_priv = (FAR void *)newpriv;
  263. return OK;
  264. }
  265. /****************************************************************************
  266. * Name: skel_opendir
  267. *
  268. * Description:
  269. * Open a directory for read access
  270. *
  271. ****************************************************************************/
  272. static int skel_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
  273. {
  274. FAR struct skel_level1_s *level1;
  275. finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
  276. DEBUGASSERT(relpath && dir && !dir->u.procfs);
  277. /* The path refers to the 1st level sbdirectory. Allocate the level1
  278. * dirent structure.
  279. */
  280. level1 = (FAR struct skel_level1_s *)
  281. kmm_zalloc(sizeof(struct skel_level1_s));
  282. if (!level1)
  283. {
  284. ferr("ERROR: Failed to allocate the level1 directory structure\n");
  285. return -ENOMEM;
  286. }
  287. /* TODO: Initialize context specific data */
  288. /* Initialize base structure components */
  289. level1->base.level = 1;
  290. level1->base.nentries = 0;
  291. level1->base.index = 0;
  292. dir->u.procfs = (FAR void *) level1;
  293. return OK;
  294. }
  295. /****************************************************************************
  296. * Name: skel_closedir
  297. *
  298. * Description: Close the directory listing
  299. *
  300. ****************************************************************************/
  301. static int skel_closedir(FAR struct fs_dirent_s *dir)
  302. {
  303. FAR struct skel_level1_s *priv;
  304. DEBUGASSERT(dir && dir->u.procfs);
  305. priv = dir->u.procfs;
  306. if (priv)
  307. {
  308. kmm_free(priv);
  309. }
  310. dir->u.procfs = NULL;
  311. return OK;
  312. }
  313. /****************************************************************************
  314. * Name: skel_readdir
  315. *
  316. * Description: Read the next directory entry
  317. *
  318. ****************************************************************************/
  319. static int skel_readdir(FAR struct fs_dirent_s *dir)
  320. {
  321. FAR struct skel_level1_s *level1;
  322. char filename[16];
  323. int index;
  324. int ret;
  325. DEBUGASSERT(dir && dir->u.procfs);
  326. level1 = dir->u.procfs;
  327. /* TODO: Perform device specific readdir function here. This may
  328. * or may not involve validating the nentries variable
  329. * in the base depending on the implementation.
  330. */
  331. /* Have we reached the end of the directory */
  332. index = level1->base.index;
  333. if (index >= level1->base.nentries)
  334. {
  335. /* We signal the end of the directory by returning the special
  336. * error -ENOENT
  337. */
  338. finfo("Entry %d: End of directory\n", index);
  339. ret = -ENOENT;
  340. }
  341. /* We are traversing a subdirectory of task attributes */
  342. else
  343. {
  344. DEBUGASSERT(level1->base.level == 1);
  345. /* TODO: Add device specific entries */
  346. strcpy(filename, "dummy");
  347. /* TODO: Specify the type of entry */
  348. dir->fd_dir.d_type = DTYPE_FILE;
  349. strncpy(dir->fd_dir.d_name, filename, NAME_MAX + 1);
  350. /* Set up the next directory entry offset. NOTE that we could use the
  351. * standard f_pos instead of our own private index.
  352. */
  353. level1->base.index = index + 1;
  354. ret = OK;
  355. }
  356. return ret;
  357. }
  358. /****************************************************************************
  359. * Name: skel_rewindir
  360. *
  361. * Description: Reset directory read to the first entry
  362. *
  363. ****************************************************************************/
  364. static int skel_rewinddir(FAR struct fs_dirent_s *dir)
  365. {
  366. FAR struct skel_level1_s *priv;
  367. DEBUGASSERT(dir && dir->u.procfs);
  368. priv = dir->u.procfs;
  369. priv->base.index = 0;
  370. return OK;
  371. }
  372. /****************************************************************************
  373. * Name: skel_stat
  374. *
  375. * Description: Return information about a file or directory
  376. *
  377. ****************************************************************************/
  378. static int skel_stat(FAR const char *relpath, FAR struct stat *buf)
  379. {
  380. int ret = -ENOENT;
  381. /* TODO: Decide if the relpath is valid and if it is a file
  382. * or a directory and set it's permissions.
  383. */
  384. memset(buf, 0, sizeof(struct stat));
  385. buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR;
  386. /* TODO: Set S_IFREG if the relpath refers to a file.
  387. * TODO: If the skel_write() method is supported, then stat must also
  388. * report S_IWOTH | S_IWGRP | S_IWUSR for files (but not for
  389. * directories) as well.
  390. * TODO: Other 'struct buf' settings may be appropriate (optional)
  391. */
  392. ret = OK;
  393. return ret;
  394. }
  395. /****************************************************************************
  396. * Public Functions
  397. ****************************************************************************/
  398. #endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS */