You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by pk...@apache.org on 2022/04/18 16:21:29 UTC

[incubator-nuttx] 01/02: libc/blockstream: add block out stream backend

This is an automated email from the ASF dual-hosted git repository.

pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 889a3bf7fc060376151f46595d0ac81d172f8009
Author: chao.an <an...@xiaomi.com>
AuthorDate: Mon Jan 10 22:56:39 2022 +0800

    libc/blockstream: add block out stream backend
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 include/nuttx/streams.h             |  53 +++++++++
 libs/libc/stream/Make.defs          |   4 +
 libs/libc/stream/lib_blkoutstream.c | 225 ++++++++++++++++++++++++++++++++++++
 3 files changed, 282 insertions(+)

diff --git a/include/nuttx/streams.h b/include/nuttx/streams.h
index 4d53114211..98348019f3 100644
--- a/include/nuttx/streams.h
+++ b/include/nuttx/streams.h
@@ -29,6 +29,9 @@
 
 #include <lzf.h>
 #include <stdio.h>
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+#include <nuttx/fs/fs.h>
+#endif
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -197,6 +200,16 @@ struct lib_lzfoutstream_s
 };
 #endif
 
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+struct lib_blkoutstream_s
+{
+  struct lib_outstream_s public;
+  FAR struct inode      *inode;
+  struct geometry        geo;
+  FAR unsigned char     *cache;
+};
+#endif
+
 /****************************************************************************
  * Public Data
  ****************************************************************************/
@@ -374,6 +387,46 @@ void lib_lzfoutstream(FAR struct lib_lzfoutstream_s *stream,
                       FAR struct lib_outstream_s *backend);
 #endif
 
