From ae8d48470bd02f4fed4e6c56f01801926b041bd1 Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Tue, 20 Jan 2026 17:41:00 +0700 Subject: [PATCH] feat(esp_libc): picolibc: add fopencookie implementation --- components/esp_libc/CMakeLists.txt | 1 + components/esp_libc/platform_include/stdio.h | 16 ++++- .../esp_libc/src/picolibc/fopencookie.c | 64 +++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 components/esp_libc/src/picolibc/fopencookie.c diff --git a/components/esp_libc/CMakeLists.txt b/components/esp_libc/CMakeLists.txt index 38f218270f..cb95a0182f 100644 --- a/components/esp_libc/CMakeLists.txt +++ b/components/esp_libc/CMakeLists.txt @@ -80,6 +80,7 @@ else() "src/picolibc/errno.c") if(CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY) list(APPEND srcs "src/picolibc/getreent.c") + list(APPEND srcs "src/picolibc/fopencookie.c") endif() endif() diff --git a/components/esp_libc/platform_include/stdio.h b/components/esp_libc/platform_include/stdio.h index 46ac1bae27..6077313015 100644 --- a/components/esp_libc/platform_include/stdio.h +++ b/components/esp_libc/platform_include/stdio.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -40,6 +40,20 @@ FILE *funopen(const void *cookie, void flockfile(FILE *); void funlockfile(FILE *); FILE *open_memstream(char **, size_t *); + +typedef ssize_t cookie_read_function_t(void *cookie, char *buf, size_t n); +typedef ssize_t cookie_write_function_t(void *cookie, const char *buf, size_t n); +typedef int cookie_seek_function_t(void *cookie, __off_t *off, int whence); +typedef int cookie_close_function_t(void *cookie); +typedef struct { + /* These four struct member names are dictated by Linux; hopefully, + they don't conflict with any macros. */ + cookie_read_function_t *read; + cookie_write_function_t *write; + cookie_seek_function_t *seek; + cookie_close_function_t *close; +} cookie_io_functions_t; +FILE *fopencookie(void *cookie, const char *mode, cookie_io_functions_t functions); #endif #ifdef __cplusplus diff --git a/components/esp_libc/src/picolibc/fopencookie.c b/components/esp_libc/src/picolibc/fopencookie.c new file mode 100644 index 0000000000..5aca079b23 --- /dev/null +++ b/components/esp_libc/src/picolibc/fopencookie.c @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "esp_compiler.h" + +struct cookie_wrap { + void *cookie; + cookie_io_functions_t fn; +}; + +static int fun_read(void *c, char *buf, int size) +{ + struct cookie_wrap *w = c; + return (int)w->fn.read(w->cookie, buf, (size_t)size); +} + +static int fun_write(void *c, const char *buf, int size) +{ + struct cookie_wrap *w = c; + return (int)w->fn.write(w->cookie, buf, (size_t)size); +} + +static off_t fun_seek(void *c, off_t off, int whence) +{ + struct cookie_wrap *w = c; + return w->fn.seek(w->cookie, &off, whence); +} + +static int fun_close(void *c) +{ + struct cookie_wrap *w = c; + int r = w->fn.close ? w->fn.close(w->cookie) : 0; + free(w); + return r; +} + +FILE *fopencookie(void *cookie, __attribute__((unused)) const char *mode, + cookie_io_functions_t fn) +{ + ESP_COMPILER_DIAGNOSTIC_PUSH_IGNORE("-Wanalyzer-malloc-leak") + struct cookie_wrap *w = malloc(sizeof * w); + if (!w) { + return NULL; + } + + w->cookie = cookie; + w->fn = fn; + + FILE *fp = funopen(w, + fn.read ? fun_read : NULL, + fn.write ? fun_write : NULL, + fn.seek ? fun_seek : NULL, + fun_close); + + if (!fp) { + free(w); + } + return fp; + ESP_COMPILER_DIAGNOSTIC_POP("-Wanalyzer-malloc-leak") +}