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-unsubscr...@nuttx.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org