pkarashchenko commented on code in PR #9929:
URL: https://github.com/apache/nuttx/pull/9929#discussion_r1277643965


##########
include/nuttx/fs/fs.h:
##########
@@ -405,6 +405,7 @@ struct inode
   uint16_t          i_flags;    /* Flags for inode */
   union inode_ops_u u;          /* Inode operations */
   ino_t             i_ino;      /* Inode serial number */
+  size_t            i_size;     /* The size of per inode driver */

Review Comment:
   Maybe we can have private in `struct fs_pseudofile_s`?



##########
fs/vfs/fs_pseudofile.c:
##########
@@ -0,0 +1,468 @@
+/****************************************************************************
+ * fs/vfs/fs_pseudofile.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <sys/param.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/fs/ioctl.h>
+#include <nuttx/lib/math32.h>
+
+#include "inode/inode.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct fs_pseudofile_s
+{
+  mutex_t lock;
+  uint8_t crefs;
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  bool unlinked;
+#endif
+  FAR char *content;
+};
+
+/****************************************************************************
+ * Private Functions Prototypes
+ ****************************************************************************/
+
+static int     pseudofile_open(FAR struct file *filep);
+static int     pseudofile_close(FAR struct file *filep);
+static ssize_t pseudofile_write(FAR struct file *filep,
+                                FAR const char *buffer, size_t buflen);
+static ssize_t pseudofile_read(FAR struct file *filep, FAR char *buffer,
+                               size_t buflen);
+static off_t   pseudofile_seek(FAR struct file *filep, off_t offset,
+                               int whence);
+static int     pseudofile_mmap(FAR struct file *filep,
+                               FAR struct mm_map_entry_s *map);
+static int     pseudofile_truncate(FAR struct file *filep, off_t length);
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+static int     pseudofile_unlink(FAR struct inode *inode);
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_pseudofile_ops =
+{
+  pseudofile_open,     /* open */
+  pseudofile_close,    /* close */
+  pseudofile_read,     /* read */
+  pseudofile_write,    /* write */
+  pseudofile_seek,     /* seek */
+  NULL,                /* ioctl */
+  pseudofile_mmap,     /* mmap */
+  pseudofile_truncate, /* truncate */
+  NULL,                /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  pseudofile_unlink,   /* unlink */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int pseudofile_open(FAR struct file *filep)
+{
+  FAR struct inode *node = filep->f_inode;
+  FAR struct fs_pseudofile_s *pf = node->i_private;
+  int ret;
+
+  ret = nxmutex_lock(&pf->lock);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  if (pf->crefs >= 255)
+    {
+      ret = -EMFILE;
+    }
+  else
+    {
+      pf->crefs += 1;
+      ret = OK;
+    }
+
+#ifdef CONFIG_PSEUDOFS_ATTRIBUTES
+  node->i_atime.tv_sec = time(NULL);
+#endif
+  nxmutex_unlock(&pf->lock);
+  return ret;
+}
+
+static void pseudofile_remove(FAR struct fs_pseudofile_s *pf)
+{
+  nxmutex_unlock(&pf->lock);
+  nxmutex_destroy(&pf->lock);
+  kmm_free(pf->content);
+  kmm_free(pf);
+}
+
+static int pseudofile_close(FAR struct file *filep)
+{
+  FAR struct inode *node = filep->f_inode;
+  FAR struct fs_pseudofile_s *pf = node->i_private;
+  int ret;
+
+  ret = nxmutex_lock(&pf->lock);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  pf->crefs--;
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  if (pf->crefs <= 0 && pf->unlinked)
+#else
+  if (pf->crefs <= 0)
+#endif
+    {
+      pseudofile_remove(pf);
+      return OK;
+    }
+
+  nxmutex_unlock(&pf->lock);
+  return OK;
+}
+
+static int pseudofile_expand(FAR struct inode *node,
+                             size_t size)
+{
+  FAR struct fs_pseudofile_s *pf = node->i_private;
+  FAR void *tmp;
+
+  if (pf->content && kmm_malloc_size(pf->content) >= size)
+    {
+      node->i_size = size;
+      return 0;
+    }
+
+  tmp = kmm_realloc(pf->content, 1 << LOG2_CEIL(size));
+  if (tmp == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  pf->content = tmp;
+  node->i_size = size;
+  return 0;
+}
+
+static ssize_t pseudofile_write(FAR struct file *filep,
+                                FAR const char *buffer, size_t buflen)
+{
+  FAR struct inode *node = filep->f_inode;
+  FAR struct fs_pseudofile_s *pf = node->i_private;
+  int ret;
+
+  ret = nxmutex_lock(&pf->lock);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  if (filep->f_oflags & O_APPEND)
+    {
+      ret = pseudofile_expand(node, node->i_size + buflen);
+      if (ret < 0)
+        {
+          nxmutex_unlock(&pf->lock);
+          return ret;
+        }
+
+      filep->f_pos = node->i_size - buflen;
+    }
+  else
+    {
+      ret = pseudofile_expand(node, filep->f_pos + buflen);
+      if (ret < 0)
+        {
+          nxmutex_unlock(&pf->lock);
+          return ret;
+        }
+    }
+
+  memcpy(pf->content + filep->f_pos, buffer, buflen);
+  filep->f_pos += buflen;
+#ifdef CONFIG_PSEUDOFS_ATTRIBUTES
+  node->i_mtime.tv_sec = time(NULL);
+#endif
+
+  nxmutex_unlock(&pf->lock);
+  return buflen;
+}
+
+static ssize_t pseudofile_read(FAR struct file *filep, FAR char *buffer,
+                               size_t buflen)
+{
+  FAR struct inode *node = filep->f_inode;
+  FAR struct fs_pseudofile_s *pf = node->i_private;
+  int ret;
+
+  if (buffer == NULL || node->i_size < filep->f_pos)
+    {
+      return -EINVAL;
+    }
+
+  ret = nxmutex_lock(&pf->lock);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  buflen = MIN(node->i_size - filep->f_pos, buflen);
+  memcpy(buffer, pf->content + filep->f_pos, buflen);
+  filep->f_pos += buflen;
+
+#ifdef CONFIG_PSEUDOFS_ATTRIBUTES
+  node->i_atime.tv_sec = time(NULL);
+#endif
+  nxmutex_unlock(&pf->lock);
+
+  return buflen;
+}
+
+static off_t pseudofile_seek(FAR struct file *filep, off_t offset,
+                             int whence)
+{
+  FAR struct inode *node = filep->f_inode;
+  FAR struct fs_pseudofile_s *pf = node->i_private;
+  int ret;
+
+  ret = nxmutex_lock(&pf->lock);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Map the offset according to the whence option */
+
+  switch (whence)
+    {
+      case SEEK_SET:
+          break;
+
+      case SEEK_CUR:
+          offset += filep->f_pos;
+          break;
+
+      case SEEK_END:
+          offset += node->i_size;
+          break;
+
+      default:
+          nxmutex_unlock(&pf->lock);
+          return -EINVAL;
+    }
+
+  if (offset < 0)
+    {
+      nxmutex_unlock(&pf->lock);
+      return -EINVAL;
+    }
+
+  filep->f_pos = offset;
+#ifdef CONFIG_PSEUDOFS_ATTRIBUTES
+  node->i_atime.tv_sec = time(NULL);
+#endif
+  nxmutex_unlock(&pf->lock);
+  return offset;
+}
+
+static int pseudofile_mmap(FAR struct file *filep,
+                           FAR struct mm_map_entry_s *map)
+{
+  FAR struct inode *node = filep->f_inode;
+  FAR struct fs_pseudofile_s *pf = node->i_private;
+
+  if (map->offset >= 0 && map->offset < node->i_size &&
+      map->length != 0 && map->offset + map->length <= node->i_size)
+    {
+      map->vaddr = pf->content + map->offset;
+      return OK;
+    }
+
+  return -EINVAL;
+}
+
+static int pseudofile_truncate(FAR struct file *filep, off_t length)
+{
+  FAR struct inode *node = filep->f_inode;
+  FAR struct fs_pseudofile_s *pf = node->i_private;
+  int ret;
+
+  ret = nxmutex_lock(&pf->lock);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  if (length < node->i_size)
+    {
+      FAR void *tmp;
+
+      tmp = kmm_realloc(pf->content, length);
+      if (tmp == NULL)
+        {
+          ret = -ENOMEM;
+          goto out;
+        }
+
+      pf->content = tmp;
+      node->i_size = length;
+    }
+  else
+    {
+      ret = pseudofile_expand(node, length);
+      if (ret < 0)
+        {
+          goto out;
+        }
+
+      memset(pf->content + node->i_size, 0, length - node->i_size);
+    }
+
+#ifdef CONFIG_PSEUDOFS_ATTRIBUTES
+  node->i_mtime.tv_sec = time(NULL);
+#endif
+
+out:
+  nxmutex_unlock(&pf->lock);
+  return ret;
+}
+
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+static int pseudofile_unlink(FAR struct inode *node)
+{
+  FAR struct fs_pseudofile_s *pf = node->i_private;
+  int ret;
+
+  ret = nxmutex_lock(&pf->lock);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  if (pf->crefs <= 0)
+    {
+      pseudofile_remove(pf);
+      return OK;
+    }
+
+  pf->unlinked = true;
+  nxmutex_unlock(&pf->lock);
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pseudofile_create
+ *
+ * Description:
+ *   Create the pseudo-file with specified path and mode, and alloc inode
+ *   of this pseudo-file.
+ *
+ ****************************************************************************/
+
+int pseudofile_create(FAR struct inode **node, FAR const char *path,
+                      mode_t mode)
+{
+  FAR struct fs_pseudofile_s *pf;
+  int ret;
+
+  if (node == NULL || path == NULL)
+    {
+      return -EINVAL;
+    }
+
+  pf = kmm_zalloc(sizeof(struct fs_pseudofile_s));
+  if (pf == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  nxmutex_init(&pf->lock);
+
+  ret = inode_lock();
+  if (ret < 0)
+    {
+      goto lock_err;
+    }
+
+  ret = inode_reserve(path, mode, node);
+  if (ret < 0)
+    {
+      goto reserve_err;
+    }
+
+  (*node)->i_crefs = 0;
+  (*node)->i_flags = 1;
+  (*node)->u.i_ops = &g_pseudofile_ops;
+  (*node)->i_private = pf;
+
+  inode_unlock();
+  return 0;
+
+reserve_err:
+  inode_unlock();
+lock_err:
+  nxmutex_destroy(&pf->lock);
+  kmm_free(pf);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: inode_is_pseudofile
+ *
+ * Description:
+ *    Check inode whether is a pseudo file.
+ *
+ ****************************************************************************/
+
+bool inode_is_pseudofile(FAR struct inode *inode)
+{
+  if (inode != NULL && inode->u.i_ops == &g_pseudofile_ops)
+    {
+      return true;
+    }
+
+  return false;

Review Comment:
   Optional
   ```suggestion
     return inode != NULL && inode->u.i_ops == &g_pseudofile_ops;
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to