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

Method fdReaddir

lib/host/wasi/inode-linux.cpp:499–558  ·  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

497// readdir entry API is going to be updated to use a stream type, so we don't
498// have to deal with it right now.
499WasiExpect<void> INode::fdReaddir(Span<uint8_t> Buffer,
500 __wasi_dircookie_t Cookie,
501 __wasi_size_t &Size) noexcept {
502 if (unlikely(!Dir.ok())) {
503 if (FdHolder NewFd(::dup(Fd)); unlikely(!NewFd.ok())) {
504 return WasiUnexpect(fromErrNo(errno));
505 } else if (DIR *D = ::fdopendir(NewFd.Fd); unlikely(!D)) {
506 return WasiUnexpect(fromErrNo(errno));
507 } else {
508 NewFd.release();
509 Dir.emplace(D);
510 }
511 }
512
513 if (Cookie == 0) {
514 ::rewinddir(Dir.Dir);
515 } else if (unlikely(Cookie != Dir.Cookie)) {
516 ::seekdir(Dir.Dir, Cookie);
517 }
518
519 Size = 0;
520 do {
521 if (!Dir.Buffer.empty()) {
522 const auto NewDataSize =
523 std::min<uint32_t>(Buffer.size(), Dir.Buffer.size());
524 std::copy(Dir.Buffer.begin(), Dir.Buffer.begin() + NewDataSize,
525 Buffer.begin());
526 Buffer = Buffer.subspan(NewDataSize);
527 Size += NewDataSize;
528 Dir.Buffer.clear();
529 if (unlikely(Buffer.empty())) {
530 break;
531 }
532 }
533 errno = 0;
534 dirent *SysDirent = ::readdir(Dir.Dir);
535 if (SysDirent == nullptr) {
536 if (errno != 0) {
537 return WasiUnexpect(fromErrNo(errno));
538 }
539 // End of entries
540 break;
541 }
542 Dir.Cookie = SysDirent->d_off;
543 std::string_view Name = SysDirent->d_name;
544
545 Dir.Buffer.resize(sizeof(__wasi_dirent_t) + Name.size());
546
547 __wasi_dirent_t *const Dirent =
548 reinterpret_cast<__wasi_dirent_t *>(Dir.Buffer.data());
549 Dirent->d_next = Dir.Cookie;
550 Dirent->d_ino = SysDirent->d_ino;
551 Dirent->d_type = fromFileType(SysDirent->d_type);
552 Dirent->d_namlen = Name.size();
553 std::copy(Name.cbegin(), Name.cend(),
554 Dir.Buffer.begin() + sizeof(__wasi_dirent_t));
555 } while (!Buffer.empty());
556 Size = EndianValue(Size).le();

Callers

nothing calls this directly

Calls 15

unlikelyFunction · 0.85
WasiUnexpectFunction · 0.85
EndianValueClass · 0.85
subspanMethod · 0.80
resizeMethod · 0.80
leMethod · 0.80
fromErrNoFunction · 0.70
fromFileTypeFunction · 0.70
okMethod · 0.45
releaseMethod · 0.45
emplaceMethod · 0.45
emptyMethod · 0.45

Tested by

no test coverage detected