Skip to content

Commit b7ad4c5

Browse files
ycsincarlescufi
authored andcommitted
posix: fs: implement readdir_r
Add implementation for `readdir_r()`. Signed-off-by: Yong Cong Sin <[email protected]>
1 parent 33d92b4 commit b7ad4c5

File tree

5 files changed

+65
-5
lines changed

5 files changed

+65
-5
lines changed

doc/services/portability/posix/option_groups/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -997,7 +997,7 @@ Enable this option with :kconfig:option:`CONFIG_POSIX_THREAD_SAFE_FUNCTIONS`.
997997
putc_unlocked(),
998998
putchar_unlocked(),
999999
rand_r(), yes
1000-
readdir_r(),
1000+
readdir_r(), yes
10011001
strerror_r(), yes
10021002
strtok_r(), yes
10031003

include/zephyr/posix/dirent.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ struct dirent {
2727
DIR *opendir(const char *dirname);
2828
int closedir(DIR *dirp);
2929
struct dirent *readdir(DIR *dirp);
30+
int readdir_r(DIR *ZRESTRICT dirp, struct dirent *ZRESTRICT entry,
31+
struct dirent **ZRESTRICT result);
3032

3133
#ifdef __cplusplus
3234
}

lib/posix/options/fs.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,40 @@ struct dirent *readdir(DIR *dirp)
314314
return &pdirent;
315315
}
316316

317+
#ifdef CONFIG_POSIX_THREAD_SAFE_FUNCTIONS
318+
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
319+
{
320+
struct dirent *dir;
321+
322+
errno = 0;
323+
324+
dir = readdir(dirp);
325+
if (dir == NULL) {
326+
int error = errno;
327+
328+
if (error != 0) {
329+
if (result != NULL) {
330+
*result = NULL;
331+
}
332+
333+
return 0;
334+
} else {
335+
return error;
336+
}
337+
}
338+
339+
if (entry != NULL) {
340+
memcpy(entry, dir, sizeof(struct dirent));
341+
}
342+
343+
if (result != NULL) {
344+
*result = entry;
345+
}
346+
347+
return 0;
348+
}
349+
#endif /* CONFIG_POSIX_THREAD_SAFE_FUNCTIONS */
350+
317351
/**
318352
* @brief Rename a file.
319353
*

tests/posix/fs/src/test_fs_dir.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,21 @@ static int test_mkdir(void)
5151
return res;
5252
}
5353

54-
static int test_lsdir(const char *path)
54+
static struct dirent *readdir_wrap(DIR *dirp, bool thread_safe)
55+
{
56+
if (thread_safe) {
57+
struct dirent *entry = NULL;
58+
struct dirent *result = NULL;
59+
60+
zassert_ok(readdir_r(dirp, entry, &result));
61+
62+
return result;
63+
} else {
64+
return readdir(dirp);
65+
}
66+
}
67+
68+
static int test_lsdir(const char *path, bool thread_safe)
5569
{
5670
DIR *dirp;
5771
int res = 0;
@@ -69,7 +83,7 @@ static int test_lsdir(const char *path)
6983
TC_PRINT("\nListing dir %s:\n", path);
7084
/* Verify fs_readdir() */
7185
errno = 0;
72-
while ((entry = readdir(dirp)) != NULL) {
86+
while ((entry = readdir_wrap(dirp, thread_safe)) != NULL) {
7387
if (entry->d_name[0] == 0) {
7488
res = -EIO;
7589
break;
@@ -124,5 +138,15 @@ ZTEST(posix_fs_dir_test, test_fs_readdir)
124138
{
125139
/* FIXME: restructure tests as per #46897 */
126140
zassert_true(test_mkdir() == TC_PASS);
127-
zassert_true(test_lsdir(TEST_DIR) == TC_PASS);
141+
zassert_true(test_lsdir(TEST_DIR, false) == TC_PASS);
142+
}
143+
144+
/**
145+
* Same test as `test_fs_readdir`, but use thread-safe `readdir_r()` function
146+
*/
147+
ZTEST(posix_fs_dir_test, test_fs_readdir_threadsafe)
148+
{
149+
/* FIXME: restructure tests as per #46897 */
150+
zassert_true(test_mkdir() == TC_PASS);
151+
zassert_true(test_lsdir(TEST_DIR, true) == TC_PASS);
128152
}

tests/posix/headers/src/dirent_h.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ ZTEST(posix_headers, test_dirent_h)
3131
/* zassert_not_null(fdopendir); */ /* not implemented */
3232
zassert_not_null(opendir);
3333
zassert_not_null(readdir);
34-
/* zassert_not_null(readdir_r); */ /* not implemented */
34+
zassert_not_null(readdir_r);
3535
/* zassert_not_null(rewinddir); */ /* not implemented */
3636
/* zassert_not_null(scandir); */ /* not implemented */
3737
/* zassert_not_null(seekdir); */ /* not implemented */

0 commit comments

Comments
 (0)