@@ -125,6 +125,7 @@ zephyr_fs_alloc_obj(bool is_dir, const char *path, int *index)
125
125
ptr -> used = true;
126
126
ptr -> is_dir = is_dir ;
127
127
ptr -> path = duplicate_string (path );
128
+ ptr -> dir_index = 0 ;
128
129
if (ptr -> path == NULL ) {
129
130
ptr -> used = false;
130
131
k_mutex_unlock (& desc_array_mutex );
@@ -253,7 +254,9 @@ os_fstatat(os_file_handle handle, const char *path,
253
254
254
255
// Fill in the __wasi_filestat_t structure
255
256
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.
257
260
buf -> st_filetype = entry .type == FS_DIR_ENTRY_DIR
258
261
? __WASI_FILETYPE_DIRECTORY
259
262
: __WASI_FILETYPE_REGULAR_FILE ;
@@ -439,29 +442,31 @@ os_openat(os_file_handle handle, const char *path, __wasi_oflags_t oflags,
439
442
return __WASI_ENOMEM ;
440
443
}
441
444
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 );
443
449
if (!ptr && (index < 0 )) {
444
450
BH_FREE (* out );
445
451
return __WASI_EMFILE ;
446
452
}
447
453
448
- if (oflags & __WASI_O_DIRECTORY ) {
449
- // Is a directory
454
+ if (is_dir ) {
450
455
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 {
454
459
// Is a file
455
460
int zmode =
456
461
wasi_flags_to_zephyr (oflags , fd_flags , lookup_flags , access_mode );
457
462
fs_file_t_init (& ptr -> file );
458
463
rc = fs_open (& ptr -> file , abs_path , zmode );
459
- }
460
464
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
+ }
465
470
}
466
471
467
472
(* out )-> fd = index ;
@@ -977,16 +982,57 @@ os_fdopendir(os_file_handle handle, os_dir_stream *dir_stream)
977
982
return __WASI_ESUCCESS ;
978
983
}
979
984
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 ;
984
1004
}
985
1005
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 ;
990
1036
}
991
1037
992
1038
__wasi_errno_t
@@ -995,7 +1041,6 @@ os_readdir(os_dir_stream dir_stream, __wasi_dirent_t *entry,
995
1041
{
996
1042
struct fs_dirent fs_entry ;
997
1043
struct zephyr_fs_desc * ptr = NULL ;
998
-
999
1044
GET_FILE_SYSTEM_DESCRIPTOR (dir_stream , ptr );
1000
1045
if (!ptr -> is_dir ) {
1001
1046
return __WASI_ENOTDIR ;
@@ -1006,13 +1051,31 @@ os_readdir(os_dir_stream dir_stream, __wasi_dirent_t *entry,
1006
1051
return convert_errno (- rc );
1007
1052
}
1008
1053
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
+
1011
1068
entry -> d_namlen = strlen (fs_entry .name );
1012
1069
entry -> d_type = fs_entry .type == FS_DIR_ENTRY_DIR
1013
1070
? __WASI_FILETYPE_DIRECTORY
1014
1071
: __WASI_FILETYPE_REGULAR_FILE ;
1015
1072
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
+
1016
1079
return __WASI_ESUCCESS ;
1017
1080
}
1018
1081
@@ -1044,6 +1107,7 @@ os_get_invalid_dir_stream()
1044
1107
bool
1045
1108
os_is_dir_stream_valid (os_dir_stream * dir_stream )
1046
1109
{
1110
+ // DSK: this probably needs a check...
1047
1111
return false;
1048
1112
}
1049
1113
0 commit comments