-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Open
Labels
area: picolibcPicolibc C Standard LibraryPicolibc C Standard LibrarybugThe issue is a bug, or the PR is fixing a bugThe issue is a bug, or the PR is fixing a bugpriority: mediumMedium impact/importance bugMedium impact/importance bug
Description
Describe the bug
When using picolibc with posix filesystem API, fwrite expects a __file object, but fopen returns an fd_entry, which does not have a put handler.
struct fd_entry {
void *obj;
const struct fd_op_vtable *vtable;
atomic_t refcount;
struct k_mutex lock;
struct k_condvar cond;
size_t offset;
uint32_t mode;
};
struct __file {
__ungetc_t unget; /* ungetc() buffer */
__uint8_t flags; /* flags, see below */
int (*put)(char, struct __file *); /* function to write one char to device */
int (*get)(struct __file *); /* function to read one char from device */
int (*flush)(struct __file *); /* function to flush output to device */
#ifdef __STDIO_LOCKING
_LOCK_RECURSIVE_T lock;
#endif
};
Regression
- This is a regression.
Steps to reproduce
Board: xiao_esp32c6/esp32c6/hpcore, for example.
prj.conf:
CONFIG_SERIAL=y
CONFIG_GPIO=y
CONFIG_LOG=y
CONFIG_CONSOLE=y
CONFIG_POSIX_API=y
CONFIG_ZVFS_OPEN_ADD_SIZE_POSIX=100
CONFIG_POSIX_FILE_SYSTEM=y
CONFIG_DISK_ACCESS=y
CONFIG_DISK_DRIVERS=y
CONFIG_DISK_DRIVER_FLASH=y
CONFIG_FILE_SYSTEM=y
CONFIG_FILE_SYSTEM_MKFS=y
CONFIG_FILE_SYSTEM_LITTLEFS=y
CONFIG_DEBUG_OPTIMIZATIONS=y
CONFIG_LOG_BUFFER_SIZE=16384#include <zephyr/storage/disk_access.h>
#include "fcntl.h"
#include "zephyr/kernel.h"
#include "zephyr/console/console.h"
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include "zephyr/fs/fs.h"
#include "zephyr/storage/flash_map.h"
#include "zephyr/fs/littlefs.h"
#include "stdlib.h"
#include "unistd.h"
// it works
void test_disk_access() {
const static struct flash_area *area;
flash_area_open(FIXED_PARTITION_ID(storage_partition), &area);
static struct flash_sector sec[1];
uint32_t cnt = 1;
flash_area_sectors(area, &cnt, sec);
printf(
"flash area :: ID = %d, offset = %u, size = %u, sector size = %d\n",
FIXED_PARTITION_ID(storage_partition),
FIXED_PARTITION_OFFSET(storage_partition),
FIXED_PARTITION_SIZE(storage_partition),
sec[0].fs_size
);
#define DISK_NAME "mydisk"
int ret = disk_access_init(DISK_NAME);
printf("disk_access_init: ret = %d\n", ret);
static uint8_t buf[4096];
ret = disk_access_read(DISK_NAME, buf, 0, 1);
printf("disk_access_read: ret = %d\n", ret);
printf("first 4 byte: %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]);
static const uint8_t s[4096] = "\xca\xfe\xba\xbe";
ret = disk_access_write(DISK_NAME, s, 0, 1);
printf("disk_access_write: ret = %d\n", ret);
ret = disk_access_read(DISK_NAME, buf, 0, 1);
printf("disk_access_read: ret = %d\n", ret);
printf("first 4 byte: %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]);
ret = disk_access_ioctl(DISK_NAME, DISK_IOCTL_CTRL_SYNC, NULL);
printf("disk_access_ioctl SYNC: ret = %d\n", ret);
fflush(stdout);
}
// it works
FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(storage);
static struct fs_mount_t lfs_storage_mnt = {
.type = FS_LITTLEFS,
.fs_data = &storage,
.storage_dev = (void *) FIXED_PARTITION_ID(storage_partition),
.mnt_point = "/lfs",
};
void test_fs() {
int ret = fs_mount(&lfs_storage_mnt);
printf("fs_mount: ret = %d\n", ret);
struct fs_file_t file;
fs_file_t_init(&file);
ret = fs_open(&file, "/lfs/hello.txt", FS_O_CREATE | FS_O_WRITE);
printf("fs_open: ret = %d\n", ret);
const char str[] = "hello, world!";
ret = fs_write(&file, str, sizeof(str));
printf("fs_write: ret = %d\n", ret);
fs_close(&file);
printf("fs_close: ret = %d\n", ret);
fs_file_t_init(&file);
ret = fs_open(&file, "/lfs/hello.txt", FS_O_READ);
printf("fs_open: ret = %d\n", ret);
static char buf[1024];
ret = fs_read(&file, buf, sizeof(buf));
printf("fs_read: ret = %d\n", ret);
printf("%s\n", buf);
fs_close(&file);
fflush(stdout);
}
// it works
void test_fs_posix_read_write() {
const int fd = open("/lfs/posix_raw.txt", O_CREAT | O_RDWR | O_TRUNC);
printf("open: fd = %d, errno = %d (%s)\n", fd, errno, strerror(errno));
const char *msg = "hello raw read/write";
int ret = write(fd, msg, strlen(msg));
printf("write: ret = %d, errno = %d (%s)\n", ret, errno, strerror(errno));
lseek(fd, 0, SEEK_SET);
char buf[1024];
ret = read(fd, buf, 100);
printf("read: ret = %d, errno = %d (%s)\n", ret, errno, strerror(errno));
puts(buf);
ret = close(fd);
printf("close: ret = %d, errno = %d (%s)\n", ret, errno, strerror(errno));
}
// bug here!
void test_fs_posix_fopen() {
FILE *fp = fopen("/lfs/posix.txt", "w+");
printf("fopen: fp = %p, errno = %d (%s)\n", fp, errno, strerror(errno));
const char *msg = "hello world";
int ret = fwrite(msg, sizeof(char), strlen(msg), fp);
printf("fwrite: ret = %d, errno = %d (%s)\n", ret, errno, strerror(errno));
ret = fseek(fp, 0, SEEK_SET);
printf("fseek: ret = %d, errno = %d (%s)\n", ret, errno, strerror(errno));
char buf[1024];
ret = fread(buf, sizeof(char), 100, fp);
printf("fread: ret = %d, errno = %d (%s)\n", ret, errno, strerror(errno));
ret = fclose(fp);
printf("fclose: ret = %d, errno = %d (%s)\n", ret, errno, strerror(errno));
}
int main() {
// test_disk_access();
test_fs();
test_fs_posix_read_write();
test_fs_posix_fopen();
}Relevant log output
fs_mount: ret = 0
fs_open: ret = 0
fs_write: ret = 14
fs_close: ret = 14
fs_open: ret = 0
fs_read: ret = 14
hello, world!
open: fd = 3, errno = 0 (Success)
write: ret = 20, errno = 0 (Success)
read: ret = 20, errno = 0 (Success)
hello raw read/write
close: ret = 0, errno = 0 (Success)
fopen: fp = 0x4080d480, errno = 0 (Success)
fwrite: ret = 0, errno = 0 (Success)
fseek: ret = -1, errno = 29 (Illegal seek)
fread: ret = 0, errno = 29 (Illegal seek)
fclose: ret = 0, errno = 29 (Illegal seek)
(gdb) x/10wx 0x4080d480
0x4080d480 <fdtable+144>: 0x40813130 0x4080d3c8 0x00000001 0x4080d48c
0x4080d490 <fdtable+160>: 0x4080d48c 0x00000000 0x00000000 0x00000000
0x4080d4a0 <fdtable+176>: 0x4080d4a0 0x4080d4a0
(gdb) x/100wx fdtable
0x4080d3f0 <fdtable>: 0x00000000 0x4280102c 0x00000001 0x4080d3fc
0x4080d400 <fdtable+16>: 0x4080d3fc 0x00000000 0x00000000 0x0000000e
0x4080d410 <fdtable+32>: 0x4080d410 0x4080d410 0x00000000 0x00000000
0x4080d420 <fdtable+48>: 0x00000000 0x4280102c 0x00000001 0x4080d42c
0x4080d430 <fdtable+64>: 0x4080d42c 0x00000000 0x00000000 0x0000000e
0x4080d440 <fdtable+80>: 0x4080d440 0x4080d440 0x00000000 0x00000000
0x4080d450 <fdtable+96>: 0x00000000 0x4280102c 0x00000001 0x4080d45c
0x4080d460 <fdtable+112>: 0x4080d45c 0x00000000 0x00000000 0x0000000e
0x4080d470 <fdtable+128>: 0x4080d470 0x4080d470 0x00000000 0x00000000
0x4080d480 <fdtable+144>: 0x40813130 0x4080d3c8 0x00000001 0x4080d48c
0x4080d490 <fdtable+160>: 0x4080d48c 0x00000000 0x00000000 0x00000000
0x4080d4a0 <fdtable+176>: 0x4080d4a0 0x4080d4a0 0x00000000 0x00000000
0x4080d4b0 <fdtable+192>: 0x00000000 0x00000000 0x00000000 0x00000000
0x4080d4c0 <fdtable+208>: 0x00000000 0x00000000 0x00000000 0x00000000
0x4080d4d0 <fdtable+224>: 0x00000000 0x00000000 0x00000000 0x00000000
0x4080d4e0 <fdtable+240>: 0x00000000 0x00000000 0x00000000 0x00000000
0x4080d4f0 <fdtable+256>: 0x00000000 0x00000000 0x00000000 0x00000000
0x4080d500 <fdtable+272>: 0x00000000 0x00000000 0x00000000 0x00000000
0x4080d510 <fdtable+288>: 0x00000000 0x00000000 0x00000000 0x00000000
0x4080d520 <fdtable+304>: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb) p fdtable[0]
$4 = {obj = 0x0, vtable = 0x4280102c <stdinout_fd_op_vtable>, refcount = 1, lock = {wait_q = {waitq = {{head = 0x4080d3fc <fdtable+12>, next = 0x4080d3fc <fdtable+12>}, {tail = 0x4080d3fc <fdtable+12>,
prev = 0x4080d3fc <fdtable+12>}}}, owner = 0x0, lock_count = 0, owner_orig_prio = 14}, cond = {wait_q = {waitq = {{head = 0x4080d410 <fdtable+32>, next = 0x4080d410 <fdtable+32>}, {tail = 0x4080d410 <fdtable+32>,
prev = 0x4080d410 <fdtable+32>}}}}, offset = 0, mode = 0}
(gdb) p fdtable[1]
$5 = {obj = 0x0, vtable = 0x4280102c <stdinout_fd_op_vtable>, refcount = 1, lock = {wait_q = {waitq = {{head = 0x4080d42c <fdtable+60>, next = 0x4080d42c <fdtable+60>}, {tail = 0x4080d42c <fdtable+60>,
prev = 0x4080d42c <fdtable+60>}}}, owner = 0x0, lock_count = 0, owner_orig_prio = 14}, cond = {wait_q = {waitq = {{head = 0x4080d440 <fdtable+80>, next = 0x4080d440 <fdtable+80>}, {tail = 0x4080d440 <fdtable+80>,
prev = 0x4080d440 <fdtable+80>}}}}, offset = 0, mode = 0}
(gdb) p fdtable[2]
$6 = {obj = 0x0, vtable = 0x4280102c <stdinout_fd_op_vtable>, refcount = 1, lock = {wait_q = {waitq = {{head = 0x4080d45c <fdtable+108>, next = 0x4080d45c <fdtable+108>}, {tail = 0x4080d45c <fdtable+108>,
prev = 0x4080d45c <fdtable+108>}}}, owner = 0x0, lock_count = 0, owner_orig_prio = 14}, cond = {wait_q = {waitq = {{head = 0x4080d470 <fdtable+128>, next = 0x4080d470 <fdtable+128>}, {
tail = 0x4080d470 <fdtable+128>, prev = 0x4080d470 <fdtable+128>}}}}, offset = 0, mode = 0}
(gdb) p fdtable[3]
$7 = {obj = 0x40813130 <_k_mem_slab_buf_file_desc_slab>, vtable = 0x4080d3c8 <posix_op_vtable>, refcount = 1, lock = {wait_q = {waitq = {{head = 0x4080d48c <fdtable+156>, next = 0x4080d48c <fdtable+156>}, {
tail = 0x4080d48c <fdtable+156>, prev = 0x4080d48c <fdtable+156>}}}, owner = 0x0, lock_count = 0, owner_orig_prio = 0}, cond = {wait_q = {waitq = {{head = 0x4080d4a0 <fdtable+176>, next = 0x4080d4a0 <fdtable+176>}, {
tail = 0x4080d4a0 <fdtable+176>, prev = 0x4080d4a0 <fdtable+176>}}}}, offset = 0, mode = 0}
(gdb) p fdtable[4]
$8 = {obj = 0x0, vtable = 0x0, refcount = 0, lock = {wait_q = {waitq = {{head = 0x0, next = 0x0}, {tail = 0x0, prev = 0x0}}}, owner = 0x0, lock_count = 0, owner_orig_prio = 0}, cond = {wait_q = {waitq = {{head = 0x0,
next = 0x0}, {tail = 0x0, prev = 0x0}}}}, offset = 0, mode = 0}Impact
Functional Limitation – Some features not working as expected, but system usable.
Environment
Zephyr SDK 4.3.99
Additional Context
No response
Metadata
Metadata
Assignees
Labels
area: picolibcPicolibc C Standard LibraryPicolibc C Standard LibrarybugThe issue is a bug, or the PR is fixing a bugThe issue is a bug, or the PR is fixing a bugpriority: mediumMedium impact/importance bugMedium impact/importance bug