feat(esp_libc): picolibc: add fopencookie implementation

This commit is contained in:
Alexey Lapshin
2026-01-20 17:41:00 +07:00
parent 48e7e0618d
commit ae8d48470b
3 changed files with 80 additions and 1 deletions
+1
View File
@@ -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()
+15 -1
View File
@@ -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
@@ -0,0 +1,64 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdlib.h>
#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")
}