fs_skeleton.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  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/statfs.h>
  42. #include <sys/stat.h>
  43. #include <stdint.h>
  44. #include <stdbool.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <fcntl.h>
  49. #include <assert.h>
  50. #include <errno.h>
  51. #include <debug.h>
  52. #include <nuttx/arch.h>
  53. #include <nuttx/sched.h>
  54. #include <nuttx/kmalloc.h>
  55. #include <nuttx/fs/fs.h>
  56. #include <nuttx/fs/procfs.h>
  57. #include <nuttx/fs/dirent.h>
  58. #include <arch/irq.h>
  59. #if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_PROCFS)
  60. /****************************************************************************
  61. * Pre-processor Definitions
  62. ****************************************************************************/
  63. /****************************************************************************
  64. * Private Types
  65. ****************************************************************************/
  66. /* This enumeration identifies all of the thread attributes that can be
  67. * accessed via the procfs file system.
  68. */
  69. /* This structure describes one open "file" */
  70. struct skel_file_s
  71. {
  72. struct procfs_file_s base; /* Base open file structure */
  73. /* Add context specific data types for managing an open file here */
  74. };
  75. /* Level 1 is the directory of attributes */
  76. struct skel_level1_s
  77. {
  78. struct procfs_dir_priv_s base; /* Base directory private data */
  79. /* Add context specific data types here for managing the directory
  80. * open / read / stat, etc.
  81. */
  82. };
  83. /****************************************************************************
  84. * Private Function Prototypes
  85. ****************************************************************************/
  86. /* File system methods */
  87. static int skel_open(FAR struct file *filep, FAR const char *relpath,
  88. int oflags, mode_t mode);
  89. static int skel_close(FAR struct file *filep);
  90. static ssize_t skel_read(FAR struct file *filep, FAR char *buffer,
  91. size_t buflen);
  92. /* TODO: Should not support skel_write if read-only */
  93. static ssize_t skel_write(FAR struct file *filep, FAR const char *buffer,
  94. size_t buflen);
  95. static int skel_dup(FAR const struct file *oldp,
  96. FAR struct file *newp);
  97. static int skel_opendir(FAR const char *relpath,
  98. FAR struct fs_dirent_s *dir);
  99. static int skel_closedir(FAR struct fs_dirent_s *dir);
  100. static int skel_readdir(FAR struct fs_dirent_s *dir);
  101. static int skel_rewinddir(FAR struct fs_dirent_s *dir);
  102. static int skel_stat(FAR const char *relpath, FAR struct stat *buf);
  103. /****************************************************************************
  104. * Private Data
  105. ****************************************************************************/
  106. /****************************************************************************
  107. * Public Data
  108. ****************************************************************************/
  109. /* See include/nutts/fs/procfs.h
  110. * We use the old-fashioned kind of initializers so that this will compile
  111. * with any compiler.
  112. */
  113. const struct procfs_operations skel_procfsoperations =
  114. {
  115. skel_open, /* open */
  116. skel_close, /* close */
  117. skel_read, /* read */
  118. /* TODO: Decide if this procfs entry supports write access */
  119. #if 0 /* NULL if the procfs entry does not support write access. */
  120. NULL, /* write */
  121. #else
  122. skel_write, /* write */
  123. #endif
  124. skel_dup, /* dup */
  125. skel_opendir, /* opendir */
  126. skel_closedir, /* closedir */
  127. skel_readdir, /* readdir */
  128. skel_rewinddir, /* rewinddir */
  129. skel_stat /* stat */
  130. };
  131. /****************************************************************************
  132. * Private Functions
  133. ****************************************************************************/
  134. /****************************************************************************
  135. * Name: skel_open
  136. ****************************************************************************/
  137. static int skel_open(FAR struct file *filep, FAR const char *relpath,
  138. int oflags, mode_t mode)
  139. {
  140. FAR struct skel_file_s *priv;
  141. finfo("Open '%s'\n", relpath);
  142. /* If PROCFS is read-only, then the (1) the skel_write() method must not
  143. * be provided and (2) any attempt to open with any kind of write access
  144. * can not be permitted.
  145. */
  146. if (((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0) &&
  147. (skel_procfsoperations.write == NULL))
  148. {
  149. ferr("ERROR: Only O_RDONLY supported\n");
  150. return -EACCES;
  151. }
  152. /* Allocate the open file structure */
  153. priv = (FAR struct skel_file_s *)kmm_zalloc(sizeof(struct skel_file_s));
  154. if (!priv)
  155. {
  156. ferr("ERROR: Failed to allocate file attributes\n");
  157. return -ENOMEM;
  158. }
  159. /* TODO: Initialize the context specific data here */
  160. /* Save the open file structure as the open-specific state in
  161. * filep->f_priv.
  162. */
  163. filep->f_priv = (FAR void *)priv;
  164. return OK;
  165. }
  166. /****************************************************************************
  167. * Name: skel_close
  168. ****************************************************************************/
  169. static int skel_close(FAR struct file *filep)
  170. {
  171. FAR struct skel_file_s *priv;
  172. /* Recover our private data from the struct file instance */
  173. priv = (FAR struct skel_file_s *)filep->f_priv;
  174. DEBUGASSERT(priv);
  175. /* Release the file attributes structure */
  176. kmm_free(priv);
  177. filep->f_priv = NULL;
  178. return OK;
  179. }
  180. /****************************************************************************
  181. * Name: skel_read
  182. *
  183. * Description:
  184. * Handle read from procfs file.
  185. *
  186. ****************************************************************************/
  187. static ssize_t skel_read(FAR struct file *filep, FAR char *buffer,
  188. size_t buflen)
  189. {
  190. FAR struct skel_file_s *priv;
  191. ssize_t ret;
  192. finfo("buffer=%p buflen=%d\n", buffer, (int)buflen);
  193. /* Recover our private data from the struct file instance */
  194. priv = (FAR struct skel_file_s *)filep->f_priv;
  195. DEBUGASSERT(priv);
  196. /* TODO: Provide the requested data.
  197. * Take into account current filep->f_pos and 'buflen'. The read
  198. * could require several calls to skel_read().
  199. */
  200. ret = 0;
  201. /* Update the file offset */
  202. if (ret > 0)
  203. {
  204. filep->f_pos += ret;
  205. }
  206. return ret;
  207. }
  208. /****************************************************************************
  209. * Name: skel_write
  210. *
  211. * Description:
  212. * Handle write3 to procfs file.
  213. *
  214. ****************************************************************************/
  215. /* TODO: Should not support skel_write if read-only */
  216. static ssize_t skel_write(FAR struct file *filep, FAR const char *buffer,
  217. size_t buflen)
  218. {
  219. FAR struct skel_file_s *priv;
  220. ssize_t ret;
  221. finfo("buffer=%p buflen=%d\n", buffer, (int)buflen);
  222. /* Recover our private data from the struct file instance */
  223. priv = (FAR struct skel_file_s *)filep->f_priv;
  224. DEBUGASSERT(priv);
  225. /* TODO: Verify that the write is within range */
  226. /* TODO: Handle the write data as appropriate to function of file.
  227. * Take into account current filep->f_pos and 'buflen' since the
  228. * write may require several calls to skel_write().
  229. */
  230. ret = 0;
  231. /* Update the file offset */
  232. if (ret > 0)
  233. {
  234. filep->f_pos += ret;
  235. }
  236. return ret;
  237. }
  238. /****************************************************************************
  239. * Name: skel_dup
  240. *
  241. * Description:
  242. * Duplicate open file data in the new file structure.
  243. *
  244. ****************************************************************************/
  245. static int skel_dup(FAR const struct file *oldp, FAR struct file *newp)
  246. {
  247. FAR struct skel_file_s *oldpriv;
  248. FAR struct skel_file_s *newpriv;
  249. finfo("Dup %p->%p\n", oldp, newp);
  250. /* Recover our private data from the old struct file instance */
  251. oldpriv = (FAR struct skel_file_s *)oldp->f_priv;
  252. DEBUGASSERT(oldpriv);
  253. /* Allocate a new container to hold the task and attribute selection */
  254. newpriv = (FAR struct skel_file_s *)kmm_zalloc(sizeof(struct skel_file_s));
  255. if (!newpriv)
  256. {
  257. ferr("ERROR: Failed to allocate file attributes\n");
  258. return -ENOMEM;
  259. }
  260. /* The copy the file attribtes from the old attributes to the new */
  261. memcpy(newpriv, oldpriv, sizeof(struct skel_file_s));
  262. /* Save the new attributes in the new file structure */
  263. newp->f_priv = (FAR void *)newpriv;
  264. return OK;
  265. }
  266. /****************************************************************************
  267. * Name: skel_opendir
  268. *
  269. * Description:
  270. * Open a directory for read access
  271. *
  272. ****************************************************************************/
  273. static int skel_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
  274. {
  275. FAR struct skel_level1_s *level1;
  276. finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
  277. DEBUGASSERT(relpath && dir && !dir->u.procfs);
  278. /* The path refers to the 1st level sbdirectory. Allocate the level1
  279. * dirent structure.
  280. */
  281. level1 = (FAR struct skel_level1_s *)
  282. kmm_zalloc(sizeof(struct skel_level1_s));
  283. if (!level1)
  284. {
  285. ferr("ERROR: Failed to allocate the level1 directory structure\n");
  286. return -ENOMEM;
  287. }
  288. /* TODO: Initialize context specific data */
  289. /* Initialze base structure components */
  290. level1->base.level = 1;
  291. level1->base.nentries = 0;
  292. level1->base.index = 0;
  293. dir->u.procfs = (FAR void *) level1;
  294. return OK;
  295. }
  296. /****************************************************************************
  297. * Name: skel_closedir
  298. *
  299. * Description: Close the directory listing
  300. *
  301. ****************************************************************************/
  302. static int skel_closedir(FAR struct fs_dirent_s *dir)
  303. {
  304. FAR struct skel_level1_s *priv;
  305. DEBUGASSERT(dir && dir->u.procfs);
  306. priv = dir->u.procfs;
  307. if (priv)
  308. {
  309. kmm_free(priv);
  310. }
  311. dir->u.procfs = NULL;
  312. return OK;
  313. }
  314. /****************************************************************************
  315. * Name: skel_readdir
  316. *
  317. * Description: Read the next directory entry
  318. *
  319. ****************************************************************************/
  320. static int skel_readdir(FAR struct fs_dirent_s *dir)
  321. {
  322. FAR struct skel_level1_s *level1;
  323. char filename[16];
  324. int index;
  325. int ret;
  326. DEBUGASSERT(dir && dir->u.procfs);
  327. level1 = dir->u.procfs;
  328. /* TODO: Perform device specific readdir function here. This may
  329. * or may not involve validating the nentries variable
  330. * in the base depending on the implementation.
  331. */
  332. /* Have we reached the end of the directory */
  333. index = level1->base.index;
  334. if (index >= level1->base.nentries)
  335. {
  336. /* We signal the end of the directory by returning the special
  337. * error -ENOENT
  338. */
  339. finfo("Entry %d: End of directory\n", index);
  340. ret = -ENOENT;
  341. }
  342. /* We are tranversing a subdirectory of task attributes */
  343. else
  344. {
  345. DEBUGASSERT(level1->base.level == 1);
  346. /* TODO: Add device specific entries */
  347. strcpy(filename, "dummy");
  348. /* TODO: Specify the type of entry */
  349. dir->fd_dir.d_type = DTYPE_FILE;
  350. strncpy(dir->fd_dir.d_name, filename, NAME_MAX + 1);
  351. /* Set up the next directory entry offset. NOTE that we could use the
  352. * standard f_pos instead of our own private index.
  353. */
  354. level1->base.index = index + 1;
  355. ret = OK;
  356. }
  357. return ret;
  358. }
  359. /****************************************************************************
  360. * Name: skel_rewindir
  361. *
  362. * Description: Reset directory read to the first entry
  363. *
  364. ****************************************************************************/
  365. static int skel_rewinddir(FAR struct fs_dirent_s *dir)
  366. {
  367. FAR struct skel_level1_s *priv;
  368. DEBUGASSERT(dir && dir->u.procfs);
  369. priv = dir->u.procfs;
  370. priv->base.index = 0;
  371. return OK;
  372. }
  373. /****************************************************************************
  374. * Name: skel_stat
  375. *
  376. * Description: Return information about a file or directory
  377. *
  378. ****************************************************************************/
  379. static int skel_stat(FAR const char *relpath, FAR struct stat *buf)
  380. {
  381. int ret = -ENOENT;
  382. /* TODO: Decide if the relpath is valid and if it is a file
  383. * or a directory and set it's permissions.
  384. */
  385. memset(buf, 0, sizeof(struct stat));
  386. buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR;
  387. /* TODO: Set S_IFREG if the relpath refers to a file.
  388. /* TODO: If the skel_write() method is supported, then stat must also
  389. * report S_IWOTH | S_IWGRP | S_IWUSR for files (but not for
  390. * directories) as well.
  391. /* TODO: Other 'struct buf' settings may be appropriate (optional) */
  392. ret = OK;
  393. return ret;
  394. }
  395. /****************************************************************************
  396. * Public Functions
  397. ****************************************************************************/
  398. #endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS */