Skip to content

Commit 7556473

Browse files
dkouba-atymsrberard
authored andcommitted
Directory support WIP
readdir works but I think we have a memory leak somewhere
1 parent 442ea20 commit 7556473

File tree

2 files changed

+88
-23
lines changed

2 files changed

+88
-23
lines changed

core/shared/platform/zephyr/platform_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ typedef struct zephyr_fs_desc {
251251
};
252252
bool is_dir;
253253
bool used;
254+
uint32_t dir_index; // DSK: supprt for rewind and seek
254255
} zephyr_fs_desc;
255256

256257
// definition of zephyr_handle

core/shared/platform/zephyr/zephyr_file.c

Lines changed: 87 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ zephyr_fs_alloc_obj(bool is_dir, const char *path, int *index)
125125
ptr->used = true;
126126
ptr->is_dir = is_dir;
127127
ptr->path = duplicate_string(path);
128+
ptr->dir_index = 0;
128129
if (ptr->path == NULL) {
129130
ptr->used = false;
130131
k_mutex_unlock(&desc_array_mutex);
@@ -253,7 +254,9 @@ os_fstatat(os_file_handle handle, const char *path,
253254

254255
// Fill in the __wasi_filestat_t structure
255256
buf->st_dev = 0; // Zephyr's fs_stat doesn't provide a device ID
256-
buf->st_ino = 0; // Zephyr's fs_stat doesn't provide an inode number
257+
// DSK: setting this to 0, in addition to d_ino = 1 causes failures with readdir()
258+
// So, here's a hack to to avoid this.
259+
buf->st_ino = 1; // Zephyr's fs_stat doesn't provide an inode number.
257260
buf->st_filetype = entry.type == FS_DIR_ENTRY_DIR
258261
? __WASI_FILETYPE_DIRECTORY
259262
: __WASI_FILETYPE_REGULAR_FILE;
@@ -439,29 +442,31 @@ os_openat(os_file_handle handle, const char *path, __wasi_oflags_t oflags,
439442
return __WASI_ENOMEM;
440443
}
441444

442-
ptr = zephyr_fs_alloc_obj(oflags & __WASI_O_DIRECTORY, abs_path, &index);
445+
// Treat directories as a special case
446+
bool is_dir = oflags & __WASI_O_DIRECTORY;
447+
448+
ptr = zephyr_fs_alloc_obj(is_dir, abs_path, &index);
443449
if (!ptr && (index < 0)) {
444450
BH_FREE(*out);
445451
return __WASI_EMFILE;
446452
}
447453

448-
if (oflags & __WASI_O_DIRECTORY) {
449-
// Is a directory
454+
if (is_dir) {
450455
fs_dir_t_init(&ptr->dir);
451-
rc = fs_opendir(&ptr->dir, abs_path);
452-
}
453-
else {
456+
// fs_opendir() is called in libc later - don't call here
457+
}
458+
else {
454459
// Is a file
455460
int zmode =
456461
wasi_flags_to_zephyr(oflags, fd_flags, lookup_flags, access_mode);
457462
fs_file_t_init(&ptr->file);
458463
rc = fs_open(&ptr->file, abs_path, zmode);
459-
}
460464

461-
if (rc < 0) {
462-
zephyr_fs_free_obj(ptr);
463-
BH_FREE(*out);
464-
return convert_errno(-rc);
465+
if (rc < 0) {
466+
zephyr_fs_free_obj(ptr);
467+
BH_FREE(*out);
468+
return convert_errno(-rc);
469+
}
465470
}
466471

467472
(*out)->fd = index;
@@ -977,16 +982,57 @@ os_fdopendir(os_file_handle handle, os_dir_stream *dir_stream)
977982
return __WASI_ESUCCESS;
978983
}
979984

980-
__wasi_errno_t
981-
os_rewinddir(os_dir_stream dir_stream)
982-
{
983-
return __WASI_ENOSYS;
985+
// DSK: simple open and close to rewind index.
986+
__wasi_errno_t
987+
os_rewinddir(os_dir_stream dir_stream) {
988+
struct zephyr_fs_desc *ptr = NULL;
989+
GET_FILE_SYSTEM_DESCRIPTOR(dir_stream, ptr);
990+
991+
if (!ptr->is_dir)
992+
return __WASI_ENOTDIR;
993+
994+
int rc = fs_closedir(&ptr->dir); // Close current stream
995+
if (rc < 0)
996+
return convert_errno(-rc);
997+
998+
rc = fs_opendir(&ptr->dir, ptr->path); // Reopen from start
999+
if (rc < 0)
1000+
return convert_errno(-rc);
1001+
1002+
ptr->dir_index = 0; // Reset virtual position tracker
1003+
return __WASI_ESUCCESS;
9841004
}
9851005

986-
__wasi_errno_t
987-
os_seekdir(os_dir_stream dir_stream, __wasi_dircookie_t position)
988-
{
989-
return __WASI_ENOSYS;
1006+
// DSK: start from 0 and linear seek since there's no cookies in the zephyr fs
1007+
// TODO: duplicated code with rewinddir
1008+
__wasi_errno_t
1009+
os_seekdir(os_dir_stream dir_stream, __wasi_dircookie_t position) {
1010+
struct zephyr_fs_desc *ptr = NULL;
1011+
GET_FILE_SYSTEM_DESCRIPTOR(dir_stream, ptr);
1012+
1013+
if (!ptr->is_dir)
1014+
return __WASI_ENOTDIR;
1015+
1016+
int rc = fs_closedir(&ptr->dir);
1017+
if (rc < 0)
1018+
return convert_errno(-rc);
1019+
1020+
rc = fs_opendir(&ptr->dir, ptr->path);
1021+
if (rc < 0)
1022+
return convert_errno(-rc);
1023+
1024+
// Emulate seek by re-reading entries up to 'position'
1025+
struct fs_dirent tmp;
1026+
for (__wasi_dircookie_t i = 0; i < position; i++) {
1027+
rc = fs_readdir(&ptr->dir, &tmp);
1028+
if (rc < 0)
1029+
return convert_errno(-rc);
1030+
if (tmp.name[0] == '\0')
1031+
break; // End of directory
1032+
}
1033+
1034+
ptr->dir_index = position;
1035+
return __WASI_ESUCCESS;
9901036
}
9911037

9921038
__wasi_errno_t
@@ -995,7 +1041,6 @@ os_readdir(os_dir_stream dir_stream, __wasi_dirent_t *entry,
9951041
{
9961042
struct fs_dirent fs_entry;
9971043
struct zephyr_fs_desc *ptr = NULL;
998-
9991044
GET_FILE_SYSTEM_DESCRIPTOR(dir_stream, ptr);
10001045
if (!ptr->is_dir) {
10011046
return __WASI_ENOTDIR;
@@ -1006,13 +1051,31 @@ os_readdir(os_dir_stream dir_stream, __wasi_dirent_t *entry,
10061051
return convert_errno(-rc);
10071052
}
10081053

1009-
entry->d_next = 0; // default value to start of the directory.
1010-
entry->d_ino = 0; // no inode in zephyr
1054+
if (fs_entry.name[0] == '\0') {
1055+
// DSK: the caller expects the name buffer to be null
1056+
// when we've reached the end of the directory.
1057+
*d_name = NULL;
1058+
return __WASI_ESUCCESS;
1059+
}
1060+
1061+
// DSK: emulated increasing value for rewinddir and seekdir
1062+
entry->d_next = ++ptr->dir_index;
1063+
1064+
// DSK: A hack to get readdir working. This needs to be non-zero along with st_ino
1065+
// for the libc side of readdir to work correctly.
1066+
entry->d_ino = 1 + ptr->dir_index;
1067+
10111068
entry->d_namlen = strlen(fs_entry.name);
10121069
entry->d_type = fs_entry.type == FS_DIR_ENTRY_DIR
10131070
? __WASI_FILETYPE_DIRECTORY
10141071
: __WASI_FILETYPE_REGULAR_FILE;
10151072

1073+
// DSK: name exists in fs_entry and we need to return it
1074+
static char name_buf[MAX_FILE_NAME + 1];
1075+
strncpy(name_buf, fs_entry.name, MAX_FILE_NAME);
1076+
name_buf[MAX_FILE_NAME] = '\0';
1077+
*d_name = name_buf;
1078+
10161079
return __WASI_ESUCCESS;
10171080
}
10181081

@@ -1044,6 +1107,7 @@ os_get_invalid_dir_stream()
10441107
bool
10451108
os_is_dir_stream_valid(os_dir_stream *dir_stream)
10461109
{
1110+
// DSK: this probably needs a check...
10471111
return false;
10481112
}
10491113

0 commit comments

Comments
 (0)