You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by "michallenc (via GitHub)" <gi...@apache.org> on 2023/09/12 08:55:26 UTC

[GitHub] [nuttx] michallenc opened a new pull request, #10602: libc: add support for custom streams with fopencookie()

michallenc opened a new pull request, #10602:
URL: https://github.com/apache/nuttx/pull/10602

   ## Summary
   This commit adds support for custom stream via `fopencookie` function. The function allows the programmer the create his own custom stream for IO operations and hook his custom functions to it.
   
   This is a non POSIX interface defined in Standard C library and implemented according to it. The only difference is in usage of `off_t` instead of `off64_t`. Programmer can use 64 bits offset if `CONFIG_FS_LARGEFILE` is enabled. In that case `off_t` is defined as `int64_t` (`int32_t` otherwise).
   
   The interface will be useful for future fmemopen implementation.
   
   ## Impact
   New interface.
   
   ## Testing
   Tested with [example application on man page](https://man7.org/linux/man-pages/man3/fopencookie.3.html) on SAMv7 MCU.
   


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] gregory-nutt commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "gregory-nutt (via GitHub)" <gi...@apache.org>.
gregory-nutt commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1719510693

   I personally think you are going down the wrong path with this ad hoc logic.  This is very high risk because I don't think either of you are considering all of the issues and complexities.  You apparently seem focused on avoiding a clean context switch (which I believe is the correct, clean, flexible solution).
   
   I believe we need to at least insist on a good test for this code to give people like me confidence.  A good test would include:
   
   - All build modes:  FLAT, PROTECTED, and KERNEL (we would need some testing help).
   - Assure that user code never executes in kernel mode in the PROTECTED build
   - Test with client and server in same task/process; Client and server in different tasks/processes and different address spaces (in KERNEL mde).
   
   If it could pass a pretty rigorous test then I would become a believer.  That, I think is a requirement for merging.  I am not a believer now.
   


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] patacongo commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "patacongo (via GitHub)" <gi...@apache.org>.
patacongo commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1720016981

   
   > This case isn't suitable for stdio functions. How can you pass FILE * from one task/process to other task/process in kernel mode? So it's impossible to call the callback function cross the address space boundary since FILE* return from fopencookie can only be used by the caller's task/process and is always invalid and impossible to pass FILE* to another task/process at the first place.
   
   I don't see the relevance of the FILE*.  I was more concerned at the io_funcs and cookie.  But looking at the prototype, it seems impossible that the io_funcs could like in a different address space. from the caller of fopencookie().
   
   


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1323074603


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */

Review Comment:
   ALL first char in comment change to upper case



##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */

Review Comment:
   add FAR



##########
include/stdio.h:
##########
@@ -244,6 +244,11 @@ int    dprintf(int fd, FAR const IPTR char *fmt, ...) printf_like(2, 3);
 int    vdprintf(int fd, FAR const IPTR char *fmt, va_list ap)
        printf_like(2, 0);
 
+/* Custom stream operation fopencookie. */
+
+FAR FILE *fopencookie(void *cookie, const char *mode,

Review Comment:
   ```suggestion
   FAR FILE *fopencookie(FAR void *cookie, FAR const char *mode,
   ```



##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;

Review Comment:
   ```suggestion
     struct cookie_s *cookie = (FAR struct cookie_s *)filep->f_priv;
   ```
   add FAR to ALL pointers



##########
include/nuttx/fs/fs.h:
##########
@@ -425,6 +425,27 @@ struct inode
 
 #define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
 
+/* Definitions for custom stream operations with fopencookie. The
+ * implementation is as defined in Standard C library (libc). The only
+ * difference is that we use off_t instead of off64_t. This means
+ * off_t is int64_t if CONFIG_FS_LARGEFILE is defined and int32_t if not.
+ */
+
+typedef ssize_t cookie_read_function_t(void *cookie, char *buf, size_t size);
+typedef ssize_t cookie_write_function_t(void *cookie, const char *buf,
+                                        size_t size);
+typedef ssize_t cookie_seek_function_t(void *cookie, off_t *offset,

Review Comment:
   ```suggestion
   typedef int cookie_seek_function_t(void *cookie, off_t *offset,
   ```



##########
include/nuttx/fs/fs.h:
##########
@@ -425,6 +425,27 @@ struct inode
 
 #define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
 
+/* Definitions for custom stream operations with fopencookie. The
+ * implementation is as defined in Standard C library (libc). The only
+ * difference is that we use off_t instead of off64_t. This means
+ * off_t is int64_t if CONFIG_FS_LARGEFILE is defined and int32_t if not.
+ */
+
+typedef ssize_t cookie_read_function_t(void *cookie, char *buf, size_t size);
+typedef ssize_t cookie_write_function_t(void *cookie, const char *buf,
+                                        size_t size);
+typedef ssize_t cookie_seek_function_t(void *cookie, off_t *offset,
+                                       int whence);
+typedef ssize_t cookie_close_function_t(void *cookie);

Review Comment:
   ```suggestion
   typedef int cookie_close_function_t(void *cookie);
   ```



##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   libc can't call os internal function directly



##########
include/nuttx/fs/fs.h:
##########
@@ -425,6 +425,27 @@ struct inode
 
 #define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
 
+/* Definitions for custom stream operations with fopencookie. The
+ * implementation is as defined in Standard C library (libc). The only
+ * difference is that we use off_t instead of off64_t. This means
+ * off_t is int64_t if CONFIG_FS_LARGEFILE is defined and int32_t if not.
+ */
+
+typedef ssize_t cookie_read_function_t(void *cookie, char *buf, size_t size);
+typedef ssize_t cookie_write_function_t(void *cookie, const char *buf,
+                                        size_t size);
+typedef ssize_t cookie_seek_function_t(void *cookie, off_t *offset,
+                                       int whence);
+typedef ssize_t cookie_close_function_t(void *cookie);
+
+typedef struct
+{
+  cookie_read_function_t *read;

Review Comment:
   add FAR for ALL pointers



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325635975


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   > > Add cookie_io_functions_t to file_struct(FILE)
   > > Assign the internal callback which read/write/seek through fd to cookie_io_functions_t in fopen
   > > Assign caller supplied callback in fopencookie
   > > Replace read/write/seek with cookie_io_functions_t's one
   > 
   > I am not sure this would solve the problem. Because the callback to `fopencookie` would still go through `fs/vfs`.
   
   In my suggestion, you should stop to implement file_operation_s and call file_allocate_from_tcb. How do you go through fs/vfs?
   
   > Now this would work in FLAT build but probably not in protected build. What we would need is that `libc` would call the callbacks directly for `FILE *` if custom streams are defined as it is done in ucLibc for example https://elixir.bootlin.com/uclibc-ng/v1.0.7/source/libc/stdio/fread.c#L68 This way we would not need But that is too big change now.
   
   This is the right way to go. And most change is minor.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325884666


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   > In my suggestion, you should stop to implement file_operation_s and call file_allocate_from_tcb. How do you go through fs/vfs without them?
   
   Yes, but you mention 
   
   > Assign the internal callback which read/write/seek through fd to cookie_io_functions_t in fopen
   
   How would I get fd without actually using `file_allocate_from_tcb`? I cannot even call `fopen` without that.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] gregory-nutt commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "gregory-nutt (via GitHub)" <gi...@apache.org>.
gregory-nutt commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324971300


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  FAR void *cookie;                /* Pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* Programmer-defined hook functions */
+  int cookie_fd;                   /* File descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(FAR void *cookie, FAR const char *mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   I am strongly opposed to adding any user interfaces to the OS that hand no basis in established standards.  This is a terrible practice and should not be accepted.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361852315


##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   `<nuttx/lib/lib.h>` was used to reference `lib_stream_initialize` and `lib_stream_release` before your patch so I am not sure if it is such a problem in this case.
   Deciding what function is to be called would require some if statements in running code which I would like to avoid.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1363385383


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,153 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cookie_read_cb
+ ****************************************************************************/
+
+ssize_t cookie_read_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  /* Per specification: if *read is a null pointer, then reads from the
+   * custom stream always return end of file.
+   */
+
+  errno = -EACCES;
+  return -1;
+}
+
+/****************************************************************************
+ * Name: cookie_write_cb
+ ****************************************************************************/
+
+ssize_t cookie_write_cb(FAR void *cookie, FAR const char *buf, size_t size)
+{
+  /* Per specification: if *write is a null pointer, then output to the
+   * stream is discarded.
+   */
+
+  errno = -EBADF;
+  return -1;
+}
+
+/****************************************************************************
+ * Name: cookie_seek_cb
+ ****************************************************************************/
+
+off_t cookie_seek_cb(FAR void *cookie, FAR off_t *offset, int whence)
+{
+  /* Per specification: if *seek is a null pointer, then it is not
+   * possible to perform seek operations on the stream.
+   */
+
+  errno = -EINVAL;

Review Comment:
   -ENOTSUP



##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,153 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cookie_read_cb
+ ****************************************************************************/
+
+ssize_t cookie_read_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  /* Per specification: if *read is a null pointer, then reads from the
+   * custom stream always return end of file.
+   */
+
+  errno = -EACCES;
+  return -1;
+}
+
+/****************************************************************************
+ * Name: cookie_write_cb
+ ****************************************************************************/
+
+ssize_t cookie_write_cb(FAR void *cookie, FAR const char *buf, size_t size)
+{
+  /* Per specification: if *write is a null pointer, then output to the
+   * stream is discarded.

Review Comment:
   good spot, done



##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,153 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cookie_read_cb
+ ****************************************************************************/
+
+ssize_t cookie_read_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  /* Per specification: if *read is a null pointer, then reads from the
+   * custom stream always return end of file.
+   */

Review Comment:
   done



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361865252


##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   both functions are moved into sched, so the inclusion doesn't need anymore



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361799024


##########
libs/libc/stdio/lib_setvbuf.c:
##########
@@ -133,7 +134,7 @@ int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size)
 
   /* Return EBADF if the file is not open */
 
-  if (stream->fs_fd < 0)
+  if (fd < 0)

Review Comment:
   hmm, what about this? Can we presume that it is not possible to have stream structure without the stream actually being open?



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1731532609

   Some initial tests can be found here: https://github.com/michallenc/incubator-nuttx-apps/commit/1cd88d54c7119fad000866a3a62f8c5afad2ebc8 I have only tested it in FLAT mode so far as I have not been able to compile NuttX in protected mode (regardless of `fopencookie`, I tried upstream NuttX without changes as well) on both samv7 and imxrt MCUs. SAMv7 fails on `NVIC_CFAULTS_MUNSTKERR` (MemManage fault on unstacking) and I could not get any output from imxrt. I used @acassis video on https://www.youtube.com/watch?v=p2aXmPNUnCg for configuration, so that stepts should be alright. There might be something wrong with MPU for ARMv7-M...


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1723360237

   https://github.com/apache/nuttx-apps/blob/master/testing/smart_test/smart_test.c contain some stdio related testing.


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] gregory-nutt commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "gregory-nutt (via GitHub)" <gi...@apache.org>.
gregory-nutt commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324992990


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  FAR void *cookie;                /* Pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* Programmer-defined hook functions */
+  int cookie_fd;                   /* File descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;

Review Comment:
   Are these the user space callbacks you were referring to?  Yes, these are wrong.  This can't work this way there can be no such calls from the kernel address space.
   
   This is similar to the way that the usrsock works.  The usrsock functions are "called" from the OS, but not directly.   Rather, the call data is marshaled through a POSIX driver interface to the user code.  This is way this should be done as well.  The interface is described in include/nuttx/net/usrsock.h
   
   Other good things to look at:
   
   - graphics/:  The NX graphics server interfaces with user space via a POSIX message queue.
   - fs/userfs/:  Supports a userspace implementation of a file system.  It uses a standard ipv4 sockets on a local interface (INADDR_LOOPBACK)
   
   At one time I wrote some user-space device drivers (character and block) based on the BSD user space drivers, but I don't think those made it into the repository.  The design was similar to the usrsock design.
   



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325250688


##########
include/stdio.h:
##########
@@ -244,6 +244,11 @@ int    dprintf(int fd, FAR const IPTR char *fmt, ...) printf_like(2, 3);
 int    vdprintf(int fd, FAR const IPTR char *fmt, va_list ap)
        printf_like(2, 0);
 
+/* Custom stream operation fopencookie. */
+
+FAR FILE *fopencookie(FAR void *cookie, FAR const char *mode,
+                      cookie_io_functions_t io_funcs);
+

Review Comment:
   it is implemented by *BSD too:
   https://man.freebsd.org/cgi/man.cgi?query=fopencookie&apropos=0&sektion=3&manpath=FreeBSD+11-current&format=html
   



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] mu578 commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "mu578 (via GitHub)" <gi...@apache.org>.
mu578 commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1720039512

   > > This case isn't suitable for stdio functions. How can you pass FILE * from one task/process to other task/process in kernel mode? So it's impossible to call the callback function cross the address space boundary since FILE* return from fopencookie can only be used by the caller's task/process and is always invalid and impossible to pass FILE* to another task/process at the first place.
   > 
   > I don't see the relevance of the FILE*. I was more concerned at the io_funcs and cookie. But looking at the prototype, it seems impossible that the io_funcs could like in a different address space. from the caller of fopencookie().
   
   Aggreed, it would require to pound defined and only allowing such APIs in usermode. However, it could be doable by making a new vfs interface handling such but it would require a whole revamp and further thoughts to make it possible, as is : it is not hot patchable -> so my proposal to support indirection for user-mode build only, at least it can be undone and evolve without breaking.
   
   That is impossible to callback from two distinct regions ; it would require some kind of trampoline jump with copies back and forth.
   


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324089124


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   I think we don't need allocate fd here, it's enough to set fs_fd to -1, just like how musl implement fopencookie:
   https://github.com/bminor/musl/blob/master/src/stdio/fopencookie.c#L121



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325934706


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   fd shouldn't reference in common code, but in the callback provided by stdio self. Actually fd should change to void * instead.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1357808217


##########
include/nuttx/fs/fs.h:
##########
@@ -425,6 +425,31 @@ struct inode
 
 #define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
 
