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-unsubscr...@nuttx.apache.org

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

Reply via email to