diff --git a/fs/vfs/fs_fdopen.c b/fs/vfs/fs_fdopen.c index 5f7bf7005ad47..5caaf15d06c25 100644 --- a/fs/vfs/fs_fdopen.c +++ b/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, FAR struct file_struct **filep) { FAR struct streamlist *slist; @@ -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) { ret = -EBADF; goto errout; @@ -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) { stream = group_zalloc(tcb->group, sizeof(FILE)); if (stream == NULL) @@ -221,8 +221,11 @@ int fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb, * file descriptor locks this stream. */ - stream->fs_fd = fd; - stream->fs_oflags = oflags; + stream->fs_cookie = (FAR void *)(intptr_t)fd; + stream->fs_oflags = oflags; +#ifdef CONFIG_FDSAN + stream->fs_hascookie = cookie; +#endif if (filep != NULL) { diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index 7c8f0a53e46f1..6d21d96f75323 100644 --- a/include/nuttx/fs/fs.h +++ b/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); +typedef CODE int cookie_close_function_t(void *cookie); + +typedef struct cookie_io_functions_t +{ + 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; + /* This is the underlying representation of an open file. A file * descriptor is an index into an array of such types. The type associates * the file descriptor to the file state and to a set of inode operations. @@ -497,7 +522,11 @@ 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 */ + cookie_io_functions_t fs_iofunc; /* Callbacks to user / system functions */ + FAR void *fs_cookie; /* Pointer to file descriptor / cookie struct */ +#ifdef CONFIG_FDSAN + uint8_t fs_hascookie; +#endif #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 */ @@ -1184,7 +1213,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, FAR struct file_struct **filep); #endif diff --git a/include/stdio.h b/include/stdio.h index 7aaa814d351f5..b7a4c3dde47a2 100644 --- a/include/stdio.h +++ b/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); + /* Operations on paths */ FAR FILE *tmpfile(void) fopen_like; diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h index e8d2a4ae970cc..d9e7e94fc0034 100644 --- a/include/sys/syscall_lookup.h +++ b/include/sys/syscall_lookup.h @@ -274,7 +274,7 @@ SYSCALL_LOOKUP(munmap, 2) #endif #ifdef CONFIG_FILE_STREAM - SYSCALL_LOOKUP(fs_fdopen, 4) + SYSCALL_LOOKUP(fs_fdopen, 5) #endif #ifndef CONFIG_DISABLE_MOUNTPOINT diff --git a/libs/libc/libc.h b/libs/libc/libc.h index 332556feb7916..c7516786fb4bd 100644 --- a/libs/libc/libc.h +++ b/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.c */ + +ssize_t lib_fread_cb(FAR void *cookie, FAR char *buf, size_t size); +ssize_t lib_fwrite_cb(FAR void *cookie, FAR const char *buf, size_t size); +off_t lib_fseek_cb(FAR void *cookie, FAR off_t *offset, int whence); +int lib_fclose_cb(FAR void *cookie); + /* Defined in lib_parsehostfile.c */ #ifdef CONFIG_NETDB_HOSTFILE diff --git a/libs/libc/stdio/CMakeLists.txt b/libs/libc/stdio/CMakeLists.txt index b1f0cb926e393..9244c0b08d715 100644 --- a/libs/libc/stdio/CMakeLists.txt +++ b/libs/libc/stdio/CMakeLists.txt @@ -104,7 +104,9 @@ if(CONFIG_FILE_STREAM) lib_libgetstreams.c lib_fputwc.c lib_putwc.c - lib_fputws.c) + lib_fputws.c + lib_fopencookie.c + lib_stdio_cb.c) endif() target_sources(c PRIVATE ${SRCS}) diff --git a/libs/libc/stdio/Make.defs b/libs/libc/stdio/Make.defs index d438ceaf6e178..ad0f2387d1dee 100644 --- a/libs/libc/stdio/Make.defs +++ b/libs/libc/stdio/Make.defs @@ -48,6 +48,7 @@ CSRCS += lib_feof.c lib_ferror.c lib_rewind.c lib_clearerr.c CSRCS += lib_scanf.c lib_vscanf.c lib_fscanf.c lib_vfscanf.c lib_tmpfile.c CSRCS += lib_setbuf.c lib_setvbuf.c lib_libstream.c lib_libfilelock.c CSRCS += lib_libgetstreams.c lib_setbuffer.c lib_fputwc.c lib_putwc.c lib_fputws.c +CSRCS += lib_fopencookie.c lib_stdio_cb.c endif # Add the stdio directory to the build diff --git a/libs/libc/stdio/lib_fclose.c b/libs/libc/stdio/lib_fclose.c index b85a497e7d05f..c2c18d47a0d2a 100644 --- a/libs/libc/stdio/lib_fclose.c +++ b/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 + * STDIO callback. This warkaround is used instead. It adds + * one if statement to fclose but overall is cheaper than + * passing entire stream to callback. + */ -#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); + int fd = (int)(intptr_t)stream->fs_cookie; + uint64_t tag = android_fdsan_create_owner_tag( + ANDROID_FDSAN_OWNER_TYPE_FILE, + (uintptr_t)stream); + return android_fdsan_close_with_tag(fd, tag); + } + else + { + status = stream->fs_iofunc.close(stream->fs_cookie); + } #else - status = close(stream->fs_fd); + status = stream->fs_iofunc.close(stream->fs_cookie); #endif - /* If close() returns an error but flush() did not then make sure - * that we return the close() error condition. - */ + /* If close() returns an error but flush() did not then make sure + * that we return the close() error condition. + */ - if (ret == OK) - { - ret = status; - errcode = get_errno(); - } + if (ret == OK) + { + ret = status; + errcode = get_errno(); } #ifndef CONFIG_STDIO_DISABLE_BUFFERING diff --git a/libs/libc/stdio/lib_fileno.c b/libs/libc/stdio/lib_fileno.c index 803890b0d2d01..c90d6bdc986a3 100644 --- a/libs/libc/stdio/lib_fileno.c +++ b/libs/libc/stdio/lib_fileno.c @@ -41,7 +41,7 @@ int fileno(FAR FILE *stream) if (stream) { - ret = stream->fs_fd; + ret = (int)(intptr_t)stream->fs_cookie; } if (ret < 0) diff --git a/libs/libc/stdio/lib_fopen.c b/libs/libc/stdio/lib_fopen.c index 80b33044c4db3..45dd2c6f53ed2 100644 --- a/libs/libc/stdio/lib_fopen.c +++ b/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); if (ret < 0) { set_errno(-ret); @@ -87,6 +87,13 @@ FAR FILE *fdopen(int fd, FAR const char *mode) (uintptr_t)filep)); #endif + /* Assign internal callbacks. */ + + filep->fs_iofunc.read = lib_fread_cb; + filep->fs_iofunc.write = lib_fwrite_cb; + filep->fs_iofunc.seek = lib_fseek_cb; + filep->fs_iofunc.close = lib_fclose_cb; + return filep; } @@ -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); if (ret < 0) { /* Don't forget to close the file descriptor if any other @@ -140,6 +147,13 @@ FAR FILE *fopen(FAR const char *path, FAR const char *mode) (uintptr_t)filep)); #endif + /* Assign internal callbacks. */ + + filep->fs_iofunc.read = lib_fread_cb; + filep->fs_iofunc.write = lib_fwrite_cb; + filep->fs_iofunc.seek = lib_fseek_cb; + filep->fs_iofunc.close = lib_fclose_cb; + return filep; } diff --git a/libs/libc/stdio/lib_fopencookie.c b/libs/libc/stdio/lib_fopencookie.c new file mode 100644 index 0000000000000..8498d89ff9373 --- /dev/null +++ b/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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#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); + if (ret < 0) + { + return NULL; + } + + /* Assign cookie and user defined callbacks. */ + + filep->fs_cookie = cookie; + filep->fs_iofunc = io_funcs; + + return filep; +} diff --git a/libs/libc/stdio/lib_fseeko.c b/libs/libc/stdio/lib_fseeko.c index 163a79de3890a..70cc6fad54721 100644 --- a/libs/libc/stdio/lib_fseeko.c +++ b/libs/libc/stdio/lib_fseeko.c @@ -87,5 +87,6 @@ int fseeko(FAR FILE *stream, off_t offset, int whence) /* Perform the fseeko on the underlying file descriptor */ - return lseek(stream->fs_fd, offset, whence) == (off_t)-1 ? ERROR : OK; + return stream->fs_iofunc.seek(stream->fs_cookie, &offset, + whence) == (off_t)-1 ? ERROR : OK; } diff --git a/libs/libc/stdio/lib_ftello.c b/libs/libc/stdio/lib_ftello.c index 0052a50e80157..a7f68b03b1b1f 100644 --- a/libs/libc/stdio/lib_ftello.c +++ b/libs/libc/stdio/lib_ftello.c @@ -97,6 +97,7 @@ static off_t lib_getoffset(FAR FILE *stream) off_t ftello(FAR FILE *stream) { off_t position; + off_t offset = 0; /* Verify that we were provided with a stream */ @@ -110,7 +111,7 @@ off_t ftello(FAR FILE *stream) * file pointer, but will return its current setting */ - position = lseek(stream->fs_fd, 0, SEEK_CUR); + position = stream->fs_iofunc.seek(stream->fs_cookie, &offset, SEEK_CUR); if (position != (off_t)-1) { return position - lib_getoffset(stream); diff --git a/libs/libc/stdio/lib_libfflush.c b/libs/libc/stdio/lib_libfflush.c index bdc0250673647..a62d73bf2b13f 100644 --- a/libs/libc/stdio/lib_libfflush.c +++ b/libs/libc/stdio/lib_libfflush.c @@ -65,7 +65,7 @@ ssize_t lib_fflush_unlocked(FAR FILE *stream, bool bforce) /* Return EBADF if the file is not opened for writing */ - if (stream->fs_fd < 0 || (stream->fs_oflags & O_WROK) == 0) + if ((stream->fs_oflags & O_WROK) == 0) { return -EBADF; } @@ -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, + nbuffer); if (bytes_written < 0) { /* Write failed. The cause of the failure is in 'errno'. diff --git a/libs/libc/stdio/lib_libfgets.c b/libs/libc/stdio/lib_libfgets.c index 29f4420d90b88..b49868dc8f737 100644 --- a/libs/libc/stdio/lib_libfgets.c +++ b/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) { return NULL; } diff --git a/libs/libc/stdio/lib_libfread_unlocked.c b/libs/libc/stdio/lib_libfread_unlocked.c index 1fb26b798ddcd..369ed999ffcb0 100644 --- a/libs/libc/stdio/lib_libfread_unlocked.c +++ b/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, + remaining); if (bytes_read < 0) { if (count - remaining > 0) @@ -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, + buffer_available); if (bytes_read < 0) { if (count - remaining > 0) @@ -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, + remaining); if (bytes_read < 0) { if (count - remaining > 0) diff --git a/libs/libc/stdio/lib_libfwrite.c b/libs/libc/stdio/lib_libfwrite.c index 265a59d85540e..4a186a28d642f 100644 --- a/libs/libc/stdio/lib_libfwrite.c +++ b/libs/libc/stdio/lib_libfwrite.c @@ -72,7 +72,7 @@ ssize_t lib_fwrite_unlocked(FAR const void *ptr, size_t count, if (stream->fs_bufstart == NULL) { - ret = _NX_WRITE(stream->fs_fd, ptr, count); + ret = stream->fs_iofunc.write(stream->fs_cookie, ptr, count); if (ret < 0) { _NX_SETERRNO(ret); @@ -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, + count); if (ret < 0) { _NX_SETERRNO(ret); @@ -163,7 +164,7 @@ ssize_t lib_fwrite_unlocked(FAR const void *ptr, size_t count, } #else { - ssize_t ret = _NX_WRITE(stream->fs_fd, ptr, count); + ssize_t ret = stream->fs_iofunc.write(stream->fs_cookie, ptr, count); if (ret < 0) { stream->fs_flags |= __FS_FLAG_ERROR; diff --git a/libs/libc/stdio/lib_libstream.c b/libs/libc/stdio/lib_libstream.c index be6a2a1c02115..8f750dc4174f1 100644 --- a/libs/libc/stdio/lib_libstream.c +++ b/libs/libc/stdio/lib_libstream.c @@ -68,11 +68,23 @@ void lib_stream_initialize(FAR struct task_group_s *group) /* Initialize stdin, stdout and stderr stream */ - list->sl_std[0].fs_fd = -1; + list->sl_std[0].fs_cookie = (FAR void *)(intptr_t)-1; + list->sl_std[0].fs_iofunc.read = lib_fread_cb; + list->sl_std[0].fs_iofunc.write = lib_fwrite_cb; + list->sl_std[0].fs_iofunc.seek = lib_fseek_cb; + list->sl_std[0].fs_iofunc.close = lib_fclose_cb; nxrmutex_init(&list->sl_std[0].fs_lock); - list->sl_std[1].fs_fd = -1; + list->sl_std[1].fs_cookie = (FAR void *)(intptr_t)-1; + list->sl_std[1].fs_iofunc.read = lib_fread_cb; + list->sl_std[1].fs_iofunc.write = lib_fwrite_cb; + list->sl_std[1].fs_iofunc.seek = lib_fseek_cb; + list->sl_std[1].fs_iofunc.close = lib_fclose_cb; nxrmutex_init(&list->sl_std[1].fs_lock); - list->sl_std[2].fs_fd = -1; + list->sl_std[2].fs_cookie = (FAR void *)(intptr_t)-1; + list->sl_std[2].fs_iofunc.read = lib_fread_cb; + list->sl_std[2].fs_iofunc.write = lib_fwrite_cb; + list->sl_std[2].fs_iofunc.seek = lib_fseek_cb; + list->sl_std[2].fs_iofunc.close = lib_fclose_cb; nxrmutex_init(&list->sl_std[2].fs_lock); } diff --git a/libs/libc/stdio/lib_rdflush_unlocked.c b/libs/libc/stdio/lib_rdflush_unlocked.c index 70c4758660de2..5294143fb556d 100644 --- a/libs/libc/stdio/lib_rdflush_unlocked.c +++ b/libs/libc/stdio/lib_rdflush_unlocked.c @@ -92,7 +92,8 @@ int lib_rdflush_unlocked(FAR FILE *stream) * user */ - if (lseek(stream->fs_fd, -rdoffset, SEEK_CUR) < 0) + rdoffset = -rdoffset; + if (stream->fs_iofunc.seek(stream->fs_cookie, &rdoffset, SEEK_CUR) < 0) { return ERROR; } diff --git a/libs/libc/stdio/lib_setvbuf.c b/libs/libc/stdio/lib_setvbuf.c index 8d5e5e57037fd..8e8e765f41248 100644 --- a/libs/libc/stdio/lib_setvbuf.c +++ b/libs/libc/stdio/lib_setvbuf.c @@ -78,6 +78,7 @@ int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size) { #ifndef CONFIG_STDIO_DISABLE_BUFFERING FAR unsigned char *newbuf = NULL; + int fd = (int)(intptr_t)stream->fs_cookie; uint8_t flags; int errcode; @@ -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) { errcode = EBADF; goto errout_with_lock; diff --git a/libs/libc/stdio/lib_stdio_cb.c b/libs/libc/stdio/lib_stdio_cb.c new file mode 100644 index 0000000000000..24194164d107f --- /dev/null +++ b/libs/libc/stdio/lib_stdio_cb.c @@ -0,0 +1,87 @@ +/**************************************************************************** + * 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 + +#include +#include +#include +#include + +#ifdef CONFIG_FDSAN +# include +#endif + +#include "libc.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_fseek_cb + ****************************************************************************/ + +off_t lib_fseek_cb(FAR void *cookie, FAR 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; + } + + return close(fd); +} diff --git a/libs/libc/stdio/lib_ungetc.c b/libs/libc/stdio/lib_ungetc.c index f5ebea1e39452..f7d906da285e5 100644 --- a/libs/libc/stdio/lib_ungetc.c +++ b/libs/libc/stdio/lib_ungetc.c @@ -39,6 +39,7 @@ int ungetc(int c, FAR FILE *stream) { + int fd = (int)(intptr_t)stream->fs_cookie; #if CONFIG_NUNGET_CHARS > 0 int nungotten; #endif @@ -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)) { return EOF; } diff --git a/sched/group/group_setupstreams.c b/sched/group/group_setupstreams.c index 1ad4eadbe265a..494d6c4b1a7ae 100644 --- a/sched/group/group_setupstreams.c +++ b/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); return OK; } diff --git a/syscall/syscall.csv b/syscall/syscall.csv index 837ae8dfb354c..09702ba8b78e1 100644 --- a/syscall/syscall.csv +++ b/syscall/syscall.csv @@ -29,7 +29,7 @@ "fchmod","sys/stat.h","","int","int","mode_t" "fchown","unistd.h","","int","int","uid_t","gid_t" "fcntl","fcntl.h","","int","int","int","...","int" -"fs_fdopen","nuttx/fs/fs.h","defined(CONFIG_FILE_STREAM)","int","int","int","FAR struct tcb_s *","FAR struct file_struct **" +"fs_fdopen","nuttx/fs/fs.h","defined(CONFIG_FILE_STREAM)","int","int","int","int","FAR struct tcb_s *","FAR struct file_struct **" "fstat","sys/stat.h","","int","int","FAR struct stat *" "fstatfs","sys/statfs.h","","int","int","FAR struct statfs *" "fsync","unistd.h","","int","int"