MCPcopy Create free account
hub / github.com/WasmEdge/WasmEdge / fdReaddir

Method fdReaddir

lib/host/wasi/inode-macos.cpp:462–521  ·  view source on GitHub ↗

Due to the unfortunate design of wasi::fd_readdir, It's nearly impossible to provide a correct implementation. The below implementation is just a workaround for most usages and may not be correct in some edge cases. The readdir entry API is going to be updated to use a stream type, so we don't have to deal with it right now.

Source from the content-addressed store, hash-verified

460// readdir entry API is going to be updated to use a stream type, so we don't
461// have to deal with it right now.
462WasiExpect<void> INode::fdReaddir(Span<uint8_t> Buffer,
463 __wasi_dircookie_t Cookie,
464 __wasi_size_t &Size) noexcept {
465 if (unlikely(!Dir.ok())) {
466 if (FdHolder NewFd(::dup(Fd)); unlikely(!NewFd.ok())) {
467 return WasiUnexpect(fromErrNo(errno));
468 } else if (DIR *D = ::fdopendir(NewFd.Fd); unlikely(!D)) {
469 return WasiUnexpect(fromErrNo(errno));
470 } else {
471 NewFd.release();
472 Dir.emplace(D);
473 }
474 }
475
476 if (Cookie == 0) {
477 ::rewinddir(Dir.Dir);
478 } else if (unlikely(Cookie != Dir.Cookie)) {
479 ::seekdir(Dir.Dir, Cookie);
480 }
481
482 Size = 0;
483 do {
484 if (!Dir.Buffer.empty()) {
485 const auto NewDataSize =
486 std::min<uint32_t>(Buffer.size(), Dir.Buffer.size());
487 std::copy(Dir.Buffer.begin(), Dir.Buffer.begin() + NewDataSize,
488 Buffer.begin());
489 Buffer = Buffer.subspan(NewDataSize);
490 Size += NewDataSize;
491 Dir.Buffer.clear();
492 if (unlikely(Buffer.empty())) {
493 break;
494 }
495 }
496 errno = 0;
497 dirent *SysDirent = ::readdir(Dir.Dir);
498 if (SysDirent == nullptr) {
499 if (errno != 0) {
500 return WasiUnexpect(fromErrNo(errno));
501 }
502 // End of entries
503 break;
504 }
505 Dir.Cookie = ::telldir(Dir.Dir);
506 std::string_view Name = SysDirent->d_name;
507
508 Dir.Buffer.resize(sizeof(__wasi_dirent_t) + Name.size());
509
510 __wasi_dirent_t *const Dirent =
511 reinterpret_cast<__wasi_dirent_t *>(Dir.Buffer.data());
512 Dirent->d_next = Dir.Cookie;
513 Dirent->d_ino = SysDirent->d_ino;
514 Dirent->d_type = fromFileType(SysDirent->d_type);
515 Dirent->d_namlen = Name.size();
516 std::copy(Name.cbegin(), Name.cend(),
517 Dir.Buffer.begin() + sizeof(__wasi_dirent_t));
518 } while (!Buffer.empty());
519

Callers

nothing calls this directly

Calls 14

unlikelyFunction · 0.85
WasiUnexpectFunction · 0.85
subspanMethod · 0.80
resizeMethod · 0.80
fromErrNoFunction · 0.70
fromFileTypeFunction · 0.70
okMethod · 0.45
releaseMethod · 0.45
emplaceMethod · 0.45
emptyMethod · 0.45
sizeMethod · 0.45
beginMethod · 0.45

Tested by

no test coverage detected