+/****************************************************************************
+ * Name: lib_blkoutstream_open
+ *
+ * Description:
+ *  open block driver stream backend
+ *
+ * Input Parameters:
+ *   stream  - User allocated, uninitialized instance of struct
+ *                lib_blkoutstream_s to be initialized.
+ *   name    - The full path to the block driver to be opened.
+ *
+ * Returned Value:
+ *   Returns zero on success or a negated errno on failure
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+int lib_blkoutstream_open(FAR struct lib_blkoutstream_s *stream,
+                          FAR const char *name);
+#endif
+
+/****************************************************************************
+ * Name: lib_blkoutstream_close
+ *
+ * Description:
+ *  close block driver stream backend
+ *
+ * Input Parameters:
+ *   stream  - User allocated, uninitialized instance of struct
+ *                lib_blkoutstream_s to be initialized.
+ *
+ * Returned Value:
+ *   None (User allocated instance initialized).
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+void lib_blkoutstream_close(FAR struct lib_blkoutstream_s *stream);
+#endif
+
 /****************************************************************************
  * Name: lib_noflush
  *
diff --git a/libs/libc/stream/Make.defs b/libs/libc/stream/Make.defs
index 7af465dc09..622b3f1f67 100644
--- a/libs/libc/stream/Make.defs
+++ b/libs/libc/stream/Make.defs
@@ -38,6 +38,10 @@ ifeq ($(CONFIG_LIBC_LZF),y)
 CSRCS += lib_lzfcompress.c
 endif
 
+ifeq ($(CONFIG_DISABLE_MOUNTPOINT),)
+CSRCS += lib_blkoutstream.c
+endif
+
 # Add the stdio directory to the build
 
 DEPPATH += --dep-path stream
diff --git a/libs/libc/stream/lib_blkoutstream.c b/libs/libc/stream/lib_blkoutstream.c
new file mode 100644
index 0000000000..929cb1997e
--- /dev/null
+++ b/libs/libc/stream/lib_blkoutstream.c
@@ -0,0 +1,225 @@
+/****************************************************************************
+ * libs/libc/stream/lib_blkoutstream.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 <unistd.h>
+#include <nuttx/streams.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: blkoutstream_flush
+ ****************************************************************************/
+
+static int blkoutstream_flush(FAR struct lib_outstream_s *this)
+{
+  FAR struct lib_blkoutstream_s *stream =
+                                 (FAR struct lib_blkoutstream_s *)this;
+  size_t sectorsize = stream->geo.geo_sectorsize;
+  int ret = OK;
+
+  if (this->nput % sectorsize > 0)
+    {
+      ret = stream->inode->u.i_bops->write(stream->inode, stream->cache,
+                                           this->nput / sectorsize, 1);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: blkoutstream_puts
+ ****************************************************************************/
+
+static int blkoutstream_puts(FAR struct lib_outstream_s *this,
+                             FAR const void *buf, int len)
+{
+  FAR struct lib_blkoutstream_s *stream =
+                                 (FAR struct lib_blkoutstream_s *)this;
+  size_t sectorsize = stream->geo.geo_sectorsize;
+  FAR struct inode *inode = stream->inode;
+  FAR const unsigned char *ptr = buf;
+  size_t remain = len;
+  int ret;
+
+  while (remain > 0)
+    {
+      size_t sblock = this->nput / sectorsize;
+      size_t offset = this->nput % sectorsize;
+
+      if (offset > 0)
+        {
+          size_t copyin = offset + remain > sectorsize ?
+                          sectorsize - offset : remain;
+
+          memcpy(stream->cache + offset, ptr, copyin);
+
+          ptr        += copyin;
+          offset     += copyin;
+          this->nput += copyin;
+          remain     -= copyin;
+
+          if (offset == stream->geo.geo_sectorsize)
+            {
+              ret = inode->u.i_bops->write(inode, stream->cache, sblock, 1);
+              if (ret < 0)
+                {
+                  return ret;
+                }
+            }
+        }
+      else if (remain < stream->geo.geo_sectorsize)
+        {
+          memcpy(stream->cache, ptr, remain);
+          this->nput += remain;
+          remain      = 0;
+        }
+      else if (remain >= stream->geo.geo_sectorsize)
+        {
+          size_t copyin = (remain / stream->geo.geo_sectorsize) *
+                                    stream->geo.geo_sectorsize;
+
+          ret = inode->u.i_bops->write(inode, ptr, sblock,
+                                       remain / stream->geo.geo_sectorsize);
+          if (ret < 0)
+            {
+              return ret;
+            }
+
+          ptr        += copyin;
+          this->nput += copyin;
+          remain     -= copyin;
+        }
+    }
+
+  return len;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lib_blkoutstream_close
+ *
+ * Description:
+ *  close block driver stream backend
+ *
+ * Input Parameters:
+ *   stream  - User allocated, uninitialized instance of struct
+ *                lib_blkoutstream_s to be initialized.
+ *
+ * Returned Value:
+ *   None (User allocated instance initialized).
+ *
+ ****************************************************************************/
+
+void lib_blkoutstream_close(FAR struct lib_blkoutstream_s *stream)
+{
+  if (stream)
+    {
+      if (stream->inode)
+        {
+          close_blockdriver(stream->inode);
+          stream->inode = NULL;
+        }
+
+      if (stream->cache)
+        {
+          lib_free(stream->cache);
+          stream->cache = NULL;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: lib_blkoutstream_open
+ *
+ * Description:
+ *  block driver stream backend
+ *
+ * Input Parameters:
+ *   stream  - User allocated, uninitialized instance of struct
+ *                lib_blkoutstream_s to be initialized.
+ *   name    - The full path to the block driver to be opened.
+ *
+ * Returned Value:
+ *   Returns zero on success or a negated errno on failure
+ *
+ ****************************************************************************/
+
+int lib_blkoutstream_open(FAR struct lib_blkoutstream_s *stream,
+                          FAR const char *name)
+{
+  FAR struct inode *inode = NULL;
+  int ret;
+
+  if (stream == NULL || name == NULL)
+    {
+      return -EINVAL;
+    }
+
+  ret = open_blockdriver(name, 0, &inode);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  memset(stream, 0, sizeof(*stream));
+
+  if (inode->u.i_bops->geometry == NULL ||
+      inode->u.i_bops->write == NULL ||
+      inode->u.i_bops->geometry(inode, &stream->geo) < 0 ||
+      stream->geo.geo_sectorsize <= 0 ||
+      stream->geo.geo_nsectors <= 0)
+    {
+      close_blockdriver(inode);
+      return -EINVAL;
+    }
+
+  stream->cache = lib_malloc(stream->geo.geo_sectorsize);
+  if (stream->cache == NULL)
+    {
+      close_blockdriver(inode);
+      return -ENOMEM;
+    }
+
+  stream->inode        = inode;
+  stream->public.puts  = blkoutstream_puts;
+  stream->public.flush = blkoutstream_flush;
+
+  return OK;
+}
+#endif