[util][dirent] On Fuchsia use zxio
Bug: 40999
Change-Id: I55450ed77b3cb3cfb0818fe372b05421c94bcf01
diff --git a/src/util/BUILD.gn b/src/util/BUILD.gn
index 26a2f63..9031325 100644
--- a/src/util/BUILD.gn
+++ b/src/util/BUILD.gn
@@ -113,7 +113,7 @@
"$magma_build_root/src/magma_util/platform:futex",
"$magma_build_root/src/magma_util:common",
"//zircon/public/lib/zx",
- "//zircon/system/fidl/fuchsia-io:llcpp",
+ "//zircon/public/lib/zxio",
]
} else {
sources += [ "anon_file.c" ]
diff --git a/src/util/os_dirent_fuchsia.cpp b/src/util/os_dirent_fuchsia.cpp
index 11efa39..8fdcf7d 100644
--- a/src/util/os_dirent_fuchsia.cpp
+++ b/src/util/os_dirent_fuchsia.cpp
@@ -7,13 +7,11 @@
#include "list.h"
#include "os/fuchsia.h"
-#include <fuchsia/io/llcpp/fidl.h>
-#include <lib/zx/channel.h>
+#include <lib/zxio/inception.h>
+#include <lib/zxio/zxio.h>
#include <magma_util/dlog.h>
-namespace fio = llcpp::fuchsia::io;
-
-// Offsets must match struct os_dir, static_asserts below.
+// Offsets must match struct os_dirent, static_asserts below.
struct os_dirent_impl {
ino_t d_ino;
char d_name[NAME_MAX];
@@ -24,62 +22,77 @@
static_assert(offsetof(struct os_dirent_impl, d_name) == offsetof(struct os_dirent, d_name),
"d_ino offset mismatch");
-// From io.fidl:
-struct __attribute__((__packed__)) dirent {
- uint64_t ino;
- uint8_t size;
- uint8_t type;
- char name[0];
-};
-
-static zx_status_t readdir(const zx::channel& control_channel, void* buffer, size_t capacity,
- size_t* out_actual)
-{
- // Explicitly allocating message buffers to avoid heap allocation.
- fidl::Buffer<fio::Directory::ReadDirentsRequest> request_buffer;
- fidl::Buffer<fio::Directory::ReadDirentsResponse> response_buffer;
- auto result =
- fio::Directory::Call::ReadDirents(zx::unowned_channel(control_channel),
- request_buffer.view(), capacity, response_buffer.view());
- if (result.status() != ZX_OK)
- return result.status();
-
- fio::Directory::ReadDirentsResponse* response = result.Unwrap();
- if (response->s != ZX_OK)
- return response->s;
-
- const auto& dirents = response->dirents;
- if (dirents.count() > capacity)
- return ZX_ERR_IO;
-
- memcpy(buffer, dirents.data(), dirents.count());
- *out_actual = dirents.count();
- return response->s;
-}
-
-struct os_dir {
+class os_dir {
+public:
os_dir() { buffer = new char[buffer_size()]; }
- ~os_dir() { delete [] buffer; }
- static size_t buffer_size() { return 4096; }
+ ~os_dir()
+ {
+ if (dir_init) {
+ zxio_close(&io_storage.io);
+ }
+ delete[] buffer;
+ }
- zx::channel control_channel;
+ static size_t buffer_size() { return ZXIO_DIRENT_ITERATOR_DEFAULT_BUFFER_SIZE; }
+
+ // Always consumes |dir_channel|
+ bool Init(zx_handle_t dir_channel)
+ {
+ zx_status_t status = zxio_dir_init(&io_storage, dir_channel);
+ if (status != ZX_OK) {
+ DLOG("zxio_dir_init failed: %d", status);
+ return false;
+ }
+ dir_init = true;
+
+ status = zxio_dirent_iterator_init(&iterator, &io_storage.io, buffer, buffer_size());
+ if (status != ZX_OK) {
+ DLOG("zxio_dirent_iterator_init failed: %d", status);
+ return false;
+ }
+
+ return true;
+ }
+
+ struct os_dirent_impl* Next()
+ {
+ zxio_dirent_t* dirent;
+ zx_status_t status = zxio_dirent_iterator_next(&iterator, &dirent);
+ if (status != ZX_OK) {
+ DLOG("zxio_dirent_iterator_next failed: %d", status);
+ return nullptr;
+ }
+
+ entry.d_ino = dirent->inode;
+ strncpy(entry.d_name, dirent->name, dirent->size);
+ entry.d_name[dirent->size] = 0;
+
+ return &entry;
+ }
+
+private:
+ bool dir_init = false;
+ zxio_storage_t io_storage;
+ zxio_dirent_iterator_t iterator;
struct os_dirent_impl entry;
char* buffer = nullptr;
- size_t count = 0;
- size_t index = 0;
};
os_dir_t* os_opendir(const char* path)
{
- zx::channel control_channel;
- if (!fuchsia_open(path, control_channel.reset_and_get_address())) {
+ zx_handle_t dir_channel;
+ if (!fuchsia_open(path, &dir_channel)) {
DLOG("fuchsia_open(%s) failed\n", path);
return nullptr;
}
auto dir = new os_dir();
- dir->control_channel = std::move(control_channel);
+
+ if (!dir->Init(dir_channel)) {
+ delete dir;
+ return nullptr;
+ }
return dir;
}
@@ -91,38 +104,4 @@
return 0;
}
-struct os_dirent* os_readdir(os_dir_t* dir)
-{
- if (dir->index >= dir->count) {
- size_t count;
- zx_status_t status =
- readdir(dir->control_channel, dir->buffer, os_dir::buffer_size(), &count);
- if (status != ZX_OK) {
- DLOG("os_readdir: readdir failed: %d\n", status);
- return nullptr;
- }
-
- dir->count = count;
- dir->index = 0;
- }
-
- if (dir->index + sizeof(dirent) > dir->count) {
- DLOG("os_readdir: no more entries");
- return nullptr;
- }
-
- dirent* entry = reinterpret_cast<dirent*>(&dir->buffer[dir->index]);
- size_t entry_size = sizeof(dirent) + entry->size;
-
- if (dir->index + entry_size > dir->count) {
- DLOG("os_readdir: last entry incomplete (this shouldn't happen)");
- return nullptr;
- }
- dir->index += entry_size;
-
- dir->entry.d_ino = entry->ino;
- strncpy(dir->entry.d_name, entry->name, entry->size);
- dir->entry.d_name[entry->size] = 0;
-
- return reinterpret_cast<os_dirent*>(&dir->entry);
-}
+struct os_dirent* os_readdir(os_dir_t* dir) { return reinterpret_cast<os_dirent*>(dir->Next()); }