CDC Badge OS
Firmware for the CDC Badge v1.0 hardware security key
Loading...
Searching...
No Matches
host_api_fs.cpp
Go to the documentation of this file.
1
11
15#include "cdc_core/Raii.h"
16
17#include <cstdio>
18#include <cstring>
19#include <string>
20#include <sys/stat.h>
21#include <dirent.h>
22
23extern "C" void* plg_get_active_plugin(void);
24
25namespace {
26
27constexpr size_t MAX_NAME_LEN = 64;
28
30bool nameOk(const char* name)
31{
32 if (!name || !*name) return false;
33 size_t n = std::strlen(name);
34 if (n > MAX_NAME_LEN || name[0] == '.') return false;
35 for (size_t i = 0; i < n; ++i) {
36 char c = name[i];
37 bool ok = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
38 (c >= '0' && c <= '9') || c == '.' || c == '_' || c == '-';
39 if (!ok) return false;
40 }
41 return true;
42}
43
45int resolveDir(std::string& out)
46{
47 auto* plugin = static_cast<cdc::plugin_manager::Plugin*>(plg_get_active_plugin());
48 if (!plugin) return HOST_ERR_GENERIC;
49 if (!plugin->manifest().capabilities.vfat) return HOST_ERR_NO_CAPABILITY;
50
51 std::string dataRoot =
52 std::string(cdc::plugin_manager::PluginStorage::basePath()) + "/data";
53 mkdir(dataRoot.c_str(), 0755);
54 out = dataRoot + "/" + plugin->id();
55 mkdir(out.c_str(), 0755);
56 return HOST_OK;
57}
58
60int resolvePath(const char* name, std::string& out)
61{
62 std::string dir;
63 int rc = resolveDir(dir);
64 if (rc != HOST_OK) return rc;
65 if (!nameOk(name)) return HOST_ERR_INVALID_ARG;
66 out = dir + "/" + name;
67 return HOST_OK;
68}
69
70} // namespace
71
72extern "C" {
73
74int host_fs_write(const char* name, const uint8_t* data, size_t len)
75{
76 if (!data && len > 0) return HOST_ERR_INVALID_ARG;
77 std::string path;
78 int rc = resolvePath(name, path);
79 if (rc != HOST_OK) return rc;
80
81 auto f = cdc::core::openFile(path.c_str(), "wb");
82 if (!f) return HOST_ERR_GENERIC;
83 if (len > 0 && std::fwrite(data, 1, len, f.get()) != len) return HOST_ERR_GENERIC;
84 return HOST_OK;
85}
86
87int host_fs_read(const char* name, uint8_t* buf, size_t* len)
88{
89 if (!buf || !len) return HOST_ERR_INVALID_ARG;
90 std::string path;
91 int rc = resolvePath(name, path);
92 if (rc != HOST_OK) return rc;
93
94 auto f = cdc::core::openFile(path.c_str(), "rb");
95 if (!f) return HOST_ERR_NOT_FOUND;
96 *len = std::fread(buf, 1, *len, f.get());
97 return HOST_OK;
98}
99
100int host_fs_remove(const char* name)
101{
102 std::string path;
103 int rc = resolvePath(name, path);
104 if (rc != HOST_OK) return rc;
105 return (std::remove(path.c_str()) == 0) ? HOST_OK : HOST_ERR_NOT_FOUND;
106}
107
108int host_fs_size(const char* name, size_t* out)
109{
110 if (!out) return HOST_ERR_INVALID_ARG;
111 std::string path;
112 int rc = resolvePath(name, path);
113 if (rc != HOST_OK) return rc;
114
115 struct stat st;
116 if (stat(path.c_str(), &st) != 0) return HOST_ERR_NOT_FOUND;
117 *out = static_cast<size_t>(st.st_size);
118 return HOST_OK;
119}
120
121int host_fs_list(char* out, size_t* out_len)
122{
123 if (!out_len) return HOST_ERR_INVALID_ARG;
124 std::string dir;
125 int rc = resolveDir(dir);
126 if (rc != HOST_OK) return rc;
127
128 DIR* d = opendir(dir.c_str());
129 if (!d) return HOST_ERR_NOT_FOUND;
130
131 size_t written = 0;
132 const size_t max = (out ? *out_len : 0);
133 for (struct dirent* e = readdir(d); e != nullptr; e = readdir(d)) {
134 if (e->d_name[0] == '.') continue;
135 size_t need = std::strlen(e->d_name) + 1;
136 if (out && (written + need) <= max) {
137 std::memcpy(out + written, e->d_name, need - 1);
138 out[written + need - 1] = '\n';
139 }
140 written += need;
141 }
142 closedir(d);
143 *out_len = written;
144 return HOST_OK;
145}
146
147int host_fs_view(const char* name)
148{
149 std::string path;
150 int rc = resolvePath(name, path);
151 if (rc != HOST_OK) return rc;
152
153 auto f = cdc::core::openFile(path.c_str(), "rb");
154 if (!f) return HOST_ERR_NOT_FOUND;
155
156 // Match the on-screen text viewer's capacity (InfoView buffer).
157 constexpr size_t VIEW_MAX = 2048;
158 std::string content;
159 content.resize(VIEW_MAX);
160 size_t n = std::fread(&content[0], 1, VIEW_MAX - 1, f.get());
161 content.resize(n);
162 // Files and filenames are UTF-8; host_ui_push_info converts to display.
163 return host_ui_push_info(name, content.c_str());
164}
165
166} // extern "C"
Mounts the FAT-FS partition that holds plugin .wasm + .meta files.
Owned WAMR module instance + per-plugin state.
char name[cdc::hal::ISecureElement::RMEM_NAME_LEN]
Shared RAII wrappers for firmware resources.
static const char * basePath()
Returns the VFS path prefix, e.g. "/plugins".
int host_ui_push_info(const char *title, const char *body)
Show a scrollable info screen with title and body.
int host_fs_view(const char *name)
Open one of the plugin's own files in a scrollable on-screen text viewer (same as opening the file in...
int host_fs_size(const char *name, size_t *out)
Write the byte size of name to *out.
int host_fs_read(const char *name, uint8_t *buf, size_t *len)
Read name into buf.
int host_fs_remove(const char *name)
Delete name.
int host_fs_write(const char *name, const uint8_t *data, size_t len)
Create or overwrite name with len bytes.
int host_fs_list(char *out, size_t *out_len)
Enumerate the plugin's own files.
CDC Badge OS plugin host API - canonical C ABI contract.
#define HOST_ERR_NO_CAPABILITY
Definition host_api.h:40
#define HOST_OK
Definition host_api.h:37
#define HOST_ERR_INVALID_ARG
Definition host_api.h:39
#define HOST_ERR_NOT_FOUND
Definition host_api.h:41
#define HOST_ERR_GENERIC
Definition host_api.h:38
void * plg_get_active_plugin(void)
FilePtr openFile(const char *path, const char *mode) noexcept
Open a FILE* and wrap it in a FilePtr.
Definition Raii.h:87