1313
1414#define UVWASI__READDIR_NUM_ENTRIES 1
1515
16+ #if !defined(_WIN32 ) && !defined(__ANDROID__ )
17+ # define UVWASI_FD_READDIR_SUPPORTED 1
18+ #endif
19+
1620#include "uvwasi.h"
1721#include "uvwasi_alloc.h"
1822#include "uv.h"
2226#include "path_resolver.h"
2327#include "poll_oneoff.h"
2428#include "wasi_rights.h"
29+ #include "wasi_serdes.h"
2530#include "debug.h"
2631
2732/* IBMi PASE does not support posix_fadvise() */
@@ -1268,7 +1273,7 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
12681273 uvwasi_size_t buf_len ,
12691274 uvwasi_dircookie_t cookie ,
12701275 uvwasi_size_t * bufused ) {
1271- /* TODO(cjihrig): Support Windows where seekdir() and telldir() are used. */
1276+ #if defined( UVWASI_FD_READDIR_SUPPORTED )
12721277 /* TODO(cjihrig): Avoid opening and closing the directory on each call. */
12731278 struct uvwasi_fd_wrap_t * wrap ;
12741279 uvwasi_dirent_t dirent ;
@@ -1282,6 +1287,7 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
12821287 long tell ;
12831288 int i ;
12841289 int r ;
1290+ #endif /* defined(UVWASI_FD_READDIR_SUPPORTED) */
12851291
12861292 UVWASI_DEBUG ("uvwasi_fd_readdir(uvwasi=%p, fd=%d, buf=%p, buf_len=%d, "
12871293 "cookie=%" PRIu64 ", bufused=%p)\n" ,
@@ -1295,6 +1301,7 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
12951301 if (uvwasi == NULL || buf == NULL || bufused == NULL )
12961302 return UVWASI_EINVAL ;
12971303
1304+ #if defined(UVWASI_FD_READDIR_SUPPORTED )
12981305 err = uvwasi_fd_table_get (uvwasi -> fds ,
12991306 fd ,
13001307 & wrap ,
@@ -1316,12 +1323,9 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
13161323 dir -> nentries = UVWASI__READDIR_NUM_ENTRIES ;
13171324 uv_fs_req_cleanup (& req );
13181325
1319- #ifndef _WIN32
1320- /* TODO(cjihrig): Need a Windows equivalent of this logic. */
13211326 /* Seek to the proper location in the directory. */
13221327 if (cookie != UVWASI_DIRCOOKIE_START )
13231328 seekdir (dir -> dir , cookie );
1324- #endif
13251329
13261330 /* Read the directory entries into the provided buffer. */
13271331 err = UVWASI_ESUCCESS ;
@@ -1333,25 +1337,20 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
13331337 goto exit ;
13341338 }
13351339
1340+ available = 0 ;
1341+
13361342 for (i = 0 ; i < r ; i ++ ) {
1337- /* TODO(cjihrig): This should probably be serialized to the buffer
1338- consistently across platforms. In other words, d_next should always
1339- be 8 bytes, d_ino should always be 8 bytes, d_namlen should always be
1340- 4 bytes, and d_type should always be 1 byte. */
1341- #ifndef _WIN32
13421343 tell = telldir (dir -> dir );
13431344 if (tell < 0 ) {
13441345 err = uvwasi__translate_uv_error (uv_translate_sys_error (errno ));
13451346 uv_fs_req_cleanup (& req );
13461347 goto exit ;
13471348 }
1348- #else
1349- tell = 0 ; /* TODO(cjihrig): Need to support Windows. */
1350- #endif /* _WIN32 */
13511349
13521350 name_len = strlen (dirents [i ].name );
13531351 dirent .d_next = (uvwasi_dircookie_t ) tell ;
1354- /* TODO(cjihrig): Missing ino libuv (and Windows) support. fstat()? */
1352+ /* TODO(cjihrig): libuv doesn't provide d_ino, and d_type is not
1353+ supported on all platforms. Use stat()? */
13551354 dirent .d_ino = 0 ;
13561355 dirent .d_namlen = name_len ;
13571356
@@ -1381,21 +1380,24 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
13811380 break ;
13821381 }
13831382
1384- /* Write dirent to the buffer. */
1385- available = buf_len - * bufused ;
1386- size_to_cp = sizeof ( dirent ) > available ? available : sizeof ( dirent ) ;
1387- memcpy (( char * ) buf + * bufused , & dirent , size_to_cp );
1388- * bufused += size_to_cp ;
1389- /* Write the entry name to the buffer. */
1383+ /* Write dirent to the buffer if it will fit . */
1384+ if ( UVWASI_SERDES_SIZE_dirent_t + * bufused > buf_len )
1385+ break ;
1386+
1387+ uvwasi_serdes_write_dirent_t ( buf , * bufused , & dirent ) ;
1388+ * bufused += UVWASI_SERDES_SIZE_dirent_t ;
13901389 available = buf_len - * bufused ;
1390+
1391+ /* Write as much of the entry name to the buffer as possible. */
13911392 size_to_cp = name_len > available ? available : name_len ;
1392- memcpy ((char * )buf + * bufused , & dirents [i ].name , size_to_cp );
1393+ memcpy ((char * )buf + * bufused , dirents [i ].name , size_to_cp );
13931394 * bufused += size_to_cp ;
1395+ available = buf_len - * bufused ;
13941396 }
13951397
13961398 uv_fs_req_cleanup (& req );
13971399
1398- if (* bufused >= buf_len )
1400+ if (available == 0 )
13991401 break ;
14001402 }
14011403
@@ -1408,6 +1410,10 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
14081410 return uvwasi__translate_uv_error (r );
14091411
14101412 return err ;
1413+ #else
1414+ /* TODO(cjihrig): Need a solution for Windows and Android. */
1415+ return UVWASI_ENOSYS ;
1416+ #endif /* defined(UVWASI_FD_READDIR_SUPPORTED) */
14111417}
14121418
14131419
@@ -2353,6 +2359,7 @@ uvwasi_errno_t uvwasi_poll_oneoff(uvwasi_t* uvwasi,
23532359 if (err != UVWASI_ESUCCESS )
23542360 return err ;
23552361
2362+ timer_userdata = 0 ;
23562363 has_timeout = 0 ;
23572364 min_timeout = 0 ;
23582365
0 commit comments