13
13
14
14
#define UVWASI__READDIR_NUM_ENTRIES 1
15
15
16
+ #if !defined(_WIN32 ) && !defined(__ANDROID__ )
17
+ # define UVWASI_FD_READDIR_SUPPORTED 1
18
+ #endif
19
+
16
20
#include "uvwasi.h"
17
21
#include "uvwasi_alloc.h"
18
22
#include "uv.h"
22
26
#include "path_resolver.h"
23
27
#include "poll_oneoff.h"
24
28
#include "wasi_rights.h"
29
+ #include "wasi_serdes.h"
25
30
#include "debug.h"
26
31
27
32
/* IBMi PASE does not support posix_fadvise() */
@@ -1268,7 +1273,7 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
1268
1273
uvwasi_size_t buf_len ,
1269
1274
uvwasi_dircookie_t cookie ,
1270
1275
uvwasi_size_t * bufused ) {
1271
- /* TODO(cjihrig): Support Windows where seekdir() and telldir() are used. */
1276
+ #if defined( UVWASI_FD_READDIR_SUPPORTED )
1272
1277
/* TODO(cjihrig): Avoid opening and closing the directory on each call. */
1273
1278
struct uvwasi_fd_wrap_t * wrap ;
1274
1279
uvwasi_dirent_t dirent ;
@@ -1282,6 +1287,7 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
1282
1287
long tell ;
1283
1288
int i ;
1284
1289
int r ;
1290
+ #endif /* defined(UVWASI_FD_READDIR_SUPPORTED) */
1285
1291
1286
1292
UVWASI_DEBUG ("uvwasi_fd_readdir(uvwasi=%p, fd=%d, buf=%p, buf_len=%d, "
1287
1293
"cookie=%" PRIu64 ", bufused=%p)\n" ,
@@ -1295,6 +1301,7 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
1295
1301
if (uvwasi == NULL || buf == NULL || bufused == NULL )
1296
1302
return UVWASI_EINVAL ;
1297
1303
1304
+ #if defined(UVWASI_FD_READDIR_SUPPORTED )
1298
1305
err = uvwasi_fd_table_get (uvwasi -> fds ,
1299
1306
fd ,
1300
1307
& wrap ,
@@ -1316,12 +1323,9 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
1316
1323
dir -> nentries = UVWASI__READDIR_NUM_ENTRIES ;
1317
1324
uv_fs_req_cleanup (& req );
1318
1325
1319
- #ifndef _WIN32
1320
- /* TODO(cjihrig): Need a Windows equivalent of this logic. */
1321
1326
/* Seek to the proper location in the directory. */
1322
1327
if (cookie != UVWASI_DIRCOOKIE_START )
1323
1328
seekdir (dir -> dir , cookie );
1324
- #endif
1325
1329
1326
1330
/* Read the directory entries into the provided buffer. */
1327
1331
err = UVWASI_ESUCCESS ;
@@ -1333,25 +1337,20 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
1333
1337
goto exit ;
1334
1338
}
1335
1339
1340
+ available = 0 ;
1341
+
1336
1342
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
1342
1343
tell = telldir (dir -> dir );
1343
1344
if (tell < 0 ) {
1344
1345
err = uvwasi__translate_uv_error (uv_translate_sys_error (errno ));
1345
1346
uv_fs_req_cleanup (& req );
1346
1347
goto exit ;
1347
1348
}
1348
- #else
1349
- tell = 0 ; /* TODO(cjihrig): Need to support Windows. */
1350
- #endif /* _WIN32 */
1351
1349
1352
1350
name_len = strlen (dirents [i ].name );
1353
1351
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()? */
1355
1354
dirent .d_ino = 0 ;
1356
1355
dirent .d_namlen = name_len ;
1357
1356
@@ -1381,21 +1380,24 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
1381
1380
break ;
1382
1381
}
1383
1382
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 ;
1390
1389
available = buf_len - * bufused ;
1390
+
1391
+ /* Write as much of the entry name to the buffer as possible. */
1391
1392
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 );
1393
1394
* bufused += size_to_cp ;
1395
+ available = buf_len - * bufused ;
1394
1396
}
1395
1397
1396
1398
uv_fs_req_cleanup (& req );
1397
1399
1398
- if (* bufused >= buf_len )
1400
+ if (available == 0 )
1399
1401
break ;
1400
1402
}
1401
1403
@@ -1408,6 +1410,10 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
1408
1410
return uvwasi__translate_uv_error (r );
1409
1411
1410
1412
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) */
1411
1417
}
1412
1418
1413
1419
@@ -2353,6 +2359,7 @@ uvwasi_errno_t uvwasi_poll_oneoff(uvwasi_t* uvwasi,
2353
2359
if (err != UVWASI_ESUCCESS )
2354
2360
return err ;
2355
2361
2362
+ timer_userdata = 0 ;
2356
2363
has_timeout = 0 ;
2357
2364
min_timeout = 0 ;
2358
2365
0 commit comments