diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index 4be0e8b058c996..e7b10af8ce7c4a 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -71,6 +71,10 @@ if (NOT CONFIG_TC_PROVIDES_POSIX_FILE_SYSTEM) zephyr_library_sources_ifdef(CONFIG_POSIX_FILE_SYSTEM fs.c) endif() +if (NOT CONFIG_TC_PROVIDES_POSIX_FILE_SYSTEM_R) + zephyr_library_sources_ifdef(CONFIG_POSIX_FILE_SYSTEM_R file_system_r.c) +endif() + zephyr_library_sources_ifdef(CONFIG_POSIX_FSYNC fsync.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MEMLOCK mlockall.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MEMLOCK_RANGE mlock.c) diff --git a/lib/posix/options/Kconfig b/lib/posix/options/Kconfig index f453f5295d02d0..c7e60d9e3238e7 100644 --- a/lib/posix/options/Kconfig +++ b/lib/posix/options/Kconfig @@ -14,6 +14,7 @@ rsource "Kconfig.c_lang_r" rsource "Kconfig.c_lib_ext" rsource "Kconfig.device_io" rsource "Kconfig.fd_mgmt" +rsource "Kconfig.file_system_r" rsource "Kconfig.fs" rsource "Kconfig.mem" rsource "Kconfig.mqueue" diff --git a/lib/posix/options/Kconfig.file_system_r b/lib/posix/options/Kconfig.file_system_r new file mode 100644 index 00000000000000..f6f66f4f7f2388 --- /dev/null +++ b/lib/posix/options/Kconfig.file_system_r @@ -0,0 +1,14 @@ +# Copyright (c) 2018 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +config POSIX_FILE_SYSTEM_R + bool "Thread-Safe File System" + select FILE_SYSTEM + select FDTABLE + help + Select 'y' here and Zephyr will provide an implementation of the POSIX_FILE_SYSTEM_R + Option Group, consisting of readdir_r(). + + For more informnation, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html diff --git a/lib/posix/options/Kconfig.fs b/lib/posix/options/Kconfig.fs index ce1acb118e0f4b..bc492e5dc7a03d 100644 --- a/lib/posix/options/Kconfig.fs +++ b/lib/posix/options/Kconfig.fs @@ -17,13 +17,4 @@ config POSIX_FILE_SYSTEM_ALIAS_FSTAT help When selected via Kconfig, Zephyr will provide an alias for fstat() as _fstat(). -config POSIX_FILE_SYSTEM_R - bool "Thread-Safe File System" - help - Select 'y' here and Zephyr will provide an implementation of the POSIX_FILE_SYSTEM_R - Option Group, consisting of readdir_r(). - - For more informnation, please see - https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html - endif # POSIX_FILE_SYSTEM diff --git a/lib/posix/options/Kconfig.pthread b/lib/posix/options/Kconfig.pthread index f821d9defebb45..4eef794039a316 100644 --- a/lib/posix/options/Kconfig.pthread +++ b/lib/posix/options/Kconfig.pthread @@ -156,7 +156,7 @@ config POSIX_THREAD_PRIO_PROTECT config POSIX_THREAD_SAFE_FUNCTIONS bool "POSIX thread-safe functions" - select POSIX_FILE_SYSTEM_R if POSIX_FILE_SYSTEM + select POSIX_FILE_SYSTEM_R select POSIX_C_LANG_SUPPORT_R help Select 'y' here to enable POSIX thread-safe functions including asctime_r(), ctime_r(), diff --git a/lib/posix/options/file_system_r.c b/lib/posix/options/file_system_r.c new file mode 100644 index 00000000000000..1e967764ef9773 --- /dev/null +++ b/lib/posix/options/file_system_r.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200809L + +#include "fs_priv.h" + +#include +#include +#include + +#include +#include +#include + +int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) +{ + int rc; + struct fs_dirent de; + struct posix_fs_desc *const ptr = dirp; + + if (result == NULL) { + return EINVAL; + } + + if (entry == NULL) { + *result = NULL; + return EINVAL; + } + + if (dirp == NULL) { + *result = NULL; + return EBADF; + } + + rc = fs_readdir(&ptr->dir, &de); + if (rc < 0) { + *result = NULL; + return -rc; + } + + strncpy(entry->d_name, de.name, MIN(sizeof(entry->d_name), sizeof(de.name))); + entry->d_name[sizeof(entry->d_name) - 1] = '\0'; + + if (entry->d_name[0] == '\0') { + *result = NULL; + return 0; + } + + *result = entry; + return 0; +} diff --git a/lib/posix/options/fs.c b/lib/posix/options/fs.c index c8221a35f955d9..45028248608f7c 100644 --- a/lib/posix/options/fs.c +++ b/lib/posix/options/fs.c @@ -6,6 +6,9 @@ #undef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200809L + +#include "fs_priv.h" + #include #include #include @@ -21,15 +24,6 @@ int zvfs_fstat(int fd, struct stat *buf); BUILD_ASSERT(PATH_MAX >= MAX_FILE_NAME, "PATH_MAX is less than MAX_FILE_NAME"); -struct posix_fs_desc { - union { - struct fs_file_t file; - struct fs_dir_t dir; - }; - bool is_dir; - bool used; -}; - static struct posix_fs_desc desc_array[CONFIG_POSIX_OPEN_MAX]; static struct fs_dirent fdirent; @@ -337,40 +331,6 @@ struct dirent *readdir(DIR *dirp) return &pdirent; } -#ifdef CONFIG_POSIX_FILE_SYSTEM_R -int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) -{ - struct dirent *dir; - - errno = 0; - - dir = readdir(dirp); - if (dir == NULL) { - int error = errno; - - if (error != 0) { - if (result != NULL) { - *result = NULL; - } - - return 0; - } else { - return error; - } - } - - if (entry != NULL) { - memcpy(entry, dir, sizeof(struct dirent)); - } - - if (result != NULL) { - *result = entry; - } - - return 0; -} -#endif /* CONFIG_POSIX_FILE_SYSTEM_R */ - /** * @brief Rename a file. * diff --git a/lib/posix/options/fs_priv.h b/lib/posix/options/fs_priv.h new file mode 100644 index 00000000000000..2c3ddb2084e823 --- /dev/null +++ b/lib/posix/options/fs_priv.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2018 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_LIB_POSIX_OPTIONS_FS_PRIV_H_ +#define ZEPHYR_LIB_POSIX_OPTIONS_FS_PRIV_H_ + +#include + +#include + +struct posix_fs_desc { + union { + struct fs_file_t file; + struct fs_dir_t dir; + }; + bool is_dir: 1; + bool used: 1; +}; + +#endif diff --git a/tests/posix/fs/prj.conf b/tests/posix/fs/prj.conf index da73481ef4d1ab..e1501c697ae191 100644 --- a/tests/posix/fs/prj.conf +++ b/tests/posix/fs/prj.conf @@ -3,6 +3,8 @@ CONFIG_LOG=y CONFIG_FAT_FILESYSTEM_ELM=y CONFIG_POSIX_API=y CONFIG_POSIX_FILE_SYSTEM=y +CONFIG_POSIX_FILE_SYSTEM_R=y CONFIG_ZTEST=y CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_ZTEST_STACK_SIZE=2048 CONFIG_EVENTFD=n diff --git a/tests/posix/fs/src/test_fs_dir.c b/tests/posix/fs/src/test_fs_dir.c index c9d967016d60b7..52a36e66304aef 100644 --- a/tests/posix/fs/src/test_fs_dir.c +++ b/tests/posix/fs/src/test_fs_dir.c @@ -57,10 +57,10 @@ static int test_mkdir(void) static struct dirent *readdir_wrap(DIR *dirp, bool thread_safe) { if (thread_safe) { - struct dirent *entry = NULL; + struct dirent entry; struct dirent *result = NULL; - zassert_ok(readdir_r(dirp, entry, &result)); + zassert_ok(readdir_r(dirp, &entry, &result)); return result; } else {