xref: /aosp_15_r20/external/mesa3d/src/gfxstream/guest/platform/fuchsia/os_dirent_fuchsia.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2024 Google LLC
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include <lib/zxio/zxio.h>
7 #include <services/service_connector.h>
8 #include <string.h>
9 
10 #include "os_dirent.h"
11 #include "util/log.h"
12 
13 struct os_dir {
~os_diros_dir14     ~os_dir() {
15         if (dir_iterator_init_) {
16             zxio_dirent_iterator_destroy(&iterator_);
17         }
18         if (zxio_init_) {
19             zxio_close(&io_storage_.io, /*should_wait=*/true);
20         }
21     }
22 
23     // Always consumes |dir_channel|
Initos_dir24     bool Init(zx_handle_t dir_channel) {
25         zx_status_t status = zxio_create(dir_channel, &io_storage_);
26         if (status != ZX_OK) {
27             mesa_loge("zxio_create failed: %d", status);
28             return false;
29         }
30 
31         zxio_init_ = true;
32 
33         status = zxio_dirent_iterator_init(&iterator_, &io_storage_.io);
34         if (status != ZX_OK) {
35             mesa_loge("zxio_dirent_iterator_init failed: %d", status);
36             return false;
37         }
38 
39         dir_iterator_init_ = true;
40         return true;
41     }
42 
Nextos_dir43     bool Next(struct os_dirent* entry) {
44         // dirent is an in-out parameter.
45         // name must be initialized to point to a buffer of at least ZXIO_MAX_FILENAME bytes.
46         static_assert(sizeof(entry->d_name) >= ZXIO_MAX_FILENAME);
47         zxio_dirent_t dirent = {.name = entry->d_name};
48 
49         zx_status_t status = zxio_dirent_iterator_next(&iterator_, &dirent);
50         if (status != ZX_OK) {
51             if (status != ZX_ERR_NOT_FOUND)
52                 mesa_loge("zxio_dirent_iterator_next failed: %d", status);
53             return false;
54         }
55 
56         entry->d_ino = dirent.has.id ? dirent.id : OS_INO_UNKNOWN;
57         entry->d_name[dirent.name_length] = '\0';
58 
59         return true;
60     }
61 
62    private:
63     bool zxio_init_ = false;
64     bool dir_iterator_init_ = false;
65     zxio_storage_t io_storage_;
66     zxio_dirent_iterator_t iterator_;
67 };
68 
os_opendir(const char * path)69 os_dir_t* os_opendir(const char* path) {
70     zx_handle_t dir_channel = GetConnectToServiceFunction()(path);
71     if (dir_channel == ZX_HANDLE_INVALID) {
72         mesa_loge("fuchsia_open(%s) failed", path);
73         return nullptr;
74     }
75 
76     auto dir = new os_dir();
77 
78     if (!dir->Init(dir_channel)) {
79         delete dir;
80         return nullptr;
81     }
82 
83     return dir;
84 }
85 
os_closedir(os_dir_t * dir)86 int os_closedir(os_dir_t* dir) {
87     delete dir;
88     return 0;
89 }
90 
os_readdir(os_dir_t * dir)91 struct os_dirent* os_readdir(os_dir_t* dir) {
92     static struct os_dirent dirent = {};
93     return reinterpret_cast<os_dirent*>(dir->Next(&dirent)) ? &dirent : nullptr;
94 }
95