+/* Definitions for custom stream operations with fopencookie. The
+ * implementation is as defined in Standard C library (libc). The only
+ * difference is that we use off_t instead of off64_t. This means
+ * off_t is int64_t if CONFIG_FS_LARGEFILE is defined and int32_t if not.
+ *
+ * These callbacks can either lead to custom functions if fopencookie is used
+ * or to standard file system functions if not.
+ */
+
+typedef CODE ssize_t cookie_read_function_t(void *cookie, char *buf,

Review Comment:
   Done



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1763319824

   > @xiaoxiang781216 I have updated the implementation and implemented most of your suggestions (see separate comments). There is a new PR in nuttx-apps [add fopecookie test and use fileno interface instead of accessing FILE](https://github.com/apache/nuttx-apps/pull/2112) that adds test application and also fix some `FILE` usage in `system` (this is should be merged before NuttX patch because of CI).
   
   @michallenc but, the ci still fail, could you take a look?


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361838991


##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   @michallenc this is the last comment you need consider, otherwise the change will break protected and kernel mode.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361809261


##########
libs/libc/stdio/lib_setvbuf.c:
##########
@@ -133,7 +134,7 @@ int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size)
 
   /* Return EBADF if the file is not open */
 
-  if (stream->fs_fd < 0)
+  if (fd < 0)

Review Comment:
   It's impossible to handle this type of error reliably. It's caller's responsibility to pass stream which comes from fopen/fdopen/fopencookie.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325570279


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  FAR void *cookie;                /* Pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* Programmer-defined hook functions */
+  int cookie_fd;                   /* File descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;

Review Comment:
   > Are these the user space callbacks you were referring to? Yes, these are wrong. This can't work this way there can be no such calls from the kernel address space.
   
   I think `stdio` library is purely user space (and protect build builds it twice, one for kernel and one for user space) so this callback here should be correct. The issue @xiaoxiang781216 is reffering to is that the route from user call to the callback is: `fseek` from app -> `fseeko` in libc -> `lseek` in `fs/vfs` -> `fseekcookie` in libc -> user callback in app. I think all we need to do is to avoid the usage of  `lseek` in `fs/vfs` and this way we ensure we stay in user space.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324119464


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   Ok, you implementation reuse file_operation_s infrastructure, but it mayn't work in protected/kernel mode, since fclosecookie... is part of kernel, but call the callback provided by userspace directly. I would suggest that you have to add these callback to file_struct and call them from libc/stdio directly.
   
   @patacongo what are you thinking?



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324119464


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   Ok, you implementation reuse file_operation_s infrastructure, but it mayn't work in protected/kernel mode, since fclosecookie... is part of kernel, but call the callback provided by userspace directly. I would suggest that you have to add the callback to file_struct and call them from libc/stdio directly.
   
   @patacongo what are you thinking?



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1334934364


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,181 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR void *s, FAR char *buf, size_t nbytes);
+static ssize_t fwritecookie(FAR void *s, FAR const char *buf, size_t nbytes);
+static off_t fseekcookie(FAR void *s, off_t offset, int whence);
+static int fclosecookie(FAR void *s);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static FAR FILE *fopencookie_init_stream(int oflags)
+{
+  FAR FILE *stream;
+
+  stream = lib_zalloc(sizeof(FILE));

Review Comment:
   stream need allocate through fs_fdopen like fopen/fdopen too.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1335166795


##########
libs/libc/libc.h:
##########
@@ -245,6 +245,13 @@ bool lib_isbasedigit(int ch, int base, FAR int *value);
 
 int lib_checkbase(int base, FAR const char **pptr);
 
+/* Defined in lib_stdio_cb */
+
+ssize_t lib_fread_cb(void *stream, char *buf, size_t size);
+ssize_t lib_fwrite_cb(void *stream, const char *buf, size_t size);
+off_t lib_fseek_cb(void *stream, off_t offset, int whence);

Review Comment:
   Yes, but fseek could do the conversion, so we don't need seek_internal_cb_t.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1335158529


##########
include/nuttx/fs/fs.h:
##########
@@ -425,6 +425,55 @@ struct inode
 
 #define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
 
+/* Definitions for custom stream operations with fopencookie. The
+ * implementation is as defined in Standard C library (libc). The only
+ * difference is that we use off_t instead of off64_t. This means
+ * off_t is int64_t if CONFIG_FS_LARGEFILE is defined and int32_t if not.
+ */
+
+typedef ssize_t cookie_read_function_t(void *cookie, char *buf, size_t size);
+typedef ssize_t cookie_write_function_t(void *cookie, const char *buf,
+                                        size_t size);
+typedef off_t cookie_seek_function_t(void *cookie, off_t *offset,
+                                     int whence);
+typedef int cookie_close_function_t(void *cookie);
+
+typedef struct

Review Comment:
   done



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1357808020


##########
libs/libc/stdio/lib_stdio_cb.c:
##########
@@ -0,0 +1,90 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_stdio_cb.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 <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lib_fseek_cb
+ ****************************************************************************/
+
+off_t lib_fseek_cb(FAR void *cookie, off_t *offset, int whence)
+{
+  int fd = (int)(intptr_t)cookie;
+  return lseek(fd, *offset, whence);
+}
+
+/****************************************************************************
+ * Name: lib_fwrite_cb
+ ****************************************************************************/
+
+ssize_t lib_fwrite_cb(FAR void *cookie, FAR const char *buf, size_t size)
+{
+  int fd = (int)(intptr_t)cookie;
+  return _NX_WRITE(fd, buf, size);
+}
+
+/****************************************************************************
+ * Name: lib_fread_cb
+ ****************************************************************************/
+
+ssize_t lib_fread_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  int fd = (int)(intptr_t)cookie;
+  return _NX_READ(fd, buf, size);
+}
+
+/****************************************************************************
+ * Name: lib_fclose_cb
+ ****************************************************************************/
+
+int lib_fclose_cb(FAR void *cookie)
+{
+  int fd = (int)(intptr_t)cookie;
+  if (fd < 0)
+    {
+      /* Do not close already closed fd! */
+
+      return -ENODEV;
+    }
+
+#ifdef CONFIG_FDSAN
+  uint64_t tag;
+  tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_FILE,

Review Comment:
   Done



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361866400


##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   @xiaoxiang781216 But why should this be a problem for protected and kernel build? In that case libc is compiled twice, once for user and once for kernel. So kernel would still have valid references (separate from user).



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361825164


##########
include/nuttx/fs/fs.h:
##########
@@ -426,6 +426,31 @@ struct inode
 
 #define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
 
+/* Definitions for custom stream operations with fopencookie. The
+ * implementation is as defined in Standard C library (libc). The only
+ * difference is that we use off_t instead of off64_t. This means
+ * off_t is int64_t if CONFIG_FS_LARGEFILE is defined and int32_t if not.
+ *
+ * These callbacks can either lead to custom functions if fopencookie is used
+ * or to standard file system functions if not.
+ */
+
+typedef CODE ssize_t cookie_read_function_t(void *cookie, char *buf,
+                                            size_t size);
+typedef CODE ssize_t cookie_write_function_t(void *cookie, const char *buf,
+                                             size_t size);
+typedef CODE off_t cookie_seek_function_t(void *cookie, off_t *offset,
+                                     int whence);

Review Comment:
   done



##########
libs/libc/stdio/lib_libfflush.c:
##########
@@ -107,7 +107,9 @@ ssize_t lib_fflush_unlocked(FAR FILE *stream, bool bforce)
         {
           /* Perform the write */
 
-          bytes_written = _NX_WRITE(stream->fs_fd, src, nbuffer);
+          bytes_written = stream->fs_iofunc.write(stream->fs_cookie,
+                                                  (const char *)src,

Review Comment:
   done



##########
libs/libc/stdio/lib_libfread_unlocked.c:
##########
@@ -170,7 +170,9 @@ ssize_t lib_fread_unlocked(FAR void *ptr, size_t count, FAR FILE *stream)
 
                   if (remaining > buffer_available)
                     {
-                      bytes_read = _NX_READ(stream->fs_fd, dest, remaining);
+                      bytes_read = stream->fs_iofunc.read(stream->fs_cookie,
+                                                          (char *)dest,

Review Comment:
   done



##########
libs/libc/stdio/lib_ungetc.c:
##########
@@ -52,7 +53,7 @@ int ungetc(int c, FAR FILE *stream)
 
   /* Stream must be open for read access */
 
-  if ((stream->fs_fd < 0) || ((stream->fs_oflags & O_RDOK) == 0))
+  if ((fd < 0) || ((stream->fs_oflags & O_RDOK) == 0))

Review Comment:
   done



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1362636318


##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   I see. Updated the implementation. I have added callbacks to `fopencookie.c` that are used if some user callback is NULL: they handle correct return value etc. and also make sure classic read/write/seek/close is not used for cookie.



##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   I see. Updated the implementation. I added callbacks to `fopencookie.c` that are used if some user callback is NULL: they handle correct return value etc. and also make sure classic read/write/seek/close is not used for cookie.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1363499727


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,156 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cookie_read_cb
+ ****************************************************************************/
+
+static ssize_t cookie_read_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  /* Per specification: if *read is a null pointer, then reads from the
+   * custom stream always return end of file.
+   */
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: cookie_write_cb
+ ****************************************************************************/
+
+static ssize_t cookie_write_cb(FAR void *cookie, FAR const char *buf,
+                               size_t size)
+{
+  /* Per specification: if *write is a null pointer, then output to the
+   * stream is discarded.
+   */
+
+  return 0;

Review Comment:
   Ok, musl also returns size. Changed.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1342495448


##########
libs/libc/stdio/lib_stdio_cb.c:
##########
@@ -0,0 +1,76 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_stdio_cb.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 <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lib_fseek_cb
+ ****************************************************************************/
+
+off_t lib_fseek_cb(FAR void *s, off_t offset, int whence)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  return lseek(stream->fs_fd, offset, whence);
+}
+
+/****************************************************************************
+ * Name: lib_fwrite_cb
+ ****************************************************************************/
+
+ssize_t lib_fwrite_cb(FAR void *s, const char *buf, size_t size)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  return _NX_WRITE(stream->fs_fd, buf, size);

Review Comment:
   Sorry for the delay @xiaoxiang781216, I was on a vacation without notebook.
   
   NuttX documentation states
   
   > Normally the logic in this file builds to a single library (libc.a). However, if NuttX is built as a separately compiled kernel (with CONFIG_BUILD_PROTECTED=y or CONFIG_BUILD_KERNEL=y), then the contents of this directory are built as two libraries: One for use by user programs (libc.a) and one for use only within the <kernel> space (libkc.a).
   
   Therefore stdio can be called inside kernel space and `_NX_WRITE` should be there to decide.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1363459539


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,156 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cookie_read_cb
+ ****************************************************************************/
+
+static ssize_t cookie_read_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  /* Per specification: if *read is a null pointer, then reads from the
+   * custom stream always return end of file.
+   */
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: cookie_write_cb
+ ****************************************************************************/
+
+static ssize_t cookie_write_cb(FAR void *cookie, FAR const char *buf,
+                               size_t size)
+{
+  /* Per specification: if *write is a null pointer, then output to the
+   * stream is discarded.
+   */
+
+  return 0;

Review Comment:
   We should return no bytes written, no?



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1363499300


##########
libs/libc/stdio/lib_libfread_unlocked.c:
##########
@@ -46,13 +46,14 @@
 
 ssize_t lib_fread_unlocked(FAR void *ptr, size_t count, FAR FILE *stream)
 {
-  FAR unsigned char *dest = (FAR unsigned char *)ptr;
+  FAR char *dest = (FAR char *)ptr;

Review Comment:
   Yes



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361767837


##########
libs/libc/stdio/lib_libfgets.c:
##########
@@ -97,10 +97,11 @@ FAR char *lib_fgets_unlocked(FAR char *buf, size_t buflen, FILE *stream,
                              bool keepnl, bool consume)
 {
   size_t nch = 0;
+  int fd = (int)(intptr_t)stream->fs_cookie;
 
   /* Sanity checks */
 
-  if (!stream || !buf || stream->fs_fd < 0)
+  if (!stream || !buf || fd < 0)

Review Comment:
   I suppose we could remove `fd < 0` as this is checked by write/read/seek/close operations further in the code.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361825521


##########
libs/libc/stdio/lib_libfwrite.c:
##########
@@ -132,7 +132,8 @@ ssize_t lib_fwrite_unlocked(FAR const void *ptr, size_t count,
 
   if (count >= CONFIG_STDIO_BUFFER_SIZE)
     {
-      ret = _NX_WRITE(stream->fs_fd, src, count);
+      ret = stream->fs_iofunc.write(stream->fs_cookie, (const char *)src,

Review Comment:
   done



##########
libs/libc/stdio/lib_libfread_unlocked.c:
##########
@@ -258,7 +260,9 @@ ssize_t lib_fread_unlocked(FAR void *ptr, size_t count, FAR FILE *stream)
 
           while (remaining > 0)
             {
-              bytes_read = _NX_READ(stream->fs_fd, dest, remaining);
+              bytes_read = stream->fs_iofunc.read(stream->fs_cookie,
+                                                  (char *)dest,

Review Comment:
   done



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361877829


##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   > `<nuttx/lib/lib.h>` was used to reference `lib_stream_initialize` and `lib_stream_release` before your patch so I am not sure if it is such a problem in this case.
   
   both functions are moved into sched, so the inclusion doesn't need anymore
   
   > Deciding what function is to be called would require some if statements in running code which I would like to avoid.
   
   but you have to do the check since:
   
   1. stdin/stdout/sderr is initialized inside kernel space
   2. The assignment of stdin/stdout/stderr's callback inside kernel space point to the lib_fxxx_cb copy which is part of kernel space
   3. fopen/fdopen point lib_fxxx_cb in user space
   
   when user call fwrite/fread on stdin/stdout/stderr, prefetch abort will happen since user space doesn't have right to execute the code inside the kernel space.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1334930318


##########
include/nuttx/fs/fs.h:
##########
@@ -425,6 +425,55 @@ struct inode
 
 #define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
 
+/* Definitions for custom stream operations with fopencookie. The
+ * implementation is as defined in Standard C library (libc). The only
+ * difference is that we use off_t instead of off64_t. This means
+ * off_t is int64_t if CONFIG_FS_LARGEFILE is defined and int32_t if not.
+ */
+
+typedef ssize_t cookie_read_function_t(void *cookie, char *buf, size_t size);
+typedef ssize_t cookie_write_function_t(void *cookie, const char *buf,
+                                        size_t size);
+typedef off_t cookie_seek_function_t(void *cookie, off_t *offset,

Review Comment:
   ```suggestion
   typedef CODE int cookie_seek_function_t(FAR void *cookie, FAR off_t *offset,
   ```
   add CODE to ALL function typdef



##########
libs/libc/libc.h:
##########
@@ -245,6 +245,13 @@ bool lib_isbasedigit(int ch, int base, FAR int *value);
 
 int lib_checkbase(int base, FAR const char **pptr);
 
+/* Defined in lib_stdio_cb */

Review Comment:
   ```suggestion
   /* Defined in lib_stdio_cb.c */
   ```



##########
include/nuttx/fs/fs.h:
##########
@@ -497,6 +546,8 @@ struct file_struct
   FAR struct file_struct *fs_next;      /* Pointer to next file stream */
   rmutex_t                fs_lock;      /* Recursive lock */
   int                     fs_fd;        /* File descriptor associated with stream */
+  FAR struct cookie_s     fs_cookie;    /* Cookie structure for fopencookie */
+  io_callbacks_t          fs_callbacks; /* Internal callbacks for IO call */

Review Comment:
   duplicated with fs_cookie.cookie_io



##########
include/nuttx/fs/fs.h:
##########
@@ -425,6 +425,55 @@ struct inode
 
 #define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
 
+/* Definitions for custom stream operations with fopencookie. The
+ * implementation is as defined in Standard C library (libc). The only
+ * difference is that we use off_t instead of off64_t. This means
+ * off_t is int64_t if CONFIG_FS_LARGEFILE is defined and int32_t if not.
+ */
+
+typedef ssize_t cookie_read_function_t(void *cookie, char *buf, size_t size);
+typedef ssize_t cookie_write_function_t(void *cookie, const char *buf,
+                                        size_t size);
+typedef off_t cookie_seek_function_t(void *cookie, off_t *offset,
+                                     int whence);
+typedef int cookie_close_function_t(void *cookie);
+
+typedef struct
+{
+  FAR cookie_read_function_t *read;
+  FAR cookie_write_function_t *write;
+  FAR cookie_seek_function_t *seek;
+  FAR cookie_close_function_t *close;
+} cookie_io_functions_t;
+
+struct cookie_s
+{
+  FAR void *cookie;                /* Pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* Programmer-defined hook functions */
+};
+
+/* Definition of internal callbacks for read/write/seek/close operations.
+ * These are needed to ensure custom callbacks from fopencookie are called
+ * from user address space and not from kernel address space. These callbacks
+ * are either routed to fopencookie related callbacks or to internal
+ * read/write/seek/close operations defined in file system (thus in kernel
+ * address space)
+ */
+
+typedef ssize_t read_internal_cb_t(FAR void *s, char *buf, size_t size);
+typedef ssize_t write_internal_cb_t(FAR void *s, const char *buf,
+                                    size_t size);
+typedef off_t seek_internal_cb_t(FAR void *s, off_t offset, int whence);
+typedef int close_internal_cb_t(FAR void *s);
+
+typedef struct
+{
+  FAR read_internal_cb_t *read;
+  FAR write_internal_cb_t *write;
+  FAR seek_internal_cb_t *seek;
+  FAR close_internal_cb_t *close;
+} io_callbacks_t;

Review Comment:
   why define the duplicated typedef and struct(from line 463 to line 475), but use cookie_io_functions_t directly?



##########
include/nuttx/fs/fs.h:
##########
@@ -425,6 +425,55 @@ struct inode
 
 #define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
 
+/* Definitions for custom stream operations with fopencookie. The
+ * implementation is as defined in Standard C library (libc). The only
+ * difference is that we use off_t instead of off64_t. This means
+ * off_t is int64_t if CONFIG_FS_LARGEFILE is defined and int32_t if not.
+ */
+
+typedef ssize_t cookie_read_function_t(void *cookie, char *buf, size_t size);

Review Comment:
   add FAR to ALL pointers



##########
include/nuttx/fs/fs.h:
##########
@@ -497,6 +546,8 @@ struct file_struct
   FAR struct file_struct *fs_next;      /* Pointer to next file stream */
   rmutex_t                fs_lock;      /* Recursive lock */
   int                     fs_fd;        /* File descriptor associated with stream */

Review Comment:
   fs_fd should union with fs_cookie.cookie



##########
include/nuttx/fs/fs.h:
##########
@@ -425,6 +425,55 @@ struct inode
 
 #define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
 
+/* Definitions for custom stream operations with fopencookie. The
+ * implementation is as defined in Standard C library (libc). The only
+ * difference is that we use off_t instead of off64_t. This means
+ * off_t is int64_t if CONFIG_FS_LARGEFILE is defined and int32_t if not.
+ */
+
+typedef ssize_t cookie_read_function_t(void *cookie, char *buf, size_t size);
+typedef ssize_t cookie_write_function_t(void *cookie, const char *buf,
+                                        size_t size);
+typedef off_t cookie_seek_function_t(void *cookie, off_t *offset,
+                                     int whence);
+typedef int cookie_close_function_t(void *cookie);
+
+typedef struct

Review Comment:
   ```suggestion
   typedef struct cookie_io_functions_s
   ```



##########
libs/libc/libc.h:
##########
@@ -245,6 +245,13 @@ bool lib_isbasedigit(int ch, int base, FAR int *value);
 
 int lib_checkbase(int base, FAR const char **pptr);
 
+/* Defined in lib_stdio_cb */
+
+ssize_t lib_fread_cb(void *stream, char *buf, size_t size);

Review Comment:
   add FAR for ALL pointer



##########
libs/libc/stdio/lib_fclose.c:
##########
@@ -129,7 +129,7 @@ int fclose(FAR FILE *stream)
                                                (uintptr_t)stream);
           status = android_fdsan_close_with_tag(stream->fs_fd, tag);

Review Comment:
   need move fdscan related code to stdio callback



##########
libs/libc/libc.h:
##########
@@ -245,6 +245,13 @@ bool lib_isbasedigit(int ch, int base, FAR int *value);
 
 int lib_checkbase(int base, FAR const char **pptr);
 
+/* Defined in lib_stdio_cb */
+
+ssize_t lib_fread_cb(void *stream, char *buf, size_t size);
+ssize_t lib_fwrite_cb(void *stream, const char *buf, size_t size);
+off_t lib_fseek_cb(void *stream, off_t offset, int whence);

Review Comment:
   ```suggestion
   int lib_fseek_cb(void *stream, off_t offset, int whence);
   ```



##########
libs/libc/stdio/lib_fclose.c:
##########
@@ -129,7 +129,7 @@ int fclose(FAR FILE *stream)
                                                (uintptr_t)stream);
           status = android_fdsan_close_with_tag(stream->fs_fd, tag);
 #else
-          status = close(stream->fs_fd);
+          status = stream->fs_callbacks.close(stream);

Review Comment:
   need pass cookie instead stream here



##########
libs/libc/stdio/lib_stdio_cb.c:
##########
@@ -0,0 +1,76 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_stdio_cb.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 <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lib_fseek_cb
+ ****************************************************************************/
+
+off_t lib_fseek_cb(FAR void *s, off_t offset, int whence)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  return lseek(stream->fs_fd, offset, whence);
+}
+
+/****************************************************************************
+ * Name: lib_fwrite_cb
+ ****************************************************************************/
+
+ssize_t lib_fwrite_cb(FAR void *s, const char *buf, size_t size)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  return _NX_WRITE(stream->fs_fd, buf, size);

Review Comment:
   change _NX_WRITE to write



##########
libs/libc/stdio/lib_stdio_cb.c:
##########
@@ -0,0 +1,76 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_stdio_cb.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 <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lib_fseek_cb
+ ****************************************************************************/
+
+off_t lib_fseek_cb(FAR void *s, off_t offset, int whence)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  return lseek(stream->fs_fd, offset, whence);
+}
+
+/****************************************************************************
+ * Name: lib_fwrite_cb
+ ****************************************************************************/
+
+ssize_t lib_fwrite_cb(FAR void *s, const char *buf, size_t size)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  return _NX_WRITE(stream->fs_fd, buf, size);
+}
+
+/****************************************************************************
+ * Name: lib_fread_cb
+ ****************************************************************************/
+
+ssize_t lib_fread_cb(FAR void *s, char *buf, size_t size)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  return _NX_READ(stream->fs_fd, buf, size);

Review Comment:
   change _NX_READ to read



##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,181 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR void *s, FAR char *buf, size_t nbytes);
+static ssize_t fwritecookie(FAR void *s, FAR const char *buf, size_t nbytes);
+static off_t fseekcookie(FAR void *s, off_t offset, int whence);
+static int fclosecookie(FAR void *s);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static FAR FILE *fopencookie_init_stream(int oflags)
+{
+  FAR FILE *stream;
+
+  stream = lib_zalloc(sizeof(FILE));
+  if (stream == NULL)
+    {
+      set_errno(-ENOMEM);
+      return NULL;
+    }
+
+  nxrmutex_init(&stream->fs_lock);
+
+#ifndef CONFIG_STDIO_DISABLE_BUFFERING
+#if CONFIG_STDIO_BUFFER_SIZE > 0
+  /* Set up pointers */
+
+  stream->fs_bufstart = stream->fs_buffer;
+  stream->fs_bufend   = &stream->fs_bufstart[CONFIG_STDIO_BUFFER_SIZE];
+  stream->fs_bufpos   = stream->fs_bufstart;
+  stream->fs_bufread  = stream->fs_bufstart;
+  stream->fs_flags    = __FS_FLAG_UBF; /* Fake setvbuf and fclose */
+
+#ifdef CONFIG_STDIO_LINEBUFFER
+  /* Setup buffer flags */
+
+  stream->fs_flags   |= __FS_FLAG_LBF; /* Line buffering */
+
+#endif /* CONFIG_STDIO_LINEBUFFER */
+#endif /* CONFIG_STDIO_BUFFER_SIZE > 0 */
+#endif /* CONFIG_STDIO_DISABLE_BUFFERING */
+
+  /* Save the file description and open flags.  Setting the
+   * file descriptor locks this stream.
+   */
+
+  stream->fs_fd       = -1;
+  stream->fs_oflags   = oflags;
+
+  return stream;
+}
+
+static ssize_t freadcookie(FAR void *s, FAR char *buf, size_t nbytes)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)&stream->fs_cookie;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR void *s, FAR const char *buf, size_t nbytes)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)&stream->fs_cookie;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR void *s, off_t offset, int whence)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)&stream->fs_cookie;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR void *s)

Review Comment:
   let's remove f*cookie and forward to cookie_io_functions_t directly



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1335159757


##########
libs/libc/libc.h:
##########
@@ -245,6 +245,13 @@ bool lib_isbasedigit(int ch, int base, FAR int *value);
 
 int lib_checkbase(int base, FAR const char **pptr);
 
+/* Defined in lib_stdio_cb */
+
+ssize_t lib_fread_cb(void *stream, char *buf, size_t size);

Review Comment:
   done



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1335167064


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,181 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR void *s, FAR char *buf, size_t nbytes);
+static ssize_t fwritecookie(FAR void *s, FAR const char *buf, size_t nbytes);
+static off_t fseekcookie(FAR void *s, off_t offset, int whence);
+static int fclosecookie(FAR void *s);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static FAR FILE *fopencookie_init_stream(int oflags)
+{
+  FAR FILE *stream;
+
+  stream = lib_zalloc(sizeof(FILE));

Review Comment:
   In the new design, FILE doesn't couple with fd, so fs_fdopen should change the first argument from fd to cookie.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324037782


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   If I create `fs/vfs/fs_fopencookie.c` with function `fs_fopencookie` that would call the internal function (similarly to `fs_fdopen`), would that be ok?



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325635975


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   > > Add cookie_io_functions_t to file_struct(FILE)
   > > Assign the internal callback which read/write/seek through fd to cookie_io_functions_t in fopen
   > > Assign caller supplied callback in fopencookie
   > > Replace read/write/seek with cookie_io_functions_t's one
   > 
   > I am not sure this would solve the problem. Because the callback to `fopencookie` would still go through `fs/vfs`.
   
   In my suggestion, you should stop to implement file_operation_s and call file_allocate_from_tcb. How do you go through fs/vfs without them?
   
   > Now this would work in FLAT build but probably not in protected build. What we would need is that `libc` would call the callbacks directly for `FILE *` if custom streams are defined as it is done in ucLibc for example https://elixir.bootlin.com/uclibc-ng/v1.0.7/source/libc/stdio/fread.c#L68 This way we would not need But that is too big change now.
   
   This is the right way to go, and most change(bunch of rename) is minor.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] mu578 commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "mu578 (via GitHub)" <gi...@apache.org>.
mu578 commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1719538014

   I once look at that to handle a fomempen and alike properly, it would require that struct FILE not to be a direct alias to internal FS struct, as indeed you need to have reference to callbacks and flags, so it would require an indirection where struct FILE holds a private pointer to internal.
   


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1350627664


##########
include/nuttx/fs/fs.h:
##########
@@ -425,6 +425,31 @@ struct inode
 
 #define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
 
+/* Definitions for custom stream operations with fopencookie. The
+ * implementation is as defined in Standard C library (libc). The only
+ * difference is that we use off_t instead of off64_t. This means
+ * off_t is int64_t if CONFIG_FS_LARGEFILE is defined and int32_t if not.
+ *
+ * These callbacks can either lead to custom functions if fopencookie is used
+ * or to standard file system functions if not.
+ */
+
+typedef CODE ssize_t cookie_read_function_t(void *cookie, char *buf,

Review Comment:
   add FAR for ALL pointers



##########
fs/vfs/fs_fdopen.c:
##########
@@ -111,7 +111,7 @@ static inline int fs_checkfd(FAR struct tcb_s *tcb, int fd, int oflags)
  *
  ****************************************************************************/
 
-int fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb,
+int fs_fdopen(int fd, int cookie, int oflags, FAR struct tcb_s *tcb,

Review Comment:
   cookie need be void * or uinptr_t for 64bit arch



##########
fs/vfs/fs_fdopen.c:
##########
@@ -120,7 +120,7 @@ int fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb,
 
   /* Check input parameters */
 
-  if (fd < 0)
+  if (fd < 0 && cookie == 0)

Review Comment:
   why check cookie value, the caller can give any value as they want



##########
sched/group/group_setupstreams.c:
##########
@@ -64,9 +64,9 @@ int group_setupstreams(FAR struct task_tcb_s *tcb)
    * fd = 2 is stderr (write-only, append)
    */
 
-  fs_fdopen(0, O_RDONLY,         (FAR struct tcb_s *)tcb, NULL);
-  fs_fdopen(1, O_WROK | O_CREAT, (FAR struct tcb_s *)tcb, NULL);
-  fs_fdopen(2, O_WROK | O_CREAT, (FAR struct tcb_s *)tcb, NULL);
+  fs_fdopen(0, 0, O_RDONLY,         (FAR struct tcb_s *)tcb, NULL);
+  fs_fdopen(1, 0, O_WROK | O_CREAT, (FAR struct tcb_s *)tcb, NULL);

Review Comment:
   ```suggestion
     fs_fdopen(1, 1, O_WROK | O_CREAT, (FAR struct tcb_s *)tcb, NULL);
   ```



##########
libs/libc/stdio/lib_fopen.c:
##########
@@ -120,7 +127,7 @@ FAR FILE *fopen(FAR const char *path, FAR const char *mode)
 
   if (fd >= 0)
     {
-      ret = fs_fdopen(fd, oflags, NULL, &filep);
+      ret = fs_fdopen(fd, 0, oflags, NULL, &filep);

Review Comment:
   ```suggestion
         ret = fs_fdopen(fd, fd, oflags, NULL, &filep);
   ```



##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,83 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(FAR void *cookie, FAR const char *mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filep = NULL;
+  int ret;
+  int oflags;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Call fs_fdopen with invalid file descriptor and cookie flag set to 1 */
+
+  ret = fs_fdopen(-1, 1, oflags, NULL, &filep);

Review Comment:
   ```suggestion
     ret = fs_fdopen(-1, cookie, oflags, NULL, &filep);
   ```



##########
libs/libc/stdio/lib_libfread_unlocked.c:
##########
@@ -213,9 +215,9 @@ ssize_t lib_fread_unlocked(FAR void *ptr, size_t count, FAR FILE *stream)
                        * into the buffer.
                        */
 
-                      bytes_read = _NX_READ(stream->fs_fd,
-                                            stream->fs_bufread,
-                                            buffer_available);
+                      bytes_read = stream->fs_iofunc.read(stream->fs_cookie,
+                                              (char *)stream->fs_bufread,

Review Comment:
   ```suggestion
                                                                (char *)stream->fs_bufread,
   ```



##########
include/nuttx/fs/fs.h:
##########
@@ -1183,7 +1209,7 @@ int close_mtddriver(FAR struct inode *pinode);
  ****************************************************************************/
 
 #ifdef CONFIG_FILE_STREAM
-int fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb,
+int fs_fdopen(int fd, int cookie, int oflags, FAR struct tcb_s *tcb,

Review Comment:
   ```suggestion
   int fs_fdopen(int fd, FAR void *cookie, int oflags, FAR struct tcb_s *tcb,
   ```



##########
fs/vfs/fs_fdopen.c:
##########
@@ -158,7 +158,7 @@ int fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb,
 
   /* Allocate FILE structure */
 
-  if (fd >= 3)
+  if (fd >= 3 || cookie == 1)

Review Comment:
   why check cookie equals 1 here



##########
sched/group/group_setupstreams.c:
##########
@@ -64,9 +64,9 @@ int group_setupstreams(FAR struct task_tcb_s *tcb)
    * fd = 2 is stderr (write-only, append)
    */
 
-  fs_fdopen(0, O_RDONLY,         (FAR struct tcb_s *)tcb, NULL);
-  fs_fdopen(1, O_WROK | O_CREAT, (FAR struct tcb_s *)tcb, NULL);
-  fs_fdopen(2, O_WROK | O_CREAT, (FAR struct tcb_s *)tcb, NULL);
+  fs_fdopen(0, 0, O_RDONLY,         (FAR struct tcb_s *)tcb, NULL);
+  fs_fdopen(1, 0, O_WROK | O_CREAT, (FAR struct tcb_s *)tcb, NULL);
+  fs_fdopen(2, 0, O_WROK | O_CREAT, (FAR struct tcb_s *)tcb, NULL);

Review Comment:
   ```suggestion
     fs_fdopen(2, 2, O_WROK | O_CREAT, (FAR struct tcb_s *)tcb, NULL);
   ```



##########
libs/libc/stdio/lib_stdio_cb.c:
##########
@@ -0,0 +1,90 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_stdio_cb.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 <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lib_fseek_cb
+ ****************************************************************************/
+
+off_t lib_fseek_cb(FAR void *cookie, off_t *offset, int whence)
+{
+  int fd = (int)(intptr_t)cookie;
+  return lseek(fd, *offset, whence);
+}
+
+/****************************************************************************
+ * Name: lib_fwrite_cb
+ ****************************************************************************/
+
+ssize_t lib_fwrite_cb(FAR void *cookie, FAR const char *buf, size_t size)
+{
+  int fd = (int)(intptr_t)cookie;
+  return _NX_WRITE(fd, buf, size);
+}
+
+/****************************************************************************
+ * Name: lib_fread_cb
+ ****************************************************************************/
+
+ssize_t lib_fread_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  int fd = (int)(intptr_t)cookie;
+  return _NX_READ(fd, buf, size);
+}
+
+/****************************************************************************
+ * Name: lib_fclose_cb
+ ****************************************************************************/
+
+int lib_fclose_cb(FAR void *cookie)
+{
+  int fd = (int)(intptr_t)cookie;
+  if (fd < 0)
+    {
+      /* Do not close already closed fd! */
+
+      return -ENODEV;
+    }
+
+#ifdef CONFIG_FDSAN
+  uint64_t tag;
+  tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_FILE,

Review Comment:
   ```suggestion
     uint64_t tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_FILE,
   ```



##########
libs/libc/stdio/lib_libstream.c:
##########
@@ -66,13 +67,27 @@ void lib_stream_initialize(FAR struct task_group_s *group)
   list->sl_head = NULL;
   list->sl_tail = NULL;
 
+  fd = -1;
+
   /* Initialize stdin, stdout and stderr stream */
 
-  list->sl_std[0].fs_fd = -1;
+  list->sl_std[0].fs_cookie       = (FAR void *)(intptr_t)fd;

Review Comment:
   -1 and remove line 59&70



##########
libs/libc/stdio/lib_stdio_cb.c:
##########
@@ -0,0 +1,90 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_stdio_cb.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 <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lib_fseek_cb
+ ****************************************************************************/
+
+off_t lib_fseek_cb(FAR void *cookie, off_t *offset, int whence)
+{
+  int fd = (int)(intptr_t)cookie;
+  return lseek(fd, *offset, whence);
+}
+
+/****************************************************************************
+ * Name: lib_fwrite_cb
+ ****************************************************************************/
+
+ssize_t lib_fwrite_cb(FAR void *cookie, FAR const char *buf, size_t size)
+{
+  int fd = (int)(intptr_t)cookie;
+  return _NX_WRITE(fd, buf, size);
+}
+
+/****************************************************************************
+ * Name: lib_fread_cb
+ ****************************************************************************/
+
+ssize_t lib_fread_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  int fd = (int)(intptr_t)cookie;
+  return _NX_READ(fd, buf, size);
+}
+
+/****************************************************************************
+ * Name: lib_fclose_cb
+ ****************************************************************************/
+
+int lib_fclose_cb(FAR void *cookie)
+{
+  int fd = (int)(intptr_t)cookie;

Review Comment:
   why check cookie here



##########
libs/libc/stdio/lib_fopen.c:
##########
@@ -74,7 +74,7 @@ FAR FILE *fdopen(int fd, FAR const char *mode)
   oflags = lib_mode2oflags(mode);
   if (oflags >= 0)
     {
-      ret = fs_fdopen(fd, oflags, NULL, &filep);
+      ret = fs_fdopen(fd, 0, oflags, NULL, &filep);

Review Comment:
   ```suggestion
         ret = fs_fdopen(fd, fd, oflags, NULL, &filep);
   ```



##########
libs/libc/stdio/lib_libfread_unlocked.c:
##########
@@ -170,7 +170,9 @@ ssize_t lib_fread_unlocked(FAR void *ptr, size_t count, FAR FILE *stream)
 
                   if (remaining > buffer_available)
                     {
-                      bytes_read = _NX_READ(stream->fs_fd, dest, remaining);
+                      bytes_read = stream->fs_iofunc.read(stream->fs_cookie,
+                                                           (char *)dest,

Review Comment:
   ```suggestion
                                                             (char *)dest,
   ```



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] gregory-nutt commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "gregory-nutt (via GitHub)" <gi...@apache.org>.
gregory-nutt commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324992990


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  FAR void *cookie;                /* Pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* Programmer-defined hook functions */
+  int cookie_fd;                   /* File descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;

Review Comment:
   Are these the user space callbacks you were referring to?  Yes, these are wrong.  This can't work this way there can be no such calls from the kernel address space.
   
   This is similar to the way that the usrsock works.  The usrsock functions are "called" from the OS, but not directly.   Rather, the call data is marshaled through a message interface to the user code.  This is way this should be done as well.  The interface is described in include/nuttx/net/usrsock.h
   
   At one time I wrote some user-space device drivers (character and block) based on the BSD user space drivers, but I don't think those made it into the repository.  The design was similar to the usrsock design.
   



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] gregory-nutt commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "gregory-nutt (via GitHub)" <gi...@apache.org>.
gregory-nutt commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324554592


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   > Ok, you implementation reuse file_operation_s infrastructure, but it mayn't work in protected/kernel mode, since fclosecookie... is part of kernel, but call the callback provided by userspace directly. I would suggest that you have to add these callback to file_struct and call them from libc/stdio directly.
   > 
   > @patacongo what are you thinking?
   
   _[I have not looked at this particular PR, but I can give my usual response when callbacks from the OS are suggested]_
   
   Direct callbacks from the OS into user code have always been forbidden.  I don't think we should permit that now.  Some justifications:
   
   - This is not the POSIX way to do things.  There is no way to do such things under any POSIX OS.  We have always been concerned about POSIX compliant and portability.  Linux code is often ported to NuttX. NuttX code should be runnable on any any POSIX OS as well (with the appropriate drivers).  To accomplish these goals, callbacks must not be used.
   
   - The callback would probably be running on an kernel stack and not the user stack.  In that case, TLS data on the stack would not be accessible.  The callback were asynchronous with the tasking.  A callback is not a context switch; the interrupt user task is still in place and the OS thinks that is that task that is running.  So any OS interactions in this bastardized state could likely be fatal.
   
   - The callback would run at whatever the priority of the calling logic is running at.  This will break real time behavior which must be strict priority-based scheduling.
   
   There are several differ build modes for NuttX:  The FLAT build, the PROTECTED build for better security, and the KERNEL build for full support of processes much like Linux.  In the PROTECTED and KERNEL builds, there are more significant technical issues.
   
   There is some documentation of at least the PROTECTED build here:  https://cwiki.apache.org/confluence/display/NUTTX/NuttX+Protected+Build
   
   - In the PROTECTED and KERNEL build modes, the kernel runs in supervisor mode in a supervisor address space while all user applications run in non-privileged user mode in a user address space.  In the PROTECTED mode, you _could_ call from the kernel supervisor code into user code but this would, however, be a gaping security hole and, hence, must never be done.  Potentially hostile user-supplied code must never run in supervisor mode in this build.
   
   - The KERNEL build differs in that each _process_ has its own address environment and, in this build, the system will crash if such a thing is attempted.  That is because the notification arrives asynchronously with tasking; you never know which process is running and you would call into the wrong address space.  This could be fixed be changing the address environment prior to each callback, that would have big performance and complexity issues.  It is better to do things in the POSIX way.
   
   So even if you use only the FLAT build, direct callbacks from the OS into the user code must be prohibited.  What is the POSIX way of doing an aynchronous notification?  Signals.  In a POSIX OS, you should use standard POSIX signaling and avoid even thinking about callbacks.
   
   Drivers under drivers/ that do asynchronous notifications use signals for this purpose.  Consider drivers/input/button_upper.c.  This is a simple button driver that sends a notification to a user task when a button is pressed or release:
   
   - Look at the function btn_ioctl().  The BTNIOC_REGISTER command is used to register a notification.  The process ID of the user thread is provided and retained for the notification.
   
   - When the button press event occurs, the notification signal is sent in btn_sample().
   
   - A signal handler in the user thread that registered for the notification can then run, in the correct task context, in user mode, and at the correct priority assigned to the task.
   
   This is 100% POSIX and works in all build modes.  It could even be implemented under any other POSIX OS such as Linux.
   
   Signals are only one option.  Below I mention usrsock as a better model to follow.  In that case, I believe that it uses a character driver in kernel space to interact with the user-space socket.
   
   



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1719935387

   > > > You apparently seem focused on avoiding a clean context switch (which I believe is the correct, clean, flexible solution).
   > > 
   > > 
   > > @patacongo My main argument againts hooks you described above (various notifications, events, signal handlers etc.) is that it would lead to additional requirements for user application (different from how `fopencookie` is used in GNU/Linux). I havent had time to go through all code you suggested (graphics etc) so maybe I am missing something. But I think we should keep it in simple `fseak`, `fputs` etc operations.
   > 
   > The marshaled data should be indisguishable from a direct function (provided an intermediate marshaling/de-marshaling,.
   > 
   > My main argument against this approach is that I have not heard any solution that will actually work in all conditions and build modes.
   
   @patacongo I think @michallenc initial design may confuse you. stdio is a pure userspace library, the implementation of fopencookie or fmemopen doesn't need involve any kernel stuff: it's enough to add the callback(read/write/seek/close) to struct file_struct(FILE).
   So, I would suggest you read the manual from:
   https://pubs.opengroup.org/onlinepubs/9699919799/functions/fmemopen.html
   https://man7.org/linux/man-pages/man3/fopencookie.3.html


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] patacongo commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "patacongo (via GitHub)" <gi...@apache.org>.
patacongo commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325337992


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   > Since stdio is a pure usespace library, I would suggest keep all fopencookie related stuff in libc to avoid the complexity of kernel/userspace interactions.
   
   That would not solve the technical problem.  It eliminates the kernal/user privilege issue, but is otherwise insufficient.  That is because the caller executes in Task/Process A but the user-implementation of the file is implemented in a different Task/Process B.  There are lots of problems with that:
   
   - You would be executing code in Task B in the context of Task A.
   - That means Task B would use Task A's stack and file structures, not those of Task B. 
   - The Task B file system code could not access Task B's TLS data .
   - From the standpoint of the OS, Task A is running, not Task B.  Task B could not access the OS as Task B and many things just would not work properly.
   - The logic in Task B would run with with priority and identity of Task A.
   - It would not work at all in the KERNEL build mode because Task B resides in a different process address space than does Task A.  That would crash immediately and dramatically.
   - etc. Many more issues.
   
   I don't believe that any of that behavior is acceptable.
   
   I still believe that the only viable solution must depend on using a proper POSIX IPC like signals, message queues, fifos, local networks, etc.  Then Task B runs in the proper context and address space of Task B.
   



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325342782


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   FILE is private to a specific task/process, it's illegal to share FILE * between the different tasks. So, @patacongo the scenario you describe can never happen.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325602413


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   > Add cookie_io_functions_t to file_struct(FILE)
   Assign the internal callback which read/write/seek through fd to cookie_io_functions_t in fopen
   Assign caller supplied callback in fopencookie
   Replace read/write/seek with cookie_io_functions_t's one
   
   I am not sure this would solve the problem. Because the callback to `fopencookie` would still go through `fs/vfs`. Now this would work in FLAT build but probably not in protected build. What we would need is that `libc` would call the callbacks directly for `FILE *` if custom streams are defined as it is done in ucLibc for example https://elixir.bootlin.com/uclibc-ng/v1.0.7/source/libc/stdio/fread.c#L68 This way we would not need  But that is too big change now.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324109559


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   But I need valid fd to be able to call proper functions, no? `fopencookie` returns `FILE` structure which contains file descriptor. Then if IO operation (lets say `write`) is called, NuttX uses the file descriptor to get `struct file` which contains pointer to `inode` which has `u.i_ops` with IO operations. And this operations lead to private functions in `lib_fopencookie.c`. 
   
   MUSL implementation is a bit different, they have pointers to IO directly in `FILE`, we don´t. So I think we always need file descriptor if we want to get there from `FILE` stream.



##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   But I need valid fd to be able to call proper functions, no? `fopencookie` returns `FILE` structure which contains file descriptor. Then if IO operation (lets say `write`) is called, NuttX uses the file descriptor to get `struct file` which contains pointer to `inode` which has `u.i_ops` with IO operations. And this operations lead to private functions in `lib_fopencookie.c`. 
   
   MUSL implementation is a bit different, they have pointers to IO directly in `FILE`, we don´t. So I think we always need file descriptor if we want to get there from `FILE` stream.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] gregory-nutt commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "gregory-nutt (via GitHub)" <gi...@apache.org>.
gregory-nutt commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324992990


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  FAR void *cookie;                /* Pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* Programmer-defined hook functions */
+  int cookie_fd;                   /* File descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;

Review Comment:
   Are these the user space callbacks you were referring to?  Yes, these are wrong.  This can't work this way there can be no such calls from the kernel address space.
   
   This is similar to the way that the usrsock works.  The usrsock functions are "called" from the OS, but not directly.   Rather, the call data is marshaled through a POSIX driver interface to the user code.  This is way this should be done as well.  The interface is described in include/nuttx/net/usrsock.h
   
   At one time I wrote some user-space device drivers (character and block) based on the BSD user space drivers, but I don't think those made it into the repository.  The design was similar to the usrsock design.
   



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1720389659

   > > This case isn't suitable for stdio functions. How can you pass FILE * from one task/process to other task/process in kernel mode? So it's impossible to call the callback function cross the address space boundary since FILE* return from fopencookie can only be used by the caller's task/process and is always invalid and impossible to pass FILE* to another task/process at the first place.
   > 
   > I don't see the relevance of the FILE*. I was more concerned at the io_funcs and cookie. But looking at the prototype, it seems impossible that the io_funcs could like in a different address space. from the caller of fopencookie().
   
   Yes, this is the key point: both io_funcs and cookie can only be used in the same proccess(address space), which simplify the thing a lot if the implementation can avoid the involve any kernel space stuff.


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1335160010


##########
libs/libc/stdio/lib_stdio_cb.c:
##########
@@ -0,0 +1,76 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_stdio_cb.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 <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lib_fseek_cb
+ ****************************************************************************/
+
+off_t lib_fseek_cb(FAR void *s, off_t offset, int whence)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  return lseek(stream->fs_fd, offset, whence);
+}
+
+/****************************************************************************
+ * Name: lib_fwrite_cb
+ ****************************************************************************/
+
+ssize_t lib_fwrite_cb(FAR void *s, const char *buf, size_t size)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  return _NX_WRITE(stream->fs_fd, buf, size);

Review Comment:
   _NX_WRITE is either write or nx_write based on which mode we are in and whether this is kernel space or user space. STDIO for protected build should be compiled twice, once for kernel and once for user space, therefore macro should decide which function is called.



##########
libs/libc/stdio/lib_stdio_cb.c:
##########
@@ -0,0 +1,76 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_stdio_cb.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 <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lib_fseek_cb
+ ****************************************************************************/
+
+off_t lib_fseek_cb(FAR void *s, off_t offset, int whence)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  return lseek(stream->fs_fd, offset, whence);
+}
+
+/****************************************************************************
+ * Name: lib_fwrite_cb
+ ****************************************************************************/
+
+ssize_t lib_fwrite_cb(FAR void *s, const char *buf, size_t size)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  return _NX_WRITE(stream->fs_fd, buf, size);
+}
+
+/****************************************************************************
+ * Name: lib_fread_cb
+ ****************************************************************************/
+
+ssize_t lib_fread_cb(FAR void *s, char *buf, size_t size)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  return _NX_READ(stream->fs_fd, buf, size);

Review Comment:
   As above



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1350311076


##########
libs/libc/libc.h:
##########
@@ -245,6 +245,13 @@ bool lib_isbasedigit(int ch, int base, FAR int *value);
 
 int lib_checkbase(int base, FAR const char **pptr);
 
+/* Defined in lib_stdio_cb */
+
+ssize_t lib_fread_cb(void *stream, char *buf, size_t size);
+ssize_t lib_fwrite_cb(void *stream, const char *buf, size_t size);
+off_t lib_fseek_cb(void *stream, off_t offset, int whence);

Review Comment:
   Yes, but `lib_fseek_cb` passed to `cookie_seek_function_t` which has to be defined with `off_t` to correspond with fopencookie specification.



##########
libs/libc/stdio/lib_fclose.c:
##########
@@ -129,7 +129,7 @@ int fclose(FAR FILE *stream)
                                                (uintptr_t)stream);
           status = android_fdsan_close_with_tag(stream->fs_fd, tag);
 #else
-          status = close(stream->fs_fd);
+          status = stream->fs_callbacks.close(stream);

Review Comment:
   Done as suggested.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 merged PR #10602:
URL: https://github.com/apache/nuttx/pull/10602


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361805528


##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   Yes, forget it's inside kernel space, but kernel code can't reference libc function directly even the inclusion is added. The better fix should be that fseek/fwrite/fread call lseek/_NX_WRITE/_NX_READ directly if the related callback is NULL.
   so, lib_stdio_cb.c could be removed and move functions inside it to lib_libf[lseek|write|read].c. To distinguish from null callback passed in fopencookie, fopencookie could provide an empty callback.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1363385134


##########
libs/libc/stdio/lib_libfread_unlocked.c:
##########
@@ -46,13 +46,14 @@
 
 ssize_t lib_fread_unlocked(FAR void *ptr, size_t count, FAR FILE *stream)
 {
-  FAR unsigned char *dest = (FAR unsigned char *)ptr;
+  FAR char *dest = (FAR char *)ptr;
   ssize_t bytes_read;
   size_t remaining = count;
 #ifndef CONFIG_STDIO_DISABLE_BUFFERING
   size_t gulp_size;
   int ret;
 #endif
+  int fd = (int)(intptr_t)stream->fs_cookie;

Review Comment:
   Done



##########
libs/libc/stdio/lib_ungetc.c:
##########
@@ -52,7 +52,7 @@ int ungetc(int c, FAR FILE *stream)
 
   /* Stream must be open for read access */
 
-  if ((stream->fs_fd < 0) || ((stream->fs_oflags & O_RDOK) == 0))
+  if (((stream->fs_oflags & O_RDOK) == 0))

Review Comment:
   done



##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,153 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cookie_read_cb
+ ****************************************************************************/
+
+ssize_t cookie_read_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  /* Per specification: if *read is a null pointer, then reads from the
+   * custom stream always return end of file.
+   */
+
+  errno = -EACCES;
+  return -1;
+}
+
+/****************************************************************************
+ * Name: cookie_write_cb
+ ****************************************************************************/
+
+ssize_t cookie_write_cb(FAR void *cookie, FAR const char *buf, size_t size)
+{
+  /* Per specification: if *write is a null pointer, then output to the
+   * stream is discarded.
+   */
+
+  errno = -EBADF;
+  return -1;
+}
+
+/****************************************************************************
+ * Name: cookie_seek_cb
+ ****************************************************************************/
+
+off_t cookie_seek_cb(FAR void *cookie, FAR off_t *offset, int whence)
+{
+  /* Per specification: if *seek is a null pointer, then it is not
+   * possible to perform seek operations on the stream.
+   */
+
+  errno = -EINVAL;
+  return -1;
+}
+
+/****************************************************************************
+ * Name: cookie_close_cb
+ ****************************************************************************/
+
+int cookie_close_cb(FAR void *cookie)
+{
+  return OK;
+}
+

Review Comment:
   done



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361865252


##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   both functions are moved into sched, so the inclusion doesn't need anymore



##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   > `<nuttx/lib/lib.h>` was used to reference `lib_stream_initialize` and `lib_stream_release` before your patch so I am not sure if it is such a problem in this case.
   
   both functions are moved into sched, so the inclusion doesn't need anymore
   
   > Deciding what function is to be called would require some if statements in running code which I would like to avoid.
   
   but you have to do the check since:
   
   1. stdin/stdout/sderr is initialized inside kernel space
   2. The assignment of stdin/stdout/stderr's callback inside kernel space point to the lib_fxxx_cb inside kernel space
   3. fopen/fdopen point lib_fxxx_cb in user space
   
   when user call fwrite/fread on stdin/stdout/stderr, prefetch abort will happen since user space doesn't right to execute the code inside the kernel space.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1753022426

   @xiaoxiang781216 I have updated the implementation and implemented most of your suggestions (see separate comments). There is a new PR in nuttx-apps [add fopecookie test and use fileno interface instead of accessing FILE](https://github.com/apache/nuttx-apps/pull/2112) that adds test application and also fix some `FILE` usage in `system` (this is should be merged before NuttX patch because of CI).


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] gregory-nutt commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "gregory-nutt (via GitHub)" <gi...@apache.org>.
gregory-nutt commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324554592


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   > Ok, you implementation reuse file_operation_s infrastructure, but it mayn't work in protected/kernel mode, since fclosecookie... is part of kernel, but call the callback provided by userspace directly. I would suggest that you have to add these callback to file_struct and call them from libc/stdio directly.
   > 
   > @patacongo what are you thinking?
   
   _[I have not looked at this particular PR, but I can give my usual response when callbacks from the OS are suggested]_
   
   Direct callbacks from the OS into user code have always been forbidden.  I don't think we should permit that now.  Some justifications:
   
   - This is not the POSIX way to do things.  There is no way to do such things under any POSIX OS.  We have always been concerned about POSIX compliant and portability.  Linux code is often ported to NuttX. NuttX code should be runnable on any any POSIX OS as well (with the appropriate drivers).  To accomplish these goals, callbacks must not be used.
   
   - The callback would probably be running on an kernel stack and not the user stack.  In that case, TLS data on the stack would not be accessible.  The callback were asynchronous with the tasking.  A callback is not a context switch; the interrupt user task is still in place and the OS thinks that is that task that is running.  So any OS interactions in this bastardized state could likely be fatal.
   
   - The callback would run at whatever the priority of the calling logic is running at.  This will break real time behavior which must be strict priority-based scheduling.
   
   There are several differ build modes for NuttX:  The FLAT build, the PROTECTED build for better security, and the KERNEL build for full support of processes much like Linux.  In the PROTECTED and KERNEL builds, there are more significant technical issues.
   
   There is some documentation of at least the PROTECTED build here:  https://cwiki.apache.org/confluence/display/NUTTX/NuttX+Protected+Build
   
   - In the PROTECTED and KERNEL build modes, the kernel runs in supervisor mode in a supervisor address space while all user applications run in non-privileged user mode in a user address space.  In the PROTECTED mode, you _could_ call from the kernel supervisor code into user code but this would, however, be a gaping security hole and, hence, must never be done.  Potentially hostile user-supplied code must never run in supervisor mode in this build.
   
   - The KERNEL build differs in that each _process_ has its own address environment and, in this build, the system will crash if such a thing is attempted.  That is because the notification arrives asynchronously with tasking; you never know which process is running and you would call into the wrong address space.  This could be fixed be changing the address environment prior to each callback, that would have big performance and complexity issues.  It is better to do things in the POSIX way.
   
   So even if you use only the FLAT build, direct callbacks from the OS into the user code must be prohibited.  What is the POSIX way of doing an aynchronous notification?  Signals.  In a POSIX OS, you should use standard POSIX signaling and avoid even thinking about callbacks.
   
   Drivers under drivers/ that do asynchronous notifications use signals for this purpose.  Consider drivers/input/button_upper.c.  This is a simple button driver that sends a notification to a user task when a button is pressed or release:
   
   - Look at the function btn_ioctl().  The BTNIOC_REGISTER command is used to register a notification.  The process ID of the user thread is provided and retained for the notification.
   
   - When the button press event occurs, the notification signal is sent in btn_sample().
   
   - A signal handler in the user thread that registered for the notification can then run, in the correct task context, in user mode, and at the correct priority assigned to the task.
   
   This is 100% POSIX and works in all build modes.  It could even be implemented under any other POSIX OS such as Linux.
   
   Signals are only one option.  Below I mention usrsock as a better model to follow.  In that case, I believe that it uses a character driver in kernel space to interact with the user-space socket implementation.
   
   



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] mu578 commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "mu578 (via GitHub)" <gi...@apache.org>.
mu578 commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1722123769

   > > > > This case isn't suitable for stdio functions. How can you pass FILE * from one task/process to other task/process in kernel mode? So it's impossible to call the callback function cross the address space boundary since FILE* return from fopencookie can only be used by the caller's task/process and is always invalid and impossible to pass FILE* to another task/process at the first place.
   > > > 
   > > > 
   > > > I don't see the relevance of the FILE*. I was more concerned at the io_funcs and cookie. But looking at the prototype, it seems impossible that the io_funcs could like in a different address space. from the caller of fopencookie().
   > > 
   > > 
   > > Aggreed, it would require to pound defined and only allowing such APIs in usermode.
   > 
   > Of course, all FILE functions can only be called inside the usermode, NuttX kernel forbid kernel code to use any FILE functions.
   > 
   > > However, it could be doable by making a new vfs interface handling such but it would require a whole revamp and further thoughts to make it possible, as is : it is not hot patchable -> so my proposal to support indirection for user-mode build only, at least it can be undone and evolve without breaking.
   > 
   > @mu578 you may misunderstand NuttX file system:
   > 
   > * nuttx/fs/vfs is the kernel VFS infrastructure, which is part of kernel, it's hard and bad to call the callback provided by userspace
   > * nuttx/libc/stdio is userspace library, which is very simple and common to call the callback provided by userspace
   > 
   > > That is impossible to callback from two distinct regions ; it would require some kind of trampoline jump with copies back and forth. E.g if `function pointers` were actually `just address pointers pointing to an actual somewhere` we would not have this conversation, but the reality is different.
   > 
   > Do you want to implement the userspace file system? NuttX already support it by socket: https://github.com/apache/nuttx/blob/master/include/nuttx/fs/userfs.h
   > 
   > > Myself, I would go to support standard only: `open_memstream` and `fmemopen` ; there is no reason to expose a non standard `fopencookie` call ; the two requires some memory mapping that's it, no callback exposure. It is all about to be able to use FILE api on a user in-memory buffer instead of on a `file descriptor/ino` ; which in case of nuttx is `kif-kif bourricot` a mere detail.
   > 
   > If we want to support all open_memstream/open_wmemstream/fmemopen, it's important to setup a callback infrastructure otherwise fread/fwrite need to add many if/else:
   > 
   > ```
   > if (file handle)
   >   {
   >     ...
   >   }
   > else if (mem handle)
   >   {
   >     ...
   >   }
   > else if (xxx handle)
   >   {
   >     ...
   >   }
   > ```
   > 
   > If we need to add the callback to FILE, why not follow fopencookie which exist in most libc implementation(glibc, newlib, *BSD), but add a NuttX specific function instead? I don't see any benefit.
   
   I fully understand vfs. 


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] mu578 commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "mu578 (via GitHub)" <gi...@apache.org>.
mu578 commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1719938788

   > > I once had a look at that to handle a `fomempen` and alike properly, it would require that LIBC `struct FILE` not to be a direct alias to internal FS struct, as indeed you need to keep a reference to fs operation callbacks and permission flags, so it would require an indirection where `struct FILE` holds a private pointer to internal. Meanwhile, I think LIBC stdio would benefit at term that indirection to be made.
   > > ```c
   > > struct libc_stdio_file
   > > {
   > >   // ... stdio specifics;
   > >   libc_stdio_fread_t  read;
   > >   libc_stdio_fwrite_t write;
   > >   libc_stdio_fseek_t  seek;
   > >   libc_stdio_fclose_t close;
   > >   libc_stdio_cookie_t cookie;
   > > 
   > >   file_struct *       internal;
   > > }
   > > 
   > > typedef libc_stdio_file FILE;
   > > ```
   > 
   > we don't need add a new struct libc_stdio_file. Here is the current definition:
   > 
   > ```
   > struct file_struct
   > {
   >   FAR struct file_struct *fs_next;      /* Pointer to next file stream */
   >   rmutex_t                fs_lock;      /* Recursive lock */
   >   int                     fs_fd;        /* File descriptor associated with stream */
   > #ifndef CONFIG_STDIO_DISABLE_BUFFERING
   >   FAR unsigned char      *fs_bufstart;  /* Pointer to start of buffer */
   >   FAR unsigned char      *fs_bufend;    /* Pointer to 1 past end of buffer */
   >   FAR unsigned char      *fs_bufpos;    /* Current position in buffer */
   >   FAR unsigned char      *fs_bufread;   /* Pointer to 1 past last buffered read char. */
   > #  if CONFIG_STDIO_BUFFER_SIZE > 0
   >   unsigned char           fs_buffer[CONFIG_STDIO_BUFFER_SIZE];
   > #  endif
   > #endif
   >   uint16_t                fs_oflags;    /* Open mode flags */
   >   uint8_t                 fs_flags;     /* Stream flags */
   > #if CONFIG_NUNGET_CHARS > 0
   >   uint8_t                 fs_nungotten; /* The number of characters buffered for ungetc */
   >   unsigned char           fs_ungotten[CONFIG_NUNGET_CHARS];
   > #endif
   > };
   > 
   > typedef struct file_struct FILE;
   > ```
   > 
   > Here is the simple change to the struct:
   > 
   > ```
   > struct file_struct
   > {
   >   ...
   > -  int                     fs_fd;        /* File descriptor associated with stream */
   > +  cookie_io_functions_t fs_iofunc;
   > +  FAR void *            fs_cookie;
   >   ...
   > };
   > ```
   > 
   > and replace all read/write/seek/close with stream->iofunc.read/write/seek/close. The remaining work is adding the simple wrapper for fopen:
   > 
   > ```
   > static ssize_t read_fd(void *cookie, char *buf, size_t size)
   > {
   >   int fd = (int)(intptr_t)cookie;
   >   return read(fd, buf, size);
   > }
   > 
   > static ssize_t write_fd(void *cookie, const char *buf, size_t size)
   > {
   >   int fd = (int)(intptr_t)cookie;
   >   return write(fd, buf, size);
   > }
   > 
   > static int seek_fd(void *cookie, off_t *offset, int whence)
   > {
   >   int fd = (int)(intptr_t)cookie;
   >   off_t ret = seek(fd, *offset, whence);
   >   if (ret >= 0)
   >     {
   >       *offset = ret;
   >       ret = 0;
   >     }
   > 
   >   return ret;
   > }
   > ```
   
   you would if want to keep separated internal implementation to actual in-memory Os layout and a libc stdio frontend. Indeed `nutxx/fs.h` is one possible core-stream handling implementation, you don't want to mixup ; theoretically you could swap to any `OS vfs` implementation without changing any of your LIBC frontend. 
   
   `fopencookie` is a solution/vilain patch which only regards end-user and a LIBC frontend to address the implementation of open_memstream and fmemopen, nuttx_file_struct should remain agnostic to such concerns, now I don't say it could be smarter and hold default callback pointers, the problem: the ones defined by `fopencookie` do not match exactly.
   
   But again do not hot patch such.
   
   
   
   


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1719917277

   > I once had a look at that to handle a `fomempen` and alike properly, it would require that LIBC `struct FILE` not to be a direct alias to internal FS struct, as indeed you need to keep a reference to fs operation callbacks and permission flags, so it would require an indirection where `struct FILE` holds a private pointer to internal. Meanwhile, I think LIBC stdio would benefit at term that indirection to be made.
   > 
   > ```c
   > struct libc_stdio_file
   > {
   >   // ... stdio specifics;
   >   libc_stdio_fread_t  read;
   >   libc_stdio_fwrite_t write;
   >   libc_stdio_fseek_t  seek;
   >   libc_stdio_fclose_t close;
   >   libc_stdio_cookie_t cookie;
   > 
   >   file_struct *       internal;
   > }
   > 
   > typedef libc_stdio_file FILE;
   > ```
   
   we don't need add a new struct libc_stdio_file. Here is the current definition:
   ```
   struct file_struct
   {
     FAR struct file_struct *fs_next;      /* Pointer to next file stream */
     rmutex_t                fs_lock;      /* Recursive lock */
     int                     fs_fd;        /* File descriptor associated with stream */
   #ifndef CONFIG_STDIO_DISABLE_BUFFERING
     FAR unsigned char      *fs_bufstart;  /* Pointer to start of buffer */
     FAR unsigned char      *fs_bufend;    /* Pointer to 1 past end of buffer */
     FAR unsigned char      *fs_bufpos;    /* Current position in buffer */
     FAR unsigned char      *fs_bufread;   /* Pointer to 1 past last buffered read char. */
   #  if CONFIG_STDIO_BUFFER_SIZE > 0
     unsigned char           fs_buffer[CONFIG_STDIO_BUFFER_SIZE];
   #  endif
   #endif
     uint16_t                fs_oflags;    /* Open mode flags */
     uint8_t                 fs_flags;     /* Stream flags */
   #if CONFIG_NUNGET_CHARS > 0
     uint8_t                 fs_nungotten; /* The number of characters buffered for ungetc */
     unsigned char           fs_ungotten[CONFIG_NUNGET_CHARS];
   #endif
   };
   
   typedef struct file_struct FILE;
   ```
   Here is the simple change to the struct:
   ```
   struct file_struct
   {
     ...
   -  int                     fs_fd;        /* File descriptor associated with stream */
   +  cookie_io_functions_t fs_iofunc;
   +  FAR void *            fs_cookie;
   ```
   };
   ```
   and replace all read/write/seek/close with stream->iofunc.read/write/seek/close.
   The remaining work is adding the simple wrapper for fopen:
   ```
   static ssize_t read_fd(void *cookie, char *buf, size_t size)
   {
     int fd = (int)(intptr_t)cookie;
     return read(fd, buf, size);
   }
   
   static ssize_t write(void *cookie, const char *buf, size_t size)
   {
     int fd = (int)(intptr_t)cookie;
     return write(fd, buf, size);
   }
   
   static int seek(void *cookie, off_t *offset, int whence)
   {
     int fd = (int)(intptr_t)cookie;
     off_t ret = seek(fd, *offset, whence);
     if (ret >= 0)
       {
         *offset = ret;
         ret = 0;
       }
   
     return ret;
   }
   ```


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1350712432


##########
fs/vfs/fs_fdopen.c:
##########
@@ -120,7 +120,7 @@ int fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb,
 
   /* Check input parameters */
 
-  if (fd < 0)
+  if (fd < 0 && cookie == 0)

Review Comment:
   @xiaoxiang781216 This is basically just a information passed to fs_fdopen that initialization is done for fopencookie (1 true) and not standard stream (0 false). It is not to pass the pointer to cookie. The implementation with pointer to cookie would be tricky because we need valid fd to pass the checks (and we need -1 reserved if open call returns error). This adds two more if statements but does not complicate the code more. Applies to most other comments.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1335166887


##########
libs/libc/stdio/lib_stdio_cb.c:
##########
@@ -0,0 +1,76 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_stdio_cb.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 <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lib_fseek_cb
+ ****************************************************************************/
+
+off_t lib_fseek_cb(FAR void *s, off_t offset, int whence)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  return lseek(stream->fs_fd, offset, whence);
+}
+
+/****************************************************************************
+ * Name: lib_fwrite_cb
+ ****************************************************************************/
+
+ssize_t lib_fwrite_cb(FAR void *s, const char *buf, size_t size)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  return _NX_WRITE(stream->fs_fd, buf, size);

Review Comment:
   stdio shouldn't be called inside kernel space, so _NX_WRITE isn't needed.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1335159579


##########
include/nuttx/fs/fs.h:
##########
@@ -497,6 +546,8 @@ struct file_struct
   FAR struct file_struct *fs_next;      /* Pointer to next file stream */
   rmutex_t                fs_lock;      /* Recursive lock */
   int                     fs_fd;        /* File descriptor associated with stream */

Review Comment:
   This should not be needed since I would pass the entire stream to internal callback.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1335159845


##########
libs/libc/stdio/lib_fclose.c:
##########
@@ -129,7 +129,7 @@ int fclose(FAR FILE *stream)
                                                (uintptr_t)stream);
           status = android_fdsan_close_with_tag(stream->fs_fd, tag);
 #else
-          status = close(stream->fs_fd);
+          status = stream->fs_callbacks.close(stream);

Review Comment:
   as mentioned above, I would pass stream



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1764104984

   > @michallenc but, the ci still fail, could you take a look?
   
   Yes, I fixed some on Saturday but I suppose the rest is somehow related to change to `fs_fdopen` which should be (at least partially) fixed by the update from your patch a remove of `fs_fdopen`.
   


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361756207


##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   `libc.h `cannot be accessed from `sched/`, no?



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361823886


##########
include/nuttx/fs/fs.h:
##########
@@ -425,6 +425,31 @@ struct inode
 
 #define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
 
+/* Definitions for custom stream operations with fopencookie. The
+ * implementation is as defined in Standard C library (libc). The only
+ * difference is that we use off_t instead of off64_t. This means
+ * off_t is int64_t if CONFIG_FS_LARGEFILE is defined and int32_t if not.
+ *
+ * These callbacks can either lead to custom functions if fopencookie is used
+ * or to standard file system functions if not.
+ */
+
+typedef CODE ssize_t cookie_read_function_t(void *cookie, char *buf,

Review Comment:
   Done, seems i havent commited it.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361866400


##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   @xiaoxiang781216 Why should this be a problem for protected and kernel build? In that case libc is compiled twice, once for user and once for kernel. So kernel would still have valid references (separate from user).



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361855494


##########
libs/libc/stdio/lib_setvbuf.c:
##########
@@ -133,7 +134,7 @@ int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size)
 
   /* Return EBADF if the file is not open */
 
-  if (stream->fs_fd < 0)
+  if (fd < 0)

Review Comment:
   Ok, removed.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1764151278

   Ok, let's wait the merging of #10913, so you can move the FILE allocation to fopencookie.


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361721417


##########
include/nuttx/fs/fs.h:
##########
@@ -426,6 +426,31 @@ struct inode
 
 #define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
 
+/* Definitions for custom stream operations with fopencookie. The
+ * implementation is as defined in Standard C library (libc). The only
+ * difference is that we use off_t instead of off64_t. This means
+ * off_t is int64_t if CONFIG_FS_LARGEFILE is defined and int32_t if not.
+ *
+ * These callbacks can either lead to custom functions if fopencookie is used
+ * or to standard file system functions if not.
+ */
+
+typedef CODE ssize_t cookie_read_function_t(void *cookie, char *buf,
+                                            size_t size);
+typedef CODE ssize_t cookie_write_function_t(void *cookie, const char *buf,
+                                             size_t size);
+typedef CODE off_t cookie_seek_function_t(void *cookie, off_t *offset,
+                                     int whence);

Review Comment:
   align



##########
libs/libc/stdio/lib_libfflush.c:
##########
@@ -107,7 +107,9 @@ ssize_t lib_fflush_unlocked(FAR FILE *stream, bool bforce)
         {
           /* Perform the write */
 
-          bytes_written = _NX_WRITE(stream->fs_fd, src, nbuffer);
+          bytes_written = stream->fs_iofunc.write(stream->fs_cookie,
+                                                  (const char *)src,

Review Comment:
   can we change the type at line 62 to avoid the cast



##########
libs/libc/stdio/lib_ungetc.c:
##########
@@ -52,7 +53,7 @@ int ungetc(int c, FAR FILE *stream)
 
   /* Stream must be open for read access */
 
-  if ((stream->fs_fd < 0) || ((stream->fs_oflags & O_RDOK) == 0))
+  if ((fd < 0) || ((stream->fs_oflags & O_RDOK) == 0))

Review Comment:
   should we allow cookie case? which may pass in the negative value



##########
libs/libc/stdio/lib_libfgets.c:
##########
@@ -97,10 +97,11 @@ FAR char *lib_fgets_unlocked(FAR char *buf, size_t buflen, FILE *stream,
                              bool keepnl, bool consume)
 {
   size_t nch = 0;
+  int fd = (int)(intptr_t)stream->fs_cookie;
 
   /* Sanity checks */
 
-  if (!stream || !buf || stream->fs_fd < 0)
+  if (!stream || !buf || fd < 0)

Review Comment:
   should we allow cookie < 0?



##########
include/nuttx/fs/fs.h:
##########
@@ -425,6 +425,31 @@ struct inode
 
 #define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
 
+/* Definitions for custom stream operations with fopencookie. The
+ * implementation is as defined in Standard C library (libc). The only
+ * difference is that we use off_t instead of off64_t. This means
+ * off_t is int64_t if CONFIG_FS_LARGEFILE is defined and int32_t if not.
+ *
+ * These callbacks can either lead to custom functions if fopencookie is used
+ * or to standard file system functions if not.
+ */
+
+typedef CODE ssize_t cookie_read_function_t(void *cookie, char *buf,

Review Comment:
   but, not change



##########
libs/libc/stdio/lib_libfread_unlocked.c:
##########
@@ -213,9 +215,9 @@ ssize_t lib_fread_unlocked(FAR void *ptr, size_t count, FAR FILE *stream)
                        * into the buffer.
                        */
 
-                      bytes_read = _NX_READ(stream->fs_fd,
-                                            stream->fs_bufread,
-                                            buffer_available);
+                      bytes_read = stream->fs_iofunc.read(stream->fs_cookie,
+                                              (char *)stream->fs_bufread,

Review Comment:
   could we change fs_bufread type to char * to avoid the cast



##########
libs/libc/stdio/lib_fclose.c:
##########
@@ -115,32 +115,18 @@ int fclose(FAR FILE *stream)
 
       nxmutex_unlock(&slist->sl_lock);
 
-      /* Check that the underlying file descriptor corresponds to an an open
-       * file.
-       */
-
-      if (stream->fs_fd >= 0)
-        {
-          /* Close the file descriptor and save the return status */
+      /* Close the file descriptor and save the return status */
 
-#ifdef CONFIG_FDSAN
-          uint64_t tag;
-          tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_FILE,
-                                               (uintptr_t)stream);
-          status = android_fdsan_close_with_tag(stream->fs_fd, tag);
-#else
-          status = close(stream->fs_fd);
-#endif
+      status = stream->fs_iofunc.close(stream->fs_cookie);

Review Comment:
   should we check close != NULL before calling, or fill the empty callback function in fopencookie



##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   change to libc.h



##########
libs/libc/stdio/lib_setvbuf.c:
##########
@@ -133,7 +134,7 @@ int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size)
 
   /* Return EBADF if the file is not open */
 
-  if (stream->fs_fd < 0)
+  if (fd < 0)

Review Comment:
   should we allow for cookie case



##########
libs/libc/stdio/lib_libfread_unlocked.c:
##########
@@ -170,7 +170,9 @@ ssize_t lib_fread_unlocked(FAR void *ptr, size_t count, FAR FILE *stream)
 
                   if (remaining > buffer_available)
                     {
-                      bytes_read = _NX_READ(stream->fs_fd, dest, remaining);
+                      bytes_read = stream->fs_iofunc.read(stream->fs_cookie,
+                                                          (char *)dest,

Review Comment:
   can we change the type at line 49 to avoid the cast



##########
libs/libc/stdio/lib_libfwrite.c:
##########
@@ -132,7 +132,8 @@ ssize_t lib_fwrite_unlocked(FAR const void *ptr, size_t count,
 
   if (count >= CONFIG_STDIO_BUFFER_SIZE)
     {
-      ret = _NX_WRITE(stream->fs_fd, src, count);
+      ret = stream->fs_iofunc.write(stream->fs_cookie, (const char *)src,

Review Comment:
   change src type to avoid the cast



##########
libs/libc/stdio/lib_libfread_unlocked.c:
##########
@@ -258,7 +260,9 @@ ssize_t lib_fread_unlocked(FAR void *ptr, size_t count, FAR FILE *stream)
 
           while (remaining > 0)
             {
-              bytes_read = _NX_READ(stream->fs_fd, dest, remaining);
+              bytes_read = stream->fs_iofunc.read(stream->fs_cookie,
+                                                  (char *)dest,

Review Comment:
   ditto



##########
libs/libc/stdio/lib_libfread_unlocked.c:
##########
@@ -213,9 +215,9 @@ ssize_t lib_fread_unlocked(FAR void *ptr, size_t count, FAR FILE *stream)
                        * into the buffer.
                        */
 
-                      bytes_read = _NX_READ(stream->fs_fd,
-                                            stream->fs_bufread,
-                                            buffer_available);
+                      bytes_read = stream->fs_iofunc.read(stream->fs_cookie,
+                                              (char *)stream->fs_bufread,

Review Comment:
   but, need add FAR



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361877829


##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   > `<nuttx/lib/lib.h>` was used to reference `lib_stream_initialize` and `lib_stream_release` before your patch so I am not sure if it is such a problem in this case.
   
   both functions are moved into sched, so the inclusion doesn't need anymore
   
   > Deciding what function is to be called would require some if statements in running code which I would like to avoid.
   
   but you have to do the check since:
   
   1. stdin/stdout/sderr is initialized inside kernel space
   2. The assignment of stdin/stdout/stderr's callback inside kernel space point to the lib_fxxx_cb copy which is part of kernel space
   3. fopen/fdopen point lib_fxxx_cb in user space
   
   when user call fwrite/fread on stdin/stdout/stderr, prefetch abort will happen since user space doesn't right to execute the code inside the kernel space.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1360401137


##########
fs/vfs/fs_fdopen.c:
##########
@@ -120,7 +120,7 @@ int fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb,
 
   /* Check input parameters */
 
-  if (fd < 0)
+  if (fd < 0 && cookie == 0)

Review Comment:
   That looks good, I will update the patch once yours is merged.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] patacongo commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "patacongo (via GitHub)" <gi...@apache.org>.
patacongo commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1719968467

   > @patacongo I think @michallenc initial design may confuse you. stdio is a pure userspace library, the implementation of fopencookie or fmemopen doesn't need involve any kernel stuff: it's enough to add the callback(read/write/seek/close) to struct file_struct(FILE).
   > So, I would suggest you read the manual from:
   > https://pubs.opengroup.org/onlinepubs/9699919799/functions/fmemopen.html
   > https://man7.org/linux/man-pages/man3/fopencookie.3.html
   
   AFAIK that is not true.  The user/supervisor mode is only one of several issues.  I have enumerated many others below that this design pure user-space design will not handle.  The bottom line:  You cannot call from one task/process address space into another.  In the FLAT build, that might work in some very, very simple cases.  But it will not work in general.  It will never work at all in the KERNEL build if the client and server lie in different process address spaces.  The virtual user address spaces overlap and it you try calling into it you will certainly crash.
   
   In order to that successfully and reliably, a context switch is required.
   
   I don't see any reason for me to participate in this any further.  I've tried to explain all of this as carefully as I can but I still see you guys marching ahead to fall off the cliff.
   


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1719956373

   
   > you would if you want to keep separated internal implementation to actual in-memory Os layout and a libc stdio frontend concern.
   > 
   > Indeed `nutxx/fs.h` is one possible core-stream handling implementation, you don't want to mixup ;
   
   If you don't like file_struct is contained in nuttx/fs.h, the right fix is moving it to stdio.h, but don't create a new libc_stdio_file since libc_stdio_file lack many fields which is required to implement buffer I/O and fungetc etc.
   
   > theoretically, you could swap to any `OS vfs` implementation without changing any of your LIBC frontend.
   > 
   
   `struct file_struct` is designed to work with stdio, `struct file` is designed to work with vfs. Please don't confuse them.
   


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] gregory-nutt commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "gregory-nutt (via GitHub)" <gi...@apache.org>.
gregory-nutt commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324969904


##########
include/stdio.h:
##########
@@ -244,6 +244,11 @@ int    dprintf(int fd, FAR const IPTR char *fmt, ...) printf_like(2, 3);
 int    vdprintf(int fd, FAR const IPTR char *fmt, va_list ap)
        printf_like(2, 0);
 
+/* Custom stream operation fopencookie. */
+
+FAR FILE *fopencookie(FAR void *cookie, FAR const char *mode,
+                      cookie_io_functions_t io_funcs);
+

Review Comment:
   It is prohibited to add non-standard interfaces to the OS.  We are purely standards based and non-standard, ad hoc OS interfaces are generally prohibited.
   
   Hmm... I see that Linux does support this interface:  https://man7.org/linux/man-pages/man3/fopencookie.3.html .. Is that a sufficient justification?  The man page lists only GNU as the justification for the interface.  That would not have been accepted in the past, but an objective to have Linux compatibility has crept into our project mindset recently.  So maybe this is okay for that reason.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325635975


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   > > Add cookie_io_functions_t to file_struct(FILE)
   > > Assign the internal callback which read/write/seek through fd to cookie_io_functions_t in fopen
   > > Assign caller supplied callback in fopencookie
   > > Replace read/write/seek with cookie_io_functions_t's one
   > 
   > I am not sure this would solve the problem. Because the callback to `fopencookie` would still go through `fs/vfs`.
   
   In my suggestion, you should stop to implement file_operation_s and call file_allocate_from_tcb. How do you go through fs/vfs?
   
   > Now this would work in FLAT build but probably not in protected build. What we would need is that `libc` would call the callbacks directly for `FILE *` if custom streams are defined as it is done in ucLibc for example https://elixir.bootlin.com/uclibc-ng/v1.0.7/source/libc/stdio/fread.c#L68 This way we would not need But that is too big change now.
   
   This is the right way to go, and most change(bunch of rename) is minor.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] gregory-nutt commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "gregory-nutt (via GitHub)" <gi...@apache.org>.
gregory-nutt commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1719921329

   > > You apparently seem focused on avoiding a clean context switch (which I believe is the correct, clean, flexible solution).
   > 
   > @patacongo My main argument againts hooks you described above (various notifications, events, signal handlers etc.) is that it would lead to additional requirements for user application (different from how `fopencookie` is used in GNU/Linux). I havent had time to go through all code you suggested (graphics etc) so maybe I am missing something. But I think we should keep it in simple `fseak`, `fputs` etc operations.
   
   The marshaled data should be indisguishable from a direct function (provided an intermediate marshaling/de-marshaling,.
   
   My main argument against this approach is that I have not heard any solution that will actually work in all conditions and build modes.
   


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1720749268

   To summarize the so far discussion a bit:
   
   The problem discussed here is a that this implementation reuses `file_operation_s` infrastructure which is a part of a file system (thus kernel address space) which is my fault as I haven´t realize during the implementation that the reuse of current infrastructure would lead to this.
   
   I quite like the proposition of reworked/new file system @mu578 suggested but as he mentioned, it is not a stuff for one patch and probably should be discussed on a mailing list first. I also do not agree with the statement 
   
   > Myself, I would go to support standard only: open_memstream and fmemopen ; there is no reason to expose a non standard fopencookie call ; the two requires some memory mapping that's it, no callback exposure.
   
   as `fopencookie` can be beneficial for programmers (maybe even more than `fmemopen`). And while not being POSIX, we should keep in mind the NuttX compatibility with Linux imho. Also if done correctly, `fopencookie` can be used both as libc call available for programmers and internal hook for `fopencookie` and `open_memstream`.
   
   Regarding kernel protected builds, address space (and also priorities to keep strict scheduling), I think it should be sufficient to ensure user calls read/write/seek/close do not enter kernel space i.e. `fs/vfs` when used with `fopencookie`. In that case all code would remain in stdio libc library and would be purely user space therefore none of the mentioned issues should occur. I would go with @xiaoxiang781216 suggested implementation for that and we will see where it leads.


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] patacongo commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "patacongo (via GitHub)" <gi...@apache.org>.
patacongo commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325337992


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   > Since stdio is a pure usespace library, I would suggest keep all fopencookie related stuff in libc to avoid the complexity of kernel/userspace interactions.
   
   That would not solve the technical problem.  It eliminates the kernal/user privilege issue, but is otherwise insufficient.  That is because the caller executes in Task/Process A but the user-implementation of the file is implemented in a different Task/Process B.  There are lots of problems with that:
   
   - You would be executing code in Task B in the context of Task A.
   - That means Task B would use Task A's stack and file structures, not those of Task B. 
   - The Task B file system code could not access Task B's TLS data .
   - From the standpoint of the OS, Task A is running, not Task B.  Task B could not access the OS as Task B and many things just would not work properly.
   - The logic in Task B would run with with priority and identity of Task A.
   - It would not work at all in the KERNEL build mode because Task B resides in a different process address space than does Task A.  That would crash immediately and dramatically.
   - etc. Many more issues.
   
   I don't believe that any of that behavior is acceptable.  There is really no situation where can generally call from code in one task into code in another task, regardless of kernel/user privileges or of build mode (although the probably is completely insurmountable in the KERNEL build mode).
   
   I still believe that the only viable solution must depend on using a proper POSIX IPC like signals, message queues, fifos, local networks, etc.  Then Task B runs in the proper context and address space of Task B.
   



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1335160098


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,181 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR void *s, FAR char *buf, size_t nbytes);
+static ssize_t fwritecookie(FAR void *s, FAR const char *buf, size_t nbytes);
+static off_t fseekcookie(FAR void *s, off_t offset, int whence);
+static int fclosecookie(FAR void *s);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static FAR FILE *fopencookie_init_stream(int oflags)
+{
+  FAR FILE *stream;
+
+  stream = lib_zalloc(sizeof(FILE));

Review Comment:
   I cannot call fs_fdopen without valid fd.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1335167602


##########
include/nuttx/fs/fs.h:
##########
@@ -497,6 +546,8 @@ struct file_struct
   FAR struct file_struct *fs_next;      /* Pointer to next file stream */
   rmutex_t                fs_lock;      /* Recursive lock */
   int                     fs_fd;        /* File descriptor associated with stream */

Review Comment:
   but the current design waste the memory:
   
   1. fs_fd dup with fs_cookie.cookie
   2. fs_callbacks dup with fs_cookie.cookie_io
   
   total bytes equal to 20(32bit) or 36(64bit).



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361756207


##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   `libc.h` cannot be accessed from `sched/`, no?



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361877829


##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   > `<nuttx/lib/lib.h>` was used to reference `lib_stream_initialize` and `lib_stream_release` before your patch so I am not sure if it is such a problem in this case.
   
   both functions are moved into sched, so the inclusion doesn't need anymore
   
   > Deciding what function is to be called would require some if statements in running code which I would like to avoid.
   
   but you have to do th check since:
   
   1. stdin/stdout/sderr is initialized inside kernel space
   2. The assignment of stdin/stdout/stderr's callback inside kernel space point to the lib_fxxx_cb inside kernel space
   3. fopen/fdopen point lib_fxxx_cb in user space
   
   when user call fwrite/fread on stdin/stdout/stderr, prefetch abort will happen since user space doesn't right to execute the code inside the kernel space.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1363400282


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,156 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cookie_read_cb
+ ****************************************************************************/
+
+static ssize_t cookie_read_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  /* Per specification: if *read is a null pointer, then reads from the
+   * custom stream always return end of file.
+   */
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: cookie_write_cb
+ ****************************************************************************/
+
+static ssize_t cookie_write_cb(FAR void *cookie, FAR const char *buf,
+                               size_t size)
+{
+  /* Per specification: if *write is a null pointer, then output to the
+   * stream is discarded.
+   */
+
+  return 0;

Review Comment:
   need return size here



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1765834322

   > @michallenc #10913 was merged, you can rebase your patch on top of it now.
   
   @xiaoxiang781216 Updated. Local CI runs were successful, lets see what GitHub CI does. 


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1363005948


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,153 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cookie_read_cb
+ ****************************************************************************/
+
+ssize_t cookie_read_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  /* Per specification: if *read is a null pointer, then reads from the
+   * custom stream always return end of file.
+   */
+
+  errno = -EACCES;
+  return -1;
+}
+
+/****************************************************************************
+ * Name: cookie_write_cb
+ ****************************************************************************/
+
+ssize_t cookie_write_cb(FAR void *cookie, FAR const char *buf, size_t size)
+{
+  /* Per specification: if *write is a null pointer, then output to the
+   * stream is discarded.
+   */
+
+  errno = -EBADF;
+  return -1;
+}
+
+/****************************************************************************
+ * Name: cookie_seek_cb
+ ****************************************************************************/
+
+off_t cookie_seek_cb(FAR void *cookie, FAR off_t *offset, int whence)
+{
+  /* Per specification: if *seek is a null pointer, then it is not
+   * possible to perform seek operations on the stream.
+   */
+
+  errno = -EINVAL;

Review Comment:
   -ENOSUP or -ENOSYS?



##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,153 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cookie_read_cb
+ ****************************************************************************/
+
+ssize_t cookie_read_cb(FAR void *cookie, FAR char *buf, size_t size)

Review Comment:
   add static for ALL dummy function.



##########
libs/libc/stdio/lib_libfread_unlocked.c:
##########
@@ -46,13 +46,14 @@
 
 ssize_t lib_fread_unlocked(FAR void *ptr, size_t count, FAR FILE *stream)
 {
-  FAR unsigned char *dest = (FAR unsigned char *)ptr;
+  FAR char *dest = (FAR char *)ptr;
   ssize_t bytes_read;
   size_t remaining = count;
 #ifndef CONFIG_STDIO_DISABLE_BUFFERING
   size_t gulp_size;
   int ret;
 #endif
+  int fd = (int)(intptr_t)stream->fs_cookie;

Review Comment:
   need move to line 72 since we can known stream 
   isn't NULL only after line 60



##########
libs/libc/stdio/lib_fclose.c:
##########
@@ -64,6 +64,7 @@ int fclose(FAR FILE *stream)
   int errcode = EINVAL;
   int ret = ERROR;
   int status;
+  int fd = (int)(intptr_t)stream->fs_cookie;

Review Comment:
   move after line 126 since stream may be NULL.



##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,153 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cookie_read_cb
+ ****************************************************************************/
+
+ssize_t cookie_read_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  /* Per specification: if *read is a null pointer, then reads from the
+   * custom stream always return end of file.
+   */

Review Comment:
   so, we should return 0 without touching errno



##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,153 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cookie_read_cb
+ ****************************************************************************/
+
+ssize_t cookie_read_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  /* Per specification: if *read is a null pointer, then reads from the
+   * custom stream always return end of file.
+   */
+
+  errno = -EACCES;
+  return -1;
+}
+
+/****************************************************************************
+ * Name: cookie_write_cb
+ ****************************************************************************/
+
+ssize_t cookie_write_cb(FAR void *cookie, FAR const char *buf, size_t size)
+{
+  /* Per specification: if *write is a null pointer, then output to the
+   * stream is discarded.
+   */
+
+  errno = -EBADF;
+  return -1;
+}
+
+/****************************************************************************
+ * Name: cookie_seek_cb
+ ****************************************************************************/
+
+off_t cookie_seek_cb(FAR void *cookie, FAR off_t *offset, int whence)
+{
+  /* Per specification: if *seek is a null pointer, then it is not
+   * possible to perform seek operations on the stream.
+   */
+
+  errno = -EINVAL;
+  return -1;
+}
+
+/****************************************************************************
+ * Name: cookie_close_cb
+ ****************************************************************************/
+
+int cookie_close_cb(FAR void *cookie)
+{
+  return OK;
+}
+

Review Comment:
   add public section banner



##########
libs/libc/stdio/lib_ungetc.c:
##########
@@ -52,7 +52,7 @@ int ungetc(int c, FAR FILE *stream)
 
   /* Stream must be open for read access */
 
-  if ((stream->fs_fd < 0) || ((stream->fs_oflags & O_RDOK) == 0))
+  if (((stream->fs_oflags & O_RDOK) == 0))

Review Comment:
   remove the extra ()



##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,153 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cookie_read_cb
+ ****************************************************************************/
+
+ssize_t cookie_read_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  /* Per specification: if *read is a null pointer, then reads from the
+   * custom stream always return end of file.
+   */
+
+  errno = -EACCES;
+  return -1;
+}
+
+/****************************************************************************
+ * Name: cookie_write_cb
+ ****************************************************************************/
+
+ssize_t cookie_write_cb(FAR void *cookie, FAR const char *buf, size_t size)
+{
+  /* Per specification: if *write is a null pointer, then output to the
+   * stream is discarded.

Review Comment:
   so, we should return size



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361805528


##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   Yes, forget it's inside kernel space, but kernel code can't reference libc function directly even th inclusion is added. The better fix should be that seek/fwrite/fread call lseek/_NX_WRITE/_NX_READ directly if the related callback is NULL.



##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   Yes, forget it's inside kernel space, but kernel code can't reference libc function directly even the inclusion is added. The better fix should be that seek/fwrite/fread call lseek/_NX_WRITE/_NX_READ directly if the related callback is NULL.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1359764221


##########
libs/libc/stdio/lib_libfread_unlocked.c:
##########
@@ -213,9 +215,9 @@ ssize_t lib_fread_unlocked(FAR void *ptr, size_t count, FAR FILE *stream)
                        * into the buffer.
                        */
 
-                      bytes_read = _NX_READ(stream->fs_fd,
-                                            stream->fs_bufread,
-                                            buffer_available);
+                      bytes_read = stream->fs_iofunc.read(stream->fs_cookie,
+                                              (char *)stream->fs_bufread,

Review Comment:
   ok



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1360449576


##########
libs/libc/stdio/lib_fclose.c:
##########
@@ -115,32 +115,41 @@ int fclose(FAR FILE *stream)
 
       nxmutex_unlock(&slist->sl_lock);
 
-      /* Check that the underlying file descriptor corresponds to an an open
-       * file.
-       */
+      /* Close the file descriptor and save the return status */
 
-      if (stream->fs_fd >= 0)
+#ifdef CONFIG_FDSAN
+      if (stream->fs_hascookie == 0)
         {
-          /* Close the file descriptor and save the return status */
+          /* This is a little warkaround. Ideally we would want to call
+           * fs_iofunc.close and let that handle it. FDSAN however requires
+           * stream to create owner tag and this is not avalialble in

Review Comment:
   Done



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361824618


##########
libs/libc/stdio/lib_fclose.c:
##########
@@ -115,32 +115,18 @@ int fclose(FAR FILE *stream)
 
       nxmutex_unlock(&slist->sl_lock);
 
-      /* Check that the underlying file descriptor corresponds to an an open
-       * file.
-       */
-
-      if (stream->fs_fd >= 0)
-        {
-          /* Close the file descriptor and save the return status */
+      /* Close the file descriptor and save the return status */
 
-#ifdef CONFIG_FDSAN
-          uint64_t tag;
-          tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_FILE,
-                                               (uintptr_t)stream);
-          status = android_fdsan_close_with_tag(stream->fs_fd, tag);
-#else
-          status = close(stream->fs_fd);
-#endif
+      status = stream->fs_iofunc.close(stream->fs_cookie);

Review Comment:
   Added NULL check. Fopencookie actually allows the user to have close == NULL.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1363462607


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,156 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cookie_read_cb
+ ****************************************************************************/
+
+static ssize_t cookie_read_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  /* Per specification: if *read is a null pointer, then reads from the
+   * custom stream always return end of file.
+   */
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: cookie_write_cb
+ ****************************************************************************/
+
+static ssize_t cookie_write_cb(FAR void *cookie, FAR const char *buf,
+                               size_t size)
+{
+  /* Per specification: if *write is a null pointer, then output to the
+   * stream is discarded.
+   */
+
+  return 0;

Review Comment:
   0 mean nothing is written, but the spec requires discard all input from the comment.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] gregory-nutt commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "gregory-nutt (via GitHub)" <gi...@apache.org>.
gregory-nutt commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324992990


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  FAR void *cookie;                /* Pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* Programmer-defined hook functions */
+  int cookie_fd;                   /* File descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;

Review Comment:
   Are these the user space callbacks you were referring to?  Yes, these are wrong.  This can't work this way there can be no such calls from the kernel address space.
   
   This is similar to the way that the usrsock works.  The usrsock functions are "called" from the OS, but not directly.   Rather, the call data is marshaled through a POSIX driver interface to the user code.  This is way this should be done as well.  The interface is described in include/nuttx/net/usrsock.h
   
   Other good things to look at:
   
   - graphics/:  The NX graphics server interfaces with user space via a POSIX message queue.
   - fs/userfs/:  Supports a userspace implementation of a file system.  It uses a standard ipv4 sockets on a local interface (INADDR_LOOPBACK).  Although this uses a file system interface vs. a file interface, it could otherwise just to cloned to implement what you need.
   
   At one time I wrote some user-space device drivers (character and block) based on the BSD user space drivers, but I don't think those made it into the repository.  The design was similar to the usrsock design.
   



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325253536


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   Since stdio is a pure usespace library, I would suggest keep all fopencookie related stuff in libc to avoid the complexity of kernel/userspace interactions.
   @michallenc you can achieve this by:
   
   1. Add cookie_io_functions_t to file_struct(FILE)
   2. Assign the internal callback which read/write/seek through fd to cookie_io_functions_t in fopen
   3. Assign caller supplied callback in fopencookie
   4. Replace read/write/seek with cookie_io_functions_t's one



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325561561


##########
include/stdio.h:
##########
@@ -244,6 +244,11 @@ int    dprintf(int fd, FAR const IPTR char *fmt, ...) printf_like(2, 3);
 int    vdprintf(int fd, FAR const IPTR char *fmt, va_list ap)
        printf_like(2, 0);
 
+/* Custom stream operation fopencookie. */
+
+FAR FILE *fopencookie(FAR void *cookie, FAR const char *mode,
+                      cookie_io_functions_t io_funcs);
+

Review Comment:
   Yes, I think the usage in Linux is a justification here although it is not a POSIX interface. Morover this will be helpful in the implementation of `fmemopen` https://pubs.opengroup.org/onlinepubs/9699919799/functions/fmemopen.html (although we can do it without `fopencookie` but it complicates things a bit).



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] gregory-nutt commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "gregory-nutt (via GitHub)" <gi...@apache.org>.
gregory-nutt commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324971300


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  FAR void *cookie;                /* Pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* Programmer-defined hook functions */
+  int cookie_fd;                   /* File descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(FAR void *cookie, FAR const char *mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   I am strongly opposed to adding any user interfaces to the OS that hand no basis in established standards.  This is a terrible practice and should not be accepted.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] gregory-nutt commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "gregory-nutt (via GitHub)" <gi...@apache.org>.
gregory-nutt commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324554592


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   > Ok, you implementation reuse file_operation_s infrastructure, but it mayn't work in protected/kernel mode, since fclosecookie... is part of kernel, but call the callback provided by userspace directly. I would suggest that you have to add these callback to file_struct and call them from libc/stdio directly.
   > 
   > @patacongo what are you thinking?
   
   _[I have not looked at this particular PR, but I can give my usual response when callbacks from the OS are suggested]_
   
   Direct callbacks from the OS into user code have always been forbidden.  I don't think we should permit that now.  Some justifications:
   
   - This is not the POSIX way to do things.  There is no way to do such things under any POSIX OS.  We have always been concerned about POSIX compliant and portability.  Linux code is often ported to NuttX. NuttX code should be runnable on any any POSIX OS as well (with the appropriate drivers).  To accomplish these goals, callbacks must not be used.
   
   - The callback would probably be running on an kernel stack and not the user stack.  In that case, TLS data on the stack would not be accessible.  The callback were asynchronous with the tasking.  A callback is not a context switch; the interrupt user task is still in place and the OS thinks that is that task that is running.  So any OS interactions in this bastardized state could likely be fatal.
   
   - The callback would run at whatever the priority of the calling logic is running at.  This will break real time behavior which must be strict priority-based scheduling.
   
   There are several differ build modes for NuttX:  The FLAT build, the PROTECTED build for better security, and the KERNEL build for full support of processes much like Linux.  In the PROTECTED and KERNEL builds, there are more significant technical issues.
   
   There is some documentation of at least the PROTECTED build here:  https://cwiki.apache.org/confluence/display/NUTTX/NuttX+Protected+Build
   
   - In the PROTECTED and KERNEL build modes, the kernel runs in supervisor mode in a supervisor address space while all user applications run in non-privileged user mode in a user address space.  In the PROTECTED mode, you _could_ call from the kernel supervisor code into user code but this would, however, be a gaping security hole and, hence, must never be done.  Potentially hostile user-supplied code must never run in supervisor mode in this build.
   
   - The KERNEL build differs in that each _process_ has its own address environment and, in this build, the system will crash if such a thing is attempted.  That is because the notification arrives asynchronously with tasking; you never know which process is running and you would call into the wrong address space.  This could be fixed be changing the address environment prior to each callback, that would have big performance and complexity issues.  It is better to do things in the POSIX way.
   
   So even if you use only the FLAT build, direct callbacks from the OS into the user code must be prohibited.  What is the POSIX way of doing an aynchronous notification?  Signals.  In a POSIX OS, you should use standard POSIX signaling and avoid even thinking about callbacks.
   
   Drivers under drivers/ that do asynchronous notifications use signals for this purpose.  Consider drivers/input/button_upper.c.  This is a simple button driver that sends a notification to a user task when a button is pressed or release:
   
   - Look at the function btn_ioctl().  The BTNIOC_REGISTER command is used to register a notification.  The process ID of the user thread is provided and retained for the notification.
   
   - When the button press event occurs, the notification signal is sent in btn_sample().
   
   - A signal handler in the user thread that registered for the notification can then run, in the correct task context, in user mode, and at the correct priority assigned to the task.
   
   This is 100% POSIX and works in all build modes.  It could even be implemented under any other POSIX OS such as Linux.
   
   Signals are only one option.  Below I mention usrsock as a better model to follow.  In that case, I believe that it uses a character driver in kernel space to interact with the user-space socket implementationi.
   
   



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] patacongo commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "patacongo (via GitHub)" <gi...@apache.org>.
patacongo commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325337992


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   > Since stdio is a pure usespace library, I would suggest keep all fopencookie related stuff in libc to avoid the complexity of kernel/userspace interactions.
   
   That would not solve the technical problem.  It eliminates the kernal/user privilege issue, but is otherwise insufficient.  That is because the caller executes in Task/Process A but the user-implementation of the file is implemented in a different Task/Process B.  There are lots of problems with that:
   
   - You would be executing code in Task B in the context of Task A.
   - That means Task B would use Task A's stack and file structures, not those of Task B. 
   - The Task B file system code could not access Task B's TLS data .
   - From the standpoint of the OS, Task A is running, not Task B.  Task B could not access the OS as Task B and many things just would not work properly.
   - The logic in Task B would run with with priority and identity of Task A.
   - It would not work at all in the KERNEL build mode because Task B resides in a different process address space than does Task A.  That would crash immediately and dramatically.
   - etc. Many more issues.
   
   I don't believe that any of that behavior is acceptable.  There is really no situation where can generally call from code in one task into code in another task, regardless of kernel/user privileges or of the build mode (although the problem is insurmountable in the KERNEL build mode).
   
   I still believe that the only viable solution must depend on using a proper POSIX IPC like signals, message queues, fifos, local networks, etc.  Then Task B runs in the proper context and address space of Task B.
   



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1722147867

   > I fully understand vfs, no callback infrastructure is needed,
   
   > that's a glibc patch, who cares?
   
   But I care where the implementation is elegance and extendable.  The code like spaghetti should avoid as mention in:
   https://github.com/apache/nuttx/blob/master/INVIOLABLES.md?plain=1#L36-L41
   https://github.com/apache/nuttx/blob/master/INVIOLABLES.md?plain=1#L90-L94
   
   > just deal with a flag about memory provider that's it.
   
   even for memory stream, there are at least two cases:
   
   1. fmemopen work on a fix size array(provided by caller, or allocated by self)
   2. open_memstream work on an allocate/reallocate extendable memory
   
   The detail is evil, you have to add more flags/fields and many if/else in many common places to handle the different behavior required by spec. The callback is better design here to encapsulate the difference behind the differerent callback(fd vs. mem, fixed vs. dynamically).


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] mu578 commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "mu578 (via GitHub)" <gi...@apache.org>.
mu578 commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1722253300

   > * provided by caller, or allocated by self)
   > * open_memstream work on an allocate/reallocate extendable memor
   
   yes make a context buffer |internal|user_malloc|user_dont_touch|
   
   ```
   
   _io_buffer_grow_if_needed(stream_flag, ** buffer)
   {
     if this type -> do that or not do
   }
   
   _io_buffer_free_if_needed(stream_flag, ** buffer)
   {
     if this type -> do that or not do
   }
   
   ```
   


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325884666


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   > In my suggestion, you should stop to implement file_operation_s and call file_allocate_from_tcb. How do you go through fs/vfs without them?
   
   Yes, but you mention 
   
   > Assign the internal callback which read/write/seek through fd to cookie_io_functions_t in fopen
   
   How would I get fd without actually using `file_allocate_from_tcb`? I can call `fopen` to get it but that would require valid path.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1719977191

   > > @patacongo I think @michallenc initial design may confuse you. stdio is a pure userspace library, the implementation of fopencookie or fmemopen doesn't need involve any kernel stuff: it's enough to add the callback(read/write/seek/close) to struct file_struct(FILE).
   > > So, I would suggest you read the manual from:
   > > https://pubs.opengroup.org/onlinepubs/9699919799/functions/fmemopen.html
   > > https://man7.org/linux/man-pages/man3/fopencookie.3.html
   > 
   > AFAIK that is not true. The user/supervisor mode is only one of several issues. I have enumerated many others below that this design pure user-space design will not handle. The bottom line: You cannot call from one task/process address space into another. 
   
   This case isn't suitable for stdio functions. How can you pass FILE * from one task/process to other task/process in kernel mode? It's impossible to happen in the first place.
   


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1720402119

   > > > This case isn't suitable for stdio functions. How can you pass FILE * from one task/process to other task/process in kernel mode? So it's impossible to call the callback function cross the address space boundary since FILE* return from fopencookie can only be used by the caller's task/process and is always invalid and impossible to pass FILE* to another task/process at the first place.
   > > 
   > > 
   > > I don't see the relevance of the FILE*. I was more concerned at the io_funcs and cookie. But looking at the prototype, it seems impossible that the io_funcs could like in a different address space. from the caller of fopencookie().
   > 
   > Aggreed, it would require to pound defined and only allowing such APIs in usermode.
   
   Of course, all FILE functions can only be called inside the usermode, NuttX kernel forbid kernel code to use any FILE functions.
   
   > However, it could be doable by making a new vfs interface handling such but it would require a whole revamp and further thoughts to make it possible, as is : it is not hot patchable -> so my proposal to support indirection for user-mode build only, at least it can be undone and evolve without breaking.
   
   @mu578 you may misunderstand NuttX file system:
   
   - nuttx/fs/vfs is the kernel VFS infrastructure, which is part of kernel, it's hard and bad to call the callback provided by userspace
   - nuttx/libc/stdio is userspace library, which is very simple and common to call the callback provided by userspace
   
   > 
   > That is impossible to callback from two distinct regions ; it would require some kind of trampoline jump with copies back and forth. E.g if `function pointers` were actually `just address pointers pointing to an actual somewhere` we would not have this conversation, but the reality is different.
   > 
   
   Do you want to implement the userspace file system? NuttX already support it by message queue:
   https://github.com/apache/nuttx/blob/master/include/nuttx/fs/userfs.h
   
   > Myself, I would go to support standard only: `open_memstream` and `fmemopen` ; there is no reason to expose a non standard `fopencookie` call ; the two requires some memory mapping that's it, no callback exposure. It is all about to be able to use FILE api on a user in-memory buffer instead of on a `file descriptor/ino` ; which in case of nuttx is `kif-kif bourricot` a mere detail.
   
   If we want to support all open_memstream/open_wmemstream/fmemopen, it's important to setup a callback infrastructure otherwise fread/fwrite need add many:
   ```
   if (file handle)
     {
       ...
     }
   else if (mem handle)
     {
       ...
     }
   else if (xxx handle)
     {
       ...
     }
   ```
   


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1350312974


##########
include/nuttx/fs/fs.h:
##########
@@ -497,6 +546,8 @@ struct file_struct
   FAR struct file_struct *fs_next;      /* Pointer to next file stream */
   rmutex_t                fs_lock;      /* Recursive lock */
   int                     fs_fd;        /* File descriptor associated with stream */

Review Comment:
   I removed  `fs_fd` entirely as it is not needed anymore. Instead all file descriptors are passed through `fs_cookie` (which is used for user cookie if fopencookie is used). `fs_callbacks` removed.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1350739537


##########
libs/libc/stdio/lib_libstream.c:
##########
@@ -66,13 +67,27 @@ void lib_stream_initialize(FAR struct task_group_s *group)
   list->sl_head = NULL;
   list->sl_tail = NULL;
 
+  fd = -1;
+
   /* Initialize stdin, stdout and stderr stream */
 
-  list->sl_std[0].fs_fd = -1;
+  list->sl_std[0].fs_cookie       = (FAR void *)(intptr_t)fd;

Review Comment:
   Done



##########
libs/libc/stdio/lib_libfread_unlocked.c:
##########
@@ -170,7 +170,9 @@ ssize_t lib_fread_unlocked(FAR void *ptr, size_t count, FAR FILE *stream)
 
                   if (remaining > buffer_available)
                     {
-                      bytes_read = _NX_READ(stream->fs_fd, dest, remaining);
+                      bytes_read = stream->fs_iofunc.read(stream->fs_cookie,
+                                                           (char *)dest,

Review Comment:
   Done



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1363493166


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,156 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cookie_read_cb
+ ****************************************************************************/
+
+static ssize_t cookie_read_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  /* Per specification: if *read is a null pointer, then reads from the
+   * custom stream always return end of file.
+   */
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: cookie_write_cb
+ ****************************************************************************/
+
+static ssize_t cookie_write_cb(FAR void *cookie, FAR const char *buf,
+                               size_t size)
+{
+  /* Per specification: if *write is a null pointer, then output to the
+   * stream is discarded.
+   */
+
+  return 0;

Review Comment:
   Hm, by discarding all input I understand that nothing is written. Returning size would mean the application could expect the pointer is somewhere else then it really is. I will look at other libc implementations how they deal with this.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361805528


##########
sched/tls/task_initinfo.c:
##########
@@ -28,6 +28,8 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/mutex.h>
 
+#include <nuttx/lib/lib.h>

Review Comment:
   Yes, forget it's in side kernel space, but kernel code can't reference libc function directly even th inclusion is added. The better fix should be that seek/fwrite/fread call lseek/_NX_WRITE/_NX_READ directly if the related callback is NULL.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1765944771

   Hmm, sim-01 fails without actually logging any error.


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361823463


##########
libs/libc/stdio/lib_libfread_unlocked.c:
##########
@@ -213,9 +215,9 @@ ssize_t lib_fread_unlocked(FAR void *ptr, size_t count, FAR FILE *stream)
                        * into the buffer.
                        */
 
-                      bytes_read = _NX_READ(stream->fs_fd,
-                                            stream->fs_bufread,
-                                            buffer_available);
+                      bytes_read = stream->fs_iofunc.read(stream->fs_cookie,
+                                              (char *)stream->fs_bufread,

Review Comment:
   FAR added. I think I would rather cast it here than change the type through the entire NuttX now. Maybe in some further patch but not together with fopencookie.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1359771817


##########
libs/libc/stdio/lib_fclose.c:
##########
@@ -115,32 +115,41 @@ int fclose(FAR FILE *stream)
 
       nxmutex_unlock(&slist->sl_lock);
 
-      /* Check that the underlying file descriptor corresponds to an an open
-       * file.
-       */
+      /* Close the file descriptor and save the return status */
 
-      if (stream->fs_fd >= 0)
+#ifdef CONFIG_FDSAN
+      if (stream->fs_hascookie == 0)
         {
-          /* Close the file descriptor and save the return status */
+          /* This is a little warkaround. Ideally we would want to call
+           * fs_iofunc.close and let that handle it. FDSAN however requires
+           * stream to create owner tag and this is not avalialble in

Review Comment:
   you can get back the stream through FIOC_GETTAG, so it's possible to move android_fdsan_xxx into lib_fclose_cb.
   



##########
fs/vfs/fs_fdopen.c:
##########
@@ -120,7 +120,7 @@ int fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb,
 
   /* Check input parameters */
 
-  if (fd < 0)
+  if (fd < 0 && cookie == 0)

Review Comment:
   with https://github.com/apache/nuttx/pull/10913, you could move FILE allocation into fopencookie, and forward fdopen to fopencookie.



##########
libs/libc/stdio/lib_stdio_cb.c:
##########
@@ -0,0 +1,90 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_stdio_cb.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 <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lib_fseek_cb
+ ****************************************************************************/
+
+off_t lib_fseek_cb(FAR void *cookie, off_t *offset, int whence)
+{
+  int fd = (int)(intptr_t)cookie;
+  return lseek(fd, *offset, whence);
+}
+
+/****************************************************************************
+ * Name: lib_fwrite_cb
+ ****************************************************************************/
+
+ssize_t lib_fwrite_cb(FAR void *cookie, FAR const char *buf, size_t size)
+{
+  int fd = (int)(intptr_t)cookie;
+  return _NX_WRITE(fd, buf, size);
+}
+
+/****************************************************************************
+ * Name: lib_fread_cb
+ ****************************************************************************/
+
+ssize_t lib_fread_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  int fd = (int)(intptr_t)cookie;
+  return _NX_READ(fd, buf, size);
+}
+
+/****************************************************************************
+ * Name: lib_fclose_cb
+ ****************************************************************************/
+
+int lib_fclose_cb(FAR void *cookie)
+{
+  int fd = (int)(intptr_t)cookie;

Review Comment:
   close will do the check for us



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325570279


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  FAR void *cookie;                /* Pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* Programmer-defined hook functions */
+  int cookie_fd;                   /* File descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;

Review Comment:
   > Are these the user space callbacks you were referring to? Yes, these are wrong. This can't work this way there can be no such calls from the kernel address space.
   
   I think `stdio` library is purely user space (and protect build builds it twice, one for kernel and one for user space) so this callback here should be correct. The issue @xiaoxiang781216 is reffering to is that the route from user call to the callback is: `fseek` from app -> `fseeko` in libc -> `lseek` in `fs/vfs` -> `fseekcookie` in libc. I think all we need to do is to avoid the usage of  `lseek` in `fs/vfs` and this way we ensure we stay in user space.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1719851812

   > You apparently seem focused on avoiding a clean context switch (which I believe is the correct, clean, flexible solution).
   
   @patacongo  My main argument againts hooks you described above (various notifications, events, signal handlers etc.) is that it would lead to additional requirements for user application (different from how `fopencookie` is used in GNU/Linux). I havent had time to go through all code you suggested (graphics etc) so maybe I am missing something. But I think we should keep it in simple `fseak`, `fputs` etc operations.
   
   @mu578 I like the structure you proposed, that would solve a lot of issues with current `file_struct` and as @xiaoxiang781216 mentioned it should not be that difficult (mostly renaming etc.). We could still keep pointers to read/write/seek at `file` in `fs/vfs` as it is now for drivers and just add the possibility for custom streams if required.
   
   I would do this primarily for `fopencookie` and than build `fmemopen` and `open_memstream` on that if the community would agree as I think it is still beneficial to have `fopencookie` implemented (and its presence in Linux should justify that in my opinion).
   
   I also think we should probably move this discussion to mailing list now.


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325884666


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   > In my suggestion, you should stop to implement file_operation_s and call file_allocate_from_tcb. How do you go through fs/vfs without them?
   
   Yes, but you mention 
   
   > Assign the internal callback which read/write/seek through fd to cookie_io_functions_t in fopen
   
   How would I get fd without actually using `file_allocate_from_tcb`? I can call `fopen` to get it but that would require valid path. We could add hook that if path is NULL (or some fopencookie string) it returns correct FD and basically just does `file_allocate_from_tcb` and that could work. 



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1342849939


##########
libs/libc/stdio/lib_stdio_cb.c:
##########
@@ -0,0 +1,76 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_stdio_cb.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 <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lib_fseek_cb
+ ****************************************************************************/
+
+off_t lib_fseek_cb(FAR void *s, off_t offset, int whence)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  return lseek(stream->fs_fd, offset, whence);
+}
+
+/****************************************************************************
+ * Name: lib_fwrite_cb
+ ****************************************************************************/
+
+ssize_t lib_fwrite_cb(FAR void *s, const char *buf, size_t size)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  return _NX_WRITE(stream->fs_fd, buf, size);

Review Comment:
   Ok, let's keep it.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324119464


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   Ok, you implementation reuse file_operation_s infrastructure, but it mayn't work in protected/kernel mode, since fclosecookie... is part of kernel, but call the callback provided by userspace directly.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325660349


##########
include/stdio.h:
##########
@@ -244,6 +244,11 @@ int    dprintf(int fd, FAR const IPTR char *fmt, ...) printf_like(2, 3);
 int    vdprintf(int fd, FAR const IPTR char *fmt, va_list ap)
        printf_like(2, 0);
 
+/* Custom stream operation fopencookie. */
+
+FAR FILE *fopencookie(FAR void *cookie, FAR const char *mode,
+                      cookie_io_functions_t io_funcs);
+

Review Comment:
   yes, it's very simple to implement fmemopen on top of opencookie.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1325934706


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   fd shouldn't reference in common code, but in the callback provided by stdio self. Actually fd should change to void * instead. only fopen can call open, and assign fd to void *.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1335158509


##########
include/nuttx/fs/fs.h:
##########
@@ -425,6 +425,55 @@ struct inode
 
 #define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
 
+/* Definitions for custom stream operations with fopencookie. The
+ * implementation is as defined in Standard C library (libc). The only
+ * difference is that we use off_t instead of off64_t. This means
+ * off_t is int64_t if CONFIG_FS_LARGEFILE is defined and int32_t if not.
+ */
+
+typedef ssize_t cookie_read_function_t(void *cookie, char *buf, size_t size);

Review Comment:
   Done



##########
include/nuttx/fs/fs.h:
##########
@@ -425,6 +425,55 @@ struct inode
 
 #define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
 
+/* Definitions for custom stream operations with fopencookie. The
+ * implementation is as defined in Standard C library (libc). The only
+ * difference is that we use off_t instead of off64_t. This means
+ * off_t is int64_t if CONFIG_FS_LARGEFILE is defined and int32_t if not.
+ */
+
+typedef ssize_t cookie_read_function_t(void *cookie, char *buf, size_t size);
+typedef ssize_t cookie_write_function_t(void *cookie, const char *buf,
+                                        size_t size);
+typedef off_t cookie_seek_function_t(void *cookie, off_t *offset,

Review Comment:
   done



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1335159510


##########
include/nuttx/fs/fs.h:
##########
@@ -497,6 +546,8 @@ struct file_struct
   FAR struct file_struct *fs_next;      /* Pointer to next file stream */
   rmutex_t                fs_lock;      /* Recursive lock */
   int                     fs_fd;        /* File descriptor associated with stream */
+  FAR struct cookie_s     fs_cookie;    /* Cookie structure for fopencookie */
+  io_callbacks_t          fs_callbacks; /* Internal callbacks for IO call */

Review Comment:
   I would not put internal callbacks to the same structure as fopencookie callbacks simply for code clarity. Also we still need those structures twice... one for internal callback and other for user defined callback.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1335159778


##########
libs/libc/libc.h:
##########
@@ -245,6 +245,13 @@ bool lib_isbasedigit(int ch, int base, FAR int *value);
 
 int lib_checkbase(int base, FAR const char **pptr);
 
+/* Defined in lib_stdio_cb */
+
+ssize_t lib_fread_cb(void *stream, char *buf, size_t size);
+ssize_t lib_fwrite_cb(void *stream, const char *buf, size_t size);
+off_t lib_fseek_cb(void *stream, off_t offset, int whence);

Review Comment:
   fseek for fopencookie is defined with off_t



##########
libs/libc/libc.h:
##########
@@ -245,6 +245,13 @@ bool lib_isbasedigit(int ch, int base, FAR int *value);
 
 int lib_checkbase(int base, FAR const char **pptr);
 
+/* Defined in lib_stdio_cb */

Review Comment:
   done



##########
libs/libc/stdio/lib_fclose.c:
##########
@@ -129,7 +129,7 @@ int fclose(FAR FILE *stream)
                                                (uintptr_t)stream);
           status = android_fdsan_close_with_tag(stream->fs_fd, tag);

Review Comment:
   done



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1335167602


##########
include/nuttx/fs/fs.h:
##########
@@ -497,6 +546,8 @@ struct file_struct
   FAR struct file_struct *fs_next;      /* Pointer to next file stream */
   rmutex_t                fs_lock;      /* Recursive lock */
   int                     fs_fd;        /* File descriptor associated with stream */

Review Comment:
   but the current design waste the memory:
   
   1. fs_fd dup with fs_cookie.cookie
   2. fs_callbacks dup with fs_cookie.cookie_io
   
   total bytes equal to 20(32bit) or 36(64bit), it can be avoided with the better implementation.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] gregory-nutt commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "gregory-nutt (via GitHub)" <gi...@apache.org>.
gregory-nutt commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324969904


##########
include/stdio.h:
##########
@@ -244,6 +244,11 @@ int    dprintf(int fd, FAR const IPTR char *fmt, ...) printf_like(2, 3);
 int    vdprintf(int fd, FAR const IPTR char *fmt, va_list ap)
        printf_like(2, 0);
 
+/* Custom stream operation fopencookie. */
+
+FAR FILE *fopencookie(FAR void *cookie, FAR const char *mode,
+                      cookie_io_functions_t io_funcs);
+

Review Comment:
   It is prohibited to add non-standard interfaces to the OS.  We are purely standards based and non-standard, ad hoc OS interfaces are generally prohibited.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324037782


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   If I create `fs/vfs/fs_fopencookie.c` with function `fs_fopencookie` that would call the internal function (similarly to `fs_fdopen`), would that be ok? Other comments done.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] gregory-nutt commented on a diff in pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "gregory-nutt (via GitHub)" <gi...@apache.org>.
gregory-nutt commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1324554592


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cookie_s
+{
+  void *cookie;                    /* pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* programmer-defined hook functions */
+  int cookie_fd;                   /* file descriptor */
+};
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes);
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes);
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence);
+static int fclosecookie(FAR struct file *filep);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct file_operations cookie_fops =
+{
+  NULL,         /* open */
+  fclosecookie, /* close */
+  freadcookie,  /* read */
+  fwritecookie, /* write */
+  fseekcookie,  /* seek */
+  NULL,         /* ioctl */
+  NULL,         /* mmap */
+  NULL,         /* truncate */
+  NULL,         /* poll */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR struct file *filep, FAR char *buf,
+                           size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR struct file *filep, FAR const char *buf,
+                            size_t nbytes)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, (FAR const char *)buf,
+                               nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR struct file *filep, off_t offset, int whence)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR struct file *filep)
+{
+  struct cookie_s *cookie = (struct cookie_s *)filep->f_priv;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.close != NULL);
+
+  ret = cookie->cookie_io.close(cookie->cookie);
+
+  free(filep->f_priv);
+  free(filep->f_inode);
+  close(cookie->cookie_fd);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fopencookie
+ ****************************************************************************/
+
+FAR FILE *fopencookie(void *restrict cookie, const char *restrict mode,
+                      cookie_io_functions_t io_funcs)
+{
+  FAR FILE *filestructp = NULL;
+  FAR struct file filep;
+  FAR struct inode *inode;
+  FAR struct cookie_s *cookie_priv;
+  int oflags;
+  int ret;
+  int fd;
+
+  /* Map the open mode string to open flags */
+
+  oflags = lib_mode2oflags(mode);
+  if (oflags < 0)
+    {
+      return NULL;
+    }
+
+  /* Allocate necessary structures. */
+
+  inode = lib_zalloc(sizeof(struct inode));
+  if (inode == NULL)
+    {
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  cookie_priv = lib_zalloc(sizeof(struct cookie_s));
+  if (cookie_priv == NULL)
+    {
+      free(inode);
+      set_errno(-ENOMEM);
+      goto fopencookie_return;
+    }
+
+  memset(&filep, 0, sizeof(filep));
+
+  /* Fill cookie_priv structure. We need to add cookie provided by user
+   * and functions providd by user.
+   */
+
+  cookie_priv->cookie = cookie;
+  cookie_priv->cookie_io.read  = io_funcs.read;
+  cookie_priv->cookie_io.write = io_funcs.write;
+  cookie_priv->cookie_io.seek  = io_funcs.seek;
+  cookie_priv->cookie_io.close = io_funcs.close;
+
+  /* Add file operations */
+
+  inode->u.i_ops = &cookie_fops;
+
+  filep.f_oflags = oflags;
+  filep.f_inode = inode;
+  filep.f_priv = cookie_priv;
+
+  /* And get file descriptor. */
+
+  fd = file_allocate_from_tcb(nxsched_self(), filep.f_inode, filep.f_oflags,

Review Comment:
   > Ok, you implementation reuse file_operation_s infrastructure, but it mayn't work in protected/kernel mode, since fclosecookie... is part of kernel, but call the callback provided by userspace directly. I would suggest that you have to add these callback to file_struct and call them from libc/stdio directly.
   > 
   > @patacongo what are you thinking?
   
   _[I have not looked at this particular PR, but I can give my usual response when callbacks from the OS are suggested]_
   
   Direct callbacks from the OS into user code have always been forbidden.  I don't think we should permit that now.  Some justifications:
   
   - This is not the POSIX way to do things.  There is no way to do such things under any POSIX OS.  We have always been concerned about POSIX compliant and portability.  Linux code is often ported to NuttX. NuttX code should be runnable on any any POSIX OS as well (with the appropriate drivers).  To accomplish these goals, callbacks must not be used.
   
   - The callback would probably be running on an kernel stack and not the user stack.  In that case, TLS data on the stack would not be accessible.  The callback were asynchronous with the tasking.  A callback is not a context switch; the interrupt user task is still in place and the OS thinks that is that task that is running.  So any OS interactions in this bastardized state could likely be fatal.
   
   - The callback would run at whatever the priority of the calling logic is running at.  This will break real time behavior which must be strict priority-based scheduling.
   
   There are several differ build modes for NuttX:  The FLAT build, the PROTECTED build for better security, and the KERNEL build for full support of processes much like Linux.  In the PROTECTED and KERNEL builds, there are more significant technical issues.
   
   There is some documentation of at least the PROTECTED build here:  https://cwiki.apache.org/confluence/display/NUTTX/NuttX+Protected+Build
   
   - In the PROTECTED and KERNEL build modes, the kernel runs in supervisor mode in a supervisor address space while all user applications run in non-privileged user mode in a user address space.  In the PROTECTED mode, you _could_ call from the kernel supervisor code into user code but this would, however, be a gaping security hole and, hence, must never be done.  Potentially hostile user-supplied code must never run in supervisor mode in this build.
   
   - The KERNEL build differs in that each _process_ has its own address environment and, in this build, the system will crash if such a thing is attempted.  That is because the notification arrives asynchronously with tasking; you never know which process is running and you would call into the wrong address space.  This could be fixed be changing the address environment prior to each callback, that would have big performance and complexity issues.  It is better to do things in the POSIX way.
   
   So even if you use only the FLAT build, direct callbacks from the OS into the user code must be prohibited.  What is the POSIX way of doing an aynchronous notification?  Signals.  In a POSIX OS, you should use standard POSIX signaling and avoid even thinking about callbacks.
   
   Drivers under drivers/ that do asynchronous notifications use signals for this purpose.  Consider drivers/input/button_upper.c.  This is a simple button driver that sends a notification to a user task when a button is pressed or release:
   
   - Look at the function btn_ioctl().  The BTNIOC_REGISTER command is used to register a notification.  The process ID of the user thread is provided and retained for the notification.
   
   - When the button press event occurs, the notification signal is sent in btn_sample().
   
   - A signal handler in the user thread that registered for the notification can then run, in the correct task context, in user mode, and at the correct priority assigned to the task.
   
   



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] michallenc commented on pull request #10602: libc: add support for custom streams with fopencookie()

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1723135999

   I have updated the implementation with internal callbacks so now the code should entirely avoid kernel address space. How are we going to design some tests that would ensure the correctness?


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1350311535


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,181 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR void *s, FAR char *buf, size_t nbytes);
+static ssize_t fwritecookie(FAR void *s, FAR const char *buf, size_t nbytes);
+static off_t fseekcookie(FAR void *s, off_t offset, int whence);
+static int fclosecookie(FAR void *s);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static FAR FILE *fopencookie_init_stream(int oflags)
+{
+  FAR FILE *stream;
+
+  stream = lib_zalloc(sizeof(FILE));
+  if (stream == NULL)
+    {
+      set_errno(-ENOMEM);
+      return NULL;
+    }
+
+  nxrmutex_init(&stream->fs_lock);
+
+#ifndef CONFIG_STDIO_DISABLE_BUFFERING
+#if CONFIG_STDIO_BUFFER_SIZE > 0
+  /* Set up pointers */
+
+  stream->fs_bufstart = stream->fs_buffer;
+  stream->fs_bufend   = &stream->fs_bufstart[CONFIG_STDIO_BUFFER_SIZE];
+  stream->fs_bufpos   = stream->fs_bufstart;
+  stream->fs_bufread  = stream->fs_bufstart;
+  stream->fs_flags    = __FS_FLAG_UBF; /* Fake setvbuf and fclose */
+
+#ifdef CONFIG_STDIO_LINEBUFFER
+  /* Setup buffer flags */
+
+  stream->fs_flags   |= __FS_FLAG_LBF; /* Line buffering */
+
+#endif /* CONFIG_STDIO_LINEBUFFER */
+#endif /* CONFIG_STDIO_BUFFER_SIZE > 0 */
+#endif /* CONFIG_STDIO_DISABLE_BUFFERING */
+
+  /* Save the file description and open flags.  Setting the
+   * file descriptor locks this stream.
+   */
+
+  stream->fs_fd       = -1;
+  stream->fs_oflags   = oflags;
+
+  return stream;
+}
+
+static ssize_t freadcookie(FAR void *s, FAR char *buf, size_t nbytes)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)&stream->fs_cookie;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.read != NULL);
+
+  ret = cookie->cookie_io.read(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static ssize_t fwritecookie(FAR void *s, FAR const char *buf, size_t nbytes)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)&stream->fs_cookie;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.write != NULL);
+
+  ret = cookie->cookie_io.write(cookie->cookie, buf, nbytes);
+  return ret;
+}
+
+static off_t fseekcookie(FAR void *s, off_t offset, int whence)
+{
+  FAR FILE *stream = (FAR FILE *)s;
+  FAR struct cookie_s *cookie = (FAR struct cookie_s *)&stream->fs_cookie;
+  int ret;
+
+  DEBUGASSERT(cookie->cookie != NULL && cookie->cookie_io.seek != NULL);
+
+  ret = cookie->cookie_io.seek(cookie->cookie, &offset, whence);
+  return ret;
+}
+
+static int fclosecookie(FAR void *s)

Review Comment:
   Done



##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,181 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+static ssize_t freadcookie(FAR void *s, FAR char *buf, size_t nbytes);
+static ssize_t fwritecookie(FAR void *s, FAR const char *buf, size_t nbytes);
+static off_t fseekcookie(FAR void *s, off_t offset, int whence);
+static int fclosecookie(FAR void *s);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static FAR FILE *fopencookie_init_stream(int oflags)
+{
+  FAR FILE *stream;
+
+  stream = lib_zalloc(sizeof(FILE));

Review Comment:
   Done.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1350309565


##########
include/nuttx/fs/fs.h:
##########
@@ -425,6 +425,55 @@ struct inode
 
 #define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
 
+/* Definitions for custom stream operations with fopencookie. The
+ * implementation is as defined in Standard C library (libc). The only
+ * difference is that we use off_t instead of off64_t. This means
+ * off_t is int64_t if CONFIG_FS_LARGEFILE is defined and int32_t if not.
+ */
+
+typedef ssize_t cookie_read_function_t(void *cookie, char *buf, size_t size);
+typedef ssize_t cookie_write_function_t(void *cookie, const char *buf,
+                                        size_t size);
+typedef off_t cookie_seek_function_t(void *cookie, off_t *offset,
+                                     int whence);
+typedef int cookie_close_function_t(void *cookie);
+
+typedef struct
+{
+  FAR cookie_read_function_t *read;
+  FAR cookie_write_function_t *write;
+  FAR cookie_seek_function_t *seek;
+  FAR cookie_close_function_t *close;
+} cookie_io_functions_t;
+
+struct cookie_s
+{
+  FAR void *cookie;                /* Pointer to the caller's cookie struct */
+  cookie_io_functions_t cookie_io; /* Programmer-defined hook functions */
+};
+
+/* Definition of internal callbacks for read/write/seek/close operations.
+ * These are needed to ensure custom callbacks from fopencookie are called
+ * from user address space and not from kernel address space. These callbacks
+ * are either routed to fopencookie related callbacks or to internal
+ * read/write/seek/close operations defined in file system (thus in kernel
+ * address space)
+ */
+
+typedef ssize_t read_internal_cb_t(FAR void *s, char *buf, size_t size);
+typedef ssize_t write_internal_cb_t(FAR void *s, const char *buf,
+                                    size_t size);
+typedef off_t seek_internal_cb_t(FAR void *s, off_t offset, int whence);
+typedef int close_internal_cb_t(FAR void *s);
+
+typedef struct
+{
+  FAR read_internal_cb_t *read;
+  FAR write_internal_cb_t *write;
+  FAR seek_internal_cb_t *seek;
+  FAR close_internal_cb_t *close;
+} io_callbacks_t;

Review Comment:
   Removed



##########
include/nuttx/fs/fs.h:
##########
@@ -497,6 +546,8 @@ struct file_struct
   FAR struct file_struct *fs_next;      /* Pointer to next file stream */
   rmutex_t                fs_lock;      /* Recursive lock */
   int                     fs_fd;        /* File descriptor associated with stream */
+  FAR struct cookie_s     fs_cookie;    /* Cookie structure for fopencookie */
+  io_callbacks_t          fs_callbacks; /* Internal callbacks for IO call */

Review Comment:
   Removed



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1350712432


##########
fs/vfs/fs_fdopen.c:
##########
@@ -120,7 +120,7 @@ int fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb,
 
   /* Check input parameters */
 
-  if (fd < 0)
+  if (fd < 0 && cookie == 0)

Review Comment:
   @xiaoxiang781216 This is basically just an information passed to fs_fdopen that initialization is done for fopencookie (1 true) and not standard stream (0 false). It is not to pass the pointer to cookie. The implementation with pointer to cookie would be tricky because we need valid fd to pass the checks (and we need -1 reserved if open call returns error). This adds two more if statements but does not complicate the code more. Applies to most other comments.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1350736791


##########
libs/libc/stdio/lib_stdio_cb.c:
##########
@@ -0,0 +1,90 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_stdio_cb.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 <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lib_fseek_cb
+ ****************************************************************************/
+
+off_t lib_fseek_cb(FAR void *cookie, off_t *offset, int whence)
+{
+  int fd = (int)(intptr_t)cookie;
+  return lseek(fd, *offset, whence);
+}
+
+/****************************************************************************
+ * Name: lib_fwrite_cb
+ ****************************************************************************/
+
+ssize_t lib_fwrite_cb(FAR void *cookie, FAR const char *buf, size_t size)
+{
+  int fd = (int)(intptr_t)cookie;
+  return _NX_WRITE(fd, buf, size);
+}
+
+/****************************************************************************
+ * Name: lib_fread_cb
+ ****************************************************************************/
+
+ssize_t lib_fread_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  int fd = (int)(intptr_t)cookie;
+  return _NX_READ(fd, buf, size);
+}
+
+/****************************************************************************
+ * Name: lib_fclose_cb
+ ****************************************************************************/
+
+int lib_fclose_cb(FAR void *cookie)
+{
+  int fd = (int)(intptr_t)cookie;

Review Comment:
   There should be a check whether we have valid fd before we call `close()`. This was previously in `lib_fclose.c` but I moved it here since in `lib_fclose.c` we dont know whether it is fd or cookie.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1350737968


##########
libs/libc/stdio/lib_libfread_unlocked.c:
##########
@@ -213,9 +215,9 @@ ssize_t lib_fread_unlocked(FAR void *ptr, size_t count, FAR FILE *stream)
                        * into the buffer.
                        */
 
-                      bytes_read = _NX_READ(stream->fs_fd,
-                                            stream->fs_bufread,
-                                            buffer_available);
+                      bytes_read = stream->fs_iofunc.read(stream->fs_cookie,
+                                              (char *)stream->fs_bufread,

Review Comment:
   I can´t move it there, the line would be too long.



##########
libs/libc/stdio/lib_libfread_unlocked.c:
##########
@@ -213,9 +215,9 @@ ssize_t lib_fread_unlocked(FAR void *ptr, size_t count, FAR FILE *stream)
                        * into the buffer.
                        */
 
-                      bytes_read = _NX_READ(stream->fs_fd,
-                                            stream->fs_bufread,
-                                            buffer_available);
+                      bytes_read = stream->fs_iofunc.read(stream->fs_cookie,
+                                              (char *)stream->fs_bufread,

Review Comment:
   I can´t move it there, the line would be too long.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1765702180

   > > @michallenc but, the ci still fail, could you take a look?
   > 
   > Yes, I fixed some on Saturday but I suppose the rest is somehow related to change to `fs_fdopen` which should be (at least partially) fixed by the update from your patch a remove of `fs_fdopen`. I will update the patch once yours is merged.
   
   @michallenc https://github.com/apache/nuttx/pull/10913 was merged, you can rebase your patch on top of it now.


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#issuecomment-1766299270

   please fix:
   ```
   81a82
   > CONFIG_TESTING_FOPENCOOKIE_TEST=y
   87d87
   < CONFIG_TESTING_FOPENCOOKIE_TEST=y
   Saving the new configuration file
   HEAD detached at pull/10602/merge
   Changes not staged for commit:
     (use "git add <file>..." to update what will be committed)
     (use "git restore <file>..." to discard changes in working directory)
   	modified:   boards/sim/sim/sim/configs/citest/defconfig
   ```


-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1361837030


##########
libs/libc/stdio/lib_libfgets.c:
##########
@@ -97,10 +97,11 @@ FAR char *lib_fgets_unlocked(FAR char *buf, size_t buflen, FILE *stream,
                              bool keepnl, bool consume)
 {
   size_t nch = 0;
+  int fd = (int)(intptr_t)stream->fs_cookie;
 
   /* Sanity checks */
 
-  if (!stream || !buf || stream->fs_fd < 0)
+  if (!stream || !buf || fd < 0)

Review Comment:
   Yes, it's better to let the code which really use fd to do the check.



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "michallenc (via GitHub)" <gi...@apache.org>.
michallenc commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1363385655


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,153 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cookie_read_cb
+ ****************************************************************************/
+
+ssize_t cookie_read_cb(FAR void *cookie, FAR char *buf, size_t size)

Review Comment:
   done



##########
libs/libc/stdio/lib_fclose.c:
##########
@@ -64,6 +64,7 @@ int fclose(FAR FILE *stream)
   int errcode = EINVAL;
   int ret = ERROR;
   int status;
+  int fd = (int)(intptr_t)stream->fs_cookie;

Review Comment:
   done



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1363401957


##########
libs/libc/stdio/lib_libfread_unlocked.c:
##########
@@ -46,13 +46,14 @@
 
 ssize_t lib_fread_unlocked(FAR void *ptr, size_t count, FAR FILE *stream)
 {
-  FAR unsigned char *dest = (FAR unsigned char *)ptr;
+  FAR char *dest = (FAR char *)ptr;

Review Comment:
   remove the cast?



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] libc: add support for custom streams with fopencookie() [nuttx]

Posted by "xiaoxiang781216 (via GitHub)" <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #10602:
URL: https://github.com/apache/nuttx/pull/10602#discussion_r1363529586


##########
libs/libc/stdio/lib_fopencookie.c:
##########
@@ -0,0 +1,156 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_fopencookie.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 <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/tls.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cookie_read_cb
+ ****************************************************************************/
+
+static ssize_t cookie_read_cb(FAR void *cookie, FAR char *buf, size_t size)
+{
+  /* Per specification: if *read is a null pointer, then reads from the
+   * custom stream always return end of file.
+   */
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: cookie_write_cb
+ ****************************************************************************/
+
+static ssize_t cookie_write_cb(FAR void *cookie, FAR const char *buf,
+                               size_t size)
+{
+  /* Per specification: if *write is a null pointer, then output to the
+   * stream is discarded.
+   */
+
+  return size;
+}
+
+/****************************************************************************
+ * Name: cookie_seek_cb
+ ****************************************************************************/
+
+static off_t cookie_seek_cb(FAR void *cookie, FAR off_t *offset, int whence)
+{
+  /* Per specification: if *seek is a null pointer, then it is not
+   * possible to perform seek operations on the stream.
+   */
+
+  errno = -ENOTSUP;

Review Comment:
   set_errno(-ENOTSUP)?



-- 
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: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org